zoukankan      html  css  js  c++  java
  • 用scala实现一个sql执行引擎-(下)

    执行

    上一篇讲述了如何通过scala提供的内置DSL支持,实现一个可以解析sql的解析器,这篇讲如何拿到了解析结果-AST以后,如何在数据上进行操作,得到我们想要的结果。之前说到,为什么选择scala作为这个引擎的实现,之一是scala提供了方便的DSL实现支持,其二是因为作为一门函数式编程语言,scala提供了丰富对于集合操作的函数。此外,函数在scala中是一个独立的类型,所以能够把现有的函数进行组合,得到更为强大的函数(和上一篇提到的用解析组合子组合已有的解析器得到更强大的解析器一样)。

    首先,我们需要弄清楚普通sql语句的执行顺序一般来说,sql的书写顺序为

    • SELECT[DISTINCT]
    • FROM
    • WHERE
    • GROUP BY
    • HAVING
    • UNION
    • ORDER BY

    但是,执行顺序为

    • FROM
    • WHERE
    • GROUP BY
    • HAVING
    • SELECT
    • DISTINCT
    • UNION
    • ORDER BY

    本次实现的sql执行不支持join,所以省去了union部分,但是大致顺序差不多,如果把一个List<Map>想象成一个数据库的表,那么执行顺序可以用下图所示,图中标绿色的箭头表示可以并发执行,聚合函数的执行是不能并发的,但是因为已经把数据给分组了,故可以在更高的一个层次并发。

    了解了大致的执行流程,下面说一下各个流程执行所用到的函数。

    • where子句
      where子句的执行,利用了 filter函数,将不符合条件的数据给过滤掉。举个例子,下面这个段代码,将列表中的奇数给过滤掉。
      scala> val L = List(1,2,3,4,5,6)
      L: List[Int] = List(1, 2, 3, 4, 5, 6)
      scala> L filter(_%2==0)
      res2: List[Int] = List(2, 4, 6)

      对每个元素进行判断这个步骤其实是可以并发执行的,你只需要这样写,就能进行安全的并发操作。

      scala> L.par.filter(_%2==0).toList
      res4: List[Int] = List(2, 4, 6)

      在scala_sql引擎中,实现where的函数为

      def where(where: Option[SqlExpr]): Table = {
            where match {
              case None => table
              case Some(x: SqlExpr) => table filter (evalWhereEachRow(_, x))
            }
          }

      其中evalWhereEachRow(_,x)是另外一个函数,第一个参数是table中的一列,即一个Map对象,第二个参数是由sql解析得到的AST中,对应where子句的部分。

    • groupBy子句
      scala中也提供了对于集合的groupBy操作,接着上个例子
      scala> L groupBy(_%2)
      res6: scala.collection.immutable.Map[Int,List[Int]] = Map(1 -> List(1, 3, 5), 0 -> List(2, 4, 6))

      上面这个函数,把L这个list根据奇偶分组。
      在scala _sql引擎中,实现groupBy的函数为

       def evalGroupBy(table: Table, groupby: SqlGroupBy): Seq[Table] = {
          val keys: Seq[String] = groupby.keys map {
            case x: FieldIdent => x.name
          }
          table.groupBy(row => keys.map(row(_))).map(_._2).toSeq
        }

    结论

    DSL主要有两种,内部DSL和外部DSL,对于外部DSL,需要一个解析器来解析DSL的脚本,得到能够让程序处理的数据结构,这种数据结构通常是一种AST。实现需要的解析器,大体有两种方式:

    • 手工写一个,例如druid中的sql解析模块。
    • 利用ANTRL等解析生成器,通过编写语法规则,生成一个解析器。

    近年来随着函数式编程慢慢得到工业界的关注,利用parser combinator(解析组合子)的方式来编写解析器实现DSL也进入了大众视野。

  • 相关阅读:
    IOS开发关于测试的好的网址资源
    创建型模式--工厂模式
    在XcodeGhost事件之后,获取更纯净的Xcode的方法。
    算法积累:解决如何获取指定文件夹路径或者文件路径下所有子文件后缀为.h .m .c的文本的行数
    结构型模式--装饰模式
    设计模式 总揽 通过这篇随笔可以访问所需要了解的设计模式
    IOS之未解问题--关于IOS图像渲染CPU和GPU
    链接
    Matlab2014下载和破解方法,以及Matlab很好的学习网站
    苹果Mac隐藏壁纸在哪里?Mac隐藏壁纸查找教程
  • 原文地址:https://www.cnblogs.com/javanerd/p/4384070.html
Copyright © 2011-2022 走看看