ElaborateStructure
Based on valueComputation and materializeQueryMeta from the old Quill This was around to flesh-out details of the outermost AST of a query based on the fields of the object T in Query[T] that the AST represents. For an example say we have something like this:
import io.getquill.ast.{ Ident => Id, Property => Prop, _ }
case class Person(name: String, age: Int)
query[Person].map(p => p) // or just query[Person]
That would turn into an AST that looks like this:
Map(EntityQuery("Person"), Id("p"), Id("p"))
This query needs to be turned into SELECT p.name, p.age from Person p
, the problem is, before Quats, Quill did not actually know how to expand Ident("p")
into SelectValue(p.name), SelectValue(p.age)
(see SqlQuery.scala) since there was no type information. Therefore...
// We needed to convert something that looks like this:
query[Person].map(p => p) // i.e. Map(EntityQuery("Person"), Id("p"), Id("p"))
// Into something that looks like this:
query[Person].map(p => p).map(p => (p.name, p.age))
// i.e. Map(Map(EntityQuery("Person"), Ident("p"), Ident("p")), Tuple(Prop(Id("p"),"name"), Prop(Id("p"),"age")))
This makes it easier to translate the above information into the finalized form
SELECT p.name, p.age FROM (SELECT p.* from Person p) AS p
(Note that redudant map would typically be flattened out since it is extraneous and the inner SELECT would no longer be present)
Some special provisions were made for fields inside optional objects:
case class Address(street: String, zip: Int)
case class Person(name: String, address: Option[Address])
// This:
query[Person]
// Would become this:
query[Person].map(p => (p.name, p.address.map(_.street), p.address.map(_.zip)))
Now, since Quats were introduced into Quill since 3.6.0 (technically since 3.5.3), this step is not necessarily needed for query expansion since Ident("p")
is now understood to expand into its corresponding SelectValue fields so for queries, this stage could technically be elimiated. However, this logic is also useful for ActionMeta where we have something like this:
case class Person(name: String, age: Int)
// This:
query[Person].insert(Person("Joe", 44))
// Needs to be converted into this:
query[Person].insert(_.name -> "Joe", _.age -> 44)
// Which is actually:
EntityQuery("Person").insert(
Assignment(Id("x1"), Prop(Id("x1"), "name"), Constant("Joe")),
Assignment(Id("x1"), Prop(Id("x1"), "name"), Constant(44))
)
The fact that we know that Person expands into Prop(Id("p"),"name"), Prop(Id("p"),"age")) helps us compute the necessary assignments in the InsertUpdateMacro
.
Attributes
- Graph
-
- Supertypes
-
class Objecttrait Matchableclass Any
- Self type
-
ElaborateStructure.type