Skip to content
This repository has been archived by the owner on Mar 20, 2024. It is now read-only.
/ blunt Public archive

Matter-of-fact typesafe query builder for doobie

License

Notifications You must be signed in to change notification settings

iOffice/blunt

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

24 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

blunt

blunt is a matter-of-fact query builder made with doobie. blunt provides a simple interface to map database schema to case classes, and an easy to use, typesafe way of constructing queries. You get all the principled function programming that doobie provides, with an additional layer of composability and brevity.

Example

import doobie.imports._
import blunt._

val xa = DriverManagerTransactor[IOLite](
  // Set up your doobie transactor
  // ... 
)

//Define case classes to match your schema
case class Post(id: Int, title: String, subtitle: Option[String], text: String)
case class Comment(id: Int, postId: Int, text: String, likes: Int)

// Create a post and insert into db
val qb = QueryBuilder[Post]
val post = Post(-1, "A Good Post", None, "Here's a real good post")
qb
  .insert(post, 'id) // pass in the post and the id column to exclude
  .build
  .run
  .transact(xa)
  .unsafePerformIO

val postId = // Get the post id with doobie and your database's preferred way

// Create a comment and insert into db
QueryBuilder[Comment]
  .insert(Comment(-1, postId, "This post is good", 5), 'id)
  .build.run.transact(xa)
  .unsafePerformIO

// Select the posts that have comments with 
// greater than or equal to 5 likes
qb.select
  .join[Comment]
  .on('id, 'postId)
  .project[Comment]
  .where[>=]('likes, 5)
  .build
  .nel
  .transact(xa)
  .unsafePerformIO
// res1: NonEmptyList[(Post, Comment)] = ...

Custom Table Names

Blunt will attempt to dervive a Queryable instance for you, by using a pluralized version of the case class name as the table name. If this convention doesn't work for you, or the pluralization is incorrect, you can provide your own Queryable instance:

case class Medium(id: Int, name: String)

object Medium {
  implicit val queryable = new Queryable[Medium] {
    val columns = Seq(fr"id", fr"name") // The order of these should match your case class fields
    val table = Fragment.const("Media")
  }
}

Releases

No releases published

Packages

No packages published

Languages