2012-05-13 114 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

是否可以動態投射?因此檢測類型並進行相應的轉換?我事先不知道類型。 –