0

複合型の場合、すべてのコンポーネント型の型を再帰的typnameに見つけるにはどうすればよいですか?oids

例:

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);

oidsのメンバーのタイプを取得できますt_employee

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
;

t_stationしかし、それは複合型の内部配列を見つけられません。

4

1 に答える 1

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

マニュアルのカタログ テーブルの詳細。

于 2012-09-21T21:34:55.040 に答える