Skip to content

Commit

Permalink
Merge pull request #2084 from getquill/minor_quat_fixes_3
Browse files Browse the repository at this point in the history
Memoize Passed-By-Name Quats of Asts Ident, Entity, and Others
  • Loading branch information
deusaquilus committed Feb 15, 2021
2 parents 660d56f + 1263bb0 commit b358484
Show file tree
Hide file tree
Showing 4 changed files with 47 additions and 20 deletions.
42 changes: 30 additions & 12 deletions quill-core-portable/src/main/scala/io/getquill/ast/Ast.scala
Expand Up @@ -72,7 +72,9 @@ object BottomTypedTerminal {
* to `T_PERSON` or `Person`.
*/
class Entity(val name: String, val properties: List[PropertyAlias])(theQuat: => Quat.Product) extends Query {
def quat: Quat.Product = theQuat
private lazy val computedQuat = theQuat
def quat = computedQuat

private def id = Entity.Id(name, properties)
// Technically this should be part of the Entity case class but due to the limitations of how
// scala creates companion objects, the apply/unapply wouldn't be able to work correctly.
Expand Down Expand Up @@ -105,13 +107,12 @@ class Entity(val name: String, val properties: List[PropertyAlias])(theQuat: =>
// => (name -> (first -> theFirst, last -> theLast))
val groupedTailPaths = tailPaths.groupBy(_._1).map(kv => (kv._1, kv._2.map(r => r._2))).toList

lazy val quat: Quat.Product =
val newQuat =
groupedTailPaths.foldLeft(this.quat) {
case (quat, (renamePath, renames)) =>
quat.renameAtPath(renamePath, renames)
}

Entity.Opinionated(name, properties, quat, renameable)
Entity.Opinionated(name, properties, newQuat, renameable)
}
}

Expand Down Expand Up @@ -219,7 +220,9 @@ object Infix {
case class Function(params: List[Ident], body: Ast) extends Ast { def quat = body.quat }

class Ident(val name: String)(theQuat: => Quat) extends Terminal with Ast {
def quat: Quat = theQuat
private lazy val computedQuat = theQuat
def quat = computedQuat

private val id = Ident.Id(name)
def visibility: Visibility = Visibility.Visible

Expand All @@ -236,8 +239,9 @@ class Ident(val name: String)(theQuat: => Quat) extends Terminal with Ast {
}

// need to define a copy which will propogate current value of visibility into the copy
def copy(name: String = this.name, quat: => Quat = this.quat): Ident =
def copy(name: String = this.name, quat: => Quat = this.quat): Ident = {
Ident.Opinionated(name, quat, this.visibility)
}
}

/**
Expand Down Expand Up @@ -416,7 +420,9 @@ case class OptionTableForall(ast: Ast, alias: Ident, body: Ast)
extends OptionOperation { def quat = body.quat }
case object OptionNoneId
class OptionNone(theQuat: => Quat) extends OptionOperation with Terminal {
def quat: Quat = theQuat
private lazy val computedQuat = theQuat
def quat = computedQuat

override def withQuat(quat: => Quat) = this.copy(quat = quat)
override def equals(obj: Any): Boolean =
obj match {
Expand Down Expand Up @@ -475,7 +481,9 @@ case class FunctionApply(function: Ast, values: List[Ast]) extends Operation { d
sealed trait Value extends Ast

class Constant(val v: Any)(theQuat: => Quat) extends Value {
def quat: Quat = theQuat
private lazy val computedQuat = theQuat
def quat = computedQuat

private val id = Constant.Id(v)
override def hashCode(): Int = id.hashCode()
override def equals(obj: Any): Boolean =
Expand All @@ -499,13 +507,22 @@ object Constant {

object NullValue extends Value { def quat = Quat.Null }

case class Tuple(values: List[Ast]) extends Value { def quat = Quat.Tuple(values.map(_.quat)) }
case class Tuple(values: List[Ast]) extends Value {
private lazy val computedQuat = Quat.Tuple(values.map(_.quat))
def quat = computedQuat
}

case class CaseClass(values: List[(String, Ast)]) extends Value { def quat = Quat.Product(values.map { case (k, v) => (k, v.quat) }) }
case class CaseClass(values: List[(String, Ast)]) extends Value {
private lazy val computedQuat = Quat.Product(values.map { case (k, v) => (k, v.quat) })
def quat = computedQuat
}

//************************************************************

case class Block(statements: List[Ast]) extends Ast { def quat = statements.last.quat } // Note. Assuming Block is not Empty
case class Block(statements: List[Ast]) extends Ast {
private lazy val computedQuat = statements.last.quat
def quat = computedQuat
} // Note. Assuming Block is not Empty

case class Val(name: Ident, body: Ast) extends Ast { def quat = body.quat }

Expand Down Expand Up @@ -581,7 +598,8 @@ object OnConflict {
//************************************************************

class Dynamic(val tree: Any)(theQuat: => Quat) extends Ast {
def quat = theQuat
private lazy val computedQuat = theQuat
def quat = computedQuat
}

object Dynamic {
Expand Down
Expand Up @@ -46,8 +46,10 @@ object RenameProperties {

object CompleteRenames extends StatelessTransformer {
// NOTE Leaving renames on Entities so knowledges of what renames have been done remains in the AST. May want to change this in the future.
override def applyIdent(e: Ident): Ident =
e.copy(quat = e.quat.applyRenames)
override def applyIdent(e: Ident): Ident = {
val newQuat = e.quat.applyRenames // Force actual quat computation for performance reasons
e.copy(quat = newQuat)
}

override def apply(e: Query): Query =
e match {
Expand All @@ -57,7 +59,8 @@ object CompleteRenames extends StatelessTransformer {

override def apply(e: Ast): Ast = e match {
case e: Ident =>
e.copy(quat = e.quat.applyRenames)
val newQuat = e.quat.applyRenames // Force actual quat computation for performance reasons
e.copy(quat = newQuat)

case other =>
super.apply(other)
Expand Down
Expand Up @@ -12,8 +12,12 @@ object QuatNestingHelper {

def valuefyQuatInProperty(ast: Ast): Ast =
ast match {
case Property(id: Ident, name) => Property(id.copy(quat = valueQuat(id.quat)), name)
case Property(prop: Property, name) => Property(valuefyQuatInProperty(prop), name)
case other => other
case Property(id: Ident, name) =>
val newQuat = valueQuat(id.quat) // Force quat value recomputation for better performance
Property(id.copy(quat = newQuat), name)
case Property(prop: Property, name) =>
Property(valuefyQuatInProperty(prop), name)
case other =>
other
}
}
Expand Up @@ -48,14 +48,16 @@ object ExpandDistinct {
// This would normally become:
// SELECT p._1, p._1 FROM (SELECT DISTINCT p.name AS _1 from Person p) AS p
case Distinct(Map(q, x, p @ Property(id: Ident, name))) =>
Map(Distinct(Map(q, x, p)), x, Property(id.copy(quat = valueQuat(id.quat)), name))
val newQuat = valueQuat(id.quat) // force quat recomputation for perf purposes
Map(Distinct(Map(q, x, p)), x, Property(id.copy(quat = newQuat), name))

// Problems with distinct were first discovered in #1032. Basically, unless
// the distinct is "expanded" adding an outer map, Ident's representing a Table will end up in invalid places
// such as "ORDER BY tableIdent" etc...
case Distinct(Map(q, x, p)) =>
val newMap = Map(q, x, Tuple(List(p)))
val newIdent = Ident(x.name, Quat.Tuple(valueQuat(p.quat)))
val newQuat = Quat.Tuple(valueQuat(p.quat)) // force quat recomputation for perf purposes
val newIdent = Ident(x.name, newQuat)
Map(Distinct(newMap), newIdent, Property(newIdent, "_1"))
}
}
Expand Down

0 comments on commit b358484

Please sign in to comment.