Skip to content

Commit

Permalink
Move simple Fast Path API up to RelationalProfile
Browse files Browse the repository at this point in the history
The old `JdbcFastPath` did not actually require JDBC because it relays
all calls to the specialized ResultConverters that it wraps. It is now
called `SimpleFastPathResultConverter` and it still requires a
`TypeMappingResultConverter` on top of a `ProductResultConverter` to
work but this has always been enforced at runtime (falling back to the
non-FastPath implementation in other cases) and is applicable outside of
`JdbcProfile` as well.
  • Loading branch information
szeiger committed Oct 2, 2015
1 parent d980dbb commit 3e29760
Show file tree
Hide file tree
Showing 5 changed files with 34 additions and 34 deletions.
5 changes: 1 addition & 4 deletions slick/src/main/scala/slick/driver/JdbcProfile.scala
@@ -1,7 +1,7 @@
package slick.driver

import slick.ast.TypeUtil.:@
import slick.relational.CompiledMapping
import slick.relational.{SimpleFastPathResultConverter, CompiledMapping}

import scala.collection.mutable.Builder
import scala.language.{implicitConversions, higherKinds}
Expand Down Expand Up @@ -46,12 +46,9 @@ trait JdbcProfile extends SqlProfile with JdbcActionComponent
}

trait API extends LowPriorityAPI with super.API with ImplicitColumnTypes {
type FastPath[T] = JdbcFastPath[T]
type SimpleDBIO[+R] = SimpleJdbcAction[R]
val SimpleDBIO = SimpleJdbcAction

implicit def jdbcFastPathExtensionMethods[T, P](mp: MappedProjection[T, P]) = new JdbcFastPathExtensionMethods[T, P](mp)

implicit def queryDeleteActionExtensionMethods[C[_]](q: Query[_ <: RelationalProfile#Table[_], _, C]): DeleteActionExtensionMethods =
createDeleteActionExtensionMethods(deleteCompiler.run(q.toNode).tree, ())
implicit def runnableCompiledDeleteActionExtensionMethods[RU, C[_]](c: RunnableCompiled[_ <: Query[_, _, C], C[RU]]): DeleteActionExtensionMethods =
Expand Down
Expand Up @@ -69,14 +69,6 @@ trait JdbcMappingCompilerComponent { driver: JdbcDriver =>
(CompiledStatement(ibr.sql, ibr, serverSide.nodeType).infer(), mapping.map(n => mappingCompiler.compileMapping(ib.transformMapping(n))))
}
}

class JdbcFastPathExtensionMethods[T, P](val mp: MappedProjection[T, P]) {
def fastPath(fpf: (TypeMappingResultConverter[JdbcResultConverterDomain, T, _] => JdbcFastPath[T])): MappedProjection[T, P] = mp.genericFastPath {
case tm @ TypeMappingResultConverter(_: ProductResultConverter[_, _], _, _) =>
fpf(tm.asInstanceOf[TypeMappingResultConverter[JdbcResultConverterDomain, T, _]])

}
}
}

trait JdbcResultConverterDomain extends ResultConverterDomain {
Expand Down
22 changes: 0 additions & 22 deletions slick/src/main/scala/slick/jdbc/JdbcResultConverter.scala
Expand Up @@ -76,25 +76,3 @@ class IsDefinedResultConverter[@specialized(Byte, Short, Int, Long, Char, Float,
def width = 1
override def getDumpInfo = super.getDumpInfo.copy(mainInfo = s"idx=$idx", attrInfo = ": " + ti)
}

/** A `ResultConverter` that simplifies the implementation of fast path
* converters for `JdbcProfile`. It always wraps a `TypeMappingResultConverter`
* on top of a `ProductResultConverter`, allowing direct access to the product
* elements. */
abstract class JdbcFastPath[T](protected[this] val rc: TypeMappingResultConverter[JdbcResultConverterDomain, T, _]) extends ResultConverter[JdbcResultConverterDomain, T] {
private[this] val ch = rc.child.asInstanceOf[ProductResultConverter[JdbcResultConverterDomain, _]].elementConverters
private[this] var idx = -1

/** Return the next specialized child `ResultConverter` for the specified type. */
protected[this] def next[C] = {
idx += 1
ch(idx).asInstanceOf[ResultConverter[JdbcResultConverterDomain, C]]
}

def read(pr: Reader) = rc.read(pr)
def update(value: T, pr: Updater) = rc.update(value, pr)
def set(value: T, pp: Writer) = rc.set(value, pp)

override def getDumpInfo = super.getDumpInfo.copy(name = "JdbcFastPath", mainInfo = "", children = Vector(("rc", rc)))
def width = rc.width
}
11 changes: 11 additions & 0 deletions slick/src/main/scala/slick/profile/RelationalProfile.scala
Expand Up @@ -24,6 +24,7 @@ trait RelationalProfile extends BasicProfile with RelationalTableComponent
override protected def computeCapabilities = super.computeCapabilities ++ RelationalProfile.capabilities.all

trait API extends super.API with ImplicitColumnTypes {
type FastPath[T] = SimpleFastPathResultConverter[ResultConverterDomain, T]
type Table[T] = driver.Table[T]
type Sequence[T] = driver.Sequence[T]
val Sequence = driver.Sequence
Expand All @@ -42,6 +43,8 @@ trait RelationalProfile extends BasicProfile with RelationalTableComponent
implicit def queryInsertActionExtensionMethods[U, C[_]](q: Query[_, U, C]) = createInsertActionExtensionMethods[U](compileInsert(q.toNode))

implicit def schemaActionExtensionMethods(sd: SchemaDescription): SchemaActionExtensionMethods = createSchemaActionExtensionMethods(sd)

implicit def fastPathExtensionMethods[T, P](mp: MappedProjection[T, P]): FastPathExtensionMethods[ResultConverterDomain, T, P] = new FastPathExtensionMethods[ResultConverterDomain, T, P](mp)
}

val api: API
Expand Down Expand Up @@ -72,6 +75,14 @@ trait RelationalProfile extends BasicProfile with RelationalTableComponent
/** Run a query synchronously on the provided session. This is used by DistributedDriver until we
* can make it fully asynchronous. */
def runSynchronousQuery[R](tree: Node, param: Any)(implicit session: Backend#Session): R

class FastPathExtensionMethods[M <: ResultConverterDomain, T, P](val mp: MappedProjection[T, P]) {
def fastPath(fpf: (TypeMappingResultConverter[M, T, _] => SimpleFastPathResultConverter[M, T])): MappedProjection[T, P] = mp.genericFastPath {
case tm @ TypeMappingResultConverter(_: ProductResultConverter[_, _], _, _) =>
fpf(tm.asInstanceOf[TypeMappingResultConverter[M, T, _]])

}
}
}

object RelationalProfile {
Expand Down
22 changes: 22 additions & 0 deletions slick/src/main/scala/slick/relational/ResultConverter.scala
Expand Up @@ -150,3 +150,25 @@ final case class OptionRebuildingResultConverter[M <: ResultConverterDomain, T](
def width = discriminator.width + data.width
override def getDumpInfo = super.getDumpInfo.copy(children = Vector(("discriminator", discriminator), ("data", data)))
}

/** A `ResultConverter` that simplifies the implementation of fast path
* converters. It always wraps a `TypeMappingResultConverter`
* on top of a `ProductResultConverter`, allowing direct access to the product
* elements. */
abstract class SimpleFastPathResultConverter[M <: ResultConverterDomain, T](protected[this] val rc: TypeMappingResultConverter[M, T, _]) extends ResultConverter[M, T] {
private[this] val ch = rc.child.asInstanceOf[ProductResultConverter[M, _]].elementConverters
private[this] var idx = -1

/** Return the next specialized child `ResultConverter` for the specified type. */
protected[this] def next[C] = {
idx += 1
ch(idx).asInstanceOf[ResultConverter[M, C]]
}

def read(pr: Reader) = rc.read(pr)
def update(value: T, pr: Updater) = rc.update(value, pr)
def set(value: T, pp: Writer) = rc.set(value, pp)

override def getDumpInfo = super.getDumpInfo.copy(name = "SimpleFastPathResultConverter", mainInfo = "", children = Vector(("rc", rc)))
def width = rc.width
}

0 comments on commit 3e29760

Please sign in to comment.