initdb: Refactor PG_CMD_PUTS loops

Keeping the SQL commands that initdb runs in string arrays before
feeding them to PG_CMD_PUTS() seems unnecessarily verbose and
inflexible.  In some cases, the array only has one member.  In other
cases, one might want to use PG_CMD_PRINTF() instead, to parametrize a
command, but that would require breaking up the loop or using
workarounds like replace_token().  Unwind all that; it's much simpler
that way.

Reviewed-by: John Naylor <john.naylor@enterprisedb.com>
Reviewed-by: Andrew Dunstan <andrew@dunslane.net>
Discussion: https://www.postgresql.org/message-id/flat/2c50823b-f453-bb97-e38b-34751c51dcdf%40enterprisedb.com
This commit is contained in:
Peter Eisentraut 2022-12-05 23:28:59 +01:00
parent d69d01ba9d
commit 1bd47d0dca

View File

@ -1350,18 +1350,11 @@ bootstrap_template1(void)
static void static void
setup_auth(FILE *cmdfd) 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.
* The authid table shouldn't be readable except through views, to */
* ensure passwords are not publicly visible. PG_CMD_PUTS("REVOKE ALL ON pg_authid FROM public;\n\n");
*/
"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) if (superuser_password)
PG_CMD_PRINTF("ALTER USER \"%s\" WITH PASSWORD E'%s';\n\n", PG_CMD_PRINTF("ALTER USER \"%s\" WITH PASSWORD E'%s';\n\n",
@ -1433,18 +1426,11 @@ get_su_pwd(void)
static void static void
setup_depend(FILE *cmdfd) 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.
* Advance the OID counter so that subsequently-created objects aren't */
* pinned. PG_CMD_PUTS("SELECT pg_stop_making_pinned_objects();\n\n");
*/
"SELECT pg_stop_making_pinned_objects();\n\n",
NULL
};
for (line = pg_depend_setup; *line != NULL; line++)
PG_CMD_PUTS(*line);
} }
/* /*
@ -1530,147 +1516,138 @@ setup_collation(FILE *cmdfd)
static void static void
setup_privileges(FILE *cmdfd) setup_privileges(FILE *cmdfd)
{ {
char **line; PG_CMD_PRINTF("UPDATE pg_class "
char **priv_lines; " SET relacl = (SELECT array_agg(a.acl) FROM "
static char *privileges_setup[] = { " (SELECT E'=r/\"%s\"' as acl "
"UPDATE pg_class " " UNION SELECT unnest(pg_catalog.acldefault("
" SET relacl = (SELECT array_agg(a.acl) FROM " " CASE WHEN relkind = " CppAsString2(RELKIND_SEQUENCE) " THEN 's' "
" (SELECT E'=r/\"$POSTGRES_SUPERUSERNAME\"' as acl " " ELSE 'r' END::\"char\"," CppAsString2(BOOTSTRAP_SUPERUSERID) "::oid))"
" UNION SELECT unnest(pg_catalog.acldefault(" " ) as a) "
" CASE WHEN relkind = " CppAsString2(RELKIND_SEQUENCE) " THEN 's' " " WHERE relkind IN (" CppAsString2(RELKIND_RELATION) ", "
" ELSE 'r' END::\"char\"," CppAsString2(BOOTSTRAP_SUPERUSERID) "::oid))" CppAsString2(RELKIND_VIEW) ", " CppAsString2(RELKIND_MATVIEW) ", "
" ) as a) " CppAsString2(RELKIND_SEQUENCE) ")"
" WHERE relkind IN (" CppAsString2(RELKIND_RELATION) ", " " AND relacl IS NULL;\n\n",
CppAsString2(RELKIND_VIEW) ", " CppAsString2(RELKIND_MATVIEW) ", " escape_quotes(username));
CppAsString2(RELKIND_SEQUENCE) ")" PG_CMD_PUTS("GRANT USAGE ON SCHEMA pg_catalog, public TO PUBLIC;\n\n");
" AND relacl IS NULL;\n\n", PG_CMD_PUTS("REVOKE ALL ON pg_largeobject FROM PUBLIC;\n\n");
"GRANT USAGE ON SCHEMA pg_catalog, public TO PUBLIC;\n\n", PG_CMD_PUTS("INSERT INTO pg_init_privs "
"REVOKE ALL ON pg_largeobject FROM PUBLIC;\n\n", " (objoid, classoid, objsubid, initprivs, privtype)"
"INSERT INTO pg_init_privs " " SELECT"
" (objoid, classoid, objsubid, initprivs, privtype)" " oid,"
" SELECT" " (SELECT oid FROM pg_class WHERE relname = 'pg_class'),"
" oid," " 0,"
" (SELECT oid FROM pg_class WHERE relname = 'pg_class')," " relacl,"
" 0," " 'i'"
" relacl," " FROM"
" 'i'" " pg_class"
" FROM" " WHERE"
" pg_class" " relacl IS NOT NULL"
" WHERE" " AND relkind IN (" CppAsString2(RELKIND_RELATION) ", "
" relacl IS NOT NULL" CppAsString2(RELKIND_VIEW) ", " CppAsString2(RELKIND_MATVIEW) ", "
" AND relkind IN (" CppAsString2(RELKIND_RELATION) ", " CppAsString2(RELKIND_SEQUENCE) ");\n\n");
CppAsString2(RELKIND_VIEW) ", " CppAsString2(RELKIND_MATVIEW) ", " PG_CMD_PUTS("INSERT INTO pg_init_privs "
CppAsString2(RELKIND_SEQUENCE) ");\n\n", " (objoid, classoid, objsubid, initprivs, privtype)"
"INSERT INTO pg_init_privs " " SELECT"
" (objoid, classoid, objsubid, initprivs, privtype)" " pg_class.oid,"
" SELECT" " (SELECT oid FROM pg_class WHERE relname = 'pg_class'),"
" pg_class.oid," " pg_attribute.attnum,"
" (SELECT oid FROM pg_class WHERE relname = 'pg_class')," " pg_attribute.attacl,"
" pg_attribute.attnum," " 'i'"
" pg_attribute.attacl," " FROM"
" 'i'" " pg_class"
" FROM" " JOIN pg_attribute ON (pg_class.oid = pg_attribute.attrelid)"
" pg_class" " WHERE"
" JOIN pg_attribute ON (pg_class.oid = pg_attribute.attrelid)" " pg_attribute.attacl IS NOT NULL"
" WHERE" " AND pg_class.relkind IN (" CppAsString2(RELKIND_RELATION) ", "
" pg_attribute.attacl IS NOT NULL" CppAsString2(RELKIND_VIEW) ", " CppAsString2(RELKIND_MATVIEW) ", "
" AND pg_class.relkind IN (" CppAsString2(RELKIND_RELATION) ", " CppAsString2(RELKIND_SEQUENCE) ");\n\n");
CppAsString2(RELKIND_VIEW) ", " CppAsString2(RELKIND_MATVIEW) ", " PG_CMD_PUTS("INSERT INTO pg_init_privs "
CppAsString2(RELKIND_SEQUENCE) ");\n\n", " (objoid, classoid, objsubid, initprivs, privtype)"
"INSERT INTO pg_init_privs " " SELECT"
" (objoid, classoid, objsubid, initprivs, privtype)" " oid,"
" SELECT" " (SELECT oid FROM pg_class WHERE relname = 'pg_proc'),"
" oid," " 0,"
" (SELECT oid FROM pg_class WHERE relname = 'pg_proc')," " proacl,"
" 0," " 'i'"
" proacl," " FROM"
" 'i'" " pg_proc"
" FROM" " WHERE"
" pg_proc" " proacl IS NOT NULL;\n\n");
" WHERE" PG_CMD_PUTS("INSERT INTO pg_init_privs "
" proacl IS NOT NULL;\n\n", " (objoid, classoid, objsubid, initprivs, privtype)"
"INSERT INTO pg_init_privs " " SELECT"
" (objoid, classoid, objsubid, initprivs, privtype)" " oid,"
" SELECT" " (SELECT oid FROM pg_class WHERE relname = 'pg_type'),"
" oid," " 0,"
" (SELECT oid FROM pg_class WHERE relname = 'pg_type')," " typacl,"
" 0," " 'i'"
" typacl," " FROM"
" 'i'" " pg_type"
" FROM" " WHERE"
" pg_type" " typacl IS NOT NULL;\n\n");
" WHERE" PG_CMD_PUTS("INSERT INTO pg_init_privs "
" typacl IS NOT NULL;\n\n", " (objoid, classoid, objsubid, initprivs, privtype)"
"INSERT INTO pg_init_privs " " SELECT"
" (objoid, classoid, objsubid, initprivs, privtype)" " oid,"
" SELECT" " (SELECT oid FROM pg_class WHERE relname = 'pg_language'),"
" oid," " 0,"
" (SELECT oid FROM pg_class WHERE relname = 'pg_language')," " lanacl,"
" 0," " 'i'"
" lanacl," " FROM"
" 'i'" " pg_language"
" FROM" " WHERE"
" pg_language" " lanacl IS NOT NULL;\n\n");
" WHERE" PG_CMD_PUTS("INSERT INTO pg_init_privs "
" lanacl IS NOT NULL;\n\n", " (objoid, classoid, objsubid, initprivs, privtype)"
"INSERT INTO pg_init_privs " " SELECT"
" (objoid, classoid, objsubid, initprivs, privtype)" " oid,"
" SELECT" " (SELECT oid FROM pg_class WHERE "
" oid," " relname = 'pg_largeobject_metadata'),"
" (SELECT oid FROM pg_class WHERE " " 0,"
" relname = 'pg_largeobject_metadata')," " lomacl,"
" 0," " 'i'"
" lomacl," " FROM"
" 'i'" " pg_largeobject_metadata"
" FROM" " WHERE"
" pg_largeobject_metadata" " lomacl IS NOT NULL;\n\n");
" WHERE" PG_CMD_PUTS("INSERT INTO pg_init_privs "
" lomacl IS NOT NULL;\n\n", " (objoid, classoid, objsubid, initprivs, privtype)"
"INSERT INTO pg_init_privs " " SELECT"
" (objoid, classoid, objsubid, initprivs, privtype)" " oid,"
" SELECT" " (SELECT oid FROM pg_class WHERE relname = 'pg_namespace'),"
" oid," " 0,"
" (SELECT oid FROM pg_class WHERE relname = 'pg_namespace')," " nspacl,"
" 0," " 'i'"
" nspacl," " FROM"
" 'i'" " pg_namespace"
" FROM" " WHERE"
" pg_namespace" " nspacl IS NOT NULL;\n\n");
" WHERE" PG_CMD_PUTS("INSERT INTO pg_init_privs "
" nspacl IS NOT NULL;\n\n", " (objoid, classoid, objsubid, initprivs, privtype)"
"INSERT INTO pg_init_privs " " SELECT"
" (objoid, classoid, objsubid, initprivs, privtype)" " oid,"
" SELECT" " (SELECT oid FROM pg_class WHERE "
" oid," " relname = 'pg_foreign_data_wrapper'),"
" (SELECT oid FROM pg_class WHERE " " 0,"
" relname = 'pg_foreign_data_wrapper')," " fdwacl,"
" 0," " 'i'"
" fdwacl," " FROM"
" 'i'" " pg_foreign_data_wrapper"
" FROM" " WHERE"
" pg_foreign_data_wrapper" " fdwacl IS NOT NULL;\n\n");
" WHERE" PG_CMD_PUTS("INSERT INTO pg_init_privs "
" fdwacl IS NOT NULL;\n\n", " (objoid, classoid, objsubid, initprivs, privtype)"
"INSERT INTO pg_init_privs " " SELECT"
" (objoid, classoid, objsubid, initprivs, privtype)" " oid,"
" SELECT" " (SELECT oid FROM pg_class "
" oid," " WHERE relname = 'pg_foreign_server'),"
" (SELECT oid FROM pg_class " " 0,"
" WHERE relname = 'pg_foreign_server')," " srvacl,"
" 0," " 'i'"
" srvacl," " FROM"
" 'i'" " pg_foreign_server"
" FROM" " WHERE"
" pg_foreign_server" " srvacl IS NOT NULL;\n\n");
" WHERE"
" srvacl IS NOT NULL;\n\n",
NULL
};
priv_lines = replace_token(privileges_setup, "$POSTGRES_SUPERUSERNAME",
escape_quotes(username));
for (line = priv_lines; *line != NULL; line++)
PG_CMD_PUTS(*line);
} }
/* /*
@ -1746,8 +1723,6 @@ vacuum_db(FILE *cmdfd)
static void static void
make_template0(FILE *cmdfd) make_template0(FILE *cmdfd)
{ {
const char *const *line;
/* /*
* pg_upgrade tries to preserve database OIDs across upgrades. It's smart * pg_upgrade tries to preserve database OIDs across upgrades. It's smart
* enough to drop and recreate a conflicting database with the same name, * enough to drop and recreate a conflicting database with the same name,
@ -1765,42 +1740,36 @@ make_template0(FILE *cmdfd)
* are cheap. "STRATEGY = wal_log" would generate more WAL, which would be * are cheap. "STRATEGY = wal_log" would generate more WAL, which would be
* a little bit slower and make the new cluster a little bit bigger. * a little bit slower and make the new cluster a little bit bigger.
*/ */
static const char *const template0_setup[] = { PG_CMD_PUTS("CREATE DATABASE template0 IS_TEMPLATE = true ALLOW_CONNECTIONS = false"
"CREATE DATABASE template0 IS_TEMPLATE = true ALLOW_CONNECTIONS = false" " OID = " CppAsString2(Template0DbOid)
" OID = " CppAsString2(Template0DbOid) " STRATEGY = file_copy;\n\n");
" STRATEGY = file_copy;\n\n",
/* /*
* template0 shouldn't have any collation-dependent objects, so unset * template0 shouldn't have any collation-dependent objects, so unset
* the collation version. This disables collation version checks when * the collation version. This disables collation version checks when
* making a new database from it. * making a new database from it.
*/ */
"UPDATE pg_database SET datcollversion = NULL WHERE datname = 'template0';\n\n", PG_CMD_PUTS("UPDATE pg_database SET datcollversion = NULL WHERE datname = 'template0';\n\n");
/* /*
* While we are here, do set the collation version on template1. * 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", PG_CMD_PUTS("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 * Explicitly revoke public create-schema and create-temp-table
* privileges in template1 and template0; else the latter would be on * privileges in template1 and template0; else the latter would be on
* by default * by default
*/ */
"REVOKE CREATE,TEMPORARY ON DATABASE template1 FROM public;\n\n", PG_CMD_PUTS("REVOKE CREATE,TEMPORARY ON DATABASE template1 FROM public;\n\n");
"REVOKE CREATE,TEMPORARY ON DATABASE template0 FROM public;\n\n", PG_CMD_PUTS("REVOKE CREATE,TEMPORARY ON DATABASE template0 FROM public;\n\n");
"COMMENT ON DATABASE template0 IS 'unmodifiable empty database';\n\n", PG_CMD_PUTS("COMMENT ON DATABASE template0 IS 'unmodifiable empty database';\n\n");
/* /*
* Finally vacuum to clean up dead rows in pg_database * Finally vacuum to clean up dead rows in pg_database
*/ */
"VACUUM pg_database;\n\n", PG_CMD_PUTS("VACUUM pg_database;\n\n");
NULL
};
for (line = template0_setup; *line; line++)
PG_CMD_PUTS(*line);
} }
/* /*
@ -1809,21 +1778,13 @@ make_template0(FILE *cmdfd)
static void static void
make_postgres(FILE *cmdfd) make_postgres(FILE *cmdfd)
{ {
const char *const *line;
/* /*
* Just as we did for template0, and for the same reasons, assign a fixed * Just as we did for template0, and for the same reasons, assign a fixed
* OID to postgres and select the file_copy strategy. * OID to postgres and select the file_copy strategy.
*/ */
static const char *const postgres_setup[] = { PG_CMD_PUTS("CREATE DATABASE postgres OID = " CppAsString2(PostgresDbOid)
"CREATE DATABASE postgres OID = " CppAsString2(PostgresDbOid) " STRATEGY = file_copy;\n\n");
" STRATEGY = file_copy;\n\n", PG_CMD_PUTS("COMMENT ON DATABASE postgres IS 'default administrative connection database';\n\n");
"COMMENT ON DATABASE postgres IS 'default administrative connection database';\n\n",
NULL
};
for (line = postgres_setup; *line; line++)
PG_CMD_PUTS(*line);
} }
/* /*