Skip to content

Commit 26eff8d

Browse files
committed
pg15
1 parent 0e59a07 commit 26eff8d

File tree

5 files changed

+279
-76
lines changed

5 files changed

+279
-76
lines changed

connection.c

+5-3
Original file line numberDiff line numberDiff line change
@@ -543,10 +543,12 @@ configure_remote_session(PGconn *conn)
543543
* anyway. However it makes the regression test outputs more predictable.
544544
*
545545
* We don't risk setting remote zone equal to ours, since the remote
546-
* server might use a different timezone database. Instead, use UTC
547-
* (quoted, because very old servers are picky about case).
546+
* server might use a different timezone database. Instead, use GMT
547+
* (quoted, because very old servers are picky about case). That's
548+
* guaranteed to work regardless of the remote's timezone database,
549+
* because pg_tzset() hard-wires it (at least in PG 9.2 and later).
548550
*/
549-
do_sql_command(conn, "SET timezone = 'UTC'");
551+
do_sql_command(conn, "SET timezone = 'GMT'");
550552

551553
/*
552554
* Set values needed to ensure unambiguous data output from remote. (This

deparse.c

+21-4
Original file line numberDiff line numberDiff line change
@@ -3344,13 +3344,12 @@ appendOrderByClause(List *pathkeys, bool has_final_sort,
33443344
{
33453345
ListCell *lcell;
33463346
int nestlevel;
3347-
const char *delim = " ";
33483347
StringInfo buf = context->buf;
3348+
bool gotone = false;
33493349

33503350
/* Make sure any constants in the exprs are printed portably */
33513351
nestlevel = set_transmission_modes();
33523352

