Skip to content

Instantly share code, notes, and snippets.

@steinybot
Last active February 2, 2018 00:00
Show Gist options
  • Save steinybot/8c3986dd15112c7811a14bc001650042 to your computer and use it in GitHub Desktop.
Save steinybot/8c3986dd15112c7811a14bc001650042 to your computer and use it in GitHub Desktop.
Understanding Slick Projections
case class Inner(a: String, b: Int)
case class Outer(a: String, i: Inner)
class InnerTable(tag: Tag) extends Table[Inner](tag, "inner") {
type UnpackedA = String
type UnpackedB = Int
type PackedA = Rep[UnpackedA]
type PackedB = Rep[UnpackedB]
type PackedAB = (PackedA, PackedB)
type UnpackedAB = (UnpackedA, UnpackedB)
type PackedAShape = Shape[FlatShapeLevel, PackedA, UnpackedA, PackedA]
type PackedBShape = Shape[FlatShapeLevel, PackedB, UnpackedB, PackedB]
type PackedABShape = Shape[FlatShapeLevel, PackedAB, UnpackedAB, PackedAB]
type ShapedABValue = ShapedValue[PackedAB, UnpackedAB]
type ColumnAType = BaseTypedType[UnpackedA]
type ColumnBType = BaseTypedType[UnpackedB]
type ProjectionAB = MappedProjection[Inner, UnpackedAB]
type ProjectionABShape = Shape[FlatShapeLevel, ProjectionAB, Inner, ProjectionAB]
def a: PackedA = column[UnpackedA]("a")
def b: PackedB = column[UnpackedB]("b")
def construct(u: UnpackedAB): Inner = Inner.tupled(u)
def deconstruct(v: Inner): Option[UnpackedAB] = Inner.unapply(v)
override def * : ProvenShape[Inner] = {
val columnAType: ColumnAType = stringColumnType
val columnBType: ColumnBType = intColumnType
val columnAShape: PackedAShape = Shape.repColumnShape[UnpackedA, FlatShapeLevel](columnAType)
val columnBShape: PackedBShape = Shape.repColumnShape[UnpackedB, FlatShapeLevel](columnBType)
val tupleABShape: PackedABShape = Shape.tuple2Shape[FlatShapeLevel, PackedA, PackedB, UnpackedA, UnpackedB, PackedA, PackedB](columnAShape, columnBShape)
val shapedABTuple: ShapedABValue = anyToShapedValue[PackedAB, UnpackedAB]((a, b))(tupleABShape)
val innerProjection: ProjectionAB = shapedABTuple.<>[Inner](construct, deconstruct)
val innerProjectionShape: ProjectionABShape = Shape.mappedProjectionShape[FlatShapeLevel, Inner, UnpackedAB]
ProvenShape.proveShapeOf[ProjectionAB, Inner](innerProjection)(innerProjectionShape)
// (a, b) <> (Inner.tupled, Inner.unapply)
}
}
class OuterTable(tag: Tag) extends Table[Outer](tag, "outer") {
type UnpackedA = String
type UnpackedB = Int
type PackedA = Rep[UnpackedA]
type PackedB = Rep[UnpackedB]
type PackedAB = (PackedA, PackedB)
type UnpackedAB = (UnpackedA, UnpackedB)
type MixedAI = (UnpackedA, Inner)
type PackedAShape = Shape[FlatShapeLevel, PackedA, UnpackedA, PackedA]
type PackedBShape = Shape[FlatShapeLevel, PackedB, UnpackedB, PackedB]
type PackedABShape = Shape[FlatShapeLevel, PackedAB, UnpackedAB, PackedAB]
type ShapedABValue = ShapedValue[PackedAB, UnpackedAB]
type ShapedMixedAIValue = ShapedValue[(PackedA, ProjectionAB), MixedAI]
type ColumnAType = BaseTypedType[UnpackedA]
type ColumnBType = BaseTypedType[UnpackedB]
type ProjectionAB = MappedProjection[Inner, UnpackedAB]
type ProjectionMixedAI = MappedProjection[Outer, MixedAI]
type ProjectionMixedAIShape = Shape[FlatShapeLevel, ProjectionMixedAI, Outer, ProjectionMixedAI]
def a: PackedA = column[UnpackedA]("a")
def ia: PackedA = column[UnpackedA]("ia")
def ib: PackedB = column[UnpackedB]("ib")
def constructInner(u: UnpackedAB): Inner = Inner.tupled(u)
def deconstructInner(v: Inner): Option[UnpackedAB] = Inner.unapply(v)
def constructOuter(u: MixedAI): Outer = Outer.tupled(u)
def deconstructOuter(v: Outer): Option[MixedAI] = Outer.unapply(v)
override def * : ProvenShape[Outer] = {
val columnAType: ColumnAType = stringColumnType
val columnBType: ColumnBType = intColumnType
val columnAShape: PackedAShape = Shape.repColumnShape[UnpackedA, FlatShapeLevel](columnAType)
val columnBShape: PackedBShape = Shape.repColumnShape[UnpackedB, FlatShapeLevel](columnBType)
val tupleABShape: PackedABShape = Shape.tuple2Shape[FlatShapeLevel, PackedA, PackedB, UnpackedA, UnpackedB, PackedA, PackedB](columnAShape, columnBShape)
val shapedABTuple: ShapedABValue = anyToShapedValue[PackedAB, UnpackedAB]((a, ib))(tupleABShape)
val innerProjection: ProjectionAB = shapedABTuple.<>[Inner](constructInner, deconstructInner)
val shapedMixedAITuple: ShapedMixedAIValue = anyToShapedValue((a, innerProjection))
val outerMixedProjection: ProjectionMixedAI = shapedMixedAITuple.<>[Outer](constructOuter, deconstructOuter)
val outerMixedProjectionShape: ProjectionMixedAIShape = Shape.mappedProjectionShape[FlatShapeLevel, Outer, MixedAI]
ProvenShape.proveShapeOf[ProjectionMixedAI, Outer](outerMixedProjection)(outerMixedProjectionShape)
// val i = (ia, ib) <> (constructInner, deconstructInner)
// (a, i) <> (constructOuter, deconstructOuter)
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment