"""
PostgreSQL の情報スキーマからテーブル定義を取得する
pip install psycopg2-binary
"""
import psycopg2
DSN = "host=localhost dbname=myapp user=postgres password=secret"
def get_columns(conn, schema="public", table=None):
query = """
SELECT
c.table_name,
c.column_name,
c.data_type,
c.character_maximum_length,
c.is_nullable,
c.column_default,
pgd.description AS column_comment
FROM information_schema.columns c
LEFT JOIN pg_catalog.pg_statio_all_tables st
ON st.schemaname = c.table_schema AND st.relname = c.table_name
LEFT JOIN pg_catalog.pg_description pgd
ON pgd.objoid = st.relid AND pgd.objsubid = c.ordinal_position
WHERE c.table_schema = %s
AND (%s IS NULL OR c.table_name = %s)
ORDER BY c.table_name, c.ordinal_position
"""
with conn.cursor() as cur:
cur.execute(query, (schema, table, table))
return cur.fetchall()
def get_indexes(conn, schema="public", table=None):
query = """
SELECT
t.relname AS table_name,
i.relname AS index_name,
ix.indisunique,
ix.indisprimary,
array_to_string(array_agg(a.attname ORDER BY k.n), ', ') AS columns
FROM pg_class t
JOIN pg_index ix ON t.oid = ix.indrelid
JOIN pg_class i ON i.oid = ix.indexrelid
JOIN pg_namespace n ON t.relnamespace = n.oid
JOIN LATERAL unnest(ix.indkey) WITH ORDINALITY AS k(attnum, n) ON true
JOIN pg_attribute a ON a.attrelid = t.oid AND a.attnum = k.attnum
WHERE n.nspname = %s
AND (%s IS NULL OR t.relname = %s)
GROUP BY t.relname, i.relname, ix.indisunique, ix.indisprimary
ORDER BY t.relname, i.relname
"""
with conn.cursor() as cur:
cur.execute(query, (schema, table, table))
return cur.fetchall()
conn = psycopg2.connect(DSN)
cols = get_columns(conn, table="orders")
print("## orders テーブル カラム定義")
for row in cols:
print(f" {row[1]:25s} {row[2]:20s} NULL={row[4]:3s} default={row[5]}")
idxs = get_indexes(conn, table="orders")
print("\n## orders テーブル インデックス")
for row in idxs:
kind = "PK" if row[3] else ("UNIQUE" if row[2] else "INDEX")
print(f" [{kind}] {row[1]}: ({row[4]})")
conn.close()