当前位置: 首页 > article >正文

Postgresql源码(138)alter table增加列的执行流程分析

alter table 逻辑比较繁琐,但并不复杂,这里以增加列为例简单梳理流程。

测试用例

drop table t_echo;
create table t_echo(a int,b int);
insert into t_echo select t.i, t.i*10 from generate_series(1,10) t(i);
alter table t_echo add c varchar(32) default pg_backend_pid();

postgres=# select * from t_echo;
 a  |  b  |   c
----+-----+-------
  1 |  10 | 13425
  2 |  20 | 13425
  3 |  30 | 13425
  4 |  40 | 13425
  5 |  50 | 13425
  6 |  60 | 13425
  7 |  70 | 13425
  8 |  80 | 13425
  9 |  90 | 13425
 10 | 100 | 13425
(10 rows)

alter table流程分析

alter table t_echo add c varchar(32) default pg_backend_pid();

1 analyze_and_rewrite阶段

parse_analyze_fixedparams

transform阶段对语句没有太多处理。使用Parse树直接返回。
在这里插入图片描述
在transformStmt中,使用switch (nodeTag(parseTree))来决定对一些需要处理的parseTree进行语义分析:

switch (nodeTag(parseTree))
	case T_InsertStmt:
			result = transformInsertStmt(pstate, (InsertStmt *) parseTree);
			break;

		case T_DeleteStmt:
			result = transformDeleteStmt(pstate, (DeleteStmt *) parseTree);
			break;

		...
		...

这里比较好扩展,如果想自己对alter语句进行处理:在switch中截获需要的类型,写个类似上面的函数进行处理即可。

alter table t_echo add c varchar(32) default pg_backend_pid();
输出Query树:
在这里插入图片描述

pg_rewrite_query

rewrite阶段对ddl也没有什么特殊处理:
在这里插入图片描述

2 plan阶段

优化器对DDL也不做特殊处理。
在这里插入图片描述

3 执行阶段

3.1 DDL走哪个分支处理?

ProcessUtilitySlow
	Node	   *parsetree = pstmt->utilityStmt;
	switch (nodeTag(parsetree))
		case T_AlterTableStmt:
			...
			AlterTable
			...

3.2 处理流程

#0  pg_backend_pid (fcinfo=0x3249ea0) at pgstatfuncs.c:663
#1  0x0000000000748fea in ExecInterpExpr (state=0x3249ce0, econtext=0x324a460, isnull=0x7ffffe4d9f07) at execExprInterp.c:746
#2  0x000000000074b332 in ExecInterpExprStillValid (state=0x3249ce0, econtext=0x324a460, isNull=0x7ffffe4d9f07) at execExprInterp.c:2033
#3  0x00000000005e6ab7 in ExecEvalExpr (state=0x3249ce0, econtext=0x324a460, isNull=0x7ffffe4d9f07) at ../../../src/include/executor/executor.h:348
#4  0x00000000005e6e3a in StoreAttrDefault (rel=0x7fc0d9c1e6a8, attnum=3, expr=0x325b718, is_internal=false, add_column_mode=true) at pg_attrdef.c:131
#5  0x00000000005c5270 in AddRelationNewConstraints (rel=0x7fc0d9c1e6a8, newColDefaults=0x325b208, newConstraints=0x0, allow_merge=false, is_local=true, is_internal=false, queryString=0x0) at heap.c:2337
#6  0x00000000006f4e32 in ATExecAddColumn (wqueue=0x7ffffe4da448, tab=0x3237e80, rel=0x7fc0d9c1e6a8, cmd=0x7ffffe4da328, recurse=true, recursing=false, lockmode=8, cur_pass=AT_PASS_ADD_COL, context=0x7ffffe4da5e0) at tablecmds.c:7174
#7  0x00000000006f09bc in ATExecCmd (wqueue=0x7ffffe4da448, tab=0x3237e80, cmd=0x32468b8, lockmode=8, cur_pass=AT_PASS_ADD_COL, context=0x7ffffe4da5e0) at tablecmds.c:5182
#8  0x00000000006f075a in ATRewriteCatalogs (wqueue=0x7ffffe4da448, lockmode=8, context=0x7ffffe4da5e0) at tablecmds.c:5129
#9  0x00000000006efafe in ATController (parsetree=0x313d2d8, rel=0x7fc0d9c1e6a8, cmds=0x313d288, recurse=true, lockmode=8, context=0x7ffffe4da5e0) at tablecmds.c:4722
#10 0x00000000006ef752 in AlterTable (stmt=0x313d2d8, lockmode=8, context=0x7ffffe4da5e0) at tablecmds.c:4368
#11 0x00000000009f7816 in ProcessUtilitySlow (pstate=0x3237d70, pstmt=0x313d388, queryString=0x313c360 "alter table t_echo add c varchar(32) default pg_backend_pid();", context=PROCESS_UTILITY_TOPLEVEL, params=0x0, queryEnv=0x0, dest=0x313d748, qc=0x7ffffe4dac10) at utility.c:1318
#12 0x00000000009f71ed in standard_ProcessUtility (pstmt=0x313d388, queryString=0x313c360 "alter table t_echo add c varchar(32) default pg_backend_pid();", readOnlyTree=false, context=PROCESS_UTILITY_TOPLEVEL, params=0x0, queryEnv=0x0, dest=0x313d748, qc=0x7ffffe4dac10) at utility.c:1067
#13 0x00000000009f6389 in ProcessUtility (pstmt=0x313d388, queryString=0x313c360 "alter table t_echo add c varchar(32) default pg_backend_pid();", readOnlyTree=false, context=PROCESS_UTILITY_TOPLEVEL, params=0x0, queryEnv=0x0, dest=0x313d748, qc=0x7ffffe4dac10) at utility.c:523
#14 0x00000000009f4fab in PortalRunUtility (portal=0x31e4ca0, pstmt=0x313d388, isTopLevel=true, setHoldSnapshot=false, dest=0x313d748, qc=0x7ffffe4dac10) at pquery.c:1158
#15 0x00000000009f5200 in PortalRunMulti (portal=0x31e4ca0, isTopLevel=true, setHoldSnapshot=false, dest=0x313d748, altdest=0x313d748, qc=0x7ffffe4dac10) at pquery.c:1316
#16 0x00000000009f4731 in PortalRun (portal=0x31e4ca0, count=9223372036854775807, isTopLevel=true, run_once=true, dest=0x313d748, altdest=0x313d748, qc=0x7ffffe4dac10) at pquery.c:791
#17 0x00000000009edfba in exec_simple_query (query_string=0x313c360 "alter table t_echo add c varchar(32) default pg_backend_pid();") at postgres.c:1284
#18 0x00000000009f288e in PostgresMain (dbname=0x3174b70 "postgres", username=0x3174b58 "mingjie") at postgres.c:4766
#19 0x00000000009ea38d in BackendMain (startup_data=0x7ffffe4daf10 "", startup_data_len=4) at backend_startup.c:107
#20 0x000000000091675c in postmaster_child_launch (child_type=B_BACKEND, startup_data=0x7ffffe4daf10 "", startup_data_len=4, client_sock=0x7ffffe4daf40) at launch_backend.c:274
#21 0x000000000091bca8 in BackendStartup (client_sock=0x7ffffe4daf40) at postmaster.c:3414
#22 0x0000000000919607 in ServerLoop () at postmaster.c:1648
#23 0x0000000000918fd5 in PostmasterMain (argc=1, argv=0x3136e70) at postmaster.c:1346
#24 0x00000000007d9efd in main (argc=1, argv=0x3136e70) at main.c:197

