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

Commit10d6d41

Browse files
committed
Rewrite fix_indxqual_references, which was entirely bogus for
multi-scan indexscan plans; it tried to use the same table-to-indexattribute mapping for all the scans, even if they used different indexes.It would klugily work as long as OR indexquals never used multikey indexes,but that's not likely to hold up much longer...
1 parentecef2ca commit10d6d41

File tree

1 file changed

+134
-147
lines changed

1 file changed

+134
-147
lines changed

‎src/backend/optimizer/plan/createplan.c

Lines changed: 134 additions & 147 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
*
88
*
99
* IDENTIFICATION
10-
* $Header: /cvsroot/pgsql/src/backend/optimizer/plan/createplan.c,v 1.66 1999/07/30 00:44:23 tgl Exp $
10+
* $Header: /cvsroot/pgsql/src/backend/optimizer/plan/createplan.c,v 1.67 1999/08/09 01:01:42 tgl Exp $
1111
*
1212
*-------------------------------------------------------------------------
1313
*/
@@ -48,7 +48,11 @@ static MergeJoin *create_mergejoin_node(MergePath *best_path, List *tlist,
4848
staticHashJoin*create_hashjoin_node(HashPath*best_path,List*tlist,
4949
List*clauses,Plan*outer_node,List*outer_tlist,
5050
Plan*inner_node,List*inner_tlist);
51-
staticNode*fix_indxqual_references(Node*clause,Path*index_path);
51+
staticList*fix_indxqual_references(List*indexquals,IndexPath*index_path);
52+
staticList*fix_one_indxqual_sublist(List*indexqual,IndexPath*index_path,
53+
Form_pg_indexindex);
54+
staticNode*fix_one_indxqual_operand(Node*node,IndexPath*index_path,
55+
Form_pg_indexindex);
5256
staticNoname*make_noname(List*tlist,List*pathkeys,Oid*operators,
5357
Plan*plan_node,intnonametype);
5458
staticIndexScan*make_indexscan(List*qptlist,List*qpqual,Indexscanrelid,
@@ -393,8 +397,7 @@ create_indexscan_node(IndexPath *best_path,
393397
indxqual=fix_opids(indxqual);
394398

395399
/* The executor needs a copy with index attrs substituted for table ones */
396-
fixed_indxqual= (List*)fix_indxqual_references((Node*)indxqual,
397-
(Path*)best_path);
400+
fixed_indxqual=fix_indxqual_references(indxqual,best_path);
398401

399402
scan_node=make_indexscan(tlist,
400403
qpqual,
@@ -457,24 +460,26 @@ create_nestloop_node(NestPath *best_path,
457460
* the inner(index) scan's qualification so that the var nodes
458461
* refer to the proper outer join relation attributes.
459462
*
460-
* XXXRe-moving index clauses doesn't work properly: 1.
463+
* XXXRemoving index clauses doesn't work properly: 1.
461464
* fix_indxqual_references may change varattno-s in
462465
* inner_indxqual; 2. clauses may be commuted I havn't time to fix
463466
* it at the moment. - vadim 04/24/97
464467
*/
465468
if (found)
466469
{
467-
List*new_inner_qual=NIL;
470+
List*new_inner_qual;
468471

469472
clauses=set_difference(clauses,inner_indxqual);/* XXX */
470-
new_inner_qual=index_outerjoin_references(inner_indxqual,
471-
outer_node->targetlist,
472-
((Scan*)inner_node)->scanrelid);
473+
/* only refs to outer vars get changed in the inner indexqual */
474+
new_inner_qual=join_references(inner_indxqual,
475+
outer_tlist,
476+
NIL);
473477
((IndexScan*)inner_node)->indxqual=lcons(new_inner_qual,NIL);
474478
}
475479
}
476480
elseif (IsA_Join(inner_node))
477481
{
482+
/* Materialize the inner join for speed reasons */
478483
inner_node= (Plan*)make_noname(inner_tlist,
479484
NIL,
480485
NULL,
@@ -629,160 +634,142 @@ create_hashjoin_node(HashPath *best_path,
629634

630635
/*
631636
* fix_indxqual_references
632-
*Adjust a qual clause to refer to an index instead of the original relation.
637+
*Adjust indexqual clauses to refer to index attributes instead of the
638+
*attributes of the original relation.
633639
*
634-
* Returns a modified copy of the given clause --- the original is not changed.
640+
* This code used to be entirely bogus for multi-index scans. Now it keeps
641+
* track of which index applies to each subgroup of index qual clauses...
642+
*
643+
* Returns a modified copy of the indexqual list --- the original is not
644+
* changed.
635645
*/
636646

637-
staticNode*
638-
fix_indxqual_references(Node*clause,Path*index_path)
647+
staticList*
648+
fix_indxqual_references(List*indexquals,IndexPath*index_path)
639649
{
640-
if (clause==NULL)
641-
returnNULL;
642-
elseif (IsA(clause,Var))
643-
{
644-
if (lfirsti(index_path->parent->relids)== ((Var*)clause)->varno)
645-
{
646-
Node*newclause;
647-
intpos=0;
648-
intvaratt= ((Var*)clause)->varattno;
649-
int*indexkeys= ((IndexPath*)index_path)->indexkeys;
650+
List*fixed_quals=NIL;
651+
List*indexids=index_path->indexid;
652+
List*i;
650653

651-
if (indexkeys)
652-
{
653-
while (indexkeys[pos]!=0)
654-
{
655-
if (varatt==indexkeys[pos])
656-
break;
657-
pos++;
658-
}
659-
}
660-
newclause=copyObject(clause);
661-
((Var*)newclause)->varattno=pos+1;
662-
returnnewclause;
663-
}
664-
/* The Var is not part of the indexed relation, leave it alone */
665-
returncopyObject(clause);
666-
}
667-
elseif (single_node(clause))
668-
returncopyObject(clause);
669-
elseif (is_opclause(clause)&&
670-
is_funcclause((Node*)get_leftop((Expr*)clause))&&
671-
((Func*) ((Expr*)get_leftop((Expr*)clause))->oper)->funcisindex)
654+
foreach(i,indexquals)
672655
{
656+
List*indexqual=lfirst(i);
657+
Oidindexid=lfirsti(indexids);
658+
HeapTupleindexTuple;
659+
Form_pg_indexindex;
673660

674-
/*
675-
* This looks pretty seriously wrong to me, but I'm not sure what
676-
* it's supposed to be doing ... tgl 5/99
677-
*/
678-
Var*newvar=makeVar((Index)lfirsti(index_path->parent->relids),
679-
1,/* func indices have one key */
680-
((Func*) ((Expr*)clause)->oper)->functype,
681-
-1,
682-
0,
683-
(Index)lfirsti(index_path->parent->relids),
684-
0);
685-
686-
return ((Node*)make_opclause((Oper*) ((Expr*)clause)->oper,
687-
newvar,
688-
get_rightop((Expr*)clause)));
661+
indexTuple=SearchSysCacheTuple(INDEXRELID,
662+
ObjectIdGetDatum(indexid),
663+
0,0,0);
664+
if (!HeapTupleIsValid(indexTuple))
665+
elog(ERROR,"fix_indxqual_references: index %u not found",
666+
indexid);
667+
index= (Form_pg_index)GETSTRUCT(indexTuple);
689668

690-
}
691-
elseif (IsA(clause,Expr))
692-
{
693-
Expr*expr= (Expr*)clause;
694-
List*new_subclauses=NIL;
695-
List*i;
669+
fixed_quals=lappend(fixed_quals,
670+
fix_one_indxqual_sublist(indexqual,
671+
index_path,
672+
index));
696673

697-
foreach(i,expr->args)
698-
{
699-
Node*subclause=lfirst(i);
674+
indexids=lnext(indexids);
675+
}
676+
returnfixed_quals;
677+
}
700678

701-
new_subclauses=lappend(new_subclauses,
702-
fix_indxqual_references(subclause,
703-
index_path));
704-
}
679+
/*
680+
* Fix the sublist of indexquals to be used in a particular scan.
681+
*
682+
* All that we need to do is change the left or right operand of the top-level
683+
* operator of each qual clause. Those are the only places that the index
684+
* attribute can appear in a valid indexqual. The other side of the indexqual
685+
* might be a complex function of joined rels; we do not need or want to
686+
* alter such an expression.
687+
*/
688+
staticList*
689+
fix_one_indxqual_sublist(List*indexqual,IndexPath*index_path,
690+
Form_pg_indexindex)
691+
{
692+
List*fixed_qual=NIL;
693+
List*i;
705694

706-
return (Node*)make_clause(expr->opType,expr->oper,new_subclauses);
707-
}
708-
elseif (IsA(clause,List))
695+
foreach(i,indexqual)
709696
{
710-
List*new_subclauses=NIL;
711-
List*i;
697+
Node*clause=lfirst(i);
698+
List*args;
699+
Expr*newclause;
700+
701+
if (!is_opclause(clause))
702+
elog(ERROR,"fix_one_indxqual_sublist: indexqual clause is not opclause");
703+
704+
/* Copy enough structure to allow replacing left or right operand */
705+
args=listCopy(((Expr*)clause)->args);
706+
newclause=make_clause(((Expr*)clause)->opType,
707+
((Expr*)clause)->oper,
708+
args);
709+
710+
lfirst(args)=fix_one_indxqual_operand(lfirst(args),
711+
index_path,
712+
index);
713+
if (lnext(args))
714+
lfirst(lnext(args))=fix_one_indxqual_operand(lfirst(lnext(args)),
715+
index_path,
716+
index);
717+
718+
fixed_qual=lappend(fixed_qual,newclause);
719+
}
720+
returnfixed_qual;
721+
}
712722

713-
foreach(i, (List*)clause)
723+
staticNode*
724+
fix_one_indxqual_operand(Node*node,IndexPath*index_path,
725+
Form_pg_indexindex)
726+
{
727+
if (node==NULL)
728+
returnNULL;
729+
if (IsA(node,Var))
730+
{
731+
if (((Var*)node)->varno==lfirsti(index_path->path.parent->relids))
714732
{
715-
Node*subclause=lfirst(i);
733+
intvaratt= ((Var*)node)->varattno;
734+
intpos;
716735

717-
new_subclauses=lappend(new_subclauses,
718-
fix_indxqual_references(subclause,
719-
index_path));
736+
for (pos=0;pos<INDEX_MAX_KEYS;pos++)
737+
{
738+
if (index->indkey[pos]==varatt)
739+
{
740+
Node*newnode=copyObject(node);
741+
((Var*)newnode)->varattno=pos+1;
742+
returnnewnode;
743+
}
744+
}
745+
/*
746+
* We should never see a reference to an attribute of the indexed
747+
* relation that is not one of the indexed attributes.
748+
*/
749+
elog(ERROR,"fix_one_indxqual_operand: failed to find index pos of index attribute");
720750
}
721-
722-
return (Node*)new_subclauses;
723-
}
724-
elseif (IsA(clause,ArrayRef))
725-
{
726-
ArrayRef*oldnode= (ArrayRef*)clause;
727-
ArrayRef*newnode=makeNode(ArrayRef);
728-
729-
newnode->refattrlength=oldnode->refattrlength;
730-
newnode->refelemlength=oldnode->refelemlength;
731-
newnode->refelemtype=oldnode->refelemtype;
732-
newnode->refelembyval=oldnode->refelembyval;
733-
newnode->refupperindexpr= (List*)
734-
fix_indxqual_references((Node*)oldnode->refupperindexpr,
735-
index_path);
736-
newnode->reflowerindexpr= (List*)
737-
fix_indxqual_references((Node*)oldnode->reflowerindexpr,
738-
index_path);
739-
newnode->refexpr=
740-
fix_indxqual_references(oldnode->refexpr,index_path);
741-
newnode->refassgnexpr=
742-
fix_indxqual_references(oldnode->refassgnexpr,index_path);
743-
744-
return (Node*)newnode;
745-
}
746-
elseif (IsA(clause,CaseExpr))
747-
{
748-
CaseExpr*oldnode= (CaseExpr*)clause;
749-
CaseExpr*newnode=makeNode(CaseExpr);
750-
751-
newnode->casetype=oldnode->casetype;
752-
newnode->arg=oldnode->arg;/* XXX should always be null
753-
* anyway ... */
754-
newnode->args= (List*)
755-
fix_indxqual_references((Node*)oldnode->args,
756-
index_path);
757-
newnode->defresult=
758-
fix_indxqual_references(oldnode->defresult,
759-
index_path);
760-
761-
return (Node*)newnode;
751+
/*
752+
* The Var is not part of the indexed relation, leave it alone.
753+
* This would normally only occur when looking at the other side
754+
* of a join indexqual.
755+
*/
756+
returnnode;
762757
}
763-
elseif (IsA(clause,CaseWhen))
764-
{
765-
CaseWhen*oldnode= (CaseWhen*)clause;
766-
CaseWhen*newnode=makeNode(CaseWhen);
767758

768-
newnode->expr=
769-
fix_indxqual_references(oldnode->expr,
770-
index_path);
771-
newnode->result=
772-
fix_indxqual_references(oldnode->result,
773-
index_path);
759+
/*
760+
* Note: currently, there is no need for us to do anything here for
761+
* functional indexes. If nodeIndexscan.c sees a func clause as the left
762+
* or right-hand toplevel operand of an indexqual, it assumes that that is
763+
* a reference to the functional index's value and makes the appropriate
764+
* substitution. (It would be cleaner to make the substitution here, I
765+
* think --- suspect this issue if a join clause involving a function call
766+
* misbehaves...)
767+
*/
774768

775-
return (Node*)newnode;
776-
}
777-
else
778-
{
779-
elog(ERROR,"fix_indxqual_references: Cannot handle node type %d",
780-
nodeTag(clause));
781-
returnNULL;
782-
}
769+
/* return the unmodified node */
770+
returnnode;
783771
}
784772

785-
786773
/*
787774
* switch_outer
788775
* Given a list of merge clauses, rearranges the elements within the
@@ -794,14 +781,13 @@ static List *
794781
switch_outer(List*clauses)
795782
{
796783
List*t_list=NIL;
797-
Expr*temp;
798784
List*i;
799-
Expr*clause;
800-
Node*op;
801785

802786
foreach(i,clauses)
803787
{
804-
clause=lfirst(i);
788+
Expr*clause=lfirst(i);
789+
Node*op;
790+
805791
Assert(is_opclause((Node*)clause));
806792
op= (Node*)get_rightop(clause);
807793
Assert(op!= (Node*)NULL);
@@ -810,12 +796,13 @@ switch_outer(List *clauses)
810796
Assert(IsA(op,Var));
811797
if (var_is_outer((Var*)op))
812798
{
813-
814799
/*
815800
* Duplicate just enough of the structure to allow commuting
816801
* the clause without changing the original list. Could use
817802
* copyObject, but a complete deep copy is overkill.
818803
*/
804+
Expr*temp;
805+
819806
temp=make_clause(clause->opType,clause->oper,
820807
lcons(get_leftop(clause),
821808
lcons(get_rightop(clause),

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp