From 530876fea5060cce019e522b05be81e0aa4d4507 Mon Sep 17 00:00:00 2001
From: "Vadim B. Mikheev" <vadim4o@yahoo.com>
Date: Fri, 22 Aug 1997 14:10:26 +0000
Subject: [PATCH] Remove DEFAULT/CHECK infos from catalog on DROP TABLE Store
 CHECK infos on CREATE TABLE

---
 src/backend/catalog/heap.c  | 195 ++++++++++++++++++++++++++++++------
 src/backend/catalog/index.c |   5 +-
 2 files changed, 167 insertions(+), 33 deletions(-)

diff --git a/src/backend/catalog/heap.c b/src/backend/catalog/heap.c
index 5f3be132c52..7899f6c0007 100644
--- a/src/backend/catalog/heap.c
+++ b/src/backend/catalog/heap.c
@@ -7,7 +7,7 @@
  *
  *
  * IDENTIFICATION
- *    $Header: /cvsroot/pgsql/src/backend/catalog/heap.c,v 1.21 1997/08/22 02:58:51 vadim Exp $
+ *    $Header: /cvsroot/pgsql/src/backend/catalog/heap.c,v 1.22 1997/08/22 14:10:24 vadim Exp $
  *
  * INTERFACE ROUTINES
  *	heap_creatr()		- Create an uncataloged heap relation
@@ -50,6 +50,7 @@
 #include <utils/builtins.h>
 #include <utils/mcxt.h>
 #include <utils/relcache.h>
+#include <nodes/plannodes.h>
 #ifndef HAVE_MEMMOVE
 # include <regex/utils.h>
 #else
@@ -68,8 +69,7 @@ static void RelationRemoveInheritance(Relation relation);
 static void RemoveFromTempRelList(Relation r);
 static void addNewRelationType(char *typeName, Oid new_rel_oid);
 static void StoreConstraints (Relation rel);
-static void StoreAttrDefault (Relation rel, AttrDefault *attrdef);
-static void StoreRelCheck (Relation rel, ConstrCheck *check);
+static void RemoveConstraints (Relation rel);
 
 
 /* ----------------------------------------------------------------
@@ -371,8 +371,10 @@ heap_creatr(char *name,
  *
  *	6) AddPgRelationTuple() is called to register the
  *	   relation itself in the catalogs.
+ *	
+ *	7) StoreConstraints is called ()	- vadim 08/22/97
  *
- *	7) the relations are closed and the new relation's oid
+ *	8) the relations are closed and the new relation's oid
  *	   is returned.
  *
  * old comments:
@@ -847,7 +849,8 @@ heap_create(char relname[],
  *	4)  remove pg_class tuple
  *	5)  remove pg_attribute tuples
  *	6)  remove pg_type tuples
- *	7)  unlink relation
+ *	7)  RemoveConstraints ()
+ *	8)  unlink relation
  *
  * old comments
  *	Except for vital relations, removes relation from
@@ -1327,6 +1330,8 @@ heap_destroy(char *relname)
      * Does nothing!!! Flushing moved below.	- vadim 06/04/97
     RelationIdInvalidateRelationCacheByRelationId(rdesc->rd_id);
      */
