Гость
Форумы / PostgreSQL [игнор отключен] [закрыт для гостей] / Нетипизированный массив-литерал не приводится к типу второго операнда / 15 сообщений из 15, страница 1 из 1
11.04.2021, 14:09
    #40061446
Cyrax_02
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Нетипизированный массив-литерал не приводится к типу второго операнда
В таблице table имеется поле field типа int2[] с индексом GIN(array_ops) .
Выполняем следующий поисковый запрос:
Код: sql
1.
2.
SELECT ... FROM "table" WHERE field OPERATOR(pg_catalog.&&) ARRAY[8];
-- SQL Error [42883]: ОШИБКА: оператор не существует: smallint[] pg_catalog.&& integer[]

Здесь вместо && указывается 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(...) ? Поиск как всегда не работает.
...
Рейтинг: 0 / 0
11.04.2021, 15:22
    #40061455
Maxim Boguk
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Нетипизированный массив-литерал не приводится к типу второго операнда
Cyrax_02
В таблице table имеется поле field типа int2[] с индексом GIN(array_ops) .
Выполняем следующий поисковый запрос:
Код: sql
1.
2.
SELECT ... FROM "table" WHERE field OPERATOR(pg_catalog.&&) ARRAY[8];
-- SQL Error [42883]: ОШИБКА: оператор не существует: smallint[] pg_catalog.&& integer[]

Здесь вместо && указывается 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
...
Рейтинг: 0 / 0
11.04.2021, 17:56
    #40061470
Cyrax_02
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Нетипизированный массив-литерал не приводится к типу второго операнда
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). Числа представляются как строковые литералы.
...
Рейтинг: 0 / 0
11.04.2021, 18:08
    #40061472
Cyrax_02
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Нетипизированный массив-литерал не приводится к типу второго операнда
авторP.S. Даже в самом PostgreSQL функция format предусматривает только строковые литералы и литералы массивов (%L). Числа представляются как строковые литералы.Хотел написать так: " В PostgreSQL функция format числовые литералы представляет как строковые (%L) ".
...
Рейтинг: 0 / 0
11.04.2021, 18:34
    #40061473
Melkij
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Нетипизированный массив-литерал не приводится к типу второго операнда
Cyrax_02
Кто знает, где в справке описывается конструктор OPERATOR(...)

https://www.postgresql.org/docs/current/ddl-schemas.html#DDL-SCHEMAS-PATH
...
Рейтинг: 0 / 0
11.04.2021, 18:46
    #40061475
Cyrax_02
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Нетипизированный массив-литерал не приводится к типу второго операнда
Как оказалось, в 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.
SELECT ... FROM "table" WHERE field OPERATOR(pg_catalog.&&) '{8}';
-- OK (нетипизированный литерал массива '{8}' автоматически приводится к типу левого операнда int2[])


P.S
.Только вот оператор здесь по-прежнему необходимо указывать со схемой - иначе для int2[] && unknown PostgreSQL не сможет выбрать оператор между int4[] && int4[] и anyarray && anyarray .
...
Рейтинг: 0 / 0
11.04.2021, 18:57
    #40061477
Cyrax_02
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Нетипизированный массив-литерал не приводится к типу второго операнда
Да, оно самое: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;Значит, только по имени схемы можно обращаться. По имени расширения нельзя.
...
Рейтинг: 0 / 0
11.04.2021, 19:10
    #40061480
Maxim Boguk
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Нетипизированный массив-литерал не приводится к типу второго операнда
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.
mboguk=# select ARRAY[100]::int[] && ARRAY[8]::smallint[];
ERROR:  operator does not exist: integer[] && smallint[]
LINE 1: select ARRAY[100]::int[] && ARRAY[8]::smallint[];
                                 ^
HINT:  No operator matches the given name and argument types. You might need to add explicit type casts.
mboguk=# CREATE OR REPLACE FUNCTION int4_int2_overlap(int[], smallint[])
RETURNS boolean
AS
$BODY$
    SELECT pg_catalog.arrayoverlap($1, $2::int[]);
