Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit ca1f941

Browse files
committed
Backports from PG10 for 1C
1 parent 76ec0df commit ca1f941

File tree

29 files changed

+1186
-219
lines changed

29 files changed

+1186
-219
lines changed

contrib/citext/expected/citext.out

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2274,8 +2274,8 @@ SELECT *
22742274
WHERE t.id IS NULL OR m.id IS NULL;
22752275
id | name | id | name
22762276
----+------+----+------
2277-
| | 2 | Two
22782277
2 | two | |
2278+
| | 2 | Two
22792279
(2 rows)
22802280

22812281
REFRESH MATERIALIZED VIEW CONCURRENTLY citext_matview;

contrib/citext/expected/citext_1.out

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2274,8 +2274,8 @@ SELECT *
22742274
WHERE t.id IS NULL OR m.id IS NULL;
22752275
id | name | id | name
22762276
----+------+----+------
2277-
| | 2 | Two
22782277
2 | two | |
2278+
| | 2 | Two
22792279
(2 rows)
22802280

22812281
REFRESH MATERIALIZED VIEW CONCURRENTLY citext_matview;

contrib/postgres_fdw/expected/postgres_fdw.out

Lines changed: 31 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -388,13 +388,14 @@ EXPLAIN (VERBOSE, COSTS OFF)
388388
Output: t1.c1, t2."C 1"
389389
-> Merge Join
390390
Output: t1.c1, t2."C 1"
391+
Inner Unique: true
391392
Merge Cond: (t1.c1 = t2."C 1")
392393
-> Foreign Scan on public.ft2 t1
393394
Output: t1.c1
394395
Remote SQL: SELECT "C 1" FROM "S 1"."T 1" ORDER BY "C 1" ASC NULLS LAST
395396
-> Index Only Scan using t1_pkey on "S 1"."T 1" t2
396397
Output: t2."C 1"
397-
(10 rows)
398+
(11 rows)
398399

399400
SELECT t1.c1, t2."C 1" FROM ft2 t1 JOIN "S 1"."T 1" t2 ON (t1.c1 = t2."C 1") OFFSET 100 LIMIT 10;
400401
c1 | C 1
@@ -421,13 +422,14 @@ EXPLAIN (VERBOSE, COSTS OFF)
421422
Output: t1.c1, t2."C 1"
422423
-> Merge Left Join
423424
Output: t1.c1, t2."C 1"
425+
Inner Unique: true
424426
Merge Cond: (t1.c1 = t2."C 1")
425427
-> Foreign Scan on public.ft2 t1
426428
Output: t1.c1
427429
Remote SQL: SELECT "C 1" FROM "S 1"."T 1" ORDER BY "C 1" ASC NULLS LAST
428430
-> Index Only Scan using t1_pkey on "S 1"."T 1" t2
429431
Output: t2."C 1"
430-
(10 rows)
432+
(11 rows)
431433

432434
SELECT t1.c1, t2."C 1" FROM ft2 t1 LEFT JOIN "S 1"."T 1" t2 ON (t1.c1 = t2."C 1") OFFSET 100 LIMIT 10;
433435
c1 | C 1
@@ -454,14 +456,15 @@ EXPLAIN (VERBOSE, COSTS OFF)
454456
Output: t1."C 1"
455457
-> Merge Right Join
456458
Output: t1."C 1"
459+
Inner Unique: true
457460
Merge Cond: (t3.c1 = t1."C 1")
458461
-> Foreign Scan
459462
Output: t3.c1
460463
Relations: (public.ft1 t2) INNER JOIN (public.ft2 t3)
461464
Remote SQL: SELECT r3."C 1" FROM ("S 1"."T 1" r2 INNER JOIN "S 1"."T 1" r3 ON (((r2."C 1" = r3."C 1")))) ORDER BY r2."C 1" ASC NULLS LAST
462465
-> Index Only Scan using t1_pkey on "S 1"."T 1" t1
463466
Output: t1."C 1"
464-
(11 rows)
467+
(12 rows)
465468

