Skip to content

v0.3.0-beta3

Compare
Choose a tag to compare
@takapi327 takapi327 released this 03 Jun 13:50
· 1150 commits to master since this release

ldbc v0.3.0-beta3 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.

Functional modification: support for connector switching

The Scala MySQL connector has added new support for switching connections between JDBC and ldbc.

The modification allows developers to flexibly select database connections using the JDBC or ldbc libraries, depending on the requirements of the project. This allows them to utilise the functionality of the different libraries and increases flexibility in setting up and operating the connection.

How to switch

First, set up common dependencies.

libraryDependencies += "io.github.takapi327" %% "ldbc-dsl" % "0.3.0-beta3"

For Cross-Platform projects (JVM, JS, and/or Native):

libraryDependencies += "io.github.takapi327" %%% "ldbc-dsl" % "0.3.0-beta3"

The dependency package used depends on whether the database connection is made via a connector using the Java API or a connector provided by ldbc.

Use jdbc connector

libraryDependencies += "io.github.takapi327" %% "jdbc-connector" % "0.3.0-beta3"

Use ldbc connector

libraryDependencies += "io.github.takapi327" %% "ldbc-connector" % "0.3.0-beta3"

For Cross-Platform projects (JVM, JS, and/or Native)

libraryDependencies += "io.github.takapi327" %%% "ldbc-connector" % "0.3.0-beta3"

Usage

The difference in usage is that there are differences in the way connections are built between jdbc and ldbc.

Caution

ldbc is currently under active development. Please note that current functionality may therefore be deprecated or changed in the future.

jdbc connector

val ds = new com.mysql.cj.jdbc.MysqlDataSource()
ds.setServerName("127.0.0.1")
ds.setPortNumber(13306)
ds.setDatabaseName("world")
ds.setUser("ldbc")
ds.setPassword("password")

val datasource = jdbc.connector.MysqlDataSource[IO](ds)

val connection: Resource[IO, Connection[IO]] =
  Resource.make(datasource.getConnection)(_.close())

ldbc connector

val connection: Resource[IO, Connection[IO]] =
  ldbc.connector.Connection[IO](
    host     = "127.0.0.1",
    port     = 3306,
    user     = "ldbc",
    password = Some("password"),
    database = Some("ldbc"),
    ssl      = SSL.Trusted
  )

The connection process to the database can be carried out using the connections established by each of these methods.

val result: IO[(List[Int], Option[Int], Int)] = connection.use { conn =>
  (for
    result1 <- sql"SELECT 1".toList[Int]
    result2 <- sql"SELECT 2".headOption[Int]
    result3 <- sql"SELECT 3".unsafe[Int]
  yield (result1, result2, result3)).readOnly(conn)
}

Using the query builder

ldbc provides not only plain queries but also type-safe database connections using the query builder.

The first step is to create a schema for use by the query builder.

ldbc maintains a one-to-one mapping between Scala models and database table definitions. The mapping between the properties held by the model and the columns held by the table is done in definition order. Table definitions are very similar to the structure of Create statements. This makes the construction of table definitions intuitive for the user.

case class User(
  id: Long,
  name: String,
  age: Option[Int],
)

val table = Table[User]("user")(                     // CREATE TABLE `user` (
  column("id", BIGINT, AUTO_INCREMENT, PRIMARY_KEY), //   `id` BIGINT NOT NULL AUTO_INCREMENT PRIMARY KEY,
  column("name", VARCHAR(255)),                      //   `name` VARCHAR(255) NOT NULL,
  column("age", INT.UNSIGNED.DEFAULT(None)),         //   `age` INT unsigned DEFAULT NULL
)              

The next step is to build a TableQuery using the schema you have created.

import ldbc.query.builder.TableQuery

val userQuery = TableQuery[IO, User](table)

Finally, you can use the query builder to create a query.

val result: IO[List[User]] = connection.use { conn =>
  userQuery.selectAll.toList[User].readOnly(conn)
  // "SELECT `id`, `name`, `age` FROM user"
}

Functional modification: extension of plain query construction.

A new feature has been added to the MySQL connector in Scala to treat static strings as query strings.

Our Scala-made MySQL connector has extended the plain query construction functionality to increase query flexibility. In particular, a new sc function has been introduced that allows static strings to be used in string completion. This allows static strings to be incorporated directly as part of the query.

Examples of use and details of functions

Introducing the sc function: sc stands for static context, which can be used in string completion to safely incorporate static strings, such as table names, into queries.

Assembling the query

val table = sc("table_name")
sql"SELECT * FROM $table WHERE id = ${1L}"

In the above code, table_name is incorporated into the query as a static string using sc and "SELECT * FROM table_name WHERE id = ?" The SQL is generated in the form "SELECT * FROM table_name WHERE id = ? In this way, the placeholder (?) corresponds to a dynamic parameter (in this case 1L).

This extension makes it easier to create more dynamic and secure queries. This new method is particularly useful when multiple table names or SQL fragments need to be combined dynamically from the programme.

Functional modification: provision of functions to support plain query construction.

The MySQL connector in Scala adds a new feature for building queries using dynamic values.

The enhancements allow developers to build SQL queries more flexibly and simplify the dynamic generation of SQL, especially when dealing with multiple values and conditions. Key new features include utility functions for efficiently building combinations of values, in, notIn, and, or and conditional expressions.

Main new functions

  • values function: allows multiple values to be incorporated into a VALUES expression, e.g. used for batch insertion.
  • in and notIn functions: generate IN and NOT IN clauses based on a specified list of values.
  • and and or functions: combine multiple conditions with AND or OR to form logical conditional expressions.
  • whereAnd and whereOr functions: incorporate multiple conditions into a WHERE clause to enhance query filtering.

examples showing the use (of a word)

val ids = List(1, 2, 3)  // Dynamically generated values
val query = sql"SELECT * FROM users WHERE" ++ in(sql"id", ids)
// SELECT * FROM users WHERE id IN (?, ?, ?)

With this retrofit, developers using the MySQL connector from Scala will be able to build programmatically complex queries easily and safely. This will improve the performance and maintainability of applications and allow for more diverse data manipulation.

What's Changed

🚀 Features

💪 Enhancement

🪲 Bug Fixes

🔧 Refactoring

📖 Documentation

⛓️ Dependency update

Full Changelog: v0.3.0-beta2...v0.3.0-beta3