diff options
Diffstat (limited to 'src/backend/optimizer/util/plancat.c')
-rw-r--r-- | src/backend/optimizer/util/plancat.c | 969 |
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; +} |