【说啥都队-喻诗媛个人总结】

说啥都队-喻诗媛个人总结

我是来自广西师范大学说啥都队伍的队员喻诗媛,从参赛开始至比赛结束我一直致力于SQL引擎中的查询解析部分的解读与赏析,即 parser 文件夹。比赛期间,围绕analyze.cpp、parser.cpp、parse_type.cpp等代码细节撰写了十余篇代码解读与赏析博客。

以下是我学习的一些总结
在这里插入图片描述在这里插入图片描述
在这里插入图片描述

SQL基本形式
SQL语句基本可以分解成下面7大块:

(5)SELECT (6)DISTINCT < select list > 
(1)FROM < table source > 
(2)WHERE < condition > 
(3)GROUP BY < group by list > 
(4)HAVING < having condition > 
(7) ORDER BY < order by list >
(一)词法分析:字符串分割

(1)Token分类

注释。
关键字(SELECT、CREATE)。
操作符(+、-、>=)。
开闭合标志((、CASE)。
占位符(?)。
空格。
引号包裹的文本、数字、字段。
方言语法(${variable})。

在词法分析阶段,我们的 Tokens 不需要关心关键词是什么,只要识别是不是关键词即可,只要切分即可。因此,在语法分析阶段,才辨别Token是什么关键词;涉及到语义处理时要考虑上下文。

(2)常见分词方法: 正则表达式分词
争对不同方言或Tokens,会有不同的分词函数。因此整体流程如下:

while (sqlStr) {
  //这里的函数每取一次 Token,都将取到的 Token 按长度丢掉,继续匹配剩下的字符串,直到字符串被切分完为止
  token = getTokenWhitespace(sqlStr, token) | getTokenBlockComment(sqlStr, token);
  sqlStr = sqlStr.substring(token.value.length);
  tokens.push(token);
}

/*
 * 使用普通的 strcmp() 比较进行二分搜索。
 */
low = keywords;
high = keywords + (num_keywords - 1);
while (low <= high) {    /* 二分搜索 */
    const ScanKeyword* middle = NULL;
    int difference;
    middle = low + (high - low) / 2;    /* 取关键词中值 */
    difference => strcmp(middle-name, word);
    if (difference == 0) {    /* 找到则返回 middle */
        return middle;
    } else if (difference < 0) {
        low = middle + 1;
    } else {
        high = middle - 1;
    }
}
return NULL;    /* 未找到则返回空值,说明该文本中不含关键词 */
(二)语法分析

分析器对词法分析器解析出来的单词(Token)序列在语法上是否满足SQL语法规则。
openGauss中定义了bison工具能够识别的语法文件gram.y,根据SQL语言的不同定义了一系列表达Statement的结构体(这些结构体通常以Stmt作为命名后缀),用来保存语法分析结果。以SELECT查询为例,它对应的Statement结构体如下。

typedef struct SelectStmt
{
	NodeTag		type;
	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;
(三)语义分析

在完成词法分析和语法分析后,parse_Ana lyze函数会根据语法树的类型,调用transformSelectStmt将parseTree改写为查询树。负责语义分析的是位于 analyze.cpp 下的 parse_analyze 函数。parse_analyze 会根据词法分析和语法分析得到的语法树,生成一个 ParseState 结构体用于记录语义分析的状态。ParseState 顾名思义-解析状态,保存了语义分析的状态信息,ParseState 结构体的具体定义如下:

struct ParseState {
    struct ParseState* parentParseState; /* 指向外层查询 */ 
    const char* p_sourcetext; /* 原始SQL命令 */
    List* p_rtable; /* 范围表 */
    List* p_joinexprs;  /* 连接表达式 */
    List* p_joinlist;  /* 连接项 */
    List* p_relnamespace; /* 表名集合 */
    List* p_varnamespace; /* 属性名集合 */
    bool  p_lateral_active;
    List* p_ctenamespace; /* 公共表达式名集合 */
    List* p_future_ctes; /* 不在p_ctenamespace中的公共表达式 */
    CommonTableExpr* p_parent_cte;
    List* p_windowdefs; /* WINDOW子句的原始定义 */
    int p_next_resno; /* 下一个分配给目标属性的资源号 */
    List* p_locking_clause; /* 原始的FOR UPDATE/FOR SHARE信息 */
    Node* p_value_substitute;
    bool p_hasAggs; /* 是否有聚集函数 */
    bool p_hasWindowFuncs; /* 是否有窗口函数 */
    bool p_hasSubLinks; /* 是否有子链接 */
    bool p_hasModifyingCTE; 
    bool p_is_insert; /* 是否为INSERT语句 */
    bool p_locked_from_parent;
    bool p_resolve_unknowns;
    bool p_hasSynonyms;
    Relation p_target_relation; /* 目标表 */
    RangeTblEntry* p_target_rangetblentry; /* 目标表在RangeTable对应的项 */
    ......
};

个人心得

此次比赛是我的一次难忘经历,极大地提升了我的学习分析能力。万事开头难,最开始比赛有点难以下手,不过经过调整静下心来阅读和学习,终于有所收获。收获很多,开心就行

相关博客链接

SQL引擎概览
openGauss:SQL引擎之查询解析中analyze.cpp解读
SQL引擎 - analyze.cpp分析
SQL引擎 - analyze.cpp分析(二)
SQL引擎 - analyze.cpp分析(三)
SQL引擎 - analyze.cpp分析(四)
SQL引擎 - parser.cpp分析
SQL引擎 - parser.cpp分析(二)
SQL引擎 - parse_type.cpp分析(一)
SQL引擎 - parse_type.cpp分析(二)
说啥都队-喻诗媛个人总结

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值