|
131 | 131 | import io.dingodb.common.util.Parameters; |
132 | 132 | import io.dingodb.common.util.Utils; |
133 | 133 | import io.dingodb.expr.common.timezone.core.DateTimeType; |
134 | | -import io.dingodb.expr.common.type.AnyType; |
135 | 134 | import io.dingodb.meta.DdlService; |
136 | 135 | import io.dingodb.meta.InfoSchemaService; |
137 | 136 | import io.dingodb.meta.MetaService; |
|
195 | 194 | import java.util.Arrays; |
196 | 195 | import java.util.Collections; |
197 | 196 | import java.util.Comparator; |
| 197 | +import java.util.HashMap; |
198 | 198 | import java.util.List; |
199 | 199 | import java.util.Map; |
200 | 200 | import java.util.Objects; |
|
221 | 221 | import static io.dingodb.common.mysql.error.ErrorCode.ErrNotFoundDropTable; |
222 | 222 | import static io.dingodb.common.mysql.error.ErrorCode.ErrNotSupportedYet; |
223 | 223 | import static io.dingodb.common.mysql.error.ErrorCode.ErrPartitionMgmtOnNonpartitioned; |
224 | | -import static io.dingodb.common.mysql.error.ErrorCode.ErrTruncatedWrongValue; |
225 | 224 | import static io.dingodb.common.mysql.error.ErrorCode.ErrUnsupportedDDLOperation; |
226 | 225 | import static io.dingodb.common.mysql.error.ErrorCode.ErrUnsupportedModifyVec; |
227 | 226 | import static io.dingodb.common.util.NameCaseUtils.caseSensitive; |
@@ -883,25 +882,7 @@ public void execute(@NonNull SqlAlterAddColumn sqlAlterAddColumn, CalcitePrepare |
883 | 882 | throw new IllegalArgumentException("Add column, the engine must be transactional."); |
884 | 883 | } |
885 | 884 | } |
886 | | - DingoSqlColumn dingoSqlColumn = (DingoSqlColumn) sqlAlterAddColumn.getColumnDeclaration(); |
887 | | - ColumnDefinition newColumn = fromSqlColumnDeclaration( |
888 | | - dingoSqlColumn, |
889 | | - new ContextSqlValidator(context, true), |
890 | | - definition.keyColumns().stream().map(Column::getName).collect(Collectors.toList()) |
891 | | - ); |
892 | | - if (newColumn == null) { |
893 | | - throw new RuntimeException("newColumn is null."); |
894 | | - } |
895 | | - |
896 | | - if (definition.getColumn(newColumn.getName()) != null) { |
897 | | - throw DINGO_RESOURCE.duplicateColumn().ex(); |
898 | | - } |
899 | | - if (dingoSqlColumn.isPrimaryKey()) { |
900 | | - throw DINGO_RESOURCE.addColumnPrimaryError(newColumn.getName(), tableName).ex(); |
901 | | - } |
902 | | - if (dingoSqlColumn.isAutoIncrement()) { |
903 | | - throw DINGO_RESOURCE.addColumnAutoIncError(newColumn.getName(), tableName).ex(); |
904 | | - } |
| 885 | + ColumnDefinition newColumn = getAddColumn(context, sqlAlterAddColumn, definition, tableName); |
905 | 886 | validateAddOrModifyColumn(newColumn, true); |
906 | 887 | SqlIdentifier afterCol = sqlAlterAddColumn.getAfterCol(); |
907 | 888 | String afterColName; |
@@ -2040,10 +2021,25 @@ public void execute(SqlBatchCreateTable sqlBatchCreateTable, CalcitePrepare.Cont |
2040 | 2021 | } |
2041 | 2022 | } |
2042 | 2023 |
|
| 2024 | + public void execute(SqlIdentifier table, List<AddingColInfo> addingColInfoList, CalcitePrepare.Context context) { |
| 2025 | + Pair<SubSnapshotSchema, String> schemaTableName |
| 2026 | + = getSchemaAndTableName(table, context); |
| 2027 | + final SubSnapshotSchema schema = Parameters.nonNull(schemaTableName.left, "table schema"); |
| 2028 | + SchemaInfo schemaInfo = schema.getSchemaInfo(schema.getSchemaName()); |
| 2029 | + String tableName = Parameters.nonNull(schemaTableName.right, "table name"); |
| 2030 | + Table definition = schema.getTableInfo(tableName); |
| 2031 | + DdlService.root().addMultiColumn(schemaInfo, definition, addingColInfoList, ""); |
| 2032 | + } |
| 2033 | + |
2043 | 2034 | public void execute(SqlAlterTableOptions sqlAlterTableOptions, CalcitePrepare.Context context) { |
2044 | 2035 | LogUtils.info(log, "DDL execute:{}", sqlAlterTableOptions); |
2045 | | - validateMultiSchemaChange(sqlAlterTableOptions, context); |
2046 | 2036 | List<SqlAlterTable> alterTableList = sqlAlterTableOptions.alterTableList; |
| 2037 | + List<AddingColInfo> addingColInfoList = mergeAddColumnDdl(alterTableList, context); |
| 2038 | + if (addingColInfoList != null) { |
| 2039 | + execute(sqlAlterTableOptions.table, addingColInfoList, context); |
| 2040 | + return; |
| 2041 | + } |
| 2042 | + validateMultiSchemaChange(sqlAlterTableOptions, context); |
2047 | 2043 | for (SqlAlterTable alterTable : alterTableList) { |
2048 | 2044 | int retry = 10; |
2049 | 2045 | while (retry-- > 0) { |
@@ -3191,4 +3187,92 @@ public static void checkRenameTable( |
3191 | 3187 | } |
3192 | 3188 | } |
3193 | 3189 |
|
| 3190 | + public List<AddingColInfo> mergeAddColumnDdl(List<SqlAlterTable> alterTableList, CalcitePrepare.Context context) { |
| 3191 | + Map<String, String> tableMap = new HashMap<>(); |
| 3192 | + List<AddingColInfo> addingColInfoList = new ArrayList<>(); |
| 3193 | + for (int i = 0; i < alterTableList.size(); i ++) { |
| 3194 | + SqlAlterTable sqlAlterTable = alterTableList.get(i); |
| 3195 | + if (sqlAlterTable instanceof SqlAlterAddColumn) { |
| 3196 | + SqlAlterAddColumn sqlAlterAddColumn = (SqlAlterAddColumn) sqlAlterTable; |
| 3197 | + Pair<SubSnapshotSchema, String> schemaTableName |
| 3198 | + = getSchemaAndTableName(sqlAlterTable.table, context); |
| 3199 | + final SubSnapshotSchema schema = Parameters.nonNull(schemaTableName.left, "table schema"); |
| 3200 | + SchemaInfo schemaInfo = schema.getSchemaInfo(schema.getSchemaName()); |
| 3201 | + String tableName = Parameters.nonNull(schemaTableName.right, "table name"); |
| 3202 | + tableName = convertName(tableName); |
| 3203 | + if (schemaInfo == null) { |
| 3204 | + if (context.getDefaultSchemaPath() != null && !context.getDefaultSchemaPath().isEmpty()) { |
| 3205 | + throw DINGO_RESOURCE.unknownSchema(context.getDefaultSchemaPath().get(0)).ex(); |
| 3206 | + } else { |
| 3207 | + throw DINGO_RESOURCE.unknownSchema("DINGO").ex(); |
| 3208 | + } |
| 3209 | + } |
| 3210 | + Table table = schema.getTableInfo(tableName); |
| 3211 | + if (table == null) { |
| 3212 | + throw DINGO_RESOURCE.unknownTable(schema.getSchemaName() + "." + tableName).ex(); |
| 3213 | + } |
| 3214 | + ColumnDefinition newColumn = getAddColumn(context, sqlAlterAddColumn, table, tableName); |
| 3215 | + validateAddOrModifyColumn(newColumn, true); |
| 3216 | + SqlIdentifier afterCol = sqlAlterAddColumn.getAfterCol(); |
| 3217 | + String afterColName; |
| 3218 | + if (afterCol != null) { |
| 3219 | + afterColName = afterCol.getSimple(); |
| 3220 | + Column afterColumn = table.getColumns().stream() |
| 3221 | + .filter(col -> col.getSchemaState() == SchemaState.SCHEMA_PUBLIC |
| 3222 | + && col.getName().equalsIgnoreCase(afterColName)).findFirst().orElse(null); |
| 3223 | + |
| 3224 | + if (afterColumn == null && findAlterColumn(afterCol, i, alterTableList)) { |
| 3225 | + throw DINGO_RESOURCE.unknownColumn(afterColName, tableName).ex(); |
| 3226 | + } |
| 3227 | + } else { |
| 3228 | + afterColName = null; |
| 3229 | + } |
| 3230 | + newColumn.setSchemaState(SchemaState.SCHEMA_PUBLIC); |
| 3231 | + |
| 3232 | + AddingColInfo addingColInfo = AddingColInfo.builder() |
| 3233 | + .column(newColumn) |
| 3234 | + .afterColName(afterColName) |
| 3235 | + .firstCol(sqlAlterAddColumn.isFirstCol()) |
| 3236 | + .build(); |
| 3237 | + addingColInfoList.add(addingColInfo); |
| 3238 | + tableMap.put(schema.getSchemaName(), tableName); |
| 3239 | + } else { |
| 3240 | + return null; |
| 3241 | + } |
| 3242 | + } |
| 3243 | + return tableMap.size() == 1 ? addingColInfoList : null; |
| 3244 | + } |
| 3245 | + |
| 3246 | + private static boolean findAlterColumn(SqlIdentifier afterCol, int index, List<SqlAlterTable> alterTableList) { |
| 3247 | + for (int i = 0; i < index; i++) { |
| 3248 | + SqlAlterAddColumn alterAddColumn = (SqlAlterAddColumn) alterTableList.get(i); |
| 3249 | + if (afterCol.equals(alterAddColumn.getAfterCol())) { |
| 3250 | + return true; |
| 3251 | + } |
| 3252 | + } |
| 3253 | + return false; |
| 3254 | + } |
| 3255 | + |
| 3256 | + private static @NonNull ColumnDefinition getAddColumn(CalcitePrepare.Context context, SqlAlterAddColumn sqlAlterAddColumn, Table table, String tableName) { |
| 3257 | + DingoSqlColumn dingoSqlColumn = (DingoSqlColumn) sqlAlterAddColumn.getColumnDeclaration(); |
| 3258 | + ColumnDefinition newColumn = fromSqlColumnDeclaration( |
| 3259 | + dingoSqlColumn, |
| 3260 | + new ContextSqlValidator(context, true), |
| 3261 | + table.keyColumns().stream().map(Column::getName).collect(Collectors.toList()) |
| 3262 | + ); |
| 3263 | + if (newColumn == null) { |
| 3264 | + throw new RuntimeException("newColumn is null."); |
| 3265 | + } |
| 3266 | + if (table.getColumn(newColumn.getName()) != null) { |
| 3267 | + throw DINGO_RESOURCE.duplicateColumn().ex(); |
| 3268 | + } |
| 3269 | + if (dingoSqlColumn.isPrimaryKey()) { |
| 3270 | + throw DINGO_RESOURCE.addColumnPrimaryError(newColumn.getName(), tableName).ex(); |
| 3271 | + } |
| 3272 | + if (dingoSqlColumn.isAutoIncrement()) { |
| 3273 | + throw DINGO_RESOURCE.addColumnAutoIncError(newColumn.getName(), tableName).ex(); |
| 3274 | + } |
| 3275 | + return newColumn; |
| 3276 | + } |
| 3277 | + |
3194 | 3278 | } |
0 commit comments