Skip to content

kwark/slick-refined

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Slick-refined

Build Status Maven version

Slick-refined is a small scala library that enables boilerplate-free integration of refinement types using the Refined library with Lightbend's Slick library.

It allows you to easily store/retrieve and manipulate Refined types to/from an SQL database.

Scala 2.11, 2.12 and 2.13 are supported. You'll also need to use Java8 and slick 3.2.x or later

The library supports the following functionality:

  • boilerplate-free mapping of refined types to/from Database tables
  • typesafe queries on refined types
  • support for Slick Plain SQL

Usage

Slick 2.11 2.12 2.13 Refined Version to use
3.2.x 0.9.0 0.2.0
3.3.0 0.9.4 0.4.0
3.3.2 0.9.8 0.5.0
3.3.3 0.9.19 0.6.0

You first need to add the following dependency to your SBT dependencies:

libraryDependencies += "be.venneborg" %% "slick-refined" % <version-to-use>

Refined Profile

Next you'll need to create a trait which extends the Slick Profile for your specific database as follows:

import be.venneborg.refined.RefinedMapping
import be.venneborg.refined.RefinedSupport

trait MyRefinedProfile extends slick.jdbc.XXXProfile
  with RefinedMapping
  with RefinedSupport {

  override val api = new API with RefinedImplicits

}

object MyRefinedProfile extends TestRefinedProfile

Mapping Refined types using a Refined Schema

To map case classes or tuples containing Refined types, you need to slightly adapt your Slick schema

Suppose we have a case class which uses Refined types:

import eu.timepit.refined.types.string.NonEmptyString
import eu.timepit.refined.types.numeric.PosInt

case class FooBar(foo: NonEmptyString, bar: PosInt)

To map this class to a database table, you can do the following:

object RefinedSchema {

  import be.venneborg.refined.MyRefinedProfile.api._
  import be.venneborg.refined.MyRefinedProfile.mapping._
  
  class FooBars(tag: Tag) extends Table[Foobar](tag, "FOOBARS") {
    def bar = column[PosInt]("BAR", O.PrimaryKey)
    def foo = column[NonEmptyString]("FOO")

    def * = (bar, foo) <> (FooBar.tupled, FooBar.unapply)
  }

  val foobars = TableQuery[FooBars]
  
}

The only difference with mapping a normal case class, which does not use refined types, are:

  • The two import statement form the Refined profile
  • the column[XXX] definitions which now take a Refined type as type parameter

Querying on Refined types

You can use Slick queries on your Refined types and they will work exactly the same as if you would run them on the unrefined base type.

import be.venneborg.refined.MyRefinedProfile.api._

val db = <some Slick database object>

// query for all foobars where the foo column contains an 'x'
db.run(foobars
  .filter(_.foo.like("%x%"))
  .result
)

Support for Plain SQL

The library also supports Slick Plain SQL queries.

Example:

import be.venneborg.refined.RefinedPlainSql._
import eu.timepit.refined.auto._

db.run(sqlu"""insert into foobars values (1, 'foo')""")

db.run(sql"""select bar from foobars where foo = 'foo'""".as[PosInt])

About

support for using refinement types with slick

Topics

Resources

Stars

Watchers

Forks

Packages

No packages published

Contributors 4

  •  
  •  
  •  
  •  

Languages