Following patch implements record of whether a constraint is inherited
or not, and prevents dropping of inherited constraints.

What it doesn't do:
It doesn't yet prevent dropping the parent constraint, which is wrong,
clearly, but what to do about it?
1. make dropping a constraint drop all constraints dependent upon it
(without any explicit cascade)
2. add a new clause to ALTER TABLE .... DROP CONSTRAINT .... CASCADE 

I prefer (1), since it is SQL Standard compliant, easier to remember and
automatic de-inheritance is the natural opposite of the automatic
inheritance process.

Current patch passes make check on cvstip, applies cleanly.

Further patch will utilise this new knowledge to reduce the number of
tests made during constraint_exclusion.

Best Regards, Simon Riggs
Index: src/backend/access/common/tupdesc.c
===================================================================
RCS file: /projects/cvsroot/pgsql/src/backend/access/common/tupdesc.c,v
retrieving revision 1.113
diff -c -r1.113 tupdesc.c
*** src/backend/access/common/tupdesc.c	22 Nov 2005 18:17:05 -0000	1.113
--- src/backend/access/common/tupdesc.c	7 Dec 2005 20:15:04 -0000
***************
*** 194,199 ****
--- 194,200 ----
  					cpy->check[i].ccname = pstrdup(constr->check[i].ccname);
  				if (constr->check[i].ccbin)
  					cpy->check[i].ccbin = pstrdup(constr->check[i].ccbin);
+ 				cpy->check[i].ccinh = constr->check[i].ccinh;
  			}
  		}
  
***************
*** 362,368 ****
  			for (j = 0; j < n; check2++, j++)
  			{
  				if (strcmp(check1->ccname, check2->ccname) == 0 &&
! 					strcmp(check1->ccbin, check2->ccbin) == 0)
  					break;
  			}
  			if (j >= n)
--- 363,370 ----
  			for (j = 0; j < n; check2++, j++)
  			{
  				if (strcmp(check1->ccname, check2->ccname) == 0 &&
! 					strcmp(check1->ccbin, check2->ccbin) == 0 &&
!                     check1->ccinh == check2->ccinh)
  					break;
  			}
  			if (j >= n)
Index: src/backend/catalog/heap.c
===================================================================
RCS file: /projects/cvsroot/pgsql/src/backend/catalog/heap.c,v
retrieving revision 1.293
diff -c -r1.293 heap.c
*** src/backend/catalog/heap.c	22 Nov 2005 18:17:08 -0000	1.293
--- src/backend/catalog/heap.c	7 Dec 2005 20:15:06 -0000
***************
*** 72,78 ****
  				   Oid new_rel_oid,
  				   char new_rel_kind);
  static void RelationRemoveInheritance(Oid relid);
! static void StoreRelCheck(Relation rel, char *ccname, char *ccbin);
  static void StoreConstraints(Relation rel, TupleDesc tupdesc);
  static void SetRelationNumChecks(Relation rel, int numchecks);
  
--- 72,78 ----
  				   Oid new_rel_oid,
  				   char new_rel_kind);
  static void RelationRemoveInheritance(Oid relid);
! static void StoreRelCheck(Relation rel, char *ccname, char *ccbin, bool ccinh);
  static void StoreConstraints(Relation rel, TupleDesc tupdesc);
  static void SetRelationNumChecks(Relation rel, int numchecks);
  
***************
*** 1305,1311 ****
   * in the pg_class entry for the relation.
   */
  static void
