feat: support SQL Server OPTION query hints (#161) - #2472
Open
fudianchn wants to merge 1 commit into
Open
Conversation
Parse the T-SQL OPTION (...) clause at the end of SELECT (including after
set operations and FOR XML), UPDATE and DELETE statements, following the
Query Hints documentation: multi-word keyword hints (RECOMPILE, HASH
JOIN, FORCE ORDER, OPTIMIZE FOR UNKNOWN, ...), single value arguments
(FAST 100, MAXDOP 4, MAX_GRANT_PERCENT = 25) and parenthesized argument
lists (USE HINT ('...'), OPTIMIZE FOR (@p = 1), TABLE HINT (t, INDEX
(i))).
Hints are kept in a generic OptionHint (keyword name + optional value or
ExpressionList parameters) attached via a new OptionClause, mirroring
how SQL Server keeps adding new hints without enum churn. OPTION is a
non-reserved keyword and K_OPTION followed by ( is excluded from alias
positions, so option remains usable as a column and table name. The
union hoisting lifts the clause from the last PlainSelect onto the
SetOperationList like ORDER BY and LIMIT.
Signed-off-by: 付典 <fudianchn@gmail.com>
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.
What
Adds support for the SQL Server (T-SQL)
OPTION (...)query hint clause at the end ofSELECT(including after set operations andFOR XML),UPDATEandDELETEstatements, modelled as a newOptionClauseholding a list ofOptionHints.Why
The grammar has no production for query hints (#161), so statements like
SELECT CustomerID, PersonID, StoreID FROM cte OPTION (MAXRECURSION 2)fail to parse, although this is everyday T-SQL for query tuning.How
OptionClause()production attached in four places (afterForClauseinPlainSelect, beforeLIMITin theSelectwrapper, afterLIMITinUpdate/Delete), following the Hints (Transact-SQL) - Query Hints documentation.OptionHintName()collects (possibly multi-word) keyword names (RECOMPILE,HASH JOIN,OPTIMIZE FOR UNKNOWN, ...) from identifiers, the non-reserved word range and an explicit list of reserved words usable inside hint keywords (JOIN,FOR,ORDER,UNION,EXCEPT,INTERSECT,USE,OPTIMIZE,FORCE,UNKNOWN).FAST 100,MAXDOP 4,MAX_GRANT_PERCENT = 25) or a parenthesized argument list (USE HINT ('...'),OPTIMIZE FOR (@p = 1),TABLE HINT (t, INDEX (i))), kept generically as name + value/parameters because SQL Server keeps adding new hints with every release.K_OPTIONis a non-reserved keyword;isAliasAhead()treatsK_OPTIONfollowed by(as a clause start rather than a table alias, sooptionremains usable as a column and table name.ORDER BY/LIMIT, the clause is hoisted from the lastPlainSelectonto theSetOperationList, soSELECT ... UNION SELECT ... ORDER BY ... OPTION (...)deparse in the right order.OptionClause/OptionHintplus wiring inSelect,Update,Delete, the three deparsers and the three validators.Root cause
Missing feature: the grammar has no production for the T-SQL query hint clause, so such statements always threw a
ParseException.Testing
OptionClauseTest(13 cases): the issue's SQL plus AST assertions, all hint shapes (keyword / value / equals / parameter list),UNION,FOR XML,UPDATE,DELETE, andoptionas column/table name;./gradlew test --tests ...OptionClauseTestpasses../gradlew spotlessApply checkon the branch: 4816 tests, 0 failures.Verification of the original issue
Before (master
406a4d4):CCJSqlParserUtil.parse("SELECT CustomerID, PersonID, StoreID FROM cte OPTION (MAXRECURSION 2)")throws aParseException.After: parses into
PlainSelectwithgetOption().getOptionHints().get(0)= nameMAXRECURSION, value2, and the deparse round-trips unchanged. All other query hint forms currently documented by Microsoft parse and round-trip as well.Grammar change, paired
gradle jmhruns (JSQLParserBenchmark.parseSQLStatementsonperformance.sql,version=latest, 10 forks x 10 iterations = 100 samples each, 32-core host), two interleaved pairs:406a4d4In both pairs the delta (+0.6%) is smaller than the combined confidence interval -> not statistically significant, no regression.
Limitation: T-SQL also allows
OPTION (...)afterINSERTandMERGEstatements, and theOPTIMIZE FOR (@var UNKNOWN)parameter form; these are not covered yet (the latter needs an AST representation for a variable followed by the bareUNKNOWNkeyword, e.g. a dedicated expression type or a nullable-valueVariableAssignment; both can be added in follow-ups without changing the modeling introduced here).Fixes #161