Skip to content

Add validate (dry-run) mode to JDBC connection string#234

Closed
ryannedolan wants to merge 1 commit into
mainfrom
rdolan/validate-mode-dry-run
Closed

Add validate (dry-run) mode to JDBC connection string#234
ryannedolan wants to merge 1 commit into
mainfrom
rdolan/validate-mode-dry-run

Conversation

@ryannedolan

@ryannedolan ryannedolan commented Jun 16, 2026

Copy link
Copy Markdown
Collaborator

Summary

  • Added mode=validate connection property.

Details

Introduce mode=validate, a dry-run flavor alongside mode=apply. In validate mode every DDL statement (CREATE, DROP, FIRE/PAUSE/RESUME) is fully parsed, planned, and validated — including deployer-level validation — but no real objects are created, updated, or deleted.

With respect to OR REPLACE, validate behaves like apply: an already-existing object is treated as an in-place update rather than an error. This means validate and apply both have slightly different semantics from the default create mode. Validate and apply are designed for checked-in "as code" DDL files, whereas the default mode is more for typical interactive or imperative API-driven execution.

The upshot is that OR REPLACE is essentially optional in apply mode, and thus also optional in validate mode.

Testing Done

Ran the SQL CLI with mode=validate, which correctly validates but does not actually deploy anything:

0: Hoptimator> create view bar as select 2, 3, 4;
INFO Validating statement: CREATE VIEW `BAR` AS
SELECT 2, 3, 4
INFO Validated sql statement. The view is named BAR and has path [DEFAULT, BAR]
INFO Validating deployable resources for view BAR
INFO Validated view BAR
INFO Specifying view (dry-run) BAR; skipping deployment
---->%----
INFO CREATE VIEW BAR completed
No rows affected (0.955 seconds)

Notice "dry-run ... skipping deployment" in the output.

@github-actions

github-actions Bot commented Jun 16, 2026

Copy link
Copy Markdown

Code Coverage

Overall Project 84.65% -0.11% 🟢
Files changed 87.5% 🟢

File Coverage
HoptimatorDdlExecutor.java 90.48% -1.51% 🟢
HoptimatorDdlUtils.java 86.06% -1.04% 🟢

@jogrogan jogrogan 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.

Is the intent for this to supersede SPECIFY mode? We are currently using this as a sort of dry-run via !specify from the cli or internally we call it plan mode. See HoptimatorDdlUtils.specifyFromSql. This mode does not support all SQL types today, notably create view or drop but that seems like a much easier extension than defining a new type.

@ryannedolan

Copy link
Copy Markdown
Collaborator Author

SPECIFY mode?

I was worried about breaking SPECIFY but looks like my VALIDATE just maps to SPECIFY in most cases anyway. sgtm, will tweak.

@ryannedolan

Copy link
Copy Markdown
Collaborator Author

I was worried about breaking SPECIFY

@jogrogan looks like SPECIFY and VALIDATE are slightly different after all. SPECIFY doesn't update the internal schema, but VALIDATE does. This is because the !specify command is supposed to have zero effects, while a sequence of DDL statements in VALIDATE mode should modify the in-memory schema.

For example, consider these two statements:

create foo ...;
create bar as select * from foo;

If these are run as separate !specify commands, the second shouldn't know about 'foo', since it was never actually created. (Thus an error.) But if these are statements in validate mode, the second statement should know about the first. (Thus success.)

@ryannedolan ryannedolan force-pushed the rdolan/validate-mode-dry-run branch from 032e631 to 4a9a703 Compare June 17, 2026 18:06
@ryannedolan ryannedolan requested a review from jogrogan June 17, 2026 18:07
@jogrogan

Copy link
Copy Markdown
Collaborator

I was worried about breaking SPECIFY

@jogrogan looks like SPECIFY and VALIDATE are slightly different after all. SPECIFY doesn't update the internal schema, but VALIDATE does. This is because the !specify command is supposed to have zero effects, while a sequence of DDL statements in VALIDATE mode should modify the in-memory schema.

For example, consider these two statements:

create foo ...;
create bar as select * from foo;

If these are run as separate !specify commands, the second shouldn't know about 'foo', since it was never actually created. (Thus an error.) But if these are statements in validate mode, the second statement should know about the first. (Thus success.)

How would this work in practice? After a validate is complete we don’t want statements to work on a schema that doesn’t actually exist. We would need someway to either issue all validate SQL as a single request or clean up when all validates are done

@ryannedolan

Copy link
Copy Markdown
Collaborator Author

we don’t want statements to work on a schema that doesn’t actually exist

Yes, that's why it's a connection property and not a bang command. There is no !validate, only mode=validate. After the connection is closed, the schema changes are gone and nothing has been deployed.

Introduce `mode=validate`, a dry-run flavor alongside `mode=apply`. Every
DDL statement (CREATE, DROP, FIRE/PAUSE/RESUME) is fully parsed, planned,
and validated — including deployer-level validation — but no real object
is created, updated, or deleted.

A dry-run still evolves the in-memory Calcite schema so a series of
statements validates against each other: e.g. a dry-run DROP VIEW followed
by a query against that view fails validation, even though no real View was
deleted. To make this explicit, DdlMode's old `mutable()` is split into two
axes: `executeDeployers` (the real side effect) and `persistsSchema`
(whether in-memory changes are kept). VALIDATE persists schema but deploys
nothing; SPECIFY (the `!specify` renderer) restores. With respect to
OR REPLACE, validate is apply-like and never errors on an existing object.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@ryannedolan ryannedolan force-pushed the rdolan/validate-mode-dry-run branch from 4a9a703 to db5881f Compare June 17, 2026 18:40
Comment on lines +238 to +241
@Override
boolean shouldRestoreSchema() {
return false;
}

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 believe CREATE and UPDATE still need restore behavior. This is the case where a deployer fails and we need to rollback the in memory map.

@jogrogan

Copy link
Copy Markdown
Collaborator

we don’t want statements to work on a schema that doesn’t actually exist

Yes, that's why it's a connection property and not a bang command. There is no !validate, only mode=validate. After the connection is closed, the schema changes are gone and nothing has been deployed.

Got it, read through the changes and all makes sense now

@ryannedolan

Copy link
Copy Markdown
Collaborator Author

This PR got a little muddy, so scrapped and rewrote in #235

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