postgres源码学习之sql查询
- sql查询的主流程
- 读取sql
- 解析sql
- 重写sql
- 获得执行计划
- 执行查询操作
- 结果返回
sql查询的主流程
参考postgres的处理流程
由上一节,我们可以看到,当有新的连接通过权限认证之后,将进入等待接收sql语句,并执行sql语句的过程。
读取sql
建立连接后,服务端postgres就等待接收命令
解析sql
解析sql语句函数为pg_parse_query,其调用栈如下:
重写sql
重写sql语句函数为parse_analyze_fixedparams,其调用栈如下:
获得执行计划
获得执行计划函数为pg_plan_queries,调用栈如下:
执行查询操作
查询操作调用顺序为PortalRun–>PortRunSelect–>ExecutorRun–>standard_ExecutorRun–>ExecutePlan
结果返回
在ExecutePlan中,会将结果集返回给客户端,调用栈如下:
涉及到查询结果返回的,会调用到printtup函数。
其函数主要内容如下:
/*
* send the attributes of this tuple
*/
for (i = 0; i < natts; ++i)
{
PrinttupAttrInfo *thisState = myState->myinfo + i;
Datum attr = slot->tts_values[i];
if (slot->tts_isnull[i])
{
pq_sendint32(buf, -1);
continue;
}
if (thisState->typisvarlena)
VALGRIND_CHECK_MEM_IS_DEFINED(DatumGetPointer(attr),
VARSIZE_ANY(attr));
if (thisState->format == 0)
{
/* Text output */
char *outputstr;
outputstr = OutputFunctionCall(&thisState->finfo, attr);
pq_sendcountedtext(buf, outputstr, strlen(outputstr));
}
else
{
/* Binary output */
bytea *outputbytes;
outputbytes = SendFunctionCall(&thisState->finfo, attr);
pq_sendint32(buf, VARSIZE(outputbytes) - VARHDRSZ);
pq_sendbytes(buf, VARDATA(outputbytes),
VARSIZE(outputbytes) - VARHDRSZ);
}
}
其输出形式和之前介绍的Mysql Resultset 解析记录中介绍的结果集存储有着相似的地方。