Typed-sql

This is a frontend library for writing doobie queries. Its goal to provide a typesafe-dsl for it and keep its constructs as close as it possible to the plain SQL language.

Usage

In addition to doobie dependencies add the following one to your build.sbt:

libraryDependencies += Seq( 
  "io.hydrosphere" %% "typed-sql" % "0.1.0"
)

Import:

import doobie._
import doobie.implicits._
import doobie.syntax._

import typed.sql.syntax._
import typed.sql.toDoobie._

Declare case class for row, create table from it and columns:

case class Row(
  a: Int,
  b: String,
  c: String
)

val table = Table.of[Row].name('test)
// or if `a` column is a primary key and has serial type
val table = Table.of[Row].autoColumn('a).name('test)

val a = table.col('a)
val b = table.col('b)
val c = table.col('c)

Now it's time for to write queries. Examples:

insert.into(table).values(1, "b", "c")
// or if `a` column is a primary key and has serial type
insert.into(table).values("b", "c")

select(*).from(table)
select(*).from(table).where(a === 1)
select(a, b).from(table)

update(table).set(b := "Upd B").where(a === 1)

delete.from(table).where(a === 1)

Convert to Query0/Update0 using toQuery/toUpdate:

val q0: Query0[Row] = select(*).from(table).toQuery
// the same for update and insert
val u0: Update0 = delete.from(table).where(a === 1).toUpdate

More examples:

Where:

select(*).from(table).where(a > 1 and a < 5)
select(*).from(table).where(a >= 1 and a =< 5)
select(*).from(table).where(a === 1 or a === 2)
select(*).from(table).where(b like "BBB%")
select(*).from(table).where(a.in(NonEmptyList.of(1,2,3)))

Order By:

// SELECT * FROM TEST ORDER BY test.a ASC
select(*).from(table).orderBy(a)

// SELECT * FROM TEST ORDER BY test.a DESC
select(*).from(table).orderBy(a.DESC)

// SELECT * FROM TEST ORDER BY test.a ASC test.b ASC
select(*).from(table).orderBy(a, b)

Limit/Offset:

select(*).from(table).limit(10).offset(1)

Joins:

case class Row2(a: Int)
val table2 = Table.of[Row2].name('test2) 
val a2 = table2.col('a2)

// Query0[(Row1, Row2)]
select(*).from(table.innerJoin(table2).on(a1 <==> a2))
// Query0[(Row1, Option[Row2])]
select(*).from(table.leftJoin(table2).on(a1 <==> a2))
// Query0[(Option[Row1], Row2)]
select(*).from(table.rightJoin(table2).on(a1 <==> a2))
// Query0[(Option[Row1], Option[Row2])]
select(*).from(table.fullJoin(table2).on(a1 <==> a2))

// Query0[(Int, Int)]
select(a, a2).from(table.innerJoin(table2).on(a1 <==> a2))

Note: it's possible to join more that two tables