This is an automated email from the ASF dual-hosted git repository.

JackieTien97 pushed a commit to branch fix/show-configuration-effective-value
in repository https://gitbox.apache.org/repos/asf/iotdb.git

commit e8f5c26196b202eee7ea60d2facb5e86353bdd8c
Author: JackieTien97 <[email protected]>
AuthorDate: Fri Jul 3 16:49:21 2026 +0800

    Fix show configuration displaying raw value instead of effective value
    
    show configuration (table model) renders 
ConfigurationFileUtils.lastAppliedProperties, which is populated from the raw 
config-file values. Several hot-reloaded parameters have setters that rewrite 
the loaded value (e.g. `if (x > 0) setX(x)` skips non-positive values; 
loadFixedSizeLimitForQuery rewrites `<=0` to a computed default), so their 
displayed value diverged from the effective in-memory value.
    
    Add overlayEffectiveConfigurationValues() to overwrite those keys with the 
post-setter effective value, invoked after the setters in both loadProperties 
(startup) and loadHotModifiedProps (hot-reload), so local and remote show 
configuration stay correct. Affected keys: cte_buffer_size_in_bytes, 
max_rows_in_cte_buffer, max_sub_task_num_for_information_table_scan, 
sort_buffer_size_in_bytes, mods_cache_size_limit_per_fi_in_bytes.
    
    Added IT: 
IoTDBLoadConfigurationTableIT#showConfigurationDisplaysEffectiveValue.
---
 .../it/db/it/IoTDBLoadConfigurationTableIT.java    | 94 ++++++++++++++++++++++
 .../org/apache/iotdb/db/conf/IoTDBDescriptor.java  | 33 ++++++++
 2 files changed, 127 insertions(+)

diff --git 
a/integration-test/src/test/java/org/apache/iotdb/relational/it/db/it/IoTDBLoadConfigurationTableIT.java
 
b/integration-test/src/test/java/org/apache/iotdb/relational/it/db/it/IoTDBLoadConfigurationTableIT.java
index 53e8bc9487e..398a7f0e1e4 100644
--- 
a/integration-test/src/test/java/org/apache/iotdb/relational/it/db/it/IoTDBLoadConfigurationTableIT.java
+++ 
b/integration-test/src/test/java/org/apache/iotdb/relational/it/db/it/IoTDBLoadConfigurationTableIT.java
@@ -19,6 +19,8 @@
 
 package org.apache.iotdb.relational.it.db.it;
 
+import org.apache.iotdb.isession.ITableSession;
+import org.apache.iotdb.isession.SessionDataSet;
 import org.apache.iotdb.it.env.EnvFactory;
 import org.apache.iotdb.it.env.cluster.node.DataNodeWrapper;
 import org.apache.iotdb.it.framework.IoTDBTestRunner;
@@ -40,6 +42,8 @@ import java.nio.channels.FileChannel;
 import java.nio.file.StandardOpenOption;
 import java.sql.Connection;
 import java.sql.Statement;
+import java.util.HashMap;
+import java.util.Map;
 
 @RunWith(IoTDBTestRunner.class)
 @Category({TableLocalStandaloneIT.class, TableClusterIT.class})
@@ -82,4 +86,94 @@ public class IoTDBLoadConfigurationTableIT {
       }
     }
   }
+
+  // `show configuration` must display the in-memory effective value, not the 
raw config-file
+  // value. Several hot-reloaded parameters have setters that rewrite the 
loaded value (e.g.
+  // `if (x > 0) setX(x)` skips non-positive values; 
loadFixedSizeLimitForQuery rewrites `<=0`
+  // to a computed default). This test verifies those keys show the effective 
value after
+  // `load configuration`.
+  @Test
+  public void showConfigurationDisplaysEffectiveValue() throws Exception {
+    DataNodeWrapper dataNodeWrapper = 
EnvFactory.getEnv().getDataNodeWrapper(0);
+    String confPath =
+        dataNodeWrapper.getNodePath()
+            + File.separator
+            + "conf"
+            + File.separator
+            + "iotdb-system.properties";
+
+    // Case 1: non-positive guard params (`if (x > 0) setX(x)`) must display 
the effective
+    // default value, not the raw file value (0 / -1).
+    Map<String, String> afterGuardReload =
+        appendLinesLoadAndShow(
+            confPath,
+            "cte_buffer_size_in_bytes=0",
+            "max_rows_in_cte_buffer=-1",
+            "max_sub_task_num_for_information_table_scan=0");
+    Assert.assertEquals("131072", 
afterGuardReload.get("cte_buffer_size_in_bytes"));
+    Assert.assertEquals("1000", 
afterGuardReload.get("max_rows_in_cte_buffer"));
+    Assert.assertEquals("4", 
afterGuardReload.get("max_sub_task_num_for_information_table_scan"));
+
+    // Case 2: a valid value is not rewritten, so display must equal the file 
value (regression).
+    Map<String, String> afterValidReload =
+        appendLinesLoadAndShow(confPath, "cte_buffer_size_in_bytes=262144");
+    Assert.assertEquals("262144", 
afterValidReload.get("cte_buffer_size_in_bytes"));
+
+    // Case 3: params whose template default is 0 are always rewritten to a 
computed default,
+    // so they must never display 0 (this was always wrong, even without a bad 
file value).
+    Map<String, String> defaultsReload = appendLinesLoadAndShow(confPath);
+    assertPositiveNonZero(defaultsReload, "sort_buffer_size_in_bytes");
+    assertPositiveNonZero(defaultsReload, 
"mods_cache_size_limit_per_fi_in_bytes");
+  }
+
+  // Appends the given lines to the config file, runs `load configuration`, 
fetches the
+  // `show configuration` result, and restores the file to its original length.
+  private Map<String, String> appendLinesLoadAndShow(String confPath, 
String... lines)
+      throws Exception {
+    long length = new File(confPath).length();
+    try {
+      if (lines.length > 0) {
+        try (FileWriter fileWriter = new FileWriter(confPath, true)) {
+          fileWriter.write(System.lineSeparator());
+          for (String line : lines) {
+            fileWriter.write(line);
+            fileWriter.write(System.lineSeparator());
+          }
+        }
+      }
+      try (Connection connection = 
EnvFactory.getEnv().getConnection(BaseEnv.TABLE_SQL_DIALECT);
+          Statement statement = connection.createStatement()) {
+        statement.execute("LOAD CONFIGURATION");
+      }
+      return fetchShowConfiguration();
+    } finally {
+      try (FileChannel fileChannel =
+          FileChannel.open(new File(confPath).toPath(), 
StandardOpenOption.WRITE)) {
+        fileChannel.truncate(length);
+      }
+    }
+  }
+
+  private Map<String, String> fetchShowConfiguration() throws Exception {
+    Map<String, String> result = new HashMap<>();
+    try (ITableSession tableSessionConnection = 
EnvFactory.getEnv().getTableSessionConnection()) {
+      SessionDataSet sessionDataSet =
+          tableSessionConnection.executeQueryStatement("show configuration");
+      SessionDataSet.DataIterator iterator = sessionDataSet.iterator();
+      while (iterator.next()) {
+        String name = iterator.getString(1);
+        String value = iterator.isNull(2) ? null : iterator.getString(2);
+        result.put(name, value);
+      }
+    }
+    return result;
+  }
+
+  private static void assertPositiveNonZero(Map<String, String> configMap, 
String key) {
+    String value = configMap.get(key);
+    Assert.assertNotNull("show configuration is missing key: " + key, value);
+    long parsed = Long.parseLong(value);
+    Assert.assertTrue(
+        key + " should display a positive effective value, but was " + value, 
parsed > 0);
+  }
 }
