product_no integer DEFAULT nextval('products_product_no_seq'),
...
);
Почему аргумент для nextval выглядит именно так и оно работает: 'tablename_colname_?'
Что здесь означает seq?
Какие ещё есть типичные случаи для default, когда вместо скалярного значения у нас функция?
Это то, во что postgres автоматически преобразует create table ( product_no serial )
Нет, то что именно это в serial преобразуется - это я знаю. Мне важнее понять скорее какие-то околоподкапотные вещи. Вот что дока пишет: "Последовательность, к которой будет обращаться одна из этих функций, определяется аргументом regclass, задающим просто OID последовательности в системном каталоге pg_class". Мне важнее понять, откуда берётся products_product_no_seq - если мы его руками не объявляли и как он разрешается.
>products_product_no_seq Создаётся при создании колонки типа serial. > и как он разрешается. Не очень понял -- в какой момент. Но в общем -- хранится оно в виде pg_node_tree в таблицэ pg_attrdef. \d+ показывает это в человеческом виде. В том числе печатает константу вида regclass как relname из pg_class. Планнер берёт NodeTree, если можэт -- несколько преобразовывает, затем выполняет. Реально внутри pg_node_tree эта константа хранится в виде восьми байт oid. Посмотреть чуть менее человеческий вид pg_node_tree можно выборкой из pg_attrdef (но это тожэ не тот бинарник, который там лежыт). То есть глубоко распарзенная структура pg_node_tree/NodeTree.
Я, кстати, ошыбся. pg_node_tree внутри базы -- это именно тот текст, который показывается по SELECT adbin FROM pg_attrdef; Удивлён.
Спасибо за ответ. Прихожу к выводу, что Постгрес это Вселенная ) А есть какие-то мысли по поводу какие-то примеров изощрённых юзкейсов с DEFAULT, когда там какое-то сложное выражение или ещё что-то?
Да так-то дофига, а вам зачем?
Партия сказала дописывать один DSL для Postgres. Вот этот: https://pgconf.ru/2021/287996
То есть нередко вычислимые колонки записывают как default, и там могут быть хоть джойны с агрегатами из других таблиц.
Соответственно, базовая часть написана - мне надо копать вширь и вглубь, чтобы дополнить уже сделанное. Сейчас я стал разбираться с CREATE TABLE, там достаточно много опций, для некоторых из которых - у меня просто недостаточно "кругозора", чтобы представить какие-то более сложные юзкейсы.
Вообще-то нет, не могут (что в generated, что в default).
Есть своё своеобразие там, да.
Тогда Ваша версия какая?) Т.е. в default у нас приходит либо относительно примитивное значение (составные типы и иже с ними считаем примитивами в этом контексте), либо результат каких-то вычислений, НО объявленный как функция. Так вот мой вопрос именно в этом - какие это могут быть функции. Можно просто ткнуть меня в доку, статью или ещё какой-то материал.
Ещё выражэния (т.е. применение операторов к каким-то константам и функцыям). Но вопрос "какие" не понят. Объявленные в pg_proc, очевидно.
Но запросы в рамках default выполнять мы не можем?
Я -- могу. Обернуть в функцыю и выполнять. Всё работает.
Я, кстати, дажэ не помню -- почему там какие-то проблемы с запросами. Вроде так-то в NodeTree запрос можэт быть записан.
Потому что их нельзя оптимизировать. На пакетную вставку 1000 строк будет дополнительно 1000 запросов, которые при ином подходе можно было бы собрать в один. Не надо туда впихивать запросы, это импакт производительности колоссальный.
(Пожав плечами) мало ли что у нас нельзя оптимизировать. Триггеры вон те жэ -- тожэ. Ну, не то чтобы нельзя -- пока не оптимизируются. И вообще -- а если меня не беспокоит пакетная вставка тысячи строк по каким-то причинам? (Например, вставка будет происходить раз в день и по одной строке?)
Тогда обернуть в функцию и всё сработает. Ограничение чисто синтаксическое. Но сам подход не очень. Это как специально раскладывать грабли, чтобы в нужный момент сходу по всем пробежаться ))
Я как-то как раз не вижу граблей. Код как код. Только почему-то запрещённый.
Верно, чтобы на грабли наступить - нужно чтобы их не было видно. Если бы грабли было сразу видно - никто бы на них не наступал 😉
Ничего подобного! Это прямо запрещено документацией. Точнее, там написано, что если будете делать такие вещи, а потом Ваша база "сломается" — к примеру, перестанет dump-иться/загружаться из дампа (тут такое, показывали, кстати) или начнёт выдавать не те результаты запросов) — это только Ваши проблемы, не нужно потом ныть писать в -bugs по этому поводу. ;)
Я же так и сказал - раскладывать грабли )
Потому что требование ко всем этим штукам — must be immutable. "Обманываете" сервер? Получите "сюрприз". ;)
Где? "DEFAULT default_expr The DEFAULT clause assigns a default data value for the column whose column definition it appears within. The value is any variable-free expression (subqueries and cross-references to other columns in the current table are not allowed). The data type of the default expression must match the data type of the column. The default expression will be used in any insert operation that does not specify a value for the column. If there is no default for a column, then the default is null." Ты точно с CHECK не путаешь?
У нас now() или nextval() что ли immutable?
Частично путаю (вот что значит писать "урывками"), а как же. ;) https://dbfiddle.uk/?rdbms=postgres_13&fiddle=594d837bb8b1bad74be84b1a7338b2d7
Оно STABLE же ж.
А, про этих. Да, понял мысль и откуда взялось. Любопытно, но это другое.
nextval VOLATILE конечно. Я половину вопроса прочёл )
Кстати, разница в подходах к AS IDENTITY и вот этой просто функцыей -- показывает, что этот подход GENERATED хорошо бы ещё обдумывать и обдумывать.
Я сходу не помню, но мне кажется, что таковы требования ISO SQL (чтобы работало не только в случае STORED). Если так, то обдумывать тут нечего. ;)
Хмм... а какой вопрос-то, конкретно? ;) > Так вот мой вопрос именно в этом - какие это могут быть функции. Практически любое выражение там может быть, если речь именно про column default.
Вот уж кто точно не стена -- подвинется! Что-то, а невыдавать ошыбки там, где ISO SQL говорит что можно выдавать -- это совсем стандартная практика.
Не в PostgreSQL. В общем-то, фактическое отношение разработчиков к такому — "Мы тут молимся на следуем стандарту. Не нравится? Так поищите другую СУБД, никто не заставляет пользоваться." ;)
Это Том Лейн или Брюс Момхан так говорил?
А никто это явно именно так [грубо] не говорил — они люди вежливые, в основном. Я же пишу о фактическом отношении, понимаете? ;)
Я такого банально не встречал. Против люди бывают -- когда появляется что-то, ломающее какую-то допустимую стандартом практику. А наоборот...
Пришли к тому, что не любые, а только ноль-арные и те, которые не выполняют запросы/подзапросы (технически - оно может заработать, но в целом это антипаттерн). Это и есть ответ на мой вопрос )
nextval опять запретили? (Он не ноль-арный).
Да ладно? Тогда почему, например: 1. В PostgreSQL тщательно (но криво, хе-хе) вписаны все ограничения из ISO SQL на допустимые в рекурсивных CTE конструкции, хотя в самой реализации таких тупо нет (т.е. он мощнее, чем требуется стандартом, и искусственно ограничивается). 2. На все вопросы о том, почему это у нас изменение типов полей практически невозможно, если они используются во view, всех банально посылают почитать стандарт (хотя могли бы реализовать почти наверняка!), где это запрещается? 3. Любые попытки расширения стандарта принимаются "в штыки" (я помню, как мучительно протаскивали [NOT] MATERIALIZED в CTE, например)? Ну и т.д. и т.п., сходу не вспоминается.
Подождите... откуда Вы это взяли? Запросы / подзапросы в функциях DEFAULT не запрещаются, они вообще могут быть любыми. Ограничение на запросы именно в выражении default — только синтаксическое (т.е. в этом месте синтаксисом требуется именно выражение, и всё).
2. Так и правда морока ведь менять rule, этот всё дерево Node вообще практически write-once для разработчиков.
Но ALTER VIEW меняет почему-то. И все зависимости уже есть в системе. Т.е. ответ даётся не в стиле "это трудно реализовать", а в стиле "стандарт это запрещает, см. рис. 1". ;)
https://t.me/pgsql/334088 https://t.me/pgsql/334091
Я же потом написал, что ошибся. Это относится только к CHECK и GENERATED, но не относится к DEFAULT.
Обсуждают сегодня