Skip to content

Conversation

@yruslan
Copy link
Collaborator

@yruslan yruslan commented Nov 12, 2025

Closes #656

Summary by CodeRabbit

  • Bug Fixes
    • Improved error handling for offset operations across all supported database platforms. The system now provides explicit, descriptive error messages when encountering unsupported offset value types, replacing previous behavior that could result in silent failures or unclear errors.

@coderabbitai
Copy link

coderabbitai bot commented Nov 12, 2025

Walkthrough

All SQL generator implementations receive consistent updates: a catch-all case is added to getOffsetWhereCondition methods across 11 database systems to throw explicit IllegalArgumentException for unsupported OffsetValue types, replacing silent fallthrough behavior with user-friendly error messaging.

Changes

Cohort / File(s) Summary
SQL Generator Error Handling
pramen/core/src/main/scala/za/co/absa/pramen/core/sql/SqlGenerator{Databricks,Db2,Denodo,Generic,Hive,HsqlDb,Microsoft,MySQL,Oracle,PostgreSQL,Sas}.scala
Added catch-all pattern match case to getOffsetWhereCondition in each SQL generator to throw IllegalArgumentException with descriptive message when encountering unsupported OffsetValue types, replacing implicit fallthrough with explicit error signaling

Sequence Diagram

sequenceDiagram
    actor User
    participant Generator as SQL Generator
    participant Handler as Offset Handler

    rect rgb(240, 248, 255)
    Note over Generator,Handler: Before: Unsupported Offset Type
    User->>Generator: Request with unsupported offset
    Generator->>Handler: Pattern match on offset type
    Handler-->>Generator: Falls through / MatchError
    Generator-->>User: Runtime error (unfriendly)
    end

    rect rgb(240, 255, 240)
    Note over Generator,Handler: After: Explicit Error Handling
    User->>Generator: Request with unsupported offset
    Generator->>Handler: Pattern match on offset type
    Handler->>Handler: Catch-all case triggered
    Handler-->>Generator: IllegalArgumentException
    Generator-->>User: Clear error message with type info
    end
Loading

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~12 minutes

  • Homogeneous changes across 11 files following identical pattern
  • Each modification is a single defensive case statement addition
  • Minimal logic density; straightforward error-handling implementation
  • Primary verification task is confirming consistent application across all generators

Poem

A rabbit hops through error paths so clear,
No more mysterious matches causing fear!
Each database now speaks with honest voice,
When offset types unknown appear—there's choice!
Friendly errors guide the way ahead,
No cryptic crashes to fill hearts with dread. 🐰✨

Pre-merge checks and finishing touches

✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The PR title clearly and specifically describes the main change: adding exhaustive offset type matching in SQL generators to replace the generic Match exception with proper error handling.
Linked Issues check ✅ Passed The PR adds explicit error handling for unsupported offset types across all SQL generators, replacing the generic Match exception with user-friendly IllegalArgumentException messages as required by issue #656.
Out of Scope Changes check ✅ Passed All changes are focused on adding catch-all cases to getOffsetWhereCondition methods across SQL generator classes for unsupported offset types, directly aligned with the objective to make offset type matching exhaustive.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
✨ Finishing touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch bugfix/656-offset-values-jdbc

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

🧹 Nitpick comments (1)
pramen/core/src/main/scala/za/co/absa/pramen/core/sql/SqlGeneratorOracle.scala (1)

100-101: Excellent fix with consistent application across all SQL generators!

The catch-all case correctly prevents MatchError exceptions by throwing a clear IllegalArgumentException with the unsupported offset type included in the message. Verification confirms this pattern is consistently applied across all 11 SQL generator implementations (PostgreSQL, Oracle, Generic, MySQL, Sas, HsqlDb, Denodo, Db2, Microsoft, Hive, Databricks), ensuring uniform error handling throughout the codebase.

Optional: Consider wrapping long lines for consistency.

Line 101 and similar lines in other generators are lengthy (~140 characters). For improved readability, consider wrapping:

      case t =>