diff --git 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/conf/IoTDBDescriptor.java
 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/conf/IoTDBDescriptor.java
index 147c3340bb3..7bd29087d50 100644
--- 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/conf/IoTDBDescriptor.java
+++ 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/conf/IoTDBDescriptor.java
@@ -1232,6 +1232,11 @@ public class IoTDBDescriptor {
     if (maxSubTaskNumForInformationTableScan > 0) {
       
conf.setMaxSubTaskNumForInformationTableScan(maxSubTaskNumForInformationTableScan);
     }
+
+    // Reflect the in-memory effective values (which the setters above may 
have rewritten) into
+    // lastAppliedProperties, so that `show configuration` displays effective 
values rather than
+    // the raw config-file values.
+    overlayEffectiveConfigurationValues();
   }
 
   private void loadFixedSizeLimitForQuery(
@@ -2333,6 +2338,9 @@ public class IoTDBDescriptor {
       }
 
       ConfigurationFileUtils.updateAppliedProperties(properties, true);
+      // Overwrite the keys whose setters above may have rewritten, so `show 
configuration`
+      // displays the effective values rather than the raw file values.
+      overlayEffectiveConfigurationValues();
     } catch (Exception e) {
       if (e instanceof InterruptedException) {
         Thread.currentThread().interrupt();
@@ -2342,6 +2350,31 @@ public class IoTDBDescriptor {
     }
   }
 
+  // `show configuration` (table model) renders 
ConfigurationFileUtils.getAppliedProperties().
+  // That map is populated from the raw config-file values, but several 
hot-reloaded parameters
+  // have setters that rewrite the loaded value before it takes effect, e.g.:
+  //   - `if (x > 0) setX(x)` skips non-positive values (keeps the 
previous/default value);
+  //   - loadFixedSizeLimitForQuery rewrites `<=0` to a computed default.
+  // For those keys the displayed value would otherwise diverge from the 
effective one. This
+  // method overwrites them with the post-setter effective value. It is 
invoked after the setters
+  // in both the startup (loadProperties) and hot-reload 
(loadHotModifiedProps) paths, so that
+  // local *and* remote `show configuration` (which reads each node's own map 
over RPC) stay
+  // correct.
+  private void overlayEffectiveConfigurationValues() {
+    ConfigurationFileUtils.updateAppliedProperties(
+        "cte_buffer_size_in_bytes", 
Long.toString(commonConfig.getCteBufferSize()));
+    ConfigurationFileUtils.updateAppliedProperties(
+        "max_rows_in_cte_buffer", 
Integer.toString(commonConfig.getMaxRowsInCteBuffer()));
+    ConfigurationFileUtils.updateAppliedProperties(
+        "max_sub_task_num_for_information_table_scan",
+        Integer.toString(conf.getMaxSubTaskNumForInformationTableScan()));
+    ConfigurationFileUtils.updateAppliedProperties(
+        "sort_buffer_size_in_bytes",
+        Long.toString(commonDescriptor.getConfig().getSortBufferSize()));
+    ConfigurationFileUtils.updateAppliedProperties(
+        "mods_cache_size_limit_per_fi_in_bytes", 
Long.toString(conf.getModsCacheSizeLimitPerFI()));
+  }
+
   private void loadQuerySampleThroughput(TrimProperties properties) throws 
IOException {
     String querySamplingRateLimitNumber =
         properties.getProperty(

Reply via email to