{"record":{"id":"5950cded63f5053d","repo":"OtterMind/Chat2DB","slug":"dm-index-must-contain-at-least-one-named-column","errorCode":null,"errorMessage":"DM index must contain at least one named column","messagePattern":"DM index must contain at least one named column","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/enums/type/DMIndexTypeEnum.java","lineNumber":109,"sourceCode":"    }\n\n\n    private String buildIndexColumn(TableIndex tableIndex) {\n        StringBuilder script = new StringBuilder();\n        script.append(\"(\");\n        boolean hasColumn = false;\n        for (TableIndexColumn column : tableIndex.getColumnList()) {\n            if (StringUtils.isNotBlank(column.getColumnName())) {\n                hasColumn = true;\n                script.append(DMIdentifierProcessor.INSTANCE.quoteIdentifierAlways(column.getColumnName()));\n                if (!StringUtils.isBlank(column.getAscOrDesc()) && !PRIMARY_KEY.equals(this)) {\n                    script.append(\" \").append(DMSqlGuards.requireAscOrDesc(column.getAscOrDesc()));\n                }\n                script.append(\",\");\n            }\n        }\n        if (!hasColumn) {\n            throw new IllegalArgumentException(\"DM index must contain at least one named column\");\n        }\n        script.deleteCharAt(script.length() - 1);\n        script.append(\")\");\n        return script.toString();\n    }\n\n    private String buildIndexName(TableIndex tableIndex) {\n        return qualifiedName(tableIndex.getSchemaName(), tableIndex.getName());\n    }\n\n    public String buildModifyIndex(TableIndex tableIndex) {\n        if (EditStatusEnum.DELETE.name().equals(tableIndex.getEditStatus())) {\n            return buildDropIndex(tableIndex);\n        }\n        if (EditStatusEnum.MODIFY.name().equals(tableIndex.getEditStatus())) {\n            return StringUtils.join(buildDropIndex(tableIndex), \";\\n\", buildIndexScript(tableIndex));\n        }\n        if (EditStatusEnum.ADD.name().equals(tableIndex.getEditStatus())) {","sourceCodeStart":91,"sourceCodeEnd":127,"githubUrl":"https://github.com/OtterMind/Chat2DB/blob/5ee1e990e73fbcae1969dc554be254fedb3ab888/chat2db-community-server/chat2db-community-plugins/chat2db-community-dm/src/main/java/ai/chat2db/plugin/dm/enums/type/DMIndexTypeEnum.java#L91-L127","documentation":"Thrown by DMIndexTypeEnum.buildIndexColumn (inside DMIndexTypeEnum) when, after iterating every TableIndexColumn, none had a non-blank columnName. The guard prevents emitting an index DDL fragment with an empty column list \"()\", which would be invalid SQL.","triggerScenarios":"Calling DMIndexTypeEnum.buildIndexScript / buildModifyIndex on a TableIndex whose columnList is non-empty but every TableIndexColumn.getColumnName() is blank, or a list of placeholder rows.","commonSituations":"A UI 'add index' action that created column rows without binding names; importing an index whose column references were dropped; constructing a TableIndex programmatically and forgetting to populate columnName.","solutions":["Populate TableIndexColumn.columnName for at least one column before building the index.","Filter out blank-name columns earlier and skip index generation entirely when none remain.","Validate the index model in the controller/service layer before reaching the DDL builder."],"exampleFix":"// before\nTableIndex idx = new TableIndex();\nidx.setColumnList(List.of(new TableIndexColumn())); // name blank\nDMIndexTypeEnum.XXX.buildIndexScript(idx);\n\n// after\nList<TableIndexColumn> named = idx.getColumnList().stream()\n    .filter(c -> StringUtils.isNotBlank(c.getColumnName()))\n    .toList();\nif (named.isEmpty()) { /* skip or surface a user error */ }\nidx.setColumnList(named);\nDMIndexTypeEnum.XXX.buildIndexScript(idx);","handlingStrategy":"validation","validationCode":"static boolean hasNamedIndexColumn(TableIndex idx) {\n    if (idx == null || idx.getColumnList() == null) return false;\n    return idx.getColumnList().stream().anyMatch(c -> StringUtils.isNotBlank(c.getColumnName()));\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Validate that at least one index column has a name before building DM index DDL.","Filter blank-name columns out of the index model upstream.","Reject empty-column indexes in the service/controller layer with a clear user message."],"tags":["dm","dameng","ddl","index","validation","business-rule"],"backgroundTag":null,"analyzedSha":"5ee1e990e73fbcae1969dc554be254fedb3ab888","analyzedAt":"2026-08-14T07:05:03.077Z","schemaVersion":2},"datasetVersion":"2026-08-14T10:17:34.591Z"}