Class SqlIdentifierSubstitution

java.lang.Object
dev.frostlake.executor.SqlIdentifierSubstitution

public final class SqlIdentifierSubstitution extends Object
Binds a named parameter into a SQL body by substituting each occurrence of the parameter's bare name with a replacement string — for UDF / stored-procedure bodies and masking-policy bodies, where the parameter is written as an ordinary identifier.

The substitution is driven by the SQL lexer, not a \b-anchored regex: the body is tokenized, and only tokens whose text matches the parameter name (case-insensitively) are replaced — and never a FrostlakeLexer.STRING_LITERAL or FrostlakeLexer.QUOTED_IDENTIFIER token. A name that also appears inside a string literal (e.g. a masking body CASE WHEN val = 'val' THEN …) or a double-quoted identifier is therefore left untouched, and line/block comments — which the lexer skips — never contribute a match. Letting the parser's own tokenizer decide what is an identifier keeps the grammar as the single source of truth about the body's lexical structure, rather than re-deriving it with hand-rolled word-boundary logic.

  • Method Details

    • substitute

      public static String substitute(String body, String identifier, String replacement)
      Returns body with every bare-identifier occurrence of identifier replaced by replacement. All other text — whitespace, punctuation, string literals, quoted identifiers, and comments — is preserved byte-for-byte. Two positions are structural NAMES, not bindable references, and are never replaced: an identifier ADJACENT TO A DOT (a qualified-name segment — TOOLS.STATS.SITE, alias.col; a parameter named stats must not rewrite the schema qualifier) and an identifier immediately PRECEDED BY A COLON (a semi-structured path segment — in so:child_stats the field name stays even when a parameter is also called child_stats; so itself, colon AFTER it, still binds).