@ -10,7 +10,7 @@
*
*
*
*
* IDENTIFICATION
* IDENTIFICATION
* $ PostgreSQL : pgsql / src / backend / optimizer / plan / createplan . c , v 1.238 2008 / 04 / 13 19 : 18 : 14 tgl Exp $
* $ PostgreSQL : pgsql / src / backend / optimizer / plan / createplan . c , v 1.239 2008 / 04 / 13 20 : 51 : 20 tgl Exp $
*
*
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
*/
*/
@ -67,12 +67,8 @@ static MergeJoin *create_mergejoin_plan(PlannerInfo *root, MergePath *best_path,
Plan * outer_plan , Plan * inner_plan ) ;
Plan * outer_plan , Plan * inner_plan ) ;
static HashJoin * create_hashjoin_plan ( PlannerInfo * root , HashPath * best_path ,
static HashJoin * create_hashjoin_plan ( PlannerInfo * root , HashPath * best_path ,
Plan * outer_plan , Plan * inner_plan ) ;
Plan * outer_plan , Plan * inner_plan ) ;
static void fix_indexqual_references ( List * indexquals , IndexPath * index_path ,
static List * fix_indexqual_references ( List * indexquals , IndexPath * index_path ) ;
List * * fixed_indexquals ,
static Node * fix_indexqual_operand ( Node * node , IndexOptInfo * index ) ;
List * * indexstrategy ,
List * * indexsubtype ) ;
static Node * fix_indexqual_operand ( Node * node , IndexOptInfo * index ,
Oid * opfamily ) ;
static List * get_switched_clauses ( List * clauses , Relids outerrelids ) ;
static List * get_switched_clauses ( List * clauses , Relids outerrelids ) ;
static List * order_qual_clauses ( PlannerInfo * root , List * clauses ) ;
static List * order_qual_clauses ( PlannerInfo * root , List * clauses ) ;
static void copy_path_costsize ( Plan * dest , Path * src ) ;
static void copy_path_costsize ( Plan * dest , Path * src ) ;
@ -80,13 +76,10 @@ static void copy_plan_costsize(Plan *dest, Plan *src);
static SeqScan * make_seqscan ( List * qptlist , List * qpqual , Index scanrelid ) ;
static SeqScan * make_seqscan ( List * qptlist , List * qpqual , Index scanrelid ) ;
static IndexScan * make_indexscan ( List * qptlist , List * qpqual , Index scanrelid ,
static IndexScan * make_indexscan ( List * qptlist , List * qpqual , Index scanrelid ,
Oid indexid , List * indexqual , List * indexqualorig ,
Oid indexid , List * indexqual , List * indexqualorig ,
List * indexstrategy , List * indexsubtype ,
ScanDirection indexscandir ) ;
ScanDirection indexscandir ) ;
static BitmapIndexScan * make_bitmap_indexscan ( Index scanrelid , Oid indexid ,
static BitmapIndexScan * make_bitmap_indexscan ( Index scanrelid , Oid indexid ,
List * indexqual ,
List * indexqual ,
List * indexqualorig ,
List * indexqualorig ) ;
List * indexstrategy ,
List * indexsubtype ) ;
static BitmapHeapScan * make_bitmap_heapscan ( List * qptlist ,
static BitmapHeapScan * make_bitmap_heapscan ( List * qptlist ,
List * qpqual ,
List * qpqual ,
Plan * lefttree ,
Plan * lefttree ,
@ -850,8 +843,6 @@ create_indexscan_plan(PlannerInfo *root,
List * qpqual ;
List * qpqual ;
List * stripped_indexquals ;
List * stripped_indexquals ;
List * fixed_indexquals ;
List * fixed_indexquals ;
List * indexstrategy ;
List * indexsubtype ;
ListCell * l ;
ListCell * l ;
IndexScan * scan_plan ;
IndexScan * scan_plan ;
@ -867,13 +858,9 @@ create_indexscan_plan(PlannerInfo *root,
/*
/*
* The executor needs a copy with the indexkey on the left of each clause
* The executor needs a copy with the indexkey on the left of each clause
* and with index attr numbers substituted for table ones . This pass also
* and with index attr numbers substituted for table ones .
* gets strategy info .
*/
*/
fix_indexqual_references ( indexquals , best_path ,
fixed_indexquals = fix_indexqual_references ( indexquals , best_path ) ;
& fixed_indexquals ,
& indexstrategy ,
& indexsubtype ) ;
/*
/*
* If this is an innerjoin scan , the indexclauses will contain join
* If this is an innerjoin scan , the indexclauses will contain join
@ -951,8 +938,6 @@ create_indexscan_plan(PlannerInfo *root,
indexoid ,
indexoid ,
fixed_indexquals ,
fixed_indexquals ,
stripped_indexquals ,
stripped_indexquals ,
indexstrategy ,
indexsubtype ,
best_path - > indexscandir ) ;
best_path - > indexscandir ) ;
copy_path_costsize ( & scan_plan - > scan . plan , & best_path - > path ) ;
copy_path_costsize ( & scan_plan - > scan . plan , & best_path - > path ) ;
@ -1193,9 +1178,7 @@ create_bitmap_subplan(PlannerInfo *root, Path *bitmapqual,
plan = ( Plan * ) make_bitmap_indexscan ( iscan - > scan . scanrelid ,
plan = ( Plan * ) make_bitmap_indexscan ( iscan - > scan . scanrelid ,
iscan - > indexid ,
iscan - > indexid ,
iscan - > indexqual ,
iscan - > indexqual ,
iscan - > indexqualorig ,
iscan - > indexqualorig ) ;
iscan - > indexstrategy ,
iscan - > indexsubtype ) ;
plan - > startup_cost = 0.0 ;
plan - > startup_cost = 0.0 ;
plan - > total_cost = ipath - > indextotalcost ;
plan - > total_cost = ipath - > indextotalcost ;
plan - > plan_rows =
plan - > plan_rows =
@ -1757,52 +1740,36 @@ create_hashjoin_plan(PlannerInfo *root,
* Adjust indexqual clauses to the form the executor ' s indexqual
* Adjust indexqual clauses to the form the executor ' s indexqual
* machinery needs .
* machinery needs .
*
*
* We have four tasks here :
* We have three tasks here :
* * Remove RestrictInfo nodes from the input clauses .
* * Remove RestrictInfo nodes from the input clauses .
* * Index keys must be represented by Var nodes with varattno set to the
* * Index keys must be represented by Var nodes with varattno set to the
* index ' s attribute number , not the attribute number in the original rel .
* index ' s attribute number , not the attribute number in the original rel .
* * If the index key is on the right , commute the clause to put it on the
* * If the index key is on the right , commute the clause to put it on the
* left .
* left .
* * We must construct lists of operator strategy numbers and subtypes
* for the top - level operators of each index clause .
*
*
* fixed_indexquals receive s a modified copy of the indexquals list - - - the
* The result is a modified copy of the indexquals list - - - the
* original is not changed . Note also that the copy shares no substructure
* original is not changed . Note also that the copy shares no substructure
* with the original ; this is needed in case there is a subplan in it ( we need
* with the original ; this is needed in case there is a subplan in it ( we need
* two separate copies of the subplan tree , or things will go awry ) .
* two separate copies of the subplan tree , or things will go awry ) .
*
* indexstrategy receives an integer list of strategy numbers .
* indexsubtype receives an OID list of strategy subtypes .
*/
*/
static void
static List *
fix_indexqual_references ( List * indexquals , IndexPath * index_path ,
fix_indexqual_references ( List * indexquals , IndexPath * index_path )
List * * fixed_indexquals ,
List * * indexstrategy ,
List * * indexsubtype )
{
{
IndexOptInfo * index = index_path - > indexinfo ;
IndexOptInfo * index = index_path - > indexinfo ;
List * fixed_indexquals ;
ListCell * l ;
ListCell * l ;
* fixed_indexquals = NIL ;
fixed_indexquals = NIL ;
* indexstrategy = NIL ;
* indexsubtype = NIL ;
/*
/*
* For each qual clause , commute if needed to put the indexkey operand on
* For each qual clause , commute if needed to put the indexkey operand on
* the left , and then fix its varattno . ( We do not need to change the
* the left , and then fix its varattno . ( We do not need to change the
* other side of the clause . ) Then determine the operator ' s strategy
* other side of the clause . )
* number and subtype number .
*/
*/
foreach ( l , indexquals )
foreach ( l , indexquals )
{
{
RestrictInfo * rinfo = ( RestrictInfo * ) lfirst ( l ) ;
RestrictInfo * rinfo = ( RestrictInfo * ) lfirst ( l ) ;
Expr * clause ;
Expr * clause ;
Oid clause_op ;
Oid opfamily ;
int stratno ;
Oid stratlefttype ;
Oid stratrighttype ;
bool is_null_op = false ;
Assert ( IsA ( rinfo , RestrictInfo ) ) ;
Assert ( IsA ( rinfo , RestrictInfo ) ) ;
@ -1831,13 +1798,11 @@ fix_indexqual_references(List *indexquals, IndexPath *index_path,
CommuteOpExpr ( op ) ;
CommuteOpExpr ( op ) ;
/*
/*
* Now , determine which index attribute this is , change the
* Now , determine which index attribute this is and change the
* indexkey operand as needed , and get the index opfamily .
* indexkey operand as needed .
*/
*/
linitial ( op - > args ) = fix_indexqual_operand ( linitial ( op - > args ) ,
linitial ( op - > args ) = fix_indexqual_operand ( linitial ( op - > args ) ,
index ,
index ) ;
& opfamily ) ;
clause_op = op - > opno ;
}
}
else if ( IsA ( clause , RowCompareExpr ) )
else if ( IsA ( clause , RowCompareExpr ) )
{
{
@ -1856,23 +1821,12 @@ fix_indexqual_references(List *indexquals, IndexPath *index_path,
/*
/*
* For each column in the row comparison , determine which index
* For each column in the row comparison , determine which index
* attribute this is and change the indexkey operand as needed .
* attribute this is and change the indexkey operand as needed .
*
* Save the index opfamily for only the first column . We will
* return the operator and opfamily info for just the first column
* of the row comparison ; the executor will have to look up the
* rest if it needs them .
*/
*/
foreach ( lc , rc - > largs )
foreach ( lc , rc - > largs )
{
{
Oid tmp_opfamily ;
lfirst ( lc ) = fix_indexqual_operand ( lfirst ( lc ) ,
lfirst ( lc ) = fix_indexqual_operand ( lfirst ( lc ) ,
index ,
index ) ;
& tmp_opfamily ) ;
if ( lc = = list_head ( rc - > largs ) )
opfamily = tmp_opfamily ;
}
}
clause_op = linitial_oid ( rc - > opnos ) ;
}
}
else if ( IsA ( clause , ScalarArrayOpExpr ) )
else if ( IsA ( clause , ScalarArrayOpExpr ) )
{
{
@ -1881,13 +1835,11 @@ fix_indexqual_references(List *indexquals, IndexPath *index_path,
/* Never need to commute... */
/* Never need to commute... */
/*
/*
* Now , d etermine which index attribute this is , change the
* D etermine which index attribute this is and change the
* indexkey operand as needed , and get the index opfamily .
* indexkey operand as needed .
*/
*/
linitial ( saop - > args ) = fix_indexqual_operand ( linitial ( saop - > args ) ,
linitial ( saop - > args ) = fix_indexqual_operand ( linitial ( saop - > args ) ,
index ,
index ) ;
& opfamily ) ;
clause_op = saop - > opno ;
}
}
else if ( IsA ( clause , NullTest ) )
else if ( IsA ( clause , NullTest ) )
{
{
@ -1895,49 +1847,20 @@ fix_indexqual_references(List *indexquals, IndexPath *index_path,
Assert ( nt - > nulltesttype = = IS_NULL ) ;
Assert ( nt - > nulltesttype = = IS_NULL ) ;
nt - > arg = ( Expr * ) fix_indexqual_operand ( ( Node * ) nt - > arg ,
nt - > arg = ( Expr * ) fix_indexqual_operand ( ( Node * ) nt - > arg ,
index ,
index ) ;
& opfamily ) ;
is_null_op = true ;
clause_op = InvalidOid ; /* keep compiler quiet */
}
}
else
else
{
elog ( ERROR , " unsupported indexqual type: %d " ,
elog ( ERROR , " unsupported indexqual type: %d " ,
( int ) nodeTag ( clause ) ) ;
( int ) nodeTag ( clause ) ) ;
continue ; /* keep compiler quiet */
}
* fixed_indexquals = lappend ( * fixed_indexquals , clause ) ;
if ( is_null_op )
fixed_indexquals = lappend ( fixed_indexquals , clause ) ;
{
/* IS NULL doesn't have a clause_op */
stratno = InvalidStrategy ;
stratrighttype = InvalidOid ;
}
}
else
{
/*
* Look up the ( possibly commuted ) operator in the operator family
* to get its strategy number and the recheck indicator . This also
* double - checks that we found an operator matching the index .
*/
bool recheck ;
get_op_opfamily_properties ( clause_op , opfamily ,
return fixed_indexquals ;
& stratno ,
& stratlefttype ,
& stratrighttype ,
& recheck ) ;
}
* indexstrategy = lappend_int ( * indexstrategy , stratno ) ;
* indexsubtype = lappend_oid ( * indexsubtype , stratrighttype ) ;
}
}
}
static Node *
static Node *
fix_indexqual_operand ( Node * node , IndexOptInfo * index , Oid * opfamily )
fix_indexqual_operand ( Node * node , IndexOptInfo * index )
{
{
/*
/*
* We represent index keys by Var nodes having the varno of the base table
* We represent index keys by Var nodes having the varno of the base table
@ -1970,8 +1893,6 @@ fix_indexqual_operand(Node *node, IndexOptInfo *index, Oid *opfamily)
{
{
result = ( Var * ) copyObject ( node ) ;
result = ( Var * ) copyObject ( node ) ;
result - > varattno = pos + 1 ;
result - > varattno = pos + 1 ;
/* return the correct opfamily, too */
* opfamily = index - > opfamily [ pos ] ;
return ( Node * ) result ;
return ( Node * ) result ;
}
}
}
}
@ -1997,8 +1918,6 @@ fix_indexqual_operand(Node *node, IndexOptInfo *index, Oid *opfamily)
result = makeVar ( index - > rel - > relid , pos + 1 ,
result = makeVar ( index - > rel - > relid , pos + 1 ,
exprType ( lfirst ( indexpr_item ) ) , - 1 ,
exprType ( lfirst ( indexpr_item ) ) , - 1 ,
0 ) ;
0 ) ;
/* return the correct opfamily, too */
* opfamily = index - > opfamily [ pos ] ;
return ( Node * ) result ;
return ( Node * ) result ;
}
}
indexpr_item = lnext ( indexpr_item ) ;
indexpr_item = lnext ( indexpr_item ) ;
@ -2007,8 +1926,7 @@ fix_indexqual_operand(Node *node, IndexOptInfo *index, Oid *opfamily)
/* Ooops... */
/* Ooops... */
elog ( ERROR , " node is not an index attribute " ) ;
elog ( ERROR , " node is not an index attribute " ) ;
* opfamily = InvalidOid ; /* keep compiler quiet */
return NULL ; /* keep compiler quiet */
return NULL ;
}
}
/*
/*
@ -2229,8 +2147,6 @@ make_indexscan(List *qptlist,
Oid indexid ,
Oid indexid ,
List * indexqual ,
List * indexqual ,
List * indexqualorig ,
List * indexqualorig ,
List * indexstrategy ,
List * indexsubtype ,
ScanDirection indexscandir )
ScanDirection indexscandir )
{
{
IndexScan * node = makeNode ( IndexScan ) ;
IndexScan * node = makeNode ( IndexScan ) ;
@ -2245,8 +2161,6 @@ make_indexscan(List *qptlist,
node - > indexid = indexid ;
node - > indexid = indexid ;
node - > indexqual = indexqual ;
node - > indexqual = indexqual ;
node - > indexqualorig = indexqualorig ;
node - > indexqualorig = indexqualorig ;
node - > indexstrategy = indexstrategy ;
node - > indexsubtype = indexsubtype ;
node - > indexorderdir = indexscandir ;
node - > indexorderdir = indexscandir ;
return node ;
return node ;
@ -2256,9 +2170,7 @@ static BitmapIndexScan *
make_bitmap_indexscan ( Index scanrelid ,
make_bitmap_indexscan ( Index scanrelid ,
Oid indexid ,
Oid indexid ,
List * indexqual ,
List * indexqual ,
List * indexqualorig ,
List * indexqualorig )
List * indexstrategy ,
List * indexsubtype )
{
{
BitmapIndexScan * node = makeNode ( BitmapIndexScan ) ;
BitmapIndexScan * node = makeNode ( BitmapIndexScan ) ;
Plan * plan = & node - > scan . plan ;
Plan * plan = & node - > scan . plan ;
@ -2272,8 +2184,6 @@ make_bitmap_indexscan(Index scanrelid,
node - > indexid = indexid ;
node - > indexid = indexid ;
node - > indexqual = indexqual ;
node - > indexqual = indexqual ;
node - > indexqualorig = indexqualorig ;
node - > indexqualorig = indexqualorig ;
node - > indexstrategy = indexstrategy ;
node - > indexsubtype = indexsubtype ;
return node ;
return node ;
}
}