openGauss源码学习--SQL解析模块_openguass语法解析模块-程序员宅基地

技术标签: opengauss  database  数据库  sql  

openGauss源码解析 ------ SQL语句解析模块

一、概述

openGauss数据库是华为深度融合在数据库领域多年经验,结合企业级场景要求推出的新一代企业级开源数据库。openGauss是关系型数据库,采用客户端/服务器,单进程多线程架构;支持单机和一主多备部署方式,同时支持备机可读、双机高可用等特性。

openGauss是基于postgresql数据库开发的。

开源地址:openGauss/openGauss-server - 码云 - 开源中国 (gitee.com)

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-E04FEZAL-1638896992737)(https://gitee.com/zhao-xiaohei/picture/blob/master/typora-user-images/image-20210409231723572.png#pic_center)]

二、SQL解析

数据库的SQL引擎作为SQL解析模块是数据库重要的子系统之一,它对上负责承接应用程序发送的SQL语句,对下负责指挥执行器运行执行计划,是整个数据库的第一个执行的模块。具体而言,就是讲用户输入的SQL语句转换为具体的能被机器识别的要求从而被执行,类似与各种编程语言的编译器。

完整过程:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-TyFPGrao-1638896418555)(https://raw.githubusercontent.com/2627020811/picture-bed/main/img/202112062329674.png)]

本文主要讲解前两部分:词法解析和语法解析。

源码文件夹:/src/common/backend/parser

三、SQL解析总体功能
  1. 当openGauss的后台服务进程openGuass收到前台发来的查询语句后,首先将其传递到查询分析模块,进行词法分析,语法分析和语义分析。
  2. 若是功能性命令(例如create table,create user和backup命令等)则将其分配到功能性命令处理模块;
  3. 对于查询处理命令(SELECT/INSERT/DELETE/UPDATE)则为其构建查询语法树,交给查询重写模块。

总的来说流程如下:

SQL命令 --(词法和语法分析)–> 分析树 --(语义分析)–> 查询树

在代码里的调用路径如下(方框内为函数,数字显示了调用顺序)

img

四、源码文件及作用:
parser.cpp 解析主程序
scan.l 词法分析,分解查询成token
scansup.cpp 处理查询语句转义符
kwlookup.cpp 将关键词转化为具体的token
keywords.cpp 标准关键词列表
analyze.cpp 语义分析
gram.y 语法分析,解析查询tokens并产生原始解析树
parse_agg.cpp 处理聚集操作,比如SUM(col1),AVG(col2)
parse_clause.cpp 处理子句,比如WHERE,ORDER BY
parse_compatibility.cpp 处理数据库兼容语法和特性支持
parse_coerce.cpp 处理表达式数据类型强制转换
parse_collate.cpp 对完成表达式添加校对信息
parse_cte.cpp 处理公共表格表达式(WITH 子句)
parse_expr.cpp 处理表达式,比如col, col+3, x = 3
parse_func.cpp 处理函数,table.column和列标识符
parse_node.cpp 对各种结构创建解析节点
parse_oper.cpp 处理表达式中的操作符
parse_param.cpp 处理参数
parse_relation.cpp 支持表和列的关系处理程序
parse_target.cpp 处理查询解析的结果列表
parse_type.cpp 处理数据类型
parse_utilcmd.cpp 处理实用命令的解析分析
五、词法解析部分

对于字符串流的输入,根据词表,将关键字、变量等转化成自定义逻辑结构,用于下一步的语法分析

分为三部分:定义段、规则段、用户程序段

  • 定义段:

    这一部分一般是一些声明及选项设置等;

    C语言的注释、头文件包含等一般就放在%{%}之间,这一部分的内容会被直接复制到生成的C文件中,还有一些参数项通过%option来设置;

    采用正则表达式定义词法规范;

    只有符合规范的关键词才允许接受,否则报错。

  • 规则段:

    规则段为一系列匹配模式和动作,模式一般使用正则表达式书写,动作部分为C代码;

    规则段模板:

    模式1

    {

    动作1 (C代码)

    }

    在输入和模式1匹配的时候,执行动作部分的代码

  • 用户程序段:

    用户自定义的程序,无固定模式·

六、词法解析代码举例
定义段:

头文件、宏定义等:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-UzC3cTx1-1638896418556)(https://raw.githubusercontent.com/2627020811/picture-bed/main/img/202112062329560.png)]

%option 此部分是Flex(词法工具)支持的一些参数,通过%option 来设置

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-FmdCpjiN-1638896418557)(https://raw.githubusercontent.com/2627020811/picture-bed/main/img/202112062329566.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-cDfP1f5E-1638896418557)(https://raw.githubusercontent.com/2627020811/picture-bed/main/img/202112062329567.png)]

%option reentrant 可重入词法分析器:传统词法分析器只能一次处理一个输入流,所以很多变量都定义的为静态变量这样分析器才能记住上次分析的地方继而可以继续分析。但是不能同时处理多个输入流。为了解决这个问题引入了可重入词法分析器。通过参数reentrant来控制。

%option bison-bridge :bison桥模式

bison的发展和flex的发展沟通并不是很密切,导致二者对yyles的调用参数不一致。所以在flex中提拱了桥模式,如果按%option bison-bridge做了声明,那么在flex中yylex将被声明为int yylex(YYSTYPE* lvalp, yyscan_t scaninfo),这样就兼容了bison。

其它的读者可自行搜索。

词法规则制定:采用正则表达式规定可接受的字符组合

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-yp33ZK06-1638896418558)(https://raw.githubusercontent.com/2627020811/picture-bed/main/img/202112062329563.png)]

规则段:

表示匹配到了某字符组合该执行什么动作:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-eAMZWAuZ-1638896418558)(https://raw.githubusercontent.com/2627020811/picture-bed/main/img/202112062338336.png)]

七、语法解析部分:

以词法分析器生成的单词符号序列作为输入,根据语言的语法规则识别出各种语法成分(如表达式、语句、程序段乃至整个程序等),并在分析过程中进行语法检查,检查所给单词符号序列是否是该语言的文法的一个句子。

同样分为三段,定义段,规则段和代码段。也是通过%%做三个段的分割。源码文件为gram.y, 最后通过Bison 编译源文件生成 gram.c

  • 定义段:{% … %}中的代码将被原样copy到生成的文件gram.c中.其中包含头文件包含,结构体定义和函数声明等,与词法分析一致
  • 规则段:主要是文法产生式,规定规约的规则,对于输入的SQL语句只要能规约到文法产生式顶层非终结符,则判断该SQL语句是语法合法的。在规约过程中顺便构建起语法分析树,为后面的语义分析做铺垫。

总体流程

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-9fXdhGEB-1638896418559)(https://raw.githubusercontent.com/2627020811/picture-bed/main/img/202112062329422.png)]

具体流程

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ScfxDqeW-1638896418560)(https://raw.githubusercontent.com/2627020811/picture-bed/main/img/202112062338372.png)]

八、语法解析代码举例:
定义段:

基本设置:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-dBtHOqX3-1638896418560)(https://raw.githubusercontent.com/2627020811/picture-bed/main/img/202112062330459.png)]

%pure-parser 声明此语法分析器是纯语法分析器。这样可以实现可重入。

%expect 0 ,意思是期待0个冲突。即不希望有任何冲突出现。

%name-prefix=“base_yy” 代表生成的函数和变量名从yy改成base_yy,同flex,为了在一个产品里使用多个语法分析器,分析不同的数据类。

%locations 声明使用位置信息。

union表示联合体:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-7yuKn08c-1638896418561)(https://raw.githubusercontent.com/2627020811/picture-bed/main/img/202112062330697.png)]

%union{} 定义yylval类型,在flex中通过yylval的返回匹配的值。

type表示非终结符:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-8UruGni5-1638896418561)(https://raw.githubusercontent.com/2627020811/picture-bed/main/img/202112062330915.png)]

非终结符用于文法产生式,为生成语法分析树服务

优先级定义:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-MQztCG6V-1638896418562)(https://raw.githubusercontent.com/2627020811/picture-bed/main/img/202112062336148.png)]

优先级和左右结合的定义可以解决一些语法上的矛盾。

具体文法产生式:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-G1UqjH18-1638896418562)(https://raw.githubusercontent.com/2627020811/picture-bed/main/img/202112062330167.png)]

Opengauss总的文法产生式极其复杂,这里只节选。

九、具体案例

SQL语句:

INSERT INTO films (code, title, did, date_prod, kind) VALUES (‘T_601’, ‘Yojimbo’, 106, ‘1961-06-16’, 'Drama’);

产生的函数调用:

PostgresMain->exec_simple_query->pg_parse_query->raw_parser->base_yyparse(yyscanner)

词法匹配(SCAN.I):

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Xl1P8svC-1638896418562)(https://raw.githubusercontent.com/2627020811/picture-bed/main/img/202112062336727.png)]

Identifier可以匹配到insert。

根据规则执行动作:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-F9nLgsrX-1638896418563)(https://raw.githubusercontent.com/2627020811/picture-bed/main/img/202112062330571.png)]

代码中keywordopengauss内置的关键字,像insert就是一个关键字keyword。

可以看到一个判断是keyword非空即检测到关键字时,根据关键字不同类型执行动作。

在yylex返回INSERT 这个token.然后分析gram.y中这个token 对应的规则 由于flex 默认向前查看一个token, 根据第二部可知第二个token 为INTO.在规则段中找到如下规则:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-a5DuFrCA-1638896418563)(https://raw.githubusercontent.com/2627020811/picture-bed/main/img/202112062337925.png)]

opt_with_clause 可以为空,并且后面跟着一个INSERT INTO, 所以即匹配上这个规则。

类似上面方法继续分析剩下的SQL语句

结果放到InsertStmt中,后面继续根据以下规则做规约处理,由于在规则段中第一个出现的非终结符号,stmtblock是我们要的结果。通过不断的规约即reduce,最后的分析结果即剩下stmtblock这一个符号即开始符号,所以是匹配成功的。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-LEyXJ2v9-1638896418564)(https://raw.githubusercontent.com/2627020811/picture-bed/main/img/202112062330015.png)]

ith_clause 可以为空,并且后面跟着一个INSERT INTO, 所以即匹配上这个规则。

类似上面方法继续分析剩下的SQL语句

结果放到InsertStmt中,后面继续根据以下规则做规约处理,由于在规则段中第一个出现的非终结符号,stmtblock是我们要的结果。通过不断的规约即reduce,最后的分析结果即剩下stmtblock这一个符号即开始符号,所以是匹配成功的。

[外链图片转存中…(img-LEyXJ2v9-1638896418564)]

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/weixin_44125904/article/details/121782236

智能推荐

数据库视图作用?什么时候用视图?_哪种情况更适合建立视图-程序员宅基地

文章浏览阅读2w次,点赞6次,收藏37次。刚工作时候第一次看到接触到视图,感觉很不能理解,我当时就在想为什么要用视图呢?明明可以关联表查出来数据的,为什么又单独创建一个视图查询数据呢?工作久了我有以下几点心得分享给大家.1.安全性 因为视图是虚拟的,物理上是不存在的,只是存储了数据的集合,视图中数据是根据基表的更新而更新,用户不可以更改/删除视图。2.方便,简化数据操作当我们业务需求要查出多张表的数据,这时我们可能会关联多张表查询处理.如..._哪种情况更适合建立视图

Anaconda介绍及常用命令总结_anaconda csdn-程序员宅基地

文章浏览阅读643次,点赞4次,收藏6次。Anaconda的安装及基本概念Anaconda中通过conda进行python包的管理Anaconda中通过conda进行虚拟环境的管理为形成良好的编程习惯,为每一个项目单独创建一个虚拟环境对开发来说至关重要。这一习惯即使对非数据data项目(如Web App)也能十分有效的帮助管理开发环境。_anaconda csdn

第25回 准确报告软件缺陷_描述缺陷发生的可能性的是-程序员宅基地

文章浏览阅读6.4k次。 软件缺陷的描述是是软件缺陷报告的基础部分,也是测试人员就一个软件问题与开发小组交流的最初且最好的机会。一个好的描述,需要使用简单的、准确的、专业的语言来抓住缺陷的本质。否则,它就会使信息含糊不清,可能会误导开发人员。准确报告软件缺陷是非常重要的,因为: 清晰准确的软件缺陷描述可以减少软件缺陷从开发人员返回的数量 提高软件缺陷修复的速度,使每一个小组能够有效的_描述缺陷发生的可能性的是

signature=77a5bffa142f96901b9bf201769a775d,tibot/yarn.lock at 79fb61111b881d3a2fc858eadda5bf250a2475...-程序员宅基地

文章浏览阅读6.6k次。# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.# yarn lockfile v1accepts@~1.3.5, accepts@~1.3.7:version "1.3.7"resolved "https://registry.yarnpkg.com/accepts/-/accepts-1.3.7.tgz#531bc..._hsck735.cc

使用jQuery1.10时复选框全选/取消全选的问题-程序员宅基地

文章浏览阅读205次。今天在使用jQuery1.10实现网页复选框全选和取消全选时遇到了如下问题,使用jQuery的attr方法获取和设置复选框的"checked"属性,发现第一次全选/取消全选有效,之后就无效了,但查看html源文件,复选框属性确实已经被更新了,就是UI没有更新,问题代码如下:<script type="text/javascript">$(functio..._jquery版本引起全选 取消全选失效

docker查询被占用端口的进程_docker tcp6的端口查看进程-程序员宅基地

文章浏览阅读3.1k次,点赞3次,收藏4次。使用idea停止docker容器时经常出现端口未释放的问题,重新启动提示端口被占用查询占用该端口的进程netstat -ntulp | grep 8089杀死该进程kill -9 15449重新启动容器即可dockers restart container_id_docker tcp6的端口查看进程

随便推点

android 清楚app缓存数据,android 获取其他应用程序的缓存大小以及清理应用缓存...-程序员宅基地

文章浏览阅读1k次。最近在做appStore时,涉及到一个第三方app下载视频后将车机存储撑爆的问题,从而影响到我们车机自带的app使用,问题很是严重,于是就需要提供缓存清理以及垃圾清理的功能,当用户使用第三方app时,存储空间达到一定量的时候会提示用户去清理,否则不允许使用第三方app。缓存获取获取各个应用程序的缓存大小,可以通过使用PackageManager.getPackageSizeInfo方法来获取,但是..._android packageinstaller缓存数据很大

vue给对象动态添加属性和值_vue3 键值对动态添加与获取-程序员宅基地

文章浏览阅读1.8w次。vue给对象动态添加属性和值一、背景介绍:在vue中请求接口中,一个请求方法可能对应后台两个请求接口,所以请求参数就会有所不同。需要我们先设置共同的参数,然后根据条件动态添加参数属性。二、案例let that = this; let params = { "type":that.addQueTab..._vue3 键值对动态添加与获取

解决keil:error C132: : not in formal parameter list等等突然出现很多很多报错_main.c(34): error c132: 'lcd1602_busycheck': not i-程序员宅基地

文章浏览阅读3.1w次,点赞55次,收藏16次。http://www.51hei.com/bbs/dpj-25003-1.html这里参考了这个帖子,在我身上发生的问题就是我在声明一个函数的时候忘记加分号了,会报错特别多奇奇怪怪的东西,吓死我了。解决办法就是加上分号就好了..._main.c(34): error c132: 'lcd1602_busycheck': not in formal parameter list

android adjustresize 设置大小,Android中adjustResize失效的解决办法之一-程序员宅基地

文章浏览阅读1.2k次。今天帮助哥们解决了一个比较蛋疼的问题,就是在有的情况下会出现设置activity的windowSoftInputMode="adjustResize"时,会失效的情况。历尽千辛万苦,终于在stackflow上找到解决方法。在activity的根布局上添加fitsSystemWindows="true".然后adjustResize就可以成功的起作用了。但是在这种情况下,你的titlebar会下移s..._adjustresize

消息自定义_c++ lersult-程序员宅基地

文章浏览阅读139次。// 消息自定义// 1、#defien WM_MSG WM_USER// 2、.h文件中添加事件: afx_msg LERSULT OnFun(WPARAM wparam, LPARAM lparam);// 3、宏定义消息路由: ON_MESSAGE(WM_MSG, OnFun)_c++ lersult

【原】移动web页面给用户发送邮件的方法 (邮件含文本、图片、链接)_前端静态网页无需后台发送邮件留言的方式-程序员宅基地

文章浏览阅读1.8k次。微信商户通有这么一个需求,用户打开H5页面后,引导用户到电脑下载设计资源包,由于各种内部原因,被告知无后台资源支持,自己折腾了一段时间找了下面2个办法,简单做下笔记。使用mailto功能,让用户自己给自己发送一份包含资源包的下载链接 调用QQ邮件分享功能,让用户自己给自己发送一份包含资源包的下载链接mailto使用方法1、基础写法当浏览者点击这个链接时,浏览器会自动调用默认的客户端电子邮件程序,并在收件人框中自动填上收件人的地址下面<a href="mailto:xxx@fo_前端静态网页无需后台发送邮件留言的方式