Skip to content

Commit 78ed95c

Browse files
committed
Add an architecture design module and include the initdb process and dual parser.
1 parent b0befe8 commit 78ed95c

File tree

6 files changed

+151
-0
lines changed

6 files changed

+151
-0
lines changed

CN/modules/ROOT/images/p20.jpg

44.1 KB
Loading

CN/modules/ROOT/images/p21.png

825 KB
Loading

CN/modules/ROOT/images/p22.png

617 KB
Loading

CN/modules/ROOT/nav.adoc

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,14 @@
1414
* IvorySQL生态
1515
** xref:v4.2/11.adoc[PostGIS]
1616
** xref:v4.2/12.adoc[pgvector]
17+
* IvorySQL架构设计
18+
** 查询处理
19+
*** xref:v4.2/31.adoc[双parser]
20+
** 兼容框架
21+
*** xref:v4.2/30.adoc[initdb过程]
22+
** 过程语言
23+
** 插件
24+
** 兼容特性
1725
* Oracle兼容功能列表
1826
** xref:v4.2/14.adoc[1、框架设计]
1927
** xref:v4.2/15.adoc[2、GUC框架]

CN/modules/ROOT/pages/v4.2/30.adoc

Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
2+
:sectnums:
3+
:sectnumlevels: 5
4+
5+
6+
= **initdb过程**
7+
8+
IvorySQL 在初始化过程中支持两种数据库模式:
9+
10+
** PG 模式:保持与原生 PostgreSQL 的兼容性
11+
** Oracle 模式(默认):提供 Oracle 语法兼容及增强功能
12+
13+
用户可通过 initdb 命令参数指定初始化模式,实现不同场景下的兼容性需求。
14+
15+
== 参数解析处理
16+
17+
initdb在开始阶段会解析输入的命令行参数。
18+
|====
19+
| 参数 | 功能描述 | 可选值 | 默认值
20+
| -m | 指定数据库模式 | oracle/pg | oracle
21+
| -C | 设置 Oracle 兼容的大小写转换模式 | interchange/normal/lowercase| interchange
22+
|====
23+
参数解析流程:
24+
25+
1.继承 PostgreSQL 原有参数处理机制
26+
27+
2.新增模式选择参数 -m 的解析逻辑
28+
29+
3.增加大小写转换参数 -C 的处理模块
30+
31+
32+
== 文件路径初始化
33+
34+
执行 setup_data_file_paths() 函数完成关键文件路径配置:
35+
```
36+
if (DB_PG == database_mode)
37+
set_input(&bki_file, "postgres.bki");
38+
else
39+
set_input(&bki_file, "postgres_oracle.bki");
40+
```
41+
路径检查机制:
42+
43+
1.验证 BKI 文件的存在性(postgres_oracle.bki / postgres.bki)
44+
45+
2.确认配置文件模板的可用性
46+
47+
3.建立与数据库模式对应的系统目录结构
48+
49+
== 数据目录初始化流程
50+
51+
通过 initialize_data_directory() 函数完成核心初始化操作:
52+
53+
=== 目录结构创建
54+
调用 create_data_directory() 创建主数据目录(PGDATA)。
55+
56+
通过 create_xlog_or_symlink() 建立 WAL 日志目录。
57+
58+
循环创建 base, global 等标准子目录。
59+
60+
=== 配置文件初始化
61+
62+
调用set_null_conf()创建空的postgresql.conf。
63+
64+
Oracle 模式下额外创建 ivorysql.conf 配置文件。
65+
66+
调用setup_config()将配置信息写入postgresql.conf。在写入配置时,如果是oracle模式,则会额外向ivorysql.conf中写入配置信息。
67+
68+
=== 模板数据库引导
69+
70+
执行 bootstrap_template1() 加载对应模式的 BKI 文件初始化template1模板数据库,
71+
72+
IvorySQL会额外设置template1模板数据库的数据库模式(oracle/pg)和大小写转换模式以。
73+
74+
load_plisql():安装兼容 Oracle PL/SQL 的 PL/iSQL 过程语言
75+
76+
load_ivorysql_ora():加载核心Oracle兼容层扩展
77+
78+
make_ivorysql():创建默认的 ivorysql 数据库
79+
80+
=== Oracle兼容用户名处理
81+
82+
当数据库模式是oracle时,会对用户名进行强制小写转换
83+
84+
.提示
85+
****
86+
在 PostgreSQL 中,"bki" 是 "Bootstrap Kit" 的简写。Bootstrap Kit 是 PostgreSQL 内部用于引导(bootstrap)数据库系统的一组工具和文件集合。
87+
88+
Bootstrap Kit 主要用于初始化 PostgreSQL 数据库系统的基础结构,包括系统目录(system catalog)、系统表(system table)以及其他必要的系统对象。这些系统目录和表存储了 PostgreSQL 数据库系统的元数据信息,如数据库对象、表结构、索引信息等。
89+
90+
genbki.pl 处理系统表文件如pg_class.h,pg_namespace.h,pg_proc.h等,并生成postgres.bki供initdb加载,主要是加载初始化数据,如创建系统表,系统函数和预定义类型等。
91+
92+
在initdb前的编译阶段,会通过genbki.pl生成postgres.bki 和 postgres_ora.bki,postgres.bki保持PG原样,postgres_ora.bki在pg的基础上增加oracle 兼容的系统对象。
93+
****
94+
95+
image::p20.jpg[]

