• PostgreSQL的 initdb 源代码分析之十三


    继续分析:

        /* Bootstrap template1 */
        bootstrap_template1();

    展开:

    我这里读入的文件是:/home/pgsql/project/share/postgres.bki 

    /*
     * run the BKI script in bootstrap mode to create template1
     */
    static void
    bootstrap_template1(void)
    {
        PG_CMD_DECL;
        char      **line;
        char       *talkargs = "";
        char      **bki_lines;
        char        headerline[MAXPGPATH];
        char        buf[64];
    
        printf(_("creating template1 database in %s/base/1 ... "), pg_data);
        fflush(stdout);
    
        if (debug)
            talkargs = "-d 5";
    
        bki_lines = readfile(bki_file);
    
        /* Check that bki file appears to be of the right version */
    
        snprintf(headerline, sizeof(headerline), "# PostgreSQL %s
    ",
                 PG_MAJORVERSION);
    
        if (strcmp(headerline, *bki_lines) != 0)
        {
            fprintf(stderr,
                    _("%s: input file "%s" does not belong to PostgreSQL %s
    "
                      "Check your installation or specify the correct path "
                      "using the option -L.
    "),
                    progname, bki_file, PG_VERSION);
            exit_nicely();
        }
    
        /* Substitute for various symbols used in the BKI file */
    
        sprintf(buf, "%d", NAMEDATALEN);
        bki_lines = replace_token(bki_lines, "NAMEDATALEN", buf);
    
        sprintf(buf, "%d", (int) sizeof(Pointer));
        bki_lines = replace_token(bki_lines, "SIZEOF_POINTER", buf);
    
        bki_lines = replace_token(bki_lines, "ALIGNOF_POINTER",
                                  (sizeof(Pointer) == 4) ? "i" : "d");
    
        bki_lines = replace_token(bki_lines, "FLOAT4PASSBYVAL",
                                  FLOAT4PASSBYVAL ? "true" : "false");
    
        bki_lines = replace_token(bki_lines, "FLOAT8PASSBYVAL",
                                  FLOAT8PASSBYVAL ? "true" : "false");
    
        bki_lines = replace_token(bki_lines, "POSTGRES", username);
    
        bki_lines = replace_token(bki_lines, "ENCODING", encodingid);
    
        bki_lines = replace_token(bki_lines, "LC_COLLATE", escape_quotes(lc_collate));
    
        bki_lines = replace_token(bki_lines, "LC_CTYPE", escape_quotes(lc_ctype));
    
        /*
         * Pass correct LC_xxx environment to bootstrap.
         *
         * The shell script arranged to restore the LC settings afterwards, but
         * there doesn't seem to be any compelling reason to do that.
         */
        snprintf(cmd, sizeof(cmd), "LC_COLLATE=%s", lc_collate);
        putenv(xstrdup(cmd));
    
        snprintf(cmd, sizeof(cmd), "LC_CTYPE=%s", lc_ctype);
        putenv(xstrdup(cmd));
    
        unsetenv("LC_ALL");
    
        /* Also ensure backend isn't confused by this environment var: */
        unsetenv("PGCLIENTENCODING");
    
        snprintf(cmd, sizeof(cmd),
                 ""%s" --boot -x1 %s %s",
                 backend_exec, boot_options, talkargs);
    
        PG_CMD_OPEN;
    
        for (line = bki_lines; *line != NULL; line++)
        {
            PG_CMD_PUTS(*line);
            free(*line);
        }
    
        PG_CMD_CLOSE;
    
        free(bki_lines);
    
        check_ok();
    }

    其中,  bki_lines = readfile(bki_file) ,是得到了要读取的文件的每一行。

    再展开看 replace_token 函数:

    这个函数就是用 replacement指向的字符串,替换在 lines所代表的文件内容行数组中所有token值。

    比如:

    sprintf(buf, "%d", NAMEDATALEN);
    bki_lines = replace_token(bki_lines, "NAMEDATALEN", buf);

    把 postgres.bki  文件中 类似于 

    insert OID = 19 ( name 11 10 NAMEDATALEN f b S f t 54 0 18 1003 namein nameout namerecv namesend - - - c p f 0 -1 0 0 _null_ _null_ )

    这样的句子,在内存中替换为(根据宏定义、NAMEDATALEN为64):

    insert OID = 19 ( name 11 10 64 f b S f t 54 0 18 1003 namein nameout namerecv namesend - - - c p f 0 -1 0 0 _null_ _null_ )

    /*
     * make a copy of the array of lines, with token replaced by replacement
     * the first time it occurs on each line.
     *
     * This does most of what sed was used for in the shell script, but
     * doesn't need any regexp stuff.
     */
    static char **
    replace_token(char **lines, const char *token, const char *replacement)
    {
        int            numlines = 1;
        int            i;
        char      **result;
        int            toklen,
                    replen,
                    diff;
    
        for (i = 0; lines[i]; i++)
            numlines++;
    
        result = (char **) pg_malloc(numlines * sizeof(char *));
    
        toklen = strlen(token);
        replen = strlen(replacement);
        diff = replen - toklen;
    
        for (i = 0; i < numlines; i++)
        {
            char       *where;
            char       *newline;
            int            pre;
    
            /* just copy pointer if NULL or no change needed */
            if (lines[i] == NULL || (where = strstr(lines[i], token)) == NULL)
            {
                result[i] = lines[i];
                continue;
            }
    
            /* if we get here a change is needed - set up new line */
    
            newline = (char *) pg_malloc(strlen(lines[i]) + diff + 1);
    
            pre = where - lines[i];
    
            strncpy(newline, lines[i], pre);
    
            strcpy(newline + pre, replacement);
    
            strcpy(newline + pre + replen, lines[i] + pre + toklen);
    
            result[i] = newline;
        }
    
        return result;
    }

    综合上述两段,加入调试信息后,可以看到:

    ---------------replace for   NAMEDATALEN ------start
    ===============lines[2301] OLD is : insert OID = 19 ( name 11 10 NAMEDATALEN f b S f t 054 0 18 1003 namein nameout namerecv namesend - - - c p f 0 -1 0 0 _null_ _null_ )
    
    ===============result[2301] NEW is : insert OID = 19 ( name 11 10 64 f b S f t 054 0 18 1003 namein nameout namerecv namesend - - - c p f 0 -1 0 0 _null_ _null_ )
    
    
    ===============lines[2458] OLD is : insert ( 1255 proname 19 -1 NAMEDATALEN 1 0 -1 -1 f p c t f f t 0 0 _null_ _null_)
    
    ===============result[2458] NEW is : insert ( 1255 proname 19 -1 64 1 0 -1 -1 f p c t f f t 0 0 _null_ _null_)
    
    
    ===============lines[2490] OLD is : insert ( 1247 typname 19 -1 NAMEDATALEN 1 0 -1 -1 f p c t f f t 0 0 _null_ _null_)
    
    ===============result[2490] NEW is : insert ( 1247 typname 19 -1 64 1 0 -1 -1 f p c t f f t 0 0 _null_ _null_)
    
    
    ===============lines[2527] OLD is : insert ( 1249 attname 19 -1 NAMEDATALEN 2 0 -1 -1 f p c t f f t 0 0 _null_ _null_)
    
    ===============result[2527] NEW is : insert ( 1249 attname 19 -1 64 2 0 -1 -1 f p c t f f t 0 0 _null_ _null_)
    
    
    ===============lines[2552] OLD is : insert ( 1259 relname 19 -1 NAMEDATALEN 1 0 -1 -1 f p c t f f t 0 0 _null_ _null_)
    
    ===============result[2552] NEW is : insert ( 1259 relname 19 -1 64 1 0 -1 -1 f p c t f f t 0 0 _null_ _null_)
    
    
    ---------------replace for   NAMEDATALEN ------end
    
    ---------------replace for   SIZEOF_POINTER ------start
    ===============lines[2428] OLD is : insert OID = 2281 ( internal 11 10 SIZEOF_POINTER t p P f t 054 0 0 0 internal_in internal_out - - - - - ALIGNOF_POINTER p f 0 -1 0 0 _null_ _null_ )
    
    ===============result[2428] NEW is : insert OID = 2281 ( internal 11 10 8 t p P f t 054 0 0 0 internal_in internal_out - - - - - ALIGNOF_POINTER p f 0 -1 0 0 _null_ _null_ )
    
    
    ---------------replace for   SIZEOF_POINTER ------end
    
    ---------------replace for   ALIGNOF_POINTER ------start
    ===============lines[2428] OLD is : insert OID = 2281 ( internal 11 10 8 t p P f t 054 0 0 0 internal_in internal_out - - - - - ALIGNOF_POINTER p f 0 -1 0 0 _null_ _null_ )
    
    ===============result[2428] NEW is : insert OID = 2281 ( internal 11 10 8 t p P f t 054 0 0 0 internal_in internal_out - - - - - d p f 0 -1 0 0 _null_ _null_ )
    
    
    ---------------replace for   ALIGNOF_POINTER ------end
    
    ---------------replace for   FLOAT4PASSBYVAL ------start
    ===============lines[2328] OLD is : insert OID = 700 ( float4 11 10 4 FLOAT4PASSBYVAL b N f t 054 0 0 1021 float4in float4out float4recv float4send - - - i p f 0 -1 0 0 _null_ _null_ )
    
    ===============result[2328] NEW is : insert OID = 700 ( float4 11 10 4 true b N f t 054 0 0 1021 float4in float4out float4recv float4send - - - i p f 0 -1 0 0 _null_ _null_ )
    
    
    ===============lines[2462] OLD is : insert ( 1255 procost 700 -1 4 5 0 -1 -1 FLOAT4PASSBYVAL p i t f f t 0 0 _null_ _null_)
    
    ===============result[2462] NEW is : insert ( 1255 procost 700 -1 4 5 0 -1 -1 true p i t f f t 0 0 _null_ _null_)
    
    
    ===============lines[2463] OLD is : insert ( 1255 prorows 700 -1 4 6 0 -1 -1 FLOAT4PASSBYVAL p i t f f t 0 0 _null_ _null_)
    
    ===============result[2463] NEW is : insert ( 1255 prorows 700 -1 4 6 0 -1 -1 true p i t f f t 0 0 _null_ _null_)
    
    
    ===============lines[2561] OLD is : insert ( 1259 reltuples 700 -1 4 10 0 -1 -1 FLOAT4PASSBYVAL p i t f f t 0 0 _null_ _null_)
    
    ===============result[2561] NEW is : insert ( 1259 reltuples 700 -1 4 10 0 -1 -1 true p i t f f t 0 0 _null_ _null_)
    
    
    ---------------replace for   FLOAT4PASSBYVAL ------end
    
    ---------------replace for   FLOAT8PASSBYVAL ------start
    ===============lines[2302] OLD is : insert OID = 20 ( int8 11 10 8 FLOAT8PASSBYVAL b N f t 054 0 0 1016 int8in int8out int8recv int8send - - - d p f 0 -1 0 0 _null_ _null_ )
    
    ===============result[2302] NEW is : insert OID = 20 ( int8 11 10 8 true b N f t 054 0 0 1016 int8in int8out int8recv int8send - - - d p f 0 -1 0 0 _null_ _null_ )
    
    
    ===============lines[2329] OLD is : insert OID = 701 ( float8 11 10 8 FLOAT8PASSBYVAL b N t t 054 0 0 1022 float8in float8out float8recv float8send - - - d p f 0 -1 0 0 _null_ _null_ )
    
    ===============result[2329] NEW is : insert OID = 701 ( float8 11 10 8 true b N t t 054 0 0 1022 float8in float8out float8recv float8send - - - d p f 0 -1 0 0 _null_ _null_ )
    
    
    ===============lines[2336] OLD is : insert OID = 790 ( money 11 10 8 FLOAT8PASSBYVAL b N f t 054 0 0 791 cash_in cash_out cash_recv cash_send - - - d p f 0 -1 0 0 _null_ _null_ )
    
    ===============result[2336] NEW is : insert OID = 790 ( money 11 10 8 true b N f t 054 0 0 791 cash_in cash_out cash_recv cash_send - - - d p f 0 -1 0 0 _null_ _null_ )
    
    
    ===============lines[2377] OLD is : insert OID = 1083 ( time 11 10 8 FLOAT8PASSBYVAL b D f t 054 0 0 1183 time_in time_out time_recv time_send timetypmodin timetypmodout - d p f 0 -1 0 0 _null_ _null_ )
    
    ===============result[2377] NEW is : insert OID = 1083 ( time 11 10 8 true b D f t 054 0 0 1183 time_in time_out time_recv time_send timetypmodin timetypmodout - d p f 0 -1 0 0 _null_ _null_ )
    
    
    ===============lines[2378] OLD is : insert OID = 1114 ( timestamp 11 10 8 FLOAT8PASSBYVAL b D f t 054 0 0 1115 timestamp_in timestamp_out timestamp_recv timestamp_send timestamptypmodin timestamptypmodout - d p f 0 -1 0 0 _null_ _null_ )
    
    ===============result[2378] NEW is : insert OID = 1114 ( timestamp 11 10 8 true b D f t 054 0 0 1115 timestamp_in timestamp_out timestamp_recv timestamp_send timestamptypmodin timestamptypmodout - d p f 0 -1 0 0 _null_ _null_ )
    
    
    ===============lines[2382] OLD is : insert OID = 1184 ( timestamptz 11 10 8 FLOAT8PASSBYVAL b D t t 054 0 0 1185 timestamptz_in timestamptz_out timestamptz_recv timestamptz_send timestamptztypmodin timestamptztypmodout - d p f 0 -1 0 0 _null_ _null_ )
    
    ===============result[2382] NEW is : insert OID = 1184 ( timestamptz 11 10 8 true b D t t 054 0 0 1185 timestamptz_in timestamptz_out timestamptz_recv timestamptz_send timestamptztypmodin timestamptztypmodout - d p f 0 -1 0 0 _null_ _null_ )
    
    
    ---------------replace for   FLOAT4PASSBYVAL ------end
    
    ---------------replace for   POSTGRES ------start
    ===============lines[4841] OLD is : insert OID = 10 ( "POSTGRES" t t t t t t t -1 _null_ _null_ )
    
    ===============result[4841] NEW is : insert OID = 10 ( "pgsql" t t t t t t t -1 _null_ _null_ )
    
    
    ---------------replace for   POSTGRES ------end
    
    ---------------replace for   ENCODING ------start
    ===============lines[4783] OLD is : insert OID = 1 ( template1 10 ENCODING "LC_COLLATE" "LC_CTYPE" t t -1 0 0 1663 _null_)
    
    ===============result[4783] NEW is : insert OID = 1 ( template1 10 6 "LC_COLLATE" "LC_CTYPE" t t -1 0 0 1663 _null_)
    
    
    ---------------replace for   ENCODING ------end
    
    ---------------replace for   LC_COLLATE ------start
    ===============lines[4783] OLD is : insert OID = 1 ( template1 10 6 "LC_COLLATE" "LC_CTYPE" t t -1 0 0 1663 _null_)
    
    ===============result[4783] NEW is : insert OID = 1 ( template1 10 6 "en_US.UTF-8" "LC_CTYPE" t t -1 0 0 1663 _null_)
    
    
    ---------------replace for   LC_COLLATE ------end
    
    ---------------replace for   LC_CTYPE ------start
    ===============lines[4783] OLD is : insert OID = 1 ( template1 10 6 "en_US.UTF-8" "LC_CTYPE" t t -1 0 0 1663 _null_)
    
    ===============result[4783] NEW is : insert OID = 1 ( template1 10 6 "en_US.UTF-8" "en_US.UTF-8" t t -1 0 0 1663 _null_)
    
    
    ---------------replace for   LC_CTYPE ------end

    这些被替换以后的信息,如何被使用呢?

    看前面的  
    bootstrap_template1 函数中的这一段:

        /*
         * Pass correct LC_xxx environment to bootstrap.
         *
         * The shell script arranged to restore the LC settings afterwards, but
         * there doesn't seem to be any compelling reason to do that.
         */
        snprintf(cmd, sizeof(cmd), "LC_COLLATE=%s", lc_collate);
        putenv(xstrdup(cmd));
    
        snprintf(cmd, sizeof(cmd), "LC_CTYPE=%s", lc_ctype);
        putenv(xstrdup(cmd));
    
        unsetenv("LC_ALL");
    
        /* Also ensure backend isn't confused by this environment var: */
        unsetenv("PGCLIENTENCODING");
    
        snprintf(cmd, sizeof(cmd),
                 ""%s" --boot -x1 %s %s",
                 backend_exec, boot_options, talkargs);

    我可以得到 cmd是: "/home/pgsql/project/bin/postgres" --boot -x1 -F  

    而后面的一段:

    则是一次一次的逐行带参数执行 Postgresql.bki中所有行(包括被替换的和没有被替换的行)

    可以理解为特殊的模式下,向postgresql 的template 数据库中逐条写入数据。

        PG_CMD_OPEN;
    
        for (line = bki_lines; *line != NULL; line++)
        {
            PG_CMD_PUTS(*line);
            free(*line);
        }
    
        PG_CMD_CLOSE;
    需要注意的是,对各个系统表的建立,都是在此处,通过执行 postgres.bki文件中的各行脚本来完成的。

  • 相关阅读:
    Android 蓝牙4.0 BLE (onServicesDiscovered 返回 status 是 129,133时)
    Android 读取蓝牙设备信息开发
    Android RxJava
    Android 通信 EventBus
    数据仓库基础介绍
    探索SQL Server元数据(三):索引元数据
    探索SQL Server元数据(二)
    MySQL常见备份方案
    hivesql优化的深入解析
    mysql执行计划看是否最优
  • 原文地址:https://www.cnblogs.com/gaojian/p/3178151.html
Copyright © 2020-2023  润新知