Skip to content

Commit d3d974d

Browse files
committed
Remove BKI file token pre-processing logic from initdb.
With this patch genbki replaces some token at compile time. Some others are initially populated with placeholder values from catalog/*.dat. Initdb run time UPDATEs these place holders plus the left over token with the respective configured values. Here are more details: - NAMEDATALEN, FLOAT8PASSBYVAL, SIZEOF_VOID_P, ALIGNOF_POINTER are replaced during compilation from genbki.pl by reading those from header files. - SIZEOF_VOID_P is available only after configuration (in pg_config.h). A new parameter include-conf had to be added to genbki to point to header files generated after configuration. - The pg_database.dat now has placeholder values which are filled in template1 during creation. Initdb uses UPDATE to set the right values for rolname in pg_authid and rest of the configured values in pg_database. - Earlier bki file was opened by initdb, and passed to postgres started in bootstrap mode. With this changes, the bki file is no longer opened in initdb, instead the file path is passed to bootstrap which solely handles the bki file. This means we have pass the file stream as yyin to allow the parsing from file directly. - The version check validating major PG version in bki file is same as the binary build is now moved to bootstrap from initdb. It only compares the string upto the EOL to avoid adding compatability handling while the version check works.
1 parent 684d9bf commit d3d974d

9 files changed

Lines changed: 139 additions & 82 deletions

File tree

src/backend/bootstrap/bootstrap.c

Lines changed: 59 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
#include "catalog/pg_collation.h"
3030
#include "catalog/pg_type.h"
3131
#include "common/link-canary.h"
32+
#include "common/string.h"
3233
#include "libpq/pqsignal.h"
3334
#include "miscadmin.h"
3435
#include "nodes/makefuncs.h"
@@ -49,6 +50,7 @@ uint32 bootstrap_data_checksum_version = 0; /* No checksum */
4950

5051

5152
static void CheckerModeMain(void);
53+
static bool verify_bki_hdr(FILE *fp);
5254
static void bootstrap_signals(void);
5355
static Form_pg_attribute AllocateAttribute(void);
5456
static void populate_typ_list(void);
@@ -206,6 +208,7 @@ BootstrapModeMain(int argc, char *argv[], bool check_only)
206208
char *progname = argv[0];
207209
int flag;
208210
char *userDoption = NULL;
211+
char *bki_file = NULL;
209212

210213
Assert(!IsUnderPostmaster);
211214

@@ -221,10 +224,13 @@ BootstrapModeMain(int argc, char *argv[], bool check_only)
221224
argv++;
222225
argc--;
223226

224-
while ((flag = getopt(argc, argv, "B:c:d:D:Fkr:X:-:")) != -1)
227+
while ((flag = getopt(argc, argv, "b:B:c:d:D:Fkr:X:-:")) != -1)
225228
{
226229
switch (flag)
227230
{
231+
case 'b':
232+
bki_file = pstrdup(optarg);
233+
break;
228234
case 'B':
229235
SetConfigOption("shared_buffers", optarg, PGC_POSTMASTER, PGC_S_ARGV);
230236
break;
@@ -354,9 +360,29 @@ BootstrapModeMain(int argc, char *argv[], bool check_only)
354360
Nulls[i] = false;
355361
}
356362

363+
/* Point boot_yyin to bki file. */
364+
elog(DEBUG4, "Open bki file %s\n", bki_file);
365+
if ((boot_yyin = fopen(bki_file, "r")) == NULL)
366+
{
367+
write_stderr("Opening bki_file=%s failed with error=%d.",
368+
bki_file ? bki_file : "", errno);
369+
cleanup();
370+
proc_exit(1);
371+
}
372+
357373
/*
358-
* Process bootstrap input.
374+
* Verify bki header match with binary version. Bki parser ignore
375+
* commments hence no need to rewind boot_yyin.
359376
*/
377+
if (!verify_bki_hdr(boot_yyin))
378+
{
379+
write_stderr("Version in bki file(%s) does not match PostgreSQL version %s",
380+
bki_file, PG_VERSION);
381+
cleanup();
382+
proc_exit(1);
383+
}
384+
385+
/* Process bootstrap input from bki file (boot_yyin) */
360386
StartTransactionCommand();
361387
boot_yyparse();
362388
CommitTransactionCommand();
@@ -480,6 +506,37 @@ closerel(char *relname)
480506
}
481507
}
482508

