diff --git a/doc/src/sgml/limits.sgml b/doc/src/sgml/limits.sgml
index f26f4466719..0e9a0b4e94e 100644
--- a/doc/src/sgml/limits.sgml
+++ b/doc/src/sgml/limits.sgml
@@ -62,6 +62,13 @@
below
+
+ CHECK constraints per table
+
+ 32,767
+ constrained by the size of pg_class.relchecks
+
+
columns in a result set
1,664
diff --git a/src/backend/catalog/heap.c b/src/backend/catalog/heap.c
index 346c770e3fc..c735ecaa910 100644
--- a/src/backend/catalog/heap.c
+++ b/src/backend/catalog/heap.c
@@ -56,6 +56,7 @@
#include "catalog/storage.h"
#include "commands/tablecmds.h"
#include "commands/typecmds.h"
+#include "common/int.h"
#include "miscadmin.h"
#include "nodes/nodeFuncs.h"
#include "optimizer/optimizer.h"
@@ -2258,7 +2259,7 @@ StoreRelCheck(Relation rel, const char *ccname, Node *expr,
static void
StoreConstraints(Relation rel, List *cooked_constraints, bool is_internal)
{
- int numchecks = 0;
+ int16 numchecks = 0;
ListCell *lc;
if (cooked_constraints == NIL)
@@ -2282,12 +2283,18 @@ StoreConstraints(Relation rel, List *cooked_constraints, bool is_internal)
is_internal, false);
break;
case CONSTR_CHECK:
+ if (pg_add_s16_overflow(numchecks, 1, &numchecks))
+ ereport(ERROR,
+ errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
+ errmsg("too many check constraints on relation \"%s\"",
+ RelationGetRelationName(rel)));
+
con->conoid =
StoreRelCheck(rel, con->name, con->expr,
!con->skip_validation, con->is_local,
con->inhcount, con->is_no_inherit,
is_internal);
- numchecks++;
+
break;
default:
elog(ERROR, "unrecognized constraint type: %d",
@@ -2342,7 +2349,7 @@ AddRelationNewConstraints(Relation rel,
int numoldchecks;
ParseState *pstate;
ParseNamespaceItem *nsitem;
- int numchecks;
+ int16 numchecks;
List *checknames;
ListCell *cell;
Node *expr;
@@ -2544,6 +2551,16 @@ AddRelationNewConstraints(Relation rel,
checknames = lappend(checknames, ccname);
}
+ /*
+ * pg_class.relchecks stores this count in an int16, so we should
+ * avoid overflowing that field
+ */
+ if (pg_add_s16_overflow(numchecks, 1, &numchecks))
+ ereport(ERROR,
+ errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
+ errmsg("too many check constraints on relation \"%s\"",
+ RelationGetRelationName(rel)));
+
/*
* OK, store it.
*/
@@ -2551,8 +2568,6 @@ AddRelationNewConstraints(Relation rel,
StoreRelCheck(rel, ccname, expr, cdef->initially_valid, is_local,
is_local ? 0 : 1, cdef->is_no_inherit, is_internal);
- numchecks++;
-
cooked = (CookedConstraint *) palloc(sizeof(CookedConstraint));
cooked->contype = CONSTR_CHECK;
cooked->conoid = constrOid;
@@ -2760,6 +2775,10 @@ SetRelationNumChecks(Relation rel, int numchecks)
if (relStruct->relchecks != numchecks)
{
+ if (numchecks > INT16_MAX || numchecks < 0)
+ elog(ERROR, "invalid new relchecks %d for relation %u",
+ numchecks, RelationGetRelid(rel));
+
relStruct->relchecks = numchecks;
CatalogTupleUpdate(relrel, &reltup->t_self, reltup);