2013-04-16 1 views
7

Tôi muốn chèn một số dữ liệu nhị phân vào một cột BYTEA, nhưng tôi thấy đầu ra Doxygen thiếu chi tiết và http://pqxx.org/ đã ngừng hoạt động trong vài ngày qua.Làm cách nào để chèn dữ liệu nhị phân vào cột PostgreSQL BYTEA bằng cách sử dụng API libpqxx C++?

Tôi làm cách nào để chèn nội dung của somefile.bin vào một bảng có cột BYTEA?

gì tôi có là dọc theo những dòng:

pqxx::work work(conn); 
work.exec("CREATE TABLE test (name varchar(20), data BYTEA)"); 
work.exec("INSERT INTO test(name, data) VALUES ('foo', <insert filename.bin here>)"); 
work.commit(); 

Nếu nó làm cho một sự khác biệt, tôi muốn sử dụng định dạng mới hex cho BYTEA sẵn trong PostgreSQL 9.1.

Trả lời

9

Đã tìm ra. Dưới đây là một ví dụ cho thấy làm thế nào để chèn một loạt các đối tượng nhị phân vào một bảng:

pqxx::connection conn(...); 
conn.prepare("test", "INSERT INTO mytable(name, binfile) VALUES ($1, $2)"); 
pqxx::work work(conn); 
for (...) 
{ 
    std::string name = "foo"; 
    void * bin_data = ...; // obviously do what you need to get the binary data... 
    size_t bin_size = 123; // ...and the size of the binary data 

    pqxx::binarystring blob(bin_data, bin_size); 
    pqxx::result r = work.prepared("test")(name)(blob).exec(); 
} 
work.commit(); 

Sau đây là cách để có được những dữ liệu nhị phân trở lại ra khỏi cơ sở dữ liệu:

pqxx::result result = work.exec("SELECT * FROM mytable"); 
for (const auto &row : result) 
{ 
    pqxx::binarystring blob(row["binfile"]); 
    void * ptr = blob.data(); 
    size_t len = blob.size(); 
    ... 
} 
+0

Tôi thích giải pháp của bạn, nhưng tôi không thích bằng cách sử dụng conn.prepare. Nó giới hạn tôi khi tôi có phần tử 'n' để chèn với một truy vấn (vấn đề hiệu năng). Tôi đang làm việc trên một giải pháp (với pqxx 5.0.1). – LAL

1

Không được pqxx: : innarystring trong chèn. Tôi đã sử dụng các giải pháp sau đây để làm điều đó:

=== TÀNG TRỮ AN wxImage TRÊN CƠ SỞ DỮ LIỆU ====

//Getting image string data 
wxImage foto = (...); 
wxMemoryOutputStream stream; 
foto.SaveFile(stream,wxBITMAP_TYPE_PNG); 
wxStreamBuffer* streamBuffer = stream.GetOutputStreamBuffer(); 
size_t tamanho = streamBuffer->GetBufferSize(); 
char* fotoData = reinterpret_cast<char*>(streamBuffer->GetBufferStart()); 
string dados(fotoData, tamanho); 

//Performing the query 
conn->prepare("InsertBinaryData", "INSERT INTO table1(bytea_field) VALUES (decode(encode($1,'HEX'),'HEX'))") ("bytea",pqxx::prepare::treat_binary); 

pqxx::work w = (...); 
w.prepared(dados).exec(); 



=== lấy một wxImage TỪ DATABASE === =

pqxx::result r = w.exec("SELECT bytea_field FROM table1 WHERE (...)"); 
w.commit(); 

const result::tuple row = r[0]; 
const result::field tfoto = row[0]; 

pqxx::binarystring bs(tfoto); 
const char* dadosImg = bs.get(); 
size_t size = bs.length(); 

wxMemoryInputStream stream(dadosImg,size); 
wxImage imagem; 

imagem.LoadFile(stream); 

Tôi hy vọng nó hữu ích.

0

Thay vì sử dụng câu lệnh SQL đã chuẩn bị với conn.prepare như trong câu trả lời của Stéphane nếu bạn muốn, bạn có thể chỉ cần thoát dữ liệu nhị phân bằng một trong các quá tải của hàm pqxx::escape_binary. Here là tài liệu.

0

Vì câu hỏi này là kết quả tìm kiếm hàng đầu để chèn BYTEA qua libpqxx, đây là một cách khác để thực hiện việc này bằng truy vấn được tham số hóa, phù hợp hơn nếu thực hiện một lần chèn.

// Assuming pre-existing pqxx::connection c, void * bin_data, size_t bin_size... 
pqxx::work txn(c); 
pqxx::result res = txn.parameterized("INSERT INTO mytable(name, binfile) VALUES ($1, $2)") 
            (name) 
            (pqxx::binarystring(bin_data, bin_size)) 
            .exec(); 
txn.commit(); 

Lưu ý rằng các thông số cần không được thoát với quote hoặc esc phương pháp.

Cũng lưu ý rằng câu trả lời được chấp nhận sử dụng pqxx::connection::prepare làm cho truy vấn đã chuẩn bị tồn tại trong toàn bộ thời gian của kết nối. Nếu kết nối sẽ kéo dài và truy vấn đã chuẩn bị không còn cần thiết, có thể nó sẽ bị xóa bằng cách gọi pqxx::connection::unprepare.

0

Tôi đã đưa ra giải pháp linh hoạt sử dụng dữ liệu nhị phân bên trong std::string.

Tôi đề xuất giải pháp mới này vì câu trả lời hiện tại là cũ (2013) và tôi đang tìm kiếm truy vấn chèn nhiều bằng pqxx 5.0.1.

Với giải pháp dưới đây, bạn có thể linh hoạt sử dụng for loop để nối thêm nhiều dữ liệu nhị phân trong một truy vấn chèn đơn.

CustomStruct data = .... ; // have some binary data 

// initialise connection and declare worker 
pqxx::connection conn = new pqxx::connection(...);  
pqxx::work w(conn); 

// prepare query 
string query += "INSERT INTO table (bytea_field) VALUES (" 
// convert your data in a binary string. 
pqxx::binarystring blob((void *)&(data), data.size()); 
// avoid null character to bug your query string. 
query += "'"+w.esc_raw(blob.str())+"');"; 

//execute query 
pqxx::result rows = w.exec(query); 

Khi chúng ta muốn lấy dữ liệu từ cơ sở dữ liệu, bạn nên có phạm vi datatype của bạn (CustomStruct ví dụ) và bạn sẽ có thể bỏ nó trở lại trong định dạng nhị phân của sự lựa chọn của bạn.

// assuming worker and connection are declared and initialized. 
string query = "SELECT bytea_field FROM table;"; 
pqxx::result rows = w.exec(query); 
for(pqxx::result::iterator col = rows.begin(); col != rows.end(); ++col) 
{ 
    pqxx::binarystring blob(col[0]); 
    CustomStruct *data = (CustomStruct*) blob.data(); 
    ... 
} 

này đã được thử nghiệm với pqxx 5.0.1, c++11postgresSQL 9.5.8