@ -197,7 +197,6 @@ static bool get_actual_variable_range(PlannerInfo *root,
Oid sortop ,
Oid sortop ,
Datum * min , Datum * max ) ;
Datum * min , Datum * max ) ;
static RelOptInfo * find_join_input_rel ( PlannerInfo * root , Relids relids ) ;
static RelOptInfo * find_join_input_rel ( PlannerInfo * root , Relids relids ) ;
static List * add_predicate_to_quals ( IndexOptInfo * index , List * indexQuals ) ;
/*
/*
@ -5251,9 +5250,11 @@ find_join_input_rel(PlannerInfo *root, Relids relids)
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
*/
*/
/* Extract the actual indexquals (as RestrictInfos) from an IndexClause list */
/*
static List *
* Extract the actual indexquals ( as RestrictInfos ) from an IndexClause list
get_index_quals ( List * indexclauses )
*/
List *
get_quals_from_indexclauses ( List * indexclauses )
{
{
List * result = NIL ;
List * result = NIL ;
ListCell * lc ;
ListCell * lc ;
@ -5273,113 +5274,59 @@ get_index_quals(List *indexclauses)
return result ;
return result ;
}
}
List *
deconstruct_indexquals ( IndexPath * path )
{
List * result = NIL ;
ListCell * lc ;
foreach ( lc , path - > indexclauses )
{
IndexClause * iclause = lfirst_node ( IndexClause , lc ) ;
int indexcol = iclause - > indexcol ;
ListCell * lc2 ;
foreach ( lc2 , iclause - > indexquals )
{
RestrictInfo * rinfo = lfirst_node ( RestrictInfo , lc2 ) ;
Expr * clause = rinfo - > clause ;
IndexQualInfo * qinfo ;
qinfo = ( IndexQualInfo * ) palloc ( sizeof ( IndexQualInfo ) ) ;
qinfo - > rinfo = rinfo ;
qinfo - > indexcol = indexcol ;
if ( IsA ( clause , OpExpr ) )
{
qinfo - > clause_op = ( ( OpExpr * ) clause ) - > opno ;
qinfo - > other_operand = get_rightop ( clause ) ;
}
else if ( IsA ( clause , RowCompareExpr ) )
{
RowCompareExpr * rc = ( RowCompareExpr * ) clause ;
qinfo - > clause_op = linitial_oid ( rc - > opnos ) ;
qinfo - > other_operand = ( Node * ) rc - > rargs ;
}
else if ( IsA ( clause , ScalarArrayOpExpr ) )
{
ScalarArrayOpExpr * saop = ( ScalarArrayOpExpr * ) clause ;
qinfo - > clause_op = saop - > opno ;
qinfo - > other_operand = ( Node * ) lsecond ( saop - > args ) ;
}
else if ( IsA ( clause , NullTest ) )
{
qinfo - > clause_op = InvalidOid ;
qinfo - > other_operand = NULL ;
}
else
{
elog ( ERROR , " unsupported indexqual type: %d " ,
( int ) nodeTag ( clause ) ) ;
}
result = lappend ( result , qinfo ) ;
}
}
return result ;
}
/*
/*
* Simple function to compute the total eval cost of the " other operands "
* Compute the total evaluation cost of the comparison operands in a list
* in an IndexQualInfo list . Since we know these will be evaluated just
* of index qual expressions . Since we know these will be evaluated just
* once per scan , there ' s no need to distinguish startup from per - row cost .
* once per scan , there ' s no need to distinguish startup from per - row cost .
*/
static Cost
other_operands_eval_cost ( PlannerInfo * root , List * qinfos )
{
Cost qual_arg_cost = 0 ;
ListCell * lc ;
foreach ( lc , qinfos )
{
IndexQualInfo * qinfo = ( IndexQualInfo * ) lfirst ( lc ) ;
QualCost index_qual_cost ;
cost_qual_eval_node ( & index_qual_cost , qinfo - > other_operand , root ) ;
qual_arg_cost + = index_qual_cost . startup + index_qual_cost . per_tuple ;
}
return qual_arg_cost ;
}
/*
* Get other - operand eval cost for an index orderby list .
*
*
* Index orderby expressions aren ' t represented as RestrictInfos ( since they
* This can be used either on the result of get_quals_from_indexclauses ( ) ,
* aren ' t boolean , usually ) . So we can ' t apply deconstruct_indexquals to
* or directly on an indexorderbys list . In both cases , we expect that the
* them . However , they are much simpler to deal with since they are always
* index key expression is on the left side of binary clauses .
* OpExprs and the index column is always on the left .
*/
*/
static Cost
Cost
orderby _operands_eval_cost( PlannerInfo * root , IndexPath * path )
index_other_operands_eval_cost ( PlannerInfo * root , List * indexquals )
{
{
Cost qual_arg_cost = 0 ;
Cost qual_arg_cost = 0 ;
ListCell * lc ;
ListCell * lc ;
foreach ( lc , path - > indexorderby s)
foreach ( lc , indexquals )
{
{
Expr * clause = ( Expr * ) lfirst ( lc ) ;
Expr * clause = ( Expr * ) lfirst ( lc ) ;
Node * other_operand ;
Node * other_operand ;
QualCost index_qual_cost ;
QualCost index_qual_cost ;
/*
* Index quals will have RestrictInfos , indexorderbys won ' t . Look
* through RestrictInfo if present .
*/
if ( IsA ( clause , RestrictInfo ) )
clause = ( ( RestrictInfo * ) clause ) - > clause ;
if ( IsA ( clause , OpExpr ) )
if ( IsA ( clause , OpExpr ) )
{
{
other_operand = get_rightop ( clause ) ;
OpExpr * op = ( OpExpr * ) clause ;
other_operand = ( Node * ) lsecond ( op - > args ) ;
}
else if ( IsA ( clause , RowCompareExpr ) )
{
RowCompareExpr * rc = ( RowCompareExpr * ) clause ;
other_operand = ( Node * ) rc - > rargs ;
}
else if ( IsA ( clause , ScalarArrayOpExpr ) )
{
ScalarArrayOpExpr * saop = ( ScalarArrayOpExpr * ) clause ;
other_operand = ( Node * ) lsecond ( saop - > args ) ;
}
else if ( IsA ( clause , NullTest ) )
{
other_operand = NULL ;
}
}
else
else
{
{
elog ( ERROR , " unsupported indexorderby type: %d " ,
elog ( ERROR , " unsupported indexqual type: %d " ,
( int ) nodeTag ( clause ) ) ;
( int ) nodeTag ( clause ) ) ;
other_operand = NULL ; /* keep compiler quiet */
other_operand = NULL ; /* keep compiler quiet */
}
}
@ -5394,11 +5341,10 @@ void
genericcostestimate ( PlannerInfo * root ,
genericcostestimate ( PlannerInfo * root ,
IndexPath * path ,
IndexPath * path ,
double loop_count ,
double loop_count ,
List * qinfos ,
GenericCosts * costs )
GenericCosts * costs )
{
{
IndexOptInfo * index = path - > indexinfo ;
IndexOptInfo * index = path - > indexinfo ;
List * indexQuals = get_index_qual s ( path - > indexclauses ) ;
List * indexQuals = get_quals_from_indexclause s ( path - > indexclauses ) ;
List * indexOrderBys = path - > indexorderbys ;
List * indexOrderBys = path - > indexorderbys ;
Cost indexStartupCost ;
Cost indexStartupCost ;
Cost indexTotalCost ;
Cost indexTotalCost ;
@ -5420,7 +5366,7 @@ genericcostestimate(PlannerInfo *root,
* given indexquals to produce a more accurate idea of the index
* given indexquals to produce a more accurate idea of the index
* selectivity .
* selectivity .
*/
*/
selectivityQuals = add_predicate_to_quals ( index , indexQuals ) ;
selectivityQuals = add_predicate_to_index_ quals ( index , indexQuals ) ;
/*
/*
* Check for ScalarArrayOpExpr index quals , and estimate the number of
* Check for ScalarArrayOpExpr index quals , and estimate the number of
@ -5563,8 +5509,8 @@ genericcostestimate(PlannerInfo *root,
* Detecting that that might be needed seems more expensive than it ' s
* Detecting that that might be needed seems more expensive than it ' s
* worth , though , considering all the other inaccuracies here . . .
* worth , though , considering all the other inaccuracies here . . .
*/
*/
qual_arg_cost = other_operands_eval_cost ( root , qinfo s) +
qual_arg_cost = index_ other_operands_eval_cost( root , indexQual s) +
orderby _operands_eval_cost( root , path ) ;
index_other _operands_eval_cost( root , indexOrderBys ) ;
qual_op_cost = cpu_operator_cost *
qual_op_cost = cpu_operator_cost *
( list_length ( indexQuals ) + list_length ( indexOrderBys ) ) ;
( list_length ( indexQuals ) + list_length ( indexOrderBys ) ) ;
@ -5609,8 +5555,8 @@ genericcostestimate(PlannerInfo *root,
* predicate_implied_by ( ) and clauselist_selectivity ( ) , but might be
* predicate_implied_by ( ) and clauselist_selectivity ( ) , but might be
* problematic if the result were passed to other things .
* problematic if the result were passed to other things .
*/
*/
static List *
List *
add_predicate_to_quals ( IndexOptInfo * index , List * indexQuals )
add_predicate_to_index_ quals ( IndexOptInfo * index , List * indexQuals )
{
{
List * predExtraQuals = NIL ;
List * predExtraQuals = NIL ;
ListCell * lc ;
ListCell * lc ;
@ -5638,7 +5584,6 @@ btcostestimate(PlannerInfo *root, IndexPath *path, double loop_count,
double * indexPages )
double * indexPages )
{
{
IndexOptInfo * index = path - > indexinfo ;
IndexOptInfo * index = path - > indexinfo ;
List * qinfos ;
GenericCosts costs ;
GenericCosts costs ;
Oid relid ;
Oid relid ;
AttrNumber colnum ;
AttrNumber colnum ;
@ -5653,9 +5598,6 @@ btcostestimate(PlannerInfo *root, IndexPath *path, double loop_count,
double num_sa_scans ;
double num_sa_scans ;
ListCell * lc ;
ListCell * lc ;
/* Do preliminary analysis of indexquals */
qinfos = deconstruct_indexquals ( path ) ;
/*
/*
* For a btree scan , only leading ' = ' quals plus inequality quals for the
* For a btree scan , only leading ' = ' quals plus inequality quals for the
* immediately next attribute contribute to index selectivity ( these are
* immediately next attribute contribute to index selectivity ( these are
@ -5679,58 +5621,81 @@ btcostestimate(PlannerInfo *root, IndexPath *path, double loop_count,
found_saop = false ;
found_saop = false ;
found_is_null_op = false ;
found_is_null_op = false ;
num_sa_scans = 1 ;
num_sa_scans = 1 ;
foreach ( lc , qinfo s)
foreach ( lc , path - > indexclause s)
{
{
IndexQualInfo * qinfo = ( IndexQualInfo * ) lfirst ( lc ) ;
IndexClause * iclause = lfirst_node ( IndexClause , lc ) ;
RestrictInfo * rinfo = qinfo - > rinfo ;
ListCell * lc2 ;
Expr * clause = rinfo - > clause ;
Oid clause_op ;
int op_strategy ;
if ( indexcol ! = qinfo - > indexcol )
if ( indexcol ! = iclause - > indexcol )
{
{
/* Beginning of a new column's quals */
/* Beginning of a new column's quals */
if ( ! eqQualHere )
if ( ! eqQualHere )
break ; /* done if no '=' qual for indexcol */
break ; /* done if no '=' qual for indexcol */
eqQualHere = false ;
eqQualHere = false ;
indexcol + + ;
indexcol + + ;
if ( indexcol ! = qinfo - > indexcol )
if ( indexcol ! = iclause - > indexcol )
break ; /* no quals at all for indexcol */
break ; /* no quals at all for indexcol */
}
}
if ( IsA ( clause , ScalarArrayOpExpr ) )
/* Examine each indexqual associated with this index clause */
foreach ( lc2 , iclause - > indexquals )
{
{
int alength = estimate_array_length ( qinfo - > other_operand ) ;
RestrictInfo * rinfo = lfirst_node ( RestrictInfo , lc2 ) ;
Expr * clause = rinfo - > clause ;
Oid clause_op = InvalidOid ;
int op_strategy ;
found_saop = true ;
if ( IsA ( clause , OpExpr ) )
/* count up number of SA scans induced by indexBoundQuals only */
{
if ( alength > 1 )
OpExpr * op = ( OpExpr * ) clause ;
num_sa_scans * = alength ;
}
clause_op = op - > opno ;
else if ( IsA ( clause , NullTest ) )
}
{
else if ( IsA ( clause , RowCompareExpr ) )
NullTest * nt = ( NullTest * ) clause ;
{
RowCompareExpr * rc = ( RowCompareExpr * ) clause ;
if ( nt - > nulltesttype = = IS_NULL )
clause_op = linitial_oid ( rc - > opnos ) ;
}
else if ( IsA ( clause , ScalarArrayOpExpr ) )
{
{
found_is_null_op = true ;
ScalarArrayOpExpr * saop = ( ScalarArrayOpExpr * ) clause ;
/* IS NULL is like = for selectivity determination purposes */
Node * other_operand = ( Node * ) lsecond ( saop - > args ) ;
eqQualHere = true ;
int alength = estimate_array_length ( other_operand ) ;
clause_op = saop - > opno ;
found_saop = true ;
/* count number of SA scans induced by indexBoundQuals only */
if ( alength > 1 )
num_sa_scans * = alength ;
}
}
}
else if ( IsA ( clause , NullTest ) )
{
NullTest * nt = ( NullTest * ) clause ;
/* check for equality operator */
if ( nt - > nulltesttype = = IS_NULL )
clause_op = qinfo - > clause_op ;
{
if ( OidIsValid ( clause_op ) )
found_is_null_op = true ;
{
/* IS NULL is like = for selectivity purposes */
op_strategy = get_op_opfamily_strategy ( clause_op ,
eqQualHere = true ;
index - > opfamily [ indexcol ] ) ;
}
Assert ( op_strategy ! = 0 ) ; /* not a member of opfamily?? */
}
if ( op_strat egy = = BTEqualStrat egyNumber )
els e
eqQualHere = true ;
elog ( ERROR , " unsupported indexqual type: %d " ,
}
( int ) nodeTag ( clause ) ) ;
indexBoundQuals = lappend ( indexBoundQuals , rinfo ) ;
/* check for equality operator */
if ( OidIsValid ( clause_op ) )
{
op_strategy = get_op_opfamily_strategy ( clause_op ,
index - > opfamily [ indexcol ] ) ;
Assert ( op_strategy ! = 0 ) ; /* not a member of opfamily?? */
if ( op_strategy = = BTEqualStrategyNumber )
eqQualHere = true ;
}
indexBoundQuals = lappend ( indexBoundQuals , rinfo ) ;
}
}
}
/*
/*
@ -5755,7 +5720,7 @@ btcostestimate(PlannerInfo *root, IndexPath *path, double loop_count,
* index - bound quals to produce a more accurate idea of the number of
* index - bound quals to produce a more accurate idea of the number of
* rows covered by the bound conditions .
* rows covered by the bound conditions .
*/
*/
selectivityQuals = add_predicate_to_quals ( index , indexBoundQuals ) ;
selectivityQuals = add_predicate_to_index_ quals ( index , indexBoundQuals ) ;
btreeSelectivity = clauselist_selectivity ( root , selectivityQuals ,
btreeSelectivity = clauselist_selectivity ( root , selectivityQuals ,
index - > rel - > relid ,
index - > rel - > relid ,
@ -5777,7 +5742,7 @@ btcostestimate(PlannerInfo *root, IndexPath *path, double loop_count,
MemSet ( & costs , 0 , sizeof ( costs ) ) ;
MemSet ( & costs , 0 , sizeof ( costs ) ) ;
costs . numIndexTuples = numIndexTuples ;
costs . numIndexTuples = numIndexTuples ;
genericcostestimate ( root , path , loop_count , qinfos , & costs ) ;
genericcostestimate ( root , path , loop_count , & costs ) ;
/*
/*
* Add a CPU - cost component to represent the costs of initial btree
* Add a CPU - cost component to represent the costs of initial btree
@ -5924,15 +5889,11 @@ hashcostestimate(PlannerInfo *root, IndexPath *path, double loop_count,
Selectivity * indexSelectivity , double * indexCorrelation ,
Selectivity * indexSelectivity , double * indexCorrelation ,
double * indexPages )
double * indexPages )
{
{
List * qinfos ;
GenericCosts costs ;
GenericCosts costs ;
/* Do preliminary analysis of indexquals */
qinfos = deconstruct_indexquals ( path ) ;
MemSet ( & costs , 0 , sizeof ( costs ) ) ;
MemSet ( & costs , 0 , sizeof ( costs ) ) ;
genericcostestimate ( root , path , loop_count , qinfos , & costs ) ;
genericcostestimate ( root , path , loop_count , & costs ) ;
/*
/*
* A hash index has no descent costs as such , since the index AM can go
* A hash index has no descent costs as such , since the index AM can go
@ -5973,16 +5934,12 @@ gistcostestimate(PlannerInfo *root, IndexPath *path, double loop_count,
double * indexPages )
double * indexPages )
{
{
IndexOptInfo * index = path - > indexinfo ;
IndexOptInfo * index = path - > indexinfo ;
List * qinfos ;
GenericCosts costs ;
GenericCosts costs ;
Cost descentCost ;
Cost descentCost ;
/* Do preliminary analysis of indexquals */
qinfos = deconstruct_indexquals ( path ) ;
MemSet ( & costs , 0 , sizeof ( costs ) ) ;
MemSet ( & costs , 0 , sizeof ( costs ) ) ;
genericcostestimate ( root , path , loop_count , qinfos , & costs ) ;
genericcostestimate ( root , path , loop_count , & costs ) ;
/*
/*
* We model index descent costs similarly to those for btree , but to do
* We model index descent costs similarly to those for btree , but to do
@ -6034,16 +5991,12 @@ spgcostestimate(PlannerInfo *root, IndexPath *path, double loop_count,
double * indexPages )
double * indexPages )
{
{
IndexOptInfo * index = path - > indexinfo ;
IndexOptInfo * index = path - > indexinfo ;
List * qinfos ;
GenericCosts costs ;
GenericCosts costs ;
Cost descentCost ;
Cost descentCost ;
/* Do preliminary analysis of indexquals */
qinfos = deconstruct_indexquals ( path ) ;
MemSet ( & costs , 0 , sizeof ( costs ) ) ;
MemSet ( & costs , 0 , sizeof ( costs ) ) ;
genericcostestimate ( root , path , loop_count , qinfos , & costs ) ;
genericcostestimate ( root , path , loop_count , & costs ) ;
/*
/*
* We model index descent costs similarly to those for btree , but to do
* We model index descent costs similarly to those for btree , but to do
@ -6214,12 +6167,12 @@ gincost_pattern(IndexOptInfo *index, int indexcol,
static bool
static bool
gincost_opexpr ( PlannerInfo * root ,
gincost_opexpr ( PlannerInfo * root ,
IndexOptInfo * index ,
IndexOptInfo * index ,
IndexQualInfo * qinfo ,
int indexcol ,
OpExpr * clause ,
GinQualCounts * counts )
GinQualCounts * counts )
{
{
int indexcol = qinfo - > indexcol ;
Oid clause_op = clause - > opno ;
Oid clause_op = qinfo - > clause_op ;
Node * operand = ( Node * ) lsecond ( clause - > args ) ;
Node * operand = qinfo - > other_operand ;
/* aggressively reduce to a constant, and look through relabeling */
/* aggressively reduce to a constant, and look through relabeling */
operand = estimate_expression_value ( root , operand ) ;
operand = estimate_expression_value ( root , operand ) ;
@ -6264,13 +6217,13 @@ gincost_opexpr(PlannerInfo *root,
static bool
static bool
gincost_scalararrayopexpr ( PlannerInfo * root ,
gincost_scalararrayopexpr ( PlannerInfo * root ,
IndexOptInfo * index ,
IndexOptInfo * index ,
IndexQualInfo * qinfo ,
int indexcol ,
ScalarArrayOpExpr * clause ,
double numIndexEntries ,
double numIndexEntries ,
GinQualCounts * counts )
GinQualCounts * counts )
{
{
int indexcol = qinfo - > indexcol ;
Oid clause_op = clause - > opno ;
Oid clause_op = qinfo - > clause_op ;
Node * rightop = ( Node * ) lsecond ( clause - > args ) ;
Node * rightop = qinfo - > other_operand ;
ArrayType * arrayval ;
ArrayType * arrayval ;
int16 elmlen ;
int16 elmlen ;
bool elmbyval ;
bool elmbyval ;
@ -6282,7 +6235,7 @@ gincost_scalararrayopexpr(PlannerInfo *root,
int numPossible = 0 ;
int numPossible = 0 ;
int i ;
int i ;
Assert ( ( ( ScalarArrayOpExpr * ) qinfo - > rinfo - > clause ) - > useOr ) ;
Assert ( clause - > useOr ) ;
/* aggressively reduce to a constant, and look through relabeling */
/* aggressively reduce to a constant, and look through relabeling */
rightop = estimate_expression_value ( root , rightop ) ;
rightop = estimate_expression_value ( root , rightop ) ;
@ -6383,10 +6336,7 @@ gincostestimate(PlannerInfo *root, IndexPath *path, double loop_count,
double * indexPages )
double * indexPages )
{
{
IndexOptInfo * index = path - > indexinfo ;
IndexOptInfo * index = path - > indexinfo ;
List * indexQuals = get_index_quals ( path - > indexclauses ) ;
List * indexQuals = get_quals_from_indexclauses ( path - > indexclauses ) ;
List * indexOrderBys = path - > indexorderbys ;
List * qinfos ;
ListCell * l ;
List * selectivityQuals ;
List * selectivityQuals ;
double numPages = index - > pages ,
double numPages = index - > pages ,
numTuples = index - > tuples ;
numTuples = index - > tuples ;
@ -6406,9 +6356,7 @@ gincostestimate(PlannerInfo *root, IndexPath *path, double loop_count,
outer_scans ;
outer_scans ;
Relation indexRel ;
Relation indexRel ;
GinStatsData ginStats ;
GinStatsData ginStats ;
ListCell * lc ;
/* Do preliminary analysis of indexquals */
qinfos = deconstruct_indexquals ( path ) ;
/*
/*
* Obtain statistical information from the meta page , if possible . Else
* Obtain statistical information from the meta page , if possible . Else
@ -6490,7 +6438,7 @@ gincostestimate(PlannerInfo *root, IndexPath *path, double loop_count,
* quals to produce a more accurate idea of the number of rows covered by
* quals to produce a more accurate idea of the number of rows covered by
* the bound conditions .
* the bound conditions .
*/
*/
selectivityQuals = add_predicate_to_quals ( index , indexQuals ) ;
selectivityQuals = add_predicate_to_index_ quals ( index , indexQuals ) ;
/* Estimate the fraction of main-table tuples that will be visited */
/* Estimate the fraction of main-table tuples that will be visited */
* indexSelectivity = clauselist_selectivity ( root , selectivityQuals ,
* indexSelectivity = clauselist_selectivity ( root , selectivityQuals ,
@ -6515,35 +6463,43 @@ gincostestimate(PlannerInfo *root, IndexPath *path, double loop_count,
counts . arrayScans = 1 ;
counts . arrayScans = 1 ;
matchPossible = true ;
matchPossible = true ;
foreach ( l , qinfo s)
foreach ( lc , path - > indexclause s )
{
{
IndexQualInfo * qinfo = ( IndexQualInfo * ) lfirst ( l ) ;
IndexClause * iclause = lfirst_node ( IndexClause , lc ) ;
Expr * clause = qinfo - > rinfo - > clause ;
ListCell * lc2 ;
if ( IsA ( clause , OpExpr ) )
foreach ( lc2 , iclause - > indexquals )
{
matchPossible = gincost_opexpr ( root ,
index ,
qinfo ,
& counts ) ;
if ( ! matchPossible )
break ;
}
else if ( IsA ( clause , ScalarArrayOpExpr ) )
{
matchPossible = gincost_scalararrayopexpr ( root ,
index ,
qinfo ,
numEntries ,
& counts ) ;
if ( ! matchPossible )
break ;
}
else
{
{
/* shouldn't be anything else for a GIN index */
RestrictInfo * rinfo = lfirst_node ( RestrictInfo , lc2 ) ;
elog ( ERROR , " unsupported GIN indexqual type: %d " ,
Expr * clause = rinfo - > clause ;
( int ) nodeTag ( clause ) ) ;
if ( IsA ( clause , OpExpr ) )
{
matchPossible = gincost_opexpr ( root ,
index ,
iclause - > indexcol ,
( OpExpr * ) clause ,
& counts ) ;
if ( ! matchPossible )
break ;
}
else if ( IsA ( clause , ScalarArrayOpExpr ) )
{
matchPossible = gincost_scalararrayopexpr ( root ,
index ,
iclause - > indexcol ,
( ScalarArrayOpExpr * ) clause ,
numEntries ,
& counts ) ;
if ( ! matchPossible )
break ;
}
else
{
/* shouldn't be anything else for a GIN index */
elog ( ERROR , " unsupported GIN indexqual type: %d " ,
( int ) nodeTag ( clause ) ) ;
}
}
}
}
}
@ -6670,12 +6626,11 @@ gincostestimate(PlannerInfo *root, IndexPath *path, double loop_count,
dataPagesFetched * spc_random_page_cost ;
dataPagesFetched * spc_random_page_cost ;
/*
/*
* Add on index qual eval costs , much as in genericcostestimate
* Add on index qual eval costs , much as in genericcostestimate . But we
* can disregard indexorderbys , since GIN doesn ' t support those .
*/
*/
qual_arg_cost = other_operands_eval_cost ( root , qinfos ) +
qual_arg_cost = index_other_operands_eval_cost ( root , indexQuals ) ;
orderby_operands_eval_cost ( root , path ) ;
qual_op_cost = cpu_operator_cost * list_length ( indexQuals ) ;
qual_op_cost = cpu_operator_cost *
( list_length ( indexQuals ) + list_length ( indexOrderBys ) ) ;
* indexStartupCost + = qual_arg_cost ;
* indexStartupCost + = qual_arg_cost ;
* indexTotalCost + = qual_arg_cost ;
* indexTotalCost + = qual_arg_cost ;
@ -6693,11 +6648,10 @@ brincostestimate(PlannerInfo *root, IndexPath *path, double loop_count,
double * indexPages )
double * indexPages )
{
{
IndexOptInfo * index = path - > indexinfo ;
IndexOptInfo * index = path - > indexinfo ;
List * indexQuals = get_index_qual s ( path - > indexclauses ) ;
List * indexQuals = get_quals_from_indexclause s ( path - > indexclauses ) ;
double numPages = index - > pages ;
double numPages = index - > pages ;
RelOptInfo * baserel = index - > rel ;
RelOptInfo * baserel = index - > rel ;
RangeTblEntry * rte = planner_rt_fetch ( baserel - > relid , root ) ;
RangeTblEntry * rte = planner_rt_fetch ( baserel - > relid , root ) ;
List * qinfos ;
Cost spc_seq_page_cost ;
Cost spc_seq_page_cost ;
Cost spc_random_page_cost ;
Cost spc_random_page_cost ;
double qual_arg_cost ;
double qual_arg_cost ;
@ -6735,11 +6689,10 @@ brincostestimate(PlannerInfo *root, IndexPath *path, double loop_count,
*/
*/
* indexCorrelation = 0 ;
* indexCorrelation = 0 ;
qinfos = deconstruct_indexquals ( path ) ;
foreach ( l , path - > indexclauses )
foreach ( l , qinfos )
{
{
IndexQualInfo * qinfo = ( IndexQualInfo * ) lfirst ( l ) ;
IndexClause * iclause = lfirst_node ( IndexClause , l ) ;
AttrNumber attnum = index - > indexkeys [ qinfo - > indexcol ] ;
AttrNumber attnum = index - > indexkeys [ iclause - > indexcol ] ;
/* attempt to lookup stats in relation for this index column */
/* attempt to lookup stats in relation for this index column */
if ( attnum ! = 0 )
if ( attnum ! = 0 )
@ -6774,7 +6727,7 @@ brincostestimate(PlannerInfo *root, IndexPath *path, double loop_count,
*/
*/
/* get the attnum from the 0-based index. */
/* get the attnum from the 0-based index. */
attnum = qinfo - > indexcol + 1 ;
attnum = iclause - > indexcol + 1 ;
if ( get_index_stats_hook & &
if ( get_index_stats_hook & &
( * get_index_stats_hook ) ( root , index - > indexoid , attnum , & vardata ) )
( * get_index_stats_hook ) ( root , index - > indexoid , attnum , & vardata ) )
@ -6853,10 +6806,10 @@ brincostestimate(PlannerInfo *root, IndexPath *path, double loop_count,
/*
/*
* Compute the index qual costs , much as in genericcostestimate , to add to
* Compute the index qual costs , much as in genericcostestimate , to add to
* the index costs .
* the index costs . We can disregard indexorderbys , since BRIN doesn ' t
* support those .
*/
*/
qual_arg_cost = other_operands_eval_cost ( root , qinfos ) +
qual_arg_cost = index_other_operands_eval_cost ( root , indexQuals ) ;
orderby_operands_eval_cost ( root , path ) ;
/*
/*
* Compute the startup cost as the cost to read the whole revmap
* Compute the startup cost as the cost to read the whole revmap