Как стать автором
Обновить

Микропост: режем UNICODE-строки для PostgreSQL

Время на прочтение 2 мин
Количество просмотров 2.5K
Периодически возникает желание положить в базу «неположимое» — например, засунуть очень длинную строку. Нет, записать ее в поле таблицы — для PostgreSQL проблем нет, но вот в индекс…

Проблема в том, что вся строка (ROW) индекса целиком должна полностью умещаться на одной странице данных (8KB), иначе вас ждет примерно такая ошибка:
ERROR: index row size… exceeds maximum… for index ...
То есть даже в простейшем случае индекса из единственной строки — можно наступить на грабли. Как с ними бороться?

Можно, конечно, сделать функциональный индекс по substring, но тогда это же выражение придется протаскивать и во все запросы, что совсем не добавляет счастья.

Аналогичные грабли ждут нас и при попытке отправить слишком большой (больше 8000 байт) payload в NOTIFY.

Вроде бы все должно быть предельно просто — возьми да отрежь (или порежь дольками, если надо) строку по 8K. Только вот по 8K — байт, а строки-то у нас на JavaScript (подставить язык по вкусу) все сплошь из unicode-символов, которые еще и длину могут иметь в байтах переменную. А заносить в базу «полувалидную» строку как-то совсем нехорошо.

А что будет, если мы строку все-таки порежем «посередине» символа? Тут нам на помощь приходит стандарт UNICODE:
U+FFFD � REPLACEMENT CHARACTER used to replace an unknown, unrecognized or unrepresentable character
Оказывается, если мы попытаемся преобразовать такую «порезаную побайтово» строку обратно, на конце мы получим символ с кодом FFFD:



Итого, если нам целиком вся-вся строка не очень дорога (например, с текстом ошибки, от которого нам важно только начало), подрежем ее до последнего целого символа под требуемый размер в байтах:

const MAX_BYTE_LEN = 8191;
let buf = Buffer.from(errorString);
if (buf.length > MAX_BYTE_LEN) {
  errorString = buf.slice(0, MAX_BYTE_LEN).toString().replace(/\uFFFD$/, '');
}
Теги:
Хабы:
+3
Комментарии 34
Комментарии Комментарии 34

Публикации

Истории

Работа

Ближайшие события

Московский туристический хакатон
Дата 23 марта – 7 апреля
Место
Москва Онлайн
Геймтон «DatsEdenSpace» от DatsTeam
Дата 5 – 6 апреля
Время 17:00 – 20:00
Место
Онлайн