PostgreSQL函数返回任意类型

nvelit 发布于 2019-01-11 plpgsql 最后更新 2019-01-11 22:59 23 浏览

有没有办法让PostgreSQL中的函数返回任意类型? 我试图使用PLV8来抓取和比较PostgreSQL 9.2中JSON类型的字段。 以下工作:

CREATE or replace FUNCTION jn (j json, key any ) RETURNS numeric 
LANGUAGE plv8   
IMMUTABLE 
AS $function$  
  var ej = JSON.parse(j);   
  if (typeof ej != 'object') return NULL;   
  return JSON.stringify(ej[key]);  
$function$;
SELECT * FROM things WHERE jn(data,'count') <= '10';
返回计数字段<= 10的位置。但是,如果该字段不是数字,则失败。 我不想为我的json可能持有的每种类型的数据创建特定的函数,是否有办法以某种方式推断数据类型并隐式转换? 另请参阅How do I query using fields inside the new PostgreSQL JSON datatype?
已邀请:

zvelit

赞同来自:

您似乎在寻找Polymorphic types的功能 阅读上面关于类型的部分以及this section中的最后两个示例。 请注意,key参数和函数输出的类型应匹配。如果不是这种情况,那么您应该返回text,然后将其转换为函数外部的正确类型。 我认为这将为您完成这项工作:

CREATE or replace FUNCTION jn (j json, key anyelement ) RETURNS anyelement
LANGUAGE plv8   
IMMUTABLE 
AS $function$  
  var ej = JSON.parse(j);   
  if (typeof ej != 'object') return NULL;   
  return JSON.stringify(ej[key]);  
$function$;
对不起,我没有9.2服务器,所以我无法测试这个。
编辑: 事情是 - 在你能够在函数中执行任何强制转换之前,必须首先创建它。在创建时,函数的输入参数的类型和返回类型是固定的。这意味着您只有两种可能性:
  • 使用anyelement类型,这将强制您使key参数具有您希望从该函数返回的相同类型;
  • 使用text类型并在函数外部投射结果。
由于PLV8尚不支持anyelement类型,您实际上可以在PL / pgSQL上创建一个包装函数来为您完成工作:
CREATE FUNCTION jn_wrap(jn varchar, key anyelement, OUT ret anyelement)
    AS $js_wrap$
BEGIN
    EXECUTE 'SELECT CAST(jn($1, $2) AS '||pg_typeof(key)||')'
        USING jn, key INTO ret;
RETURN ;
END;
$js_wrap$ LANGUAGE plpgsql;
虽然我认为它可能很典型,但key的类型将与所需的返回类型不同。