Postgresql源码(137)执行器参数传递与使用
参考
《Postgresql源码(127)投影ExecProject的表达式执行分析》
0 总结速查
prepare p_04(int,int) as select b from tbl_01 where a = $1 and b = $2
为例。
- custom计划中,在表达式计算中使用参数的值,因为custom计划会带参数值,所以表达式计算时不需要从参数列表中取值,直接EEO_CASE(EEOP_FUNCEXPR_STRICT)计算即可。
- generic计划中,在表达式计算中使用参数的值,generic计划不带参数值,所以需要多走一步EEO_CASE(EEOP_PARAM_EXTERN)、EEO_CASE(EEOP_FUNCEXPR_STRICT)。具体调用ExecEvalParamExtern函数拿到参数值。
- generic计划中,使用参数的节点会放一个Param。
1 执行器如何使用参数?
在下面例子中,execute语句执行时带了两个参数,执行器是在哪里带入参数执行的?下面做一些分析。
prepare p_04(int,int) as select b from tbl_01 where a = $1 and b = $2;
execute p_04(2,200);
带入参数的位置是PortalStart函数。
extern void PortalStart(Portal portal, ParamListInfo params, int eflags, Snapshot snapshot);
PortalStart的第二个参数可以接受参数列表ParamListInfo,从代码上看,PortalStart有三处调用位置:
exec_simple_queryPortalStart(portal, NULL, 0, InvalidSnapshot)exec_bind_messagePortalStart(portal, params, 0, InvalidSnapshot)ExecuteQueryPortalStart(portal, paramLI, eflags, GetActiveSnapshot())SPI_cursor_open_internalPortalStart(portal, paramLI, 0, snapshot)
- exec_simple_query:执行简单SQL语句,不需要传参。
- exec_bind_message:PEB协议中的B阶段,绑定参数。
- ExecuteQuery:SQL语法提供的PBE协议,在execute阶段,绑定参数。
- SPI_cursor_open_internal:PL中打开游标时,绑定参数。
下面对3、4两种情况展开分析。
2 execute执行时执行器的传参
栗子:
create table tbl_01(a int, b int);
insert into tbl_01 values (1,100);
insert into tbl_01 values (2,200);
prepare p_04(int,int) as select b from tbl_01 where a = $1 and b = $2;
execute p_04(2,200);
execute p_04(2,200);
执行时,PortalStart会带入ParamListInfo。
2.1 问题一:ParamListInfo的来源?
ExecuteQueryEvaluateParams// 准备计算参数表达式的值exprstates = ExecPrepareExprList(params, estate)makeParamListretval->parserSetup = paramlist_parser_setup// paramlist_parser_setup// pstate->p_paramref_hook = paramlist_param_ref//// paramlist_param_ref// param = makeNode(Param)// param->paramkind = PARAM_EXTERN// param->paramid = paramno// ...// 钩子函数中生成Param,该实例不会走这个钩子,注意Param结构是不带值的,只用于中间过程。// 走表达式计算参数的值// 注意值都在paramLI->params[i]->value中i = 0;foreach(l, exprstates){ExprState *n = (ExprState *) lfirst(l);ParamExternData *prm = ¶mLI->params[i];prm->ptype = param_types[i];prm->pflags = PARAM_FLAG_CONST;prm->value = ExecEvalExprSwitchContext(n,GetPerTupleExprContext(estate),&prm->isnull);i++;}
生成ParamListInfo(包含参数的全部信息,包括值)
paramLI = {paramFetch = 0x0,paramFetchArg = 0x0,paramCompile = 0x0,paramCompileArg = 0x0,parserSetup = 0x8357c1 <paramlist_parser_setup>,parserSetupArg = 0x3238da8,paramValuesStr = 0x0,numParams = 2,params = 0x3238de8}
2.2 问题二:ParamListInfo的使用位置?
custom plan
前五次执行会生成customplan,customplan在GetCachedPlan中生成,customplan计划是带着参数生成的(按参数定制的计划,更准确,但每次参数变了都要重新生成),所以计划中会有参数的具体值,执行时不会使用执行器带入的ParamListInfo。
构造customplan时,会带入参数生成计划:
ExecQual调用表达式框架计算where a = $1 and b = $2
,ExecQual函数进入表达计算。
ExecScanfor (;;)slot = ExecScanFetch...if (qual == NULL || ExecQual(qual, econtext))...return slot
ExecQual表达式计算流程:
- EEO_CASE(EEOP_SCAN_FETCHSOME)
- 从econtext->ecxt_scantuple读取到scanslot(当前要处理的一行数据)slot_getsomeattrs函数确保这一行数据中,至少有op->d.fetch.last_var个列是可以直接访问的。《Postgresql源码(127)投影ExecProject的表达式执行分析》
- EEO_CASE(EEOP_SCAN_VAR)
- 从行中拿到需要列的值。《Postgresql源码(127)投影ExecProject的表达式执行分析》
- EEO_CASE(EEOP_FUNCEXPR_STRICT)
- 计算where中第一个条件
- fcinfo : int4eq
- arg1 : 2
- arg2 : 2
- EEO_CASE(EEOP_QUAL)
- EEO_CASE(EEOP_FUNCEXPR_STRICT)
- 计算where中第二个条件
- fcinfo : int4eq
- arg1 : 200
- arg2 : 200
- EEO_CASE(EEOP_QUAL)
generic plan
第六次执行时,choose_custom_plan返回false,BuildCachedPlan时没有传入任何参数构造generic plan(通用执行计划,可以接受任何参数,不用每次都生成计划,但没有customplan精确,毕竟这里没有给参数)
执行execute p_04(2,200);给的两个参数明显是用于过滤条件的,所以在ExecScan→ExecQual中寻找使用的位置:
在ExecEvalParamExtern函数中,从econtext->ecxt_param_list_info中拿到参数值,返回给表达式框架:
ExecEvalParamExtern(ExprState *state, ExprEvalStep *op, ExprContext *econtext)
{ParamListInfo paramInfo = econtext->ecxt_param_list_info;int paramId = op->d.param.paramid;if (likely(paramInfo &¶mId > 0 && paramId <= paramInfo->numParams)){ParamExternData *prm;ParamExternData prmdata;......prm = ¶mInfo->params[paramId - 1];......*op->resvalue = prm->value;*op->resnull = prm->isnull;return;}}......
}
最终ExecScan在loop中,拿到的slot经过ExecQual的计算,决定是否保留该元组。
ExecQual调用表达式框架计算where a = $1 and b = $2
,通过ExecEvalParamExtern
函数拿到$1
、$2
的值,完成计算,放回true OR false。
ExecScanfor (;;)slot = ExecScanFetch...if (qual == NULL || ExecQual(qual, econtext))...return slot
表达式计算流程:
- EEO_CASE(EEOP_SCAN_FETCHSOME)
- EEO_CASE(EEOP_SCAN_VAR)
- EEO_CASE(EEOP_PARAM_EXTERN)
- EEO_CASE(EEOP_FUNCEXPR_STRICT)
- int4eq
- arg1 : 2
- arg2 : 2
- EEO_CASE(EEOP_QUAL)
- EEO_CASE(EEOP_SCAN_VAR)
- EEO_CASE(EEOP_PARAM_EXTERN)
- EEO_CASE(EEOP_FUNCEXPR_STRICT)
- int4eq
- arg1 : 200
- arg2 : 200
从计划上来看,参数的位置是两个Param。
3 游标打开时执行器的传参
create table tbl_01(a int, b int);
insert into tbl_01 values (1,100);
insert into tbl_01 values (2,200);do $$
declareres int;c_04 CURSOR (p1 int, p2 int) FOR select b from tbl_01 where a = p1 and b = p2;
beginopen c_04(2,200);fetch c_04 into res;raise notice '%',res;
end; $$;
PL的参数在transform阶段已经转成const了,所以执行类似customplan:
fetch堆栈:
相关文章:

