2012-05-13 68 views
2

有没有办法让PostgreSQL中的函数返回任意类型?返回任意类型的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?

回答

3

你似乎在寻找功能与Polymorphic types
请参阅this section上面的类型和最后2个示例。

请注意,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服务器身边,所以我不能对此进行测试。


编辑:

事情是 - 你将能够在函数中执行任何强制转换之前,必须首先创建。在创建时,函数的输入参数的类型和返回类型是固定的。这意味着你只有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的类型将与期望的返回类型不同。

+0

是的,我碰到“错误:错误:PL/V8函数不能返回类型anyelement”。 –

+0

是否可以动态投射?因此检测类型并进行相应的转换?我事先不知道类型。 –