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…...
攻防世界 misc题GFSJ1129-【您看我还有机会吗?】
1.工具:010editor、VMware(Ubuntu、binwalk)、在线 Brainfuck解密、CTF-Tools、ImageStrike、7zFM 2.解题: 方法一(最初的解法): 下载附件后,我们打开,发现有一张图片,点击后发现要密码,我发现没有任何密码的提示,怀疑是伪加密(由于篇幅较长,我后续会在写一篇…...
GME-Qwen2-VL-2B-Instruct效果扩展:多风格艺术画作的理解与情感分析展示
GME-Qwen2-VL-2B-Instruct效果扩展:多风格艺术画作的理解与情感分析展示 最近在玩一个挺有意思的视觉语言模型,叫GME-Qwen2-VL-2B-Instruct。它个头不大,但能力挺让人意外。我突发奇想,把它当成了一个“数字艺术评论员”…...
Fish-Speech-1.5 API调用教程:Python脚本批量生成语音
Fish-Speech-1.5 API调用教程:Python脚本批量生成语音 1. 为什么选择Fish-Speech-1.5进行批量语音生成 在日常工作中,我们经常遇到需要将大量文本转换为语音的场景。无论是为视频内容生成旁白,还是为电子书制作有声版本,传统的人…...
Xinference+tao-8k实战:快速构建文档相似度分析工具
Xinferencetao-8k实战:快速构建文档相似度分析工具 1. 从想法到工具:为什么你需要一个文档相似度分析器 想象一下这个场景:你手头有几百份技术文档、产品说明或者客户反馈,你想快速找出哪些文档在讨论同一个主题,或者…...
[特殊字符] Local Moondream2图文对话教程:详细步骤实现自定义问题提问
Local Moondream2图文对话教程:详细步骤实现自定义问题提问 1. 引言:让电脑拥有"眼睛"的智能工具 你是否曾经希望电脑能像人一样看懂图片,并且回答关于图片内容的问题?Local Moondream2就是这样一款神奇的工具&#x…...
别再手动打字了!用uniapp+百度语音识别,5分钟搞定语音转文字功能(附完整代码)
用UniApp百度语音识别实现高效语音转文字功能 在移动应用开发中,语音输入正逐渐成为提升用户体验的关键功能。想象一下,用户无需费力敲击虚拟键盘,只需轻按按钮说话,文字就能自动出现在输入框中——这种交互方式不仅自然流畅&…...
【TC3xx芯片】Endinit机制实战:从解锁到上锁的完整代码解析
1. TC3xx芯片Endinit机制的核心作用 在嵌入式系统开发中,寄存器保护是确保系统稳定性的关键机制。TC3xx系列芯片采用的Endinit(End of initialization)保护方案,就像给重要寄存器装了一把智能密码锁。想象一下,你家的保…...
Debian GNU/Linux12高效运维指南(网络配置、远程管理、软件更新与安全防护)
1. Debian GNU/Linux12网络配置实战 刚接触Debian GNU/Linux12的朋友们,网络配置可能是你们遇到的第一个挑战。别担心,我会用最直白的方式带你们搞定这个环节。网络配置就像给新房子拉网线,得先把基础线路接好,后续的上网、远程控…...
WeChatExporter:免费开源工具,轻松备份你的微信聊天记录到电脑
WeChatExporter:免费开源工具,轻松备份你的微信聊天记录到电脑 【免费下载链接】WeChatExporter 一个可以快速导出、查看你的微信聊天记录的工具 项目地址: https://gitcode.com/gh_mirrors/wec/WeChatExporter 你是否曾经担心过手机丢失、系统崩…...
Piping Server开发者指南:如何基于流传输构建自己的应用
Piping Server开发者指南:如何基于流传输构建自己的应用 【免费下载链接】piping-server Infinitely transfer between every device over pure HTTP with pipes or browsers 项目地址: https://gitcode.com/gh_mirrors/pi/piping-server Piping Server是一个…...
