aboutsummaryrefslogtreecommitdiff
path: root/src/backend
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend')
-rw-r--r--src/backend/catalog/heap.c11
-rw-r--r--src/backend/catalog/index.c50
-rw-r--r--src/backend/utils/cache/relcache.c51
3 files changed, 110 insertions, 2 deletions
diff --git a/src/backend/catalog/heap.c b/src/backend/catalog/heap.c
index b7bcdd9d0f7..84049047109 100644
--- a/src/backend/catalog/heap.c
+++ b/src/backend/catalog/heap.c
@@ -3148,8 +3148,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 67f637de11d..e9955707fa7 100644
--- a/src/backend/catalog/index.c
+++ b/src/backend/catalog/index.c
@@ -2324,6 +2324,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 ad1ff01b320..50f8912c13a 100644
--- a/src/backend/utils/cache/relcache.c
+++ b/src/backend/utils/cache/relcache.c
@@ -4630,6 +4630,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