summaryrefslogtreecommitdiff
path: root/src/backend/optimizer/util/plancat.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/optimizer/util/plancat.c')
-rw-r--r--src/backend/optimizer/util/plancat.c151
1 files changed, 103 insertions, 48 deletions
diff --git a/src/backend/optimizer/util/plancat.c b/src/backend/optimizer/util/plancat.c
index ee3523553e8..749390a4d2d 100644
--- a/src/backend/optimizer/util/plancat.c
+++ b/src/backend/optimizer/util/plancat.c
@@ -9,7 +9,7 @@
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/optimizer/util/plancat.c,v 1.65 2001/05/07 00:43:22 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/optimizer/util/plancat.c,v 1.66 2001/05/20 20:28:19 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -23,9 +23,12 @@
#include "catalog/pg_amop.h"
#include "catalog/pg_inherits.h"
#include "catalog/pg_index.h"
+#include "optimizer/clauses.h"
#include "optimizer/plancat.h"
+#include "parser/parsetree.h"
#include "utils/builtins.h"
#include "utils/fmgroids.h"
+#include "utils/lsyscache.h"
#include "utils/relcache.h"
#include "utils/syscache.h"
#include "catalog/catalog.h"
@@ -33,7 +36,7 @@
/*
- * relation_info -
+ * get_relation_info -
* Retrieves catalog information for a given relation.
* Given the Oid of the relation, return the following info:
* whether the relation has secondary indices
@@ -41,8 +44,8 @@
* number of tuples
*/
void
-relation_info(Oid relationObjectId,
- bool *hasindex, long *pages, double *tuples)
+get_relation_info(Oid relationObjectId,
+ bool *hasindex, long *pages, double *tuples)
{
HeapTuple relationTuple;
Form_pg_class relation;
@@ -51,16 +54,19 @@ relation_info(Oid relationObjectId,
ObjectIdGetDatum(relationObjectId),
0, 0, 0);
if (!HeapTupleIsValid(relationTuple))
- elog(ERROR, "relation_info: Relation %u not found",
+ elog(ERROR, "get_relation_info: Relation %u not found",
relationObjectId);
relation = (Form_pg_class) GETSTRUCT(relationTuple);
- if (IsIgnoringSystemIndexes() && IsSystemRelationName(NameStr(relation->relname)))
+ if (IsIgnoringSystemIndexes() &&
+ IsSystemRelationName(NameStr(relation->relname)))
*hasindex = false;
else
- *hasindex = (relation->relhasindex) ? true : false;
+ *hasindex = relation->relhasindex;
+
*pages = relation->relpages;
*tuples = relation->reltuples;
+
ReleaseSysCache(relationTuple);
}
@@ -110,8 +116,8 @@ find_secondary_indexes(Oid relationObjectId)
info = makeNode(IndexOptInfo);
/*
- * Need to make these arrays large enough to be sure there is a
- * terminating 0 at the end of each one.
+ * Need to make these arrays large enough to be sure there is
+ * room for a terminating 0 at the end of each one.
*/
info->classlist = (Oid *) palloc(sizeof(Oid) * (INDEX_MAX_KEYS + 1));
info->indexkeys = (int *) palloc(sizeof(int) * (INDEX_MAX_KEYS + 1));
@@ -131,14 +137,26 @@ find_secondary_indexes(Oid relationObjectId)
}
else
info->indpred = NIL;
+ info->unique = index->indisunique;
info->lossy = index->indislossy;
for (i = 0; i < INDEX_MAX_KEYS; i++)
- info->indexkeys[i] = index->indkey[i];
- info->indexkeys[INDEX_MAX_KEYS] = 0;
- for (i = 0; i < INDEX_MAX_KEYS; i++)
+ {
+ if (index->indclass[i] == (Oid) 0)
+ break;
info->classlist[i] = index->indclass[i];
- info->classlist[INDEX_MAX_KEYS] = (Oid) 0;
+ }
+ info->classlist[i] = (Oid) 0;
+ info->ncolumns = i;
+
+ for (i = 0; i < INDEX_MAX_KEYS; i++)
+ {
+ if (index->indkey[i] == 0)
+ break;
+ info->indexkeys[i] = index->indkey[i];
+ }
+ info->indexkeys[i] = 0;
+ info->nkeys = i;
/* Extract info from the relation descriptor for the index */
indexRelation = index_open(index->indexrelid);
@@ -156,7 +174,7 @@ find_secondary_indexes(Oid relationObjectId)
MemSet(info->ordering, 0, sizeof(Oid) * (INDEX_MAX_KEYS + 1));
if (amorderstrategy != 0)
{
- for (i = 0; i < INDEX_MAX_KEYS && index->indclass[i]; i++)
+ for (i = 0; i < info->ncolumns; i++)
{
HeapTuple amopTuple;
Form_pg_amop amop;
@@ -193,30 +211,34 @@ find_secondary_indexes(Oid relationObjectId)
/*
* restriction_selectivity
*
- * Returns the selectivity of a specified operator.
+ * Returns the selectivity of a specified restriction operator clause.
* This code executes registered procedures stored in the
* operator relation, by calling the function manager.
*
- * XXX The assumption in the selectivity procedures is that if the
- * relation OIDs or attribute numbers are 0, then the clause
- * isn't of the form (op var const).
+ * varRelid is either 0 or a rangetable index. See clause_selectivity()
+ * for details about its meaning.
*/
Selectivity
-restriction_selectivity(Oid functionObjectId,
- Oid operatorObjectId,
- Oid relationObjectId,
- AttrNumber attributeNumber,
- Datum constValue,
- int constFlag)
+restriction_selectivity(Query *root,
+ Oid operator,
+ List *args,
+ int varRelid)
{
+ RegProcedure oprrest = get_oprrest(operator);
float8 result;
- result = DatumGetFloat8(OidFunctionCall5(functionObjectId,
- ObjectIdGetDatum(operatorObjectId),
- ObjectIdGetDatum(relationObjectId),
- Int16GetDatum(attributeNumber),
- constValue,
- Int32GetDatum(constFlag)));
+ /*
+ * if the oprrest procedure is missing for whatever reason,
+ * use a selectivity of 0.5
+ */
+ if (!oprrest)
+ return (Selectivity) 0.5;
+
+ result = DatumGetFloat8(OidFunctionCall4(oprrest,
+ PointerGetDatum(root),
+ ObjectIdGetDatum(operator),
+ PointerGetDatum(args),
+ Int32GetDatum(varRelid)));
if (result < 0.0 || result > 1.0)
elog(ERROR, "restriction_selectivity: bad value %f", result);
@@ -227,29 +249,29 @@ restriction_selectivity(Oid functionObjectId,
/*
* join_selectivity
*
- * Returns the selectivity of an operator, given the join clause
- * information.
- *
- * XXX The assumption in the selectivity procedures is that if the
- * relation OIDs or attribute numbers are 0, then the clause
- * isn't of the form (op var var).
+ * Returns the selectivity of a specified join operator clause.
+ * This code executes registered procedures stored in the
+ * operator relation, by calling the function manager.
*/
Selectivity
-join_selectivity(Oid functionObjectId,
- Oid operatorObjectId,
- Oid relationObjectId1,
- AttrNumber attributeNumber1,
- Oid relationObjectId2,
- AttrNumber attributeNumber2)
+join_selectivity(Query *root,
+ Oid operator,
+ List *args)
{
+ RegProcedure oprjoin = get_oprjoin(operator);
float8 result;
- result = DatumGetFloat8(OidFunctionCall5(functionObjectId,
- ObjectIdGetDatum(operatorObjectId),
- ObjectIdGetDatum(relationObjectId1),
- Int16GetDatum(attributeNumber1),
- ObjectIdGetDatum(relationObjectId2),
- Int16GetDatum(attributeNumber2)));
+ /*
+ * if the oprjoin procedure is missing for whatever reason,
+ * use a selectivity of 0.5
+ */
+ if (!oprjoin)
+ return (Selectivity) 0.5;
+
+ result = DatumGetFloat8(OidFunctionCall3(oprjoin,
+ PointerGetDatum(root),
+ ObjectIdGetDatum(operator),
+ PointerGetDatum(args)));
if (result < 0.0 || result > 1.0)
elog(ERROR, "join_selectivity: bad value %f", result);
@@ -330,3 +352,36 @@ has_subclass(Oid relationId)
ReleaseSysCache(tuple);
return result;
}
+
+/*
+ * has_unique_index
+ *
+ * Detect whether there is a unique index on the specified attribute
+ * of the specified relation, thus allowing us to conclude that all
+ * the (non-null) values of the attribute are distinct.
+ */
+bool
+has_unique_index(RelOptInfo *rel, AttrNumber attno)
+{
+ List *ilist;
+
+ foreach(ilist, rel->indexlist)
+ {
+ IndexOptInfo *index = (IndexOptInfo *) lfirst(ilist);
+
+ /*
+ * Note: ignore functional, partial, or lossy indexes, since they
+ * don't allow us to conclude that all attr values are distinct.
+ * Also, a multicolumn unique index doesn't allow us to conclude
+ * that just the specified attr is unique.
+ */
+ if (index->unique &&
+ index->nkeys == 1 &&
+ index->indexkeys[0] == attno &&
+ index->indproc == InvalidOid &&
+ index->indpred == NIL &&
+ !index->lossy)
+ return true;
+ }
+ return false;
+}