Проверка, содержит ли диапазон значение, нарушенное в PQexecPrepared (работает в psql) - PullRequest
1 голос
/ 19 июня 2020

У меня есть этот (довольно уродливый, сгенерированный) подготовленный оператор для получения некоторых игровых данных. Я пытаюсь проверить, содержится ли значение ($ 3) в spawn_level_range (которое является int4range), выполнив $3<@quests.spawn_level_range:

SELECT quests.id,
       quests.base_attack,
       quests.base_strg,
       quests.base_accy,
       quests.base_hp,
       quests.name,
       quests.task,
       quests.image_url,
       quests.spawn_chance
FROM quests
WHERE (((quests.server_id=$1)
  AND ((quests.channel_id='all') OR (quests.channel_id=$2)))
  AND ($3<@quests.spawn_level_range))
ORDER BY RANDOM()
LIMIT 1;

Этот точный запрос отлично работает при вставке в psql когда я добавляю:

prepare test (varchar, varchar, int) AS

, затем запускаю его с помощью:

execute test('669105577238069249', '682205516667158549', 1);

Однако по какой-то причине он просто не работает в libpq.

При запуске оператор с PQexecPrepared, он вызывает ошибку:

ERROR:  malformed range literal: "1"
DETAIL:  Missing left parenthesis or bracket.

(обратите внимание, что 1 - это то, что я пытаюсь привязать $3 к)

Кажется, он пытается интерпретировать $3 как диапазон (а не integer) - что мне кажется ошибкой.

1 Ответ

1 голос
/ 19 июня 2020

В подготовленном операторе вы явно объявляете третий параметр как integer.

В своем вызове PQprepare (который вы не показывали) вы, должно быть, пренебрегли установкой paramTypes аргумент для указания типов параметров, так что все они от unknown до PostgreSQL, и он выводит тип данных из контекста.

Теперь есть два оператора <@ для диапазонов:

  • anyrange <@ anyrange
  • anyelement <@ anyrange

Не зная, какой из них вы хотите, PostgreSQL s правила разрешения типов данных предпочитать оператор, который имеет одинаковый тип данных с обеих сторон.

Есть два возможных решения:

  • укажите правильный тип в paramTypes аргументе PQprepare
  • добавить в запрос явное приведение типа: CAST ($3 AS integer)
...