Skip to content

Migrated MariaDB, MySQL, PostgreSQL tests to use testcontainers to simplify local setup - #2011

Open
koperagen wants to merge 9 commits into
masterfrom
testcontainers
Open

Migrated MariaDB, MySQL, PostgreSQL tests to use testcontainers to simplify local setup #2011
koperagen wants to merge 9 commits into
masterfrom
testcontainers

Conversation

@koperagen

@koperagen koperagen commented Jul 28, 2026

Copy link
Copy Markdown
Collaborator

Tests still will not be run on CI for now. But it'll be now possible to run MariaDB, MySQL, PostgreSQL in one click, providing you have docker installed on PC. It's the only prerequisite.
Let's start with those and migrate imbd, mssql example after

For reference. Looks like their JUnit4 examples are a bit outdated and nowadays modern "container" classes do not implement "testrule" class, so we use manual lifecycle management instead
https://java.testcontainers.org/modules/databases/mysql/
https://java.testcontainers.org/modules/databases/mariadb/
https://java.testcontainers.org/modules/databases/postgres/

@koperagen
koperagen requested a review from zaleslaw July 28, 2026 15:54
st.setTime(16, java.sql.Time(System.currentTimeMillis()))
st.setTimestamp(14, SqlTimestamp(System.currentTimeMillis()))
st.setTimestamp(15, SqlTimestamp(System.currentTimeMillis()))
st.setTime(16, SqlTime(System.currentTimeMillis()))

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Automatic refactorings break such fully qualified links :( I recovered it as import alias, should survive file moves etc

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Not ready to approve

It currently introduces a dependency-resolution issue in the version catalog and a Kotlin compilation error from an unused import.

Once you've addressed the issues Copilot identified, you can request another Copilot review.

This review doesn't count toward merge requirements. Sign up for the private preview to control whether Copilot approvals count.

Pull request overview

This PR migrates the JDBC integration tests for MariaDB/MySQL/PostgreSQL to Testcontainers so contributors can run them locally with Docker, while keeping CI’s default test task free of Docker-dependent tests.

Changes:

  • Added Testcontainers dependencies to the version catalog and dataframe-jdbc test configuration.
  • Updated MariaDB/MySQL/PostgreSQL test suites to start/stop containers in @BeforeClass/@AfterClass rather than relying on localhost DBs.
  • Added a dedicated testcontainersTest Gradle task and excluded the Testcontainers package from the default test task.
File summaries
File Description
gradle/libs.versions.toml Adds Testcontainers version + catalog entries for DB modules.
dataframe-jdbc/build.gradle.kts Adds Testcontainers test deps; excludes Docker tests from test and introduces testcontainersTest.
dataframe-jdbc/src/test/kotlin/org/jetbrains/kotlinx/dataframe/io/testcontainers/postgresTest.kt Switches Postgres tests to a managed PostgreSQLContainer.
dataframe-jdbc/src/test/kotlin/org/jetbrains/kotlinx/dataframe/io/testcontainers/postgresConnectionUrlTest.kt Reworks Postgres URL parsing tests to run against a container.
dataframe-jdbc/src/test/kotlin/org/jetbrains/kotlinx/dataframe/io/testcontainers/mysqlTest.kt Switches MySQL tests to a managed MySQLContainer.
dataframe-jdbc/src/test/kotlin/org/jetbrains/kotlinx/dataframe/io/testcontainers/mariadbTest.kt Switches MariaDB tests to a managed MariaDBContainer.
dataframe-jdbc/src/test/kotlin/org/jetbrains/kotlinx/dataframe/io/testcontainers/images.kt Centralizes Docker image tags used by the Testcontainers tests.
Review details

Comments suppressed due to low confidence (2)

dataframe-jdbc/src/test/kotlin/org/jetbrains/kotlinx/dataframe/io/testcontainers/mysqlTest.kt:20

  • Unused import org.junit.Ignore will fail Kotlin compilation (unused imports are errors). The @Ignore annotation was removed, so this import should be removed too.
    dataframe-jdbc/src/test/kotlin/org/jetbrains/kotlinx/dataframe/io/testcontainers/postgresTest.kt:30
  • Unused import org.junit.Ignore will fail Kotlin compilation (unused imports are errors). The @Ignore annotation was removed, so this import should be removed too.
  • Files reviewed: 7/7 changed files
  • Comments generated: 1
  • Review effort level: Low

We're testing this review assessment. Please use 👍 or 👎 to tell us if it's correct.

Comment thread gradle/libs.versions.toml
Comment on lines +125 to +127
testcontainers-postgresql = { group = "org.testcontainers", name = "testcontainers-postgresql", version.ref = "testcontainers" }
testcontainers-mysql = { group = "org.testcontainers", name = "testcontainers-mysql", version.ref = "testcontainers" }
testcontainers-mariadb = { group = "org.testcontainers", name = "testcontainers-mariadb", version.ref = "testcontainers" }
@zaleslaw

Copy link
Copy Markdown
Collaborator

@copilot will this work on Windows or on Team City?
Could we refactor it and keep both the local and test container versions of tests, but call them in two forms - Docker Container and run on Local Database, don't mind about @ignore tag - it doesn't play any role

@zaleslaw

Copy link
Copy Markdown
Collaborator

https://gh.io/copilot-coding-agent-docs will this work on Windows or on Team City?

@Jolanrensen

Jolanrensen commented Jul 29, 2026

Copy link
Copy Markdown
Collaborator

Did you test it with it already on TC?
You can configure the gradle build-step to run in a certain Docker container like dockerImage = "cimg/android:2026.02.1" I assume, like this we could make test-containers work as well.

See https://www.jetbrains.com/help/teamcity/2026.1/gradle.html?TeamCity%20Documentation#Container+Settings and https://www.jetbrains.com/help/teamcity/2026.1/container-wrapper.html?TeamCity%20Documentation

(locally, they seem to run well, btw!)

package org.jetbrains.kotlinx.dataframe.io.testcontainers

// Available image tags: https://hub.docker.com/_/mariadb/tags
const val MARIADB_IMAGE = "mariadb:12.3.2"

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I feel like these should be configurable higher up, like in Gradle with BuildConfig. If we need to bump them, it will be difficult to find them so deeply nested

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think the question here is how often we expect to update them. It's not really a dependency exposed to our users, only a test database instance we'll use to make sure our changes to JDBC module do not break anything on isolated environment. I picked all very fresh versions that are expected to be supported for 5 years.
If we're interested, i can add renovatebot with custom rule to watch over these versions right here in images.kt. That's the only common practice i could find regarding where image versions should be stored. I believe other just keep it in sync with their production database, which is not applicable to us

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shouldn't they be updated along with the library versions of the databases?

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah no, they're different, it seems. Still, it's a test dependency from an external source, which makes it little different than other testImplementation dependencies. It can be taken offline, updated, etc. so hiding it in a source file is probably not the best way to go

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think so, i'd expect a very thorough backward compatibility

https://jdbc.postgresql.org/download/
This is the current version of the driver. Unless you have unusual requirements (running old applications or JVMs), this is the driver you should be using. It supports PostgreSQL 8.4 or newer and requires Java 6 or newer. It contains support for SSL and the javax.sql package.

https://mariadb.com/docs/connectors/mariadb-connector-j/about-mariadb-connector-j
MariaDB Connector/J is compatible with all MariaDB and MySQL server versions.

MariaDB Connector/J releases older than 1.2.0 may be compatible with server versions older than MySQL 5.5, but those MariaDB Connector/J releases aren't supported anymore.

https://dev.mysql.com/doc/connector-j/en/connector-j-versions.html
MySQL Server versions: Connector/J 26.7 supports MySQL 8.0 and up. ( first released 19 April 2018)

@koperagen koperagen Jul 29, 2026

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So we go in other direction and need to update only if we want to test new feature that is supported only in most recent database

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Tbh i don't really mind moving it to buildconfid altogether. Mostly wanted to clarify my impression that updating those is not the same as updating usual dependencies, we probably shouldn't do it frequently even if it ends up in the version catalog

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I understand :) It's comparable to us sticking to an older JUnit version since it covers all we need in our tests. Even though we don't bump it often, it will be bumped at some point, so it's nice to know where the single source-of-truth regarding versions exists in the project

