Skip to content

fix(core): unquote backtick/double-quoted table tokens in alias resolution (#82)#143

Merged
haroya01 merged 2 commits into
mainfrom
fix/82-quoted-table-alias-resolution
May 19, 2026
Merged

fix(core): unquote backtick/double-quoted table tokens in alias resolution (#82)#143
haroya01 merged 2 commits into
mainfrom
fix/82-quoted-table-alias-resolution

Conversation

@haroya01
Copy link
Copy Markdown
Owner

@haroya01 haroya01 commented May 8, 2026

Summary

  • MissingIndexDetector.resolveAliases now matches and strips backtick / double-quote wrapping on each segment of FROM/JOIN table tokens.
  • Adds QuotedTableAliasResolutionTest with three failing-before regression cases that hit MissingIndexDetector and RedundantFilterDetector (the latter delegates to the same alias map).

Why

A targeted slice of #82. Hibernate emits backtick- or double-quoted table identifiers when hibernate.globally_quoted_identifiers=true or when the table name is a reserved word. For SQL like:

SELECT m1_0.id FROM `messages` m1_0 WHERE m1_0.user_id = ?

FROM_ALIAS (\bFROM\s+((?:\w+\.){0,2}\w+)…) only matches bare \w+ segments, so the regex didn't match at all and the alias map was empty. resolveTable("m1_0", emptyMap) then hit its Hibernate-pattern fallback ([a-z]{1,3}\d+_\d+) and returned null — silently dropping legitimate missing-index, redundant-filter, composite-index, and for-update findings on every Hibernate-emitted query that ran with quoted identifiers.

The fix:

  1. Allow any FROM/JOIN segment to be \w+, `…`, or "…".
  2. Unquote each segment in registerAlias before lowercasing so the canonical key matches the bare names the JSqlParser-driven WHERE/JOIN column extractor already produces.

The Hibernate-pattern guard in resolveTable stays — it's still the right behaviour when the FROM clause genuinely can't be parsed.

This is narrower than the full proposal in #82. The issue contemplates routing all detectors through EnhancedSqlParser for canonical alias resolution; that's a larger refactor and is intentionally out of scope here. Leaving #82 open for that follow-up.

Test plan

  • :query-audit-core:testQuotedTableAliasResolutionTest (3 new tests) plus the full suite green.
  • All-module ./gradlew test BUILD SUCCESSFUL on the local SB 3.4.x baseline.
  • Existing Hibernate-alias regression tests in FalsePositiveFixTest (hibernateAlias_mapsToFromTable, aliasedSoftDelete_*) still pass — the unquote step is a no-op when no quotes are present (early indexOf short-circuit).

Refs #82

…ution

Hibernate emits backtick- or double-quoted table identifiers under
hibernate.globally_quoted_identifiers=true (and for reserved-word table
names). MissingIndexDetector.resolveAliases used FROM_ALIAS / JOIN_ALIAS
regexes that only matched bare \w+ segments, so for SQL like
`SELECT m1_0.id FROM \`messages\` m1_0 WHERE m1_0.user_id = ?` the
alias-to-table map ended up empty.

resolveTable then hit its Hibernate-pattern fallback (m1_0 matches
[a-z]{1,3}\d+_\d+) and returned null — silently skipping legitimate
missing-index, redundant-filter, composite-index, and for-update
findings. The same issue applies whenever any FROM/JOIN segment is
quoted.

Allow quoted segments in both regexes and unquote them in registerAlias
before lowercasing, so the canonical map key matches the bare name that
the JSqlParser-driven WHERE-column extractor already produces. The
"Hibernate alias smells like a table" guard at line 709 stays in place
as the safety net for genuinely unparseable cases.

Refs #82.
@haroya01 haroya01 merged commit 304ccf1 into main May 19, 2026
3 checks passed
@haroya01 haroya01 deleted the fix/82-quoted-table-alias-resolution branch May 19, 2026 02:29
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.

1 participant