Question: 为何sql解析和高大上有关系?
Answer:因为数据库永远都是系统的核心,CRUD如此深入码农的内心。。。如果能把CRUD改造成高大上技术,如此不是造福嘛。。。

CRUD就是Create, Read, Update, Delete,转换成sql语句就是insert, select, update, delete

普通场景下,insert也就是一个insert了,没什么高深。。。
高并发场景下,insert就不是一个insert了,而是千千万万个insert。。。可以用到的技术有排队、分表、分区、分仓、缓存同步

普通场景下,select也就是一个select了,没什么高深。。。
高并发场景下,select就不是一个select了,而是千千万万,再千千万万个select。。。可以用到的技术有缓存、普通读写分离、深入读写分离、不锁、past锁、还有分表、分区、分仓。。。

你说这么多东西,是全部在一个sql中全部自动化掉好呢,还是让我们码农一个一个考虑,再一个一个写成代码逻辑的好?

肯定两种声音都有,还肯定有第三种声音。。。所以我还是照着我自己的思路来说吧,你们随便发挥想象。。。

我要让一个sql全部解决上面的效果,或者接近上面的效果

如何解决,那就是,以SELECT语句为例

  1. 解析SELECT语句
  2. 解析牵涉到的表、字段、主键
  3. 解析是否用到了自己扩展的dsl函数
  4. 找到相应表的分区函数
  5. 找到相应表的缓存配置
  6. 找到dsl函数对应的真实函数
  7. 其他

比如有2个SELECT语句:

  1. SELECT UserID, UserName, Age FROM Users WHERE UserID='某个guid'
  2. SELECT COUNT(1) FROM Users

很简单的两句sql,可是Users是个虚拟表,真实表有16个表:Users.[A-F], Users.[0-9],分表策略为根据主键ID的第一个字母来分表, 因此:

  • 第一句sql需要先解析where条件中UserID='guid'这个UserID是否为pkid,以及这个'guid'的值,然后根据guid的值调用分表策略函数得到相应的分表后缀,然后用类似下面这个sql来真实查询:SELECT UserID, UserName, Age FROM [Users.A] WHERE UserID='axxxxx-xxxxx-xxxx-xx'
  • 第二句sql其实是最终变成了16条sql来得到各个分表的count值,然后在程序中累加这些分表的count值

其他:

  • 其他类似缓存、队列、自定义的扩展函数,都类似于上可以得到解决。

由于只是个demo,所以没有实现上述全部功能,我们只说下关键原理、和代码。。。

我们用antlr来做词法解析、语法解析,然后再用tree walker把antlr解析出来的东西转换为我们要的数据结构,比如:SelectTerms, TableName, WhereClause, OrderByClause等

奥,我们还得写一个规则文件让Antlr吃进去,然后antlr就能调用tree walker生成我们要的数据结构了

