From 197ced5923164ab1ea6ca958d084d2e4ba46fd14 Mon Sep 17 00:00:00 2001
From: "Vadim B. Mikheev" <vadim4o@yahoo.com>
Date: Thu, 21 Aug 1997 01:36:09 +0000
Subject: [PATCH] Read info for DEFAULT from pg_attrdef.

---
 src/backend/utils/cache/relcache.c | 195 +++++++++++++++++++++++------
 1 file changed, 154 insertions(+), 41 deletions(-)

diff --git a/src/backend/utils/cache/relcache.c b/src/backend/utils/cache/relcache.c
index 69e34d3aa4..8cb08e6ab1 100644
--- a/src/backend/utils/cache/relcache.c
+++ b/src/backend/utils/cache/relcache.c
@@ -7,7 +7,7 @@
  *
  *
  * IDENTIFICATION
- *    $Header: /cvsroot/pgsql/src/backend/utils/cache/relcache.c,v 1.16 1997/08/20 14:54:07 momjian Exp $
+ *    $Header: /cvsroot/pgsql/src/backend/utils/cache/relcache.c,v 1.17 1997/08/21 01:36:09 vadim Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -81,6 +81,7 @@
 #include "catalog/pg_variable.h"
 #include "catalog/pg_log.h"
 #include "catalog/pg_time.h"
+#include "catalog/pg_attrdef.h"
 #include "catalog/indexing.h"
 #include "catalog/index.h"
 #include "fmgr.h"
