sql日常分析(sql语句分析)

 网络   2022-11-08 05:00   28

正在传统数据库中SQL引擎普通指对于用户输入的SQL语句施行剖析、优化的软件模块

SQL的剖析历程主要分为:

词法分解Lexical Analysis:将用户输入的SQL语句拆解成单词(Token)序列,并判别出枢纽字、标识、常量等。语法分解Syntax Analysis:分解器对于词法分解器剖析进去的单词(Token)序列正在语法上是否满意SQL语律例则。语义分解Semantic Analysis:语义分解是SQL剖析历程的一个逻辑阶段,主要义务是正在语法正确的根底上施行左右文相关性子的检查,正在SQL剖析历程中该阶段告竣表名、操作符、类别等元素的合法性判别,同时检测语义上的二义性。

openGauss正在pg_parse_query中挪用raw_parser函数对于用户输入的SQL敕令施行词法分解以及语法分解,天生语法树推广到链表parsetree_list中。告竣语法分解后,对付parsetree_list中的每一颗语法树parsetree,会挪用parse_analyze函数施行语义分解,根据SQL敕令的分歧,施行对于应的出口函数,最平生成盘诘树

词法分解Lexical Analysis

openGauss利用flex器械施行词法分解。flex器械经过对于一经定义好的词法文件施行编译,天生词法分解的代码。词法文件是scan.l,它根据SQL语言规范对于SQL语言中的枢纽字、标识符、操作符、常量、告终符施行了定义以及判别。正在kwlist.h中定义了大度的枢纽字,根据字母的秩序罗列,麻烦正在查找枢纽字时经过二分法施行查找。正在scan.l中处置“标识符”时,会到枢纽字列表中施行匹配,假设一个标识符匹配到枢纽字,则以为是枢纽字,不然才是标识符,即枢纽字优先.以“select a, b from item”为例阐明词法分解了局

用户自身定义的名字、常量名、变量名以及历程名,若无括号化装则对于巨细写没有敏锐

语法分解Syntax Analysis

openGauss中定义了bison器械恐怕判别的语法文件gram.y,根据SQL语言的分歧定义了一系列表达Statement的组织体(这些组织体常常以Stmt算作定名后缀),用来遗失语法分解了局。以SELECT盘诘为例,它对于应的Statement组织体以下。

typedef struct SelectStmtNodeTagtype;List *distinctClause; /* NULL, list of DISTINCT ON exprs, or* lcons(NIL,NIL) for all (SELECT DISTINCT) */IntoClause *intoClause;/* target for SELECT INTO */List *targetList;/* the target list (of ResTarget) */List *fromClause;/* the FROM clause */Node *whereClause;/* WHERE qualification */List *groupClause;/* GROUP BY clauses */Node *havingClause;/* HAVING conditional-expression */List *windowClause;/* WINDOW window_name AS (...), ... */WithClause *withClause;/* WITH clause */List *valuesLists;/* untransformed list of expression lists */List *sortClause;/* sort clause (a list of SortBy's) */Node *limitOffset;/* # of result tuples to skip */Node *limitCount;/* # of result tuples to return */} SelectStmt;

这个组织体也许看作一个多叉树,每个叶子节点都表达了SELECT盘诘语句中的一个语法组织,对于应到gram.y中,它会有一个SelectStmt。代码以下:

从simple_select语法分解组织也许看出,一条简捷的盘诘语句由以下子句组成:去除行反复的distinctClause、目的属性targetList、SELECT INTO子句intoClause、FROM子句fromClause、WHERE子句whereClause、GROUP BY子句groupClause、HAVING子句havingClause、窗口儿句windowClause以及plan_hint子句。正在乐成匹配simple_select语法组织后,将会建立一个Statement组织体,将各个子句施行相映的赋值。对于simple_select而言,目的属性、FROM子句、WHERE子句是最主要的组成全体。SelectStmt与其他组织体的联系以下

上面以“select a, b from item”为例阐明简捷select语句的剖析历程,函数exec_simple_query挪用pg_parse_query施行剖析,剖析树中只要一个元素

(gdb) p *parsetree_list$47 = {type = T_List, length = 1, head = 0x7f5ff986c8f0, tail = 0x7f5ff986c8f0}

List中的节点类别为T_SelectStmt

(gdb) p *(Node *)(parsetree_list- head.data- ptr_value)$45 = {type = T_SelectStmt}

检察SelectStmt组织体,targetList 以及fromClause非空

(gdb) set $stmt = (SelectStmt *)(parsetree_list- head.data- ptr_value)(gdb) p *$stmt$50 = {type = T_SelectStmt, distinctClause = 0x0, intoClause = 0x0, targetList = 0x7f5ffa43d588, fromClause = 0x7f5ff986c888, startWithClause = 0x0, whereClause = 0x0, groupClause = 0x0,havingClause = 0x0, windowClause = 0x0, withClause = 0x0, valuesLists = 0x0, sortClause = 0x0, limitOffset = 0x0, limitCount = 0x0, lockingClause = 0x0, hintState = 0x0, op = SETOP_NONE, all = false,larg = 0x0, rarg = 0x0, hasPlus = false}

检察SelectStmt的targetlist,有两个ResTarget

