Skip to content

Commit

Permalink
Create a TableExpansion when creating a TableNode.
Browse files Browse the repository at this point in the history
This way the expandTables phase is no longer needed. We can also remove
the expandOn function from TableNode and use the initial TableExpansion
everywhere.

TableNode and TableExpansion are still separate Nodes so we can remove
TableExpansions after flattening all projections.
  • Loading branch information
szeiger committed Aug 21, 2013
1 parent 697dc78 commit 29fc842
Show file tree
Hide file tree
Showing 9 changed files with 40 additions and 50 deletions.
1 change: 0 additions & 1 deletion slick-testkit/src/test/resources/logback-test.xml
Expand Up @@ -11,7 +11,6 @@
<logger name="scala.slick.compiler.QueryCompiler" level="${log.qcomp.phases:-inherited}" />
<logger name="scala.slick.compiler.Inline" level="${log.qcomp.inline:-inherited}" />
<logger name="scala.slick.compiler.AssignUniqueSymbols" level="${log.qcomp.assignUniqueSymbols:-inherited}" />
<logger name="scala.slick.compiler.ExpandTables" level="${log.qcomp.expandTables:-inherited}" />
<logger name="scala.slick.compiler.InferTypes" level="${log.qcomp.inferTypes:-inherited}" />
<logger name="scala.slick.compiler.CreateResultSetMapping" level="${log.qcomp.createResultSetMapping:-inherited}" />
<logger name="scala.slick.compiler.ForceOuterBinds" level="${log.qcomp.forceOuterBinds:-inherited}" />
Expand Down
2 changes: 1 addition & 1 deletion src/main/scala/scala/slick/ast/Node.scala
Expand Up @@ -533,7 +533,7 @@ object FwdPath {
}

