Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactor/2024 08 modification codec #291

Merged

Conversation

takapi327
Copy link
Owner

@takapi327 takapi327 commented Sep 9, 2024

Implementation Details

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))

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

Fixes

Fixes #xxxxx

Pull Request Checklist

  • Wrote unit and integration tests
  • Linked to Github issue with discussion and accepted design OR link to spec that describes this work.
  • Code formatting by scalafmt (sbt scalafmtAll command execution)
  • Add copyright headers to new files

References

@takapi327 takapi327 self-assigned this Sep 9, 2024
@takapi327 takapi327 added 🔧 refactor Refactoring project:queryBuilder Addition and modification of functionality to Query Builder projects project:dsl Addition and modification of functionality to DSL projects labels Sep 9, 2024
@takapi327 takapi327 added this to the 0.3.0 milestone Sep 25, 2024
@takapi327 takapi327 merged commit 1f06177 into master Sep 27, 2024
25 checks passed
@takapi327 takapi327 deleted the revert-290-revert-285-refactor/2024-08-Modification-Codec branch September 27, 2024 14:24
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
project:dsl Addition and modification of functionality to DSL projects project:queryBuilder Addition and modification of functionality to Query Builder projects 🔧 refactor Refactoring
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant