mirror of
https://github.com/postgres/postgres.git
synced 2025-06-16 06:01:02 +03:00
Move ltree parentsel() selectivity function into /contrib/ltree.
This commit is contained in:
@ -15,7 +15,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $PostgreSQL: pgsql/src/backend/utils/adt/selfuncs.c,v 1.200 2006/04/26 18:28:29 momjian Exp $
|
||||
* $PostgreSQL: pgsql/src/backend/utils/adt/selfuncs.c,v 1.201 2006/04/26 22:32:56 momjian Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -111,26 +111,6 @@
|
||||
#include "utils/syscache.h"
|
||||
|
||||
|
||||
/* Return data from examine_variable and friends */
|
||||
typedef struct
|
||||
{
|
||||
Node *var; /* the Var or expression tree */
|
||||
RelOptInfo *rel; /* Relation, or NULL if not identifiable */
|
||||
HeapTuple statsTuple; /* pg_statistic tuple, or NULL if none */
|
||||
/* NB: if statsTuple!=NULL, it must be freed when caller is done */
|
||||
Oid vartype; /* exposed type of expression */
|
||||
Oid atttype; /* type to pass to get_attstatsslot */
|
||||
int32 atttypmod; /* typmod to pass to get_attstatsslot */
|
||||
bool isunique; /* true if matched to a unique index */
|
||||
} VariableStatData;
|
||||
|
||||
#define ReleaseVariableStats(vardata) \
|
||||
do { \
|
||||
if (HeapTupleIsValid((vardata).statsTuple)) \
|
||||
ReleaseSysCache((vardata).statsTuple); \
|
||||
} while(0)
|
||||
|
||||
|
||||
static double mcv_selectivity(VariableStatData *vardata, FmgrInfo *opproc,
|
||||
Datum constval, double *sumcommonp);
|
||||
static double ineq_histogram_selectivity(VariableStatData *vardata,
|
||||
@ -158,9 +138,6 @@ static double convert_one_bytea_to_scalar(unsigned char *value, int valuelen,
|
||||
int rangelo, int rangehi);
|
||||
static char *convert_string_datum(Datum value, Oid typid);
|
||||
static double convert_timevalue_to_scalar(Datum value, Oid typid);
|
||||
static bool get_restriction_variable(PlannerInfo *root, List *args, int varRelid,
|
||||
VariableStatData *vardata, Node **other,
|
||||
bool *varonleft);
|
||||
static void get_join_variables(PlannerInfo *root, List *args,
|
||||
VariableStatData *vardata1,
|
||||
VariableStatData *vardata2);
|
||||
@ -3172,7 +3149,7 @@ convert_timevalue_to_scalar(Datum value, Oid typid)
|
||||
* Note: if there are Vars on both sides of the clause, we must fail, because
|
||||
* callers are expecting that the other side will act like a pseudoconstant.
|
||||
*/
|
||||
static bool
|
||||
bool
|
||||
get_restriction_variable(PlannerInfo *root, List *args, int varRelid,
|
||||
VariableStatData *vardata, Node **other,
|
||||
bool *varonleft)
|
||||
@ -4852,182 +4829,3 @@ gistcostestimate(PG_FUNCTION_ARGS)
|
||||
|
||||
PG_RETURN_VOID();
|
||||
}
|
||||
|
||||
|
||||
#define DEFAULT_PARENT_SEL 0.001
|
||||
|
||||
/*
|
||||
* parentsel - Selectivity of parent relationship for ltree data types.
|
||||
*/
|
||||
Datum
|
||||
parentsel(PG_FUNCTION_ARGS)
|
||||
{
|
||||
PlannerInfo *root = (PlannerInfo *) PG_GETARG_POINTER(0);
|
||||
Oid operator = PG_GETARG_OID(1);
|
||||
List *args = (List *) PG_GETARG_POINTER(2);
|
||||
int varRelid = PG_GETARG_INT32(3);
|
||||
VariableStatData vardata;
|
||||
Node *other;
|
||||
bool varonleft;
|
||||
Datum *values;
|
||||
int nvalues;
|
||||
float4 *numbers;
|
||||
int nnumbers;
|
||||
double selec = 0.0;
|
||||
|
||||
/*
|
||||
* If expression is not variable <@ something or something <@ variable,
|
||||
* then punt and return a default estimate.
|
||||
*/
|
||||
if (!get_restriction_variable(root, args, varRelid,
|
||||
&vardata, &other, &varonleft))
|
||||
PG_RETURN_FLOAT8(DEFAULT_PARENT_SEL);
|
||||
|
||||
/*
|
||||
* If the something is a NULL constant, assume operator is strict and
|
||||
* return zero, ie, operator will never return TRUE.
|
||||
*/
|
||||
if (IsA(other, Const) &&
|
||||
((Const *) other)->constisnull)
|
||||
{
|
||||
ReleaseVariableStats(vardata);
|
||||
PG_RETURN_FLOAT8(0.0);
|
||||
}
|
||||
|
||||
if (HeapTupleIsValid(vardata.statsTuple))
|
||||
{
|
||||
Form_pg_statistic stats;
|
||||
double mcvsum = 0.0;
|
||||
double mcvsel = 0.0;
|
||||
double hissel = 0.0;
|
||||
|
||||
stats = (Form_pg_statistic) GETSTRUCT(vardata.statsTuple);
|
||||
|
||||
if (IsA(other, Const))
|
||||
{
|
||||
/* Variable is being compared to a known non-null constant */
|
||||
Datum constval = ((Const *) other)->constvalue;
|
||||
bool match = false;
|
||||
int i;
|
||||
|
||||
/*
|
||||
* Is the constant "<@" to any of the column's most common values?
|
||||
*/
|
||||
if (get_attstatsslot(vardata.statsTuple,
|
||||
vardata.atttype, vardata.atttypmod,
|
||||
STATISTIC_KIND_MCV, InvalidOid,
|
||||
&values, &nvalues,
|
||||
&numbers, &nnumbers))
|
||||
{
|
||||
FmgrInfo contproc;
|
||||
|
||||
fmgr_info(get_opcode(operator), &contproc);
|
||||
|
||||
for (i = 0; i < nvalues; i++)
|
||||
{
|
||||
/* be careful to apply operator right way 'round */
|
||||
if (varonleft)
|
||||
match = DatumGetBool(FunctionCall2(&contproc,
|
||||
values[i],
|
||||
constval));
|
||||
else
|
||||
match = DatumGetBool(FunctionCall2(&contproc,
|
||||
constval,
|
||||
values[i]));
|
||||
|
||||
/* calculate total selectivity of all most-common-values */
|
||||
mcvsum += numbers[i];
|
||||
|
||||
/* calculate selectivity of matching most-common-values */
|
||||
if (match)
|
||||
mcvsel += numbers[i];
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* no most-common-values info available */
|
||||
values = NULL;
|
||||
numbers = NULL;
|
||||
i = nvalues = nnumbers = 0;
|
||||
}
|
||||
|
||||
free_attstatsslot(vardata.atttype, values, nvalues, NULL, 0);
|
||||
|
||||
/*
|
||||
* Is the constant "<@" to any of the column's histogram values?
|
||||
*/
|
||||
if (get_attstatsslot(vardata.statsTuple,
|
||||
vardata.atttype, vardata.atttypmod,
|
||||
STATISTIC_KIND_HISTOGRAM, InvalidOid,
|
||||
&values, &nvalues,
|
||||
NULL, NULL))
|
||||
{
|
||||
FmgrInfo contproc;
|
||||
|
||||
fmgr_info(get_opcode(operator), &contproc);
|
||||
|
||||
for (i = 0; i < nvalues; i++)
|
||||
{
|
||||
/* be careful to apply operator right way 'round */
|
||||
if (varonleft)
|
||||
match = DatumGetBool(FunctionCall2(&contproc,
|
||||
values[i],
|
||||
constval));
|
||||
else
|
||||
match = DatumGetBool(FunctionCall2(&contproc,
|
||||
constval,
|
||||
values[i]));
|
||||
/* count matching histogram values */
|
||||
if (match)
|
||||
hissel++;
|
||||
}
|
||||
|
||||
if (hissel > 0.0)
|
||||
{
|
||||
/*
|
||||
* some matching values found inside histogram, divide
|
||||
* matching entries number by total histogram entries to
|
||||
* get the histogram related selectivity
|
||||
*/
|
||||
hissel /= nvalues;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* no histogram info available */
|
||||
values = NULL;
|
||||
i = nvalues = 0;
|
||||
}
|
||||
|
||||
free_attstatsslot(vardata.atttype, values, nvalues,
|
||||
NULL, 0);
|
||||
|
||||
|
||||
/*
|
||||
* calculate selectivity based on MCV and histogram result
|
||||
* histogram selectivity needs to be scaled down if there are any
|
||||
* most-common-values
|
||||
*/
|
||||
selec = mcvsel + hissel * (1.0 - mcvsum);
|
||||
|
||||
/*
|
||||
* don't return 0.0 selectivity unless all table values are inside
|
||||
* mcv
|
||||
*/
|
||||
if (selec == 0.0 && mcvsum != 1.0)
|
||||
selec = DEFAULT_PARENT_SEL;
|
||||
}
|
||||
else
|
||||
selec = DEFAULT_PARENT_SEL;
|
||||
}
|
||||
else
|
||||
selec = DEFAULT_PARENT_SEL;
|
||||
|
||||
ReleaseVariableStats(vardata);
|
||||
|
||||
/* result should be in range, but make sure... */
|
||||
CLAMP_PROBABILITY(selec);
|
||||
|
||||
PG_RETURN_FLOAT8((float8) selec);
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user