(大家赶紧补下编译原理之类的基础知识以及ANTLR知识)

  1. grammar SelectSQL;
  2.  
  3. /*
  4. * Parser Rules
  5. */
  6.  
  7. compileUnit
  8. : start
  9. ;
  10.  
  11. /*
  12. * Lexer Rules
  13. */
  14.  
  15. WS
  16. : [ \t\n\r]+ -> skip
  17. ;
  18.  
  19. COMMA:',';
  20. SELECT: 'SELECT';
  21. STAR:'*';
  22. FROM:'FROM';
  23. WHERE:'WHERE';
  24. ORDERBY:'ORDER BY';
  25. DIRECTION:'ASC'|'DESC';
  26. CHAR: 'a'..'z'|'A'..'Z';
  27. NUM: ''..'';
  28. STRING:'\'' .*? '\'';
  29. LB:'(';
  30. RB:')';
  31. LBRACE:'[';
  32. RBRACE:']';
  33. CONDITIONS_OPERATOR
  34. :'AND'
  35. |'OR'
  36. ;
  37. CONDITION_OPERATOR
  38. :'='
  39. |'>'
  40. |'<'
  41. |'<>'
  42. |'!='
  43. |'>='
  44. |'<='
  45. ;
  46. FCOUNT:'COUNT';
  47.  
  48. start
  49. :statement_list
  50. ;
  51.  
  52. statement_list
  53. :statement statement*
  54. ;
  55.  
  56. statement
  57. :selectStatement
  58. ;
  59.  
  60. selectStatement
  61. :selectStmt fromStmt whereStmt? orderbyStmt?
  62. ;
  63.  
  64. selectStmt
  65. :SELECT columns
  66. ;
  67.  
  68. columns
  69. :column (COMMA column)*
  70. ;
  71.  
  72. column
  73. : identifier
  74. | LBRACE identifier RBRACE
  75. | functionStmt
  76. | STAR
  77. ;
  78.  
  79. functionStmt
  80. :function LB (parameters) RB
  81. ;
  82.  
  83. function
  84. :FCOUNT
  85. ;
  86.  
  87. parameters
  88. : parameter (COMMA parameter)*
  89. ;
  90.  
  91. parameter
  92. : identifier
  93. | integer
  94. | string
  95. | STAR
  96. ;
  97.  
  98. fromStmt
  99. :FROM table
  100. ;
  101.  
  102. table
  103. : identifier
  104. | LBRACE identifier RBRACE
  105. ;
  106.  
  107. whereStmt
  108. : WHERE conditions
  109. ;
  110.  
  111. conditions
  112. : condition (CONDITIONS_OPERATOR condition)*
  113. ;
  114.  
  115. condition
  116. :left CONDITION_OPERATOR right
  117. ;
  118.  
  119. left
  120. : parameter
  121. ;
  122.  
  123. right
  124. : parameter
  125. ;
  126.  
  127. orderbyStmt
  128. :ORDERBY sortStmt
  129. ;
  130.  
  131. sortStmt
  132. : sortCondition (COMMA sortCondition)*
  133. ;
  134.  
  135. sortCondition
  136. :sortColumn DIRECTION
  137. ;
  138.  
  139. sortColumn
  140. : identifier
  141. | LBRACE identifier RBRACE
  142. ;
  143.  
  144. identifier
  145. :CHAR (CHAR|NUM)*
  146. ;
  147. integer
  148. :NUM+
  149. ;
  150. string
  151. : STRING
  152. ;

真心呼唤广大开发人员深入编译原理之类的基础技术!

在eclipse中输入解析sql文本后,会被解析成tree

开源世界真强大啊,有yacc, flex, bison, antlr这些现成的解析工具。

我们先在eclipse中把规则测试通过后,再把这个.g4规则文件拷贝到我们的visual studio中,如下:

然后只要这个g4文件一保存,antlr的vs插件就会自动根据规则文件生成相关名称的词法解析类、文法解析类、以及我们即将要改写的TreeListener

SelectSQLBaseListener:就是antlr插件自动生成的抽象类,我们的改动都是基于这个类,来做override改写(针对规则的enter/exit)

EnterXXXXX/ExitXXXX: 对应规则文件中的规则名称,Enter/Exit代表进入规则以及离开规则之前的行为动作

