zoukankan      html  css  js  c++  java
  • slick源码阅读笔记三 ShapedValue在Table和Query上的应用

    转载请注明出处
    https://www.cnblogs.com/elyw/p/10294453.html

    目录

    slick源码阅读笔记 目录&总览

    slick源码阅读笔记一 slick.ast

    slick源码阅读笔记二 slick.lifted.Rep

    slick源码阅读笔记三 ShapedValue 在Table和Query上的应用

    slick源码阅读笔记四 隐式转换--column与Query查询功能实现

    slick源码阅读笔记五 Query查询条件生成与OptionMapper

    1. ShapedValue

    1.1. ShapedValue 和 TypedRep对比

    # TypedRep 使用Type描述Rep表示的数据类型,实现数据库类型到scala类型的映射,为scala和Node提供了沟通的桥梁。
    
    # ShapedValue 使用Shape来描述ShapedValue由哪些更基础数据组成,可以是其他的Rep也可以是其他的数据类型。  而ShapedValue本身也是Rep,可以使用encodeRef方法将shape上下文传递给其他的Node。
    
    # ShapedValue 还提供了类型转换功能,下文会详细说明。
    

    1.2 Shape

    Shape之于ShapedValue, 类似于 Type之于TypedRep。

    • Type是对数据库类型的描述,以及Type描述的数据于scala类之间的映射关系。
    • shape则描述了该Rep是由哪些更基础的类型组成。

    注意:实际上Shape的能力更加通用, 不过这里着重于Shape在Query上的使用,不会深入探讨其在生成sql和sql参数绑定上的应用(后面可能会写一篇博客专门讲这个问题)。

    1.2.1 Shape的继承树

    1.2.2 Shape的核心功能

    Shape的核心方法

     /** 
      * [打包数据:Packed]:  (Column[Int], Column[(Int, String)], (Column[Int], Column[Option[Double]]))
      * [未打包数据:Unpacked]: (Int, (Int, String), (Int, Option[Double]))
      * [混合数据:Mixed]:混合了未打包和已打包的数据
      * 例如:  (Column[Int], Column[(Int, String)], (Int, Option[Double]))
      * 
      */
    
      /**  将混合的数据打包成带有类型上下文的数据 */
      def pack(value: Mixed): Packed
    
      /** 将Shape转化为不允许[混合数据]的Shape */
      def packedShape: Shape[Level, Packed, Unpacked, Packed]
    
      /** 
       *  生成一个包含 sql 参数,以及生成具体参数方法的 Packed类型对象
       *  compiler 会用Packed来生成sql 语句中的参数,  然后用 extract来生成具体的数据做参数绑定
       */
      def buildParams(extract: Any => Unpacked): Packed
    
      /** 
       * 将value的上下文传递给 path
       *  这里虽然写着Mixed,不过实际上都是 Packed (Mixed 和Packed类型相同,参照packedShape方法)
       */
      def encodeRef(value: Mixed, path: Node): Any
    
      /** 将Mixed转化为Node,  实际使用过程中都是Packed (Mixed 和Packed类型相同,参照packedShape方法) */
      def toNode(value: Mixed): Node
    

    1.2.3 ProductNodeShape

    ProductNodeShape 是一种嵌套Shape, 用来描述复杂的数据结构 Tuple, case class,根据实际情况还会嵌套附带其他上下文

    1.2.4 RepShape

    用来描述slick.lifted.Rep及其子类的 Shape

    /**
     * 核心方法只有两个
     * 1. 更新抽象语法树时,通过encodeRef将旧的上下文传递给更新后的语法树
     * 2. 从shapedValue中直接获取抽象语法树
     */
    def encodeRef(value: Mixed, path: Node) = value.encodeRef(path)
    def toNode(value: Mixed): Node = value.toNode
    

    1.2.5 primitiveShape

    数据库原子类型Shape, 用来描述Literal。

    例如: select 1 中的 1
    

    1.2.6 unitShape

    专门用来描述 scala的Unit类型

    1.2.7 ProvenShapeShape

    专门用来描述 select * 中的 号,select查询全部列时将号展开为实际的列

    1.3 ShapedValue 在Query中的应用

    lazy val shaped = {
        /** 
         * 每个Node要对应一个自己的Rep, Table也是Rep的一种,所以新的Node都要对应产生新Table对象
         * Node包含在Tag中,因此每个Tag都要产生新的Table对象
         * 
         * cons 是Table工厂, 每次调用cons会产生一个新的Table对象 
         * 
         * 这个设计给笔者的感觉不是很好, 因为他把用在内部的Tag的概念暴露出去了, 不懂内部实现的使用者会一脸懵逼
         */
        val baseTable = cons(new BaseTag { base =>
          def taggedAs(path: Node): AbstractTable[_] = cons(new RefTag(path) {
            def taggedAs(path: Node) = base.taggedAs(path) //直接使用base.tageAs,避免递归后方法深度越来越深
          })
        })
    
        /**
         * 通过Table对象以及该Table对应的Shape 生成ShapedValue
         * Packed 指定为 Table
         * Unpacked 指定为 Table对应的Row的 case class, 不过没什么用因为RepShape不支持buildParams
         * 所以这里的ShapedValue主要是Query在做各种操作的时候将Table上附带的上下文信息传递给更新后的抽象语法树
         */
        ShapedValue(baseTable, RepShape[FlatShapeLevel, E, E#TableElementType])
      }
    
  • 相关阅读:
    oracle安装常见问题
    VM EXSI安装使用
    虚拟机---无法获取所有权
    Http常用状态码
    翻译:CommonJS的wiki
    如何在ie6/ie7/ie8中实现iframe背景透明
    网页版俄罗斯方块
    HTML5之pushstate、popstate操作history,无刷新改变当前url
    我们是如何做好前端工程化和静态资源管理
    dns-prefetch—DNS预解析技术
  • 原文地址:https://www.cnblogs.com/elyw/p/10294453.html
Copyright © 2011-2022 走看看