{"record":{"id":"e795076278e4b508","repo":"apache/shardingsphere","slug":"invalid-compaction-type-must-be-major-minor","errorCode":null,"errorMessage":"Invalid compaction type. Must be 'MAJOR', 'MINOR' or 'REBALANCE'","messagePattern":"Invalid compaction type\\. Must be 'MAJOR', 'MINOR' or 'REBALANCE'","errorType":"validation","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"parser/sql/engine/dialect/hive/src/main/java/org/apache/shardingsphere/sql/parser/engine/hive/visitor/statement/type/HiveDDLStatementVisitor.java","lineNumber":149,"sourceCode":"    public ASTNode visitAlterTable(final AlterTableContext ctx) {\n        AlterTableStatement.AlterTableStatementBuilder result = AlterTableStatement.builder().databaseType(getDatabaseType())\n                .table((SimpleTableSegment) visit(ctx.alterTableCommonClause().tableName()));\n        if (null != ctx.changeColumn()) {\n            ChangeColumnDefinitionSegment changeColumnSegment = (ChangeColumnDefinitionSegment) visit(ctx.changeColumn());\n            result.changeColumnDefinition(changeColumnSegment);\n        }\n        if (null != ctx.addColumns()) {\n            AddColumnDefinitionSegment addSeg = (AddColumnDefinitionSegment) visit(ctx.addColumns());\n            result.addColumnDefinition(addSeg);\n        }\n        if (null != ctx.replaceColumns()) {\n            ReplaceColumnDefinitionSegment repSeg = (ReplaceColumnDefinitionSegment) visit(ctx.replaceColumns());\n            result.replaceColumnDefinition(repSeg);\n        }\n        if (null != ctx.COMPACT()) {\n            String compactionType = ctx.string_().getText().replace(\"'\", \"\");\n            if (!isValidCompactionType(compactionType)) {\n                throw new IllegalArgumentException(\"Invalid compaction type. Must be 'MAJOR', 'MINOR' or 'REBALANCE'\");\n            }\n            if ((null != ctx.clusteredIntoClause() || null != ctx.orderByClause())\n                    && !\"REBALANCE\".equalsIgnoreCase(compactionType)) {\n                throw new IllegalArgumentException(\"[CLUSTERED INTO n BUCKETS] and [ORDER BY col_list] clauses can only be used with REBALANCE compaction\");\n            }\n        }\n        if (null != ctx.cherryPickClause()) {\n            int numberStartIndex = ctx.cherryPickClause().NUMBER_().getSymbol().getStartIndex();\n            int numberStopIndex = ctx.cherryPickClause().NUMBER_().getSymbol().getStopIndex();\n            LiteralExpressionSegment snapshotId = new LiteralExpressionSegment(numberStartIndex, numberStopIndex,\n                    new NumberLiteralValue(ctx.cherryPickClause().NUMBER_().getText()).getValue());\n            result.cherryPickDefinition(new CherryPickDefinitionSegment(ctx.cherryPickClause().EXECUTE().getSymbol().getStartIndex(), numberStopIndex, snapshotId));\n        }\n        if (null != ctx.tableRollback()) {\n            int startIndex = ctx.tableRollback().EXECUTE().getSymbol().getStartIndex();\n            if (null != ctx.tableRollback().string_()) {\n                int stringStartIndex = ctx.tableRollback().string_().getStart().getStartIndex();\n                int stringStopIndex = ctx.tableRollback().string_().getStop().getStopIndex();","sourceCodeStart":131,"sourceCodeEnd":167,"githubUrl":"https://github.com/apache/shardingsphere/blob/e952770a215630a3659c75d64369168cd3e26b82/parser/sql/engine/dialect/hive/src/main/java/org/apache/shardingsphere/sql/parser/engine/hive/visitor/statement/type/HiveDDLStatementVisitor.java#L131-L167","documentation":"Thrown by HiveDDLStatementVisitor when an ALTER TABLE ... COMPACT statement specifies a compaction type string that is not MAJOR, MINOR, or REBALANCE (case-insensitive check via isValidCompactionType after stripping quotes). Note this is an IllegalArgumentException, not SQLParsingException, even though it is a parse-time failure — so callers catching only SQLParsingException will not intercept it.","triggerScenarios":"Hive/Iceberg-style ALTER TABLE t COMPACT 'full' / 'minor_merge' / any unrecognized literal; typo in the quoted type; grammar accepts any string_ so the visitor validates the value. Triggered inside visitAlterTable when ctx.COMPACT() is non-null and isValidCompactionType returns false.","commonSituations":"Copying compaction commands from engine docs whose type vocabulary differs (e.g. 'full' from other systems); version drift where new compaction types exist upstream but not in this grammar's whitelist; case/whitespace mistakes inside the quoted string.","solutions":["Use exactly 'MAJOR', 'MINOR', or 'REBALANCE' (either case) as the quoted compaction type","Check for trailing spaces or smart quotes in the literal","If a newer compaction type is genuinely supported by your engine, upgrade ShardingSphere or extend isValidCompactionType locally"],"exampleFix":"// before\nALTER TABLE ice_t COMPACT 'full'\n\n// after\nALTER TABLE ice_t COMPACT 'MAJOR'","handlingStrategy":"validation","validationCode":"Set<String> VALID = Set.of(\"MAJOR\", \"MINOR\", \"REBALANCE\");\nString normalize(String compactionType) {\n    String t = compactionType.replace(\"'\", \"\").trim().toUpperCase();\n    if (!VALID.contains(t)) throw new IllegalArgumentException(\"Compaction type must be one of \" + VALID);\n    return t;\n}","typeGuard":null,"tryCatchPattern":"try { ddlEngine.parse(alterSql); } catch (IllegalArgumentException e) { /* message names the valid values; surface to user */ }","preventionTips":["Whitelist compaction types in your SQL builder before emitting COMPACT","Strip whitespace and normalize case in generated compaction literals"],"tags":["hive","ddl","compaction","alter-table","validation"],"backgroundTag":null,"analyzedSha":"e952770a215630a3659c75d64369168cd3e26b82","analyzedAt":"2026-08-14T13:54:53.392Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}