Skip to content

Commit c47c559

Browse files
committed
continue
1 parent ef0bdd4 commit c47c559

File tree

4 files changed

+80
-12
lines changed

4 files changed

+80
-12
lines changed

quill-engine/src/main/scala/io/getquill/sql/idiom/SqlIdiom.scala

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ import io.getquill.norm.ConcatBehavior.AnsiConcat
1717
import io.getquill.norm.EqualityBehavior.AnsiEquality
1818
import io.getquill.norm.{ConcatBehavior, EqualityBehavior, ExpandReturning, NormalizeCaching, ProductAggregationToken}
1919
import io.getquill.quat.Quat
20-
import io.getquill.sql.norm.{HideTopLevelFilterAlias, NormalizeFilteredActionAliases, RemoveExtraAlias, RemoveUnusedSelects}
20+
import io.getquill.sql.norm.{HideTopLevelFilterAlias, NormalizeFilteredActionAliases, RemoveExtraAlias, RemoveUnusedSelects, ValueizeSingleLeafSelects}
2121
import io.getquill.util.{Interleave, Interpolator, Messages, TraceConfig}
2222
import io.getquill.util.Messages.{TraceType, fail, trace}
2323

@@ -82,7 +82,9 @@ trait SqlIdiom extends Idiom {
8282
val sql = querifyAst(q, idiomContext.traceConfig)
8383
trace"SQL: ${sql}".andLog()
8484
VerifySqlQuery(sql).map(fail)
85-
val expanded = ExpandNestedQueries(sql, topLevelQuat)
85+
val valueized = ValueizeSingleLeafSelects(naming)(sql, topLevelQuat)
86+
trace"Valueized SQL: ${valueized}".andLog()
87+
val expanded = ExpandNestedQueries(valueized, topLevelQuat)
8688
trace"Expanded SQL: ${expanded}".andLog()
8789
val refined = if (Messages.pruneColumns) RemoveUnusedSelects(expanded) else expanded
8890
trace"Filtered SQL (only used selects): ${refined}".andLog()

quill-engine/src/main/scala/io/getquill/sql/norm/ExpandDistinct.scala

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -77,12 +77,15 @@ class ExpandDistinct(traceConfig: TraceConfig) {
7777
// Problems with distinct were first discovered in #1032. Basically, unless
7878
// the distinct is "expanded" adding an outer map, Ident's representing a Table will end up in invalid places
7979
// such as "ORDER BY tableIdent" etc...
80-
case Distinct(Map(q, x, p)) =>
81-
val newMap = Map(q, x, Tuple(List(p)))
82-
val newQuat = Quat.Tuple(valueQuat(p.quat)) // force quat recomputation for perf purposes
83-
val newIdent = Ident(x.name, newQuat)
84-
trace"ExpandDistinct Distinct(Map(other))" andReturn
85-
Map(Distinct(newMap), newIdent, Property(newIdent, "_1"))
80+
81+
// TODO EXPERIMENTING WITH THIS CLAUSE, TRY TO DISABLE``
82+
83+
// case Distinct(Map(q, x, p)) =>
84+
// val newMap = Map(q, x, Tuple(List(p)))
85+
// val newQuat = Quat.Tuple(valueQuat(p.quat)) // force quat recomputation for perf purposes
86+
// val newIdent = Ident(x.name, newQuat)
87+
// trace"ExpandDistinct Distinct(Map(other))" andReturn
88+
// Map(Distinct(newMap), newIdent, Property(newIdent, "_1"))
8689
}
8790
}
8891
}

quill-engine/src/main/scala/io/getquill/sql/norm/RemoveExtraAlias.scala

Lines changed: 65 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,71 @@
11
package io.getquill.sql.norm
22

