2013-04-16 2 views
7

Ich möchte einige Binärdaten in eine BYTEA-Spalte einfügen, aber ich finde die Doxygen-Ausgabe in Details fehlt, und http://pqxx.org/ war in den letzten paar Tagen nicht verfügbar.Wie Einfügen von Binärdaten in eine PostgreSQL BYTEA-Spalte mithilfe der C++ - API libpqxx?

Wie würde ich den Inhalt von somefile.bin in eine Tabelle mit einer BYTEA-Spalte einfügen?

Was ich habe, ist in dieser Richtung:

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(); 

Wenn es einen Unterschied macht, würde ich das neue hex Format für BYTEA in PostgreSQL 9.1 verwenden möchten.

Antwort

9

Ich habe es herausgefunden. Hier ist ein Beispiel dafür, wie eine Reihe von binären Objekten in eine Tabelle einzufügen:

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(); 

Hier ist, wie die binären Daten, um wieder aus der Datenbank:

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

ich Ihre Lösung gefällt, aber ich weiß nicht wie die conn.prepare verwenden. Es beschränkt mich, wenn ich 'n' Element mit einer Abfrage einfügen muss (Leistungsproblem). Ich arbeite an einer Lösung (mit pqxx 5.0.1). – LAL

1

Es ist nicht pqxx: : Bynarstring in der Einfügung. Früher habe ich die folgende Lösung, das zu tun:

=== Speichern eines wxImage IN DATABASE ====

//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(); 



=== ABRUFEN AN wxImage FROM 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); 

Ich hoffe es ist hilfreich.

0

Anstelle der vorbereiteten SQL-Anweisung mit wie in Stéphanes Antwort, wenn Sie möchten, können Sie einfach die Binärdaten mit einer der Überladungen von pqxx::escape_binary Funktion entkommen. Here ist die Dokumentation.

0

Da diese Frage das oberste Suchergebnis für das Einfügen eines BYTEA über libpqxx ist, gibt es eine andere Möglichkeit, dies mithilfe einer parametrisierten Abfrage zu tun, die bei einer einzelnen Einfügung besser geeignet ist.

// 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(); 

Beachten Sie, dass die Parameter sollten nicht mit den quote oder esc Methoden entwertet werden.

Beachten Sie außerdem, dass die angenommene Antwort der Verwendung von pqxx::connection::prepare die vorbereitete Abfrage für die gesamte Lebensdauer der Verbindung verursacht. Wenn die Verbindung dauerhaft ist und die vorbereitete Abfrage nicht mehr benötigt wird, sollte sie wahrscheinlich durch den Aufruf pqxx::connection::unprepare gelöscht werden.

0

Ich habe eine flexible Lösung mit binären Daten innerhalb std::string.

Ich schlage diese neue Lösung vor, weil die aktuellen Antworten alt sind (2013) und ich nach einer Multi-Insert-Abfrage mit pqxx 5.0.1 suchte.

Mit der folgenden Lösung haben Sie die Flexibilität, eine for loop zu verwenden, um mehrere Binärdaten in einer einzigen Einfügeabfrage anzuhängen.

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); 

Wenn wir wollen Daten aus der Datenbank abgerufen wird, sollten Sie den Umfang Ihres Datentyp haben (CustomStruct zum Beispiel), und Sie sollen es werfen können, wieder im binären Format Ihrer Wahl.

// 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(); 
    ... 
} 

Dies wurde getestet mit pqxx 5.0.1, c++11 und postgresSQL 9.5.8

Verwandte Themen