demo控制台程序运行输出效果:

  1. 输入SQL:
  2.  
  3. SELECT * FROM users
  4. SELECT userId, userName FROM users
  5. SELECT COUNT(1) FROM users
  6. SELECT COUNT(*) FROM users
  7. SELECT userId, userName FROM users ORDER BY userName DESC
  8. SELECT userId, userName FROM users WHERE userId='' ORDER BY userName DESC
  9.  
  10. 输出SQL:
  11. select * from [users.0]
  12. select * from [users.1]
  13. select * from [users.2]
  14. select * from [users.3]
  15. select * from [users.4]
  16. select * from [users.5]
  17. select * from [users.6]
  18. select * from [users.7]
  19. select * from [users.8]
  20. select * from [users.9]
  21. select * from [users.a]
  22. select * from [users.b]
  23. select * from [users.c]
  24. select * from [users.d]
  25. select * from [users.e]
  26. select * from [users.f]
  27. select userId, userName from [users.0]
  28. select userId, userName from [users.1]
  29. select userId, userName from [users.2]
  30. select userId, userName from [users.3]
  31. select userId, userName from [users.4]
  32. select userId, userName from [users.5]
  33. select userId, userName from [users.6]
  34. select userId, userName from [users.7]
  35. select userId, userName from [users.8]
  36. select userId, userName from [users.9]
  37. select userId, userName from [users.a]
  38. select userId, userName from [users.b]
  39. select userId, userName from [users.c]
  40. select userId, userName from [users.d]
  41. select userId, userName from [users.e]
  42. select userId, userName from [users.f]
  43. select COUNT(1) from [users.0]
  44. select COUNT(1) from [users.1]
  45. select COUNT(1) from [users.2]
  46. select COUNT(1) from [users.3]
  47. select COUNT(1) from [users.4]
  48. select COUNT(1) from [users.5]
  49. select COUNT(1) from [users.6]
  50. select COUNT(1) from [users.7]
  51. select COUNT(1) from [users.8]
  52. select COUNT(1) from [users.9]
  53. select COUNT(1) from [users.a]
  54. select COUNT(1) from [users.b]
  55. select COUNT(1) from [users.c]
  56. select COUNT(1) from [users.d]
  57. select COUNT(1) from [users.e]
  58. select COUNT(1) from [users.f]
  59. select COUNT(*) from [users.0]
  60. select COUNT(*) from [users.1]
  61. select COUNT(*) from [users.2]
  62. select COUNT(*) from [users.3]
  63. select COUNT(*) from [users.4]
  64. select COUNT(*) from [users.5]
  65. select COUNT(*) from [users.6]
  66. select COUNT(*) from [users.7]
  67. select COUNT(*) from [users.8]
  68. select COUNT(*) from [users.9]
  69. select COUNT(*) from [users.a]
  70. select COUNT(*) from [users.b]
  71. select COUNT(*) from [users.c]
  72. select COUNT(*) from [users.d]
  73. select COUNT(*) from [users.e]
  74. select COUNT(*) from [users.f]
  75. select userId, userName from [users.0] order by userName DESC
  76. select userId, userName from [users.1] order by userName DESC
  77. select userId, userName from [users.2] order by userName DESC
  78. select userId, userName from [users.3] order by userName DESC
  79. select userId, userName from [users.4] order by userName DESC
  80. select userId, userName from [users.5] order by userName DESC
  81. select userId, userName from [users.6] order by userName DESC
  82. select userId, userName from [users.7] order by userName DESC
  83. select userId, userName from [users.8] order by userName DESC
  84. select userId, userName from [users.9] order by userName DESC
  85. select userId, userName from [users.a] order by userName DESC
  86. select userId, userName from [users.b] order by userName DESC
  87. select userId, userName from [users.c] order by userName DESC
  88. select userId, userName from [users.d] order by userName DESC
  89. select userId, userName from [users.e] order by userName DESC
  90. select userId, userName from [users.f] order by userName DESC
  91. select userId, userName from [users.0] WHERE userId='' order by userName DESC
  92. select userId, userName from [users.1] WHERE userId='' order by userName DESC
  93. select userId, userName from [users.2] WHERE userId='' order by userName DESC
  94. select userId, userName from [users.3] WHERE userId='' order by userName DESC
  95. select userId, userName from [users.4] WHERE userId='' order by userName DESC
  96. select userId, userName from [users.5] WHERE userId='' order by userName DESC
  97. select userId, userName from [users.6] WHERE userId='' order by userName DESC
  98. select userId, userName from [users.7] WHERE userId='' order by userName DESC
  99. select userId, userName from [users.8] WHERE userId='' order by userName DESC
  100. select userId, userName from [users.9] WHERE userId='' order by userName DESC
  101. select userId, userName from [users.a] WHERE userId='' order by userName DESC
  102. select userId, userName from [users.b] WHERE userId='' order by userName DESC
  103. select userId, userName from [users.c] WHERE userId='' order by userName DESC
  104. select userId, userName from [users.d] WHERE userId='' order by userName DESC
  105. select userId, userName from [users.e] WHERE userId='' order by userName DESC
  106. select userId, userName from [users.f] WHERE userId='' order by userName DESC

希望大家能对基础技术真正感兴趣,赶紧学习编译原理、antlr吧。

很抱歉没能提供详细原理说明,大家baidubaidu就都有了。

代码下载 http://files.cnblogs.com/files/aarond/SQLParser_Select.rar