-       throw new IllegalArgumentException(s"Offset type [${t.dataType.dataTypeString}] is not supported in Oracle SQL query generator.")
+       throw new IllegalArgumentException(
+         s"Offset type [${t.dataType.dataTypeString}] is not supported in Oracle SQL query generator."
+       )
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 917de9a and 33cdd1a.

📒 Files selected for processing (11)
  • pramen/core/src/main/scala/za/co/absa/pramen/core/sql/SqlGeneratorDatabricks.scala (1 hunks)
  • pramen/core/src/main/scala/za/co/absa/pramen/core/sql/SqlGeneratorDb2.scala (1 hunks)
  • pramen/core/src/main/scala/za/co/absa/pramen/core/sql/SqlGeneratorDenodo.scala (1 hunks)
  • pramen/core/src/main/scala/za/co/absa/pramen/core/sql/SqlGeneratorGeneric.scala (1 hunks)
  • pramen/core/src/main/scala/za/co/absa/pramen/core/sql/SqlGeneratorHive.scala (1 hunks)
  • pramen/core/src/main/scala/za/co/absa/pramen/core/sql/SqlGeneratorHsqlDb.scala (1 hunks)
  • pramen/core/src/main/scala/za/co/absa/pramen/core/sql/SqlGeneratorMicrosoft.scala (1 hunks)
  • pramen/core/src/main/scala/za/co/absa/pramen/core/sql/SqlGeneratorMySQL.scala (1 hunks)
  • pramen/core/src/main/scala/za/co/absa/pramen/core/sql/SqlGeneratorOracle.scala (1 hunks)
  • pramen/core/src/main/scala/za/co/absa/pramen/core/sql/SqlGeneratorPostgreSQL.scala (1 hunks)
  • pramen/core/src/main/scala/za/co/absa/pramen/core/sql/SqlGeneratorSas.scala (1 hunks)
🧰 Additional context used
🧠 Learnings (1)
📚 Learning: 2025-06-18T08:27:21.504Z
Learnt from: yruslan
Repo: AbsaOSS/pramen PR: 611
File: pramen/core/src/main/scala/za/co/absa/pramen/core/metastore/model/MetastoreDependencyFactory.scala:29-29
Timestamp: 2025-06-18T08:27:21.504Z
Learning: In pramen/core/src/main/scala/za/co/absa/pramen/core/metastore/model/MetastoreDependencyFactory.scala, the constant variable name was changed from DATE_UNTIL_EXPR_KEY to DATE_TO_EXPR_KEY, but both constants hold the same string value "date.to". This is a variable name refactoring, not a configuration key change, so it doesn't affect backward compatibility.

Applied to files:

  • pramen/core/src/main/scala/za/co/absa/pramen/core/sql/SqlGeneratorHive.scala
  • pramen/core/src/main/scala/za/co/absa/pramen/core/sql/SqlGeneratorSas.scala
  • pramen/core/src/main/scala/za/co/absa/pramen/core/sql/SqlGeneratorDatabricks.scala
  • pramen/core/src/main/scala/za/co/absa/pramen/core/sql/SqlGeneratorGeneric.scala
🧬 Code graph analysis (9)
pramen/core/src/main/scala/za/co/absa/pramen/core/sql/SqlGeneratorDb2.scala (1)
pramen/core/src/main/scala/za/co/absa/pramen/core/bookkeeper/model/OffsetRecords.scala (1)
  • dataType (24-24)
pramen/core/src/main/scala/za/co/absa/pramen/core/sql/SqlGeneratorMySQL.scala (1)
pramen/core/src/main/scala/za/co/absa/pramen/core/bookkeeper/model/OffsetRecords.scala (1)
  • dataType (24-24)
pramen/core/src/main/scala/za/co/absa/pramen/core/sql/SqlGeneratorHsqlDb.scala (1)
pramen/core/src/main/scala/za/co/absa/pramen/core/bookkeeper/model/OffsetRecords.scala (1)
  • dataType (24-24)
pramen/core/src/main/scala/za/co/absa/pramen/core/sql/SqlGeneratorPostgreSQL.scala (1)
pramen/core/src/main/scala/za/co/absa/pramen/core/bookkeeper/model/OffsetRecords.scala (1)
  • dataType (24-24)
