mirror of
				https://github.com/postgres/postgres.git
				synced 2025-11-03 09:13:20 +03:00 
			
		
		
		
	Fetch information about DEFAULT/CHECK while openning a relation.
This commit is contained in:
		
							
								
								
									
										157
									
								
								src/backend/utils/cache/relcache.c
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										157
									
								
								src/backend/utils/cache/relcache.c
									
									
									
									
										vendored
									
									
								
							@@ -7,7 +7,7 @@
 | 
			
		||||
 *
 | 
			
		||||
 *
 | 
			
		||||
 * IDENTIFICATION
 | 
			
		||||
 *    $Header: /cvsroot/pgsql/src/backend/utils/cache/relcache.c,v 1.18 1997/08/21 04:09:51 vadim Exp $
 | 
			
		||||
 *    $Header: /cvsroot/pgsql/src/backend/utils/cache/relcache.c,v 1.19 1997/08/22 03:35:44 vadim Exp $
 | 
			
		||||
 *
 | 
			
		||||
 *-------------------------------------------------------------------------
 | 
			
		||||
 */
 | 
			
		||||
@@ -82,6 +82,7 @@
 | 
			
		||||
#include "catalog/pg_log.h"
 | 
			
		||||
#include "catalog/pg_time.h"
 | 
			
		||||
#include "catalog/pg_attrdef.h"
 | 
			
		||||
#include "catalog/pg_relcheck.h"
 | 
			
		||||
#include "catalog/indexing.h"
 | 
			
		||||
#include "catalog/index.h"
 | 
			
		||||
#include "fmgr.h"
 | 
			
		||||
