PostgreSQL数据库集簇初始化——initdb初始化数据库(数据库初始设置二)
数据库初始设置包括创建系统视图、系统表TOAST表等,复制template1来创建template0和postgres,这些操作都用普通的SQL命令来完成。
setup_sysviews函数建立系统视图,从system_views_file指向的文件读取SQL,并控制子进程执行这些SQL。
1 static void setup_sysviews(void) { 2 PG_CMD_DECL; 3 char **line; 4 char **sysviews_setup; 5 fputs(_("creating system views ... "), stdout); 6 fflush(stdout); 7 sysviews_setup = readfile(system_views_file); 8 /* We use -j here to avoid backslashing stuff in system_views.sql */ 9 snprintf(cmd, sizeof(cmd),"\"%s\" %s -j template1 >%s",backend_exec, backend_options,DEVNULL); 10 PG_CMD_OPEN; 11 for (line = sysviews_setup; *line != NULL; line++){ 12 PG_CMD_PUTS(*line); 13 free(*line); 14 } 15 PG_CMD_CLOSE; 16 free(sysviews_setup); 17 check_ok(); 18 }
setup_description函数加载描述数据,代码中写死了需要执行的SQL。
1 static void setup_description(void){ 2 PG_CMD_DECL; 3 fputs(_("loading system objects' descriptions ... "), stdout); 4 fflush(stdout); 5 snprintf(cmd, sizeof(cmd),"\"%s\" %s template1 >%s",backend_exec, backend_options,DEVNULL); 6 PG_CMD_OPEN; 7 PG_CMD_PUTS("CREATE TEMP TABLE tmp_pg_description ( " 8 " objoid oid, " 9 " classname name, " 10 " objsubid int4, " 11 " description text) WITHOUT OIDS;\n"); 12 PG_CMD_PRINTF1("COPY tmp_pg_description FROM E'%s';\n",escape_quotes(desc_file)); 13 PG_CMD_PUTS("INSERT INTO pg_description " 14 " SELECT t.objoid, c.oid, t.objsubid, t.description " 15 " FROM tmp_pg_description t, pg_class c " 16 " WHERE c.relname = t.classname;\n"); 17 PG_CMD_PUTS("CREATE TEMP TABLE tmp_pg_shdescription ( " 18 " objoid oid, " 19 " classname name, " 20 " description text) WITHOUT OIDS;\n"); 21 PG_CMD_PRINTF1("COPY tmp_pg_shdescription FROM E'%s';\n",escape_quotes(shdesc_file)); 22 PG_CMD_PUTS("INSERT INTO pg_shdescription " 23 " SELECT t.objoid, c.oid, t.description " 24 " FROM tmp_pg_shdescription t, pg_class c " 25 " WHERE c.relname = t.classname;\n"); 26 PG_CMD_CLOSE; 27 check_ok(); 28 }
setup_conversion函数加载转换函数
static void setup_conversion(void){ PG_CMD_DECL; char **line; char **conv_lines; fputs(_("creating conversions ... "), stdout); fflush(stdout); snprintf(cmd, sizeof(cmd), "\"%s\" %s template1 >%s",backend_exec, backend_options,DEVNULL); PG_CMD_OPEN; conv_lines = readfile(conversion_file); for (line = conv_lines; *line != NULL; line++){ if (strstr(*line, "DROP CONVERSION") != *line) PG_CMD_PUTS(*line); free(*line); } free(conv_lines); PG_CMD_CLOSE; check_ok(); }
setup_dictionary函数加载外部字典(Snowball stemmers),从dictionary_file指向的文件读取SQL,并控制子进程执行这些SQL。
static void setup_dictionary(void){ PG_CMD_DECL; char **line; char **conv_lines; fputs(_("creating dictionaries ... "), stdout); fflush(stdout); /* We use -j here to avoid backslashing stuff */ snprintf(cmd, sizeof(cmd), "\"%s\" %s -j template1 >%s",backend_exec, backend_options,DEVNULL); PG_CMD_OPEN; conv_lines = readfile(dictionary_file); for (line = conv_lines; *line != NULL; line++){ PG_CMD_PUTS(*line); free(*line); } free(conv_lines); PG_CMD_CLOSE; check_ok(); }
setup_privileges函数建立优先级,mark一些系统表为world-readable,某些对象需要不同的permissions
1 static void setup_privileges(void) { 2 PG_CMD_DECL; 3 char **line; 4 char **priv_lines; 5 static char *privileges_setup[] = { 6 "UPDATE pg_class " 7 " SET relacl = E'{\"=r/\\\\\"$POSTGRES_SUPERUSERNAME\\\\\"\"}' " 8 " WHERE relkind IN ('r', 'v', 'S') AND relacl IS NULL;\n", 9 "GRANT USAGE ON SCHEMA pg_catalog TO PUBLIC;\n", 10 "GRANT CREATE, USAGE ON SCHEMA public TO PUBLIC;\n", 11 NULL 12 }; 13 14 fputs(_("setting privileges on built-in objects ... "), stdout); 15 fflush(stdout); 16 snprintf(cmd, sizeof(cmd), "\"%s\" %s template1 >%s", backend_exec, backend_options, DEVNULL); 17 PG_CMD_OPEN; 18 priv_lines = replace_token(privileges_setup, "$POSTGRES_SUPERUSERNAME", username); 19 for (line = priv_lines; *line != NULL; line++) 20 PG_CMD_PUTS(*line); 21 PG_CMD_CLOSE; 22 check_ok(); 23 }
setup_schema函数load info schema并且从features文件中populate
1 static void setup_schema(void){ 2 PG_CMD_DECL; 3 char **line; 4 char **lines; 5 fputs(_("creating information schema ... "), stdout); 6 fflush(stdout); 7 lines = readfile(info_schema_file); 8 /* We use -j here to avoid backslashing stuff in information_schema.sql */ 9 snprintf(cmd, sizeof(cmd),"\"%s\" %s -j template1 >%s",backend_exec, backend_options,DEVNULL); 10 PG_CMD_OPEN; 11 for (line = lines; *line != NULL; line++){ 12 PG_CMD_PUTS(*line); 13 free(*line); 14 } 15 free(lines); 16 PG_CMD_CLOSE; 17 snprintf(cmd, sizeof(cmd),"\"%s\" %s template1 >%s",backend_exec, backend_options,DEVNULL); 18 PG_CMD_OPEN; 19 PG_CMD_PRINTF1("UPDATE information_schema.sql_implementation_info " 20 " SET character_value = '%s' " 21 " WHERE implementation_info_name = 'DBMS VERSION';\n", 22 infoversion); 23 PG_CMD_PRINTF1("COPY information_schema.sql_features " 24 " (feature_id, feature_name, sub_feature_id, " 25 " sub_feature_name, is_supported, comments) " 26 " FROM E'%s';\n", 27 escape_quotes(features_file)); 28 PG_CMD_CLOSE; 29 check_ok(); 30 }
vacuum_db函数清除template1中的内容
1 static void vacuum_db(void){ 2 PG_CMD_DECL; 3 fputs(_("vacuuming database template1 ... "), stdout); 4 fflush(stdout); 5 snprintf(cmd, sizeof(cmd),"\"%s\" %s template1 >%s",backend_exec, backend_options,DEVNULL); 6 PG_CMD_OPEN; 7 PG_CMD_PUTS("ANALYZE;\nVACUUM FULL;\nVACUUM FREEZE;\n"); 8 PG_CMD_CLOSE; 9 check_ok(); 10 }
make_template0函数将template0复制到templae0中
1 static void make_template0(void){ 2 PG_CMD_DECL; 3 const char **line; 4 static const char *template0_setup[] = { 5 "CREATE DATABASE template0;\n", 6 "UPDATE pg_database SET " 7 " datistemplate = 't', " 8 " datallowconn = 'f' " 9 " WHERE datname = 'template0';\n", 10 /* We use the OID of template0 to determine lastsysoid */ 11 "UPDATE pg_database SET datlastsysoid = " 12 " (SELECT oid FROM pg_database " 13 " WHERE datname = 'template0');\n", 14 /* Explicitly revoke public create-schema and create-temp-table privileges in template1 and template0; else the latter would be on by default */ 15 "REVOKE CREATE,TEMPORARY ON DATABASE template1 FROM public;\n", 16 "REVOKE CREATE,TEMPORARY ON DATABASE template0 FROM public;\n", 17 /* Finally vacuum to clean up dead rows in pg_database */ 18 "VACUUM FULL pg_database;\n", 19 NULL 20 }; 21 22 fputs(_("copying template1 to template0 ... "), stdout); 23 fflush(stdout); 24 snprintf(cmd, sizeof(cmd), 25 "\"%s\" %s template1 >%s", 26 backend_exec, backend_options, 27 DEVNULL); 28 PG_CMD_OPEN; 29 for (line = template0_setup; *line; line++) 30 PG_CMD_PUTS(*line); 31 PG_CMD_CLOSE; 32 check_ok(); 33 }
make_postgres函数将template1拷贝到postgres中
1 static void make_postgres(void){ 2 PG_CMD_DECL; 3 const char **line; 4 static const char *postgres_setup[] = { 5 "CREATE DATABASE postgres;\n", 6 NULL 7 }; 8 fputs(_("copying template1 to postgres ... "), stdout); 9 fflush(stdout); 10 snprintf(cmd, sizeof(cmd), 11 "\"%s\" %s template1 >%s", 12 backend_exec, backend_options, 13 DEVNULL); 14 PG_CMD_OPEN; 15 for (line = postgres_setup; *line; line++) 16 PG_CMD_PUTS(*line); 17 PG_CMD_CLOSE; 18 check_ok(); 19 }