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

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


The following commit(s) were added to refs/heads/master by this push:
     new 280642a  [CALCITE-2859] Centralize Calcite system properties
280642a is described below

commit 280642a02a4bcfd1fb9cbe8c5ab672d3619860e7
Author: Stamatis Zampetakis <zabe...@gmail.com>
AuthorDate: Fri Feb 22 11:30:45 2019 +0100

    [CALCITE-2859] Centralize Calcite system properties
    
    1. Move all system properties with "calcite" namespace under a common class.
    2. Improve the documentation (javadoc) of existing properties.
    3. Add review comments regarding a few properties.
    4. Deprecate SaffronProperties and move them all under 
CalciteSystemProperty.
---
 .../cassandra/CassandraToEnumerableConverter.java  |   4 +-
 .../apache/calcite/test/CassandraAdapterTest.java  |   5 +-
 .../adapter/enumerable/EnumerableAggregate.java    |   4 +-
 .../enumerable/EnumerableInterpretable.java        |   6 +-
 .../adapter/enumerable/EnumerableWindow.java       |   4 +-
 .../adapter/jdbc/JdbcToEnumerableConverter.java    |   4 +-
 .../calcite/config/CalciteSystemProperty.java      | 323 +++++++++++++++++++++
 .../apache/calcite/interpreter/Interpreter.java    |   4 +-
 .../calcite/interpreter/JaninoRexCompiler.java     |   6 +-
 .../org/apache/calcite/materialize/Lattice.java    |   4 +-
 .../apache/calcite/plan/RelOptMaterialization.java |   6 +-
 .../calcite/plan/RelOptMaterializations.java       |   4 +-
 .../apache/calcite/plan/SubstitutionVisitor.java   |   4 +-
 .../calcite/plan/volcano/VolcanoPlanner.java       |  17 +-
 .../calcite/prepare/CalciteMaterializer.java       |   3 +-
 .../apache/calcite/prepare/CalcitePrepareImpl.java |   9 +-
 .../org/apache/calcite/profile/ProfilerImpl.java   |  10 +-
 .../java/org/apache/calcite/rel/core/Filter.java   |   4 +-
 .../calcite/rel/logical/LogicalCorrelate.java      |   4 +-
 .../rel/metadata/JaninoRelMetadataProvider.java    |   7 +-
 .../calcite/rel/rules/AggregateStarTableRule.java  |   8 +-
 .../rel/rules/MultiJoinOptimizeBushyRule.java      |   4 +-
 .../org/apache/calcite/rex/RexExecutorImpl.java    |   4 +-
 .../java/org/apache/calcite/rex/RexLiteral.java    |   4 +-
 .../apache/calcite/runtime/CalciteException.java   |   4 +-
 .../java/org/apache/calcite/sql/SqlCollation.java  |   4 +-
 .../calcite/sql/fun/SqlCountAggFunction.java       |   3 +-
 .../apache/calcite/sql/parser/SqlParserUtil.java   |   6 +-
 .../apache/calcite/sql/validate/SqlValidator.java  |   4 -
 .../sql/validate/SqlValidatorException.java        |   4 +-
 .../java/org/apache/calcite/tools/Programs.java    |   4 +-
 .../apache/calcite/util/PartiallyOrderedSet.java   |  10 +-
 .../org/apache/calcite/util/SaffronProperties.java |   4 +
 .../main/java/org/apache/calcite/util/Util.java    |  29 +-
 .../apache/calcite/util/javac/JaninoCompiler.java  |   4 +-
 .../calcite/jdbc/CalciteRemoteDriverTest.java      |   6 +-
 .../calcite/plan/volcano/TraitPropagationTest.java |   4 +-
 .../calcite/sql/test/SqlOperatorBaseTest.java      |   5 +-
 .../org/apache/calcite/test/CalciteAssert.java     |  41 +--
 .../java/org/apache/calcite/test/FoodmartTest.java |   7 +-
 .../java/org/apache/calcite/test/JdbcTest.java     |   7 +-
 .../calcite/test/MultiJdbcSchemaJoinTest.java      |   4 +-
 .../org/apache/calcite/test/RelMetadataTest.java   |   6 +-
 .../org/apache/calcite/test/RexProgramTest.java    |   3 +-
 .../org/apache/calcite/tools/FrameworksTest.java   |   4 +-
 .../java/org/apache/calcite/tools/PlannerTest.java |   3 +-
 .../calcite/util/PartiallyOrderedSetTest.java      |   8 +-
 .../calcite/adapter/druid/DruidConnectionImpl.java |  12 +-
 .../org/apache/calcite/test/DruidAdapterIT.java    |  13 +-
 .../org/apache/calcite/test/DruidAdapterIT2.java   |  13 +-
 .../mongodb/MongoToEnumerableConverter.java        |   4 +-
 .../org/apache/calcite/test/MongoAssertions.java   |   6 +-
 .../apache/calcite/adapter/tpcds/TpcdsTest.java    |   8 +-
 .../org/apache/calcite/adapter/tpch/TpchTest.java  |   7 +-
 .../materialize/TpcdsLatticeSuggesterTest.java     |   4 +-
 .../adapter/spark/JdbcToSparkConverter.java        |   4 +-
 .../calcite/adapter/spark/SparkHandlerImpl.java    |   4 +-
 .../calcite/adapter/splunk/SplunkTableScan.java    |   4 +-
 .../org/apache/calcite/test/SplunkAdapterTest.java |  10 +-
 59 files changed, 480 insertions(+), 235 deletions(-)

diff --git 
a/cassandra/src/main/java/org/apache/calcite/adapter/cassandra/CassandraToEnumerableConverter.java
 
b/cassandra/src/main/java/org/apache/calcite/adapter/cassandra/CassandraToEnumerableConverter.java
index a0c0be9..02b3b5a 100644
--- 
a/cassandra/src/main/java/org/apache/calcite/adapter/cassandra/CassandraToEnumerableConverter.java
+++ 
b/cassandra/src/main/java/org/apache/calcite/adapter/cassandra/CassandraToEnumerableConverter.java
@@ -21,6 +21,7 @@ import 
org.apache.calcite.adapter.enumerable.EnumerableRelImplementor;
 import org.apache.calcite.adapter.enumerable.JavaRowFormat;
 import org.apache.calcite.adapter.enumerable.PhysType;
 import org.apache.calcite.adapter.enumerable.PhysTypeImpl;
+import org.apache.calcite.config.CalciteSystemProperty;
 import org.apache.calcite.linq4j.tree.BlockBuilder;
 import org.apache.calcite.linq4j.tree.Expression;
 import org.apache.calcite.linq4j.tree.Expressions;
@@ -30,7 +31,6 @@ import org.apache.calcite.plan.RelOptCluster;
 import org.apache.calcite.plan.RelOptCost;
 import org.apache.calcite.plan.RelOptPlanner;
 import org.apache.calcite.plan.RelTraitSet;
-import org.apache.calcite.prepare.CalcitePrepareImpl;
 import org.apache.calcite.rel.RelNode;
 import org.apache.calcite.rel.convert.ConverterImpl;
 import org.apache.calcite.rel.metadata.RelMetadataQuery;
@@ -122,7 +122,7 @@ public class CassandraToEnumerableConverter
             Expressions.call(table,
                 CassandraMethod.CASSANDRA_QUERYABLE_QUERY.method, fields,
                 selectFields, predicates, order, offset, fetch));