@@ -90,22 +91,6 @@ static void RelationFlushRelation(Relation *relationPtr,
 static Relation RelationNameCacheGetRelation(char *relationName);
 static void init_irels(void);
 static void write_irels(void);
-/* non-export function prototypes */
-static void formrdesc(char *relationName, u_int natts,
-		      FormData_pg_attribute att[]);
-static HeapTuple ScanPgRelation(RelationBuildDescInfo buildinfo);
-static HeapTuple scan_pg_rel_seq(RelationBuildDescInfo buildinfo);
-static HeapTuple scan_pg_rel_ind(RelationBuildDescInfo buildinfo);
-static Relation AllocateRelationDesc(u_int natts, Form_pg_class relp);
-static void RelationBuildTupleDesc(RelationBuildDescInfo buildinfo,    
-		Relation relation, AttributeTupleForm attp, u_int natts);
-static void build_tupdesc_seq(RelationBuildDescInfo buildinfo,
-		Relation relation, AttributeTupleForm attp, u_int natts);
-static void build_tupdesc_ind(RelationBuildDescInfo buildinfo,
-		Relation relation, AttributeTupleForm attp, u_int natts);
-static Relation RelationBuildDesc(RelationBuildDescInfo buildinfo);
-static void IndexedAccessMethodInitialize(Relation relation);
-
 
 /* ----------------
  *	defines
@@ -254,6 +239,28 @@ typedef struct relnamecacheent {
 	  } \
     }
 
+/* non-export function prototypes */
+static void formrdesc(char *relationName, u_int natts,
+		      FormData_pg_attribute att[]);
+
+#if 0		/* See comments at line 1304 */
+static void RelationFlushIndexes(Relation *r, Oid accessMethodId);
+#endif
+
+static HeapTuple ScanPgRelation(RelationBuildDescInfo buildinfo);
+static HeapTuple scan_pg_rel_seq(RelationBuildDescInfo buildinfo);
+static HeapTuple scan_pg_rel_ind(RelationBuildDescInfo buildinfo);
+static Relation AllocateRelationDesc(u_int natts, Form_pg_class relp);
+static void RelationBuildTupleDesc(RelationBuildDescInfo buildinfo,    
+		Relation relation, u_int natts);
+static void build_tupdesc_seq(RelationBuildDescInfo buildinfo,
+		Relation relation, u_int natts);
+static void build_tupdesc_ind(RelationBuildDescInfo buildinfo,
+		Relation relation, u_int natts);
+static Relation RelationBuildDesc(RelationBuildDescInfo buildinfo);
+static void IndexedAccessMethodInitialize(Relation relation);
+static void AttrDefaultFetch (Relation relation);
+
 /*
  * newlyCreatedRelns -
  *    relations created during this transaction. We need to keep track of
@@ -268,7 +275,7 @@ static List *newlyCreatedRelns = NULL;
  */
  
 
-#ifdef NOT_USED		/* XXX This doesn't seem to be used anywhere */
+#if NOT_USED		/* XXX This doesn't seem to be used anywhere */
 /* --------------------------------
  *	BuildDescInfoError returns a string appropriate to
  *	the buildinfo passed to it
@@ -481,7 +488,6 @@ AllocateRelationDesc(u_int natts, Form_pg_class relp)
 static void
 RelationBuildTupleDesc(RelationBuildDescInfo buildinfo,    
 		       Relation relation,
-		       AttributeTupleForm attp,
 		       u_int natts)
 {
     /*
@@ -491,20 +497,26 @@ RelationBuildTupleDesc(RelationBuildDescInfo buildinfo,
      */
     
     if (IsBootstrapProcessingMode())
-	build_tupdesc_seq(buildinfo, relation, attp, natts);
+	build_tupdesc_seq(buildinfo, relation, natts);
     else
-	build_tupdesc_ind(buildinfo, relation, attp, natts);
+    {
+    	relation->rd_att->constr = (AttrConstr *) palloc(sizeof(struct attrConstr));
+    	relation->rd_att->constr->num_check = 0;
+    	relation->rd_att->constr->num_defval = 0;
+    	relation->rd_att->constr->has_not_null = false;
+	build_tupdesc_ind(buildinfo, relation, natts);
+    }
 }
 
 static void
 build_tupdesc_seq(RelationBuildDescInfo buildinfo,
 		  Relation relation,
-		  AttributeTupleForm attp,
 		  u_int natts)
 {
     HeapTuple    pg_attribute_tuple;
     Relation	 pg_attribute_desc;
     HeapScanDesc pg_attribute_scan;
+    AttributeTupleForm	attp;
     ScanKeyData	 key;
     int		 need;
                                    
@@ -530,9 +542,6 @@ build_tupdesc_seq(RelationBuildDescInfo buildinfo,
      * ----------------
      */
     need = natts;
-    if (!relation->rd_att->constr)
-      relation->rd_att->constr = (AttrConstr *) palloc(sizeof(struct attrConstr));
-    relation->rd_att->constr->has_not_null = false;
 
     pg_attribute_tuple = heap_getnext(pg_attribute_scan, 0, (Buffer *) NULL);
     while (HeapTupleIsValid(pg_attribute_tuple) && need > 0) {
@@ -545,11 +554,6 @@ build_tupdesc_seq(RelationBuildDescInfo buildinfo,
 	    memmove((char *) (relation->rd_att->attrs[attp->attnum - 1]),
 		    (char *) attp,
 		    ATTRIBUTE_TUPLE_SIZE);
-
-            /* Update if this attribute have a constraint */
-            if (attp->attnotnull)
-	      relation->rd_att->constr->has_not_null = true;
-	    
 	    need--;
 	}
 	pg_attribute_tuple = heap_getnext(pg_attribute_scan,
@@ -571,17 +575,15 @@ build_tupdesc_seq(RelationBuildDescInfo buildinfo,
 static void
 build_tupdesc_ind(RelationBuildDescInfo buildinfo,
 		  Relation	relation,
-		  AttributeTupleForm attp,
 		  u_int natts)
 {
     Relation attrel;
     HeapTuple atttup;
+    AttributeTupleForm	attp;
+    AttrDefault	*attrdef = NULL;
+    int ndef = 0;
     int i;
 
-    if (!relation->rd_att->constr)
-      relation->rd_att->constr = (AttrConstr *) palloc(sizeof(struct attrConstr));
-    relation->rd_att->constr->has_not_null = false;
-     
     attrel = heap_openr(AttributeRelationName);
     
     for (i = 1; i <= relation->rd_rel->relnatts; i++) {
@@ -589,8 +591,8 @@ build_tupdesc_ind(RelationBuildDescInfo buildinfo,
 	atttup = (HeapTuple) AttributeNumIndexScan(attrel, relation->rd_id, i);
 	
 	if (!HeapTupleIsValid(atttup))
-	    elog(WARN, "cannot find attribute %d of relation %.16s", i,
-		 &(relation->rd_rel->relname.data[0]));
+	    elog(WARN, "cannot find attribute %d of relation %.*s", i,
+		 NAMEDATALEN, &(relation->rd_rel->relname.data[0]));
 	attp = (AttributeTupleForm) GETSTRUCT(atttup);
 	
 	relation->rd_att->attrs[i - 1] = 
@@ -602,10 +604,33 @@ build_tupdesc_ind(RelationBuildDescInfo buildinfo,
 
 	/* Update if this attribute have a constraint */
 	if (attp->attnotnull)
-	  relation->rd_att->constr->has_not_null = true;
+	    relation->rd_att->constr->has_not_null = true;
+	
+	if (attp->atthasdef)
+	{
+	    if ( attrdef == NULL )
+	    	attrdef = (AttrDefault*) palloc (relation->rd_rel->relnatts *
+	    					sizeof (AttrDefault));
+	    attrdef[ndef].adnum = i;
+	    attrdef[ndef].adbin = NULL;
+	    attrdef[ndef].adsrc = NULL;
+	    ndef++;
+	}
     }
     
     heap_close(attrel);
+
+    if ( ndef > 0 )
+    {
+    	if ( ndef > relation->rd_rel->relnatts )
+    	    relation->rd_att->constr->defval = (AttrDefault*) 
+    	    		repalloc (attrdef, ndef * sizeof (AttrDefault));
+    	else
+    	    relation->rd_att->constr->defval = attrdef;
+    	relation->rd_att->constr->num_defval = ndef;
+    	AttrDefaultFetch (relation);
+    }
+    
 }
 
 /* --------------------------------
@@ -759,7 +784,6 @@ RelationBuildDesc(RelationBuildDescInfo buildinfo)
     Oid			relid;
     Oid			relam;
     Form_pg_class	relp;
-    AttributeTupleForm	attp = NULL;
     
     MemoryContext	oldcxt;
     
@@ -834,7 +858,7 @@ RelationBuildDesc(RelationBuildDescInfo buildinfo)
      *  already allocated for it by AllocateRelationDesc.
      * ----------------
      */
-    RelationBuildTupleDesc(buildinfo, relation, attp, natts);
+    RelationBuildTupleDesc(buildinfo, relation, natts);
 
     /* ----------------
      *  initialize rules that affect this relation
@@ -1346,7 +1370,7 @@ RelationIdInvalidateRelationCacheByRelationId(Oid relationId)
     }
 }
 
-#ifdef NOT_USED		/* See comments at line 1304 */
+#if NOT_USED		/* See comments at line 1304 */
 /* --------------------------------
  *	RelationIdInvalidateRelationCacheByAccessMethodId
  *
@@ -1576,6 +1600,95 @@ RelationInitialize(void)
     MemoryContextSwitchTo(oldcxt);
 }
 
+static void
+AttrDefaultFetch (Relation relation)
+{
+    AttrDefault *attrdef = relation->rd_att->constr->defval;
+    int ndef = relation->rd_att->constr->num_defval;
+    Relation adrel;
+    Relation irel;
+    ScanKeyData skey;
+    HeapTuple tuple;
+    Form_pg_attrdef adform;
+    IndexScanDesc sd;
+    RetrieveIndexResult indexRes;
+    Buffer buffer;
+    ItemPointer iptr;
+    struct varlena *val;
+    bool isnull;
+    int found;
+    int i;
+    
+    ScanKeyEntryInitialize(&skey,
+			   (bits16)0x0,
+			   (AttrNumber)1,
+			   (RegProcedure)ObjectIdEqualRegProcedure,
+			   ObjectIdGetDatum(relation->rd_id));
+    
+    adrel = heap_openr(AttrDefaultRelationName);
+    irel = index_openr(AttrDefaultIndex);
+    sd = index_beginscan(irel, false, 1, &skey);
+    tuple = (HeapTuple)NULL;
+    
+    for (found = 0; ; )
+    {
+	indexRes = index_getnext(sd, ForwardScanDirection);
+	if (!indexRes)
+	    break;
+	    
+	iptr = &indexRes->heap_iptr;
+	tuple = heap_fetch(adrel, NowTimeQual, iptr, &buffer);
+	pfree(indexRes);
+    	if (!HeapTupleIsValid(tuple))
+    	    continue;
+    	adform = (Form_pg_attrdef) GETSTRUCT(tuple);
+    	for (i = 1; i <= ndef; i++)
+    	{
+    	    if ( adform->adnum != attrdef[i].adnum )
+    	    	continue;
+    	    if ( attrdef[i].adsrc != NULL )
+    	    	    elog (WARN, "AttrDefaultFetch: second record found for attr %.*s in rel %.*s",
+    	    	    	NAMEDATALEN, relation->rd_att->attrs[adform->adnum - 1]->attname.data,
+    	    	    	NAMEDATALEN, relation->rd_rel->relname.data);
+    	    
+    	    val = (struct varlena*) fastgetattr (tuple, 
+    	    					Anum_pg_attrdef_adbin,
+    	    					adrel->rd_att, &isnull);
+    	    if ( isnull )
+    	    	elog (WARN, "AttrDefaultFetch: adbin IS NULL for attr %.*s in rel %.*s",
+    	    	    NAMEDATALEN, relation->rd_att->attrs[adform->adnum - 1]->attname.data,
+    	    	    NAMEDATALEN, relation->rd_rel->relname.data);
+    	    attrdef[i].adbin = textout (val);
+    	    val = (struct varlena*) fastgetattr (tuple, 
+    	    					Anum_pg_attrdef_adsrc,
+    	    					adrel->rd_att, &isnull);
+    	    if ( isnull )
+    	    	elog (WARN, "AttrDefaultFetch: adsrc IS NULL for attr %.*s in rel %.*s",
+    	    	    NAMEDATALEN, relation->rd_att->attrs[adform->adnum - 1]->attname.data,
+    	    	    NAMEDATALEN, relation->rd_rel->relname.data);
+    	    attrdef[i].adsrc = textout (val);
+    	    found++;
+    	}
+	
+    	if ( i > ndef )
+    	    elog (WARN, "AttrDefaultFetch: unexpected record found for attr %d in rel %.*s",
+    	    	    	adform->adnum,
+    	    	    	NAMEDATALEN, relation->rd_rel->relname.data);
+	ReleaseBuffer(buffer);
+    }
+    
+    if ( found < ndef )
+    	elog (WARN, "AttrDefaultFetch: %d record not found for rel %.*s",
+    	    	    	ndef - found,
+    	    	    	NAMEDATALEN, relation->rd_rel->relname.data);
+    
+    index_endscan (sd);
+    pfree (sd);
+    index_close (irel);
+    heap_close (adrel);
+    
+}
+
 /*
  *  init_irels(), write_irels() -- handle special-case initialization of
  *				   index relation descriptors.
-- 
2.40.0