how to create a non-inherited CHECK constraint in CREATE TABLE

Started by Peter Eisentrautalmost 14 years ago20 messages
#1Peter Eisentraut
peter_e@gmx.net

It appears that the only way to create a non-inherited CHECK constraint
is using ALTER TABLE. Is there no support in CREATE TABLE planned?
That looks a bit odd.

#2Alvaro Herrera
alvherre@commandprompt.com
In reply to: Peter Eisentraut (#1)
Re: how to create a non-inherited CHECK constraint in CREATE TABLE

Excerpts from Peter Eisentraut's message of mar ene 17 13:59:57 -0300 2012:

It appears that the only way to create a non-inherited CHECK constraint
is using ALTER TABLE. Is there no support in CREATE TABLE planned?
That looks a bit odd.

There are no plans to do that AFAIR, though maybe you could convince
Nikhil to write the patch to do so.

--
Álvaro Herrera <alvherre@commandprompt.com>
The PostgreSQL Company - Command Prompt, Inc.
PostgreSQL Replication, Consulting, Custom Development, 24x7 support

#3Jim Nasby
jim@nasby.net
In reply to: Alvaro Herrera (#2)
Re: how to create a non-inherited CHECK constraint in CREATE TABLE

On Jan 17, 2012, at 11:07 AM, Alvaro Herrera wrote:

Excerpts from Peter Eisentraut's message of mar ene 17 13:59:57 -0300 2012:

It appears that the only way to create a non-inherited CHECK constraint
is using ALTER TABLE. Is there no support in CREATE TABLE planned?
That looks a bit odd.

There are no plans to do that AFAIR, though maybe you could convince
Nikhil to write the patch to do so.

That certainly doesn't meet the principle of least surprise... CREATE TABLE should support this.
--
Jim C. Nasby, Database Architect jim@nasby.net
512.569.9461 (cell) http://jim.nasby.net

#4Nikhil Sontakke
nikkhils@gmail.com
In reply to: Jim Nasby (#3)
Re: how to create a non-inherited CHECK constraint in CREATE TABLE

It appears that the only way to create a non-inherited CHECK constraint
is using ALTER TABLE. Is there no support in CREATE TABLE planned?
That looks a bit odd.

There are no plans to do that AFAIR, though maybe you could convince
Nikhil to write the patch to do so.

That certainly doesn't meet the principle of least surprise... CREATE
TABLE should support this.

Well, the above was thought about during the original discussion and
eventually we felt that CREATE TABLE already has other issues as well, so
not having this done as part of creating a table was considered acceptable
then:

http://postgresql.1045698.n5.nabble.com/Check-constraints-on-partition-parents-only-tt4633334.html#a4647144

But, let me have a stab at it when I get some free cycles.

Regards,
Nikhils

#5Robert Haas
robertmhaas@gmail.com
In reply to: Nikhil Sontakke (#4)
Re: how to create a non-inherited CHECK constraint in CREATE TABLE

On Wed, Jan 18, 2012 at 12:10 AM, Nikhil Sontakke <nikkhils@gmail.com> wrote:

It appears that the only way to create a non-inherited CHECK constraint
is using ALTER TABLE.  Is there no support in CREATE TABLE planned?
That looks a bit odd.

There are no plans to do that AFAIR, though maybe you could convince
Nikhil to write the patch to do so.

That certainly doesn't meet the principle of least surprise... CREATE
TABLE should support this.

Well, the above was thought about during the original discussion and
eventually we felt that CREATE TABLE already has other issues as well, so
not having this done as part of creating a table was considered acceptable
then:

http://postgresql.1045698.n5.nabble.com/Check-constraints-on-partition-parents-only-tt4633334.html#a4647144

But, let me have a stab at it when I get some free cycles.

I agree with Peter that we should have we should have CHECK ONLY.
ONLY is really a property of the constraint, not the ALTER TABLE
command -- if it were otherwise, we wouldn't need to store it the
system catalogs, but of course we do. The fact that it's not a
standard property isn't a reason not to have proper syntax for it.

--
Robert Haas
EnterpriseDB: http://www.enterprisedb.com
The Enterprise PostgreSQL Company

#6Peter Eisentraut
peter_e@gmx.net
In reply to: Robert Haas (#5)
Re: how to create a non-inherited CHECK constraint in CREATE TABLE

On ons, 2012-01-18 at 18:17 -0500, Robert Haas wrote:

I agree with Peter that we should have we should have CHECK ONLY.
ONLY is really a property of the constraint, not the ALTER TABLE
command -- if it were otherwise, we wouldn't need to store it the
system catalogs, but of course we do. The fact that it's not a
standard property isn't a reason not to have proper syntax for it.

Clearly, we will eventually want to support inherited and non-inherited
constraints of all types. Currently, each type of constraint has an
implicit default regarding this property:

check - inherited
not null - inherited
foreign key - not inherited
primary key - not inherited
unique - not inherited
exclusion - not inherited

As discussed above, we need to have a syntax that is attached to the
constraint, not the table operation that creates the constraint, so that
we can also create these in CREATE TABLE.

How should we resolve these different defaults?

Also, in ALTER TABLE, if you want to add either an inherited or not
inherited constraint to a parent table, you should really say ALTER
TABLE ONLY in either case. Because it's conceivably valid that ALTER
TABLE foo ADD CHECK () NOINHERIT would add an independent, not inherited
check constraint to each child table.

So, there are all kinds of inconsistencies and backward compatibility
problems lurking here. We might need either a grand transition plan or
document the heck out of these inconsistencies.

#7Nikhil Sontakke
nikkhils@gmail.com
In reply to: Peter Eisentraut (#6)
1 attachment(s)
Re: how to create a non-inherited CHECK constraint in CREATE TABLE

Hi,

So, I have a patch for this. This patch introduces support for

CHECK ONLY syntax while doing a CREATE TABLE as well as during the usual
ALTER TABLE command.

Example:

create table atacc7 (test int, test2 int CHECK ONLY (test>0), CHECK
(test2>10));
create table atacc8 () inherits (atacc7);

postgres=# \d+ atacc7
Table "public.atacc7"
Column | Type | Modifiers | Storage | Description
--------+---------+-----------+---------+-------------
test | integer | | plain |
test2 | integer | | plain |
Check constraints:
"atacc7_test2_check" CHECK (test2 > 10)
"atacc7_test_check" CHECK ONLY (test > 0)
Child tables: atacc8
Has OIDs: no

postgres=# \d+ atacc8
Table "public.atacc8"
Column | Type | Modifiers | Storage | Description
--------+---------+-----------+---------+-------------
test | integer | | plain |
test2 | integer | | plain |
Check constraints:
"atacc7_test2_check" CHECK (test2 > 10)
Inherits: atacc7
Has OIDs: no

This patch removes the support for :

ALTER TABLE ONLY constraint_rename_test ADD CONSTRAINT con2 CHECK (b > 0);

and uses

ALTER TABLE constraint_rename_test ADD CONSTRAINT con2 CHECK ONLY (b > 0);

Is this what we want? Or we would want the earlier support in place for
backward compatibility as well? We are actually introducing this in 9.2 so
I guess we can remove this.

This is a much cleaner implementation and we might not even need the
changes in pg_dump now because the pg_get_constraintdef can provide the
info about the ONLY part too. So some cleanup can be done if needed.

I know it's a bit late in the commitfest, but if this patch makes this
feature more "complete", maybe we should consider...

Thoughts?

P.S Here's the discussion thread in its entirety for reference:
http://postgresql.1045698.n5.nabble.com/how-to-create-a-non-inherited-CHECK-constraint-in-CREATE-TABLE-td5152184.html

Regards,
Nikhils

On Thu, Feb 2, 2012 at 1:32 AM, Peter Eisentraut
<peter_e@gmx.net> wrote:

Show quoted text

On ons, 2012-01-18 at 18:17 -0500, Robert Haas wrote:

I agree with Peter that we should have we should have CHECK ONLY.
ONLY is really a property of the constraint, not the ALTER TABLE
command -- if it were otherwise, we wouldn't need to store it the
system catalogs, but of course we do. The fact that it's not a
standard property isn't a reason not to have proper syntax for it.

Clearly, we will eventually want to support inherited and non-inherited
constraints of all types. Currently, each type of constraint has an
implicit default regarding this property:

check - inherited
not null - inherited
foreign key - not inherited
primary key - not inherited
unique - not inherited
exclusion - not inherited

As discussed above, we need to have a syntax that is attached to the
constraint, not the table operation that creates the constraint, so that
we can also create these in CREATE TABLE.

How should we resolve these different defaults?

Also, in ALTER TABLE, if you want to add either an inherited or not
inherited constraint to a parent table, you should really say ALTER
TABLE ONLY in either case. Because it's conceivably valid that ALTER
TABLE foo ADD CHECK () NOINHERIT would add an independent, not inherited
check constraint to each child table.

So, there are all kinds of inconsistencies and backward compatibility
problems lurking here. We might need either a grand transition plan or
document the heck out of these inconsistencies.

Attachments:

check_constraint_create_table_support.patchapplication/octet-stream; name=check_constraint_create_table_support.patchDownload
diff --git a/doc/src/sgml/ref/alter_table.sgml b/doc/src/sgml/ref/alter_table.sgml
index c3039c8..b36ddbf 100644
--- a/doc/src/sgml/ref/alter_table.sgml
+++ b/doc/src/sgml/ref/alter_table.sgml
@@ -1013,7 +1013,7 @@ ALTER TABLE distributors ADD CONSTRAINT zipchk CHECK (char_length(zipcode) = 5);
   <para>
    To add a check constraint only to a table and not to its children:
 <programlisting>
-ALTER TABLE ONLY distributors ADD CONSTRAINT zipchk CHECK (char_length(zipcode) = 5);
+ALTER TABLE distributors ADD CONSTRAINT zipchk CHECK ONLY (char_length(zipcode) = 5);
 </programlisting>
    (The check constraint will not be inherited by future children, either.)
   </para>
diff --git a/src/backend/catalog/heap.c b/src/backend/catalog/heap.c
index 8bd5a92..e15c8aa 100644
--- a/src/backend/catalog/heap.c
+++ b/src/backend/catalog/heap.c
@@ -2036,8 +2036,7 @@ AddRelationNewConstraints(Relation rel,
 						  List *newColDefaults,
 						  List *newConstraints,
 						  bool allow_merge,
-						  bool is_local,
-						  bool is_only)
+						  bool is_local)
 {
 	List	   *cookedConstraints = NIL;
 	TupleDesc	tupleDesc;
@@ -2110,7 +2109,7 @@ AddRelationNewConstraints(Relation rel,
 		cooked->skip_validation = false;
 		cooked->is_local = is_local;
 		cooked->inhcount = is_local ? 0 : 1;
-		cooked->is_only = is_only;
+		cooked->is_only = false;
 		cookedConstraints = lappend(cookedConstraints, cooked);
 	}
 
@@ -2178,7 +2177,7 @@ AddRelationNewConstraints(Relation rel,
 			 * what ATAddCheckConstraint wants.)
 			 */
 			if (MergeWithExistingConstraint(rel, ccname, expr,
-								allow_merge, is_local, is_only))
+								allow_merge, is_local, cdef->is_only))
 				continue;
 		}
 		else
@@ -2225,7 +2224,7 @@ AddRelationNewConstraints(Relation rel,
 		 * OK, store it.
 		 */
 		StoreRelCheck(rel, ccname, expr, !cdef->skip_validation, is_local,
-					  is_local ? 0 : 1, is_only);
+					  is_local ? 0 : 1, cdef->is_only);
 
 		numchecks++;
 
@@ -2237,7 +2236,7 @@ AddRelationNewConstraints(Relation rel,
 		cooked->skip_validation = cdef->skip_validation;
 		cooked->is_local = is_local;
 		cooked->inhcount = is_local ? 0 : 1;
-		cooked->is_only = is_only;
+		cooked->is_only = cdef->is_only;
 		cookedConstraints = lappend(cookedConstraints, cooked);
 	}
 
diff --git a/src/backend/commands/tablecmds.c b/src/backend/commands/tablecmds.c
index a4a3604..0c1aa0d 100644
--- a/src/backend/commands/tablecmds.c
+++ b/src/backend/commands/tablecmds.c
@@ -661,7 +661,7 @@ DefineRelation(CreateStmt *stmt, char relkind, Oid ownerId)
 	 */
 	if (rawDefaults || stmt->constraints)
 		AddRelationNewConstraints(rel, rawDefaults, stmt->constraints,
-								  true, true, false);
+								  true, true);
 
 	/*
 	 * Clean up.  We keep lock on new relation (although it shouldn't be
@@ -4573,7 +4573,7 @@ ATExecAddColumn(List **wqueue, AlteredTableInfo *tab, Relation rel,
 		 * This function is intended for CREATE TABLE, so it processes a
 		 * _list_ of defaults, but we just do one.
 		 */
-		AddRelationNewConstraints(rel, list_make1(rawEnt), NIL, false, true, false);
+		AddRelationNewConstraints(rel, list_make1(rawEnt), NIL, false, true);
 
 		/* Make the additional catalog changes visible */
 		CommandCounterIncrement();
@@ -5015,7 +5015,7 @@ ATExecColumnDefault(Relation rel, const char *colName,
 		 * This function is intended for CREATE TABLE, so it processes a
 		 * _list_ of defaults, but we just do one.
 		 */
-		AddRelationNewConstraints(rel, list_make1(rawEnt), NIL, false, true, false);
+		AddRelationNewConstraints(rel, list_make1(rawEnt), NIL, false, true);
 	}
 }
 
@@ -5680,16 +5680,11 @@ ATAddCheckConstraint(List **wqueue, AlteredTableInfo *tab, Relation rel,
 	 * omitted from the returned list, which is what we want: we do not need
 	 * to do any validation work.  That can only happen at child tables,
 	 * though, since we disallow merging at the top level.
-	 *
-	 * Note: we set is_only based on the recurse flag which is false when
-	 * interpretInhOption() of our statement returns false all the way up
-	 * in AlterTable and gets passed all the way down to here.
 	 */
 	newcons = AddRelationNewConstraints(rel, NIL,
 										list_make1(copyObject(constr)),
-										recursing, /* allow_merge */
-										!recursing, /* is_local */
-										!recurse && !recursing); /* is_only */
+										recursing,   /* allow_merge */
+										!recursing); /* is_local */
 
 	/* Add each to-be-validated constraint to Phase 3's queue */
 	foreach(lcon, newcons)
@@ -5732,8 +5727,17 @@ ATAddCheckConstraint(List **wqueue, AlteredTableInfo *tab, Relation rel,
 	/*
 	 * Adding an ONLY constraint? No need to find our children
 	 */
-	if (!recurse && !recursing)
+	if (constr->is_only)
 		return;
+	/*
+	 * Check if ONLY was specified with ALTER TABLE and not as part of the
+	 * CHECK constraint. Error out if so
+	 */
+	if (!recurse && !recursing && !constr->is_only)
+		ereport(ERROR,
+				(errcode(ERRCODE_SYNTAX_ERROR),
+				 errmsg("specify ONLY as part of the CHECK constraint definition"
+				 " to create non-inheritable constraints")));
 
 	/*
 	 * Propagate to children as appropriate.  Unlike most other ALTER
diff --git a/src/backend/nodes/copyfuncs.c b/src/backend/nodes/copyfuncs.c
index c94799b..9ccdd16 100644
--- a/src/backend/nodes/copyfuncs.c
+++ b/src/backend/nodes/copyfuncs.c
@@ -2339,6 +2339,7 @@ _copyConstraint(const Constraint *from)
 	COPY_SCALAR_FIELD(deferrable);
 	COPY_SCALAR_FIELD(initdeferred);
 	COPY_LOCATION_FIELD(location);
+	COPY_SCALAR_FIELD(is_only);
 	COPY_NODE_FIELD(raw_expr);
 	COPY_STRING_FIELD(cooked_expr);
 	COPY_NODE_FIELD(keys);
diff --git a/src/backend/nodes/equalfuncs.c b/src/backend/nodes/equalfuncs.c
index 9564210..4f89bc0 100644
--- a/src/backend/nodes/equalfuncs.c
+++ b/src/backend/nodes/equalfuncs.c
@@ -2194,6 +2194,7 @@ _equalConstraint(const Constraint *a, const Constraint *b)
 	COMPARE_SCALAR_FIELD(deferrable);
 	COMPARE_SCALAR_FIELD(initdeferred);
 	COMPARE_LOCATION_FIELD(location);
+	COMPARE_SCALAR_FIELD(is_only);
 	COMPARE_NODE_FIELD(raw_expr);
 	COMPARE_STRING_FIELD(cooked_expr);
 	COMPARE_NODE_FIELD(keys);
diff --git a/src/backend/nodes/outfuncs.c b/src/backend/nodes/outfuncs.c
index 594b3fd..e2a38ae 100644
--- a/src/backend/nodes/outfuncs.c
+++ b/src/backend/nodes/outfuncs.c
@@ -2580,6 +2580,7 @@ _outConstraint(StringInfo str, const Constraint *node)
 
 		case CONSTR_CHECK:
 			appendStringInfo(str, "CHECK");
+			WRITE_BOOL_FIELD(is_only);
 			WRITE_NODE_FIELD(raw_expr);
 			WRITE_STRING_FIELD(cooked_expr);
 			break;
diff --git a/src/backend/parser/gram.y b/src/backend/parser/gram.y
index ae1658a..67d6d49 100644
--- a/src/backend/parser/gram.y
+++ b/src/backend/parser/gram.y
@@ -420,7 +420,7 @@ static void processCASbits(int cas_bits, int location, const char *constrType,
 %type <str>		character
 %type <str>		extract_arg
 %type <str>		opt_charset
-%type <boolean> opt_varying opt_timezone
+%type <boolean> opt_varying opt_timezone opt_only
 
 %type <ival>	Iconst SignedIconst
 %type <str>		Sconst comment_text notify_payload
@@ -2685,12 +2685,13 @@ ColConstraintElem:
 					n->indexspace = $4;
 					$$ = (Node *)n;
 				}
-			| CHECK '(' a_expr ')'
+			| CHECK opt_only '(' a_expr ')'
 				{
 					Constraint *n = makeNode(Constraint);
 					n->contype = CONSTR_CHECK;
 					n->location = @1;
-					n->raw_expr = $3;
+					n->is_only = $2;
+					n->raw_expr = $4;
 					n->cooked_expr = NULL;
 					$$ = (Node *)n;
 				}
@@ -2720,6 +2721,7 @@ ColConstraintElem:
 				}
 		;
 
+
 /*
  * ConstraintAttr represents constraint attributes, which we parse as if
  * they were independent constraint clauses, in order to avoid shift/reduce
@@ -2810,14 +2812,15 @@ TableConstraint:
 		;
 
 ConstraintElem:
-			CHECK '(' a_expr ')' ConstraintAttributeSpec
+			CHECK opt_only '(' a_expr ')' ConstraintAttributeSpec
 				{
 					Constraint *n = makeNode(Constraint);
 					n->contype = CONSTR_CHECK;
 					n->location = @1;
-					n->raw_expr = $3;
+					n->is_only = $2;
+					n->raw_expr = $4;
 					n->cooked_expr = NULL;
-					processCASbits($5, @5, "CHECK",
+					processCASbits($6, @6, "CHECK",
 								   NULL, NULL, &n->skip_validation,
 								   yyscanner);
 					n->initially_valid = !n->skip_validation;
@@ -2920,6 +2923,10 @@ ConstraintElem:
 				}
 		;
 
+opt_only:	ONLY									{  $$ = TRUE; }
+			| /* EMPTY */							{  $$ = FALSE; }
+		;
+
 opt_column_list:
 			'(' columnList ')'						{ $$ = $2; }
 			| /*EMPTY*/								{ $$ = NIL; }
diff --git a/src/backend/utils/adt/ruleutils.c b/src/backend/utils/adt/ruleutils.c
index 64ba8ec..bcd770d 100644
--- a/src/backend/utils/adt/ruleutils.c
+++ b/src/backend/utils/adt/ruleutils.c
@@ -1337,10 +1337,13 @@ pg_get_constraintdef_worker(Oid constraintId, bool fullCommand,
 				 * we don't need the outer parens ... but there are other
 				 * cases where we do need 'em.  Be conservative for now.
 				 *
+				 * Also add ONLY if is_only is true
+				 *
 				 * Note that simply checking for leading '(' and trailing ')'
 				 * would NOT be good enough, consider "(x > 0) AND (y > 0)".
 				 */
-				appendStringInfo(&buf, "CHECK (%s)", consrc);
+				appendStringInfo(&buf, "CHECK%s(%s)",
+								 conForm->conisonly? " ONLY ":" ", consrc);
 
 				break;
 			}
diff --git a/src/bin/pg_dump/pg_dump.c b/src/bin/pg_dump/pg_dump.c
index db56910..9b3aeaf 100644
--- a/src/bin/pg_dump/pg_dump.c
+++ b/src/bin/pg_dump/pg_dump.c
@@ -6089,10 +6089,9 @@ getTableAttrs(Archive *fout, TableInfo *tblinfo, int numTables)
 				/*
 				 * An unvalidated constraint needs to be dumped separately, so
 				 * that potentially-violating existing data is loaded before
-				 * the constraint.  An ONLY constraint needs to be dumped
-				 * separately too.
+				 * the constraint.
 				 */
-				constrs[j].separate = !validated || isonly;
+				constrs[j].separate = !validated;
 
 				constrs[j].dobj.dump = tbinfo->dobj.dump;
 
@@ -13048,9 +13047,9 @@ dumpConstraint(Archive *fout, ConstraintInfo *coninfo)
 		/* Ignore if not to be dumped separately */
 		if (coninfo->separate)
 		{
-			/* add ONLY if we do not want it to propagate to children */
-			appendPQExpBuffer(q, "ALTER TABLE %s %s\n",
-							 coninfo->conisonly ? "ONLY" : "", fmtId(tbinfo->dobj.name));
+			/* not ONLY since we want it to propagate to children */
+			appendPQExpBuffer(q, "ALTER TABLE %s\n",
+							  fmtId(tbinfo->dobj.name));
 			appendPQExpBuffer(q, "    ADD CONSTRAINT %s %s;\n",
 							  fmtId(coninfo->dobj.name),
 							  coninfo->condef);
diff --git a/src/bin/psql/describe.c b/src/bin/psql/describe.c
index 844a291..d39c9c5 100644
--- a/src/bin/psql/describe.c
+++ b/src/bin/psql/describe.c
@@ -1812,9 +1812,8 @@ describeOneTableDetails(const char *schemaname,
 				for (i = 0; i < tuples; i++)
 				{
 					/* untranslated contraint name and def */
-					printfPQExpBuffer(&buf, "    \"%s\"%s%s",
+					printfPQExpBuffer(&buf, "    \"%s\" %s",
 									  PQgetvalue(result, i, 0),
-									  (strcmp(PQgetvalue(result, i, 1), "t") == 0) ? " (ONLY) ":" ",
 									  PQgetvalue(result, i, 2));
 
 					printTableAddFooter(&cont, buf.data);
diff --git a/src/include/catalog/heap.h b/src/include/catalog/heap.h
index 2055382..a1b565b 100644
--- a/src/include/catalog/heap.h
+++ b/src/include/catalog/heap.h
@@ -92,8 +92,7 @@ extern List *AddRelationNewConstraints(Relation rel,
 						  List *newColDefaults,
 						  List *newConstraints,
 						  bool allow_merge,
-						  bool is_local,
-						  bool is_only);
+						  bool is_local);
 
 extern void StoreAttrDefault(Relation rel, AttrNumber attnum, Node *expr);
 
diff --git a/src/include/nodes/parsenodes.h b/src/include/nodes/parsenodes.h
index aaa950d..6583b17 100644
--- a/src/include/nodes/parsenodes.h
+++ b/src/include/nodes/parsenodes.h
@@ -1528,6 +1528,7 @@ typedef struct Constraint
 	int			location;		/* token location, or -1 if unknown */
 
 	/* Fields used for constraints with expressions (CHECK and DEFAULT): */
+	bool		is_only;		/* is constraint non-inheritable? */
 	Node	   *raw_expr;		/* expr, as untransformed parse tree */
 	char	   *cooked_expr;	/* expr, as nodeToString representation */
 
diff --git a/src/test/regress/expected/alter_table.out b/src/test/regress/expected/alter_table.out
index eba0493..464ff74 100644
--- a/src/test/regress/expected/alter_table.out
+++ b/src/test/regress/expected/alter_table.out
@@ -235,7 +235,7 @@ Check constraints:
     "con1foo" CHECK (a > 0)
 Inherits: constraint_rename_test
 
-ALTER TABLE ONLY constraint_rename_test ADD CONSTRAINT con2 CHECK (b > 0);
+ALTER TABLE constraint_rename_test ADD CONSTRAINT con2 CHECK ONLY (b > 0);
 ALTER TABLE ONLY constraint_rename_test RENAME CONSTRAINT con2 TO con2foo; -- ok
 ALTER TABLE constraint_rename_test RENAME CONSTRAINT con2foo TO con2bar; -- ok
 \d constraint_rename_test
@@ -246,7 +246,7 @@ Table "public.constraint_rename_test"
  b      | integer | 
  c      | integer | 
 Check constraints:
-    "con2bar" (ONLY) CHECK (b > 0)
+    "con2bar" CHECK ONLY (b > 0)
     "con1foo" CHECK (a > 0)
 Number of child tables: 1 (Use \d+ to list them.)
 
@@ -275,7 +275,7 @@ Table "public.constraint_rename_test"
 Indexes:
     "con3foo" PRIMARY KEY, btree (a)
 Check constraints:
-    "con2bar" (ONLY) CHECK (b > 0)
+    "con2bar" CHECK ONLY (b > 0)
     "con1foo" CHECK (a > 0)
 Number of child tables: 1 (Use \d+ to list them.)
 
@@ -643,7 +643,7 @@ drop table atacc1;
 create table atacc1 (test int);
 create table atacc2 (test2 int) inherits (atacc1);
 -- ok:
-alter table only atacc1 add constraint foo check (test>0);
+alter table atacc1 add constraint foo check only (test>0);
 -- check constraint is not there on child
 insert into atacc2 (test) values (-3);
 -- check constraint is there on parent
@@ -652,7 +652,7 @@ ERROR:  new row for relation "atacc1" violates check constraint "foo"
 DETAIL:  Failing row contains (-3).
 insert into atacc1 (test) values (3);
 -- fail, violating row:
-alter table only atacc2 add constraint foo check (test>0);
+alter table atacc2 add constraint foo check only (test>0);
 ERROR:  check constraint "foo" is violated by some row
 drop table atacc2;
 drop table atacc1;
diff --git a/src/test/regress/expected/inherit.out b/src/test/regress/expected/inherit.out
index d8f20e8c..d1f7b5d 100644
--- a/src/test/regress/expected/inherit.out
+++ b/src/test/regress/expected/inherit.out
@@ -598,7 +598,7 @@ select * from d;
 
 -- Test non-inheritable parent constraints
 create table p1(ff1 int);
-alter table only p1 add constraint p1chk check (ff1 > 0);
+alter table p1 add constraint p1chk check only (ff1 > 0);
 alter table p1 add constraint p2chk check (ff1 > 10);
 -- conisonly should be true for ONLY constraint
 select pc.relname, pgc.conname, pgc.contype, pgc.conislocal, pgc.coninhcount, pgc.conisonly from pg_class as pc inner join pg_constraint as pgc on (pgc.conrelid = pc.oid) where pc.relname = 'p1' order by 1,2;
@@ -616,7 +616,7 @@ create table c1 () inherits (p1);
 --------+---------+-----------
  ff1    | integer | 
 Check constraints:
-    "p1chk" (ONLY) CHECK (ff1 > 0)
+    "p1chk" CHECK ONLY (ff1 > 0)
     "p2chk" CHECK (ff1 > 10)
 Number of child tables: 1 (Use \d+ to list them.)
 
diff --git a/src/test/regress/input/constraints.source b/src/test/regress/input/constraints.source
index b84d51e..9eb1a29 100644
--- a/src/test/regress/input/constraints.source
+++ b/src/test/regress/input/constraints.source
@@ -144,6 +144,34 @@ SELECT * FROM INSERT_CHILD;
 DROP TABLE INSERT_CHILD;
 
 --
+-- Check ONLY type of constraints and inheritance
+--
+
+CREATE TABLE ATACC1 (TEST INT
+	CHECK ONLY (TEST > 0));
+
+CREATE TABLE ATACC2 (TEST2 INT) INHERITS (ATACC1);
+-- check constraint is not there on child
+INSERT INTO ATACC2 (TEST) VALUES (-3);
+-- check constraint is there on parent
+INSERT INTO ATACC1 (TEST) VALUES (-3);
+DROP TABLE ATACC1 CASCADE;
+
+CREATE TABLE ATACC1 (TEST INT, TEST2 INT
+	CHECK (TEST > 0), CHECK ONLY (TEST2 > 10));
+
+CREATE TABLE ATACC2 () INHERITS (ATACC1);
+-- check constraint is there on child
+INSERT INTO ATACC2 (TEST) VALUES (-3);
+-- check constraint is there on parent
+INSERT INTO ATACC1 (TEST) VALUES (-3);
+-- check constraint is not there on child
+INSERT INTO ATACC2 (TEST2) VALUES (3);
+-- check constraint is there on parent
+INSERT INTO ATACC1 (TEST2) VALUES (3);
+DROP TABLE ATACC1 CASCADE;
+
+--
 -- Check constraints on INSERT INTO
 --
 
diff --git a/src/test/regress/output/constraints.source b/src/test/regress/output/constraints.source
index 3e02e8d..dc0adee 100644
--- a/src/test/regress/output/constraints.source
+++ b/src/test/regress/output/constraints.source
@@ -228,6 +228,39 @@ SELECT * FROM INSERT_CHILD;
 
 DROP TABLE INSERT_CHILD;
 --
+-- Check ONLY type of constraints and inheritance
+--
+CREATE TABLE ATACC1 (TEST INT
+	CHECK ONLY (TEST > 0));
+CREATE TABLE ATACC2 (TEST2 INT) INHERITS (ATACC1);
+-- check constraint is not there on child
+INSERT INTO ATACC2 (TEST) VALUES (-3);
+-- check constraint is there on parent
+INSERT INTO ATACC1 (TEST) VALUES (-3);
+ERROR:  new row for relation "atacc1" violates check constraint "atacc1_test_check"
+DETAIL:  Failing row contains (-3).
+DROP TABLE ATACC1 CASCADE;
+NOTICE:  drop cascades to table atacc2
+CREATE TABLE ATACC1 (TEST INT, TEST2 INT
+	CHECK (TEST > 0), CHECK ONLY (TEST2 > 10));
+CREATE TABLE ATACC2 () INHERITS (ATACC1);
+-- check constraint is there on child
+INSERT INTO ATACC2 (TEST) VALUES (-3);
+ERROR:  new row for relation "atacc2" violates check constraint "atacc1_test_check"
+DETAIL:  Failing row contains (-3, null).
+-- check constraint is there on parent
+INSERT INTO ATACC1 (TEST) VALUES (-3);
+ERROR:  new row for relation "atacc1" violates check constraint "atacc1_test_check"
+DETAIL:  Failing row contains (-3, null).
+-- check constraint is not there on child
+INSERT INTO ATACC2 (TEST2) VALUES (3);
+-- check constraint is there on parent
+INSERT INTO ATACC1 (TEST2) VALUES (3);
+ERROR:  new row for relation "atacc1" violates check constraint "atacc1_test2_check"
+DETAIL:  Failing row contains (null, 3).
+DROP TABLE ATACC1 CASCADE;
+NOTICE:  drop cascades to table atacc2
+--
 -- Check constraints on INSERT INTO
 --
 DELETE FROM INSERT_TBL;
diff --git a/src/test/regress/sql/alter_table.sql b/src/test/regress/sql/alter_table.sql
index 50c58d2..9edb2df 100644
--- a/src/test/regress/sql/alter_table.sql
+++ b/src/test/regress/sql/alter_table.sql
@@ -218,7 +218,7 @@ ALTER TABLE ONLY constraint_rename_test RENAME CONSTRAINT con1 TO con1foo; -- fa
 ALTER TABLE constraint_rename_test RENAME CONSTRAINT con1 TO con1foo; -- ok
 \d constraint_rename_test
 \d constraint_rename_test2
-ALTER TABLE ONLY constraint_rename_test ADD CONSTRAINT con2 CHECK (b > 0);
+ALTER TABLE constraint_rename_test ADD CONSTRAINT con2 CHECK ONLY (b > 0);
 ALTER TABLE ONLY constraint_rename_test RENAME CONSTRAINT con2 TO con2foo; -- ok
 ALTER TABLE constraint_rename_test RENAME CONSTRAINT con2foo TO con2bar; -- ok
 \d constraint_rename_test
@@ -500,14 +500,14 @@ drop table atacc1;
 create table atacc1 (test int);
 create table atacc2 (test2 int) inherits (atacc1);
 -- ok:
-alter table only atacc1 add constraint foo check (test>0);
+alter table atacc1 add constraint foo check only (test>0);
 -- check constraint is not there on child
 insert into atacc2 (test) values (-3);
 -- check constraint is there on parent
 insert into atacc1 (test) values (-3);
 insert into atacc1 (test) values (3);
 -- fail, violating row:
-alter table only atacc2 add constraint foo check (test>0);
+alter table atacc2 add constraint foo check only (test>0);
 drop table atacc2;
 drop table atacc1;
 
diff --git a/src/test/regress/sql/inherit.sql b/src/test/regress/sql/inherit.sql
index eec8192..44eda8a 100644
--- a/src/test/regress/sql/inherit.sql
+++ b/src/test/regress/sql/inherit.sql
@@ -140,7 +140,7 @@ select * from d;
 
 -- Test non-inheritable parent constraints
 create table p1(ff1 int);
-alter table only p1 add constraint p1chk check (ff1 > 0);
+alter table p1 add constraint p1chk check only (ff1 > 0);
 alter table p1 add constraint p2chk check (ff1 > 10);
 -- conisonly should be true for ONLY constraint
 select pc.relname, pgc.conname, pgc.contype, pgc.conislocal, pgc.coninhcount, pgc.conisonly from pg_class as pc inner join pg_constraint as pgc on (pgc.conrelid = pc.oid) where pc.relname = 'p1' order by 1,2;
#8Alvaro Herrera
alvherre@commandprompt.com
In reply to: Nikhil Sontakke (#7)
Re: how to create a non-inherited CHECK constraint in CREATE TABLE

Excerpts from Nikhil Sontakke's message of mié abr 11 15:07:45 -0300 2012:

This patch removes the support for :

ALTER TABLE ONLY constraint_rename_test ADD CONSTRAINT con2 CHECK (b > 0);

and uses

ALTER TABLE constraint_rename_test ADD CONSTRAINT con2 CHECK ONLY (b > 0);

Is this what we want? Or we would want the earlier support in place for
backward compatibility as well? We are actually introducing this in 9.2 so
I guess we can remove this.

I'm not quite following that logic. I don't think support for the
previous syntax should be removed -- does it cause some serious problem?

This is a much cleaner implementation and we might not even need the
changes in pg_dump now because the pg_get_constraintdef can provide the
info about the ONLY part too. So some cleanup can be done if needed.

I know it's a bit late in the commitfest, but if this patch makes this
feature more "complete", maybe we should consider...

Thoughts?

Personally I don't think we should consider this for 9.2.

--
Álvaro Herrera <alvherre@commandprompt.com>
The PostgreSQL Company - Command Prompt, Inc.
PostgreSQL Replication, Consulting, Custom Development, 24x7 support

#9Tom Lane
tgl@sss.pgh.pa.us
In reply to: Alvaro Herrera (#8)
Re: how to create a non-inherited CHECK constraint in CREATE TABLE

Alvaro Herrera <alvherre@commandprompt.com> writes:

Excerpts from Nikhil Sontakke's message of mié abr 11 15:07:45 -0300 2012:

This patch removes the support for :

ALTER TABLE ONLY constraint_rename_test ADD CONSTRAINT con2 CHECK (b > 0);

and uses

ALTER TABLE constraint_rename_test ADD CONSTRAINT con2 CHECK ONLY (b > 0);

I know it's a bit late in the commitfest, but if this patch makes this
feature more "complete", maybe we should consider...

Personally I don't think we should consider this for 9.2.

Well, if we're going to regret having offered the other syntax, now
would be the time to figure that out, before we ship it not after.
I would go so far as to say that if we don't accept this for 9.2
we probably shouldn't accept it at all, because two different ways
to spell the same thing isn't nice.

I don't really care for the idea that the ONLY goes in a different place
for this operation than for every other kind of ALTER TABLE, but it does
make sense if you subscribe to the quoted theory that ONLY is a property
of the constraint and not the ALTER command as such.

regards, tom lane

#10Andrew Dunstan
andrew@dunslane.net
In reply to: Tom Lane (#9)
Re: how to create a non-inherited CHECK constraint in CREATE TABLE

On 04/11/2012 02:45 PM, Tom Lane wrote:

Alvaro Herrera<alvherre@commandprompt.com> writes:

Excerpts from Nikhil Sontakke's message of mié abr 11 15:07:45 -0300 2012:

This patch removes the support for :

ALTER TABLE ONLY constraint_rename_test ADD CONSTRAINT con2 CHECK (b> 0);

and uses

ALTER TABLE constraint_rename_test ADD CONSTRAINT con2 CHECK ONLY (b> 0);

I know it's a bit late in the commitfest, but if this patch makes this
feature more "complete", maybe we should consider...

Personally I don't think we should consider this for 9.2.

Well, if we're going to regret having offered the other syntax, now
would be the time to figure that out, before we ship it not after.
I would go so far as to say that if we don't accept this for 9.2
we probably shouldn't accept it at all, because two different ways
to spell the same thing isn't nice.

I don't really care for the idea that the ONLY goes in a different place
for this operation than for every other kind of ALTER TABLE, but it does
make sense if you subscribe to the quoted theory that ONLY is a property
of the constraint and not the ALTER command as such.

I think I rather dislike it. ONLY should be followed by the name of the
parent table whose children it causes us to exclude, IMNSHO. Moving it
elsewhere doesn't seem to me to be a blow for clarity at all.

cheers

andrew

#11Alvaro Herrera
alvherre@commandprompt.com
In reply to: Andrew Dunstan (#10)
Re: how to create a non-inherited CHECK constraint in CREATE TABLE

Excerpts from Andrew Dunstan's message of mié abr 11 15:51:51 -0300 2012:

On 04/11/2012 02:45 PM, Tom Lane wrote:

Alvaro Herrera<alvherre@commandprompt.com> writes:

Excerpts from Nikhil Sontakke's message of mié abr 11 15:07:45 -0300 2012:

This patch removes the support for :

ALTER TABLE ONLY constraint_rename_test ADD CONSTRAINT con2 CHECK (b> 0);

and uses

ALTER TABLE constraint_rename_test ADD CONSTRAINT con2 CHECK ONLY (b> 0);

I know it's a bit late in the commitfest, but if this patch makes this
feature more "complete", maybe we should consider...

Personally I don't think we should consider this for 9.2.

Well, if we're going to regret having offered the other syntax, now
would be the time to figure that out, before we ship it not after.
I would go so far as to say that if we don't accept this for 9.2
we probably shouldn't accept it at all, because two different ways
to spell the same thing isn't nice.

I don't really care for the idea that the ONLY goes in a different place
for this operation than for every other kind of ALTER TABLE, but it does
make sense if you subscribe to the quoted theory that ONLY is a property
of the constraint and not the ALTER command as such.

I think I rather dislike it. ONLY should be followed by the name of the
parent table whose children it causes us to exclude, IMNSHO. Moving it
elsewhere doesn't seem to me to be a blow for clarity at all.

If that's the only objection, maybe we could use a different keyword
then, perhaps NOINHERIT:

ALTER TABLE constraint_rename_test ADD CONSTRAINT con2 CHECK NOINHERIT (b> 0);

--
Álvaro Herrera <alvherre@commandprompt.com>
The PostgreSQL Company - Command Prompt, Inc.
PostgreSQL Replication, Consulting, Custom Development, 24x7 support

#12Tom Lane
tgl@sss.pgh.pa.us
In reply to: Alvaro Herrera (#11)
Re: how to create a non-inherited CHECK constraint in CREATE TABLE

Alvaro Herrera <alvherre@commandprompt.com> writes:

Excerpts from Andrew Dunstan's message of mié abr 11 15:51:51 -0300 2012:

On 04/11/2012 02:45 PM, Tom Lane wrote:

I don't really care for the idea that the ONLY goes in a different place
for this operation than for every other kind of ALTER TABLE, but it does
make sense if you subscribe to the quoted theory that ONLY is a property
of the constraint and not the ALTER command as such.

I think I rather dislike it. ONLY should be followed by the name of the
parent table whose children it causes us to exclude, IMNSHO. Moving it
elsewhere doesn't seem to me to be a blow for clarity at all.

If that's the only objection, maybe we could use a different keyword
then, perhaps NOINHERIT:

ALTER TABLE constraint_rename_test ADD CONSTRAINT con2 CHECK NOINHERIT (b> 0);

I could live with that. "CHECK ONLY" isn't particularly transparent as
to what it means, anyway. "CHECK NOINHERIT" seems a lot clearer.

I'd propose "CHECK NO INHERIT", though, as (a) it seems better English
and (b) it avoids creating any new keyword.

regards, tom lane

#13Andrew Dunstan
andrew@dunslane.net
In reply to: Tom Lane (#12)
Re: how to create a non-inherited CHECK constraint in CREATE TABLE

On 04/11/2012 03:06 PM, Tom Lane wrote:

I'd propose "CHECK NO INHERIT", though, as (a) it seems better English
and (b) it avoids creating any new keyword.

I could live with that too.

cheers

andrew

#14Robert Haas
robertmhaas@gmail.com
In reply to: Tom Lane (#9)
Re: how to create a non-inherited CHECK constraint in CREATE TABLE

On Wed, Apr 11, 2012 at 2:45 PM, Tom Lane <tgl@sss.pgh.pa.us> wrote:

Alvaro Herrera <alvherre@commandprompt.com> writes:

Excerpts from Nikhil Sontakke's message of mié abr 11 15:07:45 -0300 2012:

This patch removes the support for :

ALTER TABLE ONLY constraint_rename_test ADD CONSTRAINT con2 CHECK (b > 0);

and uses

ALTER TABLE constraint_rename_test ADD CONSTRAINT con2 CHECK ONLY (b > 0);

I know it's a bit late in the commitfest, but if this patch makes this
feature more "complete", maybe we should consider...

Personally I don't think we should consider this for 9.2.

Well, if we're going to regret having offered the other syntax, now
would be the time to figure that out, before we ship it not after.
I would go so far as to say that if we don't accept this for 9.2
we probably shouldn't accept it at all, because two different ways
to spell the same thing isn't nice.

+1 for fixing up the syntax before 9.2 goes out the door. I think the
original syntax was misguided to begin with.

CHECK NO INHERIT sounds fine to me; will that display ALTER TABLE ONLY
x as the one true way of doing this?

--
Robert Haas
EnterpriseDB: http://www.enterprisedb.com
The Enterprise PostgreSQL Company

#15Tom Lane
tgl@sss.pgh.pa.us
In reply to: Robert Haas (#14)
Re: how to create a non-inherited CHECK constraint in CREATE TABLE

Robert Haas <robertmhaas@gmail.com> writes:

+1 for fixing up the syntax before 9.2 goes out the door. I think the
original syntax was misguided to begin with.

Well, it was fine in isolation, but once you consider how to make CREATE
TABLE do this too, it's hard to avoid the conclusion that you need to
attach the modifier to the CHECK constraint not the ALTER TABLE command.

CHECK NO INHERIT sounds fine to me; will that display ALTER TABLE ONLY
x as the one true way of doing this?

s/display/displace/, I think you meant? Yeah, that's what I understand
the proposal to be.

regards, tom lane

#16Nikhil Sontakke
nikkhils@gmail.com
In reply to: Tom Lane (#15)
Re: how to create a non-inherited CHECK constraint in CREATE TABLE

Hi,

Cumulative reaction to all the responses first:

Whoa! :)

I was under the impression that a majority of us felt that the current
mechanism was inadequate. Also if you go through the nabble thread, the
fact that CREATE TABLE did not support such constraints was considered to
be an annoyance. And I was enquired if/when I can provide this
functionality. Apologies though with the timing.

+1 for fixing up the syntax before 9.2 goes out the door. I think the
original syntax was misguided to begin with.

Well, it was fine in isolation, but once you consider how to make CREATE
TABLE do this too, it's hard to avoid the conclusion that you need to
attach the modifier to the CHECK constraint not the ALTER TABLE command.

Yeah, exactly.

CHECK NO INHERIT sounds fine to me; will that display ALTER TABLE ONLY
x as the one true way of doing this?

s/display/displace/, I think you meant? Yeah, that's what I understand
the proposal to be.

Displace yes. It would error out if someone says

ALTER TABLE ONLY... CHECK ();

suggesting to use the ONLY with the CHECK.

This patch does this and also makes both CREATE TABLE and ALTER TABLE use
it in a uniform manner.

Regarding "NO INHERIT" versus "ONLY", we again have had discussions on the
longish original thread quite a while back:

http://postgresql.1045698.n5.nabble.com/Check-constraints-on-partition-parents-only-tt4633334.html

But now if we prefer NO INHERIT, I can live with that.

Regards,
Nikhils

#17Noah Misch
noah@leadboat.com
In reply to: Nikhil Sontakke (#16)
Re: how to create a non-inherited CHECK constraint in CREATE TABLE

On Thu, Apr 12, 2012 at 10:50:31AM +0530, Nikhil Sontakke wrote:

CHECK NO INHERIT sounds fine to me; will that display ALTER TABLE ONLY
x as the one true way of doing this?

s/display/displace/, I think you meant? Yeah, that's what I understand
the proposal to be.

+1 for that proposal.

Displace yes. It would error out if someone says

ALTER TABLE ONLY... CHECK ();

suggesting to use the ONLY with the CHECK.

I'd say the behavior for that case can revert to the PostgreSQL 9.1 behavior.
If the table has children, raise an error. Otherwise, add an inheritable
CHECK constraint, albeit one lacking inheritors at that moment.

Thanks,
nm

#18Nikhil Sontakke
nikkhils@gmail.com
In reply to: Noah Misch (#17)
Re: how to create a non-inherited CHECK constraint in CREATE TABLE

Displace yes. It would error out if someone says

ALTER TABLE ONLY... CHECK ();

suggesting to use the ONLY with the CHECK.

I'd say the behavior for that case can revert to the PostgreSQL 9.1
behavior.
If the table has children, raise an error. Otherwise, add an inheritable
CHECK constraint, albeit one lacking inheritors at that moment.

Ok, that sounds reasonable.

Another thing that we should consider is that if we are replacing ONLY with
NO INHERIT, then instead of just making a cosmetic syntactic change, we
should also replace all the is*only type of field names with noinherit for
the sake of completeness and uniformity.

Regards,
Nikhils

#19Alvaro Herrera
alvherre@commandprompt.com
In reply to: Nikhil Sontakke (#18)
Re: how to create a non-inherited CHECK constraint in CREATE TABLE

Excerpts from Nikhil Sontakke's message of lun abr 16 03:56:06 -0300 2012:

Displace yes. It would error out if someone says

ALTER TABLE ONLY... CHECK ();

suggesting to use the ONLY with the CHECK.

I'd say the behavior for that case can revert to the PostgreSQL 9.1
behavior.
If the table has children, raise an error. Otherwise, add an inheritable
CHECK constraint, albeit one lacking inheritors at that moment.

Ok, that sounds reasonable.

Good, I agree with that too.

Are you going to submit an updated patch? I started working on your
original a couple of days ago but got distracted by some family news
here. I'll send it to you so that you can start from there, to avoid
duplicate work.

Another thing that we should consider is that if we are replacing ONLY with
NO INHERIT, then instead of just making a cosmetic syntactic change, we
should also replace all the is*only type of field names with noinherit for
the sake of completeness and uniformity.

Yeah, I was considering the same thing. "conisonly" isn't a very good
name on its own (it only made sense because the ONLY came from "ALTER
TABLE ONLY").

--
Álvaro Herrera <alvherre@commandprompt.com>
The PostgreSQL Company - Command Prompt, Inc.
PostgreSQL Replication, Consulting, Custom Development, 24x7 support

#20Nikhil Sontakke
nikkhils@gmail.com
In reply to: Alvaro Herrera (#19)
1 attachment(s)
Re: how to create a non-inherited CHECK constraint in CREATE TABLE

Hi,

Are you going to submit an updated patch? I started working on your

original a couple of days ago but got distracted by some family news
here. I'll send it to you so that you can start from there, to avoid
duplicate work.

Thanks Alvaro. PFA, a revised patch with the "NO INHERIT" support in the
complete sense. I also fixed up the ALTER TABLE ONLY ... CHECK semantics as
per Noah's suggestion upthread. We now allow ONLY if the table has no
children currently. The pg_dump sources have also been cleaned up now that
these constraints need not be dumped separately. So this is a good change
overall.

Have used connoinherit as the name in the catalog and Alvaro replaced
is_only references with is_no_inherit so that stays. I leave it to the
eventual committer now to pick up any more variations if desired :)

Regards,
Nikhils

Attachments:

check_constraint_create_table_support_no_inherit_syntax.patchapplication/octet-stream; name=check_constraint_create_table_support_no_inherit_syntax.patchDownload
diff --git a/doc/src/sgml/ref/alter_table.sgml b/doc/src/sgml/ref/alter_table.sgml
index c3039c8..3af65ac 100644
--- a/doc/src/sgml/ref/alter_table.sgml
+++ b/doc/src/sgml/ref/alter_table.sgml
@@ -907,7 +907,8 @@ ALTER TABLE [ IF EXISTS ] <replaceable class="PARAMETER">name</replaceable>
     and <literal>TABLESPACE</> actions never recurse to descendant tables;
     that is, they always act as though <literal>ONLY</> were specified.
     Adding a constraint can recurse only for <literal>CHECK</> constraints,
-    and is required to do so for such constraints.
+    and is required to do so for such constraints, except those that are
+    explicitely marked <literal>NO INHERIT</>.
    </para>
 
    <para>
@@ -1013,7 +1014,7 @@ ALTER TABLE distributors ADD CONSTRAINT zipchk CHECK (char_length(zipcode) = 5);
   <para>
    To add a check constraint only to a table and not to its children:
 <programlisting>
-ALTER TABLE ONLY distributors ADD CONSTRAINT zipchk CHECK (char_length(zipcode) = 5);
+ALTER TABLE distributors ADD CONSTRAINT zipchk CHECK NO INHERIT (char_length(zipcode) = 5);
 </programlisting>
    (The check constraint will not be inherited by future children, either.)
   </para>
diff --git a/doc/src/sgml/ref/create_table.sgml b/doc/src/sgml/ref/create_table.sgml
index bb93214..4da6eea 100644
--- a/doc/src/sgml/ref/create_table.sgml
+++ b/doc/src/sgml/ref/create_table.sgml
@@ -47,7 +47,7 @@ CREATE [ [ GLOBAL | LOCAL ] { TEMPORARY | TEMP } | UNLOGGED ] TABLE [ IF NOT EXI
 [ CONSTRAINT <replaceable class="PARAMETER">constraint_name</replaceable> ]
 { NOT NULL |
   NULL |
-  CHECK ( <replaceable class="PARAMETER">expression</replaceable> ) |
+  CHECK [ NO INHERIT ] ( <replaceable class="PARAMETER">expression</replaceable> ) |
   DEFAULT <replaceable>default_expr</replaceable> |
   UNIQUE <replaceable class="PARAMETER">index_parameters</replaceable> |
   PRIMARY KEY <replaceable class="PARAMETER">index_parameters</replaceable> |
@@ -58,7 +58,7 @@ CREATE [ [ GLOBAL | LOCAL ] { TEMPORARY | TEMP } | UNLOGGED ] TABLE [ IF NOT EXI
 <phrase>and <replaceable class="PARAMETER">table_constraint</replaceable> is:</phrase>
 
 [ CONSTRAINT <replaceable class="PARAMETER">constraint_name</replaceable> ]
-{ CHECK ( <replaceable class="PARAMETER">expression</replaceable> ) |
+{ CHECK [ NO INHERIT ] ( <replaceable class="PARAMETER">expression</replaceable> ) |
   UNIQUE ( <replaceable class="PARAMETER">column_name</replaceable> [, ... ] ) <replaceable class="PARAMETER">index_parameters</replaceable> |
   PRIMARY KEY ( <replaceable class="PARAMETER">column_name</replaceable> [, ... ] ) <replaceable class="PARAMETER">index_parameters</replaceable> |
   EXCLUDE [ USING <replaceable class="parameter">index_method</replaceable> ] ( <replaceable class="parameter">exclude_element</replaceable> WITH <replaceable class="parameter">operator</replaceable> [, ... ] ) <replaceable class="parameter">index_parameters</replaceable> [ WHERE ( <replaceable class="parameter">predicate</replaceable> ) ] |
@@ -299,7 +299,8 @@ CREATE [ [ GLOBAL | LOCAL ] { TEMPORARY | TEMP } | UNLOGGED ] TABLE [ IF NOT EXI
       contain identically-named <literal>CHECK</> constraints, these
       constraints must all have the same check expression, or an error will be
       reported.  Constraints having the same name and expression will
-      be merged into one copy.  Notice that an unnamed <literal>CHECK</>
+      be merged into one copy.  A constraint marked <literal>NO INHERIT</> in a
+      parent will not be considered.  Notice that an unnamed <literal>CHECK</>
       constraint in the new table will never be merged, since a unique name
       will always be chosen for it.
      </para>
@@ -415,7 +416,7 @@ CREATE [ [ GLOBAL | LOCAL ] { TEMPORARY | TEMP } | UNLOGGED ] TABLE [ IF NOT EXI
    </varlistentry>
 
    <varlistentry>
-    <term><literal>CHECK ( <replaceable class="PARAMETER">expression</replaceable> )</literal></term>
+    <term><literal>CHECK [ NO INHERIT ] ( <replaceable class="PARAMETER">expression</replaceable> )</literal></term>
     <listitem>
      <para>
       The <literal>CHECK</> clause specifies an expression producing a
@@ -434,6 +435,11 @@ CREATE [ [ GLOBAL | LOCAL ] { TEMPORARY | TEMP } | UNLOGGED ] TABLE [ IF NOT EXI
       subqueries nor refer to variables other than columns of the
       current row.
      </para>
+
+     <para>
+      A constraint marked with <literal>NO INHERIT</> will not propagate to
+      children tables.
+     </para>
     </listitem>
    </varlistentry>
 
diff --git a/src/backend/catalog/heap.c b/src/backend/catalog/heap.c
index 8bd5a92..5ee6f31 100644
--- a/src/backend/catalog/heap.c
+++ b/src/backend/catalog/heap.c
@@ -92,10 +92,10 @@ static Oid AddNewRelationType(const char *typeName,
 				   Oid new_array_type);
 static void RelationRemoveInheritance(Oid relid);
 static void StoreRelCheck(Relation rel, char *ccname, Node *expr,
-			  bool is_validated, bool is_local, int inhcount, bool is_only);
+			  bool is_validated, bool is_local, int inhcount, bool is_no_inherit);
 static void StoreConstraints(Relation rel, List *cooked_constraints);
 static bool MergeWithExistingConstraint(Relation rel, char *ccname, Node *expr,
-							bool allow_merge, bool is_local, bool is_only);
+							bool allow_merge, bool is_local, bool is_no_inherit);
 static void SetRelationNumChecks(Relation rel, int numchecks);
 static Node *cookConstraint(ParseState *pstate,
 			   Node *raw_constraint,
@@ -1868,7 +1868,7 @@ StoreAttrDefault(Relation rel, AttrNumber attnum, Node *expr)
  */
 static void
 StoreRelCheck(Relation rel, char *ccname, Node *expr,
-			  bool is_validated, bool is_local, int inhcount, bool is_only)
+			  bool is_validated, bool is_local, int inhcount, bool is_no_inherit)
 {
 	char	   *ccbin;
 	char	   *ccsrc;
@@ -1952,7 +1952,7 @@ StoreRelCheck(Relation rel, char *ccname, Node *expr,
 						  ccsrc,	/* Source form of check constraint */
 						  is_local,		/* conislocal */
 						  inhcount,		/* coninhcount */
-						  is_only);		/* conisonly */
+						  is_no_inherit);		/* connoinherit */
 
 	pfree(ccbin);
 	pfree(ccsrc);
@@ -1993,7 +1993,7 @@ StoreConstraints(Relation rel, List *cooked_constraints)
 				break;
 			case CONSTR_CHECK:
 				StoreRelCheck(rel, con->name, con->expr, !con->skip_validation,
-							  con->is_local, con->inhcount, con->is_only);
+							  con->is_local, con->inhcount, con->is_no_inherit);
 				numchecks++;
 				break;
 			default:
@@ -2036,8 +2036,7 @@ AddRelationNewConstraints(Relation rel,
 						  List *newColDefaults,
 						  List *newConstraints,
 						  bool allow_merge,
-						  bool is_local,
-						  bool is_only)
+						  bool is_local)
 {
 	List	   *cookedConstraints = NIL;
 	TupleDesc	tupleDesc;
@@ -2110,7 +2109,7 @@ AddRelationNewConstraints(Relation rel,
 		cooked->skip_validation = false;
 		cooked->is_local = is_local;
 		cooked->inhcount = is_local ? 0 : 1;
-		cooked->is_only = is_only;
+		cooked->is_no_inherit = false;
 		cookedConstraints = lappend(cookedConstraints, cooked);
 	}
 
@@ -2178,7 +2177,8 @@ AddRelationNewConstraints(Relation rel,
 			 * what ATAddCheckConstraint wants.)
 			 */
 			if (MergeWithExistingConstraint(rel, ccname, expr,
-								allow_merge, is_local, is_only))
+											allow_merge, is_local,
+											cdef->is_no_inherit))
 				continue;
 		}
 		else
@@ -2225,7 +2225,7 @@ AddRelationNewConstraints(Relation rel,
 		 * OK, store it.
 		 */
 		StoreRelCheck(rel, ccname, expr, !cdef->skip_validation, is_local,
-					  is_local ? 0 : 1, is_only);
+					  is_local ? 0 : 1, cdef->is_no_inherit);
 
 		numchecks++;
 
@@ -2237,7 +2237,7 @@ AddRelationNewConstraints(Relation rel,
 		cooked->skip_validation = cdef->skip_validation;
 		cooked->is_local = is_local;
 		cooked->inhcount = is_local ? 0 : 1;
-		cooked->is_only = is_only;
+		cooked->is_no_inherit = cdef->is_no_inherit;
 		cookedConstraints = lappend(cookedConstraints, cooked);
 	}
 
@@ -2266,7 +2266,7 @@ AddRelationNewConstraints(Relation rel,
 static bool
 MergeWithExistingConstraint(Relation rel, char *ccname, Node *expr,
 							bool allow_merge, bool is_local,
-							bool is_only)
+							bool is_no_inherit)
 {
 	bool		found;
 	Relation	conDesc;
@@ -2322,8 +2322,8 @@ MergeWithExistingConstraint(Relation rel, char *ccname, Node *expr,
 			tup = heap_copytuple(tup);
 			con = (Form_pg_constraint) GETSTRUCT(tup);
 
-			/* If the constraint is "only" then cannot merge */
-			if (con->conisonly)
+			/* If the constraint is "no inherit" then cannot merge */
+			if (con->connoinherit)
 				ereport(ERROR,
 						(errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
 						 errmsg("constraint \"%s\" conflicts with non-inherited constraint on relation \"%s\"",
@@ -2333,10 +2333,10 @@ MergeWithExistingConstraint(Relation rel, char *ccname, Node *expr,
 				con->conislocal = true;
 			else
 				con->coninhcount++;
-			if (is_only)
+			if (is_no_inherit)
 			{
 				Assert(is_local);
-				con->conisonly = true;
+				con->connoinherit = true;
 			}
 			/* OK to update the tuple */
 			ereport(NOTICE,
diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c
index 3fd0e60..c1407de 100644
--- a/src/backend/catalog/index.c
+++ b/src/backend/catalog/index.c
@@ -1156,7 +1156,7 @@ index_constraint_create(Relation heapRelation,
 								   NULL,
 								   true,		/* islocal */
 								   0,			/* inhcount */
-								   false);		/* isonly */
+								   false);		/* isnoinherit */
 
 	/*
 	 * Register the index as internally dependent on the constraint.
diff --git a/src/backend/catalog/pg_constraint.c b/src/backend/catalog/pg_constraint.c
index bf174b6..dca5d09 100644
--- a/src/backend/catalog/pg_constraint.c
+++ b/src/backend/catalog/pg_constraint.c
@@ -67,7 +67,7 @@ CreateConstraintEntry(const char *constraintName,
 					  const char *conSrc,
 					  bool conIsLocal,
 					  int conInhCount,
-					  bool conIsOnly)
+					  bool conNoInherit)
 {
 	Relation	conDesc;
 	Oid			conOid;
@@ -170,7 +170,7 @@ CreateConstraintEntry(const char *constraintName,
 	values[Anum_pg_constraint_confmatchtype - 1] = CharGetDatum(foreignMatchType);
 	values[Anum_pg_constraint_conislocal - 1] = BoolGetDatum(conIsLocal);
 	values[Anum_pg_constraint_coninhcount - 1] = Int32GetDatum(conInhCount);
-	values[Anum_pg_constraint_conisonly - 1] = BoolGetDatum(conIsOnly);
+	values[Anum_pg_constraint_connoinherit - 1] = BoolGetDatum(conNoInherit);
 
 	if (conkeyArray)
 		values[Anum_pg_constraint_conkey - 1] = PointerGetDatum(conkeyArray);
diff --git a/src/backend/commands/tablecmds.c b/src/backend/commands/tablecmds.c
index a4a3604..d55afdc 100644
--- a/src/backend/commands/tablecmds.c
+++ b/src/backend/commands/tablecmds.c
@@ -601,7 +601,7 @@ DefineRelation(CreateStmt *stmt, char relkind, Oid ownerId)
 			cooked->skip_validation = false;
 			cooked->is_local = true;	/* not used for defaults */
 			cooked->inhcount = 0;		/* ditto */
-			cooked->is_only = false;
+			cooked->is_no_inherit = false;
 			cookedDefaults = lappend(cookedDefaults, cooked);
 			descriptor->attrs[attnum - 1]->atthasdef = true;
 		}
@@ -661,7 +661,7 @@ DefineRelation(CreateStmt *stmt, char relkind, Oid ownerId)
 	 */
 	if (rawDefaults || stmt->constraints)
 		AddRelationNewConstraints(rel, rawDefaults, stmt->constraints,
-								  true, true, false);
+								  true, true);
 
 	/*
 	 * Clean up.  We keep lock on new relation (although it shouldn't be
@@ -1655,7 +1655,7 @@ MergeAttributes(List *schema, List *supers, char relpersistence,
 				Node	   *expr;
 
 				/* ignore if the constraint is non-inheritable */
-				if (check[i].cconly)
+				if (check[i].ccnoinherit)
 					continue;
 
 				/* adjust varattnos of ccbin here */
@@ -1676,7 +1676,7 @@ MergeAttributes(List *schema, List *supers, char relpersistence,
 					cooked->skip_validation = false;
 					cooked->is_local = false;
 					cooked->inhcount = 1;
-					cooked->is_only = false;
+					cooked->is_no_inherit = false;
 					constraints = lappend(constraints, cooked);
 				}
 			}
@@ -2399,7 +2399,7 @@ rename_constraint_internal(Oid myrelid,
 			 constraintOid);
 	con = (Form_pg_constraint) GETSTRUCT(tuple);
 
-	if (myrelid && con->contype == CONSTRAINT_CHECK && !con->conisonly)
+	if (myrelid && con->contype == CONSTRAINT_CHECK && !con->connoinherit)
 	{
 		if (recurse)
 		{
@@ -4573,7 +4573,7 @@ ATExecAddColumn(List **wqueue, AlteredTableInfo *tab, Relation rel,
 		 * This function is intended for CREATE TABLE, so it processes a
 		 * _list_ of defaults, but we just do one.
 		 */
-		AddRelationNewConstraints(rel, list_make1(rawEnt), NIL, false, true, false);
+		AddRelationNewConstraints(rel, list_make1(rawEnt), NIL, false, true);
 
 		/* Make the additional catalog changes visible */
 		CommandCounterIncrement();
@@ -5015,7 +5015,7 @@ ATExecColumnDefault(Relation rel, const char *colName,
 		 * This function is intended for CREATE TABLE, so it processes a
 		 * _list_ of defaults, but we just do one.
 		 */
-		AddRelationNewConstraints(rel, list_make1(rawEnt), NIL, false, true, false);
+		AddRelationNewConstraints(rel, list_make1(rawEnt), NIL, false, true);
 	}
 }
 
@@ -5680,16 +5680,11 @@ ATAddCheckConstraint(List **wqueue, AlteredTableInfo *tab, Relation rel,
 	 * omitted from the returned list, which is what we want: we do not need
 	 * to do any validation work.  That can only happen at child tables,
 	 * though, since we disallow merging at the top level.
-	 *
-	 * Note: we set is_only based on the recurse flag which is false when
-	 * interpretInhOption() of our statement returns false all the way up
-	 * in AlterTable and gets passed all the way down to here.
 	 */
 	newcons = AddRelationNewConstraints(rel, NIL,
 										list_make1(copyObject(constr)),
-										recursing, /* allow_merge */
-										!recursing, /* is_local */
-										!recurse && !recursing); /* is_only */
+										recursing,   /* allow_merge */
+										!recursing); /* is_local */
 
 	/* Add each to-be-validated constraint to Phase 3's queue */
 	foreach(lcon, newcons)
@@ -5730,9 +5725,9 @@ ATAddCheckConstraint(List **wqueue, AlteredTableInfo *tab, Relation rel,
 		return;
 
 	/*
-	 * Adding an ONLY constraint? No need to find our children
+	 * Adding a NO INHERIT constraint? No need to find our children
 	 */
-	if (!recurse && !recursing)
+	if (constr->is_no_inherit)
 		return;
 
 	/*
@@ -5742,6 +5737,16 @@ ATAddCheckConstraint(List **wqueue, AlteredTableInfo *tab, Relation rel,
 	 */
 	children = find_inheritance_children(RelationGetRelid(rel), lockmode);
 
+	/*
+	 * Check if ONLY was specified with ALTER TABLE.  If yes, allow the
+	 * contraint creation only if there are no children currently.  Error out
+	 * otherwise.
+	 */
+	if (children && !recurse && !recursing)
+		ereport(ERROR,
+				(errcode(ERRCODE_INVALID_TABLE_DEFINITION),
+				 errmsg("constraint must be added to child tables too")));
+
 	foreach(child, children)
 	{
 		Oid			childrelid = lfirst_oid(child);
@@ -6127,7 +6132,7 @@ ATAddForeignKeyConstraint(AlteredTableInfo *tab, Relation rel,
 									  NULL,
 									  true,		/* islocal */
 									  0,		/* inhcount */
-									  false);	/* isonly */
+									  false);	/* isnoinherit */
 
 	/*
 	 * Create the triggers that will enforce the constraint.
@@ -6999,7 +7004,7 @@ ATExecDropConstraint(Relation rel, const char *constrName,
 	HeapTuple	tuple;
 	bool		found = false;
 	bool		is_check_constraint = false;
-	bool		is_only_constraint = false;
+	bool		is_no_inherit_constraint = false;
 
 	/* At top level, permission check was done in ATPrepCmd, else do it */
 	if (recursing)
@@ -7037,10 +7042,10 @@ ATExecDropConstraint(Relation rel, const char *constrName,
 		if (con->contype == CONSTRAINT_CHECK)
 			is_check_constraint = true;
 		
-		if (con->conisonly)
+		if (con->connoinherit)
 		{
 			Assert(is_check_constraint);
-			is_only_constraint = true;
+			is_no_inherit_constraint = true;
 		}
 
 		/*
@@ -7084,7 +7089,7 @@ ATExecDropConstraint(Relation rel, const char *constrName,
 	 * routines, we have to do this one level of recursion at a time; we can't
 	 * use find_all_inheritors to do it in one pass.
 	 */
-	if (is_check_constraint && !is_only_constraint)
+	if (is_check_constraint && !is_no_inherit_constraint)
 		children = find_inheritance_children(RelationGetRelid(rel), lockmode);
 	else
 		children = NIL;
@@ -9250,8 +9255,8 @@ MergeConstraintsIntoExisting(Relation child_rel, Relation parent_rel)
 		if (parent_con->contype != CONSTRAINT_CHECK)
 			continue;
 
-		/* if the parent's constraint is marked ONLY, it's not inherited */
-		if (parent_con->conisonly)
+		/* if the parent's constraint is marked NO INHERIT, it's not inherited */
+		if (parent_con->connoinherit)
 			continue;
 
 		/* Search for a child constraint matching this one */
@@ -9281,8 +9286,8 @@ MergeConstraintsIntoExisting(Relation child_rel, Relation parent_rel)
 								RelationGetRelationName(child_rel),
 								NameStr(parent_con->conname))));
 
-			/* If the constraint is "only" then cannot merge */
-			if (child_con->conisonly)
+			/* If the constraint is "no inherit" then cannot merge */
+			if (child_con->connoinherit)
 				ereport(ERROR,
 						(errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
 						 errmsg("constraint \"%s\" conflicts with non-inherited constraint on child table \"%s\"",
diff --git a/src/backend/commands/trigger.c b/src/backend/commands/trigger.c
index a98d1b8..1218d03 100644
--- a/src/backend/commands/trigger.c
+++ b/src/backend/commands/trigger.c
@@ -459,7 +459,7 @@ CreateTrigger(CreateTrigStmt *stmt, const char *queryString,
 											  NULL,
 											  true,		/* islocal */
 											  0,		/* inhcount */
-											  false);	/* isonly */
+											  false);	/* isnoinherit */
 	}
 
 	/*
diff --git a/src/backend/nodes/copyfuncs.c b/src/backend/nodes/copyfuncs.c
index eed0ea4..a92641c 100644
--- a/src/backend/nodes/copyfuncs.c
+++ b/src/backend/nodes/copyfuncs.c
@@ -2339,6 +2339,7 @@ _copyConstraint(const Constraint *from)
 	COPY_SCALAR_FIELD(deferrable);
 	COPY_SCALAR_FIELD(initdeferred);
 	COPY_LOCATION_FIELD(location);
+	COPY_SCALAR_FIELD(is_no_inherit);
 	COPY_NODE_FIELD(raw_expr);
 	COPY_STRING_FIELD(cooked_expr);
 	COPY_NODE_FIELD(keys);
diff --git a/src/backend/nodes/equalfuncs.c b/src/backend/nodes/equalfuncs.c
index c06b068..70888a5 100644
--- a/src/backend/nodes/equalfuncs.c
+++ b/src/backend/nodes/equalfuncs.c
@@ -2197,6 +2197,7 @@ _equalConstraint(const Constraint *a, const Constraint *b)
 	COMPARE_SCALAR_FIELD(deferrable);
 	COMPARE_SCALAR_FIELD(initdeferred);
 	COMPARE_LOCATION_FIELD(location);
+	COMPARE_SCALAR_FIELD(is_no_inherit);
 	COMPARE_NODE_FIELD(raw_expr);
 	COMPARE_STRING_FIELD(cooked_expr);
 	COMPARE_NODE_FIELD(keys);
diff --git a/src/backend/nodes/outfuncs.c b/src/backend/nodes/outfuncs.c
index f713773..f3649ba 100644
--- a/src/backend/nodes/outfuncs.c
+++ b/src/backend/nodes/outfuncs.c
@@ -2589,6 +2589,7 @@ _outConstraint(StringInfo str, const Constraint *node)
 
 		case CONSTR_CHECK:
 			appendStringInfo(str, "CHECK");
+			WRITE_BOOL_FIELD(is_no_inherit);
 			WRITE_NODE_FIELD(raw_expr);
 			WRITE_STRING_FIELD(cooked_expr);
 			break;
diff --git a/src/backend/parser/gram.y b/src/backend/parser/gram.y
index ae1658a..8d55dae 100644
--- a/src/backend/parser/gram.y
+++ b/src/backend/parser/gram.y
@@ -420,7 +420,7 @@ static void processCASbits(int cas_bits, int location, const char *constrType,
 %type <str>		character
 %type <str>		extract_arg
 %type <str>		opt_charset
-%type <boolean> opt_varying opt_timezone
+%type <boolean> opt_varying opt_timezone opt_no_inherit
 
 %type <ival>	Iconst SignedIconst
 %type <str>		Sconst comment_text notify_payload
@@ -2685,12 +2685,13 @@ ColConstraintElem:
 					n->indexspace = $4;
 					$$ = (Node *)n;
 				}
-			| CHECK '(' a_expr ')'
+			| CHECK opt_no_inherit '(' a_expr ')'
 				{
 					Constraint *n = makeNode(Constraint);
 					n->contype = CONSTR_CHECK;
 					n->location = @1;
-					n->raw_expr = $3;
+					n->is_no_inherit = $2;
+					n->raw_expr = $4;
 					n->cooked_expr = NULL;
 					$$ = (Node *)n;
 				}
@@ -2720,6 +2721,7 @@ ColConstraintElem:
 				}
 		;
 
+
 /*
  * ConstraintAttr represents constraint attributes, which we parse as if
  * they were independent constraint clauses, in order to avoid shift/reduce
@@ -2810,14 +2812,15 @@ TableConstraint:
 		;
 
 ConstraintElem:
-			CHECK '(' a_expr ')' ConstraintAttributeSpec
+			CHECK opt_no_inherit '(' a_expr ')' ConstraintAttributeSpec
 				{
 					Constraint *n = makeNode(Constraint);
 					n->contype = CONSTR_CHECK;
 					n->location = @1;
-					n->raw_expr = $3;
+					n->is_no_inherit = $2;
+					n->raw_expr = $4;
 					n->cooked_expr = NULL;
-					processCASbits($5, @5, "CHECK",
+					processCASbits($6, @6, "CHECK",
 								   NULL, NULL, &n->skip_validation,
 								   yyscanner);
 					n->initially_valid = !n->skip_validation;
@@ -2920,6 +2923,10 @@ ConstraintElem:
 				}
 		;
 
+opt_no_inherit:	NO INHERIT							{  $$ = TRUE; }
+			| /* EMPTY */							{  $$ = FALSE; }
+		;
+
 opt_column_list:
 			'(' columnList ')'						{ $$ = $2; }
 			| /*EMPTY*/								{ $$ = NIL; }
diff --git a/src/backend/utils/adt/ruleutils.c b/src/backend/utils/adt/ruleutils.c
index 64ba8ec..040e79e 100644
--- a/src/backend/utils/adt/ruleutils.c
+++ b/src/backend/utils/adt/ruleutils.c
@@ -1337,10 +1337,14 @@ pg_get_constraintdef_worker(Oid constraintId, bool fullCommand,
 				 * we don't need the outer parens ... but there are other
 				 * cases where we do need 'em.  Be conservative for now.
 				 *
+				 * Also add NO INHERIT if connoinherit is true
+				 *
 				 * Note that simply checking for leading '(' and trailing ')'
 				 * would NOT be good enough, consider "(x > 0) AND (y > 0)".
 				 */
-				appendStringInfo(&buf, "CHECK (%s)", consrc);
+				appendStringInfo(&buf, "CHECK %s(%s)",
+								 conForm->connoinherit? "NO INHERIT " : "",
+								 consrc);
 
 				break;
 			}
diff --git a/src/backend/utils/cache/relcache.c b/src/backend/utils/cache/relcache.c
index 9cadb3f..7f0e20e 100644
--- a/src/backend/utils/cache/relcache.c
+++ b/src/backend/utils/cache/relcache.c
@@ -3262,7 +3262,7 @@ CheckConstraintFetch(Relation relation)
 				 RelationGetRelationName(relation));
 
 		check[found].ccvalid = conform->convalidated;
-		check[found].cconly	= conform->conisonly;
+		check[found].ccnoinherit = conform->connoinherit;
 		check[found].ccname = MemoryContextStrdup(CacheMemoryContext,
 												  NameStr(conform->conname));
 
diff --git a/src/bin/pg_dump/pg_dump.c b/src/bin/pg_dump/pg_dump.c
index db56910..36a4e12 100644
--- a/src/bin/pg_dump/pg_dump.c
+++ b/src/bin/pg_dump/pg_dump.c
@@ -5960,13 +5960,15 @@ getTableAttrs(Archive *fout, TableInfo *tblinfo, int numTables)
 			if (fout->remoteVersion >= 90200)
 			{
 				/*
-				 * conisonly and convalidated are new in 9.2 (actually, the latter
+				 * connoinherit and convalidated are new in 9.2 (actually, the latter
 				 * is there in 9.1, but it wasn't ever false for check constraints
-				 * until 9.2).
+				 * until 9.2). The connoinherit attribute is not needed per se
+				 * because the pg_get_constraintdef function fills up the info
+				 * suitably as needed..
 				 */
 				appendPQExpBuffer(q, "SELECT tableoid, oid, conname, "
 						   "pg_catalog.pg_get_constraintdef(oid) AS consrc, "
-								  "conislocal, convalidated, conisonly "
+								  "conislocal, convalidated "
 								  "FROM pg_catalog.pg_constraint "
 								  "WHERE conrelid = '%u'::pg_catalog.oid "
 								  "   AND contype = 'c' "
@@ -5977,8 +5979,7 @@ getTableAttrs(Archive *fout, TableInfo *tblinfo, int numTables)
 			{
 				appendPQExpBuffer(q, "SELECT tableoid, oid, conname, "
 						   "pg_catalog.pg_get_constraintdef(oid) AS consrc, "
-								  "conislocal, true AS convalidated, "
-								  "false as conisonly "
+								  "conislocal, true AS convalidated "
 								  "FROM pg_catalog.pg_constraint "
 								  "WHERE conrelid = '%u'::pg_catalog.oid "
 								  "   AND contype = 'c' "
@@ -5989,8 +5990,7 @@ getTableAttrs(Archive *fout, TableInfo *tblinfo, int numTables)
 			{
 				appendPQExpBuffer(q, "SELECT tableoid, oid, conname, "
 						   "pg_catalog.pg_get_constraintdef(oid) AS consrc, "
-								  "true AS conislocal, true AS convalidated, "
-								  "false as conisonly "
+								  "true AS conislocal, true AS convalidated "
 								  "FROM pg_catalog.pg_constraint "
 								  "WHERE conrelid = '%u'::pg_catalog.oid "
 								  "   AND contype = 'c' "
@@ -6002,8 +6002,7 @@ getTableAttrs(Archive *fout, TableInfo *tblinfo, int numTables)
 				/* no pg_get_constraintdef, must use consrc */
 				appendPQExpBuffer(q, "SELECT tableoid, oid, conname, "
 								  "'CHECK (' || consrc || ')' AS consrc, "
-								  "true AS conislocal, true AS convalidated, "
-								  "false as conisonly "
+								  "true AS conislocal, true AS convalidated "
 								  "FROM pg_catalog.pg_constraint "
 								  "WHERE conrelid = '%u'::pg_catalog.oid "
 								  "   AND contype = 'c' "
@@ -6016,8 +6015,7 @@ getTableAttrs(Archive *fout, TableInfo *tblinfo, int numTables)
 				appendPQExpBuffer(q, "SELECT tableoid, 0 AS oid, "
 								  "rcname AS conname, "
 								  "'CHECK (' || rcsrc || ')' AS consrc, "
-								  "true AS conislocal, true AS convalidated, "
-								  "false as conisonly "
+								  "true AS conislocal, true AS convalidated "
 								  "FROM pg_relcheck "
 								  "WHERE rcrelid = '%u'::oid "
 								  "ORDER BY rcname",
@@ -6028,8 +6026,7 @@ getTableAttrs(Archive *fout, TableInfo *tblinfo, int numTables)
 				appendPQExpBuffer(q, "SELECT tableoid, oid, "
 								  "rcname AS conname, "
 								  "'CHECK (' || rcsrc || ')' AS consrc, "
-								  "true AS conislocal, true AS convalidated, "
-								  "false as conisonly "
+								  "true AS conislocal, true AS convalidated "
 								  "FROM pg_relcheck "
 								  "WHERE rcrelid = '%u'::oid "
 								  "ORDER BY rcname",
@@ -6042,8 +6039,7 @@ getTableAttrs(Archive *fout, TableInfo *tblinfo, int numTables)
 								  "(SELECT oid FROM pg_class WHERE relname = 'pg_relcheck') AS tableoid, "
 								  "oid, rcname AS conname, "
 								  "'CHECK (' || rcsrc || ')' AS consrc, "
-								  "true AS conislocal, true AS convalidated, "
-								  "false as conisonly "
+								  "true AS conislocal, true AS convalidated "
 								  "FROM pg_relcheck "
 								  "WHERE rcrelid = '%u'::oid "
 								  "ORDER BY rcname",
@@ -6068,7 +6064,6 @@ getTableAttrs(Archive *fout, TableInfo *tblinfo, int numTables)
 			for (j = 0; j < numConstrs; j++)
 			{
 				bool	validated = PQgetvalue(res, j, 5)[0] == 't';
-				bool	isonly = PQgetvalue(res, j, 6)[0] == 't';
 
 				constrs[j].dobj.objType = DO_CONSTRAINT;
 				constrs[j].dobj.catId.tableoid = atooid(PQgetvalue(res, j, 0));
@@ -6085,14 +6080,12 @@ getTableAttrs(Archive *fout, TableInfo *tblinfo, int numTables)
 				constrs[j].condeferrable = false;
 				constrs[j].condeferred = false;
 				constrs[j].conislocal = (PQgetvalue(res, j, 4)[0] == 't');
-				constrs[j].conisonly = isonly;
 				/*
 				 * An unvalidated constraint needs to be dumped separately, so
 				 * that potentially-violating existing data is loaded before
-				 * the constraint.  An ONLY constraint needs to be dumped
-				 * separately too.
+				 * the constraint.
 				 */
-				constrs[j].separate = !validated || isonly;
+				constrs[j].separate = !validated;
 
 				constrs[j].dobj.dump = tbinfo->dobj.dump;
 
@@ -13048,9 +13041,9 @@ dumpConstraint(Archive *fout, ConstraintInfo *coninfo)
 		/* Ignore if not to be dumped separately */
 		if (coninfo->separate)
 		{
-			/* add ONLY if we do not want it to propagate to children */
-			appendPQExpBuffer(q, "ALTER TABLE %s %s\n",
-							 coninfo->conisonly ? "ONLY" : "", fmtId(tbinfo->dobj.name));
+			/* not ONLY since we want it to propagate to children */
+			appendPQExpBuffer(q, "ALTER TABLE %s\n",
+							  fmtId(tbinfo->dobj.name));
 			appendPQExpBuffer(q, "    ADD CONSTRAINT %s %s;\n",
 							  fmtId(coninfo->dobj.name),
 							  coninfo->condef);
diff --git a/src/bin/pg_dump/pg_dump.h b/src/bin/pg_dump/pg_dump.h
index fba6953..5d6125c 100644
--- a/src/bin/pg_dump/pg_dump.h
+++ b/src/bin/pg_dump/pg_dump.h
@@ -370,7 +370,6 @@ typedef struct _constraintInfo
 	bool		condeferrable;	/* TRUE if constraint is DEFERRABLE */
 	bool		condeferred;	/* TRUE if constraint is INITIALLY DEFERRED */
 	bool		conislocal;		/* TRUE if constraint has local definition */
-	bool		conisonly;		/* TRUE if constraint is non-inheritable */
 	bool		separate;		/* TRUE if must dump as separate item */
 } ConstraintInfo;
 
diff --git a/src/bin/psql/describe.c b/src/bin/psql/describe.c
index 844a291..e2415f0 100644
--- a/src/bin/psql/describe.c
+++ b/src/bin/psql/describe.c
@@ -1786,20 +1786,13 @@ describeOneTableDetails(const char *schemaname,
 		/* print table (and column) check constraints */
 		if (tableinfo.checks)
 		{
-			char *is_only;
-
-			if (pset.sversion >= 90200)
-				is_only = "r.conisonly";
-			else
-				is_only = "false AS conisonly";
-
 			printfPQExpBuffer(&buf,
-							  "SELECT r.conname, %s, "
+							  "SELECT r.conname, "
 							  "pg_catalog.pg_get_constraintdef(r.oid, true)\n"
 							  "FROM pg_catalog.pg_constraint r\n"
 				   "WHERE r.conrelid = '%s' AND r.contype = 'c'\n"
 				   			  "ORDER BY 2 DESC, 1;",
-							  is_only, oid);
+							  oid);
 			result = PSQLexec(buf.data, false);
 			if (!result)
 				goto error_return;
@@ -1812,10 +1805,9 @@ describeOneTableDetails(const char *schemaname,
 				for (i = 0; i < tuples; i++)
 				{
 					/* untranslated contraint name and def */
-					printfPQExpBuffer(&buf, "    \"%s\"%s%s",
+					printfPQExpBuffer(&buf, "    \"%s\" %s",
 									  PQgetvalue(result, i, 0),
-									  (strcmp(PQgetvalue(result, i, 1), "t") == 0) ? " (ONLY) ":" ",
-									  PQgetvalue(result, i, 2));
+									  PQgetvalue(result, i, 1));
 
 					printTableAddFooter(&cont, buf.data);
 				}
diff --git a/src/include/access/tupdesc.h b/src/include/access/tupdesc.h
index 0df47a0..953e146 100644
--- a/src/include/access/tupdesc.h
+++ b/src/include/access/tupdesc.h
@@ -30,7 +30,7 @@ typedef struct constrCheck
 	char	   *ccname;
 	char	   *ccbin;			/* nodeToString representation of expr */
 	bool		ccvalid;
-	bool		cconly;			/* this is a non-inheritable constraint */
+	bool		ccnoinherit;	/* this is a non-inheritable constraint */
 } ConstrCheck;
 
 /* This structure contains constraints of a tuple */
diff --git a/src/include/catalog/heap.h b/src/include/catalog/heap.h
index 2055382..c0deab7 100644
--- a/src/include/catalog/heap.h
+++ b/src/include/catalog/heap.h
@@ -33,7 +33,8 @@ typedef struct CookedConstraint
 	bool		skip_validation;	/* skip validation? (only for CHECK) */
 	bool		is_local;		/* constraint has local (non-inherited) def */
 	int			inhcount;		/* number of times constraint is inherited */
-	bool		is_only;		/* constraint has local def and cannot be inherited */
+	bool		is_no_inherit;	/* constraint has local def and cannot be
+								 * inherited */
 } CookedConstraint;
 
 extern Relation heap_create(const char *relname,
@@ -92,8 +93,7 @@ extern List *AddRelationNewConstraints(Relation rel,
 						  List *newColDefaults,
 						  List *newConstraints,
 						  bool allow_merge,
-						  bool is_local,
-						  bool is_only);
+						  bool is_local);
 
 extern void StoreAttrDefault(Relation rel, AttrNumber attnum, Node *expr);
 
diff --git a/src/include/catalog/pg_constraint.h b/src/include/catalog/pg_constraint.h
index 22d6595..3a77124 100644
--- a/src/include/catalog/pg_constraint.h
+++ b/src/include/catalog/pg_constraint.h
@@ -89,7 +89,7 @@ CATALOG(pg_constraint,2606)
 	int4		coninhcount;
 
 	/* Has a local definition and cannot be inherited */
-	bool		conisonly;
+	bool		connoinherit;
 
 #ifdef CATALOG_VARLEN			/* variable-length fields start here */
 	/*
@@ -166,7 +166,7 @@ typedef FormData_pg_constraint *Form_pg_constraint;
 #define Anum_pg_constraint_confmatchtype	13
 #define Anum_pg_constraint_conislocal		14
 #define Anum_pg_constraint_coninhcount		15
-#define Anum_pg_constraint_conisonly		16
+#define Anum_pg_constraint_connoinherit		16
 #define Anum_pg_constraint_conkey			17
 #define Anum_pg_constraint_confkey			18
 #define Anum_pg_constraint_conpfeqop		19
diff --git a/src/include/nodes/parsenodes.h b/src/include/nodes/parsenodes.h
index aaa950d..13b95e1 100644
--- a/src/include/nodes/parsenodes.h
+++ b/src/include/nodes/parsenodes.h
@@ -1528,6 +1528,7 @@ typedef struct Constraint
 	int			location;		/* token location, or -1 if unknown */
 
 	/* Fields used for constraints with expressions (CHECK and DEFAULT): */
+	bool		is_no_inherit;	/* is constraint non-inheritable? */
 	Node	   *raw_expr;		/* expr, as untransformed parse tree */
 	char	   *cooked_expr;	/* expr, as nodeToString representation */
 
diff --git a/src/test/regress/expected/alter_table.out b/src/test/regress/expected/alter_table.out
index eba0493..595ca41 100644
--- a/src/test/regress/expected/alter_table.out
+++ b/src/test/regress/expected/alter_table.out
@@ -235,7 +235,7 @@ Check constraints:
     "con1foo" CHECK (a > 0)
 Inherits: constraint_rename_test
 
-ALTER TABLE ONLY constraint_rename_test ADD CONSTRAINT con2 CHECK (b > 0);
+ALTER TABLE constraint_rename_test ADD CONSTRAINT con2 CHECK NO INHERIT (b > 0);
 ALTER TABLE ONLY constraint_rename_test RENAME CONSTRAINT con2 TO con2foo; -- ok
 ALTER TABLE constraint_rename_test RENAME CONSTRAINT con2foo TO con2bar; -- ok
 \d constraint_rename_test
@@ -246,7 +246,7 @@ Table "public.constraint_rename_test"
  b      | integer | 
  c      | integer | 
 Check constraints:
-    "con2bar" (ONLY) CHECK (b > 0)
+    "con2bar" CHECK NO INHERIT (b > 0)
     "con1foo" CHECK (a > 0)
 Number of child tables: 1 (Use \d+ to list them.)
 
@@ -275,7 +275,7 @@ Table "public.constraint_rename_test"
 Indexes:
     "con3foo" PRIMARY KEY, btree (a)
 Check constraints:
-    "con2bar" (ONLY) CHECK (b > 0)
+    "con2bar" CHECK NO INHERIT (b > 0)
     "con1foo" CHECK (a > 0)
 Number of child tables: 1 (Use \d+ to list them.)
 
@@ -643,7 +643,7 @@ drop table atacc1;
 create table atacc1 (test int);
 create table atacc2 (test2 int) inherits (atacc1);
 -- ok:
-alter table only atacc1 add constraint foo check (test>0);
+alter table atacc1 add constraint foo check no inherit (test>0);
 -- check constraint is not there on child
 insert into atacc2 (test) values (-3);
 -- check constraint is there on parent
@@ -652,7 +652,7 @@ ERROR:  new row for relation "atacc1" violates check constraint "foo"
 DETAIL:  Failing row contains (-3).
 insert into atacc1 (test) values (3);
 -- fail, violating row:
-alter table only atacc2 add constraint foo check (test>0);
+alter table atacc2 add constraint foo check no inherit (test>0);
 ERROR:  check constraint "foo" is violated by some row
 drop table atacc2;
 drop table atacc1;
diff --git a/src/test/regress/expected/inherit.out b/src/test/regress/expected/inherit.out
index d8f20e8c..cbfe7bd 100644
--- a/src/test/regress/expected/inherit.out
+++ b/src/test/regress/expected/inherit.out
@@ -598,17 +598,17 @@ select * from d;
 
 -- Test non-inheritable parent constraints
 create table p1(ff1 int);
-alter table only p1 add constraint p1chk check (ff1 > 0);
+alter table p1 add constraint p1chk check no inherit (ff1 > 0);
 alter table p1 add constraint p2chk check (ff1 > 10);
--- conisonly should be true for ONLY constraint
-select pc.relname, pgc.conname, pgc.contype, pgc.conislocal, pgc.coninhcount, pgc.conisonly from pg_class as pc inner join pg_constraint as pgc on (pgc.conrelid = pc.oid) where pc.relname = 'p1' order by 1,2;
- relname | conname | contype | conislocal | coninhcount | conisonly 
----------+---------+---------+------------+-------------+-----------
+-- connoinherit should be true for NO INHERIT constraint
+select pc.relname, pgc.conname, pgc.contype, pgc.conislocal, pgc.coninhcount, pgc.connoinherit from pg_class as pc inner join pg_constraint as pgc on (pgc.conrelid = pc.oid) where pc.relname = 'p1' order by 1,2;
+ relname | conname | contype | conislocal | coninhcount | connoinherit 
+---------+---------+---------+------------+-------------+--------------
  p1      | p1chk   | c       | t          |           0 | t
  p1      | p2chk   | c       | t          |           0 | f
 (2 rows)
 
--- Test that child does not inherit ONLY constraints
+-- Test that child does not inherit NO INHERIT constraints
 create table c1 () inherits (p1);
 \d p1
       Table "public.p1"
@@ -616,7 +616,7 @@ create table c1 () inherits (p1);
 --------+---------+-----------
  ff1    | integer | 
 Check constraints:
-    "p1chk" (ONLY) CHECK (ff1 > 0)
+    "p1chk" CHECK NO INHERIT (ff1 > 0)
     "p2chk" CHECK (ff1 > 10)
 Number of child tables: 1 (Use \d+ to list them.)
 
@@ -867,8 +867,8 @@ NOTICE:  merging constraint "pp1_a2_check" with inherited definition
  f4     | double precision | 
  a2     | integer          | 
 Check constraints:
-    "pp1_a1_check" CHECK (a1 > 0)
     "pp1_a2_check" CHECK (a2 > 0)
+    "pp1_a1_check" CHECK (a1 > 0)
 Inherits: pp1,
           cc1
 
diff --git a/src/test/regress/input/constraints.source b/src/test/regress/input/constraints.source
index b84d51e..37d06b0 100644
--- a/src/test/regress/input/constraints.source
+++ b/src/test/regress/input/constraints.source
@@ -144,6 +144,34 @@ SELECT * FROM INSERT_CHILD;
 DROP TABLE INSERT_CHILD;
 
 --
+-- Check NO INHERIT type of constraints and inheritance
+--
+
+CREATE TABLE ATACC1 (TEST INT
+	CHECK NO INHERIT (TEST > 0));
+
+CREATE TABLE ATACC2 (TEST2 INT) INHERITS (ATACC1);
+-- check constraint is not there on child
+INSERT INTO ATACC2 (TEST) VALUES (-3);
+-- check constraint is there on parent
+INSERT INTO ATACC1 (TEST) VALUES (-3);
+DROP TABLE ATACC1 CASCADE;
+
+CREATE TABLE ATACC1 (TEST INT, TEST2 INT
+	CHECK (TEST > 0), CHECK NO INHERIT (TEST2 > 10));
+
+CREATE TABLE ATACC2 () INHERITS (ATACC1);
+-- check constraint is there on child
+INSERT INTO ATACC2 (TEST) VALUES (-3);
+-- check constraint is there on parent
+INSERT INTO ATACC1 (TEST) VALUES (-3);
+-- check constraint is not there on child
+INSERT INTO ATACC2 (TEST2) VALUES (3);
+-- check constraint is there on parent
+INSERT INTO ATACC1 (TEST2) VALUES (3);
+DROP TABLE ATACC1 CASCADE;
+
+--
 -- Check constraints on INSERT INTO
 --
 
diff --git a/src/test/regress/output/constraints.source b/src/test/regress/output/constraints.source
index 3e02e8d..f37c9b1 100644
--- a/src/test/regress/output/constraints.source
+++ b/src/test/regress/output/constraints.source
@@ -228,6 +228,39 @@ SELECT * FROM INSERT_CHILD;
 
 DROP TABLE INSERT_CHILD;
 --
+-- Check NO INHERIT type of constraints and inheritance
+--
+CREATE TABLE ATACC1 (TEST INT
+	CHECK NO INHERIT (TEST > 0));
+CREATE TABLE ATACC2 (TEST2 INT) INHERITS (ATACC1);
+-- check constraint is not there on child
+INSERT INTO ATACC2 (TEST) VALUES (-3);
+-- check constraint is there on parent
+INSERT INTO ATACC1 (TEST) VALUES (-3);
+ERROR:  new row for relation "atacc1" violates check constraint "atacc1_test_check"
+DETAIL:  Failing row contains (-3).
+DROP TABLE ATACC1 CASCADE;
+NOTICE:  drop cascades to table atacc2
+CREATE TABLE ATACC1 (TEST INT, TEST2 INT
+	CHECK (TEST > 0), CHECK NO INHERIT (TEST2 > 10));
+CREATE TABLE ATACC2 () INHERITS (ATACC1);
+-- check constraint is there on child
+INSERT INTO ATACC2 (TEST) VALUES (-3);
+ERROR:  new row for relation "atacc2" violates check constraint "atacc1_test_check"
+DETAIL:  Failing row contains (-3, null).
+-- check constraint is there on parent
+INSERT INTO ATACC1 (TEST) VALUES (-3);
+ERROR:  new row for relation "atacc1" violates check constraint "atacc1_test_check"
+DETAIL:  Failing row contains (-3, null).
+-- check constraint is not there on child
+INSERT INTO ATACC2 (TEST2) VALUES (3);
+-- check constraint is there on parent
+INSERT INTO ATACC1 (TEST2) VALUES (3);
+ERROR:  new row for relation "atacc1" violates check constraint "atacc1_test2_check"
+DETAIL:  Failing row contains (null, 3).
+DROP TABLE ATACC1 CASCADE;
+NOTICE:  drop cascades to table atacc2
+--
 -- Check constraints on INSERT INTO
 --
 DELETE FROM INSERT_TBL;
diff --git a/src/test/regress/sql/alter_table.sql b/src/test/regress/sql/alter_table.sql
index 50c58d2..5c03123 100644
--- a/src/test/regress/sql/alter_table.sql
+++ b/src/test/regress/sql/alter_table.sql
@@ -218,7 +218,7 @@ ALTER TABLE ONLY constraint_rename_test RENAME CONSTRAINT con1 TO con1foo; -- fa
 ALTER TABLE constraint_rename_test RENAME CONSTRAINT con1 TO con1foo; -- ok
 \d constraint_rename_test
 \d constraint_rename_test2
-ALTER TABLE ONLY constraint_rename_test ADD CONSTRAINT con2 CHECK (b > 0);
+ALTER TABLE constraint_rename_test ADD CONSTRAINT con2 CHECK NO INHERIT (b > 0);
 ALTER TABLE ONLY constraint_rename_test RENAME CONSTRAINT con2 TO con2foo; -- ok
 ALTER TABLE constraint_rename_test RENAME CONSTRAINT con2foo TO con2bar; -- ok
 \d constraint_rename_test
@@ -500,14 +500,14 @@ drop table atacc1;
 create table atacc1 (test int);
 create table atacc2 (test2 int) inherits (atacc1);
 -- ok:
-alter table only atacc1 add constraint foo check (test>0);
+alter table atacc1 add constraint foo check no inherit (test>0);
 -- check constraint is not there on child
 insert into atacc2 (test) values (-3);
 -- check constraint is there on parent
 insert into atacc1 (test) values (-3);
 insert into atacc1 (test) values (3);
 -- fail, violating row:
-alter table only atacc2 add constraint foo check (test>0);
+alter table atacc2 add constraint foo check no inherit (test>0);
 drop table atacc2;
 drop table atacc1;
 
diff --git a/src/test/regress/sql/inherit.sql b/src/test/regress/sql/inherit.sql
index eec8192..18b7a8c 100644
--- a/src/test/regress/sql/inherit.sql
+++ b/src/test/regress/sql/inherit.sql
@@ -140,12 +140,12 @@ select * from d;
 
 -- Test non-inheritable parent constraints
 create table p1(ff1 int);
-alter table only p1 add constraint p1chk check (ff1 > 0);
+alter table p1 add constraint p1chk check no inherit (ff1 > 0);
 alter table p1 add constraint p2chk check (ff1 > 10);
--- conisonly should be true for ONLY constraint
-select pc.relname, pgc.conname, pgc.contype, pgc.conislocal, pgc.coninhcount, pgc.conisonly from pg_class as pc inner join pg_constraint as pgc on (pgc.conrelid = pc.oid) where pc.relname = 'p1' order by 1,2;
+-- connoinherit should be true for NO INHERIT constraint
+select pc.relname, pgc.conname, pgc.contype, pgc.conislocal, pgc.coninhcount, pgc.connoinherit from pg_class as pc inner join pg_constraint as pgc on (pgc.conrelid = pc.oid) where pc.relname = 'p1' order by 1,2;
 
--- Test that child does not inherit ONLY constraints
+-- Test that child does not inherit NO INHERIT constraints
 create table c1 () inherits (p1);
 \d p1
 \d c1