@koperagen

koperagen commented Jul 29, 2026

Copy link
Copy Markdown
Collaborator Author

@copilot will this work on Windows or on Team City? Could we refactor it and keep both the local and test container versions of tests, but call them in two forms - Docker Container and run on Local Database, don't mind about @ignore tag - it doesn't play any role

bad copilot : ( why did it have to commit things to my branch and break CI. Besised, i'd do abstract test class and have LocalMariaDb tests + DockerMariaDb tests instead

@koperagen

Copy link
Copy Markdown
Collaborator Author

Did you test it with it already on TC?
will this work on Windows or on Team City?

On TeamCity eventually yes, need to configure teamcity to run on agents that have docker daemon

@zaleslaw

Copy link
Copy Markdown
Collaborator

Great job! Will test it next week on both MacOS and WIndows, locally and not, and it will be shipped!

@zaleslaw

zaleslaw commented Aug 4, 2026

Copy link
Copy Markdown
Collaborator

Is it possible to migrate MSSQL ? Also, it's very painful to test

@koperagen

koperagen commented Aug 4, 2026

Copy link
Copy Markdown
Collaborator Author

Is it possible to migrate MSSQL ? Also, it's very painful to test

i believe so, but i want to make sure it's ok for us because we need to accept some license agreement to use mssql

if overall we're ok with migrating to testcontainers i'll proceed with mssql

Due to licencing restrictions you are required to accept an EULA for this container image. To indicate that you accept the MS SQL Server image EULA, call the acceptLicense() method, or place a file at the root of the classpath named container-license-acceptance.txt, e.g. at src/test/resources/container-license-acceptance.txt. This file should contain the line: mcr.microsoft.com/mssql/server:2017-CU12 (or, if you are overriding the docker image name/tag, update accordingly).

Please see the microsoft-mssql-server image documentation for a link to the EULA document.

private val testcontainersTests = "org.jetbrains.kotlinx.dataframe.io.testcontainers.*"

// Implementations of the abstract database tests running against database servers on localhost
private val localDbTests = "org.jetbrains.kotlinx.dataframe.io.local.*LocalTest"

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It doesn't cover and run the MS SQL test

@zaleslaw zaleslaw left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Include in the Readme.md information and links about requirement to set up the Docker env for test conteainers with minimum technical requirements for 3 OS or link to that

  • describe the idea of test separation (it's complicated)

`## :dataframe-jdbc

This module, published as dataframe-jdbc, contains all logic and tests for DataFrame to be able to work with
JDBC data sources.

See Read from SQL databases for more information
about how to use it.

Testing

The JDBC tests are split into three tiers by how they obtain a database. This keeps the default build
fast and dependency-free, while still allowing full coverage against real database engines.

1. H2 tests (default suite)

These run against an in-memory H2 database using its compatibility modes
(MODE=PostgreSQL, MODE=MySQL, MODE=MariaDB, MODE=MSSQLServer, etc.). They need no Docker and no external
server, so they are part of the regular test task and run in CI on every build.

Location: src/test/kotlin/.../io/h2/ (e.g. PostgresH2Test, MysqlH2Test, MariadbH2Test, MssqlH2Test).
Together with the SQLite/DuckDB tests they form the baseline coverage that always runs.

./gradlew :dataframe-jdbc:test

2. Testcontainers tests (real DB engines via Docker)

These spin up real PostgreSQL, MySQL, and MariaDB engines in Docker using
Testcontainers. They give the highest-fidelity coverage but require a running
Docker daemon, so they are excluded from the default test task and run under a dedicated Gradle task.

Location: src/test/kotlin/.../io/testcontainers/ (package org.jetbrains.kotlinx.dataframe.io.testcontainers).
The container image tags are configured in build.gradle.kts via BuildConfig
(POSTGRES_IMAGE, MYSQL_IMAGE, MARIADB_IMAGE).

Requirements: a running Docker daemon.

./gradlew :dataframe-jdbc:testcontainersTest

3. Local DB tests (servers on localhost)

These connect to database servers you run yourself on localhost (e.g. Postgres on 5432, MySQL, MariaDB, MSSQL).
They are meant for local, manual verification against a specific server and are excluded from the default
test task
.

Location: src/test/kotlin/.../io/local/. Only classes whose names end with LocalTest
(PostgresLocalTest, MySqlLocalTest, MariadbLocalTest, PostgresConnectionUrlLocalTest) are picked up by the
dedicated task. The connection URLs/credentials are hardcoded in each test class, so start a matching server
before running them.

./gradlew :dataframe-jdbc:localDbTest

How the exclusions are wired

The default test task explicitly excludes both the Testcontainers and local-DB tests, and each is exposed as its
own task (see build.gradle.kts):

private val testcontainersTests = "org.jetbrains.kotlinx.dataframe.io.testcontainers.*"
private val localDbTests = "org.jetbrains.kotlinx.dataframe.io.local.*LocalTest"

tasks.test {
    filter {
        excludeTestsMatching(testcontainersTests)
        excludeTestsMatching(localDbTests)
    }
}

tasks.register<Test>("testcontainersTest") { /* includeTestsMatching(testcontainersTests) */ }
tasks.register<Test>("localDbTest")        { /* includeTestsMatching(localDbTests) */ }

So: H2 (and SQLite/DuckDB) run by default; Testcontainers and local-DB tests are opt-in via their own tasks.`

}

@Test
fun `read from all tables`() {

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Failed for me

org.postgresql.util.PSQLException: Conversion of money failed.
at org.postgresql.util.PGmoney.setValue(PGmoney.java:74)
at org.postgresql.jdbc.PgConnection.getObject(PgConnection.java:800)
at org.postgresql.jdbc.PgResultSet.getObject(PgResultSet.java:4106)
at org.jetbrains.kotlinx.dataframe.io.db.PostgreSql.getValueFromResultSet(PostgreSql.kt:73)
at org.jetbrains.kotlinx.dataframe.io.ReadJdbcKt.readAndPreprocessRowsFromResultSet(readJdbc.kt:994)
at org.jetbrains.kotlinx.dataframe.io.ReadJdbcKt.fetchAndConvertDataFromResultSet(readJdbc.kt:922)
at org.jetbrains.kotlinx.dataframe.io.ReadJdbcKt.executeQueryAndBuildDataFrame(readJdbc.kt:187)
at org.jetbrains.kotlinx.dataframe.io.ReadJdbcKt.readSqlTable(readJdbc.kt:148)
at org.jetbrains.kotlinx.dataframe.io.ReadJdbcKt.readTableAsDataFrame(readJdbc.kt:860)
at org.jetbrains.kotlinx.dataframe.io.ReadJdbcKt.readAllSqlTables(readJdbc.kt:818)
at org.jetbrains.kotlinx.dataframe.io.ReadJdbcKt.readAllSqlTables$default(readJdbc.kt:788)
at org.jetbrains.kotlinx.dataframe.io.PostgresTestBase.read from all tables(postgresTestBase.kt:324)
at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:103)
at java.base/java.lang.reflect.Method.invoke(Method.java:580)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:59)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:56)
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
at org.junit.runners.ParentRunner$3.evaluate(ParentRunner.java:306)
at org.junit.runners.BlockJUnit4ClassRunner$1.evaluate(BlockJUnit4ClassRunner.java:100)
at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:366)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:103)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:63)
at org.junit.runners.ParentRunner$4.run(ParentRunner.java:331)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:79)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:329)
at org.junit.runners.ParentRunner.access$100(ParentRunner.java:66)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:293)
at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:26)
at org.junit.internal.runners.statements.RunAfters.evaluate(RunAfters.java:27)
at org.junit.runners.ParentRunner$3.evaluate(ParentRunner.java:306)
at org.junit.runners.ParentRunner.run(ParentRunner.java:413)
at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
at org.junit.runner.JUnitCore.run(JUnitCore.java:115)
at org.gradle.api.internal.tasks.testing.junit.JUnitTestExecutor.runRequest(JUnitTestExecutor.java:175)
at org.gradle.api.internal.tasks.testing.junit.JUnitTestExecutor.accept(JUnitTestExecutor.java:84)
at org.gradle.api.internal.tasks.testing.junit.JUnitTestExecutor.accept(JUnitTestExecutor.java:47)
at org.gradle.api.internal.tasks.testing.junit.AbstractJUnitTestDefinitionProcessor.processTestDefinition(AbstractJUnitTestDefinitionProcessor.java:65)
at org.gradle.api.internal.tasks.testing.SuiteTestDefinitionProcessor.processTestDefinition(SuiteTestDefinitionProcessor.java:53)
at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:103)
at java.base/java.lang.reflect.Method.invoke(Method.java:580)
at org.gradle.internal.dispatch.MethodInvocation.invokeOn(MethodInvocation.java:77)
at org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:28)
at org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:19)
at org.gradle.internal.dispatch.ContextClassLoaderDispatch.dispatch(ContextClassLoaderDispatch.java:33)
at org.gradle.internal.dispatch.ProxyDispatchAdapter$DispatchingInvocationHandler.invoke(ProxyDispatchAdapter.java:88)
at jdk.proxy1/jdk.proxy1.$Proxy4.processTestDefinition(Unknown Source)
at org.gradle.api.internal.tasks.testing.worker.TestWorker$2.run(TestWorker.java:178)
at org.gradle.api.internal.tasks.testing.worker.TestWorker.executeAndMaintainThreadName(TestWorker.java:126)
at org.gradle.api.internal.tasks.testing.worker.TestWorker.execute(TestWorker.java:103)
at org.gradle.api.internal.tasks.testing.worker.TestWorker.execute(TestWorker.java:63)
at org.gradle.process.internal.worker.child.ActionExecutionWorker.execute(ActionExecutionWorker.java:56)
at org.gradle.process.internal.worker.child.SystemApplicationClassLoaderWorker.call(SystemApplicationClassLoaderWorker.java:122)
at org.gradle.process.internal.worker.child.SystemApplicationClassLoaderWorker.call(SystemApplicationClassLoaderWorker.java:72)
at worker.org.gradle.process.internal.worker.GradleWorkerMain.run(GradleWorkerMain.java:69)
at worker.org.gradle.process.internal.worker.GradleWorkerMain.main(GradleWorkerMain.java:74)
Caused by: java.lang.NumberFormatException: For input string: "2345 ?"
at java.base/jdk.internal.math.FloatingDecimal.readJavaFormatString(FloatingDecimal.java:2054)
at java.base/jdk.internal.math.FloatingDecimal.parseDouble(FloatingDecimal.java:110)
at java.base/java.lang.Double.parseDouble(Double.java:792)
at org.postgresql.util.PGmoney.setValue(PGmoney.java:70)
... 55 more

