客户端通过pg服务器查询的大致过程如下
一、 建立连接
客户端首先需要连接上pg服务器,服务器在和客户端建立连接后fork一个子进程处理后续客户端的请求,服务器然后等待下一个客户端的连接。
二、发送请求
客户端发送请求数据给pg服务器,pg子进程读取请求。
- 客户端发送请求
比如命令行,读取用户输入,发送给服务器
src/bin/psql/mainloop.c
int
MainLoop(FILE *source)
{
...
SendQuery(query_buf->data);
...
}
- 服务器接收请求
void
PostgresMain(int argc, char *argv[],
const char *dbname,
const char *username)
{
...
for (;;)
{
...
firstchar = ReadCommand(&input_message);
...
}
}
三、解析
以简单查询为例子。服务器接收到的是一串字符串,需要解析理解这个数据才能执行。
src/backend/tcop/postgres.c
static void
exec_simple_query(const char *query_string)
{
...
parsetree_list = pg_parse_query(query_string);
...
}
通过词法以及语法解析,构建一个原始的语法树。
四、优化
static void
exec_simple_query(const char *query_string)
{
...
querytree_list = pg_analyze_and_rewrite(parsetree, query_string,
NULL, 0, NULL);
plantree_list = pg_plan_queries(querytree_list, query_string,
CURSOR_OPT_PARALLEL_OK, NULL);
..
}
将原始的语法树转化为一个查询树,并且对查询树进行优化以及重写,提升执行速度。
五、执行
static void
exec_simple_query(const char *query_string)
{
...
(void) PortalRun(portal,
FETCH_ALL,
true, /* always top level */
true,
receiver,
receiver,
&qc);
...
}
六、返回结果
具体函数还为找到 😦