From ed39cf53788242d6b6990497ae86250dd658d26c Mon Sep 17 00:00:00 2001
From: Andres Freund <andres@anarazel.de>
Date: Sun, 20 Feb 2022 11:03:20 -0800
Subject: [PATCH v1 3/5] initdb: perform everything during --boot, mostly in
 backend.

Author:
Reviewed-By:
Discussion: https://postgr.es/m/
Backpatch:
---
 src/include/bootstrap/bootstrap.h   |   1 +
 src/include/commands/extension.h    |   2 +
 src/include/tcop/tcopprot.h         |   1 +
 src/include/utils/relcache.h        |   1 +
 src/backend/bootstrap/bootscanner.l |   6 +
 src/backend/bootstrap/bootstrap.c   | 306 +++++++++++++++-
 src/backend/catalog/Makefile        |   2 +
 src/backend/catalog/description.sql |  16 +
 src/backend/catalog/privileges.sql  | 154 ++++++++
 src/backend/commands/extension.c    |   5 +-
 src/backend/main/main.c             |   1 +
 src/backend/tcop/postgres.c         |  12 +
 src/backend/utils/cache/relcache.c  |  11 +-
 src/bin/initdb/initdb.c             | 532 ++--------------------------
 14 files changed, 535 insertions(+), 515 deletions(-)
 create mode 100644 src/backend/catalog/description.sql
 create mode 100644 src/backend/catalog/privileges.sql

diff --git a/src/include/bootstrap/bootstrap.h b/src/include/bootstrap/bootstrap.h
index 471414909f3..f94e9339373 100644
--- a/src/include/bootstrap/bootstrap.h
+++ b/src/include/bootstrap/bootstrap.h
@@ -54,6 +54,7 @@ extern void boot_get_type_io_data(Oid typid,
 								  Oid *typinput,
 								  Oid *typoutput);
 
+extern void boot_input(FILE *file);
 extern int	boot_yyparse(void);
 
 extern int	boot_yylex(void);