高大上技术之sql解析的更多相关文章

  1. 步步深入:MySQL架构总览->查询执行流程->SQL解析顺序

    前言: 一直是想知道一条SQL语句是怎么被执行的,它执行的顺序是怎样的,然后查看总结各方资料,就有了下面这一篇博文了. 本文将从MySQL总体架构--->查询执行流程--->语句执行顺序来 ...

  2. SQL解析在美团的应用

    https://tech.meituan.com/SQL_parser_used_in_mtdp.html 数据库作为核心的基础组件,是需要重点保护的对象.任何一个线上的不慎操作,都有可能给数据库带来 ...

  3. MySQL架构总览->查询执行流程->SQL解析顺序

    Reference:  https://www.cnblogs.com/annsshadow/p/5037667.html 前言: 一直是想知道一条SQL语句是怎么被执行的,它执行的顺序是怎样的,然后 ...

  4. 转载:一文详解SQL解析与应用

    转载地址:http://www.elecfans.com/emb/20180618696111.html 数据库作为核心的基础组件,是需要重点保护的对象.任何一个线上的不慎操作,都有可能给数据库带来严 ...

  5. Spark SQL源码剖析(一)SQL解析框架Catalyst流程概述

    Spark SQL模块,主要就是处理跟SQL解析相关的一些内容,说得更通俗点就是怎么把一个SQL语句解析成Dataframe或者说RDD的任务.以Spark 2.4.3为例,Spark SQL这个大模 ...

  6. Oracle体系结构概述与SQL解析剖析

    Oracle服务器 是一个数据库管理系统,它提供了一种全面.开放.集成的方法来管理信息. Oracle服务器由Oracle数据库和Oracle实例组成. oracle数据库软件和Oracle数据库软件 ...

  7. Pisa-Proxy 之 SQL 解析实践

    SQL 语句解析是一个重要且复杂的技术,数据库流量相关的 SQL 审计.读写分离.分片等功能都依赖于 SQL 解析,而 Pisa-Proxy 作为 Database Mesh 理念的一个实践,对数据库 ...

  8. openGauss内核:SQL解析过程分析

    摘要:在传统数据库中SQL引擎一般指对用户输入的SQL语句进行解析.优化的软件模块.SQL的解析过程主要分为:词法.语法和语义分析. 本文分享自华为云社区< openGauss内核分析(三):S ...

  9. 如何实现一个SQL解析器

    ​作者:vivo 互联网搜索团队- Deng Jie 一.背景 随着技术的不断的发展,在大数据领域出现了越来越多的技术框架.而为了降低大数据的学习成本和难度,越来越多的大数据技术和应用开始支持SQL进 ...

随机推荐

  1. Windows 打印控件

    Windows窗体的PrintDocument组件用于设置一些属性,这些属性说明,在基于Windows的应用程序中要打印说明内容以及打印文档的能力,可将它与PrintDialog组件一起使用来控制文档 ...

  2. Jade之Interpolation

    Interpolation jade为不同的需求提供了一些特殊的操作符.详见Github = 将右边的值赋予左边,或者替换为右边变量的值. //- 赋值,js格式即可. - var title = & ...

  3. 删除xcode中的描述文件的路径

    打开Finder  commend + shift +g 进入文件夹  : ~/Library/MobileDevice/Provisioning Profiles  删除即可

  4. STL(1)

    这一篇因为游戏设计而写的,里面采用了STL,先借用一下,过段时间专项研究. 模板 模板就是一种通用化的类,同一种模板可以创建无数种具有共同特征的容器类型.首先需要指定基础类型,比如int ,char, ...

  5. UILabel和UIButton

    一.UILabel 1.UILabel:标签,主要用来显示文字. 创建步骤: (1)开辟空间并初始化(如果本类有初始化方法,使用自己的,否则,使用负父类的).   UILabel *textLabel ...

  6. iOS URL 编码

    一.iOS 中的NSURL编码 iOS 中,NSURL 的基本样式是 scheme://username:password@host:port/path?query#fragment RFC 1738 ...

  7. SQLSERVER拯救某个时间点被误删除的数据

    SQLSERVER拯救某个时间点被误删除的数据 转载自:http://blog.csdn.net/dba_huangzj/article/details/8491327 要拯救某个时间点被误删除的数据 ...

  8. php url rewrite

    1.检测Apache是否支持mod_rewrite 通过php提供的phpinfo()函数查看环境配置,通过Ctrl+F查找到“Loaded Modules”,其中列出了所有apache2handle ...

  9. MySQL中表名大小写问题

    在设计数据表时,有自己特有的规则:英文单词的首字母大写,比如表名User, Article, UserRole, 等等,这种办法使用得很顺手习惯,在以往使用的MS SQL Server.MS Acce ...

  10. 转:DataSet、DataTable、DataRow、DataColumn区别及使用实例

    DataSet 表示数据在内存中的缓存. 属性 Tables  获取包含在 DataSet 中的表的集合. ds.Tables["sjxx"] DataTable 表示内存中数据的 ...