Skip to content
Snippets Groups Projects
Commit 61b1fd41 authored by Marcel Huber's avatar Marcel Huber
Browse files

dump_table_ddl prints primary and foreign key constraints

- fixes the previous inability to print combined primary keys
- extends the ability to print foreign key constraints

Merge branch 'release_21.15.1'
parents 76a06b53 5abf7a41
No related branches found
No related tags found
No related merge requests found
wait-for-it.sh: waiting 20 seconds for postgres:5432
wait-for-it.sh: postgres:5432 is available after 0 seconds
-- tag::starttime[]
20210601T223144Z
20210602T152735Z
-- end::starttime[]
You are now connected to database "postgres" as user "postgres".
Target width is unset.
......@@ -44,19 +44,71 @@ DROP FUNCTION
-- end::extensions-2-text[]
-- end::extensions-2-output[]
-- tag::extensions-3-query[]
CREATE OR REPLACE FUNCTION dump_table_ddl (table_name TEXT)
CREATE OR REPLACE FUNCTION dump_table_ddl (table_name TEXT, dump_fk BOOL DEFAULT TRUE, dump_pk BOOL DEFAULT TRUE)
RETURNS TEXT
LANGUAGE SQL
AS $$
SELECT
'CREATE TABLE ' || a.attrelid::REGCLASS::TEXT || E' (
' || string_agg(' '|| a.attname || ' ' || upper(pg_catalog.format_type(a.atttypid, a.atttypmod)) || CASE WHEN (SELECT substring(pg_catalog.pg_get_expr(d.adbin, d.adrelid) for 128) FROM pg_catalog.pg_attrdef d WHERE d.adrelid = a.attrelid AND d.adnum = a.attnum AND a.atthasdef) IS NOT NULL THEN ' DEFAULT ' || (SELECT substring(pg_catalog.pg_get_expr(d.adbin, d.adrelid) for 128) FROM pg_catalog.pg_attrdef d WHERE d.adrelid = a.attrelid AND d.adnum = a.attnum AND a.atthasdef) ELSE '' END || CASE WHEN (SELECT a.attname FROM pg_index i WHERE a.attrelid = i.indrelid AND a.attnum = ANY(i.indkey)) IS NOT NULL THEN ' PRIMARY KEY' ELSE CASE WHEN a.attnotnull = true THEN ' NOT NULL' ELSE '' END END, E',
') || E'
);' FROM pg_catalog.pg_attribute a join pg_class on a.attrelid = pg_class.oid WHERE a.attrelid::regclass::varchar = table_name AND a.attnum > 0 AND NOT a.attisdropped and pg_class.relkind = 'r'
GROUP BY
a.attrelid;
'CREATE TABLE ' || a.attrelid::REGCLASS::TEXT || E' (\n' || string_agg(' ' || a.attname || ' ' || upper(pg_catalog.format_type(a.atttypid, a.atttypmod)) || CASE WHEN (
SELECT
substring(pg_catalog.pg_get_expr(d.adbin, d.adrelid)
FOR 128)
FROM pg_catalog.pg_attrdef d
WHERE
d.adrelid = a.attrelid
AND d.adnum = a.attnum
AND a.atthasdef) IS NOT NULL THEN
' DEFAULT ' || (
SELECT
substring(pg_catalog.pg_get_expr(d.adbin, d.adrelid)
FOR 128)
FROM pg_catalog.pg_attrdef d
WHERE
d.adrelid = a.attrelid
AND d.adnum = a.attnum
AND a.atthasdef)
ELSE
''
END || CASE WHEN a.attnotnull = TRUE THEN
' NOT NULL'
ELSE
''
END, E',\n') || (
SELECT
coalesce(E',\n' || string_agg(' ' || pg_catalog.pg_get_constraintdef(con.oid, TRUE), E',\n'), '')
FROM
pg_catalog.pg_class c,
pg_catalog.pg_class c2,
pg_catalog.pg_index i
LEFT JOIN pg_catalog.pg_constraint con ON (conrelid = i.indrelid
AND conindid = i.indexrelid
AND contype IN ('p', 'u', 'x'))
WHERE
c.oid = a.attrelid
AND c.oid = i.indrelid
AND i.indexrelid = c2.oid
AND dump_pk) || (
SELECT
coalesce(E',\n' || string_agg(' ' || pg_catalog.pg_get_constraintdef(con.oid, TRUE), E',\n'), '')
FROM
pg_catalog.pg_constraint con
WHERE
con.conrelid = a.attrelid
AND con.contype = 'f'
AND con.conparentid = 0
AND dump_fk) || E'\n);'
FROM
pg_catalog.pg_attribute a
JOIN pg_class cl ON a.attrelid = cl.oid
WHERE
a.attrelid::REGCLASS::VARCHAR = table_name
AND a.attnum > 0
AND NOT a.attisdropped
AND cl.relkind = 'r'
GROUP BY
a.attrelid;
$$
LANGUAGE SQL;
$$;
-- end::extensions-3-query[]
-- tag::extensions-3-output[]
Output format is aligned.
......@@ -72,13 +124,13 @@ START TRANSACTION
SELECT
*
FROM
dump_table_ddl ('angestellter');
dump_table_ddl ('angestellter', FALSE);
-- end::schema-original-1-query[]
-- tag::schema-original-1-output[]
Output format is unaligned.
-- tag::schema-original-1-text[]
CREATE TABLE angestellter (
persnr INTEGER PRIMARY KEY,
persnr INTEGER NOT NULL,
name CHARACTER VARYING(20) NOT NULL,
tel INTEGER,
salaer NUMERIC(7,2) NOT NULL,
......@@ -86,7 +138,8 @@ CREATE TABLE angestellter (
abtnr INTEGER NOT NULL,
wohnort CHARACTER VARYING(20),
eintrittsdatum DATE DEFAULT CURRENT_DATE,
bonus NUMERIC(7,2) DEFAULT 0
bonus NUMERIC(7,2) DEFAULT 0,
PRIMARY KEY (persnr)
);
-- end::schema-original-1-text[]
-- end::schema-original-1-output[]
......@@ -109,13 +162,13 @@ ALTER TABLE
SELECT
*
FROM
dump_table_ddl ('angestellter');
dump_table_ddl ('angestellter', FALSE);
-- end::extend-with-ogc_fid-2-query[]
-- tag::extend-with-ogc_fid-2-output[]
Output format is unaligned.
-- tag::extend-with-ogc_fid-2-text[]
CREATE TABLE angestellter (
persnr INTEGER PRIMARY KEY,
persnr INTEGER NOT NULL,
name CHARACTER VARYING(20) NOT NULL,
tel INTEGER,
salaer NUMERIC(7,2) NOT NULL,
......@@ -124,7 +177,8 @@ CREATE TABLE angestellter (
wohnort CHARACTER VARYING(20),
eintrittsdatum DATE DEFAULT CURRENT_DATE,
bonus NUMERIC(7,2) DEFAULT 0,
ogc_fid INTEGER DEFAULT 0
ogc_fid INTEGER DEFAULT 0,
PRIMARY KEY (persnr)
);
-- end::extend-with-ogc_fid-2-text[]
-- end::extend-with-ogc_fid-2-output[]
......@@ -147,13 +201,13 @@ ALTER TABLE
SELECT
*
FROM
dump_table_ddl ('angestellter');
dump_table_ddl ('angestellter', FALSE);
-- end::change-data-type-of-field-2-query[]
-- tag::change-data-type-of-field-2-output[]
Output format is unaligned.
-- tag::change-data-type-of-field-2-text[]
CREATE TABLE angestellter (
persnr INTEGER PRIMARY KEY,
persnr INTEGER NOT NULL,
name CHARACTER VARYING(20) NOT NULL,
salaer NUMERIC(7,2) NOT NULL,
chef INTEGER,
......@@ -161,7 +215,8 @@ CREATE TABLE angestellter (
wohnort CHARACTER VARYING(20),
eintrittsdatum DATE DEFAULT CURRENT_DATE,
bonus NUMERIC(7,2) DEFAULT 0,
tel CHARACTER VARYING(20)
tel CHARACTER VARYING(20),
PRIMARY KEY (persnr)
);
-- end::change-data-type-of-field-2-text[]
-- end::change-data-type-of-field-2-output[]
......@@ -301,13 +356,13 @@ Output format is aligned.
SELECT
*
FROM
dump_table_ddl ('angestellter');
dump_table_ddl ('angestellter', FALSE);
-- end::split-attribute-7-query[]
-- tag::split-attribute-7-output[]
Output format is unaligned.
-- tag::split-attribute-7-text[]
CREATE TABLE angestellter (
persnr INTEGER PRIMARY KEY,
persnr INTEGER NOT NULL,
tel INTEGER,
salaer NUMERIC(7,2) NOT NULL,
chef INTEGER,
......@@ -316,12 +371,13 @@ CREATE TABLE angestellter (
eintrittsdatum DATE DEFAULT CURRENT_DATE,
bonus NUMERIC(7,2) DEFAULT 0,
vorname CHARACTER VARYING(20) NOT NULL,
nachname CHARACTER VARYING(20) NOT NULL
nachname CHARACTER VARYING(20) NOT NULL,
PRIMARY KEY (persnr)
);
-- end::split-attribute-7-text[]
-- end::split-attribute-7-output[]
ROLLBACK
-- end::split-attribute[]
-- tag::endtime[]
20210601T223146Z
20210602T152736Z
-- end::endtime[]
......@@ -16,7 +16,7 @@
"queries": {
"SELECT name,version,installed,comment FROM pg_available_extension_versions where name in ('postgis');": {},
"drop function if exists dump_table_ddl(text);": {},
"create or replace function dump_table_ddl(table_name text) returns text as \\$\\$ select 'CREATE TABLE ' || a.attrelid::regclass::text || E' (\\n' || string_agg(' '|| a.attname || ' ' || upper(pg_catalog.format_type(a.atttypid, a.atttypmod)) || CASE WHEN (SELECT substring(pg_catalog.pg_get_expr(d.adbin, d.adrelid) for 128) FROM pg_catalog.pg_attrdef d WHERE d.adrelid = a.attrelid AND d.adnum = a.attnum AND a.atthasdef) IS NOT NULL THEN ' DEFAULT ' || (SELECT substring(pg_catalog.pg_get_expr(d.adbin, d.adrelid) for 128) FROM pg_catalog.pg_attrdef d WHERE d.adrelid = a.attrelid AND d.adnum = a.attnum AND a.atthasdef) ELSE '' END || CASE WHEN (SELECT a.attname FROM pg_index i WHERE a.attrelid = i.indrelid AND a.attnum = ANY(i.indkey)) IS NOT NULL THEN ' PRIMARY KEY' ELSE CASE WHEN a.attnotnull = true THEN ' NOT NULL' ELSE '' END END, E',\\n') || E'\\n);' FROM pg_catalog.pg_attribute a join pg_class on a.attrelid = pg_class.oid WHERE a.attrelid::regclass::varchar = table_name AND a.attnum > 0 AND NOT a.attisdropped and pg_class.relkind = 'r' group by a.attrelid; \\$\\$ language SQL;": {
"create or replace function dump_table_ddl(table_name text,dump_fk BOOL DEFAULT true, dump_pk BOOL DEFAULT true) returns text language SQL as \\$\\$ select 'CREATE TABLE ' || a.attrelid::regclass::text || E' (\\\\\\\\n' || string_agg(' '|| a.attname || ' ' || upper(pg_catalog.format_type(a.atttypid, a.atttypmod)) || CASE WHEN (SELECT substring(pg_catalog.pg_get_expr(d.adbin, d.adrelid) for 128) FROM pg_catalog.pg_attrdef d WHERE d.adrelid = a.attrelid AND d.adnum = a.attnum AND a.atthasdef) IS NOT NULL THEN ' DEFAULT ' || (SELECT substring(pg_catalog.pg_get_expr(d.adbin, d.adrelid) for 128) FROM pg_catalog.pg_attrdef d WHERE d.adrelid = a.attrelid AND d.adnum = a.attnum AND a.atthasdef) ELSE '' END || CASE WHEN a.attnotnull = true THEN ' NOT NULL' ELSE '' END, E',\\\\\\\\n') || (SELECT COALESCE(E',\\\\\\\\n' || string_agg(' ' || pg_catalog.pg_get_constraintdef(con.oid, true),E',\\\\\\\\n'),'') FROM pg_catalog.pg_class c, pg_catalog.pg_class c2, pg_catalog.pg_index i LEFT JOIN pg_catalog.pg_constraint con ON (conrelid = i.indrelid AND conindid = i.indexrelid AND contype IN ('p','u','x')) WHERE c.oid = a.attrelid AND c.oid = i.indrelid AND i.indexrelid = c2.oid AND dump_pk) || (SELECT COALESCE(E',\\\\\\\\n' || string_agg(' ' || pg_catalog.pg_get_constraintdef(con.oid, TRUE), E',\\\\\\\\n'),'') FROM pg_catalog.pg_constraint con WHERE con.conrelid = a.attrelid AND con.contype = 'f' AND con.conparentid = 0 AND dump_fk) || E'\\\\\\\\n);' FROM pg_catalog.pg_attribute a join pg_class cl on a.attrelid = cl.oid WHERE a.attrelid::regclass::varchar = table_name AND a.attnum > 0 AND NOT a.attisdropped and cl.relkind = 'r' group by a.attrelid; \\$\\$;": {
"pg_format_opts": "--no-extra-line --function-case 1 --spaces 2 --keyword-case 2 --type-case 2"
}
}
......@@ -25,7 +25,7 @@
"description": "Query current table layout of angestellter",
"exec-commit": false,
"queries": {
"select * from dump_table_ddl('angestellter');": {
"select * from dump_table_ddl('angestellter',false);": {
"tuples_only": true,
"format_text": "unaligned"
}
......@@ -38,7 +38,7 @@
"ALTER TABLE angestellter ADD COLUMN ogc_fid INTEGER DEFAULT 0;": {
"tuples_only": false
},
"select * from dump_table_ddl('angestellter');": {
"select * from dump_table_ddl('angestellter',false);": {
"tuples_only": true,
"format_text": "unaligned"
}
......@@ -51,7 +51,7 @@
"ALTER TABLE angestellter ALTER COLUMN tel SET DATA TYPE VARCHAR(20);": {
"tuples_only": false
},
"select * from dump_table_ddl('angestellter');": {
"select * from dump_table_ddl('angestellter',false);": {
"tuples_only": true,
"format_text": "unaligned"
}
......@@ -69,7 +69,7 @@
"ALTER TABLE angestellter ALTER COLUMN vorname SET NOT NULL, ALTER COLUMN nachname SET NOT NULL;": {},
"ALTER TABLE angestellter DROP COLUMN name;": {},
"select nachname, vorname, persnr from angestellter order by nachname,vorname;": {},
"select * from dump_table_ddl('angestellter');": {
"select * from dump_table_ddl('angestellter',false);": {
"tuples_only": true,
"format_text": "unaligned"
}
......
= Changelog
ifndef::ci_commit_link[:ci_commit_link: link:/../../commit/]
== tag: 21.15.1
* bumped version ({ci_commit_link}2059f8c[2059f8c])
* dump_table_ddl prints primary and foreign key constraints ({ci_commit_link}7d00e4f[7d00e4f])
* dump_table_ddl function prints primary and foreign keys ({ci_commit_link}57b7575[57b7575])
* added plenty of backslash escapes to fix query formatting ({ci_commit_link}d15470e[d15470e])
* adapted final exercise to dynamic queries content ({ci_commit_link}f9c6a9f[f9c6a9f])
== tag: 21.15.0
* adapted final exercise to dynamic queries content ({ci_commit_link}76a06b5[76a06b5])
* changelog updated ({ci_commit_link}df4d27e[df4d27e])
* bumped version ({ci_commit_link}553f395[553f395])
......
21.15.0
21.15.1
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment