📄 initdb.c
字号:
fflush(stdout); sysviews_setup = readfile(system_views_file); /* * We use -N here to avoid backslashing stuff in system_views.sql */ snprintf(cmd, sizeof(cmd), "\"%s\" %s -N template1 >%s", backend_exec, backend_options, DEVNULL); PG_CMD_OPEN; for (line = sysviews_setup; *line != NULL; line++) { PG_CMD_PUTS(*line); free(*line); } PG_CMD_CLOSE; free(sysviews_setup); check_ok();}/* * load description data */static voidsetup_description(void){ PG_CMD_DECL; fputs(_("loading pg_description ... "), stdout); fflush(stdout); snprintf(cmd, sizeof(cmd), "\"%s\" %s template1 >%s", backend_exec, backend_options, DEVNULL); PG_CMD_OPEN; PG_CMD_PUTS("CREATE TEMP TABLE tmp_pg_description ( " " objoid oid, " " classname name, " " objsubid int4, " " description text) WITHOUT OIDS;\n"); PG_CMD_PRINTF1("COPY tmp_pg_description FROM '%s';\n", desc_file); PG_CMD_PUTS("INSERT INTO pg_description " " SELECT t.objoid, c.oid, t.objsubid, t.description " " FROM tmp_pg_description t, pg_class c " " WHERE c.relname = t.classname;\n"); PG_CMD_CLOSE; check_ok();}/* * load conversion functions */static voidsetup_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();}/* * 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). */static voidsetup_privileges(void){ PG_CMD_DECL; char **line; char **priv_lines; static char *privileges_setup[] = { "UPDATE pg_class " " SET relacl = E'{\"=r/\\\\\"$POSTGRES_SUPERUSERNAME\\\\\"\"}' " " WHERE relkind IN ('r', 'v', 'S') AND relacl IS NULL;\n", "GRANT USAGE ON SCHEMA pg_catalog TO PUBLIC;\n", "GRANT CREATE, USAGE ON SCHEMA public TO PUBLIC;\n", NULL }; fputs(_("setting privileges on built-in objects ... "), stdout); fflush(stdout); snprintf(cmd, sizeof(cmd), "\"%s\" %s template1 >%s", backend_exec, backend_options, DEVNULL); PG_CMD_OPEN; priv_lines = replace_token(privileges_setup, "$POSTGRES_SUPERUSERNAME", username); for (line = priv_lines; *line != NULL; line++) PG_CMD_PUTS(*line); PG_CMD_CLOSE; check_ok();}/* * extract the strange version of version required for information schema * (09.08.0007abc) */static voidset_info_version(void){ char *letterversion; long major = 0, minor = 0, micro = 0; char *endptr; char *vstr = xstrdup(PG_VERSION); char *ptr; ptr = vstr + (strlen(vstr) - 1); while (ptr != vstr && (*ptr < '0' || *ptr > '9')) ptr--; letterversion = ptr + 1; major = strtol(vstr, &endptr, 10); if (*endptr) minor = strtol(endptr + 1, &endptr, 10); if (*endptr) micro = strtol(endptr + 1, &endptr, 10); snprintf(infoversion, sizeof(infoversion), "%02ld.%02ld.%04ld%s", major, minor, micro, letterversion);}/* * load info schema and populate from features file */static voidsetup_schema(void){ PG_CMD_DECL; char **line; char **lines; fputs(_("creating information schema ... "), stdout); fflush(stdout); lines = readfile(info_schema_file); /* * We use -N here to avoid backslashing stuff in information_schema.sql */ snprintf(cmd, sizeof(cmd), "\"%s\" %s -N template1 >%s", backend_exec, backend_options, DEVNULL); PG_CMD_OPEN; for (line = lines; *line != NULL; line++) { PG_CMD_PUTS(*line); free(*line); } free(lines); PG_CMD_CLOSE; snprintf(cmd, sizeof(cmd), "\"%s\" %s template1 >%s", backend_exec, backend_options, DEVNULL); PG_CMD_OPEN; PG_CMD_PRINTF1("UPDATE information_schema.sql_implementation_info " " SET character_value = '%s' " " WHERE implementation_info_name = 'DBMS VERSION';\n", infoversion); PG_CMD_PRINTF1("COPY information_schema.sql_features " " (feature_id, feature_name, sub_feature_id, " " sub_feature_name, is_supported, comments) " " FROM '%s';\n", features_file); PG_CMD_CLOSE; check_ok();}/* * clean everything up in template1 */static voidvacuum_db(void){ PG_CMD_DECL; fputs(_("vacuuming database template1 ... "), stdout); fflush(stdout); snprintf(cmd, sizeof(cmd), "\"%s\" %s template1 >%s", backend_exec, backend_options, DEVNULL); PG_CMD_OPEN; PG_CMD_PUTS("ANALYZE;\nVACUUM FULL;\nVACUUM FREEZE;\n"); PG_CMD_CLOSE; check_ok();}/* * copy template1 to template0 */static voidmake_template0(void){ PG_CMD_DECL; char **line; static char *template0_setup[] = { "CREATE DATABASE template0;\n", "UPDATE pg_database SET " " datistemplate = 't', " " datallowconn = 'f' " " WHERE datname = 'template0';\n", /* * We use the OID of template0 to determine lastsysoid */ "UPDATE pg_database SET datlastsysoid = " " (SELECT oid FROM pg_database " " WHERE datname = 'template0');\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", /* * Finally vacuum to clean up dead rows in pg_database */ "VACUUM FULL pg_database;\n", NULL }; fputs(_("copying template1 to template0 ... "), stdout); fflush(stdout); snprintf(cmd, sizeof(cmd), "\"%s\" %s template1 >%s", backend_exec, backend_options, DEVNULL); PG_CMD_OPEN; for (line = template0_setup; *line; line++) PG_CMD_PUTS(*line); PG_CMD_CLOSE; check_ok();}/* * copy template1 to postgres */static voidmake_postgres(void){ PG_CMD_DECL; char **line; static char *postgres_setup[] = { "CREATE DATABASE postgres;\n", NULL }; fputs(_("copying template1 to postgres ... "), stdout); fflush(stdout); snprintf(cmd, sizeof(cmd), "\"%s\" %s template1 >%s", backend_exec, backend_options, DEVNULL); PG_CMD_OPEN; for (line = postgres_setup; *line; line++) PG_CMD_PUTS(*line); PG_CMD_CLOSE; check_ok();}/* * signal handler in case we are interrupted. * * The Windows runtime docs at * http://msdn.microsoft.com/library/en-us/vclib/html/_crt_signal.asp * specifically forbid a number of things being done from a signal handler, * including IO, memory allocation and system calls, and only allow jmpbuf * if you are handling SIGFPE. * * I avoided doing the forbidden things by setting a flag instead of calling * exit_nicely() directly. * * Also note the behaviour of Windows with SIGINT, which says this: * Note SIGINT is not supported for any Win32 application, including * Windows 98/Me and Windows NT/2000/XP. When a CTRL+C interrupt occurs, * Win32 operating systems generate a new thread to specifically handle * that interrupt. This can cause a single-thread application such as UNIX, * to become multithreaded, resulting in unexpected behavior. * * I have no idea how to handle this. (Strange they call UNIX an application!) * So this will need some testing on Windows. */static voidtrapsig(int signum){ /* handle systems that reset the handler, like Windows (grr) */ pqsignal(signum, trapsig); caught_signal = true;}/* * call exit_nicely() if we got a signal, or else output "ok". */static voidcheck_ok(void){ if (caught_signal) { printf(_("caught signal\n")); fflush(stdout); exit_nicely(); } else if (output_failed) { printf(_("could not write to child process: %s\n"), strerror(output_errno)); fflush(stdout); exit_nicely(); } else { /* all seems well */ printf(_("ok\n")); fflush(stdout); }}/* * Escape any single quotes or backslashes in given string */static char *escape_quotes(const char *src){ int len = strlen(src), i, j; char *result = pg_malloc(len * 2 + 1); for (i = 0, j = 0; i < len; i++) { if (SQL_STR_DOUBLE(src[i])) result[j++] = src[i]; result[j++] = src[i]; } result[j] = '\0'; return result;}/* * check if given string is a valid locale specifier */static boolchklocale(const char *locale){ bool ret; int category = LC_CTYPE; char *save; save = setlocale(category, NULL); if (!save) return false; /* should not happen; */ save = xstrdup(save); ret = (setlocale(category, locale) != NULL); setlocale(category, save); free(save); /* should we exit here? */ if (!ret) fprintf(stderr, _("%s: invalid locale name \"%s\"\n"), progname, locale); return ret;}/* * set up the locale variables * * assumes we have called setlocale(LC_ALL,"") */static voidsetlocales(void){ /* set empty lc_* values to locale config if set */ if (strlen(locale) > 0) { if (strlen(lc_ctype) == 0) lc_ctype = locale; if (strlen(lc_collate) == 0) lc_collate = locale; if (strlen(lc_numeric) == 0) lc_numeric = locale; if (strlen(lc_time) == 0) lc_time = locale; if (strlen(lc_monetary) == 0) lc_monetary = locale; if (strlen(lc_messages) == 0) lc_messages = locale; } /* * override absent/invalid config settings from initdb's locale settings */ if (strlen(lc_ctype) == 0 || !chklocale(lc_ctype)) lc_ctype = xstrdup(setlocale(LC_CTYPE, NULL)); if (strlen(lc_collate) == 0 || !chklocale(lc_collate)) lc_collate = xstrdup(setlocale(LC_COLLATE, NULL)); if (strlen(lc_numeric) == 0 || !chklocale(lc_numeric)) lc_numeric = xstrdup(setlocale(LC_NUMERIC, NULL)); if (strlen(lc_time) == 0 || !chklocale(lc_time)) lc_time = xstrdup(setlocale(LC_TIME, NULL)); if (strlen(lc_monetary) == 0 || !chklocale(lc_monetary)) lc_monetary = xstrdup(setlocale(LC_MONETARY, NULL)); if (strlen(lc_messages) == 0 || !chklocale(lc_messages))#if defined(LC_MESSAGES) && !defined(WIN32) { /* when available get the current locale setting */ lc_messages = xstrdup(setlocale(LC_MESSAGES, NULL)); }#else { /* when not available, get the CTYPE setting */ lc_messages = xstrdup(setlocale(LC_CTYPE, NULL)); }#endif}/* * print help text */static voidusage(const char *progname){ printf(_("%s initializes a PostgreSQL database cluster.\n\n"), progname); printf(_("Usage:\n")); printf(_(" %s [OPTION]... [DATADIR]\n"), progname); printf(_("\nOptions:\n")); printf(_(" [-D, --pgdata=]DATADIR location for this database cluster\n")); printf(_(" -E, --encoding=ENCODING set default encoding for new databases\n")); printf(_(" --locale=LOCALE initialize database cluster with given locale\n")); printf(_(" --lc-collate, --lc-ctype, --lc-messages=LOCALE\n" " --lc-monetary, --lc-numeric, --lc-time=LOCALE\n" " initialize database cluster with given locale\n" " in the respective category (default taken from\n" " environment)\n")); printf(_(" --no-locale equivalent to --locale=C\n")); printf(_(" -A, --auth=METHOD default authentication method for local connections\n")); printf(_(" -U, --username=NAME database superuser name\n")); printf(_(" -W, --pwprompt prompt for a password for the new superuser\n")); printf(_(" --pwfile=FILE read password for the new superuser from file\n")); printf(_(" -?, --help show this help, then exit\n")); printf(_(" -V, --version output version information, then exit\n")); printf(_("\nLess commonly used options:\n")); printf(_(" -d, --debug generate lots of debugging output\n")); printf(_(" -s, --show show internal settings\n")); printf(_(" -L DIRECTORY where to find the input files\n")); printf(_(" -n, --noclean do not clean up after errors\n")); printf(_("\nIf the data directory is not specified, the environment variable PGDATA\n" "is used.\n")); printf(_("\nReport bugs to <pgsql-bugs@postgresql.org>.\n"));}intmain(int argc, char *argv[]){ /* * options with no short version return a low integer, the rest return
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -