aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTom Lane <tgl@sss.pgh.pa.us>2015-11-04 12:03:30 -0500
committerTom Lane <tgl@sss.pgh.pa.us>2015-11-04 12:03:30 -0500
commitb9f117d6cd3c79780b0c0e57068f0837f7493aa6 (patch)
treedb30bd3990804e89f467b31d3e51f1dc7ae0f129
parentd89494166351e1fdac77d87c6af500401deb2422 (diff)
downloadpostgresql-b9f117d6cd3c79780b0c0e57068f0837f7493aa6.tar.gz
postgresql-b9f117d6cd3c79780b0c0e57068f0837f7493aa6.zip
Add regression tests for remote execution of extension operators/functions.
Rather than relying on other extensions to be available for installation, let's just add some test objects to the postgres_fdw extension itself within the regression script.
-rw-r--r--contrib/postgres_fdw/expected/postgres_fdw.out178
-rw-r--r--contrib/postgres_fdw/sql/postgres_fdw.sql68
2 files changed, 182 insertions, 64 deletions
diff --git a/contrib/postgres_fdw/expected/postgres_fdw.out b/contrib/postgres_fdw/expected/postgres_fdw.out
index 0159bf52ad0..866a09bea52 100644
--- a/contrib/postgres_fdw/expected/postgres_fdw.out
+++ b/contrib/postgres_fdw/expected/postgres_fdw.out
@@ -112,6 +112,14 @@ ALTER SERVER testserver1 OPTIONS (
-- gsslib 'value',
--replication 'value'
);
+-- Error, invalid list syntax
+ALTER SERVER testserver1 OPTIONS (ADD extensions 'foo; bar');
+ERROR: parameter "extensions" must be a list of extension names
+-- OK but gets a warning
+ALTER SERVER testserver1 OPTIONS (ADD extensions 'foo, bar');
+WARNING: extension "foo" is not installed
+WARNING: extension "bar" is not installed
+ALTER SERVER testserver1 OPTIONS (DROP extensions);
ALTER USER MAPPING FOR public SERVER testserver1
OPTIONS (DROP user, DROP password);
ALTER FOREIGN TABLE ft1 OPTIONS (schema_name 'S 1', table_name 'T 1');
@@ -335,53 +343,6 @@ SELECT 'fixed', NULL FROM ft1 t1 WHERE c1 = 1;
fixed |
(1 row)
--- user-defined operator/function
-CREATE FUNCTION postgres_fdw_abs(int) RETURNS int AS $$
-BEGIN
-RETURN abs($1);
-END
-$$ LANGUAGE plpgsql IMMUTABLE;
-CREATE OPERATOR === (
- LEFTARG = int,
- RIGHTARG = int,
- PROCEDURE = int4eq,
- COMMUTATOR = ===,
- NEGATOR = !==
-);
-EXPLAIN (VERBOSE, COSTS false) SELECT * FROM ft1 t1 WHERE t1.c1 = postgres_fdw_abs(t1.c2);
- QUERY PLAN
--------------------------------------------------------------------------
- Foreign Scan on public.ft1 t1
- Output: c1, c2, c3, c4, c5, c6, c7, c8
- Filter: (t1.c1 = postgres_fdw_abs(t1.c2))
- Remote SQL: SELECT "C 1", c2, c3, c4, c5, c6, c7, c8 FROM "S 1"."T 1"
-(4 rows)
-
-EXPLAIN (VERBOSE, COSTS false) SELECT * FROM ft1 t1 WHERE t1.c1 === t1.c2;
- QUERY PLAN
--------------------------------------------------------------------------
- Foreign Scan on public.ft1 t1
- Output: c1, c2, c3, c4, c5, c6, c7, c8
- Filter: (t1.c1 === t1.c2)
- Remote SQL: SELECT "C 1", c2, c3, c4, c5, c6, c7, c8 FROM "S 1"."T 1"
-(4 rows)
-
-EXPLAIN (VERBOSE, COSTS false) SELECT * FROM ft1 t1 WHERE t1.c1 = abs(t1.c2);
- QUERY PLAN
----------------------------------------------------------------------------------------------------
- Foreign Scan on public.ft1 t1
- Output: c1, c2, c3, c4, c5, c6, c7, c8
- Remote SQL: SELECT "C 1", c2, c3, c4, c5, c6, c7, c8 FROM "S 1"."T 1" WHERE (("C 1" = abs(c2)))
-(3 rows)
-
-EXPLAIN (VERBOSE, COSTS false) SELECT * FROM ft1 t1 WHERE t1.c1 = t1.c2;
- QUERY PLAN
-----------------------------------------------------------------------------------------------
- Foreign Scan on public.ft1 t1
- Output: c1, c2, c3, c4, c5, c6, c7, c8
- Remote SQL: SELECT "C 1", c2, c3, c4, c5, c6, c7, c8 FROM "S 1"."T 1" WHERE (("C 1" = c2))
-(3 rows)
-
-- ===================================================================
-- WHERE with remotely-executable conditions
-- ===================================================================
@@ -672,6 +633,129 @@ EXPLAIN (VERBOSE, COSTS false)
Remote SQL: SELECT "C 1", c2, c3, c4, c5, c6, c7, c8 FROM "S 1"."T 1"
(6 rows)
+-- user-defined operator/function
+CREATE FUNCTION postgres_fdw_abs(int) RETURNS int AS $$
+BEGIN
+RETURN abs($1);
+END
+$$ LANGUAGE plpgsql IMMUTABLE;
+CREATE OPERATOR === (
+ LEFTARG = int,
+ RIGHTARG = int,
+ PROCEDURE = int4eq,
+ COMMUTATOR = ===
+);
+-- built-in operators and functions can be shipped for remote execution
+EXPLAIN (VERBOSE, COSTS false)
+ SELECT count(c3) FROM ft1 t1 WHERE t1.c1 = abs(t1.c2);
+ QUERY PLAN
+--------------------------------------------------------------------------
+ Aggregate
+ Output: count(c3)
+ -> Foreign Scan on public.ft1 t1
+ Output: c3
+ Remote SQL: SELECT c3 FROM "S 1"."T 1" WHERE (("C 1" = abs(c2)))
+(5 rows)
+
+SELECT count(c3) FROM ft1 t1 WHERE t1.c1 = abs(t1.c2);
+ count
+-------
+ 9
+(1 row)
+
+EXPLAIN (VERBOSE, COSTS false)
+ SELECT count(c3) FROM ft1 t1 WHERE t1.c1 = t1.c2;
+ QUERY PLAN
+---------------------------------------------------------------------
+ Aggregate
+ Output: count(c3)
+ -> Foreign Scan on public.ft1 t1
+ Output: c3
+ Remote SQL: SELECT c3 FROM "S 1"."T 1" WHERE (("C 1" = c2))
+(5 rows)
+
+SELECT count(c3) FROM ft1 t1 WHERE t1.c1 = t1.c2;
+ count
+-------
+ 9
+(1 row)
+
+-- by default, user-defined ones cannot
+EXPLAIN (VERBOSE, COSTS false)
+ SELECT count(c3) FROM ft1 t1 WHERE t1.c1 = postgres_fdw_abs(t1.c2);
+ QUERY PLAN
+-----------------------------------------------------------
+ Aggregate
+ Output: count(c3)
+ -> Foreign Scan on public.ft1 t1
+ Output: c3
+ Filter: (t1.c1 = postgres_fdw_abs(t1.c2))
+ Remote SQL: SELECT "C 1", c2, c3 FROM "S 1"."T 1"
+(6 rows)
+
+SELECT count(c3) FROM ft1 t1 WHERE t1.c1 = postgres_fdw_abs(t1.c2);
+ count
+-------
+ 9
+(1 row)
+
+EXPLAIN (VERBOSE, COSTS false)
+ SELECT count(c3) FROM ft1 t1 WHERE t1.c1 === t1.c2;
+ QUERY PLAN
+-----------------------------------------------------------
+ Aggregate
+ Output: count(c3)
+ -> Foreign Scan on public.ft1 t1
+ Output: c3
+ Filter: (t1.c1 === t1.c2)
+ Remote SQL: SELECT "C 1", c2, c3 FROM "S 1"."T 1"
+(6 rows)
+
+SELECT count(c3) FROM ft1 t1 WHERE t1.c1 === t1.c2;
+ count
+-------
+ 9
+(1 row)
+
+-- but let's put them in an extension ...
+ALTER EXTENSION postgres_fdw ADD FUNCTION postgres_fdw_abs(int);
+ALTER EXTENSION postgres_fdw ADD OPERATOR === (int, int);
+ALTER SERVER loopback OPTIONS (ADD extensions 'postgres_fdw');
+-- ... now they can be shipped
+EXPLAIN (VERBOSE, COSTS false)
+ SELECT count(c3) FROM ft1 t1 WHERE t1.c1 = postgres_fdw_abs(t1.c2);
+ QUERY PLAN
+----------------------------------------------------------------------------------------------
+ Aggregate
+ Output: count(c3)
+ -> Foreign Scan on public.ft1 t1
+ Output: c3
+ Remote SQL: SELECT c3 FROM "S 1"."T 1" WHERE (("C 1" = public.postgres_fdw_abs(c2)))
+(5 rows)
+
+SELECT count(c3) FROM ft1 t1 WHERE t1.c1 = postgres_fdw_abs(t1.c2);
+ count
+-------
+ 9
+(1 row)
+
+EXPLAIN (VERBOSE, COSTS false)
+ SELECT count(c3) FROM ft1 t1 WHERE t1.c1 === t1.c2;
+ QUERY PLAN
+----------------------------------------------------------------------------------------
+ Aggregate
+ Output: count(c3)
+ -> Foreign Scan on public.ft1 t1
+ Output: c3
+ Remote SQL: SELECT c3 FROM "S 1"."T 1" WHERE (("C 1" OPERATOR(public.===) c2))
+(5 rows)
+
+SELECT count(c3) FROM ft1 t1 WHERE t1.c1 === t1.c2;
+ count
+-------
+ 9
+(1 row)
+
-- ===================================================================
-- parameterized queries
-- ===================================================================
diff --git a/contrib/postgres_fdw/sql/postgres_fdw.sql b/contrib/postgres_fdw/sql/postgres_fdw.sql
index a87a63fe845..671e38ceaa3 100644
--- a/contrib/postgres_fdw/sql/postgres_fdw.sql
+++ b/contrib/postgres_fdw/sql/postgres_fdw.sql
@@ -121,8 +121,17 @@ ALTER SERVER testserver1 OPTIONS (
-- gsslib 'value',
--replication 'value'
);
+
+-- Error, invalid list syntax
+ALTER SERVER testserver1 OPTIONS (ADD extensions 'foo; bar');
+
+-- OK but gets a warning
+ALTER SERVER testserver1 OPTIONS (ADD extensions 'foo, bar');
+ALTER SERVER testserver1 OPTIONS (DROP extensions);
+
ALTER USER MAPPING FOR public SERVER testserver1
OPTIONS (DROP user, DROP password);
+
ALTER FOREIGN TABLE ft1 OPTIONS (schema_name 'S 1', table_name 'T 1');
ALTER FOREIGN TABLE ft2 OPTIONS (schema_name 'S 1', table_name 'T 1');
ALTER FOREIGN TABLE ft1 ALTER COLUMN c1 OPTIONS (column_name 'C 1');
@@ -169,23 +178,6 @@ SELECT * FROM ft1 t1 WHERE t1.c3 = (SELECT MAX(c3) FROM ft2 t2) ORDER BY c1;
WITH t1 AS (SELECT * FROM ft1 WHERE c1 <= 10) SELECT t2.c1, t2.c2, t2.c3, t2.c4 FROM t1, ft2 t2 WHERE t1.c1 = t2.c1 ORDER BY t1.c1;
-- fixed values
SELECT 'fixed', NULL FROM ft1 t1 WHERE c1 = 1;
--- user-defined operator/function
-CREATE FUNCTION postgres_fdw_abs(int) RETURNS int AS $$
-BEGIN
-RETURN abs($1);
-END
-$$ LANGUAGE plpgsql IMMUTABLE;
-CREATE OPERATOR === (
- LEFTARG = int,
- RIGHTARG = int,
- PROCEDURE = int4eq,
- COMMUTATOR = ===,
- NEGATOR = !==
-);
-EXPLAIN (VERBOSE, COSTS false) SELECT * FROM ft1 t1 WHERE t1.c1 = postgres_fdw_abs(t1.c2);
-EXPLAIN (VERBOSE, COSTS false) SELECT * FROM ft1 t1 WHERE t1.c1 === t1.c2;
-EXPLAIN (VERBOSE, COSTS false) SELECT * FROM ft1 t1 WHERE t1.c1 = abs(t1.c2);
-EXPLAIN (VERBOSE, COSTS false) SELECT * FROM ft1 t1 WHERE t1.c1 = t1.c2;
-- ===================================================================
-- WHERE with remotely-executable conditions
@@ -222,6 +214,48 @@ EXPLAIN (VERBOSE, COSTS false)
EXPLAIN (VERBOSE, COSTS false)
SELECT * FROM ft2 ORDER BY ft2.c1, ft2.c3 collate "C";
+-- user-defined operator/function
+CREATE FUNCTION postgres_fdw_abs(int) RETURNS int AS $$
+BEGIN
+RETURN abs($1);
+END
+$$ LANGUAGE plpgsql IMMUTABLE;
+CREATE OPERATOR === (
+ LEFTARG = int,
+ RIGHTARG = int,
+ PROCEDURE = int4eq,
+ COMMUTATOR = ===
+);
+
+-- built-in operators and functions can be shipped for remote execution
+EXPLAIN (VERBOSE, COSTS false)
+ SELECT count(c3) FROM ft1 t1 WHERE t1.c1 = abs(t1.c2);
+SELECT count(c3) FROM ft1 t1 WHERE t1.c1 = abs(t1.c2);
+EXPLAIN (VERBOSE, COSTS false)
+ SELECT count(c3) FROM ft1 t1 WHERE t1.c1 = t1.c2;
+SELECT count(c3) FROM ft1 t1 WHERE t1.c1 = t1.c2;
+
+-- by default, user-defined ones cannot
+EXPLAIN (VERBOSE, COSTS false)
+ SELECT count(c3) FROM ft1 t1 WHERE t1.c1 = postgres_fdw_abs(t1.c2);
+SELECT count(c3) FROM ft1 t1 WHERE t1.c1 = postgres_fdw_abs(t1.c2);
+EXPLAIN (VERBOSE, COSTS false)
+ SELECT count(c3) FROM ft1 t1 WHERE t1.c1 === t1.c2;
+SELECT count(c3) FROM ft1 t1 WHERE t1.c1 === t1.c2;
+
+-- but let's put them in an extension ...
+ALTER EXTENSION postgres_fdw ADD FUNCTION postgres_fdw_abs(int);
+ALTER EXTENSION postgres_fdw ADD OPERATOR === (int, int);
+ALTER SERVER loopback OPTIONS (ADD extensions 'postgres_fdw');
+
+-- ... now they can be shipped
+EXPLAIN (VERBOSE, COSTS false)
+ SELECT count(c3) FROM ft1 t1 WHERE t1.c1 = postgres_fdw_abs(t1.c2);
+SELECT count(c3) FROM ft1 t1 WHERE t1.c1 = postgres_fdw_abs(t1.c2);
+EXPLAIN (VERBOSE, COSTS false)
+ SELECT count(c3) FROM ft1 t1 WHERE t1.c1 === t1.c2;
+SELECT count(c3) FROM ft1 t1 WHERE t1.c1 === t1.c2;
+
-- ===================================================================
-- parameterized queries
-- ===================================================================