Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    primarykey
    data
    text
    <p>I never used Slick or ScalaQuery so it was quite an adventure to find out how to achieve this. Slick is very extensible, but the documentation on extending is a bit tricky. It might already exist, but this is what I came up with. If I have done something incorrect, please correct me.</p> <p>First we need to create a custom driver. I extended the <code>H2Driver</code> to be able to test easily.</p> <pre><code>trait CustomDriver extends H2Driver { // make sure we create our query builder override def createQueryBuilder(input: QueryBuilderInput): QueryBuilder = new QueryBuilder(input) // extend the H2 query builder class QueryBuilder(input: QueryBuilderInput) extends super.QueryBuilder(input) { // we override the expr method in order to support the 'As' function override def expr(n: Node, skipParens: Boolean = false) = n match { // if we match our function we simply build the appropriate query case CustomDriver.As(column, LiteralNode(name: String)) =&gt; b"(" super.expr(column, skipParens) b") as ${name}" // we don't know how to handle this, so let super hanle it case _ =&gt; super.expr(n, skipParens) } } } object CustomDriver extends CustomDriver { // simply define 'As' as a function symbol val As = new FunctionSymbol("As") // we override SimpleSql to add an extra implicit trait SimpleQL extends super.SimpleQL { // This is the part that makes it easy to use on queries. It's an enrichment class. implicit class RichQuery[T: TypeMapper](q: Query[Column[T], T]) { // here we redirect our as call to the As method we defined in our custom driver def as(name: String) = CustomDriver.As.column[T](Node(q.unpackable.value), name) } } // we need to override simple to use our version override val simple: SimpleQL = new SimpleQL {} } </code></pre> <p>In order to use it we need to import specific things:</p> <pre><code>import CustomDriver.simple._ import Database.threadLocalSession </code></pre> <p>Then, to use it you can do the following (I used the tables from the official Slick documentation in my example).</p> <pre><code>// first create a function to create a count query def countCoffees(supID: Column[Int]) = for { c &lt;- Coffees if (c.supID === supID) } yield (c.length) // create the query to combine name and count val coffeesPerSupplier = for { s &lt;- Suppliers } yield (s.name, countCoffees(s.id) as "test") // print out the name and count coffeesPerSupplier foreach { case (name, count) =&gt; println(s"$name has $count type(s) of coffee") } </code></pre> <p>The result is this:</p> <pre><code>Acme, Inc. has 2 type(s) of coffee Superior Coffee has 2 type(s) of coffee The High Ground has 1 type(s) of coffee </code></pre>
    singulars
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. VO
      singulars
      1. This table or related slice is empty.
    2. VO
      singulars
      1. This table or related slice is empty.
    3. VO
      singulars
      1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload