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

yashmayya pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/pinot.git


The following commit(s) were added to refs/heads/master by this push:
     new bd1e8824a88 Split list configs on commas when set via cluster config, 
and trim planner rule names (#19644)
bd1e8824a88 is described below

commit bd1e8824a88c7ca5de67db2510e775851d506234
Author: Yash Mayya <[email protected]>
AuthorDate: Thu Sep 24 14:41:49 2026 -0700

    Split list configs on commas when set via cluster config, and trim planner 
rule names (#19644)
---
 .../broker/broker/helix/BaseBrokerStarter.java     |  8 ++-
 .../broker/broker/helix/BaseBrokerStarterTest.java | 53 ++++++++++++++++
 .../common/utils/config/QueryOptionsUtils.java     | 26 ++++----
 .../common/utils/config/QueryOptionsUtilsTest.java | 14 +++++
 .../apache/pinot/controller/ControllerConf.java    |  3 +-
 .../pinot/controller/ControllerConfTest.java       | 20 +++++++
 .../pinot/query/QueryPlannerRuleOptionsTest.java   | 12 ++++
 .../org/apache/pinot/server/conf/ServerConf.java   |  4 +-
 .../apache/pinot/server/conf/ServerConfTest.java   | 70 ++++++++++++++++++++++
 .../apache/pinot/spi/env/PinotConfiguration.java   | 24 ++++++++
 .../pinot/spi/env/PinotConfigurationTest.java      | 30 ++++++++++
 11 files changed, 246 insertions(+), 18 deletions(-)

diff --git 
a/pinot-broker/src/main/java/org/apache/pinot/broker/broker/helix/BaseBrokerStarter.java
 
b/pinot-broker/src/main/java/org/apache/pinot/broker/broker/helix/BaseBrokerStarter.java
index f6378e38041..18cac8d2825 100644
--- 
a/pinot-broker/src/main/java/org/apache/pinot/broker/broker/helix/BaseBrokerStarter.java
+++ 
b/pinot-broker/src/main/java/org/apache/pinot/broker/broker/helix/BaseBrokerStarter.java
@@ -422,7 +422,7 @@ public abstract class BaseBrokerStarter implements 
ServiceStartable {
         _brokerConf.getProperty(Broker.CONFIG_OF_METRICS_NAME_PREFIX, 
Broker.DEFAULT_METRICS_NAME_PREFIX),
         _metricsRegistry,
         _brokerConf.getProperty(Broker.CONFIG_OF_ENABLE_TABLE_LEVEL_METRICS, 
Broker.DEFAULT_ENABLE_TABLE_LEVEL_METRICS),
-        
_brokerConf.getProperty(Broker.CONFIG_OF_ALLOWED_TABLES_FOR_EMITTING_METRICS, 
List.of()));
+        getAllowedTablesForEmittingMetrics(_brokerConf));
     _brokerMetrics.initializeGlobalMeters();
     _brokerMetrics.setValueOfGlobalGauge(BrokerGauge.VERSION, 
PinotVersion.VERSION_METRIC_NAME, 1);
     _brokerMetrics.setValueOfGlobalGauge(BrokerGauge.ZK_JUTE_MAX_BUFFER,
@@ -755,6 +755,12 @@ public abstract class BaseBrokerStarter implements 
ServiceStartable {
     LOGGER.info("Finish starting Pinot broker");
   }
 
+  /// Returns the tables that emit table-level metrics even when table-level 
metrics are disabled.
+  @VisibleForTesting
+  static List<String> getAllowedTablesForEmittingMetrics(PinotConfiguration 
brokerConf) {
+    return 
brokerConf.getCommaSeparatedList(Broker.CONFIG_OF_ALLOWED_TABLES_FOR_EMITTING_METRICS,
 List.of());
+  }
+
   protected void initClusterChangeMediator() throws Exception {
     for (ClusterChangeHandler clusterConfigChangeHandler : 
_clusterConfigChangeHandlers) {
       clusterConfigChangeHandler.init(_spectatorHelixManager);
diff --git 
a/pinot-broker/src/test/java/org/apache/pinot/broker/broker/helix/BaseBrokerStarterTest.java
 
b/pinot-broker/src/test/java/org/apache/pinot/broker/broker/helix/BaseBrokerStarterTest.java
new file mode 100644
index 00000000000..581620e92ec
--- /dev/null
+++ 
b/pinot-broker/src/test/java/org/apache/pinot/broker/broker/helix/BaseBrokerStarterTest.java
@@ -0,0 +1,53 @@
+/**
+ * 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.pinot.broker.broker.helix;
+
+import java.util.List;
+import java.util.Map;
+import org.apache.pinot.spi.env.PinotConfiguration;
+import org.testng.annotations.Test;
+
+import static 
org.apache.pinot.spi.utils.CommonConstants.Broker.CONFIG_OF_ALLOWED_TABLES_FOR_EMITTING_METRICS;
+import static org.testng.Assert.assertEquals;
+
+
+/// Tests the list configs that [BaseBrokerStarter] reads. The cluster config 
test sets the value with
+/// [PinotConfiguration#setProperty], as 
`ServiceStartableUtils.applyClusterConfig` does. That value is not split on
+/// commas.
+public class BaseBrokerStarterTest {
+
+  @Test
+  public void testAllowedTablesForEmittingMetricsFromClusterConfig() {
+    PinotConfiguration brokerConf = new PinotConfiguration();
+    brokerConf.setProperty(CONFIG_OF_ALLOWED_TABLES_FOR_EMITTING_METRICS, 
"table1, table2");
+    
assertEquals(BaseBrokerStarter.getAllowedTablesForEmittingMetrics(brokerConf), 
List.of("table1", "table2"));
+  }
+
+  @Test
+  public void testAllowedTablesForEmittingMetricsFromBrokerConfig() {
+    PinotConfiguration brokerConf =
+        new 
PinotConfiguration(Map.of(CONFIG_OF_ALLOWED_TABLES_FOR_EMITTING_METRICS, 
"table1, table2"));
+    
assertEquals(BaseBrokerStarter.getAllowedTablesForEmittingMetrics(brokerConf), 
List.of("table1", "table2"));
+  }
+
+  @Test
+  public void testAllowedTablesForEmittingMetricsUnset() {
+    assertEquals(BaseBrokerStarter.getAllowedTablesForEmittingMetrics(new 
PinotConfiguration()), List.of());
+  }
+}
diff --git 
a/pinot-common/src/main/java/org/apache/pinot/common/utils/config/QueryOptionsUtils.java
 
b/pinot-common/src/main/java/org/apache/pinot/common/utils/config/QueryOptionsUtils.java
index f93a4597230..68eb597482e 100644
--- 
a/pinot-common/src/main/java/org/apache/pinot/common/utils/config/QueryOptionsUtils.java
+++ 
b/pinot-common/src/main/java/org/apache/pinot/common/utils/config/QueryOptionsUtils.java
@@ -30,6 +30,7 @@ import java.util.Map;
 import java.util.Optional;
 import java.util.Set;
 import java.util.concurrent.ConcurrentHashMap;
+import java.util.stream.Collectors;
 import javax.annotation.Nullable;
 import org.apache.commons.lang3.StringUtils;
 import org.apache.pinot.spi.config.table.FieldConfig;
@@ -456,26 +457,23 @@ public class QueryOptionsUtils {
 
   public static Set<String> getSkipPlannerRules(Map<String, String> 
queryOptions) {
     // Example config:  
skipPlannerRules='FilterIntoJoin,FilterAggregateTranspose'
-    String skipPlannerRulesStr = 
queryOptions.get(QueryOptionKey.SKIP_PLANNER_RULES);
-    if (skipPlannerRulesStr == null) {
-      return Set.of();
-    }
-
-    String[] skippedRules = StringUtils.split(skipPlannerRulesStr, ',');
-
-    return new HashSet<>(List.of(skippedRules));
+    return 
parsePlannerRules(queryOptions.get(QueryOptionKey.SKIP_PLANNER_RULES));
   }
 
   public static Set<String> getUsePlannerRules(Map<String, String> 
queryOptions) {
     // Example config:  usePlannerRules='SortJoinTranspose, 
AggregateJoinTransposeExtended'
-    String usePlannerRulesStr = 
queryOptions.get(QueryOptionKey.USE_PLANNER_RULES);
-    if (usePlannerRulesStr == null) {
+    return 
parsePlannerRules(queryOptions.get(QueryOptionKey.USE_PLANNER_RULES));
+  }
+
+  /// Parses a comma-separated list of planner rule names. Each name is 
trimmed, and empty names are dropped.
+  private static Set<String> parsePlannerRules(@Nullable String plannerRules) {
+    if (plannerRules == null) {
       return Set.of();
     }
-
-    String[] useRules = StringUtils.split(usePlannerRulesStr, ',');
-
-    return new HashSet<>(List.of(useRules));
+    return Arrays.stream(StringUtils.split(plannerRules, ','))
+        .map(String::trim)
+        .filter(ruleName -> !ruleName.isEmpty())
+        .collect(Collectors.toSet());
   }
 
   /// Returns the per-query override of the approximate-function rewrite, or 
`null` if the query does not set one, in
diff --git 
a/pinot-common/src/test/java/org/apache/pinot/common/utils/config/QueryOptionsUtilsTest.java
 
b/pinot-common/src/test/java/org/apache/pinot/common/utils/config/QueryOptionsUtilsTest.java
index 0b8155403aa..1bda5547c27 100644
--- 
a/pinot-common/src/test/java/org/apache/pinot/common/utils/config/QueryOptionsUtilsTest.java
+++ 
b/pinot-common/src/test/java/org/apache/pinot/common/utils/config/QueryOptionsUtilsTest.java
@@ -139,6 +139,20 @@ public class QueryOptionsUtilsTest {
     QueryOptionsUtils.getSkipIndexes(queryOptions);
   }
 
+  @Test
+  public void testPlannerRulesParsing() {
+    // Rule names are trimmed, and empty names are dropped
+    Map<String, String> queryOptions = Map.of(USE_PLANNER_RULES, 
"SortJoinTranspose, AggregateJoinTransposeExtended, ",
+        SKIP_PLANNER_RULES, " FilterIntoJoin ,,FilterAggregateTranspose");
+    assertEquals(QueryOptionsUtils.getUsePlannerRules(queryOptions),
+        Set.of("SortJoinTranspose", "AggregateJoinTransposeExtended"));
+    assertEquals(QueryOptionsUtils.getSkipPlannerRules(queryOptions),
+        Set.of("FilterIntoJoin", "FilterAggregateTranspose"));
+
+    assertEquals(QueryOptionsUtils.getUsePlannerRules(Map.of()), Set.of());
+    assertEquals(QueryOptionsUtils.getSkipPlannerRules(Map.of()), Set.of());
+  }
+
   @Test
   public void testIntegerSettingParseSuccess() {
     HashMap<String, String> map = new HashMap<>();
diff --git 
a/pinot-controller/src/main/java/org/apache/pinot/controller/ControllerConf.java
 
b/pinot-controller/src/main/java/org/apache/pinot/controller/ControllerConf.java
index efd06aae9ff..fd6ccdcdea5 100644
--- 
a/pinot-controller/src/main/java/org/apache/pinot/controller/ControllerConf.java
+++ 
b/pinot-controller/src/main/java/org/apache/pinot/controller/ControllerConf.java
@@ -609,7 +609,8 @@ public class ControllerConf extends PinotConfiguration {
   }
 
   public List<String> getControllerAccessProtocols() {
-    return getProperty(CONTROLLER_ACCESS_PROTOCOLS, getControllerPort() == 
null ? List.of("http") : List.of());
+    return getCommaSeparatedList(CONTROLLER_ACCESS_PROTOCOLS,
+        getControllerPort() == null ? List.of("http") : List.of());
   }
 
   public String getControllerAccessProtocolProperty(String protocol, String 
property) {
diff --git 
a/pinot-controller/src/test/java/org/apache/pinot/controller/ControllerConfTest.java
 
b/pinot-controller/src/test/java/org/apache/pinot/controller/ControllerConfTest.java
index ab61aa277c4..1fc53dcd1eb 100644
--- 
a/pinot-controller/src/test/java/org/apache/pinot/controller/ControllerConfTest.java
+++ 
b/pinot-controller/src/test/java/org/apache/pinot/controller/ControllerConfTest.java
@@ -199,6 +199,26 @@ public class ControllerConfTest {
             
TimeUtils.convertPeriodToMillis(DEFAULT_RETENTION_MANAGER_FREQUENCY_PERIOD), 
TimeUnit.MILLISECONDS));
   }
 
+  @Test
+  public void testControllerAccessProtocolsFromClusterConfig() {
+    // ServiceStartableUtils.applyClusterConfig applies cluster configs with 
setProperty, which doesn't split lists
+    ControllerConf conf = new ControllerConf();
+    conf.setProperty(ControllerConf.CONTROLLER_ACCESS_PROTOCOLS, "http,https");
+    conf.setProperty(ControllerConf.CONTROLLER_ACCESS_PROTOCOLS + 
".https.port", "8443");
+    conf.setProperty(ControllerConf.CONTROLLER_ACCESS_PROTOCOLS + 
".https.vip", "true");
+    Assert.assertEquals(conf.getControllerAccessProtocols(), List.of("http", 
"https"));
+    Assert.assertEquals(conf.getControllerVipPort(), "8443");
+  }
+
+  @Test
+  public void testControllerAccessProtocolsDefault() {
+    ControllerConf conf = new ControllerConf();
+    Assert.assertEquals(conf.getControllerAccessProtocols(), List.of("http"));
+
+    conf.setProperty(ControllerConf.CONTROLLER_PORT, "9000");
+    Assert.assertEquals(conf.getControllerAccessProtocols(), List.of());
+  }
+
   @Test
   public void testConcurrentSchedulingEnabledDefault() {
     ControllerConf conf = new ControllerConf();
diff --git 
a/pinot-query-planner/src/test/java/org/apache/pinot/query/QueryPlannerRuleOptionsTest.java
 
b/pinot-query-planner/src/test/java/org/apache/pinot/query/QueryPlannerRuleOptionsTest.java
index f2faaccf546..be830d02240 100644
--- 
a/pinot-query-planner/src/test/java/org/apache/pinot/query/QueryPlannerRuleOptionsTest.java
+++ 
b/pinot-query-planner/src/test/java/org/apache/pinot/query/QueryPlannerRuleOptionsTest.java
@@ -319,6 +319,18 @@ public class QueryPlannerRuleOptionsTest extends 
QueryEnvironmentTestBase {
     //@formatter:on
   }
 
+  @Test
+  public void testEnableTwoRulesSeparatedByCommaAndSpace() {
+    // The space after the comma must not stop the second rule from matching
+    String query = "EXPLAIN PLAN FOR SELECT col1 FROM a ORDER BY col1";
+    String explain = explainQueryWithRuleEnabled(query,
+        PlannerRuleNames.SORT_JOIN_TRANSPOSE + ", " + 
PlannerRuleNames.SORT_PROJECT_TRANSPOSE);
+    int sortIdx = explain.indexOf("LogicalSort");
+    int projectIdx = explain.indexOf("LogicalProject");
+    assertTrue(projectIdx >= 0 && sortIdx > projectIdx,
+        "With SortProjectTranspose enabled, Project must be above Sort. 
Plan:\n" + explain);
+  }
+
   @Test
   public void testAggregateJoinTransposeExtendedDisabledByDefault() {
     // test aggregate function pushdown is disabled by default
diff --git 
a/pinot-server/src/main/java/org/apache/pinot/server/conf/ServerConf.java 
b/pinot-server/src/main/java/org/apache/pinot/server/conf/ServerConf.java
index 79e6675442d..375d1285ba7 100644
--- a/pinot-server/src/main/java/org/apache/pinot/server/conf/ServerConf.java
+++ b/pinot-server/src/main/java/org/apache/pinot/server/conf/ServerConf.java
@@ -126,7 +126,7 @@ public class ServerConf {
   /// Returns a list of transform function names as defined in the config
   /// @return List of transform functions
   public List<String> getTransformFunctions() {
-    return _serverConf.getProperty(CONFIG_OF_TRANSFORM_FUNCTIONS, List.of());
+    return _serverConf.getCommaSeparatedList(CONFIG_OF_TRANSFORM_FUNCTIONS, 
List.of());
   }
 
   public boolean emitTableLevelMetrics() {
@@ -134,7 +134,7 @@ public class ServerConf {
   }
 
   public Collection<String> getAllowedTablesForEmittingMetrics() {
-    return 
_serverConf.getProperty(CONFIG_OF_ALLOWED_TABLES_FOR_EMITTING_METRICS, 
List.of());
+    return 
_serverConf.getCommaSeparatedList(CONFIG_OF_ALLOWED_TABLES_FOR_EMITTING_METRICS,
 List.of());
   }
 
   public String getMetricsPrefix() {
diff --git 
a/pinot-server/src/test/java/org/apache/pinot/server/conf/ServerConfTest.java 
b/pinot-server/src/test/java/org/apache/pinot/server/conf/ServerConfTest.java
new file mode 100644
index 00000000000..dcd7e399782
--- /dev/null
+++ 
b/pinot-server/src/test/java/org/apache/pinot/server/conf/ServerConfTest.java
@@ -0,0 +1,70 @@
+/**
+ * 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.pinot.server.conf;
+
+import java.util.List;
+import java.util.Map;
+import org.apache.pinot.spi.env.PinotConfiguration;
+import org.testng.annotations.Test;
+
+import static 
org.apache.pinot.spi.utils.CommonConstants.Server.CONFIG_OF_ALLOWED_TABLES_FOR_EMITTING_METRICS;
+import static 
org.apache.pinot.spi.utils.CommonConstants.Server.CONFIG_OF_TRANSFORM_FUNCTIONS;
+import static org.testng.Assert.assertEquals;
+
+
+/// Tests the list configs of [ServerConf]. The cluster config tests set the 
value with
+/// [PinotConfiguration#setProperty], as 
`ServiceStartableUtils.applyClusterConfig` does. That value is not split on
+/// commas.
+public class ServerConfTest {
+  private static final String TRANSFORM_FUNCTIONS = 
"com.example.FirstFunction, com.example.SecondFunction";
+  private static final List<String> EXPECTED_TRANSFORM_FUNCTIONS =
+      List.of("com.example.FirstFunction", "com.example.SecondFunction");
+  private static final String ALLOWED_TABLES = "table1, table2";
+  private static final List<String> EXPECTED_ALLOWED_TABLES = 
List.of("table1", "table2");
+
+  @Test
+  public void testTransformFunctionsFromClusterConfig() {
+    PinotConfiguration config = new PinotConfiguration();
+    config.setProperty(CONFIG_OF_TRANSFORM_FUNCTIONS, TRANSFORM_FUNCTIONS);
+    assertEquals(new ServerConf(config).getTransformFunctions(), 
EXPECTED_TRANSFORM_FUNCTIONS);
+  }
+
+  @Test
+  public void testAllowedTablesForEmittingMetricsFromClusterConfig() {
+    PinotConfiguration config = new PinotConfiguration();
+    config.setProperty(CONFIG_OF_ALLOWED_TABLES_FOR_EMITTING_METRICS, 
ALLOWED_TABLES);
+    assertEquals(new ServerConf(config).getAllowedTablesForEmittingMetrics(), 
EXPECTED_ALLOWED_TABLES);
+  }
+
+  @Test
+  public void testListConfigsFromServerConfig() {
+    ServerConf serverConf = new ServerConf(new PinotConfiguration(
+        Map.of(CONFIG_OF_TRANSFORM_FUNCTIONS, TRANSFORM_FUNCTIONS, 
CONFIG_OF_ALLOWED_TABLES_FOR_EMITTING_METRICS,
+            ALLOWED_TABLES)));
+    assertEquals(serverConf.getTransformFunctions(), 
EXPECTED_TRANSFORM_FUNCTIONS);
+    assertEquals(serverConf.getAllowedTablesForEmittingMetrics(), 
EXPECTED_ALLOWED_TABLES);
+  }
+
+  @Test
+  public void testListConfigsUnset() {
+    ServerConf serverConf = new ServerConf(new PinotConfiguration());
+    assertEquals(serverConf.getTransformFunctions(), List.of());
+    assertEquals(serverConf.getAllowedTablesForEmittingMetrics(), List.of());
+  }
+}
diff --git 
a/pinot-spi/src/main/java/org/apache/pinot/spi/env/PinotConfiguration.java 
b/pinot-spi/src/main/java/org/apache/pinot/spi/env/PinotConfiguration.java
index 1e3a41d9e6a..b0103c7775a 100644
--- a/pinot-spi/src/main/java/org/apache/pinot/spi/env/PinotConfiguration.java
+++ b/pinot-spi/src/main/java/org/apache/pinot/spi/env/PinotConfiguration.java
@@ -32,6 +32,7 @@ import org.apache.commons.configuration2.MapConfiguration;
 import org.apache.commons.configuration2.PropertiesConfiguration;
 import org.apache.commons.configuration2.convert.LegacyListDelimiterHandler;
 import org.apache.commons.configuration2.ex.ConfigurationException;
+import org.apache.commons.lang3.StringUtils;
 import org.apache.pinot.spi.ingestion.batch.spec.PinotFSSpec;
 import org.apache.pinot.spi.utils.Obfuscator;
 import org.slf4j.Logger;
@@ -337,6 +338,9 @@ public class PinotConfiguration {
   /// Retrieves a list of String values with the given property name. See 
[PinotConfiguration] for supported key
   /// naming conventions.
   ///
+  /// A value set with [#setProperty(String, Object)] is not split on commas. 
For a list config that can be set this
+  /// way, such as a cluster config, use [#getCommaSeparatedList(String, 
List)].
+  ///
   /// @param name of the property to retrieve a list of values. Property name 
will be sanitized.
   /// @return the property String value. Fallback to the provided default 
values if no property is found.
   public List<String> getProperty(String name, List<String> defaultValues) {
@@ -345,6 +349,26 @@ public class PinotConfiguration {
         .filter(list -> !list.isEmpty()).orElse(defaultValues);
   }
 
+  /// Retrieves a list of String values with the given property name, and 
splits each value on commas. Each value is
+  /// trimmed, and empty values are dropped. See [PinotConfiguration] for 
supported key naming conventions.
+  ///
+  /// Use this instead of [#getProperty(String, List)] for a list config that 
can be set with
+  /// [#setProperty(String, Object)], such as a cluster config. Values from a 
[Map] or a config file are split on
+  /// commas when they are loaded, but a value set with [#setProperty(String, 
Object)] is kept as one value. Do not
+  /// use this for values that can contain commas.
+  ///
+  /// @param name of the property to retrieve a list of values. Property name 
will be sanitized.
+  /// @param defaultValues to return if the property is missing or has no 
values.
+  /// @return an unmodifiable list of the values, or `defaultValues` if there 
are none.
+  public List<String> getCommaSeparatedList(String name, List<String> 
defaultValues) {
+    List<String> values = 
Arrays.stream(_configuration.getStringArray(relaxPropertyName(name)))
+        .flatMap(value -> Arrays.stream(StringUtils.split(value, ',')))
+        .map(String::trim)
+        .filter(value -> !value.isEmpty())
+        .collect(Collectors.toUnmodifiableList());
+    return values.isEmpty() ? defaultValues : values;
+  }
+
   /// Retrieves a long value with the given property name. See 
[PinotConfiguration] for supported key naming
   /// conventions.
   ///
diff --git 
a/pinot-spi/src/test/java/org/apache/pinot/spi/env/PinotConfigurationTest.java 
b/pinot-spi/src/test/java/org/apache/pinot/spi/env/PinotConfigurationTest.java
index 6df9099ed13..aaba9751b80 100644
--- 
a/pinot-spi/src/test/java/org/apache/pinot/spi/env/PinotConfigurationTest.java
+++ 
b/pinot-spi/src/test/java/org/apache/pinot/spi/env/PinotConfigurationTest.java
@@ -123,6 +123,36 @@ public class PinotConfigurationTest {
     Assert.assertEquals(pinotConfiguration.getRawProperty("raw-property"), 
object);
   }
 
+  @Test
+  public void assertCommaSeparatedList() {
+    // Unlike values loaded from a map or a file, a value set with setProperty 
is not split on commas
+    PinotConfiguration pinotConfiguration = new PinotConfiguration();
+    pinotConfiguration.setProperty("config.list", "val1, val2,, ,val3,");
+    Assert.assertEquals(pinotConfiguration.getProperty("config.list", 
List.of()), List.of("val1, val2,, ,val3,"));
+    
Assert.assertEquals(pinotConfiguration.getCommaSeparatedList("config.list", 
List.of()),
+        List.of("val1", "val2", "val3"));
+    // Scalar getters are not affected
+    Assert.assertEquals(pinotConfiguration.getProperty("config.list"), "val1, 
val2,, ,val3,");
+    Assert.assertEquals(pinotConfiguration.getRawProperty("config.list"), 
"val1, val2,, ,val3,");
+
+    pinotConfiguration = new PinotConfiguration(Map.of("config.list", "val1, 
val2,val3"));
+    Assert.assertEquals(pinotConfiguration.getProperty("config.list", 
List.of()), List.of("val1", "val2", "val3"));
+    
Assert.assertEquals(pinotConfiguration.getCommaSeparatedList("config.list", 
List.of()),
+        List.of("val1", "val2", "val3"));
+
+    pinotConfiguration = new PinotConfiguration();
+    pinotConfiguration.setProperty("config.list", List.of("val1", "val2, 
val3"));
+    
Assert.assertEquals(pinotConfiguration.getCommaSeparatedList("config.list", 
List.of()),
+        List.of("val1", "val2", "val3"));
+
+    // The default values are returned when the property is missing or has no 
values
+    pinotConfiguration.setProperty("config.empty", " , ");
+    
Assert.assertEquals(pinotConfiguration.getCommaSeparatedList("config.empty", 
List.of("default")),
+        List.of("default"));
+    
Assert.assertEquals(pinotConfiguration.getCommaSeparatedList("config.missing", 
List.of("default")),
+        List.of("default"));
+  }
+
   @Test
   public void assertPropertyPriorities()
       throws IOException {


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to