PG源码阅读打卡

17 阅读3分钟

我是一名想学数据库内核的小白,欢迎大佬的建议和批评指正!

Pg源码分析第一阶段(select 1+1)

Parse

语法分析阶段,输入是原sql语句,输出是rawstsmt组合成的list。

然后对一些具体全局变量和条件进行判断后,最终处理在base_yyparse函数中,实际将sql转化为list的过程也是在这个过程中发生,具体转化过程中,:自动生成base_yyparse函数,其中rawstmt的装入通过lapend函数将makerawstmt函数返回的rawstmt装入list中,经过parse处理后,会生成若干个语句对应的rawstmt,他们在后续阶段都会被单独处理,互相独立。

Analyze

语义分析阶段,输入rawstmt,输出query组成的list

语义分析的核心目标:让底层能真正读懂sql语句,语义分析阶段会根据rawstmt的具体情况进行拆分,

1.先判读stmt的类型,不同的stmt会有对应的不同处理策略

2..对stmt的不同部分进行分别处理,分别对应原sql语句的,where,from,实际参数等等内容

3.处理过程涉及一个核心数据结构:TargetEntry,这个结构相比于parse阶段的restarget

多了三个核心结构:expr,resno,rejunk,分别代表数据表达式,列编号,和垃圾列。Analyze阶段主要核心目标就是expr,在select 1+1案例中,A_expr to Op_expr的转换是核心目标。Resno和resjunk会对后续plan与execut阶段读取数据提供依据。回到具体执行,targetentry的值也是通过lappend函数装载到query中的。

  1. transformExprRecurse会根据expr的nodetag(来源于restaget)来决定如何处理,在select 1+1;处理运算符的时候会递归调用处理参数,处理参数的过程直接停止即可无需递归,处理“+”的时候,会向系统表中查“+“对应的oid,放入opfuncid中,同样的consttype和opno也会存储参数类型和+对应函数的oid。

Rewrite

主要针对RIR规则(视图展开规则)和non-select规则

进行重写,select 1+1;并没有表和视图需要展开,rewrite阶段什么也不做

Optimzer

计划阶段,输入query组成的list,输出planstmt组成的list

计划的核心目标:将query变成执行计划,指导execute阶段的执行。

两个核心数据结构,

Plansnedtmt:记录了一些基础信息,例如表,子计划,当前是否为临时计划等等。

Plan:内含于plannedstmt,记录了开销代价等等。

在select 1+1中因为ratble=NIL,节点类型为result

Executor

执行阶段,输入plannedstmt组成的list,输出tupletableslot

这里三个核心结构,

Querydesc是个总闸,内含estate和planstate,

Estate内含状态信息,每个querydec只有一个,

Planstate则是根据算子类型(result,agg。。。)处理自带的指针,使用统一接口execprocnode处理不同类型算子,

在select 1+1过程中,在初始化阶段,通过fmgr_info(opfuncid, flinfo)根据opfuncid从系统表查找对应函数,将int4pl的地址存入fn_addr,执行时直接调用fn_addr完成计算。指针对应函数是execresult,经过filter之后,主要处理在projecttion中,经过两次函数调用后,retDatum = state->evalfunc(state, econtext, isNull);这一行同样通过指针统一接口调用最后在ExecInterpExpr里面完成计算1+1;返回的datum值直接赋值给tupletableslot中的tts_values[0]。

以后我会每周在这里分享自己的学习进度。