(gdb) p *($stmt- targetList)$55 = {type = T_List, length = 2, head = 0x7f5ffa43d540, tail = 0x7f5ffa43d800}(gdb) p *(Node *)($stmt- targetList- head.data- ptr_value)$57 = {type = T_ResTarget}(gdb) set $restarget1=(ResTarget *)($stmt- targetList- head.data- ptr_value)(gdb) p *$restarget1$60 = {type = T_ResTarget, name = 0x0, indirection = 0x0, val = 0x7f5ffa43d378, location = 7}(gdb) p *$restarget1- val$63 = {type = T_ColumnRef}(gdb) p *(ColumnRef *)$restarget1- val$64 = {type = T_ColumnRef, fields = 0x7f5ffa43d470, prior = false, indnum = 0, location = 7}(gdb) p *((ColumnRef *)$restarget1- val)- fields$66 = {type = T_List, length = 1, head = 0x7f5ffa43d428, tail = 0x7f5ffa43d428}(gdb) p *(Node *)(((ColumnRef *)$restarget1- val)- fields)- head.data- ptr_value$67 = {type = T_String}(gdb) p *(Value *)(((ColumnRef *)$restarget1- val)- fields)- head.data- ptr_value$77 = {type = T_String, val = {ival = 140050197369648, str = 0x7f5ffa43d330 "a"}}

(gdb) set $restarget2=(ResTarget *)($stmt- targetList- tail.data- ptr_value)(gdb) p *$restarget2$89 = {type = T_ResTarget, name = 0x0, indirection = 0x0, val = 0x7f5ffa43d638, location = 10}(gdb) p *$restarget2- val$90 = {type = T_ColumnRef}(gdb) p *(ColumnRef *)$restarget2- val$91 = {type = T_ColumnRef, fields = 0x7f5ffa43d730, prior = false, indnum = 0, location = 10}(gdb) p *((ColumnRef *)$restarget2- val)- fields$92 = {type = T_List, length = 1, head = 0x7f5ffa43d6e8, tail = 0x7f5ffa43d6e8}(gdb) p *(Node *)(((ColumnRef *)$restarget2- val)- fields)- head.data- ptr_value$93 = {type = T_String}(gdb) p *(Value *)(((ColumnRef *)$restarget2- val)- fields)- head.data- ptr_value$94 = {type = T_String, val = {ival = 140050197370352, str = 0x7f5ffa43d5f0 "b"}}

sql日常分析(sql语句分析)

检察SelectStmt的fromClause,有一个RangeVar

(gdb) p *$stmt- fromClause$102 = {type = T_List, length = 1, head = 0x7f5ffa43dfe0, tail = 0x7f5ffa43dfe0}(gdb) set $fromclause=(RangeVar*)($stmt- fromClause- head.data- ptr_value)(gdb) p *$fromclause$103 = {type = T_RangeVar, catalogname = 0x0, schemaname = 0x0, relname = 0x7f5ffa43d848 "item", partitionname = 0x0, subpartitionname = 0x0, inhOpt = INH_DEFAULT, relpersistence = 112 'p', alias = 0x0,location = 17, ispartition = false, issubpartition = false, partitionKeyValuesList = 0x0, isbucket = false, buckets = 0x0, length = 0, foreignOid = 0, withVerExpr = false}

分析以上分解也许失去语法树组织

语义分解Semantic Analysis

正在告竣词法分解以及语法分解后,parse_analyze函数会根据语法树的类别,挪用transformSelectStmt将parseTree改写为盘诘树

(gdb) p *result$3 = {type = T_Query, commandType = CMD_SELECT, querySource = QSRC_ORIGINAL, queryId = 0, canSetTag = false, utilityStmt = 0x0, resultRelation = 0, hasAggs = false, hasWindowFuncs = false,hasSubLinks = false, hasDistinctOn = false, hasRecursive = false, hasModifyingCTE = false, hasForUpdate = false, hasRowSecurity = false, hasSynonyms = false, cteList = 0x0, rtable = 0x7f5ff5eb8c88,jointree = 0x7f5ff5eb9310, targetList = 0x7f5ff5eb9110,…}(gdb) p *result- targetList$13 = {type = T_List, length = 2, head = 0x7f5ff5eb90c8, tail = 0x7f5ff5eb92c8}(gdb) p *(Node *)(result- targetList- head.data- ptr_value)$8 = {type = T_TargetEntry}(gdb) p *(TargetEntry*)(result- targetList- head.data- ptr_value)$9 = {xpr = {type = T_TargetEntry, selec = 0}, expr = 0x7f5ff636ff48, resno = 1, resname = 0x7f5ff5caf330 "a", ressortgroupref = 0, resorigtbl = 24576, resorigcol = 1, resjunk = false}(gdb) p *(TargetEntry*)(result- targetList- tail.data- ptr_value)$10 = {xpr = {type = T_TargetEntry, selec = 0}, expr = 0x7f5ff5eb9178, resno = 2, resname = 0x7f5ff5caf5f0 "b", ressortgroupref = 0, resorigtbl = 24576, resorigcol = 2, resjunk = false}(gdb)

(gdb) p *result- rtable$14 = {type = T_List, length = 1, head = 0x7f5ff5eb8c40, tail = 0x7f5ff5eb8c40}(gdb) p *(Node *)(result- rtable- head.data- ptr_value)$15 = {type = T_RangeTblEntry}(gdb) p *(RangeTblEntry*)(result- rtable- head.data- ptr_value)$16 = {type = T_RangeTblEntry, rtekind = RTE_RELATION, relname = 0x7f5ff636efb0 "item", partAttrNum = 0x0, relid = 24576, partitionOid = 0, isContainPartition = false, subpartitionOid = 0……}

失去的盘诘树组织以下:

告竣词法、语法以及语义分解后,SQL剖析历程告竣,SQL引擎结束施行盘诘优化,鄙人一期中再全部分解。

本文地址:http://yz.ziyouea.com/p/57917.html
版权声明:本站文章来自网络,如有违规侵权请联系我们下架。