Postgresql源码(137)执行器参数传递与使用
参考 《Postgresql源码(127)投影ExecProject的表达式执行分析》 0 总结速查 prepare p_04(int,int) as select b from tbl_01 where a $1 and b $2为例。 custom计划中,在表达式计算中使用参数的值,因为custom计划会带参数值&…...

韩国恋爱游戏:阿西, 美女室友竟然…?百度网盘下载
故事情节/出场人物 [阿西, 美女室友竟然…?]是一款 FMV 真人视频恋爱游戏,你将以第一人称与5位美女室友一起体验别样合租生活。 在本作中,您将扮演合租公寓的房东男主 吴宥万(直译:牛奶男),一直独来独往的你,生活…...
一个运维牛人对运维规则的10个总结
一个运维牛人对运维规则的10个总结 在运维领域,经验和流程往往决定了系统的稳定性与可靠性。一个运维人,总结出了以下10条运维规则,涵盖了从基础管理到高级策略的全面内容,旨在帮助运维人员更好地应对各种挑战,确保系…...

Istio基本概念及部署
一、Istio架构及组件 Istio服务网格在逻辑上分为数据平面和控制平面。 控制平面:使用全新的部署模式:Istiod,这个组件负责处理Sidecar注入,证书颁发,配置管理等功能,替代原有组件,降低复杂度&…...

