Skip to content

Commit eb68379

Browse files
committed
Allow forcing nullness of columns during bootstrap.
Bootstrap determines whether a column is null based on simple builtin rules. Those work surprisingly well, but nonetheless a few existing columns aren't set correctly. Additionally there is at least one patch sent to hackers where forcing the nullness of a column would be helpful. The boostrap format has gained FORCE [NOT] NULL for this, which will be emitted by genbki.pl when BKI_FORCE_(NOT_)?NULL is specified for a column in a catalog header. This patch doesn't change the marking of any existing columns. Discussion: 20150215170014.GE15326@awork2.anarazel.de
1 parent 0627eff commit eb68379

File tree

9 files changed

+131
-49
lines changed

9 files changed

+131
-49
lines changed

doc/src/sgml/bki.sgml

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -75,9 +75,12 @@
7575
<optional><literal>without_oids</></optional>
7676
<optional><literal>rowtype_oid</> <replaceable>oid</></optional>
7777
(<replaceable class="parameter">name1</replaceable> =
78-
<replaceable class="parameter">type1</replaceable> <optional>,
79-
<replaceable class="parameter">name2</replaceable> = <replaceable
80-
class="parameter">type2</replaceable>, ...</optional>)
78+
<replaceable class="parameter">type1</replaceable>
79+
<optional>FORCE NOT NULL | FORCE NULL </optional> <optional>,
80+
<replaceable class="parameter">name2</replaceable> =
81+
<replaceable class="parameter">type2</replaceable>
82+
<optional>FORCE NOT NULL | FORCE NULL </optional>,
83+
...</optional>)
8184
</term>
8285

8386
<listitem>

src/backend/bootstrap/bootparse.y

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -107,14 +107,15 @@ static int num_columns_read = 0;
107107
%type <list> boot_index_params
108108
%type <ielem> boot_index_param
109109
%type <str> boot_const boot_ident
110-
%type <ival> optbootstrap optsharedrelation optwithoutoids
110+
%type <ival> optbootstrap optsharedrelation optwithoutoids boot_column_nullness
111111
%type <oidval> oidspec optoideq optrowtypeoid
112112

113113
%token <str> CONST_P ID
114114
%token OPEN XCLOSE XCREATE INSERT_TUPLE
115115
%token XDECLARE INDEX ON USING XBUILD INDICES UNIQUE XTOAST
116116
%token COMMA EQUALS LPAREN RPAREN
117117
%token OBJ_ID XBOOTSTRAP XSHARED_RELATION XWITHOUT_OIDS XROWTYPE_OID NULLVAL
118+
%token XFORCE XNOT XNULL
118119

119120
%start TopLevel
120121

@@ -427,14 +428,20 @@ boot_column_list:
427428
;
428429

429430
boot_column_def:
430-
boot_ident EQUALS boot_ident
431+
boot_ident EQUALS boot_ident boot_column_nullness
431432
{
432433
if (++numattr > MAXATTR)
433434
elog(FATAL, "too many columns");
434-
DefineAttr($1, $3, numattr-1);
435+
DefineAttr($1, $3, numattr-1, $4);
435436
}
436437
;
437438

439+
boot_column_nullness:
440+
XFORCE XNOT XNULL { $$ = BOOTCOL_NULL_FORCE_NOT_NULL; }
441+
| XFORCE XNULL { $$ = BOOTCOL_NULL_FORCE_NULL; }
442+
| { $$ = BOOTCOL_NULL_AUTO; }
443+
;
444+
438445
oidspec:
439446
boot_ident { $$ = atooid($1); }
440447
;

src/backend/bootstrap/bootscanner.l

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,9 @@ insert { return(INSERT_TUPLE); }
109109
"on" { return(ON); }
110110
"using" { return(USING); }
111111
"toast" { return(XTOAST); }
112+
"FORCE" { return(XFORCE); }
113+
"NOT" { return(XNOT); }
114+
"NULL" { return(XNULL); }
112115

