Commit 24b130cb authored by Tom Lane's avatar Tom Lane

Add relcache support for system catalogs with attnotnull columns.

The code was not making TupleConstr structs for such catalogs in
several places; with the consequence that the not-null constraint
wasn't actually enforced.  With this change,
INSERT INTO pg_proc VALUES('sdf');
generates a 'Fail to add null value' error instead of a core dump.
parent 4bc3598a
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/utils/cache/relcache.c,v 1.180 2002/11/13 00:39:47 momjian Exp $ * $Header: /cvsroot/pgsql/src/backend/utils/cache/relcache.c,v 1.181 2002/11/15 17:18:49 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -1333,8 +1333,8 @@ LookupOpclassInfo(Oid operatorClassOid, ...@@ -1333,8 +1333,8 @@ LookupOpclassInfo(Oid operatorClassOid,
* formrdesc is currently used for: pg_class, pg_attribute, pg_proc, * formrdesc is currently used for: pg_class, pg_attribute, pg_proc,
* and pg_type (see RelationCacheInitialize). * and pg_type (see RelationCacheInitialize).
* *
* Note that these catalogs can't have constraints, default values, * Note that these catalogs can't have constraints (except attnotnull),
* rules, or triggers, since we don't cope with any of that. * default values, rules, or triggers, since we don't cope with any of that.
* *
* NOTE: we assume we are already switched into CacheMemoryContext. * NOTE: we assume we are already switched into CacheMemoryContext.
*/ */
...@@ -1345,6 +1345,7 @@ formrdesc(const char *relationName, ...@@ -1345,6 +1345,7 @@ formrdesc(const char *relationName,
{ {
Relation relation; Relation relation;
int i; int i;
bool has_not_null;
/* /*
* allocate new relation desc * allocate new relation desc
...@@ -1408,12 +1409,14 @@ formrdesc(const char *relationName, ...@@ -1408,12 +1409,14 @@ formrdesc(const char *relationName,
/* /*
* initialize tuple desc info * initialize tuple desc info
*/ */
has_not_null = false;
for (i = 0; i < natts; i++) for (i = 0; i < natts; i++)
{ {
relation->rd_att->attrs[i] = (Form_pg_attribute) palloc(ATTRIBUTE_TUPLE_SIZE); relation->rd_att->attrs[i] = (Form_pg_attribute) palloc(ATTRIBUTE_TUPLE_SIZE);
memcpy((char *) relation->rd_att->attrs[i], memcpy((char *) relation->rd_att->attrs[i],
(char *) &att[i], (char *) &att[i],
ATTRIBUTE_TUPLE_SIZE); ATTRIBUTE_TUPLE_SIZE);
has_not_null |= att[i].attnotnull;
/* make sure attcacheoff is valid */ /* make sure attcacheoff is valid */
relation->rd_att->attrs[i]->attcacheoff = -1; relation->rd_att->attrs[i]->attcacheoff = -1;
} }
...@@ -1421,6 +1424,15 @@ formrdesc(const char *relationName, ...@@ -1421,6 +1424,15 @@ formrdesc(const char *relationName,
/* initialize first attribute's attcacheoff, cf RelationBuildTupleDesc */ /* initialize first attribute's attcacheoff, cf RelationBuildTupleDesc */
relation->rd_att->attrs[0]->attcacheoff = 0; relation->rd_att->attrs[0]->attcacheoff = 0;
/* mark not-null status */
if (has_not_null)
{
TupleConstr *constr = (TupleConstr *) palloc0(sizeof(TupleConstr));
constr->has_not_null = true;
relation->rd_att->constr = constr;
}
/* /*
* initialize relation id from info in att array (my, this is ugly) * initialize relation id from info in att array (my, this is ugly)
*/ */
...@@ -2035,6 +2047,7 @@ RelationBuildLocalRelation(const char *relname, ...@@ -2035,6 +2047,7 @@ RelationBuildLocalRelation(const char *relname,
MemoryContext oldcxt; MemoryContext oldcxt;
int natts = tupDesc->natts; int natts = tupDesc->natts;
int i; int i;
bool has_not_null;
AssertArg(natts > 0); AssertArg(natts > 0);
...@@ -2081,8 +2094,20 @@ RelationBuildLocalRelation(const char *relname, ...@@ -2081,8 +2094,20 @@ RelationBuildLocalRelation(const char *relname,
* however. * however.
*/ */
rel->rd_att = CreateTupleDescCopy(tupDesc); rel->rd_att = CreateTupleDescCopy(tupDesc);
has_not_null = false;
for (i = 0; i < natts; i++) for (i = 0; i < natts; i++)
{
rel->rd_att->attrs[i]->attnotnull = tupDesc->attrs[i]->attnotnull; rel->rd_att->attrs[i]->attnotnull = tupDesc->attrs[i]->attnotnull;
has_not_null |= tupDesc->attrs[i]->attnotnull;
}
if (has_not_null)
{
TupleConstr *constr = (TupleConstr *) palloc0(sizeof(TupleConstr));
constr->has_not_null = true;
rel->rd_att->constr = constr;
}
/* /*
* initialize relation tuple form (caller may add/override data later) * initialize relation tuple form (caller may add/override data later)
...@@ -2723,6 +2748,7 @@ load_relcache_init_file(void) ...@@ -2723,6 +2748,7 @@ load_relcache_init_file(void)
size_t nread; size_t nread;
Relation rel; Relation rel;
Form_pg_class relform; Form_pg_class relform;
bool has_not_null;
/* first read the relation descriptor length */ /* first read the relation descriptor length */
if ((nread = fread(&len, 1, sizeof(len), fp)) != sizeof(len)) if ((nread = fread(&len, 1, sizeof(len), fp)) != sizeof(len))
...@@ -2764,6 +2790,7 @@ load_relcache_init_file(void) ...@@ -2764,6 +2790,7 @@ load_relcache_init_file(void)
relform->relhasoids); relform->relhasoids);
/* next read all the attribute tuple form data entries */ /* next read all the attribute tuple form data entries */
has_not_null = false;
for (i = 0; i < relform->relnatts; i++) for (i = 0; i < relform->relnatts; i++)
{ {
if ((nread = fread(&len, 1, sizeof(len), fp)) != sizeof(len)) if ((nread = fread(&len, 1, sizeof(len), fp)) != sizeof(len))
...@@ -2773,6 +2800,17 @@ load_relcache_init_file(void) ...@@ -2773,6 +2800,17 @@ load_relcache_init_file(void)
if ((nread = fread(rel->rd_att->attrs[i], 1, len, fp)) != len) if ((nread = fread(rel->rd_att->attrs[i], 1, len, fp)) != len)
goto read_failed; goto read_failed;
has_not_null |= rel->rd_att->attrs[i]->attnotnull;
}
/* mark not-null status */
if (has_not_null)
{
TupleConstr *constr = (TupleConstr *) palloc0(sizeof(TupleConstr));
constr->has_not_null = true;
rel->rd_att->constr = constr;
} }
/* If it's an index, there's more to do */ /* If it's an index, there's more to do */
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment