Initial outline for a simple query builder

This commit is contained in:
Eike Kettner
2020-12-07 19:30:10 +01:00
parent b338f18e98
commit 2dbb1db2fd
22 changed files with 716 additions and 0 deletions

View File

@ -0,0 +1,37 @@
package docspell.store.qb
import minitest._
import docspell.store.qb.model._
import docspell.store.qb.DSL._
object QueryBuilderTest extends SimpleTestSuite {
test("simple") {
val c = CourseRecord.as("c")
val owner = PersonRecord.as("p1")
val lecturer = PersonRecord.as("p2")
val proj = select(c.all, owner.all, lecturer.all)
val tables =
from(c)
.innerJoin(owner, c.ownerId === owner.id)
.leftJoin(lecturer, c.lecturerId === lecturer.id)
val cond =
where(
c.name.like("%scala%"),
c.lessons <= 15,
or(
owner.name.like("%"),
lecturer.id >= 1
)
)
// val order =
// orderBy(c.name.asc)
val q = Select(proj, tables, cond)
println(q)
}
}

View File

@ -0,0 +1,50 @@
package docspell.store.qb.impl
import minitest._
import docspell.store.qb._
import docspell.store.qb.model._
import docspell.store.qb.DSL._
import docspell.common._
object DoobieQueryTest extends SimpleTestSuite {
test("basic fragment") {
val c = CourseRecord.as("c")
val owner = PersonRecord.as("o")
val lecturer = PersonRecord.as("l")
val proj = select(c.all)
val table = from(c)
.innerJoin(owner, c.ownerId === owner.id)
.leftJoin(lecturer, c.lecturerId === lecturer.id)
val cond = where(
c.name.like("%test%"),
owner.name === "Harald"
)
val q = Select(proj, table, cond)
val frag = DoobieQuery.select(q)
assertEquals(
frag.toString,
"""Fragment("SELECT c.id, c.name, c.owner_id, c.lecturer_id, c.lessons FROM course c INNER JOIN person o ON c.owner_id = o.id LEFT JOIN person l ON c.lecturer_id = l.id WHERE (LOWER(c.name) LIKE ? AND o.name = ? )")"""
)
}
test("basic update") {
val p = PersonRecord.table
val update = PersonRecord.update(p.name.set("john"), p.id.set(15L)).where(p.id >= 2)
println(DoobieQuery.update(update))
}
test("basic insert") {
val p = PersonRecord(1, "John", Timestamp.Epoch)
val insert = PersonRecord.insertAll(p)
println(insert)
}
}

View File

@ -0,0 +1,34 @@
package docspell.store.qb.model
import docspell.store.qb._
case class CourseRecord(
id: Long,
name: String,
ownerId: Long,
lecturerId: Option[Long],
lessons: Int
)
object CourseRecord {
final case class Table(alias: Option[String]) extends TableDef {
override val tableName = "course"
val id = Column[Long]("id", this)
val name = Column[String]("name", this)
val ownerId = Column[Long]("owner_id", this)
val lecturerId = Column[Long]("lecturer_id", this)
val lessons = Column[Int]("lessons", this)
val all = List(id, name, ownerId, lecturerId, lessons)
}
def as(alias: String): Table =
Table(Some(alias))
def update: UpdateTable =
UpdateTable(Table(None), None, Seq.empty)
}

View File

@ -0,0 +1,38 @@
package docspell.store.qb.model
import docspell.store.qb._
import docspell.common._
import doobie.implicits._
import docspell.store.impl.DoobieMeta._
import doobie._
case class PersonRecord(id: Long, name: String, created: Timestamp)
object PersonRecord {
final case class Table(alias: Option[String]) extends TableDef {
val tableName = "person"
val id = Column[Long]("id", this)
val name = Column[String]("name", this)
val created = Column[Timestamp]("created", this)
val all = List(id, name, created)
}
def as(alias: String): Table =
Table(Some(alias))
def table: Table = Table(None)
def update(set: UpdateTable.Setter[_], sets: UpdateTable.Setter[_]*): UpdateTable =
UpdateTable(table, None, sets :+ set)
def insertAll(v: PersonRecord): ConnectionIO[Int] =
InsertTable(
table,
table.all,
fr"${v.id},${v.name},${v.created}"
).toFragment.update.run
}