Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commitca1f941

Browse files
committed
Backports from PG10 for 1C
1 parent76ec0df commitca1f941

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+
caseT_NestLoop:
1382+
caseT_MergeJoin:
1383+
caseT_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
caseJOIN_INNER:

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp