函数参数anyelement,PostgreSQL错误?

前端之家收集整理的这篇文章主要介绍了函数参数anyelement,PostgreSQL错误?前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
我没有看到这个实现中的错误

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”

猜你在找的Postgre SQL相关文章