@@ -260,6 +261,7 @@ static void build_tupdesc_ind(RelationBuildDescInfo buildinfo,
 | 
			
		||||
static Relation RelationBuildDesc(RelationBuildDescInfo buildinfo);
 | 
			
		||||
static void IndexedAccessMethodInitialize(Relation relation);
 | 
			
		||||
static void AttrDefaultFetch (Relation relation);
 | 
			
		||||
static void RelCheckFetch (Relation relation);
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * newlyCreatedRelns -
 | 
			
		||||
@@ -482,7 +484,7 @@ AllocateRelationDesc(u_int natts, Form_pg_class relp)
 | 
			
		||||
 *	RelationBuildTupleDesc
 | 
			
		||||
 *
 | 
			
		||||
 *	Form the relation's tuple descriptor from information in
 | 
			
		||||
 *	the pg_attribute system catalog.
 | 
			
		||||
 *	the pg_attribute, pg_attrdef & pg_relcheck system cataloges.
 | 
			
		||||
 * --------------------------------
 | 
			
		||||
 */
 | 
			
		||||
static void
 | 
			
		||||
@@ -499,13 +501,7 @@ RelationBuildTupleDesc(RelationBuildDescInfo buildinfo,
 | 
			
		||||
    if (IsBootstrapProcessingMode())
 | 
			
		||||
	build_tupdesc_seq(buildinfo, relation, natts);
 | 
			
		||||
    else
 | 
			
		||||
    {
 | 
			
		||||
    	relation->rd_att->constr = (TupleConstr *) palloc(sizeof(TupleConstr));
 | 
			
		||||
    	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
 | 
			
		||||
@@ -580,10 +576,13 @@ build_tupdesc_ind(RelationBuildDescInfo buildinfo,
 | 
			
		||||
    Relation attrel;
 | 
			
		||||
    HeapTuple atttup;
 | 
			
		||||
    AttributeTupleForm	attp;
 | 
			
		||||
    TupleConstr *constr = (TupleConstr *) palloc(sizeof(TupleConstr));
 | 
			
		||||
    AttrDefault	*attrdef = NULL;
 | 
			
		||||
    int ndef = 0;
 | 
			
		||||
    int i;
 | 
			
		||||
 | 
			
		||||
    
 | 
			
		||||
    constr->has_not_null = false;
 | 
			
		||||
    
 | 
			
		||||
    attrel = heap_openr(AttributeRelationName);
 | 
			
		||||
    
 | 
			
		||||
    for (i = 1; i <= relation->rd_rel->relnatts; i++) {
 | 
			
		||||
@@ -604,7 +603,7 @@ build_tupdesc_ind(RelationBuildDescInfo buildinfo,
 | 
			
		||||
 | 
			
		||||
	/* Update if this attribute have a constraint */
 | 
			
		||||
	if (attp->attnotnull)
 | 
			
		||||
	    relation->rd_att->constr->has_not_null = true;
 | 
			
		||||
	    constr->has_not_null = true;
 | 
			
		||||
	
 | 
			
		||||
	if (attp->atthasdef)
 | 
			
		||||
	{
 | 
			
		||||
@@ -619,16 +618,39 @@ build_tupdesc_ind(RelationBuildDescInfo buildinfo,
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    heap_close(attrel);
 | 
			
		||||
 | 
			
		||||
    if ( ndef > 0 )
 | 
			
		||||
    
 | 
			
		||||
    if ( constr->has_not_null || ndef > 0 || relation->rd_rel->relchecks )
 | 
			
		||||
    {
 | 
			
		||||
    	if ( ndef > relation->rd_rel->relnatts )
 | 
			
		||||
    	    relation->rd_att->constr->defval = (AttrDefault*) 
 | 
			
		||||
    	relation->rd_att->constr = constr;
 | 
			
		||||
    	
 | 
			
		||||
    	if ( ndef > 0 )					/* DEFAULTs */
 | 
			
		||||
    	{
 | 
			
		||||
    	    if ( ndef < relation->rd_rel->relnatts )
 | 
			
		||||
    	    	constr->defval = (AttrDefault*) 
 | 
			
		||||
    	    		repalloc (attrdef, ndef * sizeof (AttrDefault));
 | 
			
		||||
    	    else
 | 
			
		||||
    	    	constr->defval = attrdef;
 | 
			
		||||
    	    constr->num_defval = ndef;
 | 
			
		||||
    	    AttrDefaultFetch (relation);
 | 
			
		||||
    	}
 | 
			
		||||
    	else
 | 
			
		||||
    	    relation->rd_att->constr->defval = attrdef;
 | 
			
		||||
    	relation->rd_att->constr->num_defval = ndef;
 | 
			
		||||
    	AttrDefaultFetch (relation);
 | 
			
		||||
    	    constr->num_defval = 0;
 | 
			
		||||
    	
 | 
			
		||||
	if ( relation->rd_rel->relchecks > 0 )		/* CHECKs */
 | 
			
		||||
	{
 | 
			
		||||
	    constr->num_check = relation->rd_rel->relchecks;
 | 
			
		||||
	    constr->check = (ConstrCheck *) palloc (constr->num_check * 
 | 
			
		||||
	    						sizeof (ConstrCheck));
 | 
			
		||||
	    memset (constr->check, 0, constr->num_check * sizeof (ConstrCheck));
 | 
			
		||||
	    RelCheckFetch (relation);
 | 
			
		||||
	}
 | 
			
		||||
	else
 | 
			
		||||
	    constr->num_check = 0;
 | 
			
		||||
    }
 | 
			
		||||
    else
 | 
			
		||||
    {
 | 
			
		||||
    	pfree (constr);
 | 
			
		||||
    	relation->rd_att->constr = NULL;
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
}
 | 
			
		||||
@@ -1252,8 +1274,6 @@ static void
 | 
			
		||||
RelationFlushRelation(Relation *relationPtr,
 | 
			
		||||
		      bool onlyFlushReferenceCountZero)
 | 
			
		||||
{
 | 
			
		||||
    int			i;
 | 
			
		||||
    AttributeTupleForm	*p;
 | 
			
		||||
    MemoryContext	oldcxt;
 | 
			
		||||
    Relation 		relation = *relationPtr;
 | 
			
		||||
    
 | 
			
		||||
@@ -1268,14 +1288,8 @@ RelationFlushRelation(Relation *relationPtr,
 | 
			
		||||
	oldcxt = MemoryContextSwitchTo((MemoryContext)CacheCxt);
 | 
			
		||||
	
 | 
			
		||||
	RelationCacheDelete(relation);
 | 
			
		||||
 | 
			
		||||
	p = relation->rd_att->attrs;
 | 
			
		||||
	for (i = 0; i < relation->rd_rel->relnatts; i++, p++)
 | 
			
		||||
	    pfree (*p);
 | 
			
		||||
	pfree (relation->rd_att->attrs);
 | 
			
		||||
        if (relation->rd_att->constr)
 | 
			
		||||
           pfree (relation->rd_att->constr);
 | 
			
		||||
        pfree (relation->rd_att);
 | 
			
		||||
	
 | 
			
		||||
	FreeTupleDesc (relation->rd_att);
 | 
			
		||||
 | 
			
		||||
#if 0
 | 
			
		||||
	if (relation->rd_rules) {
 | 
			
		||||
@@ -1641,8 +1655,9 @@ AttrDefaultFetch (Relation relation)
 | 
			
		||||
	pfree(indexRes);
 | 
			
		||||
    	if (!HeapTupleIsValid(tuple))
 | 
			
		||||
    	    continue;
 | 
			
		||||
    	found++;
 | 
			
		||||
    	adform = (Form_pg_attrdef) GETSTRUCT(tuple);
 | 
			
		||||
    	for (i = 1; i <= ndef; i++)
 | 
			
		||||
    	for (i = 0; i < ndef; i++)
 | 
			
		||||
    	{
 | 
			
		||||
    	    if ( adform->adnum != attrdef[i].adnum )
 | 
			
		||||
    	    	continue;
 | 
			
		||||
@@ -1667,10 +1682,10 @@ AttrDefaultFetch (Relation relation)
 | 
			
		||||
    	    	    NAMEDATALEN, relation->rd_att->attrs[adform->adnum - 1]->attname.data,
 | 
			
		||||
    	    	    NAMEDATALEN, relation->rd_rel->relname.data);
 | 
			
		||||
    	    attrdef[i].adsrc = textout (val);
 | 
			
		||||
    	    found++;
 | 
			
		||||
    	    break;
 | 
			
		||||
    	}
 | 
			
		||||
	
 | 
			
		||||
    	if ( i > ndef )
 | 
			
		||||
    	if ( i >= ndef )
 | 
			
		||||
    	    elog (WARN, "AttrDefaultFetch: unexpected record found for attr %d in rel %.*s",
 | 
			
		||||
    	    	    	adform->adnum,
 | 
			
		||||
    	    	    	NAMEDATALEN, relation->rd_rel->relname.data);
 | 
			
		||||
@@ -1689,6 +1704,88 @@ AttrDefaultFetch (Relation relation)
 | 
			
		||||
    
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
RelCheckFetch (Relation relation)
 | 
			
		||||
{
 | 
			
		||||
    ConstrCheck *check = relation->rd_att->constr->check;
 | 
			
		||||
    int ncheck = relation->rd_att->constr->num_check;
 | 
			
		||||
    Relation rcrel;
 | 
			
		||||
    Relation irel;
 | 
			
		||||
    ScanKeyData skey;
 | 
			
		||||
    HeapTuple tuple;
 | 
			
		||||
    IndexScanDesc sd;
 | 
			
		||||
    RetrieveIndexResult indexRes;
 | 
			
		||||
    Buffer buffer;
 | 
			
		||||
    ItemPointer iptr;
 | 
			
		||||
    Name rcname;
 | 
			
		||||
    struct varlena *val;
 | 
			
		||||
    bool isnull;
 | 
			
		||||
    int found;
 | 
			
		||||
    
 | 
			
		||||
    ScanKeyEntryInitialize(&skey,
 | 
			
		||||
			   (bits16)0x0,
 | 
			
		||||
			   (AttrNumber)1,
 | 
			
		||||
			   (RegProcedure)ObjectIdEqualRegProcedure,
 | 
			
		||||
			   ObjectIdGetDatum(relation->rd_id));
 | 
			
		||||
    
 | 
			
		||||
    rcrel = heap_openr(RelCheckRelationName);
 | 
			
		||||
    irel = index_openr(RelCheckIndex);
 | 
			
		||||
    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(rcrel, NowTimeQual, iptr, &buffer);
 | 
			
		||||
	pfree(indexRes);
 | 
			
		||||
    	if (!HeapTupleIsValid(tuple))
 | 
			
		||||
    	    continue;
 | 
			
		||||
    	if ( found == ncheck )
 | 
			
		||||
    	    elog (WARN, "RelCheckFetch: unexpected record found for rel %.*s",
 | 
			
		||||
    	    	    	NAMEDATALEN, relation->rd_rel->relname.data);
 | 
			
		||||
    	
 | 
			
		||||
    	rcname = (Name) fastgetattr (tuple, 
 | 
			
		||||
    	    				Anum_pg_relcheck_rcname,
 | 
			
		||||
    	    				rcrel->rd_att, &isnull);
 | 
			
		||||
    	if ( isnull )
 | 
			
		||||
    	    elog (WARN, "RelCheckFetch: rcname IS NULL for rel %.*s",
 | 
			
		||||
    	    	    NAMEDATALEN, relation->rd_rel->relname.data);
 | 
			
		||||
    	check[found].ccname = nameout (rcname);
 | 
			
		||||
    	val = (struct varlena*) fastgetattr (tuple, 
 | 
			
		||||
    	    					Anum_pg_relcheck_rcbin,
 | 
			
		||||
    	    					rcrel->rd_att, &isnull);
 | 
			
		||||
    	if ( isnull )
 | 
			
		||||
    	    elog (WARN, "RelCheckFetch: rcbin IS NULL for rel %.*s",
 | 
			
		||||
    	    	    NAMEDATALEN, relation->rd_rel->relname.data);
 | 
			
		||||
    	check[found].ccbin = textout (val);
 | 
			
		||||
    	val = (struct varlena*) fastgetattr (tuple, 
 | 
			
		||||
    	    					Anum_pg_relcheck_rcsrc,
 | 
			
		||||
    	    					rcrel->rd_att, &isnull);
 | 
			
		||||
    	if ( isnull )
 | 
			
		||||
    	    elog (WARN, "RelCheckFetch: rcsrc IS NULL for rel %.*s",
 | 
			
		||||
    	    	    NAMEDATALEN, relation->rd_rel->relname.data);
 | 
			
		||||
    	check[found].ccsrc = textout (val);
 | 
			
		||||
    	found++;
 | 
			
		||||
	
 | 
			
		||||
	ReleaseBuffer(buffer);
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    if ( found < ncheck )
 | 
			
		||||
    	elog (WARN, "RelCheckFetch: %d record not found for rel %.*s",
 | 
			
		||||
    	    	    	ncheck - found,
 | 
			
		||||
    	    	    	NAMEDATALEN, relation->rd_rel->relname.data);
 | 
			
		||||
    
 | 
			
		||||
    index_endscan (sd);
 | 
			
		||||
    pfree (sd);
 | 
			
		||||
    index_close (irel);
 | 
			
		||||
    heap_close (rcrel);
 | 
			
		||||
    
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 *  init_irels(), write_irels() -- handle special-case initialization of
 | 
			
		||||
 *				   index relation descriptors.
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user