33
import io.getquill.NamingStrategy
4-
import io.getquill.ast.{Property, Renameable}
5-
import io.getquill.context.sql.{FlattenSqlQuery, SelectValue}
4+
import io.getquill.ast.Ast.LeafQuat
5+
import io.getquill.ast.{Ast, CollectAst, Ident, Property, Renameable}
6+
import io.getquill.context.sql.{FlatJoinContext, FlattenSqlQuery, FromContext, InfixContext, JoinContext, QueryContext, SelectValue, TableContext}
7+
import io.getquill.norm.{BetaReduction, TypeBehavior}
8+
import io.getquill.quat.Quat
9+
10+
// 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`
11+
// in that case we know that SelectValue(x) is a leaf clause that we should expand into a `x.value`.
12+
// MAKE SURE THIS RUNS BEFORE ExpandNestedQueries otherwise it will be incorrect, it should only run for single-selects from atomic values,
13+
// 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
14+
case class ValueizeSingleLeafSelects(strategy: NamingStrategy) extends StatelessQueryTransformer {
15+
protected def productize(ast: Ident) =
16+
Ident(ast.name, Quat.Product("<Value>", "value" -> Quat.Value))
17+
18+
protected def valueize(ast: Ident) =
19+
Property(productize(ast), "value")
20+
21+
// Turn every `SELECT primitive-x` into a `SELECT case-class-x.primitive-value`
22+
override protected def expandNested(q: FlattenSqlQuery, level: QueryLevel): FlattenSqlQuery = {
23+
// get the alises before we transform (i.e. Valueize) the contexts inside turning the leaf-quat alises into product-quat alises
24+
val fromContextAliases = collectAliases(q.from).filter(!_.quat.isProduct)
25+
// now transform the inner clauses
26+
val from = q.from.map(expandContext(_))
27+
28+
def containsAlias(ast: Ast): Boolean =
29+
CollectAst.byType[Ident](ast).exists(id => fromContextAliases.contains(id))
30+
31+
// if it is a leaf add leaf.value
32+
val select =
33+
q.select.map {
34+
// TODO need to do this kind of replacement in Join-by clauses the aggregations etc...
35+
case sv: SelectValue if containsAlias(sv.ast) =>
36+
val reductions = CollectAst.byType[Ident](sv.ast).map(id => id -> valueize(id))
37+
val newAst = BetaReduction(sv.ast, TypeBehavior.ReplaceWithReduction, reductions: _*)
38+
val newSelectValue = SelectValue(newAst, sv.alias, sv.concat)
39+
newSelectValue match {
40+
case sv @ SelectValue(LeafQuat(ast), _, _) => sv.copy(alias = Some("value"))
41+
case _ => newSelectValue
42+
}
43+
case sv @ SelectValue(LeafQuat(ast), _, _) =>
44+
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
45+
case sv => sv
46+
47+
}
48+
q.copy(select = select, from = from)(q.quat)
49+
}
50+
51+
// Turn every `FROM primitive-x` into a `FROM case-class(x.primitive)`
52+
override protected def expandContext(s: FromContext): FromContext =
53+
super.expandContext(s) match {
54+
case QueryContext(query, LeafQuat(id: Ident)) =>
55+
QueryContext(query, productize(id))
56+
case other =>
57+
other
58+
}
59+
60+
private def collectAliases(contexts: List[FromContext]): List[Ident] =
61+
contexts.flatMap {
62+
case c: TableContext => List(c.alias)
63+
case c: QueryContext => List(c.alias)
64+
case c: InfixContext => List(c.alias)
65+
case JoinContext(_, a, b, _) => collectAliases(List(a)) ++ collectAliases(List(b))
66+
case FlatJoinContext(_, from, _) => collectAliases(List(from))
67+
}
68+
}
669

770
/**
871
* Remove aliases at the top level of the AST since they are not needed (quill

quill-engine/src/main/scala/io/getquill/sql/norm/SqlNormalize.scala

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -63,8 +63,8 @@ class SqlNormalize(
6363
.andThen(demarcate("ExpandJoin"))
6464
.andThen(ExpandMappedInfix.apply _)
6565
.andThen(demarcate("ExpandMappedInfix"))
66-
.andThen(SheathLeafClausesPhase.apply _)
67-
.andThen(demarcate("SheathLeaves"))
66+
// .andThen(SheathLeafClausesPhase.apply _)
67+
// .andThen(demarcate("SheathLeaves"))
6868
.andThen { ast =>
6969
// In the final stage of normalization, change all temporary aliases into
7070
// shorter ones of the form x[0-9]+.

0 commit comments

Comments
 (0)