{"record":{"id":"cd0c8ac6d1350842","repo":"vitessio/vitess","slug":"non-constant-regexp","errorCode":null,"errorMessage":"non-constant regexp","messagePattern":"non-constant regexp","errorType":"error_code","errorClass":"errNonConstantRegexp","httpStatus":null,"severity":"warning","filePath":"go/vt/vtgate/evalengine/fn_regexp.go","lineNumber":212,"sourceCode":"\t\tcase icuregex.LookBehindLimit:\n\t\t\terr = vterrors.NewError(vtrpcpb.Code_INVALID_ARGUMENT, vterrors.RegexpLookBehindLimit, compileErr.Error())\n\t\tcase icuregex.MissingCloseBracket:\n\t\t\terr = vterrors.NewError(vtrpcpb.Code_INVALID_ARGUMENT, vterrors.RegexpMissingCloseBracket, compileErr.Error())\n\t\tcase icuregex.InvalidRange:\n\t\t\terr = vterrors.NewError(vtrpcpb.Code_INVALID_ARGUMENT, vterrors.RegexpInvalidRange, compileErr.Error())\n\t\tcase icuregex.PatternTooBig:\n\t\t\terr = vterrors.NewError(vtrpcpb.Code_INVALID_ARGUMENT, vterrors.RegexpPatternTooBig, compileErr.Error())\n\t\tcase icuregex.InvalidCaptureGroupName:\n\t\t\terr = vterrors.NewError(vtrpcpb.Code_INVALID_ARGUMENT, vterrors.RegexpInvalidCaptureGroup, compileErr.Error())\n\t\tdefault:\n\t\t\terr = vterrors.NewError(vtrpcpb.Code_INVALID_ARGUMENT, vterrors.RegexpInternal, compileErr.Error())\n\t\t}\n\t}\n\n\treturn nil, err\n}\n\nvar errNonConstantRegexp = errors.New(\"non-constant regexp\")\n\nfunc compileConstantRegex(c *compiler, args TupleExpr, pat, mt int, cs collations.TypedCollation, flags icuregex.RegexpFlag, f string) (*icuregex.Pattern, error) {\n\tpattern := args[pat]\n\tif !pattern.constant() {\n\t\treturn nil, errNonConstantRegexp\n\t}\n\tvar err error\n\tstaticEnv := EmptyExpressionEnv(c.env)\n\tpattern, err = simplifyExpr(staticEnv, pattern)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\tif len(args) > mt {\n\t\tfl := args[mt]\n\t\tif !fl.constant() {\n\t\t\treturn nil, errNonConstantRegexp\n\t\t}","sourceCodeStart":194,"sourceCodeEnd":230,"githubUrl":"https://github.com/vitessio/vitess/blob/01a25a7d176f94613b8d59d799f438380a8760e4/go/vt/vtgate/evalengine/fn_regexp.go#L194-L230","documentation":"The regexp compiler in the eval engine requires the pattern argument to be a constant expression so it can be compiled once at plan time. errNonConstantRegexp is returned by compileConstantRegex when the pattern argument (or another required argument) is not a constant, e.g. a column reference or non-deterministic expression.","triggerScenarios":"Using RLIKE/REGEXP/REGEXP_REPLACE (or related functions) where the pattern is derived from a column, parameter, or runtime expression rather than a literal.","commonSituations":"Queries like `col RLIKE other_col` or patterns built from user input passed as bound parameters in the plan compiler path.","solutions":["Use a constant string literal for the regexp pattern","Move variable-pattern matching out of SQL or evaluate via a different approach","Ensure the pattern expression is one the compiler recognizes as constant (e.g. a literal or constant foldable expression)"],"exampleFix":"// before\nSELECT * FROM t WHERE name RLIKE pattern_col;\n// after\nSELECT * FROM t WHERE name RLIKE '^[A-Za-z]+$';","handlingStrategy":"try-catch","validationCode":"if expr, ok := patternExpr.(sqlparser.Literal); !ok || expr.Type != sqlparser.StrVal {\n    return errors.New(\"regexp pattern must be a constant string\")\n}","typeGuard":null,"tryCatchPattern":"pat, err := compileConstantRegex(c, args, patIdx, mtIdx, cs, flags, fnName)\nif errors.Is(err, errNonConstantRegexp) {\n    // fall back to runtime evaluation or reject the plan\n}","preventionTips":["Use string literals for REGEXP/RLIKE patterns","Keep regexp patterns out of columns and bound variables when using the plan compiler","Document the constant-pattern requirement in query-writing guidelines"],"tags":["sql","regexp","evalengine","query-planning"],"backgroundTag":"non-constant-regexp-pattern","analyzedSha":"01a25a7d176f94613b8d59d799f438380a8760e4","analyzedAt":"2026-09-01T17:28:30.605Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}