You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@doris.apache.org by mo...@apache.org on 2020/07/09 13:48:57 UTC
[incubator-doris] branch master updated: [Feature] Batch update
partition's property in one command (#3981)
This is an automated email from the ASF dual-hosted git repository.
morningman pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-doris.git
The following commit(s) were added to refs/heads/master by this push:
new d2ab38a [Feature] Batch update partition's property in one command (#3981)
d2ab38a is described below
commit d2ab38a5e00d95949a349c213c33a8cf78796b89
Author: xy720 <22...@users.noreply.github.com>
AuthorDate: Thu Jul 9 21:48:43 2020 +0800
[Feature] Batch update partition's property in one command (#3981)
Support following command.
```
alter table tbl_name modify partition (p1, p2, p3) set ("replication_num" = "3");
```
---
.../sql-statements/Data Definition/ALTER TABLE.md | 14 +-
.../sql-statements/Data Definition/ALTER TABLE.md | 14 +-
fe/src/main/cup/sql_parser.cup | 12 +-
fe/src/main/java/org/apache/doris/alter/Alter.java | 229 ++++++++++++++++++++-
.../apache/doris/alter/SchemaChangeHandler.java | 45 ++++
.../doris/analysis/ModifyPartitionClause.java | 84 +++++++-
.../java/org/apache/doris/catalog/Catalog.java | 118 -----------
.../org/apache/doris/catalog/DataProperty.java | 3 +
.../org/apache/doris/journal/JournalEntity.java | 6 +
.../doris/journal/local/LocalJournalCursor.java | 6 +
.../doris/persist/BatchModifyPartitionsInfo.java | 74 +++++++
.../java/org/apache/doris/persist/EditLog.java | 13 +-
.../apache/doris/persist/ModifyPartitionInfo.java | 21 ++
.../org/apache/doris/persist/OperationType.java | 1 +
.../java/org/apache/doris/alter/AlterTest.java | 88 ++++++++
.../persist/BatchModifyPartitionsInfoTest.java | 61 ++++++
16 files changed, 646 insertions(+), 143 deletions(-)
diff --git a/docs/en/sql-reference/sql-statements/Data Definition/ALTER TABLE.md b/docs/en/sql-reference/sql-statements/Data Definition/ALTER TABLE.md
index d7c3b54..c57f3ee 100644
--- a/docs/en/sql-reference/sql-statements/Data Definition/ALTER TABLE.md
+++ b/docs/en/sql-reference/sql-statements/Data Definition/ALTER TABLE.md
@@ -64,7 +64,7 @@ under the License.
3. Modify the partition properties
grammar:
- MODIFY PARTITION partition_name SET ("key" = "value", ...)
+ MODIFY PARTITION p1|(p1[, p2, ...]) SET ("key" = "value", ...)
Description:
1) The following attributes of the modified partition are currently supported.
- storage_medium
@@ -233,12 +233,20 @@ under the License.
4. Modify the number of partition copies
ALTER TABLE example_db.my_table
MODIFY PARTITION p1 SET("replication_num"="1");
+
+ 5. Batch modify the specified partitions
+ ALTER TABLE example_db.my_table
+ MODIFY PARTITION (p1, p2, p4) SET("in_memory"="true");
+
+ 6. Batch modify all partitions
+ ALTER TABLE example_db.my_table
+ MODIFY PARTITION (*) SET("storage_medium"="HDD");
- 5. Delete the partition
+ 7. Delete the partition
ALTER TABLE example_db.my_table
DROP PARTITION p1;
- 6. Add a partition that specifies the upper and lower bounds
+ 8. Add a partition that specifies the upper and lower bounds
ALTER TABLE example_db.my_table
ADD PARTITION p1 VALUES [("2014-01-01"), ("2014-02-01"));
diff --git a/docs/zh-CN/sql-reference/sql-statements/Data Definition/ALTER TABLE.md b/docs/zh-CN/sql-reference/sql-statements/Data Definition/ALTER TABLE.md
index 552ab28..4f5f9e6 100644
--- a/docs/zh-CN/sql-reference/sql-statements/Data Definition/ALTER TABLE.md
+++ b/docs/zh-CN/sql-reference/sql-statements/Data Definition/ALTER TABLE.md
@@ -64,7 +64,7 @@ under the License.
3. 修改分区属性
语法:
- MODIFY PARTITION partition_name SET ("key" = "value", ...)
+ MODIFY PARTITION p1|(p1[, p2, ...]) SET ("key" = "value", ...)
说明:
1) 当前支持修改分区的下列属性:
- storage_medium
@@ -230,12 +230,20 @@ under the License.
4. 修改分区副本数
ALTER TABLE example_db.my_table
MODIFY PARTITION p1 SET("replication_num"="1");
+
+ 5. 批量修改指定分区
+ ALTER TABLE example_db.my_table
+ MODIFY PARTITION (p1, p2, p4) SET("in_memory"="true");
+
+ 6. 批量修改所有分区
+ ALTER TABLE example_db.my_table
+ MODIFY PARTITION (*) SET("storage_medium"="HDD");
- 5. 删除分区
+ 7. 删除分区
ALTER TABLE example_db.my_table
DROP PARTITION p1;
- 6. 增加一个指定上下界的分区
+ 8. 增加一个指定上下界的分区
ALTER TABLE example_db.my_table
ADD PARTITION p1 VALUES [("2014-01-01"), ("2014-02-01"));
diff --git a/fe/src/main/cup/sql_parser.cup b/fe/src/main/cup/sql_parser.cup
index 5589fbd..6f40dfe 100644
--- a/fe/src/main/cup/sql_parser.cup
+++ b/fe/src/main/cup/sql_parser.cup
@@ -883,7 +883,17 @@ alter_table_clause ::=
:}
| KW_MODIFY KW_PARTITION ident:partitionName KW_SET LPAREN key_value_map:properties RPAREN
{:
- RESULT = new ModifyPartitionClause(partitionName, properties);
+ ArrayList<String> partitions = new ArrayList<String>();
+ partitions.add(partitionName);
+ RESULT = new ModifyPartitionClause(partitions, properties);
+ :}
+ | KW_MODIFY KW_PARTITION LPAREN ident_list:partitions RPAREN KW_SET LPAREN key_value_map:properties RPAREN
+ {:
+ RESULT = new ModifyPartitionClause(partitions, properties);
+ :}
+ | KW_MODIFY KW_PARTITION LPAREN STAR RPAREN KW_SET LPAREN key_value_map:properties RPAREN
+ {:
+ RESULT = ModifyPartitionClause.createStarClause(properties);
:}
| KW_REPLACE opt_partition_names:partitions KW_WITH opt_partition_names:tempPartitions opt_properties:properties
{:
diff --git a/fe/src/main/java/org/apache/doris/alter/Alter.java b/fe/src/main/java/org/apache/doris/alter/Alter.java
index 017d4b1..2bda6b1 100644
--- a/fe/src/main/java/org/apache/doris/alter/Alter.java
+++ b/fe/src/main/java/org/apache/doris/alter/Alter.java
@@ -35,9 +35,12 @@ import org.apache.doris.analysis.TableName;
import org.apache.doris.analysis.TableRenameClause;
import org.apache.doris.catalog.Catalog;
import org.apache.doris.catalog.Column;
+import org.apache.doris.catalog.DataProperty;
import org.apache.doris.catalog.Database;
import org.apache.doris.catalog.OlapTable;
import org.apache.doris.catalog.OlapTable.OlapTableState;
+import org.apache.doris.catalog.Partition;
+import org.apache.doris.catalog.PartitionInfo;
import org.apache.doris.catalog.Table;
import org.apache.doris.catalog.Table.TableType;
import org.apache.doris.catalog.View;
@@ -50,9 +53,13 @@ import org.apache.doris.common.UserException;
import org.apache.doris.common.util.DynamicPartitionUtil;
import org.apache.doris.common.util.PropertyAnalyzer;
import org.apache.doris.persist.AlterViewInfo;
+import org.apache.doris.persist.BatchModifyPartitionsInfo;
+import org.apache.doris.persist.ModifyPartitionInfo;
import org.apache.doris.qe.ConnectContext;
-
+import org.apache.doris.thrift.TTabletType;
+import com.google.common.base.Joiner;
import com.google.common.base.Preconditions;
+import com.google.common.collect.Lists;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
@@ -203,12 +210,20 @@ public class Alter {
Catalog.getCurrentCatalog().replaceTempPartition(db, tableName, (ReplacePartitionClause) alterClause);
} else if (alterClause instanceof ModifyPartitionClause) {
ModifyPartitionClause clause = ((ModifyPartitionClause) alterClause);
+ // expand the partition names if it is 'Modify Partition(*)'
+ if (clause.isNeedExpand()) {
+ List<String> partitionNames = clause.getPartitionNames();
+ partitionNames.clear();
+ for (Partition partition : olapTable.getPartitions()) {
+ partitionNames.add(partition.getName());
+ }
+ }
Map<String, String> properties = clause.getProperties();
if (properties.containsKey(PropertyAnalyzer.PROPERTIES_INMEMORY)) {
needProcessOutsideDatabaseLock = true;
} else {
- String partitionName = clause.getPartitionName();
- Catalog.getCurrentCatalog().modifyPartitionProperty(db, olapTable, partitionName, properties);
+ List<String> partitionNames = clause.getPartitionNames();
+ modifyPartitionsProperty(db, olapTable, partitionNames, properties);
}
} else if (alterClause instanceof AddPartitionClause) {
needProcessOutsideDatabaseLock = true;
@@ -238,17 +253,16 @@ public class Alter {
} else if (alterClause instanceof ModifyPartitionClause) {
ModifyPartitionClause clause = ((ModifyPartitionClause) alterClause);
Map<String, String> properties = clause.getProperties();
- String partitionName = clause.getPartitionName();
+ List<String> partitionNames = clause.getPartitionNames();
// currently, only in memory property could reach here
Preconditions.checkState(properties.containsKey(PropertyAnalyzer.PROPERTIES_INMEMORY));
- boolean isInMemory = Boolean.parseBoolean(properties.get(PropertyAnalyzer.PROPERTIES_INMEMORY));
- ((SchemaChangeHandler) schemaChangeHandler).updatePartitionInMemoryMeta(
- db, tableName, partitionName, isInMemory);
+ ((SchemaChangeHandler) schemaChangeHandler).updatePartitionsInMemoryMeta(
+ db, tableName, partitionNames, properties);
db.writeLock();
try {
OlapTable olapTable = (OlapTable) db.getTable(tableName);
- Catalog.getCurrentCatalog().modifyPartitionProperty(db, olapTable, partitionName, properties);
+ modifyPartitionsProperty(db, olapTable, partitionNames, properties);
} finally {
db.writeUnlock();
}
@@ -362,6 +376,205 @@ public class Alter {
}
}
+ /**
+ * Batch update partitions' properties
+ * caller should hold the db lock
+ */
+ public void modifyPartitionsProperty(Database db,
+ OlapTable olapTable,
+ List<String> partitionNames,
+ Map<String, String> properties)
+ throws DdlException, AnalysisException {
+ Preconditions.checkArgument(db.isWriteLockHeldByCurrentThread());
+ List<ModifyPartitionInfo> modifyPartitionInfos = Lists.newArrayList();
+ if (olapTable.getState() != OlapTableState.NORMAL) {
+ throw new DdlException("Table[" + olapTable.getName() + "]'s state is not NORMAL");
+ }
+
+ for (String partitionName : partitionNames) {
+ Partition partition = olapTable.getPartition(partitionName);
+ if (partition == null) {
+ throw new DdlException(
+ "Partition[" + partitionName + "] does not exist in table[" + olapTable.getName() + "]");
+ }
+ }
+
+ boolean hasInMemory = false;
+ if (properties.containsKey(PropertyAnalyzer.PROPERTIES_INMEMORY)) {
+ hasInMemory = true;
+ }
+
+ // get value from properties here
+ // 1. data property
+ DataProperty newDataProperty =
+ PropertyAnalyzer.analyzeDataProperty(properties, null);
+ // 2. replication num
+ short newReplicationNum =
+ PropertyAnalyzer.analyzeReplicationNum(properties, (short) -1);
+ // 3. in memory
+ boolean newInMemory = PropertyAnalyzer.analyzeBooleanProp(properties,
+ PropertyAnalyzer.PROPERTIES_INMEMORY, false);
+ // 4. tablet type
+ TTabletType tTabletType =
+ PropertyAnalyzer.analyzeTabletType(properties);
+
+ // modify meta here
+ PartitionInfo partitionInfo = olapTable.getPartitionInfo();
+ for (String partitionName : partitionNames) {
+ Partition partition = olapTable.getPartition(partitionName);
+ // 1. date property
+ if (newDataProperty != null) {
+ partitionInfo.setDataProperty(partition.getId(), newDataProperty);
+ }
+ // 2. replication num
+ if (newReplicationNum != (short) -1) {
+ partitionInfo.setReplicationNum(partition.getId(), newReplicationNum);
+ }
+ // 3. in memory
+ boolean oldInMemory = partitionInfo.getIsInMemory(partition.getId());
+ if (hasInMemory && (newInMemory != oldInMemory)) {
+ partitionInfo.setIsInMemory(partition.getId(), newInMemory);
+ }
+ // 4. tablet type
+ if (tTabletType != partitionInfo.getTabletType(partition.getId())) {
+ partitionInfo.setTabletType(partition.getId(), tTabletType);
+ }
+ ModifyPartitionInfo info = new ModifyPartitionInfo(db.getId(), olapTable.getId(), partition.getId(),
+ newDataProperty, newReplicationNum, hasInMemory ? newInMemory : oldInMemory);
+ modifyPartitionInfos.add(info);
+ }
+
+ // log here
+ BatchModifyPartitionsInfo info = new BatchModifyPartitionsInfo(modifyPartitionInfos);
+ Catalog.getCurrentCatalog().getEditLog().logBatchModifyPartition(info);
+ }
+
+ /**
+ * Update partition's properties
+ * caller should hold the db lock
+ */
+ public ModifyPartitionInfo modifyPartitionProperty(Database db,
+ OlapTable olapTable,
+ String partitionName,
+ Map<String, String> properties)
+ throws DdlException {
+ Preconditions.checkArgument(db.isWriteLockHeldByCurrentThread());
+ if (olapTable.getState() != OlapTableState.NORMAL) {
+ throw new DdlException("Table[" + olapTable.getName() + "]'s state is not NORMAL");
+ }
+
+ Partition partition = olapTable.getPartition(partitionName);
+ if (partition == null) {
+ throw new DdlException(
+ "Partition[" + partitionName + "] does not exist in table[" + olapTable.getName() + "]");
+ }
+
+ PartitionInfo partitionInfo = olapTable.getPartitionInfo();
+
+ // 1. data property
+ DataProperty oldDataProperty = partitionInfo.getDataProperty(partition.getId());
+ DataProperty newDataProperty = null;
+ try {
+ newDataProperty = PropertyAnalyzer.analyzeDataProperty(properties, oldDataProperty);
+ } catch (AnalysisException e) {
+ throw new DdlException(e.getMessage());
+ }
+ Preconditions.checkNotNull(newDataProperty);
+
+ if (newDataProperty.equals(oldDataProperty)) {
+ newDataProperty = null;
+ }
+
+ // 2. replication num
+ short oldReplicationNum = partitionInfo.getReplicationNum(partition.getId());
+ short newReplicationNum = (short) -1;
+ try {
+ newReplicationNum = PropertyAnalyzer.analyzeReplicationNum(properties, oldReplicationNum);
+ } catch (AnalysisException e) {
+ throw new DdlException(e.getMessage());
+ }
+
+ if (newReplicationNum == oldReplicationNum) {
+ newReplicationNum = (short) -1;
+ } else if (Catalog.getCurrentColocateIndex().isColocateTable(olapTable.getId())) {
+ ErrorReport.reportDdlException(ErrorCode.ERR_COLOCATE_TABLE_MUST_HAS_SAME_REPLICATION_NUM, oldReplicationNum);
+ }
+
+ // 3. in memory
+ boolean isInMemory = PropertyAnalyzer.analyzeBooleanProp(properties,
+ PropertyAnalyzer.PROPERTIES_INMEMORY, partitionInfo.getIsInMemory(partition.getId()));
+
+ // 4. tablet type
+ TTabletType tabletType = TTabletType.TABLET_TYPE_DISK;
+ try {
+ tabletType = PropertyAnalyzer.analyzeTabletType(properties);
+ } catch (AnalysisException e) {
+ throw new DdlException(e.getMessage());
+ }
+
+ // check if has other undefined properties
+ if (properties != null && !properties.isEmpty()) {
+ Joiner.MapJoiner mapJoiner = Joiner.on(", ").withKeyValueSeparator(" = ");
+ throw new DdlException("Unknown properties: " + mapJoiner.join(properties));
+ }
+
+ // modify meta here
+ // date property
+ if (newDataProperty != null) {
+ partitionInfo.setDataProperty(partition.getId(), newDataProperty);
+ LOG.debug("modify partition[{}-{}-{}] data property to {}", db.getId(), olapTable.getId(), partitionName,
+ newDataProperty.toString());
+ }
+
+ // replication num
+ if (newReplicationNum != (short) -1) {
+ partitionInfo.setReplicationNum(partition.getId(), newReplicationNum);
+ LOG.debug("modify partition[{}-{}-{}] replication num to {}", db.getId(), olapTable.getId(), partitionName,
+ newReplicationNum);
+ }
+
+ // in memory
+ if (isInMemory != partitionInfo.getIsInMemory(partition.getId())) {
+ partitionInfo.setIsInMemory(partition.getId(), isInMemory);
+ LOG.debug("modify partition[{}-{}-{}] in memory to {}", db.getId(), olapTable.getId(), partitionName,
+ isInMemory);
+ }
+
+ // tablet type
+ // TODO: serialize to edit log
+ if (tabletType != partitionInfo.getTabletType(partition.getId())) {
+ partitionInfo.setTabletType(partition.getId(), tabletType);
+ LOG.debug("modify partition[{}-{}-{}] tablet type to {}", db.getId(), olapTable.getId(), partitionName,
+ tabletType);
+ }
+
+ // log
+ ModifyPartitionInfo info = new ModifyPartitionInfo(db.getId(), olapTable.getId(), partition.getId(),
+ newDataProperty, newReplicationNum, isInMemory);
+ Catalog.getCurrentCatalog().getEditLog().logModifyPartition(info);
+
+ LOG.info("finish modify partition[{}-{}-{}]", db.getId(), olapTable.getId(), partitionName);
+ return info;
+ }
+
+ public void replayModifyPartition(ModifyPartitionInfo info) {
+ Database db = Catalog.getCurrentCatalog().getDb(info.getDbId());
+ db.writeLock();
+ try {
+ OlapTable olapTable = (OlapTable) db.getTable(info.getTableId());
+ PartitionInfo partitionInfo = olapTable.getPartitionInfo();
+ if (info.getDataProperty() != null) {
+ partitionInfo.setDataProperty(info.getPartitionId(), info.getDataProperty());
+ }
+ if (info.getReplicationNum() != (short) -1) {
+ partitionInfo.setReplicationNum(info.getPartitionId(), info.getReplicationNum());
+ }
+ partitionInfo.setIsInMemory(info.getPartitionId(), info.isInMemory());
+ } finally {
+ db.writeUnlock();
+ }
+ }
+
public AlterHandler getSchemaChangeHandler() {
return this.schemaChangeHandler;
}
diff --git a/fe/src/main/java/org/apache/doris/alter/SchemaChangeHandler.java b/fe/src/main/java/org/apache/doris/alter/SchemaChangeHandler.java
index 3e5b71d..98074f8 100644
--- a/fe/src/main/java/org/apache/doris/alter/SchemaChangeHandler.java
+++ b/fe/src/main/java/org/apache/doris/alter/SchemaChangeHandler.java
@@ -1463,6 +1463,9 @@ public class SchemaChangeHandler extends AlterHandler {
LOG.info("send clear alter task for table {}, number: {}", olapTable.getName(), batchTask.getTaskNum());
}
+ /**
+ * Update all partitions' in-memory property of table
+ */
public void updateTableInMemoryMeta(Database db, String tableName, Map<String, String> properties) throws DdlException {
List<Partition> partitions = Lists.newArrayList();
OlapTable olapTable;
@@ -1491,6 +1494,48 @@ public class SchemaChangeHandler extends AlterHandler {
}
}
+ /**
+ * Update some specified partitions' in-memory property of table
+ */
+ public void updatePartitionsInMemoryMeta(Database db,
+ String tableName,
+ List<String> partitionNames,
+ Map<String, String> properties) throws DdlException {
+ OlapTable olapTable;
+ db.readLock();
+ try {
+ olapTable = (OlapTable)db.getTable(tableName);
+ for (String partitionName : partitionNames) {
+ Partition partition = olapTable.getPartition(partitionName);
+ if (partition == null) {
+ throw new DdlException("Partition[" + partitionName + "] does not exist in " +
+ "table[" + olapTable.getName() + "]");
+ }
+ }
+ } finally {
+ db.readUnlock();
+ }
+
+ boolean isInMemory = Boolean.parseBoolean(properties.get(PropertyAnalyzer.PROPERTIES_INMEMORY));
+ if (isInMemory == olapTable.isInMemory()) {
+ return;
+ }
+
+ for(String partitionName : partitionNames) {
+ try {
+ updatePartitionInMemoryMeta(db, olapTable.getName(), partitionName, isInMemory);
+ } catch (Exception e) {
+ String errMsg = "Failed to update partition[" + partitionName + "]'s 'in_memory' property. " +
+ "The reason is [" + e.getMessage() + "]";
+ throw new DdlException(errMsg);
+ }
+ }
+ }
+
+ /**
+ * Update one specified partition's in-memory property by partition name of table
+ * This operation may return partial successfully, with a exception to inform user to retry
+ */
public void updatePartitionInMemoryMeta(Database db,
String tableName,
String partitionName,
diff --git a/fe/src/main/java/org/apache/doris/analysis/ModifyPartitionClause.java b/fe/src/main/java/org/apache/doris/analysis/ModifyPartitionClause.java
index 6f9c21f..cba71ae 100644
--- a/fe/src/main/java/org/apache/doris/analysis/ModifyPartitionClause.java
+++ b/fe/src/main/java/org/apache/doris/analysis/ModifyPartitionClause.java
@@ -18,27 +18,40 @@
package org.apache.doris.analysis;
import org.apache.doris.alter.AlterOpType;
+import org.apache.doris.catalog.DataProperty;
import org.apache.doris.common.AnalysisException;
+import org.apache.doris.common.FeConstants;
import org.apache.doris.common.util.PrintableMap;
-
+import org.apache.doris.common.util.PropertyAnalyzer;
+import com.google.common.base.Joiner;
+import com.google.common.base.Preconditions;
import com.google.common.base.Strings;
+import com.google.common.collect.Lists;
+import com.google.common.collect.Maps;
+import java.util.List;
import java.util.Map;
// clause which is used to modify partition properties
+// 1. Modify Partition p1 set ("replication_num" = "3")
+// 2. Modify Partition (p1, p3, p4) set ("replication_num" = "3")
+// 3. Modify Partition (*) set ("replication_num" = "3")
public class ModifyPartitionClause extends AlterTableClause {
- private String partitionName;
+ private List<String> partitionNames;
private Map<String, String> properties;
+ private boolean needExpand = false;
- public String getPartitionName() {
- return partitionName;
+ public List<String> getPartitionNames() {
+ return partitionNames;
}
- public ModifyPartitionClause(String partitionName, Map<String, String> properties) {
+ // c'tor for non-star clause
+ public ModifyPartitionClause(List<String> partitionNames, Map<String, String> properties) {
super(AlterOpType.MODIFY_PARTITION);
- this.partitionName = partitionName;
+ this.partitionNames = partitionNames;
this.properties = properties;
+ this.needExpand = false;
// ATTN: currently, modify partition only allow 3 kinds of operations:
// 1. modify replication num
// 2. modify data property
@@ -48,15 +61,58 @@ public class ModifyPartitionClause extends AlterTableClause {
this.needTableStable = false;
}
+ // c'tor for 'Modify Partition(*)' clause
+ private ModifyPartitionClause(Map<String, String> properties) {
+ super(AlterOpType.MODIFY_PARTITION);
+ this.partitionNames = Lists.newArrayList();
+ this.properties = properties;
+ this.needExpand = true;
+ this.needTableStable = false;
+ }
+
+ public static ModifyPartitionClause createStarClause(Map<String, String> properties) {
+ return new ModifyPartitionClause(properties);
+ }
+
@Override
public void analyze(Analyzer analyzer) throws AnalysisException {
- if (Strings.isNullOrEmpty(partitionName)) {
- throw new AnalysisException("Partition name is not set");
+ if (partitionNames == null || (!needExpand && partitionNames.isEmpty())) {
+ throw new AnalysisException("Partition names is not set or empty");
+ }
+
+ if (partitionNames.stream().anyMatch(entity -> Strings.isNullOrEmpty(entity))) {
+ throw new AnalysisException("there are empty partition name");
}
if (properties == null || properties.isEmpty()) {
throw new AnalysisException("Properties is not set");
}
+
+ // check properties here
+ checkProperties(Maps.newHashMap(properties));
+ }
+
+ // Check the following properties' legality before modifying partition.
+ // 1. replication_num
+ // 2. storage_medium && storage_cooldown_time
+ // 3. in_memory
+ // 4. tablet type
+ private void checkProperties(Map<String, String> properties) throws AnalysisException {
+ // 1. data property
+ DataProperty newDataProperty = null;
+ newDataProperty = PropertyAnalyzer.analyzeDataProperty(properties, DataProperty.DEFAULT_DATA_PROPERTY);
+ Preconditions.checkNotNull(newDataProperty);
+
+ // 2. replication num
+ short newReplicationNum = (short) -1;
+ newReplicationNum = PropertyAnalyzer.analyzeReplicationNum(properties, FeConstants.default_replication_num);
+ Preconditions.checkState(newReplicationNum != (short) -1);
+
+ // 3. in memory
+ PropertyAnalyzer.analyzeBooleanProp(properties, PropertyAnalyzer.PROPERTIES_INMEMORY, false);
+
+ // 4. tablet type
+ PropertyAnalyzer.analyzeTabletType(properties);
}
@Override
@@ -64,11 +120,21 @@ public class ModifyPartitionClause extends AlterTableClause {
return this.properties;
}
+ public boolean isNeedExpand() {
+ return this.needExpand;
+ }
+
@Override
public String toSql() {
StringBuilder sb = new StringBuilder();
sb.append("MODIFY PARTITION ");
- sb.append(partitionName);
+ sb.append("(");
+ if (needExpand) {
+ sb.append("*");
+ } else {
+ sb.append(Joiner.on(", ").join(partitionNames));
+ }
+ sb.append(")");
sb.append(" SET (");
sb.append(new PrintableMap<String, String>(properties, "=", true, false));
sb.append(")");
diff --git a/fe/src/main/java/org/apache/doris/catalog/Catalog.java b/fe/src/main/java/org/apache/doris/catalog/Catalog.java
index 0c0251b..d1a4460 100755
--- a/fe/src/main/java/org/apache/doris/catalog/Catalog.java
+++ b/fe/src/main/java/org/apache/doris/catalog/Catalog.java
@@ -208,9 +208,7 @@ import org.apache.doris.thrift.TTabletType;
import org.apache.doris.thrift.TTaskType;
import org.apache.doris.transaction.GlobalTransactionMgr;
import org.apache.doris.transaction.PublishVersionDaemon;
-
import com.google.common.base.Joiner;
-import com.google.common.base.Joiner.MapJoiner;
import com.google.common.base.Preconditions;
import com.google.common.base.Strings;
import com.google.common.collect.HashMultimap;
@@ -3349,122 +3347,6 @@ public class Catalog {
}
}
- public void modifyPartitionProperty(Database db, OlapTable olapTable, String partitionName, Map<String, String> properties)
- throws DdlException {
- Preconditions.checkArgument(db.isWriteLockHeldByCurrentThread());
- if (olapTable.getState() != OlapTableState.NORMAL) {
- throw new DdlException("Table[" + olapTable.getName() + "]'s state is not NORMAL");
- }
-
- Partition partition = olapTable.getPartition(partitionName);
- if (partition == null) {
- throw new DdlException(
- "Partition[" + partitionName + "] does not exist in table[" + olapTable.getName() + "]");
- }
-
- PartitionInfo partitionInfo = olapTable.getPartitionInfo();
-
- // 1. data property
- DataProperty oldDataProperty = partitionInfo.getDataProperty(partition.getId());
- DataProperty newDataProperty = null;
- try {
- newDataProperty = PropertyAnalyzer.analyzeDataProperty(properties, oldDataProperty);
- } catch (AnalysisException e) {
- throw new DdlException(e.getMessage());
- }
- Preconditions.checkNotNull(newDataProperty);
-
- if (newDataProperty.equals(oldDataProperty)) {
- newDataProperty = null;
- }
-
- // 2. replication num
- short oldReplicationNum = partitionInfo.getReplicationNum(partition.getId());
- short newReplicationNum = (short) -1;
- try {
- newReplicationNum = PropertyAnalyzer.analyzeReplicationNum(properties, oldReplicationNum);
- } catch (AnalysisException e) {
- throw new DdlException(e.getMessage());
- }
-
- if (newReplicationNum == oldReplicationNum) {
- newReplicationNum = (short) -1;
- } else if (Catalog.getCurrentColocateIndex().isColocateTable(olapTable.getId())) {
- ErrorReport.reportDdlException(ErrorCode.ERR_COLOCATE_TABLE_MUST_HAS_SAME_REPLICATION_NUM, oldReplicationNum);
- }
-
- // 3. in memory
- boolean isInMemory = PropertyAnalyzer.analyzeBooleanProp(properties,
- PropertyAnalyzer.PROPERTIES_INMEMORY, partitionInfo.getIsInMemory(partition.getId()));
-
- // 4. tablet type
- TTabletType tabletType = TTabletType.TABLET_TYPE_DISK;
- try {
- tabletType = PropertyAnalyzer.analyzeTabletType(properties);
- } catch (AnalysisException e) {
- throw new DdlException(e.getMessage());
- }
-
- // check if has other undefined properties
- if (properties != null && !properties.isEmpty()) {
- MapJoiner mapJoiner = Joiner.on(", ").withKeyValueSeparator(" = ");
- throw new DdlException("Unknown properties: " + mapJoiner.join(properties));
- }
-
- // modify meta here
- // date property
- if (newDataProperty != null) {
- partitionInfo.setDataProperty(partition.getId(), newDataProperty);
- LOG.debug("modify partition[{}-{}-{}] data property to {}", db.getId(), olapTable.getId(), partitionName,
- newDataProperty.toString());
- }
-
- // replication num
- if (newReplicationNum != (short) -1) {
- partitionInfo.setReplicationNum(partition.getId(), newReplicationNum);
- LOG.debug("modify partition[{}-{}-{}] replication num to {}", db.getId(), olapTable.getId(), partitionName,
- newReplicationNum);
- }
-
- // in memory
- if (isInMemory != partitionInfo.getIsInMemory(partition.getId())) {
- partitionInfo.setIsInMemory(partition.getId(), isInMemory);
- LOG.debug("modify partition[{}-{}-{}] in memory to {}", db.getId(), olapTable.getId(), partitionName,
- isInMemory);
- }
-
- // tablet type
- // TODO: serialize to edit log
- if (tabletType != partitionInfo.getTabletType(partition.getId())) {
- partitionInfo.setTabletType(partition.getId(), tabletType);
- LOG.debug("modify partition[{}-{}-{}] tablet type to {}", db.getId(), olapTable.getId(), partitionName,
- tabletType);
- }
-
- // log
- ModifyPartitionInfo info = new ModifyPartitionInfo(db.getId(), olapTable.getId(), partition.getId(),
- newDataProperty, newReplicationNum, isInMemory);
- editLog.logModifyPartition(info);
- }
-
- public void replayModifyPartition(ModifyPartitionInfo info) {
- Database db = this.getDb(info.getDbId());
- db.writeLock();
- try {
- OlapTable olapTable = (OlapTable) db.getTable(info.getTableId());
- PartitionInfo partitionInfo = olapTable.getPartitionInfo();
- if (info.getDataProperty() != null) {
- partitionInfo.setDataProperty(info.getPartitionId(), info.getDataProperty());
- }
- if (info.getReplicationNum() != (short) -1) {
- partitionInfo.setReplicationNum(info.getPartitionId(), info.getReplicationNum());
- }
- partitionInfo.setIsInMemory(info.getPartitionId(), info.isInMemory());
- } finally {
- db.writeUnlock();
- }
- }
-
private Partition createPartitionWithIndices(String clusterName, long dbId, long tableId,
long baseIndexId, long partitionId, String partitionName,
Map<Long, MaterializedIndexMeta> indexIdToMeta,
diff --git a/fe/src/main/java/org/apache/doris/catalog/DataProperty.java b/fe/src/main/java/org/apache/doris/catalog/DataProperty.java
index ec5fb9a..593f3d3 100644
--- a/fe/src/main/java/org/apache/doris/catalog/DataProperty.java
+++ b/fe/src/main/java/org/apache/doris/catalog/DataProperty.java
@@ -22,6 +22,7 @@ import org.apache.doris.common.io.Text;
import org.apache.doris.common.io.Writable;
import org.apache.doris.common.util.TimeUtils;
import org.apache.doris.thrift.TStorageMedium;
+import com.google.gson.annotations.SerializedName;
import java.io.DataInput;
import java.io.DataOutput;
@@ -32,7 +33,9 @@ public class DataProperty implements Writable {
"SSD".equalsIgnoreCase(Config.default_storage_medium) ? TStorageMedium.SSD : TStorageMedium.HDD);
public static final long MAX_COOLDOWN_TIME_MS = 253402271999000L; // 9999-12-31 23:59:59
+ @SerializedName(value = "storageMedium")
private TStorageMedium storageMedium;
+ @SerializedName(value = "cooldownTimeMs")
private long cooldownTimeMs;
private DataProperty() {
diff --git a/fe/src/main/java/org/apache/doris/journal/JournalEntity.java b/fe/src/main/java/org/apache/doris/journal/JournalEntity.java
index 5704bc7..f76dfed 100644
--- a/fe/src/main/java/org/apache/doris/journal/JournalEntity.java
+++ b/fe/src/main/java/org/apache/doris/journal/JournalEntity.java
@@ -50,6 +50,7 @@ import org.apache.doris.persist.AlterViewInfo;
import org.apache.doris.persist.BackendIdsUpdateInfo;
import org.apache.doris.persist.BackendTabletsInfo;
import org.apache.doris.persist.BatchDropInfo;
+import org.apache.doris.persist.BatchModifyPartitionsInfo;
import org.apache.doris.persist.ClusterInfo;
import org.apache.doris.persist.ColocatePersistInfo;
import org.apache.doris.persist.ConsistencyCheckInfo;
@@ -189,6 +190,11 @@ public class JournalEntity implements Writable {
isRead = true;
break;
}
+ case OperationType.OP_BATCH_MODIFY_PARTITION: {
+ data = BatchModifyPartitionsInfo.read(in);
+ isRead = true;
+ break;
+ }
case OperationType.OP_ERASE_DB:
case OperationType.OP_ERASE_TABLE:
case OperationType.OP_ERASE_PARTITION: {
diff --git a/fe/src/main/java/org/apache/doris/journal/local/LocalJournalCursor.java b/fe/src/main/java/org/apache/doris/journal/local/LocalJournalCursor.java
index 57f1bf2..34f39d9 100644
--- a/fe/src/main/java/org/apache/doris/journal/local/LocalJournalCursor.java
+++ b/fe/src/main/java/org/apache/doris/journal/local/LocalJournalCursor.java
@@ -29,6 +29,7 @@ import org.apache.doris.load.DeleteInfo;
import org.apache.doris.load.LoadErrorHub;
import org.apache.doris.load.LoadJob;
import org.apache.doris.persist.BatchDropInfo;
+import org.apache.doris.persist.BatchModifyPartitionsInfo;
import org.apache.doris.persist.ConsistencyCheckInfo;
import org.apache.doris.persist.CreateTableInfo;
import org.apache.doris.persist.DatabaseInfo;
@@ -250,6 +251,11 @@ public final class LocalJournalCursor implements JournalCursor {
ret.setData(info);
break;
}
+ case OperationType.OP_BATCH_MODIFY_PARTITION: {
+ BatchModifyPartitionsInfo info = BatchModifyPartitionsInfo.read(in);
+ ret.setData(info);
+ break;
+ }
case OperationType.OP_ERASE_DB:
case OperationType.OP_ERASE_TABLE:
case OperationType.OP_ERASE_PARTITION: {
diff --git a/fe/src/main/java/org/apache/doris/persist/BatchModifyPartitionsInfo.java b/fe/src/main/java/org/apache/doris/persist/BatchModifyPartitionsInfo.java
new file mode 100644
index 0000000..86f32ed
--- /dev/null
+++ b/fe/src/main/java/org/apache/doris/persist/BatchModifyPartitionsInfo.java
@@ -0,0 +1,74 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+package org.apache.doris.persist;
+
+import org.apache.doris.common.io.Text;
+import org.apache.doris.common.io.Writable;
+import org.apache.doris.persist.gson.GsonUtils;
+import com.google.gson.annotations.SerializedName;
+
+import java.io.DataInput;
+import java.io.DataOutput;
+import java.io.IOException;
+import java.util.List;
+
+/**
+ * used for batch modify multi partitions in one atomic operation
+ */
+
+public class BatchModifyPartitionsInfo implements Writable {
+ @SerializedName(value = "infos")
+ private List<ModifyPartitionInfo> infos;
+
+ public BatchModifyPartitionsInfo(List<ModifyPartitionInfo> infos) {
+ this.infos = infos;
+ }
+
+ @Override
+ public void write(DataOutput out) throws IOException {
+ Text.writeString(out, GsonUtils.GSON.toJson(this));
+ }
+
+ public static BatchModifyPartitionsInfo read(DataInput in) throws IOException {
+ String json = Text.readString(in);
+ return GsonUtils.GSON.fromJson(json, BatchModifyPartitionsInfo.class);
+ }
+
+ public List<ModifyPartitionInfo> getModifyPartitionInfos() {
+ return infos;
+ }
+
+ @Override
+ public boolean equals(Object other) {
+ if (this == other) {
+ return true;
+ }
+ if (!(other instanceof BatchModifyPartitionsInfo)) {
+ return false;
+ }
+ List<ModifyPartitionInfo> otherInfos = ((BatchModifyPartitionsInfo) other).getModifyPartitionInfos();
+ for (ModifyPartitionInfo thisInfo : infos) {
+ for (ModifyPartitionInfo otherInfo : otherInfos) {
+ if (!thisInfo.equals(otherInfo)) {
+ return false;
+ }
+ }
+ }
+ return true;
+ }
+}
diff --git a/fe/src/main/java/org/apache/doris/persist/EditLog.java b/fe/src/main/java/org/apache/doris/persist/EditLog.java
index 14bb416..728ee0e 100644
--- a/fe/src/main/java/org/apache/doris/persist/EditLog.java
+++ b/fe/src/main/java/org/apache/doris/persist/EditLog.java
@@ -212,7 +212,14 @@ public class EditLog {
ModifyPartitionInfo info = (ModifyPartitionInfo) journal.getData();
LOG.info("Begin to unprotect modify partition. db = " + info.getDbId()
+ " table = " + info.getTableId() + " partitionId = " + info.getPartitionId());
- catalog.replayModifyPartition(info);
+ catalog.getAlterInstance().replayModifyPartition(info);
+ break;
+ }
+ case OperationType.OP_BATCH_MODIFY_PARTITION: {
+ BatchModifyPartitionsInfo info = (BatchModifyPartitionsInfo) journal.getData();
+ for(ModifyPartitionInfo modifyPartitionInfo : info.getModifyPartitionInfos()) {
+ catalog.getAlterInstance().replayModifyPartition(modifyPartitionInfo);
+ }
break;
}
case OperationType.OP_ERASE_TABLE: {
@@ -922,6 +929,10 @@ public class EditLog {
logEdit(OperationType.OP_MODIFY_PARTITION, info);
}
+ public void logBatchModifyPartition(BatchModifyPartitionsInfo info) {
+ logEdit(OperationType.OP_BATCH_MODIFY_PARTITION, info);
+ }
+
public void logDropTable(DropInfo info) {
logEdit(OperationType.OP_DROP_TABLE, info);
}
diff --git a/fe/src/main/java/org/apache/doris/persist/ModifyPartitionInfo.java b/fe/src/main/java/org/apache/doris/persist/ModifyPartitionInfo.java
index 56a6d0d..7996906 100644
--- a/fe/src/main/java/org/apache/doris/persist/ModifyPartitionInfo.java
+++ b/fe/src/main/java/org/apache/doris/persist/ModifyPartitionInfo.java
@@ -21,6 +21,7 @@ import org.apache.doris.catalog.Catalog;
import org.apache.doris.catalog.DataProperty;
import org.apache.doris.common.FeMetaVersion;
import org.apache.doris.common.io.Writable;
+import com.google.gson.annotations.SerializedName;
import java.io.DataInput;
import java.io.DataOutput;
@@ -28,11 +29,17 @@ import java.io.IOException;
public class ModifyPartitionInfo implements Writable {
+ @SerializedName(value = "dbId")
private long dbId;
+ @SerializedName(value = "tableId")
private long tableId;
+ @SerializedName(value = "partitionId")
private long partitionId;
+ @SerializedName(value = "dataProperty")
private DataProperty dataProperty;
+ @SerializedName(value = "replicationNum")
private short replicationNum;
+ @SerializedName(value = "isInMemory")
private boolean isInMemory;
public ModifyPartitionInfo() {
@@ -81,6 +88,20 @@ public class ModifyPartitionInfo implements Writable {
}
@Override
+ public boolean equals(Object other) {
+ if (this == other) {
+ return true;
+ }
+ if (!(other instanceof ModifyPartitionInfo)) {
+ return false;
+ }
+ ModifyPartitionInfo otherInfo = (ModifyPartitionInfo) other;
+ return dbId == otherInfo.getDbId() && tableId == otherInfo.getTableId() &&
+ dataProperty.equals(otherInfo.getDataProperty()) && replicationNum == otherInfo.getReplicationNum()
+ && isInMemory == otherInfo.isInMemory();
+ }
+
+ @Override
public void write(DataOutput out) throws IOException {
out.writeLong(dbId);
out.writeLong(tableId);
diff --git a/fe/src/main/java/org/apache/doris/persist/OperationType.java b/fe/src/main/java/org/apache/doris/persist/OperationType.java
index 01171e6..969160c 100644
--- a/fe/src/main/java/org/apache/doris/persist/OperationType.java
+++ b/fe/src/main/java/org/apache/doris/persist/OperationType.java
@@ -44,6 +44,7 @@ public class OperationType {
public static final short OP_TRUNCATE_TABLE = 118;
public static final short OP_MODIFY_VIEW_DEF = 119;
public static final short OP_REPLACE_TEMP_PARTITION = 210;
+ public static final short OP_BATCH_MODIFY_PARTITION = 211;
// 20~29 120~129 220~229 ...
public static final short OP_START_ROLLUP = 20;
diff --git a/fe/src/test/java/org/apache/doris/alter/AlterTest.java b/fe/src/test/java/org/apache/doris/alter/AlterTest.java
index 26669be..41dadc0 100644
--- a/fe/src/test/java/org/apache/doris/alter/AlterTest.java
+++ b/fe/src/test/java/org/apache/doris/alter/AlterTest.java
@@ -20,14 +20,20 @@ package org.apache.doris.alter;
import org.apache.doris.analysis.AlterTableStmt;
import org.apache.doris.analysis.CreateDbStmt;
import org.apache.doris.analysis.CreateTableStmt;
+import org.apache.doris.analysis.DateLiteral;
import org.apache.doris.catalog.Catalog;
+import org.apache.doris.catalog.DataProperty;
import org.apache.doris.catalog.Database;
import org.apache.doris.catalog.OlapTable;
import org.apache.doris.catalog.Partition;
+import org.apache.doris.catalog.Type;
import org.apache.doris.common.Config;
import org.apache.doris.common.FeConstants;
+import org.apache.doris.common.util.TimeUtils;
import org.apache.doris.qe.ConnectContext;
+import org.apache.doris.thrift.TStorageMedium;
import org.apache.doris.utframe.UtFrameUtils;
+import com.google.common.collect.Lists;
import org.junit.AfterClass;
import org.junit.Assert;
@@ -35,6 +41,7 @@ import org.junit.BeforeClass;
import org.junit.Test;
import java.io.File;
+import java.util.List;
import java.util.Map;
import java.util.UUID;
@@ -94,6 +101,28 @@ public class AlterTest {
")\n" +
"DISTRIBUTED BY HASH(k2) BUCKETS 3\n" +
"PROPERTIES('replication_num' = '1');");
+
+ createTable("CREATE TABLE test.tbl4\n" +
+ "(\n" +
+ " k1 date,\n" +
+ " k2 int,\n" +
+ " v1 int sum\n" +
+ ")\n" +
+ "PARTITION BY RANGE(k1)\n" +
+ "(\n" +
+ " PARTITION p1 values less than('2020-02-01'),\n" +
+ " PARTITION p2 values less than('2020-03-01'),\n" +
+ " PARTITION p3 values less than('2020-04-01'),\n" +
+ " PARTITION p4 values less than('2020-05-01')\n" +
+ ")\n" +
+ "DISTRIBUTED BY HASH(k2) BUCKETS 3\n" +
+ "PROPERTIES" +
+ "(" +
+ " 'replication_num' = '1',\n" +
+ " 'in_memory' = 'false',\n" +
+ " 'storage_medium' = 'SSD',\n" +
+ " 'storage_cooldown_time' = '9999-12-31 00:00:00'\n" +
+ ");");
}
@AfterClass
@@ -213,6 +242,65 @@ public class AlterTest {
alterTable(stmt, false);
}
+ // test batch update range partitions' properties
+ @Test
+ public void testBatchUpdatePartitionProperties() throws Exception {
+ Database db = Catalog.getCurrentCatalog().getDb("default_cluster:test");
+ OlapTable tbl4 = (OlapTable) db.getTable("tbl4");
+ Partition p1 = tbl4.getPartition("p1");
+ Partition p2 = tbl4.getPartition("p2");
+ Partition p3 = tbl4.getPartition("p3");
+ Partition p4 = tbl4.getPartition("p4");
+
+ // batch update replication_num property
+ String stmt = "alter table test.tbl4 modify partition (p1, p2, p4) set ('replication_num' = '3')";
+ List<Partition> partitionList = Lists.newArrayList(p1, p2, p4);
+ for (Partition partition : partitionList) {
+ Assert.assertEquals(Short.valueOf("1"), Short.valueOf(tbl4.getPartitionInfo().getReplicationNum(partition.getId())));
+ }
+ alterTable(stmt, false);
+ for (Partition partition : partitionList) {
+ Assert.assertEquals(Short.valueOf("3"), Short.valueOf(tbl4.getPartitionInfo().getReplicationNum(partition.getId())));
+ }
+ Assert.assertEquals(Short.valueOf("1"), Short.valueOf(tbl4.getPartitionInfo().getReplicationNum(p3.getId())));
+
+ // batch update in_memory property
+ stmt = "alter table test.tbl4 modify partition (p1, p2, p3) set ('in_memory' = 'true')";
+ partitionList = Lists.newArrayList(p1, p2, p3);
+ for (Partition partition : partitionList) {
+ Assert.assertEquals(false, tbl4.getPartitionInfo().getIsInMemory(partition.getId()));
+ }
+ alterTable(stmt, false);
+ for (Partition partition : partitionList) {
+ Assert.assertEquals(true, tbl4.getPartitionInfo().getIsInMemory(partition.getId()));
+ }
+ Assert.assertEquals(false, tbl4.getPartitionInfo().getIsInMemory(p4.getId()));
+
+ // batch update storage_medium and storage_cool_down properties
+ stmt = "alter table test.tbl4 modify partition (p2, p3, p4) set ('storage_medium' = 'HDD')";
+ DateLiteral dateLiteral = new DateLiteral("9999-12-31 00:00:00", Type.DATETIME);
+ long coolDownTimeMs = dateLiteral.unixTimestamp(TimeUtils.getTimeZone());
+ DataProperty oldDataProperty = new DataProperty(TStorageMedium.SSD, coolDownTimeMs);
+ partitionList = Lists.newArrayList(p2, p3, p4);
+ for (Partition partition : partitionList) {
+ Assert.assertEquals(oldDataProperty, tbl4.getPartitionInfo().getDataProperty(partition.getId()));
+ }
+ alterTable(stmt, false);
+ DataProperty newDataProperty = new DataProperty(TStorageMedium.HDD, DataProperty.MAX_COOLDOWN_TIME_MS);
+ for (Partition partition : partitionList) {
+ Assert.assertEquals(newDataProperty, tbl4.getPartitionInfo().getDataProperty(partition.getId()));
+ }
+ Assert.assertEquals(oldDataProperty, tbl4.getPartitionInfo().getDataProperty(p1.getId()));
+
+ // batch update range partitions' properties with *
+ stmt = "alter table test.tbl4 modify partition (*) set ('replication_num' = '1')";
+ partitionList = Lists.newArrayList(p1, p2, p3, p4);
+ alterTable(stmt, false);
+ for (Partition partition : partitionList) {
+ Assert.assertEquals(Short.valueOf("1"), Short.valueOf(tbl4.getPartitionInfo().getReplicationNum(partition.getId())));
+ }
+ }
+
@Test
public void testDynamicPartitionDropAndAdd() throws Exception {
// test day range
diff --git a/fe/src/test/java/org/apache/doris/persist/BatchModifyPartitionsInfoTest.java b/fe/src/test/java/org/apache/doris/persist/BatchModifyPartitionsInfoTest.java
new file mode 100644
index 0000000..e2b8c18
--- /dev/null
+++ b/fe/src/test/java/org/apache/doris/persist/BatchModifyPartitionsInfoTest.java
@@ -0,0 +1,61 @@
+package org.apache.doris.persist;
+
+import org.apache.doris.catalog.DataProperty;
+import org.apache.doris.common.AnalysisException;
+import com.google.common.collect.Lists;
+
+import org.junit.After;
+import org.junit.Assert;
+import org.junit.Test;
+
+import java.io.DataInputStream;
+import java.io.DataOutputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.util.List;
+
+public class BatchModifyPartitionsInfoTest {
+ private static String fileName = "./BatchModifyPartitionsInfoTest";
+
+ private final long DB_ID = 10000L;
+ private final long TB_ID = 30000L;
+ private final long PARTITION_ID_1 = 40000L;
+ private final long PARTITION_ID_2 = 40001L;
+ private final long PARTITION_ID_3 = 40002L;
+
+ @After
+ public void tearDown() {
+ File file = new File(fileName);
+ file.delete();
+ }
+
+ @Test
+ public void testSerialzeBatchModifyPartitionsInfo() throws IOException, AnalysisException {
+ List<ModifyPartitionInfo> ModifyInfos = Lists.newArrayList();
+ // 1. Write objects to file
+ File file = new File(fileName);
+ file.createNewFile();
+ DataOutputStream out = new DataOutputStream(new FileOutputStream(file));
+
+ List<Long> partitionIds = Lists.newArrayList(PARTITION_ID_1, PARTITION_ID_2, PARTITION_ID_3);
+ for (long partitionId : partitionIds) {
+ ModifyInfos.add(new ModifyPartitionInfo(DB_ID, TB_ID, partitionId,
+ DataProperty.DEFAULT_DATA_PROPERTY, (short) 3, true));
+ }
+
+ BatchModifyPartitionsInfo batchModifyPartitionsInfo = new BatchModifyPartitionsInfo(ModifyInfos);
+ batchModifyPartitionsInfo.write(out);
+ out.flush();
+ out.close();
+
+ // 2. Read objects from file
+ DataInputStream in = new DataInputStream(new FileInputStream(file));
+
+ BatchModifyPartitionsInfo readBatchModifyPartitionsInfo = BatchModifyPartitionsInfo.read(in);
+ Assert.assertEquals(batchModifyPartitionsInfo, readBatchModifyPartitionsInfo);
+
+ in.close();
+ }
+}
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@doris.apache.org
For additional commands, e-mail: commits-help@doris.apache.org