Skip to content

fix(snowflake): recognise query sources with leading comments - #377

Open
barveP wants to merge 2 commits into
apache:mainfrom
barveP:fix/snowflake-query-source
Open

fix(snowflake): recognise query sources with leading comments#377
barveP wants to merge 2 commits into
apache:mainfrom
barveP:fix/snowflake-query-source

Conversation

@barveP

@barveP barveP commented Sep 10, 2026

Copy link
Copy Markdown

Summary

_parse_source in the Snowflake converter decided "query or table" with a fixed prefix check (SELECT , SELECT\n, SELECT\t, WITH …). A query that starts with a --, // or /* */ comment, uses \r\n after the keyword, is wrapped in parentheses, or has no whitespace after SELECT fell through to the relation path, which split the text on dots and emitted an uppercased database/schema/table with no warning:

source: |
  -- revenue source
  SELECT amount FROM db.schema.orders

became base_table: {database: "-- REVENUE SOURCE\nSELECT AMOUNT FROM DB", schema: SCHEMA, table: ORDERS}.

This PR:

  • adds _is_query_source, which skips leading whitespace, SQL comments and opening parentheses, then matches SELECT/WITH only when the next character cannot continue an unquoted identifier. SELECT_RESULTS and SELECT$ARCHIVE stay relations; SELECT*FROM, SELECT/*c*/ and CRLF after the keyword are queries. Query text is emitted verbatim as base_table.definition, which Snowflake documents for query-backed tables.
  • makes the relation path require three valid quoted or unquoted identifiers and raise OssieConversionError otherwise, so unrecognised text can no longer become a database name.

No behaviour change for existing physical-table or plain-query inputs: all 107 existing tests pass unchanged, and 23 tests are added (query shapes, relation-shaped garbage rejection, a keyword-prefixed table name and a $ identifier as controls, and one end-to-end conversion). The change applies cleanly alongside #338. The Honeydew and NVIDIA converters have the same prefix check and will get follow-up PRs referencing #376.

Related Issues

Fixes #376

Checklist

Specification

  • Spec changes are included in core-spec/ and follow the existing structure
  • Spec changes have been discussed on the mailing list or in a linked issue
  • Breaking changes to the spec are clearly called out in the summary

Ontology

  • Ontology changes in ontology/ are consistent with spec changes
  • New or modified terms are defined and documented

Converters

  • Converter logic in converters/ is updated to reflect spec or ontology changes
  • New converters include tests under the converter's test directory

Validation

  • Validation rules in validation/ are updated if the spec changed
  • New validation cases are covered by tests

Documentation

  • docs/ is updated to reflect any user-facing changes
  • New features or behaviors are documented with examples where appropriate
  • CONTRIBUTING.md is updated if the contribution process changed

Examples

  • examples/ are added or updated for any new spec constructs or converter support

Tests

  • All existing tests pass (pytest / CI green)
  • New functionality is covered by tests

Compliance

  • ASF license headers are present on all new source files
  • No third-party dependencies are added without PMC/IPMC approval

A dataset source that is a SQL query but does not start with the bare
SELECT/WITH keyword (leading -- or /* */ comment, CRLF after the keyword,
surrounding parentheses, or no whitespace as in SELECT*FROM) fell through
to the relation path, which split the text on dots and emitted an
uppercased bogus database/schema/table with no warning.

Detect queries after skipping leading whitespace, SQL comments and opening
parentheses, matching SELECT/WITH as a whole word so names such as
SELECT_RESULTS stay relations. Query text is emitted verbatim as
base_table.definition. The relation path now requires three valid quoted
or unquoted identifiers and raises otherwise.

Fixes apache#376
The keyword check used a \b word boundary, but Snowflake allows `$` in
unquoted identifiers, so a valid table reference such as
select$archive.public.orders was classified as a query. Match the keyword
only when the next character cannot continue an unquoted identifier.

Also skip Snowflake's `// ...` single-line comments before a query, and
cover both cases with tests.
Comment on lines +432 to +437
_LEADING_SQL_TRIVIA = re.compile(
r"^(?:\s+|--[^\n]*(?:\n|$)|//[^\n]*(?:\n|$)|/\*.*?\*/)+", re.DOTALL
)
_QUERY_KEYWORD = re.compile(r"^(?:SELECT|WITH)(?![A-Za-z0-9_$])", re.IGNORECASE)
_UNQUOTED_IDENTIFIER = re.compile(r"^[A-Za-z_][A-Za-z0-9_$]*$")
_QUOTED_IDENTIFIER = re.compile(r'^"(?:[^"]|"")+"$')

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Probably a question for @khush-bhatia but I see sqlglot used in other parts of Ossie & it supports the Snowflake dialect. I wonder if directly parsing would be a bit easier for handling edge cases when compared to regex

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Thanks, that could make this simpler. Happy to try SQLGlot here.
@khush-bhatia, what do you think?

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.

Snowflake converter turns a query source with a leading comment into a fake table

2 participants