继续分析:

    /* 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[]; 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\n",
PG_MAJORVERSION); if (strcmp(headerline, *bki_lines) != )
{
fprintf(stderr,
_("%s: input file \"%s\" does not belong to PostgreSQL %s\n"
"Check your installation or specify the correct path "
"using the option -L.\n"),
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) == ) ? "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 \054 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 \054 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 = ;
int i;
char **result;
int toklen,
replen,
diff; for (i = ; lines[i]; i++)
numlines++; result = (char **) pg_malloc(numlines * sizeof(char *)); toklen = strlen(token);
replen = strlen(replacement);
diff = replen - toklen; for (i = ; 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 + ); 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[] OLD is : insert OID = ( name NAMEDATALEN f b S f t \ namein nameout namerecv namesend - - - c p f - _null_ _null_ ) ===============result[] NEW is : insert OID = ( name f b S f t \ namein nameout namerecv namesend - - - c p f - _null_ _null_ ) ===============lines[] OLD is : insert ( proname - NAMEDATALEN - - f p c t f f t _null_ _null_) ===============result[] NEW is : insert ( proname - - - f p c t f f t _null_ _null_) ===============lines[] OLD is : insert ( typname - NAMEDATALEN - - f p c t f f t _null_ _null_) ===============result[] NEW is : insert ( typname - - - f p c t f f t _null_ _null_) ===============lines[] OLD is : insert ( attname - NAMEDATALEN - - f p c t f f t _null_ _null_) ===============result[] NEW is : insert ( attname - - - f p c t f f t _null_ _null_) ===============lines[] OLD is : insert ( relname - NAMEDATALEN - - f p c t f f t _null_ _null_) ===============result[] NEW is : insert ( relname - - - f p c t f f t _null_ _null_) ---------------replace for NAMEDATALEN ------end ---------------replace for SIZEOF_POINTER ------start
===============lines[] OLD is : insert OID = ( internal SIZEOF_POINTER t p P f t \ internal_in internal_out - - - - - ALIGNOF_POINTER p f - _null_ _null_ ) ===============result[] NEW is : insert OID = ( internal t p P f t \ internal_in internal_out - - - - - ALIGNOF_POINTER p f - _null_ _null_ ) ---------------replace for SIZEOF_POINTER ------end ---------------replace for ALIGNOF_POINTER ------start
===============lines[] OLD is : insert OID = ( internal t p P f t \ internal_in internal_out - - - - - ALIGNOF_POINTER p f - _null_ _null_ ) ===============result[] NEW is : insert OID = ( internal t p P f t \ internal_in internal_out - - - - - d p f - _null_ _null_ ) ---------------replace for ALIGNOF_POINTER ------end ---------------replace for FLOAT4PASSBYVAL ------start
===============lines[] OLD is : insert OID = ( float4 FLOAT4PASSBYVAL b N f t \ float4in float4out float4recv float4send - - - i p f - _null_ _null_ ) ===============result[] NEW is : insert OID = ( float4 true b N f t \ float4in float4out float4recv float4send - - - i p f - _null_ _null_ ) ===============lines[] OLD is : insert ( procost - - - FLOAT4PASSBYVAL p i t f f t _null_ _null_) ===============result[] NEW is : insert ( procost - - - true p i t f f t _null_ _null_) ===============lines[] OLD is : insert ( prorows - - - FLOAT4PASSBYVAL p i t f f t _null_ _null_) ===============result[] NEW is : insert ( prorows - - - true p i t f f t _null_ _null_) ===============lines[] OLD is : insert ( reltuples - - - FLOAT4PASSBYVAL p i t f f t _null_ _null_) ===============result[] NEW is : insert ( reltuples - - - true p i t f f t _null_ _null_) ---------------replace for FLOAT4PASSBYVAL ------end ---------------replace for FLOAT8PASSBYVAL ------start
===============lines[] OLD is : insert OID = ( int8 FLOAT8PASSBYVAL b N f t \ int8in int8out int8recv int8send - - - d p f - _null_ _null_ ) ===============result[] NEW is : insert OID = ( int8 true b N f t \ int8in int8out int8recv int8send - - - d p f - _null_ _null_ ) ===============lines[] OLD is : insert OID = ( float8 FLOAT8PASSBYVAL b N t t \ float8in float8out float8recv float8send - - - d p f - _null_ _null_ ) ===============result[] NEW is : insert OID = ( float8 true b N t t \ float8in float8out float8recv float8send - - - d p f - _null_ _null_ ) ===============lines[] OLD is : insert OID = ( money FLOAT8PASSBYVAL b N f t \ cash_in cash_out cash_recv cash_send - - - d p f - _null_ _null_ ) ===============result[] NEW is : insert OID = ( money true b N f t \ cash_in cash_out cash_recv cash_send - - - d p f - _null_ _null_ ) ===============lines[] OLD is : insert OID = ( time FLOAT8PASSBYVAL b D f t \ time_in time_out time_recv time_send timetypmodin timetypmodout - d p f - _null_ _null_ ) ===============result[] NEW is : insert OID = ( time true b D f t \ time_in time_out time_recv time_send timetypmodin timetypmodout - d p f - _null_ _null_ ) ===============lines[] OLD is : insert OID = ( timestamp FLOAT8PASSBYVAL b D f t \ timestamp_in timestamp_out timestamp_recv timestamp_send timestamptypmodin timestamptypmodout - d p f - _null_ _null_ ) ===============result[] NEW is : insert OID = ( timestamp true b D f t \ timestamp_in timestamp_out timestamp_recv timestamp_send timestamptypmodin timestamptypmodout - d p f - _null_ _null_ ) ===============lines[] OLD is : insert OID = ( timestamptz FLOAT8PASSBYVAL b D t t \ timestamptz_in timestamptz_out timestamptz_recv timestamptz_send timestamptztypmodin timestamptztypmodout - d p f - _null_ _null_ ) ===============result[] NEW is : insert OID = ( timestamptz true b D t t \ timestamptz_in timestamptz_out timestamptz_recv timestamptz_send timestamptztypmodin timestamptztypmodout - d p f - _null_ _null_ ) ---------------replace for FLOAT4PASSBYVAL ------end ---------------replace for POSTGRES ------start
===============lines[] OLD is : insert OID = ( "POSTGRES" t t t t t t t - _null_ _null_ ) ===============result[] NEW is : insert OID = ( "pgsql" t t t t t t t - _null_ _null_ ) ---------------replace for POSTGRES ------end ---------------replace for ENCODING ------start
===============lines[] OLD is : insert OID = ( template1 ENCODING "LC_COLLATE" "LC_CTYPE" t t - _null_) ===============result[] NEW is : insert OID = ( template1 "LC_COLLATE" "LC_CTYPE" t t - _null_) ---------------replace for ENCODING ------end ---------------replace for LC_COLLATE ------start
===============lines[] OLD is : insert OID = ( template1 "LC_COLLATE" "LC_CTYPE" t t - _null_) ===============result[] NEW is : insert OID = ( template1 "en_US.UTF-8" "LC_CTYPE" t t - _null_) ---------------replace for LC_COLLATE ------end ---------------replace for LC_CTYPE ------start
===============lines[] OLD is : insert OID = ( template1 "en_US.UTF-8" "LC_CTYPE" t t - _null_) ===============result[] NEW is : insert OID = ( template1 "en_US.UTF-8" "en_US.UTF-8" t t - _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文件中的各行脚本来完成的。

PostgreSQL的 initdb 源代码分析之十三的更多相关文章

  1. PostgreSQL的 initdb 源代码分析之二十三

    继续分析: vacuum_db(); 展开: cmd是:/home/pgsql/project/bin/postgres" --single -F -O -c search_path=pg_ ...

  2. PostgreSQL的initdb 源代码分析之六

    继续分析 下面的是获取运行此程序的用户名称,主要还是为了防止在linux下用root来运行的情形. effective_user = get_id(); ) username = effective_ ...

  3. PostgreSQL的 initdb 源代码分析之二

    继续分析 下面这一段,当 initdb --version 或者  initdb --help 才有意义. ) { ], || strcmp(argv[], ) { usage(progname); ...

  4. PostgreSQL的 initdb 源代码分析之二十四

    继续分析: make_template0(); 展开: 无需再作解释,就是创建template0数据库 /* * copy template1 to template0 */ static void ...

  5. PostgreSQL的 initdb 源代码分析之十五

    继续分析: if (pwprompt || pwfilename) get_set_pwd(); 由于我启动initdb的时候,没有设置口令相关的选项,故此略过. 接下来: setup_depend( ...

  6. PostgreSQL的 initdb 源代码分析之十二

    继续分析 /* Now create all the text config files */ setup_config(); 将其展开: 实质就是,确定各种参数,分别写入 postgresql.co ...

  7. PostgreSQL的 initdb 源代码分析之十一

    继续分析: /* Top level PG_VERSION is checked by bootstrapper, so make it first */ write_version_file(NUL ...

  8. PostgreSQL的 initdb 源代码分析之七

    继续分析:由于我使用initdb的时候,没有指定 locale,所以会使用OS的缺省locale,这里是 en_US.UTF-8 printf(_("The files belonging ...

  9. PostgreSQL的initdb 源代码分析之五

    接前面,继续分析: putenv("TZ=GMT") 设置了时区信息. find_other_exec(argv[0], "postgres", PG_BACK ...

随机推荐

  1. delphi 当月的第一天, 当月的最后一天

    //取当月的第一天function TDealWithXML.FDOM(Date: TDateTime): TDateTime;var Year, Month, Day: Word;begin Dec ...

  2. 转载:看c++ primer 学习心得

    学习C++ Primer时遇到的问题及解释 chenm91 感觉: l          啰嗦有时会掩盖主题:这本书确实有些啰嗦,比如在讲函数重载的时候,讲了太长一大段(有两节是打了*号的,看还是不看 ...

  3. ASIHTTPREQUEST 文档

    http://blog.csdn.net/ysysbaobei/article/details/17026577 Please note that I am no longer working on ...

  4. Linux基本命令(2)有关磁盘空间的命令

    有关磁盘空间的命令 命令 功能 mount 挂载文件系统 umount 卸载已挂载上的文件系统 df 检查各个硬盘分区和已挂上来的文件系统的磁盘空间 du 显示文件目录和大小 fsck 主要是检查和修 ...

  5. Ubuntu下命令行cd进不了/home/用户目录

    输入命令:cd /home/usr后和刚刚进入终端一样,其实已经进入了usr中,终端默认用usr用户登录,输入ls就可以查看usr目录下的文件

  6. 【windows核心编程】 第八章 用户模式下的线程同步

    Windows核心编程 第八章 用户模式下的线程同步 1. 线程之间通信发生在以下两种情况: ①    需要让多个线程同时访问一个共享资源,同时不能破坏资源的完整性 ②    一个线程需要通知其他线程 ...

  7. Core Java 学习笔记——2.基本数据类型&类型转换

    数据类型(8种基本类型:int/short/long/byte/float/double/char/boolean) 整型 int 4字节 -2 147 483 648~2 147 483 647 s ...

  8. bzoj 2502 清理雪道(有源汇的上下界最小流)

    [题意] 有一个DAG,要求每条边必须经过一次,求最少经过次数. [思路] 有上下界的最小流.  边的下界为1,上界为无穷.构造可行流模型,先不加ts边跑一遍最大流,然后加上t->s的inf边跑 ...

  9. Android Environment 类详解

    Android应用开发中,常使用Environment类去获取外部存储目录,在访问外部存储之前一定要先判断外部存储是否已经是可使用(已挂载&可使用)状态, 并且需要在AndroidManife ...

  10. The solution to Force.Com IDE 29.0 PassWord Problem

    我最近使用Force.com IDE 时,经常提示密码错误.从Google 中终于发现一个解决方法,分享给大家,以供大家参考. 在Force.com IDE  29.0中,IDE 存储我们开发Org ...