{"record":{"id":"d1483a17d41b6f43","repo":"prestodb/presto","slug":"duplicate-determinism-characteristics-s","errorCode":null,"errorMessage":"Duplicate determinism characteristics: %s","messagePattern":"Duplicate determinism characteristics: (.+?)","errorType":"exception","errorClass":"ParsingException","httpStatus":null,"severity":"error","filePath":"presto-parser/src/main/java/com/facebook/presto/sql/parser/AstBuilder.java","lineNumber":3075,"sourceCode":"        Language language = null;\n        Determinism determinism = null;\n        NullCallClause nullCallClause = null;\n\n        for (SqlBaseParser.RoutineCharacteristicContext characteristic : context.routineCharacteristic()) {\n            if (characteristic.language() != null) {\n                if (language != null) {\n                    throw new ParsingException(format(\"Duplicate language clause: %s\", characteristic.language().getText()), getLocation(characteristic.language()));\n                }\n                if (characteristic.language().SQL() != null) {\n                    language = Language.SQL;\n                }\n                else {\n                    language = new Language(((Identifier) visit(characteristic.language().identifier())).getValue());\n                }\n            }\n            else if (characteristic.determinism() != null) {\n                if (determinism != null) {\n                    throw new ParsingException(format(\"Duplicate determinism characteristics: %s\", characteristic.determinism().getText()), getLocation(characteristic.determinism()));\n                }\n                determinism = characteristic.determinism().NOT() == null ? DETERMINISTIC : NOT_DETERMINISTIC;\n            }\n            else if (characteristic.nullCallClause() != null) {\n                if (nullCallClause != null) {\n                    throw new ParsingException(format(\"Duplicate null-call clause: %s\", characteristic.nullCallClause().getText()), getLocation(characteristic.nullCallClause()));\n                }\n                nullCallClause = characteristic.nullCallClause().CALLED() != null ? CALLED_ON_NULL_INPUT : RETURNS_NULL_ON_NULL_INPUT;\n            }\n            else {\n                throw new IllegalArgumentException(format(\"Unsupported RoutineCharacteristic: %s\", characteristic.getText()));\n            }\n        }\n\n        return new RoutineCharacteristics(\n                Optional.ofNullable(language),\n                Optional.ofNullable(determinism),\n                Optional.ofNullable(nullCallClause));","sourceCodeStart":3057,"sourceCodeEnd":3093,"githubUrl":"https://github.com/prestodb/presto/blob/55bb57d202de3b926896fa966c2c4a44c779634e/presto-parser/src/main/java/com/facebook/presto/sql/parser/AstBuilder.java#L3057-L3093","documentation":"Duplicate-clause guard in the routine-characteristics loop of AstBuilder: a CREATE FUNCTION statement specifies the DETERMINISTIC/NOT DETERMINISTIC characteristic more than once. The second determinism clause is rejected as a ParsingException at its source location, mirroring the duplicate language-clause check.","triggerScenarios":"Parsing 'CREATE FUNCTION ... DETERMINISTIC NOT DETERMINISTIC ...' or repeating the same determinism keyword twice in the characteristics list.","commonSituations":"SQL generators concatenating characteristic strings from multiple config sources, or users writing both DETERMINISTIC and NOT DETERMINISTIC when toggling behavior.","solutions":["Keep exactly one DETERMINISTIC or NOT DETERMINISTIC clause.","Make the SQL builder overwrite rather than append determinism settings.","Validate characteristic uniqueness before submitting the statement.","Fix config merge logic that emits the clause from more than one source."],"exampleFix":"// before\nCREATE FUNCTION f() RETURNS int DETERMINISTIC NOT DETERMINISTIC RETURN 1;\n// after\nCREATE FUNCTION f() RETURNS int DETERMINISTIC RETURN 1;","handlingStrategy":"validation","validationCode":"int determinismClauses = countMatches(sql, \"(?i)\\\\b(NOT\\\\s+)?DETERMINISTIC\\\\b\");\nif (determinismClauses > 1) {\n    throw new IllegalArgumentException(\"Only one DETERMINISTIC/NOT DETERMINISTIC allowed\");\n}","typeGuard":"boolean hasSingleDeterminismClause(String sql) {\n    Matcher m = Pattern.compile(\"(?i)\\\\b(NOT\\\\s+)?DETERMINISTIC\\\\b\").matcher(sql);\n    return count(m) <= 1;\n}","tryCatchPattern":"try {\n    parser.createStatement(sql);\n} catch (ParsingException e) {\n    if (e.getMessage().startsWith(\"Duplicate determinism characteristics\")) {\n        throw new IllegalArgumentException(\"Specify DETERMINISTIC or NOT DETERMINISTIC exactly once\", e);\n    }\n    throw e;\n}","preventionTips":["Model determinism as a boolean in application code and render it once.","Deduplicate characteristics when merging config sources.","Snapshot-test generated CREATE FUNCTION DDL."],"tags":["sql-parser","create-function","duplicate-clause"],"backgroundTag":"duplicate-clause","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"}