fix(trino): support inline SQL UDFs (WITH FUNCTION ... BEGIN ... END)#41803
fix(trino): support inline SQL UDFs (WITH FUNCTION ... BEGIN ... END)#41803rusackas wants to merge 6 commits into
Conversation
Code Review Agent Run #216c6bActionable Suggestions - 0Review Details
Bito Usage GuideCommands Type the following command in the pull request comment and save the comment.
Refer to the documentation for additional commands. Configuration This repository uses Documentation & Help |
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## master #41803 +/- ##
==========================================
+ Coverage 56.62% 65.16% +8.53%
==========================================
Files 2774 2775 +1
Lines 156694 156831 +137
Branches 35771 35804 +33
==========================================
+ Hits 88725 102193 +13468
+ Misses 67138 52670 -14468
- Partials 831 1968 +1137
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
✅ Deploy Preview for superset-docs-preview ready!
To edit notification comments on pull requests, go to your Netlify project configuration. |
Code Review Agent Run #3ae36bActionable Suggestions - 0Review Details
Bito Usage GuideCommands Type the following command in the pull request comment and save the comment.
Refer to the documentation for additional commands. Configuration This repository uses Documentation & Help |
|
Ugh. Something's off with things here. The replies to codeant's comments claim Separately, |
7216898 to
32977f5
Compare
Code Review Agent Run #d4578cActionable Suggestions - 0Review Details
Bito Usage GuideCommands Type the following command in the pull request comment and save the comment.
Refer to the documentation for additional commands. Configuration This repository uses Documentation & Help |
Code Review Agent Run #1f0222Actionable Suggestions - 0Additional Suggestions - 1
Review Details
Bito Usage GuideCommands Type the following command in the pull request comment and save the comment.
Refer to the documentation for additional commands. Configuration This repository uses Documentation & Help |
|
@rusackas have we considered submitting these changes upstream directly to |
sqlglot cannot parse Trino SQL routine syntax, so queries declaring inline UDFs failed to parse in SQL Lab: the parser splits statements on every semicolon (including the ones inside BEGIN ... END routine bodies) and has no grammar for FUNCTION specifications in a WITH clause. The upstream issue (tobymao/sqlglot#5178) was closed as low priority, so this extends the Trino dialect on the Superset side. The custom dialect keeps routine bodies intact when splitting statements and parses inline function specifications into opaque InlineUDF nodes that regenerate verbatim. Trino does not allow queries inside SQL UDF bodies, so the opaque representation hides no table references from Superset's security checks. The extensions only activate on syntax that fails to parse today, so existing queries are unaffected. Fixes #26162 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Adds unit tests for the two Trino dialect branches the CI coverage gate flagged as untested: a RETURN body with no following expression, and a statement-terminating semicolon that carries an attached comment or has no trailing statement. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Add type annotations to the module-level constants and local counters in the Trino dialect, and fix the `IF (a > b) THEN` vs. scalar `IF(...)` ambiguity: an IF immediately followed by `(` is now classified as a procedural block only when the matching closing paren is followed by THEN, otherwise as a scalar function call. Adds a regression test for the parenthesized condition case. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
routine_mode only triggered when FUNCTION appeared immediately after WITH, so a WITH clause defining a regular CTE before the inline UDF (e.g. `WITH cte AS (...), FUNCTION f() ...`) never entered routine mode, letting semicolons inside the function body incorrectly split the statement. Detect FUNCTION as a fresh WITH-list entry whenever it follows WITH or a top-level comma, not just at the very start. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Adds cases for nested parens inside an `IF (...)` condition, a scalar function literally named `function` outside a routine specification, and an unbalanced `IF` condition, restoring 100% coverage on superset/sql/dialects/trino.py required by unit-tests-required. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The nested-parens regression test only checked the statement count, not that the IF condition was actually recognized as a block opener rather than a scalar call. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
de2e8ab to
e896050
Compare
Code Review Agent Run #8f3c61Actionable Suggestions - 0Review Details
Bito Usage GuideCommands Type the following command in the pull request comment and save the comment.
Refer to the documentation for additional commands. Configuration This repository uses Documentation & Help |
|
Good call @betodealmeida. Opened tobymao/sqlglot#7926 upstream, with real grammar support for the whole routine body rather than the opaque approach here. If that lands, we can drop this dialect whenever we bump sqlglot... in the meantime this PR still fixes it for the pinned version. |
|
One thing I learned while upstreaming this: per Trino's actual grammar ( |
SUMMARY
Trino queries that declare inline SQL UDFs (
WITH FUNCTION ... RETURNS ... BEGIN ... END SELECT ...) fail to parse in SQL Lab, even though they run fine in Trino itself. Two things go wrong: sqlglot splits statements on every semicolon (including the ones insideBEGIN ... ENDroutine bodies), and it has no grammar forFUNCTIONspecifications in aWITHclause. The upstream issue (tobymao/sqlglot#5178) was closed as "low priority, PRs welcome", so this fixes it on our side with a custom Trino dialect insuperset/sql/dialects/trino.py, following the same pattern as our Firebolt/Dremio/Pinot dialects.The dialect does two things: keeps routine bodies intact when chunking statements (tracking
BEGIN/CASE/IF/LOOP/REPEAT/WHILE...ENDnesting), and parses inline function specifications into opaqueInlineUDFnodes that regenerate verbatim. Trino doesn't allow queries inside SQL UDF bodies, so the opaque representation hides no table references from the security checks... table extraction, mutation detection, and limit handling all keep working on the main query. The new code paths only activate on syntax that fails to parse today (WITH FUNCTION,CREATE [OR REPLACE] FUNCTION), so existing queries are untouched — a CTE literally namedfunctionstill parses as a regular CTE, and there's a test pinning that.A procedural
IFstatement whose condition is parenthesized (IF (a > b) THEN) is disambiguated from the scalarIF()function by checking whether the matching close paren is followed byTHEN; aWITHclause with a normal CTE before the inline function (WITH cte AS (...), FUNCTION f() ...) is also handled.BEFORE/AFTER SCREENSHOTS OR ANIMATED GIF
Before (from #26162):
sql parse error: Expecting (. Line 2, Col: 29.— after, the query from the Trino docs parses, splits, and round-trips correctly.TESTING INSTRUCTIONS
Run
pytest tests/unit_tests/sql/dialects/trino_tests.py. Or with a Trino 458+ database connected, paste the example from the issue into SQL Lab and run it:ADDITIONAL INFORMATION
;characters cannot run on Superset SQL Lab Editor #26162🤖 Generated with Claude Code