Обновить

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

JavaScriptPostgreSQLNode.JS
Периодически возникает желание положить в базу «неположимое» — например, засунуть очень длинную строку. Нет, записать ее в поле таблицы — для 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$/, '');
}
Теги:postgresqljavascriptunicodenodejsстрокирегулярные выражения
Хабы: JavaScript PostgreSQL Node.JS
Рейтинг +3
Количество просмотров 1,5k Добавить в закладки 19
Комментарии
Комментарии 34

Похожие публикации

JavaScript Developer. Professional
29 марта 202172 500 ₽OTUS
Node.js: серверный JavaScript
5 апреля 202127 000 ₽Loftschool
PostgreSQL
15 апреля 202180 000 ₽OTUS
Комплексное обучение JavaScript
19 апреля 202127 000 ₽Loftschool
Интенсив «Full stack разработчик. JavaScript»
15 марта 2021230 000 ₽Elbrus Coding Bootcamp

Лучшие публикации за сутки