509+
/* -----------------------
510+
* verify_bki_hdr
511+
*
512+
* Verify that the bki file is generated for the
513+
* same major version as that of the bootstrap.
514+
* -----------------------
515+
*/
516+
static bool
517+
verify_bki_hdr(FILE *b)
518+
{
519+
StringInfoData line;
520+
char headerline[MAXPGPATH];
521+
int ver_str_len = 0;
522+
bool ret = true;
523+
524+
initStringInfo(&line);
525+
if (!pg_get_line_buf(b, &line))
526+
{
527+
return false;
528+
}
529+
530+
ver_str_len = snprintf(headerline, sizeof(headerline), "# PostgreSQL %s",
531+
PG_MAJORVERSION);
532+
if (ver_str_len <= 0 || strncmp(headerline, line.data, ver_str_len) != 0)
533+
{
534+
ret = false;
535+
}
536+
537+
pfree(line.data);
538+
return ret;
539+
}
483540

484541

485542
/* ----------------

src/backend/catalog/Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -169,7 +169,7 @@ generated-header-symlinks: $(top_builddir)/src/include/catalog/header-stamp
169169
# instead is cheating a bit, but it will achieve the goal of updating the
170170
# version number when it changes.
171171
bki-stamp: genbki.pl Catalog.pm $(POSTGRES_BKI_SRCS) $(POSTGRES_BKI_DATA) $(top_srcdir)/configure.ac $(top_srcdir)/src/include/access/transam.h
172-
$(PERL) $< --include-path=$(top_srcdir)/src/include/ \
172+
$(PERL) $< --include-path=$(top_srcdir)/src/include/ --include-conf=$(top_builddir)/src/include/ \
173173
--set-version=$(MAJORVERSION) $(POSTGRES_BKI_SRCS)
174174
touch $@
175175

src/backend/catalog/genbki.pl

Lines changed: 33 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,20 +25,23 @@
2525
my $output_path = '';
2626
my $major_version;
2727
my $include_path;
28+
my $include_conf;
2829

2930
my $num_errors = 0;
3031

3132
GetOptions(
3233
'output:s' => \$output_path,
3334
'set-version:s' => \$major_version,
34-
'include-path:s' => \$include_path) || usage();
35+
'include-path:s' => \$include_path,
36+
'include-conf:s' => \$include_conf) || usage();
3537

3638
# Sanity check arguments.
3739
die "No input files.\n" unless @ARGV;
3840
die "--set-version must be specified.\n" unless $major_version;
3941
die "Invalid version string: $major_version\n"
4042
unless $major_version =~ /^\d+$/;
4143
die "--include-path must be specified.\n" unless $include_path;
44+
die "--include-conf must be specified.\n" unless $include_conf;
4245

4346
# Make sure paths end with a slash.
4447
if ($output_path ne '' && substr($output_path, -1) ne '/')
@@ -180,6 +183,12 @@
180183
# Hash of next available OID, indexed by catalog name.
181184
my %GenbkiNextOids;
182185

186+
my $NameDataLen=Catalog::FindDefinedSymbol('pg_config_manual.h', $include_path,
187+
'NAMEDATALEN');
188+
my $SizeOfPointer=Catalog::FindDefinedSymbol('pg_config.h', $include_conf,
189+
'SIZEOF_VOID_P');
190+
my $Float8PassByVal=$SizeOfPointer >= 8 ? "true": "false";
191+
my $AlignOfPointer=$SizeOfPointer == 4 ? "i" : "d";
183192

184193
# Fetch some special data that we will substitute into the output file.
185194
# CAUTION: be wary about what symbols you substitute into the .bki file here!
@@ -634,6 +643,23 @@
634643
my $symbol = form_pg_type_symbol($bki_values{typname});
635644
$bki_values{oid_symbol} = $symbol
636645
if defined $symbol;
646+
647+
if ($bki_values{typlen} eq 'NAMEDATALEN')
648+
{
649+
$bki_values{typlen} = $NameDataLen;
650+
}
651+
if ($bki_values{typlen} eq 'SIZEOF_POINTER')
652+
{
653+
$bki_values{typlen} = $SizeOfPointer;
654+
}
655+
if ($bki_values{typalign} eq 'ALIGNOF_POINTER')
656+
{
657+
$bki_values{typalign} = $AlignOfPointer;
658+
}
659+
if ($bki_values{typbyval} eq 'FLOAT8PASSBYVAL')
660+
{
661+
$bki_values{typbyval} = $Float8PassByVal;
662+
}
637663
}
638664

639665
# Write to postgres.bki
@@ -812,6 +838,11 @@ sub gen_pg_attribute
812838
($row{attnotnull} eq 't'
813839
&& ($row{attlen} eq 'NAMEDATALEN' || $row{attlen} > 0));
814840

841+
if ($row{attnotnull} eq 't' && ($row{attlen} eq 'NAMEDATALEN'))
842+
{
843+
$row{attlen} = $NameDataLen;
844+
}
845+
815846
# If it's bootstrapped, put an entry in postgres.bki.
816847
print_bki_insert(\%row, $schema) if $table->{bootstrap};
817848

@@ -1106,6 +1137,7 @@ sub usage
11061137
--output Output directory (default '.')
11071138
--set-version PostgreSQL version number for initdb cross-check
11081139
--include-path Include path in source tree
1140+
--include-conf Include file path generated after configuration
11091141
11101142
genbki.pl generates postgres.bki and symbol definition
11111143
headers from specially formatted header files and .dat

src/backend/main/main.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -372,6 +372,7 @@ help(const char *progname)
372372
printf(_(" --check selects check mode (must be first argument)\n"));
373373
printf(_(" DBNAME database name (mandatory argument in bootstrapping mode)\n"));
374374
printf(_(" -r FILENAME send stdout and stderr to given file\n"));
375+
printf(_(" -b FILENAME path to bki file\n"));
375376

376377
printf(_("\nPlease read the documentation for the complete list of run-time\n"
377378
"configuration settings and how to set them on the command line or in\n"

src/bin/initdb/initdb.c

Lines changed: 37 additions & 72 deletions
Original file line numberDiff line numberDiff line change
@@ -764,15 +764,6 @@ get_id(void)
764764
return pg_strdup(username);
765765
}
766766

767-
static char *
768-
encodingid_to_string(int enc)
769-
{
770-
char result[20];
771-
772-
sprintf(result, "%d", enc);
773-
return pg_strdup(result);
774-
}
775-
776767
/*
777768
* get the encoding id for a given encoding name
778769
*/
@@ -1473,70 +1464,17 @@ bootstrap_template1(void)
14731464
{
14741465
PG_CMD_DECL;
14751466
PQExpBufferData cmd;
1476-
char **line;
1477-
char **bki_lines;
1478-
char headerline[MAXPGPATH];
1479-
char buf[64];
14801467

14811468
printf(_("running bootstrap script ... "));
14821469
fflush(stdout);
14831470

1484-
bki_lines = readfile(bki_file);
1485-
1486-
/* Check that bki file appears to be of the right version */
1487-
1488-
snprintf(headerline, sizeof(headerline), "# PostgreSQL %s\n",
1489-
PG_MAJORVERSION);
1490-
1491-
if (strcmp(headerline, *bki_lines) != 0)
1492-
{
1493-
pg_log_error("input file \"%s\" does not belong to PostgreSQL %s",
1494-
bki_file, PG_VERSION);
1495-
pg_log_error_hint("Specify the correct path using the option -L.");
1496-
exit(1);
1497-
}
1498-
1499-
/* Substitute for various symbols used in the BKI file */
1500-
1501-
sprintf(buf, "%d", NAMEDATALEN);
1502-
bki_lines = replace_token(bki_lines, "NAMEDATALEN", buf);
1503-
1504-
sprintf(buf, "%d", (int) sizeof(Pointer));
1505-
bki_lines = replace_token(bki_lines, "SIZEOF_POINTER", buf);
1506-
1507-
bki_lines = replace_token(bki_lines, "ALIGNOF_POINTER",
1508-
(sizeof(Pointer) == 4) ? "i" : "d");
1509-
1510-
bki_lines = replace_token(bki_lines, "FLOAT8PASSBYVAL",
1511-
FLOAT8PASSBYVAL ? "true" : "false");
1512-
1513-
bki_lines = replace_token(bki_lines, "POSTGRES",
1514-
escape_quotes_bki(username));
1515-
1516-
bki_lines = replace_token(bki_lines, "ENCODING",
1517-
encodingid_to_string(encodingid));
1518-
1519-
bki_lines = replace_token(bki_lines, "LC_COLLATE",
1520-
escape_quotes_bki(lc_collate));
1521-
1522-
bki_lines = replace_token(bki_lines, "LC_CTYPE",
1523-
escape_quotes_bki(lc_ctype));
1524-
1525-
bki_lines = replace_token(bki_lines, "ICU_LOCALE",
1526-
icu_locale ? escape_quotes_bki(icu_locale) : "_null_");
1527-
1528-
bki_lines = replace_token(bki_lines, "ICU_RULES",
1529-
icu_rules ? escape_quotes_bki(icu_rules) : "_null_");
1530-
1531-
sprintf(buf, "%c", locale_provider);
1532-
bki_lines = replace_token(bki_lines, "LOCALE_PROVIDER", buf);
1533-
15341471
/* Also ensure backend isn't confused by this environment var: */
15351472
unsetenv("PGCLIENTENCODING");
15361473

15371474
initPQExpBuffer(&cmd);
15381475

1539-
printfPQExpBuffer(&cmd, "\"%s\" --boot %s %s", backend_exec, boot_options, extra_options);
1476+
printfPQExpBuffer(&cmd, "\"%s\" --boot %s %s -b %s", backend_exec, boot_options,
1477+
extra_options, bki_file);
15401478
appendPQExpBuffer(&cmd, " -X %d", wal_segment_size_mb * (1024 * 1024));
15411479
if (data_checksums)
15421480
appendPQExpBuffer(&cmd, " -k");
@@ -1545,21 +1483,46 @@ bootstrap_template1(void)
15451483

15461484

15471485
PG_CMD_OPEN(cmd.data);
1548-
1549-
for (line = bki_lines; *line != NULL; line++)
1550-
{
1551-
PG_CMD_PUTS(*line);
1552-
free(*line);
1553-
}
1554-
15551486
PG_CMD_CLOSE();
15561487

15571488
termPQExpBuffer(&cmd);
1558-
free(bki_lines);
15591489

15601490
check_ok();
15611491
}
15621492