466469
SELECT t1."C 1" FROM "S 1"."T 1" t1 left join ft1 t2 join ft2 t3 on (t2.c1 = t3.c1) on (t3.c1 = t1."C 1") OFFSET 100 LIMIT 10;
467470
C 1
@@ -489,14 +492,15 @@ EXPLAIN (VERBOSE, COSTS OFF)
489492
Output: t1."C 1", t2.c1, t3.c1
490493
-> Merge Right Join
491494
Output: t1."C 1", t2.c1, t3.c1
495+
Inner Unique: true
492496
Merge Cond: (t3.c1 = t1."C 1")
493497
-> Foreign Scan
494498
Output: t3.c1, t2.c1
495499
Relations: (public.ft2 t3) LEFT JOIN (public.ft1 t2)
496500
Remote SQL: SELECT r3."C 1", r2."C 1" FROM ("S 1"."T 1" r3 LEFT JOIN "S 1"."T 1" r2 ON (((r2."C 1" = r3."C 1")))) ORDER BY r3."C 1" ASC NULLS LAST
497501
-> Index Only Scan using t1_pkey on "S 1"."T 1" t1
498502
Output: t1."C 1"
499-
(11 rows)
503+
(12 rows)
500504

501505
SELECT t1."C 1", t2.c1, t3.c1 FROM "S 1"."T 1" t1 left join ft1 t2 full join ft2 t3 on (t2.c1 = t3.c1) on (t3.c1 = t1."C 1") OFFSET 100 LIMIT 10;
502506
C 1 | c1 | c1
@@ -522,14 +526,15 @@ EXPLAIN (VERBOSE, COSTS OFF)
522526
Output: t1."C 1", t2.c1, t3.c1
523527
-> Merge Full Join
524528
Output: t1."C 1", t2.c1, t3.c1
529+
Inner Unique: true
525530
Merge Cond: (t3.c1 = t1."C 1")
526531
-> Foreign Scan
527532
Output: t2.c1, t3.c1
528533
Relations: (public.ft1 t2) FULL JOIN (public.ft2 t3)
529534
Remote SQL: SELECT r2."C 1", r3."C 1" FROM ("S 1"."T 1" r2 FULL JOIN "S 1"."T 1" r3 ON (((r2."C 1" = r3."C 1")))) ORDER BY r3."C 1" ASC NULLS LAST
530535
-> Index Only Scan using t1_pkey on "S 1"."T 1" t1
531536
Output: t1."C 1"
532-
(11 rows)
537+
(12 rows)
533538

534539
SELECT t1."C 1", t2.c1, t3.c1 FROM "S 1"."T 1" t1 full join ft1 t2 full join ft2 t3 on (t2.c1 = t3.c1) on (t3.c1 = t1."C 1") OFFSET 100 LIMIT 10;
535540
C 1 | c1 | c1
@@ -1759,8 +1764,8 @@ SELECT t1.ctid, t1, t2, t1.c1 FROM ft1 t1 JOIN ft2 t2 ON (t1.c1 = t2.c1) ORDER B
17591764
-- SEMI JOIN, not pushed down
17601765
EXPLAIN (VERBOSE, COSTS OFF)
17611766
SELECT t1.c1 FROM ft1 t1 WHERE EXISTS (SELECT 1 FROM ft2 t2 WHERE t1.c1 = t2.c1) ORDER BY t1.c1 OFFSET 100 LIMIT 10;
1762-
QUERY PLAN
1763-
---------------------------------------------------------------------------------------------
1767+
QUERY PLAN
1768+
---------------------------------------------------------------------------------------
17641769
Limit
17651770
Output: t1.c1
17661771
-> Merge Semi Join
@@ -1769,12 +1774,10 @@ SELECT t1.c1 FROM ft1 t1 WHERE EXISTS (SELECT 1 FROM ft2 t2 WHERE t1.c1 = t2.c1)
17691774
-> Foreign Scan on public.ft1 t1
17701775
Output: t1.c1
17711776
Remote SQL: SELECT "C 1" FROM "S 1"."T 1" ORDER BY "C 1" ASC NULLS LAST
1772-
-> Materialize
1777+
-> Foreign Scan on public.ft2 t2
17731778
Output: t2.c1
1774-
-> Foreign Scan on public.ft2 t2
1775-
Output: t2.c1
1776-
Remote SQL: SELECT "C 1" FROM "S 1"."T 1" ORDER BY "C 1" ASC NULLS LAST
1777-
(13 rows)
1779+
Remote SQL: SELECT "C 1" FROM "S 1"."T 1" ORDER BY "C 1" ASC NULLS LAST
1780+
(11 rows)
17781781

