Repository navigation
Conversation
Case setup of CREATE TABLE with NUMBER and VARCHAR columns and INSERT INTO it VALUES of literals now converts: the tables join the case's schema and their DuckDB statements run before the query, with the run database and schema placeholders read as DuckDB's memory.main. Every other setup statement still refuses, as do constraints, defaults, quoted names and values a column would round. Incomplete: SET variables, CREATE TYPE and SEMANTIC VIEW, the ALTER SESSION profile overlay, docs, and a full verify are not done. Checked: the new setup test only.
conversion/constants.rs is at 2,000 lines on main, and the BINARY rules add to it. The 601-line table of time zone names Snowflake was recorded accepting now lives in time_zones/constants.rs. No behaviour change.
…part 2, slice 2) SET of a variable, or of a list of them, to a literal, NULL or a scalar subquery is recorded during setup, and $name reads the expression it was set to (rule.session_variable). Subqueries reading variables or calling functions whose result can change between the SET and the read refuse. Main merged in; the recorded time zone table moved out of conversion/constants.rs. Incomplete: fensu faults in convert_setup.rs (split needed), CREATE TYPE, SEMANTIC VIEW, ALTER SESSION, docs, full verify. The new rule has no case on main until the 6n2b cases land. Checked: setup tests; the 6n2b session-variable and name-resolution cases replay on a scratch merge.
convert_setup keeps only the statement loop; CREATE TABLE and INSERT live in _helpers/setup/tables.rs, SET and UNSET in variables.rs, and the helpers return what they read instead of mutating the setup. fensu reports no faults. No behaviour change.
…ts base type (D228 part 2) Setup records each CREATE TYPE name AS data_type. When the tree is built, a custom type spelled as a plain name that setup created is replaced by its base type, so casts, typing and setup CREATE TABLE columns all see the base type, as Snowflake's receipts report it. Quoted names, redefinitions, OR REPLACE, IF NOT EXISTS, qualified names, built-in type names and non-alias definitions refuse.
…(D306) Only cases/translation/expressions/session-variables.toml, which rule.session_variable needs to verify; its obligations stay with C's later landing.
…(D306) The ten result files of the five session-variables cases, as A recorded them; nothing else from that commit.
kvlonge
added a commit
that referenced
this pull request
Nov 6, 2026
DuckDB recomputes the subquery at each $name read, while Snowflake computed it once at SET time, so a later CREATE TABLE or INSERT could change the value. Such a write now refuses while the variable is set. A user-defined type's name must also parse as a custom type, so GEOGRAPHY and other names SQLQuack does not convert refuse too.
SET of one and of two variables read in a BETWEEN, a number and a text variable, case-insensitive names, a variable set from a query, and a NULL column beside a variable.
… cases (D228) sf.expressions.session-variables moves from unmeasured to matching, with its five obligations met and five statements matching; nothing else changes.
kvlonge
added a commit
that referenced
this pull request
Nov 6, 2026
Contributor
Author
|
Closing: SQLQuack lands through local-gate trains, not PR merges (D94), so open PRs only add clutter (D628/D630). The branch is kept. Any work here that isn't on main yet is tracked by the train owner and lands through a train. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
D228, part 2: verify replays a case's
setupon DuckDB. Part 1 (the case format and recorder contract) made every setup case refuse. This replays the setup statements that have receipts and still refuses the rest.What setup replays
Setup runs statement by statement, in order, and the whole case refuses at the first statement it can't replay:
CREATE TABLE/INSERT INTO … VALUES: an unqualified, unquoted table with typed NUMBER and VARCHAR columns, created once, holding literals or NULL that each column holds without rounding. Relations resolve through{{run_database}}/{{run_schema}}and unqualified names.SET/UNSETof session variables (rule.session_variable): to a literal, NULL or a deterministic scalar subquery.$namereads it in either case. A variable setup didn't SET, an UNSET of one it never set, an expression, and a subquery whose result can change between calls (RANDOM, the clock) all refuse. DuckDB computes a subquery's value at each read, while Snowflake computes it once at SET, so a CREATE TABLE or INSERT while such a variable is still set refuses (review round 1).CREATE TYPE name AS data_type: a type spelled as that plain name, in either case, resolves to its base type in casts, typing and later setup columns. That's what Snowflake's receipts report:a::ageis NUMBER(3,0), anda + bover twoagecolumns is NUMBER(4,0). Quoted names, redefinitions, OR REPLACE, IF NOT EXISTS, qualified names and non-alias definitions refuse. So does a built-in type's name: one SQLQuack converts, or one that doesn't parse as a custom type, such as GEOGRAPHY (review round 1).Not replayed (still refuse)
CREATE SEMANTIC VIEWonly as raw text (node:raw).SEMANTIC_VIEW(…)stores METRICS and DIMENSIONS in separate fields, so it loses the clause order that decides column order (semantic-view t002). Both need parser work before a rule can be receipt-backed.::addressover OBJECT(…)) was already refused, and still is.Brought in from land/d151-6n2b (ruling D306)
rule.session_variableneeds a passing case, so this PR carries the session-variables cases and their receipts, byte for byte, and nothing else from that branch: no recorder, no other cases, no obligations.cases/translation/expressions/session-variables.tomlevidence/results/{13884601cc86…,24b0b834ddee…,bbd0b6d5c294…,c41db8d3b834…,fbd897b012ca…}.{json,arrow}, the receipts of t004, t003, t001, t005 and t002All 11 blobs are identical to their source commits' (
git rev-parse <commit>:<path>). The evidence guard passes, with 10 added result files. The five cases are uncited until C lands their obligations inobligations/expressions.toml, which are left out here. A and C have been told these paths land through this PR.Evidence
In a scratch merge with
land/d151-6n2b, the 21 setup cases give:That's 13 passed and 0 failed. Unit tests in
test_case_setupcover each accepted and refused shape, including:"age"that must not resolve, an alias of an alias, and a setup column typed by an aliasSEMANTIC VIEW is a separate post-launch item (D306).
Gate
Gate (D94) on e56c888, which merges main de14f81 and is 98bdfd0 minus the baseline re-record:
make check-mergeexits 0: clippy, fensu (0 faults) and all test binaries pass.verify --require-verified --strict-errors: 12,012 cases, 7,858 passed, 1,032 diverged as expected, 3,085 refused, 37 typed, 0 pending, 0 unproven, 0 failed. 221 of 221 equivalences and rules are verified, includingrule.session_variable.translation-results --againstmain de14f81: 0 regressions and 11 changes, all gains.sf.expressions.session-variablesgoes Unmeasured → Matching (59 → 60 of 1,183 forms), its five obligations are met, and its five statements match.coverage/translation/results-baseline.jsonfrom that run. It checks clean against itself.catalogue/constants.rsand the baseline.Draft, for the auditor. GitHub Actions is blocked by billing, so the local D94 gate counts.