首页 > 解决方案 > 检查范围是否包含在 PQexecPrepared 中损坏的值(在 psql 中工作)

问题描述

我有这个(相当丑陋的,生成的)准备好的语句来获取一些游戏数据。我尝试通过执行以下操作检查值($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)——这对我来说似乎是一个错误。

标签: postgresqllibpq

解决方案


在您准备好的语句中,您将第三个参数显式声明为integer.

在您的PQprepare调用(您没有显示)中,您一定忽略了设置paramTypes参数以指示参数的类型,因此它们都是unknownPostgreSQL 的,它从上下文中推断出数据类型。

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

  • anyrange <@ anyrange
  • anyelement <@ anyrange

不知道你想要哪一个,PostgreSQL 的数据类型解析规则更喜欢两边数据类型相同的运算符。

有两种可能的解决方案:

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

推荐阅读