{"record":{"id":"80cd561a071fbadc","repo":"OtterMind/Chat2DB","slug":"unsupported-dm-varchar-unit-unit","errorCode":null,"errorMessage":"Unsupported DM VARCHAR unit: {unit}","messagePattern":"Unsupported DM VARCHAR unit: (.+?)","errorType":"validation","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"chat2db-community-server/chat2db-community-plugins/chat2db-community-dm/src/main/java/ai/chat2db/plugin/dm/DMSqlGuards.java","lineNumber":52,"sourceCode":"        return value;\n    }\n\n    /**\n     * Validates one complete DM column type expression, including\n     * parameterized built-in and schema-qualified user-defined types.\n     */\n    public static String requireColumnTypeExpression(String typeName) {\n        if (StringUtils.isBlank(typeName)) {\n            throw invalid(\"column type\", typeName);\n        }\n        scanExpression(typeName.trim(), true, \"column type\");\n        return typeName;\n    }\n\n    public static String requireUnit(String unit) {\n        String trimmed = StringUtils.trimToEmpty(unit);\n        if (!\"CHAR\".equalsIgnoreCase(trimmed) && !\"BYTE\".equalsIgnoreCase(trimmed)) {\n            throw new IllegalArgumentException(\"Unsupported DM VARCHAR unit: \" + unit);\n        }\n        return trimmed;\n    }\n\n    public static String requireAscOrDesc(String value) {\n        String trimmed = StringUtils.trimToEmpty(value);\n        if (\"ASC\".equalsIgnoreCase(trimmed)) {\n            return \"ASC\";\n        }\n        if (\"DESC\".equalsIgnoreCase(trimmed)) {\n            return \"DESC\";\n        }\n        throw new IllegalArgumentException(\"Invalid DM index sort direction: \" + value);\n    }\n\n    public static String requireBitLiteral(String value) {\n        if (StringUtils.isBlank(value)) {\n            return \"NULL\";","sourceCodeStart":34,"sourceCodeEnd":70,"githubUrl":"https://github.com/OtterMind/Chat2DB/blob/5ee1e990e73fbcae1969dc554be254fedb3ab888/chat2db-community-server/chat2db-community-plugins/chat2db-community-dm/src/main/java/ai/chat2db/plugin/dm/DMSqlGuards.java#L34-L70","documentation":"Thrown by DMSqlGuards.requireUnit when a DM (Dameng) VARCHAR length unit is neither CHAR nor BYTE. Dameng supports CHAR/BYTE length semantics for VARCHAR, so this guard whitelists exactly those two units before they are interpolated into non-escapable DDL positions. Any other token (including null after trimming) is rejected.","triggerScenarios":"Calling DMSqlGuards.requireUnit(unit) with a value other than \"CHAR\"/\"BYTE\" (case-insensitive), e.g. null, \"\", \"WORD\", \"OCTET\". Reached when building DM column DDL that carries an explicit length-semantic unit on a VARCHAR type.","commonSituations":"Migrating a schema from Oracle/PostgreSQL whose driver reports a different unit label; a form field letting users type a free-text unit; mapping a generic 'length semantics' enum that includes values Dameng does not support.","solutions":["Pass only \"CHAR\" or \"BYTE\" (any case) to requireUnit; trim happens internally so surrounding whitespace is fine.","If the source of the unit is unknown, default it to the dialect default (usually BYTE) instead of forwarding an empty string.","Constrain the UI/API for DM VARCHAR length semantics to a CHAR/BYTE dropdown so invalid tokens never reach the guard."],"exampleFix":"// before\nString unit = column.getLengthUnit(); // could be null or \"\"\nDDL.append(\"VARCHAR(\").append(size).append(\" \").append(DMSqlGuards.requireUnit(unit));\n\n// after\nString unit = column.getLengthUnit();\nif (StringUtils.isBlank(unit)) {\n    unit = \"BYTE\"; // DM default length semantics\n}\nDDL.append(\"VARCHAR(\").append(size).append(\" \").append(DMSqlGuards.requireUnit(unit));","handlingStrategy":"validation","validationCode":"static boolean isDmUnit(String unit) {\n    if (unit == null) return false;\n    String t = unit.trim();\n    return \"CHAR\".equalsIgnoreCase(t) || \"BYTE\".equalsIgnoreCase(t);\n}","typeGuard":"static String dmUnitOrDefault(String unit) {\n    if (\"CHAR\".equalsIgnoreCase(unit) || \"BYTE\".equalsIgnoreCase(unit)) return unit.trim().toUpperCase(Locale.ROOT);\n    return \"BYTE\"; // DM default length semantics\n}","tryCatchPattern":null,"preventionTips":["Default a blank VARCHAR unit to the DM default (BYTE) before calling the guard.","Restrict the DM length-semantics input to a CHAR/BYTE choice.","Normalize Oracle/MariaDB unit labels to CHAR/BYTE when importing schemas."],"tags":["dm","dameng","sql-guard","ddl","validation","varchar"],"backgroundTag":null,"analyzedSha":"5ee1e990e73fbcae1969dc554be254fedb3ab888","analyzedAt":"2026-08-14T07:05:03.077Z","schemaVersion":2},"datasetVersion":"2026-08-14T10:17:34.591Z"}