当前位置:网站首页>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’
边栏推荐
- 每日三题 6.28
- 2022年R1快开门式压力容器操作考题及答案
- Behind sharing e-commerce: the spirit of CO creation, symbiosis, sharing, CO prosperity and win-win
- Redis数据类型和应用场景
- Yoga27 multidimensional all-in-one computer with excellent appearance and high-end configuration
- 2022 R1 fast opening pressure vessel operation test questions and answers
- mysql ---- Oracle中的rownum转换成MySQL
- 【微服务|Sentinel】@SentinelResource详解
- Matplotlib common settings
- Paramètres communs de matplotlib
猜你喜欢
![Jielizhi Bluetooth headset quality control and production skills [chapter]](/img/3e/571d246d211a979e948dae1de56e93.png)
Jielizhi Bluetooth headset quality control and production skills [chapter]

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

SWT/ANR问题--SWT 导致 kernel fuse deadlock

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

Aaai22 | structural tagging and interaction modeling: a "slim" network for graph classification

Istio、eBPF 和 RSocket Broker:深入研究服务网格

MySQL binlog cleanup

Yunxin small class | common cognitive misunderstandings in IM and audio and video

2022安全员-C证考试题模拟考试题库及模拟考试

众昂矿业:发展以氟化工为主的特色化工产业具有先天优势
随机推荐
微服务服务稳定性治理
ShanDong Multi-University Training #3
2022 crane driver (limited to bridge crane) examination questions and simulation examination
[micro service sentinel] sentinelresourceaspect details
Create Ca and issue certificate through go language
Redis数据类型和应用场景
Compare the version number [double pointer to intercept the string you want]
2022 examination questions and online simulation examination for safety management personnel of hazardous chemical business units
Commemorate becoming the first dayus200 tripartite demo contributor
[applet] realize the left and right [sliding] list through the scroll view component
物联网开发零基础教程
Aaai22 | structural tagging and interaction modeling: a "slim" network for graph classification
SWT / anr problem - SWT causes kernel fuse deadlock
软件架构的本质
建模和影视后期有什么关联?
证券开户选哪个证券公司比较好,哪个更安全
from pip._internal.cli.main import main ModuleNotFoundError: No module named ‘pip‘
Future trend and development of neural network Internet of things
Programming English vocabulary notebook
rviz打开后如何显示实时2D地图