ldbc v0.3.0-beta8 is released.
This release adds enhancements to existing features.
Note
ldbc is pre-1.0 software and is still undergoing active development. New versions are not binary compatible with prior versions, although in most cases user code will be source compatible.
The major version will be the stable version.
What's Changed
Caution
This version is not compatible with the previous version, v0.3.0-beta7.
Bug Fix
The process to retrieve records by matching the table name and column name, such as when using JOIN, does not work as intended.
sql"SELECT c.Id, c.Name, ct.Code, ct.Name FROM city AS c JOIN country AS ct ON c.CountryCode = ct.Code"
.query[(Int, String, String, String)]
There is no problem in retrieving records by specifying the Index, but when retrieving records by specifying the column name internally, the records are not retrieved correctly because they are retrieved as Id
instead of c.Id
.
JDBC allows the retrieval of records by the combination of table name and column name, so the modification was made accordingly.
Support for custom data types (Breaking change)
When using user-defined data types, custom data types were supported using ResultSetReader
and Parameter
.
With this update, the method of supporting custom data types using ResultSetReader
and Parameter
has changed.
Encoder
Change from Parameter to Encoder for dynamic embedding in query strings.
This eliminates the need for the user to write a redundant process to receive the Effect Type, and allows for simpler implementation and use of custom data types as parameters.
enum Status(val code: Int, val name: String):
case Active extends Status(1, "Active")
case InActive extends Status(2, "InActive")
Before
given Parameter[Status] with
override def bind[F[_]](
statement: PreparedStatement[F],
index: Int,
status: Status
): F[Unit] = statement.setInt(index, status.code)
After
given Encoder[Status] with
override def encode(status: Status): Int = status.done
Encoder's encoding process can only return Scala types that can be handled by PreparedStatement.
The following types are supported at this time.
Scala Type | Methods called in PreparedStatement |
---|---|
Boolean | setBoolean |
Byte | setByte |
Short | setShort |
Int | setInt |
Long | setLong |
Float | setFloat |
Double | setDouble |
BigDecimal | setBigDecimal |
String | setString |
Array[Byte] | setBytes |
java.time.LocalDate | setDate |
java.time.LocalTime | setTime |
java.time.LocalDateTime | setTimestamp |
None | setNull |
Decoder
Change the process of getting data from ResultSet from ResultSetReader to Decoder.
This allows users to convert retrieved records into nested hierarchical data.
case class City(id: Int, name: String, countryCode: String)
case class Country(code: String, name: String)
case class CityWithCountry(city: City, country: Country)
sql"SELECT city.Id, city.Name, city.CountryCode, country.Code, country.Name FROM city JOIN country ON city.CountryCode = country.Code".query[CityWithCountry]
Using Query Builder
case class City(id: Int, name: String, countryCode: String) derives Table
case class Country(code: String, name: String) derives Table
val city = Table[City]
val country = Table[Country]
city.join(country).join((city, country) => city.countryCode === country.code)
.select((city, country) => (city.name, country.name))
.query // (String, String)
.to[Option]
city.join(country).join((city, country) => city.countryCode === country.code)
.selectAll
.query // (City, Country)
.to[Option]
Custom type decoding
Decoding of custom types will change from ResultSetReader to the following
Before
enum Custom:
case ...
given ResultSetReader[IO, Custom] =
ResultSetReader.mapping[IO, str, Custom](str => Custom.valueOf(str))
After
enum Custom:
case ...
given Decoder.Elem[Custom] =
Decoder.Elem.mapping[String, Custom](str => Custom.valueOf(str))
Query (Breaking Change)
When using selectAll
in a query built with Query Builder, the type that could be obtained with query
was a Tuple type consisting of all records in the selected table. Therefore, conversion to the model corresponding to the table had to be done explicitly using queryTo
.
This was redundant, and if the user wanted to retrieve all the records, the application would have taken that model as the income.
Therefore, the change has been made so that selections made with selectAll
are converted directly into models when query
is used. If you use select
to retrieve only specific records, the query
will still be of type Tuple. Conversion to the specified model can still be done using queryTo
.
Before
case class City(id: Int, name: String, countryCode: String) derives Table
city.selectAll.query // (Int, String, String)
After
case class City(id: Int, name: String, countryCode: String) derives Table
city.selectAll.query // City
🪲 Bug Fixes
- Bug/2024 08 fix schema alias by @takapi327 in #283
- Hotfix/2024 09 fixed result set get by name by @takapi327 in #289
- Chore/2024 09 added connection test by @takapi327 in #299
🔧 Refactoring
- Refactor/2024 08 modification codec by @takapi327 in #285
- Refactor/2024 08 modification codec by @takapi327 in #291
- Refactor/2024 09 database term from option to default catalog by @takapi327 in #300
⛓️ Dependency update
- Update scala3-library from 3.4.3 to 3.5.0 by @scala-steward in #282
- Update fs2-core, fs2-io from 3.10.2 to 3.11.0 by @scala-steward in #284
- Update otel4s-core-trace from 0.8.1 to 0.9.0 by @scala-steward in #286
- Update circe-generic from 0.14.9 to 0.14.10 by @scala-steward in #287
- Update doobie-core from 1.0.0-RC5 to 1.0.0-RC6 by @scala-steward in #295
- Update scala3-library from 3.5.0 to 3.5.1 by @scala-steward in #296
- Update sbt from 1.10.1 to 1.10.2 by @scala-steward in #292
- Update otel4s-core-trace from 0.9.0 to 0.10.0 by @scala-steward in #298
- Update sbt-scalajs, scalajs-library_2.13, ... from 1.16.0 to 1.17.0 by @scala-steward in #301
Full Changelog: v0.3.0-beta7...v0.3.0-beta8