检查范围是否包含在 PQexecPrepared 中损坏的值(适用于 psql)

Checking if a range contains a value broken in PQexecPrepared (works in psql)

我有这个(相当难看,生成的)准备好的语句来获取一些游戏数据。我尝试通过执行 <@quests.spawn_level_range:

来检查 spawn_level_range(这是一个 int4range)中是否包含一个值 ($3)
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=)
  AND ((quests.channel_id='all') OR (quests.channel_id=)))
  AND (<@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 是我要将 </code> 绑定到的内容)</p> <p>它似乎试图将 <code> 解释为一个范围(而不是 integer)——这对我来说似乎是一个错误。

在准备好的语句中,您明确声明第三个参数为 integer

在你的 PQprepare 调用中(你没有显示)你一定是忽略了设置 paramTypes 参数来指示参数的类型,所以它们都是 unknown 到 PostgreSQL,它从上下文推断数据类型。

现在有两个运算符 <@ 用于范围:

  • anyrange <@ anyrange
  • anyelement <@ anyrange

不知道你想要哪个,PostgreSQL 的 data type resolution rules 更喜欢两边具有相同数据类型的运算符。

有两种可能的解决方案:

  • PQprepare
  • paramTypes 参数中指定正确的类型
  • 向查询添加显式类型转换:CAST ( AS integer)