当前位置:网站首页>Postgresql随手记(10)动态执行EXECUTING语法解析过程
Postgresql随手记(10)动态执行EXECUTING语法解析过程
2022-07-01 22:57:00 【mingjie73】
背景
Postgresql中PLPGSQL支持动态拼接SQL并执行:
https://www.postgresql.org/docs/current/plpgsql-statements.html#PLPGSQL-STATEMENTS-EXECUTING-DYN
例如:
EXECUTE 'SELECT count(*) FROM mytable WHERE inserted_by = $1 AND inserted <= $2'
INTO c
USING checked_user, checked_date;
本篇简单分析下EXECUTE执行流程。
测试case
drop table u1tbl;
create table u1tbl(i int);
insert into u1tbl values (1);
insert into u1tbl values (2);
insert into u1tbl values (3);
drop function f1();
CREATE OR REPLACE FUNCTION f1() RETURNS int AS $$
DECLARE
id int;
i1 int := 1;
i2 int := 2;
BEGIN
EXECUTE 'SELECT sum(i) FROM u1tbl WHERE i >= $1 AND i <= $2'
INTO id
USING i1, i2;
return id;
END;
$$ LANGUAGE plpgsql;
select f1();
postgres=# select f1();
f1
----
3
(1 row)
EXECUTE解析流程
EXECUTE 'SELECT sum(i) FROM u1tbl WHERE i >= $1 AND i <= $2' INTO id USING i1, i2;
1、第一次read_sql_construct中会调用多次lex把需要的SQL全部提取出来,实际情况是第一次lex后,会把EXECUTE后''内的所有文本拿出来,给出一个SCONST的token。
过程如下:
EXECUTE 'SELECT sum(i) FROM u1tbl WHERE i >= $1 AND i <= $2' INTO id USING i1, i2;
|--------------- SCONST -----------------| K_INTO K_USING
[pl_gram.y] stmt_dynexecute : K_EXECUTE read_sql_construct
[ scan.l] {xqstart} BEGIN(xq);
[ scan.l] <xq,xus>{xqinside} addlit(yytext, yyleng, yyscanner);
[ scan.l] <xb,xh,xq,xe,xus>{quote} BEGIN(xqs);
[ scan.l] <xqs><<EOF>> BEGIN(INITIAL); return SCONST;
[pl_gram.y]
2、后面在循环体里面的read_sql_construct会把USING后面的所有SQL或变量名读取出来,按,分隔。每一个SQL或变量记为一个expr作为链表挂在PLpgSQL_stmt_dynexecute->param后。
最后返回的PLpgSQL_stmt_dynexecute结构:
{
cmd_type = PLPGSQL_STMT_DYNEXECUTE,
lineno = 7,
stmtid = 1,
query = 0x1a3a328, <PLpgSQL_expr> 'SELECT sum(i) FROM u1tbl WHERE i >= $1 AND i <= $2'
into = true,
strict = false,
target = 0x1a3a490, <PLpgSQL_variable> dno=4 --> ((PLpgSQL_row*)plpgsql_Datums[4])
params = 0x1a3a600 List: <PLpgSQL_expr> <PLpgSQL_expr>
}
pl_gram.y相关源码
stmt_dynexecute : K_EXECUTE
{
PLpgSQL_stmt_dynexecute *new;
PLpgSQL_expr *expr;
int endtoken;
expr = read_sql_construct(K_INTO, K_USING, ';',
"INTO or USING or ;",
RAW_PARSE_PLPGSQL_EXPR,
true, true, true,
NULL, &endtoken);
new = palloc(sizeof(PLpgSQL_stmt_dynexecute));
new->cmd_type = PLPGSQL_STMT_DYNEXECUTE;
new->lineno = plpgsql_location_to_lineno(@1);
new->stmtid = ++plpgsql_curr_compile->nstatements;
new->query = expr;
new->into = false;
new->strict = false;
new->target = NULL;
new->params = NIL;
/*
* We loop to allow the INTO and USING clauses to
* appear in either order, since people easily get
* that wrong. This coding also prevents "INTO foo"
* from getting absorbed into a USING expression,
* which is *really* confusing.
*/
for (;;)
{
if (endtoken == K_INTO)
{
if (new->into) /* multiple INTO */
yyerror("syntax error");
new->into = true;
read_into_target(&new->target, &new->strict);
endtoken = yylex();
}
else if (endtoken == K_USING)
{
if (new->params) /* multiple USING */
yyerror("syntax error");
do
{
expr = read_sql_construct(',', ';', K_INTO,
", or ; or INTO",
RAW_PARSE_PLPGSQL_EXPR,
true, true, true,
NULL, &endtoken);
new->params = lappend(new->params, expr);
} while (endtoken == ',');
}
else if (endtoken == ';')
break;
else
yyerror("syntax error");
}
$$ = (PLpgSQL_stmt *)new;
}
;
SELECT sum(i) FROM u1tbl WHERE i >= $1 AND i <= $2’
边栏推荐
- MySQL binlog cleanup
- Why is PHP called hypertext preprocessor
- Linux foundation - centos7 offline installation of MySQL
- Redis~02 cache: how to ensure data consistency in MySQL and redis when updating data?
- Is it safe to choose mobile phone for stock trading account opening in Shanghai?
- 数字峰会人气火爆,城链科技引发新一轮商业变革
- Daily three questions 6.30 (2)
- 2022 examination questions and online simulation examination for safety management personnel of hazardous chemical business units
- from pip._internal.cli.main import main ModuleNotFoundError: No module named ‘pip‘
- 问题随记 —— file /usr/share/mysql/charsets/README from install of MySQL-server-5.1.73-1.glibc23.x86_64 c
猜你喜欢

2022年R1快开门式压力容器操作考题及答案

实在RPA:银行数字化,业务流程自动化“一小步”,贷款审核效率“一大步”

【微服务|Sentinel】sentinel整合openfeign

CKS CKA CKAD 将终端更改为远程桌面

from pip._ internal. cli. main import main ModuleNotFoundError: No module named ‘pip‘

2022 safety officer-c certificate examination question simulation examination question bank and simulation examination

神经网络物联网的发展趋势和未来方向

De PIP. Interne. CLI. Main Import main modulenotfounderror: No module named 'PIP'
![Jerry's records are powered by Vbat with a power supply voltage of 4.2V [chapter]](/img/3e/571d246d211a979e948dae1de56e93.png)
Jerry's records are powered by Vbat with a power supply voltage of 4.2V [chapter]

CKS CKA ckad change terminal to remote desktop
随机推荐
Which securities company is better and which is safer to open a securities account
Leetcode(34)——在排序数组中查找元素的第一个和最后一个位置
CADD course learning (3) -- target drug interaction
CKS CKA ckad change terminal to remote desktop
[micro service sentinel] sentinelresourceaspect details
赵福全:短期解决保供,长期要打造安全、高效有韧性的供应链
为什么PHP叫超文本预处理器
Programming English vocabulary notebook
日本购物网站的网络乞丐功能
STM32F030F4驱动TIM1637数码管芯片
共享电商的背后: 共创、共生、共享、共富,共赢的共富精神
【Swoole系列1】在Swoole的世界中,你将学习到什么?
win 10 mstsc连接 RemoteApp
神经网络物联网的发展趋势和未来方向
【小程序】通过scroll-view组件实现左右【滑动】列表
从第三次技术革命看企业应用三大开发趋势
Experience of practical learning of Silicon Valley products
众昂矿业:发展以氟化工为主的特色化工产业具有先天优势
[micro service sentinel] @sentinelresource details
Switch to software testing, knowing these four points is enough!