Migration Notes (from 0.6.x to 0.7.x)
Packages
All Packages
🎯 Key Changes
1. New Testing Modules
0.7.0 introduces two dedicated modules for writing database tests more easily.
ldbc-testkit
A new framework-agnostic ldbc-testkit module has been added. It provides automatic rollback at the end of tests.
RollbackHandler: Provides a Connector wrapped in a Resource that automatically rolls back all changes after the test completes.
import ldbc.testkit.RollbackHandler
RollbackHandler.resource[F](dataSource).use { connector =>
// All changes within this block are rolled back after the test
connector.use { conn =>
conn.executeUpdate("INSERT INTO users VALUES (1, 'Alice')")
}
}
TestConnection: Intercepts commit() and setAutoCommit(true) as no-ops to prevent accidental commits during tests.
ldbc-testkit-munit
A new ldbc-testkit-munit module provides MUnit integration for database testing.
LdbcSuite: A base trait extending CatsEffectSuite with ldbc-specific test helpers.
import ldbc.testkit.munit.LdbcSuite
class MyDbTest extends LdbcSuite {
// Test that rolls back after completion (for DML operations)
ephemeralTest("insert and query") { conn =>
for
_ <- conn.executeUpdate("INSERT INTO users VALUES (1, 'Alice')")
count <- conn.executeQuery("SELECT COUNT(*) FROM users").map(_.head)
yield assertCount(count, 1)
}
// Test that actually commits (for DDL operations)
persistentTest("create table") { conn =>
conn.executeUpdate("CREATE TABLE IF NOT EXISTS test_table (id INT)")
}
}
Available assertion helpers:
| Method | Description |
|---|---|
assertCount(result, expected) |
Assert row count |
assertEmpty(result) |
Assert empty result set |
assertRowsUnordered(result, expected) |
Assert rows regardless of order |
assertRowsOrdered(result, expected) |
Assert rows in exact order |
2. New DSL Helper Functions
The following functions have been added to ldbc.dsl.syntax.HelperFunctionsSyntax.
ident() — Safe SQL identifier escaping
val tableName = "my_table"
sql"SELECT * FROM ${ident(tableName)}"
// → SELECT * FROM `my_table`
Wraps identifiers in backticks and removes NUL characters to prevent SQL injection.
when() — Conditional SQL fragments
val limit = 10
sql"SELECT * FROM users" ++ when(limit > 0)(sql" LIMIT $limit")
paginate() — Pagination helper
// With offset
sql"SELECT * FROM users " ++ paginate(limit = 20, offset = 40)
// → SELECT * FROM users LIMIT ? OFFSET ?
// Without offset
sql"SELECT * FROM users " ++ paginate(limit = 20)
// → SELECT * FROM users LIMIT ?
Throws IllegalArgumentException if limit or offset is negative.
3. OpenTelemetry Type-Safe Semantic Conventions Migration
TelemetryAttribute string constants have been migrated to the type-safe API from the otel4s-semconv library. This is an internal change with no direct impact on user code.
Before (0.6.x) — internal implementation:
TelemetryAttribute.dbSystemName
TelemetryAttribute.serverAddress(host)
TelemetryAttribute.dbNamespace(db)
TelemetryAttribute.dbOperationName(op)
TelemetryAttribute.dbQueryText(sql)
After (0.7.x) — internal implementation:
DbAttributes.DbSystemName(DbAttributes.DbSystemNameValue.Mysql.value)
ServerAttributes.ServerAddress(host)
DbAttributes.DbNamespace(db)
DbAttributes.DbOperationName(op)
DbAttributes.DbQueryText(sql)
What remains in TelemetryAttribute are MySQL-specific attributes (DB_MYSQL_VERSION, DB_MYSQL_THREAD_ID, DB_MYSQL_AUTH_PLUGIN) and the SqlOperation object only.
4. Enhanced Scala Native Support
sbt-scala-native has been upgraded from 0.4.17 to 0.5.10. Scala Native 0.5 introduces official multithreading support, which significantly advances ldbc's Scala Native capabilities.
Multithreading Support in Scala Native 0.5
Scala Native 0.4 only supported single-threaded execution, but 0.5 enables true multithreaded execution.
Cats Effect 3.7.0 responds to this change by porting the JVM's WorkStealingThreadPool and IORuntime to Scala Native 0.5. As a result, the following features are now available on Scala Native:
WorkStealingThreadPool: A work-stealing thread pool equivalent to the JVM now runs on Native- epoll / kqueue support: Non-blocking I/O polling via
epollon Linux andkqueueon macOS/BSD - Full
IORuntimesupport: Fiber scheduling works nearly on par with the JVM
Fiber Model and ThreadLocal Incompatibility
Because Cats Effect Fibers can migrate freely between threads, the HikariCP-style approach of using ThreadLocal for connection pool caching does not apply. ldbc's connection pool implementation (ConcurrentBag) accounts for this constraint by adopting lock-free shared data structures using Ref[F, ...] and Queue[F, ...].
5. Code Generator YAML Parser Migration
The YAML parser for JS/Native platforms has been migrated from circe-scala-yaml (armanbilge) to scala-yaml (VirtusLab). There are no API changes for users of the code generator.
Breaking Changes
Java 11 Support Dropped
Java 11 (corretto@11) is no longer supported.
Supported Java versions: 17, 21, 25
Scala Version Update
The minimum supported Scala version has been updated from Scala 3.7.x to Scala 3.8.x.
| Before (0.6.x) | After (0.7.x) | |
|---|---|---|
| Scala version | 3.7.4 | 3.8.3 |
Deprecated APIs
The following APIs are deprecated in 0.7.0 and will be removed in a future release.
| API | Deprecated in | Replacement |
|---|---|---|
sc(identifier) |
0.7.0 | ident(identifier) |
Connection.fromSocketGroup(...) |
0.7.0 | Connection.fromNetwork(...) |
SSL.fromKeyStoreFile(java.nio.file.Path, ...) |
0.7.0 | SSL.fromKeyStoreFile(fs2.io.file.Path, ...) |
Migration Guide
Replace sc() with ident()
The sc() function is deprecated. Please migrate to ident().
Before (0.6.x):
sql"SELECT * FROM ${sc(tableName)}"
After (0.7.x):
sql"SELECT * FROM ${ident(tableName)}"
// → SELECT * FROM `tableName`
ident() wraps identifiers in backticks, making it safe against SQL injection for table and column names.
Replace Connection.fromSocketGroup with fromNetwork
Before (0.6.x):
Connection.fromSocketGroup(socketGroup, host, port, user, password, database)
After (0.7.x):
Connection.fromNetwork(network, host, port, user, password, database)
Update the path type for SSL.fromKeyStoreFile
Before (0.6.x):
import java.nio.file.Paths
SSL.fromKeyStoreFile(Paths.get("/path/to/keystore"), password, keyPassword)
After (0.7.x):
import fs2.io.file.Path
SSL.fromKeyStoreFile(Path("/path/to/keystore"), password, keyPassword)
Adopt the testing modules
You can migrate existing rollback logic to ldbc-testkit.
Add dependencies to build.sbt:
// Framework-agnostic
libraryDependencies += "io.github.takapi327" %% "ldbc-testkit" % "0.7.0" % Test
// MUnit integration
libraryDependencies += "io.github.takapi327" %% "ldbc-testkit-munit" % "0.7.0" % Test
After (0.7.x):
import ldbc.testkit.munit.LdbcSuite
class UserRepositoryTest extends LdbcSuite {
ephemeralTest("can create a user") { conn =>
for
_ <- conn.executeUpdate("INSERT INTO users (name) VALUES ('Alice')")
count <- conn.executeQuery("SELECT COUNT(*) FROM users").map(_.head)
yield assertCount(count, 1)
}
}
Summary
Migrating to 0.7.x brings the following benefits:
- Dedicated testing modules:
ldbc-testkitandldbc-testkit-munitmake it easy to write tests with automatic rollback and MUnit integration - Richer DSL helpers:
ident(),when(), andpaginate()enable safer and more readable SQL construction - Type-safe OpenTelemetry: Migration to the semantic conventions library improves the robustness of internal implementation
- Enhanced Scala Native support: Upgrading to
sbt-scala-native 0.5.ximproves cross-platform support with true multithreading
The impact on user code is primarily the migration of deprecated APIs (sc() → ident(), fromSocketGroup → fromNetwork) and updating Java/Scala version requirements.