protected abstract val connection: Connection

@Test
fun `read from tables`() {

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Failed for me with

`2026-08-04 15:07:15:426 +0200 [Test worker] ERROR org.jetbrains.kotlinx.dataframe.io.ReadJdbc - Database operation failed: SELECT * FROM "table2"
org.postgresql.util.PSQLException: Conversion of money failed.
at org.postgresql.util.PGmoney.setValue(PGmoney.java:74)
at org.postgresql.jdbc.PgConnection.getObject(PgConnection.java:800)
at org.postgresql.jdbc.PgResultSet.getObject(PgResultSet.java:4106)
at org.jetbrains.kotlinx.dataframe.io.db.PostgreSql.getValueFromResultSet(PostgreSql.kt:73)
at org.jetbrains.kotlinx.dataframe.io.ReadJdbcKt.readAndPreprocessRowsFromResultSet(readJdbc.kt:994)
at org.jetbrains.kotlinx.dataframe.io.ReadJdbcKt.fetchAndConvertDataFromResultSet(readJdbc.kt:922)
at org.jetbrains.kotlinx.dataframe.io.ReadJdbcKt.executeQueryAndBuildDataFrame(readJdbc.kt:187)
at org.jetbrains.kotlinx.dataframe.io.ReadJdbcKt.readSqlTable(readJdbc.kt:148)
at org.jetbrains.kotlinx.dataframe.io.ReadJdbcKt.readSqlTable$default(readJdbc.kt:129)
at org.jetbrains.kotlinx.dataframe.io.PostgresTestBase.read from tables(postgresTestBase.kt:286)
at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:103)
at java.base/java.lang.reflect.Method.invoke(Method.java:580)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:59)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:56)
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
at org.junit.runners.ParentRunner$3.evaluate(ParentRunner.java:306)
at org.junit.runners.BlockJUnit4ClassRunner$1.evaluate(BlockJUnit4ClassRunner.java:100)
at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:366)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:103)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:63)
at org.junit.runners.ParentRunner$4.run(ParentRunner.java:331)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:79)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:329)
at org.junit.runners.ParentRunner.access$100(ParentRunner.java:66)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:293)
at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:26)
at org.junit.internal.runners.statements.RunAfters.evaluate(RunAfters.java:27)
at org.junit.runners.ParentRunner$3.evaluate(ParentRunner.java:306)
at org.junit.runners.ParentRunner.run(ParentRunner.java:413)
at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
at org.junit.runner.JUnitCore.run(JUnitCore.java:115)
at org.gradle.api.internal.tasks.testing.junit.JUnitTestExecutor.runRequest(JUnitTestExecutor.java:175)
at org.gradle.api.internal.tasks.testing.junit.JUnitTestExecutor.accept(JUnitTestExecutor.java:84)
at org.gradle.api.internal.tasks.testing.junit.JUnitTestExecutor.accept(JUnitTestExecutor.java:47)
at org.gradle.api.internal.tasks.testing.junit.AbstractJUnitTestDefinitionProcessor.processTestDefinition(AbstractJUnitTestDefinitionProcessor.java:65)
at org.gradle.api.internal.tasks.testing.SuiteTestDefinitionProcessor.processTestDefinition(SuiteTestDefinitionProcessor.java:53)
at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:103)
at java.base/java.lang.reflect.Method.invoke(Method.java:580)
at org.gradle.internal.dispatch.MethodInvocation.invokeOn(MethodInvocation.java:77)
at org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:28)
at org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:19)
at org.gradle.internal.dispatch.ContextClassLoaderDispatch.dispatch(ContextClassLoaderDispatch.java:33)
at org.gradle.internal.dispatch.ProxyDispatchAdapter$DispatchingInvocationHandler.invoke(ProxyDispatchAdapter.java:88)
at jdk.proxy1/jdk.proxy1.$Proxy4.processTestDefinition(Unknown Source)
at org.gradle.api.internal.tasks.testing.worker.TestWorker$2.run(TestWorker.java:178)
at org.gradle.api.internal.tasks.testing.worker.TestWorker.executeAndMaintainThreadName(TestWorker.java:126)
at org.gradle.api.internal.tasks.testing.worker.TestWorker.execute(TestWorker.java:103)
at org.gradle.api.internal.tasks.testing.worker.TestWorker.execute(TestWorker.java:63)
at org.gradle.process.internal.worker.child.ActionExecutionWorker.execute(ActionExecutionWorker.java:56)
at org.gradle.process.internal.worker.child.SystemApplicationClassLoaderWorker.call(SystemApplicationClassLoaderWorker.java:122)
at org.gradle.process.internal.worker.child.SystemApplicationClassLoaderWorker.call(SystemApplicationClassLoaderWorker.java:72)
at worker.org.gradle.process.internal.worker.GradleWorkerMain.run(GradleWorkerMain.java:69)
at worker.org.gradle.process.internal.worker.GradleWorkerMain.main(GradleWorkerMain.java:74)
Caused by: java.lang.NumberFormatException: For input string: "2345 ?"
at java.base/jdk.internal.math.FloatingDecimal.readJavaFormatString(FloatingDecimal.java:2054)
at java.base/jdk.internal.math.FloatingDecimal.parseDouble(FloatingDecimal.java:110)
at java.base/java.lang.Double.parseDouble(Double.java:792)
at org.postgresql.util.PGmoney.setValue(PGmoney.java:70)
... 53 more

Failed to read from database. Query: SELECT * FROM "table2", Database: postgresql
java.lang.IllegalStateException: Failed to read from database. Query: SELECT * FROM "table2", Database: postgresql
at org.jetbrains.kotlinx.dataframe.io.ReadJdbcKt.executeQueryAndBuildDataFrame(readJdbc.kt:193)
at org.jetbrains.kotlinx.dataframe.io.ReadJdbcKt.readSqlTable(readJdbc.kt:148)
at org.jetbrains.kotlinx.dataframe.io.ReadJdbcKt.readSqlTable$default(readJdbc.kt:129)
at org.jetbrains.kotlinx.dataframe.io.PostgresTestBase.read from tables(postgresTestBase.kt:286)
at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:103)
at java.base/java.lang.reflect.Method.invoke(Method.java:580)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:59)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:56)
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
at org.junit.runners.ParentRunner$3.evaluate(ParentRunner.java:306)
at org.junit.runners.BlockJUnit4ClassRunner$1.evaluate(BlockJUnit4ClassRunner.java:100)
at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:366)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:103)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:63)
at org.junit.runners.ParentRunner$4.run(ParentRunner.java:331)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:79)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:329)
at org.junit.runners.ParentRunner.access$100(ParentRunner.java:66)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:293)
at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:26)
at org.junit.internal.runners.statements.RunAfters.evaluate(RunAfters.java:27)
at org.junit.runners.ParentRunner$3.evaluate(ParentRunner.java:306)
at org.junit.runners.ParentRunner.run(ParentRunner.java:413)
at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
at org.junit.runner.JUnitCore.run(JUnitCore.java:115)
at org.gradle.api.internal.tasks.testing.junit.JUnitTestExecutor.runRequest(JUnitTestExecutor.java:175)
at org.gradle.api.internal.tasks.testing.junit.JUnitTestExecutor.accept(JUnitTestExecutor.java:84)
at org.gradle.api.internal.tasks.testing.junit.JUnitTestExecutor.accept(JUnitTestExecutor.java:47)
at org.gradle.api.internal.tasks.testing.junit.AbstractJUnitTestDefinitionProcessor.processTestDefinition(AbstractJUnitTestDefinitionProcessor.java:65)
at org.gradle.api.internal.tasks.testing.SuiteTestDefinitionProcessor.processTestDefinition(SuiteTestDefinitionProcessor.java:53)
at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:103)
at java.base/java.lang.reflect.Method.invoke(Method.java:580)
at org.gradle.internal.dispatch.MethodInvocation.invokeOn(MethodInvocation.java:77)
at org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:28)
at org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:19)
at org.gradle.internal.dispatch.ContextClassLoaderDispatch.dispatch(ContextClassLoaderDispatch.java:33)
at org.gradle.internal.dispatch.ProxyDispatchAdapter$DispatchingInvocationHandler.invoke(ProxyDispatchAdapter.java:88)
at jdk.proxy1/jdk.proxy1.$Proxy4.processTestDefinition(Unknown Source)
at org.gradle.api.internal.tasks.testing.worker.TestWorker$2.run(TestWorker.java:178)
at org.gradle.api.internal.tasks.testing.worker.TestWorker.executeAndMaintainThreadName(TestWorker.java:126)
at org.gradle.api.internal.tasks.testing.worker.TestWorker.execute(TestWorker.java:103)
at org.gradle.api.internal.tasks.testing.worker.TestWorker.execute(TestWorker.java:63)
at org.gradle.process.internal.worker.child.ActionExecutionWorker.execute(ActionExecutionWorker.java:56)
at org.gradle.process.internal.worker.child.SystemApplicationClassLoaderWorker.call(SystemApplicationClassLoaderWorker.java:122)
at org.gradle.process.internal.worker.child.SystemApplicationClassLoaderWorker.call(SystemApplicationClassLoaderWorker.java:72)
at worker.org.gradle.process.internal.worker.GradleWorkerMain.run(GradleWorkerMain.java:69)
at worker.org.gradle.process.internal.worker.GradleWorkerMain.main(GradleWorkerMain.java:74)
Caused by: org.postgresql.util.PSQLException: Conversion of money failed.
at org.postgresql.util.PGmoney.setValue(PGmoney.java:74)
at org.postgresql.jdbc.PgConnection.getObject(PgConnection.java:800)
at org.postgresql.jdbc.PgResultSet.getObject(PgResultSet.java:4106)
at org.jetbrains.kotlinx.dataframe.io.db.PostgreSql.getValueFromResultSet(PostgreSql.kt:73)
at org.jetbrains.kotlinx.dataframe.io.ReadJdbcKt.readAndPreprocessRowsFromResultSet(readJdbc.kt:994)
at org.jetbrains.kotlinx.dataframe.io.ReadJdbcKt.fetchAndConvertDataFromResultSet(readJdbc.kt:922)
at org.jetbrains.kotlinx.dataframe.io.ReadJdbcKt.executeQueryAndBuildDataFrame(readJdbc.kt:187)
... 47 more
Caused by: java.lang.NumberFormatException: For input string: "2345 ?"
at java.base/jdk.internal.math.FloatingDecimal.readJavaFormatString(FloatingDecimal.java:2054)
at java.base/jdk.internal.math.FloatingDecimal.parseDouble(FloatingDecimal.java:110)
at java.base/java.lang.Double.parseDouble(Double.java:792)
at org.postgresql.util.PGmoney.setValue(PGmoney.java:70)
... 53 more

Conversion of money failed.
org.postgresql.util.PSQLException: Conversion of money failed.
at app//org.postgresql.util.PGmoney.setValue(PGmoney.java:74)
at app//org.postgresql.jdbc.PgConnection.getObject(PgConnection.java:800)
at app//org.postgresql.jdbc.PgResultSet.getObject(PgResultSet.java:4106)
at app//org.jetbrains.kotlinx.dataframe.io.db.PostgreSql.getValueFromResultSet(PostgreSql.kt:73)
at app//org.jetbrains.kotlinx.dataframe.io.ReadJdbcKt.readAndPreprocessRowsFromResultSet(readJdbc.kt:994)
at app//org.jetbrains.kotlinx.dataframe.io.ReadJdbcKt.fetchAndConvertDataFromResultSet(readJdbc.kt:922)
at app//org.jetbrains.kotlinx.dataframe.io.ReadJdbcKt.executeQueryAndBuildDataFrame(readJdbc.kt:187)
at app//org.jetbrains.kotlinx.dataframe.io.ReadJdbcKt.readSqlTable(readJdbc.kt:148)
at app//org.jetbrains.kotlinx.dataframe.io.ReadJdbcKt.readSqlTable$default(readJdbc.kt:129)
at app//org.jetbrains.kotlinx.dataframe.io.PostgresTestBase.read from tables(postgresTestBase.kt:286)
at java.base@21.0.6/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:103)
at java.base@21.0.6/java.lang.reflect.Method.invoke(Method.java:580)
at app//org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:59)
at app//org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
at app//org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:56)
at app//org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
at app//org.junit.runners.ParentRunner$3.evaluate(ParentRunner.java:306)
at app//org.junit.runners.BlockJUnit4ClassRunner$1.evaluate(BlockJUnit4ClassRunner.java:100)
at app//org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:366)
at app//org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:103)
at app//org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:63)
at app//org.junit.runners.ParentRunner$4.run(ParentRunner.java:331)
at app//org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:79)
at app//org.junit.runners.ParentRunner.runChildren(ParentRunner.java:329)
at app//org.junit.runners.ParentRunner.access$100(ParentRunner.java:66)
at app//org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:293)
at app//org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:26)
at app//org.junit.internal.runners.statements.RunAfters.evaluate(RunAfters.java:27)
at app//org.junit.runners.ParentRunner$3.evaluate(ParentRunner.java:306)
at app//org.junit.runners.ParentRunner.run(ParentRunner.java:413)
at app//org.junit.runner.JUnitCore.run(JUnitCore.java:137)
at app//org.junit.runner.JUnitCore.run(JUnitCore.java:115)
at org.gradle.api.internal.tasks.testing.junit.JUnitTestExecutor.runRequest(JUnitTestExecutor.java:175)
at org.gradle.api.internal.tasks.testing.junit.JUnitTestExecutor.accept(JUnitTestExecutor.java:84)
at org.gradle.api.internal.tasks.testing.junit.JUnitTestExecutor.accept(JUnitTestExecutor.java:47)
at org.gradle.api.internal.tasks.testing.junit.AbstractJUnitTestDefinitionProcessor.processTestDefinition(AbstractJUnitTestDefinitionProcessor.java:65)
at org.gradle.api.internal.tasks.testing.SuiteTestDefinitionProcessor.processTestDefinition(SuiteTestDefinitionProcessor.java:53)
at java.base@21.0.6/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:103)
at java.base@21.0.6/java.lang.reflect.Method.invoke(Method.java:580)
at org.gradle.internal.dispatch.MethodInvocation.invokeOn(MethodInvocation.java:77)
at org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:28)
at org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:19)
at org.gradle.internal.dispatch.ContextClassLoaderDispatch.dispatch(ContextClassLoaderDispatch.java:33)
at org.gradle.internal.dispatch.ProxyDispatchAdapter$DispatchingInvocationHandler.invoke(ProxyDispatchAdapter.java:88)
at jdk.proxy1/jdk.proxy1.$Proxy4.processTestDefinition(Unknown Source)
at org.gradle.api.internal.tasks.testing.worker.TestWorker$2.run(TestWorker.java:178)
at org.gradle.api.internal.tasks.testing.worker.TestWorker.executeAndMaintainThreadName(TestWorker.java:126)
at org.gradle.api.internal.tasks.testing.worker.TestWorker.execute(TestWorker.java:103)
at org.gradle.api.internal.tasks.testing.worker.TestWorker.execute(TestWorker.java:63)
at org.gradle.process.internal.worker.child.ActionExecutionWorker.execute(ActionExecutionWorker.java:56)
at org.gradle.process.internal.worker.child.SystemApplicationClassLoaderWorker.call(SystemApplicationClassLoaderWorker.java:122)
at org.gradle.process.internal.worker.child.SystemApplicationClassLoaderWorker.call(SystemApplicationClassLoaderWorker.java:72)
at app//worker.org.gradle.process.internal.worker.GradleWorkerMain.run(GradleWorkerMain.java:69)
at app//worker.org.gradle.process.internal.worker.GradleWorkerMain.main(GradleWorkerMain.java:74)
Caused by: java.lang.NumberFormatException: For input string: "2345 ?"
at java.base/jdk.internal.math.FloatingDecimal.readJavaFormatString(FloatingDecimal.java:2054)
at java.base/jdk.internal.math.FloatingDecimal.parseDouble(FloatingDecimal.java:110)
at java.base/java.lang.Double.parseDouble(Double.java:792)
at org.postgresql.util.PGmoney.setValue(PGmoney.java:70)
... 53 more`

}

