{"record":{"id":"016b05cdae72508c","repo":"prestodb/presto","slug":"identifiers-must-not-contain-symbol","errorCode":null,"errorMessage":"identifiers must not contain '${symbol}'","messagePattern":"identifiers must not contain '(.+?)'","errorType":"exception","errorClass":"ParsingException","httpStatus":null,"severity":"error","filePath":"presto-parser/src/main/java/com/facebook/presto/sql/parser/SqlParser.java","lineNumber":209,"sourceCode":"            extends SqlBaseBaseListener\n    {\n        private final List<String> ruleNames;\n        private final Consumer<ParsingWarning> warningConsumer;\n\n        public PostProcessor(List<String> ruleNames, Consumer<ParsingWarning> warningConsumer)\n        {\n            this.ruleNames = ruleNames;\n            this.warningConsumer = requireNonNull(warningConsumer, \"warningConsumer is null\");\n        }\n\n        @Override\n        public void exitUnquotedIdentifier(SqlBaseParser.UnquotedIdentifierContext context)\n        {\n            String identifier = context.IDENTIFIER().getText();\n            for (IdentifierSymbol identifierSymbol : EnumSet.complementOf(allowedIdentifierSymbols)) {\n                char symbol = identifierSymbol.getSymbol();\n                if (identifier.indexOf(symbol) >= 0) {\n                    throw new ParsingException(\"identifiers must not contain '\" + identifierSymbol.getSymbol() + \"'\", null, context.IDENTIFIER().getSymbol().getLine(), context.IDENTIFIER().getSymbol().getCharPositionInLine());\n                }\n            }\n        }\n\n        @Override\n        public void exitBackQuotedIdentifier(SqlBaseParser.BackQuotedIdentifierContext context)\n        {\n            Token token = context.BACKQUOTED_IDENTIFIER().getSymbol();\n            throw new ParsingException(\n                    \"backquoted identifiers are not supported; use double quotes to quote identifiers\",\n                    null,\n                    token.getLine(),\n                    token.getCharPositionInLine());\n        }\n\n        @Override\n        public void exitDigitIdentifier(SqlBaseParser.DigitIdentifierContext context)\n        {","sourceCodeStart":191,"sourceCodeEnd":227,"githubUrl":"https://github.com/prestodb/presto/blob/55bb57d202de3b926896fa966c2c4a44c779634e/presto-parser/src/main/java/com/facebook/presto/sql/parser/SqlParser.java#L191-L227","documentation":"After parsing, PostProcessor.exitUnquotedIdentifier validates unquoted identifier text against the set of allowed identifier symbols. If the identifier contains a disallowed character (the complement of allowedIdentifierSymbols), a ParsingException is thrown naming the offending symbol. This enforces which punctuation may appear bare inside identifiers.","triggerScenarios":"An unquoted identifier containing characters like '.' or other disallowed symbols in an unrestricted parse — e.g. SELECT a.b.c interpreted as one unquoted token in a context where such symbols are not allowed.","commonSituations":"Copy-pasted qualified names from other systems, identifiers pasted with trailing punctuation, parsing fragments where dot-containing names were meant to be quoted.","solutions":["Wrap the identifier in double quotes: \"a.b.c\"","Remove the offending character from the identifier","Parse with parser options/initializer that allow the needed identifier symbol if applicable"],"exampleFix":"// before\nString sql = \"SELECT my.column FROM t\"; // identifiers must not contain '.'\n// after\nString sql = \"SELECT \\\"my.column\\\" FROM t\";","handlingStrategy":"validation","validationCode":"// Verify unquoted identifiers contain only allowed characters before building SQL\nPattern OK = Pattern.compile(\"[A-Za-z_][A-Za-z0-9_$]*\");\nif (!OK.matcher(identifier).matches()) {\n    identifier = '\"' + identifier.replace(\"\\\"\", \"\\\"\\\"\") + '\"';\n}","typeGuard":"boolean isSafeUnquotedIdentifier(String id) {\n    return id != null && id.matches(\"[A-Za-z_][A-Za-z0-9_]*\");\n}","tryCatchPattern":"try {\n    return sqlParser.createStatement(sql);\n} catch (ParsingException e) {\n    if (e.getMessage() != null && e.getMessage().startsWith(\"identifiers must not contain\")) {\n        throw new IdentifierQuotingRequiredException(e.getMessage(), e);\n    }\n    throw e;\n}","preventionTips":["Always double-quote identifiers that contain dots or special characters","Escape embedded double quotes by doubling them","Whitelist identifier characters in query-building helpers","Never paste qualified names as a single bare identifier"],"tags":["sql","identifier","parser"],"backgroundTag":"invalid-identifier","analyzedSha":"55bb57d202de3b926896fa966c2c4a44c779634e","analyzedAt":"2026-09-04T12:50:26.162Z","contentChangedAt":"2026-09-04T12:50:26.162Z","schemaVersion":2},"datasetVersion":"2026-09-11T21:17:09.523Z"}