Skip to content

Require a source after FROM or TO in COPY - #144

Closed
kvlonge wants to merge 3 commits into
mainfrom
fix/copy-from-source
Closed

kvlonge wants to merge 3 commits into
mainfrom
fix/copy-from-source

Conversation

@kvlonge

@kvlonge kvlonge commented Nov 7, 2026

Copy link
Copy Markdown
Contributor

Stacked on #143 (its single settlement commit ee4cc0d is the first commit here), so it lands after #142 and #143.

COPY INTO 'azure://…' FROM v1 = ( ) ; is a syntax error in Snowflake (1003, receipt in import 159, run c9-ex-00), but the parser accepted it. The source list stops before a name followed by =, because it takes that name for the first copy option. So FROM ended up with no source, and the option loop read v1 = ( ) as an option named V1. An empty source after FROM or TO is now a parse error.

  • Now refused (SQ0001): … FROM v1 = ( ), … FROM v1 = 1, COPY INTO t1 FROM ( x = 1 ).
  • Still accepted: COPY INTO <table> with no FROM, FROM a stage, a URL, a table with CREDENTIALS, a ( SELECT … ), and the sqlglot corpus COPY shapes I probed.
  • Test: two acceptance rows in test_snowflake_recorded.rs. The 1003 row fails without the fix. The CREDENTIALS neighbour (recorded 1008, after parsing) stays accepted.

syntax-coverage diff coverage/syntax/baseline.json at 16a35f1:

  • Forms gained or lost: none. Obligations lost: none. stale is empty.
  • Obligations gained: 22, against Settle ten cases from receipts already on main #143's 5. The 17 added here are copy-into-location o018, o046, o189, o421, o424, o449, o452, o474, o477, o526, o527, o534 and o535, which goes from disagreement to met, plus copy-into-table…externallocation o121, o160, o179 and o597.
  • Receipts the parser contradicts drop from 5128 to 5115. The only local parse failures are still the same two (abs o008, coalesce o011).

Checks: sqlquack-syntax and sqlquack-syntax-coverage tests, clippy -D warnings, fmt and the hygiene scan. The full gate runs at the slot.

A rebuild with the case builder settles ten cases whose receipts landed without a rebuild:
six observed cases take the expect their receipts agree on (three reject, three accept with
a semantic stage), and four accepted cases gain the semantic stage their receipts record.
No case is added or removed and no SQL, setup or session changes.
The source list stops before a name followed by =, taking it for the first copy option, so
COPY INTO <location> FROM v1 = ( ) parsed with no source and read v1 = ( ) as an option.
Snowflake rejects it as a syntax error (1003). An empty source after FROM or TO is now a
parse error; COPY INTO <table> with no FROM still parses.
The empty-source check ran in every dialect and mode, so PostgreSQL COPY statements that
polyglot also refuses failed with a different message in the exact check. It now applies
only where Snowflake's statement-context rules do, as the other Snowflake refusals.
kvlonge added a commit that referenced this pull request Nov 7, 2026
kvlonge added a commit that referenced this pull request Nov 7, 2026

kvlonge commented Nov 8, 2026

Copy link
Copy Markdown
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.

@kvlonge kvlonge closed this Nov 8, 2026
@kvlonge
kvlonge deleted the fix/copy-from-source branch November 9, 2026 21:31
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.

1 participant