Skip to main content

kebs-slick

Automatic column type mappings for Slick.

Setup​

libraryDependencies += "pl.iterators" %% "kebs-slick" % kebsVersion

Value class mappings​

Instead of writing manual MappedColumnType.base for every wrapper type, mix in KebsSlickSupport:

import pl.iterators.kebs.slick.KebsSlickSupport
import pl.iterators.kebs.core.macros.CaseClass1ToValueClass

// With a custom driver (e.g. slick-pg):
object MyPostgresProfile extends ExPostgresDriver with PgArraySupport {
override val api: API = new API {}
trait API extends super.API with ArrayImplicits with KebsSlickSupport with CaseClass1ToValueClass
}

This derives BaseColumnType[CC] for any single-field case class, tagged type, or opaque type. It also derives List[CC] column types for Postgres arrays.

Column extension methods​

Wrapped columns automatically get the extension methods of their underlying type:

  • Rep[CC] where CC wraps String gets StringColumnExtensionMethods (.toLowerCase, .like, etc.)
  • Rep[CC] where CC wraps a numeric type gets arithmetic and comparison methods
  • Rep[CC] where CC wraps Boolean gets &&, ||, etc.

You can also compare a Rep[CC] directly against its unwrapped base type without explicit conversion.

Instance support (java.time, UUID, etc.)​

When kebs-instances traits are mixed into the API, types with an InstanceConverter (e.g. java.time.YearMonth, URI, UUID) also get automatic column types and array support:

import pl.iterators.kebs.instances.time.YearMonthString

trait API extends super.API with KebsSlickSupport with CaseClass1ToValueClass with YearMonthString

Postgres array support​

Works automatically for value classes, enums, and instance types:

class ArrayTestTable(tag: Tag)
extends Table[(Long, List[Institution], Option[List[MarketFinancialProduct]])](tag, "ArrayTest") {
def id = column[Long]("id", O.AutoInc, O.PrimaryKey)
def institutions = column[List[Institution]]("institutions")
def mktFinancialProducts = column[Option[List[MarketFinancialProduct]]]("mktFinancialProducts")
def * = (id, institutions, mktFinancialProducts)
}

Seq columns (stored as Postgres arrays, like List) are also supported. For enums they work out of the box. For value classes and instance types, mix in KebsSeqImplicits. It is opt-in because in Scala 3 these instances confuse type inference of slick-pg array extension methods (such as @>) on List columns.

Postgres hstore support​

Mix in HStoreImplicits alongside KebsSlickSupport and the appropriate instance traits:

import pl.iterators.kebs.instances.time.YearMonthString

object MyPostgresProfile extends ExPostgresProfile with PgHStoreSupport {
override val api: APIWithHstore = new APIWithHstore {}
trait APIWithHstore extends super.API with HStoreImplicits
with KebsSlickSupport with CaseClass1ToValueClass with YearMonthString
}

Hstore columns gain rich query operators: +> (get value), ?? (key exists), ?& (all keys exist), @> (contains), @+ (concatenate), -- (delete keys), slice, and more.

Value classes, instance types, and enums can all be used as hstore map keys and values. Custom types can participate by providing a ToFromStringForHstore[T] implicit.

Enum support​

For Enumeratum (Scala 2 & 3):

import pl.iterators.kebs.enumeratum.{KebsEnumeratum, KebsValueEnumeratum}

trait API extends super.API with KebsSlickSupport with KebsEnumeratum with KebsValueEnumeratum

For Scala 3 native enums:

import pl.iterators.kebs.enums.{KebsEnum, KebsValueEnum}

trait API extends super.API with KebsSlickSupport with KebsEnum with KebsValueEnum

Enum casing strategies​

By default, enums are stored using their entry name. For lowercase or uppercase storage, use the casing variant inner traits instead of the default enum implicits. These are available as inner traits within KebsSlickSupport (e.g. KebsLowercaseEnumImplicits, KebsUppercaseEnumImplicits).

Enum types also work as Postgres array column types (List[MyEnum], Seq[MyEnum]) and as hstore map keys/values.