diff --git a/src/include/commands/extension.h b/src/include/commands/extension.h
index e24e3759f0c..cd1668e5865 100644
--- a/src/include/commands/extension.h
+++ b/src/include/commands/extension.h
@@ -48,6 +48,8 @@ extern ObjectAddress ExecAlterExtensionContentsStmt(AlterExtensionContentsStmt *
 extern Oid	get_extension_oid(const char *extname, bool missing_ok);
 extern char *get_extension_name(Oid ext_oid);
 extern bool extension_file_exists(const char *extensionName);
+extern void execute_sql_string(const char *sql);
+extern char *read_whole_file(const char *filename, int *length);
 
 extern ObjectAddress AlterExtensionNamespace(const char *extensionName, const char *newschema,
 											 Oid *oldschema);
diff --git a/src/include/tcop/tcopprot.h b/src/include/tcop/tcopprot.h
index 15a11bc3ff1..47c8ff283e4 100644
--- a/src/include/tcop/tcopprot.h
+++ b/src/include/tcop/tcopprot.h
@@ -60,6 +60,7 @@ extern PlannedStmt *pg_plan_query(Query *querytree, const char *query_string,
 extern List *pg_plan_queries(List *querytrees, const char *query_string,
 							 int cursorOptions,
 							 ParamListInfo boundParams);
+extern void exec_simple_query_bootstrap(const char *query_string);
 
 extern bool check_max_stack_depth(int *newval, void **extra, GucSource source);
 extern void assign_max_stack_depth(int newval, void *extra);
diff --git a/src/include/utils/relcache.h b/src/include/utils/relcache.h
index 84d6afef19b..e400146f648 100644
--- a/src/include/utils/relcache.h
+++ b/src/include/utils/relcache.h
@@ -93,6 +93,7 @@ extern int	errtableconstraint(Relation rel, const char *conname);
 extern void RelationCacheInitialize(void);
 extern void RelationCacheInitializePhase2(void);
 extern void RelationCacheInitializePhase3(void);
+extern void RelationCacheInitializePhase3b(bool needNewCacheFile);
 
 /*
  * Routine to create a relcache entry for an about-to-be-created relation
diff --git a/src/backend/bootstrap/bootscanner.l b/src/backend/bootstrap/bootscanner.l
index 3094ccb93f4..72c3f40a88f 100644
--- a/src/backend/bootstrap/bootscanner.l
+++ b/src/backend/bootstrap/bootscanner.l
@@ -125,3 +125,9 @@ yyerror(const char *message)
 {
 	elog(ERROR, "%s at line %d", message, yyline);
 }
+
+void
+boot_input(FILE *file)
+{
+	yyin = file;
+}
diff --git a/src/backend/bootstrap/bootstrap.c b/src/backend/bootstrap/bootstrap.c
index 667c829064d..3fd8ed60715 100644
--- a/src/backend/bootstrap/bootstrap.c
+++ b/src/backend/bootstrap/bootstrap.c
@@ -2,7 +2,10 @@
  *
  * bootstrap.c
  *	  routines to support running postgres in 'bootstrap' mode
- *	bootstrap mode is used to create the initial template database
+ *
+ * bootstrap mode is used to create the initial template1 database, perform
+ * additional initialization it via SQL scripts, and then create template0,
+ * postgres from template1.
  *
  * Portions Copyright (c) 1996-2022, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
@@ -26,10 +29,14 @@
 #include "access/xlog_internal.h"
 #include "bootstrap/bootstrap.h"
 #include "catalog/index.h"
+#include "catalog/pg_authid_d.h"
 #include "catalog/pg_collation.h"
 #include "catalog/pg_type.h"
+#include "commands/extension.h"
 #include "common/link-canary.h"
+#include "common/string.h"
 #include "libpq/pqsignal.h"
+#include "mb/pg_wchar.h"
 #include "miscadmin.h"
 #include "nodes/makefuncs.h"
 #include "pg_getopt.h"
@@ -41,6 +48,7 @@
 #include "tcop/tcopprot.h"
 #include "utils/builtins.h"
 #include "utils/fmgroids.h"
+#include "utils/inval.h"
 #include "utils/memutils.h"
 #include "utils/rel.h"
 #include "utils/relmapper.h"
@@ -55,6 +63,12 @@ static void populate_typ_list(void);
 static Oid	gettype(char *type);
 static void cleanup(void);
 
+static void bootstrap_load_nonbki(const char *share_path);
+static void bootstrap_create_databases(void);
+
+static void exec_sql(const char *share_path, const char *str);
+static void exec_sql_file(const char *share_path, const char *str);
+
 /* ----------------
  *		global variables
  * ----------------
@@ -206,6 +220,7 @@ BootstrapModeMain(int argc, char *argv[], bool check_only)
 	char	   *progname = argv[0];
 	int			flag;
 	char	   *userDoption = NULL;
+	char	   *share_path = NULL;
 
 	Assert(!IsUnderPostmaster);
 
@@ -221,7 +236,12 @@ BootstrapModeMain(int argc, char *argv[], bool check_only)
 	argv++;
 	argc--;
 
-	while ((flag = getopt(argc, argv, "B:c:d:D:Fkr:X:-:")) != -1)
+	/*
+	 * XXX: -s for share_path is probably a bad choice, it conflicts with a
+	 * normal postgres option. Also, should probably just determine share path
+	 * ourselves.
+	 */
+	while ((flag = getopt(argc, argv, "B:c:d:D:s:Fkr:X:-:")) != -1)
 	{
 		switch (flag)
 		{
@@ -247,6 +267,9 @@ BootstrapModeMain(int argc, char *argv[], bool check_only)
 			case 'F':
 				SetConfigOption("fsync", "false", PGC_POSTMASTER, PGC_S_ARGV);
 				break;
+			case 's':
+			    share_path = optarg;
+				break;
 			case 'k':
 				bootstrap_data_checksum_version = PG_DATA_CHECKSUM_VERSION;
 				break;
@@ -338,6 +361,12 @@ BootstrapModeMain(int argc, char *argv[], bool check_only)
 		abort();
 	}
 
+	if (share_path == NULL)
+	{
+		write_stderr("%s: -s is required in --boot mode\n", progname);
+		proc_exit(1);
+	}
+
 	/*
 	 * Do backend-like initialization for bootstrap mode
 	 */
@@ -365,11 +394,34 @@ BootstrapModeMain(int argc, char *argv[], bool check_only)
 	}
 
 	/*
-	 * Process bootstrap input.
+	 * Process bootstrap file to create initial template1 contents.
 	 */
-	StartTransactionCommand();
-	boot_yyparse();
-	CommitTransactionCommand();
+	{
+		char bootstrap_file[MAXPGPATH];
+		FILE *boot;
+		instr_time start_ts, boot_ts;
+
+		INSTR_TIME_SET_CURRENT(start_ts);
+
+		sprintf(bootstrap_file, "%s/%s", share_path, "postgres.bki");
+
+		boot = fopen(bootstrap_file, "r");
+		if (boot == NULL)
+			elog(ERROR, "could not open bootstrap file \"%s\": %m",
+				 bootstrap_file);
+		boot_input(boot);
+
+		StartTransactionCommand();
+		boot_yyparse();
+		CommitTransactionCommand();
+
+		fclose(boot);
+
+		INSTR_TIME_SET_CURRENT(boot_ts);
+
+		elog(LOG, "boot in %.3f ms",
+			 (INSTR_TIME_GET_DOUBLE(boot_ts) - INSTR_TIME_GET_DOUBLE(start_ts)) * 1000);
+	}
 
 	/*
 	 * We should now know about all mapped relations, so it's okay to write
@@ -377,11 +429,251 @@ BootstrapModeMain(int argc, char *argv[], bool check_only)
 	 */
 	RelationMapFinishBootstrap();
 
-	/* Clean up and exit */
+	/* Clean up and exit FIXME */
 	cleanup();
+
+	/*
+	 * Now that the catalog is populated with crucial contents, bring up
+	 * system caches into a fully valid state.
+	 */
+
+	SetProcessingMode(InitProcessing);
+
+	IgnoreSystemIndexes = false;
+
+	StartTransactionCommand();
+	/* Seeing odd "row is too big:" failures without */
+	InvalidateSystemCaches();
+	/* FIXME: speechless-making API */
+	RelationCacheInitializePhase3b(true);
+	CommitTransactionCommand();
+
+	/*
+	 * Load further catalog contents by running a bunch of SQL commands.
+	 */
+	SetProcessingMode(NormalProcessing);
+
+	bootstrap_load_nonbki(share_path);
+
+	bootstrap_create_databases();
+
 	proc_exit(0);
 }
 
+/*
+ * Create template0 and postgres from template1.
+ *
+ * XXX: Several of the statements contain commands that cannot be executed in
+ * a transaction (VACUUM, CREATE DATABASE) and thus require a fairly
+ * complicated dance to maintain correct state. The easiest is to just rely on
+ * exec_simple_query() (via a wrapper) for that. Don't want to do that for
+ * everything else, because it's considerably faster to use exec_sql().
+ */
+static void
+bootstrap_create_databases(void)
+{
+	/*
+	 * pg_upgrade tries to preserve database OIDs across upgrades. It's smart
+	 * enough to drop and recreate a conflicting database with the same name,
+	 * but if the same OID were used for one system-created database in the
+	 * old cluster and a different system-created database in the new cluster,
+	 * it would fail. To avoid that, assign a fixed OID to template0 rather
+	 * than letting the server choose one.
+	 *
+	 * (Note that, while the user could have dropped and recreated these
+	 * objects in the old cluster, the problem scenario only exists if the OID
+	 * that is in use in the old cluster is also used in the new cluster - and
+	 * the new cluster should be the result of a fresh initdb.)
+	 */
+	static const char *const template0_setup[] = {
+		"CREATE DATABASE template0 IS_TEMPLATE = true ALLOW_CONNECTIONS = false OID = "
+		CppAsString2(Template0ObjectId) ";\n",
+
+		/*
+		 * template0 shouldn't have any collation-dependent objects, so unset
+		 * the collation version.  This disables collation version checks when
+		 * making a new database from it.
+		 */
+		"UPDATE pg_database SET datcollversion = NULL WHERE datname = 'template0';\n",
+
+		/*
+		 * While we are here, do set the collation version on template1.
+		 */
+		"UPDATE pg_database SET datcollversion = pg_database_collation_actual_version(oid) WHERE datname = 'template1';\n",
+
+		/*
+		 * Explicitly revoke public create-schema and create-temp-table
+		 * privileges in template1 and template0; else the latter would be on
+		 * by default
+		 */
+		"REVOKE CREATE,TEMPORARY ON DATABASE template1 FROM public;\n",
+		"REVOKE CREATE,TEMPORARY ON DATABASE template0 FROM public;\n",
+
+		"COMMENT ON DATABASE template0 IS 'unmodifiable empty database';\n",
+		NULL
+	};
+
+	/* Assign a fixed OID to postgres, for the same reasons as template0 */
+	static const char *const postgres_setup[] = {
+		"CREATE DATABASE postgres OID = " CppAsString2(PostgresObjectId) ";\n",
+		"COMMENT ON DATABASE postgres IS 'default administrative connection database';\n",
+		NULL
+	};
+	instr_time start_ts, created_ts;
+
+	INSTR_TIME_SET_CURRENT(start_ts);
+
+
+	MessageContext = AllocSetContextCreate(TopMemoryContext,
+										   "MessageContext",
+										   ALLOCSET_DEFAULT_SIZES);
+
+	/*
+	 * clean everything up in template1
+	 */
+	exec_simple_query_bootstrap("VACUUM FREEZE");
+
+	/*
+	 * copy template1 to template0
+	 */
+	for (const char *const *line = template0_setup; *line; line++)
+		exec_simple_query_bootstrap(*line);
+
+	/*
+	 * copy template1 to postgres
+	 */
+	for (const char *const *line = postgres_setup; *line; line++)
+		exec_simple_query_bootstrap(*line);
+
+	/*
+	 * Finally vacuum to clean up dead rows in pg_database
+	 */
+	exec_simple_query_bootstrap("VACUUM pg_database");
+
+	MemoryContextDelete(MessageContext);
+	MessageContext = NULL;
+
+	INSTR_TIME_SET_CURRENT(created_ts);
+
+	elog(LOG, "created template0 and postgres in %.3f ms",
+		 (INSTR_TIME_GET_DOUBLE(created_ts) - INSTR_TIME_GET_DOUBLE(start_ts)) * 1000);
+}
+
+static void
+bootstrap_load_nonbki(const char *share_path)
+{
+	StringInfoData sql;
+
+	initStringInfo(&sql);
+
+	StartTransactionCommand();
+	PushActiveSnapshot(GetTransactionSnapshot());
+
+	exec_sql_file(share_path, "system_constraints.sql");
+	exec_sql_file(share_path, "system_functions.sql");
+
+	/*
+	 * set up the shadow password table
+	 */
+	exec_sql("pg_authid", "REVOKE ALL ON pg_authid FROM public;");
+
+	/*
+	 * Advance the OID counter so that subsequently-created objects aren't
+	 * pinned. Subsequent objects are all droppable at the whim of the DBA.
+	 */
+	StopGeneratingPinnedObjectIds();
+
+	exec_sql_file(share_path, "system_views.sql");
+
+	exec_sql_file(share_path, "description.sql");
+
+	/* populate pg_collation */
+	{
+		/*
+		 * Add an SQL-standard name.  We don't want to pin this, so it doesn't go
+		 * in pg_collation.h.  But add it before reading system collations, so
+		 * that it wins if libc defines a locale named ucs_basic.
+		 */
+		appendStringInfo(&sql,
+						 "INSERT INTO pg_collation (oid, collname, "
+						 "    collnamespace, collowner, "
+						 "    collprovider, collisdeterministic, collencoding, "
+						 "    collcollate, collctype) "
+						 "VALUES ("
+						 "    pg_nextoid('pg_catalog.pg_collation', 'oid', "
+						 "        'pg_catalog.pg_collation_oid_index'), "
+						 "    'ucs_basic', 'pg_catalog'::regnamespace, %u, "
+						 "    '%c', true, %d, 'C', 'C');",
+						 BOOTSTRAP_SUPERUSERID, COLLPROVIDER_LIBC, PG_UTF8);
+		exec_sql("pg_collation", sql.data);
+		resetStringInfo(&sql);
+
+		/* Now import all collations we can find in the operating system */
+		exec_sql("import collations",
+				 "SELECT pg_import_system_collations('pg_catalog');");
+	}
+
+	exec_sql_file(share_path, "snowball_create.sql");
+
+	exec_sql_file(share_path, "privileges.sql");
+
+	exec_sql_file(share_path, "information_schema.sql");
+
+	exec_sql("plpgsql", "CREATE EXTENSION plpgsql;");
+
+	/*
+	 * Process SQL coming from initdb. This includes things like setting
+	 * up passwords, which would be a bit of pain to move to the backend.
+	 */
+	while (true)
+	{
+		if (!pg_get_line_buf(stdin, &sql))
+			break;
+
+		/* XXX: better descriptor than more */
+		exec_sql("more", sql.data);
+		resetStringInfo(&sql);
+	}
+
+	/* Run analyze before VACUUM so the statistics are frozen. */
+	exec_sql("analyze", "ANALYZE");
+
+	PopActiveSnapshot();
+	CommitTransactionCommand();
+}
+
+static void
+exec_sql(const char *name, const char *sql)
+{
+	instr_time start_ts, exec_ts;
+
+	INSTR_TIME_SET_CURRENT(start_ts);
+
+	execute_sql_string(sql);
+
+	INSTR_TIME_SET_CURRENT(exec_ts);
+
+	elog(LOG, "exec %s in %.3f ms",
+		 name,
+		 (INSTR_TIME_GET_DOUBLE(exec_ts) - INSTR_TIME_GET_DOUBLE(start_ts)) * 1000);
+}
+
+static void
+exec_sql_file(const char *share_path, const char *filename)
+{
+	int length;
+	char *str;
+	char filepath[MAXPGPATH];
+
+	sprintf(filepath, "%s/%s", share_path, filename);
+
+	str = read_whole_file(filepath, &length);
+
+	exec_sql(filename, str);
+
+	pfree(str);
+}
+
 
 /* ----------------------------------------------------------------
  *						misc functions
diff --git a/src/backend/catalog/Makefile b/src/backend/catalog/Makefile
index eefebb7bb83..d014e52968a 100644
--- a/src/backend/catalog/Makefile
+++ b/src/backend/catalog/Makefile
@@ -125,6 +125,8 @@ install-data: bki-stamp installdirs
 	$(INSTALL_DATA) $(call vpathsearch,system_constraints.sql) '$(DESTDIR)$(datadir)/system_constraints.sql'
 	$(INSTALL_DATA) $(srcdir)/system_functions.sql '$(DESTDIR)$(datadir)/system_functions.sql'
 	$(INSTALL_DATA) $(srcdir)/system_views.sql '$(DESTDIR)$(datadir)/system_views.sql'
+	$(INSTALL_DATA) $(srcdir)/description.sql '$(DESTDIR)$(datadir)/description.sql'
+	$(INSTALL_DATA) $(srcdir)/privileges.sql '$(DESTDIR)$(datadir)/privileges.sql'
 	$(INSTALL_DATA) $(srcdir)/information_schema.sql '$(DESTDIR)$(datadir)/information_schema.sql'
 	$(INSTALL_DATA) $(srcdir)/sql_features.txt '$(DESTDIR)$(datadir)/sql_features.txt'
 
diff --git a/src/backend/catalog/description.sql b/src/backend/catalog/description.sql
new file mode 100644
index 00000000000..b46a3094452
--- /dev/null
+++ b/src/backend/catalog/description.sql
@@ -0,0 +1,16 @@
+/* Create default descriptions for operator implementation functions */
+WITH funcdescs AS (
+    SELECT p.oid as p_oid, o.oid as o_oid, oprname
+    FROM pg_proc p  JOIN pg_operator o ON oprcode = p.oid
+)
+INSERT INTO pg_description
+    SELECT p_oid, 'pg_proc'::regclass, 0,
+        'implementation of ' || oprname || ' operator'
+    FROM funcdescs
+    WHERE NOT EXISTS (
+           SELECT 1 FROM pg_description
+           WHERE objoid = p_oid AND classoid = 'pg_proc'::regclass)
+        AND NOT EXISTS (
+	    SELECT 1 FROM pg_description
+            WHERE objoid = o_oid AND classoid = 'pg_operator'::regclass
+                AND description LIKE 'deprecated%');
diff --git a/src/backend/catalog/privileges.sql b/src/backend/catalog/privileges.sql
new file mode 100644
index 00000000000..3843c970df5
--- /dev/null
+++ b/src/backend/catalog/privileges.sql
@@ -0,0 +1,154 @@
+/*
+ * Set up privileges
+ *
+ * We mark most system catalogs as world-readable.  We don't currently have
+ * to touch functions, languages, or databases, because their default
+ * permissions are OK.
+ *
+ * Some objects may require different permissions by default, so we
+ * make sure we don't overwrite privilege sets that have already been
+ * set (NOT NULL).
+ *
+ * Also populate pg_init_privs to save what the privileges are at init
+ * time.  This is used by pg_dump to allow users to change privileges
+ * on catalog objects and to have those privilege changes preserved
+ * across dump/reload and pg_upgrade.
+ *
+ * Note that pg_init_privs is only for per-database objects and therefore
+ * we don't include databases or tablespaces.
+ */
+
+UPDATE pg_class
+  SET relacl = (SELECT array_agg(a.acl) FROM
+ (SELECT '=r/"POSTGRES"' as acl
+  UNION SELECT unnest(pg_catalog.acldefault(
+    CASE WHEN relkind = 'S' THEN 's'
+         ELSE 'r' END::"char", 10::oid)) -- FIXME, inlined BOOTSTRAP_SUPERUSERID
+ ) as a)
+  WHERE relkind IN ('r', 'v', 'm','S')
+  AND relacl IS NULL;
+
+GRANT USAGE ON SCHEMA pg_catalog, public TO PUBLIC;
+REVOKE ALL ON pg_largeobject FROM PUBLIC;
+INSERT INTO pg_init_privs
+  (objoid, classoid, objsubid, initprivs, privtype)
+    SELECT
+        oid,
+        (SELECT oid FROM pg_class WHERE relname = 'pg_class'),
+        0,
+        relacl,
+        'i'
+    FROM
+        pg_class
+    WHERE
+        relacl IS NOT NULL
+        AND relkind IN ('r', 'v', 'm','S');
+
+INSERT INTO pg_init_privs
+  (objoid, classoid, objsubid, initprivs, privtype)
+    SELECT
+        pg_class.oid,
+        (SELECT oid FROM pg_class WHERE relname = 'pg_class'),
+        pg_attribute.attnum,
+        pg_attribute.attacl,
+        'i'
+    FROM
+        pg_class
+        JOIN pg_attribute ON (pg_class.oid = pg_attribute.attrelid)
+    WHERE
+        pg_attribute.attacl IS NOT NULL
+        AND pg_class.relkind IN ('r', 'v', 'm', 'S');
+
+INSERT INTO pg_init_privs
+  (objoid, classoid, objsubid, initprivs, privtype)
+    SELECT
+        oid,
+        (SELECT oid FROM pg_class WHERE relname = 'pg_proc'),
+        0,
+        proacl,
+        'i'
+    FROM
+        pg_proc
+    WHERE
+        proacl IS NOT NULL;
+
+INSERT INTO pg_init_privs
+  (objoid, classoid, objsubid, initprivs, privtype)
+    SELECT
+        oid,
+        (SELECT oid FROM pg_class WHERE relname = 'pg_type'),
+        0,
+        typacl,
+        'i'
+    FROM
+        pg_type
+    WHERE
+        typacl IS NOT NULL;
+
+INSERT INTO pg_init_privs
+  (objoid, classoid, objsubid, initprivs, privtype)
+    SELECT
+        oid,
+        (SELECT oid FROM pg_class WHERE relname = 'pg_language'),
+        0,
+        lanacl,
+        'i'
+    FROM
+        pg_language
+    WHERE
+        lanacl IS NOT NULL;
+
+INSERT INTO pg_init_privs
+  (objoid, classoid, objsubid, initprivs, privtype)
+    SELECT
+        oid,
+        (SELECT oid FROM pg_class WHERE
+         relname = 'pg_largeobject_metadata'),
+        0,
+        lomacl,
+        'i'
+    FROM
+        pg_largeobject_metadata
+    WHERE
+        lomacl IS NOT NULL;
+
+INSERT INTO pg_init_privs
+  (objoid, classoid, objsubid, initprivs, privtype)
+    SELECT
+        oid,
+        (SELECT oid FROM pg_class WHERE relname = 'pg_namespace'),
+        0,
+        nspacl,
+        'i'
+    FROM
+        pg_namespace
+    WHERE
+        nspacl IS NOT NULL;
+
+INSERT INTO pg_init_privs
+  (objoid, classoid, objsubid, initprivs, privtype)
+    SELECT
+        oid,
+        (SELECT oid FROM pg_class WHERE
+         relname = 'pg_foreign_data_wrapper'),
+        0,
+        fdwacl,
+        'i'
+    FROM
+        pg_foreign_data_wrapper
+    WHERE
+        fdwacl IS NOT NULL;
+
+INSERT INTO pg_init_privs
+  (objoid, classoid, objsubid, initprivs, privtype)
+    SELECT
+        oid,
+        (SELECT oid FROM pg_class
+         WHERE relname = 'pg_foreign_server'),
+        0,
+        srvacl,
+        'i'
+    FROM
+        pg_foreign_server
+    WHERE
+        srvacl IS NOT NULL;
diff --git a/src/backend/commands/extension.c b/src/backend/commands/extension.c
index 0e04304cb09..c46e607bccb 100644
--- a/src/backend/commands/extension.c
+++ b/src/backend/commands/extension.c
@@ -127,7 +127,6 @@ static void ApplyExtensionUpdates(Oid extensionOid,
 								  char *origSchemaName,
 								  bool cascade,
 								  bool is_create);
-static char *read_whole_file(const char *filename, int *length);
 
 
 /*
@@ -716,7 +715,7 @@ read_extension_script_file(const ExtensionControlFile *control,
  * on printing the whole string as errcontext in case of any error, and that
  * could be very long.
  */
-static void
+void
 execute_sql_string(const char *sql)
 {
 	List	   *raw_parsetree_list;
@@ -3429,7 +3428,7 @@ ExecAlterExtensionContentsStmt(AlterExtensionContentsStmt *stmt,
  * The file contents are returned as a single palloc'd chunk. For convenience
  * of the callers, an extra \0 byte is added to the end.
  */
-static char *
+char *
 read_whole_file(const char *filename, int *length)
 {
 	char	   *buf;
diff --git a/src/backend/main/main.c b/src/backend/main/main.c
index 3d67ce9dcea..3b28f9c57d0 100644
--- a/src/backend/main/main.c
+++ b/src/backend/main/main.c
@@ -394,6 +394,7 @@ help(const char *progname)
 	printf(_("  --check            selects check mode (must be first argument)\n"));
 	printf(_("  DBNAME             database name (mandatory argument in bootstrapping mode)\n"));
 	printf(_("  -r FILENAME        send stdout and stderr to given file\n"));
+	printf(_("  -s SHAREPATH       path to share directory\n"));
 
 	printf(_("\nPlease read the documentation for the complete list of run-time\n"
 			 "configuration settings and how to set them on the command line or in\n"
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c
index 3c7d08209f3..1e48645a748 100644
--- a/src/backend/tcop/postgres.c
+++ b/src/backend/tcop/postgres.c
@@ -1314,6 +1314,18 @@ exec_simple_query(const char *query_string)
 	debug_query_string = NULL;
 }
 
+/* just for bootstrap */
+void
+exec_simple_query_bootstrap(const char *query_string)
+{
+	MemoryContextSwitchTo(MessageContext);
+	SetCurrentStatementStartTimestamp();
+
+	exec_simple_query(query_string);
+
+	MemoryContextReset(MessageContext);
+}
+
 /*
  * exec_parse_message
  *
diff --git a/src/backend/utils/cache/relcache.c b/src/backend/utils/cache/relcache.c
index 2707fed12f4..6b4b14819c1 100644
--- a/src/backend/utils/cache/relcache.c
+++ b/src/backend/utils/cache/relcache.c
@@ -3949,8 +3949,6 @@ RelationCacheInitializePhase2(void)
 void
 RelationCacheInitializePhase3(void)
 {
-	HASH_SEQ_STATUS status;
-	RelIdCacheEnt *idhentry;
 	MemoryContext oldcxt;
 	bool		needNewCacheFile = !criticalSharedRelcachesBuilt;
 
@@ -3992,6 +3990,15 @@ RelationCacheInitializePhase3(void)
 	if (IsBootstrapProcessingMode())
 		return;
 
+	RelationCacheInitializePhase3b(needNewCacheFile);
+}
+
+void
+RelationCacheInitializePhase3b(bool needNewCacheFile)
+{
+	HASH_SEQ_STATUS status;
+	RelIdCacheEnt *idhentry;
+
 	/*
 	 * If we didn't get the critical system indexes loaded into relcache, do
 	 * so now.  These are critical because the catcache and/or opclass cache
diff --git a/src/bin/initdb/initdb.c b/src/bin/initdb/initdb.c
index 37ac928b2ef..bff2e5cb407 100644
--- a/src/bin/initdb/initdb.c
+++ b/src/bin/initdb/initdb.c
@@ -76,6 +76,7 @@
 #include "getopt_long.h"
 #include "mb/pg_wchar.h"
 #include "miscadmin.h"
+#include "portability/instr_time.h"
 
 
 /* Ideally this would be in a .h file, but it hardly seems worth the trouble */
@@ -158,12 +159,7 @@ static char *bki_file;
 static char *hba_file;
 static char *ident_file;
 static char *conf_file;
-static char *dictionary_file;
-static char *info_schema_file;
 static char *features_file;
-static char *system_constraints_file;
-static char *system_functions_file;
-static char *system_views_file;
 static bool success = false;
 static bool made_new_pgdata = false;
 static bool found_existing_pgdata = false;
@@ -201,8 +197,7 @@ static bool authwarning = false;
  * but here it is more convenient to pass it as an environment variable
  * (no quoting to worry about).
  */
-static const char *boot_options = "-F -c log_checkpoints=false";
-static const char *backend_options = "--single -F -O -j -c search_path=pg_catalog -c exit_on_error=true -c log_checkpoints=false";
+static const char *boot_options = " -F -c allow_system_table_mods=true -c search_path=pg_catalog -c exit_on_error=true";
 
 /* Additional switches to pass to backend (either boot or standalone) */
 static char *extra_options = "";
@@ -254,21 +249,10 @@ static void write_version_file(const char *extrapath);
 static void set_null_conf(void);
 static void test_config_settings(void);
 static void setup_config(void);
-static void bootstrap_template1(void);
-static void setup_auth(FILE *cmdfd);
 static void get_su_pwd(void);
-static void setup_depend(FILE *cmdfd);
-static void setup_run_file(FILE *cmdfd, const char *filename);
-static void setup_description(FILE *cmdfd);
-static void setup_collation(FILE *cmdfd);
-static void setup_privileges(FILE *cmdfd);
 static void set_info_version(void);
 static void setup_schema(FILE *cmdfd);
-static void load_plpgsql(FILE *cmdfd);
 static void set_remaining_details(FILE *cmdfd);
-static void vacuum_db(FILE *cmdfd);
-static void make_template0(FILE *cmdfd);
-static void make_postgres(FILE *cmdfd);
 static void trapsig(int signum);
 static void check_ok(void);
 static char *escape_quotes(const char *src);
@@ -1326,89 +1310,6 @@ setup_config(void)
 	check_ok();
 }
 
-
-/*
- * run the BKI script in bootstrap mode to create template1
- */
-static void
-bootstrap_template1(void)
-{
-	PG_CMD_DECL;
-	char	  **line;
-	char	  **bki_lines;
-	char		headerline[MAXPGPATH];
-
-	printf(_("running bootstrap script ... "));
-	fflush(stdout);
-
-	bki_lines = readfile(bki_file);
-
-	/* Check that bki file appears to be of the right version */
-
-	snprintf(headerline, sizeof(headerline), "# PostgreSQL %s\n",
-			 PG_MAJORVERSION);
-
-	if (strcmp(headerline, *bki_lines) != 0)
-	{
-		pg_log_error("input file \"%s\" does not belong to PostgreSQL %s",
-					 bki_file, PG_VERSION);
-		fprintf(stderr,
-				_("Check your installation or specify the correct path "
-				  "using the option -L.\n"));
-		exit(1);
-	}
-
-	/* Also ensure backend isn't confused by this environment var: */
-	unsetenv("PGCLIENTENCODING");
-
-	snprintf(cmd, sizeof(cmd),
-			 "\"%s\" --boot -X %d %s %s %s %s",
-			 backend_exec,
-			 wal_segment_size_mb * (1024 * 1024),
-			 data_checksums ? "-k" : "",
-			 boot_options, extra_options,
-			 debug ? "-d 5" : "");
-
-
-	PG_CMD_OPEN;
-
-	for (line = bki_lines; *line != NULL; line++)
-	{
-		PG_CMD_PUTS(*line);
-		free(*line);
-	}
-
-	PG_CMD_CLOSE;
-
-	free(bki_lines);
-
-	check_ok();
-}
-
-/*
- * set up the shadow password table
- */
-static void
-setup_auth(FILE *cmdfd)
-{
-	const char *const *line;
-	static const char *const pg_authid_setup[] = {
-		/*
-		 * The authid table shouldn't be readable except through views, to
-		 * ensure passwords are not publicly visible.
-		 */
-		"REVOKE ALL ON pg_authid FROM public;\n\n",
-		NULL
-	};
-
-	for (line = pg_authid_setup; *line != NULL; line++)
-		PG_CMD_PUTS(*line);
-
-	if (superuser_password)
-		PG_CMD_PRINTF("ALTER USER \"%s\" WITH PASSWORD E'%s';\n\n",
-					  username, escape_quotes(superuser_password));
-}
-
 /*
  * get the superuser password if required
  */
@@ -1472,249 +1373,6 @@ get_su_pwd(void)
 	superuser_password = pwd1;
 }
 
-/*
- * set up pg_depend
- */
-static void
-setup_depend(FILE *cmdfd)
-{
-	const char *const *line;
-	static const char *const pg_depend_setup[] = {
-		/*
-		 * Advance the OID counter so that subsequently-created objects aren't
-		 * pinned.
-		 */
-		"SELECT pg_stop_making_pinned_objects();\n\n",
-		NULL
-	};
-
-	for (line = pg_depend_setup; *line != NULL; line++)
-		PG_CMD_PUTS(*line);
-}
-
-/*
- * Run external file
- */
-static void
-setup_run_file(FILE *cmdfd, const char *filename)
-{
-	char	  **lines;
-
-	lines = readfile(filename);
-
-	for (char **line = lines; *line != NULL; line++)
-	{
-		PG_CMD_PUTS(*line);
-		free(*line);
-	}
-
-	PG_CMD_PUTS("\n\n");
-
-	free(lines);
-}
-
-/*
- * fill in extra description data
- */
-static void
-setup_description(FILE *cmdfd)
-{
-	/* Create default descriptions for operator implementation functions */
-	PG_CMD_PUTS("WITH funcdescs AS ( "
-				"SELECT p.oid as p_oid, o.oid as o_oid, oprname "
-				"FROM pg_proc p JOIN pg_operator o ON oprcode = p.oid ) "
-				"INSERT INTO pg_description "
-				"  SELECT p_oid, 'pg_proc'::regclass, 0, "
-				"    'implementation of ' || oprname || ' operator' "
-				"  FROM funcdescs "
-				"  WHERE NOT EXISTS (SELECT 1 FROM pg_description "
-				"   WHERE objoid = p_oid AND classoid = 'pg_proc'::regclass) "
-				"  AND NOT EXISTS (SELECT 1 FROM pg_description "
-				"   WHERE objoid = o_oid AND classoid = 'pg_operator'::regclass"
-				"         AND description LIKE 'deprecated%');\n\n");
-}
-
-/*
- * populate pg_collation
- */
-static void
-setup_collation(FILE *cmdfd)
-{
-	/*
-	 * Add an SQL-standard name.  We don't want to pin this, so it doesn't go
-	 * in pg_collation.h.  But add it before reading system collations, so
-	 * that it wins if libc defines a locale named ucs_basic.
-	 */
-	PG_CMD_PRINTF("INSERT INTO pg_collation (oid, collname, collnamespace, collowner, collprovider, collisdeterministic, collencoding, collcollate, collctype)"
-				  "VALUES (pg_nextoid('pg_catalog.pg_collation', 'oid', 'pg_catalog.pg_collation_oid_index'), 'ucs_basic', 'pg_catalog'::regnamespace, %u, '%c', true, %d, 'C', 'C');\n\n",
-				  BOOTSTRAP_SUPERUSERID, COLLPROVIDER_LIBC, PG_UTF8);
-
-	/* Now import all collations we can find in the operating system */
-	PG_CMD_PUTS("SELECT pg_import_system_collations('pg_catalog');\n\n");
-}
-
-/*
- * Set up privileges
- *
- * We mark most system catalogs as world-readable.  We don't currently have
- * to touch functions, languages, or databases, because their default
- * permissions are OK.
- *
- * Some objects may require different permissions by default, so we
- * make sure we don't overwrite privilege sets that have already been
- * set (NOT NULL).
- *
- * Also populate pg_init_privs to save what the privileges are at init
- * time.  This is used by pg_dump to allow users to change privileges
- * on catalog objects and to have those privilege changes preserved
- * across dump/reload and pg_upgrade.
- *
- * Note that pg_init_privs is only for per-database objects and therefore
- * we don't include databases or tablespaces.
- */
-static void
-setup_privileges(FILE *cmdfd)
-{
-	const char *const *line;
-	static const char *const privileges_setup[] = {
-		"UPDATE pg_class "
-		"  SET relacl = (SELECT array_agg(a.acl) FROM "
-		" (SELECT '=r/\"POSTGRES\"' as acl "
-		"  UNION SELECT unnest(pg_catalog.acldefault("
-		"    CASE WHEN relkind = " CppAsString2(RELKIND_SEQUENCE) " THEN 's' "
-		"         ELSE 'r' END::\"char\"," CppAsString2(BOOTSTRAP_SUPERUSERID) "::oid))"
-		" ) as a) "
-		"  WHERE relkind IN (" CppAsString2(RELKIND_RELATION) ", "
-		CppAsString2(RELKIND_VIEW) ", " CppAsString2(RELKIND_MATVIEW) ", "
-		CppAsString2(RELKIND_SEQUENCE) ")"
-		"  AND relacl IS NULL;\n\n",
-		"GRANT USAGE ON SCHEMA pg_catalog, public TO PUBLIC;\n\n",
-		"REVOKE ALL ON pg_largeobject FROM PUBLIC;\n\n",
-		"INSERT INTO pg_init_privs "
-		"  (objoid, classoid, objsubid, initprivs, privtype)"
-		"    SELECT"
-		"        oid,"
-		"        (SELECT oid FROM pg_class WHERE relname = 'pg_class'),"
-		"        0,"
-		"        relacl,"
-		"        'i'"
-		"    FROM"
-		"        pg_class"
-		"    WHERE"
-		"        relacl IS NOT NULL"
-		"        AND relkind IN (" CppAsString2(RELKIND_RELATION) ", "
-		CppAsString2(RELKIND_VIEW) ", " CppAsString2(RELKIND_MATVIEW) ", "
-		CppAsString2(RELKIND_SEQUENCE) ");\n\n",
-		"INSERT INTO pg_init_privs "
-		"  (objoid, classoid, objsubid, initprivs, privtype)"
-		"    SELECT"
-		"        pg_class.oid,"
-		"        (SELECT oid FROM pg_class WHERE relname = 'pg_class'),"
-		"        pg_attribute.attnum,"
-		"        pg_attribute.attacl,"
-		"        'i'"
-		"    FROM"
-		"        pg_class"
-		"        JOIN pg_attribute ON (pg_class.oid = pg_attribute.attrelid)"
-		"    WHERE"
-		"        pg_attribute.attacl IS NOT NULL"
-		"        AND pg_class.relkind IN (" CppAsString2(RELKIND_RELATION) ", "
-		CppAsString2(RELKIND_VIEW) ", " CppAsString2(RELKIND_MATVIEW) ", "
-		CppAsString2(RELKIND_SEQUENCE) ");\n\n",
-		"INSERT INTO pg_init_privs "
-		"  (objoid, classoid, objsubid, initprivs, privtype)"
-		"    SELECT"
-		"        oid,"
-		"        (SELECT oid FROM pg_class WHERE relname = 'pg_proc'),"
-		"        0,"
-		"        proacl,"
-		"        'i'"
-		"    FROM"
-		"        pg_proc"
-		"    WHERE"
-		"        proacl IS NOT NULL;\n\n",
-		"INSERT INTO pg_init_privs "
-		"  (objoid, classoid, objsubid, initprivs, privtype)"
-		"    SELECT"
-		"        oid,"
-		"        (SELECT oid FROM pg_class WHERE relname = 'pg_type'),"
-		"        0,"
-		"        typacl,"
-		"        'i'"
-		"    FROM"
-		"        pg_type"
-		"    WHERE"
-		"        typacl IS NOT NULL;\n\n",
-		"INSERT INTO pg_init_privs "
-		"  (objoid, classoid, objsubid, initprivs, privtype)"
-		"    SELECT"
-		"        oid,"
-		"        (SELECT oid FROM pg_class WHERE relname = 'pg_language'),"
-		"        0,"
-		"        lanacl,"
-		"        'i'"
-		"    FROM"
-		"        pg_language"
-		"    WHERE"
-		"        lanacl IS NOT NULL;\n\n",
-		"INSERT INTO pg_init_privs "
-		"  (objoid, classoid, objsubid, initprivs, privtype)"
-		"    SELECT"
-		"        oid,"
-		"        (SELECT oid FROM pg_class WHERE "
-		"         relname = 'pg_largeobject_metadata'),"
-		"        0,"
-		"        lomacl,"
-		"        'i'"
-		"    FROM"
-		"        pg_largeobject_metadata"
-		"    WHERE"
-		"        lomacl IS NOT NULL;\n\n",
-		"INSERT INTO pg_init_privs "
-		"  (objoid, classoid, objsubid, initprivs, privtype)"
-		"    SELECT"
-		"        oid,"
-		"        (SELECT oid FROM pg_class WHERE relname = 'pg_namespace'),"
-		"        0,"
-		"        nspacl,"
-		"        'i'"
-		"    FROM"
-		"        pg_namespace"
-		"    WHERE"
-		"        nspacl IS NOT NULL;\n\n",
-		"INSERT INTO pg_init_privs "
-		"  (objoid, classoid, objsubid, initprivs, privtype)"
-		"    SELECT"
-		"        oid,"
-		"        (SELECT oid FROM pg_class WHERE "
-		"         relname = 'pg_foreign_data_wrapper'),"
-		"        0,"
-		"        fdwacl,"
-		"        'i'"
-		"    FROM"
-		"        pg_foreign_data_wrapper"
-		"    WHERE"
-		"        fdwacl IS NOT NULL;\n\n",
-		"INSERT INTO pg_init_privs "
-		"  (objoid, classoid, objsubid, initprivs, privtype)"
-		"    SELECT"
-		"        oid,"
-		"        (SELECT oid FROM pg_class "
-		"         WHERE relname = 'pg_foreign_server'),"
-		"        0,"
-		"        srvacl,"
-		"        'i'"
-		"    FROM"
-		"        pg_foreign_server"
-		"    WHERE"
-		"        srvacl IS NOT NULL;\n\n",
-		NULL
-	};
-
-	for (line = privileges_setup; *line != NULL; line++)
-		PG_CMD_PUTS(*line);
-}
-
 /*
  * extract the strange version of version required for information schema
  * (09.08.0007abc)
@@ -1749,29 +1407,18 @@ set_info_version(void)
 static void
 setup_schema(FILE *cmdfd)
 {
-	setup_run_file(cmdfd, info_schema_file);
-
 	PG_CMD_PRINTF("UPDATE information_schema.sql_implementation_info "
 				  "  SET character_value = '%s' "
-				  "  WHERE implementation_info_name = 'DBMS VERSION';\n\n",
+				  "  WHERE implementation_info_name = 'DBMS VERSION';\n",
 				  infoversion);
 
 	PG_CMD_PRINTF("COPY information_schema.sql_features "
 				  "  (feature_id, feature_name, sub_feature_id, "
 				  "  sub_feature_name, is_supported, comments) "
-				  " FROM E'%s';\n\n",
+				  " FROM E'%s';\n",
 				  escape_quotes(features_file));
 }
 
-/*
- * load PL/pgSQL server-side language
- */
-static void
-load_plpgsql(FILE *cmdfd)
-{
-	PG_CMD_PUTS("CREATE EXTENSION plpgsql;\n\n");
-}
-
 /*
  * Set some remaining details that aren't known when postgres.bki is made.
  *
@@ -1796,8 +1443,8 @@ set_remaining_details(FILE *cmdfd)
 	 * locale/encoding without cheating.
 	 */
 	static char *final_details[] = {
-		"UPDATE pg_authid SET rolname = E'SUPERUSER_NAME' WHERE rolname = 'POSTGRES';\n\n",
-		"UPDATE pg_database SET encoding = E'ENCODING', datcollate = E'LC_COLLATE', datctype = E'LC_CTYPE';\n\n",
+		"UPDATE pg_authid SET rolname = E'SUPERUSER_NAME' WHERE rolname = 'POSTGRES';\n",
+		"UPDATE pg_database SET encoding = E'ENCODING', datcollate = E'LC_COLLATE', datctype = E'LC_CTYPE';\n",
 		NULL
 	};
 
@@ -1814,93 +1461,6 @@ set_remaining_details(FILE *cmdfd)
 		PG_CMD_PUTS(*line);
 }
 
-/*
- * clean everything up in template1
- */
-static void
-vacuum_db(FILE *cmdfd)
-{
-	/* Run analyze before VACUUM so the statistics are frozen. */
-	PG_CMD_PUTS("ANALYZE;\n\nVACUUM FREEZE;\n\n");
-}
-
-/*
- * copy template1 to template0
- */
-static void
-make_template0(FILE *cmdfd)
-{
-	const char *const *line;
-
-	/*
-	 * pg_upgrade tries to preserve database OIDs across upgrades. It's smart
-	 * enough to drop and recreate a conflicting database with the same name,
-	 * but if the same OID were used for one system-created database in the
-	 * old cluster and a different system-created database in the new cluster,
-	 * it would fail. To avoid that, assign a fixed OID to template0 rather
-	 * than letting the server choose one.
-	 *
-	 * (Note that, while the user could have dropped and recreated these
-	 * objects in the old cluster, the problem scenario only exists if the OID
-	 * that is in use in the old cluster is also used in the new cluster - and
-	 * the new cluster should be the result of a fresh initdb.)
-	 */
-	static const char *const template0_setup[] = {
-		"CREATE DATABASE template0 IS_TEMPLATE = true ALLOW_CONNECTIONS = false OID = "
-		CppAsString2(Template0ObjectId) ";\n\n",
-
-		/*
-		 * template0 shouldn't have any collation-dependent objects, so unset
-		 * the collation version.  This disables collation version checks when
-		 * making a new database from it.
-		 */
-		"UPDATE pg_database SET datcollversion = NULL WHERE datname = 'template0';\n\n",
-
-		/*
-		 * While we are here, do set the collation version on template1.
-		 */
-		"UPDATE pg_database SET datcollversion = pg_database_collation_actual_version(oid) WHERE datname = 'template1';\n\n",
-
-		/*
-		 * Explicitly revoke public create-schema and create-temp-table
-		 * privileges in template1 and template0; else the latter would be on
-		 * by default
-		 */
-		"REVOKE CREATE,TEMPORARY ON DATABASE template1 FROM public;\n\n",
-		"REVOKE CREATE,TEMPORARY ON DATABASE template0 FROM public;\n\n",
-
-		"COMMENT ON DATABASE template0 IS 'unmodifiable empty database';\n\n",
-
-		/*
-		 * Finally vacuum to clean up dead rows in pg_database
-		 */
-		"VACUUM pg_database;\n\n",
-		NULL
-	};
-
-	for (line = template0_setup; *line; line++)
-		PG_CMD_PUTS(*line);
-}
-
-/*
- * copy template1 to postgres
- */
-static void
-make_postgres(FILE *cmdfd)
-{
-	const char *const *line;
-
-	/* Assign a fixed OID to postgres, for the same reasons as template0 */
-	static const char *const postgres_setup[] = {
-		"CREATE DATABASE postgres OID = " CppAsString2(PostgresObjectId) ";\n\n",
-		"COMMENT ON DATABASE postgres IS 'default administrative connection database';\n\n",
-		NULL
-	};
-
-	for (line = postgres_setup; *line; line++)
-		PG_CMD_PUTS(*line);
-}
-
 /*
  * signal handler in case we are interrupted.
  *
@@ -2446,16 +2006,10 @@ setup_locale_encoding(void)
 void
 setup_data_file_paths(void)
 {
-	set_input(&bki_file, "postgres.bki");
 	set_input(&hba_file, "pg_hba.conf.sample");
 	set_input(&ident_file, "pg_ident.conf.sample");
 	set_input(&conf_file, "postgresql.conf.sample");
-	set_input(&dictionary_file, "snowball_create.sql");
-	set_input(&info_schema_file, "information_schema.sql");
 	set_input(&features_file, "sql_features.txt");
-	set_input(&system_constraints_file, "system_constraints.sql");
-	set_input(&system_functions_file, "system_functions.sql");
-	set_input(&system_views_file, "system_views.sql");
 
 	if (show_setting || debug)
 	{
@@ -2474,16 +2028,9 @@ setup_data_file_paths(void)
 			exit(0);
 	}
 
-	check_input(bki_file);
 	check_input(hba_file);
 	check_input(ident_file);
 	check_input(conf_file);
-	check_input(dictionary_file);
-	check_input(info_schema_file);
-	check_input(features_file);
-	check_input(system_constraints_file);
-	check_input(system_functions_file);
-	check_input(system_views_file);
 }
 
 
@@ -2744,6 +2291,7 @@ initialize_data_directory(void)
 {
 	PG_CMD_DECL;
 	int			i;
+	instr_time	last_ts, cur_ts;
 
 	setup_signals();
 
@@ -2788,68 +2336,46 @@ initialize_data_directory(void)
 	write_version_file(NULL);
 
 	/* Select suitable configuration settings */
+	INSTR_TIME_SET_CURRENT(last_ts);
 	set_null_conf();
 	test_config_settings();
+	INSTR_TIME_SET_CURRENT(cur_ts);
+	fprintf(stderr, "config determination in %.3f ms\n",
+			(INSTR_TIME_GET_DOUBLE(cur_ts) - INSTR_TIME_GET_DOUBLE(last_ts)) * 1000);
 
 	/* Now create all the text config files */
 	setup_config();
 
-	/* Bootstrap template1 */
-	bootstrap_template1();
-
 	/*
 	 * Make the per-database PG_VERSION for template1 only after init'ing it
+	 *
+	 * FIXME: move to server
 	 */
 	write_version_file("base/1");
 
-	/*
-	 * Create the stuff we don't need to use bootstrap mode for, using a
-	 * backend running in simple standalone mode.
-	 */
-	fputs(_("performing post-bootstrap initialization ... "), stdout);
-	fflush(stdout);
-
 	snprintf(cmd, sizeof(cmd),
-			 "\"%s\" %s %s template1 >%s",
-			 backend_exec, backend_options, extra_options,
+			 "\"%s\" --boot -s \"%s\" -X %d %s %s %s %s >%s 2>&1",
+			 backend_exec,
+			 share_path,
+			 wal_segment_size_mb * (1024 * 1024),
+			 data_checksums ? "-k" : "",
+			 boot_options, extra_options,
+			 debug ? "-d 5" : "",
 			 DEVNULL);
 
+	/* Also ensure backend isn't confused by this environment var: */
+	unsetenv("PGCLIENTENCODING");
+
+	printf(_("running database bootstrap ... "));
+
 	PG_CMD_OPEN;
 
-	setup_auth(cmdfd);
-
-	setup_run_file(cmdfd, system_constraints_file);
-
-	setup_run_file(cmdfd, system_functions_file);
-
-	setup_depend(cmdfd);
-
-	/*
-	 * Note that no objects created after setup_depend() will be "pinned".
-	 * They are all droppable at the whim of the DBA.
-	 */
-
-	setup_run_file(cmdfd, system_views_file);
-
-	setup_description(cmdfd);
-
-	setup_collation(cmdfd);
-
-	setup_run_file(cmdfd, dictionary_file);
-
-	setup_privileges(cmdfd);
-
 	setup_schema(cmdfd);
-
-	load_plpgsql(cmdfd);
-
 	set_remaining_details(cmdfd);
 
-	vacuum_db(cmdfd);
-
-	make_template0(cmdfd);
-
-	make_postgres(cmdfd);
+	if (superuser_password)
+		PG_CMD_PRINTF("ALTER USER \"%s\" WITH PASSWORD E'%s';\n",
+					  username, escape_quotes(superuser_password));
 
 	PG_CMD_CLOSE;
 
@@ -3178,7 +2704,7 @@ main(int argc, char *argv[])
 	else
 		printf(_("\nSync to disk skipped.\nThe data directory might become corrupt if the operating system crashes.\n"));
 
-	if (authwarning)
+	if (authwarning && false)
 	{
 		printf("\n");
 		pg_log_warning("enabling \"trust\" authentication for local connections");
-- 
2.34.0