17791782
SELECT t1.c1 FROM ft1 t1 WHERE EXISTS (SELECT 1 FROM ft2 t2 WHERE t1.c1 = t2.c1) ORDER BY t1.c1 OFFSET 100 LIMIT 10;
17801783
c1
@@ -1804,12 +1807,10 @@ SELECT t1.c1 FROM ft1 t1 WHERE NOT EXISTS (SELECT 1 FROM ft2 t2 WHERE t1.c1 = t2
18041807
-> Foreign Scan on public.ft1 t1
18051808
Output: t1.c1
18061809
Remote SQL: SELECT "C 1" FROM "S 1"."T 1" ORDER BY "C 1" ASC NULLS LAST
1807-
-> Materialize
1810+
-> Foreign Scan on public.ft2 t2
18081811
Output: t2.c2
1809-
-> Foreign Scan on public.ft2 t2
1810-
Output: t2.c2
1811-
Remote SQL: SELECT c2 FROM "S 1"."T 1" ORDER BY c2 ASC NULLS LAST
1812-
(13 rows)
1812+
Remote SQL: SELECT c2 FROM "S 1"."T 1" ORDER BY c2 ASC NULLS LAST
1813+
(11 rows)
18131814

18141815
SELECT t1.c1 FROM ft1 t1 WHERE NOT EXISTS (SELECT 1 FROM ft2 t2 WHERE t1.c1 = t2.c2) ORDER BY t1.c1 OFFSET 100 LIMIT 10;
18151816
c1
@@ -2837,20 +2838,18 @@ explain (verbose, costs off) select * from ft3 where f2 = 'foo' COLLATE "C";
28372838

28382839
explain (verbose, costs off) select * from ft3 f, loct3 l
28392840
where f.f3 = l.f3 COLLATE "POSIX" and l.f1 = 'foo';
2840-
QUERY PLAN
2841-
-------------------------------------------------------------
2842-
Hash Join
2841+
QUERY PLAN
2842+
---------------------------------------------------------
2843+
Nested Loop
28432844
Output: f.f1, f.f2, f.f3, l.f1, l.f2, l.f3
2844-
Hash Cond: ((f.f3)::text = (l.f3)::text)
2845+
Join Filter: ((f.f3)::text = (l.f3)::text)
2846+
-> Index Scan using loct3_f1_key on public.loct3 l
2847+
Output: l.f1, l.f2, l.f3
2848+
Index Cond: (l.f1 = 'foo'::text)
28452849
-> Foreign Scan on public.ft3 f
28462850
Output: f.f1, f.f2, f.f3
28472851
Remote SQL: SELECT f1, f2, f3 FROM public.loct3
2848-
-> Hash
2849-
Output: l.f1, l.f2, l.f3
2850-
-> Index Scan using loct3_f1_key on public.loct3 l
2851-
Output: l.f1, l.f2, l.f3
2852-
Index Cond: (l.f1 = 'foo'::text)
2853-
(11 rows)
2852+
(9 rows)
28542853

28552854
-- ===================================================================
28562855
-- test writable foreign table stuff
@@ -5367,6 +5366,7 @@ select * from bar where f1 in (select f1 from foo) for share;
53675366
Output: bar.f1, bar.f2, bar.ctid, bar.*, bar.tableoid, foo.ctid, foo.*, foo.tableoid
53685367
-> Hash Join
53695368
Output: bar.f1, bar.f2, bar.ctid, bar.*, bar.tableoid, foo.ctid, foo.*, foo.tableoid
5369+
Inner Unique: true
53705370
Hash Cond: (bar.f1 = foo.f1)
53715371
-> Append
53725372
-> Seq Scan on public.bar
@@ -5385,7 +5385,7 @@ select * from bar where f1 in (select f1 from foo) for share;
53855385
-> Foreign Scan on public.foo2
53865386
Output: foo2.ctid, foo2.*, foo2.tableoid, foo2.f1
53875387
Remote SQL: SELECT f1, f2, f3, ctid FROM public.loct1
5388-
(22 rows)
5388+
(23 rows)
53895389

53905390
select * from bar where f1 in (select f1 from foo) for share;
53915391
f1 | f2
@@ -5407,6 +5407,7 @@ update bar set f2 = f2 + 100 where f1 in (select f1 from foo);
54075407
Remote SQL: UPDATE public.loct2 SET f2 = $2 WHERE ctid = $1
54085408
-> Hash Join
54095409
Output: bar.f1, (bar.f2 + 100), bar.ctid, foo.ctid, foo.*, foo.tableoid
5410+
Inner Unique: true
54105411
Hash Cond: (bar.f1 = foo.f1)
54115412
-> Seq Scan on public.bar
54125413
Output: bar.f1, bar.f2, bar.ctid
@@ -5423,6 +5424,7 @@ update bar set f2 = f2 + 100 where f1 in (select f1 from foo);
54235424
Remote SQL: SELECT f1, f2, f3, ctid FROM public.loct1
54245425
-> Hash Join
54255426
Output: bar2.f1, (bar2.f2 + 100), bar2.f3, bar2.ctid, foo.ctid, foo.*, foo.tableoid
5427+
Inner Unique: true
54265428
Hash Cond: (bar2.f1 = foo.f1)
54275429
-> Foreign Scan on public.bar2
54285430
Output: bar2.f1, bar2.f2, bar2.f3, bar2.ctid
@@ -5438,7 +5440,7 @@ update bar set f2 = f2 + 100 where f1 in (select f1 from foo);
54385440
-> Foreign Scan on public.foo2
54395441
Output: foo2.ctid, foo2.*, foo2.tableoid, foo2.f1
54405442
Remote SQL: SELECT f1, f2, f3, ctid FROM public.loct1
5441-
(37 rows)
5443+
(39 rows)
54425444

54435445
update bar set f2 = f2 + 100 where f1 in (select f1 from foo);
54445446
select tableoid::regclass, * from bar order by 1,2;

src/backend/commands/explain.c

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1375,6 +1375,23 @@ ExplainNode(PlanState *planstate, List *ancestors,
13751375
if (es->verbose)
13761376
show_plan_tlist(planstate, ancestors, es);
13771377

1378+
/* unique join */
1379+
switch (nodeTag(plan))
1380+
{
1381+
case T_NestLoop:
1382+
case T_MergeJoin:
1383+
case T_HashJoin:
1384+
/* try not to be too chatty about this in text mode */
1385+
if (es->format != EXPLAIN_FORMAT_TEXT ||
1386+
(es->verbose && ((Join *) plan)->inner_unique))
1387+
ExplainPropertyBool("Inner Unique",
1388+
((Join *) plan)->inner_unique,
1389+
es);
1390+
break;
1391+
default:
1392+
break;
1393+
}
1394+
13781395
/* quals, sort keys, etc */
13791396
switch (nodeTag(plan))
13801397
{

src/backend/executor/nodeHashjoin.c

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -306,10 +306,11 @@ ExecHashJoin(HashJoinState *node)
306306
}
307307

308308
/*
309-
* In a semijoin, we'll consider returning the first
310-
* match, but after that we're done with this outer tuple.
309+
* If we only need to join to the first matching inner
310+
* tuple, then consider returning this one, but after that
311+
* continue with next outer tuple.
311312
*/
312-
if (node->js.jointype == JOIN_SEMI)
313+
if (node->js.single_match)
313314
node->hj_JoinState = HJ_NEED_NEW_OUTER;
314315

315316
if (otherqual == NIL ||
@@ -495,6 +496,12 @@ ExecInitHashJoin(HashJoin *node, EState *estate, int eflags)
495496
ExecInitResultTupleSlot(estate, &hjstate->js.ps);
496497
hjstate->hj_OuterTupleSlot = ExecInitExtraTupleSlot(estate);
497498

499+
/*
500+
* detect whether we need only consider the first matching inner tuple
501+
*/
502+
hjstate->js.single_match = (node->join.inner_unique ||
503+
node->join.jointype == JOIN_SEMI);
504+
498505
/* set up null tuples for outer joins, if needed */
499506
switch (node->join.jointype)
500507
{

src/backend/executor/nodeMergejoin.c

Lines changed: 40 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -840,10 +840,11 @@ ExecMergeJoin(MergeJoinState *node)
840840
}
841841

842842
/*
843-
* In a semijoin, we'll consider returning the first
844-
* match, but after that we're done with this outer tuple.
843+
* If we only need to join to the first matching inner
844+
* tuple, then consider returning this one, but after that
845+
* continue with next outer tuple.
845846
*/
846-
if (node->js.jointype == JOIN_SEMI)
847+
if (node->js.single_match)
847848
node->mj_JoinState = EXEC_MJ_NEXTOUTER;
848849

849850
qualResult = (otherqual == NIL ||
@@ -1099,6 +1100,10 @@ ExecMergeJoin(MergeJoinState *node)
10991100
* scan position to the first mark, and go join that tuple
11001101
* (and any following ones) to the new outer.
11011102
*
1103+
* If we were able to determine mark and restore are not
1104+
* needed, then we don't have to back up; the current
1105+
* inner is already the first possible match.
1106+
*
11021107
* NOTE: we do not need to worry about the MatchedInner
11031108
* state for the rescanned inner tuples. We know all of
11041109
* them will match this new outer tuple and therefore
@@ -1111,16 +1116,19 @@ ExecMergeJoin(MergeJoinState *node)
11111116
* forcing the merge clause to never match, so we never
11121117
* get here.
11131118
*/
1114-
ExecRestrPos(innerPlan);
1119+
if (!node->mj_SkipMarkRestore)
1120+
{
1121+
ExecRestrPos(innerPlan);
11151122

1116-
/*
1117-
* ExecRestrPos probably should give us back a new Slot,
1118-
* but since it doesn't, use the marked slot. (The
1119-
* previously returned mj_InnerTupleSlot cannot be assumed
1120-
* to hold the required tuple.)
1121-
*/
1122-
node->mj_InnerTupleSlot = innerTupleSlot;
1123-
/* we need not do MJEvalInnerValues again */
1123+
/*
1124+
* ExecRestrPos probably should give us back a new
1125+
* Slot, but since it doesn't, use the marked slot.
1126+
* (The previously returned mj_InnerTupleSlot cannot
1127+
* be assumed to hold the required tuple.)
1128+
*/
1129+
node->mj_InnerTupleSlot = innerTupleSlot;
1130+
/* we need not do MJEvalInnerValues again */
1131+
}
11241132

11251133
node->mj_JoinState = EXEC_MJ_JOINTUPLES;
11261134
}
@@ -1221,7 +1229,8 @@ ExecMergeJoin(MergeJoinState *node)
12211229

12221230
if (compareResult == 0)
12231231
{
1224-
ExecMarkPos(innerPlan);
1232+
if (!node->mj_SkipMarkRestore)
1233+
ExecMarkPos(innerPlan);
12251234

12261235
MarkInnerTuple(node->mj_InnerTupleSlot, node);
12271236

@@ -1520,11 +1529,18 @@ ExecInitMergeJoin(MergeJoin *node, EState *estate, int eflags)
15201529
/*
15211530
* initialize child nodes
15221531
*
1523-
* inner child must support MARK/RESTORE.
1532+
* inner child must support MARK/RESTORE, unless we have detected that we
1533+
* don't need that. Note that skip_mark_restore must never be set if
1534+
* there are non-mergeclause joinquals, since the logic wouldn't work.
15241535
*/
1536+
Assert(node->join.joinqual == NIL || !node->skip_mark_restore);
1537+
mergestate->mj_SkipMarkRestore = node->skip_mark_restore;
1538+
15251539
outerPlanState(mergestate) = ExecInitNode(outerPlan(node), estate, eflags);
15261540
innerPlanState(mergestate) = ExecInitNode(innerPlan(node), estate,
1527-
eflags | EXEC_FLAG_MARK);
1541+
mergestate->mj_SkipMarkRestore ?
1542+
eflags :
1543+
(eflags | EXEC_FLAG_MARK));
15281544

15291545
/*
15301546
* For certain types of inner child nodes, it is advantageous to issue
@@ -1537,7 +1553,8 @@ ExecInitMergeJoin(MergeJoin *node, EState *estate, int eflags)
15371553
* only if eflags doesn't specify REWIND.
15381554
*/
15391555
if (IsA(innerPlan(node), Material) &&
1540-
(eflags & EXEC_FLAG_REWIND) == 0)
1556+
(eflags & EXEC_FLAG_REWIND) == 0 &&
1557+
!mergestate->mj_SkipMarkRestore)
15411558
mergestate->mj_ExtraMarks = true;
15421559
else
15431560
mergestate->mj_ExtraMarks = false;
@@ -1551,6 +1568,13 @@ ExecInitMergeJoin(MergeJoin *node, EState *estate, int eflags)
15511568
ExecSetSlotDescriptor(mergestate->mj_MarkedTupleSlot,
15521569
ExecGetResultType(innerPlanState(mergestate)));
15531570

1571+
/*
1572+
* detect whether we need only consider the first matching inner tuple
1573+
*/
1574+
mergestate->js.single_match = (node->join.inner_unique ||
1575+
node->join.jointype == JOIN_SEMI);
1576+
1577+
/* set up null tuples for outer joins, if needed */
15541578
switch (node->join.jointype)
15551579
{
15561580
case JOIN_INNER:

0 commit comments

Comments
 (0)