1
0
mirror of https://github.com/postgres/postgres.git synced 2025-07-30 11:03:19 +03:00

Move ltree parentsel() selectivity function into /contrib/ltree.

This commit is contained in:
Bruce Momjian
2006-04-26 22:33:36 +00:00
parent cae5671945
commit 59d61409cd
8 changed files with 230 additions and 221 deletions

View File

@ -2,15 +2,15 @@
psql:ltree.sql:7: NOTICE: type "ltree" is not yet defined
DETAIL: Creating a shell type definition.
psql:ltree.sql:12: NOTICE: argument type ltree is only a shell
psql:ltree.sql:299: NOTICE: type "lquery" is not yet defined
psql:ltree.sql:304: NOTICE: type "lquery" is not yet defined
DETAIL: Creating a shell type definition.
psql:ltree.sql:304: NOTICE: argument type lquery is only a shell
psql:ltree.sql:410: NOTICE: type "ltxtquery" is not yet defined
psql:ltree.sql:309: NOTICE: argument type lquery is only a shell
psql:ltree.sql:415: NOTICE: type "ltxtquery" is not yet defined
DETAIL: Creating a shell type definition.
psql:ltree.sql:415: NOTICE: argument type ltxtquery is only a shell
psql:ltree.sql:477: NOTICE: type "ltree_gist" is not yet defined
psql:ltree.sql:420: NOTICE: argument type ltxtquery is only a shell
psql:ltree.sql:482: NOTICE: type "ltree_gist" is not yet defined
DETAIL: Creating a shell type definition.
psql:ltree.sql:482: NOTICE: argument type ltree_gist is only a shell
psql:ltree.sql:487: NOTICE: argument type ltree_gist is only a shell
SELECT ''::ltree;
ltree
-------

View File

@ -225,6 +225,11 @@ RETURNS ltree
AS 'MODULE_PATHNAME'
LANGUAGE C RETURNS NULL ON NULL INPUT IMMUTABLE;
CREATE FUNCTION ltreeparentsel(internal, oid, internal, integer)
RETURNS float8
AS 'MODULE_PATHNAME'
LANGUAGE C RETURNS NULL ON NULL INPUT IMMUTABLE;
CREATE OPERATOR @> (
LEFTARG = ltree,
RIGHTARG = ltree,

View File

@ -1,12 +1,19 @@
/*
* op function for ltree
* Teodor Sigaev <teodor@stack.net>
* $PostgreSQL: pgsql/contrib/ltree/ltree_op.c,v 1.9 2006/03/11 04:38:29 momjian Exp $
* $PostgreSQL: pgsql/contrib/ltree/ltree_op.c,v 1.10 2006/04/26 22:32:36 momjian Exp $
*/
#include "ltree.h"
#include <ctype.h>
#include "access/heapam.h"
#include "catalog/pg_statistic.h"
#include "nodes/relation.h"
#include "utils/lsyscache.h"
#include "utils/selfuncs.h"
#include "utils/syscache.h"
/* compare functions */
PG_FUNCTION_INFO_V1(ltree_cmp);
PG_FUNCTION_INFO_V1(ltree_lt);
@ -44,6 +51,7 @@ Datum ltree_textadd(PG_FUNCTION_ARGS);
Datum lca(PG_FUNCTION_ARGS);
Datum ltree2text(PG_FUNCTION_ARGS);
Datum text2ltree(PG_FUNCTION_ARGS);
Datum ltreeparentsel(PG_FUNCTION_ARGS);
int
ltree_compare(const ltree * a, const ltree * b)
@ -551,3 +559,181 @@ ltree2text(PG_FUNCTION_ARGS)
PG_RETURN_POINTER(out);
}
#define DEFAULT_PARENT_SEL 0.001
/*
* ltreeparentsel - Selectivity of parent relationship for ltree data types.
*/
Datum
ltreeparentsel(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);
}