+    
+    RemoveConstraints (rdesc);
 
     /* ----------------
      *	unlink the relation and finish up.
@@ -1468,30 +1473,6 @@ DestroyTempRels(void)
     tempRels = NULL;
 }
 
-static void 
-StoreConstraints (Relation rel)
-{
-    TupleConstr *constr = rel->rd_att->constr;
-    int i;
-    
-    if ( !constr )
-    	return;
-    
-    if ( constr->num_defval > 0 )
-    {
-    	for (i = 0; i < constr->num_defval; i++)
-    	    StoreAttrDefault (rel, &(constr->defval[i]));
-    }
-    
-    if ( constr->num_check > 0 )
-    {
-    	for (i = 0; i < constr->num_check; i++)
-    	    StoreRelCheck (rel, &(constr->check[i]));
-    }
-    
-    return;
-}
-
 extern List *flatten_tlist(List *tlist);
 extern List *pg_plan(char *query_string, Oid *typev, int nargs,                
                      QueryTreeList **queryListP, CommandDest dest);            
@@ -1520,12 +1501,14 @@ StoreAttrDefault (Relation rel, AttrDefault *attrdef)
 start:;
     sprintf (str, "select %s%s from %.*s", attrdef->adsrc, cast,
     		NAMEDATALEN, rel->rd_rel->relname.data);
+    setheapoverride(true);
     planTree_list = (List*) pg_plan (str, NULL, 0, &queryTree_list, None);
+    setheapoverride(false);
     query = (Query*) (queryTree_list->qtrees[0]);
     
     if ( length (query->rtable) > 1 || 
     		flatten_tlist (query->targetList) != NIL )
-    	elog (WARN, "AttributeDefault: cannot use attribute(s)");
+    	elog (WARN, "DEFAULT: cannot use attribute(s)");
     te = (TargetEntry *) lfirst (query->targetList);
     resdom = te->resdom;
     expr = te->expr;
@@ -1535,13 +1518,13 @@ start:;
     	if ( ((Const*)expr)->consttype != atp->atttypid )
     	{
     	    if ( *cast != 0 )
-    	    	elog (WARN, "AttributeDefault: casting failed - const type mismatched");
+    	    	elog (WARN, "DEFAULT: const type mismatched");
     	    sprintf (cast, ":: %s", get_id_typname (atp->atttypid));
     	    goto start;
     	}
     }
     else if ( exprType (expr) != atp->atttypid )
-    	elog (WARN, "AttributeDefault: type mismatched");
+    	elog (WARN, "DEFAULT: type mismatched");
     
     adbin = nodeToString (expr);
     oldcxt = MemoryContextSwitchTo ((MemoryContext) CacheCxt);
@@ -1560,6 +1543,7 @@ start:;
     heap_insert (adrel, tuple);
     CatalogIndexInsert (idescs, Num_pg_attrdef_indices, adrel, tuple);
     CatalogCloseIndices (Num_pg_attrdef_indices, idescs);
+    heap_close (adrel);
     
     pfree (DatumGetPointer(values[Anum_pg_attrdef_adbin - 1]));
     pfree (DatumGetPointer(values[Anum_pg_attrdef_adsrc - 1]));
@@ -1570,6 +1554,153 @@ start:;
 static void 
 StoreRelCheck (Relation rel, ConstrCheck *check)
 {
+    char str[MAX_PARSE_BUFFER];
+    QueryTreeList *queryTree_list;
+    Query *query;
+    List *planTree_list;
+    Plan *plan;
+    List *qual;
+    char *ccbin;
+    MemoryContext oldcxt;
+    Relation rcrel;
+    Relation idescs[Num_pg_relcheck_indices];
+    HeapTuple tuple;
+    Datum values[4];
+    char nulls[4] = {' ', ' ', ' ', ' '};
+    extern GlobalMemory	CacheCxt;
+    
+    sprintf (str, "select 1 from %.*s where %s", 
+    		NAMEDATALEN, rel->rd_rel->relname.data, check->ccsrc);
+    setheapoverride(true);
+    planTree_list = (List*) pg_plan (str, NULL, 0, &queryTree_list, None);
+    setheapoverride(false);
+    query = (Query*) (queryTree_list->qtrees[0]);
+    
+    if ( length (query->rtable) > 1 )
+    	elog (WARN, "CHECK: only relation %.*s can be referenced",
+    		NAMEDATALEN, rel->rd_rel->relname.data);
+    
+    plan = (Plan*) lfirst(planTree_list);
+    qual = plan->qual;
+    
+    ccbin = nodeToString (qual);
+    oldcxt = MemoryContextSwitchTo ((MemoryContext) CacheCxt);
+    check->ccbin = (char*) palloc (strlen (ccbin) + 1);
+    strcpy (check->ccbin, ccbin);
+    (void) MemoryContextSwitchTo (oldcxt);
+    pfree (ccbin);
+    
+    values[Anum_pg_relcheck_rcrelid - 1] = rel->rd_id;
+    values[Anum_pg_relcheck_rcname - 1] = PointerGetDatum (namein (check->ccname));
+    values[Anum_pg_relcheck_rcbin - 1] = PointerGetDatum (textin (check->ccbin));
+    values[Anum_pg_relcheck_rcsrc - 1] = PointerGetDatum (textin (check->ccsrc));
+    rcrel = heap_openr (RelCheckRelationName);
+    tuple = heap_formtuple (rcrel->rd_att, values, nulls);
+    CatalogOpenIndices (Num_pg_relcheck_indices, Name_pg_relcheck_indices, idescs);
+    heap_insert (rcrel, tuple);
+    CatalogIndexInsert (idescs, Num_pg_relcheck_indices, rcrel, tuple);
+    CatalogCloseIndices (Num_pg_relcheck_indices, idescs);
+    heap_close (rcrel);
+    
+    pfree (DatumGetPointer(values[Anum_pg_relcheck_rcname - 1]));
+    pfree (DatumGetPointer(values[Anum_pg_relcheck_rcbin - 1]));
+    pfree (DatumGetPointer(values[Anum_pg_relcheck_rcsrc - 1]));
+    pfree (tuple);
+
+    return;
+}
+
+static void 
+StoreConstraints (Relation rel)
+{
+    TupleConstr *constr = rel->rd_att->constr;
+    int i;
+    
+    if ( !constr )
+    	return;
+    
+    if ( constr->num_defval > 0 )
+    {
+    	for (i = 0; i < constr->num_defval; i++)
+    	    StoreAttrDefault (rel, &(constr->defval[i]));
+    }
+    
+    if ( constr->num_check > 0 )
+    {
+    	for (i = 0; i < constr->num_check; i++)
+    	    StoreRelCheck (rel, &(constr->check[i]));
+    }
+    
+    return;
+}
+
+static void 
+RemoveAttrDefault (Relation rel)
+{
+    Relation		adrel;
+    HeapScanDesc	adscan;
+    ScanKeyData	        key;
+    HeapTuple		tup;
+    
+    adrel = heap_openr (AttrDefaultRelationName);
+    
+    ScanKeyEntryInitialize(&key, 0, Anum_pg_attrdef_adrelid,
+			   ObjectIdEqualRegProcedure, rel->rd_id);
+    
+    RelationSetLockForWrite (adrel);
+    
+    adscan = heap_beginscan(adrel, 0, NowTimeQual, 1, &key);
+    
+    while (tup = heap_getnext (adscan, 0, (Buffer *)NULL), PointerIsValid(tup))
+	heap_delete (adrel, &tup->t_ctid);
+    
+    heap_endscan (adscan);
+    
+    RelationUnsetLockForWrite (adrel);
+    heap_close (adrel);
+
+}
+
+static void 
+RemoveRelCheck (Relation rel)
+{
+    Relation		rcrel;
+    HeapScanDesc	rcscan;
+    ScanKeyData	        key;
+    HeapTuple		tup;
+    
+    rcrel = heap_openr (RelCheckRelationName);
+    
+    ScanKeyEntryInitialize(&key, 0, Anum_pg_relcheck_rcrelid,
+			   ObjectIdEqualRegProcedure, rel->rd_id);
+    
+    RelationSetLockForWrite (rcrel);
+    
+    rcscan = heap_beginscan(rcrel, 0, NowTimeQual, 1, &key);
+    
+    while (tup = heap_getnext (rcscan, 0, (Buffer *)NULL), PointerIsValid(tup))
+	heap_delete (rcrel, &tup->t_ctid);
+    
+    heap_endscan (rcscan);
+    
+    RelationUnsetLockForWrite (rcrel);
+    heap_close (rcrel);
+
+}
 
+static void 
+RemoveConstraints (Relation rel)
+{
+    TupleConstr *constr = rel->rd_att->constr;
+    
+    if ( !constr )
+    	return;
+    
+    if ( constr->num_defval > 0 )
+    	RemoveAttrDefault (rel);
+    
+    if ( constr->num_check > 0 )
+    	RemoveRelCheck (rel);
+    
     return;
 }
diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c
index 95b6b0e6df7..b2071f814f2 100644
--- a/src/backend/catalog/index.c
+++ b/src/backend/catalog/index.c
@@ -7,7 +7,7 @@
  *
  *
  * IDENTIFICATION
- *    $Header: /cvsroot/pgsql/src/backend/catalog/index.c,v 1.18 1997/08/21 01:32:04 vadim Exp $
+ *    $Header: /cvsroot/pgsql/src/backend/catalog/index.c,v 1.19 1997/08/22 14:10:26 vadim Exp $
  *
  *
  * INTERFACE ROUTINES
@@ -419,6 +419,9 @@ ConstructTupleDescriptor(Oid heapoid,
 	
 	((AttributeTupleForm) to)->attnum = i+1;
 	((AttributeTupleForm) to)->attcacheoff = -1;
+	
+	((AttributeTupleForm) to)->attnotnull = false;
+	((AttributeTupleForm) to)->atthasdef = false;
 
 	/* if the keytype is defined, we need to change the tuple form's
 	   atttypid & attlen field to match that of the key's type */
-- 
GitLab