From 867a151ca541a0207f2948ef326cbc5487e7538d Mon Sep 17 00:00:00 2001 From: libo Date: Thu, 18 Jun 2026 16:51:40 +0800 Subject: [PATCH 1/8] Supply the max_schema/data_region_group_num param to modify schema when create or alter database --- .../IoTDBDatabaseRegionControlIT.java | 18 +- .../manual/enhanced/IoTDBPipeMetaIT.java | 1 - .../auto/enhanced/IoTDBPipeIdempotentIT.java | 2 +- .../relational/it/schema/IoTDBDatabaseIT.java | 33 ++- .../IoTDBDatabaseMaxRegionGroupNumIT.java | 100 ++++++++ ...IoTDBDatabaseMixedRegionGroupPolicyIT.java | 77 ++++++ .../iotdb/db/qp/sql/IdentifierParser.g4 | 4 +- .../apache/iotdb/db/qp/sql/IoTDBSqlParser.g4 | 4 +- .../org/apache/iotdb/db/qp/sql/SqlLexer.g4 | 8 +- .../manager/partition/PartitionManager.java | 10 +- .../manager/schema/ClusterSchemaManager.java | 238 ++++++++++++++---- .../persistence/schema/ClusterSchemaInfo.java | 14 ++ .../config/TableConfigTaskVisitor.java | 19 +- .../config/metadata/DatabaseSchemaTask.java | 9 +- .../relational/AbstractDatabaseTask.java | 4 +- .../queryengine/plan/parser/ASTVisitor.java | 12 +- .../metadata/DatabaseSchemaStatement.java | 28 +-- .../reporter/iotdb/IoTDBSessionReporter.java | 4 +- 18 files changed, 474 insertions(+), 111 deletions(-) create mode 100644 integration-test/src/test/java/org/apache/iotdb/relational/it/schema/IoTDBDatabaseMaxRegionGroupNumIT.java create mode 100644 integration-test/src/test/java/org/apache/iotdb/relational/it/schema/IoTDBDatabaseMixedRegionGroupPolicyIT.java diff --git a/integration-test/src/test/java/org/apache/iotdb/confignode/it/database/IoTDBDatabaseRegionControlIT.java b/integration-test/src/test/java/org/apache/iotdb/confignode/it/database/IoTDBDatabaseRegionControlIT.java index b66fadeb35f9a..bcee965cbcda0 100644 --- a/integration-test/src/test/java/org/apache/iotdb/confignode/it/database/IoTDBDatabaseRegionControlIT.java +++ b/integration-test/src/test/java/org/apache/iotdb/confignode/it/database/IoTDBDatabaseRegionControlIT.java @@ -58,6 +58,8 @@ public static void setUp() throws Exception { EnvFactory.getEnv() .getConfig() .getCommonConfig() + .setSchemaRegionGroupExtensionPolicy("CUSTOM") + .setDataRegionGroupExtensionPolicy("CUSTOM") .setDefaultSchemaRegionGroupNumPerDatabase(testDefaultSchemaRegionGroupNumPerDatabase) .setDefaultDataRegionGroupNumPerDatabase(testDefaultDataRegionGroupNumPerDatabase); @@ -132,7 +134,7 @@ public void testRegionGroupNumControlThroughCreation() final int testDataRegionGroupNum = 3; String createDatabaseSQL = String.format( - "CREATE DATABASE %s WITH SCHEMA_REGION_GROUP_NUM=%d, DATA_REGION_GROUP_NUM=%d;", + "CREATE DATABASE %s WITH MAX_SCHEMA_REGION_GROUP_NUM=%d, MAX_DATA_REGION_GROUP_NUM=%d;", database, testSchemaRegionGroupNum, testDataRegionGroupNum); statement.execute(createDatabaseSQL); insertBatchData(statement, database, 0); @@ -204,7 +206,7 @@ public void testRegionGroupNumControlThroughAlter() final int testDataRegionGroupNum = 3; String alterDatabaseSQL = String.format( - "ALTER DATABASE %s WITH SCHEMA_REGION_GROUP_NUM=%d, DATA_REGION_GROUP_NUM=%d;", + "ALTER DATABASE %s WITH MAX_SCHEMA_REGION_GROUP_NUM=%d, MAX_DATA_REGION_GROUP_NUM=%d;", database, testSchemaRegionGroupNum, testDataRegionGroupNum); statement.execute(alterDatabaseSQL); insertBatchData(statement, database, batchSize); @@ -233,4 +235,16 @@ public void testRegionGroupNumControlThroughAlter() Assert.assertEquals(testDataRegionGroupNum, dataRegionGroupNum.get()); } } + + @Test + public void testDeprecatedRegionGroupNumSqlRejected() throws SQLException { + try (final Connection connection = EnvFactory.getEnv().getConnection(); + final Statement statement = connection.createStatement()) { + Assert.assertThrows( + SQLException.class, + () -> + statement.execute( + "CREATE DATABASE root.paradise3 WITH SCHEMA_REGION_GROUP_NUM=3, DATA_REGION_GROUP_NUM=4;")); + } + } } diff --git a/integration-test/src/test/java/org/apache/iotdb/pipe/it/dual/tablemodel/manual/enhanced/IoTDBPipeMetaIT.java b/integration-test/src/test/java/org/apache/iotdb/pipe/it/dual/tablemodel/manual/enhanced/IoTDBPipeMetaIT.java index f26aa171ae11b..0b0a82999c37a 100644 --- a/integration-test/src/test/java/org/apache/iotdb/pipe/it/dual/tablemodel/manual/enhanced/IoTDBPipeMetaIT.java +++ b/integration-test/src/test/java/org/apache/iotdb/pipe/it/dual/tablemodel/manual/enhanced/IoTDBPipeMetaIT.java @@ -230,7 +230,6 @@ public void testNoTree() throws Exception { senderEnv, Arrays.asList( "create database root.test", - "alter database root.test with schema_region_group_num=2, data_region_group_num=3", "create timeSeries root.test.d1.s1 int32", "insert into root.test.d1 (s1) values (1)")); diff --git a/integration-test/src/test/java/org/apache/iotdb/pipe/it/dual/treemodel/auto/enhanced/IoTDBPipeIdempotentIT.java b/integration-test/src/test/java/org/apache/iotdb/pipe/it/dual/treemodel/auto/enhanced/IoTDBPipeIdempotentIT.java index 6596c77913267..469448c5781b8 100644 --- a/integration-test/src/test/java/org/apache/iotdb/pipe/it/dual/treemodel/auto/enhanced/IoTDBPipeIdempotentIT.java +++ b/integration-test/src/test/java/org/apache/iotdb/pipe/it/dual/treemodel/auto/enhanced/IoTDBPipeIdempotentIT.java @@ -289,7 +289,7 @@ public void testCreateDatabaseIdempotent() throws Exception { public void testAlterDatabaseIdempotent() throws Exception { testIdempotent( Collections.singletonList("create database root.sg1"), - "ALTER DATABASE root.sg1 WITH SCHEMA_REGION_GROUP_NUM=2, DATA_REGION_GROUP_NUM=3;", + "ALTER DATABASE root.sg1 WITH TTL=3600000;", "create database root.sg2", "count databases", "count,", diff --git a/integration-test/src/test/java/org/apache/iotdb/relational/it/schema/IoTDBDatabaseIT.java b/integration-test/src/test/java/org/apache/iotdb/relational/it/schema/IoTDBDatabaseIT.java index 58834cb5d799f..6868ef00ba75b 100644 --- a/integration-test/src/test/java/org/apache/iotdb/relational/it/schema/IoTDBDatabaseIT.java +++ b/integration-test/src/test/java/org/apache/iotdb/relational/it/schema/IoTDBDatabaseIT.java @@ -203,8 +203,7 @@ public void testManageDatabase() { statement.execute("drop database IF EXISTS test"); // Test create database with properties - statement.execute( - "create database test_prop with (ttl=300, schema_region_group_num=DEFAULT, time_partition_interval=100000)"); + statement.execute("create database test_prop with (ttl=300, time_partition_interval=100000)"); databaseNames = new String[] {"test_prop"}; TTLs = new String[] {"300"}; timePartitionInterval = new int[] {100000}; @@ -812,7 +811,7 @@ public void testMixedDatabase() throws SQLException { final Statement statement = connection.createStatement()) { statement.execute("create database root.test"); statement.execute( - "alter database root.test WITH SCHEMA_REGION_GROUP_NUM=2, DATA_REGION_GROUP_NUM=3"); + "alter database root.test WITH MAX_SCHEMA_REGION_GROUP_NUM=2, MAX_DATA_REGION_GROUP_NUM=3"); statement.execute("insert into root.test.d1 (s1) values(1)"); statement.execute("drop database root.test"); } @@ -882,6 +881,34 @@ public void testCountDatabases() throws SQLException { } } + @Test + public void testMaxRegionGroupNumRejectedInAutoPolicy() throws SQLException { + try (final Connection connection = + EnvFactory.getEnv().getConnection(BaseEnv.TABLE_SQL_DIALECT); + final Statement statement = connection.createStatement()) { + try { + statement.execute("create database test_max with(max_data_region_group_num=4)"); + fail("max_data_region_group_num should be rejected under AUTO policy"); + } catch (final SQLException e) { + assertTrue( + e.getMessage() + .contains( + "max_data_region_group_num can only be set when data_region_group_extension_policy is CUSTOM")); + } + + statement.execute("create database test_max"); + try { + statement.execute("alter database test_max set properties max_data_region_group_num=4"); + fail("max_data_region_group_num should be rejected under AUTO policy"); + } catch (final SQLException e) { + assertTrue( + e.getMessage() + .contains( + "max_data_region_group_num can only be set when data_region_group_extension_policy is CUSTOM")); + } + } + } + @Test public void testDBAuth() throws SQLException { try (final Connection adminCon = EnvFactory.getEnv().getConnection(BaseEnv.TABLE_SQL_DIALECT); diff --git a/integration-test/src/test/java/org/apache/iotdb/relational/it/schema/IoTDBDatabaseMaxRegionGroupNumIT.java b/integration-test/src/test/java/org/apache/iotdb/relational/it/schema/IoTDBDatabaseMaxRegionGroupNumIT.java new file mode 100644 index 0000000000000..c3ae953ff2aee --- /dev/null +++ b/integration-test/src/test/java/org/apache/iotdb/relational/it/schema/IoTDBDatabaseMaxRegionGroupNumIT.java @@ -0,0 +1,100 @@ +/* + * 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.iotdb.relational.it.schema; + +import org.apache.iotdb.db.it.utils.TestUtils; +import org.apache.iotdb.it.env.EnvFactory; +import org.apache.iotdb.it.framework.IoTDBTestRunner; +import org.apache.iotdb.itbase.category.TableClusterIT; +import org.apache.iotdb.itbase.category.TableLocalStandaloneIT; +import org.apache.iotdb.itbase.env.BaseEnv; + +import org.junit.After; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; +import org.junit.experimental.categories.Category; +import org.junit.runner.RunWith; + +import java.sql.Connection; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.sql.Statement; +import java.util.Collections; + +@RunWith(IoTDBTestRunner.class) +@Category({TableLocalStandaloneIT.class, TableClusterIT.class}) +public class IoTDBDatabaseMaxRegionGroupNumIT { + + @Before + public void setUp() throws Exception { + EnvFactory.getEnv() + .getConfig() + .getCommonConfig() + .setSchemaRegionGroupExtensionPolicy("CUSTOM") + .setDataRegionGroupExtensionPolicy("CUSTOM") + .setDefaultSchemaRegionGroupNumPerDatabase(1) + .setDefaultDataRegionGroupNumPerDatabase(2); + EnvFactory.getEnv().initClusterEnvironment(); + } + + @After + public void tearDown() throws Exception { + EnvFactory.getEnv().cleanClusterEnvironment(); + } + + @Test + public void testCreateAndAlterMaxRegionGroupNum() throws SQLException { + try (final Connection connection = + EnvFactory.getEnv().getConnection(BaseEnv.TABLE_SQL_DIALECT); + final Statement statement = connection.createStatement()) { + statement.execute( + "create database test_create with(max_schema_region_group_num=3, max_data_region_group_num=4)"); + TestUtils.assertResultSetEqual( + statement.executeQuery( + "select database, max_schema_region_group_num, max_data_region_group_num " + + "from information_schema.databases where database = 'test_create'"), + "database,max_schema_region_group_num,max_data_region_group_num,", + Collections.singleton("test_create,3,4,")); + + statement.execute("create database test_alter"); + statement.execute( + "alter database test_alter set properties max_schema_region_group_num=3, max_data_region_group_num=4"); + try (final ResultSet resultSet = statement.executeQuery("show databases details")) { + boolean found = false; + while (resultSet.next()) { + if (!"test_alter".equals(resultSet.getString("Database"))) { + continue; + } + found = true; + org.junit.Assert.assertEquals(3, resultSet.getInt("MaxSchemaRegionGroupNum")); + org.junit.Assert.assertEquals(4, resultSet.getInt("MaxDataRegionGroupNum")); + } + org.junit.Assert.assertTrue(found); + } + + Assert.assertThrows( + SQLException.class, + () -> + statement.execute( + "create database test_deprecated with(schema_region_group_num=4, data_region_group_num=5)")); + } + } +} diff --git a/integration-test/src/test/java/org/apache/iotdb/relational/it/schema/IoTDBDatabaseMixedRegionGroupPolicyIT.java b/integration-test/src/test/java/org/apache/iotdb/relational/it/schema/IoTDBDatabaseMixedRegionGroupPolicyIT.java new file mode 100644 index 0000000000000..e90046c59b301 --- /dev/null +++ b/integration-test/src/test/java/org/apache/iotdb/relational/it/schema/IoTDBDatabaseMixedRegionGroupPolicyIT.java @@ -0,0 +1,77 @@ +/* + * 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.iotdb.relational.it.schema; + +import org.apache.iotdb.db.it.utils.TestUtils; +import org.apache.iotdb.it.env.EnvFactory; +import org.apache.iotdb.it.framework.IoTDBTestRunner; +import org.apache.iotdb.itbase.category.TableClusterIT; +import org.apache.iotdb.itbase.category.TableLocalStandaloneIT; +import org.apache.iotdb.itbase.env.BaseEnv; + +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import org.junit.experimental.categories.Category; +import org.junit.runner.RunWith; + +import java.sql.Connection; +import java.sql.SQLException; +import java.sql.Statement; +import java.util.Collections; + +@RunWith(IoTDBTestRunner.class) +@Category({TableLocalStandaloneIT.class, TableClusterIT.class}) +public class IoTDBDatabaseMixedRegionGroupPolicyIT { + + @Before + public void setUp() throws Exception { + EnvFactory.getEnv() + .getConfig() + .getCommonConfig() + .setSchemaRegionGroupExtensionPolicy("CUSTOM") + .setDataRegionGroupExtensionPolicy("AUTO") + .setDefaultSchemaRegionGroupNumPerDatabase(1) + .setDefaultDataRegionGroupNumPerDatabase(1) + .setDataRegionPerDataNode(4); + EnvFactory.getEnv().initClusterEnvironment(); + } + + @After + public void tearDown() throws Exception { + EnvFactory.getEnv().cleanClusterEnvironment(); + } + + @Test + public void testAutoPolicyStillAdjustsWhenTheOtherPolicyIsCustom() throws SQLException { + try (final Connection connection = + EnvFactory.getEnv().getConnection(BaseEnv.TABLE_SQL_DIALECT); + final Statement statement = connection.createStatement()) { + statement.execute("create database test_mixed with(max_schema_region_group_num=2)"); + + TestUtils.assertResultSetEqual( + statement.executeQuery( + "select database, max_schema_region_group_num, max_data_region_group_num " + + "from information_schema.databases where database = 'test_mixed'"), + "database,max_schema_region_group_num,max_data_region_group_num,", + Collections.singleton("test_mixed,2,4,")); + } + } +} diff --git a/iotdb-core/antlr/src/main/antlr4/org/apache/iotdb/db/qp/sql/IdentifierParser.g4 b/iotdb-core/antlr/src/main/antlr4/org/apache/iotdb/db/qp/sql/IdentifierParser.g4 index 54d53bab67431..e96d84e892c8c 100644 --- a/iotdb-core/antlr/src/main/antlr4/org/apache/iotdb/db/qp/sql/IdentifierParser.g4 +++ b/iotdb-core/antlr/src/main/antlr4/org/apache/iotdb/db/qp/sql/IdentifierParser.g4 @@ -82,7 +82,7 @@ keyWords | CURRENT_USER | DATA | DATA_REPLICATION_FACTOR - | DATA_REGION_GROUP_NUM + | MAX_DATA_REGION_GROUP_NUM | DATABASE | DATABASES | DATANODE @@ -215,7 +215,7 @@ keyWords | RUNNING | SCHEMA | SCHEMA_REPLICATION_FACTOR - | SCHEMA_REGION_GROUP_NUM + | MAX_SCHEMA_REGION_GROUP_NUM | SECURITY | SELECT | SERIESSLOTID diff --git a/iotdb-core/antlr/src/main/antlr4/org/apache/iotdb/db/qp/sql/IoTDBSqlParser.g4 b/iotdb-core/antlr/src/main/antlr4/org/apache/iotdb/db/qp/sql/IoTDBSqlParser.g4 index 3ac375b7f1504..2f91b573aef0e 100644 --- a/iotdb-core/antlr/src/main/antlr4/org/apache/iotdb/db/qp/sql/IoTDBSqlParser.g4 +++ b/iotdb-core/antlr/src/main/antlr4/org/apache/iotdb/db/qp/sql/IoTDBSqlParser.g4 @@ -121,8 +121,8 @@ databaseAttributeClause databaseAttributeKey : TTL | TIME_PARTITION_INTERVAL - | SCHEMA_REGION_GROUP_NUM - | DATA_REGION_GROUP_NUM + | MAX_SCHEMA_REGION_GROUP_NUM + | MAX_DATA_REGION_GROUP_NUM ; // ---- Drop Database diff --git a/iotdb-core/antlr/src/main/antlr4/org/apache/iotdb/db/qp/sql/SqlLexer.g4 b/iotdb-core/antlr/src/main/antlr4/org/apache/iotdb/db/qp/sql/SqlLexer.g4 index 59bac72fc7813..3950de50ea477 100644 --- a/iotdb-core/antlr/src/main/antlr4/org/apache/iotdb/db/qp/sql/SqlLexer.g4 +++ b/iotdb-core/antlr/src/main/antlr4/org/apache/iotdb/db/qp/sql/SqlLexer.g4 @@ -1227,12 +1227,12 @@ TIME_PARTITION_INTERVAL : T I M E '_' P A R T I T I O N '_' I N T E R V A L ; -SCHEMA_REGION_GROUP_NUM - : S C H E M A '_' R E G I O N '_' G R O U P '_' N U M +MAX_SCHEMA_REGION_GROUP_NUM + : M A X '_' S C H E M A '_' R E G I O N '_' G R O U P '_' N U M ; -DATA_REGION_GROUP_NUM - : D A T A '_' R E G I O N '_' G R O U P '_' N U M +MAX_DATA_REGION_GROUP_NUM + : M A X '_' D A T A '_' R E G I O N '_' G R O U P '_' N U M ; CURRENT_TIMESTAMP diff --git a/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/manager/partition/PartitionManager.java b/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/manager/partition/PartitionManager.java index dfa3448bc0f3b..095bbb8626865 100644 --- a/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/manager/partition/PartitionManager.java +++ b/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/manager/partition/PartitionManager.java @@ -625,14 +625,14 @@ private TSStatus customExtendRegionGroupIfNecessary( for (final Map.Entry entry : unassignedPartitionSlotsCountMap.entrySet()) { final String database = entry.getKey(); - final int minRegionGroupNum = - getClusterSchemaManager().getMinRegionGroupNum(database, consensusGroupType); + final int maxRegionGroupNum = + getClusterSchemaManager().getMaxRegionGroupNum(database, consensusGroupType); final int allocatedRegionGroupCount = partitionInfo.getRegionGroupCount(database, consensusGroupType); - // Extend RegionGroups until allocatedRegionGroupCount == minRegionGroupNum - if (allocatedRegionGroupCount < minRegionGroupNum) { - allotmentMap.put(database, minRegionGroupNum - allocatedRegionGroupCount); + // Extend RegionGroups until allocatedRegionGroupCount == maxRegionGroupNum + if (allocatedRegionGroupCount < maxRegionGroupNum) { + allotmentMap.put(database, maxRegionGroupNum - allocatedRegionGroupCount); } } diff --git a/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/manager/schema/ClusterSchemaManager.java b/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/manager/schema/ClusterSchemaManager.java index fbf62d8f1ddc5..ba0295dfc69d5 100644 --- a/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/manager/schema/ClusterSchemaManager.java +++ b/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/manager/schema/ClusterSchemaManager.java @@ -95,6 +95,7 @@ import org.apache.iotdb.confignode.manager.node.NodeManager; import org.apache.iotdb.confignode.manager.partition.PartitionManager; import org.apache.iotdb.confignode.manager.partition.PartitionMetrics; +import org.apache.iotdb.confignode.manager.partition.RegionGroupExtensionPolicy; import org.apache.iotdb.confignode.persistence.schema.ClusterSchemaInfo; import org.apache.iotdb.confignode.rpc.thrift.TDatabaseInfo; import org.apache.iotdb.confignode.rpc.thrift.TDatabaseSchema; @@ -267,6 +268,27 @@ public TSStatus alterDatabase( } } + if (databaseSchema.isSetMaxSchemaRegionGroupNum()) { + result = + validateMaxRegionGroupNumOnAlter( + databaseSchema.getName(), + TConsensusGroupType.SchemaRegion, + databaseSchema.getMaxSchemaRegionGroupNum()); + if (result.getCode() != TSStatusCode.SUCCESS_STATUS.getStatusCode()) { + return result; + } + } + if (databaseSchema.isSetMaxDataRegionGroupNum()) { + result = + validateMaxRegionGroupNumOnAlter( + databaseSchema.getName(), + TConsensusGroupType.DataRegion, + databaseSchema.getMaxDataRegionGroupNum()); + if (result.getCode() != TSStatusCode.SUCCESS_STATUS.getStatusCode()) { + return result; + } + } + // Alter DatabaseSchema try { result = @@ -475,6 +497,14 @@ public TSStatus setTimePartitionInterval( * each Database based on existing cluster resources */ public synchronized void adjustMaxRegionGroupNum() { + final boolean isAdjustSchemaRegionGroupNum = + !CONF.getSchemaRegionGroupExtensionPolicy().equals(RegionGroupExtensionPolicy.CUSTOM); + final boolean isAdjustDataRegionGroupNum = + !CONF.getDataRegionGroupExtensionPolicy().equals(RegionGroupExtensionPolicy.CUSTOM); + if (!isAdjustSchemaRegionGroupNum && !isAdjustDataRegionGroupNum) { + return; + } + // Get all DatabaseSchemas final Map databaseSchemaMap = getMatchedDatabaseSchemasByName(getDatabaseNames(null), null); @@ -507,60 +537,64 @@ public synchronized void adjustMaxRegionGroupNum() { continue; } - // Adjust maxSchemaRegionGroupNum for each Database. - // All Databases share the DataNodes equally. - // The allocated SchemaRegionGroups will not be shrunk. - final int allocatedSchemaRegionGroupCount; - try { - allocatedSchemaRegionGroupCount = - getPartitionManager() - .getRegionGroupCount(databaseSchema.getName(), TConsensusGroupType.SchemaRegion); - } catch (final DatabaseNotExistsException e) { - // ignore the pre deleted database - continue; + int maxSchemaRegionGroupNum = databaseSchema.getMaxSchemaRegionGroupNum(); + if (isAdjustSchemaRegionGroupNum) { + // Adjust maxSchemaRegionGroupNum for each Database. + // All Databases share the DataNodes equally. + // The allocated SchemaRegionGroups will not be shrunk. + final int allocatedSchemaRegionGroupCount; + try { + allocatedSchemaRegionGroupCount = + getPartitionManager() + .getRegionGroupCount(databaseSchema.getName(), TConsensusGroupType.SchemaRegion); + } catch (final DatabaseNotExistsException e) { + // ignore the pre deleted database + continue; + } + maxSchemaRegionGroupNum = + calcMaxRegionGroupNum( + databaseSchema.getMinSchemaRegionGroupNum(), + SCHEMA_REGION_PER_DATA_NODE, + dataNodeNum, + databaseNum, + databaseSchema.getSchemaReplicationFactor(), + allocatedSchemaRegionGroupCount); + LOGGER.info( + ConfigNodeMessages.ADJUSTREGIONGROUPNUM_THE_MAXIMUM_NUMBER_OF_SCHEMAREGIONGROUPS_FOR, + databaseSchema.getName(), + maxSchemaRegionGroupNum); } - final int maxSchemaRegionGroupNum = - calcMaxRegionGroupNum( - databaseSchema.getMinSchemaRegionGroupNum(), - SCHEMA_REGION_PER_DATA_NODE, - dataNodeNum, - databaseNum, - databaseSchema.getSchemaReplicationFactor(), - allocatedSchemaRegionGroupCount); - LOGGER.info( - ConfigNodeMessages.ADJUSTREGIONGROUPNUM_THE_MAXIMUM_NUMBER_OF_SCHEMAREGIONGROUPS_FOR, - databaseSchema.getName(), - maxSchemaRegionGroupNum); - - // Adjust maxDataRegionGroupNum for each Database. - // All Databases share the DataNodes equally. - // The allocated DataRegionGroups will not be shrunk. - final int allocatedDataRegionGroupCount; - try { - allocatedDataRegionGroupCount = - getPartitionManager() - .getRegionGroupCount(databaseSchema.getName(), TConsensusGroupType.DataRegion); - } catch (final DatabaseNotExistsException e) { - // ignore the pre deleted database - continue; + int maxDataRegionGroupNum = databaseSchema.getMaxDataRegionGroupNum(); + if (isAdjustDataRegionGroupNum) { + // Adjust maxDataRegionGroupNum for each Database. + // All Databases share the DataNodes equally. + // The allocated DataRegionGroups will not be shrunk. + final int allocatedDataRegionGroupCount; + try { + allocatedDataRegionGroupCount = + getPartitionManager() + .getRegionGroupCount(databaseSchema.getName(), TConsensusGroupType.DataRegion); + } catch (final DatabaseNotExistsException e) { + // ignore the pre deleted database + continue; + } + maxDataRegionGroupNum = + calcMaxRegionGroupNum( + databaseSchema.getMinDataRegionGroupNum(), + DATA_REGION_PER_DATA_NODE == 0 + ? CONF.getDataRegionPerDataNodeProportion() + : DATA_REGION_PER_DATA_NODE, + DATA_REGION_PER_DATA_NODE == 0 ? totalCpuCoreNum : dataNodeNum, + databaseNum, + databaseSchema.getDataReplicationFactor(), + allocatedDataRegionGroupCount); + LOGGER.info( + ConfigNodeMessages.ADJUSTREGIONGROUPNUM_THE_MAXIMUM_NUMBER_OF_DATAREGIONGROUPS_FOR, + databaseSchema.getName(), + maxDataRegionGroupNum); } - final int maxDataRegionGroupNum = - calcMaxRegionGroupNum( - databaseSchema.getMinDataRegionGroupNum(), - DATA_REGION_PER_DATA_NODE == 0 - ? CONF.getDataRegionPerDataNodeProportion() - : DATA_REGION_PER_DATA_NODE, - DATA_REGION_PER_DATA_NODE == 0 ? totalCpuCoreNum : dataNodeNum, - databaseNum, - databaseSchema.getDataReplicationFactor(), - allocatedDataRegionGroupCount); - LOGGER.info( - ConfigNodeMessages.ADJUSTREGIONGROUPNUM_THE_MAXIMUM_NUMBER_OF_DATAREGIONGROUPS_FOR, - databaseSchema.getName(), - maxDataRegionGroupNum); - adjustMaxRegionGroupNumPlan.putEntry( databaseSchema.getName(), new Pair<>(maxSchemaRegionGroupNum, maxDataRegionGroupNum)); } @@ -908,14 +942,112 @@ public static TSStatus enrichDatabaseSchemaWithDefaultProperties( .FAILED_TO_CREATE_DATABASE_THE_DATAREGIONGROUPNUM_SHOULD_BE_POSITIVE); } + if (databaseSchema.isSetMaxSchemaRegionGroupNum()) { + errorResp = + validateMaxRegionGroupNumOnCreation( + databaseSchema, TConsensusGroupType.SchemaRegion, errorResp); + } + if (databaseSchema.isSetMaxDataRegionGroupNum()) { + errorResp = + validateMaxRegionGroupNumOnCreation( + databaseSchema, TConsensusGroupType.DataRegion, errorResp); + } + if (errorResp != null) { LOGGER.warn(ConfigNodeMessages.EXECUTE_SETDATABASE_WITH_RESULT, databaseSchema, errorResp); return errorResp; } - // The maxRegionGroupNum is equal to the minRegionGroupNum when initialize - databaseSchema.setMaxSchemaRegionGroupNum(databaseSchema.getMinSchemaRegionGroupNum()); - databaseSchema.setMaxDataRegionGroupNum(databaseSchema.getMinDataRegionGroupNum()); + if (!databaseSchema.isSetMaxSchemaRegionGroupNum()) { + databaseSchema.setMaxSchemaRegionGroupNum(databaseSchema.getMinSchemaRegionGroupNum()); + } + if (!databaseSchema.isSetMaxDataRegionGroupNum()) { + databaseSchema.setMaxDataRegionGroupNum(databaseSchema.getMinDataRegionGroupNum()); + } + + return StatusUtils.OK; + } + + private static TSStatus validateMaxRegionGroupNumOnCreation( + final TDatabaseSchema databaseSchema, + final TConsensusGroupType consensusGroupType, + final TSStatus previousError) { + final TSStatus status = + validateMaxRegionGroupNum( + databaseSchema.getName(), + consensusGroupType, + TConsensusGroupType.SchemaRegion.equals(consensusGroupType) + ? databaseSchema.getMaxSchemaRegionGroupNum() + : databaseSchema.getMaxDataRegionGroupNum(), + true); + return status.getCode() == TSStatusCode.SUCCESS_STATUS.getStatusCode() ? previousError : status; + } + + private static TSStatus validateMaxRegionGroupNum( + final String database, + final TConsensusGroupType consensusGroupType, + final int maxRegionGroupNum, + final boolean isCreate) { + final boolean isSchemaRegion = TConsensusGroupType.SchemaRegion.equals(consensusGroupType); + final RegionGroupExtensionPolicy policy = + isSchemaRegion + ? CONF.getSchemaRegionGroupExtensionPolicy() + : CONF.getDataRegionGroupExtensionPolicy(); + final String configKey = + isSchemaRegion ? "max_schema_region_group_num" : "max_data_region_group_num"; + final String fieldName = isSchemaRegion ? "MaxSchemaRegionGroupNum" : "MaxDataRegionGroupNum"; + + if (!policy.equals(RegionGroupExtensionPolicy.CUSTOM)) { + return new TSStatus(TSStatusCode.DATABASE_CONFIG_ERROR.getStatusCode()) + .setMessage( + String.format( + "Failed to %s database. The %s can only be set when %s_region_group_extension_policy is CUSTOM.", + isCreate ? "create" : "alter", configKey, isSchemaRegion ? "schema" : "data")); + } + + final int defaultRegionGroupNum = + isSchemaRegion + ? CONF.getDefaultSchemaRegionGroupNumPerDatabase() + : CONF.getDefaultDataRegionGroupNumPerDatabase(); + if (maxRegionGroupNum < defaultRegionGroupNum) { + return new TSStatus(TSStatusCode.DATABASE_CONFIG_ERROR.getStatusCode()) + .setMessage( + String.format( + "%s should be greater than or equal to default %sRegionGroupNum: %d.", + fieldName, isSchemaRegion ? "Schema" : "Data", defaultRegionGroupNum)); + } + + return StatusUtils.OK; + } + + private TSStatus validateMaxRegionGroupNumOnAlter( + final String database, + final TConsensusGroupType consensusGroupType, + final int maxRegionGroupNum) { + TSStatus status = + validateMaxRegionGroupNum(database, consensusGroupType, maxRegionGroupNum, false); + if (status.getCode() != TSStatusCode.SUCCESS_STATUS.getStatusCode()) { + return status; + } + + final boolean isSchemaRegion = TConsensusGroupType.SchemaRegion.equals(consensusGroupType); + final String fieldName = isSchemaRegion ? "MaxSchemaRegionGroupNum" : "MaxDataRegionGroupNum"; + + final int allocatedRegionGroupCount; + try { + allocatedRegionGroupCount = + getPartitionManager().getRegionGroupCount(database, consensusGroupType); + } catch (final DatabaseNotExistsException e) { + return new TSStatus(TSStatusCode.DATABASE_NOT_EXIST.getStatusCode()) + .setMessage(e.getMessage()); + } + if (maxRegionGroupNum < allocatedRegionGroupCount) { + return new TSStatus(TSStatusCode.DATABASE_CONFIG_ERROR.getStatusCode()) + .setMessage( + String.format( + "%s should be greater than or equal to allocated %sRegionGroupNum: %d.", + fieldName, isSchemaRegion ? "Schema" : "Data", allocatedRegionGroupCount)); + } return StatusUtils.OK; } diff --git a/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/persistence/schema/ClusterSchemaInfo.java b/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/persistence/schema/ClusterSchemaInfo.java index 47f2264505b73..90f21d2e75c2d 100644 --- a/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/persistence/schema/ClusterSchemaInfo.java +++ b/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/persistence/schema/ClusterSchemaInfo.java @@ -267,6 +267,20 @@ public TSStatus alterDatabase(final DatabaseSchemaPlan plan) { currentSchema.getName(), currentSchema.getMaxDataRegionGroupNum()); } + if (alterSchema.isSetMaxSchemaRegionGroupNum()) { + currentSchema.setMaxSchemaRegionGroupNum(alterSchema.getMaxSchemaRegionGroupNum()); + LOGGER.info( + ConfigNodeMessages.ADJUSTREGIONGROUPNUM_THE_MAXIMUM_NUMBER_OF_SCHEMAREGIONGROUPS_FOR, + currentSchema.getName(), + currentSchema.getMaxSchemaRegionGroupNum()); + } + if (alterSchema.isSetMaxDataRegionGroupNum()) { + currentSchema.setMaxDataRegionGroupNum(alterSchema.getMaxDataRegionGroupNum()); + LOGGER.info( + ConfigNodeMessages.ADJUSTREGIONGROUPNUM_THE_MAXIMUM_NUMBER_OF_DATAREGIONGROUPS_FOR, + currentSchema.getName(), + currentSchema.getMaxDataRegionGroupNum()); + } if (alterSchema.isSetTTL()) { currentSchema.setTTL(alterSchema.getTTL()); diff --git a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/execution/config/TableConfigTaskVisitor.java b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/execution/config/TableConfigTaskVisitor.java index 4eff93bfc12d2..20f484e10d7c6 100644 --- a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/execution/config/TableConfigTaskVisitor.java +++ b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/execution/config/TableConfigTaskVisitor.java @@ -285,8 +285,8 @@ import static org.apache.iotdb.commons.schema.table.TsTable.TABLE_ALLOWED_PROPERTIES; import static org.apache.iotdb.commons.schema.table.TsTable.TIME_COLUMN_NAME; import static org.apache.iotdb.commons.schema.table.TsTable.TTL_PROPERTY; -import static org.apache.iotdb.db.queryengine.plan.execution.config.metadata.relational.CreateDBTask.DATA_REGION_GROUP_NUM_KEY; -import static org.apache.iotdb.db.queryengine.plan.execution.config.metadata.relational.CreateDBTask.SCHEMA_REGION_GROUP_NUM_KEY; +import static org.apache.iotdb.db.queryengine.plan.execution.config.metadata.relational.CreateDBTask.MAX_DATA_REGION_GROUP_NUM_KEY; +import static org.apache.iotdb.db.queryengine.plan.execution.config.metadata.relational.CreateDBTask.MAX_SCHEMA_REGION_GROUP_NUM_KEY; import static org.apache.iotdb.db.queryengine.plan.execution.config.metadata.relational.CreateDBTask.TIME_PARTITION_INTERVAL_KEY; import static org.apache.iotdb.db.queryengine.plan.execution.config.metadata.relational.CreateDBTask.TTL_KEY; import static org.apache.tsfile.common.constant.TsFileConstant.PATH_SEPARATOR; @@ -351,8 +351,8 @@ private IConfigTask visitDatabaseStatement( if (property.isSetToDefault()) { switch (key) { case TIME_PARTITION_INTERVAL_KEY: - case SCHEMA_REGION_GROUP_NUM_KEY: - case DATA_REGION_GROUP_NUM_KEY: + case MAX_SCHEMA_REGION_GROUP_NUM_KEY: + case MAX_DATA_REGION_GROUP_NUM_KEY: break; case TTL_KEY: if (node.getType() == DatabaseSchemaStatement.DatabaseSchemaStatementType.ALTER) { @@ -386,12 +386,13 @@ private IConfigTask visitDatabaseStatement( case TIME_PARTITION_INTERVAL_KEY: schema.setTimePartitionInterval(parseLongFromLiteral(value, TIME_PARTITION_INTERVAL_KEY)); break; - case SCHEMA_REGION_GROUP_NUM_KEY: - schema.setMinSchemaRegionGroupNum( - parseIntFromLiteral(value, SCHEMA_REGION_GROUP_NUM_KEY)); + case MAX_SCHEMA_REGION_GROUP_NUM_KEY: + schema.setMaxSchemaRegionGroupNum( + parseIntFromLiteral(value, MAX_SCHEMA_REGION_GROUP_NUM_KEY)); break; - case DATA_REGION_GROUP_NUM_KEY: - schema.setMinDataRegionGroupNum(parseIntFromLiteral(value, DATA_REGION_GROUP_NUM_KEY)); + case MAX_DATA_REGION_GROUP_NUM_KEY: + schema.setMaxDataRegionGroupNum( + parseIntFromLiteral(value, MAX_DATA_REGION_GROUP_NUM_KEY)); break; default: throw new SemanticException( diff --git a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/execution/config/metadata/DatabaseSchemaTask.java b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/execution/config/metadata/DatabaseSchemaTask.java index ab9dee095aaab..31c96887600c5 100644 --- a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/execution/config/metadata/DatabaseSchemaTask.java +++ b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/execution/config/metadata/DatabaseSchemaTask.java @@ -66,11 +66,12 @@ public static TDatabaseSchema constructDatabaseSchema( if (databaseSchemaStatement.getTimePartitionInterval() != null) { databaseSchema.setTimePartitionInterval(databaseSchemaStatement.getTimePartitionInterval()); } - if (databaseSchemaStatement.getSchemaRegionGroupNum() != null) { - databaseSchema.setMinSchemaRegionGroupNum(databaseSchemaStatement.getSchemaRegionGroupNum()); + if (databaseSchemaStatement.getMaxSchemaRegionGroupNum() != null) { + databaseSchema.setMaxSchemaRegionGroupNum( + databaseSchemaStatement.getMaxSchemaRegionGroupNum()); } - if (databaseSchemaStatement.getDataRegionGroupNum() != null) { - databaseSchema.setMinDataRegionGroupNum(databaseSchemaStatement.getDataRegionGroupNum()); + if (databaseSchemaStatement.getMaxDataRegionGroupNum() != null) { + databaseSchema.setMaxDataRegionGroupNum(databaseSchemaStatement.getMaxDataRegionGroupNum()); } databaseSchema.setIsTableModel(false); return databaseSchema; diff --git a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/execution/config/metadata/relational/AbstractDatabaseTask.java b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/execution/config/metadata/relational/AbstractDatabaseTask.java index df280c8759de2..59b50536c15ba 100644 --- a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/execution/config/metadata/relational/AbstractDatabaseTask.java +++ b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/execution/config/metadata/relational/AbstractDatabaseTask.java @@ -27,8 +27,8 @@ public abstract class AbstractDatabaseTask implements IConfigTask { /////////////////////////////// Allowed properties /////////////////////////////// public static final String TTL_KEY = "ttl"; public static final String TIME_PARTITION_INTERVAL_KEY = "time_partition_interval"; - public static final String SCHEMA_REGION_GROUP_NUM_KEY = "schema_region_group_num"; - public static final String DATA_REGION_GROUP_NUM_KEY = "data_region_group_num"; + public static final String MAX_SCHEMA_REGION_GROUP_NUM_KEY = "max_schema_region_group_num"; + public static final String MAX_DATA_REGION_GROUP_NUM_KEY = "max_data_region_group_num"; // Deprecated public static final String SCHEMA_REPLICATION_FACTOR_KEY = "schema_replication_factor"; diff --git a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/parser/ASTVisitor.java b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/parser/ASTVisitor.java index 6ecf65c86bb3c..b9e2fe21c7a54 100644 --- a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/parser/ASTVisitor.java +++ b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/parser/ASTVisitor.java @@ -2998,12 +2998,12 @@ private void parseDatabaseAttributesClause( } else if (attributeKey.TIME_PARTITION_INTERVAL() != null) { final long timePartitionInterval = Long.parseLong(attribute.INTEGER_LITERAL().getText()); databaseSchemaStatement.setTimePartitionInterval(timePartitionInterval); - } else if (attributeKey.SCHEMA_REGION_GROUP_NUM() != null) { - final int schemaRegionGroupNum = Integer.parseInt(attribute.INTEGER_LITERAL().getText()); - databaseSchemaStatement.setSchemaRegionGroupNum(schemaRegionGroupNum); - } else if (attributeKey.DATA_REGION_GROUP_NUM() != null) { - final int dataRegionGroupNum = Integer.parseInt(attribute.INTEGER_LITERAL().getText()); - databaseSchemaStatement.setDataRegionGroupNum(dataRegionGroupNum); + } else if (attributeKey.MAX_SCHEMA_REGION_GROUP_NUM() != null) { + final int maxSchemaRegionGroupNum = Integer.parseInt(attribute.INTEGER_LITERAL().getText()); + databaseSchemaStatement.setMaxSchemaRegionGroupNum(maxSchemaRegionGroupNum); + } else if (attributeKey.MAX_DATA_REGION_GROUP_NUM() != null) { + final int maxDataRegionGroupNum = Integer.parseInt(attribute.INTEGER_LITERAL().getText()); + databaseSchemaStatement.setMaxDataRegionGroupNum(maxDataRegionGroupNum); } } } diff --git a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/statement/metadata/DatabaseSchemaStatement.java b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/statement/metadata/DatabaseSchemaStatement.java index 9fc9f2704f019..b31520fdc7605 100644 --- a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/statement/metadata/DatabaseSchemaStatement.java +++ b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/statement/metadata/DatabaseSchemaStatement.java @@ -36,8 +36,8 @@ public class DatabaseSchemaStatement extends Statement implements IConfigStateme private PartialPath databasePath; private Long ttl = null; private Long timePartitionInterval = null; - private Integer schemaRegionGroupNum = null; - private Integer dataRegionGroupNum = null; + private Integer maxSchemaRegionGroupNum = null; + private Integer maxDataRegionGroupNum = null; private boolean enablePrintExceptionLog = true; // Deprecated @@ -94,20 +94,20 @@ public void setTimePartitionInterval(final Long timePartitionInterval) { this.timePartitionInterval = timePartitionInterval; } - public Integer getSchemaRegionGroupNum() { - return schemaRegionGroupNum; + public Integer getMaxSchemaRegionGroupNum() { + return maxSchemaRegionGroupNum; } - public void setSchemaRegionGroupNum(final Integer schemaRegionGroupNum) { - this.schemaRegionGroupNum = schemaRegionGroupNum; + public void setMaxSchemaRegionGroupNum(final Integer maxSchemaRegionGroupNum) { + this.maxSchemaRegionGroupNum = maxSchemaRegionGroupNum; } - public Integer getDataRegionGroupNum() { - return dataRegionGroupNum; + public Integer getMaxDataRegionGroupNum() { + return maxDataRegionGroupNum; } - public void setDataRegionGroupNum(final Integer dataRegionGroupNum) { - this.dataRegionGroupNum = dataRegionGroupNum; + public void setMaxDataRegionGroupNum(final Integer maxDataRegionGroupNum) { + this.maxDataRegionGroupNum = maxDataRegionGroupNum; } public boolean getEnablePrintExceptionLog() { @@ -152,10 +152,10 @@ public String toString() { + dataReplicationFactor + ", timePartitionInterval=" + timePartitionInterval - + ", schemaRegionGroupNum=" - + schemaRegionGroupNum - + ", dataRegionGroupNum=" - + dataRegionGroupNum + + ", maxSchemaRegionGroupNum=" + + maxSchemaRegionGroupNum + + ", maxDataRegionGroupNum=" + + maxDataRegionGroupNum + '}'; } diff --git a/iotdb-core/metrics/interface/src/main/java/org/apache/iotdb/metrics/reporter/iotdb/IoTDBSessionReporter.java b/iotdb-core/metrics/interface/src/main/java/org/apache/iotdb/metrics/reporter/iotdb/IoTDBSessionReporter.java index 8e73776e53796..4561fac09a9fe 100644 --- a/iotdb-core/metrics/interface/src/main/java/org/apache/iotdb/metrics/reporter/iotdb/IoTDBSessionReporter.java +++ b/iotdb-core/metrics/interface/src/main/java/org/apache/iotdb/metrics/reporter/iotdb/IoTDBSessionReporter.java @@ -84,9 +84,7 @@ public IoTDBSessionReporter(AbstractMetricManager metricManager) { if (!result.hasNext()) { try (SessionDataSetWrapper result2 = this.sessionPool.executeQueryStatement( - "CREATE DATABASE " - + metricConfig.getInternalDatabase() - + " WITH SCHEMA_REGION_GROUP_NUM=1, DATA_REGION_GROUP_NUM=1")) { + "CREATE DATABASE " + metricConfig.getInternalDatabase())) { if (!result2.hasNext()) { LOGGER.error(MetricsMessages.IOTDB_SESSION_REPORTER_DB_FAILED); } From e3cd74af709c226b7a47a204b7ab1eb60af7bd6a Mon Sep 17 00:00:00 2001 From: libo Date: Thu, 18 Jun 2026 17:28:35 +0800 Subject: [PATCH 2/8] Fix unexpected SQL execution on the IT --- .../treemodel/auto/enhanced/IoTDBPipeIdempotentIT.java | 6 +++++- .../iotdb/relational/it/schema/IoTDBDatabaseIT.java | 8 ++++++-- 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/integration-test/src/test/java/org/apache/iotdb/pipe/it/dual/treemodel/auto/enhanced/IoTDBPipeIdempotentIT.java b/integration-test/src/test/java/org/apache/iotdb/pipe/it/dual/treemodel/auto/enhanced/IoTDBPipeIdempotentIT.java index 469448c5781b8..33a68d43ff207 100644 --- a/integration-test/src/test/java/org/apache/iotdb/pipe/it/dual/treemodel/auto/enhanced/IoTDBPipeIdempotentIT.java +++ b/integration-test/src/test/java/org/apache/iotdb/pipe/it/dual/treemodel/auto/enhanced/IoTDBPipeIdempotentIT.java @@ -65,6 +65,8 @@ public void setUp() { // Limit the schemaRegion number to 1 to guarantee the after sql executed on the same region // of the tested idempotent sql. .setDefaultSchemaRegionGroupNumPerDatabase(1) + .setSchemaRegionGroupExtensionPolicy("CUSTOM") + .setDataRegionGroupExtensionPolicy("CUSTOM") .setConfigNodeConsensusProtocolClass(ConsensusFactory.RATIS_CONSENSUS) .setSchemaRegionConsensusProtocolClass(ConsensusFactory.RATIS_CONSENSUS) .setEnforceStrongPassword(false) @@ -75,6 +77,8 @@ public void setUp() { .getConfig() .getCommonConfig() .setAutoCreateSchemaEnabled(true) + .setSchemaRegionGroupExtensionPolicy("CUSTOM") + .setDataRegionGroupExtensionPolicy("CUSTOM") .setConfigNodeConsensusProtocolClass(ConsensusFactory.RATIS_CONSENSUS) .setSchemaRegionConsensusProtocolClass(ConsensusFactory.RATIS_CONSENSUS) .setEnforceStrongPassword(false) @@ -289,7 +293,7 @@ public void testCreateDatabaseIdempotent() throws Exception { public void testAlterDatabaseIdempotent() throws Exception { testIdempotent( Collections.singletonList("create database root.sg1"), - "ALTER DATABASE root.sg1 WITH TTL=3600000;", + "ALTER DATABASE root.sg1 WITH MAX_SCHEMA_REGION_GROUP_NUM=2, MAX_DATA_REGION_GROUP_NUM=3;", "create database root.sg2", "count databases", "count,", diff --git a/integration-test/src/test/java/org/apache/iotdb/relational/it/schema/IoTDBDatabaseIT.java b/integration-test/src/test/java/org/apache/iotdb/relational/it/schema/IoTDBDatabaseIT.java index 6868ef00ba75b..dac15d8b66bf4 100644 --- a/integration-test/src/test/java/org/apache/iotdb/relational/it/schema/IoTDBDatabaseIT.java +++ b/integration-test/src/test/java/org/apache/iotdb/relational/it/schema/IoTDBDatabaseIT.java @@ -27,6 +27,7 @@ import org.apache.iotdb.itbase.category.TableClusterIT; import org.apache.iotdb.itbase.category.TableLocalStandaloneIT; import org.apache.iotdb.itbase.env.BaseEnv; +import org.apache.iotdb.jdbc.IoTDBSQLException; import org.junit.After; import org.junit.Assert; @@ -810,8 +811,11 @@ public void testMixedDatabase() throws SQLException { try (final Connection connection = EnvFactory.getEnv().getConnection(); final Statement statement = connection.createStatement()) { statement.execute("create database root.test"); - statement.execute( - "alter database root.test WITH MAX_SCHEMA_REGION_GROUP_NUM=2, MAX_DATA_REGION_GROUP_NUM=3"); + Assert.assertThrows( + IoTDBSQLException.class, + () -> + statement.execute( + "alter database root.test WITH MAX_SCHEMA_REGION_GROUP_NUM=2, MAX_DATA_REGION_GROUP_NUM=3")); statement.execute("insert into root.test.d1 (s1) values(1)"); statement.execute("drop database root.test"); } From 515c13747d5a19042f383aa5f32d7f1e34cf0c8a Mon Sep 17 00:00:00 2001 From: libo Date: Thu, 18 Jun 2026 18:40:37 +0800 Subject: [PATCH 3/8] The old statement shall be reclaimed in the same manner as the original connection when the connection is closed --- .../src/test/java/org/apache/iotdb/db/it/utils/TestUtils.java | 1 + 1 file changed, 1 insertion(+) diff --git a/integration-test/src/test/java/org/apache/iotdb/db/it/utils/TestUtils.java b/integration-test/src/test/java/org/apache/iotdb/db/it/utils/TestUtils.java index 93f14dc572b55..1fc35a35b31e4 100644 --- a/integration-test/src/test/java/org/apache/iotdb/db/it/utils/TestUtils.java +++ b/integration-test/src/test/java/org/apache/iotdb/db/it/utils/TestUtils.java @@ -1216,6 +1216,7 @@ public static boolean tryExecuteNonQueriesWithRetry( } } connectionToUse = null; + statement = null; if (retryCountLeft > 0) { try { From 23d514ce99e99ee28d99da0a7e5c19d751af67e8 Mon Sep 17 00:00:00 2001 From: libo Date: Mon, 22 Jun 2026 12:31:09 +0800 Subject: [PATCH 4/8] Fix problems based on review suggestion --- .../apache/iotdb/db/it/utils/TestUtils.java | 1 - .../IoTDBDatabaseMaxRegionGroupNumIT.java | 96 ++++++++++- .../manager/schema/ClusterSchemaManager.java | 163 ++++++++---------- .../persistence/schema/ClusterSchemaInfo.java | 30 ---- 4 files changed, 170 insertions(+), 120 deletions(-) diff --git a/integration-test/src/test/java/org/apache/iotdb/db/it/utils/TestUtils.java b/integration-test/src/test/java/org/apache/iotdb/db/it/utils/TestUtils.java index 1fc35a35b31e4..93f14dc572b55 100644 --- a/integration-test/src/test/java/org/apache/iotdb/db/it/utils/TestUtils.java +++ b/integration-test/src/test/java/org/apache/iotdb/db/it/utils/TestUtils.java @@ -1216,7 +1216,6 @@ public static boolean tryExecuteNonQueriesWithRetry( } } connectionToUse = null; - statement = null; if (retryCountLeft > 0) { try { diff --git a/integration-test/src/test/java/org/apache/iotdb/relational/it/schema/IoTDBDatabaseMaxRegionGroupNumIT.java b/integration-test/src/test/java/org/apache/iotdb/relational/it/schema/IoTDBDatabaseMaxRegionGroupNumIT.java index c3ae953ff2aee..e80aca504c312 100644 --- a/integration-test/src/test/java/org/apache/iotdb/relational/it/schema/IoTDBDatabaseMaxRegionGroupNumIT.java +++ b/integration-test/src/test/java/org/apache/iotdb/relational/it/schema/IoTDBDatabaseMaxRegionGroupNumIT.java @@ -19,6 +19,7 @@ package org.apache.iotdb.relational.it.schema; +import org.apache.iotdb.commons.partition.executor.hash.BKDRHashExecutor; import org.apache.iotdb.db.it.utils.TestUtils; import org.apache.iotdb.it.env.EnvFactory; import org.apache.iotdb.it.framework.IoTDBTestRunner; @@ -26,6 +27,7 @@ import org.apache.iotdb.itbase.category.TableLocalStandaloneIT; import org.apache.iotdb.itbase.env.BaseEnv; +import org.apache.tsfile.file.metadata.IDeviceID; import org.junit.After; import org.junit.Assert; import org.junit.Before; @@ -38,11 +40,17 @@ import java.sql.SQLException; import java.sql.Statement; import java.util.Collections; +import java.util.HashSet; +import java.util.Set; @RunWith(IoTDBTestRunner.class) @Category({TableLocalStandaloneIT.class, TableClusterIT.class}) public class IoTDBDatabaseMaxRegionGroupNumIT { + private static final int SERIES_SLOT_NUM = 8; + private static final String TABLE_NAME = "table1"; + private static final BKDRHashExecutor PARTITION_EXECUTOR = new BKDRHashExecutor(SERIES_SLOT_NUM); + @Before public void setUp() throws Exception { EnvFactory.getEnv() @@ -51,7 +59,10 @@ public void setUp() throws Exception { .setSchemaRegionGroupExtensionPolicy("CUSTOM") .setDataRegionGroupExtensionPolicy("CUSTOM") .setDefaultSchemaRegionGroupNumPerDatabase(1) - .setDefaultDataRegionGroupNumPerDatabase(2); + .setDefaultDataRegionGroupNumPerDatabase(2) + .setSeriesSlotNum(SERIES_SLOT_NUM) + .setSeriesPartitionExecutorClass(BKDRHashExecutor.class.getName()) + .setTimePartitionInterval(10); EnvFactory.getEnv().initClusterEnvironment(); } @@ -97,4 +108,87 @@ public void testCreateAndAlterMaxRegionGroupNum() throws SQLException { "create database test_deprecated with(schema_region_group_num=4, data_region_group_num=5)")); } } + + @Test + public void testCreatePartitionAfterAlterMaxRegionGroupNum() throws SQLException { + try (final Connection connection = + EnvFactory.getEnv().getConnection(BaseEnv.TABLE_SQL_DIALECT); + final Statement statement = connection.createStatement()) { + statement.execute("create database test_partition"); + statement.execute("use test_partition"); + statement.execute("create table " + TABLE_NAME + "(device string tag, s1 int32 field)"); + + final Set usedSeriesSlots = new HashSet<>(); + final String firstDevice = getDeviceInNewSeriesSlot(usedSeriesSlots); + final String secondDevice = getDeviceInNewSeriesSlot(usedSeriesSlots); + + insertData(statement, firstDevice, 0, 0); + assertRegionGroupNum(statement, "test_partition", 1, 2); + + statement.execute( + "alter database test_partition set properties max_schema_region_group_num=3"); + insertData(statement, secondDevice, 0, 1); + assertRegionGroupNum(statement, "test_partition", 3, 2); + + statement.execute("alter database test_partition set properties max_data_region_group_num=4"); + insertData(statement, secondDevice, 20, 2); + assertRegionGroupNum(statement, "test_partition", 3, 4); + + TestUtils.assertResultSetEqual( + statement.executeQuery("select count(*) from " + TABLE_NAME), + "_col0,", + Collections.singleton("3,")); + } + } + + private static void insertData( + final Statement statement, final String device, final int time, final int value) + throws SQLException { + statement.execute( + "insert into " + + TABLE_NAME + + "(time, device, s1) values(" + + time + + ", '" + + device + + "', " + + value + + ")"); + } + + private static String getDeviceInNewSeriesSlot(final Set usedSeriesSlots) { + for (int i = 0; i < 1_000; i++) { + final String device = "d" + i; + if (usedSeriesSlots.add(getSeriesSlot(device))) { + return device; + } + } + throw new AssertionError("Failed to find a device in a new series partition slot"); + } + + private static int getSeriesSlot(final String device) { + return PARTITION_EXECUTOR + .getSeriesPartitionSlot( + IDeviceID.Factory.DEFAULT_FACTORY.create(new String[] {TABLE_NAME, device})) + .getSlotId(); + } + + private static void assertRegionGroupNum( + final Statement statement, + final String database, + final int schemaRegionGroupNum, + final int dataRegionGroupNum) + throws SQLException { + try (final ResultSet resultSet = + statement.executeQuery( + "select schema_region_group_num, data_region_group_num " + + "from information_schema.databases where database = '" + + database + + "'")) { + Assert.assertTrue(resultSet.next()); + Assert.assertEquals(schemaRegionGroupNum, resultSet.getInt("schema_region_group_num")); + Assert.assertEquals(dataRegionGroupNum, resultSet.getInt("data_region_group_num")); + Assert.assertFalse(resultSet.next()); + } + } } diff --git a/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/manager/schema/ClusterSchemaManager.java b/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/manager/schema/ClusterSchemaManager.java index ba0295dfc69d5..0de3c2c058455 100644 --- a/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/manager/schema/ClusterSchemaManager.java +++ b/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/manager/schema/ClusterSchemaManager.java @@ -239,35 +239,6 @@ public TSStatus alterDatabase( return result; } - if (databaseSchema.isSetMinSchemaRegionGroupNum()) { - // Validate alter SchemaRegionGroupNum - final int minSchemaRegionGroupNum = - getMinRegionGroupNum(databaseSchema.getName(), TConsensusGroupType.SchemaRegion); - if (databaseSchema.getMinSchemaRegionGroupNum() <= minSchemaRegionGroupNum) { - result = new TSStatus(TSStatusCode.DATABASE_CONFIG_ERROR.getStatusCode()); - result.setMessage( - String.format( - "Failed to alter database. The SchemaRegionGroupNum could only be increased. " - + "Current SchemaRegionGroupNum: %d, Alter SchemaRegionGroupNum: %d", - minSchemaRegionGroupNum, databaseSchema.getMinSchemaRegionGroupNum())); - return result; - } - } - if (databaseSchema.isSetMinDataRegionGroupNum()) { - // Validate alter DataRegionGroupNum - final int minDataRegionGroupNum = - getMinRegionGroupNum(databaseSchema.getName(), TConsensusGroupType.DataRegion); - if (databaseSchema.getMinDataRegionGroupNum() <= minDataRegionGroupNum) { - result = new TSStatus(TSStatusCode.DATABASE_CONFIG_ERROR.getStatusCode()); - result.setMessage( - String.format( - "Failed to alter database. The DataRegionGroupNum could only be increased. " - + "Current DataRegionGroupNum: %d, Alter DataRegionGroupNum: %d", - minDataRegionGroupNum, databaseSchema.getMinDataRegionGroupNum())); - return result; - } - } - if (databaseSchema.isSetMaxSchemaRegionGroupNum()) { result = validateMaxRegionGroupNumOnAlter( @@ -539,60 +510,34 @@ public synchronized void adjustMaxRegionGroupNum() { int maxSchemaRegionGroupNum = databaseSchema.getMaxSchemaRegionGroupNum(); if (isAdjustSchemaRegionGroupNum) { - // Adjust maxSchemaRegionGroupNum for each Database. - // All Databases share the DataNodes equally. - // The allocated SchemaRegionGroups will not be shrunk. - final int allocatedSchemaRegionGroupCount; try { - allocatedSchemaRegionGroupCount = - getPartitionManager() - .getRegionGroupCount(databaseSchema.getName(), TConsensusGroupType.SchemaRegion); + maxSchemaRegionGroupNum = + adjustRegionGroupNum( + TConsensusGroupType.SchemaRegion, + databaseSchema, + dataNodeNum, + databaseNum, + totalCpuCoreNum); } catch (final DatabaseNotExistsException e) { // ignore the pre deleted database continue; } - maxSchemaRegionGroupNum = - calcMaxRegionGroupNum( - databaseSchema.getMinSchemaRegionGroupNum(), - SCHEMA_REGION_PER_DATA_NODE, - dataNodeNum, - databaseNum, - databaseSchema.getSchemaReplicationFactor(), - allocatedSchemaRegionGroupCount); - LOGGER.info( - ConfigNodeMessages.ADJUSTREGIONGROUPNUM_THE_MAXIMUM_NUMBER_OF_SCHEMAREGIONGROUPS_FOR, - databaseSchema.getName(), - maxSchemaRegionGroupNum); } int maxDataRegionGroupNum = databaseSchema.getMaxDataRegionGroupNum(); if (isAdjustDataRegionGroupNum) { - // Adjust maxDataRegionGroupNum for each Database. - // All Databases share the DataNodes equally. - // The allocated DataRegionGroups will not be shrunk. - final int allocatedDataRegionGroupCount; try { - allocatedDataRegionGroupCount = - getPartitionManager() - .getRegionGroupCount(databaseSchema.getName(), TConsensusGroupType.DataRegion); + maxDataRegionGroupNum = + adjustRegionGroupNum( + TConsensusGroupType.DataRegion, + databaseSchema, + dataNodeNum, + databaseNum, + totalCpuCoreNum); } catch (final DatabaseNotExistsException e) { // ignore the pre deleted database continue; } - maxDataRegionGroupNum = - calcMaxRegionGroupNum( - databaseSchema.getMinDataRegionGroupNum(), - DATA_REGION_PER_DATA_NODE == 0 - ? CONF.getDataRegionPerDataNodeProportion() - : DATA_REGION_PER_DATA_NODE, - DATA_REGION_PER_DATA_NODE == 0 ? totalCpuCoreNum : dataNodeNum, - databaseNum, - databaseSchema.getDataReplicationFactor(), - allocatedDataRegionGroupCount); - LOGGER.info( - ConfigNodeMessages.ADJUSTREGIONGROUPNUM_THE_MAXIMUM_NUMBER_OF_DATAREGIONGROUPS_FOR, - databaseSchema.getName(), - maxDataRegionGroupNum); } adjustMaxRegionGroupNumPlan.putEntry( @@ -627,6 +572,48 @@ public static int calcMaxRegionGroupNum( allocatedRegionGroupCount)); } + /** + * Adjust the max quota of schema or data region group. The specific implementations are as + * follows: 1.Adjust maxSchemaGroupNum or maxDataRegionGroupNum for each Database. 2.All Databases + * share the DataNodes equally. 3.The allocated SchemaGroups or DataRegionGroups will not be + * shrunk. + */ + public int adjustRegionGroupNum( + TConsensusGroupType consensusGroupType, + TDatabaseSchema databaseSchema, + int dataNodeNum, + int databaseNum, + int totalCpuCoreNum) + throws DatabaseNotExistsException { + final int allocatedRegionGroupCount = + getPartitionManager().getRegionGroupCount(databaseSchema.getName(), consensusGroupType); + + int maxRegionGroupNum = + calcMaxRegionGroupNum( + (consensusGroupType == TConsensusGroupType.SchemaRegion) + ? databaseSchema.getMinSchemaRegionGroupNum() + : databaseSchema.getMinDataRegionGroupNum(), + (consensusGroupType == TConsensusGroupType.SchemaRegion) + ? SCHEMA_REGION_PER_DATA_NODE + : (DATA_REGION_PER_DATA_NODE == 0 + ? CONF.getDataRegionPerDataNodeProportion() + : DATA_REGION_PER_DATA_NODE), + (consensusGroupType == TConsensusGroupType.SchemaRegion) + ? dataNodeNum + : (DATA_REGION_PER_DATA_NODE == 0 ? totalCpuCoreNum : dataNodeNum), + databaseNum, + databaseSchema.getSchemaReplicationFactor(), + allocatedRegionGroupCount); + LOGGER.info( + (consensusGroupType == TConsensusGroupType.SchemaRegion) + ? ConfigNodeMessages.ADJUSTREGIONGROUPNUM_THE_MAXIMUM_NUMBER_OF_SCHEMAREGIONGROUPS_FOR + : ConfigNodeMessages.ADJUSTREGIONGROUPNUM_THE_MAXIMUM_NUMBER_OF_DATAREGIONGROUPS_FOR, + databaseSchema.getName(), + maxRegionGroupNum); + + return maxRegionGroupNum; + } + // ====================================================== // Leader scheduling interfaces // ====================================================== @@ -944,13 +931,11 @@ public static TSStatus enrichDatabaseSchemaWithDefaultProperties( if (databaseSchema.isSetMaxSchemaRegionGroupNum()) { errorResp = - validateMaxRegionGroupNumOnCreation( - databaseSchema, TConsensusGroupType.SchemaRegion, errorResp); + validateMaxRegionGroupNumOnCreation(databaseSchema, TConsensusGroupType.SchemaRegion); } if (databaseSchema.isSetMaxDataRegionGroupNum()) { errorResp = - validateMaxRegionGroupNumOnCreation( - databaseSchema, TConsensusGroupType.DataRegion, errorResp); + validateMaxRegionGroupNumOnCreation(databaseSchema, TConsensusGroupType.DataRegion); } if (errorResp != null) { @@ -969,22 +954,16 @@ public static TSStatus enrichDatabaseSchemaWithDefaultProperties( } private static TSStatus validateMaxRegionGroupNumOnCreation( - final TDatabaseSchema databaseSchema, - final TConsensusGroupType consensusGroupType, - final TSStatus previousError) { - final TSStatus status = - validateMaxRegionGroupNum( - databaseSchema.getName(), - consensusGroupType, - TConsensusGroupType.SchemaRegion.equals(consensusGroupType) - ? databaseSchema.getMaxSchemaRegionGroupNum() - : databaseSchema.getMaxDataRegionGroupNum(), - true); - return status.getCode() == TSStatusCode.SUCCESS_STATUS.getStatusCode() ? previousError : status; + final TDatabaseSchema databaseSchema, final TConsensusGroupType consensusGroupType) { + return validateMaxRegionGroupNum( + consensusGroupType, + TConsensusGroupType.SchemaRegion.equals(consensusGroupType) + ? databaseSchema.getMaxSchemaRegionGroupNum() + : databaseSchema.getMaxDataRegionGroupNum(), + true); } private static TSStatus validateMaxRegionGroupNum( - final String database, final TConsensusGroupType consensusGroupType, final int maxRegionGroupNum, final boolean isCreate) { @@ -1024,8 +1003,7 @@ private TSStatus validateMaxRegionGroupNumOnAlter( final String database, final TConsensusGroupType consensusGroupType, final int maxRegionGroupNum) { - TSStatus status = - validateMaxRegionGroupNum(database, consensusGroupType, maxRegionGroupNum, false); + TSStatus status = validateMaxRegionGroupNum(consensusGroupType, maxRegionGroupNum, false); if (status.getCode() != TSStatusCode.SUCCESS_STATUS.getStatusCode()) { return status; } @@ -1033,6 +1011,15 @@ private TSStatus validateMaxRegionGroupNumOnAlter( final boolean isSchemaRegion = TConsensusGroupType.SchemaRegion.equals(consensusGroupType); final String fieldName = isSchemaRegion ? "MaxSchemaRegionGroupNum" : "MaxDataRegionGroupNum"; + final int minRegionGroupNum = getMinRegionGroupNum(database, consensusGroupType); + if (maxRegionGroupNum < minRegionGroupNum) { + return new TSStatus(TSStatusCode.DATABASE_CONFIG_ERROR.getStatusCode()) + .setMessage( + String.format( + "%s should be greater than or equal to current min %sRegionGroupNum: %d.", + fieldName, isSchemaRegion ? "Schema" : "Data", minRegionGroupNum)); + } + final int allocatedRegionGroupCount; try { allocatedRegionGroupCount = diff --git a/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/persistence/schema/ClusterSchemaInfo.java b/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/persistence/schema/ClusterSchemaInfo.java index 90f21d2e75c2d..b4e2f349f015a 100644 --- a/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/persistence/schema/ClusterSchemaInfo.java +++ b/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/persistence/schema/ClusterSchemaInfo.java @@ -237,36 +237,6 @@ public TSStatus alterDatabase(final DatabaseSchemaPlan plan) { mTree.getDatabaseNodeByDatabasePath(partialPathName).getAsMNode().getDatabaseSchema(); // TODO: Support alter other fields - if (alterSchema.isSetMinSchemaRegionGroupNum()) { - currentSchema.setMinSchemaRegionGroupNum(alterSchema.getMinSchemaRegionGroupNum()); - currentSchema.setMaxSchemaRegionGroupNum( - Math.max( - currentSchema.getMinSchemaRegionGroupNum(), - currentSchema.getMaxSchemaRegionGroupNum())); - LOGGER.info( - ConfigNodeMessages.ADJUSTREGIONGROUPNUM_THE_MINIMUM_NUMBER_OF_SCHEMAREGIONGROUPS_FOR, - currentSchema.getName(), - currentSchema.getMinSchemaRegionGroupNum()); - LOGGER.info( - ConfigNodeMessages.ADJUSTREGIONGROUPNUM_THE_MAXIMUM_NUMBER_OF_SCHEMAREGIONGROUPS_FOR, - currentSchema.getName(), - currentSchema.getMaxSchemaRegionGroupNum()); - } - if (alterSchema.isSetMinDataRegionGroupNum()) { - currentSchema.setMinDataRegionGroupNum(alterSchema.getMinDataRegionGroupNum()); - currentSchema.setMaxDataRegionGroupNum( - Math.max( - currentSchema.getMinDataRegionGroupNum(), - currentSchema.getMaxDataRegionGroupNum())); - LOGGER.info( - ConfigNodeMessages.ADJUSTREGIONGROUPNUM_THE_MINIMUM_NUMBER_OF_DATAREGIONGROUPS_FOR, - currentSchema.getName(), - currentSchema.getMinDataRegionGroupNum()); - LOGGER.info( - ConfigNodeMessages.ADJUSTREGIONGROUPNUM_THE_MAXIMUM_NUMBER_OF_DATAREGIONGROUPS_FOR, - currentSchema.getName(), - currentSchema.getMaxDataRegionGroupNum()); - } if (alterSchema.isSetMaxSchemaRegionGroupNum()) { currentSchema.setMaxSchemaRegionGroupNum(alterSchema.getMaxSchemaRegionGroupNum()); LOGGER.info( From 8a2fd6189cbf6d6712f7e55ed00e99d6c98c6b76 Mon Sep 17 00:00:00 2001 From: libo Date: Mon, 22 Jun 2026 14:59:15 +0800 Subject: [PATCH 5/8] Fix conflict --- .../manager/schema/ClusterSchemaManager.java | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/manager/schema/ClusterSchemaManager.java b/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/manager/schema/ClusterSchemaManager.java index 0de3c2c058455..6b0c82ff1f056 100644 --- a/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/manager/schema/ClusterSchemaManager.java +++ b/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/manager/schema/ClusterSchemaManager.java @@ -142,8 +142,6 @@ public class ClusterSchemaManager { private static final Logger LOGGER = LoggerFactory.getLogger(ClusterSchemaManager.class); private static final ConfigNodeConfig CONF = ConfigNodeDescriptor.getInstance().getConf(); - private static final int SCHEMA_REGION_PER_DATA_NODE = CONF.getSchemaRegionPerDataNode(); - private static final int DATA_REGION_PER_DATA_NODE = CONF.getDataRegionPerDataNode(); private final IManager configManager; private final ClusterSchemaInfo clusterSchemaInfo; @@ -594,13 +592,13 @@ public int adjustRegionGroupNum( ? databaseSchema.getMinSchemaRegionGroupNum() : databaseSchema.getMinDataRegionGroupNum(), (consensusGroupType == TConsensusGroupType.SchemaRegion) - ? SCHEMA_REGION_PER_DATA_NODE - : (DATA_REGION_PER_DATA_NODE == 0 + ? CONF.getSchemaRegionPerDataNode() + : (CONF.getDataRegionPerDataNode() == 0 ? CONF.getDataRegionPerDataNodeProportion() - : DATA_REGION_PER_DATA_NODE), + : CONF.getDataRegionPerDataNode()), (consensusGroupType == TConsensusGroupType.SchemaRegion) ? dataNodeNum - : (DATA_REGION_PER_DATA_NODE == 0 ? totalCpuCoreNum : dataNodeNum), + : (CONF.getDataRegionPerDataNode() == 0 ? totalCpuCoreNum : dataNodeNum), databaseNum, databaseSchema.getSchemaReplicationFactor(), allocatedRegionGroupCount); From 30e59239b5470036204ac1436de4640468491a06 Mon Sep 17 00:00:00 2001 From: libo Date: Mon, 22 Jun 2026 15:58:47 +0800 Subject: [PATCH 6/8] Check whether the allocated schema or data region group count will reach the maximum quota after increasing the corresponding quota limit --- .../IoTDBDatabaseMaxRegionGroupNumIT.java | 55 +++++++++++++++---- 1 file changed, 45 insertions(+), 10 deletions(-) diff --git a/integration-test/src/test/java/org/apache/iotdb/relational/it/schema/IoTDBDatabaseMaxRegionGroupNumIT.java b/integration-test/src/test/java/org/apache/iotdb/relational/it/schema/IoTDBDatabaseMaxRegionGroupNumIT.java index e80aca504c312..90966f6406e0a 100644 --- a/integration-test/src/test/java/org/apache/iotdb/relational/it/schema/IoTDBDatabaseMaxRegionGroupNumIT.java +++ b/integration-test/src/test/java/org/apache/iotdb/relational/it/schema/IoTDBDatabaseMaxRegionGroupNumIT.java @@ -48,6 +48,10 @@ public class IoTDBDatabaseMaxRegionGroupNumIT { private static final int SERIES_SLOT_NUM = 8; + private static final int DEFAULT_SCHEMA_REGION_GROUP_NUM = 1; + private static final int DEFAULT_DATA_REGION_GROUP_NUM = 2; + private static final int MAX_SCHEMA_REGION_GROUP_NUM = 3; + private static final int MAX_DATA_REGION_GROUP_NUM = 4; private static final String TABLE_NAME = "table1"; private static final BKDRHashExecutor PARTITION_EXECUTOR = new BKDRHashExecutor(SERIES_SLOT_NUM); @@ -58,8 +62,8 @@ public void setUp() throws Exception { .getCommonConfig() .setSchemaRegionGroupExtensionPolicy("CUSTOM") .setDataRegionGroupExtensionPolicy("CUSTOM") - .setDefaultSchemaRegionGroupNumPerDatabase(1) - .setDefaultDataRegionGroupNumPerDatabase(2) + .setDefaultSchemaRegionGroupNumPerDatabase(DEFAULT_SCHEMA_REGION_GROUP_NUM) + .setDefaultDataRegionGroupNumPerDatabase(DEFAULT_DATA_REGION_GROUP_NUM) .setSeriesSlotNum(SERIES_SLOT_NUM) .setSeriesPartitionExecutorClass(BKDRHashExecutor.class.getName()) .setTimePartitionInterval(10); @@ -110,7 +114,7 @@ public void testCreateAndAlterMaxRegionGroupNum() throws SQLException { } @Test - public void testCreatePartitionAfterAlterMaxRegionGroupNum() throws SQLException { + public void testAllocatedRegionGroupNumEqualsQuotaAfterAlterAndWrite() throws SQLException { try (final Connection connection = EnvFactory.getEnv().getConnection(BaseEnv.TABLE_SQL_DIALECT); final Statement statement = connection.createStatement()) { @@ -123,16 +127,27 @@ public void testCreatePartitionAfterAlterMaxRegionGroupNum() throws SQLException final String secondDevice = getDeviceInNewSeriesSlot(usedSeriesSlots); insertData(statement, firstDevice, 0, 0); - assertRegionGroupNum(statement, "test_partition", 1, 2); + assertRegionGroupNum( + statement, + "test_partition", + DEFAULT_SCHEMA_REGION_GROUP_NUM, + DEFAULT_SCHEMA_REGION_GROUP_NUM, + DEFAULT_DATA_REGION_GROUP_NUM, + DEFAULT_DATA_REGION_GROUP_NUM); statement.execute( - "alter database test_partition set properties max_schema_region_group_num=3"); + "alter database test_partition set properties max_schema_region_group_num=" + + MAX_SCHEMA_REGION_GROUP_NUM); insertData(statement, secondDevice, 0, 1); - assertRegionGroupNum(statement, "test_partition", 3, 2); + assertAllocatedRegionGroupNumEqualsQuota( + statement, "test_partition", MAX_SCHEMA_REGION_GROUP_NUM, DEFAULT_DATA_REGION_GROUP_NUM); - statement.execute("alter database test_partition set properties max_data_region_group_num=4"); + statement.execute( + "alter database test_partition set properties max_data_region_group_num=" + + MAX_DATA_REGION_GROUP_NUM); insertData(statement, secondDevice, 20, 2); - assertRegionGroupNum(statement, "test_partition", 3, 4); + assertAllocatedRegionGroupNumEqualsQuota( + statement, "test_partition", MAX_SCHEMA_REGION_GROUP_NUM, MAX_DATA_REGION_GROUP_NUM); TestUtils.assertResultSetEqual( statement.executeQuery("select count(*) from " + TABLE_NAME), @@ -173,21 +188,41 @@ private static int getSeriesSlot(final String device) { .getSlotId(); } + private static void assertAllocatedRegionGroupNumEqualsQuota( + final Statement statement, + final String database, + final int schemaRegionGroupQuota, + final int dataRegionGroupQuota) + throws SQLException { + assertRegionGroupNum( + statement, + database, + schemaRegionGroupQuota, + schemaRegionGroupQuota, + dataRegionGroupQuota, + dataRegionGroupQuota); + } + private static void assertRegionGroupNum( final Statement statement, final String database, final int schemaRegionGroupNum, - final int dataRegionGroupNum) + final int maxSchemaRegionGroupNum, + final int dataRegionGroupNum, + final int maxDataRegionGroupNum) throws SQLException { try (final ResultSet resultSet = statement.executeQuery( - "select schema_region_group_num, data_region_group_num " + "select schema_region_group_num, max_schema_region_group_num, " + + "data_region_group_num, max_data_region_group_num " + "from information_schema.databases where database = '" + database + "'")) { Assert.assertTrue(resultSet.next()); Assert.assertEquals(schemaRegionGroupNum, resultSet.getInt("schema_region_group_num")); + Assert.assertEquals(maxSchemaRegionGroupNum, resultSet.getInt("max_schema_region_group_num")); Assert.assertEquals(dataRegionGroupNum, resultSet.getInt("data_region_group_num")); + Assert.assertEquals(maxDataRegionGroupNum, resultSet.getInt("max_data_region_group_num")); Assert.assertFalse(resultSet.next()); } } From e780a745a5eadaf29571d8fb82651b1081d76808 Mon Sep 17 00:00:00 2001 From: libo Date: Mon, 22 Jun 2026 18:13:12 +0800 Subject: [PATCH 7/8] Adjust to dynamic compute the expect value --- .../schema/IoTDBDatabaseMixedRegionGroupPolicyIT.java | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/integration-test/src/test/java/org/apache/iotdb/relational/it/schema/IoTDBDatabaseMixedRegionGroupPolicyIT.java b/integration-test/src/test/java/org/apache/iotdb/relational/it/schema/IoTDBDatabaseMixedRegionGroupPolicyIT.java index e90046c59b301..83e2137de3cf1 100644 --- a/integration-test/src/test/java/org/apache/iotdb/relational/it/schema/IoTDBDatabaseMixedRegionGroupPolicyIT.java +++ b/integration-test/src/test/java/org/apache/iotdb/relational/it/schema/IoTDBDatabaseMixedRegionGroupPolicyIT.java @@ -41,6 +41,8 @@ @Category({TableLocalStandaloneIT.class, TableClusterIT.class}) public class IoTDBDatabaseMixedRegionGroupPolicyIT { + private static final int DATA_REGION_PER_DATA_NODE = 4; + @Before public void setUp() throws Exception { EnvFactory.getEnv() @@ -50,7 +52,8 @@ public void setUp() throws Exception { .setDataRegionGroupExtensionPolicy("AUTO") .setDefaultSchemaRegionGroupNumPerDatabase(1) .setDefaultDataRegionGroupNumPerDatabase(1) - .setDataRegionPerDataNode(4); + .setDataReplicationFactor(1) + .setDataRegionPerDataNode(DATA_REGION_PER_DATA_NODE); EnvFactory.getEnv().initClusterEnvironment(); } @@ -64,6 +67,9 @@ public void testAutoPolicyStillAdjustsWhenTheOtherPolicyIsCustom() throws SQLExc try (final Connection connection = EnvFactory.getEnv().getConnection(BaseEnv.TABLE_SQL_DIALECT); final Statement statement = connection.createStatement()) { + final int expectedMaxDataRegionGroupNum = + DATA_REGION_PER_DATA_NODE * EnvFactory.getEnv().getDataNodeWrapperList().size(); + statement.execute("create database test_mixed with(max_schema_region_group_num=2)"); TestUtils.assertResultSetEqual( @@ -71,7 +77,7 @@ public void testAutoPolicyStillAdjustsWhenTheOtherPolicyIsCustom() throws SQLExc "select database, max_schema_region_group_num, max_data_region_group_num " + "from information_schema.databases where database = 'test_mixed'"), "database,max_schema_region_group_num,max_data_region_group_num,", - Collections.singleton("test_mixed,2,4,")); + Collections.singleton("test_mixed,2," + expectedMaxDataRegionGroupNum + ",")); } } } From 2518a496833d2f76d5c99fbf50128b53f7329184 Mon Sep 17 00:00:00 2001 From: libo Date: Mon, 22 Jun 2026 21:34:43 +0800 Subject: [PATCH 8/8] Modify the prefix name of output string --- .../plan/statement/metadata/DatabaseSchemaStatement.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/statement/metadata/DatabaseSchemaStatement.java b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/statement/metadata/DatabaseSchemaStatement.java index b31520fdc7605..e27dde87b41b8 100644 --- a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/statement/metadata/DatabaseSchemaStatement.java +++ b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/statement/metadata/DatabaseSchemaStatement.java @@ -141,8 +141,8 @@ public List getPaths() { @Override public String toString() { - return "SetStorageGroupStatement{" - + "storageGroupPath=" + return "DatabaseSchemaStatement{" + + "databasePath=" + databasePath + ", ttl=" + ttl