2.2.2 postgres.bki
后端接口postgres.bki文件是在编译的过程中由/src/backend/catalog目录下的脚本程序genbki.sh读取/src/include/catalog目录下的以.h结尾的系统表定义文件(包括系统表索引和TOAST表定义文件)创建,并且通常存放在安装树的share子目录下。在pg_*.h(星号表示对应系统表的名称,每一个这样的头文件对应一个系统表的结构定义)的头文件中包含如下内容的定义:
定义CATALOG宏,用于以统一的模式去定义系统表的结构以及用以描述系统表的数据结构,如系统表pg_class的定义通过CATALOG(pg_class,1259)来表现。
通过宏DATA(x)和DESCR(x)来定义insert操作,这样的insert操作可能会有多个,用于定义系统表中的初始数据。
模板数据库template1是通过运行在bootstrap模式的postgres程序读取postgres.bki文件创建的。BKI文件是一些用特殊语言写的脚本,这些脚本使PostgreSQL后端能够理解,且以特殊的“bootstrap”模式来执行之,这种模式允许在不存在系统表的零初始条件下执行数据库函数,而普通的SQL命令要求系统表必须存在。因此BKI文件仅用于初始化数据集簇。
BKI命令的格式如下:
(1)create[bootstrap][shared_relation][without_Oids]tablename tableOid(name1=type1[,name2=type2,...])
创建一个名为tablename并且OID为tableOid的表,表的字段在圆括弧中给出。Bootstrap模式支持下列字段类型:bool、bytea、char(1字节)、name、int2、int4、regproc、regclass、regtype、text、Oid、tid、xid、cid、int2vector、Oidvector、_int4(数组)、_text(数组)、_Oid(数组)、_char(数组)、_aclitem(数组)。只有在创建完pg_type并且填充了合适的数据之后才可以创建包含其他类型字段的表。
如果指定了bootstrap选项,那么将只创建表而不向pg_class等系统表里面插入任何记录。因此这样的表将无法被普通的SQL操作访问,直到系统表中的初始记录用硬方法(BKI的insert命令)插入。这个选项用于创建诸如pg_class等核心的系统表。
如果指定了shared_relation选项,那么该表将作为整个数据集簇的共享表创建(比如创建pg_database)。
如果指定了without_Oids选项,则该表将不会具有OID字段。
(2)open tablename
打开一个名为tablename的表,准备插入数据。在BKI被执行时,每一个时刻都只有一个表被打开,因此使用open命令时,任何当前已经打开的表都会被关闭。
(3)insert[OID=Oid_value](value1 value2...)
以value1、value2等作为字段值插入一个元组,如果该表具有OID属性,则把Oid_value作为被插入元组的OID。如果Oid_value为零或者省略了OID关键字,将为该插入元组分配系统中可用的下一个OID。
(4)close[tablename]
关闭当前被打开的表。由于每一时刻只有一个表被打开,因此可以省略tablename。
(5)declare[unique]index indexname indexOid on tablename using amname(opclass1 name1[,...])
在名为tablename的表上用amname访问方法创建一个OID为indexOid且名为indexname的索引。索引属性是tablename表的name1、name2等属性,在属性上使用的操作符类分别是opclass1、opclass2等。该命令仅仅是创建一个索引的结构,索引的内容(即索引项)并不由该命令填充。
(6)declare toast toasttableOid toastindexOid on tablename
为名为tablename的表创建一个TOAST表。该TOAST表的OID为toasttableOid,其索引的OID为toastindexOid。与declare index命令一样,该命令也不会填充TOAST表的索引。
(7)build indices
对使用(5)、(6)两种命令创建的索引进行内容填充。
特别需要说明的是,在有一些基本的系统表(关键表)被创建并初始化其数据之前,不能使用open命令打开非关键系统表。其中关键表包括:pg_class、pg_attribute、pg_proc和pg_type。根据前面对这几个系统表用途的介绍,我们可以很容易理解为什么只有在关键表建立之后才能使用open命令,因为这几个关键表存储了所有系统表的模式信息,如果它们没有被建立,open命令不可能在其中找到要打开的系统表的模式信息。由于关键表不能用open打开进行填充,BKI提供了带bootstrap选项的create命令,该命令可以在创建关键表后自动将其打开。同样,“declare index”和“declare toast”命令也不能在它们所需要的系统表(比如前者需要pg_index等)被创建并填充之前使用。
在整个源代码被编译时,genbki.sh脚本会被调用,它将从每一个pg_*.h文件中读取系统表定义、系统表的初始化数据、系统表上的索引等信息,然后分别将其转换为对应的BKI命令,最后将所有的BKI命令写入到postgres.bki文件中,该文件的内容如下:
1) 一个“create bootstrap”命令,用于创建其中一个关键表。
2) 一个或多个insert命令,用于填充步骤1创建的关键表中的数据。
3) 一个close命令,用于关闭步骤1创建的关键表。
4) 重复步骤1~3创建和填充其他关键表。
5) 一个不带bootstrap选项的create命令,用于创建一个非关键表。
6) 一个open命令,打开非关键表。
7) 一个或多个insert命令,填充非关键表所需要的数据。
8) 一个close命令,关闭上面打开的非关键表。
9) 重复创建其他非关键表。
10) 一个或多个“declare index”命令,用于定义索引。
11) 一个“build indices”命令,用于实际建立上一步所定义的索引。
【责任编辑:云霞 TEL:(010)68476606】