aboutsummaryrefslogtreecommitdiff
path: root/src/backend
diff options
context:
space:
mode:
authorTom Lane <tgl@sss.pgh.pa.us>2020-07-21 13:03:48 -0400
committerTom Lane <tgl@sss.pgh.pa.us>2020-07-21 13:03:48 -0400
commitfc032bed2fb809ee69eaf2fece349f65274c876f (patch)
treeffa25e5ca8c23870892aaf0b8b292b46637de7aa /src/backend
parent3e66019f15549d3e1e13da665b2549684061d630 (diff)
downloadpostgresql-fc032bed2fb809ee69eaf2fece349f65274c876f.tar.gz
postgresql-fc032bed2fb809ee69eaf2fece349f65274c876f.zip
Be more careful about marking catalog columns NOT NULL by default.
The bug fixed in commit 72eab84a5 would not have occurred if initdb had a less surprising rule about which columns should be marked NOT NULL by default. Let's make that rule be strictly that the column must be fixed-width and its predecessors must be fixed-width and NOT NULL, removing the hacky and unsafe exceptions for oidvector and int2vector. Since we do still want all existing oidvector and int2vector columns to be marked NOT NULL, we have to put BKI_FORCE_NOT_NULL labels on them. But making this less magic and more documented seems like a good idea, even if it's a shade more verbose. I didn't bump catversion since the initial catalog contents are not actually changed by this patch. Note however that the contents of postgres.bki do change, and feeding an old copy of that to a new backend will produce wrong results. Discussion: https://postgr.es/m/204760.1595181800@sss.pgh.pa.us
Diffstat (limited to 'src/backend')
-rw-r--r--src/backend/bootstrap/bootstrap.c17
-rw-r--r--src/backend/catalog/genbki.pl33
2 files changed, 23 insertions, 27 deletions
diff --git a/src/backend/bootstrap/bootstrap.c b/src/backend/bootstrap/bootstrap.c
index 5480a024e05..45b7efbe465 100644
--- a/src/backend/bootstrap/bootstrap.c
+++ b/src/backend/bootstrap/bootstrap.c
@@ -770,25 +770,18 @@ DefineAttr(char *name, char *type, int attnum, int nullness)
/*
* Mark as "not null" if type is fixed-width and prior columns are
- * too. This corresponds to case where column can be accessed
- * directly via C struct declaration.
- *
- * oidvector and int2vector are also treated as not-nullable, even
- * though they are no longer fixed-width.
+ * likewise fixed-width and not-null. This corresponds to case where
+ * column can be accessed directly via C struct declaration.
*/
-#define MARKNOTNULL(att) \
- ((att)->attlen > 0 || \
- (att)->atttypid == OIDVECTOROID || \
- (att)->atttypid == INT2VECTOROID)
-
- if (MARKNOTNULL(attrtypes[attnum]))
+ if (attrtypes[attnum]->attlen > 0)
{
int i;
/* check earlier attributes */
for (i = 0; i < attnum; i++)
{
- if (!attrtypes[i]->attnotnull)
+ if (attrtypes[i]->attlen <= 0 ||
+ !attrtypes[i]->attnotnull)
break;
}
if (i == attnum)
diff --git a/src/backend/catalog/genbki.pl b/src/backend/catalog/genbki.pl
index b07537fbbac..dc5f442397a 100644
--- a/src/backend/catalog/genbki.pl
+++ b/src/backend/catalog/genbki.pl
@@ -713,8 +713,8 @@ sub gen_pg_attribute
push @tables_needing_macros, $table_name;
# Generate entries for user attributes.
- my $attnum = 0;
- my $priornotnull = 1;
+ my $attnum = 0;
+ my $priorfixedwidth = 1;
foreach my $attr (@{ $table->{columns} })
{
$attnum++;
@@ -722,8 +722,12 @@ sub gen_pg_attribute
$row{attnum} = $attnum;
$row{attrelid} = $table->{relation_oid};
- morph_row_for_pgattr(\%row, $schema, $attr, $priornotnull);
- $priornotnull &= ($row{attnotnull} eq 't');
+ morph_row_for_pgattr(\%row, $schema, $attr, $priorfixedwidth);
+
+ # Update $priorfixedwidth --- must match morph_row_for_pgattr
+ $priorfixedwidth &=
+ ($row{attnotnull} eq 't'
+ && ($row{attlen} eq 'NAMEDATALEN' || $row{attlen} > 0));
# If it's bootstrapped, put an entry in postgres.bki.
print_bki_insert(\%row, $schema) if $table->{bootstrap};
@@ -765,13 +769,13 @@ sub gen_pg_attribute
# Given $pgattr_schema (the pg_attribute schema for a catalog sufficient for
# AddDefaultValues), $attr (the description of a catalog row), and
-# $priornotnull (whether all prior attributes in this catalog are not null),
+# $priorfixedwidth (all prior columns are fixed-width and not null),
# modify the $row hashref for print_bki_insert. This includes setting data
# from the corresponding pg_type element and filling in any default values.
# Any value not handled here must be supplied by caller.
sub morph_row_for_pgattr
{
- my ($row, $pgattr_schema, $attr, $priornotnull) = @_;
+ my ($row, $pgattr_schema, $attr, $priorfixedwidth) = @_;
my $attname = $attr->{name};
my $atttype = $attr->{type};
@@ -801,19 +805,18 @@ sub morph_row_for_pgattr
{
$row->{attnotnull} = 'f';
}
- elsif ($priornotnull)
+ elsif ($priorfixedwidth)
{
# attnotnull will automatically be set if the type is
- # fixed-width and prior columns are all NOT NULL ---
- # compare DefineAttr in bootstrap.c. oidvector and
- # int2vector are also treated as not-nullable.
+ # fixed-width and prior columns are likewise fixed-width
+ # and NOT NULL --- compare DefineAttr in bootstrap.c.
+ # At this point the width of type name is still symbolic,
+ # so we need a special test.
$row->{attnotnull} =
- $type->{typname} eq 'oidvector' ? 't'
- : $type->{typname} eq 'int2vector' ? 't'
- : $type->{typlen} eq 'NAMEDATALEN' ? 't'
- : $type->{typlen} > 0 ? 't'
- : 'f';
+ $row->{attlen} eq 'NAMEDATALEN' ? 't'
+ : $row->{attlen} > 0 ? 't'
+ : 'f';
}
else
{