Skip to content
Permalink
Browse files

queryable: added .length with explicit execution

  • Loading branch information...
cvogt committed Jul 10, 2012
1 parent b178c71 commit bff0d0a15bca811e8637b6bf4f01819b29cfb76c
@@ -42,6 +42,20 @@ case class Utils[C <: Context]( c:C ) {
}

object QueryableMacros{
private def _scalar_helper[C <: Context]( c:C )( name:String ) = {
import c.universe._
//val element_type = implicitly[c.TypeTag[S]].tpe
val reifiedExpression = c.Expr[ru.Expr[Int]](
c.reifyTree( c.runtimeUniverse, EmptyTree, c.typeCheck(
Utils[c.type](c).removeDoubleReify(
Select(c.prefix.tree, newTermName( "_"+name+"_placeholder" ))
).asInstanceOf[Tree])))
c.reify{ new QueryableValue( reifiedExpression.splice ) } //new QueryableValue( reifiedExpression.splice )}
}
def length
(c: scala.reflect.makro.Context)
: c.Expr[QueryableValue[Int]] = _scalar_helper[c.type]( c )( "length" )

private def _helper[C <: Context,S:c.TypeTag]( c:C )( name:String, projection:c.Expr[_] ) = {
import c.universe._
//val element_type = implicitly[c.TypeTag[S]].tpe
@@ -75,9 +89,9 @@ class BoundQueryable[T]( backend : SlickBackend ){
}
*/

class Queryable[T](
val expr_or_typetag : Either[ ru.Expr[_], (ru.TypeTag[_],ClassTag[_]) ]
){
class QueryableValue[T]( val value : ru.Expr[T] )

class Queryable[T]( val expr_or_typetag : Either[ ru.Expr[_], (ru.TypeTag[_],ClassTag[_]) ] ){
def _map_placeholder[S]( projection: T => S ) : Queryable[S] = ???
def map[S]( projection: T => S ) : Queryable[S] = macro QueryableMacros.map[T,S]

@@ -87,4 +101,7 @@ class Queryable[T](
def _filter_placeholder( projection: T => Boolean ) : Queryable[T] = ???
def filter( projection: T => Boolean ) : Queryable[T] = macro QueryableMacros.filter[T]
def withFilter( projection: T => Boolean ) : Queryable[T] = macro QueryableMacros.filter[T]

def _length_placeholder[S] : Int = ???
def length : QueryableValue[Int] = macro QueryableMacros.length
}
@@ -241,7 +241,10 @@ class SlickBackend(driver:BasicDriver) extends QueryableBackend{
if package_.decoded == "scala" && class_.decoded.startsWith("Tuple") && method_.decoded == "apply" // FIXME: match smarter than matching strings
=>
sq.ProductNode( components.map(s2sq(_).node) )


case Select(scala_lhs, term)
if scala_lhs.tpe.erasure <:< typeOf[Queryable[_]].erasure && (term.decoded == "_length_placeholder" || term.decoded == "_size_placeholder")
=> sq.Pure( Library.CountAll( s2sq(scala_lhs).node ) )

case tree if tree.tpe.erasure <:< typeOf[Queryable[_]].erasure
=> toQuery( eval(tree).asInstanceOf[Queryable[_]] )
@@ -265,6 +268,11 @@ class SlickBackend(driver:BasicDriver) extends QueryableBackend{
val query = this.toQuery(queryable)
driver.compiler.run(query.node)
}

private def queryablevalue2cstate[R]( queryablevalue:QueryableValue[R] ) : CompilationState = {
val query = this.toQuery(queryablevalue.value.tree)
driver.compiler.run(query.node)
}

protected def resultByType( expectedType : Type, cl: ClassLoader, rs: PositionedResult )(implicit session:Session) : Any = {
val cm = runtimeMirror(cl)
@@ -290,9 +298,16 @@ class SlickBackend(driver:BasicDriver) extends QueryableBackend{
createInstance( args )
})
}

def result[R:TypeTag:ClassTag]( queryable:Queryable[R] )(implicit session:Session) = {
def result[R:TypeTag:ClassTag]( queryable:Queryable[R] )(implicit session:Session) : Vector[R] = {
val cstate = queryable2cstate( queryable )
result( cstate )
}
def result[R:TypeTag:ClassTag]( queryablevalue:QueryableValue[R] )(implicit session:Session) : R = {
val cstate = queryablevalue2cstate( queryablevalue )
val res = result( cstate )
res(0)
}
def result[R:TypeTag:ClassTag]( cstate:CompilationState )(implicit session:Session) : Vector[R] = {
val linearizer = new CollectionLinearizer[Vector,R]{
def elementLinearizer: ValueLinearizer[R] = new RecordLinearizer[R]{
def getResult(profile: BasicProfile, rs: PositionedResult): R
@@ -197,6 +197,11 @@ class QueryableTest(val tdb: TestDB) extends DBTest {
}
}

assert( resultsMatch(
query.flatMap(e1 => query.map(e2=>e1).map(e2=>e1)),
inMem.flatMap(e1 => inMem.map(e2=>e1).map(e2=>e1))
))

// nesting with outer macro reference
{
val inMemResult = for( o <- inMem; i <- inMem ) yield o.name
@@ -232,6 +237,9 @@ class QueryableTest(val tdb: TestDB) extends DBTest {
query.map( c=> (c.name,c.sales,c) ),
inMem.map( c=> (c.name,c.sales,c) )
))
// length
val l = backend.result(query.length)
assertEquals( l, inMem.length )
}
}
}

0 comments on commit bff0d0a

Please sign in to comment.
You can’t perform that action at this time.