Обновление таблицы PostgreSQL двоичными данными
У меня есть std::stringstream strs
переменная с этими сериализованными двоичными данными:
G {SSF >% hgRQ;Tjh A "ʐk R3 1[Z yA _ Kx O f ' t % +>, ~ 삾 +/ Tb Ҷ 7 (Q1 5m& ( G# bm 3O AN) DP߇g 0=ʆ 0 j u E 3 G # " \! %O% L. WMG?B- 3 }&. S (B j& @ %&, 65 0!G 5R N 0 b hv) 8 x %7 5e: w|7ώJ 8 X/ v c h2 3 i o^
A oG 0 + Ȑ" n 4 F# >b . m =; X < c(= 7Y: �� �� Q��O� w�k�q! �D��G�8 O���l�1 j��DH ��rhJ v͑UF� �P���; �| ���h �U��z�* 0 Ԏ��6 @I� ��,K�� �R�B� ��ﲒi ��o�H�0 �"�� ���B,� $6QP�@ YŽ�05 �8�s�� �>���:> ���*� Kp1>�~< ����� x�5 05 S?�V�" �m�7 )����z$ �Ye��- �nKPz ~8�쩳 dF �̄5 �ɼ��% v�x�O�# 9�B�/�6 �5��[. ��P%:� ���V�t
G' O #bQ 9)�0%�[0 f�(? e( �
5 rt O [ ۠ ɴKG '$ _s g:] Aߞ, Q
Это те же данные после использования GDB:
" \ 374G \ 371 {SSF \ 301 \ 251 *> \ 177% \ 225 \ 201 \ 253i \ Ъ \344\206\341hgRQ\016\022\001;TJH \002\000\000\000A\000\000\000\001\000\000\000\"ʐk\323R3\000\061[Z\272yA\001\000_\340\016K\004x\005\000O\226\ F \ 262 \ а \ 375 \ 020 \ 000 \ 346 \ 302 \ 341f\230\235'\000\026\275\367\371\ рамой 215T \020\000%\356\033\372+>,\000\307\016\361\327~\223\033\000삾\351\254+/\000Tb\335Ҷ\363\067\000\342(\357\336\346\326\017\000\327Q1\320\065m&\000\034\216\377\035\005(\a\000\020G#\345bm\017\000\063O\324AN)\000\225DP߇g\a\000\355\060= 260 260 260 060\000\232\377\272j\234U \006\000E\304\063\372\355\v\ е \000\223G\353\024#\307\"\000\\317\327!\270o%\000\005L\035 \345\306\002\000\257WMG?B-\000\063\275\342\373\304}&\000\365\017.\367S\264\031\000(\236\033B\354\255\ п \000\316\034j&\321\021\ п \000\266@\226\314%&,\000\066\065\236\024\271\033\060\000!G\332\v5R\030\000\372\ F \353N\225\201\060\000\331\377\035b\244\263\033\000h\361\205\267\207v)\000\322\027\070\246\212w\ Ъ \ 000x <\ 001 \ 026n} \ 034 \ 000Җp {\ 362F \ т \ 000 \ 370 \ 352m \ 026ŵ8 \ 000 (\ 366 \ 366: \ 017 \ 000 \ 364 \ 026 \ 210 Ь = \ 235 \ " \ 000 \ 251 \ 214 [) \ 262 \ 342 \ 022 \ 000 м \ 316fd \ 345 \ 060 \ 000 [VAl \ 206 \ 233 \ 006 \ 000 \ 035 \ 354o \ 021'9 # \ 000 \ 363 \ 032 \ 327 \ 372 \ 357 \ 322 \ 034 \ 000 |! '\ 256 \ 306K {\ 021 \ 000B \ 266 \ 33 \ 257 \ 332+ \ 000x \ 346 \ 023 \ 300 \ 315 \ 306 \ 000qO \ 016 \ 005wz * \ 000 трлн \ 236 * \ 021 \ 272H; \ 000 \ ба \ 006 $ \ 376 \ 214 \ 027 \ 000 \ 213 \ 377 \ а \ 330 \ 372 \ 023 \ 003 \ 000 \ 361, м \ 274 \ 300 \ 321 \ 004 \ 000DË \ 277 \ 272T \ 000 \ 357 \ 231Ţ \ 355 \ 270 \ 067 \ 000;: \ 263 \ 303 \ 070 \ 246 \ 022 \ 000 ~ \ 267 \ 374 \ 060 \ 272 \ 261 \ г \ 000 \ 264> \ 374 \ 021 \ 027% 7 \ 000 \ 065 \ 034e \ 216 \ 305: \ 006 \ 000W |7ώJ\006\000\070\242\210\310\343\206\ N \000\365\263\370\377\005X/\000V \335c\200h\035\062\000\063\225\363\244i\362\ г \000o^\371\353\302\ п \ 027 \ 000 \ 000 \ 000 \ 000 \ 000 \ 000 \ 000 \ 000 \ 000 \ т \ 224А \207\331\374\024\000\254oG\352\364\177\060\000+\254\332\330Ȑ\"\000n\024\310\360\265?\ B \000\004\234\231\006\250\064\016\000F#\225>b\020 \000.\271\224м \ 246 =; \ 000 \ 305 \ t \ 017 \ 372X \ 024 \ 024 \ 000 \ 232 \ 023 \ 005 \ 360 \ 277 <\ 017 \ 000 \ 036 \ 242 c \ 005 (= \ 000 \ 211 \ 200 \ 212 \ 067Y
:\000\273\206\017\n\204\233\027\000\002Q\364\376O\277\033\000w\212\033k\273q!\000\333D\204\241G\331\070\000O\242\306\346l\327\061\000j\224\205DH\033\032\000\270\025\375rhJ\n\000v͑UF\227 \000\230P\272\211\247\005;\000\372\177\017\310\b|\032\000\367\357\255\352h\n\036\000\226U\230\255z\247*\000\060\000Ԏ\241\301\066\000\315\b@\024I\227\032\000\275\322,K\275\304\034\000\332R\375B\023\376\001\000\331\324ﲒi\r\000\256\353o\237H\205\060\000\353\"\026\025\360\320\n\000\203\306\344B,\200\006\000$6QP\325@\017\000YŽ\036\203\060\065\000\366\070\251s\264\252\017\000\360>\251\310\340:>\000\257\310\326\005*\216\036\000Kp1>\232~<\000\225\002\253\302\365\350\021\000x\341\065\000\060\065\021\000S?\331V\311\"\000\000\356m\307\003\030\067\004\000)\212\265\351\331z$\000\336Ye\217\323\033-\000\215nK\026Pz\v\000~8\273쩳\r\000dF\r\261̄5\000\206\aɼ\303\365%\000v\365x\304O\346#\000\071\210B\373/\264\066\000\324\065\216\003\274[.\000\363\343P%:\311\033\000\244\301\370V\367t\006\000
G \ 005' \ 213O \ 017 \ 000 \ 252 \ 220 # Бк \ 324 \ 071 \ 000 \ 376 \ 272 \ 377 \ 347 \ 016 \ 237) \ 000\374\060%\311[0\000\177\rf\357\233(?\000e(\r\204
5 \ г \000rt\000\005\230O*\000\345[\204 х \ б \000\207ɴKG\224\ V \000\273'$\261_s\036\000\215\240\ фг:]\002\000Aߞ,\303Q\ т \000\000\000\000\000\000\000\000"
Я пытаюсь загрузить эти данные (хранится в std::stringstream strs
) в базу данных PostgreSQL, закодированную UTF8
и в byte_info
исключая столбец bytea
используя библиотеку libpqxx:
pqxx::connection Con("My con information");
pqxx::work W(Con);
W.exec("UPDATE " + tableName + " SET byte_info =" + strs.str() + " WHERE id = 1;");
W.commit();
Но я получаю только эту ошибку:
ОШИБКА: неверная последовательность байтов для кодировки "UTF8": 0xfc
Что я здесь упускаю или делаю не так?
1 ответ
Согласно руководству по PostgreSQL bytea, существует 2 способа написания оператора, содержащего двоичный поток.
Для строки "\x4A\xC3\xA1\xF2\x18"
- наговор
bytea
:E'\\x4AC3A1F218'
- спасся
bytea
:E'J\\303\\241\\362\\030'::bytea
-- побег\
как\\\\
, побег'
как\'
и бежать не для печати как\\three-digit-octal
Таким образом, вы можете придумать функции, подобные этим.
std::string ascii_to_hex_bytea(std::string_view sv) {
std::ostringstream os;
os << R"(E'\\x)" << std::hex << std::uppercase;
for (unsigned char ch : sv) {
os << std::setfill('0') << std::setw(2) << static_cast<uint16_t>(ch);
}
os << "'";
return os.str();
}
std::string ascii_to_escaped_bytea(std::string_view sv) {
std::ostringstream os;
os << "E'" << std::oct;
for (unsigned char ch : sv) {
if (isprint(ch))
switch (ch) {
case('\\') : os << R"(\\\\)"; break; // escape back slash
case('\'') : os << R"(\')"; break; // escape single quote
default : os << ch; // simply put printable char
}
else // escape the rest as an octal with back slash leading
os << R"(\\)" << std::setfill('0') << std::setw(3) << static_cast<uint16_t>(ch);
}
os << "'::bytea";
return os.str();
}
Предположим, у вас есть ss
как stringstream
с некоторыми данными (для демо, мы просто стучим здесь)
std::stringstream ss;
{ // random bits for length of 1024
std::string str(1024,'\0');
for (char* addr = str.data(); addr < str.data() + str.size(); ++addr )
*addr = static_cast<char>(std::experimental::randint<uint16_t>(0,255) );
ss.str(str);
}
Вы можете написать заявление, используя эти функции
auto hex_str = ascii_to_hex_bytea(ss.str() );
std::cout << hex_str << "\n";
std::string tableName{"table_name"};
std::string statement1 = "UPDATE " + tableName + " SET byte_info = " + hex_str + " WHERE id = 1;";
std::cout << statement1 << "\n\n";
auto escaped_str = ascii_to_escaped_bytea(ss.str() );
std::cout << escaped_str << "\n";
std::string statement2 = "UPDATE " + tableName + " SET byte_info = " + escaped_str + " WHERE id = 1;";
std::cout << statement2 << "\n";
Распечатать
E'\\x4AC3A1F218E1ED92AB0B3966C3E99CC5BD8419B4A91D504F85AE7621525F305A...'
UPDATE table_name SET byte_info = E'\\x4AC3A1F218E1ED92AB0B3966C3E99C...' WHERE id = 1;
E'J\\303\\241\\362\\030\\341\\355\\222\\253\\0139f\\303\\351\\234\\30...'::bytea
UPDATE table_name SET byte_info = E'J\\303\\241\\362\\030\\341\\355\\...'::bytea WHERE id = 1;