Попробуйте это:
# 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 отстой здесь.