我有两个相同的 JSON 对象。
第一个对象 | 第二个对象 |
---|---|
[{"id": 123,"firstname": "Mike","lastname": "Smith","ani": 123456,"email": "[电子邮件受保护]"}] | [{"id": 123,"firstname": "Mike","lastname": "Smith","ani": 123456,"email": "[电子邮件受保护]"}] |
但是,在调用 postgres 函数时,postgres(或至少 PgAmdin 4)并没有以相同的方式对待它们...
当我直接从 pgadmin4 调用该函数时,如下所示:
select * from myfunction(123, abc, '[{"id": 123,"firstname": "Mike","lastname": "Smith","ani": 123456,"email": "[email protected]"}]')
注意物体周围的 ' 标记一切正常。
但是,当我从用 Node js 编写的 AWS Lambda 函数调用 postgres 函数时,如下所示:
let callfunction = `SELECT * FROM myfunction($1, $2, $3)`;
const dataResult = await client.query(callfunction, [123, abc, '[{"id": 123,"firstname": "Mike","lastname": "Smith","ani": 123456,"email": "[email protected]"}]']);
这失败了,说:
json 类型的输入语法无效
我认为,它们是相同的函数调用——无论如何,JavaScript 应该构建一个相同的查询。
但是,这个占位符有一些奇怪的地方,因为无论字符、撇号等如何组合,它总是会失败。
我能够让它工作的唯一方法是将对象包含在实际的函数调用本身中,如下所示:
let callfunction = `SELECT * FROM myfunction($1, $2, '[{"id": 123,"firstname": "Mike","lastname": "Smith","ani": 123456,"email": "[email protected]"}]')`;
同样,这“有效”,但在缓解 SQL 注入漏洞方面显然是一个大禁忌......
为什么这个函数调用在参数化时会有这样的行为?
我无法重现该问题,该代码确实应该有效。请注意,撇号与错误消息无关,而且它们无论如何都有不同的用途:在 SQL 代码中,它们分隔 SQL 文字并将被转义为
''
,而在 JavaScript 代码中,它们分隔字符串文字并将被转义作为\'
。
但是,有两个建议:
::json
指定参数的类型,以确保正确解决任何潜在的 myfunction
重载:
let callfunction = `SELECT * FROM myfunction($1, $2, $3::json)`;
JSON.stringify
(而不是文字 json 字符串)来确保传递有效的 JSON:
const value = [
{"id": 123,"firstname": "Mike","lastname": "Smith","ani": 123456,"email": "[email protected]"}
];
const dataResult = await client.query(
callfunction,
[123, abc, JSON.stringify(value)]
);