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[]; 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 源代码分析之十三的更多相关文章
- PostgreSQL的 initdb 源代码分析之二十三
继续分析: vacuum_db(); 展开: cmd是:/home/pgsql/project/bin/postgres" --single -F -O -c search_path=pg_ ...
- PostgreSQL的initdb 源代码分析之六
继续分析 下面的是获取运行此程序的用户名称,主要还是为了防止在linux下用root来运行的情形. effective_user = get_id(); ) username = effective_ ...
- PostgreSQL的 initdb 源代码分析之二
继续分析 下面这一段,当 initdb --version 或者 initdb --help 才有意义. ) { ], || strcmp(argv[], ) { usage(progname); ...
- PostgreSQL的 initdb 源代码分析之二十四
继续分析: make_template0(); 展开: 无需再作解释,就是创建template0数据库 /* * copy template1 to template0 */ static void ...
- PostgreSQL的 initdb 源代码分析之十五
继续分析: if (pwprompt || pwfilename) get_set_pwd(); 由于我启动initdb的时候,没有设置口令相关的选项,故此略过. 接下来: setup_depend( ...
- PostgreSQL的 initdb 源代码分析之十二
继续分析 /* Now create all the text config files */ setup_config(); 将其展开: 实质就是,确定各种参数,分别写入 postgresql.co ...
- PostgreSQL的 initdb 源代码分析之十一
继续分析: /* Top level PG_VERSION is checked by bootstrapper, so make it first */ write_version_file(NUL ...
- PostgreSQL的 initdb 源代码分析之七
继续分析:由于我使用initdb的时候,没有指定 locale,所以会使用OS的缺省locale,这里是 en_US.UTF-8 printf(_("The files belonging ...
- PostgreSQL的initdb 源代码分析之五
接前面,继续分析: putenv("TZ=GMT") 设置了时区信息. find_other_exec(argv[0], "postgres", PG_BACK ...
随机推荐
- hdu 3535 AreYouBusy
// 混合背包// xiaoA想尽量多花时间做ACM,但老板要求他在T时间内做完n堆工作,每个工作耗时ac[i][j],// 幸福感ag[i][j],每堆工作有m[i]个工作,每堆工作都有一个性质,/ ...
- MySQL基础之第9章 触发器
触发器(TRIGGER)是由事件来触发某个操作.这些事件包括INSERT语句.UPDATE语句和DELETE语句.当数据库系统执行这些事件时,就会激活触发器执行相应的操作.MySQL从5.0.2版本开 ...
- 【转】C++ 内存分配(new,operator new)详解
本文主要讲述C++ new运算符和operator new, placement new之间的种种关联,new的底层实现,以及operator new的重载和一些在内存池,STL中的应用. 一 new ...
- Cocos2d-x使用iOS游戏内付费IAP(C++篇)
本文章转载 http://www.ityran.com/archives/5515.非本人原创! 前期准备 设备与账号 在开始编码之前我们需要准备测试环境. IAP只能真机测试,准备一台iOS设备是必 ...
- CSS基础知识——选择器
选择器 元素选择器# 文档元素为最基本的选择器 例子:div{属性:值}; 选择器分组 例子:h2,p{属性:值}; 表示符合这两种规则的元素设置相同的属性值 通配选择器 表示所有元素 类选择器 应用 ...
- 微软控制台带来的PHP控制台输出问题
/** * 测试文件包含方式对跨平台的影响 * 控制台下测试. * 默认的文件编码为 UTF-8 */ function testChinese() { $file = __DIR__ . '/con ...
- JavaScript相关图书推荐
JavaScript语言精粹(修订版) 作 者 Douglas Crockford(道格拉斯·克罗克福德) 著:赵泽欣 等 译 出 版 社 电子工业出版社 出版时间 2012-09-01 版 ...
- Codevs No.1163 访问艺术馆
2016-05-31 20:48:47 题目链接: 访问艺术馆 (Codevs No.1163) 题目大意: 一个贼要在一个二叉树结构的艺术馆中偷画,画都处于叶子节点处,偷画和经过走廊都需要时间,求在 ...
- MSSql得到表的结构和字段
得到数据库中所有的表 select name from sysobjects where xtype='u' and name='{0}' 1.获取表的基本字段属性 --获取SqlServer中表结构 ...
- android - python 自动化测试 移动互联网 - SegmentFault
android - python 自动化测试 移动互联网 - SegmentFault splinter