CN/modules/ROOT/pages/v4.2/31.adoc

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
2+
:sectnums:
3+
:sectnumlevels: 5
4+
5+
6+
= **Oracle兼容框架之双parser**
7+
8+
双parser框架主要分为两部分,包括SQL端和服务器端编程语言。
9+
10+
== SQL端词法语法分离
11+
12+
基本做法是新增一套兼容Oracle风格的语法和词法,在开启Oracle兼容的情况下,走Oracle风格的语法分析,生成相应的语法树。
13+
14+
具体方法:
15+
在src/backend/下面,新建一个oracle_parser目录,将src/backend/parser/下的scan.l和gram.y复制到该目录下,改名成ora_gram.y和ora_scan.l,添加 Oracle风格的语法和此法分析代码,同时复制keywords.c到该目录下,用来存放自己的关键字。该oracle_parser目录编译成一个动态库 libparser_oracle.so。当开启Oracle兼容的时候,配置文件ivorysql.conf被嵌入到postgresql.conf文件的末尾。配置文件ivorysql.conf中的shared_preload_libraries参数中添加“liboracle_parser”,这样当数据库启动时能够自动载入liboracle_parser动态库。
16+
17+
新增ora_raw_parser 函数指针,当libparser_oracle.so动态库被加载时,该动态库中的 _PG_init() 函数将 oracle_raw_parser() 函数的地址赋值给 ora_raw_parser,_PG_fini()则在兼容模式切换时负责重置 ora_raw_parser 为空。
18+
19+
每一个后端进程调用BackendInitialize()函数,通过后端进程所连接的端口号来设置 port->connmode。如果端口是Oracle兼容端口,则设置connmode为’o’,否则设置为’p’。
20+
21+
这之后PostgresMain()调用InitIvorysql(),如果port->connmode是’o’,则调用函数 SetConfigOption("ivorysql.compatible_mode", "oracle", PGC_USERSET, PGC_S_OVERRIDE);
22+
由于这个参数设置了 assign_hook,因此当 SetConfigOption() 函数里执行assign_hook()时,相当于调用 assign_compatible_mode(),从而设置 sql_raw_parser = ora_raw_parser;
23+
24+
在对SQL语句进行分析时,函数pg_parse_query()->raw_parser() 通过函数指针 sql_raw_parser 调用standard parser() 或者 ora_raw_parser()。
25+
26+
下面的图演示了SQL语句分析时发生的事情。
27+
28+
image::p21.jpg[]
29+
== 服务器端编程语言词法语法分离
30+
31+
在系统表pg_language中新增pliSQL语言。
32+
33+
具体实现方法:
34+
将PG源码中的plpgsql目录,复制一份,改名为plisql,里面的文件名称,改成plisql开头,因为plpgsql是一个language,改造的plisql也是一个language,因此,plpgsql language的注册函数如plpgsql_validator, plpgsql_call_handler, plpgsql_inline_handler都需要改成plisql开头,里面其他函数的改名都改成以plisql开头。
35+
36+
plisql目录构建为一个插件,initdb时如果数据库模式是Oracle,则创建这个插件。这个插件会将pliSQL语言注册到数据库的系统表中。
37+
38+
pliSQL端没有自己的词法规约,它依赖SQL端的词法规约,因此,针对pliSQL,强制其走兼容Oracle的词法规约,主要改造点是在 plisql_scanner_init 函数中,里面应该调用ora_scanner_init()函数,plisql目录中的 internal_yylex() 函数调用 ora_core_yylex。
39+
40+
pliSQL语法规则在plisql/src/pl_gram.y中,兼容Oracle plSQL块的语法规则都在这个模块中实现。
41+
42+
SQL端创建函数,没有指定language的时候,如果当前是兼容Oracle模式,则默认language是plisql,如果是兼容pg模式,则默认language是plpgsql。oracle_parser中的ora_gram.y默认是plisql,pg parser中的gram.y默认是plpgsql。
43+
44+
匿名块没有指定language的时候,如果是兼容Oracle模式,默认plisql,如果是兼容pg模式,则默认plpgsql。
45+
46+
处理过程的ExecuteDoStmt函数同样根据兼容模式来决定默认language。
47+
48+
image::p22.jpg[]

0 commit comments

Comments
 (0)