目标
添加一个连接参数,默认为 false 。当 psql 连接时,若该连接参数非 “true” 时,用户 “u1“ 对表对象无操作权限,包括自己拥有的表。
连接机制简介
连接过程如下所述:
- 客户端初始化一个空连接,设置连接状态为 CONNECTION_NEEDED 。
- 然后创建 socket,与服务端建立 tcp 连接,状态设置为 CONNECTION_STARTED ,检查 socket 连接是否正常。
- 初始化连接中的 socket 地址,修改连接状态为 CONNECTED_MODE 。
- 给服务端发送协议号等信息,发送启动包给服务端后,设置状态为 CONNECTION_AWAITING_RESPONSE 。
- 处理身份验证交换,等待 postmaster 消息并根据需要作出响应,最终设置状态为 CONNECTION_AUTH_OK。(后续过程再次不再细述,有兴趣可以自己查资料进行学习)。
我们重点关注启动包,因为参数的发送、解析都是通过启动包完成。启动包不止包含了连接协议,还包含了些连接选项等信息( dbname、user 等)。此次连接参数的发送解析就在启动包中。
实现
此处以添加 conninfo 为例:
确定标志为 priv_flag,默认为 false ,并设置为全局变量。确定连接参数为 char* 型的变量 privilege_flag 。
定义全局变量 priv_flag
在 src/backend/utils/init/globals.c 文件中定义
bool priv_flag = false;
并在 src/include/miscadmin.h 中声明此变量
extern bool priv_flag;
在 Port 和 conn 结构体中添加字段
主要目的是在建立连接的过程中,对该参数的赋值发送和接受,进行处理。pg_conn 为客户端存储连接状态结构体,Port 为服务端相关联结构体。
在 src/include/libpq/libpq-be.h 文件的 Port 结构体中添加 privilege_flag 字段:
char *privilege_flag;
src/interfaces/libpq/libpq-int.h 文件中 pg_conn 结构体同理添加:
char *privilege_flag;
在 conninfo 中添加 privilege_flag
psql 首先会对命令行 -选项 的命令进行解析,未匹配的“”引号里面的信息,会在客户端填充第一包数据之前,进行解析,此时依赖的就是 connin