Почему оператор intarray недоступен, когда запрос вызывается с использованием PDO?

PostgreSQL версии 14

У меня есть запрос, который при запуске из pgAdmin ведет себя иначе, чем при запуске из PHP.

SELECT * FROM UNNEST('{1,2,3,4,5}'::integer[] - '{2,4}'::integer[])

Когда я запускаю это из pgAdmin, все работает нормально. Когда я передаю его через PHP с помощью PDO, я получаю ОШИБКА: оператор не существует: целое число[] - целое число[].

Этот оператор массива предоставляется модулем intarray. CREATE EXTENSION intarray сообщает мне, что расширение уже установлено. Это похоже на то, что модуль intarray по какой-то причине недоступен для процесса PHP.

Может ли кто-нибудь указать мне правильное направление относительно того, что здесь может происходить?

Лучше всего предположить, что база данных, к которой вы подключаетесь с помощью кода PHP, отличается от той, к которой вы подключаетесь в pgAdmin4. Проверьте это, проверив журнал Postgres.

Adrian Klaver 07.08.2024 23:20

Где находится php-код, который вызывает ошибку?

u_mulder 07.08.2024 23:20

Возможно, это ограничение PDO по сравнению с драйвером pg_*.

Alex Howansky 07.08.2024 23:31

@AdrianKlaver: Та же база данных, но другой пользователь. Один с меньшим количеством разрешений. Я попробую запустить от имени этого пользователя и посмотреть, смогу ли я повторить. u_mulder: Этот код работает нормально уже много лет. Только эта ситуация является проблемой, поэтому я не думаю, что это общая проблема PHP, если только, как предполагает Алекс Ховански, это не особенность PDO.

EMF 07.08.2024 23:37

Я попытался сделать пользователя суперпользователем. Никаких изменений.

EMF 07.08.2024 23:50

Ошибка довольно специфична: проблема связана с оператором - для массивов, который предоставляется intarray. Я не понимаю, как может быть что-то еще, кроме того, что intarray не установлен или недоступен. В psql что означает \dx возврат на продление. Также проверьте журнал Postgres для получения дополнительной информации.

Adrian Klaver 08.08.2024 00:16

Посмотрите эту скрипку.

Zegarek 08.08.2024 01:11

@Zegarek: БИНГО!!! intarray является общедоступным, и существует код, явно устанавливающий путь поиска к определенной схеме без включения public. Пожалуйста, опубликуйте это как ответ, чтобы я мог принять его.

EMF 08.08.2024 01:26
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Symfony Station Communiqué - 7 июля 2023 г
Symfony Station Communiqué - 7 июля 2023 г
Это коммюнике первоначально появилось на Symfony Station .
Оживление вашего приложения Laravel: Понимание режима обслуживания
Оживление вашего приложения Laravel: Понимание режима обслуживания
Здравствуйте, разработчики! В сегодняшней статье мы рассмотрим важный аспект управления приложениями, который часто упускается из виду в суете...
Установка и настройка Nginx и PHP на Ubuntu-сервере
Установка и настройка Nginx и PHP на Ubuntu-сервере
В этот раз я сделаю руководство по установке и настройке nginx и php на Ubuntu OS.
Коллекции в Laravel более простым способом
Коллекции в Laravel более простым способом
Привет, читатели, сегодня мы узнаем о коллекциях. В Laravel коллекции - это способ манипулировать массивами и играть с массивами данных. Благодаря...
Как установить PHP на Mac
Как установить PHP на Mac
PHP - это популярный язык программирования, который используется для разработки веб-приложений. Если вы используете Mac и хотите разрабатывать...
1
9
81
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Согласно комментарию @Adrian Klaver, полезно сначала подтвердить, что ваше PHP-приложение и клиент, с которым вы запускали тесты, оба подключаются к одному и тому же кластеру и на нем есть одна и та же база данных, которая установили intarray. Несколько экземпляров, работающих на одном хосте или за установленными на нем туннелями, опечатки в имени базы данных или номере порта могут скрыть тот факт, что вы имеете дело с разными, несовпадающими базами данных.

Поскольку вы можете подтвердить, что это не так, моя ставка будет заключаться в том, что intarray установлен только в пространстве имен, которое не отображается в вашем search_path/ current_schemas(true), когда вы запускаете тесты из приложения PHP.
Вы можете проверить, где это: демо на db<>fiddle

create schema some_other_schema;
create extension intarray schema some_other_schema;
select extname,extnamespace::regnamespace from pg_extension;
добавочное имя пространство extname plpgsql pg_catalog интаррей some_other_schema
select e.extnamespace::regnamespace
     , p.oprnamespace::regnamespace
     , e.extname
     , p.oid::regoperator
     , p.oprname
     , p.oprcode::regprocedure
from pg_catalog.pg_operator as p
join pg_catalog.pg_depend    as d on (d.objid    = p.oid)
join pg_catalog.pg_extension as e on (d.refobjid = e.oid)
where e.extname='intarray'
  and p.oprname='-';
пространство extname пространство имен добавочное имя оид имя_опра код операции some_other_schema some_other_schema интаррей some_other_schema.-(целое число[],целое число) - some_other_schema.intarray_del_elem(целое число[],целое число) some_other_schema some_other_schema интаррей some_other_schema.-(целое число[],целое число[]) - some_other_schema.intset_subtract(целое число[],целое число[])

Как только вы убедитесь, где он находится, добавьте квалификацию схемы оператора с помощью operator() :

select array[1,2] operator(some_other_schema.-) array[2,3];

Или добавьте схему в search_path:

select set_config( 'search_path'
                  ,'some_other_schema, '
                   ||current_setting('search_path')
                  ,false);

Это позволяет пропустить квалификацию схемы оператора:

select array[1,2] - array[2,3];

Стоит отметить, что вопреки тому, что следует из названия расширения, intarrayint[] - int[] вычитает множества, а не массивы. Перед вычитанием оба операнда будут отсортированы и дедуплицированы. Станет немного яснее, если вы проверите, что вариант -, вычитающий все остальное int[], называется intset_subtract, а вариант, вычитающий один элемент, называется intarray_del_elem и не выполняет молчание uniq(sort()).

Этот ответ решил мою проблему. intarray установлен публично, и мой путь поиска в PHP не включал public. Спасибо!!!!

EMF 08.08.2024 22:37

Другие вопросы по теме