@ -10,7 +10,7 @@
*
*
* IDENTIFICATION
* $ PostgreSQL : pgsql / src / backend / optimizer / plan / createplan . c , v 1.237 2008 / 01 / 01 19 : 45 : 50 momjian Exp $
* $ PostgreSQL : pgsql / src / backend / optimizer / plan / createplan . c , v 1.238 2008 / 04 / 13 19 : 18 : 14 tgl Exp $
*
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
*/
@ -47,13 +47,12 @@ static Plan *create_unique_plan(PlannerInfo *root, UniquePath *best_path);
static SeqScan * create_seqscan_plan ( PlannerInfo * root , Path * best_path ,
List * tlist , List * scan_clauses ) ;
static IndexScan * create_indexscan_plan ( PlannerInfo * root , IndexPath * best_path ,
List * tlist , List * scan_clauses ,
List * * nonlossy_clauses ) ;
List * tlist , List * scan_clauses ) ;
static BitmapHeapScan * create_bitmap_scan_plan ( PlannerInfo * root ,
BitmapHeapPath * best_path ,
List * tlist , List * scan_clauses ) ;
static Plan * create_bitmap_subplan ( PlannerInfo * root , Path * bitmapqual ,
List * * qual , List * * indexqual ) ;
List * * qual ) ;
static TidScan * create_tidscan_plan ( PlannerInfo * root , TidPath * best_path ,
List * tlist , List * scan_clauses ) ;
static SubqueryScan * create_subqueryscan_plan ( PlannerInfo * root , Path * best_path ,
@ -70,7 +69,6 @@ static HashJoin *create_hashjoin_plan(PlannerInfo *root, HashPath *best_path,
Plan * outer_plan , Plan * inner_plan ) ;
static void fix_indexqual_references ( List * indexquals , IndexPath * index_path ,
List * * fixed_indexquals ,
List * * nonlossy_indexquals ,
List * * indexstrategy ,
List * * indexsubtype ) ;
static Node * fix_indexqual_operand ( Node * node , IndexOptInfo * index ,
@ -239,8 +237,7 @@ create_scan_plan(PlannerInfo *root, Path *best_path)
plan = ( Plan * ) create_indexscan_plan ( root ,
( IndexPath * ) best_path ,
tlist ,
scan_clauses ,
NULL ) ;
scan_clauses ) ;
break ;
case T_BitmapHeapScan :
@ -840,16 +837,12 @@ create_seqscan_plan(PlannerInfo *root, Path *best_path,
* The indexquals list of the path contains implicitly - ANDed qual conditions .
* The list can be empty - - - then no index restrictions will be applied during
* the scan .
*
* If nonlossy_clauses isn ' t NULL , * nonlossy_clauses receives a list of the
* nonlossy indexquals .
*/
static IndexScan *
create_indexscan_plan ( PlannerInfo * root ,
IndexPath * best_path ,
List * tlist ,
List * scan_clauses ,
List * * nonlossy_clauses )
List * scan_clauses )
{
List * indexquals = best_path - > indexquals ;
Index baserelid = best_path - > path . parent - > relid ;
@ -857,7 +850,6 @@ create_indexscan_plan(PlannerInfo *root,
List * qpqual ;
List * stripped_indexquals ;
List * fixed_indexquals ;
List * nonlossy_indexquals ;
List * indexstrategy ;
List * indexsubtype ;
ListCell * l ;
@ -876,18 +868,13 @@ create_indexscan_plan(PlannerInfo *root,
/*
* 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
* gets strategy info and looks for " lossy " operators .
* gets strategy info .
*/
fix_indexqual_references ( indexquals , best_path ,
& fixed_indexquals ,
& nonlossy_indexquals ,
& indexstrategy ,
& indexsubtype ) ;
/* pass back nonlossy quals if caller wants 'em */
if ( nonlossy_clauses )
* nonlossy_clauses = nonlossy_indexquals ;
/*
* If this is an innerjoin scan , the indexclauses will contain join
* clauses that are not present in scan_clauses ( since the passed - in value
@ -907,9 +894,8 @@ create_indexscan_plan(PlannerInfo *root,
* by the index . All the predicates in the indexquals will be checked
* ( either by the index itself , or by nodeIndexscan . c ) , but if there are
* any " special " operators involved then they must be included in qpqual .
* Also , any lossy index operators must be rechecked in the qpqual . The
* upshot is that qpqual must contain scan_clauses minus whatever appears
* in nonlossy_indexquals .
* The upshot is that qpqual must contain scan_clauses minus whatever
* appears in indexquals .
*
* In normal cases simple pointer equality checks will be enough to spot
* duplicate RestrictInfos , so we try that first . In some situations
@ -932,13 +918,13 @@ create_indexscan_plan(PlannerInfo *root,
Assert ( IsA ( rinfo , RestrictInfo ) ) ;
if ( rinfo - > pseudoconstant )
continue ; /* we may drop pseudoconstants here */
if ( list_member_ptr ( nonlossy_ indexquals, rinfo ) )
if ( list_member_ptr ( indexquals , rinfo ) )
continue ;
if ( ! contain_mutable_functions ( ( Node * ) rinfo - > clause ) )
{
List * clausel = list_make1 ( rinfo - > clause ) ;
if ( predicate_implied_by ( clausel , nonlossy_ indexquals) )
if ( predicate_implied_by ( clausel , indexquals ) )
continue ;
if ( best_path - > indexinfo - > indpred )
{
@ -990,7 +976,6 @@ create_bitmap_scan_plan(PlannerInfo *root,
Index baserelid = best_path - > path . parent - > relid ;
Plan * bitmapqualplan ;
List * bitmapqualorig ;
List * indexquals ;
List * qpqual ;
ListCell * l ;
BitmapHeapScan * scan_plan ;
@ -999,9 +984,9 @@ create_bitmap_scan_plan(PlannerInfo *root,
Assert ( baserelid > 0 ) ;
Assert ( best_path - > path . parent - > rtekind = = RTE_RELATION ) ;
/* Process the bitmapqual tree into a Plan tree and qual lists */
/* Process the bitmapqual tree into a Plan tree and qual list */
bitmapqualplan = create_bitmap_subplan ( root , best_path - > bitmapqual ,
& bitmapqualorig , & indexquals ) ;
& bitmapqualorig ) ;
/* Reduce RestrictInfo list to bare expressions; ignore pseudoconstants */
scan_clauses = extract_actual_clauses ( scan_clauses , false ) ;
@ -1023,9 +1008,9 @@ create_bitmap_scan_plan(PlannerInfo *root,
* The qpqual list must contain all restrictions not automatically handled
* by the index . All the predicates in the indexquals will be checked
* ( either by the index itself , or by nodeBitmapHeapscan . c ) , but if there
* are any " special " or lossy o perators involved then they must be added
* to qpqual . The upshot is that qpqual must contain scan_clauses minus
* whatever appears in indexquals .
* are any " special " operators involved then they must be added to qpqual .
* The upshot is that qpqual must contain scan_clauses minus whatever
* appears in bitmapqualorig .
*
* In normal cases simple equal ( ) checks will be enough to spot duplicate
* clauses , so we try that first . In some situations ( particularly with
@ -1037,22 +1022,22 @@ create_bitmap_scan_plan(PlannerInfo *root,
*
* Unlike create_indexscan_plan ( ) , we need take no special thought here
* for partial index predicates ; this is because the predicate conditions
* are already listed in bitmapqualorig and indexquals . Bitmap scans have
* to do it that way because predicate conditions need to be rechecked if
* the scan becomes lossy .
* are already listed in bitmapqualorig . Bitmap scans have to do it that
* way because predicate conditions need to be rechecked if the scan ' s
* bitmap becomes lossy .
*/
qpqual = NIL ;
foreach ( l , scan_clauses )
{
Node * clause = ( Node * ) lfirst ( l ) ;
if ( list_member ( indexquals , clause ) )
if ( list_member ( bitmapqualorig , clause ) )
continue ;
if ( ! contain_mutable_functions ( clause ) )
{
List * clausel = list_make1 ( clause ) ;
if ( predicate_implied_by ( clausel , indexquals ) )
if ( predicate_implied_by ( clausel , bitmapqualorig ) )
continue ;
}
qpqual = lappend ( qpqual , clause ) ;
@ -1062,7 +1047,7 @@ create_bitmap_scan_plan(PlannerInfo *root,
qpqual = order_qual_clauses ( root , qpqual ) ;
/*
* When dealing with special or lossy o perators , we will at this point
* When dealing with special operators , we will at this point
* have duplicate clauses in qpqual and bitmapqualorig . We may as well
* drop ' em from bitmapqualorig , since there ' s no point in making the
* tests twice .
@ -1086,19 +1071,19 @@ create_bitmap_scan_plan(PlannerInfo *root,
/*
* Given a bitmapqual tree , generate the Plan tree that implements it
*
* As byproducts , we also return in * qual and * indexqual the qual lists
* ( in implicit - AND form , without RestrictInfos ) describing the original index
* conditions and the generated indexqual conditions . The latter is made to
* exclude lossy index operators . Both lists include partial - index predicates ,
* because we have to recheck predicates as well as index conditions if the
* bitmap scan b ecomes lossy .
* As a byproduct , we also return in * qual a qual list ( in implicit - AND
* form , without RestrictInfos ) describing the generated indexqual
* conditions , as needed for rechecking heap tuples in lossy cases .
* This list also includes partial - index predicates , because we have to
* recheck predicates as well as index conditions if the scan ' s bitmap
* becomes lossy .
*
* Note : if you find yourself changing this , you probably need to change
* make_restrictinfo_from_bitmapqual too .
*/
static Plan *
create_bitmap_subplan ( PlannerInfo * root , Path * bitmapqual ,
List * * qual , List * * indexqual )
List * * qual )
{
Plan * plan ;
@ -1107,7 +1092,6 @@ create_bitmap_subplan(PlannerInfo *root, Path *bitmapqual,
BitmapAndPath * apath = ( BitmapAndPath * ) bitmapqual ;
List * subplans = NIL ;
List * subquals = NIL ;
List * subindexquals = NIL ;
ListCell * l ;
/*
@ -1121,13 +1105,11 @@ create_bitmap_subplan(PlannerInfo *root, Path *bitmapqual,
{
Plan * subplan ;
List * subqual ;
List * subindexqual ;
subplan = create_bitmap_subplan ( root , ( Path * ) lfirst ( l ) ,
& subqual , & subindexqual ) ;
& subqual ) ;
subplans = lappend ( subplans , subplan ) ;
subquals = list_concat_unique ( subquals , subqual ) ;
subindexquals = list_concat_unique ( subindexquals , subindexqual ) ;
}
plan = ( Plan * ) make_bitmap_and ( subplans ) ;
plan - > startup_cost = apath - > path . startup_cost ;
@ -1136,16 +1118,13 @@ create_bitmap_subplan(PlannerInfo *root, Path *bitmapqual,
clamp_row_est ( apath - > bitmapselectivity * apath - > path . parent - > tuples ) ;
plan - > plan_width = 0 ; /* meaningless */
* qual = subquals ;
* indexqual = subindexquals ;
}
else if ( IsA ( bitmapqual , BitmapOrPath ) )
{
BitmapOrPath * opath = ( BitmapOrPath * ) bitmapqual ;
List * subplans = NIL ;
List * subquals = NIL ;
List * subindexquals = NIL ;
bool const_true_subqual = false ;
bool const_true_subindexqual = false ;
ListCell * l ;
/*
@ -1161,21 +1140,15 @@ create_bitmap_subplan(PlannerInfo *root, Path *bitmapqual,
{
Plan * subplan ;
List * subqual ;
List * subindexqual ;
subplan = create_bitmap_subplan ( root , ( Path * ) lfirst ( l ) ,
& subqual , & subindexqual ) ;
& subqual ) ;
subplans = lappend ( subplans , subplan ) ;
if ( subqual = = NIL )
const_true_subqual = true ;
else if ( ! const_true_subqual )
subquals = lappend ( subquals ,
make_ands_explicit ( subqual ) ) ;
if ( subindexqual = = NIL )
const_true_subindexqual = true ;
else if ( ! const_true_subindexqual )
subindexquals = lappend ( subindexquals ,
make_ands_explicit ( subindexqual ) ) ;
}
/*
@ -1207,23 +1180,15 @@ create_bitmap_subplan(PlannerInfo *root, Path *bitmapqual,
* qual = subquals ;
else
* qual = list_make1 ( make_orclause ( subquals ) ) ;
if ( const_true_subindexqual )
* indexqual = NIL ;
else if ( list_length ( subindexquals ) < = 1 )
* indexqual = subindexquals ;
else
* indexqual = list_make1 ( make_orclause ( subindexquals ) ) ;
}
else if ( IsA ( bitmapqual , IndexPath ) )
{
IndexPath * ipath = ( IndexPath * ) bitmapqual ;
IndexScan * iscan ;
List * nonlossy_clauses ;
ListCell * l ;
/* Use the regular indexscan plan build machinery... */
iscan = create_indexscan_plan ( root , ipath , NIL , NIL ,
& nonlossy_clauses ) ;
iscan = create_indexscan_plan ( root , ipath , NIL , NIL ) ;
/* then convert to a bitmap indexscan */
plan = ( Plan * ) make_bitmap_indexscan ( iscan - > scan . scanrelid ,
iscan - > indexid ,
@ -1237,7 +1202,6 @@ create_bitmap_subplan(PlannerInfo *root, Path *bitmapqual,
clamp_row_est ( ipath - > indexselectivity * ipath - > path . parent - > tuples ) ;
plan - > plan_width = 0 ; /* meaningless */
* qual = get_actual_clauses ( ipath - > indexclauses ) ;
* indexqual = get_actual_clauses ( nonlossy_clauses ) ;
foreach ( l , ipath - > indexinfo - > indpred )
{
Expr * pred = ( Expr * ) lfirst ( l ) ;
@ -1249,10 +1213,7 @@ create_bitmap_subplan(PlannerInfo *root, Path *bitmapqual,
* generating redundant conditions .
*/
if ( ! predicate_implied_by ( list_make1 ( pred ) , ipath - > indexclauses ) )
{
* qual = lappend ( * qual , pred ) ;
* indexqual = lappend ( * indexqual , pred ) ;
}
}
}
else
@ -1794,9 +1755,9 @@ create_hashjoin_plan(PlannerInfo *root,
/*
* fix_indexqual_references
* Adjust indexqual clauses to the form the executor ' s indexqual
* machinery needs , and check for recheckable ( lossy ) index conditions .
* machinery needs .
*
* We have five tasks here :
* We have four tasks here :
* * Remove RestrictInfo nodes from the input clauses .
* * 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 .
@ -1804,24 +1765,18 @@ create_hashjoin_plan(PlannerInfo *root,
* left .
* * We must construct lists of operator strategy numbers and subtypes
* for the top - level operators of each index clause .
* * We must detect any lossy index operators . The API is that we return
* a list of the input clauses whose operators are NOT lossy .
*
* fixed_indexquals receives a modified copy of the indexquals list - - - the
* 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
* two separate copies of the subplan tree , or things will go awry ) .
*
* nonlossy_indexquals receives a list of the original input clauses ( with
* RestrictInfos ) that contain non - lossy operators .
*
* indexstrategy receives an integer list of strategy numbers .
* indexsubtype receives an OID list of strategy subtypes .
*/
static void
fix_indexqual_references ( List * indexquals , IndexPath * index_path ,
List * * fixed_indexquals ,
List * * nonlossy_indexquals ,
List * * indexstrategy ,
List * * indexsubtype )
{
@ -1829,7 +1784,6 @@ fix_indexqual_references(List *indexquals, IndexPath *index_path,
ListCell * l ;
* fixed_indexquals = NIL ;
* nonlossy_indexquals = NIL ;
* indexstrategy = NIL ;
* indexsubtype = NIL ;
@ -1837,7 +1791,7 @@ fix_indexqual_references(List *indexquals, IndexPath *index_path,
* 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
* other side of the clause . ) Then determine the operator ' s strategy
* number and subtype number , and check for lossy index behavior .
* number and subtype number .
*/
foreach ( l , indexquals )
{
@ -1848,7 +1802,6 @@ fix_indexqual_references(List *indexquals, IndexPath *index_path,
int stratno ;
Oid stratlefttype ;
Oid stratrighttype ;
bool recheck ;
bool is_null_op = false ;
Assert ( IsA ( rinfo , RestrictInfo ) ) ;
@ -1961,8 +1914,6 @@ fix_indexqual_references(List *indexquals, IndexPath *index_path,
/* IS NULL doesn't have a clause_op */
stratno = InvalidStrategy ;
stratrighttype = InvalidOid ;
/* We assume it's non-lossy ... might need more work someday */
recheck = false ;
}
else
{
@ -1971,6 +1922,8 @@ fix_indexqual_references(List *indexquals, IndexPath *index_path,
* 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 ,
& stratno ,
& stratlefttype ,
@ -1980,10 +1933,6 @@ fix_indexqual_references(List *indexquals, IndexPath *index_path,
* indexstrategy = lappend_int ( * indexstrategy , stratno ) ;
* indexsubtype = lappend_oid ( * indexsubtype , stratrighttype ) ;
/* If it's not lossy, add to nonlossy_indexquals */
if ( ! recheck )
* nonlossy_indexquals = lappend ( * nonlossy_indexquals , rinfo ) ;
}
}