|
|
|
|
@ -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. |
|
|
|
|
|