mirror of
https://github.com/postgres/postgres.git
synced 2025-07-03 20:02:46 +03:00
Read info for DEFAULT from pg_attrdef.
This commit is contained in:
193
src/backend/utils/cache/relcache.c
vendored
193
src/backend/utils/cache/relcache.c
vendored
@ -7,7 +7,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* 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_variable.h"
|
||||||
#include "catalog/pg_log.h"
|
#include "catalog/pg_log.h"
|
||||||
#include "catalog/pg_time.h"
|
#include "catalog/pg_time.h"
|
||||||
|
#include "catalog/pg_attrdef.h"
|
||||||
#include "catalog/indexing.h"
|
#include "catalog/indexing.h"
|
||||||
#include "catalog/index.h"
|
#include "catalog/index.h"
|
||||||
#include "fmgr.h"
|
#include "fmgr.h"
|
||||||
@ -90,22 +91,6 @@ static void RelationFlushRelation(Relation *relationPtr,
|
|||||||
static Relation RelationNameCacheGetRelation(char *relationName);
|
static Relation RelationNameCacheGetRelation(char *relationName);
|
||||||
static void init_irels(void);
|
static void init_irels(void);
|
||||||
static void write_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
|
* 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 -
|
* newlyCreatedRelns -
|
||||||
* relations created during this transaction. We need to keep track of
|
* 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
|
* BuildDescInfoError returns a string appropriate to
|
||||||
* the buildinfo passed to it
|
* the buildinfo passed to it
|
||||||
@ -481,7 +488,6 @@ AllocateRelationDesc(u_int natts, Form_pg_class relp)
|
|||||||
static void
|
static void
|
||||||
RelationBuildTupleDesc(RelationBuildDescInfo buildinfo,
|
RelationBuildTupleDesc(RelationBuildDescInfo buildinfo,
|
||||||
Relation relation,
|
Relation relation,
|
||||||
AttributeTupleForm attp,
|
|
||||||
u_int natts)
|
u_int natts)
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
@ -491,20 +497,26 @@ RelationBuildTupleDesc(RelationBuildDescInfo buildinfo,
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
if (IsBootstrapProcessingMode())
|
if (IsBootstrapProcessingMode())
|
||||||
build_tupdesc_seq(buildinfo, relation, attp, natts);
|
build_tupdesc_seq(buildinfo, relation, natts);
|
||||||
else
|
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
|
static void
|
||||||
build_tupdesc_seq(RelationBuildDescInfo buildinfo,
|
build_tupdesc_seq(RelationBuildDescInfo buildinfo,
|
||||||
Relation relation,
|
Relation relation,
|
||||||
AttributeTupleForm attp,
|
|
||||||
u_int natts)
|
u_int natts)
|
||||||
{
|
{
|
||||||
HeapTuple pg_attribute_tuple;
|
HeapTuple pg_attribute_tuple;
|
||||||
Relation pg_attribute_desc;
|
Relation pg_attribute_desc;
|
||||||
HeapScanDesc pg_attribute_scan;
|
HeapScanDesc pg_attribute_scan;
|
||||||
|
AttributeTupleForm attp;
|
||||||
ScanKeyData key;
|
ScanKeyData key;
|
||||||
int need;
|
int need;
|
||||||
|
|
||||||
@ -530,9 +542,6 @@ build_tupdesc_seq(RelationBuildDescInfo buildinfo,
|
|||||||
* ----------------
|
* ----------------
|
||||||
*/
|
*/
|
||||||
need = natts;
|
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);
|
pg_attribute_tuple = heap_getnext(pg_attribute_scan, 0, (Buffer *) NULL);
|
||||||
while (HeapTupleIsValid(pg_attribute_tuple) && need > 0) {
|
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]),
|
memmove((char *) (relation->rd_att->attrs[attp->attnum - 1]),
|
||||||
(char *) attp,
|
(char *) attp,
|
||||||
ATTRIBUTE_TUPLE_SIZE);
|
ATTRIBUTE_TUPLE_SIZE);
|
||||||
|
|
||||||
/* Update if this attribute have a constraint */
|
|
||||||
if (attp->attnotnull)
|
|
||||||
relation->rd_att->constr->has_not_null = true;
|
|
||||||
|
|
||||||
need--;
|
need--;
|
||||||
}
|
}
|
||||||
pg_attribute_tuple = heap_getnext(pg_attribute_scan,
|
pg_attribute_tuple = heap_getnext(pg_attribute_scan,
|
||||||
@ -571,17 +575,15 @@ build_tupdesc_seq(RelationBuildDescInfo buildinfo,
|
|||||||
static void
|
static void
|
||||||
build_tupdesc_ind(RelationBuildDescInfo buildinfo,
|
build_tupdesc_ind(RelationBuildDescInfo buildinfo,
|
||||||
Relation relation,
|
Relation relation,
|
||||||
AttributeTupleForm attp,
|
|
||||||
u_int natts)
|
u_int natts)
|
||||||
{
|
{
|
||||||
Relation attrel;
|
Relation attrel;
|
||||||
HeapTuple atttup;
|
HeapTuple atttup;
|
||||||
|
AttributeTupleForm attp;
|
||||||
|
AttrDefault *attrdef = NULL;
|
||||||
|
int ndef = 0;
|
||||||
int i;
|
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);
|
attrel = heap_openr(AttributeRelationName);
|
||||||
|
|
||||||
for (i = 1; i <= relation->rd_rel->relnatts; i++) {
|
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);
|
atttup = (HeapTuple) AttributeNumIndexScan(attrel, relation->rd_id, i);
|
||||||
|
|
||||||
if (!HeapTupleIsValid(atttup))
|
if (!HeapTupleIsValid(atttup))
|
||||||
elog(WARN, "cannot find attribute %d of relation %.16s", i,
|
elog(WARN, "cannot find attribute %d of relation %.*s", i,
|
||||||
&(relation->rd_rel->relname.data[0]));
|
NAMEDATALEN, &(relation->rd_rel->relname.data[0]));
|
||||||
attp = (AttributeTupleForm) GETSTRUCT(atttup);
|
attp = (AttributeTupleForm) GETSTRUCT(atttup);
|
||||||
|
|
||||||
relation->rd_att->attrs[i - 1] =
|
relation->rd_att->attrs[i - 1] =
|
||||||
@ -603,9 +605,32 @@ build_tupdesc_ind(RelationBuildDescInfo buildinfo,
|
|||||||
/* Update if this attribute have a constraint */
|
/* Update if this attribute have a constraint */
|
||||||
if (attp->attnotnull)
|
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);
|
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 relid;
|
||||||
Oid relam;
|
Oid relam;
|
||||||
Form_pg_class relp;
|
Form_pg_class relp;
|
||||||
AttributeTupleForm attp = NULL;
|
|
||||||
|
|
||||||
MemoryContext oldcxt;
|
MemoryContext oldcxt;
|
||||||
|
|
||||||
@ -834,7 +858,7 @@ RelationBuildDesc(RelationBuildDescInfo buildinfo)
|
|||||||
* already allocated for it by AllocateRelationDesc.
|
* already allocated for it by AllocateRelationDesc.
|
||||||
* ----------------
|
* ----------------
|
||||||
*/
|
*/
|
||||||
RelationBuildTupleDesc(buildinfo, relation, attp, natts);
|
RelationBuildTupleDesc(buildinfo, relation, natts);
|
||||||
|
|
||||||
/* ----------------
|
/* ----------------
|
||||||
* initialize rules that affect this relation
|
* 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
|
* RelationIdInvalidateRelationCacheByAccessMethodId
|
||||||
*
|
*
|
||||||
@ -1576,6 +1600,95 @@ RelationInitialize(void)
|
|||||||
MemoryContextSwitchTo(oldcxt);
|
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
|
* init_irels(), write_irels() -- handle special-case initialization of
|
||||||
* index relation descriptors.
|
* index relation descriptors.
|
||||||
|
Reference in New Issue
Block a user