Как вставить двоичные данные в столбец PostgreSQL BYTEA, используя C ++ libpqxx API?

Я хотел бы вставить некоторые двоичные данные в столбец BYTEA, но я обнаружил, что вывод Doxygen не хватает деталей, и http://pqxx.org/ был вниз в течение последних нескольких дней.

Как бы я вставил содержимое файла somefile.bin в таблицу со столбцом BYTEA?

Что у меня есть по этим направлениям:

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

Если это имеет значение, я хотел бы использовать новый hex Формат для BYTEA доступен в PostgreSQL 9.1.

8

Решение

Догадаться. Вот пример, показывающий, как вставить группу двоичных объектов в таблицу:

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

Вот как вернуть двоичные данные из базы данных:

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

Другие решения

Во вставке нет pqxx :: bynarystring. Для этого я использовал следующее решение:


=== ХРАНЕНИЕ wxImage В БАЗЕ ДАННЫХ ====

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




=== ПОЛУЧЕНИЕ wxImage ИЗ БАЗЫ ДАННЫХ ====

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

Я надеюсь, что это будет полезно.

1

Вместо использования подготовленного оператора SQL с conn.prepare как в ответе Стефана, если вы хотите, вы можете просто избежать двоичных данных с одной из перегрузок: pqxx::escape_binary функция. Вот это документация

0

Так как этот вопрос является лучшим результатом поиска для вставки BYTEA через libpqxx, вот другой способ сделать это с помощью параметризованного запроса, который более подходит при выполнении одной вставки.

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

Обратите внимание, что параметры должны не сбежать с quote или же esc методы.

Также обратите внимание, что принятый ответ использования pqxx::connection::prepare заставляет подготовленный запрос существовать в течение всего времени жизни соединения. Если соединение будет продолжительным и подготовленный запрос больше не нужен, его, вероятно, следует удалить, вызвав pqxx::connection::unprepare,

0

Я придумал гибкое решение, использующее двоичные данные внутри std::string,

Я предлагаю это новое решение, потому что текущие ответы устарели (2013), и я искал многостраничный запрос с использованием pqxx 5.0.1.

С приведенным ниже решением у вас есть возможность использовать for loop добавить несколько двоичных данных в одном запросе вставки.

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

Когда мы хотим получить данные из базы данных, вы должны иметь область действия своего типа данных (CustomStruct например), и вы сможете преобразовать его обратно в двоичный формат по вашему выбору.

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

Это было проверено с pqxx 5.0.1, c++11 а также postgresSQL 9.5.8

0
По вопросам рекламы [email protected]