113116
{arrayid} {
114117
yylval.str = MapArrayTypeName(yytext);

src/backend/bootstrap/bootstrap.c

Lines changed: 35 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -642,7 +642,7 @@ closerel(char *name)
642642
* ----------------
643643
*/
644644
void
645-
DefineAttr(char *name, char *type, int attnum)
645+
DefineAttr(char *name, char *type, int attnum, int nullness)
646646
{
647647
Oid typeoid;
648648

@@ -697,30 +697,44 @@ DefineAttr(char *name, char *type, int attnum)
697697
attrtypes[attnum]->atttypmod = -1;
698698
attrtypes[attnum]->attislocal = true;
699699

700-
/*
701-
* Mark as "not null" if type is fixed-width and prior columns are too.
702-
* This corresponds to case where column can be accessed directly via C
703-
* struct declaration.
704-
*
705-
* oidvector and int2vector are also treated as not-nullable, even though
706-
* they are no longer fixed-width.
707-
*/
708-
#define MARKNOTNULL(att) \
709-
((att)->attlen > 0 || \
710-
(att)->atttypid == OIDVECTOROID || \
711-
(att)->atttypid == INT2VECTOROID)
712-
713-
if (MARKNOTNULL(attrtypes[attnum]))
700+
if (nullness == BOOTCOL_NULL_FORCE_NOT_NULL)
701+
{
702+
attrtypes[attnum]->attnotnull = true;
703+
}
704+
else if (nullness == BOOTCOL_NULL_FORCE_NULL)
714705
{
715-
int i;
706+
attrtypes[attnum]->attnotnull = false;
707+
}
708+
else
709+
{
710+
Assert(nullness == BOOTCOL_NULL_AUTO);
716711

717-
for (i = 0; i < attnum; i++)
712+
/*
713+
* Mark as "not null" if type is fixed-width and prior columns are
714+
* too. This corresponds to case where column can be accessed
715+
* directly via C struct declaration.
716+
*
717+
* oidvector and int2vector are also treated as not-nullable, even
718+
* though they are no longer fixed-width.
719+
*/
720+
#define MARKNOTNULL(att) \
721+
((att)->attlen > 0 || \
722+
(att)->atttypid == OIDVECTOROID || \
723+
(att)->atttypid == INT2VECTOROID)
724+
725+
if (MARKNOTNULL(attrtypes[attnum]))
718726
{
719-
if (!MARKNOTNULL(attrtypes[i]))
720-
break;
727+
int i;
728+
729+
/* check earlier attributes */
730+
for (i = 0; i < attnum; i++)
731+
{
732+
if (!attrtypes[i]->attnotnull)
733+
break;
734+
}
735+
if (i == attnum)
736+
attrtypes[attnum]->attnotnull = true;
721737
}
722-
if (i == attnum)
723-
attrtypes[attnum]->attnotnull = true;
724738
}
725739
}
726740

src/backend/catalog/Catalog.pm

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -161,7 +161,8 @@ sub Catalogs
161161
}
162162
else
163163
{
164-
my ($atttype, $attname) = split /\s+/, $_;
164+
my %row;
165+
my ($atttype, $attname, $attopt) = split /\s+/, $_;
165166
die "parse error ($input_file)" unless $attname;
166167
if (exists $RENAME_ATTTYPE{$atttype})
167168
{
@@ -172,7 +173,26 @@ sub Catalogs
172173
$attname = $1;
173174
$atttype .= '[]'; # variable-length only
174175
}
175-
push @{ $catalog{columns} }, { $attname => $atttype };
176+
177+
$row{'type'} = $atttype;
178+
$row{'name'} = $attname;
179+
180+
if (defined $attopt)
181+
{
182+
if ($attopt eq 'PG_FORCE_NULL')
183+
{
184+
$row{'forcenull'} = 1;
185+
}
186+
elsif ($attopt eq 'BKI_FORCE_NOT_NULL')
187+
{
188+
$row{'forcenotnull'} = 1;
189+
}
190+
else
191+
{
192+
die "unknown column option $attopt on column $attname"
193+
}
194+
}
195+
push @{ $catalog{columns} }, \%row;
176196
}
177197
}
178198
}

src/backend/catalog/genbki.pl

Lines changed: 47 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -118,17 +118,36 @@
118118

119119
my %bki_attr;
120120
my @attnames;
121+
my $first = 1;
122+
123+
print BKI " (\n";
121124
foreach my $column (@{ $catalog->{columns} })
122125
{
123-
my ($attname, $atttype) = %$column;
124-
$bki_attr{$attname} = $atttype;
126+
my $attname = $column->{name};
127+
my $atttype = $column->{type};
128+
$bki_attr{$attname} = $column;
125129
push @attnames, $attname;
130+
131+
if (!$first)
132+
{
133+
print BKI " ,\n";
134+
}
135+
$first = 0;
136+
137+
print BKI " $attname = $atttype";
138+
139+
if (defined $column->{forcenotnull})
140+
{
141+
print BKI " FORCE NOT NULL";
142+
}
143+
elsif (defined $column->{forcenull})
144+
{
145+
print BKI " FORCE NULL";
146+
}
126147
}
127-
print BKI " (\n";
128-
print BKI join " ,\n", map(" $_ = $bki_attr{$_}", @attnames);
129148
print BKI "\n )\n";
130149

