📄 plancat.c
字号:
/*------------------------------------------------------------------------- * * plancat.c * routines for accessing the system catalogs * * * Copyright (c) 1994, Regents of the University of California * * * IDENTIFICATION * $Header: /usr/local/cvsroot/pgsql/src/backend/optimizer/util/plancat.c,v 1.31 1999/07/07 16:09:33 momjian Exp $ * *------------------------------------------------------------------------- */#include <stdio.h>#include <math.h>#include "postgres.h"#include "access/heapam.h"#include "access/genam.h"#include "access/htup.h"#include "access/itup.h"#include "catalog/catname.h"#include "catalog/pg_amop.h"#include "catalog/pg_index.h"#include "catalog/pg_inherits.h"#include "catalog/pg_version.h"#include "parser/parsetree.h" /* for getrelid() */#include "fmgr.h"#include "optimizer/internal.h"#include "optimizer/plancat.h"#include "utils/syscache.h"#ifndef HAVE_MEMMOVE#include <regex/utils.h>#else#include <string.h>#endifstatic void IndexSelectivity(Oid indexrelid, Oid indrelid, int32 nIndexKeys, Oid *AccessMethodOperatorClasses, Oid *operatorObjectIds, int32 *varAttributeNumbers, char **constValues, int32 *constFlags, 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 */voidrelation_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(ERROR, "RelationCatalogInformation: Relation %u 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 * * Returns true if successful and false otherwise. Index info is returned * via the transient data structure 'info'. * */boolindex_info(Query *root, bool first, int relid, IdxInfoRetval *info){ int i; HeapTuple indexTuple, amopTuple; Form_pg_index 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, SnapshotNow, 1, &indexKey); } if (!HeapScanIsValid(scan)) elog(ERROR, "index_info: scan not started"); indexTuple = heap_getnext(scan, 0); if (!HeapTupleIsValid(indexTuple)) { heap_endscan(scan); heap_close(relation); scan = (HeapScanDesc) NULL; relation = (Relation) NULL; return 0; } /* Extract info from the index tuple */ index = (Form_pg_index) GETSTRUCT(indexTuple); info->relid = index->indexrelid; /* index relation */ for (i = 0; i < INDEX_MAX_KEYS; i++) info->indexkeys[i] = index->indkey[i]; for (i = 0; i < INDEX_MAX_KEYS; i++) info->classlist[i] = index->indclass[i]; info->indproc = index->indproc; /* functional index ?? */ /* 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(ERROR, "index_info: no amop %u %u %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. * * 'indid' is the index OID * 'classes' is a list of index key classes * 'opnos' is a list of index key operator OIDs * 'relid' is the OID of the relation indexed * 'attnos' is a list of the relation attnos which the index keys over * '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'. * */voidindex_selectivity(Oid indid, 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; if (length(opnos) != nkeys || length(attnos) != nkeys || length(values) != nkeys || length(flags) != nkeys) { *idxPages = 0.0; *idxSelec = 1.0; 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 * * 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). */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -