Skip to content

Commit

Permalink
continue
Browse files Browse the repository at this point in the history
  • Loading branch information
deusaquilus committed Jul 3, 2024
1 parent ef0bdd4 commit c47c559
Show file tree
Hide file tree
Showing 4 changed files with 80 additions and 12 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ import io.getquill.norm.ConcatBehavior.AnsiConcat
import io.getquill.norm.EqualityBehavior.AnsiEquality
import io.getquill.norm.{ConcatBehavior, EqualityBehavior, ExpandReturning, NormalizeCaching, ProductAggregationToken}
import io.getquill.quat.Quat
import io.getquill.sql.norm.{HideTopLevelFilterAlias, NormalizeFilteredActionAliases, RemoveExtraAlias, RemoveUnusedSelects}
import io.getquill.sql.norm.{HideTopLevelFilterAlias, NormalizeFilteredActionAliases, RemoveExtraAlias, RemoveUnusedSelects, ValueizeSingleLeafSelects}
import io.getquill.util.{Interleave, Interpolator, Messages, TraceConfig}
import io.getquill.util.Messages.{TraceType, fail, trace}

Expand Down Expand Up @@ -82,7 +82,9 @@ trait SqlIdiom extends Idiom {
val sql = querifyAst(q, idiomContext.traceConfig)
trace"SQL: ${sql}".andLog()
VerifySqlQuery(sql).map(fail)
val expanded = ExpandNestedQueries(sql, topLevelQuat)
val valueized = ValueizeSingleLeafSelects(naming)(sql, topLevelQuat)
trace"Valueized SQL: ${valueized}".andLog()
val expanded = ExpandNestedQueries(valueized, topLevelQuat)
trace"Expanded SQL: ${expanded}".andLog()
val refined = if (Messages.pruneColumns) RemoveUnusedSelects(expanded) else expanded
trace"Filtered SQL (only used selects): ${refined}".andLog()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -77,12 +77,15 @@ class ExpandDistinct(traceConfig: TraceConfig) {
// 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 newQuat = Quat.Tuple(valueQuat(p.quat)) // force quat recomputation for perf purposes
val newIdent = Ident(x.name, newQuat)
trace"ExpandDistinct Distinct(Map(other))" andReturn
Map(Distinct(newMap), newIdent, Property(newIdent, "_1"))

// TODO EXPERIMENTING WITH THIS CLAUSE, TRY TO DISABLE``

// case Distinct(Map(q, x, p)) =>
// val newMap = Map(q, x, Tuple(List(p)))
// val newQuat = Quat.Tuple(valueQuat(p.quat)) // force quat recomputation for perf purposes
// val newIdent = Ident(x.name, newQuat)
// trace"ExpandDistinct Distinct(Map(other))" andReturn
// Map(Distinct(newMap), newIdent, Property(newIdent, "_1"))
}
}
}
Original file line number Diff line number Diff line change
@@ -1,8 +1,71 @@
package io.getquill.sql.norm

import io.getquill.NamingStrategy
import io.getquill.ast.{Property, Renameable}
import io.getquill.context.sql.{FlattenSqlQuery, SelectValue}
import io.getquill.ast.Ast.LeafQuat
import io.getquill.ast.{Ast, CollectAst, Ident, Property, Renameable}
import io.getquill.context.sql.{FlatJoinContext, FlattenSqlQuery, FromContext, InfixContext, JoinContext, QueryContext, SelectValue, TableContext}
import io.getquill.norm.{BetaReduction, TypeBehavior}
import io.getquill.quat.Quat

// If we run this right after SqlQuery we know that in every place with a single select-value it is a leaf clause e.g. `SELECT x FROM (SELECT p.name from Person p)) AS x`
// in that case we know that SelectValue(x) is a leaf clause that we should expand into a `x.value`.
// MAKE SURE THIS RUNS BEFORE ExpandNestedQueries otherwise it will be incorrect, it should only run for single-selects from atomic values,
// if the ExpandNestedQueries ran it could be a single field that is coming from a case class e.g. case class MySingleValue(stuff: Int) that is being selected from
case class ValueizeSingleLeafSelects(strategy: NamingStrategy) extends StatelessQueryTransformer {
protected def productize(ast: Ident) =
Ident(ast.name, Quat.Product("<Value>", "value" -> Quat.Value))

protected def valueize(ast: Ident) =
Property(productize(ast), "value")

// Turn every `SELECT primitive-x` into a `SELECT case-class-x.primitive-value`
override protected def expandNested(q: FlattenSqlQuery, level: QueryLevel): FlattenSqlQuery = {
// get the alises before we transform (i.e. Valueize) the contexts inside turning the leaf-quat alises into product-quat alises
val fromContextAliases = collectAliases(q.from).filter(!_.quat.isProduct)
// now transform the inner clauses
val from = q.from.map(expandContext(_))

def containsAlias(ast: Ast): Boolean =
CollectAst.byType[Ident](ast).exists(id => fromContextAliases.contains(id))

// if it is a leaf add leaf.value
val select =
q.select.map {
// TODO need to do this kind of replacement in Join-by clauses the aggregations etc...
case sv: SelectValue if containsAlias(sv.ast) =>
val reductions = CollectAst.byType[Ident](sv.ast).map(id => id -> valueize(id))
val newAst = BetaReduction(sv.ast, TypeBehavior.ReplaceWithReduction, reductions: _*)
val newSelectValue = SelectValue(newAst, sv.alias, sv.concat)
newSelectValue match {
case sv @ SelectValue(LeafQuat(ast), _, _) => sv.copy(alias = Some("value"))
case _ => newSelectValue
}
case sv @ SelectValue(LeafQuat(ast), _, _) =>
sv.copy(alias = Some("value")) // TODO check if there is no alias already? Probably don't need to since aliasing only really happens in ExpandNestedQueries
case sv => sv

}
q.copy(select = select, from = from)(q.quat)
}

// Turn every `FROM primitive-x` into a `FROM case-class(x.primitive)`
override protected def expandContext(s: FromContext): FromContext =
super.expandContext(s) match {
case QueryContext(query, LeafQuat(id: Ident)) =>
QueryContext(query, productize(id))
case other =>
other
}

private def collectAliases(contexts: List[FromContext]): List[Ident] =
contexts.flatMap {
case c: TableContext => List(c.alias)
case c: QueryContext => List(c.alias)
case c: InfixContext => List(c.alias)
case JoinContext(_, a, b, _) => collectAliases(List(a)) ++ collectAliases(List(b))
case FlatJoinContext(_, from, _) => collectAliases(List(from))
}
}

/**
* Remove aliases at the top level of the AST since they are not needed (quill
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -63,8 +63,8 @@ class SqlNormalize(
.andThen(demarcate("ExpandJoin"))
.andThen(ExpandMappedInfix.apply _)
.andThen(demarcate("ExpandMappedInfix"))
.andThen(SheathLeafClausesPhase.apply _)
.andThen(demarcate("SheathLeaves"))
// .andThen(SheathLeafClausesPhase.apply _)
// .andThen(demarcate("SheathLeaves"))
.andThen { ast =>
// In the final stage of normalization, change all temporary aliases into
// shorter ones of the form x[0-9]+.
Expand Down

0 comments on commit c47c559

Please sign in to comment.