mirror of
https://git.postgresql.org/git/postgresql.git
synced 2024-12-27 08:39:28 +08:00
Fix up gincostestimate for new extractQuery API.
The only reason this wasn't crashing while testing the core anyarray operators was that it was disabled for those cases because of passing the wrong type information to get_opfamily_proc :-(. So fix that too, and make it insist on finding the support proc --- in hindsight, silently doing nothing is not as sane a coping mechanism as all that.
This commit is contained in:
parent
833a2b57bc
commit
4d1b76e49e
@ -6281,7 +6281,6 @@ gincostestimate(PG_FUNCTION_ARGS)
|
|||||||
Selectivity *indexSelectivity = (Selectivity *) PG_GETARG_POINTER(7);
|
Selectivity *indexSelectivity = (Selectivity *) PG_GETARG_POINTER(7);
|
||||||
double *indexCorrelation = (double *) PG_GETARG_POINTER(8);
|
double *indexCorrelation = (double *) PG_GETARG_POINTER(8);
|
||||||
ListCell *l;
|
ListCell *l;
|
||||||
int32 nfullscan = 0;
|
|
||||||
List *selectivityQuals;
|
List *selectivityQuals;
|
||||||
double numPages = index->pages,
|
double numPages = index->pages,
|
||||||
numTuples = index->tuples;
|
numTuples = index->tuples;
|
||||||
@ -6289,6 +6288,7 @@ gincostestimate(PG_FUNCTION_ARGS)
|
|||||||
numDataPages,
|
numDataPages,
|
||||||
numPendingPages,
|
numPendingPages,
|
||||||
numEntries;
|
numEntries;
|
||||||
|
bool haveFullScan = false;
|
||||||
double partialEntriesInQuals = 0.0;
|
double partialEntriesInQuals = 0.0;
|
||||||
double searchEntriesInQuals = 0.0;
|
double searchEntriesInQuals = 0.0;
|
||||||
double exactEntriesInQuals = 0.0;
|
double exactEntriesInQuals = 0.0;
|
||||||
@ -6394,6 +6394,8 @@ gincostestimate(PG_FUNCTION_ARGS)
|
|||||||
int32 nentries = 0;
|
int32 nentries = 0;
|
||||||
bool *partial_matches = NULL;
|
bool *partial_matches = NULL;
|
||||||
Pointer *extra_data = NULL;
|
Pointer *extra_data = NULL;
|
||||||
|
bool *nullFlags = NULL;
|
||||||
|
int32 searchMode = GIN_SEARCH_MODE_DEFAULT;
|
||||||
int indexcol;
|
int indexcol;
|
||||||
|
|
||||||
Assert(IsA(rinfo, RestrictInfo));
|
Assert(IsA(rinfo, RestrictInfo));
|
||||||
@ -6414,7 +6416,7 @@ gincostestimate(PG_FUNCTION_ARGS)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
elog(ERROR, "Could not match index to operand");
|
elog(ERROR, "could not match index to operand");
|
||||||
operand = NULL; /* keep compiler quiet */
|
operand = NULL; /* keep compiler quiet */
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -6443,42 +6445,43 @@ gincostestimate(PG_FUNCTION_ARGS)
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
* Get the operator's strategy number and declared input data types
|
* Get the operator's strategy number and declared input data types
|
||||||
* within the index opfamily.
|
* within the index opfamily. (We don't need the latter, but we
|
||||||
|
* use get_op_opfamily_properties because it will throw error if
|
||||||
|
* it fails to find a matching pg_amop entry.)
|
||||||
*/
|
*/
|
||||||
get_op_opfamily_properties(clause_op, index->opfamily[indexcol], false,
|
get_op_opfamily_properties(clause_op, index->opfamily[indexcol], false,
|
||||||
&strategy_op, &lefttype, &righttype);
|
&strategy_op, &lefttype, &righttype);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* GIN (like GiST) always has lefttype == righttype in pg_amproc
|
* GIN always uses the "default" support functions, which are those
|
||||||
* and they are equal to type Oid on which index was created/designed
|
* with lefttype == righttype == the opclass' opcintype (see
|
||||||
|
* IndexSupportInitialize in relcache.c).
|
||||||
*/
|
*/
|
||||||
extractProcOid = get_opfamily_proc(index->opfamily[indexcol],
|
extractProcOid = get_opfamily_proc(index->opfamily[indexcol],
|
||||||
lefttype, lefttype,
|
index->opcintype[indexcol],
|
||||||
|
index->opcintype[indexcol],
|
||||||
GIN_EXTRACTQUERY_PROC);
|
GIN_EXTRACTQUERY_PROC);
|
||||||
|
|
||||||
if (!OidIsValid(extractProcOid))
|
if (!OidIsValid(extractProcOid))
|
||||||
{
|
{
|
||||||
/* probably shouldn't happen, but cope sanely if so */
|
/* should not happen; throw same error as index_getprocinfo */
|
||||||
searchEntriesInQuals++;
|
elog(ERROR, "missing support function %d for attribute %d of index \"%s\"",
|
||||||
continue;
|
GIN_EXTRACTQUERY_PROC, indexcol+1,
|
||||||
|
get_rel_name(index->indexoid));
|
||||||
}
|
}
|
||||||
|
|
||||||
OidFunctionCall5(extractProcOid,
|
OidFunctionCall7(extractProcOid,
|
||||||
((Const*)operand)->constvalue,
|
((Const*) operand)->constvalue,
|
||||||
PointerGetDatum(&nentries),
|
PointerGetDatum(&nentries),
|
||||||
UInt16GetDatum(strategy_op),
|
UInt16GetDatum(strategy_op),
|
||||||
PointerGetDatum(&partial_matches),
|
PointerGetDatum(&partial_matches),
|
||||||
PointerGetDatum(&extra_data));
|
PointerGetDatum(&extra_data),
|
||||||
|
PointerGetDatum(&nullFlags),
|
||||||
|
PointerGetDatum(&searchMode));
|
||||||
|
|
||||||
if (nentries == 0)
|
if (nentries <= 0 && searchMode == GIN_SEARCH_MODE_DEFAULT)
|
||||||
{
|
{
|
||||||
nfullscan++;
|
/* No match is possible */
|
||||||
}
|
|
||||||
else if (nentries < 0)
|
|
||||||
{
|
|
||||||
/*
|
|
||||||
* GIN_EXTRACTQUERY_PROC guarantees that nothing will be found
|
|
||||||
*/
|
|
||||||
*indexStartupCost = 0;
|
*indexStartupCost = 0;
|
||||||
*indexTotalCost = 0;
|
*indexTotalCost = 0;
|
||||||
*indexSelectivity = 0;
|
*indexSelectivity = 0;
|
||||||
@ -6486,7 +6489,7 @@ gincostestimate(PG_FUNCTION_ARGS)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
int i;
|
int32 i;
|
||||||
|
|
||||||
for (i=0; i<nentries; i++)
|
for (i=0; i<nentries; i++)
|
||||||
{
|
{
|
||||||
@ -6503,10 +6506,28 @@ gincostestimate(PG_FUNCTION_ARGS)
|
|||||||
searchEntriesInQuals++;
|
searchEntriesInQuals++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (searchMode == GIN_SEARCH_MODE_INCLUDE_EMPTY)
|
||||||
|
{
|
||||||
|
/* Treat "include empty" like an exact-match item */
|
||||||
|
exactEntriesInQuals++;
|
||||||
|
searchEntriesInQuals++;
|
||||||
|
}
|
||||||
|
else if (searchMode != GIN_SEARCH_MODE_DEFAULT)
|
||||||
|
{
|
||||||
|
/* It's GIN_SEARCH_MODE_ALL */
|
||||||
|
haveFullScan = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (nfullscan == list_length(indexQuals))
|
if (haveFullScan || indexQuals == NIL)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* Full index scan will be required. We treat this as if every key in
|
||||||
|
* the index had been listed in the query; is that reasonable?
|
||||||
|
*/
|
||||||
searchEntriesInQuals = numEntries;
|
searchEntriesInQuals = numEntries;
|
||||||
|
}
|
||||||
|
|
||||||
/* Will we have more than one iteration of a nestloop scan? */
|
/* Will we have more than one iteration of a nestloop scan? */
|
||||||
if (outer_rel != NULL && outer_rel->rows > 1)
|
if (outer_rel != NULL && outer_rel->rows > 1)
|
||||||
|
Loading…
Reference in New Issue
Block a user