/** A Node representing a database table. */
final case class TableNode(schemaName: Option[String], tableName: String, tableIdentitySymbol: TableIdentitySymbol, expandOn: Symbol => Node, driverTable: Any) extends NullaryNode with TypedNode {
final case class TableNode(schemaName: Option[String], tableName: String, tableIdentitySymbol: TableIdentitySymbol, driverTable: Any) extends NullaryNode with TypedNode {
type Self = TableNode
def tpe = CollectionType(CollectionTypeConstructor.default, NominalType(tableIdentitySymbol)(NoType))
def nodeRebuild = copy()
Expand Down
20 changes: 0 additions & 20 deletions src/main/scala/scala/slick/compiler/Columnizer.scala
Expand Up @@ -104,26 +104,6 @@ class ReplaceFieldSymbols extends Phase with ColumnizerUtils {
}
}

/** Replace all TableNodes with TableExpansions which contain both the
* expansion and the original table. */
class ExpandTables extends Phase {
val name = "expandTables"

def apply(state: CompilerState): CompilerState = state.map { n =>
ClientSideOp.mapServerSide(n)(ch => apply(ch, state))
}

def apply(n: Node, state: CompilerState): Node = n match {
case t: TableExpansion => t
case t: TableNode =>
val sym = new AnonSymbol
val expanded = t.expandOn(sym)
val processed = apply(state.compiler.runBefore(this, state.withNode(expanded)).tree, state)
TableExpansion(sym, t, ProductNode(processed.flattenProduct))
case n => n.nodeMapChildren(ch => apply(ch, state))
}
}

/** Expand Paths to ProductNodes and TableExpansions into ProductNodes of
* Paths and TableRefExpansions of Paths, so that all Paths point to
* individual columns by index. */
Expand Down
25 changes: 19 additions & 6 deletions src/main/scala/scala/slick/compiler/InsertCompiler.scala
Expand Up @@ -20,18 +20,31 @@ trait InsertCompiler extends Phase {
val rref = Ref(rgen)

var table: TableNode = null
var expansionRef: Symbol = null
val cols = new ArrayBuffer[Select]
def setTable(te: TableExpansion) {
val t = te.table.asInstanceOf[TableNode]
if(table eq null) {
table = t
expansionRef = te.generator
}
else if(table ne t) throw new SlickException("Cannot insert into more than one table at once")
}

def tr(n: Node): Node = n match {
case _: OptionApply | _: GetOrElse | _: ProductNode | _: TypeMapping => n.nodeMapChildren(tr, keepType = true)
case t: TableNode => tr(t.expandOn(t.nodeIntrinsicSymbol))
case sel @ Select(Ref(IntrinsicSymbol(t: TableNode)), fs: FieldSymbol) =>
if(table eq null) table = t
else if(table ne t) throw new SlickException("Cannot insert into more than one table at once")
case te @ TableExpansion(_, _, expansion) =>
setTable(te)
tr(expansion match {
case ProductNode(Seq(ch)) => ch
case n => n
})
case sel @ Select(Ref(s), fs: FieldSymbol) if s == expansionRef =>
cols += Select(tref, fs).nodeTyped(sel.nodeType)
Select(rref, ElementSymbol(cols.size)).nodeTyped(sel.nodeType)
case Bind(gen, t: TableNode, Pure(sel)) =>
tr(sel.replace({ case Ref(s) if s == gen => Ref(t.nodeIntrinsicSymbol) }, keepType = true))
case Bind(gen, te @ TableExpansion(_, t: TableNode, _), Pure(sel)) =>
setTable(te)
tr(sel.replace({ case Ref(s) if s == gen => Ref(expansionRef) }, keepType = true))
case _ => throw new SlickException("Cannot use node "+n+" for inserting data")
}
val tree2 = tr(tree)
Expand Down
2 changes: 0 additions & 2 deletions src/main/scala/scala/slick/compiler/QueryCompiler.scala
Expand Up @@ -65,7 +65,6 @@ object QueryCompiler {
Phase.inline,
Phase.assignUniqueSymbols,
// Distribute and normalize
Phase.expandTables,
Phase.inferTypes,
Phase.createResultSetMapping,
Phase.forceOuterBinds,
Expand Down Expand Up @@ -111,7 +110,6 @@ object Phase {
/** The standard phases of the query compiler */
val inline = new Inline
val assignUniqueSymbols = new AssignUniqueSymbols
val expandTables = new ExpandTables
val inferTypes = new InferTypes
val createResultSetMapping = new CreateResultSetMapping
val forceOuterBinds = new ForceOuterBinds
Expand Down
29 changes: 14 additions & 15 deletions src/main/scala/scala/slick/direct/SlickBackend.scala
Expand Up @@ -202,21 +202,20 @@ class SlickBackend( val driver: JdbcDriver, mapper:Mapper ) extends QueryableBac
def typetagToQuery(typetag:TypeTag[_]) : Query = {
def _fields = getConstructorArgs(typetag.tpe)
val tableName = mapper.typeToTable( typetag.tpe )
val table = sq.TableNode(None, tableName, sq.SimpleTableIdentitySymbol(driver, "_", tableName),
expandOn = { tableRef: sq.Symbol => sq.TypeMapping(
sq.ProductNode( _fields.map( fieldSym => columnSelect(fieldSym, sq.Ref(tableRef)) )),
v => throw new Exception("not implemented yet"),
v => cm.reflectClass( cm.classSymbol(cm.runtimeClass(typetag.tpe)) )
.reflectConstructor(
typetag.tpe.member( nme.CONSTRUCTOR ).asMethod
)( (v match {
case v:Vector[_] => v
case v:Product => v.productIterator.toVector
}):_* )
)},
driverTable = null
)
new Query( table, Scope() )
val table = sq.TableNode(None, tableName, sq.SimpleTableIdentitySymbol(driver, "_", tableName), null)
val tableRef = new sq.AnonSymbol
val tableExp = sq.TableExpansion(tableRef, table, sq.TypeMapping(
sq.ProductNode( _fields.map( fieldSym => columnSelect(fieldSym, sq.Ref(tableRef)) )),
v => throw new Exception("not implemented yet"),
v => cm.reflectClass( cm.classSymbol(cm.runtimeClass(typetag.tpe)) )
.reflectConstructor(
typetag.tpe.member( nme.CONSTRUCTOR ).asMethod
)( (v match {
case v:Vector[_] => v
case v:Product => v.productIterator.toVector
}):_* )
))
new Query( tableExp, Scope() )
}

def toQuery( tree:Tree, scope : Scope = Scope() ) : (Type,Query) = {
Expand Down
Expand Up @@ -459,7 +459,7 @@ trait JdbcStatementBuilderComponent { driver: JdbcDriver =>

/** Builder for various DDL statements. */
class TableDDLBuilder(val table: Table[_]) { self =>
protected val tableNode = table.toNode.asInstanceOf[TableNode]
protected val tableNode = table.toNode.asInstanceOf[TableExpansion].table.asInstanceOf[TableNode]
protected val columns: Iterable[ColumnDDLBuilder] = table.create_*.map(fs => createColumnDDLBuilder(fs, table))
protected val indexes: Iterable[Index] = table.indexes
protected val foreignKeys: Iterable[ForeignKey] = table.foreignKeys
Expand Down
7 changes: 4 additions & 3 deletions src/main/scala/scala/slick/lifted/AbstractTable.scala
Expand Up @@ -20,15 +20,16 @@ abstract class AbstractTable[T](val tableTag: Tag, val schemaName: Option[String

def tableIdentitySymbol: TableIdentitySymbol

lazy val tableNode: TableNode =
TableNode(schemaName, tableName, tableIdentitySymbol, { t => tableTag.taggedAs(List(t)).*.toNode }, this)
lazy val tableNode = TableNode(schemaName, tableName, tableIdentitySymbol, this)

def encodeRef(path: List[Symbol]) = tableTag.taggedAs(path).asInstanceOf[AbstractTable[T]]

def * : ProvenShape[T]

override def toNode = tableTag match {
case _: BaseTag => tableNode
case _: BaseTag =>
val sym = new AnonSymbol
TableExpansion(sym, tableNode, ProductNode(tableTag.taggedAs(List(sym)).*.toNode.flattenProduct))
case t: RefTag => Path(t.path)
}

Expand Down
2 changes: 1 addition & 1 deletion src/main/scala/scala/slick/lifted/Query.scala
Expand Up @@ -108,7 +108,7 @@ object Query extends Query[Column[Unit], Unit] {

def apply[E, U, R](value: E)(implicit unpack: Shape[E, U, R]): Query[R, U] = {
val unpackable = ShapedValue(value, unpack).packedValue
if(unpackable.toNode.isInstanceOf[TableNode])
if(unpackable.toNode.isInstanceOf[TableExpansion])
new NonWrappingQuery[R, U](unpackable.toNode, unpackable)
else new WrappingQuery[R, U](Pure(unpackable.toNode), unpackable)
}
Expand Down

0 comments on commit 29fc842

Please sign in to comment.