-    if (CalcitePrepareImpl.DEBUG) {
+    if (CalciteSystemProperty.DEBUG.value()) {
       System.out.println("Cassandra: " + predicates);
     }
     Hook.QUERY_PLAN.run(predicates);
diff --git 
a/cassandra/src/test/java/org/apache/calcite/test/CassandraAdapterTest.java 
b/cassandra/src/test/java/org/apache/calcite/test/CassandraAdapterTest.java
index dd1a67e..4574586 100644
--- a/cassandra/src/test/java/org/apache/calcite/test/CassandraAdapterTest.java
+++ b/cassandra/src/test/java/org/apache/calcite/test/CassandraAdapterTest.java
@@ -16,10 +16,10 @@
  */
 package org.apache.calcite.test;
 
+import org.apache.calcite.config.CalciteSystemProperty;
 import org.apache.calcite.util.Bug;
 import org.apache.calcite.util.Sources;
 import org.apache.calcite.util.TestUtil;
-import org.apache.calcite.util.Util;
 
 import org.apache.cassandra.config.DatabaseDescriptor;
 
@@ -82,8 +82,7 @@ public class CassandraAdapterTest {
    *         {@code false} otherwise
    */
   private static boolean enabled() {
-    final boolean enabled =
-        Util.getBooleanProperty("calcite.test.cassandra", true);
+    final boolean enabled = CalciteSystemProperty.TEST_CASSANDRA.value();
     Bug.upgrade("remove JDK version check once current adapter supports 
Cassandra 4.x");
     final boolean compatibleJdk = TestUtil.getJavaMajorVersion() != 11
                                       && TestUtil.getJavaMajorVersion() != 12;
diff --git 
a/core/src/main/java/org/apache/calcite/adapter/enumerable/EnumerableAggregate.java
 
b/core/src/main/java/org/apache/calcite/adapter/enumerable/EnumerableAggregate.java
index 1caf4e3..3130bd0 100644
--- 
a/core/src/main/java/org/apache/calcite/adapter/enumerable/EnumerableAggregate.java
+++ 
b/core/src/main/java/org/apache/calcite/adapter/enumerable/EnumerableAggregate.java
@@ -19,6 +19,7 @@ package org.apache.calcite.adapter.enumerable;
 import org.apache.calcite.adapter.enumerable.impl.AggAddContextImpl;
 import org.apache.calcite.adapter.enumerable.impl.AggResultContextImpl;
 import org.apache.calcite.adapter.java.JavaTypeFactory;
+import org.apache.calcite.config.CalciteSystemProperty;
 import org.apache.calcite.jdbc.JavaTypeFactoryImpl;
 import org.apache.calcite.linq4j.Ord;
 import org.apache.calcite.linq4j.function.Function0;
@@ -31,7 +32,6 @@ import org.apache.calcite.linq4j.tree.ParameterExpression;
 import org.apache.calcite.linq4j.tree.Types;
 import org.apache.calcite.plan.RelOptCluster;
 import org.apache.calcite.plan.RelTraitSet;
-import org.apache.calcite.prepare.CalcitePrepareImpl;
 import org.apache.calcite.rel.InvalidRelException;
 import org.apache.calcite.rel.RelCollations;
 import org.apache.calcite.rel.RelNode;
@@ -212,7 +212,7 @@ public class EnumerableAggregate extends Aggregate 
implements EnumerableRel {
       final List<Expression> decls = new ArrayList<>(state.size());
       for (int i = 0; i < state.size(); i++) {
         String aggName = "a" + agg.aggIdx;
-        if (CalcitePrepareImpl.DEBUG) {
+        if (CalciteSystemProperty.DEBUG.value()) {
           aggName = Util.toJavaId(agg.call.getAggregation().getName(), 0)
               .substring("ID$0$".length()) + aggName;
         }
diff --git 
a/core/src/main/java/org/apache/calcite/adapter/enumerable/EnumerableInterpretable.java
 
b/core/src/main/java/org/apache/calcite/adapter/enumerable/EnumerableInterpretable.java
index 17447bc..beafd4c 100644
--- 
a/core/src/main/java/org/apache/calcite/adapter/enumerable/EnumerableInterpretable.java
+++ 
b/core/src/main/java/org/apache/calcite/adapter/enumerable/EnumerableInterpretable.java
@@ -18,6 +18,7 @@ package org.apache.calcite.adapter.enumerable;
 
 import org.apache.calcite.DataContext;
 import org.apache.calcite.avatica.Helper;
+import org.apache.calcite.config.CalciteSystemProperty;
 import org.apache.calcite.interpreter.Compiler;
 import org.apache.calcite.interpreter.InterpretableConvention;
 import org.apache.calcite.interpreter.InterpretableRel;
@@ -33,7 +34,6 @@ import org.apache.calcite.linq4j.tree.Expressions;
 import org.apache.calcite.plan.ConventionTraitDef;
 import org.apache.calcite.plan.RelOptCluster;
 import org.apache.calcite.plan.RelTraitSet;
-import org.apache.calcite.prepare.CalcitePrepareImpl;
 import org.apache.calcite.rel.RelNode;
 import org.apache.calcite.rel.convert.ConverterImpl;
 import org.apache.calcite.runtime.ArrayBindable;
@@ -92,7 +92,7 @@ public class EnumerableInterpretable extends ConverterImpl
     final ClassDeclaration expr = relImplementor.implementRoot(rel, prefer);
     String s = Expressions.toString(expr.memberDeclarations, "\n", false);
 
-    if (CalcitePrepareImpl.DEBUG) {
+    if (CalciteSystemProperty.DEBUG.value()) {
       Util.debugCode(System.out, s);
     }
 
@@ -133,7 +133,7 @@ public class EnumerableInterpretable extends ConverterImpl
             ? new Class[] {Bindable.class, Typed.class}
             : new Class[] {ArrayBindable.class});
     cbe.setParentClassLoader(EnumerableInterpretable.class.getClassLoader());
-    if (CalcitePrepareImpl.DEBUG) {
+    if (CalciteSystemProperty.DEBUG.value()) {
       // Add line numbers to the generated janino class
       cbe.setDebuggingInformation(true, true, true);
     }
diff --git 
a/core/src/main/java/org/apache/calcite/adapter/enumerable/EnumerableWindow.java
 
b/core/src/main/java/org/apache/calcite/adapter/enumerable/EnumerableWindow.java
index d013c20..4805793 100644
--- 
a/core/src/main/java/org/apache/calcite/adapter/enumerable/EnumerableWindow.java
+++ 
b/core/src/main/java/org/apache/calcite/adapter/enumerable/EnumerableWindow.java
@@ -20,6 +20,7 @@ import 
org.apache.calcite.adapter.enumerable.impl.WinAggAddContextImpl;
 import org.apache.calcite.adapter.enumerable.impl.WinAggResetContextImpl;
 import org.apache.calcite.adapter.enumerable.impl.WinAggResultContextImpl;
 import org.apache.calcite.adapter.java.JavaTypeFactory;
+import org.apache.calcite.config.CalciteSystemProperty;
 import org.apache.calcite.linq4j.tree.BinaryExpression;
 import org.apache.calcite.linq4j.tree.BlockBuilder;
 import org.apache.calcite.linq4j.tree.BlockStatement;
@@ -34,7 +35,6 @@ import org.apache.calcite.plan.RelOptCluster;
 import org.apache.calcite.plan.RelOptCost;
 import org.apache.calcite.plan.RelOptPlanner;
 import org.apache.calcite.plan.RelTraitSet;
-import org.apache.calcite.prepare.CalcitePrepareImpl;
 import org.apache.calcite.rel.RelFieldCollation;
 import org.apache.calcite.rel.RelNode;
 import org.apache.calcite.rel.core.AggregateCall;
@@ -798,7 +798,7 @@ public class EnumerableWindow extends Window implements 
EnumerableRel {
             }
           };
       String aggName = "a" + agg.aggIdx;
-      if (CalcitePrepareImpl.DEBUG) {
+      if (CalciteSystemProperty.DEBUG.value()) {
         aggName = Util.toJavaId(agg.call.getAggregation().getName(), 0)
             .substring("ID$0$".length()) + aggName;
       }
diff --git 
a/core/src/main/java/org/apache/calcite/adapter/jdbc/JdbcToEnumerableConverter.java
 
b/core/src/main/java/org/apache/calcite/adapter/jdbc/JdbcToEnumerableConverter.java
index f24f6f3..7164466 100644
--- 
a/core/src/main/java/org/apache/calcite/adapter/jdbc/JdbcToEnumerableConverter.java
+++ 
b/core/src/main/java/org/apache/calcite/adapter/jdbc/JdbcToEnumerableConverter.java
@@ -23,6 +23,7 @@ import org.apache.calcite.adapter.enumerable.JavaRowFormat;
 import org.apache.calcite.adapter.enumerable.PhysType;
 import org.apache.calcite.adapter.enumerable.PhysTypeImpl;
 import org.apache.calcite.adapter.java.JavaTypeFactory;
+import org.apache.calcite.config.CalciteSystemProperty;
 import org.apache.calcite.linq4j.tree.BlockBuilder;
 import org.apache.calcite.linq4j.tree.ConstantExpression;
 import org.apache.calcite.linq4j.tree.Expression;
@@ -35,7 +36,6 @@ import org.apache.calcite.plan.RelOptCluster;
 import org.apache.calcite.plan.RelOptCost;
 import org.apache.calcite.plan.RelOptPlanner;
 import org.apache.calcite.plan.RelTraitSet;
-import org.apache.calcite.prepare.CalcitePrepareImpl;
 import org.apache.calcite.rel.RelNode;
 import org.apache.calcite.rel.convert.ConverterImpl;
 import org.apache.calcite.rel.metadata.RelMetadataQuery;
@@ -94,7 +94,7 @@ public class JdbcToEnumerableConverter
         (JdbcConvention) child.getConvention();
     SqlString sqlString = generateSql(jdbcConvention.dialect);
     String sql = sqlString.getSql();
-    if (CalcitePrepareImpl.DEBUG) {
+    if (CalciteSystemProperty.DEBUG.value()) {
       System.out.println("[" + sql + "]");
     }
     Hook.QUERY_PLAN.run(sql);
diff --git 
a/core/src/main/java/org/apache/calcite/config/CalciteSystemProperty.java 
b/core/src/main/java/org/apache/calcite/config/CalciteSystemProperty.java
new file mode 100644
index 0000000..bdda3e6
--- /dev/null
+++ b/core/src/main/java/org/apache/calcite/config/CalciteSystemProperty.java
@@ -0,0 +1,323 @@
+/*
+ * 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.calcite.config;
+
+import com.google.common.collect.ImmutableSet;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.security.AccessControlException;
+import java.util.Locale;
+import java.util.Properties;
+import java.util.Set;
+import java.util.function.Function;
+import java.util.stream.Stream;
+
+/**
+ * A Calcite specific system property that is used to configure various 
aspects of the framework.
+ *
+ * <p>Calcite system properties must always be in the "calcite" root 
namespace.</p>
+ *
+ * @param <T> the type of the property value
+ */
+public final class CalciteSystemProperty<T> {
+  /**
+   * Holds all system properties related with the Calcite.
+   *
+   * <p>Deprecated <code>"saffron.properties"</code> (in namespaces"saffron" 
and "net.sf.saffron")
+   * are also kept here but under "calcite" namespace.</p>
+   */
+  private static final Properties PROPERTIES = loadProperties();
+  /**
+   * Whether to run Calcite in debug mode.
+   *
+   * <p>When debug mode is activated significantly more information is 
gathered and printed to
+   * STDOUT. It is most commonly used to print and identify problems in 
generated java code. Debug
+   * mode is also used to perform more verifications at runtime, which are not 
performed during
+   * normal execution.</p>
+   */
+  public static final CalciteSystemProperty<Boolean> DEBUG =
+      booleanProperty("calcite.debug", false);
+  /**
+   * Whether to exploit join commutative property.
+   */
+  // TODO review zabetak:
+  // Does the property control join commutativity or rather join 
associativity? The property is
+  // associated with {@link org.apache.calcite.rel.rules.JoinAssociateRule} 
and not with
+  // {@link org.apache.calcite.rel.rules.JoinCommuteRule}.
+  public static final CalciteSystemProperty<Boolean> COMMUTE =
+      booleanProperty("calcite.enable.join.commute", false);
+  /**
+   *  Whether to follow the SQL standard strictly.
+   */
+  public static final CalciteSystemProperty<Boolean> STRICT =
+      booleanProperty("calcite.strict.sql", false);
+  /**
+   * Whether to include a GraphViz representation when dumping the state of 
the Volcano planner.
+   */
+  public static final CalciteSystemProperty<Boolean> DUMP_GRAPHVIZ =
+      booleanProperty("calcite.volcano.dump.graphviz", true);
+  /**
+   * Whether to include <code>RelSet</code> information when dumping the state 
of the Volcano
+   * planner.
+   */
+  public static final CalciteSystemProperty<Boolean> DUMP_SETS =
+      booleanProperty("calcite.volcano.dump.sets", true);
+  /**
+   * Whether to run integration tests.
+   */
+  // TODO review zabetak:
+  // The property is used in only one place and it is associated with mongodb. 
Should we drop this
+  // property and just use TEST_MONGODB?
+  public static final CalciteSystemProperty<Boolean> INTEGRATION_TEST =
+      booleanProperty("calcite.integrationTest", false);
+
+  /**
+   * Which database to use for tests that require a JDBC data source.
+   *
+   * The property can take one of the following values:
+   * <ul>
+   *   <li>HSQLDB(default)</li>
+   *   <li>H2</li>
+   *   <li>MYSQL</li>
+   *   <li>ORACLE</li>
+   *   <li>POSTGRESQL</li>
+   * </ul>
+   * If the specified value is not included in the previous list the default 
is used.
+   *
+   * <p>We recommend that casual users use hsqldb, and frequent Calcite 
developers use MySQL.
+   * The test suite runs faster against the MySQL database (mainly because of 
the 0.1s versus 6s
+   * startup time). You have to populate MySQL manually with the foodmart data 
set, otherwise there
+   * will be test failures.</p>
+   * */
+  public static final CalciteSystemProperty<String> TEST_DB =
+      stringProperty("calcite.test.db", "HSQLDB",
+          ImmutableSet.of(
+              "HSQLDB",
+              "H2",
+              "MYSQL",
+              "ORACLE",
+              "POSTGRESQL"));
+
+  /**
+   * Path to the dataset file that should used for integration tests.
+   *
+   * If a path is not set, then one of the following values will be used:
+   * <ul>
+   *   <li>../calcite-test-dataset</li>
+   *   <li>../../calcite-test-dataset</li>
+   *   <li>.</li>
+   * </ul>
+   * The first valid path that exists in the filesystem will be chosen.
+   */
+  public static final CalciteSystemProperty<String> TEST_DATASET_PATH =
+      new CalciteSystemProperty<>("calcite.test.dataset", v -> {
+        if (v != null) {
+          return v;
+        }
+        final String[] dirs = {
+            "../calcite-test-dataset",
+            "../../calcite-test-dataset"
+        };
+        for (String s : dirs) {
+          if (new File(s).exists() && new File(s, "vm").exists()) {
+            return s;
+          }
+        }
+        return ".";
+      });
+  /**
+   * Whether to run slow tests.
+   */
+  public static final CalciteSystemProperty<Boolean> TEST_SLOW =
+      booleanProperty("calcite.test.slow", false);
+  /**
+   * Whether to run MongoDB tests.
+   */
+  public static final CalciteSystemProperty<Boolean> TEST_MONGODB =
+      booleanProperty("calcite.test.mongodb", true);
+  /**
+   * Whether to run Splunk tests.
+   *
+   * Disabled by default, because we do not expect Splunk to be installed and 
populated data set.
+   */
+  public static final CalciteSystemProperty<Boolean> TEST_SPLUNK =
+      booleanProperty("calcite.test.splunk", false);
+  /**
+   * Whether to run Druid tests.
+   */
+  public static final CalciteSystemProperty<Boolean> TEST_DRUID =
+      booleanProperty("calcite.test.druid", true);
+  /**
+   * Whether to run Cassandra tests.
+   */
+  public static final CalciteSystemProperty<Boolean> TEST_CASSANDRA =
+      booleanProperty("calcite.test.cassandra", true);
+
+  /**
+   * A list of ids designating the queries
+   * (from query.json in new.hydromatic:foodmart-queries:0.4.1) that should be 
run as part of
+   * FoodmartTest.
+   *
+   */
+  // TODO review zabetak:
+  // The name of the property is not appropriate. A better alternative would be
+  // calcite.test.foodmart.queries.ids. Moreover, I am not in favor of using 
system properties for
+  // parameterized tests.
+  public static final CalciteSystemProperty<String> TEST_FOODMART_QUERY_IDS =
+      new CalciteSystemProperty<>("calcite.ids", Function.identity());
+
+  /**
+   * Whether the optimizer will consider adding converters of infinite cost in
+   * order to convert a relational expression from one calling convention to
+   * another.
+   */
+  public static final CalciteSystemProperty<Boolean> 
ALLOW_INFINITE_COST_CONVERTERS =
+      booleanProperty("calcite.opt.allowInfiniteCostConverters", true);
+
+  /**
+   * Which is the name of the default character set.
+   *
+   * <p>It is used by {@link org.apache.calcite.sql.validate.SqlValidator}.</p>
+   */
+  // TODO review zabetak:
+  // What happens if a wrong value is specified?
+  public static final CalciteSystemProperty<String> DEFAULT_CHARSET =
+      stringProperty("calcite.default.charset", "ISO-8859-1");
+
+  /**
+   * Which is the name of the default national character set.
+   *
+   * <p>It is used with the N'string' construct in
+   * {@link org.apache.calcite.sql.SqlLiteral#SqlLiteral}
+   * and may be different from the {@link #DEFAULT_CHARSET}.
+   */
+  // TODO review zabetak:
+  // What happens if a wrong value is specified?
+  public static final CalciteSystemProperty<String> DEFAULT_NATIONAL_CHARSET =
+      stringProperty("calcite.default.nationalcharset", "ISO-8859-1");
+
+  /**
+   * Which is the name of the default collation.
+   *
+   * <p>It is used in {@link org.apache.calcite.sql.SqlCollation} and
+   * {@link org.apache.calcite.sql.SqlLiteral#SqlLiteral}</p>
+   */
+  // TODO review zabetak:
+  // What happens if a wrong value is specified?
+  public static final CalciteSystemProperty<String> DEFAULT_COLLATION =
+      stringProperty("calcite.default.collation.name", "ISO-8859-1$en_US");
+
+  /**
+   * Which is the strength of the default collation.
+   *
+   * <p>It is used in {@link org.apache.calcite.sql.SqlCollation} and
+   * {@link org.apache.calcite.sql.SqlLiteral#SqlLiteral}.</p>
+   */
+  // TODO review zabetak:
+  // What are the allowed values? What happens if a wrong value is specified?
+  public static final CalciteSystemProperty<String> DEFAULT_COLLATION_STRENGTH 
=
+      stringProperty("calcite.default.collation.strength", "primary");
+
+  /**
+   * Which is the maximum size of the cache of metadata handlers.
+   *
+   * <p>A typical value is the number of queries being concurrently prepared 
multiplied by the
+   * number of types of metadata.</p>
+   *
+   * <p>If the value is less than 0, there is no limit.</p>
+   */
+  public static final CalciteSystemProperty<Integer> 
METADATA_HANDLER_CACHE_MAXIMUM_SIZE =
+      intProperty("calcite.metadata.handler.cache.maximum.size", 1000);
+
+  private static CalciteSystemProperty<Boolean> booleanProperty(String key, 
boolean defaultValue) {
+    return new CalciteSystemProperty<>(key,
+        v -> v == null ? defaultValue : Boolean.parseBoolean(v));
+  }
+
+  private static CalciteSystemProperty<Integer> intProperty(String key, int 
defaultValue) {
+    return new CalciteSystemProperty<>(key,
+        v -> v == null ? defaultValue : Integer.parseInt(v));
+  }
+
+  private static CalciteSystemProperty<String> stringProperty(String key, 
String defaultValue) {
+    return new CalciteSystemProperty<>(key, v -> v == null ? defaultValue : v);
+  }
+
+  private static CalciteSystemProperty<String> stringProperty(
+      String key,
+      String defaultValue,
+      Set<String> allowedValues) {
+    return new CalciteSystemProperty<>(key, v -> {
+      if (v == null) {
+        return defaultValue;
+      }
+      String normalizedValue = v.toUpperCase(Locale.ROOT);
+      return allowedValues.contains(normalizedValue) ? normalizedValue : 
defaultValue;
+    });
+  }
+
+  private static Properties loadProperties() {
+    Properties saffronProperties = new Properties();
+    // Read properties from the file "saffron.properties", if it exists in 
classpath
+    try (InputStream stream = CalciteSystemProperty.class.getClassLoader()
+        .getResourceAsStream("saffron.properties")) {
+      if (stream != null) {
+        saffronProperties.load(stream);
+      }
+    } catch (IOException e) {
+      throw new RuntimeException("while reading from saffron.properties file", 
e);
+    } catch (AccessControlException e) {
+      // we're in a sandbox
+    }
+
+    Properties allProperties = new Properties();
+    // Merge system and saffron properties mapping deprecated saffron 
namespaces to calcite
+    Stream.concat(
+        saffronProperties.entrySet().stream(),
+        System.getProperties().entrySet().stream()).
+        forEach(prop -> {
+            String deprecatedKey = (String) prop.getKey();
+            String newKey = deprecatedKey
+                .replace("net.sf.saffron.", "calcite.")
+                .replace("saffron.", "calcite.");
+            if (newKey.startsWith("calcite.")) {
+              allProperties.setProperty(newKey, (String) prop.getValue());
+            }
+          });
+    return allProperties;
+  }
+
+  private final T value;
+
+  private CalciteSystemProperty(String key, Function<String, T> valueParser) {
+    this.value = valueParser.apply(PROPERTIES.getProperty(key));
+  }
+
+  /**
+   * Returns the value of this property.
+   *
+   * @return the value of this property or <code>null</code> if a default 
value has not been
+   * defined for this property.
+   */
+  public T value() {
+    return value;
+  }
+}
+
+// End CalciteSystemProperty.java
diff --git a/core/src/main/java/org/apache/calcite/interpreter/Interpreter.java 
b/core/src/main/java/org/apache/calcite/interpreter/Interpreter.java
index 0a85351..f11c351 100644
--- a/core/src/main/java/org/apache/calcite/interpreter/Interpreter.java
+++ b/core/src/main/java/org/apache/calcite/interpreter/Interpreter.java
@@ -17,6 +17,7 @@
 package org.apache.calcite.interpreter;
 
 import org.apache.calcite.DataContext;
+import org.apache.calcite.config.CalciteSystemProperty;
 import org.apache.calcite.linq4j.AbstractEnumerable;
 import org.apache.calcite.linq4j.Enumerable;
 import org.apache.calcite.linq4j.Enumerator;
@@ -27,7 +28,6 @@ import org.apache.calcite.plan.RelOptCluster;
 import org.apache.calcite.plan.hep.HepPlanner;
 import org.apache.calcite.plan.hep.HepProgram;
 import org.apache.calcite.plan.hep.HepProgramBuilder;
-import org.apache.calcite.prepare.CalcitePrepareImpl;
 import org.apache.calcite.rel.RelNode;
 import org.apache.calcite.rel.RelVisitor;
 import org.apache.calcite.rel.rules.CalcSplitRule;
@@ -417,7 +417,7 @@ public class Interpreter extends 
AbstractEnumerable<Object[]>
         if (rel == null) {
           break;
         }
-        if (CalcitePrepareImpl.DEBUG) {
+        if (CalciteSystemProperty.DEBUG.value()) {
           System.out.println("Interpreter: rewrite " + p + " to " + rel);
         }
         p = rel;
diff --git 
a/core/src/main/java/org/apache/calcite/interpreter/JaninoRexCompiler.java 
b/core/src/main/java/org/apache/calcite/interpreter/JaninoRexCompiler.java
index 5702667..c573f6b 100644
--- a/core/src/main/java/org/apache/calcite/interpreter/JaninoRexCompiler.java
+++ b/core/src/main/java/org/apache/calcite/interpreter/JaninoRexCompiler.java
@@ -19,6 +19,7 @@ package org.apache.calcite.interpreter;
 import org.apache.calcite.adapter.enumerable.JavaRowFormat;
 import org.apache.calcite.adapter.enumerable.PhysTypeImpl;
 import org.apache.calcite.adapter.enumerable.RexToLixTranslator;
+import org.apache.calcite.config.CalciteSystemProperty;
 import org.apache.calcite.jdbc.JavaTypeFactoryImpl;
 import org.apache.calcite.linq4j.function.Function1;
 import org.apache.calcite.linq4j.tree.BlockBuilder;
@@ -28,7 +29,6 @@ import org.apache.calcite.linq4j.tree.Expression;
 import org.apache.calcite.linq4j.tree.Expressions;
 import org.apache.calcite.linq4j.tree.MemberDeclaration;
 import org.apache.calcite.linq4j.tree.ParameterExpression;
-import org.apache.calcite.prepare.CalcitePrepareImpl;
 import org.apache.calcite.rel.type.RelDataType;
 import org.apache.calcite.rex.RexBuilder;
 import org.apache.calcite.rex.RexNode;
@@ -146,7 +146,7 @@ public class JaninoRexCompiler implements 
Interpreter.ScalarCompiler {
         Expressions.classDecl(Modifier.PUBLIC, "Buzz", null,
             ImmutableList.of(Scalar.class), declarations);
     String s = Expressions.toString(declarations, "\n", false);
-    if (CalcitePrepareImpl.DEBUG) {
+    if (CalciteSystemProperty.DEBUG.value()) {
       Util.debugCode(System.out, s);
     }
     try {
@@ -169,7 +169,7 @@ public class JaninoRexCompiler implements 
Interpreter.ScalarCompiler {
     cbe.setClassName(expr.name);
     cbe.setImplementedInterfaces(new Class[]{Scalar.class});
     cbe.setParentClassLoader(JaninoRexCompiler.class.getClassLoader());
-    if (CalcitePrepareImpl.DEBUG) {
+    if (CalciteSystemProperty.DEBUG.value()) {
       // Add line numbers to the generated janino class
       cbe.setDebuggingInformation(true, true, true);
     }
diff --git a/core/src/main/java/org/apache/calcite/materialize/Lattice.java 
b/core/src/main/java/org/apache/calcite/materialize/Lattice.java
index a4724eb..b12bcf7 100644
--- a/core/src/main/java/org/apache/calcite/materialize/Lattice.java
+++ b/core/src/main/java/org/apache/calcite/materialize/Lattice.java
@@ -17,12 +17,12 @@
 package org.apache.calcite.materialize;
 
 import org.apache.calcite.avatica.AvaticaUtils;
+import org.apache.calcite.config.CalciteSystemProperty;
 import org.apache.calcite.jdbc.CalcitePrepare;
 import org.apache.calcite.jdbc.CalciteSchema;
 import org.apache.calcite.linq4j.Ord;
 import org.apache.calcite.linq4j.tree.Primitive;
 import org.apache.calcite.plan.RelOptUtil;
-import org.apache.calcite.prepare.CalcitePrepareImpl;
 import org.apache.calcite.rel.RelNode;
 import org.apache.calcite.rel.core.AggregateCall;
 import org.apache.calcite.rel.core.JoinRelType;
@@ -339,7 +339,7 @@ public class Lattice {
         }
       }
     }
-    if (CalcitePrepareImpl.DEBUG) {
+    if (CalciteSystemProperty.DEBUG.value()) {
       System.out.println("Lattice SQL:\n"
           + buf);
     }
diff --git 
a/core/src/main/java/org/apache/calcite/plan/RelOptMaterialization.java 
b/core/src/main/java/org/apache/calcite/plan/RelOptMaterialization.java
index fea1cba..673148f 100644
--- a/core/src/main/java/org/apache/calcite/plan/RelOptMaterialization.java
+++ b/core/src/main/java/org/apache/calcite/plan/RelOptMaterialization.java
@@ -16,7 +16,7 @@
  */
 package org.apache.calcite.plan;
 
-import org.apache.calcite.prepare.CalcitePrepareImpl;
+import org.apache.calcite.config.CalciteSystemProperty;
 import org.apache.calcite.rel.RelNode;
 import org.apache.calcite.rel.RelShuttleImpl;
 import org.apache.calcite.rel.core.Filter;
@@ -279,7 +279,7 @@ public class RelOptMaterialization {
             ProjectMergeRule.INSTANCE),
         false,
         DefaultRelMetadataProvider.INSTANCE);
-    if (CalcitePrepareImpl.DEBUG) {
+    if (CalciteSystemProperty.DEBUG.value()) {
       System.out.println(
           RelOptUtil.dumpPlan("before", rel, SqlExplainFormat.TEXT,
               SqlExplainLevel.DIGEST_ATTRIBUTES));
@@ -287,7 +287,7 @@ public class RelOptMaterialization {
     final RelNode rel2 = program.run(null, rel, null,
         ImmutableList.of(),
         ImmutableList.of());
-    if (CalcitePrepareImpl.DEBUG) {
+    if (CalciteSystemProperty.DEBUG.value()) {
       System.out.println(
           RelOptUtil.dumpPlan("after", rel2, SqlExplainFormat.TEXT,
               SqlExplainLevel.DIGEST_ATTRIBUTES));
diff --git 
a/core/src/main/java/org/apache/calcite/plan/RelOptMaterializations.java 
b/core/src/main/java/org/apache/calcite/plan/RelOptMaterializations.java
index c4553fb..e89b31f 100644
--- a/core/src/main/java/org/apache/calcite/plan/RelOptMaterializations.java
+++ b/core/src/main/java/org/apache/calcite/plan/RelOptMaterializations.java
@@ -16,10 +16,10 @@
  */
 package org.apache.calcite.plan;
 
+import org.apache.calcite.config.CalciteSystemProperty;
 import org.apache.calcite.plan.hep.HepPlanner;
 import org.apache.calcite.plan.hep.HepProgram;
 import org.apache.calcite.plan.hep.HepProgramBuilder;
-import org.apache.calcite.prepare.CalcitePrepareImpl;
 import org.apache.calcite.rel.RelNode;
 import org.apache.calcite.rel.rules.FilterProjectTransposeRule;
 import org.apache.calcite.rel.rules.ProjectMergeRule;
@@ -109,7 +109,7 @@ public abstract class RelOptMaterializations {
       if (queryTableNames.contains(lattice.rootTable().getQualifiedName())) {
         RelNode rel2 = lattice.rewrite(leafJoinRoot.get());
         if (rel2 != null) {
-          if (CalcitePrepareImpl.DEBUG) {
+          if (CalciteSystemProperty.DEBUG.value()) {
             System.out.println("use lattice:\n"
                 + RelOptUtil.toString(rel2));
           }
diff --git 
a/core/src/main/java/org/apache/calcite/plan/SubstitutionVisitor.java 
b/core/src/main/java/org/apache/calcite/plan/SubstitutionVisitor.java
index b30763c..277a911 100644
--- a/core/src/main/java/org/apache/calcite/plan/SubstitutionVisitor.java
+++ b/core/src/main/java/org/apache/calcite/plan/SubstitutionVisitor.java
@@ -16,8 +16,8 @@
  */
 package org.apache.calcite.plan;
 
+import org.apache.calcite.config.CalciteSystemProperty;
 import org.apache.calcite.linq4j.Ord;
-import org.apache.calcite.prepare.CalcitePrepareImpl;
 import org.apache.calcite.rel.RelNode;
 import org.apache.calcite.rel.core.Aggregate;
 import org.apache.calcite.rel.core.AggregateCall;
@@ -112,7 +112,7 @@ import static org.apache.calcite.rex.RexUtil.removeAll;
  * {@link org.apache.calcite.rel.logical.LogicalAggregate}.</p>
  */
 public class SubstitutionVisitor {
-  private static final boolean DEBUG = CalcitePrepareImpl.DEBUG;
+  private static final boolean DEBUG = CalciteSystemProperty.DEBUG.value();
 
   private static final Logger LOGGER = CalciteTrace.getPlannerTracer();
 
diff --git 
a/core/src/main/java/org/apache/calcite/plan/volcano/VolcanoPlanner.java 
b/core/src/main/java/org/apache/calcite/plan/volcano/VolcanoPlanner.java
index 54f5049..cd4af85 100644
--- a/core/src/main/java/org/apache/calcite/plan/volcano/VolcanoPlanner.java
+++ b/core/src/main/java/org/apache/calcite/plan/volcano/VolcanoPlanner.java
@@ -18,6 +18,7 @@ package org.apache.calcite.plan.volcano;
 
 import org.apache.calcite.avatica.util.Spaces;
 import org.apache.calcite.config.CalciteConnectionConfig;
+import org.apache.calcite.config.CalciteSystemProperty;
 import org.apache.calcite.linq4j.tree.Expressions;
 import org.apache.calcite.plan.AbstractRelOptPlanner;
 import org.apache.calcite.plan.Context;
@@ -39,7 +40,6 @@ import org.apache.calcite.plan.RelOptUtil;
 import org.apache.calcite.plan.RelTrait;
 import org.apache.calcite.plan.RelTraitDef;
 import org.apache.calcite.plan.RelTraitSet;
-import org.apache.calcite.prepare.CalcitePrepareImpl;
 import org.apache.calcite.rel.RelNode;
 import org.apache.calcite.rel.RelVisitor;
 import org.apache.calcite.rel.convert.Converter;
@@ -64,7 +64,6 @@ import org.apache.calcite.sql.SqlExplainLevel;
 import org.apache.calcite.util.Litmus;
 import org.apache.calcite.util.Pair;
 import org.apache.calcite.util.PartiallyOrderedSet;
-import org.apache.calcite.util.SaffronProperties;
 import org.apache.calcite.util.Util;
 
 import com.google.common.collect.ImmutableList;
@@ -99,12 +98,6 @@ import java.util.regex.Pattern;
  * according to a dynamic programming algorithm.
  */
 public class VolcanoPlanner extends AbstractRelOptPlanner {
-  //~ Static fields/initializers ---------------------------------------------
-  private static final boolean DUMP_GRAPHVIZ =
-      Util.getBooleanProperty("calcite.volcano.dump.graphviz", true);
-  private static final boolean DUMP_SETS =
-      Util.getBooleanProperty("calcite.volcano.dump.sets", true);
-
   protected static final double COST_IMPROVEMENT = .5;
 
   //~ Instance fields --------------------------------------------------------
@@ -912,7 +905,7 @@ public class VolcanoPlanner extends AbstractRelOptPlanner {
     addRule(JoinCommuteRule.INSTANCE);
     addRule(SemiJoinRule.PROJECT);
     addRule(SemiJoinRule.JOIN);
-    if (CalcitePrepareImpl.COMMUTE) {
+    if (CalciteSystemProperty.COMMUTE.value()) {
       addRule(JoinAssociateRule.INSTANCE);
     }
     addRule(AggregateRemoveRule.INSTANCE);
@@ -1012,7 +1005,7 @@ public class VolcanoPlanner extends AbstractRelOptPlanner 
{
     assert fromTraits.size() >= toTraits.size();
 
     final boolean allowInfiniteCostConverters =
-        SaffronProperties.INSTANCE.allowInfiniteCostConverters().get();
+        CalciteSystemProperty.ALLOW_INFINITE_COST_CONVERTERS.value();
 
     // Traits may build on top of another...for example a collation trait
     // would typically come after a distribution trait since distribution
@@ -1175,12 +1168,12 @@ public class VolcanoPlanner extends 
AbstractRelOptPlanner {
       originalRoot.explain(
           new RelWriterImpl(pw, SqlExplainLevel.ALL_ATTRIBUTES, false));
     }
-    if (DUMP_SETS) {
+    if (CalciteSystemProperty.DUMP_SETS.value()) {
       pw.println();
       pw.println("Sets:");
       dumpSets(pw);
     }
-    if (DUMP_GRAPHVIZ) {
+    if (CalciteSystemProperty.DUMP_GRAPHVIZ.value()) {
       pw.println();
       pw.println("Graphviz:");
       dumpGraphviz(pw);
diff --git 
a/core/src/main/java/org/apache/calcite/prepare/CalciteMaterializer.java 
b/core/src/main/java/org/apache/calcite/prepare/CalciteMaterializer.java
index 45c4850..855cc40 100644
--- a/core/src/main/java/org/apache/calcite/prepare/CalciteMaterializer.java
+++ b/core/src/main/java/org/apache/calcite/prepare/CalciteMaterializer.java
@@ -17,6 +17,7 @@
 package org.apache.calcite.prepare;
 
 import org.apache.calcite.adapter.enumerable.EnumerableRel;
+import org.apache.calcite.config.CalciteSystemProperty;
 import org.apache.calcite.interpreter.BindableConvention;
 import org.apache.calcite.jdbc.CalcitePrepare;
 import org.apache.calcite.jdbc.CalciteSchema;
@@ -107,7 +108,7 @@ class CalciteMaterializer extends 
CalcitePrepareImpl.CalcitePreparingStmt {
     for (Callback x : useStar(schema, materialization.queryRel)) {
       // Success -- we found a star table that matches.
       materialization.materialize(x.rel, x.starRelOptTable);
-      if (CalcitePrepareImpl.DEBUG) {
+      if (CalciteSystemProperty.DEBUG.value()) {
         System.out.println("Materialization "
             + materialization.materializedTable + " matched star table "
             + x.starTable + "; query after re-write: "
diff --git 
a/core/src/main/java/org/apache/calcite/prepare/CalcitePrepareImpl.java 
b/core/src/main/java/org/apache/calcite/prepare/CalcitePrepareImpl.java
index 90979c4..a7181a0 100644
--- a/core/src/main/java/org/apache/calcite/prepare/CalcitePrepareImpl.java
+++ b/core/src/main/java/org/apache/calcite/prepare/CalcitePrepareImpl.java
@@ -29,6 +29,7 @@ import org.apache.calcite.avatica.AvaticaParameter;
 import org.apache.calcite.avatica.ColumnMetaData;
 import org.apache.calcite.avatica.Meta;
 import org.apache.calcite.config.CalciteConnectionConfig;
+import org.apache.calcite.config.CalciteSystemProperty;
 import org.apache.calcite.interpreter.BindableConvention;
 import org.apache.calcite.interpreter.Bindables;
 import org.apache.calcite.interpreter.Interpreters;
@@ -163,12 +164,6 @@ import static org.apache.calcite.util.Static.RESOURCE;
  * subject to change without notice.</p>
  */
 public class CalcitePrepareImpl implements CalcitePrepare {
-
-  public static final boolean DEBUG = Util.getBooleanProperty("calcite.debug");
-
-  public static final boolean COMMUTE =
-      Util.getBooleanProperty("calcite.enable.join.commute");
-
   /** Whether to enable the collation trait. Some extra optimizations are
    * possible if enabled, but queries should work either way. At some point
    * this will become a preference, or we will run multiple phases: first
@@ -221,7 +216,7 @@ public class CalcitePrepareImpl implements CalcitePrepare {
           AggregateStarTableRule.INSTANCE,
           AggregateStarTableRule.INSTANCE2,
           TableScanRule.INSTANCE,
-          COMMUTE
+          CalciteSystemProperty.COMMUTE.value()
               ? JoinAssociateRule.INSTANCE
               : ProjectMergeRule.INSTANCE,
           FilterTableScanRule.INSTANCE,
diff --git a/core/src/main/java/org/apache/calcite/profile/ProfilerImpl.java 
b/core/src/main/java/org/apache/calcite/profile/ProfilerImpl.java
index 2dd8af9..1115946 100644
--- a/core/src/main/java/org/apache/calcite/profile/ProfilerImpl.java
+++ b/core/src/main/java/org/apache/calcite/profile/ProfilerImpl.java
@@ -16,10 +16,10 @@
  */
 package org.apache.calcite.profile;
 
+import org.apache.calcite.config.CalciteSystemProperty;
 import org.apache.calcite.linq4j.Ord;
 import org.apache.calcite.linq4j.tree.Primitive;
 import org.apache.calcite.materialize.Lattice;
-import org.apache.calcite.prepare.CalcitePrepareImpl;
 import org.apache.calcite.rel.metadata.NullSentinel;
 import org.apache.calcite.runtime.FlatLists;
 import org.apache.calcite.util.ImmutableBitSet;
@@ -275,7 +275,7 @@ public class ProfilerImpl implements Profiler {
     }
 
     void pass(int pass, List<Space> spaces, Iterable<List<Comparable>> rows) {
-      if (CalcitePrepareImpl.DEBUG) {
+      if (CalciteSystemProperty.DEBUG.value()) {
         System.out.println("pass: " + pass
             + ", spaces.size: " + spaces.size()
             + ", distributions.size: " + distributions.size());
@@ -361,7 +361,7 @@ public class ProfilerImpl implements Profiler {
               new Distribution(space.columns, space.valueSet, 
space.cardinality,
                   space.nullCount, expectedCardinality, minimal);
           final double surprise = distribution.surprise();
-          if (CalcitePrepareImpl.DEBUG && surprise > 0.1d) {
+          if (CalciteSystemProperty.DEBUG.value() && surprise > 0.1d) {
             System.out.println(distribution.columnOrdinals()
                 + " " + distribution.columns
                 + ", cardinality: " + distribution.cardinality
@@ -757,7 +757,7 @@ public class ProfilerImpl implements Profiler {
     }
 
     boolean isValid() {
-      if (CalcitePrepareImpl.DEBUG) {
+      if (CalciteSystemProperty.DEBUG.value()) {
         System.out.println(toString());
       }
       assert deque.size() == priorityQueue.size();
@@ -779,7 +779,7 @@ public class ProfilerImpl implements Profiler {
       } else {
         b = false;
       }
-      if (CalcitePrepareImpl.DEBUG) {
+      if (CalciteSystemProperty.DEBUG.value()) {
         System.out.println("offer " + d
             + " min " + priorityQueue.peek()
             + " accepted " + b);
diff --git a/core/src/main/java/org/apache/calcite/rel/core/Filter.java 
b/core/src/main/java/org/apache/calcite/rel/core/Filter.java
index 492ab27..b539d09 100644
--- a/core/src/main/java/org/apache/calcite/rel/core/Filter.java
+++ b/core/src/main/java/org/apache/calcite/rel/core/Filter.java
@@ -16,11 +16,11 @@
  */
 package org.apache.calcite.rel.core;
 
+import org.apache.calcite.config.CalciteSystemProperty;
 import org.apache.calcite.plan.RelOptCluster;
 import org.apache.calcite.plan.RelOptCost;
 import org.apache.calcite.plan.RelOptPlanner;
 import org.apache.calcite.plan.RelTraitSet;
-import org.apache.calcite.prepare.CalcitePrepareImpl;
 import org.apache.calcite.rel.RelInput;
 import org.apache.calcite.rel.RelNode;
 import org.apache.calcite.rel.RelWriter;
@@ -74,7 +74,7 @@ public abstract class Filter extends SingleRel {
     assert RexUtil.isFlat(condition) : condition;
     this.condition = condition;
     // Too expensive for everyday use:
-    assert !CalcitePrepareImpl.DEBUG || isValid(Litmus.THROW, null);
+    assert !CalciteSystemProperty.DEBUG.value() || isValid(Litmus.THROW, null);
   }
 
   /**
diff --git 
a/core/src/main/java/org/apache/calcite/rel/logical/LogicalCorrelate.java 
b/core/src/main/java/org/apache/calcite/rel/logical/LogicalCorrelate.java
index 1c85672..a2943de 100644
--- a/core/src/main/java/org/apache/calcite/rel/logical/LogicalCorrelate.java
+++ b/core/src/main/java/org/apache/calcite/rel/logical/LogicalCorrelate.java
@@ -16,10 +16,10 @@
  */
 package org.apache.calcite.rel.logical;
 
+import org.apache.calcite.config.CalciteSystemProperty;
 import org.apache.calcite.plan.Convention;
 import org.apache.calcite.plan.RelOptCluster;
 import org.apache.calcite.plan.RelTraitSet;
-import org.apache.calcite.prepare.CalcitePrepareImpl;
 import org.apache.calcite.rel.RelInput;
 import org.apache.calcite.rel.RelNode;
 import org.apache.calcite.rel.RelShuttle;
@@ -71,7 +71,7 @@ public final class LogicalCorrelate extends Correlate {
         correlationId,
         requiredColumns,
         joinType);
-    assert !CalcitePrepareImpl.DEBUG || isValid(Litmus.THROW, null);
+    assert !CalciteSystemProperty.DEBUG.value() || isValid(Litmus.THROW, null);
   }
 
   @Deprecated // to be removed before 2.0
diff --git 
a/core/src/main/java/org/apache/calcite/rel/metadata/JaninoRelMetadataProvider.java
 
b/core/src/main/java/org/apache/calcite/rel/metadata/JaninoRelMetadataProvider.java
index e206ff3..9ec51cf 100644
--- 
a/core/src/main/java/org/apache/calcite/rel/metadata/JaninoRelMetadataProvider.java
+++ 
b/core/src/main/java/org/apache/calcite/rel/metadata/JaninoRelMetadataProvider.java
@@ -21,13 +21,13 @@ import 
org.apache.calcite.adapter.enumerable.EnumerableFilter;
 import org.apache.calcite.adapter.enumerable.EnumerableJoin;
 import org.apache.calcite.adapter.enumerable.EnumerableProject;
 import org.apache.calcite.adapter.enumerable.EnumerableTableScan;
+import org.apache.calcite.config.CalciteSystemProperty;
 import org.apache.calcite.interpreter.JaninoRexCompiler;
 import org.apache.calcite.linq4j.Ord;
 import org.apache.calcite.linq4j.tree.Primitive;
 import org.apache.calcite.plan.hep.HepRelVertex;
 import org.apache.calcite.plan.volcano.AbstractConverter;
 import org.apache.calcite.plan.volcano.RelSubset;
-import org.apache.calcite.prepare.CalcitePrepareImpl;
 import org.apache.calcite.rel.AbstractRelNode;
 import org.apache.calcite.rel.RelNode;
 import org.apache.calcite.rel.convert.ConverterImpl;
@@ -52,7 +52,6 @@ import org.apache.calcite.rel.stream.LogicalDelta;
 import org.apache.calcite.rex.RexNode;
 import org.apache.calcite.util.ControlFlowException;
 import org.apache.calcite.util.Pair;
-import org.apache.calcite.util.SaffronProperties;
 import org.apache.calcite.util.Util;
 
 import com.google.common.cache.CacheBuilder;
@@ -104,7 +103,7 @@ public class JaninoRelMetadataProvider implements 
RelMetadataProvider {
   @SuppressWarnings("unchecked")
   private static final LoadingCache<Key, MetadataHandler> HANDLERS =
       maxSize(CacheBuilder.newBuilder(),
-          SaffronProperties.INSTANCE.metadataHandlerCacheMaximumSize().get())
+          CalciteSystemProperty.METADATA_HANDLER_CACHE_MAXIMUM_SIZE.value())
           .build(
               CacheLoader.from(key ->
                   load3(key.def, key.provider.handlers(key.def),
@@ -445,7 +444,7 @@ public class JaninoRelMetadataProvider implements 
RelMetadataProvider {
         + "\n"
         + "}";
 
-    if (CalcitePrepareImpl.DEBUG) {
+    if (CalciteSystemProperty.DEBUG.value()) {
       // Add line numbers to the generated janino class
       compiler.setDebuggingInformation(true, true, true);
       System.out.println(s);
diff --git 
a/core/src/main/java/org/apache/calcite/rel/rules/AggregateStarTableRule.java 
b/core/src/main/java/org/apache/calcite/rel/rules/AggregateStarTableRule.java
index 317b0c5..b9820c1 100644
--- 
a/core/src/main/java/org/apache/calcite/rel/rules/AggregateStarTableRule.java
+++ 
b/core/src/main/java/org/apache/calcite/rel/rules/AggregateStarTableRule.java
@@ -17,6 +17,7 @@
 package org.apache.calcite.rel.rules;
 
 import org.apache.calcite.config.CalciteConnectionConfig;
+import org.apache.calcite.config.CalciteSystemProperty;
 import org.apache.calcite.jdbc.CalciteSchema;
 import org.apache.calcite.materialize.Lattice;
 import org.apache.calcite.materialize.TileKey;
@@ -29,7 +30,6 @@ import org.apache.calcite.plan.RelOptRuleOperand;
 import org.apache.calcite.plan.RelOptTable;
 import org.apache.calcite.plan.SubstitutionVisitor;
 import org.apache.calcite.plan.ViewExpanders;
-import org.apache.calcite.prepare.CalcitePrepareImpl;
 import org.apache.calcite.prepare.RelOptTableImpl;
 import org.apache.calcite.rel.RelNode;
 import org.apache.calcite.rel.core.Aggregate;
@@ -150,14 +150,14 @@ public class AggregateStarTableRule extends RelOptRule {
             rowCount);
     
relBuilder.push(aggregateRelOptTable.toRel(ViewExpanders.simpleContext(cluster)));
     if (tileKey == null) {
-      if (CalcitePrepareImpl.DEBUG) {
+      if (CalciteSystemProperty.DEBUG.value()) {
         System.out.println("Using materialization "
             + aggregateRelOptTable.getQualifiedName()
             + " (exact match)");
       }
     } else if (!tileKey.dimensions.equals(aggregate.getGroupSet())) {
       // Aggregate has finer granularity than we need. Roll up.
-      if (CalcitePrepareImpl.DEBUG) {
+      if (CalciteSystemProperty.DEBUG.value()) {
         System.out.println("Using materialization "
             + aggregateRelOptTable.getQualifiedName()
             + ", rolling up " + tileKey.dimensions + " to "
@@ -181,7 +181,7 @@ public class AggregateStarTableRule extends RelOptRule {
           aggregate.copy(aggregate.getTraitSet(), relBuilder.build(), false,
               groupSet.build(), null, aggCalls));
     } else if (!tileKey.measures.equals(measures)) {
-      if (CalcitePrepareImpl.DEBUG) {
+      if (CalciteSystemProperty.DEBUG.value()) {
         System.out.println("Using materialization "
             + aggregateRelOptTable.getQualifiedName()
             + ", right granularity, but different measures "
diff --git 
a/core/src/main/java/org/apache/calcite/rel/rules/MultiJoinOptimizeBushyRule.java
 
b/core/src/main/java/org/apache/calcite/rel/rules/MultiJoinOptimizeBushyRule.java
index 3439376..46f910d 100644
--- 
a/core/src/main/java/org/apache/calcite/rel/rules/MultiJoinOptimizeBushyRule.java
+++ 
b/core/src/main/java/org/apache/calcite/rel/rules/MultiJoinOptimizeBushyRule.java
@@ -16,9 +16,9 @@
  */
 package org.apache.calcite.rel.rules;
 
+import org.apache.calcite.config.CalciteSystemProperty;
 import org.apache.calcite.plan.RelOptRule;
 import org.apache.calcite.plan.RelOptRuleCall;
-import org.apache.calcite.prepare.CalcitePrepareImpl;
 import org.apache.calcite.rel.RelNode;
 import org.apache.calcite.rel.core.JoinRelType;
 import org.apache.calcite.rel.core.RelFactories;
@@ -72,7 +72,7 @@ public class MultiJoinOptimizeBushyRule extends RelOptRule {
   public static final MultiJoinOptimizeBushyRule INSTANCE =
       new MultiJoinOptimizeBushyRule(RelFactories.LOGICAL_BUILDER);
 
-  private final PrintWriter pw = CalcitePrepareImpl.DEBUG
+  private final PrintWriter pw = CalciteSystemProperty.DEBUG.value()
       ? Util.printWriter(System.out)
       : null;
 
diff --git a/core/src/main/java/org/apache/calcite/rex/RexExecutorImpl.java 
b/core/src/main/java/org/apache/calcite/rex/RexExecutorImpl.java
index 407a2f8..a222f00 100644
--- a/core/src/main/java/org/apache/calcite/rex/RexExecutorImpl.java
+++ b/core/src/main/java/org/apache/calcite/rex/RexExecutorImpl.java
@@ -20,6 +20,7 @@ import org.apache.calcite.DataContext;
 import org.apache.calcite.adapter.enumerable.RexToLixTranslator;
 import org.apache.calcite.adapter.enumerable.RexToLixTranslator.InputGetter;
 import org.apache.calcite.adapter.java.JavaTypeFactory;
+import org.apache.calcite.config.CalciteSystemProperty;
 import org.apache.calcite.jdbc.JavaTypeFactoryImpl;
 import org.apache.calcite.linq4j.tree.BlockBuilder;
 import org.apache.calcite.linq4j.tree.Expression;
@@ -28,7 +29,6 @@ import org.apache.calcite.linq4j.tree.IndexExpression;
 import org.apache.calcite.linq4j.tree.MethodCallExpression;
 import org.apache.calcite.linq4j.tree.MethodDeclaration;
 import org.apache.calcite.linq4j.tree.ParameterExpression;
-import org.apache.calcite.prepare.CalcitePrepareImpl;
 import org.apache.calcite.rel.type.RelDataType;
 import org.apache.calcite.rel.type.RelDataTypeFactory;
 import org.apache.calcite.sql.validate.SqlConformance;
@@ -91,7 +91,7 @@ public class RexExecutorImpl implements RexExecutor {
             BuiltInMethod.FUNCTION1_APPLY.method.getName(),
             ImmutableList.of(root0_), blockBuilder.toBlock());
     String code = Expressions.toString(methodDecl);
-    if (CalcitePrepareImpl.DEBUG) {
+    if (CalciteSystemProperty.DEBUG.value()) {
       Util.debugCode(System.out, code);
     }
     return code;
diff --git a/core/src/main/java/org/apache/calcite/rex/RexLiteral.java 
b/core/src/main/java/org/apache/calcite/rex/RexLiteral.java
index be580ba..aa78730 100644
--- a/core/src/main/java/org/apache/calcite/rex/RexLiteral.java
+++ b/core/src/main/java/org/apache/calcite/rex/RexLiteral.java
@@ -19,6 +19,7 @@ package org.apache.calcite.rex;
 import org.apache.calcite.avatica.util.ByteString;
 import org.apache.calcite.avatica.util.DateTimeUtils;
 import org.apache.calcite.avatica.util.TimeUnit;
+import org.apache.calcite.config.CalciteSystemProperty;
 import org.apache.calcite.rel.RelNode;
 import org.apache.calcite.rel.type.RelDataType;
 import org.apache.calcite.sql.SqlCollation;
@@ -32,7 +33,6 @@ import org.apache.calcite.util.ConversionUtil;
 import org.apache.calcite.util.DateString;
 import org.apache.calcite.util.Litmus;
 import org.apache.calcite.util.NlsString;
-import org.apache.calcite.util.SaffronProperties;
 import org.apache.calcite.util.TimeString;
 import org.apache.calcite.util.TimestampString;
 import org.apache.calcite.util.Unsafe;
@@ -589,7 +589,7 @@ public class RexLiteral extends RexNode {
         boolean includeCharset =
             (nlsString.getCharsetName() != null)
                 && !nlsString.getCharsetName().equals(
-                    SaffronProperties.INSTANCE.defaultCharset().get());
+                CalciteSystemProperty.DEFAULT_CHARSET.value());
         pw.print(nlsString.asSql(includeCharset, false));
       }
       break;
diff --git 
a/core/src/main/java/org/apache/calcite/runtime/CalciteException.java 
b/core/src/main/java/org/apache/calcite/runtime/CalciteException.java
index 3250f44..b073069 100644
--- a/core/src/main/java/org/apache/calcite/runtime/CalciteException.java
+++ b/core/src/main/java/org/apache/calcite/runtime/CalciteException.java
@@ -16,7 +16,7 @@
  */
 package org.apache.calcite.runtime;
 
-import org.apache.calcite.prepare.CalcitePrepareImpl;
+import org.apache.calcite.config.CalciteSystemProperty;
 
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -60,7 +60,7 @@ public class CalciteException extends RuntimeException {
     // TODO: Force the caller to pass in a Logger as a trace argument for
     // better context.  Need to extend ResGen for this.
     LOGGER.trace("CalciteException", this);
-    if (CalcitePrepareImpl.DEBUG) {
+    if (CalciteSystemProperty.DEBUG.value()) {
       LOGGER.error(toString());
     }
   }
diff --git a/core/src/main/java/org/apache/calcite/sql/SqlCollation.java 
b/core/src/main/java/org/apache/calcite/sql/SqlCollation.java
index 493fbd1..4ad5899 100644
--- a/core/src/main/java/org/apache/calcite/sql/SqlCollation.java
+++ b/core/src/main/java/org/apache/calcite/sql/SqlCollation.java
@@ -16,9 +16,9 @@
  */
 package org.apache.calcite.sql;
 
+import org.apache.calcite.config.CalciteSystemProperty;
 import org.apache.calcite.sql.parser.SqlParserUtil;
 import org.apache.calcite.util.Glossary;
-import org.apache.calcite.util.SaffronProperties;
 import org.apache.calcite.util.SerializableCharset;
 import org.apache.calcite.util.Util;
 
@@ -104,7 +104,7 @@ public class SqlCollation implements Serializable {
    */
   public SqlCollation(Coercibility coercibility) {
     this(
-        SaffronProperties.INSTANCE.defaultCollation().get(),
+        CalciteSystemProperty.DEFAULT_COLLATION.value(),
         coercibility);
   }
 
diff --git 
a/core/src/main/java/org/apache/calcite/sql/fun/SqlCountAggFunction.java 
b/core/src/main/java/org/apache/calcite/sql/fun/SqlCountAggFunction.java
index 1678727..0ade8f8 100644
--- a/core/src/main/java/org/apache/calcite/sql/fun/SqlCountAggFunction.java
+++ b/core/src/main/java/org/apache/calcite/sql/fun/SqlCountAggFunction.java
@@ -16,6 +16,7 @@
  */
 package org.apache.calcite.sql.fun;
 
+import org.apache.calcite.config.CalciteSystemProperty;
 import org.apache.calcite.rel.type.RelDataType;
 import org.apache.calcite.rel.type.RelDataTypeFactory;
 import org.apache.calcite.sql.SqlAggFunction;
@@ -47,7 +48,7 @@ public class SqlCountAggFunction extends SqlAggFunction {
   //~ Constructors -----------------------------------------------------------
 
   public SqlCountAggFunction(String name) {
-    this(name, SqlValidator.STRICT ? OperandTypes.ANY : 
OperandTypes.ONE_OR_MORE);
+    this(name, CalciteSystemProperty.STRICT.value() ? OperandTypes.ANY : 
OperandTypes.ONE_OR_MORE);
   }
 
   public SqlCountAggFunction(String name,
diff --git 
a/core/src/main/java/org/apache/calcite/sql/parser/SqlParserUtil.java 
b/core/src/main/java/org/apache/calcite/sql/parser/SqlParserUtil.java
index 0071c77..5f0f729 100644
--- a/core/src/main/java/org/apache/calcite/sql/parser/SqlParserUtil.java
+++ b/core/src/main/java/org/apache/calcite/sql/parser/SqlParserUtil.java
@@ -18,6 +18,7 @@ package org.apache.calcite.sql.parser;
 
 import org.apache.calcite.avatica.util.Casing;
 import org.apache.calcite.avatica.util.DateTimeUtils;
+import org.apache.calcite.config.CalciteSystemProperty;
 import org.apache.calcite.rel.type.RelDataTypeSystem;
 import org.apache.calcite.runtime.CalciteContextException;
 import org.apache.calcite.sql.SqlBinaryOperator;
@@ -39,7 +40,6 @@ import org.apache.calcite.sql.SqlUtil;
 import org.apache.calcite.sql.fun.SqlStdOperatorTable;
 import org.apache.calcite.util.DateString;
 import org.apache.calcite.util.PrecedenceClimbingParser;
-import org.apache.calcite.util.SaffronProperties;
 import org.apache.calcite.util.TimeString;
 import org.apache.calcite.util.TimestampString;
 import org.apache.calcite.util.Util;
@@ -88,7 +88,7 @@ public final class SqlParserUtil {
       return null;
     }
     if (Character.toUpperCase(s.charAt(0)) == 'N') {
-      return SaffronProperties.INSTANCE.defaultNationalCharset().get();
+      return CalciteSystemProperty.DEFAULT_NATIONAL_CHARSET.value();
     }
     int i = s.indexOf("'");
     return s.substring(1, i); // skip prefixed '_'
@@ -551,7 +551,7 @@ public final class SqlParserUtil {
       strength = st.nextToken();
     } else {
       strength =
-          SaffronProperties.INSTANCE.defaultCollationStrength().get();
+          CalciteSystemProperty.DEFAULT_COLLATION_STRENGTH.value();
     }
 
     Charset charset = Charset.forName(charsetStr);
diff --git 
a/core/src/main/java/org/apache/calcite/sql/validate/SqlValidator.java 
b/core/src/main/java/org/apache/calcite/sql/validate/SqlValidator.java
index 2045eac..d385e14 100644
--- a/core/src/main/java/org/apache/calcite/sql/validate/SqlValidator.java
+++ b/core/src/main/java/org/apache/calcite/sql/validate/SqlValidator.java
@@ -42,7 +42,6 @@ import org.apache.calcite.sql.SqlUpdate;
 import org.apache.calcite.sql.SqlWindow;
 import org.apache.calcite.sql.SqlWith;
 import org.apache.calcite.sql.SqlWithItem;
-import org.apache.calcite.util.Util;
 
 import java.util.List;
 import java.util.Map;
@@ -103,9 +102,6 @@ import java.util.Map;
  * names in a particular clause of a SQL statement.</p>
  */
 public interface SqlValidator {
-  /** Whether to follow the SQL standard strictly. */
-  boolean STRICT = Util.getBooleanProperty("calcite.strict.sql");
-
   //~ Methods ----------------------------------------------------------------
 
   /**
diff --git 
a/core/src/main/java/org/apache/calcite/sql/validate/SqlValidatorException.java 
b/core/src/main/java/org/apache/calcite/sql/validate/SqlValidatorException.java
index a81bd85..a46485b 100644
--- 
a/core/src/main/java/org/apache/calcite/sql/validate/SqlValidatorException.java
+++ 
b/core/src/main/java/org/apache/calcite/sql/validate/SqlValidatorException.java
@@ -16,7 +16,7 @@
  */
 package org.apache.calcite.sql.validate;
 
-import org.apache.calcite.prepare.CalcitePrepareImpl;
+import org.apache.calcite.config.CalciteSystemProperty;
 import org.apache.calcite.util.CalciteValidatorException;
 
 import org.slf4j.Logger;
@@ -57,7 +57,7 @@ public class SqlValidatorException extends Exception
 
     // TODO: see note in CalciteException constructor
     LOGGER.trace("SqlValidatorException", this);
-    if (CalcitePrepareImpl.DEBUG) {
+    if (CalciteSystemProperty.DEBUG.value()) {
       LOGGER.error(toString());
     }
   }
diff --git a/core/src/main/java/org/apache/calcite/tools/Programs.java 
b/core/src/main/java/org/apache/calcite/tools/Programs.java
index 38d6aa5..f479aff 100644
--- a/core/src/main/java/org/apache/calcite/tools/Programs.java
+++ b/core/src/main/java/org/apache/calcite/tools/Programs.java
@@ -18,6 +18,7 @@ package org.apache.calcite.tools;
 
 import org.apache.calcite.adapter.enumerable.EnumerableRules;
 import org.apache.calcite.config.CalciteConnectionConfig;
+import org.apache.calcite.config.CalciteSystemProperty;
 import org.apache.calcite.interpreter.NoneToBindableConverterRule;
 import org.apache.calcite.plan.RelOptCostImpl;
 import org.apache.calcite.plan.RelOptLattice;
@@ -30,7 +31,6 @@ import org.apache.calcite.plan.hep.HepMatchOrder;
 import org.apache.calcite.plan.hep.HepPlanner;
 import org.apache.calcite.plan.hep.HepProgram;
 import org.apache.calcite.plan.hep.HepProgramBuilder;
-import org.apache.calcite.prepare.CalcitePrepareImpl;
 import org.apache.calcite.rel.RelNode;
 import org.apache.calcite.rel.core.Calc;
 import org.apache.calcite.rel.core.RelFactories;
@@ -123,7 +123,7 @@ public class Programs {
           SemiJoinRule.PROJECT,
           SemiJoinRule.JOIN,
           TableScanRule.INSTANCE,
-          CalcitePrepareImpl.COMMUTE
+          CalciteSystemProperty.COMMUTE.value()
               ? JoinAssociateRule.INSTANCE
               : ProjectMergeRule.INSTANCE,
           AggregateStarTableRule.INSTANCE,
diff --git 
a/core/src/main/java/org/apache/calcite/util/PartiallyOrderedSet.java 
b/core/src/main/java/org/apache/calcite/util/PartiallyOrderedSet.java
index 313b033..5149bef 100644
--- a/core/src/main/java/org/apache/calcite/util/PartiallyOrderedSet.java
+++ b/core/src/main/java/org/apache/calcite/util/PartiallyOrderedSet.java
@@ -16,6 +16,8 @@
  */
 package org.apache.calcite.util;
 
+import org.apache.calcite.config.CalciteSystemProperty;
+
 import com.google.common.collect.ImmutableList;
 
 import java.util.AbstractSet;
@@ -84,10 +86,6 @@ public class PartiallyOrderedSet<E> extends AbstractSet<E> {
   private final Node<E> topNode;
   private final Node<E> bottomNode;
 
-  /** Whether to check internal consistency all the time.
-   * False unless you specify "-Dcalcite.debug" on the command line. */
-  private static final boolean DEBUG = 
Util.getBooleanProperty("calcite.debug");
-
   /**
    * Creates a partially-ordered set.
    *
@@ -219,7 +217,7 @@ public class PartiallyOrderedSet<E> extends AbstractSet<E> {
    */
   @Override public boolean add(E e) {
     assert e != null;
-    assert !DEBUG || isValid(true);
+    assert !CalciteSystemProperty.DEBUG.value() || isValid(true);
     Node<E> node = map.get(e);
     if (node != null) {
       // already present
@@ -266,7 +264,7 @@ public class PartiallyOrderedSet<E> extends AbstractSet<E> {
     }
 
     map.put(node.e, node);
-    assert !DEBUG || isValid(true);
+    assert !CalciteSystemProperty.DEBUG.value() || isValid(true);
     return true;
   }
 
diff --git a/core/src/main/java/org/apache/calcite/util/SaffronProperties.java 
b/core/src/main/java/org/apache/calcite/util/SaffronProperties.java
index 7ae8682..ed96273 100644
--- a/core/src/main/java/org/apache/calcite/util/SaffronProperties.java
+++ b/core/src/main/java/org/apache/calcite/util/SaffronProperties.java
@@ -45,7 +45,11 @@ import java.util.Properties;
  * comment must describe the name of the property (for example,
  * "net.sf.saffron.connection.PoolSize") and the default value, if any. <em>
  * Developers, please make sure that this remains so!</em>
+ *
+ * @deprecated As of release 1.19,
+ * replaced by {@link org.apache.calcite.config.CalciteSystemProperty}
  */
+@Deprecated
 public interface SaffronProperties {
   /**
    * The boolean property "saffron.opt.allowInfiniteCostConverters" determines
diff --git a/core/src/main/java/org/apache/calcite/util/Util.java 
b/core/src/main/java/org/apache/calcite/util/Util.java
index 1a5a429..2544481 100644
--- a/core/src/main/java/org/apache/calcite/util/Util.java
+++ b/core/src/main/java/org/apache/calcite/util/Util.java
@@ -18,6 +18,7 @@ package org.apache.calcite.util;
 
 import org.apache.calcite.avatica.util.DateTimeUtils;
 import org.apache.calcite.avatica.util.Spaces;
+import org.apache.calcite.config.CalciteSystemProperty;
 import org.apache.calcite.linq4j.Ord;
 import org.apache.calcite.runtime.CalciteException;
 import org.apache.calcite.sql.SqlAggFunction;
@@ -141,7 +142,7 @@ public class Util {
       Pattern.compile("[a-zA-Z_$][a-zA-Z0-9$]*");
 
   private static final Charset DEFAULT_CHARSET =
-      Charset.forName(SaffronProperties.INSTANCE.defaultCharset().get());
+      Charset.forName(CalciteSystemProperty.DEFAULT_CHARSET.value());
 
   /**
    * Maps classes to the map of their enum values. Uses a weak map so that
@@ -792,7 +793,7 @@ public class Util {
 
   /**
    * Returns the {@link Charset} object representing the value of
-   * {@link SaffronProperties#defaultCharset}
+   * {@link CalciteSystemProperty#DEFAULT_CHARSET}
    *
    * @throws java.nio.charset.IllegalCharsetNameException If the given charset
    *                                                      name is illegal
@@ -2274,30 +2275,6 @@ public class Util {
     }
   }
 
-  /** Returns the value of a system property as a boolean.
-   *
-   * <p>For example, the property "foo" is considered true if you supply
-   * {@code -Dfoo} or {@code -Dfoo=true} or {@code -Dfoo=TRUE},
-   * false if you omit the flag or supply {@code -Dfoo=false}.
-   *
-   * @param property Property name
-   * @return Whether property is true
-   */
-  public static boolean getBooleanProperty(String property) {
-    return getBooleanProperty(property, false);
-  }
-
-  /** Returns the value of a system property as a boolean, returning a given
-   * default value if the property is not specified. */
-  public static boolean getBooleanProperty(String property,
-      boolean defaultValue) {
-    final String v = System.getProperties().getProperty(property);
-    if (v == null) {
-      return defaultValue;
-    }
-    return "".equals(v) || "true".equalsIgnoreCase(v);
-  }
-
   /** Returns a copy of a list of lists, making the component lists immutable 
if
    * they are not already. */
   public static <E> List<List<E>> immutableCopy(
diff --git 
a/core/src/main/java/org/apache/calcite/util/javac/JaninoCompiler.java 
b/core/src/main/java/org/apache/calcite/util/javac/JaninoCompiler.java
index b94cce1..45b0031 100644
--- a/core/src/main/java/org/apache/calcite/util/javac/JaninoCompiler.java
+++ b/core/src/main/java/org/apache/calcite/util/javac/JaninoCompiler.java
@@ -16,7 +16,7 @@
  */
 package org.apache.calcite.util.javac;
 
-import org.apache.calcite.prepare.CalcitePrepareImpl;
+import org.apache.calcite.config.CalciteSystemProperty;
 
 import org.codehaus.janino.JavaSourceClassLoader;
 import org.codehaus.janino.util.ClassFile;
@@ -78,7 +78,7 @@ public class JaninoCompiler implements JavaCompiler {
             sourceFinder,
             null,
             args.destdir == null ? null : new File(args.destdir));
-    if (CalcitePrepareImpl.DEBUG) {
+    if (CalciteSystemProperty.DEBUG.value()) {
       // Add line numbers to the generated janino class
       classLoader.setDebuggingInfo(true, true, true);
     }
diff --git 
a/core/src/test/java/org/apache/calcite/jdbc/CalciteRemoteDriverTest.java 
b/core/src/test/java/org/apache/calcite/jdbc/CalciteRemoteDriverTest.java
index 694ef1e..9290dac 100644
--- a/core/src/test/java/org/apache/calcite/jdbc/CalciteRemoteDriverTest.java
+++ b/core/src/test/java/org/apache/calcite/jdbc/CalciteRemoteDriverTest.java
@@ -25,7 +25,7 @@ import org.apache.calcite.avatica.remote.Service;
 import org.apache.calcite.avatica.server.AvaticaJsonHandler;
 import org.apache.calcite.avatica.server.HttpServer;
 import org.apache.calcite.avatica.server.Main;
-import org.apache.calcite.prepare.CalcitePrepareImpl;
+import org.apache.calcite.config.CalciteSystemProperty;
 import org.apache.calcite.test.CalciteAssert;
 import org.apache.calcite.test.JdbcFrontLinqBackTest;
 import org.apache.calcite.test.JdbcTest;
@@ -92,7 +92,7 @@ public class CalciteRemoteDriverTest {
   public static final String LJS = Factory2.class.getName();
 
   private final PrintWriter out =
-      CalcitePrepareImpl.DEBUG ? Util.printWriter(System.out)
+      CalciteSystemProperty.DEBUG.value() ? Util.printWriter(System.out)
           : new PrintWriter(new StringWriter());
 
   private static final CalciteAssert.ConnectionFactory 
REMOTE_CONNECTION_FACTORY =
@@ -430,7 +430,7 @@ public class CalciteRemoteDriverTest {
         SqlType.SQLXML
     };
     final PrintWriter out =
-        CalcitePrepareImpl.DEBUG
+        CalciteSystemProperty.DEBUG.value()
             ? Util.printWriter(System.out)
             : new PrintWriter(new StringWriter());
     for (SqlType.Method row : SqlType.Method.values()) {
diff --git 
a/core/src/test/java/org/apache/calcite/plan/volcano/TraitPropagationTest.java 
b/core/src/test/java/org/apache/calcite/plan/volcano/TraitPropagationTest.java
index e901868..11be2c2 100644
--- 
a/core/src/test/java/org/apache/calcite/plan/volcano/TraitPropagationTest.java
+++ 
b/core/src/test/java/org/apache/calcite/plan/volcano/TraitPropagationTest.java
@@ -18,6 +18,7 @@ package org.apache.calcite.plan.volcano;
 
 import org.apache.calcite.adapter.enumerable.EnumerableTableScan;
 import org.apache.calcite.adapter.java.JavaTypeFactory;
+import org.apache.calcite.config.CalciteSystemProperty;
 import org.apache.calcite.jdbc.CalcitePrepare;
 import org.apache.calcite.plan.Convention;
 import org.apache.calcite.plan.ConventionTraitDef;
@@ -34,7 +35,6 @@ import org.apache.calcite.plan.RelTrait;
 import org.apache.calcite.plan.RelTraitSet;
 import org.apache.calcite.plan.volcano.AbstractConverter.ExpandConversionRule;
 import org.apache.calcite.prepare.CalciteCatalogReader;
-import org.apache.calcite.prepare.CalcitePrepareImpl;
 import org.apache.calcite.rel.AbstractRelNode;
 import org.apache.calcite.rel.RelCollation;
 import org.apache.calcite.rel.RelCollationTraitDef;
@@ -105,7 +105,7 @@ public class TraitPropagationTest {
 
   @Test public void testOne() throws Exception {
     RelNode planned = run(new PropAction(), RULES);
-    if (CalcitePrepareImpl.DEBUG) {
+    if (CalciteSystemProperty.DEBUG.value()) {
       System.out.println(
           RelOptUtil.dumpPlan("LOGICAL PLAN", planned, SqlExplainFormat.TEXT,
               SqlExplainLevel.ALL_ATTRIBUTES));
diff --git 
a/core/src/test/java/org/apache/calcite/sql/test/SqlOperatorBaseTest.java 
b/core/src/test/java/org/apache/calcite/sql/test/SqlOperatorBaseTest.java
index a5bc2e6..22a13e8 100644
--- a/core/src/test/java/org/apache/calcite/sql/test/SqlOperatorBaseTest.java
+++ b/core/src/test/java/org/apache/calcite/sql/test/SqlOperatorBaseTest.java
@@ -18,6 +18,7 @@ package org.apache.calcite.sql.test;
 
 import org.apache.calcite.avatica.util.DateTimeUtils;
 import org.apache.calcite.config.CalciteConnectionProperty;
+import org.apache.calcite.config.CalciteSystemProperty;
 import org.apache.calcite.linq4j.Linq4j;
 import org.apache.calcite.plan.Strong;
 import org.apache.calcite.rel.type.RelDataType;
@@ -5491,7 +5492,7 @@ public abstract class SqlOperatorBaseTest {
   protected static Pair<String, Hook.Closeable> currentTimeString(TimeZone tz) 
{
     final Calendar calendar;
     final Hook.Closeable closeable;
-    if (CalciteAssert.ENABLE_SLOW) {
+    if (CalciteSystemProperty.TEST_SLOW.value()) {
       calendar = getCalendarNotTooNear(Calendar.HOUR_OF_DAY);
       closeable = () -> { };
     } else {
@@ -8002,7 +8003,7 @@ public abstract class SqlOperatorBaseTest {
   /** Test that calls all operators with all possible argument types, and for
    * each type, with a set of tricky values. */
   @Test public void testArgumentBounds() {
-    if (!CalciteAssert.ENABLE_SLOW) {
+    if (!CalciteSystemProperty.TEST_SLOW.value()) {
       return;
     }
     final SqlValidatorImpl validator = (SqlValidatorImpl) 
tester.getValidator();
diff --git a/core/src/test/java/org/apache/calcite/test/CalciteAssert.java 
b/core/src/test/java/org/apache/calcite/test/CalciteAssert.java
index 03e7d80..35505fd 100644
--- a/core/src/test/java/org/apache/calcite/test/CalciteAssert.java
+++ b/core/src/test/java/org/apache/calcite/test/CalciteAssert.java
@@ -23,6 +23,7 @@ import org.apache.calcite.adapter.jdbc.JdbcSchema;
 import org.apache.calcite.avatica.ConnectionProperty;
 import org.apache.calcite.avatica.util.DateTimeUtils;
 import org.apache.calcite.config.CalciteConnectionProperty;
+import org.apache.calcite.config.CalciteSystemProperty;
 import org.apache.calcite.config.Lex;
 import org.apache.calcite.jdbc.CalciteConnection;
 import org.apache.calcite.jdbc.CalciteMetaImpl;
@@ -71,7 +72,6 @@ import net.hydromatic.scott.data.hsqldb.ScottHsqldb;
 
 import org.hamcrest.Matcher;
 
-import java.io.File;
 import java.lang.reflect.InvocationTargetException;
 import java.lang.reflect.Method;
 import java.lang.reflect.Modifier;
@@ -122,23 +122,13 @@ import static org.junit.Assert.fail;
 public class CalciteAssert {
   private CalciteAssert() {}
 
-  /** Which database to use for tests that require a JDBC data source. By
-   * default the test suite runs against the embedded hsqldb database.
+  /**
+   * Which database to use for tests that require a JDBC data source.
    *
-   * <p>We recommend that casual users use hsqldb, and frequent Calcite
-   * developers use MySQL. The test suite runs faster against the MySQL 
database
-   * (mainly because of the 0.1s versus 6s startup time). You have to populate
-   * MySQL manually with the foodmart data set, otherwise there will be test
-   * failures.  To run against MySQL, specify '-Dcalcite.test.db=mysql' on the
-   * java command line. */
+   * @see CalciteSystemProperty#TEST_DB
+   **/
   public static final DatabaseInstance DB =
-      DatabaseInstance.valueOf(
-          Util.first(System.getProperty("calcite.test.db"), "HSQLDB")
-              .toUpperCase(Locale.ROOT));
-
-  /** Whether to enable slow tests. Default is false. */
-  public static final boolean ENABLE_SLOW =
-      Util.getBooleanProperty("calcite.test.slow");
+      DatabaseInstance.valueOf(CalciteSystemProperty.TEST_DB.value());
 
   private static final DateFormat UTC_DATE_FORMAT;
   private static final DateFormat UTC_TIME_FORMAT;
@@ -1814,7 +1804,7 @@ public class CalciteAssert {
         new ConnectionSpec(ScottHsqldb.URI, ScottHsqldb.USER,
             ScottHsqldb.PASSWORD, "org.hsqldb.jdbcDriver", "SCOTT")),
     H2(
-        new ConnectionSpec("jdbc:h2:" + getDataSetPath()
+        new ConnectionSpec("jdbc:h2:" + 
CalciteSystemProperty.TEST_DATASET_PATH.value()
             + "/h2/target/foodmart;user=foodmart;password=foodmart",
             "foodmart", "foodmart", "org.h2.Driver", "foodmart"), null),
     MYSQL(
@@ -1831,23 +1821,6 @@ public class CalciteAssert {
     public final ConnectionSpec foodmart;
     public final ConnectionSpec scott;
 
-    private static String getDataSetPath() {
-      String path = System.getProperty("calcite.test.dataset");
-      if (path != null) {
-        return path;
-      }
-      final String[] dirs = {
-          "../calcite-test-dataset",
-          "../../calcite-test-dataset"
-      };
-      for (String s : dirs) {
-        if (new File(s).exists() && new File(s, "vm").exists()) {
-          return s;
-        }
-      }
-      return ".";
-    }
-
     DatabaseInstance(ConnectionSpec foodmart, ConnectionSpec scott) {
       this.foodmart = foodmart;
       this.scott = scott;
diff --git a/core/src/test/java/org/apache/calcite/test/FoodmartTest.java 
b/core/src/test/java/org/apache/calcite/test/FoodmartTest.java
index 9fe32a6..a905f9b 100644
--- a/core/src/test/java/org/apache/calcite/test/FoodmartTest.java
+++ b/core/src/test/java/org/apache/calcite/test/FoodmartTest.java
@@ -16,6 +16,7 @@
  */
 package org.apache.calcite.test;
 
+import org.apache.calcite.config.CalciteSystemProperty;
 import org.apache.calcite.linq4j.tree.Primitive;
 import org.apache.calcite.util.IntegerIntervalSet;
 
@@ -101,8 +102,8 @@ public class FoodmartTest {
 
   @Parameterized.Parameters(name = "{index}: foodmart({0})={1}")
   public static List<Object[]> getSqls() throws IOException {
-    String idList = System.getProperty("calcite.ids");
-    if (!CalciteAssert.ENABLE_SLOW && idList == null) {
+    String idList = CalciteSystemProperty.TEST_FOODMART_QUERY_IDS.value();
+    if (!CalciteSystemProperty.TEST_SLOW.value() && idList == null) {
       // Avoid loading the query set in a regular test suite run. It burns too
       // much memory.
       return ImmutableList.of();
@@ -126,7 +127,7 @@ public class FoodmartTest {
       }
     } else {
       for (FoodMartQuerySet.FoodmartQuery query1 : set.queries.values()) {
-        if (!CalciteAssert.ENABLE_SLOW && query1.id != 2) {
+        if (!CalciteSystemProperty.TEST_SLOW.value() && query1.id != 2) {
           // If slow queries are not enabled, only run query #2.
           continue;
         }
diff --git a/core/src/test/java/org/apache/calcite/test/JdbcTest.java 
b/core/src/test/java/org/apache/calcite/test/JdbcTest.java
index d64c90f..959aa12 100644
--- a/core/src/test/java/org/apache/calcite/test/JdbcTest.java
+++ b/core/src/test/java/org/apache/calcite/test/JdbcTest.java
@@ -32,6 +32,7 @@ import org.apache.calcite.avatica.util.Casing;
 import org.apache.calcite.avatica.util.Quoting;
 import org.apache.calcite.config.CalciteConnectionConfig;
 import org.apache.calcite.config.CalciteConnectionProperty;
+import org.apache.calcite.config.CalciteSystemProperty;
 import org.apache.calcite.config.Lex;
 import org.apache.calcite.config.NullCollation;
 import org.apache.calcite.jdbc.CalciteConnection;
@@ -3483,7 +3484,7 @@ public class JdbcTest {
             "deptno=10; empid=110; S=21710.0; FIVE=5; M=10000.0; C=2",
             "deptno=10; empid=150; S=18760.0; FIVE=5; M=7000.0; C=2",
             "deptno=20; empid=200; S=8200.0; FIVE=5; M=8000.0; C=1")
-        .planContains(CalcitePrepareImpl.DEBUG
+        .planContains(CalciteSystemProperty.DEBUG.value()
             ? "_list.add(new Object[] {\n"
             + "        row[0],\n" // box-unbox is optimized
             + "        row[1],\n"
@@ -3552,7 +3553,7 @@ public class JdbcTest {
   @Test public void testWinAggScalarNonNullPhysType() {
     String planLine =
         "a0s0w0 = org.apache.calcite.runtime.SqlFunctions.lesser(a0s0w0, 
org.apache.calcite.runtime.SqlFunctions.toFloat(_rows[j]));";
-    if (CalcitePrepareImpl.DEBUG) {
+    if (CalciteSystemProperty.DEBUG.value()) {
       planLine = planLine.replaceAll("a0s0w0", "MINa0s0w0");
     }
     CalciteAssert.hr()
@@ -3577,7 +3578,7 @@ public class JdbcTest {
   @Test public void testWinAggScalarNonNullPhysTypePlusOne() {
     String planLine =
         "a0s0w0 = org.apache.calcite.runtime.SqlFunctions.lesser(a0s0w0, 
org.apache.calcite.runtime.SqlFunctions.toFloat(_rows[j]));";
-    if (CalcitePrepareImpl.DEBUG) {
+    if (CalciteSystemProperty.DEBUG.value()) {
       planLine = planLine.replaceAll("a0s0w0", "MINa0s0w0");
     }
     CalciteAssert.hr()
diff --git 
a/core/src/test/java/org/apache/calcite/test/MultiJdbcSchemaJoinTest.java 
b/core/src/test/java/org/apache/calcite/test/MultiJdbcSchemaJoinTest.java
index e9c2795..3346c61 100644
--- a/core/src/test/java/org/apache/calcite/test/MultiJdbcSchemaJoinTest.java
+++ b/core/src/test/java/org/apache/calcite/test/MultiJdbcSchemaJoinTest.java
@@ -18,8 +18,8 @@ package org.apache.calcite.test;
 
 import org.apache.calcite.adapter.java.ReflectiveSchema;
 import org.apache.calcite.adapter.jdbc.JdbcSchema;
+import org.apache.calcite.config.CalciteSystemProperty;
 import org.apache.calcite.jdbc.CalciteConnection;
-import org.apache.calcite.prepare.CalcitePrepareImpl;
 import org.apache.calcite.schema.SchemaPlus;
 
 import com.google.common.collect.Sets;
@@ -152,7 +152,7 @@ public class MultiJdbcSchemaJoinTest {
     Statement stmt = calciteConnection.createStatement();
     try {
       ResultSet rs;
-      if (CalcitePrepareImpl.DEBUG) {
+      if (CalciteSystemProperty.DEBUG.value()) {
         rs = stmt.executeQuery("explain plan for " + query);
         rs.next();
         System.out.println(rs.getString(1));
diff --git a/core/src/test/java/org/apache/calcite/test/RelMetadataTest.java 
b/core/src/test/java/org/apache/calcite/test/RelMetadataTest.java
index 3eda72d..2e0fef2 100644
--- a/core/src/test/java/org/apache/calcite/test/RelMetadataTest.java
+++ b/core/src/test/java/org/apache/calcite/test/RelMetadataTest.java
@@ -17,6 +17,7 @@
 package org.apache.calcite.test;
 
 import org.apache.calcite.adapter.enumerable.EnumerableMergeJoin;
+import org.apache.calcite.config.CalciteSystemProperty;
 import org.apache.calcite.linq4j.tree.Types;
 import org.apache.calcite.plan.RelOptCluster;
 import org.apache.calcite.plan.RelOptPlanner;
@@ -90,7 +91,6 @@ import org.apache.calcite.tools.RelBuilder;
 import org.apache.calcite.util.BuiltInMethod;
 import org.apache.calcite.util.ImmutableBitSet;
 import org.apache.calcite.util.ImmutableIntList;
-import org.apache.calcite.util.SaffronProperties;
 import org.apache.calcite.util.TestUtil;
 
 import com.google.common.collect.ImmutableList;
@@ -794,10 +794,10 @@ public class RelMetadataTest extends SqlToRelTestBase {
    * OutOfMemoryError</a>. */
   @Test public void testMetadataHandlerCacheLimit() {
     Assume.assumeTrue("too slow to run every day, and it does not reproduce 
the issue",
-        CalciteAssert.ENABLE_SLOW);
+        CalciteSystemProperty.TEST_SLOW.value());
     Assume.assumeTrue("If cache size is too large, this test may fail and the "
             + "test won't be to blame",
-        SaffronProperties.INSTANCE.metadataHandlerCacheMaximumSize().get()
+        CalciteSystemProperty.METADATA_HANDLER_CACHE_MAXIMUM_SIZE.value()
             < 10_000);
     final int iterationCount = 2_000;
     final RelNode rel = convertSql("select * from emp");
diff --git a/core/src/test/java/org/apache/calcite/test/RexProgramTest.java 
b/core/src/test/java/org/apache/calcite/test/RexProgramTest.java
index f0ddfe8..3b5454f 100644
--- a/core/src/test/java/org/apache/calcite/test/RexProgramTest.java
+++ b/core/src/test/java/org/apache/calcite/test/RexProgramTest.java
@@ -17,6 +17,7 @@
 package org.apache.calcite.test;
 
 import org.apache.calcite.avatica.util.ByteString;
+import org.apache.calcite.config.CalciteSystemProperty;
 import org.apache.calcite.plan.RelOptPredicateList;
 import org.apache.calcite.plan.RelOptUtil;
 import org.apache.calcite.plan.Strong;
@@ -957,7 +958,7 @@ public class RexProgramTest extends RexProgramBuilderBase {
    * to CNF. */
   @Test public void testCnfExponential() {
     // run out of memory if limit is higher than about 20
-    final int limit = CalciteAssert.ENABLE_SLOW ? 16 : 6;
+    final int limit = CalciteSystemProperty.TEST_SLOW.value() ? 16 : 6;
     for (int i = 2; i < limit; i++) {
       checkExponentialCnf(i);
     }
diff --git a/core/src/test/java/org/apache/calcite/tools/FrameworksTest.java 
b/core/src/test/java/org/apache/calcite/tools/FrameworksTest.java
index 06559e6..29c0ec3 100644
--- a/core/src/test/java/org/apache/calcite/tools/FrameworksTest.java
+++ b/core/src/test/java/org/apache/calcite/tools/FrameworksTest.java
@@ -19,6 +19,7 @@ package org.apache.calcite.tools;
 import org.apache.calcite.DataContext;
 import org.apache.calcite.adapter.enumerable.EnumerableConvention;
 import org.apache.calcite.adapter.enumerable.EnumerableTableScan;
+import org.apache.calcite.config.CalciteSystemProperty;
 import org.apache.calcite.linq4j.Enumerable;
 import org.apache.calcite.linq4j.QueryProvider;
 import org.apache.calcite.linq4j.Queryable;
@@ -33,7 +34,6 @@ import org.apache.calcite.plan.RelOptUtil;
 import org.apache.calcite.plan.RelTraitDef;
 import org.apache.calcite.plan.RelTraitSet;
 import org.apache.calcite.plan.volcano.AbstractConverter;
-import org.apache.calcite.prepare.CalcitePrepareImpl;
 import org.apache.calcite.prepare.Prepare;
 import org.apache.calcite.rel.RelDistributionTraitDef;
 import org.apache.calcite.rel.RelNode;
@@ -325,7 +325,7 @@ public class FrameworksTest {
         .programs(Programs.ofRules(Programs.RULE_SET))
         .build();
     executeQuery(config, " UPDATE MYTABLE set id=7 where id=1",
-        CalcitePrepareImpl.DEBUG);
+        CalciteSystemProperty.DEBUG.value());
   }
 
   private void executeQuery(FrameworkConfig config,
diff --git a/core/src/test/java/org/apache/calcite/tools/PlannerTest.java 
b/core/src/test/java/org/apache/calcite/tools/PlannerTest.java
index bb706f7..802756a 100644
--- a/core/src/test/java/org/apache/calcite/tools/PlannerTest.java
+++ b/core/src/test/java/org/apache/calcite/tools/PlannerTest.java
@@ -25,6 +25,7 @@ import org.apache.calcite.adapter.jdbc.JdbcConvention;
 import org.apache.calcite.adapter.jdbc.JdbcImplementor;
 import org.apache.calcite.adapter.jdbc.JdbcRel;
 import org.apache.calcite.adapter.jdbc.JdbcRules;
+import org.apache.calcite.config.CalciteSystemProperty;
 import org.apache.calcite.config.Lex;
 import org.apache.calcite.plan.ConventionTraitDef;
 import org.apache.calcite.plan.RelOptCluster;
@@ -734,7 +735,7 @@ public class PlannerTest {
     checkJoinNWay(5); // LoptOptimizeJoinRule disabled; takes about .4s
     checkJoinNWay(9); // LoptOptimizeJoinRule enabled; takes about 0.04s
     checkJoinNWay(35); // takes about 2s
-    if (CalciteAssert.ENABLE_SLOW) {
+    if (CalciteSystemProperty.TEST_SLOW.value()) {
       checkJoinNWay(60); // takes about 15s
     }
   }
diff --git 
a/core/src/test/java/org/apache/calcite/util/PartiallyOrderedSetTest.java 
b/core/src/test/java/org/apache/calcite/util/PartiallyOrderedSetTest.java
index 50ca11f..359e86d 100644
--- a/core/src/test/java/org/apache/calcite/util/PartiallyOrderedSetTest.java
+++ b/core/src/test/java/org/apache/calcite/util/PartiallyOrderedSetTest.java
@@ -16,7 +16,7 @@
  */
 package org.apache.calcite.util;
 
-import org.apache.calcite.test.CalciteAssert;
+import org.apache.calcite.config.CalciteSystemProperty;
 import org.apache.calcite.test.SlowTests;
 
 import org.junit.Assume;
@@ -48,7 +48,7 @@ public class PartiallyOrderedSetTest {
   private static final boolean DEBUG = false;
 
   // 100, 250, 1000, 3000 are reasonable
-  private static final int SCALE = CalciteAssert.ENABLE_SLOW ? 250 : 50;
+  private static final int SCALE = CalciteSystemProperty.TEST_SLOW.value() ? 
250 : 50;
 
   final long seed = new Random().nextLong();
   final Random random = new Random(seed);
@@ -216,14 +216,14 @@ public class PartiallyOrderedSetTest {
   @Test public void testPosetBitsLarge() {
     Assume.assumeTrue(
         "it takes 80 seconds, and the computations are exactly the same every 
time",
-        CalciteAssert.ENABLE_SLOW);
+        CalciteSystemProperty.TEST_SLOW.value());
     final PartiallyOrderedSet<Integer> poset =
         new PartiallyOrderedSet<>(PartiallyOrderedSetTest::isBitSuperset);
     checkPosetBitsLarge(poset, 30000, 2921, 164782);
   }
 
   @Test public void testPosetBitsLarge2() {
-    Assume.assumeTrue("too slow to run every day", CalciteAssert.ENABLE_SLOW);
+    Assume.assumeTrue("too slow to run every day", 
CalciteSystemProperty.TEST_SLOW.value());
     final int n = 30000;
     final PartiallyOrderedSet<Integer> poset =
         new PartiallyOrderedSet<>(PartiallyOrderedSetTest::isBitSuperset,
diff --git 
a/druid/src/main/java/org/apache/calcite/adapter/druid/DruidConnectionImpl.java 
b/druid/src/main/java/org/apache/calcite/adapter/druid/DruidConnectionImpl.java
index e1a8f66..09d90f9 100644
--- 
a/druid/src/main/java/org/apache/calcite/adapter/druid/DruidConnectionImpl.java
+++ 
b/druid/src/main/java/org/apache/calcite/adapter/druid/DruidConnectionImpl.java
@@ -19,12 +19,12 @@ package org.apache.calcite.adapter.druid;
 import org.apache.calcite.avatica.AvaticaUtils;
 import org.apache.calcite.avatica.ColumnMetaData;
 import org.apache.calcite.avatica.util.DateTimeUtils;
+import org.apache.calcite.config.CalciteSystemProperty;
 import org.apache.calcite.interpreter.Row;
 import org.apache.calcite.interpreter.Sink;
 import org.apache.calcite.linq4j.AbstractEnumerable;
 import org.apache.calcite.linq4j.Enumerable;
 import org.apache.calcite.linq4j.Enumerator;
-import org.apache.calcite.prepare.CalcitePrepareImpl;
 import org.apache.calcite.sql.type.SqlTypeName;
 import org.apache.calcite.util.Holder;
 import org.apache.calcite.util.Util;
@@ -103,7 +103,7 @@ class DruidConnectionImpl implements DruidConnection {
     final String url = this.url + "/druid/v2/?pretty";
     final Map<String, String> requestHeaders =
         ImmutableMap.of("Content-Type", "application/json");
-    if (CalcitePrepareImpl.DEBUG) {
+    if (CalciteSystemProperty.DEBUG.value()) {
       System.out.println(data);
     }
     try (InputStream in0 = post(url, data, requestHeaders, 10000, 1800000);
@@ -122,7 +122,7 @@ class DruidConnectionImpl implements DruidConnection {
     final JsonFactory factory = new JsonFactory();
     final Row.RowBuilder rowBuilder = Row.newBuilder(fieldNames.size());
 
-    if (CalcitePrepareImpl.DEBUG) {
+    if (CalciteSystemProperty.DEBUG.value()) {
       try {
         final byte[] bytes = AvaticaUtils.readFullyToBytes(in);
         System.out.println("Response: "
@@ -565,7 +565,7 @@ class DruidConnectionImpl implements DruidConnection {
     final Map<String, String> requestHeaders =
         ImmutableMap.of("Content-Type", "application/json");
     final String data = DruidQuery.metadataQuery(dataSourceName, intervals);
-    if (CalcitePrepareImpl.DEBUG) {
+    if (CalciteSystemProperty.DEBUG.value()) {
       System.out.println("Druid: " + data);
     }
     try (InputStream in0 = post(url, data, requestHeaders, 10000, 1800000);
@@ -624,7 +624,7 @@ class DruidConnectionImpl implements DruidConnection {
         ImmutableMap.of("Content-Type", "application/json");
     final String data = null;
     final String url = coordinatorUrl + 
"/druid/coordinator/v1/metadata/datasources";
-    if (CalcitePrepareImpl.DEBUG) {
+    if (CalciteSystemProperty.DEBUG.value()) {
       System.out.println("Druid: table names" + data + "; " + url);
     }
     try (InputStream in0 = post(url, data, requestHeaders, 10000, 1800000);
@@ -641,7 +641,7 @@ class DruidConnectionImpl implements DruidConnection {
   }
 
   private InputStream traceResponse(InputStream in) {
-    if (CalcitePrepareImpl.DEBUG) {
+    if (CalciteSystemProperty.DEBUG.value()) {
       try {
         final byte[] bytes = AvaticaUtils.readFullyToBytes(in);
         in.close();
diff --git a/druid/src/test/java/org/apache/calcite/test/DruidAdapterIT.java 
b/druid/src/test/java/org/apache/calcite/test/DruidAdapterIT.java
index a6a5ca5..f4bcaf6 100644
--- a/druid/src/test/java/org/apache/calcite/test/DruidAdapterIT.java
+++ b/druid/src/test/java/org/apache/calcite/test/DruidAdapterIT.java
@@ -20,13 +20,12 @@ import org.apache.calcite.adapter.druid.DruidQuery;
 import org.apache.calcite.adapter.druid.DruidSchema;
 import org.apache.calcite.config.CalciteConnectionConfig;
 import org.apache.calcite.config.CalciteConnectionProperty;
-import org.apache.calcite.prepare.CalcitePrepareImpl;
+import org.apache.calcite.config.CalciteSystemProperty;
 import org.apache.calcite.rel.type.RelDataType;
 import org.apache.calcite.schema.impl.AbstractSchema;
 import org.apache.calcite.sql.fun.SqlStdOperatorTable;
 import org.apache.calcite.sql.type.SqlTypeName;
 import org.apache.calcite.util.TestUtil;
-import org.apache.calcite.util.Util;
 
 import com.google.common.collect.ArrayListMultimap;
 import com.google.common.collect.ImmutableList;
@@ -92,12 +91,6 @@ public class DruidAdapterIT {
   public static final URL WIKI_AUTO2 =
       DruidAdapterIT.class.getResource("/druid-wiki-no-tables-model.json");
 
-  /** Whether to run Druid tests. Enabled by default, however test is only
-   * included if "it" profile is activated ({@code -Pit}). To disable,
-   * specify {@code -Dcalcite.test.druid=false} on the Java command line. */
-  public static final boolean ENABLED =
-      Util.getBooleanProperty("calcite.test.druid", true);
-
   private static final String VARCHAR_TYPE =
       "VARCHAR";
 
@@ -105,7 +98,7 @@ public class DruidAdapterIT {
 
   /** Whether to run this test. */
   protected boolean enabled() {
-    return ENABLED;
+    return CalciteSystemProperty.TEST_DRUID.value();
   }
 
   /** Returns a consumer that checks that a particular Druid query is
@@ -386,7 +379,7 @@ public class DruidAdapterIT {
             while (r.next()) {
               map.put(r.getString("TYPE_NAME"), true);
             }
-            if (CalcitePrepareImpl.DEBUG) {
+            if (CalciteSystemProperty.DEBUG.value()) {
               System.out.println(map);
             }
             // 1 timestamp, 2 float measure, 1 int measure, 88 dimensions
diff --git a/druid/src/test/java/org/apache/calcite/test/DruidAdapterIT2.java 
b/druid/src/test/java/org/apache/calcite/test/DruidAdapterIT2.java
index 421e3907..57c6b5b 100644
--- a/druid/src/test/java/org/apache/calcite/test/DruidAdapterIT2.java
+++ b/druid/src/test/java/org/apache/calcite/test/DruidAdapterIT2.java
@@ -20,13 +20,12 @@ import org.apache.calcite.adapter.druid.DruidQuery;
 import org.apache.calcite.adapter.druid.DruidSchema;
 import org.apache.calcite.config.CalciteConnectionConfig;
 import org.apache.calcite.config.CalciteConnectionProperty;
-import org.apache.calcite.prepare.CalcitePrepareImpl;
+import org.apache.calcite.config.CalciteSystemProperty;
 import org.apache.calcite.rel.type.RelDataType;
 import org.apache.calcite.schema.impl.AbstractSchema;
 import org.apache.calcite.sql.fun.SqlStdOperatorTable;
 import org.apache.calcite.sql.type.SqlTypeName;
 import org.apache.calcite.util.TestUtil;
-import org.apache.calcite.util.Util;
 
 import com.google.common.collect.ArrayListMultimap;
 import com.google.common.collect.ImmutableList;
@@ -76,12 +75,6 @@ public class DruidAdapterIT2 {
   public static final URL FOODMART =
       
DruidAdapterIT2.class.getResource("/druid-foodmart-model-timestamp.json");
 
-  /** Whether to run Druid tests. Enabled by default, however test is only
-   * included if "it" profile is activated ({@code -Pit}). To disable,
-   * specify {@code -Dcalcite.test.druid=false} on the Java command line. */
-  public static final boolean ENABLED =
-      Util.getBooleanProperty("calcite.test.druid", true);
-
   private static final String VARCHAR_TYPE =
       "VARCHAR";
 
@@ -89,7 +82,7 @@ public class DruidAdapterIT2 {
 
   /** Whether to run this test. */
   protected boolean enabled() {
-    return ENABLED;
+    return CalciteSystemProperty.TEST_DRUID.value();
   }
 
   /** Returns a function that checks that a particular Druid query is
@@ -146,7 +139,7 @@ public class DruidAdapterIT2 {
             while (r.next()) {
               map.put(r.getString("TYPE_NAME"), true);
             }
-            if (CalcitePrepareImpl.DEBUG) {
+            if (CalciteSystemProperty.DEBUG.value()) {
               System.out.println(map);
             }
             // 1 timestamp, 2 float measure, 1 int measure, 88 dimensions
diff --git 
a/mongodb/src/main/java/org/apache/calcite/adapter/mongodb/MongoToEnumerableConverter.java
 
b/mongodb/src/main/java/org/apache/calcite/adapter/mongodb/MongoToEnumerableConverter.java
index 53a8668..cdc9863 100644
--- 
a/mongodb/src/main/java/org/apache/calcite/adapter/mongodb/MongoToEnumerableConverter.java
+++ 
b/mongodb/src/main/java/org/apache/calcite/adapter/mongodb/MongoToEnumerableConverter.java
@@ -21,6 +21,7 @@ import 
org.apache.calcite.adapter.enumerable.EnumerableRelImplementor;
 import org.apache.calcite.adapter.enumerable.JavaRowFormat;
 import org.apache.calcite.adapter.enumerable.PhysType;
 import org.apache.calcite.adapter.enumerable.PhysTypeImpl;
+import org.apache.calcite.config.CalciteSystemProperty;
 import org.apache.calcite.linq4j.tree.BlockBuilder;
 import org.apache.calcite.linq4j.tree.Expression;
 import org.apache.calcite.linq4j.tree.Expressions;
@@ -30,7 +31,6 @@ import org.apache.calcite.plan.RelOptCluster;
 import org.apache.calcite.plan.RelOptCost;
 import org.apache.calcite.plan.RelOptPlanner;
 import org.apache.calcite.plan.RelTraitSet;
-import org.apache.calcite.prepare.CalcitePrepareImpl;
 import org.apache.calcite.rel.RelNode;
 import org.apache.calcite.rel.convert.ConverterImpl;
 import org.apache.calcite.rel.metadata.RelMetadataQuery;
@@ -129,7 +129,7 @@ public class MongoToEnumerableConverter
         list.append("enumerable",
             Expressions.call(table,
                 MongoMethod.MONGO_QUERYABLE_AGGREGATE.method, fields, ops));
-    if (CalcitePrepareImpl.DEBUG) {
+    if (CalciteSystemProperty.DEBUG.value()) {
       System.out.println("Mongo: " + opList);
     }
     Hook.QUERY_PLAN.run(opList);
diff --git a/mongodb/src/test/java/org/apache/calcite/test/MongoAssertions.java 
b/mongodb/src/test/java/org/apache/calcite/test/MongoAssertions.java
index 2974179..5761af5 100644
--- a/mongodb/src/test/java/org/apache/calcite/test/MongoAssertions.java
+++ b/mongodb/src/test/java/org/apache/calcite/test/MongoAssertions.java
@@ -16,8 +16,8 @@
  */
 package org.apache.calcite.test;
 
+import org.apache.calcite.config.CalciteSystemProperty;
 import org.apache.calcite.util.TestUtil;
-import org.apache.calcite.util.Util;
 
 import com.google.common.collect.Ordering;
 
@@ -80,8 +80,8 @@ public class MongoAssertions {
    * @return Whether current tests should use an external mongo instance
    */
   public static boolean useMongo() {
-    return Util.getBooleanProperty("calcite.integrationTest")
-            && Util.getBooleanProperty("calcite.test.mongodb", true);
+    return CalciteSystemProperty.INTEGRATION_TEST.value()
+            && CalciteSystemProperty.TEST_MONGODB.value();
   }
 
   /**
diff --git a/plus/src/test/java/org/apache/calcite/adapter/tpcds/TpcdsTest.java 
b/plus/src/test/java/org/apache/calcite/adapter/tpcds/TpcdsTest.java
index a4ee925..3be02f6 100644
--- a/plus/src/test/java/org/apache/calcite/adapter/tpcds/TpcdsTest.java
+++ b/plus/src/test/java/org/apache/calcite/adapter/tpcds/TpcdsTest.java
@@ -16,6 +16,7 @@
  */
 package org.apache.calcite.adapter.tpcds;
 
+import org.apache.calcite.config.CalciteSystemProperty;
 import org.apache.calcite.plan.RelOptUtil;
 import org.apache.calcite.plan.RelTraitDef;
 import org.apache.calcite.rel.RelNode;
@@ -43,9 +44,8 @@ import java.util.function.Consumer;
 
 /** Unit test for {@link org.apache.calcite.adapter.tpcds.TpcdsSchema}.
  *
- * <p>Only runs if {@code -Dcalcite.test.slow} is specified on the
- * command-line.
- * (See {@link org.apache.calcite.test.CalciteAssert#ENABLE_SLOW}.)</p> */
+ * <p>Only runs if {@link 
org.apache.calcite.config.CalciteSystemProperty#TEST_SLOW} is set.</p>
+ */
 public class TpcdsTest {
   private static Consumer<Holder<Program>> handler(
       final boolean bushy, final int minJoinCount) {
@@ -80,7 +80,7 @@ public class TpcdsTest {
 
   private CalciteAssert.AssertThat with() {
     return CalciteAssert.model(TPCDS_MODEL)
-        .enable(CalciteAssert.ENABLE_SLOW);
+        .enable(CalciteSystemProperty.TEST_SLOW.value());
   }
 
   @Test public void testCallCenter() {
diff --git a/plus/src/test/java/org/apache/calcite/adapter/tpch/TpchTest.java 
b/plus/src/test/java/org/apache/calcite/adapter/tpch/TpchTest.java
index 3d9de10..1199559 100644
--- a/plus/src/test/java/org/apache/calcite/adapter/tpch/TpchTest.java
+++ b/plus/src/test/java/org/apache/calcite/adapter/tpch/TpchTest.java
@@ -16,6 +16,7 @@
  */
 package org.apache.calcite.adapter.tpch;
 
+import org.apache.calcite.config.CalciteSystemProperty;
 import org.apache.calcite.plan.RelOptUtil;
 import org.apache.calcite.test.CalciteAssert;
 import org.apache.calcite.util.TestUtil;
@@ -36,11 +37,11 @@ import static org.junit.Assert.assertThat;
  *
  * <p>Because the TPC-H data generator takes time and memory to instantiate,
  * tests that read data (that is, most tests) only run
- * if {@code -Dcalcite.test.slow} is specified on the command-line.
- * (See {@link org.apache.calcite.test.CalciteAssert#ENABLE_SLOW}.)</p> */
+ * if {@link org.apache.calcite.config.CalciteSystemProperty#TEST_SLOW} is 
set.</p>
+ */
 public class TpchTest {
   public static final boolean ENABLE =
-      CalciteAssert.ENABLE_SLOW && TestUtil.getJavaMajorVersion() >= 7;
+      CalciteSystemProperty.TEST_SLOW.value() && 
TestUtil.getJavaMajorVersion() >= 7;
 
   private static String schema(String name, String scaleFactor) {
     return "     {\n"
diff --git 
a/plus/src/test/java/org/apache/calcite/materialize/TpcdsLatticeSuggesterTest.java
 
b/plus/src/test/java/org/apache/calcite/materialize/TpcdsLatticeSuggesterTest.java
index 0bb7f36..8d245f7 100644
--- 
a/plus/src/test/java/org/apache/calcite/materialize/TpcdsLatticeSuggesterTest.java
+++ 
b/plus/src/test/java/org/apache/calcite/materialize/TpcdsLatticeSuggesterTest.java
@@ -19,8 +19,8 @@ package org.apache.calcite.materialize;
 import org.apache.calcite.adapter.tpcds.TpcdsSchema;
 import org.apache.calcite.config.CalciteConnectionConfigImpl;
 import org.apache.calcite.config.CalciteConnectionProperty;
+import org.apache.calcite.config.CalciteSystemProperty;
 import org.apache.calcite.plan.Contexts;
-import org.apache.calcite.prepare.CalcitePrepareImpl;
 import org.apache.calcite.prepare.PlannerImpl;
 import org.apache.calcite.rel.RelRoot;
 import org.apache.calcite.schema.SchemaPlus;
@@ -70,7 +70,7 @@ public class TpcdsLatticeSuggesterTest {
           .replaceAll("14 days", "interval '14' day")
           .replaceAll("substr\\(([^,]*),([^,]*),([^)]*)\\)",
               "substring($1 from $2 for $3)");
-      if (CalcitePrepareImpl.DEBUG) {
+      if (CalciteSystemProperty.DEBUG.value()) {
         System.out.println("Query #" + query.id + "\n"
             + number(sql));
       }
diff --git 
a/spark/src/main/java/org/apache/calcite/adapter/spark/JdbcToSparkConverter.java
 
b/spark/src/main/java/org/apache/calcite/adapter/spark/JdbcToSparkConverter.java
index 14d105e..27699a4 100644
--- 
a/spark/src/main/java/org/apache/calcite/adapter/spark/JdbcToSparkConverter.java
+++ 
b/spark/src/main/java/org/apache/calcite/adapter/spark/JdbcToSparkConverter.java
@@ -24,6 +24,7 @@ import org.apache.calcite.adapter.jdbc.JdbcConvention;
 import org.apache.calcite.adapter.jdbc.JdbcImplementor;
 import org.apache.calcite.adapter.jdbc.JdbcRel;
 import org.apache.calcite.adapter.jdbc.JdbcSchema;
+import org.apache.calcite.config.CalciteSystemProperty;
 import org.apache.calcite.linq4j.tree.BlockBuilder;
 import org.apache.calcite.linq4j.tree.Expression;
 import org.apache.calcite.linq4j.tree.Expressions;
@@ -33,7 +34,6 @@ import org.apache.calcite.plan.RelOptCluster;
 import org.apache.calcite.plan.RelOptCost;
 import org.apache.calcite.plan.RelOptPlanner;
 import org.apache.calcite.plan.RelTraitSet;
-import org.apache.calcite.prepare.CalcitePrepareImpl;
 import org.apache.calcite.rel.RelNode;
 import org.apache.calcite.rel.convert.ConverterImpl;
 import org.apache.calcite.rel.metadata.RelMetadataQuery;
@@ -77,7 +77,7 @@ public class JdbcToSparkConverter
     final JdbcConvention jdbcConvention =
         (JdbcConvention) child.getConvention();
     String sql = generateSql(jdbcConvention.dialect);
-    if (CalcitePrepareImpl.DEBUG) {
+    if (CalciteSystemProperty.DEBUG.value()) {
       System.out.println("[" + sql + "]");
     }
     final Expression sqlLiteral =
diff --git 
a/spark/src/main/java/org/apache/calcite/adapter/spark/SparkHandlerImpl.java 
b/spark/src/main/java/org/apache/calcite/adapter/spark/SparkHandlerImpl.java
index 811a047..325c496 100644
--- a/spark/src/main/java/org/apache/calcite/adapter/spark/SparkHandlerImpl.java
+++ b/spark/src/main/java/org/apache/calcite/adapter/spark/SparkHandlerImpl.java
@@ -17,11 +17,11 @@
 package org.apache.calcite.adapter.spark;
 
 import org.apache.calcite.adapter.enumerable.EnumerableRules;
+import org.apache.calcite.config.CalciteSystemProperty;
 import org.apache.calcite.jdbc.CalcitePrepare;
 import org.apache.calcite.linq4j.tree.ClassDeclaration;
 import org.apache.calcite.plan.RelOptPlanner;
 import org.apache.calcite.plan.RelOptRule;
-import org.apache.calcite.prepare.CalcitePrepareImpl;
 import org.apache.calcite.rel.RelNode;
 import org.apache.calcite.runtime.ArrayBindable;
 import org.apache.calcite.util.Util;
@@ -113,7 +113,7 @@ public class SparkHandlerImpl implements 
CalcitePrepare.SparkHandler {
         + s + "\n"
         + "}\n";
 
-    if (CalcitePrepareImpl.DEBUG) {
+    if (CalciteSystemProperty.DEBUG.value()) {
       Util.debugCode(System.out, source);
     }
 
diff --git 
a/splunk/src/main/java/org/apache/calcite/adapter/splunk/SplunkTableScan.java 
b/splunk/src/main/java/org/apache/calcite/adapter/splunk/SplunkTableScan.java
index adb2bd5..77a8050 100644
--- 
a/splunk/src/main/java/org/apache/calcite/adapter/splunk/SplunkTableScan.java
+++ 
b/splunk/src/main/java/org/apache/calcite/adapter/splunk/SplunkTableScan.java
@@ -21,6 +21,7 @@ import org.apache.calcite.adapter.enumerable.EnumerableRel;
 import org.apache.calcite.adapter.enumerable.EnumerableRelImplementor;
 import org.apache.calcite.adapter.enumerable.PhysType;
 import org.apache.calcite.adapter.enumerable.PhysTypeImpl;
+import org.apache.calcite.config.CalciteSystemProperty;
 import org.apache.calcite.linq4j.tree.BlockBuilder;
 import org.apache.calcite.linq4j.tree.Expression;
 import org.apache.calcite.linq4j.tree.Expressions;
@@ -28,7 +29,6 @@ import org.apache.calcite.linq4j.tree.Types;
 import org.apache.calcite.plan.RelOptCluster;
 import org.apache.calcite.plan.RelOptPlanner;
 import org.apache.calcite.plan.RelOptTable;
-import org.apache.calcite.prepare.CalcitePrepareImpl;
 import org.apache.calcite.rel.RelWriter;
 import org.apache.calcite.rel.core.TableScan;
 import org.apache.calcite.rel.type.RelDataType;
@@ -125,7 +125,7 @@ public class SplunkTableScan
         .put("latest", Util.first(latest, ""))
         .put("fieldList", fieldList)
         .build();
-    if (CalcitePrepareImpl.DEBUG) {
+    if (CalciteSystemProperty.DEBUG.value()) {
       System.out.println("Splunk: " + map);
     }
     Hook.QUERY_PLAN.run(map);
diff --git 
a/splunk/src/test/java/org/apache/calcite/test/SplunkAdapterTest.java 
b/splunk/src/test/java/org/apache/calcite/test/SplunkAdapterTest.java
index 5cd7b10..e0daff5 100644
--- a/splunk/src/test/java/org/apache/calcite/test/SplunkAdapterTest.java
+++ b/splunk/src/test/java/org/apache/calcite/test/SplunkAdapterTest.java
@@ -16,8 +16,8 @@
  */
 package org.apache.calcite.test;
 
+import org.apache.calcite.config.CalciteSystemProperty;
 import org.apache.calcite.util.TestUtil;
-import org.apache.calcite.util.Util;
 
 import com.google.common.collect.ImmutableSet;
 
@@ -47,16 +47,10 @@ public class SplunkAdapterTest {
   public static final String SPLUNK_USER = "admin";
   public static final String SPLUNK_PASSWORD = "changeme";
 
-  /** Whether to run Splunk tests. Disabled by default, because we do not 
expect
-   * Splunk to be installed and populated data set. To enable,
-   * specify {@code -Dcalcite.test.splunk} on the Java command line. */
-  public static final boolean ENABLED =
-      Util.getBooleanProperty("calcite.test.splunk");
-
   /** Whether this test is enabled. Tests are disabled unless we know that
    * Splunk is present and loaded with the requisite data. */
   private boolean enabled() {
-    return ENABLED;
+    return CalciteSystemProperty.TEST_SPLUNK.value();
   }
 
   private void loadDriverClass() {

Reply via email to