Quill is a compile-time language integrated query library with a powerful query compilation mechanism based on the paper "A Practical Theory of Language-Integrated Query". This talk will give an overview of the query compilation, present the Quoted Domain Specific Language (QDSL) approach, and give a quick view of Quill's functionality and internals.
24. val ageFromName = quote {
(s: String) =>
for {
u <- query[Person] if (s == u.name)
} yield {
u.age
}
}
quote {
(s: String, t: String) =>
for {
a <- ageFromName(s)
b <- ageFromName(t)
r <- range(a, b)
} yield {
r
}
}
@vonjuliano
25. val ageFromName = quote {
(s: String) =>
for {
u <- query[Person] if (s == u.name)
} yield {
u.age
}
}
quote {
(s: String, t: String) =>
for {
a <- ageFromName(s)
b <- ageFromName(t)
r <- range(a, b)
} yield {
r
}
}
@vonjuliano
27. sealed trait Predicate
case class Above(i: Int) extends Predicate
case class Below(i: Int) extends Predicate
case class And(a: Predicate, b: Predicate) extends Predicate
case class Or(a: Predicate, b: Predicate) extends Predicate
case class Not(p: Predicate) extends Predicate
def eval(t: Predicate): Quoted[Int => Boolean] =
t match {
case Above(n) => quote((x: Int) => x > lift(n))
case Below(n) => quote((x: Int) => x < lift(n))
case And(t1, t2) => quote((x: Int) => eval(t1)(x) && eval(t2)(x))
case Or(t1, t2) => quote((x: Int) => eval(t1)(x) || eval(t2)(x))
case Not(t0) => quote((x: Int) => !eval(t0)(x))
}
@vonjuliano
28. sealed trait Predicate
case class Above(i: Int) extends Predicate
case class Below(i: Int) extends Predicate
case class And(a: Predicate, b: Predicate) extends Predicate
case class Or(a: Predicate, b: Predicate) extends Predicate
case class Not(p: Predicate) extends Predicate
def eval(t: Predicate): Quoted[Int => Boolean] =
t match {
case Above(n) => quote((x: Int) => x > lift(n))
case Below(n) => quote((x: Int) => x < lift(n))
case And(t1, t2) => quote((x: Int) => eval(t1)(x) && eval(t2)(x))
case Or(t1, t2) => quote((x: Int) => eval(t1)(x) || eval(t2)(x))
case Not(t0) => quote((x: Int) => !eval(t0)(x))
}
@vonjuliano
Compile-time Language Integrated Query for Scala
Boilerplate-free mapping: The database schema is mapped using simple case classes
Quoted DSL: Quill parses each quoted block of code (quotation) at compile time and translates them to an internal Abstract Syntax Tree (AST)
Compile-time query generation: The ctx.run call reads the quotation's AST and translates it to the target language at compile time
Compile-time query validation: (optional) the query is verified against the database at compile time and the compilation fails if it is not valid
Failure and avalanche
each query in the host language generate exactly one SQL query