Fix SET LOCAL session-variable tracking and hostgroup routing (#6397)

Closed
RE
15d ago
+760-92

SET LOCAL innodb_lock_wait_timeout=5 bypasses ProxySQL's tracked-variable dispatch and locks the frontend to a hostgroup. A later query routed elsewhere can fail with error 9006. This change treats MySQL LOCAL like SESSION for supported tracked-variable assignments by extending the dispatch and legacy SET-parser scope regexes.

The ParserSQL session-tracking path also validates assignment scopes before normalization. Mixed LOCAL/GLOBAL, persistent, and user-variable targets fall back to forwarding the complete original statement before changing tracked state. This prevents false local success when scope stripping would otherwise turn a global assignment into a session assignment. The validation checks ParserSQL tokenizer errors directly because the vendored parser can omit a malformed assignment while reporting a successful parse. Conflicting LOCAL @@global targets are rejected as well.

Regression coverage includes lowercase syntax, quoted names, multiple LOCAL assignments, writer/reader/writer routing, and mixed-scope fallback. The live test checks backend errors and counters as well as unchanged tracked state. It runs algorithms 1 and 2 and algorithm 3 with both query-processor modes. Fixture cleanup is exception-safe, ownership is explicit, and setup/test helpers address the SonarCloud findings.

The ParserSQL digest adapter now also falls back to ProxySQL's existing dialect tokenizer when grammar parsing fails, stops early, has no AST, or cannot emit a digest. This protects the currently vendored ParserSQL 1.0.11 independently of the 1.1.0 upgrade in #6405. Successful complete-AST normalization stays unchanged; fallback formatting/options follow the legacy tokenizer. The fallback is independent of AST arena limits, retains first-comment metadata, and excludes the PostgreSQL wire terminator. Digest-constrained query rules now reject missing digest metadata instead of treating the predicate as satisfied.

Validation:

  • Full PROXYSQL31=1 make -j8 debug build passed.
  • New digest fallback suite: 110/110 assertions passed with ParserSQL 1.0.11, covering both dialects, both regex engines, unsupported DDL, incomplete input, large input, length limits, and protocol framing. Existing parser and rule-matching suites also pass 230/230 and 211/211 assertions.
  • Live digest-rule regression: 5/5 assertions passed in the isolated MySQL 8.4 runner, checking tokenizer and ParserSQL modes. The existing SET LOCAL regression was rerun and passes 261/261 assertions with the fallback installed.
  • parsersql_unit-t: 230 assertions passed, including 26 new scope and value-handling cases.
  • Existing SET parser suites: 236, 234, and 504 assertions passed.
  • reg_test_6397-set_local-t through the isolated mysql84-g1 runner: 261 assertions passed across four parser configurations, including fixture restoration.
  • The five-case mixed-scope regression reproduced 30 failing assertions in the two ParserSQL modes before the scope fix; both legacy modes passed. Further unit regressions reproduced malformed-assignment and conflicting-scope bypasses before their fixes.
  • Live validation used MySQL 8.4. The test remains registered in legacy-g1; MariaDB was not run locally.

PostgreSQL SET scope semantics are unchanged; the digest fallback and missing-metadata rule protection cover both protocols. Commits have detailed descriptions. No benchmarks are included. Remote CI and SonarCloud must validate the updated head.

Fixes #6397.


Summary by cubic

Fixes SET LOCAL session-variable tracking so statements like SET LOCAL innodb_lock_wait_timeout=5 no longer lock the frontend to a hostgroup, preventing error 9006 when a later query routes elsewhere. Treats MySQL LOCAL as a SESSION synonym at the tracked-variable dispatch gate and in the shared scope regex used by SET parser algorithms 1 and 2, and validates assignment scopes before tracking so mixed GLOBAL/PERSIST/user-variable statements are forwarded to the backend instead of being accepted as local state.

Adds a digest fallback that uses ProxySQL's tokenizer when ParserSQL cannot build a complete AST, so unsupported DDL, grammar errors, and statements exceeding AST arena limits still produce digests, and requires actual digest metadata before digest-constrained query rules match.

  • Adds unit and live regression coverage: SET parsing across all three algorithms, writer/reader/writer routing with tracked values, and mixed-scope forwarding that leaves tracked state unchanged.
  • Digest fallback preserves tokenizer options, first-comment metadata, and PostgreSQL wire-terminator handling. Missing or empty digest metadata now rejects digest-constrained rules rather than satisfying them.

Summary by CodeRabbit

  • Bug Fixes
    • SET LOCAL session-variable assignments are now recognized and tracked for routing decisions, including quoted names, varied spacing, and multiple assignments.
    • Improved compatibility for SET LOCAL statements across supported parser modes.
    • Invalid or mixed-scope SET statements no longer update tracked session-variable values.
    • SQL digests are now generated reliably when full parsing fails or encounters unsupported syntax, improving digest-based query rule matching.
    • Digest-based rules no longer match queries with missing or empty digest information.