pramen/core/src/main/scala/za/co/absa/pramen/core/sql/SqlGeneratorMicrosoft.scala (1)
pramen/core/src/main/scala/za/co/absa/pramen/core/bookkeeper/model/OffsetRecords.scala (1)
  • dataType (24-24)
pramen/core/src/main/scala/za/co/absa/pramen/core/sql/SqlGeneratorDenodo.scala (1)
pramen/core/src/main/scala/za/co/absa/pramen/core/bookkeeper/model/OffsetRecords.scala (1)
  • dataType (24-24)
pramen/core/src/main/scala/za/co/absa/pramen/core/sql/SqlGeneratorOracle.scala (1)
pramen/core/src/main/scala/za/co/absa/pramen/core/bookkeeper/model/OffsetRecords.scala (1)
  • dataType (24-24)
pramen/core/src/main/scala/za/co/absa/pramen/core/sql/SqlGeneratorSas.scala (1)
pramen/core/src/main/scala/za/co/absa/pramen/core/bookkeeper/model/OffsetRecords.scala (1)
  • dataType (24-24)
pramen/core/src/main/scala/za/co/absa/pramen/core/sql/SqlGeneratorGeneric.scala (1)
pramen/core/src/main/scala/za/co/absa/pramen/core/bookkeeper/model/OffsetRecords.scala (1)
  • dataType (24-24)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (8)
  • GitHub Check: Test Spark 3.3.4 on Scala 2.13.16
  • GitHub Check: Test Spark 3.4.4 on Scala 2.12.20
  • GitHub Check: Test Spark 2.4.8 on Scala 2.11.12
  • GitHub Check: Test Spark 3.5.5 on Scala 2.13.16
  • GitHub Check: Test Spark 3.5.5 on Scala 2.12.20
  • GitHub Check: Test Spark 3.3.4 on Scala 2.12.20
  • GitHub Check: Test Spark 3.4.4 on Scala 2.13.16
  • GitHub Check: Test Coverage on Scala 2.12.18
🔇 Additional comments (10)
pramen/core/src/main/scala/za/co/absa/pramen/core/sql/SqlGeneratorSas.scala (1)

202-204: LGTM! Excellent fix for the match exception issue.

The catch-all case correctly handles unsupported OffsetValue types by throwing a descriptive IllegalArgumentException instead of letting a MatchError propagate. This directly addresses issue #656 where kafka offset types would cause runtime exceptions, and the error message clearly identifies both the unsupported type and which SQL generator is rejecting it.

pramen/core/src/main/scala/za/co/absa/pramen/core/sql/SqlGeneratorPostgreSQL.scala (1)

103-104: Excellent fix for the match exception issue.

This catch-all case properly addresses issue #656 by replacing the uninformative MatchError with a clear, user-friendly IllegalArgumentException that includes the unsupported offset type. The error message provides sufficient context for debugging and troubleshooting.

pramen/core/src/main/scala/za/co/absa/pramen/core/sql/SqlGeneratorHive.scala (1)

121-122: LGTM! Excellent fix for the exhaustiveness issue.

The catch-all case correctly handles unsupported offset types by throwing an explicit IllegalArgumentException with a clear error message. This replaces the previous MatchError with a user-friendly exception that identifies both the unsupported type and the specific SQL generator.

pramen/core/src/main/scala/za/co/absa/pramen/core/sql/SqlGeneratorDatabricks.scala (1)

121-122: LGTM! Consistent with other SQL generators.

The catch-all case provides the same defensive handling as in SqlGeneratorHive and other SQL generators. The error message correctly identifies the Databricks generator and includes the unsupported offset type, ensuring users can quickly diagnose configuration issues.

pramen/core/src/main/scala/za/co/absa/pramen/core/sql/SqlGeneratorGeneric.scala (1)

107-108: LGTM! Excellent fix for the match exhaustiveness issue.

The catch-all case correctly addresses issue #656 by replacing the implicit MatchError with an explicit IllegalArgumentException that provides a user-friendly error message. This ensures that unsupported offset types (like "kafka" for JDBC sources) produce clear diagnostic information rather than cryptic match exceptions.