基于 Python 的 Django 框架开发的电影推荐系统
项目简介:本项目是基于 Python 的 Django 框架开发的电影推荐系统,主要功能包括: 电影信息爬取:获取并更新电影数据。数据展示:提供电影数据的列表展示。推荐系统:基于协同过滤算法实现个性化推荐。用户系…...
离线数仓开发SQL编写和调试的最佳实践(如何又快又好完成任务,学会几条就不用当很辛苦的牛马)
目录 在开发阶段对数据进行抽样 理论基础 实践应用 使用Hive进行数据采样 使用Spark进行数据采样 采用CTE模块化设计 逐步验证 逐步验证案例实践: 验证sales_data CTE: 验证ranked_sales CTE: 验证top_sales CTE: 结论 用Doris或Impala等更快查询的代替Hive …...
PostgreSQL 增量备份:保护你的数据资产
全文目录: 开篇语📜 前言📚 增量备份概述🔑 增量备份的优势 🛠️ PostgreSQL 增量备份实施步骤🌟 环境准备🚀 第一步:全量备份⏳ 第二步:定期增量备份🔄 第三…...

字节青训-寻找最大葫芦
问题描述 在一场经典的德州扑克游戏中,有一种牌型叫做“葫芦”。“葫芦”由五张牌组成,其中包括三张相同牌面值的牌 aa 和另外两张相同牌面值的牌 bb。如果两个人同时拥有“葫芦”,我们会优先比较牌 aa 的大小,若牌 aa 相同则再比…...
el-checkbox勾选一个变成了勾选所有
问题: el-checkbox完成后勾选一个选项变成了所有选项都勾选了。非model值不正确,我的model值绑定的是数组,但是还是勾选一个变成了勾选多个。 解决 因为勾选的内容比较简单,且值不需要入库,所以我最开始定义的option为…...

ExpandingCard扩展卡片
文章目录 演示效果分析思路核心代码总结 源码 演示效果 分析思路 使用flex布局,每个卡片的宽度都由flex进行灵活调整交互可以增加和删除active,来实现宽度扩增和恢复还需要使用transition进行动画过渡,使得平滑切换 核心代码 首先创建一个…...

移远通信推出八款天线新品,覆盖5G、4G、Wi-Fi和LoRa领域
近日,全球领先的物联网整体解决方案供应商移远通信宣布,再次推出八款高性能天线新品,进一步丰富其天线产品阵容,更好地满足全球客户对高品质天线的更多需求。具体包括5G超宽带天线YECT005W1A和YECT004W1A、5G天线YECT028W1A、4G天…...

MySQL 9从入门到性能优化-创建触发器
【图书推荐】《MySQL 9从入门到性能优化(视频教学版)》-CSDN博客 《MySQL 9从入门到性能优化(视频教学版)(数据库技术丛书)》(王英英)【摘要 书评 试读】- 京东图书 (jd.com) MySQL9数据库技术_夏天又到了…...

UE5 第三人称学习之动画 control rig
这个东西和建模软件里有的是一个东西,然后IK就是你动脚,他帮你算出小腿大腿该怎么动,FK就是你自己动了大腿,摆小腿,然后再摆脚 就是给每一根骨骼搞一个控制器,给他一个容易选中和操作更明显的图形作为控制…...
C++之--初见模板初阶
一、泛型编程 为了实现一个通用的函数,在此之前,我们学过函数重载,使用函数重载虽然可以实现,但是有一下几个不好的地方: 1. 重载的函数仅仅是类型不同,代码复用率比较低,只要有新类型出现时&a…...

Nature|用于无线监测颅内信号的植入式柔性超声波传感器(柔性传感/健康监测/植入式电子/水凝胶)
华中科技大学臧剑锋(Jianfeng Zang)、华中科技大学同济医学院附属协和医院姜晓兵(Xiaobing Jiang)和新加坡南洋理工大学陈晓东(Xiaodong Chen)团队,在《Nature》上发布了一篇题为“Injectable ultrasonic sensor for wireless monitoring of intracranial signals”的论…...