131-
# open it, unless bootstrap case (create bootstrap does this automatically)
150+
# open it, unless bootstrap case (create bootstrap does this automatically)
132151
if ($catalog->{bootstrap} eq '')
133152
{
134153
print BKI "open $catname\n";
@@ -210,7 +229,7 @@
210229
# Store schemapg entries for later.
211230
$row =
212231
emit_schemapg_row($row,
213-
grep { $bki_attr{$_} eq 'bool' } @attnames);
232+
grep { $bki_attr{$_}{type} eq 'bool' } @attnames);
214233
push @{ $schemapg_entries{$table_name} }, '{ '
215234
. join(
216235
', ', grep { defined $_ }
@@ -223,13 +242,13 @@
223242
{
224243
$attnum = 0;
225244
my @SYS_ATTRS = (
226-
{ ctid => 'tid' },
227-
{ oid => 'oid' },
228-
{ xmin => 'xid' },
229-
{ cmin => 'cid' },
230-
{ xmax => 'xid' },
231-
{ cmax => 'cid' },
232-
{ tableoid => 'oid' });
245+
{ name => 'ctid', type => 'tid' },
246+
{ name => 'oid', type => 'oid' },
247+
{ name => 'xmin', type => 'xid' },
248+
{ name => 'cmin', type=> 'cid' },
249+
{ name => 'xmax', type=> 'xid' },
250+
{ name => 'cmax', type => 'cid' },
251+
{ name => 'tableoid', type => 'oid' });
233252
foreach my $attr (@SYS_ATTRS)
234253
{
235254
$attnum--;
@@ -326,7 +345,8 @@
326345
sub emit_pgattr_row
327346
{
328347
my ($table_name, $attr, $priornotnull) = @_;
329-
my ($attname, $atttype) = %$attr;
348+
my $attname = $attr->{name};
349+
my $atttype = $attr->{type};
330350
my %row;
331351

332352
$row{attrelid} = $catalogs->{$table_name}->{relation_oid};
@@ -354,11 +374,20 @@ sub emit_pgattr_row
354374
$row{attndims} = $type->{typcategory} eq 'A' ? '1' : '0';
355375
$row{attcollation} = $type->{typcollation};
356376

357-
# attnotnull must be set true if the type is fixed-width and
358-
# prior columns are too --- compare DefineAttr in bootstrap.c.
359-
# oidvector and int2vector are also treated as not-nullable.
360-
if ($priornotnull)
377+
if (defined $attr->{forcenotnull})
378+
{
379+
$row{attnotnull} = 't';
380+
}
381+
elsif (defined $attr->{forcenull})
382+
{
383+
$row{attnotnull} = 'f';
384+
}
385+
elsif ($priornotnull)
361386
{
387+
# attnotnull will automatically be set if the type is
388+
# fixed-width and prior columns are all NOT NULL ---
389+
# compare DefineAttr in bootstrap.c. oidvector and
390+
# int2vector are also treated as not-nullable.
362391
$row{attnotnull} =
363392
$type->{typname} eq 'oidvector' ? 't'
364393
: $type->{typname} eq 'int2vector' ? 't'

src/backend/utils/Gen_fmgrtab.pl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@
5252
my @attnames;
5353
foreach my $column (@{ $catalogs->{pg_proc}->{columns} })
5454
{
55-
push @attnames, keys %$column;
55+
push @attnames, $column->{name};
5656
}
5757

5858
my $data = $catalogs->{pg_proc}->{data};

src/include/bootstrap/bootstrap.h

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,10 @@
2323
*/
2424
#define MAXATTR 40
2525

26+
#define BOOTCOL_NULL_AUTO 1
27+
#define BOOTCOL_NULL_FORCE_NULL 2
28+
#define BOOTCOL_NULL_FORCE_NOT_NULL 3
29+
2630
extern Relation boot_reldesc;
2731
extern Form_pg_attribute attrtypes[MAXATTR];
2832
extern int numattr;
@@ -35,7 +39,7 @@ extern void err_out(void);
3539
extern void closerel(char *name);
3640
extern void boot_openrel(char *name);
3741

38-
extern void DefineAttr(char *name, char *type, int attnum);
42+
extern void DefineAttr(char *name, char *type, int attnum, int nullness);
3943
extern void InsertOneTuple(Oid objectid);
4044
extern void InsertOneValue(char *value, int i);
4145
extern void InsertOneNull(int i);

src/include/catalog/genbki.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,8 @@
2828
#define BKI_WITHOUT_OIDS
2929
#define BKI_ROWTYPE_OID(oid)
3030
#define BKI_SCHEMA_MACRO
31+
#define BKI_FORCE_NULL
32+
#define BKI_FORCE_NOT_NULL
3133

3234
/*
3335
* This is never defined; it's here only for documentation.

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy