加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

函数参数anyelement,PostgreSQL错误?

发布时间:2020-12-13 15:51:03 所属栏目:百科 来源:网络整理
导读:我没有看到这个实现中的错误: CREATE FUNCTION foo(anyelement) RETURNS SETOF int AS $f$ SELECT id FROM unnest(array[1,2,3]) t(id) WHERE CASE WHEN (pg_typeof($1)::text)='integer' THEN $1::int2 ELSE true END$f$LANGUAGE SQL IMMUTABLE;SELECT * F
我没有看到这个实现中的错误:

CREATE FUNCTION foo(anyelement) RETURNS SETOF int  AS $f$
    SELECT id FROM unnest(array[1,2,3]) t(id) 
    WHERE CASE WHEN (pg_typeof($1)::text)='integer' THEN $1::int>2 ELSE true END
$f$LANGUAGE SQL IMMUTABLE;

SELECT * FROM foo(123); -- OK!
SELECT * FROM foo('test'::text); -- BUG

这是某种PostgreSQL错误还是对任何元素数据类型的非文档限制?

有趣:当被隔离时,CASE条款正常工作:

CREATE FUNCTION bar(anyelement) RETURNS boolean  AS $f$
   SELECT CASE WHEN (pg_typeof($1)::text)='integer' THEN $1::int>2;
 $f$LANGUAGE SQL IMMUTABLE;

 SELECT bar('test'::text),bar(123),bar(1); -- works fine!

解决方法

您的问题是由于SQL语句的计划方式. SQL对数据类型非常严格. Postgres函数为多态伪类型ANYELEMENT提供了一些灵活性,但SQL语句仍然是静态地使用给定类型进行规划.

虽然表达式$1 :: int> 2永远不会被执行,如果$1不是整数(你可以避免这种方式除以零),这无法避免在规划查询的早期阶段出现的语法错误.

您仍然可以使用您拥有的功能执行某些操作.使用无类型字符串文字:

CREATE OR REPLACE FUNCTION foo(anyelement)
  RETURNS SETOF int AS
 $func$
   SELECT id FROM unnest(array[1,3]) id
   WHERE  CASE WHEN pg_typeof($1) = 'integer'::regtype
               THEN $1 > '2'  -- use a string literal!
               ELSE true END
$func$LANGUAGE sql IMMUTABLE;

这至少适用于所有字符和数字数据类型.字符串文字被强制转换为提供的数据类型.但对于“2”无效的其他数据类型,它仍然会失败.

值得注意的是,您的第二个示例不会触发语法错误.从我对Postgres 9.5的测试中可以看出,如果函数不是IMMUTABLE,则会触发语法错误,或者在FROM列表中调用set-returns函数(RETURNS SETOF …而不是RETURNS boolean):SELECT * FROM foo(而不是SELECT foo().对于可以内联的简单IMMUTABLE函数,似乎对查询规划的处理方式不同.

除此之外,使用:

pg_typeof($1) = 'integer'::regtype

代替:

(pg_typeof($1)::文本)= ‘整数’

这通常更好.每次强制转换常量而不是计算值总是更好.这也适用于类型名称的已知别名.

> PostgreSQL syntax error in parameterized query on “date $1”

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读