背景

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 cUSING 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 $$
DECLAREid int;i1 int := 1;i2 int := 2;
BEGINEXECUTE 'SELECT sum(i) FROM u1tbl WHERE i >= $1 AND i <= $2'INTO idUSING 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;elseyyerror("syntax error");}$$ = (PLpgSQL_stmt *)new;};

SELECT sum(i) FROM u1tbl WHERE i >= $1 AND i <= $2’

Postgresql动态执行EXECUTING语法解析过程相关推荐

  1. 「三」浏览器中CSS 语法解析过程

    CSS 语法解析过程 1.在浏览器系列文章中,今天终点讲下CSS解析这块内容.我们已知浏览器的渲染流程中HTML Parser会生成 DOM树,而 CSS Parser会将解析结果附加到 DOM 树上 ...

  2. oracle 动态执行ddl语句,Oracle过程中执行动态SQL或DDL语句

    如果你用的是 Oracle 8i 及以上的版本,那简单,在过程中用 execute immediate sql_str 就行, sql_str 是一个拼凑的 SQL 语句, 如果你用的是 Oracle ...

  3. 内核级python:编译器的词法和语法解析基本原理

    python在收到代码内容后,首先要启动两个流程,分别为词法解析和语法解析.看过我编译原理课程的同学对这两个流程应该不陌生.词法解析其实就是把代码里面不同的元素分别归类,例如234,1.35,1e3等 ...

  4. mysql查询解析过程_MySQL查询执行过程详解

    查询是用户通过设置某些查询条件,从表或其他查询中选取全部或者部分数据,以表的形式显示数据供用户浏览.查询是一个独立的.功能强大的.具有计算功能和条件检索功能的数据库对象.MySQL数据库中,MySQL ...

  5. 【原创】大数据基础之Hive(2)Hive SQL执行过程之SQL解析过程

    Hive SQL解析过程 SQL->AST(Abstract Syntax Tree)->Task(MapRedTask,FetchTask)->QueryPlan(Task集合)- ...

  6. Android 8.0 学习(12)---init.rc语法及解析过程总结

    Android 8.0 init.rc语法及解析过程总结       Android O高通默认使用QMMI取代了fastmmi,但是由于QMMI是一个APK,属于Android应用层面,所以必须等到 ...

  7. mysql ddl 语法解析工具_sharding-sphere之语法解析器

    语法解析器,根据不同类型的语句有不同的语法解析器去解析成成SQLStatement,SQL解析器的类图我用脑图画出来如下: SQLParser.png 可以看到,不同的sql有不同的处理解析器去解析, ...

  8. python动态运行py代码_Python 动态执行

    Python 动态执行 2015-06-16 Tuesday 在 Python 中,允许通过 exec 和 eval 执行以字符串形式表示的代码片段,这体现了动态语言的特性,可以让代码变得更灵活.实际 ...

  9. sqlparser mysql_SQL语法解析器JSQLParser | IT瘾

    相关 [sql 语法 解析器] 推荐: SQL 语法解释器jsqlparser. 是用java 开发的解析器, 可以生成java类层次结构.. 可以完美解析 表的 增删查改等操作.. 展开它的源码你会 ...

  10. oracle 测试sql执行时间_通过错误的SQL来测试推理SQL的解析过程

    这是学习笔记的第 1977 篇文章 如果抛出一个问题,你是如何理解MySQL解析器的,它和Oracle解析器有什么差别?相信大多数同学都会比较迷茫,因为这个问题很难验证,要不是看源码,要不就是查看书上 ...

最新文章

  1. Unix shell 编程相关命令
  2. Makefile文件生成
  3. python定义函数计算斐波那契公式前20的项_Python3算法之二:斐波那契函数
  4. PHP学习笔记六【方法-递归】
  5. mfc 改变tab快捷键对控件的顺序
  6. php写简单的随机验证码
  7. No field gDefault in class Landroid/app/ActivityManagerNative
  8. kindeditor图片上传
  9. Ubuntu18.04创建新的系统用户
  10. freebsd mount linprocfs
  11. 设计模式(3)——装饰者模式
  12. redux-saga源码解析
  13. 汇编:1位16进制数到ASCII码转换
  14. 无标度网络的C++代码实现
  15. 微信小程序uniapp实现小图标转成SVN代码
  16. oracle分析函数结构,oracle之分析函数解析及其应用场景
  17. Nucleus SE RTOS 初始化和启动
  18. 中国计算机展望未来,作文:展望未来中国的2025
  19. 计算机网络 如何算 子网号,计算机网络的划分以及主机号子网号的计算方法
  20. 华为 Python:初级能力测评

热门文章

  1. 语音识别 卷积神经网络,卷积神经网络字符识别
  2. python除法运算定律有哪些_小学数学最重要的7个运算定律,都在这里了
  3. 计算机硬件 系统安装维护教程 02安装基础篇-02:MBR与GPT、分区、活动分区
  4. 2021牛客多校9.F.Train Wreck 构造
  5. 创新电影院意在传播中华民族优秀传统文化
  6. 博观约取,厚积薄发,聊一聊最近读完的几本书,太上头了~
  7. 任正非:不要在微信里消耗你的人生和青春
  8. 如何破解域管理员密码
  9. tas5424_TAS5424 Datasheet(数据表) 16 Page - Texas Instruments
  10. ubuntu16如何开wifi