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

Commitf01313b

Browse files
committed
Improve create_unique_path to not be fooled by unrelated clauses that happen
to be syntactically part of a semijoin clause. For example givenWHERE EXISTS(SELECT ... WHERE upper.var = lower.var AND some-condition)where some-condition is just a restriction on the lower relation, we canuse unique-ification on lower.var after having applied some-condition withinthe scan on lower.
1 parentf4fea44 commitf01313b

File tree

1 file changed

+60
-8
lines changed

1 file changed

+60
-8
lines changed

‎src/backend/optimizer/util/pathnode.c

Lines changed: 60 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
*
99
*
1010
* IDENTIFICATION
11-
* $PostgreSQL: pgsql/src/backend/optimizer/util/pathnode.c,v 1.149 2009/01/01 17:23:44 momjian Exp $
11+
* $PostgreSQL: pgsql/src/backend/optimizer/util/pathnode.c,v 1.150 2009/02/27 00:06:27 tgl Exp $
1212
*
1313
*-------------------------------------------------------------------------
1414
*/
@@ -765,19 +765,34 @@ create_unique_path(PlannerInfo *root, RelOptInfo *rel, Path *subpath,
765765
*/
766766
oldcontext=MemoryContextSwitchTo(root->planner_cxt);
767767

768-
/*
768+
/*----------
769769
* Look to see whether the semijoin's join quals consist of AND'ed
770770
* equality operators, with (only) RHS variables on only one side of
771771
* each one. If so, we can figure out how to enforce uniqueness for
772772
* the RHS.
773773
*
774+
* Note that the input join_quals list is the list of quals that are
775+
* *syntactically* associated with the semijoin, which in practice means
776+
* the synthesized comparison list for an IN or the WHERE of an EXISTS.
777+
* Particularly in the latter case, it might contain clauses that aren't
778+
* *semantically* associated with the join, but refer to just one side or
779+
* the other. We can ignore such clauses here, as they will just drop
780+
* down to be processed within one side or the other. (It is okay to
781+
* consider only the syntactically-associated clauses here because for a
782+
* semijoin, no higher-level quals could refer to the RHS, and so there
783+
* can be no other quals that are semantically associated with this join.
784+
* We do things this way because it is useful to be able to run this test
785+
* before we have extracted the list of quals that are actually
786+
* semantically associated with the particular join.)
787+
*
774788
* Note that the in_operators list consists of the joinqual operators
775789
* themselves (but commuted if needed to put the RHS value on the right).
776790
* These could be cross-type operators, in which case the operator
777791
* actually needed for uniqueness is a related single-type operator.
778792
* We assume here that that operator will be available from the btree
779793
* or hash opclass when the time comes ... if not, create_unique_plan()
780794
* will fail.
795+
*----------
781796
*/
782797
in_operators=NIL;
783798
uniq_exprs=NIL;
@@ -791,19 +806,52 @@ create_unique_path(PlannerInfo *root, RelOptInfo *rel, Path *subpath,
791806
Node*right_expr;
792807
Relidsleft_varnos;
793808
Relidsright_varnos;
809+
Relidsall_varnos;
794810

795-
/* must be binary opclause... */
796-
if (!IsA(op,OpExpr))
797-
gotono_unique_path;
798-
if (list_length(op->args)!=2)
811+
/* Is it a binary opclause? */
812+
if (!IsA(op,OpExpr)||
813+
list_length(op->args)!=2)
814+
{
815+
/* No, but does it reference both sides? */
816+
all_varnos=pull_varnos((Node*)op);
817+
if (!bms_overlap(all_varnos,sjinfo->syn_righthand)||
818+
bms_is_subset(all_varnos,sjinfo->syn_righthand))
819+
{
820+
/*
821+
* Clause refers to only one rel, so ignore it --- unless it
822+
* contains volatile functions, in which case we'd better
823+
* punt.
824+
*/
825+
if (contain_volatile_functions((Node*)op))
826+
gotono_unique_path;
827+
continue;
828+
}
829+
/* Non-operator clause referencing both sides, must punt */
799830
gotono_unique_path;
831+
}
832+
833+
/* Extract data from binary opclause */
800834
opno=op->opno;
801835
left_expr=linitial(op->args);
802836
right_expr=lsecond(op->args);
803-
804-
/* check rel membership of arguments */
805837
left_varnos=pull_varnos(left_expr);
806838
right_varnos=pull_varnos(right_expr);
839+
all_varnos=bms_union(left_varnos,right_varnos);
840+
841+
/* Does it reference both sides? */
842+
if (!bms_overlap(all_varnos,sjinfo->syn_righthand)||
843+
bms_is_subset(all_varnos,sjinfo->syn_righthand))
844+
{
845+
/*
846+
* Clause refers to only one rel, so ignore it --- unless it
847+
* contains volatile functions, in which case we'd better punt.
848+
*/
849+
if (contain_volatile_functions((Node*)op))
850+
gotono_unique_path;
851+
continue;
852+
}
853+
854+
/* check rel membership of arguments */
807855
if (!bms_is_empty(right_varnos)&&
808856
bms_is_subset(right_varnos,sjinfo->syn_righthand)&&
809857
!bms_overlap(left_varnos,sjinfo->syn_righthand))
@@ -845,6 +893,10 @@ create_unique_path(PlannerInfo *root, RelOptInfo *rel, Path *subpath,
845893
uniq_exprs=lappend(uniq_exprs,copyObject(right_expr));
846894
}
847895

896+
/* Punt if we didn't find at least one column to unique-ify */
897+
if (uniq_exprs==NIL)
898+
gotono_unique_path;
899+
848900
/*
849901
* The expressions we'd need to unique-ify mustn't be volatile.
850902
*/

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp