Skip to content

feat: support OPTION hints after MERGE and INSERT ... VALUES, and the OPTIMIZE FOR (@var UNKNOWN) parameter form - #2486

Open
fudianchn wants to merge 1 commit into
JSQLParser:masterfrom
fudianchn:feat/option-hints-followup
Open

feat: support OPTION hints after MERGE and INSERT ... VALUES, and the OPTIMIZE FOR (@var UNKNOWN) parameter form#2486
fudianchn wants to merge 1 commit into
JSQLParser:masterfrom
fudianchn:feat/option-hints-followup

Conversation

@fudianchn

@fudianchn fudianchn commented Aug 18, 2026

Copy link
Copy Markdown
Contributor

Description

Completes the follow-ups declared in the limitations of #2472 (SQL Server OPTION query hints):

  1. MERGE ... OPTION (...) previously failed to parse. The clause is now attached to MERGE statements, mirroring the existing UPDATE / DELETE attach points (Merge.setOption(...), deparser and validator included).
  2. INSERT INTO t (a) VALUES (1) OPTION (...) was parsed but the OPTION clause was silently dropped from the deparser output: ValuesStatementDeParser never rendered it. The modeling is unchanged (the clause lives on the inner Values select, as introduced in feat: support SQL Server OPTION query hints (#161) #2472); only the missing rendering is added.
  3. OPTIMIZE FOR (@variable_name UNKNOWN) previously failed to parse (the @var = literal form already worked via VariableAssignment). The parameter form is modeled as a new UnknownVariable expression, produced by a dedicated OptionHintParameter() production with a semantic lookahead (S_AT_IDENTIFIER followed by K_UNKNOWN), so the bare UNKNOWN keyword stays illegal everywhere else.

The expression type is the first variant named in the #2472 limitation ("a dedicated expression type or a nullable-value VariableAssignment"); the second variant would avoid the new ExpressionVisitor method but overload VariableAssignment with a non-assignment meaning.

Testing

OptionClauseTest: 5 new tests (18/18 pass), each failing on master (2 parse errors, 1 dropped clause, 2 more of the same); AST assertions pin the UnknownVariable parameter and the statement-level attach point. Full ./gradlew spotlessCheck check: 4867 tests, 0 failures, javacc warning count unchanged.

Performance

gradle jmh, JSQLParserBenchmark.parseSQLStatements on performance.sql, version=latest, 10 forks x 10 iterations (100 samples) per run, two interleaved runs per build on a 32-core host:

build run 1 run 2
master 7013909 3.707 ± 0.024 3.693 ± 0.020
this PR 1157f74 3.713 ± 0.020 3.717 ± 0.022

Mean delta +0.4% with all four confidence intervals overlapping -> no regression. (Replaces an earlier non-interleaved measurement taken under transient background load, whose runs showed ~10x wider intervals.)

… OPTIMIZE FOR (@var UNKNOWN) parameter form

Completes the follow-ups declared in the limitations of JSQLParser#2472:

- attach the OPTION clause to MERGE statements, which rejected it
  before, mirroring the existing UPDATE and DELETE attach points
- render the OPTION clause when deparsing INSERT ... VALUES: it was
  parsed into the Values select but silently dropped from the output
- model the OPTIMIZE FOR (@variable_name UNKNOWN) parameter form as a
  new UnknownVariable expression (the @var = literal form already
  worked via VariableAssignment)

Signed-off-by: 付典 <fudianchn@gmail.com>
* <a href="https://learn.microsoft.com/en-us/sql/t-sql/queries/hints-transact-sql-query">Hints
* (Transact-SQL) - Query Hints</a>.
*/
public class UnknownVariable extends ASTNodeAccessImpl implements Expression {

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.

Do we really need an extra class for this? Why not just carry a normal "Identifier" or "String" along? I would love to avoid especially the extra methods in the Visitors.

(PlainSelect) assertSqlCanBeParsedAndDeparsed(sql, true);
OptionHint optimizeFor = plainSelect.getOption().getOptionHints().get(0);
Assertions.assertEquals(1, optimizeFor.getParameters().size());
Assertions.assertTrue(optimizeFor.getParameters().get(0) instanceof UnknownVariable);

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.

Assertions should provide assertInstanceOf directly.

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.

2 participants