diff options
Diffstat (limited to 'src/backend')
-rw-r--r-- | src/backend/catalog/heap.c | 11 | ||||
-rw-r--r-- | src/backend/catalog/index.c | 50 | ||||
-rw-r--r-- | src/backend/utils/cache/relcache.c | 51 |
3 files changed, 110 insertions, 2 deletions
diff --git a/src/backend/catalog/heap.c b/src/backend/catalog/heap.c index b8b4768fd69..1c367527672 100644 --- a/src/backend/catalog/heap.c +++ b/src/backend/catalog/heap.c @@ -3149,8 +3149,15 @@ RelationTruncateIndexes(Relation heapRelation) /* Open the index relation; use exclusive lock, just to be sure */ currentIndex = index_open(indexId, AccessExclusiveLock); - /* Fetch info needed for index_build */ - indexInfo = BuildIndexInfo(currentIndex); + /* + * Fetch info needed for index_build. Since we know there are no + * tuples that actually need indexing, we can use a dummy IndexInfo. + * This is slightly cheaper to build, but the real point is to avoid + * possibly running user-defined code in index expressions or + * predicates. We might be getting invoked during ON COMMIT + * processing, and we don't want to run any such code then. + */ + indexInfo = BuildDummyIndexInfo(currentIndex); /* * Now truncate the actual file (and discard buffers). diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 4ae65915ac4..344c881e95e 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -2347,6 +2347,56 @@ BuildIndexInfo(Relation index) return ii; } +/* ---------------- + * BuildDummyIndexInfo + * Construct a dummy IndexInfo record for an open index + * + * This differs from the real BuildIndexInfo in that it will never run any + * user-defined code that might exist in index expressions or predicates. + * Instead of the real index expressions, we return null constants that have + * the right types/typmods/collations. Predicates and exclusion clauses are + * just ignored. This is sufficient for the purpose of truncating an index, + * since we will not need to actually evaluate the expressions or predicates; + * the only thing that's likely to be done with the data is construction of + * a tupdesc describing the index's rowtype. + * ---------------- + */ +IndexInfo * +BuildDummyIndexInfo(Relation index) +{ + IndexInfo *ii; + Form_pg_index indexStruct = index->rd_index; + int i; + int numAtts; + + /* check the number of keys, and copy attr numbers into the IndexInfo */ + numAtts = indexStruct->indnatts; + if (numAtts < 1 || numAtts > INDEX_MAX_KEYS) + elog(ERROR, "invalid indnatts %d for index %u", + numAtts, RelationGetRelid(index)); + + /* + * Create the node, using dummy index expressions, and pretending there is + * no predicate. + */ + ii = makeIndexInfo(indexStruct->indnatts, + indexStruct->indnkeyatts, + index->rd_rel->relam, + RelationGetDummyIndexExpressions(index), + NIL, + indexStruct->indisunique, + indexStruct->indisready, + false); + + /* fill in attribute numbers */ + for (i = 0; i < numAtts; i++) + ii->ii_IndexAttrNumbers[i] = indexStruct->indkey.values[i]; + + /* We ignore the exclusion constraint if any */ + + return ii; +} + /* * CompareIndexInfo * Return whether the properties of two indexes (in different tables) diff --git a/src/backend/utils/cache/relcache.c b/src/backend/utils/cache/relcache.c index e8d11a1d0ee..1d611685334 100644 --- a/src/backend/utils/cache/relcache.c +++ b/src/backend/utils/cache/relcache.c @@ -4659,6 +4659,57 @@ RelationGetIndexExpressions(Relation relation) } /* + * RelationGetDummyIndexExpressions -- get dummy expressions for an index + * + * Return a list of dummy expressions (just Const nodes) with the same + * types/typmods/collations as the index's real expressions. This is + * useful in situations where we don't want to run any user-defined code. + */ +List * +RelationGetDummyIndexExpressions(Relation relation) +{ + List *result; + Datum exprsDatum; + bool isnull; + char *exprsString; + List *rawExprs; + ListCell *lc; + + /* Quick exit if there is nothing to do. */ + if (relation->rd_indextuple == NULL || + heap_attisnull(relation->rd_indextuple, Anum_pg_index_indexprs, NULL)) + return NIL; + + /* Extract raw node tree(s) from index tuple. */ + exprsDatum = heap_getattr(relation->rd_indextuple, + Anum_pg_index_indexprs, + GetPgIndexDescriptor(), + &isnull); + Assert(!isnull); + exprsString = TextDatumGetCString(exprsDatum); + rawExprs = (List *) stringToNode(exprsString); + pfree(exprsString); + + /* Construct null Consts; the typlen and typbyval are arbitrary. */ + result = NIL; + foreach(lc, rawExprs) + { + Node *rawExpr = (Node *) lfirst(lc); + + result = lappend(result, + makeConst(exprType(rawExpr), + exprTypmod(rawExpr), + exprCollation(rawExpr), + 1, + (Datum) 0, + true, + true)); + } + + return result; +} + +/* * RelationGetIndexPredicate -- get the index predicate for an index * * We cache the result of transforming pg_index.indpred into an implicit-AND |