AlterTable执行:

AlterTable
	ATController
		/* Phase 1: preliminary examination of commands, create work queue */
		foreach
			ATPrepCmd
		/* Phase 2: update system catalogs */
		ATRewriteCatalogs
		/* Phase 3: scan/rewrite tables as needed, and run afterStmts */
		ATRewriteTables

处理分为三个阶段:

  1. 预检查:主要是权限检查,会递归到每一层函数。
  2. 改表结构:ATExecCmd函数中的大switch控制具体执行的指令,例如add column、column default等等。
    • 例如本文开头提供的用例:alter table t_echo add c varchar(32) default pg_backend_pid();
    • ATExecCmd
      • ATExecAddColumn:增加列
        • AddRelationNewConstraints
          • StoreAttrDefault:设置列默认值
            • ExecEvalExpr:计算列默认值表达式
                • ExecInterpExpr
                  • pg_backend_pid
  3. 收尾工作:比如修改某些数据类型了要检查依赖、修改约束了要检查约束等等。

http://www.kler.cn/a/397935.html

相关文章:

  • LLaMA-Factory全流程训练模型
  • 【Linux】Ubuntu中muduo库的编译环境安装
  • 北京大学c++程序设计听课笔记101
  • 金山云Java 开发面试题及参考答案
  • FlinkSql读取kafka数据流的方法(scala)
  • 数据分析-48-时间序列变点检测之在线实时数据的CPD
  • MySQL系列之数据授权(privilege)
  • GBase8c 数据库审计项配置审计日志维护
  • 【安卓恶意软件检测-论文】DroidEvoler:自我进化的 Android 恶意软件检测系统
  • Notepad++的完美替代
  • Spring Boot 启动时修改上下文
  • 如何设置MySQL 数据库的默认字符集和默认排序规则
  • 【Golang】——Gin 框架中间件详解:从基础到实战
  • 【C++ 算法进阶】算法提升十五
  • 19-简单理解JavaScript中的Promise:手写Promise实现
  • Redis高可用-主从复制
  • 无人机吊舱基础——CKESC电调小课堂09
  • 永夜星河主题特效2(星河背景 + 闪烁文字+点击星星 + 文字弹出特效)
  • skywalking各项指标说明
  • Robot | 用 RDK 做一个小型机器人(更新中)
  • 222. 完全二叉树的节点个数【 力扣(LeetCode) 】
  • uniapp 跨域前端代理
  • FPGA 第8讲 简单组合逻辑--半加器
  • uni-app快速入门(三)--UniApp生命周期
  • java导出pdf
  • 后台管理系统(开箱即用)