【和AI的《趣味》聊天】01 AI:你找茬是吧(
我: 以下哪个选项是中文? A.Chinese B.英文 AI: 我: 这不对吧,我说的是那个选项的语言是中文 AI: 非常抱歉,我之前的回答有误。您问的是哪个选项的语言是中文,那么答案应该是…...

“发放父作业单”是“过数”用例里面的内容吗
刘京城 2020-4-14 23:01 。。。。(注:这是一个人的昵称,不是省略号) 首先,执行者是同一个,那么思考焦点要关注“过数”用例是不是“发放父作业单”用例的一个步骤,和行为操作的频率无关,而是和责任有关&am…...

Linux补基础之:网络配置
目录 一、检查主机与虚拟机是否能正常通信 二、网络的连接模式 桥接模式 流程 特点 NAT模式 流程 特点 仅主机 流程 特点 三、修改静态IP 四、可能遇到的问题 防火墙 DNS 五、主机名更改 六、登录服务器 实际的大数据管理中,会有由很多服务器构成的…...
【flink】之kafka到kafka
一、概述 本文档旨在介绍如何使用Apache Flink从Kafka接收数据流,并将处理后的数据写入到另一个Kafka Topic中。Apache Flink是一个开源的流处理框架,能够处理无界和有界数据流,并且支持高吞吐量和低延迟的数据处理。通过Flink与Kafka的集成…...

微信小程序时间弹窗——年月日时分
需求 1、默认当前时间2、选择时间弹窗限制最大值、最小值3、每次弹起更新最大值为当前时间,默认值为上次选中时间4、 minDate: new Date(2023, 10, 1).getTime(),也可以传入时间字符串new Date(2023-10-1 12:22).getTime() html <view class"flex bb ptb…...
redis进入后台操作、查看key、删除key
cmd进入 redis后台 避免报错NOAUTH Authentication required 第一步 ./redis-cli -h 127.0.0.1 -p 6379第二步 AUTH YourPassword通过key删除redis缓存 进了后台之后输入 keys * 删除key del key1...

Redis:介绍和认识,通用命令,数据类型和内部编码,单线程模型
介绍和认识 Redis是一个基于内存的,高性能的,支持许多数据类型的NoSQL数据库,可以持久化,也支持分布式。 在许多的互联网产品中,对于数据库的访问速度要求很高,例如Mysql数据库无法满足其要求,…...
Unity3D 逻辑代码性能优化策略
前言 在Unity3D中优化逻辑代码性能是提升游戏流畅度的关键。以下是系统性的优化策略和示例: 对惹,这里有一个游戏开发交流小组,希望大家可以点击进来一起交流一下开发经验呀! 1. 避免高频操作中的开销 缓存组件引用 private …...

基于Java(Jsp+servelet+Javabean)+MySQL实现图书管理系统
图书管理系统 一、需求分析 1.1 功能描述 1.1.1“读者”功能 1)图书的查询:图书的查询可以通过搜索图书 id、书名、作者名、出版社来实现,显示结果中需要包括书籍信息以及是否被借阅的情况; 2)图书的借阅:借阅图书…...
Kubernetes 集群到 Jumpserver
以下是使用 ServiceAccount Token(令牌) 连接 Kubernetes 集群到 Jumpserver 的 详细分步指南,包括权限配置、Token 获取和常见问题排查。 1. 创建 ServiceAccount 并分配权限 1.1 创建 ServiceAccount 在 Kubernetes 集群中创建一个专用于…...
Open SSL 3.0相关知识以及源码流程分析
Open SSL 3.0相关知识以及源码流程分析 编译 windows环境编译1、工具安装 安装安装perl脚本解释器、安装nasm汇编器(添加到环境变量)、Visual Studio编译工具 安装dmake ppm install dmake # 需要过墙2、开始编译 # 1、找到Visual Studio命令行编译工具目录 或者菜单栏直接…...

【QT】使用QT帮助手册找控件样式
选择帮助—》输入stylesheet(小写)—》选择stylesheet—》右侧选择Qt Style Sheets Reference 2.使用CtrlF—》输入要搜索的控件—》点击Customizing QScrollBar 3.显示参考样式表–》即可放入QT-designer的样式表中...
k8s热更新-subPath 不支持热更新
文章目录 k8s热更新-subPath 不支持热更新背景subPath 不支持热更新1. 为什么 subPath 不支持热更新?2. 挂载整个目录为何支持热更新?使用demo举例:挂载整个目录(不使用 subPath) k8s热更新-subPath 不支持热更新 背景…...

性能优化 - 案例篇:缓存_Guava#LoadingCache设计
文章目录 Pre引言1. 缓存基本概念2. Guava 的 LoadingCache2.1 引入依赖与初始化2.2 手动 put 与自动加载(CacheLoader)2.2.1 示例代码 2.3 缓存移除与监听(invalidate removalListener) 3. 缓存回收策略3.1 基于容量的回收&…...

学习日记-day21-6.3
完成目标: 目录 知识点: 1.集合_哈希表存储过程说明 2.集合_哈希表源码查看 3.集合_哈希表无索引&哈希表有序无序详解 4.集合_TreeSet和TreeMap 5.集合_Hashtable和Vector&Vector源码分析 6.集合_Properties属性集 7.集合_集合嵌套 8.…...