diff options
Diffstat (limited to 'src/backend/utils')
| -rw-r--r-- | src/backend/utils/adt/ruleutils.c | 61 | ||||
| -rw-r--r-- | src/backend/utils/adt/selfuncs.c | 60 |
2 files changed, 110 insertions, 11 deletions
diff --git a/src/backend/utils/adt/ruleutils.c b/src/backend/utils/adt/ruleutils.c index 5f7cfead6c1..afc2b63430b 100644 --- a/src/backend/utils/adt/ruleutils.c +++ b/src/backend/utils/adt/ruleutils.c @@ -3,7 +3,7 @@ * back to source text * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/utils/adt/ruleutils.c,v 1.79 2001/07/10 00:02:02 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/utils/adt/ruleutils.c,v 1.80 2001/07/16 05:06:59 tgl Exp $ * * This software is copyrighted by Jan Wieck - Hamburg. * @@ -40,6 +40,7 @@ #include <unistd.h> #include <fcntl.h> +#include "catalog/heap.h" #include "catalog/pg_index.h" #include "catalog/pg_operator.h" #include "catalog/pg_shadow.h" @@ -555,6 +556,64 @@ pg_get_indexdef(PG_FUNCTION_ARGS) /* ---------- + * get_expr - Decompile an expression tree + * + * Input: an expression tree in nodeToString form, and a relation OID + * + * Output: reverse-listed expression + * + * Currently, the expression can only refer to a single relation, namely + * the one specified by the second parameter. This is sufficient for + * partial indexes, column default expressions, etc. + * ---------- + */ +Datum +pg_get_expr(PG_FUNCTION_ARGS) +{ + text *expr = PG_GETARG_TEXT_P(0); + Oid relid = PG_GETARG_OID(1); + text *result; + Node *node; + List *context; + char *exprstr; + char *relname; + char *str; + + /* Get the name for the relation */ + relname = get_rel_name(relid); + if (relname == NULL) + PG_RETURN_NULL(); /* should we raise an error? */ + + /* Convert input TEXT object to C string */ + exprstr = DatumGetCString(DirectFunctionCall1(textout, + PointerGetDatum(expr))); + + /* Convert expression to node tree */ + node = (Node *) stringToNode(exprstr); + + /* + * If top level is a List, assume it is an implicit-AND structure, + * and convert to explicit AND. This is needed for partial index + * predicates. + */ + if (node && IsA(node, List)) + { + node = (Node *) make_ands_explicit((List *) node); + } + + /* Deparse */ + context = deparse_context_for(relname, relid); + str = deparse_expression(node, context, false); + + /* Pass the result back as TEXT */ + result = DatumGetTextP(DirectFunctionCall1(textin, + CStringGetDatum(str))); + + PG_RETURN_TEXT_P(result); +} + + +/* ---------- * get_userbyid - Get a user name by usesysid and * fallback to 'unknown (UID=n)' * ---------- diff --git a/src/backend/utils/adt/selfuncs.c b/src/backend/utils/adt/selfuncs.c index 3ab3881c257..e0cfeefaee4 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.94 2001/06/25 21:11:44 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/utils/adt/selfuncs.c,v 1.95 2001/07/16 05:06:59 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -86,6 +86,7 @@ #include "optimizer/cost.h" #include "optimizer/pathnode.h" #include "optimizer/plancat.h" +#include "optimizer/prep.h" #include "parser/parse_func.h" #include "parser/parse_oper.h" #include "parser/parsetree.h" @@ -2950,24 +2951,63 @@ genericcostestimate(Query *root, RelOptInfo *rel, { double numIndexTuples; double numIndexPages; + List *selectivityQuals = indexQuals; - /* Estimate the fraction of main-table tuples that will be visited */ - *indexSelectivity = clauselist_selectivity(root, indexQuals, - lfirsti(rel->relids)); + /* + * If the index is partial, AND the index predicate with the explicitly + * given indexquals to produce a more accurate idea of the index + * restriction. This may produce redundant clauses, which we hope that + * cnfify and clauselist_selectivity will deal with intelligently. + * + * Note that index->indpred and indexQuals are both in implicit-AND + * form to start with, which we have to make explicit to hand to + * canonicalize_qual, and then we get back implicit-AND form again. + */ + if (index->indpred != NIL) + { + Expr *andedQuals; - /* Estimate the number of index tuples that will be visited */ - numIndexTuples = *indexSelectivity * index->tuples; + andedQuals = make_ands_explicit(nconc(listCopy(index->indpred), + indexQuals)); + selectivityQuals = canonicalize_qual(andedQuals, true); + } - /* Estimate the number of index pages that will be retrieved */ - numIndexPages = *indexSelectivity * index->pages; + /* Estimate the fraction of main-table tuples that will be visited */ + *indexSelectivity = clauselist_selectivity(root, selectivityQuals, + lfirsti(rel->relids)); /* - * Always estimate at least one tuple and page are touched, even when + * Estimate the number of tuples that will be visited. We do it in + * this rather peculiar-looking way in order to get the right answer + * for partial indexes. We can bound the number of tuples by the + * index size, in any case. + */ + numIndexTuples = *indexSelectivity * rel->tuples; + + if (numIndexTuples > index->tuples) + numIndexTuples = index->tuples; + + /* + * Always estimate at least one tuple is touched, even when * indexSelectivity estimate is tiny. */ if (numIndexTuples < 1.0) numIndexTuples = 1.0; - if (numIndexPages < 1.0) + + /* + * Estimate the number of index pages that will be retrieved. + * + * For all currently-supported index types, the first page of the index + * is a metadata page, and we should figure on fetching that plus a + * pro-rated fraction of the remaining pages. + */ + if (index->pages > 1 && index->tuples > 0) + { + numIndexPages = (numIndexTuples / index->tuples) * (index->pages - 1); + numIndexPages += 1; /* count the metapage too */ + numIndexPages = ceil(numIndexPages); + } + else numIndexPages = 1.0; /* |
