diff options
author | Tom Lane | 2021-12-20 19:06:15 +0000 |
---|---|---|
committer | Tom Lane | 2021-12-20 19:06:15 +0000 |
commit | d1029bb5a26cb84b116b0dee4dde312291359f2a (patch) | |
tree | 4601ec2967c69dc6031d63034129b4a242d30267 /contrib | |
parent | 33d3eeadb21d2268104840cfef6bc2226ddfc680 (diff) |
Remove dynamic translation of regression test scripts, step 1.
pg_regress has long had provisions for dynamically substituting path
names into regression test scripts and result files, but use of that
feature has always been a serious pain in the neck, mainly because
updating the result files requires tedious manual editing. Let's
get rid of that in favor of passing down the paths in environment
variables.
In addition to being easier to maintain, this way is capable of
dealing with path names that require escaping at runtime, for example
paths containing single-quote marks. (There are other stumbling
blocks in the way of actually building in a path that looks like
that, but removing this one seems like a good thing to do.) The key
coding rule that makes that possible is to concatenate pieces of a
dynamically-variable string using psql's \set command, and then use
the :'variable' notation to quote and escape the string for the next
level of interpretation.
In hopes of making this change more transparent to "git blame",
I've split it into two steps. This commit adds the necessary
pg_regress.c support and changes all the *.source files in-place
so that they no longer require any dynamic translation. The next
commit will just "git mv" them into the regular sql/ and expected/
directories.
Discussion: https://postgr.es/m/1655733.1639871614@sss.pgh.pa.us
Diffstat (limited to 'contrib')
-rw-r--r-- | contrib/dblink/input/paths.source | 15 | ||||
-rw-r--r-- | contrib/dblink/output/paths.source | 13 | ||||
-rw-r--r-- | contrib/file_fdw/input/file_fdw.source | 53 | ||||
-rw-r--r-- | contrib/file_fdw/output/file_fdw.source | 55 |
4 files changed, 103 insertions, 33 deletions
diff --git a/contrib/dblink/input/paths.source b/contrib/dblink/input/paths.source index 881a65314f..30403d9d5f 100644 --- a/contrib/dblink/input/paths.source +++ b/contrib/dblink/input/paths.source @@ -1,14 +1,23 @@ -- Initialization that requires path substitution. +-- directory paths and dlsuffix are passed to us in environment variables +\getenv abs_srcdir PG_ABS_SRCDIR +\getenv libdir PG_LIBDIR +\getenv dlsuffix PG_DLSUFFIX + +\set regresslib :libdir '/regress' :dlsuffix + CREATE FUNCTION setenv(text, text) RETURNS void - AS '@libdir@/regress@DLSUFFIX@', 'regress_setenv' + AS :'regresslib', 'regress_setenv' LANGUAGE C STRICT; CREATE FUNCTION wait_pid(int) RETURNS void - AS '@libdir@/regress@DLSUFFIX@' + AS :'regresslib' LANGUAGE C STRICT; +\set path :abs_srcdir '/' +\set fnbody 'SELECT setenv(''PGSERVICEFILE'', ' :'path' ' || $1)' CREATE FUNCTION set_pgservicefile(text) RETURNS void LANGUAGE SQL - AS $$SELECT setenv('PGSERVICEFILE', '@abs_srcdir@/' || $1)$$; + AS :'fnbody'; diff --git a/contrib/dblink/output/paths.source b/contrib/dblink/output/paths.source index 8ed95e1f78..d09b169b19 100644 --- a/contrib/dblink/output/paths.source +++ b/contrib/dblink/output/paths.source @@ -1,11 +1,18 @@ -- Initialization that requires path substitution. +-- directory paths and dlsuffix are passed to us in environment variables +\getenv abs_srcdir PG_ABS_SRCDIR +\getenv libdir PG_LIBDIR +\getenv dlsuffix PG_DLSUFFIX +\set regresslib :libdir '/regress' :dlsuffix CREATE FUNCTION setenv(text, text) RETURNS void - AS '@libdir@/regress@DLSUFFIX@', 'regress_setenv' + AS :'regresslib', 'regress_setenv' LANGUAGE C STRICT; CREATE FUNCTION wait_pid(int) RETURNS void - AS '@libdir@/regress@DLSUFFIX@' + AS :'regresslib' LANGUAGE C STRICT; +\set path :abs_srcdir '/' +\set fnbody 'SELECT setenv(''PGSERVICEFILE'', ' :'path' ' || $1)' CREATE FUNCTION set_pgservicefile(text) RETURNS void LANGUAGE SQL - AS $$SELECT setenv('PGSERVICEFILE', '@abs_srcdir@/' || $1)$$; + AS :'fnbody'; diff --git a/contrib/file_fdw/input/file_fdw.source b/contrib/file_fdw/input/file_fdw.source index 45b728eeb3..0ea8b14508 100644 --- a/contrib/file_fdw/input/file_fdw.source +++ b/contrib/file_fdw/input/file_fdw.source @@ -2,6 +2,9 @@ -- Test foreign-data wrapper file_fdw. -- +-- directory paths are passed to us in environment variables +\getenv abs_srcdir PG_ABS_SRCDIR + -- Clean up in case a prior regression run failed SET client_min_messages TO 'warning'; DROP ROLE IF EXISTS regress_file_fdw_superuser, regress_file_fdw_user, regress_no_priv_user; @@ -14,6 +17,22 @@ CREATE ROLE regress_no_priv_user LOGIN; -- has priv but no user -- Install file_fdw CREATE EXTENSION file_fdw; +-- create function to filter unstable results of EXPLAIN +CREATE FUNCTION explain_filter(text) RETURNS setof text +LANGUAGE plpgsql AS +$$ +declare + ln text; +begin + for ln in execute $1 + loop + -- Remove the path portion of foreign file names + ln := regexp_replace(ln, 'Foreign File: .*/([a-z.]+)$', 'Foreign File: .../\1'); + return next ln; + end loop; +end; +$$; + -- regress_file_fdw_superuser owns fdw-related objects SET ROLE regress_file_fdw_superuser; CREATE SERVER file_server FOREIGN DATA WRAPPER file_fdw; @@ -61,33 +80,39 @@ CREATE FOREIGN TABLE tbl () SERVER file_server OPTIONS (format 'csv', null ' '); -- ERROR CREATE FOREIGN TABLE tbl () SERVER file_server; -- ERROR +\set filename :abs_srcdir '/data/agg.data' CREATE FOREIGN TABLE agg_text ( a int2 CHECK (a >= 0), b float4 ) SERVER file_server -OPTIONS (format 'text', filename '@abs_srcdir@/data/agg.data', delimiter ' ', null '\N'); +OPTIONS (format 'text', filename :'filename', delimiter ' ', null '\N'); GRANT SELECT ON agg_text TO regress_file_fdw_user; + +\set filename :abs_srcdir '/data/agg.csv' CREATE FOREIGN TABLE agg_csv ( a int2, b float4 ) SERVER file_server -OPTIONS (format 'csv', filename '@abs_srcdir@/data/agg.csv', header 'true', delimiter ';', quote '@', escape '"', null ''); +OPTIONS (format 'csv', filename :'filename', header 'true', delimiter ';', quote '@', escape '"', null ''); ALTER FOREIGN TABLE agg_csv ADD CHECK (a >= 0); + +\set filename :abs_srcdir '/data/agg.bad' CREATE FOREIGN TABLE agg_bad ( a int2, b float4 ) SERVER file_server -OPTIONS (format 'csv', filename '@abs_srcdir@/data/agg.bad', header 'true', delimiter ';', quote '@', escape '"', null ''); +OPTIONS (format 'csv', filename :'filename', header 'true', delimiter ';', quote '@', escape '"', null ''); ALTER FOREIGN TABLE agg_bad ADD CHECK (a >= 0); -- per-column options tests +\set filename :abs_srcdir '/data/text.csv' CREATE FOREIGN TABLE text_csv ( word1 text OPTIONS (force_not_null 'true'), word2 text OPTIONS (force_not_null 'off'), word3 text OPTIONS (force_null 'true'), word4 text OPTIONS (force_null 'off') ) SERVER file_server -OPTIONS (format 'text', filename '@abs_srcdir@/data/text.csv', null 'NULL'); +OPTIONS (format 'text', filename :'filename', null 'NULL'); SELECT * FROM text_csv; -- ERROR ALTER FOREIGN TABLE text_csv OPTIONS (SET format 'csv'); \pset null _null_ @@ -119,7 +144,7 @@ SELECT * FROM agg_bad; -- ERROR -- misc query tests \t on -EXPLAIN (VERBOSE, COSTS FALSE) SELECT * FROM agg_csv; +SELECT explain_filter('EXPLAIN (VERBOSE, COSTS FALSE) SELECT * FROM agg_csv'); \t off PREPARE st(int) AS SELECT * FROM agg_csv WHERE a = $1; EXECUTE st(100); @@ -143,12 +168,12 @@ COPY agg_csv FROM STDIN; -- constraint exclusion tests \t on -EXPLAIN (VERBOSE, COSTS FALSE) SELECT * FROM agg_csv WHERE a < 0; +SELECT explain_filter('EXPLAIN (VERBOSE, COSTS FALSE) SELECT * FROM agg_csv WHERE a < 0'); \t off SELECT * FROM agg_csv WHERE a < 0; SET constraint_exclusion = 'on'; \t on -EXPLAIN (VERBOSE, COSTS FALSE) SELECT * FROM agg_csv WHERE a < 0; +SELECT explain_filter('EXPLAIN (VERBOSE, COSTS FALSE) SELECT * FROM agg_csv WHERE a < 0'); \t off SELECT * FROM agg_csv WHERE a < 0; RESET constraint_exclusion; @@ -170,14 +195,17 @@ DROP TABLE agg; -- declarative partitioning tests SET ROLE regress_file_fdw_superuser; CREATE TABLE pt (a int, b text) partition by list (a); +\set filename :abs_srcdir '/data/list1.csv' CREATE FOREIGN TABLE p1 partition of pt for values in (1) SERVER file_server -OPTIONS (format 'csv', filename '@abs_srcdir@/data/list1.csv', delimiter ','); +OPTIONS (format 'csv', filename :'filename', delimiter ','); CREATE TABLE p2 partition of pt for values in (2); SELECT tableoid::regclass, * FROM pt; SELECT tableoid::regclass, * FROM p1; SELECT tableoid::regclass, * FROM p2; -COPY pt FROM '@abs_srcdir@/data/list2.bad' with (format 'csv', delimiter ','); -- ERROR -COPY pt FROM '@abs_srcdir@/data/list2.csv' with (format 'csv', delimiter ','); +\set filename :abs_srcdir '/data/list2.bad' +COPY pt FROM :'filename' with (format 'csv', delimiter ','); -- ERROR +\set filename :abs_srcdir '/data/list2.csv' +COPY pt FROM :'filename' with (format 'csv', delimiter ','); SELECT tableoid::regclass, * FROM pt; SELECT tableoid::regclass, * FROM p1; SELECT tableoid::regclass, * FROM p2; @@ -190,8 +218,9 @@ SELECT tableoid::regclass, * FROM p2; DROP TABLE pt; -- generated column tests +\set filename :abs_srcdir '/data/list1.csv' CREATE FOREIGN TABLE gft1 (a int, b text, c text GENERATED ALWAYS AS ('foo') STORED) SERVER file_server -OPTIONS (format 'csv', filename '@abs_srcdir@/data/list1.csv', delimiter ','); +OPTIONS (format 'csv', filename :'filename', delimiter ','); SELECT a, c FROM gft1; DROP FOREIGN TABLE gft1; @@ -204,7 +233,7 @@ SET ROLE regress_no_priv_user; SELECT * FROM agg_text ORDER BY a; -- ERROR SET ROLE regress_file_fdw_user; \t on -EXPLAIN (VERBOSE, COSTS FALSE) SELECT * FROM agg_text WHERE a > 0; +SELECT explain_filter('EXPLAIN (VERBOSE, COSTS FALSE) SELECT * FROM agg_text WHERE a > 0'); \t off -- file FDW allows foreign tables to be accessed without user mapping DROP USER MAPPING FOR regress_file_fdw_user SERVER file_server; diff --git a/contrib/file_fdw/output/file_fdw.source b/contrib/file_fdw/output/file_fdw.source index 52b4d5f1df..891146fef3 100644 --- a/contrib/file_fdw/output/file_fdw.source +++ b/contrib/file_fdw/output/file_fdw.source @@ -1,6 +1,8 @@ -- -- Test foreign-data wrapper file_fdw. -- +-- directory paths are passed to us in environment variables +\getenv abs_srcdir PG_ABS_SRCDIR -- Clean up in case a prior regression run failed SET client_min_messages TO 'warning'; DROP ROLE IF EXISTS regress_file_fdw_superuser, regress_file_fdw_user, regress_no_priv_user; @@ -10,6 +12,21 @@ CREATE ROLE regress_file_fdw_user LOGIN; -- has priv and user map CREATE ROLE regress_no_priv_user LOGIN; -- has priv but no user mapping -- Install file_fdw CREATE EXTENSION file_fdw; +-- create function to filter unstable results of EXPLAIN +CREATE FUNCTION explain_filter(text) RETURNS setof text +LANGUAGE plpgsql AS +$$ +declare + ln text; +begin + for ln in execute $1 + loop + -- Remove the path portion of foreign file names + ln := regexp_replace(ln, 'Foreign File: .*/([a-z.]+)$', 'Foreign File: .../\1'); + return next ln; + end loop; +end; +$$; -- regress_file_fdw_superuser owns fdw-related objects SET ROLE regress_file_fdw_superuser; CREATE SERVER file_server FOREIGN DATA WRAPPER file_fdw; @@ -77,32 +94,36 @@ CREATE FOREIGN TABLE tbl () SERVER file_server OPTIONS (format 'csv', null ' ERROR: COPY null representation cannot use newline or carriage return CREATE FOREIGN TABLE tbl () SERVER file_server; -- ERROR ERROR: either filename or program is required for file_fdw foreign tables +\set filename :abs_srcdir '/data/agg.data' CREATE FOREIGN TABLE agg_text ( a int2 CHECK (a >= 0), b float4 ) SERVER file_server -OPTIONS (format 'text', filename '@abs_srcdir@/data/agg.data', delimiter ' ', null '\N'); +OPTIONS (format 'text', filename :'filename', delimiter ' ', null '\N'); GRANT SELECT ON agg_text TO regress_file_fdw_user; +\set filename :abs_srcdir '/data/agg.csv' CREATE FOREIGN TABLE agg_csv ( a int2, b float4 ) SERVER file_server -OPTIONS (format 'csv', filename '@abs_srcdir@/data/agg.csv', header 'true', delimiter ';', quote '@', escape '"', null ''); +OPTIONS (format 'csv', filename :'filename', header 'true', delimiter ';', quote '@', escape '"', null ''); ALTER FOREIGN TABLE agg_csv ADD CHECK (a >= 0); +\set filename :abs_srcdir '/data/agg.bad' CREATE FOREIGN TABLE agg_bad ( a int2, b float4 ) SERVER file_server -OPTIONS (format 'csv', filename '@abs_srcdir@/data/agg.bad', header 'true', delimiter ';', quote '@', escape '"', null ''); +OPTIONS (format 'csv', filename :'filename', header 'true', delimiter ';', quote '@', escape '"', null ''); ALTER FOREIGN TABLE agg_bad ADD CHECK (a >= 0); -- per-column options tests +\set filename :abs_srcdir '/data/text.csv' CREATE FOREIGN TABLE text_csv ( word1 text OPTIONS (force_not_null 'true'), word2 text OPTIONS (force_not_null 'off'), word3 text OPTIONS (force_null 'true'), word4 text OPTIONS (force_null 'off') ) SERVER file_server -OPTIONS (format 'text', filename '@abs_srcdir@/data/text.csv', null 'NULL'); +OPTIONS (format 'text', filename :'filename', null 'NULL'); SELECT * FROM text_csv; -- ERROR ERROR: COPY force not null available only in CSV mode ALTER FOREIGN TABLE text_csv OPTIONS (SET format 'csv'); @@ -176,10 +197,10 @@ ERROR: invalid input syntax for type real: "aaa" CONTEXT: COPY agg_bad, line 3, column b: "aaa" -- misc query tests \t on -EXPLAIN (VERBOSE, COSTS FALSE) SELECT * FROM agg_csv; +SELECT explain_filter('EXPLAIN (VERBOSE, COSTS FALSE) SELECT * FROM agg_csv'); Foreign Scan on public.agg_csv Output: a, b - Foreign File: @abs_srcdir@/data/agg.csv + Foreign File: .../agg.csv \t off PREPARE st(int) AS SELECT * FROM agg_csv WHERE a = $1; @@ -226,11 +247,11 @@ COPY agg_csv FROM STDIN; ERROR: cannot insert into foreign table "agg_csv" -- constraint exclusion tests \t on -EXPLAIN (VERBOSE, COSTS FALSE) SELECT * FROM agg_csv WHERE a < 0; +SELECT explain_filter('EXPLAIN (VERBOSE, COSTS FALSE) SELECT * FROM agg_csv WHERE a < 0'); Foreign Scan on public.agg_csv Output: a, b Filter: (agg_csv.a < 0) - Foreign File: @abs_srcdir@/data/agg.csv + Foreign File: .../agg.csv \t off SELECT * FROM agg_csv WHERE a < 0; @@ -240,7 +261,7 @@ SELECT * FROM agg_csv WHERE a < 0; SET constraint_exclusion = 'on'; \t on -EXPLAIN (VERBOSE, COSTS FALSE) SELECT * FROM agg_csv WHERE a < 0; +SELECT explain_filter('EXPLAIN (VERBOSE, COSTS FALSE) SELECT * FROM agg_csv WHERE a < 0'); Result Output: a, b One-Time Filter: false @@ -295,8 +316,9 @@ DROP TABLE agg; -- declarative partitioning tests SET ROLE regress_file_fdw_superuser; CREATE TABLE pt (a int, b text) partition by list (a); +\set filename :abs_srcdir '/data/list1.csv' CREATE FOREIGN TABLE p1 partition of pt for values in (1) SERVER file_server -OPTIONS (format 'csv', filename '@abs_srcdir@/data/list1.csv', delimiter ','); +OPTIONS (format 'csv', filename :'filename', delimiter ','); CREATE TABLE p2 partition of pt for values in (2); SELECT tableoid::regclass, * FROM pt; tableoid | a | b @@ -317,10 +339,12 @@ SELECT tableoid::regclass, * FROM p2; ----------+---+--- (0 rows) -COPY pt FROM '@abs_srcdir@/data/list2.bad' with (format 'csv', delimiter ','); -- ERROR +\set filename :abs_srcdir '/data/list2.bad' +COPY pt FROM :'filename' with (format 'csv', delimiter ','); -- ERROR ERROR: cannot insert into foreign table "p1" CONTEXT: COPY pt, line 2: "1,qux" -COPY pt FROM '@abs_srcdir@/data/list2.csv' with (format 'csv', delimiter ','); +\set filename :abs_srcdir '/data/list2.csv' +COPY pt FROM :'filename' with (format 'csv', delimiter ','); SELECT tableoid::regclass, * FROM pt; tableoid | a | b ----------+---+----- @@ -376,8 +400,9 @@ SELECT tableoid::regclass, * FROM p2; DROP TABLE pt; -- generated column tests +\set filename :abs_srcdir '/data/list1.csv' CREATE FOREIGN TABLE gft1 (a int, b text, c text GENERATED ALWAYS AS ('foo') STORED) SERVER file_server -OPTIONS (format 'csv', filename '@abs_srcdir@/data/list1.csv', delimiter ','); +OPTIONS (format 'csv', filename :'filename', delimiter ','); SELECT a, c FROM gft1; a | c ---+-------- @@ -412,11 +437,11 @@ SELECT * FROM agg_text ORDER BY a; -- ERROR ERROR: permission denied for foreign table agg_text SET ROLE regress_file_fdw_user; \t on -EXPLAIN (VERBOSE, COSTS FALSE) SELECT * FROM agg_text WHERE a > 0; +SELECT explain_filter('EXPLAIN (VERBOSE, COSTS FALSE) SELECT * FROM agg_text WHERE a > 0'); Foreign Scan on public.agg_text Output: a, b Filter: (agg_text.a > 0) - Foreign File: @abs_srcdir@/data/agg.data + Foreign File: .../agg.data \t off -- file FDW allows foreign tables to be accessed without user mapping |