aboutsummaryrefslogtreecommitdiff
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.c969
1 files changed, 500 insertions, 469 deletions
diff --git a/src/backend/optimizer/util/plancat.c b/src/backend/optimizer/util/plancat.c
index abe764aa4e0..0e88a72c4eb 100644
--- a/src/backend/optimizer/util/plancat.c
+++ b/src/backend/optimizer/util/plancat.c
@@ -1,14 +1,14 @@
/*-------------------------------------------------------------------------
*
* plancat.c--
- * routines for accessing the system catalogs
+ * routines for accessing the system catalogs
*
*
* Copyright (c) 1994, Regents of the University of California
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/optimizer/util/plancat.c,v 1.6 1997/04/24 16:07:14 vadim Exp $
+ * $Header: /cvsroot/pgsql/src/backend/optimizer/util/plancat.c,v 1.7 1997/09/07 04:44:31 momjian Exp $
*
*-------------------------------------------------------------------------
*/
@@ -26,7 +26,7 @@
#include "catalog/pg_inherits.h"
#include "catalog/pg_version.h"
-#include "parser/parsetree.h" /* for getrelid() */
+#include "parser/parsetree.h" /* for getrelid() */
#include "fmgr.h"
#include "optimizer/internal.h"
@@ -34,193 +34,203 @@
#include "utils/syscache.h"
#ifndef HAVE_MEMMOVE
-# include <regex/utils.h>
+#include <regex/utils.h>
#else
-# include <string.h>
+#include <string.h>
#endif
-static void IndexSelectivity(Oid indexrelid, Oid indrelid, int32 nIndexKeys,
- Oid AccessMethodOperatorClasses[], Oid operatorObjectIds[],
+static void
+IndexSelectivity(Oid indexrelid, Oid indrelid, int32 nIndexKeys,
+ Oid AccessMethodOperatorClasses[], Oid operatorObjectIds[],
int32 varAttributeNumbers[], char *constValues[], int32 constFlags[],
- float *idxPages, float *idxSelec);
+ float *idxPages, float *idxSelec);
/*
* relation-info -
- * Retrieves catalog information for a given relation. Given the oid of
- * the relation, return the following information:
- * whether the relation has secondary indices
- * number of pages
- * number of tuples
+ * Retrieves catalog information for a given relation. Given the oid of
+ * the relation, return the following information:
+ * whether the relation has secondary indices
+ * number of pages
+ * number of tuples
*/
void
-relation_info(Query *root, Index relid,
- bool *hasindex, int *pages, int *tuples)
+relation_info(Query * root, Index relid,
+ bool * hasindex, int *pages, int *tuples)
{
- HeapTuple relationTuple;
- Form_pg_class relation;
- Oid relationObjectId;
-
- relationObjectId = getrelid(relid, root->rtable);
- relationTuple = SearchSysCacheTuple(RELOID,
- ObjectIdGetDatum(relationObjectId),
- 0,0,0);
- if (HeapTupleIsValid(relationTuple)) {
- relation = (Form_pg_class)GETSTRUCT(relationTuple);
-
- *hasindex = (relation->relhasindex) ? TRUE : FALSE;
- *pages = relation->relpages;
- *tuples = relation->reltuples;
- } else {
- elog(WARN, "RelationCatalogInformation: Relation %d not found",
- relationObjectId);
- }
-
- return;
+ HeapTuple relationTuple;
+ Form_pg_class relation;
+ Oid relationObjectId;
+
+ relationObjectId = getrelid(relid, root->rtable);
+ relationTuple = SearchSysCacheTuple(RELOID,
+ ObjectIdGetDatum(relationObjectId),
+ 0, 0, 0);
+ if (HeapTupleIsValid(relationTuple))
+ {
+ relation = (Form_pg_class) GETSTRUCT(relationTuple);
+
+ *hasindex = (relation->relhasindex) ? TRUE : FALSE;
+ *pages = relation->relpages;
+ *tuples = relation->reltuples;
+ }
+ else
+ {
+ elog(WARN, "RelationCatalogInformation: Relation %d not found",
+ relationObjectId);
+ }
+
+ return;
}
-/*
+/*
* index-info--
- * Retrieves catalog information on an index on a given relation.
- *
- * The index relation is opened on the first invocation. The current
- * retrieves the next index relation within the catalog that has not
- * already been retrieved by a previous call. The index catalog
- * is closed when no more indices for 'relid' can be found.
- *
- * 'first' is 1 if this is the first call
- *
+ * Retrieves catalog information on an index on a given relation.
+ *
+ * The index relation is opened on the first invocation. The current
+ * retrieves the next index relation within the catalog that has not
+ * already been retrieved by a previous call. The index catalog
+ * is closed when no more indices for 'relid' can be found.
+ *
+ * 'first' is 1 if this is the first call
+ *
* Returns true if successful and false otherwise. Index info is returned
* via the transient data structure 'info'.
- *
+ *
*/
bool
-index_info(Query *root, bool first, int relid, IdxInfoRetval *info)
+index_info(Query * root, bool first, int relid, IdxInfoRetval * info)
{
- register i;
- HeapTuple indexTuple, amopTuple;
- IndexTupleForm index;
- Relation indexRelation;
- uint16 amstrategy;
- Oid relam;
- Oid indrelid;
-
- static Relation relation = (Relation) NULL;
- static HeapScanDesc scan = (HeapScanDesc) NULL;
- static ScanKeyData indexKey;
-
-
- /* find the oid of the indexed relation */
- indrelid = getrelid(relid, root->rtable);
-
- memset(info, 0, sizeof(IdxInfoRetval));
-
- /*
- * the maximum number of elements in each of the following arrays is
- * 8. We allocate one more for a terminating 0 to indicate the end
- * of the array.
- */
- info->indexkeys = (int *)palloc(sizeof(int)*9);
- memset(info->indexkeys, 0, sizeof(int)*9);
- info->orderOprs = (Oid *)palloc(sizeof(Oid)*9);
- memset(info->orderOprs, 0, sizeof(Oid)*9);
- info->classlist = (Oid *)palloc(sizeof(Oid)*9);
- memset(info->classlist, 0, sizeof(Oid)*9);
-
- /* Find an index on the given relation */
- if (first) {
- if (RelationIsValid(relation))
- heap_close(relation);
- if (HeapScanIsValid(scan))
- heap_endscan(scan);
-
- ScanKeyEntryInitialize(&indexKey, 0,
- Anum_pg_index_indrelid,
- F_OIDEQ,
- ObjectIdGetDatum(indrelid));
-
- relation = heap_openr(IndexRelationName);
- scan = heap_beginscan(relation, 0, NowTimeQual,
- 1, &indexKey);
- }
- if (!HeapScanIsValid(scan))
- elog(WARN, "index_info: scan not started");
- indexTuple = heap_getnext(scan, 0, (Buffer *) NULL);
- if (!HeapTupleIsValid(indexTuple)) {
- heap_endscan(scan);
- heap_close(relation);
- scan = (HeapScanDesc) NULL;
- relation = (Relation) NULL;
- return(0);
- }
-
- /* Extract info from the index tuple */
- index = (IndexTupleForm)GETSTRUCT(indexTuple);
- info->relid = index->indexrelid; /* index relation */
- for (i = 0; i < 8; i++)
- info->indexkeys[i] = index->indkey[i];
- for (i = 0; i < 8; i++)
- info->classlist[i] = index->indclass[i];
-
- info->indproc = index->indproc; /* functional index ?? */
-
- /* partial index ?? */
- if (VARSIZE(&index->indpred) != 0) {
+ register i;
+ HeapTuple indexTuple,
+ amopTuple;
+ IndexTupleForm index;
+ Relation indexRelation;
+ uint16 amstrategy;
+ Oid relam;
+ Oid indrelid;
+
+ static Relation relation = (Relation) NULL;
+ static HeapScanDesc scan = (HeapScanDesc) NULL;
+ static ScanKeyData indexKey;
+
+
+ /* find the oid of the indexed relation */
+ indrelid = getrelid(relid, root->rtable);
+
+ memset(info, 0, sizeof(IdxInfoRetval));
+
/*
- * The memory allocated here for the predicate (in lispReadString)
- * only needs to stay around until it's used in find_index_paths,
- * which is all within a command, so the automatic pfree at end
- * of transaction should be ok.
+ * the maximum number of elements in each of the following arrays is
+ * 8. We allocate one more for a terminating 0 to indicate the end of
+ * the array.
*/
- char *predString;
+ info->indexkeys = (int *) palloc(sizeof(int) * 9);
+ memset(info->indexkeys, 0, sizeof(int) * 9);
+ info->orderOprs = (Oid *) palloc(sizeof(Oid) * 9);
+ memset(info->orderOprs, 0, sizeof(Oid) * 9);
+ info->classlist = (Oid *) palloc(sizeof(Oid) * 9);
+ memset(info->classlist, 0, sizeof(Oid) * 9);
+
+ /* Find an index on the given relation */
+ if (first)
+ {
+ if (RelationIsValid(relation))
+ heap_close(relation);
+ if (HeapScanIsValid(scan))
+ heap_endscan(scan);
+
+ ScanKeyEntryInitialize(&indexKey, 0,
+ Anum_pg_index_indrelid,
+ F_OIDEQ,
+ ObjectIdGetDatum(indrelid));
+
+ relation = heap_openr(IndexRelationName);
+ scan = heap_beginscan(relation, 0, NowTimeQual,
+ 1, &indexKey);
+ }
+ if (!HeapScanIsValid(scan))
+ elog(WARN, "index_info: scan not started");
+ indexTuple = heap_getnext(scan, 0, (Buffer *) NULL);
+ if (!HeapTupleIsValid(indexTuple))
+ {
+ heap_endscan(scan);
+ heap_close(relation);
+ scan = (HeapScanDesc) NULL;
+ relation = (Relation) NULL;
+ return (0);
+ }
+
+ /* Extract info from the index tuple */
+ index = (IndexTupleForm) GETSTRUCT(indexTuple);
+ info->relid = index->indexrelid; /* index relation */
+ for (i = 0; i < 8; i++)
+ info->indexkeys[i] = index->indkey[i];
+ for (i = 0; i < 8; i++)
+ info->classlist[i] = index->indclass[i];
- predString = fmgr(F_TEXTOUT, &index->indpred);
- info->indpred = (Node*)stringToNode(predString);
- pfree(predString);
- }
+ info->indproc = index->indproc; /* functional index ?? */
- /* Extract info from the relation descriptor for the index */
- indexRelation = index_open(index->indexrelid);
+ /* partial index ?? */
+ if (VARSIZE(&index->indpred) != 0)
+ {
+
+ /*
+ * The memory allocated here for the predicate (in lispReadString)
+ * only needs to stay around until it's used in find_index_paths,
+ * which is all within a command, so the automatic pfree at end of
+ * transaction should be ok.
+ */
+ char *predString;
+
+ predString = fmgr(F_TEXTOUT, &index->indpred);
+ info->indpred = (Node *) stringToNode(predString);
+ pfree(predString);
+ }
+
+ /* Extract info from the relation descriptor for the index */
+ indexRelation = index_open(index->indexrelid);
#ifdef notdef
- /* XXX should iterate through strategies -- but how? use #1 for now */
- amstrategy = indexRelation->rd_am->amstrategies;
-#endif /* notdef */
- amstrategy = 1;
- relam = indexRelation->rd_rel->relam;
- info->relam = relam;
- info->pages = indexRelation->rd_rel->relpages;
- info->tuples = indexRelation->rd_rel->reltuples;
- heap_close(indexRelation);
-
- /*
- * Find the index ordering keys
- *
- * Must use indclass to know when to stop looking since with
- * functional indices there could be several keys (args) for
- * one opclass. -mer 27 Sept 1991
- */
- for (i = 0; i < 8 && index->indclass[i]; ++i) {
- amopTuple = SearchSysCacheTuple(AMOPSTRATEGY,
- ObjectIdGetDatum(relam),
- ObjectIdGetDatum(index->indclass[i]),
- UInt16GetDatum(amstrategy),
- 0);
- if (!HeapTupleIsValid(amopTuple))
- elog(WARN, "index_info: no amop %d %d %d",
- relam, index->indclass[i], amstrategy);
- info->orderOprs[i] =
- ((Form_pg_amop)GETSTRUCT(amopTuple))->amopopr;
- }
- return(TRUE);
+ /* XXX should iterate through strategies -- but how? use #1 for now */
+ amstrategy = indexRelation->rd_am->amstrategies;
+#endif /* notdef */
+ amstrategy = 1;
+ relam = indexRelation->rd_rel->relam;
+ info->relam = relam;
+ info->pages = indexRelation->rd_rel->relpages;
+ info->tuples = indexRelation->rd_rel->reltuples;
+ heap_close(indexRelation);
+
+ /*
+ * Find the index ordering keys
+ *
+ * Must use indclass to know when to stop looking since with functional
+ * indices there could be several keys (args) for one opclass. -mer 27
+ * Sept 1991
+ */
+ for (i = 0; i < 8 && index->indclass[i]; ++i)
+ {
+ amopTuple = SearchSysCacheTuple(AMOPSTRATEGY,
+ ObjectIdGetDatum(relam),
+ ObjectIdGetDatum(index->indclass[i]),
+ UInt16GetDatum(amstrategy),
+ 0);
+ if (!HeapTupleIsValid(amopTuple))
+ elog(WARN, "index_info: no amop %d %d %d",
+ relam, index->indclass[i], amstrategy);
+ info->orderOprs[i] =
+ ((Form_pg_amop) GETSTRUCT(amopTuple))->amopopr;
+ }
+ return (TRUE);
}
-/*
+/*
* index-selectivity--
- *
- * Call util/plancat.c:IndexSelectivity with the indicated arguments.
- *
+ *
+ * Call util/plancat.c:IndexSelectivity with the indicated arguments.
+ *
* 'indid' is the index OID
* 'classes' is a list of index key classes
* 'opnos' is a list of index key operator OIDs
@@ -229,153 +239,162 @@ index_info(Query *root, bool first, int relid, IdxInfoRetval *info)
* 'values' is a list of the values of the clause's constants
* 'flags' is a list of fixnums which describe the constants
* 'nkeys' is the number of index keys
- *
+ *
* Returns two floats: index pages and index selectivity in 'idxPages' and
- * 'idxSelec'.
- *
+ * 'idxSelec'.
+ *
*/
void
index_selectivity(Oid indid,
- Oid *classes,
- List *opnos,
- Oid relid,
- List *attnos,
- List *values,
- List *flags,
- int32 nkeys,
- float *idxPages,
- float *idxSelec)
+ Oid * classes,
+ List * opnos,
+ Oid relid,
+ List * attnos,
+ List * values,
+ List * flags,
+ int32 nkeys,
+ float *idxPages,
+ float *idxSelec)
{
- Oid *opno_array;
- int *attno_array, *flag_array;
- char **value_array;
- int i = 0;
- List *xopno, *xattno, *value, *flag;
+ Oid *opno_array;
+ int *attno_array,
+ *flag_array;
+ char **value_array;
+ int i = 0;
+ List *xopno,
+ *xattno,
+ *value,
+ *flag;
+
+ if (length(opnos) != nkeys || length(attnos) != nkeys ||
+ length(values) != nkeys || length(flags) != nkeys)
+ {
+
+ *idxPages = 0.0;
+ *idxSelec = 1.0;
+ return;
+ }
- if (length(opnos)!=nkeys || length(attnos)!=nkeys ||
- length(values)!=nkeys || length(flags)!=nkeys) {
+ opno_array = (Oid *) palloc(nkeys * sizeof(Oid));
+ attno_array = (int *) palloc(nkeys * sizeof(int32));
+ value_array = (char **) palloc(nkeys * sizeof(char *));
+ flag_array = (int *) palloc(nkeys * sizeof(int32));
- *idxPages = 0.0;
- *idxSelec = 1.0;
+ i = 0;
+ foreach(xopno, opnos)
+ {
+ opno_array[i++] = lfirsti(xopno);
+ }
+
+ i = 0;
+ foreach(xattno, attnos)
+ {
+ attno_array[i++] = lfirsti(xattno);
+ }
+
+ i = 0;
+ foreach(value, values)
+ {
+ value_array[i++] = (char *) lfirst(value);
+ }
+
+ i = 0;
+ foreach(flag, flags)
+ {
+ flag_array[i++] = lfirsti(flag);
+ }
+
+ IndexSelectivity(indid,
+ relid,
+ nkeys,
+ classes, /* not used */
+ opno_array,
+ attno_array,
+ value_array,
+ flag_array,
+ idxPages,
+ idxSelec);
return;
- }
-
- opno_array = (Oid *)palloc(nkeys*sizeof(Oid));
- attno_array = (int *)palloc(nkeys*sizeof(int32));
- value_array = (char **)palloc(nkeys*sizeof(char *));
- flag_array = (int *)palloc(nkeys*sizeof(int32));
-
- i = 0;
- foreach(xopno, opnos) {
- opno_array[i++] = lfirsti(xopno);
- }
-
- i = 0;
- foreach(xattno,attnos) {
- attno_array[i++] = lfirsti(xattno);
- }
-
- i = 0;
- foreach(value, values) {
- value_array[i++] = (char *)lfirst(value);
- }
-
- i = 0;
- foreach(flag,flags) {
- flag_array[i++] = lfirsti(flag);
- }
-
- IndexSelectivity(indid,
- relid,
- nkeys,
- classes, /* not used */
- opno_array,
- attno_array,
- value_array,
- flag_array,
- idxPages,
- idxSelec);
- return;
}
/*
* restriction_selectivity in lisp system.--
*
- * NOTE: The routine is now merged with RestrictionClauseSelectivity
- * as defined in plancat.c
+ * NOTE: The routine is now merged with RestrictionClauseSelectivity
+ * as defined in plancat.c
*
* Returns the selectivity of a specified operator.
* 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 -1, then the clause
- * isn't of the form (op var const).
+ * relation OIDs or attribute numbers are -1, then the clause
+ * isn't of the form (op var const).
*/
Cost
restriction_selectivity(Oid functionObjectId,
- Oid operatorObjectId,
- Oid relationObjectId,
- AttrNumber attributeNumber,
- char *constValue,
- int32 constFlag)
+ Oid operatorObjectId,
+ Oid relationObjectId,
+ AttrNumber attributeNumber,
+ char *constValue,
+ int32 constFlag)
{
- float64 result;
-
- result = (float64) fmgr(functionObjectId,
- (char *) operatorObjectId,
- (char *) relationObjectId,
- (char *) (int)attributeNumber,
- (char *) constValue,
- (char *) constFlag,
- NULL);
- if (!PointerIsValid(result))
- elog(WARN, "RestrictionClauseSelectivity: bad pointer");
-
- if (*result < 0.0 || *result > 1.0)
- elog(WARN, "RestrictionClauseSelectivity: bad value %lf",
- *result);
-
- return ((Cost)*result);
+ float64 result;
+
+ result = (float64) fmgr(functionObjectId,
+ (char *) operatorObjectId,
+ (char *) relationObjectId,
+ (char *) (int) attributeNumber,
+ (char *) constValue,
+ (char *) constFlag,
+ NULL);
+ if (!PointerIsValid(result))
+ elog(WARN, "RestrictionClauseSelectivity: bad pointer");
+
+ if (*result < 0.0 || *result > 1.0)
+ elog(WARN, "RestrictionClauseSelectivity: bad value %lf",
+ *result);
+
+ return ((Cost) * result);
}
/*
* join_selectivity--
- * Similarly, this routine is merged with JoinClauseSelectivity in
- * plancat.c
+ * Similarly, this routine is merged with JoinClauseSelectivity in
+ * plancat.c
*
- * Returns the selectivity of an operator, given the join clause
- * information.
+ * 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 -1, then the clause
- * isn't of the form (op var var).
+ * relation OIDs or attribute numbers are -1, then the clause
+ * isn't of the form (op var var).
*/
Cost
-join_selectivity (Oid functionObjectId,
- Oid operatorObjectId,
- Oid relationObjectId1,
- AttrNumber attributeNumber1,
- Oid relationObjectId2,
- AttrNumber attributeNumber2)
+join_selectivity(Oid functionObjectId,
+ Oid operatorObjectId,
+ Oid relationObjectId1,
+ AttrNumber attributeNumber1,
+ Oid relationObjectId2,
+ AttrNumber attributeNumber2)
{
- float64 result;
-
- result = (float64) fmgr(functionObjectId,
- (char *) operatorObjectId,
- (char *) relationObjectId1,
- (char *) (int)attributeNumber1,
- (char *) relationObjectId2,
- (char *) (int)attributeNumber2,
- NULL);
- if (!PointerIsValid(result))
- elog(WARN, "JoinClauseSelectivity: bad pointer");
-
- if (*result < 0.0 || *result > 1.0)
- elog(WARN, "JoinClauseSelectivity: bad value %lf",
- *result);
-
- return((Cost)*result);
+ float64 result;
+
+ result = (float64) fmgr(functionObjectId,
+ (char *) operatorObjectId,
+ (char *) relationObjectId1,
+ (char *) (int) attributeNumber1,
+ (char *) relationObjectId2,
+ (char *) (int) attributeNumber2,
+ NULL);
+ if (!PointerIsValid(result))
+ elog(WARN, "JoinClauseSelectivity: bad pointer");
+
+ if (*result < 0.0 || *result > 1.0)
+ elog(WARN, "JoinClauseSelectivity: bad value %lf",
+ *result);
+
+ return ((Cost) * result);
}
/*
@@ -384,33 +403,34 @@ join_selectivity (Oid functionObjectId,
* Returns a LISP list containing the OIDs of all relations which
* inherits from the relation with OID 'inhparent'.
*/
-List *
+List *
find_inheritance_children(Oid inhparent)
{
- static ScanKeyData key[1] = {
- { 0, Anum_pg_inherits_inhparent, F_OIDEQ }
- };
-
- HeapTuple inheritsTuple;
- Relation relation;
- HeapScanDesc scan;
- List *list = NIL;
- Oid inhrelid;
-
- fmgr_info(F_OIDEQ, &key[0].sk_func, &key[0].sk_nargs);
-
- key[0].sk_argument = ObjectIdGetDatum((Oid)inhparent);
- relation = heap_openr(InheritsRelationName);
- scan = heap_beginscan(relation, 0, NowTimeQual, 1, key);
- while (HeapTupleIsValid(inheritsTuple =
- heap_getnext(scan, 0,
- (Buffer *) NULL))) {
- inhrelid = ((InheritsTupleForm)GETSTRUCT(inheritsTuple))->inhrel;
- list = lappendi(list, inhrelid);
- }
- heap_endscan(scan);
- heap_close(relation);
- return(list);
+ static ScanKeyData key[1] = {
+ {0, Anum_pg_inherits_inhparent, F_OIDEQ}
+ };
+
+ HeapTuple inheritsTuple;
+ Relation relation;
+ HeapScanDesc scan;
+ List *list = NIL;
+ Oid inhrelid;
+
+ fmgr_info(F_OIDEQ, &key[0].sk_func, &key[0].sk_nargs);
+
+ key[0].sk_argument = ObjectIdGetDatum((Oid) inhparent);
+ relation = heap_openr(InheritsRelationName);
+ scan = heap_beginscan(relation, 0, NowTimeQual, 1, key);
+ while (HeapTupleIsValid(inheritsTuple =
+ heap_getnext(scan, 0,
+ (Buffer *) NULL)))
+ {
+ inhrelid = ((InheritsTupleForm) GETSTRUCT(inheritsTuple))->inhrel;
+ list = lappendi(list, inhrelid);
+ }
+ heap_endscan(scan);
+ heap_close(relation);
+ return (list);
}
/*
@@ -419,39 +439,40 @@ find_inheritance_children(Oid inhparent)
* Returns a LISP list containing the OIDs of all relations which are
* base relations of the relation with OID 'verrelid'.
*/
-List *
+List *
VersionGetParents(Oid verrelid)
{
- static ScanKeyData key[1] = {
- { 0, Anum_pg_version_verrelid, F_OIDEQ }
- };
-
- HeapTuple versionTuple;
- Relation relation;
- HeapScanDesc scan;
- Oid verbaseid;
- List *list= NIL;
-
- fmgr_info(F_OIDEQ, &key[0].sk_func, &key[0].sk_nargs);
- relation = heap_openr(VersionRelationName);
- key[0].sk_argument = ObjectIdGetDatum(verrelid);
- scan = heap_beginscan(relation, 0, NowTimeQual, 1, key);
- for (;;) {
- versionTuple = heap_getnext(scan, 0,
- (Buffer *) NULL);
- if (!HeapTupleIsValid(versionTuple))
- break;
- verbaseid = ((VersionTupleForm)
- GETSTRUCT(versionTuple))->verbaseid;
-
- list = lconsi(verbaseid, list);
-
- key[0].sk_argument = ObjectIdGetDatum(verbaseid);
- heap_rescan(scan, 0, key);
- }
- heap_endscan(scan);
- heap_close(relation);
- return(list);
+ static ScanKeyData key[1] = {
+ {0, Anum_pg_version_verrelid, F_OIDEQ}
+ };
+
+ HeapTuple versionTuple;
+ Relation relation;
+ HeapScanDesc scan;
+ Oid verbaseid;
+ List *list = NIL;
+
+ fmgr_info(F_OIDEQ, &key[0].sk_func, &key[0].sk_nargs);
+ relation = heap_openr(VersionRelationName);
+ key[0].sk_argument = ObjectIdGetDatum(verrelid);
+ scan = heap_beginscan(relation, 0, NowTimeQual, 1, key);
+ for (;;)
+ {
+ versionTuple = heap_getnext(scan, 0,
+ (Buffer *) NULL);
+ if (!HeapTupleIsValid(versionTuple))
+ break;
+ verbaseid = ((VersionTupleForm)
+ GETSTRUCT(versionTuple))->verbaseid;
+
+ list = lconsi(verbaseid, list);
+
+ key[0].sk_argument = ObjectIdGetDatum(verbaseid);
+ heap_rescan(scan, 0, key);
+ }
+ heap_endscan(scan);
+ heap_close(relation);
+ return (list);
}
/*****************************************************************************
@@ -461,14 +482,14 @@ VersionGetParents(Oid verrelid)
/*
* IdexSelectivity--
*
- * Retrieves the 'amopnpages' and 'amopselect' parameters for each
- * AM operator when a given index (specified by 'indexrelid') is used.
- * These two parameters are returned by copying them to into an array of
- * floats.
+ * Retrieves the 'amopnpages' and 'amopselect' parameters for each
+ * AM operator when a given index (specified by 'indexrelid') is used.
+ * These two parameters are returned by copying them to into an array of
+ * floats.
*
- * Assumption: the attribute numbers and operator ObjectIds are in order
- * WRT to each other (otherwise, you have no way of knowing which
- * AM operator class or attribute number corresponds to which operator.
+ * Assumption: the attribute numbers and operator ObjectIds are in order
+ * WRT to each other (otherwise, you have no way of knowing which
+ * AM operator class or attribute number corresponds to which operator.
*
* 'varAttributeNumbers' contains attribute numbers for variables
* 'constValues' contains the constant values
@@ -481,144 +502,154 @@ VersionGetParents(Oid verrelid)
*/
static void
IndexSelectivity(Oid indexrelid,
- Oid indrelid,
- int32 nIndexKeys,
- Oid AccessMethodOperatorClasses[], /* XXX not used? */
- Oid operatorObjectIds[],
- int32 varAttributeNumbers[],
- char *constValues[],
- int32 constFlags[],
- float *idxPages,
- float *idxSelec)
+ Oid indrelid,
+ int32 nIndexKeys,
+ Oid AccessMethodOperatorClasses[], /* XXX not used? */
+ Oid operatorObjectIds[],
+ int32 varAttributeNumbers[],
+ char *constValues[],
+ int32 constFlags[],
+ float *idxPages,
+ float *idxSelec)
{
- register i, n;
- HeapTuple indexTuple, amopTuple, indRel;
- IndexTupleForm index;
- Form_pg_amop amop;
- Oid indclass;
- float64data npages, select;
- float64 amopnpages, amopselect;
- Oid relam;
- bool nphack = false;
- float64data fattr_select = 1.0;
-
- indRel = SearchSysCacheTuple(RELOID,
- ObjectIdGetDatum(indexrelid),
- 0,0,0);
- if (!HeapTupleIsValid(indRel))
- elog(WARN, "IndexSelectivity: index %d not found",
- indexrelid);
- relam = ((Form_pg_class)GETSTRUCT(indRel))->relam;
-
- indexTuple = SearchSysCacheTuple(INDEXRELID,
- ObjectIdGetDatum(indexrelid),
- 0,0,0);
- if (!HeapTupleIsValid(indexTuple))
- elog(WARN, "IndexSelectivity: index %d not found",
- indexrelid);
- index = (IndexTupleForm)GETSTRUCT(indexTuple);
-
- /*
- * Hack for non-functional btree npages estimation:
- * npages = index_pages * selectivity_of_1st_attr_clause(s)
- * - vadim 04/24/97
- */
- if ( relam == BTREE_AM_OID &&
- varAttributeNumbers[0] != InvalidAttrNumber )
- nphack = true;
-
- npages = 0.0;
- select = 1.0;
- for (n = 0; n < nIndexKeys; ++n) {
- /*
- * Find the AM class for this key.
- *
- * If the first attribute number is invalid then we have a
- * functional index, and AM class is the first one defined
- * since functional indices have exactly one key.
+ register i,
+ n;
+ HeapTuple indexTuple,
+ amopTuple,
+ indRel;
+ IndexTupleForm index;
+ Form_pg_amop amop;
+ Oid indclass;
+ float64data npages,
+ select;
+ float64 amopnpages,
+ amopselect;
+ Oid relam;
+ bool nphack = false;
+ float64data fattr_select = 1.0;
+
+ indRel = SearchSysCacheTuple(RELOID,
+ ObjectIdGetDatum(indexrelid),
+ 0, 0, 0);
+ if (!HeapTupleIsValid(indRel))
+ elog(WARN, "IndexSelectivity: index %d not found",
+ indexrelid);
+ relam = ((Form_pg_class) GETSTRUCT(indRel))->relam;
+
+ indexTuple = SearchSysCacheTuple(INDEXRELID,
+ ObjectIdGetDatum(indexrelid),
+ 0, 0, 0);
+ if (!HeapTupleIsValid(indexTuple))
+ elog(WARN, "IndexSelectivity: index %d not found",
+ indexrelid);
+ index = (IndexTupleForm) GETSTRUCT(indexTuple);
+
+ /*
+ * Hack for non-functional btree npages estimation: npages =
+ * index_pages * selectivity_of_1st_attr_clause(s) - vadim 04/24/97
*/
- indclass = (varAttributeNumbers[0] == InvalidAttrNumber) ?
- index->indclass[0] : InvalidOid;
- i = 0;
- while ((i < nIndexKeys) && (indclass == InvalidOid)) {
- if (varAttributeNumbers[n] == index->indkey[i]) {
- indclass = index->indclass[i];
- break;
- }
- i++;
- }
- if (!OidIsValid(indclass)) {
- /*
- * Presumably this means that we are using a functional
- * index clause and so had no variable to match to
- * the index key ... if not we are in trouble.
- */
- elog(NOTICE, "IndexSelectivity: no key %d in index %d",
- varAttributeNumbers[n], indexrelid);
- continue;
- }
+ if (relam == BTREE_AM_OID &&
+ varAttributeNumbers[0] != InvalidAttrNumber)
+ nphack = true;
- amopTuple = SearchSysCacheTuple(AMOPOPID,
- ObjectIdGetDatum(indclass),
- ObjectIdGetDatum(operatorObjectIds[n]),
- ObjectIdGetDatum(relam),
- 0);
- if (!HeapTupleIsValid(amopTuple))
- elog(WARN, "IndexSelectivity: no amop %d %d",
- indclass, operatorObjectIds[n]);
- amop = (Form_pg_amop)GETSTRUCT(amopTuple);
-
- if ( !nphack )
+ npages = 0.0;
+ select = 1.0;
+ for (n = 0; n < nIndexKeys; ++n)
{
- amopnpages = (float64) fmgr(amop->amopnpages,
- (char *) operatorObjectIds[n],
- (char *) indrelid,
- (char *) varAttributeNumbers[n],
- (char *) constValues[n],
- (char *) constFlags[n],
- (char *) nIndexKeys,
- (char *) indexrelid);
-#if 0
-/*
+
+ /*
+ * Find the AM class for this key.
+ *
+ * If the first attribute number is invalid then we have a functional
+ * index, and AM class is the first one defined since functional
+ * indices have exactly one key.
+ */
+ indclass = (varAttributeNumbers[0] == InvalidAttrNumber) ?
+ index->indclass[0] : InvalidOid;
+ i = 0;
+ while ((i < nIndexKeys) && (indclass == InvalidOid))
+ {
+ if (varAttributeNumbers[n] == index->indkey[i])
+ {
+ indclass = index->indclass[i];
+ break;
+ }
+ i++;
+ }
+ if (!OidIsValid(indclass))
+ {
+
+ /*
+ * Presumably this means that we are using a functional index
+ * clause and so had no variable to match to the index key ...
+ * if not we are in trouble.
+ */
+ elog(NOTICE, "IndexSelectivity: no key %d in index %d",
+ varAttributeNumbers[n], indexrelid);
+ continue;
+ }
+
+ amopTuple = SearchSysCacheTuple(AMOPOPID,
+ ObjectIdGetDatum(indclass),
+ ObjectIdGetDatum(operatorObjectIds[n]),
+ ObjectIdGetDatum(relam),
+ 0);
+ if (!HeapTupleIsValid(amopTuple))
+ elog(WARN, "IndexSelectivity: no amop %d %d",
+ indclass, operatorObjectIds[n]);
+ amop = (Form_pg_amop) GETSTRUCT(amopTuple);
+
+ if (!nphack)
+ {
+ amopnpages = (float64) fmgr(amop->amopnpages,
+ (char *) operatorObjectIds[n],
+ (char *) indrelid,
+ (char *) varAttributeNumbers[n],
+ (char *) constValues[n],
+ (char *) constFlags[n],
+ (char *) nIndexKeys,
+ (char *) indexrelid);
+#if 0
+/*
* So cool guys! Npages for x > 10 and x < 20 is twice as
* npages for x > 10! - vadim 04/09/97
*/
- npages += PointerIsValid(amopnpages) ? *amopnpages : 0.0;
- if ((i = npages) < npages) /* ceil(npages)? */
- npages += 1.0;
+ npages += PointerIsValid(amopnpages) ? *amopnpages : 0.0;
+ if ((i = npages) < npages) /* ceil(npages)? */
+ npages += 1.0;
#endif
- npages += PointerIsValid(amopnpages) ? *amopnpages : 0.0;
+ npages += PointerIsValid(amopnpages) ? *amopnpages : 0.0;
+ }
+
+ amopselect = (float64) fmgr(amop->amopselect,
+ (char *) operatorObjectIds[n],
+ (char *) indrelid,
+ (char *) varAttributeNumbers[n],
+ (char *) constValues[n],
+ (char *) constFlags[n],
+ (char *) nIndexKeys,
+ (char *) indexrelid);
+
+ if (nphack && varAttributeNumbers[n] == index->indkey[0])
+ fattr_select *= PointerIsValid(amopselect) ? *amopselect : 1.0;
+
+ select *= PointerIsValid(amopselect) ? *amopselect : 1.0;
}
-
- amopselect = (float64) fmgr(amop->amopselect,
- (char *) operatorObjectIds[n],
- (char *) indrelid,
- (char *) varAttributeNumbers[n],
- (char *) constValues[n],
- (char *) constFlags[n],
- (char *) nIndexKeys,
- (char *) indexrelid);
-
- if ( nphack && varAttributeNumbers[n] == index->indkey[0] )
- fattr_select *= PointerIsValid(amopselect) ? *amopselect : 1.0;
-
- select *= PointerIsValid(amopselect) ? *amopselect : 1.0;
- }
- /*
- * Estimation of npages below is hack of course, but it's
- * better than it was before. - vadim 04/09/97
- */
- if ( nphack )
- {
- npages = fattr_select * ((Form_pg_class)GETSTRUCT(indRel))->relpages;
- *idxPages = ceil ((double)npages);
- }
- else
- {
- if ( nIndexKeys > 1 )
- npages = npages / (1.0 + nIndexKeys);
- *idxPages = ceil ((double)(npages/nIndexKeys));
- }
- *idxSelec = select;
-}
+ /*
+ * Estimation of npages below is hack of course, but it's better than
+ * it was before. - vadim 04/09/97
+ */
+ if (nphack)
+ {
+ npages = fattr_select * ((Form_pg_class) GETSTRUCT(indRel))->relpages;
+ *idxPages = ceil((double) npages);
+ }
+ else
+ {
+ if (nIndexKeys > 1)
+ npages = npages / (1.0 + nIndexKeys);
+ *idxPages = ceil((double) (npages / nIndexKeys));
+ }
+ *idxSelec = select;
+}