Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit 24b130c

Browse files
committed
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.
1 parent 4bc3598 commit 24b130c

File tree

1 file changed

+41
-3
lines changed

1 file changed

+41
-3
lines changed

src/backend/utils/cache/relcache.c

Lines changed: 41 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
*
99
*
1010
* IDENTIFICATION
11-
* $Header: /cvsroot/pgsql/src/backend/utils/cache/relcache.c,v 1.180 2002/11/13 00:39:47 momjian Exp $
11+
* $Header: /cvsroot/pgsql/src/backend/utils/cache/relcache.c,v 1.181 2002/11/15 17:18:49 tgl Exp $
1212
*
1313
*-------------------------------------------------------------------------
1414
*/
@@ -1333,8 +1333,8 @@ LookupOpclassInfo(Oid operatorClassOid,
13331333
* formrdesc is currently used for: pg_class, pg_attribute, pg_proc,
13341334
* and pg_type (see RelationCacheInitialize).
13351335
*
1336-
* Note that these catalogs can't have constraints, default values,
1337-
* rules, or triggers, since we don't cope with any of that.
1336+
* Note that these catalogs can't have constraints (except attnotnull),
1337+
* default values, rules, or triggers, since we don't cope with any of that.
13381338
*
13391339
* NOTE: we assume we are already switched into CacheMemoryContext.
13401340
*/
@@ -1345,6 +1345,7 @@ formrdesc(const char *relationName,
13451345
{
13461346
Relation relation;
13471347
int i;
1348+
bool has_not_null;
13481349

13491350
/*
13501351
* allocate new relation desc
@@ -1408,19 +1409,30 @@ formrdesc(const char *relationName,
14081409
/*
14091410
* initialize tuple desc info
14101411
*/
1412+
has_not_null = false;
14111413
for (i = 0; i < natts; i++)
14121414
{
14131415
relation->rd_att->attrs[i] = (Form_pg_attribute) palloc(ATTRIBUTE_TUPLE_SIZE);
14141416
memcpy((char *) relation->rd_att->attrs[i],
14151417
(char *) &att[i],
14161418
ATTRIBUTE_TUPLE_SIZE);
1419+
has_not_null |= att[i].attnotnull;
14171420
/* make sure attcacheoff is valid */
14181421
relation->rd_att->attrs[i]->attcacheoff = -1;
14191422
}
14201423

14211424
/* initialize first attribute's attcacheoff, cf RelationBuildTupleDesc */
14221425
relation->rd_att->attrs[0]->attcacheoff = 0;
14231426

1427+
/* mark not-null status */
1428+
if (has_not_null)
1429+
{
1430+
TupleConstr *constr = (TupleConstr *) palloc0(sizeof(TupleConstr));
1431+
1432+
constr->has_not_null = true;
1433+
relation->rd_att->constr = constr;
1434+
}
1435+
14241436
/*
14251437
* initialize relation id from info in att array (my, this is ugly)
14261438
*/
@@ -2035,6 +2047,7 @@ RelationBuildLocalRelation(const char *relname,
20352047
MemoryContext oldcxt;
20362048
int natts = tupDesc->natts;
20372049
int i;
2050+
bool has_not_null;
20382051

20392052
AssertArg(natts > 0);
20402053

@@ -2081,8 +2094,20 @@ RelationBuildLocalRelation(const char *relname,
20812094
* however.
20822095
*/
20832096
rel->rd_att = CreateTupleDescCopy(tupDesc);
2097+
has_not_null = false;
20842098
for (i = 0; i < natts; i++)
2099+
{
20852100
rel->rd_att->attrs[i]->attnotnull = tupDesc->attrs[i]->attnotnull;
2101+
has_not_null |= tupDesc->attrs[i]->attnotnull;
2102+
}
2103+
2104+
if (has_not_null)
2105+
{
2106+
TupleConstr *constr = (TupleConstr *) palloc0(sizeof(TupleConstr));
2107+
2108+
constr->has_not_null = true;
2109+
rel->rd_att->constr = constr;
2110+
}
20862111

20872112
/*
20882113
* initialize relation tuple form (caller may add/override data later)
@@ -2723,6 +2748,7 @@ load_relcache_init_file(void)
27232748
size_t nread;
27242749
Relation rel;
27252750
Form_pg_class relform;
2751+
bool has_not_null;
27262752

27272753
/* first read the relation descriptor length */
27282754
if ((nread = fread(&len, 1, sizeof(len), fp)) != sizeof(len))
@@ -2764,6 +2790,7 @@ load_relcache_init_file(void)
27642790
relform->relhasoids);
27652791

27662792
/* next read all the attribute tuple form data entries */
2793+
has_not_null = false;
27672794
for (i = 0; i < relform->relnatts; i++)
27682795
{
27692796
if ((nread = fread(&len, 1, sizeof(len), fp)) != sizeof(len))
@@ -2773,6 +2800,17 @@ load_relcache_init_file(void)
27732800

27742801
if ((nread = fread(rel->rd_att->attrs[i], 1, len, fp)) != len)
27752802
goto read_failed;
2803+
2804+
has_not_null |= rel->rd_att->attrs[i]->attnotnull;
2805+
}
2806+
2807+
/* mark not-null status */
2808+
if (has_not_null)
2809+
{
2810+
TupleConstr *constr = (TupleConstr *) palloc0(sizeof(TupleConstr));
2811+
2812+
constr->has_not_null = true;
2813+
rel->rd_att->constr = constr;
27762814
}
27772815

27782816
/* If it's an index, there's more to do */

0 commit comments

Comments
 (0)