PostgreSQL:LISTEN 的参数替换?
PostgreSQL: Parameter substitution for LISTEN?
常识表明 SQL 查询字符串 永远 不应手动组装。因此,所有数据库接口都提供参数替换,所有用户都使用它,无一例外。*
我正在使用 PostgreSQL v10.5、nodejs v8.12.0、node-postgres 7.6.1。
SELECT
语句的参数替换按预期工作:
> await db.query("select from users where id = 'mic'");
(success, 1 row returned)
> await db.query("select from users where id = ", ["mic"]);
(success, 1 row returned)
但它不适用于 LISTEN
语句:
> await db.query("listen topicname");
(success)
> await db.query("listen ", ["topicname"]);
(error: syntax error at or near "")
我想听的话题名称是动态的。它来自半可信的来源,不应该是用户可控的。但是为什么要违背所有既定的最佳实践并冒险呢?
不幸的是,根据我的测试,我担心 PostgreSQL 根本无法对 LISTEN
查询进行参数替换。
对此有任何解决方案或解决方法吗?
*)这种说法可能只在某些乌托邦式的未来社会才成立。
你是对的,这不能在 PostgreSQL 中完成。
作为解决方法,编写一个使用 dynamic SQL 的 PL/pgSQL 函数,如下所示:
EXECUTE format('LISTEN %L', topicname);
format
函数正确转义字符串;在这种情况下,生成正确引用字符串 Literal 的 %L
格式是合适的格式。
我没有足够的声誉来评论答案,但建议的解决方案对我不起作用。
使用 %L
会导致带引号的字符串,从而导致以下错误:
ERROR: syntax error at or near "'topic'"
应改用 %I
格式(SQL 标识符,这是针对 table 和列名称记录的,但它也适用于频道名称)。您还可以使用 quote_ident
函数。请参阅有关创建动态查询的文档 here。
以下 PL/pgSQL 函数适用于我们:
CREATE OR REPLACE FUNCTION listenForChannel(
channel_ TEXT
) RETURNS VOID AS $$
BEGIN
EXECUTE format('LISTEN %I', channel_);
END
$$ LANGUAGE PLPGSQL;
常识表明 SQL 查询字符串 永远 不应手动组装。因此,所有数据库接口都提供参数替换,所有用户都使用它,无一例外。*
我正在使用 PostgreSQL v10.5、nodejs v8.12.0、node-postgres 7.6.1。
SELECT
语句的参数替换按预期工作:
> await db.query("select from users where id = 'mic'");
(success, 1 row returned)
> await db.query("select from users where id = ", ["mic"]);
(success, 1 row returned)
但它不适用于 LISTEN
语句:
> await db.query("listen topicname");
(success)
> await db.query("listen ", ["topicname"]);
(error: syntax error at or near "")
我想听的话题名称是动态的。它来自半可信的来源,不应该是用户可控的。但是为什么要违背所有既定的最佳实践并冒险呢?
不幸的是,根据我的测试,我担心 PostgreSQL 根本无法对 LISTEN
查询进行参数替换。
对此有任何解决方案或解决方法吗?
*)这种说法可能只在某些乌托邦式的未来社会才成立。
你是对的,这不能在 PostgreSQL 中完成。
作为解决方法,编写一个使用 dynamic SQL 的 PL/pgSQL 函数,如下所示:
EXECUTE format('LISTEN %L', topicname);
format
函数正确转义字符串;在这种情况下,生成正确引用字符串 Literal 的 %L
格式是合适的格式。
我没有足够的声誉来评论答案,但建议的解决方案对我不起作用。
使用 %L
会导致带引号的字符串,从而导致以下错误:
ERROR: syntax error at or near "'topic'"
应改用 %I
格式(SQL 标识符,这是针对 table 和列名称记录的,但它也适用于频道名称)。您还可以使用 quote_ident
函数。请参阅有关创建动态查询的文档 here。
以下 PL/pgSQL 函数适用于我们:
CREATE OR REPLACE FUNCTION listenForChannel(
channel_ TEXT
) RETURNS VOID AS $$
BEGIN
EXECUTE format('LISTEN %I', channel_);
END
$$ LANGUAGE PLPGSQL;