|
-- DROP FUNCTION public.get_table_definition(varchar, varchar); |
|
|
|
CREATE OR REPLACE FUNCTION public.get_table_definition(p_schema_name character varying, p_table_name character varying) |
|
RETURNS SETOF text |
|
LANGUAGE plpgsql |
|
AS $function$ |
|
BEGIN |
|
RETURN query |
|
WITH table_rec AS ( |
|
SELECT |
|
c.relname, |
|
n.nspname, |
|
c.oid, |
|
COALESCE(obj_description((p_schema_name||'.'||quote_ident(p_table_name))::regclass), '') AS commentlines |
|
FROM |
|
pg_catalog.pg_class c |
|
LEFT JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace |
|
WHERE |
|
relkind = 'r' |
|
AND n.nspname = p_schema_name |
|
AND c.relname LIKE p_table_name |
|
ORDER BY |
|
c.relname |
|
), |
|
trig_rec AS ( |
|
SELECT tc.*, |
|
it.trigger_name, |
|
it.event_manipulation, |
|
it.event_object_table, |
|
it.action_statement, |
|
it.action_orientation, |
|
it.action_timing |
|
FROM information_schema.triggers AS it |
|
INNER JOIN table_rec AS tc ON tc.nspname = it.event_object_schema AND it.event_object_table = tc.relname |
|
WHERE event_object_schema = p_schema_name |
|
AND event_object_table = p_table_name |
|
ORDER BY event_object_table, event_manipulation |
|
), |
|
col_rec AS ( |
|
SELECT |
|
a.attname AS colname, |
|
a.attrelid AS attrelid, |
|
pg_catalog.format_type(a.atttypid, a.atttypmod) AS coltype, |
|
a.attrelid AS oid, |
|
' DEFAULT ' || ( |
|
SELECT |
|
pg_catalog.pg_get_expr(d.adbin, d.adrelid) |
|
FROM |
|
pg_catalog.pg_attrdef d |
|
WHERE |
|
d.adrelid = a.attrelid |
|
AND d.adnum = a.attnum |
|
AND a.atthasdef) AS column_default_value, |
|
CASE WHEN a.attnotnull = TRUE THEN |
|
'NOT NULL' |
|
ELSE |
|
'NULL' |
|
END AS column_not_null, |
|
a.attnum AS attnum |
|
FROM |
|
pg_catalog.pg_attribute a |
|
WHERE |
|
a.attnum > 0 |
|
AND NOT a.attisdropped |
|
ORDER BY |
|
a.attnum |
|
), |
|
con_rec AS ( |
|
SELECT |
|
conrelid::regclass::text AS relname, |
|
n.nspname, |
|
conname, |
|
pg_get_constraintdef(c.oid) AS condef, |
|
contype, |
|
conrelid AS oid |
|
FROM |
|
pg_constraint c |
|
JOIN pg_namespace n ON n.oid = c.connamespace |
|
), |
|
glue AS ( |
|
SELECT |
|
format( E'-- %1$I.%2$I Table definition\n\n-- Drop table\n\n-- DROP TABLE IF EXISTS %1$I.%2$I\n\nCREATE TABLE IF NOT EXISTS %1$I.%2$I (\n', p_schema_name, table_rec.relname) AS top, |
|
format( E'\n);\n\n\n-- Table Constraints, Comments and Triggers') AS bottom, |
|
oid |
|
FROM |
|
table_rec |
|
), |
|
cols AS ( |
|
SELECT |
|
string_agg(format(' %I %s%s %s', colname, coltype, column_default_value, column_not_null), E',\n') AS lines, |
|
oid |
|
FROM |
|
col_rec |
|
GROUP BY |
|
oid |
|
), |
|
constrnt AS ( |
|
SELECT |
|
string_agg(format('-- ALTER TABLE %s DROP CONSTRAINT IF EXISTS %s;', relname, con_rec.conname), E'\n') AS droplines, |
|
string_agg(format('ALTER TABLE %s ADD CONSTRAINT %s %s;', relname, con_rec.conname, con_rec.condef), E'\n') AS addlines, |
|
oid |
|
FROM |
|
con_rec |
|
WHERE |
|
contype <> 'f' |
|
GROUP BY |
|
oid |
|
), |
|
frnkey AS ( |
|
SELECT |
|
string_agg(format('ALTER TABLE %s ADD CONSTRAINT %s %s;', relname, conname, condef), E'\n') AS lines, |
|
oid |
|
FROM |
|
con_rec |
|
WHERE |
|
contype = 'f' |
|
GROUP BY |
|
oid |
|
), |
|
indexlines AS ( |
|
SELECT string_agg(format('%s', pgi.indexdef), E';\n') AS indices, |
|
oid |
|
FROM table_rec |
|
LEFT JOIN (SELECT * FROM pg_indexes) AS pgi ON (table_rec.relname = pgi.tablename AND table_rec.nspname = pgi.schemaname) |
|
GROUP BY oid |
|
), |
|
commentlines AS ( |
|
SELECT |
|
string_agg(format('COMMENT ON TABLE %1$I.%2$I IS ''%3$s'';', p_schema_name, table_rec.relname, table_rec.commentlines), E'\n') AS lines, |
|
oid |
|
FROM |
|
table_rec |
|
GROUP BY |
|
oid |
|
|
|
), |
|
commentcols AS ( |
|
SELECT |
|
string_agg(format('COMMENT ON COLUMN %1$I.%2$I.%3$I IS ''%4$s'';', table_rec.nspname, table_rec.relname, col_rec.colname, pgd.description), E'\n') AS lines, |
|
table_rec.oid |
|
FROM |
|
table_rec |
|
LEFT JOIN col_rec ON col_rec.oid = table_rec.oid |
|
LEFT OUTER JOIN pg_attribute as pga ON (col_rec.colname = pga.attname AND table_rec.oid = pga.attrelid) |
|
LEFT OUTER JOIN pg_description AS pgd ON (pgd.objoid = col_rec.oid AND pgd.objsubid = pga.attnum) |
|
GROUP BY table_rec.oid |
|
), |
|
triggerlines AS ( |
|
SELECT |
|
string_agg(format('-- DROP TRIGGER IF EXISTS %1$s ON %4$s.%5$s;\n', trigger_name, action_timing, event_manipulation, nspname, relname, action_statement), E'\n') AS trigdrop, |
|
string_agg(format('CREATE TRIGGER %1$s %2$s %3$s ON %4$s.%5$s FOR EACH ROW %6$s;\n', trigger_name, action_timing, event_manipulation, nspname, relname, action_statement), E'\n') AS trigadd, |
|
oid |
|
FROM |
|
trig_rec |
|
GROUP BY oid |
|
) |
|
SELECT |
|
concat_ws(E'\n', |
|
glue.top, |
|
cols.lines, |
|
glue.bottom, |
|
E'\n--- Table comments', commentlines.lines, commentcols.lines, |
|
E'\n--- Table indices', indexlines.indices, |
|
E'\n--- Remove existing constraints if needed', constrnt.droplines, |
|
E'\n--- Non-foreign key constraints', constrnt.addlines, |
|
E'\n--- Foreign Key Restraints', frnkey.lines, |
|
E'\n--- Triggers', triggerlines.trigdrop, triggerlines.trigadd) |
|
FROM |
|
glue |
|
JOIN cols ON cols.oid = glue.oid |
|
LEFT JOIN constrnt ON constrnt.oid = glue.oid |
|
LEFT JOIN commentlines ON commentlines.oid = glue.oid |
|
LEFT JOIN commentcols ON commentcols.oid = glue.oid |
|
LEFT JOIN indexlines ON indexlines.oid = glue.oid |
|
LEFT JOIN frnkey ON frnkey.oid = glue.oid |
|
LEFT JOIN triggerlines ON triggerlines.oid = glue.oid; |
|
END; |
|
$function$ |
|
; |