pramen/core/src/main/scala/za/co/absa/pramen/core/sql/SqlGeneratorHsqlDb.scala (1)

107-109: Code change is correct and safe — dataType property is guaranteed accessible.

The sealed trait contract ensures all OffsetValue subtypes have the dataType property, eliminating any risk of NullPointerException. The pattern is consistently applied across 11 SQL generator implementations, confirming intentional design.

Consider adding test coverage for unsupported offset types (e.g., passing a KafkaOffsetValue to HSQLDB generator) to prevent regressions.

pramen/core/src/main/scala/za/co/absa/pramen/core/sql/SqlGeneratorDenodo.scala (1)

125-126: LGTM! Good fix for the match exception issue.

The catch-all case correctly addresses the bug by throwing a user-friendly IllegalArgumentException instead of allowing a match exception. The error message is clear and includes the unsupported type.

Verification confirms this fix is consistently applied across all 11 SQL generators (Databricks, Db2, Generic, Hive, HsqlDb, Microsoft, MySQL, Oracle, PostgreSQL, Sas, and Denodo) with identical error handling patterns.

pramen/core/src/main/scala/za/co/absa/pramen/core/sql/SqlGeneratorMySQL.scala (1)

103-104: Good defensive fallback. The explicit IllegalArgumentException avoids a scala.MatchError and gives users actionable detail about unsupported offsets in MySQL.

pramen/core/src/main/scala/za/co/absa/pramen/core/sql/SqlGeneratorMicrosoft.scala (1)

193-194: Verified: Consistent error handling across all SQL generators.

This fix properly replaces silent MatchError with explicit IllegalArgumentException across all 10 SQL generator implementations. Each generator includes:

  • Catch-all pattern case t => to capture the unsupported offset type
  • Clear error message specifying the database type (e.g., "MS SQL Server query generator", "PostgreSQL query generator")
  • Access to actual type information via t.dataType.dataTypeString for debugging

All implementations are consistent and follow the same error-handling pattern. The approach provides users with actionable feedback when using unsupported offset types (e.g., Kafka) with JDBC data sources.

pramen/core/src/main/scala/za/co/absa/pramen/core/sql/SqlGeneratorDb2.scala (1)

107-108: API usage confirmed; test coverage requires manual verification.

The fix is correctly implemented and consistent across all 11 SQL generators. The dataType.dataTypeString API is valid, as confirmed by existing usage in the OffsetValue class, and all 11 generators now consistently throw IllegalArgumentException with database-specific error messages for unsupported offset types.

However, no tests were found in SqlGeneratorDb2Suite.scala for the error handling path. Please confirm that unit tests exist to validate this catch-all case with unsupported types like KafkaValue, as their absence could leave this error path untested.

@github-actions
Copy link

Unit Test Coverage

Overall Project 83.34% -0.21% 🍏
Files changed 0%

Module Coverage
pramen:core Jacoco Report 85.28% -0.24%
Files
Module File Coverage
pramen:core Jacoco Report SqlGeneratorDenodo.scala 93.91% -3.7%
SqlGeneratorSas.scala 93.87% -2.43%
SqlGeneratorDb2.scala 93.87% -3.72%
SqlGeneratorHive.scala 93.83% -3.74%
SqlGeneratorDatabricks.scala 93.83% -3.74%
SqlGeneratorHsqlDb.scala 93.83% -3.74%
SqlGeneratorGeneric.scala 93.64% -3.86%
SqlGeneratorOracle.scala 90.71% -4.05%
SqlGeneratorPostgreSQL.scala 89.24% -3.81%
SqlGeneratorMySQL.scala 89.24% -3.81%
SqlGeneratorMicrosoft.scala 86.95% -1.11%

@yruslan yruslan merged commit e556287 into main Nov 12, 2025
9 checks passed
@yruslan yruslan deleted the bugfix/656-offset-values-jdbc branch November 12, 2025 09:01
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.

The offset value types is not exhaustive in SQL query generators

2 participants