morningman commented on code in PR #19090: URL: https://github.com/apache/doris/pull/19090#discussion_r1181634672
########## fe/fe-core/src/main/java/org/apache/doris/datasource/InternalCatalog.java: ########## @@ -1341,6 +1341,50 @@ public void replayCreateTable(String dbName, Table table) throws MetaNotFoundExc } } + public void addPartitionLike(Database db, String tableName, AddPartitionLikeClause addPartitionLikeClause) + throws DdlException { + try { + Table table = db.getTableOrDdlException(tableName); + + if (table.getType() == TableType.VIEW) { Review Comment: ```suggestion if (table.getType() != TableType.OLAP) { ``` ########## fe/fe-core/src/main/java/org/apache/doris/datasource/InternalCatalog.java: ########## @@ -1341,6 +1341,50 @@ public void replayCreateTable(String dbName, Table table) throws MetaNotFoundExc } } + public void addPartitionLike(Database db, String tableName, AddPartitionLikeClause addPartitionLikeClause) + throws DdlException { + try { + Table table = db.getTableOrDdlException(tableName); + + if (table.getType() == TableType.VIEW) { + throw new DdlException("Not support create partition from a View"); Review Comment: ```suggestion throw new DdlException("Only support create partition from a OLAP table"); ``` ########## fe/fe-core/src/main/java/org/apache/doris/datasource/InternalCatalog.java: ########## @@ -1341,6 +1341,50 @@ public void replayCreateTable(String dbName, Table table) throws MetaNotFoundExc } } + public void addPartitionLike(Database db, String tableName, AddPartitionLikeClause addPartitionLikeClause) + throws DdlException { + try { + Table table = db.getTableOrDdlException(tableName); + + if (table.getType() == TableType.VIEW) { + throw new DdlException("Not support create partition from a View"); + } + + table.readLock(); + try { + if (table.getType().equals(TableType.OLAP)) { + String partitionName = addPartitionLikeClause.getPartitionName(); + String existedName = addPartitionLikeClause.getExistedPartitionName(); + OlapTable olapTable = (OlapTable) table; + Partition part = olapTable.getPartition(existedName); + PartitionInfo partitionInfo = olapTable.getPartitionInfo(); + PartitionDesc partitionDesc = partitionInfo.toPartitionDesc((OlapTable) table); + SinglePartitionDesc oldPartitionDesc = partitionDesc.getSinglePartitionDescByName(existedName); + if (oldPartitionDesc == null) { + throw new DdlException("Failed to ADD PARTITION" + partitionName + " LIKE " + + existedName + ". Reason: " + "partition " + existedName + "not exist"); + } + DistributionDesc distributionDesc = part.getDistributionInfo().toDistributionDesc(); + SinglePartitionDesc newPartitionDesc = new SinglePartitionDesc(false, partitionName, + oldPartitionDesc.getPartitionKeyDesc(), oldPartitionDesc.getProperties()); + Map<String, String> properties = newPartitionDesc.getProperties(); + AddPartitionClause clause = new AddPartitionClause(newPartitionDesc, distributionDesc, + properties, addPartitionLikeClause.getIsTempPartition()); + table.readUnlock(); Review Comment: This `table.readUnlock();` should be in a `finally` block. You split the whole logic into 2 parts: One is for creating an `AddPartitionClause`, the other is for calling `addPartition()`. And refactor the current `try..catch` ########## fe/fe-core/src/main/java/org/apache/doris/datasource/InternalCatalog.java: ########## @@ -1341,6 +1341,50 @@ public void replayCreateTable(String dbName, Table table) throws MetaNotFoundExc } } + public void addPartitionLike(Database db, String tableName, AddPartitionLikeClause addPartitionLikeClause) + throws DdlException { + try { + Table table = db.getTableOrDdlException(tableName); + + if (table.getType() == TableType.VIEW) { + throw new DdlException("Not support create partition from a View"); + } + + table.readLock(); + try { + if (table.getType().equals(TableType.OLAP)) { Review Comment: Remove this `if` ########## fe/fe-core/src/main/java/org/apache/doris/qe/StmtExecutor.java: ########## @@ -2145,6 +2163,160 @@ private void handleCtasRollback(TableName table) { } } + private void handleIotStmt() { + InsertOverwriteTableStmt iotStmt = (InsertOverwriteTableStmt) this.parsedStmt; + if (iotStmt.getPartitionNames().size() == 0) { + // insert overwrite table + handleOverwriteTable(iotStmt); + } else { + // insert overwrite table with partition + handleOverwritePartition(iotStmt); + } + } + + private void handleOverwriteTable(InsertOverwriteTableStmt iotStmt) { + UUID uuid = UUID.randomUUID(); + // to comply with naming rules + TableName tmpTableName = new TableName(null, iotStmt.getDb(), "tmp_table_" + uuid.toString().replace('-', '_')); + TableName targetTableName = new TableName(null, iotStmt.getDb(), iotStmt.getTbl()); + try { + // create a tmp table with uuid + parsedStmt = new CreateTableLikeStmt(false, tmpTableName, targetTableName, null, false); + parsedStmt.setUserInfo(context.getCurrentUserIdentity()); + execute(); + } catch (Exception e) { + // Maybe our bug + LOG.warn("IOT create a tmp table error, stmt={}", originStmt.originStmt, e); + context.getState().setError(ErrorCode.ERR_UNKNOWN_ERROR, "Unexpected exception: " + e.getMessage()); + return; + } + // after success create table insert data + try { + parsedStmt = new InsertStmt(tmpTableName, iotStmt.getQueryStmt()); + parsedStmt.setUserInfo(context.getCurrentUserIdentity()); + execute(); + if (MysqlStateType.ERR.equals(context.getState().getStateType())) { + LOG.warn("IOT insert data error, stmt={}", parsedStmt.toSql()); + handleIotRollback(tmpTableName); + return; + } + } catch (Exception e) { + LOG.warn("IOT insert data error, stmt={}", parsedStmt.toSql(), e); + context.getState().setError(ErrorCode.ERR_UNKNOWN_ERROR, "Unexpected exception: " + e.getMessage()); + handleIotRollback(tmpTableName); + return; + } + + // overwrite old table with tmp table + try { + List<AlterClause> ops = new ArrayList<>(); + Map<String, String> properties = new HashMap<>(); + properties.put("swap", "false"); + ops.add(new ReplaceTableClause(tmpTableName.getTbl(), properties)); + parsedStmt = new AlterTableStmt(targetTableName, ops); + parsedStmt.setUserInfo(context.getCurrentUserIdentity()); + execute(); + context.getState().setOk(); + } catch (Exception e) { + // Maybe our bug + LOG.warn("IOT overwrite table error, stmt={}", parsedStmt.toSql(), e); + context.getState().setError(ErrorCode.ERR_UNKNOWN_ERROR, "Unexpected exception: " + e.getMessage()); + handleIotRollback(tmpTableName); + } + + } + + private void handleOverwritePartition(InsertOverwriteTableStmt iotStmt) { + TableName targetTableName = new TableName(null, iotStmt.getDb(), iotStmt.getTbl()); + List<String> partitionNames = iotStmt.getPartitionNames(); + List<String> tempPartitionName = new ArrayList<>(); + try { + // create tmp partitions with uuid + for (String partitionName : partitionNames) { + UUID uuid = UUID.randomUUID(); + // to comply with naming rules + String tempPartName = "tmp_partition_" + uuid.toString().replace('-', '_'); + tempPartitionName.add(tempPartName); + List<AlterClause> ops = new ArrayList<>(); + ops.add(new AddPartitionLikeClause(tempPartName, partitionName, true)); + parsedStmt = new AlterTableStmt(targetTableName, ops); + parsedStmt.setUserInfo(context.getCurrentUserIdentity()); + execute(); + } + } catch (Exception e) { + // Maybe our bug + LOG.warn("IOT create tmp table partitions error, stmt={}", originStmt.originStmt, e); + context.getState().setError(ErrorCode.ERR_UNKNOWN_ERROR, "Unexpected exception: " + e.getMessage()); + return; + } + + // after success add tmp partitions + try { + parsedStmt = new InsertStmt(targetTableName, new PartitionNames(true, tempPartitionName), + iotStmt.getQueryStmt()); + parsedStmt.setUserInfo(context.getCurrentUserIdentity()); + execute(); + if (MysqlStateType.ERR.equals(context.getState().getStateType())) { + LOG.warn("IOT insert data error, stmt={}", parsedStmt.toSql()); + handleIotPartitionRollback(targetTableName, tempPartitionName); + return; + } + } catch (Exception e) { + LOG.warn("IOT insert data error, stmt={}", parsedStmt.toSql(), e); + context.getState().setError(ErrorCode.ERR_UNKNOWN_ERROR, "Unexpected exception: " + e.getMessage()); + handleIotPartitionRollback(targetTableName, tempPartitionName); + return; + } + + // overwrite old table with tmp table Review Comment: ```suggestion // overwrite old partition with tmp partition ``` -- This is an automated message from the Apache Git Service. To respond to the message, please log on to GitHub and use the URL above to go to the specific comment. To unsubscribe, e-mail: commits-unsubscr...@doris.apache.org For queries about this service, please contact Infrastructure at: us...@infra.apache.org --------------------------------------------------------------------- To unsubscribe, e-mail: commits-unsubscr...@doris.apache.org For additional commands, e-mail: commits-h...@doris.apache.org