aboutsummaryrefslogtreecommitdiff
path: root/src/backend/executor/execMain.c
diff options
context:
space:
mode:
authorTom Lane <tgl@sss.pgh.pa.us>2021-04-06 10:34:37 -0400
committerTom Lane <tgl@sss.pgh.pa.us>2021-04-06 10:34:39 -0400
commit091e22b2e673e3e8480abd68fbb827c5d6979615 (patch)
tree837fd7f82f0e9d269c6e85f2ca395457f05fa3a1 /src/backend/executor/execMain.c
parent9de9294b0c4dac77edb80f029648afca79d14653 (diff)
downloadpostgresql-091e22b2e673e3e8480abd68fbb827c5d6979615.tar.gz
postgresql-091e22b2e673e3e8480abd68fbb827c5d6979615.zip
Clean up treatment of missing default and CHECK-constraint records.
Andrew Gierth reported that it's possible to crash the backend if no pg_attrdef record is found to match an attribute that has atthasdef set. AttrDefaultFetch warns about this situation, but then leaves behind a relation tupdesc that has null "adbin" pointer(s), which most places don't guard against. We considered promoting the warning to an error, but throwing errors during relcache load is pretty drastic: it effectively locks one out of using the relation at all. What seems better is to leave the load-time behavior as a warning, but then throw an error in any code path that wants to use a default and can't find it. This confines the error to a subset of INSERT/UPDATE operations on the table, and in particular will at least allow a pg_dump to succeed. Also, we should fix AttrDefaultFetch to not leave any null pointers in the tupdesc, because that just creates an untested bug hazard. While at it, apply the same philosophy of "warn at load, throw error only upon use of the known-missing info" to CHECK constraints. CheckConstraintFetch is very nearly the same logic as AttrDefaultFetch, but for reasons lost in the mists of time, it was throwing ERROR for the same cases that AttrDefaultFetch treats as WARNING. Make the two functions more nearly alike. In passing, get rid of potentially-O(N^2) loops in equalTupleDesc by making AttrDefaultFetch sort the entries after fetching them, so that equalTupleDesc can assume that entries in two equal tupdescs must be in matching order. (CheckConstraintFetch already was sorting CHECK constraints, but equalTupleDesc hadn't been told about it.) There's some argument for back-patching this, but with such a small number of field reports, I'm content to fix it in HEAD. Discussion: https://postgr.es/m/87pmzaq4gx.fsf@news-spur.riddles.org.uk
Diffstat (limited to 'src/backend/executor/execMain.c')
-rw-r--r--src/backend/executor/execMain.c11
1 files changed, 10 insertions, 1 deletions
diff --git a/src/backend/executor/execMain.c b/src/backend/executor/execMain.c
index 163242f54eb..9f86910a6bf 100644
--- a/src/backend/executor/execMain.c
+++ b/src/backend/executor/execMain.c
@@ -1610,6 +1610,15 @@ ExecRelCheck(ResultRelInfo *resultRelInfo,
int i;
/*
+ * CheckConstraintFetch let this pass with only a warning, but now we
+ * should fail rather than possibly failing to enforce an important
+ * constraint.
+ */
+ if (ncheck != rel->rd_rel->relchecks)
+ elog(ERROR, "%d pg_constraint record(s) missing for relation \"%s\"",
+ rel->rd_rel->relchecks - ncheck, RelationGetRelationName(rel));
+
+ /*
* If first time through for this result relation, build expression
* nodetrees for rel's constraint expressions. Keep them in the per-query
* memory context so they'll survive throughout the query.
@@ -1862,7 +1871,7 @@ ExecConstraints(ResultRelInfo *resultRelInfo,
}
}
- if (constr->num_check > 0)
+ if (rel->rd_rel->relchecks > 0)
{
const char *failed;