! StoreRelCheck(Relation rel, char *ccname, char *ccbin)
  {
  	Node	   *expr;
  	char	   *ccsrc;
--- 1305,1311 ----
   * in the pg_class entry for the relation.
   */
  static void
! StoreRelCheck(Relation rel, char *ccname, char *ccbin, bool ccinh)
  {
  	Node	   *expr;
  	char	   *ccsrc;
***************
*** 1366,1371 ****
--- 1366,1372 ----
  						  CONSTRAINT_CHECK,		/* Constraint Type */
  						  false,	/* Is Deferrable */
  						  false,	/* Is Deferred */
+                           ccinh,    /* Is Inherited */
  						  RelationGetRelid(rel),		/* relation */
  						  attNos,		/* attrs in the constraint */
  						  keycount,		/* # attrs in the constraint */
***************
*** 1414,1420 ****
  
  	for (i = 0; i < constr->num_check; i++)
  		StoreRelCheck(rel, constr->check[i].ccname,
! 					  constr->check[i].ccbin);
  
  	if (constr->num_check > 0)
  		SetRelationNumChecks(rel, constr->num_check);
--- 1415,1422 ----
  
  	for (i = 0; i < constr->num_check; i++)
  		StoreRelCheck(rel, constr->check[i].ccname,
! 					  constr->check[i].ccbin,
! 					  constr->check[i].ccinh);
  
  	if (constr->num_check > 0)
  		SetRelationNumChecks(rel, constr->num_check);
***************
*** 1619,1625 ****
  		/*
  		 * OK, store it.
  		 */
! 		StoreRelCheck(rel, ccname, nodeToString(expr));
  
  		numchecks++;
  
--- 1621,1627 ----
  		/*
  		 * OK, store it.
  		 */
! 		StoreRelCheck(rel, ccname, nodeToString(expr), false);
  
  		numchecks++;
  
***************
*** 1782,1788 ****
   */
  int
  RemoveRelConstraints(Relation rel, const char *constrName,
! 					 DropBehavior behavior)
  {
  	int			ndeleted = 0;
  	Relation	conrel;
--- 1784,1790 ----
   */
  int
  RemoveRelConstraints(Relation rel, const char *constrName,
! 					 DropBehavior behavior, bool isChild)
  {
  	int			ndeleted = 0;
  	Relation	conrel;
***************
*** 1813,1818 ****
--- 1815,1828 ----
  		{
  			ObjectAddress conobj;
  
+             /*
+              * Cannot DROP inherited constraints on child tables
+              * unless this is action is part of the ripple down
+              * effect when the top level constraint itself is deleted
+              */
+             if (!isChild && con->coninherited)
+                 return -1;
+ 
  			conobj.classId = ConstraintRelationId;
  			conobj.objectId = HeapTupleGetOid(contup);
  			conobj.objectSubId = 0;
Index: src/backend/catalog/index.c
===================================================================
RCS file: /projects/cvsroot/pgsql/src/backend/catalog/index.c,v
retrieving revision 1.262
diff -c -r1.262 index.c
*** src/backend/catalog/index.c	22 Nov 2005 18:17:08 -0000	1.262
--- src/backend/catalog/index.c	7 Dec 2005 20:15:08 -0000
***************
*** 644,649 ****
--- 644,650 ----
  										   constraintType,
  										   false,		/* isDeferrable */
  										   false,		/* isDeferred */
+                                            false,       /* Is Inherited */
  										   heapRelationId,
  										   indexInfo->ii_KeyAttrNumbers,
  										   indexInfo->ii_NumIndexAttrs,
Index: src/backend/catalog/pg_constraint.c
===================================================================
RCS file: /projects/cvsroot/pgsql/src/backend/catalog/pg_constraint.c,v
retrieving revision 1.28
diff -c -r1.28 pg_constraint.c
*** src/backend/catalog/pg_constraint.c	22 Nov 2005 18:17:08 -0000	1.28
--- src/backend/catalog/pg_constraint.c	7 Dec 2005 20:15:08 -0000
***************
*** 46,51 ****
--- 46,52 ----
  					  char constraintType,
  					  bool isDeferrable,
  					  bool isDeferred,
+                       bool isInherited,
  					  Oid relId,
  					  const int16 *constraintKey,
  					  int constraintNKeys,
***************
*** 118,123 ****
--- 119,125 ----
  	values[Anum_pg_constraint_contype - 1] = CharGetDatum(constraintType);
  	values[Anum_pg_constraint_condeferrable - 1] = BoolGetDatum(isDeferrable);
  	values[Anum_pg_constraint_condeferred - 1] = BoolGetDatum(isDeferred);
+ 	values[Anum_pg_constraint_coninherited - 1] = BoolGetDatum(isInherited);
  	values[Anum_pg_constraint_conrelid - 1] = ObjectIdGetDatum(relId);
  	values[Anum_pg_constraint_contypid - 1] = ObjectIdGetDatum(domainId);
  	values[Anum_pg_constraint_confrelid - 1] = ObjectIdGetDatum(foreignRelId);
Index: src/backend/commands/tablecmds.c
===================================================================
RCS file: /projects/cvsroot/pgsql/src/backend/commands/tablecmds.c,v
retrieving revision 1.176
diff -c -r1.176 tablecmds.c
*** src/backend/commands/tablecmds.c	22 Nov 2005 18:17:09 -0000	1.176
--- src/backend/commands/tablecmds.c	7 Dec 2005 20:15:14 -0000
***************
*** 402,407 ****
--- 402,408 ----
  			{
  				check[ncheck].ccname = cdef->name;
  				check[ncheck].ccbin = pstrdup(cdef->cooked_expr);
+                 check[ncheck].ccinh = true;
  				ncheck++;
  			}
  		}
***************
*** 3999,4004 ****
--- 4000,4006 ----
  									  CONSTRAINT_FOREIGN,
  									  fkconstraint->deferrable,
  									  fkconstraint->initdeferred,
+                                       false,    /* Is Inherited */
  									  RelationGetRelid(rel),
  									  fkattnum,
  									  numfks,
***************
*** 4658,4667 ****
  {
  	int			deleted;
  
! 	deleted = RemoveRelConstraints(rel, constrName, behavior);
  
  	if (!quiet)
  	{
  		/* If zero constraints deleted, complain */
  		if (deleted == 0)
  			ereport(ERROR,
--- 4660,4676 ----
  {
  	int			deleted;
  
! 	deleted = RemoveRelConstraints(rel, constrName, behavior, quiet);
  
  	if (!quiet)
  	{
+ 		/* If deleted is negative, then constraint deletion not allowed */
+ 		if (deleted < 0)
+ 			ereport(ERROR,
+ 					(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
+ 					 errmsg("inherited constraint \"%s\" cannot be dropped",
+ 							constrName)));
+ 
  		/* If zero constraints deleted, complain */
  		if (deleted == 0)
  			ereport(ERROR,
Index: src/backend/commands/typecmds.c
===================================================================
RCS file: /projects/cvsroot/pgsql/src/backend/commands/typecmds.c,v
retrieving revision 1.85
diff -c -r1.85 typecmds.c
*** src/backend/commands/typecmds.c	22 Nov 2005 18:17:09 -0000	1.85
--- src/backend/commands/typecmds.c	7 Dec 2005 20:15:16 -0000
***************
*** 1880,1885 ****
--- 1880,1886 ----
  						  CONSTRAINT_CHECK,		/* Constraint Type */
  						  false,	/* Is Deferrable */
  						  false,	/* Is Deferred */
+                           false,    /* Is Inherited */
  						  InvalidOid,	/* not a relation constraint */
  						  NULL,
  						  0,
***************
*** 1893,1899 ****
  						  InvalidOid,
  						  expr, /* Tree form check constraint */
  						  ccbin,	/* Binary form check constraint */
! 						  ccsrc);		/* Source form check constraint */
  
  	/*
  	 * Return the compiled constraint expression so the calling routine can
--- 1894,1900 ----
  						  InvalidOid,
  						  expr, /* Tree form check constraint */
  						  ccbin,	/* Binary form check constraint */
! 						  ccsrc);    /* Source form check constraint */
  
  	/*
  	 * Return the compiled constraint expression so the calling routine can
Index: src/backend/utils/cache/relcache.c
===================================================================
RCS file: /projects/cvsroot/pgsql/src/backend/utils/cache/relcache.c,v
retrieving revision 1.232
diff -c -r1.232 relcache.c
*** src/backend/utils/cache/relcache.c	22 Nov 2005 18:17:24 -0000	1.232
--- src/backend/utils/cache/relcache.c	7 Dec 2005 20:15:20 -0000
***************
*** 2476,2481 ****
--- 2476,2483 ----
  		check[found].ccbin = MemoryContextStrdup(CacheMemoryContext,
  								 DatumGetCString(DirectFunctionCall1(textout,
  																	 val)));
+ 
+         check[found].ccinh = DatumGetBool(conform->coninherited);
  		found++;
  	}
  
Index: src/include/access/tupdesc.h
===================================================================
RCS file: /projects/cvsroot/pgsql/src/include/access/tupdesc.h,v
retrieving revision 1.47
diff -c -r1.47 tupdesc.h
*** src/include/access/tupdesc.h	7 Mar 2005 04:42:17 -0000	1.47
--- src/include/access/tupdesc.h	7 Dec 2005 20:15:24 -0000
***************
*** 29,34 ****
--- 29,35 ----
  {
  	char	   *ccname;
  	char	   *ccbin;			/* nodeToString representation of expr */
+     bool        ccinh;
  } ConstrCheck;
  
  /* This structure contains constraints of a tuple */
Index: src/include/catalog/heap.h
===================================================================
RCS file: /projects/cvsroot/pgsql/src/include/catalog/heap.h,v
retrieving revision 1.76
diff -c -r1.76 heap.h
*** src/include/catalog/heap.h	15 Oct 2005 02:49:42 -0000	1.76
--- src/include/catalog/heap.h	7 Dec 2005 20:15:24 -0000
***************
*** 75,81 ****
  			char *attname);
  
  extern int RemoveRelConstraints(Relation rel, const char *constrName,
! 					 DropBehavior behavior);
  
  extern void DeleteRelationTuple(Oid relid);
  extern void DeleteAttributeTuples(Oid relid);
--- 75,81 ----
  			char *attname);
  
  extern int RemoveRelConstraints(Relation rel, const char *constrName,
! 					 DropBehavior behavior, bool isChild);
  
  extern void DeleteRelationTuple(Oid relid);
  extern void DeleteAttributeTuples(Oid relid);
Index: src/include/catalog/pg_constraint.h
===================================================================
RCS file: /projects/cvsroot/pgsql/src/include/catalog/pg_constraint.h,v
retrieving revision 1.19
diff -c -r1.19 pg_constraint.h
*** src/include/catalog/pg_constraint.h	22 Nov 2005 18:17:30 -0000	1.19
--- src/include/catalog/pg_constraint.h	7 Dec 2005 20:15:24 -0000
***************
*** 49,54 ****
--- 49,55 ----
  	char		contype;		/* constraint type; see codes below */
  	bool		condeferrable;	/* deferrable constraint? */
  	bool		condeferred;	/* deferred by default? */
+     bool        coninherited;   /* inherited constraint? */
  
  	/*
  	 * conrelid and conkey are only meaningful if the constraint applies to a
***************
*** 111,132 ****
   *		compiler constants for pg_constraint
   * ----------------
   */
! #define Natts_pg_constraint					15
  #define Anum_pg_constraint_conname			1
  #define Anum_pg_constraint_connamespace		2
  #define Anum_pg_constraint_contype			3
  #define Anum_pg_constraint_condeferrable	4
  #define Anum_pg_constraint_condeferred		5
! #define Anum_pg_constraint_conrelid			6
! #define Anum_pg_constraint_contypid			7
! #define Anum_pg_constraint_confrelid		8
! #define Anum_pg_constraint_confupdtype		9
! #define Anum_pg_constraint_confdeltype		10
! #define Anum_pg_constraint_confmatchtype	11
! #define Anum_pg_constraint_conkey			12
! #define Anum_pg_constraint_confkey			13
! #define Anum_pg_constraint_conbin			14
! #define Anum_pg_constraint_consrc			15
  
  
  /* Valid values for contype */
--- 112,134 ----
   *		compiler constants for pg_constraint
   * ----------------
   */
! #define Natts_pg_constraint					16
  #define Anum_pg_constraint_conname			1
  #define Anum_pg_constraint_connamespace		2
  #define Anum_pg_constraint_contype			3
  #define Anum_pg_constraint_condeferrable	4
  #define Anum_pg_constraint_condeferred		5
! #define Anum_pg_constraint_coninherited		6
! #define Anum_pg_constraint_conrelid			7
! #define Anum_pg_constraint_contypid			8
! #define Anum_pg_constraint_confrelid		9
! #define Anum_pg_constraint_confupdtype		10
! #define Anum_pg_constraint_confdeltype		11
! #define Anum_pg_constraint_confmatchtype	12
! #define Anum_pg_constraint_conkey			13
! #define Anum_pg_constraint_confkey			14
! #define Anum_pg_constraint_conbin			15
! #define Anum_pg_constraint_consrc			16
  
  
  /* Valid values for contype */
***************
*** 159,164 ****
--- 161,167 ----
  					  char constraintType,
  					  bool isDeferrable,
  					  bool isDeferred,
+                       bool isInherited,
  					  Oid relId,
  					  const int16 *constraintKey,
  					  int constraintNKeys,
---------------------------(end of broadcast)---------------------------
TIP 2: Don't 'kill -9' the postmaster

Reply via email to