Skip to content

Add Spark 4.x / Scala 2.13 support (#22) - #24

Merged
dolfinus merged 11 commits into
MTSWebServices:developfrom
CMBCKSRL:spark4-scala213-support
Sep 24, 2026
Merged

dolfinus merged 11 commits into
MTSWebServices:developfrom
CMBCKSRL:spark4-scala213-support

Conversation

@CMBCKSRL

@CMBCKSRL CMBCKSRL commented Aug 24, 2026 •

Copy link
Copy Markdown
Contributor

Cross-build the dialect against two Spark / Scala lines, selected with -PsparkProfile (default spark3, unchanged behaviour):

spark3 -> Scala 2.12 / Spark 3.5.x / Java 8-11 -> spark-dialect-extension_2.12
spark4 -> Scala 2.13 / Spark 4.x / Java 17 -> spark-dialect-extension_2.13

Build layout (per maintainer guidance in #22):

  • Split the single module into Gradle sub-projects: version-agnostic common (runtime registry + shared test fixtures), and one implementation module per Spark line (spark35, spark41). Only the profile-compatible module is included, and each publishes a single fat jar bundling common + its dialect. The registry selects the implementation at runtime from the Spark version, so one Scala 2.13 artifact serves every Spark 4.x minor release.
  • Tests are split per Spark version (spark35/spark41) instead of using in-test conditionals; shared infrastructure lives in common test fixtures.

Spark 4 specifics:

  • Override JdbcDialect.isObjectNotFoundException to detect ClickHouse error code 60 (UNKNOWN_TABLE) via the JDBC SQLException vendor code (locale independent), so writes to a not-yet-existing table work.
  • Add the standard --add-opens JVM args to the test task on Java 9+.
  • Version-specific array-read expectations: several Array(Int16/Int32/Int64/ Float32/Float64) now read successfully with driver 0.7.x; the rest surface as COLUMN_ARRAY_ELEMENT_TYPE_MISMATCH.
  • Scalafix is limited to the spark3 profile (no semanticdb-scalac for the Scala 2.13 patch Spark 4 pulls in); Scalafmt runs on both.

Extract ClickhouseDialectRegistry.dialectClassName so the version dispatch is unit-testable without an active Spark session (Spark 4's getActiveSession filters out non-usable/mocked sessions).

CI test and release workflows run both profiles with the matching Java version.

Change Summary

Related issue number

Checklist

  • Commit message and PR title is comprehensive
  • Keep the change as small as possible
  • Unit and integration tests for the changes exist
  • Tests pass on CI and coverage does not decrease
  • Documentation reflects the changes where applicable
  • My PR is ready to review.

Cross-build the dialect against two Spark / Scala lines, selected with
`-PsparkProfile` (default `spark3`, unchanged behaviour):

  spark3 -> Scala 2.12 / Spark 3.5.x / Java 8-11 -> spark-dialect-extension_2.12
  spark4 -> Scala 2.13 / Spark 4.x   / Java 17   -> spark-dialect-extension_2.13

Build layout (per maintainer guidance in MTSWebServices#22):
- Split the single module into Gradle sub-projects: version-agnostic `common`
  (runtime registry + shared test fixtures), and one implementation module per
  Spark line (`spark35`, `spark41`). Only the profile-compatible module is
  included, and each publishes a single fat jar bundling `common` + its dialect.
  The registry selects the implementation at runtime from the Spark version, so
  one Scala 2.13 artifact serves every Spark 4.x minor release.
- Tests are split per Spark version (spark35/spark41) instead of using in-test
  conditionals; shared infrastructure lives in `common` test fixtures.

Spark 4 specifics:
- Override `JdbcDialect.isObjectNotFoundException` to detect ClickHouse error
  code 60 (UNKNOWN_TABLE) via the JDBC `SQLException` vendor code (locale
  independent), so writes to a not-yet-existing table work.
- Add the standard `--add-opens` JVM args to the test task on Java 9+.
- Version-specific array-read expectations: several `Array(Int16/Int32/Int64/
  Float32/Float64)` now read successfully with driver 0.7.x; the rest surface as
  `COLUMN_ARRAY_ELEMENT_TYPE_MISMATCH`.
- Scalafix is limited to the spark3 profile (no semanticdb-scalac for the Scala
  2.13 patch Spark 4 pulls in); Scalafmt runs on both.

Extract `ClickhouseDialectRegistry.dialectClassName` so the version dispatch is
unit-testable without an active Spark session (Spark 4's `getActiveSession`
filters out non-usable/mocked sessions).

CI test and release workflows run both profiles with the matching Java version.
@dolfinus
dolfinus requested review from dolfinus and matveeysv and removed request for matveeysv August 24, 2026 09:41
Comment thread .github/workflows/release.yml Outdated
Comment thread .github/workflows/tests_clickhouse.yml Outdated
Comment thread docs/using_the_dialect.md Outdated
Comment thread CONTRIBUTING.md Outdated
Comment thread CONTRIBUTING.md Outdated
Comment thread CONTRIBUTING.md Outdated
Comment thread CONTRIBUTING.md Outdated
Comment thread README.md Outdated
CMBCKSRL and others added 8 commits August 24, 2026 17:36
Co-authored-by: Maxim Martynov <martinov_m_s_@mail.ru>
Co-authored-by: Maxim Martynov <martinov_m_s_@mail.ru>
Co-authored-by: Maxim Martynov <martinov_m_s_@mail.ru>
Co-authored-by: Maxim Martynov <martinov_m_s_@mail.ru>
Co-authored-by: Maxim Martynov <martinov_m_s_@mail.ru>
Co-authored-by: Maxim Martynov <martinov_m_s_@mail.ru>
Co-authored-by: Maxim Martynov <martinov_m_s_@mail.ru>
Co-authored-by: Maxim Martynov <martinov_m_s_@mail.ru>
Comment thread .github/workflows/tests_clickhouse.yml
…bServices#22 review)

Address review feedback: avoid copy-pasting the dialect implementation between
Spark versions. All type-mapping logic now lives in a single
`ClickhouseDialectBase` in the version-agnostic `common` module; the per-version
modules are thin subclasses:

- spark35: `object ClickhouseDialectExtension extends ClickhouseDialectBase`
- spark41: same, plus the Spark-4-only `isObjectNotFoundException` override.

The implementation modules now compileOnly-depend on `common` (the fat jar
already bundles the `common` classes, so this stays out of the published POM).

The spark41 dialect keeps being compiled against Spark 4.1.x (where
`isObjectNotFoundException` was introduced) but the artifact also runs on Spark
4.0.x: there `JdbcUtils.tableExists` uses the older `Try { probe }.isSuccess`
logic and never calls the method, so it is inert and the older behaviour is
unaffected.
@dolfinus
dolfinus requested a review from matveeysv September 24, 2026 08:30
@dolfinus
dolfinus merged commit 5839ea0 into MTSWebServices:develop Sep 24, 2026
6 checks passed
@dolfinus

Copy link
Copy Markdown
Member

@CMBCKSRL that is awesome, thank you!

@github-actions

Copy link
Copy Markdown

Coverage

Overall Project 5.31% -0.18% ❌
Files changed 96.3% 🍏

Module Coverage
spark41 6.23% -0.33% 🍏
spark41 6.23% -0.33% 🍏
spark35 4.15% 🍏
spark35 4.15% 🍏
Files
Module File Coverage
spark41 ClickhouseDialectExtension.scala 6.23% -0.33% 🍏
spark41 ClickhouseDialectExtension.scala 6.23% -0.33% 🍏
spark35 ClickhouseDialectExtension.scala 4.15% 🍏
spark35 ClickhouseDialectExtension.scala 4.15% 🍏

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.

3 participants