|
Нетипизированный массив-литерал не приводится к типу второго операнда
|
|||
---|---|---|---|
#18+
В таблице table имеется поле field типа int2[] с индексом GIN(array_ops) . Выполняем следующий поисковый запрос: Код: sql 1. 2.
Здесь вместо && указывается OPERATOR(pg_catalog.&&) по следующим причинам: 1) в схеме public установлено расширение intarray с одноимённым оператором int4[] && int4[]. 2) нетипизированный массив-литерал ARRAY[8] по умолчанию приводится к int4[]/int8[] (в данном случае к int4[] ) => применяется оператор int4 && int4 от расширения intarray => GIN-индекс (созданный для типа int2[] ), не применяется. Вопросы : 1) Почему нетипизированный массив-литерал всегда приводится к int4/int8 ? Более корректная логика: приведение нетипизированного массива-литерала к типу парного типизированного операнда (в данном случае = int2[] ). 2) Как на уровне приложения (формирующего запрос к БД) решить проблему типизации массива-литерала ? В общем случае приложение знает только общие типы данных полей (строковое, целочисленное, вещественное, булево, массив и т.д.), но не знает и не должно знать конкретного SQL-типа ( int2[] , int4[] и т.д.). Как в этом случае приложению сформировать корректный (работающий) запрос ? 3) Если оба оператора (стандартный anyarray && anyarray и int4[] && int4[] от intarray ) будут находиться в одной схеме, то как можно будет явно указать, какой оператор должен использоваться ? OPERATOR(???. && ) P.S . Кто знает, где в справке описывается конструктор OPERATOR(...) ? Поиск как всегда не работает. ... |
|||
:
Нравится:
Не нравится:
|
|||
11.04.2021, 14:09 |
|
Нетипизированный массив-литерал не приводится к типу второго операнда
|
|||
---|---|---|---|
#18+
Cyrax_02 В таблице table имеется поле field типа int2[] с индексом GIN(array_ops) . Выполняем следующий поисковый запрос: Код: sql 1. 2.
Здесь вместо && указывается OPERATOR(pg_catalog.&&) по следующим причинам: 1) в схеме public установлено расширение intarray с одноимённым оператором int4[] && int4[]. 2) нетипизированный массив-литерал ARRAY[8] по умолчанию приводится к int4[]/int8[] (в данном случае к int4[] ) => применяется оператор int4 && int4 от расширения intarray => GIN-индекс (созданный для типа int2[] ), не применяется. Вопросы : 1) Почему нетипизированный массив-литерал всегда приводится к int4/int8 ? Более корректная логика: приведение нетипизированного массива-литерала к типу парного типизированного операнда (в данном случае = int2[] ). 2) Как на уровне приложения (формирующего запрос к БД) решить проблему типизации массива-литерала ? В общем случае приложение знает только общие типы данных полей (строковое, целочисленное, вещественное, булево, массив и т.д.), но не знает и не должно знать конкретного SQL-типа ( int2[] , int4[] и т.д.). Как в этом случае приложению сформировать корректный (работающий) запрос ? 3) Если оба оператора (стандартный anyarray && anyarray и int4[] && int4[] от intarray ) будут находиться в одной схеме, то как можно будет явно указать, какой оператор должен использоваться ? OPERATOR(???. && ) P.S . Кто знает, где в справке описывается конструктор OPERATOR(...) ? Поиск как всегда не работает. 1)потому что определение типов вводных данных производится задолго ДО ТОГО КАК смотрим какой там тип на другой стороне (и даже до того как он может быть хотя бы теоретически быть известным)... более того ваша идея полностью ломает возможность использования/создания операторов int2+int8 например ну и как вы предлагаете тогда определять типы в конструкции 1+100000000 в вашей парадигме? 2)"В общем случае приложение знает только общие типы данных полей" - приложение должно знать и учитывать и в нормальной ситуации ПРИНУДИТЕЛЬНО всегда приводить к нужным типам... автоприведение типов вообще минное поле... вот сколько должно быть field1(тип int4)+ 0.03 ? а сколько должно быть 2/5 ? автор запросов должен знать типы полей и приводить литералы к нужным типам (ORM кстати основные это умеют и делают) для типовых случаев типа '+' есть просто операторы для всех вероятных сочетаний (для целочисленных все 9 операторов по матрице smallint/int/bigint) для array[] && операторов просто не сделали такие наборы... поэтому там надо руками приводить. 3)на этот вопрос читайте ответ тут вот: https://www.postgresql.org/docs/13/typeconv-oper.html в части "Look for the best match." ну и в одну схему вы их не засунете в данном случае потому что один системный и жить ему всегда в pg_catalog а второй из extension и жить ему где угодно КРОМЕ pg_catalog 4)OPERATOR - служебная конструкция чем меньше вы ее используете тем лучше )). -- Maxim Boguk лучшая поддержка PostgreSQL: dataegret.ru ... |
|||
:
Нравится:
Не нравится:
|
|||
11.04.2021, 15:22 |
|
Нетипизированный массив-литерал не приводится к типу второго операнда
|
|||
---|---|---|---|
#18+
Maxim Boguk1) потому что определение типов вводных данных производится задолго ДО ТОГО КАК смотрим какой там тип на другой стороне (и даже до того как он может быть хотя бы теоретически быть известным)...Определение типа нетипизированного операнда можно отложить до соответствующего момента, либо тип нетипизированного операнда пересмотреть в соответствующий момент. Это уже вопрос реализации , а не логики. Логика первостепенна. Maxim Bogukболее того ваша идея полностью ломает возможность использования/создания операторов int2+int8 например ну и как вы предлагаете тогда определять типы в конструкции 1+100000000 в вашей парадигме? ...вот сколько должно быть field1(тип int4)+ 0.03 ? а сколько должно быть 2/5 ?Логика " приведение типа нетипизированного литерала к совместимому типу парного типизированного операнда" к вашим примерам неприменима (в первом примере с обоих сторон - типизированные операнды, во втором примере типы несовместимы). А вот к сабжевому примеру - применима. Maxim Bogukприложение должно знать и учитывать и в нормальной ситуации ПРИНУДИТЕЛЬНО всегда приводить к нужным типам... автоприведение типов вообще минное поле... Автор запросов должен знать типы полей и приводить литералы к нужным типам (ORM кстати основные это умеют и делают) Насколько я себе представляю, все ORM в составе фреймворков как раз и реализуют то самое автоприведение типов литералов. А если ORM базируется на надстройках типа php-ного PDO, то это самое приведение реализуется на самом примитивном уровне (целое, строка, булево и, возможно, вещественное). Допустим, в БД для некоторого поля мы изменили тип поля с int2 на int4 . В этом случае потребуется изменить тип приведения во всех связанных запросах по всему коду приложения. Таких мест может быть и 10, и 100, и 1000. И менять придётся вручную (IDE-рефакторинг не поможет). Если же автоприведение всё-таки реализуется на уровне ORM, то чем оно принципиально отличается от автоприведения, реализуемого на уровне СУБД ? На уровне СУБД автоприведение всегда будет надёжнее и безопаснее. P.S . Даже в самом PostgreSQL функция format предусматривает только строковые литералы и литералы массивов (%L). Числа представляются как строковые литералы. ... |
|||
:
Нравится:
Не нравится:
|
|||
11.04.2021, 17:56 |
|
Нетипизированный массив-литерал не приводится к типу второго операнда
|
|||
---|---|---|---|
#18+
авторP.S. Даже в самом PostgreSQL функция format предусматривает только строковые литералы и литералы массивов (%L). Числа представляются как строковые литералы.Хотел написать так: " В PostgreSQL функция format числовые литералы представляет как строковые (%L) ". ... |
|||
:
Нравится:
Не нравится:
|
|||
11.04.2021, 18:08 |
|
Нетипизированный массив-литерал не приводится к типу второго операнда
|
|||
---|---|---|---|
#18+
Cyrax_02 Кто знает, где в справке описывается конструктор OPERATOR(...) https://www.postgresql.org/docs/current/ddl-schemas.html#DDL-SCHEMAS-PATH ... |
|||
:
Нравится:
Не нравится:
|
|||
11.04.2021, 18:34 |
|
Нетипизированный массив-литерал не приводится к типу второго операнда
|
|||
---|---|---|---|
#18+
Как оказалось, в PostgreSQL озвученная логика " приведение типа нетипизированного литерала к совместимому типу парного типизированного операнда " уже реализована: https://www.postgresql.org/docs/13/typeconv-oper.htmlIf one argument of a binary operator invocation is of the unknown type, then assume it is the same type as the other argument for this check. Invocations involving two unknown inputs, or a unary operator with an unknown input, will never find a match at this step.А почему это самое автоприведение не работало в сабжевом запросе - потому что с обоих сторон были указаны типизированные операнды. ARRAY[8] - это не нетипизированный литерал , а выражение-конструктор, возвращающее типизированный литерал типа int4[] или int8[] . Нетипизированный литерал массива (с типом данных " unknown ") - это строка '{8}' : Код: sql 1. 2.
P.S .Только вот оператор здесь по-прежнему необходимо указывать со схемой - иначе для int2[] && unknown PostgreSQL не сможет выбрать оператор между int4[] && int4[] и anyarray && anyarray . ... |
|||
:
Нравится:
Не нравится:
|
|||
11.04.2021, 18:46 |
|
Нетипизированный массив-литерал не приводится к типу второго операнда
|
|||
---|---|---|---|
#18+
Да, оно самое:https://www.postgresql.org/docs/current/ddl-schemas.html#DDL-SCHEMAS-PATHIf you need to write a qualified operator name in an expression, there is a special provision: you must write OPERATOR(schema.operator) This is needed to avoid syntactic ambiguity. An example is: SELECT 3 OPERATOR(pg_catalog.+) 4;Значит, только по имени схемы можно обращаться. По имени расширения нельзя. ... |
|||
:
Нравится:
Не нравится:
|
|||
11.04.2021, 18:57 |
|
Нетипизированный массив-литерал не приводится к типу второго операнда
|
|||
---|---|---|---|
#18+
Cyrax_02, То что вы хотите в PG решается не через умное приведение типов (оно там и так слишком умное с моей т.з) а через заведение совместимых операторов на все очевидно совместимые комбинации. В данном случае проблема в отсутствии оператора smallint[] && integer[] (и вообще в отсутствии cross-compatible-type операций на массивах). в принципе мы его вполне себе можете сами описать я думаю и разместить в схеме public и даже GIN поддержку наверное можно будет без С хакинга вставить (но тут я уже не уверен проверять надо). Равно как и + в случае smallint_var + bigint_constant не занимается попыткой угадать типы чтобы + совместимый был а просто использует smallint+bigint оператор заданный в системе. Вот вам прототип если очень хочется покопать: Код: sql 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19. 20. 21. 22. 23. 24.
-- Maxim Boguk лучшая поддержка PostgreSQL: dataegret.ru ... |
|||
:
Нравится:
Не нравится:
|
|||
11.04.2021, 19:10 |
|
Нетипизированный массив-литерал не приводится к типу второго операнда
|
|||
---|---|---|---|
#18+
Значит, операторы всё-таки разрешает создавать на уровне SQL (базовые типы - нет). В любом случае операторы на уровне SQL будут работать очень медленно. А это критично при выполнении запросов. А писать на C более трудоёмко + придётся постоянно поддерживать работоспособность от версии к версии. На данный момент более приемлемым выглядит вариант указания оператора через схему OPERATOR(pg_catalog.&&) + автоприведение типов. Можно прописать константой в ORM или Query Builder'е и использовать в приложении вместо "&&". ... |
|||
:
Нравится:
Не нравится:
|
|||
11.04.2021, 19:26 |
|
Нетипизированный массив-литерал не приводится к типу второго операнда
|
|||
---|---|---|---|
#18+
Cyrax_02 Значит, операторы всё-таки разрешает создавать на уровне SQL (базовые типы - нет). В любом случае операторы на уровне SQL будут работать очень медленно. А это критично при выполнении запросов. А писать на C более трудоёмко + придётся постоянно поддерживать работоспособность от версии к версии. На данный момент более приемлемым выглядит вариант указания оператора через схему OPERATOR(pg_catalog.&&) . Можно прописать константой в ORM или Query Builder'е и использовать в пользовательском коде вместо "&&". Да и типы тоже позволяет на самом деле. https://www.postgresql.org/docs/13/sql-createtype.html PS: а что вы под базовыми типами понимаете? -- Maxim Boguk лучшая поддержка PostgreSQL: dataegret.ru ... |
|||
:
Нравится:
Не нравится:
|
|||
11.04.2021, 19:29 |
|
Нетипизированный массив-литерал не приводится к типу второго операнда
|
|||
---|---|---|---|
#18+
Maxim Boguk PS: а что вы под базовыми типами понимаете? https://www.postgresql.org/docs/13/sql-createtype.html#id-1.9.3.94.5.8 Для базовых типов функции ввода/вывода на SQL были запрещены в последних версиях PostgreSQL. ... |
|||
:
Нравится:
Не нравится:
|
|||
11.04.2021, 19:37 |
|
Нетипизированный массив-литерал не приводится к типу второго операнда
|
|||
---|---|---|---|
#18+
Cyrax_02 Maxim Boguk PS: а что вы под базовыми типами понимаете? https://www.postgresql.org/docs/13/sql-createtype.html#id-1.9.3.94.5.8 Для базовых типов функции ввода/вывода на SQL были запрещены в последних версиях PostgreSQL. Смысл реализации скалярных типов без поддержки на уровне С кода - от меня ускользает. -- Maxim Boguk лучшая поддержка PostgreSQL: dataegret.ru ... |
|||
:
Нравится:
Не нравится:
|
|||
11.04.2021, 19:59 |
|
Нетипизированный массив-литерал не приводится к типу второго операнда
|
|||
---|---|---|---|
#18+
Maxim BogukСмысл реализации скалярных типов без поддержки на уровне С кода - от меня ускользает.То же самое относится и к написанным вами выше функции и оператору на уровне SQL. И операторы, и ввод/вывод базовых типов одинаково критичны при выполнении запросов. ... |
|||
:
Нравится:
Не нравится:
|
|||
11.04.2021, 20:03 |
|
Нетипизированный массив-литерал не приводится к типу второго операнда
|
|||
---|---|---|---|
#18+
Cyrax_02ARRAY[8] - это не нетипизированный литерал , а выражение-конструктор, возвращающее типизированный литерал типа int4[] или int8[].Правильно так: ARRAY[8] - это не нетипизированный литерал , а выражение-конструктор, возвращающее типизированный массив типа int4[] . Maxim Bogukну и в одну схему вы их не засунете в данном случае потому что один системный и жить ему всегда в pg_catalog а второй из extension и жить ему где угодно КРОМЕ pg_catalogНапример, устанавливаем два расширения в схему public . Каждое из них создаёт свой оператор && . Как в этом случае указать, какой именно оператор должен применяться ? ... |
|||
:
Нравится:
Не нравится:
|
|||
12.04.2021, 17:03 |
|
Нетипизированный массив-литерал не приводится к типу второго операнда
|
|||
---|---|---|---|
#18+
Cyrax_02 Например, устанавливаем два расширения в схему public . Каждое из них создаёт свой оператор && . Как в этом случае указать, какой именно оператор должен применяться ? А как такое может произойти? "pg_operator_oprname_l_r_n_index" UNIQUE, btree (oprname, oprleft, oprright, oprnamespace) ну а если сами сломаете это ограничение уникальности - то приключения за свой счёт. ... |
|||
:
Нравится:
Не нравится:
|
|||
12.04.2021, 17:39 |
|
|
start [/forum/topic.php?fid=53&msg=40061455&tid=1994087]: |
0ms |
get settings: |
9ms |
get forum list: |
15ms |
check forum access: |
4ms |
check topic access: |
4ms |
track hit: |
27ms |
get topic data: |
9ms |
get forum data: |
3ms |
get page messages: |
51ms |
get tp. blocked users: |
1ms |
others: | 261ms |
total: | 384ms |
0 / 0 |