1493+
/*
1494+
* Placeholder values from catalog *.dat are used to create template1.
1495+
* Here we UPDATE with configured values from current initdb run.
1496+
*/
1497+
static void
1498+
update_params(FILE *cmdfd)
1499+
{
1500+
1501+
char *icu_locale_str = NULL;
1502+
char *icu_rules_str = NULL;
1503+
char *line = NULL;
1504+
1505+
if (icu_locale)
1506+
{
1507+
icu_locale_str = psprintf(",daticulocale=%s", escape_quotes_bki(icu_locale));
1508+
}
1509+
1510+
if (icu_rules)
1511+
{
1512+
icu_rules_str = psprintf(",daticulocale=%s", escape_quotes_bki(icu_rules));
1513+
}
1514+
1515+
line = psprintf("UPDATE pg_authid SET rolname='%s' WHERE rolname='POSTGRES'; \n\n"
1516+
"UPDATE pg_database SET encoding='%d', datcollate='%s', datctype='%s',"
1517+
"datlocprovider='%c' %s %s "
1518+
"WHERE datname='template1'; \n\n",
1519+
escape_quotes(username), encodingid, escape_quotes(lc_collate),
1520+
escape_quotes(lc_ctype), locale_provider,
1521+
icu_locale_str ? icu_locale_str : "",
1522+
icu_rules_str ? icu_rules_str : "");
1523+
PG_CMD_PUTS(line);
1524+
}
1525+
15631526
/*
15641527
* set up the shadow password table
15651528
*/
@@ -3028,6 +2991,8 @@ initialize_data_directory(void)
30282991

