Pull to refresh

Comments 11

Казалось бы, числовые типы наименее проблемные с точки зрения сюрпризов в поведении.

Упал со стула)) Я уверен что казаться такое может кому-то только по наивности и неопытности) Да это самый лютый ад который может быть, даже возня со строками в СИ не настолько лютая как числа (если ты близко к железу а не витаешь в абстракциях, есть конечно разные ЯП).
Есть такое. Еще не упомянул ряд примеров, скажем, попытку привести число 123456789 к типу REAL. Тоже будет сюрприз :)
У Firebird есть несколько интересных приколов с датами.

1. Вместо функции now() есть строковый литерал 'NOW', который при преобразовании в дату дает текущий момент. Также есть упрощенный CAST в C-стиле: TIMESTAMP'строковое представление даты', который вычисляется в момент синтаксического разбора. Веселье начинается при их объединении: TIMESTAMP'NOW'. Для простых запросов это не критично, а для хранимых процедур дата вычисляется лишь раз и не меняется. В 4.0 обещали запретить эту конструкцию.

2. TIMESTAMP'01.02.03' — 1 февраля 2003, а TIMESTAMP'01/02/03' — 2 января 2003
В PostgreSQL тоже нужно быть особенно внимательными с константами типа now (не путать с функцией now()!). К примеру, конструкция TIMESTAMP 'now' в качестве параметра для DEFAULT при создании таблицы будет всегда возвращать дату/время создания таблицы вместо текущего значения, и об этом в документации даже есть специальное предупреждение
Видимо, DEFAULT-ограничения реализуются в виде триггеров, соответственно, также один раз происходит вычисление при создании.
В дополнение к досье номер три еще одни потенциальные грабельки:
SELECT '{"foo": "bar", "baz": "qux"}'::jsonb

jsonb                       |
----------------------------|
{"baz": "qux", "foo": "bar"}|


База сама решает, к каком порядке сформировать JSONB
Да, вообще говоря, когда мы работаем с jsonb, мы работаем с индексированной внутри базы структурой, в которой порядок не обязательно будет соблюден. И хотя логично предположить, что сортировка будет по текстовому ключу, закладываться на это не стоит, так как в документации ничего об этом не говорится
С последним примером для меня большей неожиданностью оказалось то, что NULL приводится к пустому массиву.
ARRAY[1,2] || 3 => 1,2,3
ARRAY[1,2] || NULL => 1,2
ARRAY[1,2] || [NULL] => 1,2,NULL

Взял на заметку, что если хочу явно приклеивать в том числе NULL, то нужно явно указывать массив.
Да, это равносильно SELECT array[1, 2] || NULL::int[]. Если же мы явно приведем NULL к int, база увидит, что это не массив, а элемент массива, и добавит его к имеющимся, т.е. SELECT array[1, 2] || NULL::int даст {1,2,NULL}

Это не странности, это некоторая определенна реализация функционала, покрытая юнит-тестами (и потому стабильная). Могла бы быть и другая реализация, но какая разница? Сделали, как проще и как по дефолту, как меньше ифов в коде и краевых случаев.

Тут даже вопрос не в том, что функционал стабилен и покрыт юнит-тестами (это де-факто правило хорошего тона для любого качественного продукта, к коему я, безусловно, отношу PostgreSQL). Скорее тут поставили в приоритет удобство использования, а я лишь описал эти особенности, чтобы было под рукой.
Sign up to leave a comment.