timescaledb/test/sql/utils/testsupport.sql
Erik Nordström 500563ffe5 Add support for PostgreSQL 10
The extension now works with PostgreSQL 10, while
retaining compatibility with version 9.6.

PostgreSQL 10 has numerous internal changes to functions and
APIs, which necessitates various glue code and compatibility
wrappers to seamlessly retain backwards compatiblity with older
versions.

Test output might also differ between versions. In particular,
the psql client generates version-specific output with `\d` and
EXPLAINs might differ due to new query optimizations. The test
suite has been modified as follows to handle these issues. First,
tests now use version-independent functions to query system
catalogs instead of using `\d`. Second, changes have been made to
the test suite to be able to verify some test outputs against
version-dependent reference files.
2017-11-10 09:44:20 +01:00

235 lines
7.2 KiB
PL/PgSQL

CREATE SCHEMA IF NOT EXISTS test;
GRANT USAGE ON SCHEMA test TO PUBLIC;
-- Utility functions to show relation information in tests. These
-- functions generate output which is the same across PostgreSQL
-- versions. Their usage is preferred over psql's '\d <relation>',
-- since that output typically changes across PostgreSQL versions.
CREATE OR REPLACE FUNCTION test.show_columns(rel regclass)
RETURNS TABLE("Column" name,
"Type" text,
"Nullable" boolean) LANGUAGE SQL STABLE AS
$BODY$
SELECT a.attname,
format_type(t.oid, t.typtypmod),
a.attnotnull
FROM pg_attribute a, pg_type t
WHERE a.attrelid = rel
AND a.atttypid = t.oid
AND a.attnum >= 0
ORDER BY a.attnum;
$BODY$;
CREATE OR REPLACE FUNCTION test.show_columnsp(pattern text)
RETURNS TABLE("Relation" regclass,
"Kind" "char",
"Column" name,
"Column type" text,
"Nullable" boolean) LANGUAGE PLPGSQL STABLE AS
$BODY$
DECLARE
schema_name name = split_part(pattern, '.', 1);
table_name name = split_part(pattern, '.', 2);
BEGIN
IF schema_name = '' OR table_name = '' THEN
schema_name := current_schema();
table_name := pattern;
END IF;
RETURN QUERY
SELECT c.oid::regclass,
c.relkind,
a.attname,
format_type(t.oid, t.typtypmod),
a.attnotnull
FROM pg_class c, pg_attribute a, pg_type t
WHERE format('%I.%I', c.relnamespace::regnamespace::name, c.relname) LIKE format('%I.%s', schema_name, table_name)
AND a.attrelid = c.oid
AND a.atttypid = t.oid
AND a.attnum >= 0
ORDER BY c.relname, a.attnum;
END
$BODY$;
CREATE OR REPLACE FUNCTION test.show_indexes(rel regclass)
RETURNS TABLE("Index" regclass,
"Columns" name[],
"Unique" boolean,
"Primary" boolean,
"Exclusion" boolean,
"Tablespace" name) LANGUAGE SQL STABLE AS
$BODY$
SELECT c.oid::regclass,
array(SELECT "Column" FROM test.show_columns(c.oid)),
i.indisunique,
i.indisprimary,
i.indisexclusion,
(SELECT t.spcname FROM pg_tablespace t WHERE t.oid = c.reltablespace)
FROM pg_class c, pg_index i
WHERE c.oid = i.indexrelid AND i.indrelid = rel
ORDER BY c.oid;
$BODY$;
CREATE OR REPLACE FUNCTION test.show_indexesp(pattern text)
RETURNS TABLE("Table" regclass,
"Index" regclass,
"Columns" name[],
"Unique" boolean,
"Primary" boolean,
"Exclusion" boolean,
"Tablespace" name) LANGUAGE PLPGSQL STABLE AS
$BODY$
DECLARE
schema_name name = split_part(pattern, '.', 1);
table_name name = split_part(pattern, '.', 2);
BEGIN
IF schema_name = '' OR table_name = '' THEN
schema_name := current_schema();
table_name := pattern;
END IF;
RETURN QUERY
SELECT c.oid::regclass,
i.indexrelid::regclass,
array(SELECT "Column" FROM test.show_columns(c.oid)),
i.indisunique,
i.indisprimary,
i.indisexclusion,
(SELECT t.spcname FROM pg_class cc, pg_tablespace t WHERE cc.oid = i.indexrelid AND t.oid = cc.reltablespace)
FROM pg_class c, pg_index i
WHERE format('%I.%I', c.relnamespace::regnamespace::name, c.relname) LIKE format('%I.%s', schema_name, table_name)
AND c.oid = i.indrelid
ORDER BY c.oid, i.indexrelid;
END
$BODY$;
CREATE OR REPLACE FUNCTION test.show_constraints(rel regclass)
RETURNS TABLE("Constraint" name,
"Type" "char",
"Columns" name[],
"Index" regclass,
"Expr" text) LANGUAGE SQL STABLE AS
$BODY$
SELECT c.conname,
c.contype,
array(SELECT attname FROM pg_attribute a, unnest(conkey) k WHERE a.attrelid = rel AND k = a.attnum),
c.conindid::regclass,
c.consrc
FROM pg_constraint c
WHERE c.conrelid = rel
ORDER BY c.conname;
$BODY$;
CREATE OR REPLACE FUNCTION test.show_constraintsp(pattern text)
RETURNS TABLE("Table" regclass,
"Constraint" name,
"Type" "char",
"Columns" name[],
"Index" regclass,
"Expr" text) LANGUAGE PLPGSQL STABLE AS
$BODY$
DECLARE
schema_name name = split_part(pattern, '.', 1);
table_name name = split_part(pattern, '.', 2);
BEGIN
IF schema_name = '' OR table_name = '' THEN
schema_name := current_schema();
table_name := pattern;
END IF;
RETURN QUERY
SELECT cl.oid::regclass,
c.conname,
c.contype,
array(SELECT attname FROM pg_attribute a, unnest(conkey) k WHERE a.attrelid = cl.oid AND k = a.attnum),
c.conindid::regclass,
c.consrc
FROM pg_class cl, pg_constraint c
WHERE format('%I.%I', cl.relnamespace::regnamespace::name, cl.relname) LIKE format('%I.%s', schema_name, table_name)
AND c.conrelid = cl.oid
ORDER BY cl.relname, c.conname;
END
$BODY$;
CREATE OR REPLACE FUNCTION test.show_triggers(rel regclass)
RETURNS TABLE("Trigger" name,
"Type" smallint,
"Function" regproc,
"Definition" text) LANGUAGE SQL STABLE AS
$BODY$
SELECT t.tgname,
t.tgtype,
t.tgfoid::regproc,
-- remove 'CREATE TRIGGER' part from definition
substring(pg_get_triggerdef(t.oid) from 15)
FROM pg_trigger t
WHERE t.tgrelid = rel
ORDER BY t.tgname;
$BODY$;
CREATE OR REPLACE FUNCTION test.show_triggersp(pattern text)
RETURNS TABLE("Table" regclass,
"Trigger" name,
"Type" smallint,
"Function" regproc,
"Definition" text) LANGUAGE PLPGSQL STABLE AS
$BODY$
DECLARE
schema_name name = split_part(pattern, '.', 1);
table_name name = split_part(pattern, '.', 2);
BEGIN
IF schema_name = '' OR table_name = '' THEN
schema_name := current_schema();
table_name := pattern;
END IF;
RETURN QUERY
SELECT t.tgrelid::regclass,
t.tgname,
t.tgtype,
t.tgfoid::regproc,
-- remove 'CREATE TRIGGER' part from definition
substring(pg_get_triggerdef(t.oid) from 15)
FROM pg_class cl, pg_trigger t
WHERE format('%I.%I', cl.relnamespace::regnamespace::name, cl.relname) LIKE format('%I.%s', schema_name, table_name)
AND t.tgrelid = cl.oid
ORDER BY t.tgrelid, t.tgname;
END
$BODY$;
CREATE OR REPLACE FUNCTION test.show_subtables(rel regclass)
RETURNS TABLE("Child" regclass) LANGUAGE SQL STABLE AS
$BODY$
SELECT objid::regclass
FROM pg_depend d
WHERE d.refobjid = rel
AND d.deptype = 'n'
AND d.classid = 'pg_class'::regclass
ORDER BY d.refobjid, d.objid;
$BODY$;
CREATE OR REPLACE FUNCTION test.show_subtablesp(pattern text)
RETURNS TABLE("Parent" regclass,
"Child" regclass) LANGUAGE PLPGSQL STABLE AS
$BODY$
DECLARE
schema_name name = split_part(pattern, '.', 1);
table_name name = split_part(pattern, '.', 2);
BEGIN
IF schema_name = '' OR table_name = '' THEN
schema_name := current_schema();
table_name := pattern;
END IF;
RETURN QUERY
SELECT refobjid::regclass,
objid::regclass
FROM pg_class c, pg_depend d
WHERE format('%I.%I', c.relnamespace::regnamespace::name, c.relname) LIKE format('%I.%s', schema_name, table_name)
AND d.refobjid = c.oid
AND d.deptype = 'n'
AND d.classid = 'pg_class'::regclass
ORDER BY d.refobjid, d.objid;
END
$BODY$;