Hey Scala devs! I’m excited to share sqala – a powerful new SQL query library built specifically for Scala 3 that blends SQL expressiveness with Scala’s type system. If you’re tired of ORM quirks or string-based SQL, this might be your new favorite tool.
Killer Features
- Projections to Named Tuples:
you can easily project your fields to named tuples usingmap
orselect
method:
case class User(@autoInc id: Long, name: String, age: Int)
val q = query:
from[User].filter(_.name == "Dove").map(u => (name = u.name))
val res = db.fetch(q) // the type of res will be `List[(name: String)]`
-
Show sql as compiler info when query is an inline function:
-
SQL semantic checking with meaningful warning:
-
Support Oracle’s
CONNECT BY
(query recursive data) feature but generating standard SQL.
case class Department(id: Int, managerId: Int, name: String)
val q = query:
from[Department]
.connectBy(d => prior(d.id) == d.managerId)
.startWith(d => d.managerId == 0)
.map(d => (id = d.id, managerId = d.managerId, name = d.name))
// will generate query with CTE, use inline def and db.fetch(q) to see generated sql
Getting Started
Docs are in site sqala-docs and you can do a quick experiment using scala-cli
with following code:
//> using scala 3.7.1
//> using dep com.h2database:h2:2.3.232
//> using dep com.wz7982::sqala-jdbc:0.3.6
import org.h2.jdbcx.*
import sqala.jdbc.*
import sqala.metadata.*
import sqala.static.dsl.*
object DB:
val ds = JdbcDataSource()
ds.setURL("jdbc:h2:mem:default")
val db = JdbcContext(ds, H2Dialect)
case class User(@autoInc id: Long, name: String, age: Int)
object Main:
import DB.{db, ds}
def main(args: Array[String]) =
// logging with println
given Logger = Logger(log => println(log))
val conn = ds.getConnection()
conn
.createStatement()
.executeUpdate:
"""CREATE TABLE `user` (`id` BIGINT AUTO_INCREMENT PRIMARY KEY,`name` TEXT,`age` INT)"""
conn.commit()
val user = User(0L, "Dove", 8)
db.insert(user)
inline def q = query:
from[User].filter(_.name == "Dove").map(u => (id = u.id, name = u.name))
val res = db.fetch(q)
for re <- res do println(re.name)