zoukankan      html  css  js  c++  java
  • ANTLR实现的SQL解析器 OQL

    使用ANTLR写了个SQL解析器,这样ORM的基本功能就比较完整了。几天的时间比较仓促,所以对于最终目标,还只能算是个雏形。

    总体状况
    使用SQL解析器的主要优点:
    1. 基于解析之后的语法树提供用户操作接口,灵活性非常好,因为达到了对SQL每一部分的完整控制。
    2. 对数据库的适应性。
       首先可以采用标准SQL,以及部分封装好的特性(例如分页)、函数(例如主要数据库都支持的函数,但语法有一定差异的),使用一个适配器Dialect基于语法树进行翻译。这样能满足绝大部分用途。
       如果确实需要使用某数据库的特性,可能只需要修改语法描述文件就能实现,或者对语法树等作少量修改进行配合。
    3. 跟LINQ的比较。
       a. LINQ具备编译期检查,与VS整合的优点。
       b. 根据粗略的了解,感觉LINQ语法树操作起来比较繁琐。
       c. 自己完全把握住了整个解析过程,不会受LINQ语法和语法树的限制。
       d. 不了解LINQ语法树的开放性,即结构的稳定、兼容性。例如以后添加新的特性,是否会影响到语法树的结构?
       类似LINQ to Hinbernate一样,只将LINQ当作查询的输入,而使用自己的ORM实现持久化,中间的可控能力会比较强。虽然LINQ与OQL在功能上重合,只是各有优缺点而已,并且可以采用不错的结合点。

    目前的主要缺点:
    1. 基于SQL Server的语法。
    2. AST语法树看起来以及实现上不大流畅,表达式类体系结构理的不大清楚。
    3. 数据库Dialect的机制不好。

    以后的目标:
    1. 多数据库支持。
       不管是纯粹ORM操作,还是OQL或者SQL,都能由数据库dialect自动翻译。
    2. 语法: 基于标准DML语法,添加必要的特性。
       a. 分页,预计使用select distinct? range(start, end) column1, column2..这样的方式,由数据库dialect向各特定数据库SQL语法进行翻译。SQL Server 2000这种不完整支持的,由dialect辅助完成。
       b. 标准函数,常用的SQL 92标准函数应当都能向各个数据库进行翻译,还可以提取一些其它函数,主流数据库都支持且能够进行翻译的。
    3. 标准化Query Hints。
       目的是在OQL中提供一个性能调优的机会,针对主要Query Hints进行提取,由dialect翻译成各数据库特定语法。
    4. Object Query / 标准SQL Query功能。
       a. 不象Hibernate要求纯粹的对象模型,OQL使用DomainClass1 inner join DomainClass2 on ...这样的方式。缺点是对象模型的内部结构被暴露,但更具灵活性。以后考虑对对象模型的自动支持,也就是可以使用各种混合方式进行开发。还允许DomainClass和Database Table混合写在OQL中,用于满足类似many-to-many的关联表不会建立DomainClass,又不想用对象属性建立双向映射关系的情况。
       b. 程序先给出查询语句,OQL解析出语法树,基于语法树再动态修改,例如根据界面的选择添加查询条件、排序方式、需要的字段等。进一步,一些非必要的关联关系能够在运行时自动、动态确定。
       c. 基于语法树进行修改的灵活性,应当能够提供比较灵活的AOP功能,例如AOP方式的数据权限控制。

    下一步代办事项:
    1. 项目中将用户接口和必要的功能特性进行完善。
    2. 语法树结构的完善,表达式类体系的完善,数据库Dialect、O-R Mapping等与OQL结合的机制以及职责的梳理完善。
    3. 标准化,主流数据库Dialect。
    4. 语法优化(重点是解析性能)。

    目前语法大致描述:
    Statement: SelectStatement | UnionStatement | InsertStatement | UpdateStatement | DeleteStatement;
    SelectStatement: SelectClause FromClause? WhereClause? (GroupByClause Having?)? OrderByClause?;

    SelectClause: Columns+;
    Column: '*'? | Identifier '.*'
                 | Expressions Alias?
    //MathOperator为数学运算符,例如+, -, *, /, %
    Expressions: Expression (MathOperator Expression)*;
    //Identifier为字段/属性名,Constant为常量,包括系统变量例如@@identity之类以及字符串等
    //Case .. When 语句当作Function处理
    Expression: Identifier | Constant | UserVariable | Function | SelectStatement | UnionStatement;

    //Where子句采用较标准的运算语法树形式,类EBNF描述
    WhereClause: Condition;
    Condition: SubCondition ((AND ^ | OR ^) SubCondition)*
    SubCondition: '(' Condition ')' | Predicate;
    Predicate: Expressions (
            ComparisonOperator Expressions //ComparisonOperator为>, <=, !>, Like等比较运算符
            | IS NOT? NULL
            | IN '(' Expressions (',' Expressions)* ')'
            | BETWEEN Expressions AND Expressions
            | IN '(' (SelectStatement | UnionStatement) ')'
        ) |
        EXISTS '(' (SelectStatement | UnionStatement) ')';

    整体:

    090828114203.jpg
      

    Where子句:   
    090828114342.jpg
    Select子句:                                                        
    090828114217.jpg
    解析性能测试:
    下面这个SQL应该能够代表绝大部分普通查询情况,循环解析1000次,所用时间在480-600ms之间。其中{0}, {1}是在循环中替换为当前计数,使每次解析的SQL不一样。这样普通情况下,把解析后的语法树进行缓存已经没有太多必要。
    Select 12'ada {0} And >0""' As c1, (select 1), @UserNamecase when a=1 then 1 else 0 endsum(a) as Total
    From Sys_User a, Sys_Org b
    inner join Sys_Org_View c on c.Org_Id=b.Org_Id and (ccc={1})
    Where cast(a.User_Id as varchar)=b.User_Id or (a=and Total between 100 And 1000)
    Group bY a, b
    haViNg Total between 100 And 1000
    Order By a, DDD Desc, A asc
  • 相关阅读:
    [ACM_模拟] ZJUT 1155 爱乐大街的门牌号 (规律 长为n的含k个逆序数的最小字典序)
    [ACM_搜索] ZOJ 1103 || POJ 2415 Hike on a Graph (带条件移动3盘子到同一位置的最少步数 广搜)
    [ACM_动态规划] POJ 1050 To the Max ( 动态规划 二维 最大连续和 最大子矩阵)
    [ACM_搜索] POJ 1096 Space Station Shielding (搜索 + 洪泛算法Flood_Fill)
    [JAVA] java_实例 获得系统字体
    [JAVA] java仿windows 字体设置选项卡
    [JAVA] 一个可以编辑、编译、运行Java简单文件的记事本java实现
    [ACM_模拟] POJ 1094 Sorting It All Out (拓扑排序+Floyd算法 判断关系是否矛盾或统一)
    JS的数组相关知识
    JS的join方法
  • 原文地址:https://www.cnblogs.com/aquester/p/9891872.html
Copyright © 2011-2022 走看看