Двоичные типы данных

Тип данных bytea позволяет хранить двоичные строки; см. Таблицу 6.

Таблица 6. Двоичные типы данных

ИмяРазмерОписание
bytea1 или 4 байта плюс сама двоичная строкадвоичная строка переменной длины

Двоичная строка — это последовательность октетов (или байтов). Двоичные строки имеют два отличия от символьных строк. Во-первых, двоичные строки позволяют хранить октеты с нулевым значением и другие «непечатаемые» октеты (как правило, это октеты вне десятичного диапазона от 32 до 126). Строки символов запрещают нулевые октеты, а также любые другие значения октетов и последовательности значений октетов, недопустимые в соответствии с выбранной кодировкой набора символов базы данных. Во-вторых, операции над двоичными строками обрабатывают фактические байты, тогда как обработка символьных строк зависит от настроек локали. Иными словами, двоичные строки подходят для хранения данных, которые программист считает «необработанными байтами», тогда как символьные строки подходят для хранения текста.

Тип bytea поддерживает два формата для ввода и вывода: hex («шестнадцатеричный») и традиционный для QHB формат escape («экранированный»). Входные данные всегда принимаются в обоих форматах. Формат вывода зависит от параметра конфигурации bytea_output; по умолчанию используется «шестнадцатеричный».

Стандарт SQL определяет другой тип двоичной строки, который называется BLOB или BINARY LARGE OBJECT. Формат ввода отличается от bytea, но предоставляемые функции и операторы в основном одинаковы.


Шестнадцатеричный формат bytea

«Шестнадцатеричный» формат кодирует двоичные данные в виде 2 шестнадцатеричных цифр на байт, при этом первая цифра представляет собой наиболее значимые 4 бита. Всей строке предшествует последовательность \x (чтобы отличить ее от экранированного формата). Возможно, в некоторых контекстах понадобится экранировать обратный слеш путем его дублирования (см. подраздел Строковые константы). Вводимые шестнадцатеричные цифры могут быть в верхнем или нижнем регистре, и между парами цифр допускается пробел (но не внутри пары цифр и не в начальной последовательности \x). Шестнадцатеричный формат совместим с широким спектром внешних приложений и протоколов; кроме того, он, как правило, преобразуется быстрее экранированного формата, поэтому предпочтительнее использовать его.

Пример:

SELECT '\xDEADBEEF';

Экранированный формат bytea

Экранированный формат является традиционным форматом QHB для типа bytea. В нем используется подход, представляющий двоичную строку как последовательность символов ASCII, а те байты, которые нельзя представить в виде символа ASCII, преобразуются в специальные экранированные последовательности. Если с точки зрения приложения представление байтов в виде символов имеет смысл, то такое представление может быть удобным. Но на практике это обычно вносит путаницу, поскольку стирает различия между двоичными и символьными строками, а кроме того выбранный механизм экранирования последовательностей несколько громоздок. Поэтому в большинстве новых приложений этот формат, наверное, использовать не стоит.

При вводе значений bytea в экранированном формате октеты определенных значений нужно экранировать тогда как все октетные значения можно экранировать. В целом, чтобы экранировать октет, преобразуйте его в трехзначное восьмеричное значение и поставьте перед ним обратный слеш. Сам обратный слеш (символ с десятичным кодом 92) также можно записать в виде двойного обратного слеша. В Таблице 7 перечислены символы, которые нужно экранировать, а также приведены альтернативные экранированные последовательности, где это возможно.

Таблица 7. Экранированные октеты литералов bytea

Десятичное значение октетаОписаниеЭкранированное входное представлениеПримерШестнадцатеричное представление
0нулевой октет'\000''\000'::bytea;\x00
39апостроф'''' или '\047'''''::bytea;\x27
92обратный слеш'\\' или '\134''\\'::bytea;\x5c
От 0 до 31 и от 127 до 255«Непечатные» октеты'\ xxx' (восьмеричное значение)'\001'::bytea;\x01

Необходимость экранирования непечатаемых октетов зависит от настроек локали. В некоторых случаях их можно оставить без экранирования.

Причина, по которой апострофы необходимо дублировать, как показано в Таблице 7, заключается в том, что это верно для любого строкового литерала в команде SQL. Универсальный синтаксический анализатор строковых литералов убирает внешние апострофы и сводит любую пару апострофов к одному символу данных. В результате функция ввода bytea видит всего лишь один апостроф, который она обрабатывает как обычный символ данных. Однако обратный слеш функция ввода bytea обрабатывает как спецсимвол, тем самым реализуя другие действия, показанные в Таблице 7.

В некоторых контекстах обратный слеш необходимо дублировать (относительно показанных выше примеров), потому что общий анализатор строковых литералов также сократит пары обратных слешей до одного символа данных (см. подраздел Строковые константы).

Октеты bytea по умолчанию выводятся в шестнадцатеричном формате. Если поменять значение bytea_output на escape, «непечатаемые» октеты преобразуются в равнозначные им трехзначные восьмеричные значения, перед которыми стоит один обратный слеш. Большинство «печатаемых» октетов выводятся в виде стандартного представления из клиентского набора символов, например:

SET bytea_output = 'escape';

SELECT 'abc \153\154\155 \052\251\124'::bytea;
     bytea
----------------
 abc klm *\251T

Октет с десятичным значением 92 (обратный слеш) при выводе дублируется. Подробности см. в Таблице 8.

Таблица 8. Выходные экранированные октеты bytea

Десятичное значение октетаОписаниеВыходное экранированное представлениеПримерРезультат на выходе
92обратный слеш\\'\134'::bytea;\\
От 0 до 31 и от 127 до 255«Непечатаемые» октеты\xxx (восьмеричное значение)'\001'::bytea;\001
От 32 до 126«Печатаемые» октетыпредставление набора символов клиента'\176'::bytea;~

В зависимости от используемого интерфейса QHB, может понадобиться выполнить дополнительные действия, связанные с экранированием и деэкранированием строк bytea. Например, если интерфейс автоматически преобразует символы перевода строк и возврата каретки, возможно, их тоже придется экранировать.