Skip to content

fix: address review of the dialect resolution changes - #362

Merged
zantvoort merged 1 commit into
mainfrom
fix/dialect-resolution-review-followup
Aug 3, 2026
Merged

fix: address review of the dialect resolution changes#362
zantvoort merged 1 commit into
mainfrom
fix/dialect-resolution-review-followup

Conversation

@zantvoort

Copy link
Copy Markdown
Collaborator

Follow-up to #360, which merged before its review comments were addressed. Three of the five were raised inline, two were suppressed; all five held up.

Resolving the dialect no longer opens a connection

SchemaValidator.of(DataSource) resolved the dialect while constructing the validator, which reached the database for its product name. Building a validator could therefore fail on connection pool initialisation, authentication or the network before validate() was ever called.

validate() already holds an open connection, and Providers.getSqlDialect(Connection, StormConfig) already exists, so the dialect is resolved there instead. The extra connection is gone rather than moved. A dialect passed explicitly to the three-argument factory still wins, and ORMTemplateImpl keeps resolving from its own data source with its own config.

This also removes the helper that duplicated Providers.getSqlDialect(DataSource, StormConfig), including its fallback branch, which the default provider made unreachable.

Discovery is recorded per table

Constraint discovery was recorded for the schema as a whole. Under the JDBC metadata strategy, which asks per table, one table a driver could not answer for disabled primary and unique key validation for every table. A view that does not support getPrimaryKeys would have hidden real mismatches across the schema.

Discovery is now recorded per table, so a failure costs only the table it happened on. The bulk strategies read every table in one query, so their success or failure still covers the whole schema, which the same per-table record expresses.

Primary keys and unique keys are separate kinds

They were one KEY kind, but the JDBC metadata strategy reads them with separate calls: getPrimaryKeys and getIndexInfo. A driver that could not report unique indexes therefore also cost the primary keys. They are now PRIMARY_KEY and UNIQUE_KEY, and each failure comment names the kind it belongs to rather than saying "keys" in a foreign key block.

Tests

Two tests in DatabaseSchemaTest cover the new precision, using a DatabaseMetaData proxy that fails one call for one table:

  • a failed read for one table leaves the other tables discovered
  • a failed unique key read leaves the primary keys discovered

Unlike the tests in #360, these two cannot be run against the previous code to show them failing: the enum constants and the isDiscovered signature both changed, so there is no earlier version to point them at. They hold by construction.

The regression tests from #360 still bite: pointing the deferred resolution back at the product-blind lookup fails two of them.

Full reactor on this base: BUILD SUCCESS, 7240 tests.

Resolving the dialect while constructing a SchemaValidator opened a JDBC
connection, so merely creating one could fail on pool initialisation,
authentication or the network before validate() was ever called. The
dialect is now resolved inside validate(), from the connection it already
holds, which removes the extra connection rather than moving it. The
helper that duplicated Providers.getSqlDialect(DataSource, StormConfig)
goes with it.

Constraint discovery was recorded for the schema as a whole, so one table
that a driver could not answer for disabled primary and unique key
validation for every other table, hiding mismatches unrelated to it.
Discovery is now recorded per table.

Primary keys and unique keys were recorded as one kind although the JDBC
metadata strategy reads them with separate calls, so a driver that could
not report unique indexes also cost the primary keys. They are separate
kinds now, and each failure comment names the kind it belongs to.
Copilot AI review requested due to automatic review settings August 2, 2026 13:04
@zantvoort zantvoort added this to the 1.13.1 milestone Aug 2, 2026

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Pull request overview

This PR is a follow-up to #360 to refine schema validation behavior by (1) deferring SQL dialect resolution until validation time (so building a SchemaValidator doesn’t need to open a connection) and (2) making constraint discovery tracking more precise (per-table, and with primary/unique keys tracked separately) to avoid over-skipping validation when JDBC metadata calls fail partially.

Changes:

  • Move dialect resolution from SchemaValidator.of(DataSource, …) construction time into validate() using the already-open validation connection.
  • Track constraint discovery per table and split “keys” into PRIMARY_KEY vs UNIQUE_KEY to prevent unrelated failures from disabling validation broadly.
  • Add regression tests using a DatabaseMetaData proxy to simulate per-table/per-method JDBC metadata failures.

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 1 comment.

File Description
storm-core/src/test/java/st/orm/core/template/impl/DatabaseSchemaTest.java Adds JDBC-metadata failure simulation tests to verify per-table discovery and PK/UK separation.
storm-core/src/main/java/st/orm/core/template/impl/SchemaValidator.java Defers dialect resolution to validation time and threads the resolved dialect through schema reads/validation.
storm-core/src/main/java/st/orm/core/template/impl/DatabaseSchema.java Changes constraint discovery tracking to be per-table and splits key kinds into PRIMARY_KEY / UNIQUE_KEY.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines 119 to 133
/**
* A kind of constraint a schema read discovers.
*
* <p>Each kind is read by one query (or one set of metadata calls) per strategy, so a failure applies to the
* kind as a whole. See {@link #isDiscovered(ConstraintKind)} for why the outcome is recorded.</p>
* <p>The kinds are separate because a strategy can read one and fail on another: the JDBC metadata strategy
* asks for each with its own call. See {@link #isDiscovered(String, ConstraintKind)} for why the outcome is
* recorded.</p>
*/
public enum ConstraintKind {
/** Primary keys and unique keys, which every strategy reads together. */
KEY,
/** Primary keys. */
PRIMARY_KEY,
/** Unique keys. */
UNIQUE_KEY,
/** Foreign keys. */
FOREIGN_KEY
}
@zantvoort
zantvoort merged commit d8991c7 into main Aug 3, 2026
8 checks passed
@zantvoort
zantvoort deleted the fix/dialect-resolution-review-followup branch August 3, 2026 10:17
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.

2 participants