aboutsummaryrefslogtreecommitdiff
path: root/src/backend
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend')
-rw-r--r--src/backend/access/common/tupdesc.c3
-rw-r--r--src/backend/commands/comment.c8
-rw-r--r--src/backend/optimizer/path/clausesel.c17
-rw-r--r--src/backend/optimizer/path/indxpath.c3
-rw-r--r--src/backend/parser/analyze.c3
-rw-r--r--src/backend/utils/adt/formatting.c10
-rw-r--r--src/backend/utils/adt/selfuncs.c328
7 files changed, 359 insertions, 13 deletions
diff --git a/src/backend/access/common/tupdesc.c b/src/backend/access/common/tupdesc.c
index 86d704e8d08..37e895479e2 100644
--- a/src/backend/access/common/tupdesc.c
+++ b/src/backend/access/common/tupdesc.c
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/access/common/tupdesc.c,v 1.74 2001/05/07 00:43:15 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/access/common/tupdesc.c,v 1.75 2001/06/25 21:11:43 tgl Exp $
*
* NOTES
* some of the executor utility code such as "ExecTypeFromTL" should be
@@ -20,6 +20,7 @@
#include "postgres.h"
#include "catalog/pg_type.h"
+#include "nodes/parsenodes.h"
#include "parser/parse_type.h"
#include "utils/builtins.h"
#include "utils/syscache.h"
diff --git a/src/backend/commands/comment.c b/src/backend/commands/comment.c
index 39668f867e0..2f28130f8b9 100644
--- a/src/backend/commands/comment.c
+++ b/src/backend/commands/comment.c
@@ -7,14 +7,13 @@
* Copyright (c) 1999-2001, PostgreSQL Global Development Group
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/commands/comment.c,v 1.30 2001/06/13 21:44:40 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/commands/comment.c,v 1.31 2001/06/25 21:11:43 tgl Exp $
*
*-------------------------------------------------------------------------
*/
#include "postgres.h"
-#include "utils/builtins.h"
#include "access/heapam.h"
#include "catalog/catname.h"
#include "catalog/indexing.h"
@@ -26,11 +25,12 @@
#include "catalog/pg_class.h"
#include "commands/comment.h"
#include "miscadmin.h"
-#include "parser/parse.h"
#include "parser/parse_expr.h"
#include "parser/parse_func.h"
+#include "parser/parse.h"
#include "rewrite/rewriteRemove.h"
#include "utils/acl.h"
+#include "utils/builtins.h"
#include "utils/fmgroids.h"
#include "utils/syscache.h"
@@ -717,7 +717,7 @@ CommentOperator(char *opername, List *arguments, char *comment)
/*** Get the procedure associated with the operator ***/
data = (Form_pg_operator) GETSTRUCT(optuple);
- oid = RegprocToOid(data->oprcode);
+ oid = data->oprcode;
if (oid == InvalidOid)
elog(ERROR, "operator '%s' does not have an underlying function", opername);
diff --git a/src/backend/optimizer/path/clausesel.c b/src/backend/optimizer/path/clausesel.c
index cafc01fc33f..36d8f229f1b 100644
--- a/src/backend/optimizer/path/clausesel.c
+++ b/src/backend/optimizer/path/clausesel.c
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/optimizer/path/clausesel.c,v 1.45 2001/06/05 05:26:04 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/optimizer/path/clausesel.c,v 1.46 2001/06/25 21:11:43 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -24,6 +24,7 @@
#include "parser/parsetree.h"
#include "utils/fmgroids.h"
#include "utils/lsyscache.h"
+#include "utils/selfuncs.h"
/* note that pg_type.h hardwires size of bool as 1 ... duplicate it */
@@ -509,6 +510,16 @@ clause_selectivity(Query *root,
*/
s1 = (Selectivity) 0.5;
}
+ else if (IsA(clause, NullTest))
+ {
+ /* Use node specific selectivity calculation function */
+ s1 = nulltestsel(root, (NullTest *) clause, varRelid);
+ }
+ else if (IsA(clause, BooleanTest))
+ {
+ /* Use node specific selectivity calculation function */
+ s1 = booltestsel(root, (BooleanTest *) clause, varRelid);
+ }
else if (IsA(clause, RelabelType))
{
/* Not sure this case is needed, but it can't hurt */
@@ -517,5 +528,9 @@ clause_selectivity(Query *root,
varRelid);
}
+#ifdef SELECTIVITY_DEBUG
+ elog(NOTICE, "clause_selectivity: s1 %f", s1);
+#endif /* SELECTIVITY_DEBUG */
+
return s1;
}
diff --git a/src/backend/optimizer/path/indxpath.c b/src/backend/optimizer/path/indxpath.c
index fc25058ab65..477fa6ed5ca 100644
--- a/src/backend/optimizer/path/indxpath.c
+++ b/src/backend/optimizer/path/indxpath.c
@@ -9,7 +9,7 @@
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/optimizer/path/indxpath.c,v 1.107 2001/06/17 02:05:19 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/optimizer/path/indxpath.c,v 1.108 2001/06/25 21:11:43 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -37,6 +37,7 @@
#include "utils/builtins.h"
#include "utils/fmgroids.h"
#include "utils/lsyscache.h"
+#include "utils/selfuncs.h"
#include "utils/syscache.h"
diff --git a/src/backend/parser/analyze.c b/src/backend/parser/analyze.c
index c0280c7b881..fc03173ce3d 100644
--- a/src/backend/parser/analyze.c
+++ b/src/backend/parser/analyze.c
@@ -6,7 +6,7 @@
* Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $Header: /cvsroot/pgsql/src/backend/parser/analyze.c,v 1.190 2001/06/23 00:07:34 momjian Exp $
+ * $Header: /cvsroot/pgsql/src/backend/parser/analyze.c,v 1.191 2001/06/25 21:11:44 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -33,6 +33,7 @@
#include "rewrite/rewriteManip.h"
#include "utils/builtins.h"
#include "utils/fmgroids.h"
+#include "utils/numeric.h"
#include "utils/relcache.h"
#include "utils/syscache.h"
diff --git a/src/backend/utils/adt/formatting.c b/src/backend/utils/adt/formatting.c
index 1ad99d330e5..ee92651f574 100644
--- a/src/backend/utils/adt/formatting.c
+++ b/src/backend/utils/adt/formatting.c
@@ -1,7 +1,7 @@
/* -----------------------------------------------------------------------
* formatting.c
*
- * $Header: /cvsroot/pgsql/src/backend/utils/adt/formatting.c,v 1.37 2001/05/03 22:53:07 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/utils/adt/formatting.c,v 1.38 2001/06/25 21:11:44 tgl Exp $
*
*
* Portions Copyright (c) 1999-2000, PostgreSQL Global Development Group
@@ -67,21 +67,23 @@
#define DEBUG_elog_output NOTICE
***/
-#include <stdio.h>
-#include <string.h>
+#include "postgres.h"
+
#include <ctype.h>
#include <sys/time.h>
#include <unistd.h>
+#ifdef USE_LOCALE
#include <locale.h>
+#endif
#include <math.h>
#include <float.h>
-#include "postgres.h"
#include "utils/builtins.h"
#include "utils/date.h"
#include "utils/datetime.h"
#include "utils/formatting.h"
#include "utils/int8.h"
+#include "utils/numeric.h"
#include "utils/pg_locale.h"
/* ----------
diff --git a/src/backend/utils/adt/selfuncs.c b/src/backend/utils/adt/selfuncs.c
index 099cc37e9dd..3ab3881c257 100644
--- a/src/backend/utils/adt/selfuncs.c
+++ b/src/backend/utils/adt/selfuncs.c
@@ -15,7 +15,7 @@
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/utils/adt/selfuncs.c,v 1.93 2001/06/09 22:16:18 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/utils/adt/selfuncs.c,v 1.94 2001/06/25 21:11:44 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -93,6 +93,7 @@
#include "utils/date.h"
#include "utils/int8.h"
#include "utils/lsyscache.h"
+#include "utils/selfuncs.h"
#include "utils/syscache.h"
/*
@@ -117,6 +118,10 @@
/* default number of distinct values in a table */
#define DEFAULT_NUM_DISTINCT 200
+/* default selectivity estimate for boolean and null test nodes */
+#define DEFAULT_UNK_SEL 0.005
+#define DEFAULT_NOT_UNK_SEL (1.0 - DEFAULT_UNK_SEL)
+#define DEFAULT_BOOL_SEL 0.5
static bool convert_to_scalar(Datum value, Oid valuetypid, double *scaledvalue,
Datum lobound, Datum hibound, Oid boundstypid,
@@ -934,6 +939,327 @@ icnlikesel(PG_FUNCTION_ARGS)
}
/*
+ * booltestsel - Selectivity of BooleanTest Node.
+ */
+Selectivity
+booltestsel(Query *root, BooleanTest *clause, int varRelid)
+{
+ Var *var;
+ Node *arg;
+ Oid relid;
+ HeapTuple statsTuple;
+ Datum *values;
+ int nvalues;
+ float4 *numbers;
+ int nnumbers;
+ double selec;
+
+ Assert(clause && IsA(clause, BooleanTest));
+
+ arg = (Node *) clause->arg;
+
+ /*
+ * Ignore any binary-compatible relabeling (probably unnecessary,
+ * but can't hurt)
+ */
+ if (IsA(arg, RelabelType))
+ arg = ((RelabelType *) arg)->arg;
+
+ if (IsA(arg, Var) && (varRelid == 0 || varRelid == ((Var *) arg)->varno))
+ var = (Var *) arg;
+ else
+ {
+ /*
+ * If argument is not a Var, we can't get statistics for it, but
+ * perhaps clause_selectivity can do something with it. We ignore
+ * the possibility of a NULL value when using clause_selectivity,
+ * and just assume the value is either TRUE or FALSE.
+ */
+ switch (clause->booltesttype)
+ {
+ case IS_UNKNOWN:
+ selec = DEFAULT_UNK_SEL;
+ break;
+ case IS_NOT_UNKNOWN:
+ selec = DEFAULT_NOT_UNK_SEL;
+ break;
+ case IS_TRUE:
+ case IS_NOT_FALSE:
+ selec = (double) clause_selectivity(root, arg, varRelid);
+ break;
+ case IS_FALSE:
+ case IS_NOT_TRUE:
+ selec = 1.0 - (double) clause_selectivity(root, arg, varRelid);
+ break;
+ default:
+ elog(ERROR, "booltestsel: unexpected booltesttype %d",
+ (int) clause->booltesttype);
+ selec = 0.0; /* Keep compiler quiet */
+ break;
+ }
+ return (Selectivity) selec;
+ }
+
+ /* get stats for the attribute, if available */
+ relid = getrelid(var->varno, root->rtable);
+ if (relid == InvalidOid)
+ statsTuple = NULL;
+ else
+ statsTuple = SearchSysCache(STATRELATT,
+ ObjectIdGetDatum(relid),
+ Int16GetDatum(var->varattno),
+ 0, 0);
+
+ if (HeapTupleIsValid(statsTuple))
+ {
+ Form_pg_statistic stats;
+ double freq_null;
+
+ stats = (Form_pg_statistic) GETSTRUCT(statsTuple);
+
+ freq_null = stats->stanullfrac;
+
+ if (get_attstatsslot(statsTuple, var->vartype, var->vartypmod,
+ STATISTIC_KIND_MCV, InvalidOid,
+ &values, &nvalues,
+ &numbers, &nnumbers)
+ && nnumbers > 0)
+ {
+ double freq_true;
+ double freq_false;
+
+ /*
+ * Get first MCV frequency and derive frequency for true.
+ */
+ if (DatumGetBool(values[0]))
+ freq_true = numbers[0];
+ else
+ freq_true = 1.0 - numbers[0] - freq_null;
+
+ /*
+ * Next derive freqency for false.
+ * Then use these as appropriate to derive frequency for each case.
+ */
+ freq_false = 1.0 - freq_true - freq_null;
+
+ switch (clause->booltesttype)
+ {
+ case IS_UNKNOWN:
+ /* select only NULL values */
+ selec = freq_null;
+ break;
+ case IS_NOT_UNKNOWN:
+ /* select non-NULL values */
+ selec = 1.0 - freq_null;
+ break;
+ case IS_TRUE:
+ /* select only TRUE values */
+ selec = freq_true;
+ break;
+ case IS_NOT_TRUE:
+ /* select non-TRUE values */
+ selec = 1.0 - freq_true;
+ break;
+ case IS_FALSE:
+ /* select only FALSE values */
+ selec = freq_false;
+ break;
+ case IS_NOT_FALSE:
+ /* select non-FALSE values */
+ selec = 1.0 - freq_false;
+ break;
+ default:
+ elog(ERROR, "booltestsel: unexpected booltesttype %d",
+ (int) clause->booltesttype);
+ selec = 0.0; /* Keep compiler quiet */
+ break;
+ }
+
+ free_attstatsslot(var->vartype, values, nvalues,
+ numbers, nnumbers);
+ }
+ else
+ {
+ /*
+ * No most-common-value info available.
+ * Still have null fraction information,
+ * so use it for IS [NOT] UNKNOWN.
+ * Otherwise adjust for null fraction and
+ * assume an even split for boolean tests.
+ */
+ switch (clause->booltesttype)
+ {
+ case IS_UNKNOWN:
+ /*
+ * Use freq_null directly.
+ */
+ selec = freq_null;
+ break;
+ case IS_NOT_UNKNOWN:
+ /*
+ * Select not unknown (not null) values.
+ * Calculate from freq_null.
+ */
+ selec = 1.0 - freq_null;
+ break;
+ case IS_TRUE:
+ case IS_NOT_TRUE:
+ case IS_FALSE:
+ case IS_NOT_FALSE:
+ selec = (1.0 - freq_null) / 2.0;
+ break;
+ default:
+ elog(ERROR, "booltestsel: unexpected booltesttype %d",
+ (int) clause->booltesttype);
+ selec = 0.0; /* Keep compiler quiet */
+ break;
+ }
+ }
+
+ ReleaseSysCache(statsTuple);
+ }
+ else
+ {
+ /*
+ * No VACUUM ANALYZE stats available, so use a default value.
+ * (Note: not much point in recursing to clause_selectivity here.)
+ */
+ switch (clause->booltesttype)
+ {
+ case IS_UNKNOWN:
+ selec = DEFAULT_UNK_SEL;
+ break;
+ case IS_NOT_UNKNOWN:
+ selec = DEFAULT_NOT_UNK_SEL;
+ break;
+ case IS_TRUE:
+ case IS_NOT_TRUE:
+ case IS_FALSE:
+ case IS_NOT_FALSE:
+ selec = DEFAULT_BOOL_SEL;
+ break;
+ default:
+ elog(ERROR, "booltestsel: unexpected booltesttype %d",
+ (int) clause->booltesttype);
+ selec = 0.0; /* Keep compiler quiet */
+ break;
+ }
+ }
+
+ /* result should be in range, but make sure... */
+ if (selec < 0.0)
+ selec = 0.0;
+ else if (selec > 1.0)
+ selec = 1.0;
+
+ return (Selectivity) selec;
+}
+
+/*
+ * nulltestsel - Selectivity of NullTest Node.
+ */
+Selectivity
+nulltestsel(Query *root, NullTest *clause, int varRelid)
+{
+ Var *var;
+ Node *arg;
+ Oid relid;
+ HeapTuple statsTuple;
+ double selec;
+ double defselec;
+ double freq_null;
+
+ Assert(clause && IsA(clause, NullTest));
+
+ switch (clause->nulltesttype)
+ {
+ case IS_NULL:
+ defselec = DEFAULT_UNK_SEL;
+ break;
+ case IS_NOT_NULL:
+ defselec = DEFAULT_NOT_UNK_SEL;
+ break;
+ default:
+ elog(ERROR, "nulltestsel: unexpected nulltesttype %d",
+ (int) clause->nulltesttype);
+ return (Selectivity) 0; /* keep compiler quiet */
+ }
+
+ arg = (Node *) clause->arg;
+
+ /*
+ * Ignore any binary-compatible relabeling
+ */
+ if (IsA(arg, RelabelType))
+ arg = ((RelabelType *) arg)->arg;
+
+ if (IsA(arg, Var) && (varRelid == 0 || varRelid == ((Var *) arg)->varno))
+ var = (Var *) arg;
+ else
+ {
+ /*
+ * punt if non-Var argument
+ */
+ return (Selectivity) defselec;
+ }
+
+ relid = getrelid(var->varno, root->rtable);
+ if (relid == InvalidOid)
+ return (Selectivity) defselec;
+
+ /* get stats for the attribute, if available */
+ statsTuple = SearchSysCache(STATRELATT,
+ ObjectIdGetDatum(relid),
+ Int16GetDatum(var->varattno),
+ 0, 0);
+ if (HeapTupleIsValid(statsTuple))
+ {
+ Form_pg_statistic stats;
+
+ stats = (Form_pg_statistic) GETSTRUCT(statsTuple);
+ freq_null = stats->stanullfrac;
+
+ switch (clause->nulltesttype)
+ {
+ case IS_NULL:
+ /*
+ * Use freq_null directly.
+ */
+ selec = freq_null;
+ break;
+ case IS_NOT_NULL:
+ /*
+ * Select not unknown (not null) values.
+ * Calculate from freq_null.
+ */
+ selec = 1.0 - freq_null;
+ break;
+ default:
+ elog(ERROR, "nulltestsel: unexpected nulltesttype %d",
+ (int) clause->nulltesttype);
+ return (Selectivity) 0; /* keep compiler quiet */
+ }
+
+ ReleaseSysCache(statsTuple);
+ }
+ else
+ {
+ /*
+ * No VACUUM ANALYZE stats available, so make a guess
+ */
+ selec = defselec;
+ }
+
+ /* result should be in range, but make sure... */
+ if (selec < 0.0)
+ selec = 0.0;
+ else if (selec > 1.0)
+ selec = 1.0;
+
+ return (Selectivity) selec;
+}
+
+/*
* eqjoinsel - Join selectivity of "="
*/
Datum