тип байта & null, Postgres - PullRequest
       9

тип байта & null, Postgres

2 голосов
/ 07 июня 2010

Я использую тип bytea в PostgreSQL, который, на мой взгляд, содержит только серию байтов. Однако я не могу заставить его играть хорошо с нулями. Например:

=# select length(E'aa\x00aa'::bytea);
 length
--------
      2
(1 row)

Я ожидал 5. Также:

=# select md5(E'aa\x00aa'::bytea);
               md5
----------------------------------
 4124bc0a9335c27f086f24ba207a4912
(1 row)

Это MD5 слова "аа", а не "аа \ x00aa". Очевидно, я делаю это неправильно, но я не знаю, что я делаю неправильно. Я также использую старую версию Postgres (8.1.11) по независящим от меня причинам. (Я посмотрю, будет ли это так же на последних Postgres, как только я вернусь домой ...)

Ответы [ 2 ]

9 голосов
/ 07 июня 2010

Попробуйте это:

# select length(E'aa\\000aa'::bytea);
 length
--------
      5

Обновлено: почему оригинал не работал? Сначала поймите разницу между одним слешем и двумя:

pg=# select E'aa\055aa', length(E'aa\055aa') ;
 ?column? | length
----------+--------
 aa-aa    |      5
(1 row)

pg=# select E'aa\\055aa', length(E'aa\\055aa') ;
 ?column? | length
----------+--------
 aa\055aa |      8

В первом случае я пишу буквенную строку, 4 символа без экранирования ('a') и один с экранированием. Косая черта потребляется синтаксическим анализатором за первый проход, который преобразует полное значение \055 на один символ (в данном случае '-').

Во втором случае первая косая черта просто ускользает от второго, пара \\ преобразуется парсером в один \, а 055 выглядит как три символа.

Теперь при преобразовании текста в bytea escape-символы (в уже проанализированном или созданном тексте) анализируются / интерпретируются снова ! (Да, это сбивает с толку).

Итак, когда я пишу

 select E'aa\000aa'::bytea;

при первом разборе литерал E'aa \ 000aa 'преобразуется во внутренний текст с нулевым символом в третьей позиции (и в зависимости от вашей версии postgresql нулевой символ интерпретируется как EOS, а текст предполагается, что он имеет длину два или в других версиях выдается недопустимая строковая ошибка).

Вместо этого, когда я пишу

 select E'aa\\000aa'::bytea;

при первом разборе видна буквальная строка «aa \ 000aa» (восемь символов), и она сопоставляется с текстом; затем при приведении к bytea он снова анализируется, и последовательность символов '\ 000' интерпретируется как нулевой байт.

IMO postgresql отстой здесь.

0 голосов
/ 07 марта 2019

Вы можете использовать обычные строки или строки в кавычках вместо экранированных строк:

# select length('aa\000aa'::bytea);
 length 
════════
      5
(1 row)

# select length($$aa\000aa$$::bytea);
length 
════════
      5
(1 row)

Я думаю, что строки в кавычках лучше, потому что, если параметр конфигурации standard_conforming_strings выключен,затем PostgreSQL распознает экранирование с обратной косой чертой как в обычных, так и в экранированных строковых константах.Однако, начиная с PostgreSQL 9.1, по умолчанию включено, что означает, что экранирование с обратной косой чертой распознается только в константах escape-строки.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...