@Test
fun `read columns of different types to check type mapping`() {

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Conversion of money failed.
org.postgresql.util.PSQLException: Conversion of money failed.
at app//org.postgresql.util.PGmoney.setValue(PGmoney.java:74)
at app//org.postgresql.jdbc.PgConnection.getObject(PgConnection.java:800)
at app//org.postgresql.jdbc.PgResultSet.getObject(PgResultSet.java:4106)
at app//org.jetbrains.kotlinx.dataframe.io.db.PostgreSql.getValueFromResultSet(PostgreSql.kt:73)
at app//org.jetbrains.kotlinx.dataframe.io.ReadJdbcKt.readAndPreprocessRowsFromResultSet(readJdbc.kt:994)
at app//org.jetbrains.kotlinx.dataframe.io.ReadJdbcKt.fetchAndConvertDataFromResultSet(readJdbc.kt:922)
at app//org.jetbrains.kotlinx.dataframe.io.ReadJdbcKt.executeQueryAndBuildDataFrame(readJdbc.kt:187)
at app//org.jetbrains.kotlinx.dataframe.io.ReadJdbcKt.readSqlTable(readJdbc.kt:148)
at app//org.jetbrains.kotlinx.dataframe.io.ReadJdbcKt.readSqlTable$default(readJdbc.kt:129)
at app//org.jetbrains.kotlinx.dataframe.io.PostgresTestBase.read columns of different types to check type mapping(postgresTestBase.kt:359)
at java.base@21.0.6/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:103)
at java.base@21.0.6/java.lang.reflect.Method.invoke(Method.java:580)
at app//org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:59)
at app//org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
at app//org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:56)
at app//org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
at app//org.junit.runners.ParentRunner$3.evaluate(ParentRunner.java:306)
at app//org.junit.runners.BlockJUnit4ClassRunner$1.evaluate(BlockJUnit4ClassRunner.java:100)
at app//org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:366)
at app//org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:103)
at app//org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:63)
at app//org.junit.runners.ParentRunner$4.run(ParentRunner.java:331)
at app//org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:79)
at app//org.junit.runners.ParentRunner.runChildren(ParentRunner.java:329)
at app//org.junit.runners.ParentRunner.access$100(ParentRunner.java:66)
at app//org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:293)
at app//org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:26)
at app//org.junit.internal.runners.statements.RunAfters.evaluate(RunAfters.java:27)
at app//org.junit.runners.ParentRunner$3.evaluate(ParentRunner.java:306)
at app//org.junit.runners.ParentRunner.run(ParentRunner.java:413)
at app//org.junit.runner.JUnitCore.run(JUnitCore.java:137)
at app//org.junit.runner.JUnitCore.run(JUnitCore.java:115)
at org.gradle.api.internal.tasks.testing.junit.JUnitTestExecutor.runRequest(JUnitTestExecutor.java:175)
at org.gradle.api.internal.tasks.testing.junit.JUnitTestExecutor.accept(JUnitTestExecutor.java:84)
at org.gradle.api.internal.tasks.testing.junit.JUnitTestExecutor.accept(JUnitTestExecutor.java:47)
at org.gradle.api.internal.tasks.testing.junit.AbstractJUnitTestDefinitionProcessor.processTestDefinition(AbstractJUnitTestDefinitionProcessor.java:65)
at org.gradle.api.internal.tasks.testing.SuiteTestDefinitionProcessor.processTestDefinition(SuiteTestDefinitionProcessor.java:53)
at java.base@21.0.6/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:103)
at java.base@21.0.6/java.lang.reflect.Method.invoke(Method.java:580)
at org.gradle.internal.dispatch.MethodInvocation.invokeOn(MethodInvocation.java:77)
at org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:28)
at org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:19)
at org.gradle.internal.dispatch.ContextClassLoaderDispatch.dispatch(ContextClassLoaderDispatch.java:33)
at org.gradle.internal.dispatch.ProxyDispatchAdapter$DispatchingInvocationHandler.invoke(ProxyDispatchAdapter.java:88)
at jdk.proxy1/jdk.proxy1.$Proxy4.processTestDefinition(Unknown Source)
at org.gradle.api.internal.tasks.testing.worker.TestWorker$2.run(TestWorker.java:178)
at org.gradle.api.internal.tasks.testing.worker.TestWorker.executeAndMaintainThreadName(TestWorker.java:126)
at org.gradle.api.internal.tasks.testing.worker.TestWorker.execute(TestWorker.java:103)
at org.gradle.api.internal.tasks.testing.worker.TestWorker.execute(TestWorker.java:63)
at org.gradle.process.internal.worker.child.ActionExecutionWorker.execute(ActionExecutionWorker.java:56)
at org.gradle.process.internal.worker.child.SystemApplicationClassLoaderWorker.call(SystemApplicationClassLoaderWorker.java:122)
at org.gradle.process.internal.worker.child.SystemApplicationClassLoaderWorker.call(SystemApplicationClassLoaderWorker.java:72)
at app//worker.org.gradle.process.internal.worker.GradleWorkerMain.run(GradleWorkerMain.java:69)
at app//worker.org.gradle.process.internal.worker.GradleWorkerMain.main(GradleWorkerMain.java:74)
Caused by: java.lang.NumberFormatException: For input string: "2345 ?"
at java.base/jdk.internal.math.FloatingDecimal.readJavaFormatString(FloatingDecimal.java:2054)
at java.base/jdk.internal.math.FloatingDecimal.parseDouble(FloatingDecimal.java:110)
at java.base/java.lang.Double.parseDouble(Double.java:792)
at org.postgresql.util.PGmoney.setValue(PGmoney.java:70)
... 53 more

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It could be a problem with dependency or visibility PostgreSQL classes and the result of decision to include PG types

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is it local DB or testcontainer image?

@zaleslaw

zaleslaw commented Aug 4, 2026

Copy link
Copy Markdown
Collaborator

Yes, we can proceed with MSSQL Testcontainers.

  1. MSSQL is used only during tests and is not distributed with Kotlin DataFrame.
  2. The SQL Server Docker image remains a separate external component, so it does not affect our Apache 2.0 license.
  3. acceptLicense() only sets ACCEPT_EULA=Y inside the container; it does not send TeamCity environment data to Microsoft.

Our purpose is clear: use MSSQL only for automated integration testing.

@koperagen

@zaleslaw

zaleslaw commented Aug 4, 2026

Copy link
Copy Markdown
Collaborator

Could help with, but need to verify #563

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants