文章目录

本文以createuser和pg_dump两个过程为例,分析PostgreSQL的工具程序的一般设计方式。本文使用的是PostgreSQL 9.3.4版本。

所有这些工具过程的main函数代码都在源码目录的src\bin目录下面,例如,createuser和pg_dump就分别对应src\bin\scripts\createuser.csrc\bin\pg_dump\pg_dump.c

首先,createuser.c的main入口附近,先是include一些头文件,并定义一些参数的默认值,如下,

然后从86行开始,是解析参数,并给参数变量赋值,还有一些参数检查的工作,如下,

一直到248行出现了connectDatabase调用,表示,过程要开始连接数据库了,如下,

接下来,程序开始拼SQL,在309行的时候,程序执行之前拼出来的SQL,如下,

最后,检查执行的返回,清除返回结果集,关闭连接,退出程序。

可以看出,createuser的主程序非常简单,其实scripts目录下的程序基本都是这个结构,就是为常用的SQL脚本做了一层简单的包装。那么这个程序的关键就变为,如何处理拼出来的SQL。从PostgreSQL的文档中可以找到,createuser实际上就是SQL命令CREATE ROLE的封装,两者并无差异,而CREATE ROLE的实现是在src\backend\commands\user.cCreateRole函数中。实际上src\backend\commands目录下,存放了所有SQL命令执行的入口。

CreateRole入口中,先是检查输入的SQL语句的参数,然后检查参数的合法性,如下,

从第342行开始,根据输入的参数组成将要插入的数据,存在new_record中,如下,

然后在378行,把new_record中的数据转换到tuple变量中,之后,使用tuple中的数据完成插入等一系列操作,如下

其中最重要的一步应该是393行插入到pg_authid表(变量pg_authid_rel)这一步,如下,

根据PostgreSQL的文档,pg_authid表是一个很关键而又很特别的系统表。

系统表 pg_authid 包含有关数据库认证标识符(角色)的信息。 一个角色体现"用户"和"组"的概念。 一个用户实际上只是一个设置了 rolcanlogin 标志的角色。 任何角色(不管设置了 rolcanlogin 标志)都可以有其它角色做为成员。

程序中也反应了这一点,在406行,设置其他角色和新建的角色的关系,应该就是在完成设置新建角色使用其他角色为成员的工作,如下,

完成上述步骤之后,程序的工作基本就完成了,在退出之前,调用InvokeObjectPostCreateHook完成新增角色引起的其他动作,然后关闭pg_authid表,即回收pg_authid_rel变量,最后return已创建角色的roleid,退出。

以上是createuser的分析,pg_dump过程的步骤不太一样,它不是通过单纯的调用SQL完成的。

pg_dump.c的main函数之前声明了很多函数,main函数的开头也一样是定义了很多参数的默认值,并获取输入参数,做参数的检查,然后在637行的时候连接数据库,并将连接存在fout变量,如下,

连接之后,还会调用pg_catalog.pg_is_in_recovery()检查现在系统是否正处在恢复过程中,之后就是获取要导出对象的oid的集合,包括用户本身的oid,还有,根据输入schema和table的信息,匹配到符合条件的schema和table,如下,

再接下来,获取schema的信息,获取table信息,获取Blob信息,获取依赖信息等等,还有一些辅助的dummy数据,这些函数都是形如getXXXXData,例如getSchemaData,这些函数定义在common.c中,很多表相关的信息保存在tblinfo变量中,还有一些存储过程相关的对象存在dumpIdMap中,如下,

然后获取需要导出的对象(758行)的指针,并存储在dobjsnumObjs两个变量中,并将导出的过程对象根据依赖关系做排序,如下,

一系列的准备工作和获取需要的信息都已经完成,从792行开始,正式导出数据,最先导出的是字符集信息,接下来数据库表的信息,然后是之前排序好的过程对象,如下,

最后,设置一些归档的参数,关闭数据库连接,退出程序,如下,

因此,整个步骤中,最关键的几个步骤是,获取导出对象,排序导出对象,和最后的执行导出对象这三个步骤。其中一些关键的函数的作用应该是这样的,

getSchemaData,获取导出数据库、表、以及过程相关对象等的信息; sortDumpableObjects,根据过程的依赖关系,排序导出的先后; dumpDatabase,导出数据库和表相关的信息; dumpDumpableObject,导出过程相关对象的信息;

文章目录

欢迎来到Valleylord的博客!

本博的文章尽量原创。