30292992
PG_CMD_OPEN(cmd.data);
30302993

2994+
update_params(cmdfd);
2995+
30312996
setup_auth(cmdfd);
30322997

30332998
setup_run_file(cmdfd, system_constraints_file);

src/include/bootstrap/bootstrap.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,5 +58,6 @@ extern int boot_yyparse(void);
5858

5959
extern int boot_yylex(void);
6060
extern void boot_yyerror(const char *message) pg_attribute_noreturn();
61+
extern FILE *boot_yyin;
6162

6263
#endif /* BOOTSTRAP_H */

src/include/catalog/meson.build

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,7 @@ generated_catalog_headers = custom_target('generated_catalog_headers',
123123
perl,
124124
files('../../backend/catalog/genbki.pl'),
125125
'--include-path=@SOURCE_ROOT@/src/include',
126+
'--include-conf=@BUILD_ROOT@/src/include',
126127
'--set-version=' + pg_version_major.to_string(),
127128
'--output=@OUTDIR@', '@INPUT@'
128129
],

src/include/catalog/pg_database.dat

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -14,11 +14,11 @@
1414

1515
{ oid => '1', oid_symbol => 'Template1DbOid',
1616
descr => 'default template for new databases',
17-
datname => 'template1', encoding => 'ENCODING',
18-
datlocprovider => 'LOCALE_PROVIDER', datistemplate => 't',
17+
datname => 'template1', encoding => '0',
18+
datlocprovider => 'd', datistemplate => 't',
1919
datallowconn => 't', datconnlimit => '-1', datfrozenxid => '0',
20-
datminmxid => '1', dattablespace => 'pg_default', datcollate => 'LC_COLLATE',
21-
datctype => 'LC_CTYPE', daticulocale => 'ICU_LOCALE',
22-
daticurules => 'ICU_RULES', datacl => '_null_' },
20+
datminmxid => '1', dattablespace => 'pg_default', datcollate => 'C',
21+
datctype => 'C', daticulocale => '_null_',
22+
daticurules => '_null_', datacl => '_null_' },
2323

2424
]

0 commit comments

Comments
 (0)