3353-
appendStringInfoString(buf, " ORDER BY");
33543353
foreach(lcell, pathkeys)
33553354
{
33563355
PathKey *pathkey = lfirst(lcell);
@@ -3383,6 +3382,26 @@ appendOrderByClause(List *pathkeys, bool has_final_sort,
33833382

33843383
em_expr = em->em_expr;
33853384

3385+
/*
3386+
* If the member is a Const expression then we needn't add it to the
3387+
* ORDER BY clause. This can happen in UNION ALL queries where the
3388+
* union child targetlist has a Const. Adding these would be
3389+
* wasteful, but also, for INT columns, an integer literal would be
3390+
* seen as an ordinal column position rather than a value to sort by.
3391+
* deparseConst() does have code to handle this, but it seems less
3392+
* effort on all accounts just to skip these for ORDER BY clauses.
3393+
*/
3394+
if (IsA(em_expr, Const))
3395+
continue;
3396+
3397+
if (!gotone)
3398+
{
3399+
appendStringInfoString(buf, " ORDER BY ");
3400+
gotone = true;
3401+
}
3402+
else
3403+
appendStringInfoString(buf, ", ");
3404+
33863405
/*
33873406
* Lookup the operator corresponding to the strategy in the opclass.
33883407
* The datatype used by the opfamily is not necessarily the same as
@@ -3397,7 +3416,6 @@ appendOrderByClause(List *pathkeys, bool has_final_sort,
33973416
pathkey->pk_strategy, em->em_datatype, em->em_datatype,
33983417
pathkey->pk_opfamily);
33993418

3400-
appendStringInfoString(buf, delim);
34013419
deparseExpr(em_expr, context);
34023420

34033421
/*
@@ -3407,7 +3425,6 @@ appendOrderByClause(List *pathkeys, bool has_final_sort,
34073425
appendOrderBySuffix(oprid, exprType((Node *) em_expr),
34083426
pathkey->pk_nulls_first, context);
34093427

3410-
delim = ", ";
34113428
}
34123429
reset_transmission_modes(nestlevel);
34133430
}

expected/postgres_fdw.out

+158-41
Original file line numberDiff line numberDiff line change
@@ -631,6 +631,17 @@ EXPLAIN (VERBOSE, COSTS OFF) SELECT * FROM ft_empty ORDER BY c1;
631631
Remote SQL: SELECT c1, c2 FROM public.loct_empty ORDER BY c1 ASC NULLS LAST
632632
(3 rows)
633633

634+
-- test restriction on non-system foreign tables.
635+
SET restrict_nonsystem_relation_kind TO 'foreign-table';
636+
SELECT * from ft1 where c1 < 1; -- ERROR
637+
ERROR: access to non-system foreign table is restricted
638+
INSERT INTO ft1 (c1) VALUES (1); -- ERROR
639+
ERROR: access to non-system foreign table is restricted
640+
DELETE FROM ft1 WHERE c1 = 1; -- ERROR
641+
ERROR: access to non-system foreign table is restricted
642+
TRUNCATE ft1; -- ERROR
643+
ERROR: access to non-system foreign table is restricted
644+
RESET restrict_nonsystem_relation_kind;
634645
-- ===================================================================
635646
-- WHERE with remotely-executable conditions
636647
-- ===================================================================
@@ -738,10 +749,10 @@ EXPLAIN (VERBOSE, COSTS OFF)
738749
Remote SQL: SELECT "C 1", c2, c3, c4, c5, c6, c7, c8 FROM "S 1"."T 1" WHERE (($1::integer = "C 1"))
739750
(8 rows)
740751

741-
SELECT * FROM ft2 a, ft2 b WHERE a.c1 = 47 AND b.c1 = a.c2;
742-
c1 | c2 | c3 | c4 | c5 | c6 | c7 | c8 | c1 | c2 | c3 | c4 | c5 | c6 | c7 | c8
743-
----+----+-------+------------------------------+--------------------------+----+------------+-----+----+----+-------+------------------------------+--------------------------+----+------------+-----
744-
47 | 7 | 00047 | Tue Feb 17 00:00:00 1970 PST | Tue Feb 17 00:00:00 1970 | 7 | 7 | foo | 7 | 7 | 00007 | Thu Jan 08 00:00:00 1970 PST | Thu Jan 08 00:00:00 1970 | 7 | 7 | foo
752+
SELECT * FROM "S 1"."T 1" a, ft2 b WHERE a."C 1" = 47 AND b.c1 = a.c2;
753+
C 1 | c2 | c3 | c4 | c5 | c6 | c7 | c8 | c1 | c2 | c3 | c4 | c5 | c6 | c7 | c8
754+
-----+----+-------+------------------------------+--------------------------+----+------------+-----+----+----+-------+------------------------------+--------------------------+----+------------+-----
755+
47 | 7 | 00047 | Tue Feb 17 00:00:00 1970 PST | Tue Feb 17 00:00:00 1970 | 7 | 7 | foo | 7 | 7 | 00007 | Thu Jan 08 00:00:00 1970 PST | Thu Jan 08 00:00:00 1970 | 7 | 7 | foo
745756
(1 row)
746757

747758
-- check both safe and unsafe join conditions
@@ -887,32 +898,6 @@ SELECT * FROM ft2 WHERE c1 = ANY (ARRAY(SELECT c1 FROM ft1 WHERE c1 < 5));
887898
4 | 4 | 00004 | Mon Jan 05 00:00:00 1970 PST | Mon Jan 05 00:00:00 1970 | 4 | 4 | foo
888899
(4 rows)
889900

890-
-- we should not push order by clause with volatile expressions or unsafe
891-
-- collations
892-
EXPLAIN (VERBOSE, COSTS OFF)
893-
SELECT * FROM ft2 ORDER BY ft2.c1, random();
894-
QUERY PLAN
895-
-------------------------------------------------------------------------------
896-
Sort
897-
Output: c1, c2, c3, c4, c5, c6, c7, c8, (random())
898-
Sort Key: ft2.c1, (random())
899-
-> Foreign Scan on public.ft2
900-
Output: c1, c2, c3, c4, c5, c6, c7, c8, random()
901-
Remote SQL: SELECT "C 1", c2, c3, c4, c5, c6, c7, c8 FROM "S 1"."T 1"
902-
(6 rows)
903-
904-
EXPLAIN (VERBOSE, COSTS OFF)
905-
SELECT * FROM ft2 ORDER BY ft2.c1, ft2.c3 collate "C";
906-
QUERY PLAN
907-
-------------------------------------------------------------------------------
908-
Sort
909-
Output: c1, c2, c3, c4, c5, c6, c7, c8, ((c3)::text)
910-
Sort Key: ft2.c1, ft2.c3 COLLATE "C"
911-
-> Foreign Scan on public.ft2
912-
Output: c1, c2, c3, c4, c5, c6, c7, c8, c3
913-
Remote SQL: SELECT "C 1", c2, c3, c4, c5, c6, c7, c8 FROM "S 1"."T 1"
914-
(6 rows)
915-
916901
-- user-defined operator/function
917902
CREATE FUNCTION postgres_fdw_abs(int) RETURNS int AS $$
918903
BEGIN
@@ -1067,6 +1052,27 @@ SELECT * FROM ft1 t1 WHERE t1.c1 === t1.c2 order by t1.c2 limit 1;
10671052
1 | 1 | 00001 | Fri Jan 02 00:00:00 1970 PST | Fri Jan 02 00:00:00 1970 | 1 | 1 | foo
10681053
(1 row)
10691054

1055+
-- Ensure we don't ship FETCH FIRST .. WITH TIES
1056+
EXPLAIN (VERBOSE, COSTS OFF)
1057+
SELECT t1.c2 FROM ft1 t1 WHERE t1.c1 > 960 ORDER BY t1.c2 FETCH FIRST 2 ROWS WITH TIES;
1058+
QUERY PLAN
1059+
-------------------------------------------------------------------------------------------------
1060+
Limit
1061+
Output: c2
1062+
-> Foreign Scan on public.ft1 t1
1063+
Output: c2
1064+
Remote SQL: SELECT c2 FROM "S 1"."T 1" WHERE (("C 1" > 960)) ORDER BY c2 ASC NULLS LAST
1065+
(5 rows)
1066+
1067+
SELECT t1.c2 FROM ft1 t1 WHERE t1.c1 > 960 ORDER BY t1.c2 FETCH FIRST 2 ROWS WITH TIES;
1068+
c2
1069+
----
1070+
0
1071+
0
1072+
0
1073+
0
1074+
(4 rows)
1075+
10701076
-- check schema-qualification of regconfig constant
10711077
CREATE TEXT SEARCH CONFIGURATION public.custom_search
10721078
(COPY = pg_catalog.english);
@@ -1087,6 +1093,73 @@ WHERE c1 = 642 AND length(to_tsvector('custom_search'::regconfig, c3)) > 0;
10871093
642 | '00642':1
10881094
(1 row)
10891095

1096+
-- ===================================================================
1097+
-- ORDER BY queries
1098+
-- ===================================================================
1099+
-- we should not push order by clause with volatile expressions or unsafe
1100+
-- collations
1101+
EXPLAIN (VERBOSE, COSTS OFF)
1102+
SELECT * FROM ft2 ORDER BY ft2.c1, random();
1103+
QUERY PLAN
1104+
-------------------------------------------------------------------------------
1105+
Sort
1106+
Output: c1, c2, c3, c4, c5, c6, c7, c8, (random())
1107+
Sort Key: ft2.c1, (random())
1108+
-> Foreign Scan on public.ft2
1109+
Output: c1, c2, c3, c4, c5, c6, c7, c8, random()
1110+
Remote SQL: SELECT "C 1", c2, c3, c4, c5, c6, c7, c8 FROM "S 1"."T 1"
1111+
(6 rows)
1112+
1113+
EXPLAIN (VERBOSE, COSTS OFF)
1114+
SELECT * FROM ft2 ORDER BY ft2.c1, ft2.c3 collate "C";
1115+
QUERY PLAN
1116+
-------------------------------------------------------------------------------
1117+
Sort
1118+
Output: c1, c2, c3, c4, c5, c6, c7, c8, ((c3)::text)
1119+
Sort Key: ft2.c1, ft2.c3 COLLATE "C"
1120+
-> Foreign Scan on public.ft2
1121+
Output: c1, c2, c3, c4, c5, c6, c7, c8, c3
1122+
Remote SQL: SELECT "C 1", c2, c3, c4, c5, c6, c7, c8 FROM "S 1"."T 1"
1123+
(6 rows)
1124+
1125+
-- Ensure we don't push ORDER BY expressions which are Consts at the UNION
1126+
-- child level to the foreign server.
1127+
EXPLAIN (VERBOSE, COSTS OFF)
1128+
SELECT * FROM (
1129+
SELECT 1 AS type,c1 FROM ft1
1130+
UNION ALL
1131+
SELECT 2 AS type,c1 FROM ft2
1132+
) a ORDER BY type,c1;
1133+
QUERY PLAN
1134+
---------------------------------------------------------------------------------
1135+
Merge Append
1136+
Sort Key: (1), ft1.c1
1137+
-> Foreign Scan on public.ft1
1138+
Output: 1, ft1.c1
1139+
Remote SQL: SELECT "C 1" FROM "S 1"."T 1" ORDER BY "C 1" ASC NULLS LAST
1140+
-> Foreign Scan on public.ft2
1141+
Output: 2, ft2.c1
1142+
Remote SQL: SELECT "C 1" FROM "S 1"."T 1" ORDER BY "C 1" ASC NULLS LAST
1143+
(8 rows)
1144+
1145+
EXPLAIN (VERBOSE, COSTS OFF)
1146+
SELECT * FROM (
1147+
SELECT 1 AS type,c1 FROM ft1
1148+
UNION ALL
1149+
SELECT 2 AS type,c1 FROM ft2
1150+
) a ORDER BY type;
1151+
QUERY PLAN
1152+
---------------------------------------------------
1153+
Merge Append
1154+
Sort Key: (1)
1155+
-> Foreign Scan on public.ft1
1156+
Output: 1, ft1.c1
1157+
Remote SQL: SELECT "C 1" FROM "S 1"."T 1"
1158+
-> Foreign Scan on public.ft2
1159+
Output: 2, ft2.c1
1160+
Remote SQL: SELECT "C 1" FROM "S 1"."T 1"
1161+
(8 rows)
1162+
10901163
-- ===================================================================
10911164
-- JOIN queries
10921165
-- ===================================================================
@@ -2197,6 +2270,32 @@ SELECT t1."C 1" FROM "S 1"."T 1" t1, LATERAL (SELECT DISTINCT t2.c1, t3.c1 FROM
21972270
1
21982271
(10 rows)
21992272

2273+
-- join with pseudoconstant quals, not pushed down.
2274+
EXPLAIN (VERBOSE, COSTS OFF)
2275+
SELECT t1.c1, t2.c1 FROM ft1 t1 JOIN ft2 t2 ON (t1.c1 = t2.c1 AND CURRENT_USER = SESSION_USER) ORDER BY t1.c3, t1.c1 OFFSET 100 LIMIT 10;
2276+
QUERY PLAN
2277+
-------------------------------------------------------------------------------
2278+
Limit
2279+
Output: t1.c1, t2.c1, t1.c3
2280+
-> Sort
2281+
Output: t1.c1, t2.c1, t1.c3
2282+
Sort Key: t1.c3, t1.c1
2283+
-> Result
2284+
Output: t1.c1, t2.c1, t1.c3
2285+
One-Time Filter: (CURRENT_USER = SESSION_USER)
2286+
-> Hash Join
2287+
Output: t1.c1, t1.c3, t2.c1
2288+
Hash Cond: (t2.c1 = t1.c1)
2289+
-> Foreign Scan on public.ft2 t2
2290+
Output: t2.c1
2291+
Remote SQL: SELECT "C 1" FROM "S 1"."T 1"
2292+
-> Hash
2293+
Output: t1.c1, t1.c3
2294+
-> Foreign Scan on public.ft1 t1
2295+
Output: t1.c1, t1.c3
2296+
Remote SQL: SELECT "C 1", c3 FROM "S 1"."T 1"
2297+
(19 rows)
2298+
22002299
-- non-Var items in targetlist of the nullable rel of a join preventing
22012300
-- push-down in some cases
22022301
-- unable to push {ft1, ft2}
@@ -6724,6 +6823,28 @@ select * from grem1;
67246823
(2 rows)
67256824

67266825
delete from grem1;
6826+
-- batch insert with foreign partitions.
6827+
-- This schema uses two partitions, one local and one remote with a modulo
6828+
-- to loop across all of them in batches.
6829+
create table tab_batch_local (id int, data text);
6830+
insert into tab_batch_local select i, 'test'|| i from generate_series(1, 45) i;
6831+
create table tab_batch_sharded (id int, data text) partition by hash(id);
6832+
create table tab_batch_sharded_p0 partition of tab_batch_sharded
6833+
for values with (modulus 2, remainder 0);
6834+
create table tab_batch_sharded_p1_remote (id int, data text);
6835+
create foreign table tab_batch_sharded_p1 partition of tab_batch_sharded
6836+
for values with (modulus 2, remainder 1)
6837+
server loopback options (table_name 'tab_batch_sharded_p1_remote');
6838+
insert into tab_batch_sharded select * from tab_batch_local;
6839+
select count(*) from tab_batch_sharded;
6840+
count
6841+
-------
6842+
45
6843+
(1 row)
6844+
6845+
drop table tab_batch_local;
6846+
drop table tab_batch_sharded;
6847+
drop table tab_batch_sharded_p1_remote;
67276848
alter server loopback options (drop batch_size);
67286849
-- ===================================================================
67296850
-- test local triggers
@@ -9969,17 +10090,6 @@ SELECT COUNT(*) FROM ftable;
996910090
34
997010091
(1 row)
997110092

9972-
TRUNCATE batch_table;
9973-
DROP FOREIGN TABLE ftable;
9974-
-- try if large batches exceed max number of bind parameters
9975-
CREATE FOREIGN TABLE ftable ( x int ) SERVER loopback OPTIONS ( table_name 'batch_table', batch_size '100000' );
9976-
INSERT INTO ftable SELECT * FROM generate_series(1, 70000) i;
9977-
SELECT COUNT(*) FROM ftable;
9978-
count
9979-
-------
9980-
70000
9981-
(1 row)
9982-
998310093
TRUNCATE batch_table;
998410094
DROP FOREIGN TABLE ftable;
998510095
-- Disable batch insert
@@ -10366,6 +10476,13 @@ SELECT * FROM result_tbl ORDER BY a;
1036610476
(2 rows)
1036710477

1036810478
DELETE FROM result_tbl;
10479+
-- Test error handling, if accessing one of the foreign partitions errors out
10480+
CREATE FOREIGN TABLE async_p_broken PARTITION OF async_pt FOR VALUES FROM (10000) TO (10001)
10481+
SERVER loopback OPTIONS (table_name 'non_existent_table');
10482+
SELECT * FROM async_pt;
10483+
ERROR: relation "public.non_existent_table" does not exist
10484+
CONTEXT: remote SQL command: SELECT a, b, c FROM public.non_existent_table
10485+
DROP FOREIGN TABLE async_p_broken;
1036910486
-- Check case where multiple partitions use the same connection
1037010487
CREATE TABLE base_tbl3 (a int, b int, c text);
1037110488
CREATE FOREIGN TABLE async_p3 PARTITION OF async_pt FOR VALUES FROM (3000) TO (4000)

0 commit comments

Comments
 (0)