$BODY$
LANGUAGE SQL;
CREATE FUNCTION
mboguk=# CREATE OPERATOR && (
    FUNCTION = int4_int2_overlap,
    LEFTARG = int[],
    RIGHTARG = smallint[]
);
CREATE OPERATOR
mboguk=# select ARRAY[100]::int[] && ARRAY[8]::smallint[];
 ?column? 
----------
 f
(1 row)




--
Maxim Boguk
лучшая поддержка PostgreSQL: dataegret.ru
...
Рейтинг: 0 / 0
11.04.2021, 19:26
    #40061483
Cyrax_02
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Нетипизированный массив-литерал не приводится к типу второго операнда
Значит, операторы всё-таки разрешает создавать на уровне SQL (базовые типы - нет).
В любом случае операторы на уровне SQL будут работать очень медленно. А это критично при выполнении запросов.
А писать на C более трудоёмко + придётся постоянно поддерживать работоспособность от версии к версии.

На данный момент более приемлемым выглядит вариант указания оператора через схему OPERATOR(pg_catalog.&&) + автоприведение типов. Можно прописать константой в ORM или Query Builder'е и использовать в приложении вместо "&&".
...
Рейтинг: 0 / 0
11.04.2021, 19:29
    #40061484
Maxim Boguk
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Нетипизированный массив-литерал не приводится к типу второго операнда
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
...
Рейтинг: 0 / 0
11.04.2021, 19:37
    #40061486
Cyrax_02
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Нетипизированный массив-литерал не приводится к типу второго операнда
Maxim Boguk
PS: а что вы под базовыми типами понимаете?

https://www.postgresql.org/docs/13/sql-createtype.html#id-1.9.3.94.5.8
Для базовых типов функции ввода/вывода на SQL были запрещены в последних версиях PostgreSQL.
...
Рейтинг: 0 / 0
11.04.2021, 19:59
    #40061487
Maxim Boguk
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Нетипизированный массив-литерал не приводится к типу второго операнда
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
...
Рейтинг: 0 / 0
11.04.2021, 20:03
    #40061488
Cyrax_02
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Нетипизированный массив-литерал не приводится к типу второго операнда
Maxim BogukСмысл реализации скалярных типов без поддержки на уровне С кода - от меня ускользает.То же самое относится и к написанным вами выше функции и оператору на уровне SQL.
И операторы, и ввод/вывод базовых типов одинаково критичны при выполнении запросов.
...
Рейтинг: 0 / 0
12.04.2021, 17:03
    #40061781
Cyrax_02
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Нетипизированный массив-литерал не приводится к типу второго операнда
Cyrax_02ARRAY[8] - это не нетипизированный литерал , а выражение-конструктор, возвращающее типизированный литерал типа int4[] или int8[].Правильно так:
ARRAY[8] - это не нетипизированный литерал , а выражение-конструктор, возвращающее типизированный массив типа int4[] .

Maxim Bogukну и в одну схему вы их не засунете в данном случае
потому что один системный и жить ему всегда в pg_catalog
а второй из extension и жить ему где угодно КРОМЕ pg_catalogНапример, устанавливаем два расширения в схему public . Каждое из них создаёт свой оператор && .
Как в этом случае указать, какой именно оператор должен применяться ?
...
Рейтинг: 0 / 0
12.04.2021, 17:39
    #40061797
Melkij
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Нетипизированный массив-литерал не приводится к типу второго операнда
Cyrax_02
Например, устанавливаем два расширения в схему public . Каждое из них создаёт свой оператор && .
Как в этом случае указать, какой именно оператор должен применяться ?

А как такое может произойти?
"pg_operator_oprname_l_r_n_index" UNIQUE, btree (oprname, oprleft, oprright, oprnamespace)
ну а если сами сломаете это ограничение уникальности - то приключения за свой счёт.
...
Рейтинг: 0 / 0
Форумы / PostgreSQL [игнор отключен] [закрыт для гостей] / Нетипизированный массив-литерал не приводится к типу второго операнда / 15 сообщений из 15, страница 1 из 1
Целевая тема:
Создать новую тему:
Автор:
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]