2012-09-21 48 views
0

鑑於typname的複合類型,我如何找到所有組件類型的oids遞歸地使用WITH RECURSIVE查找所有複合類型組件類型

例子:

CREATE TYPE t_station AS (x INT, 
          y INT, 
          label VARCHAR); 

CREATE TYPE t_address AS (city VARCHAR, 
          street VARCHAR, 
          no INT, 
          stations t_station[]); 

CREATE TYPE t_employee AS (name VARCHAR, 
          age INT, 
          coins INT[], 
          notes VARCHAR, 
          address t_address); 

我可以得到的類型t_employee成員oids

SELECT 
    t.typname, t.oid, a.attname, a.atttypid 
FROM 
    pg_attribute a INNER JOIN pg_type t ON a.attrelid = t.typrelid 
    AND t.typname = 't_employee' 

但我需要遞歸的是,我想可以用WITH RECURSIVE做到:

WITH RECURSIVE allattrs(typname, oid, attname, atttypid) AS (
    select t.typname, t.oid, a.attname, a.atttypid from pg_attribute a inner join pg_type t on a.attrelid = t.typrelid and t.typname = 't_employee' 
    union all 
    select z.* from 
    (select t.typname, t.oid, a.attname, a.atttypid from pg_attribute a inner join pg_type t on a.attrelid = t.typrelid) z, 
    allattrs y where y.atttypid = z.oid 
) 
SELECT * FROM allattrs limit 100 
; 

但是,沒有找到內部的AR ray的t_station複合型。

回答

1

數組類型會破壞您所遵循的簡單鏈。在陣列類型的情況下,您必須解析pg_type.typelem以獲得基本類型。

WITH RECURSIVE cte(typname, type_oid, attname, atttypid, typelem) AS (
    SELECT t.typname, t.oid, a.attname, a.atttypid, t.typelem 
    FROM pg_type t 
    LEFT JOIN pg_attribute a ON a.attrelid = t.typrelid 
           AND a.attnum > 0 
           AND NOT a.attisdropped 
    WHERE t.typrelid = 't_employee'::regclass 

    UNION ALL 
    SELECT t.typname, t.oid 
     ,COALESCE(a.attname, t.typelem::regtype::text) 
     ,COALESCE(a.atttypid, t.typelem), t.typelem 
    FROM cte c 
    JOIN pg_type t ON t.oid = c.atttypid AND (t.typtype = 'c' OR t.typelem > 0) 
    LEFT JOIN pg_attribute a ON a.attrelid = t.typrelid 
           AND a.attnum > 0 
           AND NOT a.attisdropped 
    ) 
SELECT typname, type_oid, attname, atttypid 
FROM cte 
WHERE typelem = 0 -- filter out rows for array types 

如果要包括在結果數組類型的額外行,刪除最後一個WHERE條件..

這JOIN條件只是跟隨複合類型或數組:

AND (t.typtype = 'c' OR t.typelem > 0) 

我還添加了排除系統色譜柱和色譜柱的條件:

AND a.attnum > 0 
AND NOT a.attisdropped 

Details about catalog tables in the manual.

+0

啊,真好!正是我需要的。我剛開始使用遞歸CTE,並且有一條學習曲線......但是PG功能真的很棒! – oberstet