You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@calcite.apache.org by jh...@apache.org on 2024/02/27 01:51:24 UTC

(calcite) branch main updated (85d96207ef -> 2558c13cdb)

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

jhyde pushed a change to branch main
in repository https://gitbox.apache.org/repos/asf/calcite.git


    from 85d96207ef Clarify semantics of SAFE* functions
     new 96485c0ec8 Cosmetic
     new 2558c13cdb [CALCITE-6219] 'Must-filter' columns

The 2 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.


Summary of changes:
 build.gradle.kts                                   |   2 +
 .../adapter/enumerable/EnumerableRelFactories.java |   6 +-
 .../org/apache/calcite/adapter/jdbc/JdbcRules.java |   7 +-
 .../org/apache/calcite/interpreter/Bindables.java  |   5 +-
 .../apache/calcite/jdbc/CalciteConnectionImpl.java |   5 +-
 .../org/apache/calcite/jdbc/CalcitePrepare.java    |   5 +-
 .../org/apache/calcite/jdbc/CalciteSchema.java     |   5 +-
 .../org/apache/calcite/materialize/Lattice.java    |   9 +-
 .../apache/calcite/materialize/LatticeNode.java    |   7 +-
 .../calcite/materialize/MaterializationActor.java  |   5 +-
 .../org/apache/calcite/profile/ProfilerImpl.java   |  11 +-
 .../org/apache/calcite/rel/RelCollationImpl.java   |   6 +-
 .../org/apache/calcite/rel/core/AggregateCall.java |   9 +-
 .../java/org/apache/calcite/rel/core/Match.java    |   5 +-
 .../java/org/apache/calcite/rel/core/SetOp.java    |   5 +-
 .../org/apache/calcite/rel/core/TableModify.java   |  11 +-
 .../java/org/apache/calcite/rel/hint/RelHint.java  |  11 +-
 .../metadata/ReflectiveRelMetadataProvider.java    |   5 +-
 .../calcite/rel/metadata/RelMdUniqueKeys.java      |   5 +-
 .../org/apache/calcite/rel/metadata/RelMdUtil.java |   7 +-
 .../AggregateExpandDistinctAggregatesRule.java     |   9 +-
 .../apache/calcite/rel/rules/CalcRelSplitter.java  |   6 +-
 .../calcite/rel/rules/ProjectToWindowRule.java     |   5 +-
 .../materialize/MaterializedViewAggregateRule.java |   5 +-
 .../java/org/apache/calcite/rex/RexBuilder.java    |   6 +-
 .../org/apache/calcite/rex/RexFieldAccess.java     |   7 +-
 .../java/org/apache/calcite/rex/RexLiteral.java    |   9 +-
 .../main/java/org/apache/calcite/rex/RexOver.java  |   6 +-
 .../java/org/apache/calcite/rex/RexSubQuery.java   |   5 +-
 .../java/org/apache/calcite/rex/RexWindow.java     |   5 +-
 .../apache/calcite/runtime/AutomatonBuilder.java   |   8 +-
 .../apache/calcite/runtime/CalciteException.java   |   3 +-
 .../apache/calcite/runtime/CalciteResource.java    |   3 +
 .../java/org/apache/calcite/runtime/Pattern.java   |   7 +-
 .../java/org/apache/calcite/schema/Schemas.java    |   5 +-
 .../java/org/apache/calcite/sql/SqlDialect.java    |   7 +-
 .../calcite/sql/SqlGroupedWindowFunction.java      |   8 +-
 .../main/java/org/apache/calcite/sql/SqlJoin.java  |   6 +-
 .../org/apache/calcite/sql/SqlMatchRecognize.java  |  12 +-
 .../calcite/sql/SqlNullTreatmentOperator.java      |   6 +-
 .../org/apache/calcite/sql/SqlTimeLiteral.java     |   6 +-
 .../apache/calcite/sql/SqlTimestampLiteral.java    |   8 +-
 .../apache/calcite/sql/SqlWindowTableFunction.java |   5 +-
 .../calcite/sql/advise/SqlAdvisorValidator.java    |   2 +-
 .../calcite/sql/ddl/SqlCreateForeignSchema.java    |   5 +-
 .../apache/calcite/sql/ddl/SqlCreateFunction.java  |   8 +-
 .../apache/calcite/sql/ddl/SqlCreateTableLike.java |  22 +-
 .../calcite/sql/dialect/PrestoSqlDialect.java      |   5 +-
 .../calcite/sql/fun/SqlAnyValueAggFunction.java    |   6 +-
 .../apache/calcite/sql/fun/SqlAvgAggFunction.java  |   4 +-
 .../calcite/sql/fun/SqlBitOpAggFunction.java       |   8 +-
 .../calcite/sql/fun/SqlCovarAggFunction.java       |   4 +-
 .../sql/fun/SqlFirstLastValueAggFunction.java      |   6 +-
 .../apache/calcite/sql/fun/SqlFloorFunction.java   |   6 +-
 .../calcite/sql/fun/SqlLeadLagAggFunction.java     |   5 +-
 .../org/apache/calcite/sql/fun/SqlLibrary.java     |   6 +-
 .../calcite/sql/fun/SqlMinMaxAggFunction.java      |   6 +-
 .../calcite/sql/fun/SqlQuantifyOperator.java       |   8 +-
 .../calcite/sql/fun/SqlRegrCountAggFunction.java   |   4 +-
 .../apache/calcite/sql/parser/SqlParserUtil.java   |  12 +-
 .../apache/calcite/sql/pretty/SqlPrettyWriter.java |   5 +-
 .../org/apache/calcite/sql/type/BasicSqlType.java  |   6 +-
 .../calcite/sql/type/MatchReturnTypeInference.java |   7 +-
 .../org/apache/calcite/sql/type/ReturnTypes.java   |   7 +-
 .../calcite/sql/type/SqlOperandCountRanges.java    |   6 +-
 .../sql/type/SqlReturnTypeInferenceChain.java      |   5 +-
 .../calcite/sql/type/SqlTypeTransformCascade.java  |   5 +-
 .../org/apache/calcite/sql/type/SqlTypeUtil.java   |  19 +-
 .../calcite/sql/validate/AbstractNamespace.java    |  34 ++--
 .../calcite/sql/validate/DelegatingNamespace.java  |   2 +-
 .../calcite/sql/validate/DelegatingScope.java      |   6 +-
 .../calcite/sql/validate/IdentifierNamespace.java  |  47 ++---
 .../org/apache/calcite/sql/validate/ListScope.java |   4 +-
 .../{LambdaNamespace.java => SemanticTable.java}   |  46 ++---
 .../calcite/sql/validate/SqlLambdaScope.java       |   6 +-
 .../apache/calcite/sql/validate/SqlQualified.java  |  27 ++-
 .../calcite/sql/validate/SqlValidatorImpl.java     | 156 +++++++++++---
 .../sql/validate/SqlValidatorNamespace.java        |   9 +-
 .../calcite/sql/validate/SqlValidatorUtil.java     |  14 +-
 .../calcite/sql/validate/TableNamespace.java       |  11 +
 .../calcite/sql/validate/WithItemNamespace.java    |   1 +
 .../apache/calcite/sql/validate/WithNamespace.java |   6 +
 .../calcite/sql2rel/ReflectiveConvertletTable.java |   7 +-
 .../calcite/sql2rel/SqlNodeToRexConverterImpl.java |   7 +-
 .../calcite/sql2rel/StandardConvertletTable.java   |   3 +-
 .../main/java/org/apache/calcite/tools/Hoist.java  |  11 +-
 .../java/org/apache/calcite/tools/RelBuilder.java  |   4 +-
 .../java/org/apache/calcite/util/DateString.java   |  17 +-
 .../java/org/apache/calcite/util/JdbcTypeImpl.java |  10 +-
 .../calcite/util/TimeWithTimeZoneString.java       |  14 +-
 .../org/apache/calcite/util/TimestampString.java   |   2 +-
 .../calcite/util/TimestampWithTimeZoneString.java  |  14 +-
 .../calcite/runtime/CalciteResource.properties     |   1 +
 .../calcite/test/SqlValidatorFeatureTest.java      |  19 +-
 .../org/apache/calcite/test/SqlValidatorTest.java  | 223 +++++++++++++++++++++
 .../apache/calcite/adapter/druid/DruidTable.java   |   7 +-
 .../adapter/elasticsearch/ElasticsearchSchema.java |   5 +-
 .../elasticsearch/ElasticsearchSchemaFactory.java  |   5 +-
 .../adapter/elasticsearch/PredicateAnalyzer.java   |  12 +-
 .../calcite/adapter/elasticsearch/Scrolling.java   |   7 +-
 .../elasticsearch/EmbeddedElasticsearchNode.java   |  10 +-
 .../calcite/adapter/geode/rel/GeodeFilter.java     |   7 +-
 .../calcite/adapter/geode/rel/GeodeRules.java      |   5 +-
 .../adapter/geode/rel/GeodeEmbeddedPolicy.java     |   8 +-
 .../calcite/adapter/innodb/IndexCondition.java     |   2 +-
 .../org/apache/calcite/linq4j/ModularInteger.java  |   6 +-
 .../org/apache/calcite/adapter/pig/PigFilter.java  |   6 +-
 .../calcite/adapter/pig/PigRelFactories.java       |   5 +-
 .../calcite/adapter/redis/RedisSchemaFactory.java  |  12 +-
 .../apache/calcite/server/ServerDdlExecutor.java   |   9 +-
 .../java/org/apache/calcite/test/Matchers.java     |   4 +-
 .../apache/calcite/test/RelMetadataFixture.java    |   5 +-
 .../apache/calcite/test/SqlValidatorFixture.java   |   6 +-
 .../calcite/test/catalog/MockCatalogReader.java    |  65 +++++-
 .../test/catalog/MustFilterMockCatalogReader.java  |  84 ++++++++
 .../calcite/benchmarks/PreconditionTest.java       |   6 +-
 116 files changed, 995 insertions(+), 437 deletions(-)
 copy core/src/main/java/org/apache/calcite/sql/validate/{LambdaNamespace.java => SemanticTable.java} (52%)
 create mode 100644 testkit/src/main/java/org/apache/calcite/test/catalog/MustFilterMockCatalogReader.java


(calcite) 01/02: Cosmetic

Posted by jh...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

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

commit 96485c0ec8366d04f08f5c9a72bbee5b47503d6e
Author: Julian Hyde <jh...@apache.org>
AuthorDate: Fri Feb 16 21:45:19 2024 -0800

    Cosmetic
    
    Require that Preconditions.checkArgument is used via static import;
    and other changes that do not affect functionality.
---
 build.gradle.kts                                   |  2 +
 .../adapter/enumerable/EnumerableRelFactories.java |  6 +--
 .../org/apache/calcite/adapter/jdbc/JdbcRules.java |  7 +--
 .../org/apache/calcite/interpreter/Bindables.java  |  5 +-
 .../apache/calcite/jdbc/CalciteConnectionImpl.java |  5 +-
 .../org/apache/calcite/jdbc/CalcitePrepare.java    |  5 +-
 .../org/apache/calcite/jdbc/CalciteSchema.java     |  5 +-
 .../org/apache/calcite/materialize/Lattice.java    |  9 ++--
 .../apache/calcite/materialize/LatticeNode.java    |  7 +--
 .../calcite/materialize/MaterializationActor.java  |  5 +-
 .../org/apache/calcite/profile/ProfilerImpl.java   | 11 ++--
 .../org/apache/calcite/rel/RelCollationImpl.java   |  6 +--
 .../org/apache/calcite/rel/core/AggregateCall.java |  9 ++--
 .../java/org/apache/calcite/rel/core/Match.java    |  5 +-
 .../java/org/apache/calcite/rel/core/SetOp.java    |  5 +-
 .../org/apache/calcite/rel/core/TableModify.java   | 11 ++--
 .../java/org/apache/calcite/rel/hint/RelHint.java  | 11 ++--
 .../metadata/ReflectiveRelMetadataProvider.java    |  5 +-
 .../calcite/rel/metadata/RelMdUniqueKeys.java      |  5 +-
 .../org/apache/calcite/rel/metadata/RelMdUtil.java |  7 +--
 .../AggregateExpandDistinctAggregatesRule.java     |  9 ++--
 .../apache/calcite/rel/rules/CalcRelSplitter.java  |  6 +--
 .../calcite/rel/rules/ProjectToWindowRule.java     |  5 +-
 .../materialize/MaterializedViewAggregateRule.java |  5 +-
 .../java/org/apache/calcite/rex/RexBuilder.java    |  6 +--
 .../org/apache/calcite/rex/RexFieldAccess.java     |  7 ++-
 .../java/org/apache/calcite/rex/RexLiteral.java    |  9 ++--
 .../main/java/org/apache/calcite/rex/RexOver.java  |  6 +--
 .../java/org/apache/calcite/rex/RexSubQuery.java   |  5 +-
 .../java/org/apache/calcite/rex/RexWindow.java     |  5 +-
 .../apache/calcite/runtime/AutomatonBuilder.java   |  8 +--
 .../apache/calcite/runtime/CalciteException.java   |  3 +-
 .../java/org/apache/calcite/runtime/Pattern.java   |  7 +--
 .../java/org/apache/calcite/schema/Schemas.java    |  5 +-
 .../java/org/apache/calcite/sql/SqlDialect.java    |  7 +--
 .../calcite/sql/SqlGroupedWindowFunction.java      |  8 +--
 .../main/java/org/apache/calcite/sql/SqlJoin.java  |  6 +--
 .../org/apache/calcite/sql/SqlMatchRecognize.java  | 12 ++---
 .../calcite/sql/SqlNullTreatmentOperator.java      |  6 +--
 .../org/apache/calcite/sql/SqlTimeLiteral.java     |  6 +--
 .../apache/calcite/sql/SqlTimestampLiteral.java    |  8 +--
 .../apache/calcite/sql/SqlWindowTableFunction.java |  5 +-
 .../calcite/sql/advise/SqlAdvisorValidator.java    |  2 +-
 .../calcite/sql/ddl/SqlCreateForeignSchema.java    |  5 +-
 .../apache/calcite/sql/ddl/SqlCreateFunction.java  |  8 +--
 .../apache/calcite/sql/ddl/SqlCreateTableLike.java | 22 ++++----
 .../calcite/sql/dialect/PrestoSqlDialect.java      |  5 +-
 .../calcite/sql/fun/SqlAnyValueAggFunction.java    |  6 +--
 .../apache/calcite/sql/fun/SqlAvgAggFunction.java  |  4 +-
 .../calcite/sql/fun/SqlBitOpAggFunction.java       |  8 +--
 .../calcite/sql/fun/SqlCovarAggFunction.java       |  4 +-
 .../sql/fun/SqlFirstLastValueAggFunction.java      |  6 +--
 .../apache/calcite/sql/fun/SqlFloorFunction.java   |  6 +--
 .../calcite/sql/fun/SqlLeadLagAggFunction.java     |  5 +-
 .../org/apache/calcite/sql/fun/SqlLibrary.java     |  6 +--
 .../calcite/sql/fun/SqlMinMaxAggFunction.java      |  6 +--
 .../calcite/sql/fun/SqlQuantifyOperator.java       |  8 +--
 .../calcite/sql/fun/SqlRegrCountAggFunction.java   |  4 +-
 .../apache/calcite/sql/parser/SqlParserUtil.java   | 12 ++---
 .../apache/calcite/sql/pretty/SqlPrettyWriter.java |  5 +-
 .../org/apache/calcite/sql/type/BasicSqlType.java  |  6 +--
 .../calcite/sql/type/MatchReturnTypeInference.java |  7 +--
 .../org/apache/calcite/sql/type/ReturnTypes.java   |  7 ++-
 .../calcite/sql/type/SqlOperandCountRanges.java    |  6 +--
 .../sql/type/SqlReturnTypeInferenceChain.java      |  5 +-
 .../calcite/sql/type/SqlTypeTransformCascade.java  |  5 +-
 .../org/apache/calcite/sql/type/SqlTypeUtil.java   | 19 ++++---
 .../calcite/sql/validate/AbstractNamespace.java    | 24 ++++-----
 .../calcite/sql/validate/DelegatingNamespace.java  |  2 +-
 .../calcite/sql/validate/DelegatingScope.java      |  6 +--
 .../calcite/sql/validate/IdentifierNamespace.java  | 46 ++++++++---------
 .../org/apache/calcite/sql/validate/ListScope.java |  4 +-
 .../calcite/sql/validate/SqlLambdaScope.java       |  6 +--
 .../apache/calcite/sql/validate/SqlQualified.java  |  2 +-
 .../calcite/sql/validate/SqlValidatorImpl.java     | 60 ++++++++++++----------
 .../sql/validate/SqlValidatorNamespace.java        |  2 +-
 .../calcite/sql/validate/SqlValidatorUtil.java     | 11 ++--
 .../calcite/sql2rel/ReflectiveConvertletTable.java |  7 ++-
 .../calcite/sql2rel/SqlNodeToRexConverterImpl.java |  7 ++-
 .../calcite/sql2rel/StandardConvertletTable.java   |  3 +-
 .../main/java/org/apache/calcite/tools/Hoist.java  | 11 ++--
 .../java/org/apache/calcite/tools/RelBuilder.java  |  4 +-
 .../java/org/apache/calcite/util/DateString.java   | 17 +++---
 .../java/org/apache/calcite/util/JdbcTypeImpl.java | 10 ++--
 .../calcite/util/TimeWithTimeZoneString.java       | 14 ++---
 .../org/apache/calcite/util/TimestampString.java   |  2 +-
 .../calcite/util/TimestampWithTimeZoneString.java  | 14 ++---
 .../calcite/test/SqlValidatorFeatureTest.java      | 19 +++----
 .../apache/calcite/adapter/druid/DruidTable.java   |  7 +--
 .../adapter/elasticsearch/ElasticsearchSchema.java |  5 +-
 .../elasticsearch/ElasticsearchSchemaFactory.java  |  5 +-
 .../adapter/elasticsearch/PredicateAnalyzer.java   | 12 +++--
 .../calcite/adapter/elasticsearch/Scrolling.java   |  7 +--
 .../elasticsearch/EmbeddedElasticsearchNode.java   | 10 ++--
 .../calcite/adapter/geode/rel/GeodeFilter.java     |  7 ++-
 .../calcite/adapter/geode/rel/GeodeRules.java      |  5 +-
 .../adapter/geode/rel/GeodeEmbeddedPolicy.java     |  8 +--
 .../calcite/adapter/innodb/IndexCondition.java     |  2 +-
 .../org/apache/calcite/linq4j/ModularInteger.java  |  6 +--
 .../org/apache/calcite/adapter/pig/PigFilter.java  |  6 +--
 .../calcite/adapter/pig/PigRelFactories.java       |  5 +-
 .../calcite/adapter/redis/RedisSchemaFactory.java  | 12 ++---
 .../apache/calcite/server/ServerDdlExecutor.java   |  9 ++--
 .../java/org/apache/calcite/test/Matchers.java     |  4 +-
 .../apache/calcite/test/RelMetadataFixture.java    |  5 +-
 .../apache/calcite/test/SqlValidatorFixture.java   |  6 +--
 .../calcite/test/catalog/MockCatalogReader.java    | 20 ++++++--
 .../calcite/benchmarks/PreconditionTest.java       |  6 +--
 108 files changed, 461 insertions(+), 409 deletions(-)

diff --git a/build.gradle.kts b/build.gradle.kts
index 0df08ac15c..3ad31fedac 100644
--- a/build.gradle.kts
+++ b/build.gradle.kts
@@ -647,6 +647,8 @@ allprojects {
                     replace("hamcrest: startsWith", "org.hamcrest.core.StringStartsWith.startsWith", "org.hamcrest.CoreMatchers.startsWith")
                     replaceRegex("hamcrest: size", "\\.size\\(\\), (is|equalTo)\\(", ", hasSize\\(")
                     replaceRegex("use static import: toImmutableList", "ImmutableList\\.(toImmutableList\\(\\))", "$1")
+                    replaceRegex("use static import: checkArgument", "Preconditions\\.(checkArgument\\()", "$1")
+                    replaceRegex("use static import: checkArgument", "Preconditions\\.(checkState\\()", "$1")
                     custom("((() preventer", 1) { contents: String ->
                         ParenthesisBalancer.apply(contents)
                     }
diff --git a/core/src/main/java/org/apache/calcite/adapter/enumerable/EnumerableRelFactories.java b/core/src/main/java/org/apache/calcite/adapter/enumerable/EnumerableRelFactories.java
index 05c0890189..38adfd50a1 100644
--- a/core/src/main/java/org/apache/calcite/adapter/enumerable/EnumerableRelFactories.java
+++ b/core/src/main/java/org/apache/calcite/adapter/enumerable/EnumerableRelFactories.java
@@ -26,13 +26,13 @@ import org.apache.calcite.rex.RexNode;
 import org.apache.calcite.rex.RexUtil;
 import org.apache.calcite.sql.validate.SqlValidatorUtil;
 
-import com.google.common.base.Preconditions;
-
 import org.checkerframework.checker.nullness.qual.Nullable;
 
 import java.util.List;
 import java.util.Set;
 
+import static com.google.common.base.Preconditions.checkArgument;
+
 /**
  * Contains factory interface and default implementation for creating various
  * rel nodes.
@@ -72,7 +72,7 @@ public class EnumerableRelFactories {
         List<? extends RexNode> childExprs,
         @Nullable List<? extends @Nullable String> fieldNames,
         Set<CorrelationId> variablesSet) {
-      Preconditions.checkArgument(variablesSet.isEmpty(),
+      checkArgument(variablesSet.isEmpty(),
           "EnumerableProject does not allow variables");
       final RelDataType rowType =
           RexUtil.createStructType(input.getCluster().getTypeFactory(), childExprs,
diff --git a/core/src/main/java/org/apache/calcite/adapter/jdbc/JdbcRules.java b/core/src/main/java/org/apache/calcite/adapter/jdbc/JdbcRules.java
index 29b73a3deb..86503ca492 100644
--- a/core/src/main/java/org/apache/calcite/adapter/jdbc/JdbcRules.java
+++ b/core/src/main/java/org/apache/calcite/adapter/jdbc/JdbcRules.java
@@ -71,7 +71,6 @@ import org.apache.calcite.util.ImmutableBitSet;
 import org.apache.calcite.util.Util;
 import org.apache.calcite.util.trace.CalciteTrace;
 
-import com.google.common.base.Preconditions;
 import com.google.common.collect.ImmutableList;
 import com.google.common.collect.ImmutableSet;
 
@@ -83,6 +82,8 @@ import java.util.List;
 import java.util.Set;
 import java.util.function.Consumer;
 
+import static com.google.common.base.Preconditions.checkArgument;
+
 import static java.util.Objects.requireNonNull;
 
 /**
@@ -98,7 +99,7 @@ public class JdbcRules {
 
   static final RelFactories.ProjectFactory PROJECT_FACTORY =
       (input, hints, projects, fieldNames, variablesSet) -> {
-        Preconditions.checkArgument(variablesSet.isEmpty(),
+        checkArgument(variablesSet.isEmpty(),
             "JdbcProject does not allow variables");
         final RelOptCluster cluster = input.getCluster();
         final RelDataType rowType =
@@ -110,7 +111,7 @@ public class JdbcRules {
 
   static final RelFactories.FilterFactory FILTER_FACTORY =
       (input, condition, variablesSet) -> {
-        Preconditions.checkArgument(variablesSet.isEmpty(),
+        checkArgument(variablesSet.isEmpty(),
             "JdbcFilter does not allow variables");
         return new JdbcFilter(input.getCluster(),
             input.getTraitSet(), input, condition);
diff --git a/core/src/main/java/org/apache/calcite/interpreter/Bindables.java b/core/src/main/java/org/apache/calcite/interpreter/Bindables.java
index 9f879da917..cc52e7c6d8 100644
--- a/core/src/main/java/org/apache/calcite/interpreter/Bindables.java
+++ b/core/src/main/java/org/apache/calcite/interpreter/Bindables.java
@@ -76,7 +76,6 @@ import org.apache.calcite.tools.RelBuilderFactory;
 import org.apache.calcite.util.ImmutableBitSet;
 import org.apache.calcite.util.ImmutableIntList;
 
-import com.google.common.base.Preconditions;
 import com.google.common.collect.ImmutableList;
 import com.google.common.collect.ImmutableSet;
 
@@ -89,6 +88,8 @@ import java.util.Objects;
 import java.util.Set;
 import java.util.SortedSet;
 
+import static com.google.common.base.Preconditions.checkArgument;
+
 /**
  * Utilities pertaining to {@link BindableRel} and {@link BindableConvention}.
  */
@@ -219,7 +220,7 @@ public class Bindables {
       super(cluster, traitSet, ImmutableList.of(), table);
       this.filters = Objects.requireNonNull(filters, "filters");
       this.projects = Objects.requireNonNull(projects, "projects");
-      Preconditions.checkArgument(canHandle(table));
+      checkArgument(canHandle(table));
     }
 
     /** Creates a BindableTableScan. */
diff --git a/core/src/main/java/org/apache/calcite/jdbc/CalciteConnectionImpl.java b/core/src/main/java/org/apache/calcite/jdbc/CalciteConnectionImpl.java
index 12fae54572..073b425657 100644
--- a/core/src/main/java/org/apache/calcite/jdbc/CalciteConnectionImpl.java
+++ b/core/src/main/java/org/apache/calcite/jdbc/CalciteConnectionImpl.java
@@ -68,7 +68,6 @@ import org.apache.calcite.util.BuiltInMethod;
 import org.apache.calcite.util.Holder;
 import org.apache.calcite.util.Util;
 
-import com.google.common.base.Preconditions;
 import com.google.common.collect.ImmutableList;
 import com.google.common.collect.ImmutableMap;
 
@@ -88,6 +87,8 @@ import java.util.TimeZone;
 import java.util.concurrent.atomic.AtomicBoolean;
 import java.util.function.Supplier;
 
+import static com.google.common.base.Preconditions.checkArgument;
+
 import static org.apache.calcite.linq4j.Nullness.castNonNull;
 
 import static java.util.Objects.requireNonNull;
@@ -148,7 +149,7 @@ abstract class CalciteConnectionImpl
         requireNonNull(rootSchema != null
             ? rootSchema
             : CalciteSchema.createRootSchema(true));
-    Preconditions.checkArgument(this.rootSchema.isRoot(), "must be root schema");
+    checkArgument(this.rootSchema.isRoot(), "must be root schema");
     this.properties.put(InternalProperty.CASE_SENSITIVE, cfg.caseSensitive());
     this.properties.put(InternalProperty.UNQUOTED_CASING, cfg.unquotedCasing());
     this.properties.put(InternalProperty.QUOTED_CASING, cfg.quotedCasing());
diff --git a/core/src/main/java/org/apache/calcite/jdbc/CalcitePrepare.java b/core/src/main/java/org/apache/calcite/jdbc/CalcitePrepare.java
index 866cf42930..bda806be90 100644
--- a/core/src/main/java/org/apache/calcite/jdbc/CalcitePrepare.java
+++ b/core/src/main/java/org/apache/calcite/jdbc/CalcitePrepare.java
@@ -47,7 +47,6 @@ import org.apache.calcite.tools.RelRunner;
 import org.apache.calcite.util.ImmutableIntList;
 
 import com.fasterxml.jackson.annotation.JsonIgnore;
-import com.google.common.base.Preconditions;
 import com.google.common.collect.ImmutableList;
 
 import org.checkerframework.checker.nullness.qual.Nullable;
@@ -60,6 +59,8 @@ import java.util.Deque;
 import java.util.List;
 import java.util.Map;
 
+import static com.google.common.base.Preconditions.checkArgument;
+
 import static org.apache.calcite.linq4j.Nullness.castNonNull;
 
 import static java.util.Objects.requireNonNull;
@@ -312,7 +313,7 @@ public interface CalcitePrepare {
       this.constraint = constraint;
       this.columnMapping = columnMapping;
       this.modifiable = modifiable;
-      Preconditions.checkArgument(modifiable == (table != null));
+      checkArgument(modifiable == (table != null));
     }
   }
 
diff --git a/core/src/main/java/org/apache/calcite/jdbc/CalciteSchema.java b/core/src/main/java/org/apache/calcite/jdbc/CalciteSchema.java
index 76e1ba39f1..418b9e1a60 100644
--- a/core/src/main/java/org/apache/calcite/jdbc/CalciteSchema.java
+++ b/core/src/main/java/org/apache/calcite/jdbc/CalciteSchema.java
@@ -34,7 +34,6 @@ import org.apache.calcite.util.NameMultimap;
 import org.apache.calcite.util.NameSet;
 import org.apache.calcite.util.Pair;
 
-import com.google.common.base.Preconditions;
 import com.google.common.collect.ImmutableList;
 import com.google.common.collect.ImmutableSortedMap;
 import com.google.common.collect.ImmutableSortedSet;
@@ -49,6 +48,8 @@ import java.util.NavigableMap;
 import java.util.NavigableSet;
 import java.util.Set;
 
+import static com.google.common.base.Preconditions.checkArgument;
+
 import static java.util.Objects.requireNonNull;
 
 /**
@@ -441,7 +442,7 @@ public abstract class CalciteSchema {
    * @return the schema snapshot.
    */
   public CalciteSchema createSnapshot(SchemaVersion version) {
-    Preconditions.checkArgument(this.isRoot(), "must be root schema");
+    checkArgument(this.isRoot(), "must be root schema");
     return snapshot(null, version);
   }
 
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 596b17769e..95ba02c355 100644
--- a/core/src/main/java/org/apache/calcite/materialize/Lattice.java
+++ b/core/src/main/java/org/apache/calcite/materialize/Lattice.java
@@ -57,7 +57,6 @@ import org.apache.calcite.util.graph.DirectedGraph;
 import org.apache.calcite.util.graph.TopologicalOrderIterator;
 import org.apache.calcite.util.mapping.IntPair;
 
-import com.google.common.base.Preconditions;
 import com.google.common.collect.ImmutableList;
 import com.google.common.collect.ImmutableListMultimap;
 import com.google.common.collect.ImmutableSortedSet;
@@ -86,6 +85,8 @@ import java.util.function.Function;
 import java.util.function.IntFunction;
 import java.util.stream.Collectors;
 
+import static com.google.common.base.Preconditions.checkArgument;
+
 import static org.apache.calcite.linq4j.Nullness.castNonNull;
 
 import static java.util.Objects.requireNonNull;
@@ -130,7 +131,7 @@ public class Lattice {
       // [CALCITE-429] Add statistics SPI for lattice optimization algorithm
       rowCountEstimate = 1000d;
     }
-    Preconditions.checkArgument(rowCountEstimate > 0d);
+    checkArgument(rowCountEstimate > 0d);
     this.rowCountEstimate = rowCountEstimate;
     @SuppressWarnings("argument.type.incompatible")
     LatticeStatisticProvider statisticProvider =
@@ -798,7 +799,7 @@ public class Lattice {
 
     public Builder(LatticeSpace space, CalciteSchema schema, String sql) {
       this.rootSchema = requireNonNull(schema.root());
-      Preconditions.checkArgument(rootSchema.isRoot(), "must be root schema");
+      checkArgument(rootSchema.isRoot(), "must be root schema");
       CalcitePrepare.ConvertResult parsed =
           Schemas.convert(MaterializedViewTable.MATERIALIZATION_CONNECTION,
               schema, schema.path(null), sql);
@@ -934,7 +935,7 @@ public class Lattice {
                   LatticeStatisticProvider.Factory.class,
                   this.statisticProvider)
               : Lattices.CACHED_SQL;
-      Preconditions.checkArgument(rootSchema.isRoot(), "must be root schema");
+      checkArgument(rootSchema.isRoot(), "must be root schema");
       final ImmutableList.Builder<Column> columnBuilder =
           ImmutableList.<Column>builder()
           .addAll(baseColumns)
diff --git a/core/src/main/java/org/apache/calcite/materialize/LatticeNode.java b/core/src/main/java/org/apache/calcite/materialize/LatticeNode.java
index 1e4e458e45..6e8225db15 100644
--- a/core/src/main/java/org/apache/calcite/materialize/LatticeNode.java
+++ b/core/src/main/java/org/apache/calcite/materialize/LatticeNode.java
@@ -19,7 +19,6 @@ package org.apache.calcite.materialize;
 import org.apache.calcite.plan.RelOptTable;
 import org.apache.calcite.util.mapping.IntPair;
 
-import com.google.common.base.Preconditions;
 import com.google.common.collect.ImmutableList;
 
 import org.checkerframework.checker.initialization.qual.Initialized;
@@ -27,6 +26,8 @@ import org.checkerframework.checker.nullness.qual.Nullable;
 
 import java.util.List;
 
+import static com.google.common.base.Preconditions.checkArgument;
+
 import static java.util.Objects.requireNonNull;
 
 /** Source relation of a lattice.
@@ -51,8 +52,8 @@ public abstract class LatticeNode {
     this.startCol = mutableNode.startCol;
     this.endCol = mutableNode.endCol;
     this.alias = mutableNode.alias;
-    Preconditions.checkArgument(startCol >= 0);
-    Preconditions.checkArgument(endCol > startCol);
+    checkArgument(startCol >= 0);
+    checkArgument(endCol > startCol);
 
     final StringBuilder sb = new StringBuilder()
         .append(space.simpleName(table));
diff --git a/core/src/main/java/org/apache/calcite/materialize/MaterializationActor.java b/core/src/main/java/org/apache/calcite/materialize/MaterializationActor.java
index e61bee8597..89a6ea2bf4 100644
--- a/core/src/main/java/org/apache/calcite/materialize/MaterializationActor.java
+++ b/core/src/main/java/org/apache/calcite/materialize/MaterializationActor.java
@@ -19,7 +19,6 @@ package org.apache.calcite.materialize;
 import org.apache.calcite.jdbc.CalciteSchema;
 import org.apache.calcite.rel.type.RelDataType;
 
-import com.google.common.base.Preconditions;
 import com.google.common.collect.HashMultimap;
 import com.google.common.collect.Multimap;
 
@@ -30,6 +29,8 @@ import java.util.List;
 import java.util.Map;
 import java.util.Objects;
 
+import static com.google.common.base.Preconditions.checkArgument;
+
 /**
  * Actor that manages the state of materializations in the system.
  */
@@ -78,7 +79,7 @@ class MaterializationActor {
         @Nullable List<String> viewSchemaPath) {
       this.key = key;
       this.rootSchema = Objects.requireNonNull(rootSchema, "rootSchema");
-      Preconditions.checkArgument(rootSchema.isRoot(), "must be root schema");
+      checkArgument(rootSchema.isRoot(), "must be root schema");
       this.materializedTable = materializedTable; // may be null
       this.sql = sql;
       this.rowType = rowType;
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 0c60f278f1..b37a306800 100644
--- a/core/src/main/java/org/apache/calcite/profile/ProfilerImpl.java
+++ b/core/src/main/java/org/apache/calcite/profile/ProfilerImpl.java
@@ -27,7 +27,6 @@ import org.apache.calcite.util.Pair;
 import org.apache.calcite.util.PartiallyOrderedSet;
 import org.apache.calcite.util.Util;
 
-import com.google.common.base.Preconditions;
 import com.google.common.collect.ImmutableList;
 import com.google.common.collect.ImmutableSortedSet;
 import com.google.common.collect.Iterables;
@@ -57,6 +56,8 @@ import java.util.SortedSet;
 import java.util.TreeSet;
 import java.util.function.Predicate;
 
+import static com.google.common.base.Preconditions.checkArgument;
+
 import static org.apache.calcite.linq4j.Nullness.castNonNull;
 import static org.apache.calcite.profile.ProfilerImpl.CompositeCollector.OF;
 
@@ -96,8 +97,8 @@ public class ProfilerImpl implements Profiler {
    */
   ProfilerImpl(int combinationsPerPass,
       int interestingCount, Predicate<Pair<Space, Column>> predicate) {
-    Preconditions.checkArgument(combinationsPerPass > 2);
-    Preconditions.checkArgument(interestingCount > 2);
+    checkArgument(combinationsPerPass > 2);
+    checkArgument(interestingCount > 2);
     this.combinationsPerPass = combinationsPerPass;
     this.interestingCount = interestingCount;
     this.predicate = predicate;
@@ -770,8 +771,8 @@ public class ProfilerImpl implements Profiler {
     SurpriseQueue(int warmUpCount, int size) {
       this.warmUpCount = warmUpCount;
       this.size = size;
-      Preconditions.checkArgument(warmUpCount > 3);
-      Preconditions.checkArgument(size > 0);
+      checkArgument(warmUpCount > 3);
+      checkArgument(size > 0);
     }
 
     @Override public String toString() {
diff --git a/core/src/main/java/org/apache/calcite/rel/RelCollationImpl.java b/core/src/main/java/org/apache/calcite/rel/RelCollationImpl.java
index 06433cd57c..19219f741a 100644
--- a/core/src/main/java/org/apache/calcite/rel/RelCollationImpl.java
+++ b/core/src/main/java/org/apache/calcite/rel/RelCollationImpl.java
@@ -26,7 +26,6 @@ import org.apache.calcite.runtime.Utilities;
 import org.apache.calcite.util.Util;
 import org.apache.calcite.util.mapping.Mappings;
 
-import com.google.common.base.Preconditions;
 import com.google.common.collect.ImmutableList;
 import com.google.common.collect.UnmodifiableIterator;
 
@@ -35,6 +34,8 @@ import org.checkerframework.checker.nullness.qual.Nullable;
 import java.util.Iterator;
 import java.util.List;
 
+import static com.google.common.base.Preconditions.checkArgument;
+
 /**
  * Simple implementation of {@link RelCollation}.
  */
@@ -55,8 +56,7 @@ public class RelCollationImpl implements RelCollation {
 
   protected RelCollationImpl(ImmutableList<RelFieldCollation> fieldCollations) {
     this.fieldCollations = fieldCollations;
-    Preconditions.checkArgument(
-        Util.isDistinct(RelCollations.ordinals(fieldCollations)),
+    checkArgument(Util.isDistinct(RelCollations.ordinals(fieldCollations)),
         "fields must be distinct");
   }
 
diff --git a/core/src/main/java/org/apache/calcite/rel/core/AggregateCall.java b/core/src/main/java/org/apache/calcite/rel/core/AggregateCall.java
index fa0d978962..aa6ea524ac 100644
--- a/core/src/main/java/org/apache/calcite/rel/core/AggregateCall.java
+++ b/core/src/main/java/org/apache/calcite/rel/core/AggregateCall.java
@@ -32,7 +32,6 @@ import org.apache.calcite.util.Optionality;
 import org.apache.calcite.util.mapping.Mapping;
 import org.apache.calcite.util.mapping.Mappings;
 
-import com.google.common.base.Preconditions;
 import com.google.common.collect.ImmutableList;
 
 import org.checkerframework.checker.nullness.qual.Nullable;
@@ -40,6 +39,8 @@ import org.checkerframework.checker.nullness.qual.Nullable;
 import java.util.List;
 import java.util.Objects;
 
+import static com.google.common.base.Preconditions.checkArgument;
+
 import static java.util.Objects.requireNonNull;
 
 /**
@@ -121,10 +122,10 @@ public class AggregateCall {
     this.distinct = distinct;
     this.approximate = approximate;
     this.ignoreNulls = ignoreNulls;
-    Preconditions.checkArgument(
-        aggFunction.getDistinctOptionality() != Optionality.IGNORED || !distinct,
+    checkArgument(aggFunction.getDistinctOptionality() != Optionality.IGNORED
+            || !distinct,
         "DISTINCT has no effect for this aggregate function, so must be false");
-    Preconditions.checkArgument(filterArg < 0 || aggFunction.allowsFilter());
+    checkArgument(filterArg < 0 || aggFunction.allowsFilter());
   }
 
   //~ Methods ----------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/calcite/rel/core/Match.java b/core/src/main/java/org/apache/calcite/rel/core/Match.java
index abdea8e978..dbfd8c9200 100644
--- a/core/src/main/java/org/apache/calcite/rel/core/Match.java
+++ b/core/src/main/java/org/apache/calcite/rel/core/Match.java
@@ -35,7 +35,6 @@ import org.apache.calcite.sql.fun.SqlSumAggFunction;
 import org.apache.calcite.sql.fun.SqlSumEmptyIsZeroAggFunction;
 import org.apache.calcite.util.ImmutableBitSet;
 
-import com.google.common.base.Preconditions;
 import com.google.common.collect.ImmutableMap;
 import com.google.common.collect.ImmutableSortedMap;
 import com.google.common.collect.ImmutableSortedSet;
@@ -52,6 +51,8 @@ import java.util.SortedSet;
 import java.util.TreeMap;
 import java.util.TreeSet;
 
+import static com.google.common.base.Preconditions.checkArgument;
+
 /**
  * Relational expression that represent a MATCH_RECOGNIZE node.
  *
@@ -105,7 +106,7 @@ public abstract class Match extends SingleRel {
     super(cluster, traitSet, input);
     this.rowType = Objects.requireNonNull(rowType, "rowType");
     this.pattern = Objects.requireNonNull(pattern, "pattern");
-    Preconditions.checkArgument(patternDefinitions.size() > 0);
+    checkArgument(!patternDefinitions.isEmpty());
     this.strictStart = strictStart;
     this.strictEnd = strictEnd;
     this.patternDefinitions = ImmutableMap.copyOf(patternDefinitions);
diff --git a/core/src/main/java/org/apache/calcite/rel/core/SetOp.java b/core/src/main/java/org/apache/calcite/rel/core/SetOp.java
index 1b5d57158d..45a3febb32 100644
--- a/core/src/main/java/org/apache/calcite/rel/core/SetOp.java
+++ b/core/src/main/java/org/apache/calcite/rel/core/SetOp.java
@@ -30,13 +30,14 @@ import org.apache.calcite.rel.type.RelDataType;
 import org.apache.calcite.sql.SqlKind;
 import org.apache.calcite.util.Util;
 
-import com.google.common.base.Preconditions;
 import com.google.common.collect.ImmutableList;
 
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.List;
 
+import static com.google.common.base.Preconditions.checkArgument;
+
 /**
  * <code>SetOp</code> is an abstract base for relational set operators such
  * as UNION, MINUS (aka EXCEPT), and INTERSECT.
@@ -57,7 +58,7 @@ public abstract class SetOp extends AbstractRelNode implements Hintable {
   protected SetOp(RelOptCluster cluster, RelTraitSet traits, List<RelHint> hints,
       List<RelNode> inputs, SqlKind kind, boolean all) {
     super(cluster, traits);
-    Preconditions.checkArgument(kind == SqlKind.UNION
+    checkArgument(kind == SqlKind.UNION
         || kind == SqlKind.INTERSECT
         || kind == SqlKind.EXCEPT);
     this.kind = kind;
diff --git a/core/src/main/java/org/apache/calcite/rel/core/TableModify.java b/core/src/main/java/org/apache/calcite/rel/core/TableModify.java
index 1d57f22a3b..879052166a 100644
--- a/core/src/main/java/org/apache/calcite/rel/core/TableModify.java
+++ b/core/src/main/java/org/apache/calcite/rel/core/TableModify.java
@@ -36,13 +36,13 @@ import org.apache.calcite.rex.RexNode;
 import org.apache.calcite.sql.SqlKind;
 import org.apache.calcite.sql.type.SqlTypeUtil;
 
-import com.google.common.base.Preconditions;
-
 import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
 import org.checkerframework.checker.nullness.qual.Nullable;
 
 import java.util.List;
 
+import static com.google.common.base.Preconditions.checkArgument;
+
 import static java.util.Objects.requireNonNull;
 
 /**
@@ -126,15 +126,14 @@ public abstract class TableModify extends SingleRel {
     if (operation == Operation.UPDATE) {
       requireNonNull(updateColumnList, "updateColumnList");
       requireNonNull(sourceExpressionList, "sourceExpressionList");
-      Preconditions.checkArgument(sourceExpressionList.size()
-          == updateColumnList.size());
+      checkArgument(sourceExpressionList.size() == updateColumnList.size());
     } else {
       if (operation == Operation.MERGE) {
         requireNonNull(updateColumnList, "updateColumnList");
       } else {
-        Preconditions.checkArgument(updateColumnList == null);
+        checkArgument(updateColumnList == null);
       }
-      Preconditions.checkArgument(sourceExpressionList == null);
+      checkArgument(sourceExpressionList == null);
     }
     RelOptSchema relOptSchema = table.getRelOptSchema();
     if (relOptSchema != null) {
diff --git a/core/src/main/java/org/apache/calcite/rel/hint/RelHint.java b/core/src/main/java/org/apache/calcite/rel/hint/RelHint.java
index 65ea0a5c0c..0312d2d138 100644
--- a/core/src/main/java/org/apache/calcite/rel/hint/RelHint.java
+++ b/core/src/main/java/org/apache/calcite/rel/hint/RelHint.java
@@ -16,7 +16,6 @@
  */
 package org.apache.calcite.rel.hint;
 
-import com.google.common.base.Preconditions;
 import com.google.common.collect.ImmutableList;
 import com.google.common.collect.ImmutableMap;
 
@@ -29,6 +28,8 @@ import java.util.List;
 import java.util.Map;
 import java.util.Objects;
 
+import static com.google.common.base.Preconditions.checkState;
+
 /**
  * Hint attached to a relation expression.
  *
@@ -198,7 +199,7 @@ public class RelHint {
     /** Add a hint option as string. */
     public Builder hintOption(String hintOption) {
       Objects.requireNonNull(hintOption, "hintOption");
-      Preconditions.checkState(this.kvOptions.size() == 0,
+      checkState(this.kvOptions.isEmpty(),
           "List options and key value options can not be mixed in");
       this.listOptions.add(hintOption);
       return this;
@@ -207,7 +208,7 @@ public class RelHint {
     /** Add multiple string hint options. */
     public Builder hintOptions(Iterable<String> hintOptions) {
       Objects.requireNonNull(hintOptions, "hintOptions");
-      Preconditions.checkState(this.kvOptions.size() == 0,
+      checkState(this.kvOptions.isEmpty(),
           "List options and key value options can not be mixed in");
       this.listOptions = ImmutableList.copyOf(hintOptions);
       return this;
@@ -217,7 +218,7 @@ public class RelHint {
     public Builder hintOption(String optionKey, String optionValue) {
       Objects.requireNonNull(optionKey, "optionKey");
       Objects.requireNonNull(optionValue, "optionValue");
-      Preconditions.checkState(this.listOptions.size() == 0,
+      checkState(this.listOptions.isEmpty(),
           "List options and key value options can not be mixed in");
       this.kvOptions.put(optionKey, optionValue);
       return this;
@@ -226,7 +227,7 @@ public class RelHint {
     /** Add multiple string key-value pair hint options. */
     public Builder hintOptions(Map<String, String> kvOptions) {
       Objects.requireNonNull(kvOptions, "kvOptions");
-      Preconditions.checkState(this.listOptions.size() == 0,
+      checkState(this.listOptions.isEmpty(),
           "List options and key value options can not be mixed in");
       this.kvOptions = kvOptions;
       return this;
diff --git a/core/src/main/java/org/apache/calcite/rel/metadata/ReflectiveRelMetadataProvider.java b/core/src/main/java/org/apache/calcite/rel/metadata/ReflectiveRelMetadataProvider.java
index 14c040017a..10ed040570 100644
--- a/core/src/main/java/org/apache/calcite/rel/metadata/ReflectiveRelMetadataProvider.java
+++ b/core/src/main/java/org/apache/calcite/rel/metadata/ReflectiveRelMetadataProvider.java
@@ -25,7 +25,6 @@ import org.apache.calcite.util.Pair;
 import org.apache.calcite.util.ReflectiveVisitor;
 import org.apache.calcite.util.Util;
 
-import com.google.common.base.Preconditions;
 import com.google.common.collect.ImmutableList;
 import com.google.common.collect.ImmutableMultimap;
 import com.google.common.collect.Multimap;
@@ -46,6 +45,8 @@ import java.util.Set;
 import java.util.concurrent.ConcurrentHashMap;
 import java.util.concurrent.ConcurrentMap;
 
+import static com.google.common.base.Preconditions.checkArgument;
+
 import static org.apache.calcite.util.ReflectUtil.isPublic;
 import static org.apache.calcite.util.ReflectUtil.isStatic;
 
@@ -90,7 +91,7 @@ public class ReflectiveRelMetadataProvider
       Class<? extends Metadata> metadataClass0,
       Multimap<Method, MetadataHandler<?>> handlerMap,
       Class<? extends MetadataHandler<?>> handlerClass) {
-    Preconditions.checkArgument(!map.isEmpty(), "ReflectiveRelMetadataProvider "
+    checkArgument(!map.isEmpty(), "ReflectiveRelMetadataProvider "
         + "methods map is empty; are your methods named wrong?");
     this.map = map;
     this.metadataClass0 = metadataClass0;
diff --git a/core/src/main/java/org/apache/calcite/rel/metadata/RelMdUniqueKeys.java b/core/src/main/java/org/apache/calcite/rel/metadata/RelMdUniqueKeys.java
index 392c431da1..9e7d84a838 100644
--- a/core/src/main/java/org/apache/calcite/rel/metadata/RelMdUniqueKeys.java
+++ b/core/src/main/java/org/apache/calcite/rel/metadata/RelMdUniqueKeys.java
@@ -43,7 +43,6 @@ import org.apache.calcite.util.ImmutableBitSet;
 import org.apache.calcite.util.ImmutableIntList;
 import org.apache.calcite.util.Util;
 
-import com.google.common.base.Preconditions;
 import com.google.common.collect.ImmutableList;
 import com.google.common.collect.ImmutableMultimap;
 import com.google.common.collect.ImmutableSet;
@@ -59,6 +58,8 @@ import java.util.Map;
 import java.util.Set;
 import java.util.stream.Collectors;
 
+import static com.google.common.base.Preconditions.checkArgument;
+
 import static org.apache.calcite.rel.metadata.RelMdColumnUniqueness.PASSTHROUGH_AGGREGATIONS;
 import static org.apache.calcite.rel.metadata.RelMdColumnUniqueness.getConstantColumnSet;
 
@@ -386,7 +387,7 @@ public class RelMdUniqueKeys
    * {@link RelMdColumnUniqueness#PASSTHROUGH_AGGREGATIONS pass-through aggregation function}.
    */
   private Set<ImmutableBitSet> getPassedThroughCols(ImmutableBitSet inputColumns, Aggregate rel) {
-    Preconditions.checkArgument(Aggregate.isSimple(rel));
+    checkArgument(Aggregate.isSimple(rel));
     Set<ImmutableBitSet> conbinations = new HashSet<>();
     conbinations.add(ImmutableBitSet.of());
     for (Integer inputColumn : inputColumns.asSet()) {
diff --git a/core/src/main/java/org/apache/calcite/rel/metadata/RelMdUtil.java b/core/src/main/java/org/apache/calcite/rel/metadata/RelMdUtil.java
index 696daa77db..11121db1cf 100644
--- a/core/src/main/java/org/apache/calcite/rel/metadata/RelMdUtil.java
+++ b/core/src/main/java/org/apache/calcite/rel/metadata/RelMdUtil.java
@@ -47,7 +47,6 @@ import org.apache.calcite.util.ImmutableBitSet;
 import org.apache.calcite.util.NumberUtil;
 import org.apache.calcite.util.Util;
 
-import com.google.common.base.Preconditions;
 import com.google.common.collect.ImmutableList;
 
 import org.checkerframework.checker.nullness.qual.Nullable;
@@ -59,6 +58,8 @@ import java.util.LinkedHashSet;
 import java.util.List;
 import java.util.Set;
 
+import static com.google.common.base.Preconditions.checkArgument;
+
 import static org.apache.calcite.util.NumberUtil.multiply;
 
 /**
@@ -883,8 +884,8 @@ public class RelMdUtil {
    */
   public static double linear(int x, int minX, int maxX, double minY, double
       maxY) {
-    Preconditions.checkArgument(minX < maxX);
-    Preconditions.checkArgument(minY < maxY);
+    checkArgument(minX < maxX);
+    checkArgument(minY < maxY);
     if (x < minX) {
       return minY;
     }
diff --git a/core/src/main/java/org/apache/calcite/rel/rules/AggregateExpandDistinctAggregatesRule.java b/core/src/main/java/org/apache/calcite/rel/rules/AggregateExpandDistinctAggregatesRule.java
index 41e979c239..7a00db8d72 100644
--- a/core/src/main/java/org/apache/calcite/rel/rules/AggregateExpandDistinctAggregatesRule.java
+++ b/core/src/main/java/org/apache/calcite/rel/rules/AggregateExpandDistinctAggregatesRule.java
@@ -43,7 +43,6 @@ import org.apache.calcite.util.Optionality;
 import org.apache.calcite.util.Pair;
 import org.apache.calcite.util.Util;
 
-import com.google.common.base.Preconditions;
 import com.google.common.collect.ImmutableList;
 import com.google.common.collect.Iterables;
 import com.google.common.collect.Lists;
@@ -65,6 +64,9 @@ import java.util.TreeSet;
 import java.util.stream.Collectors;
 import java.util.stream.Stream;
 
+import static com.google.common.base.Preconditions.checkArgument;
+import static com.google.common.base.Preconditions.checkState;
+
 import static java.util.Objects.requireNonNull;
 
 /**
@@ -161,8 +163,7 @@ public final class AggregateExpandDistinctAggregatesRule
         .map(aggCall -> Pair.of(aggCall.getArgList(), aggCall.filterArg))
         .collect(Collectors.toCollection(LinkedHashSet::new));
 
-    Preconditions.checkState(distinctCallArgLists.size() > 0,
-        "containsDistinctCall lied");
+    checkState(!distinctCallArgLists.isEmpty(), "containsDistinctCall lied");
 
     // If all of the agg expressions are distinct and have the same
     // arguments then we can use a more efficient form.
@@ -282,7 +283,7 @@ public final class AggregateExpandDistinctAggregatesRule
 
     // In this case, we are assuming that there is a single distinct function.
     // So make sure that argLists is of size one.
-    Preconditions.checkArgument(argLists.size() == 1);
+    checkArgument(argLists.size() == 1);
 
     // For example,
     //    SELECT deptno, COUNT(*), SUM(bonus), MIN(DISTINCT sal)
diff --git a/core/src/main/java/org/apache/calcite/rel/rules/CalcRelSplitter.java b/core/src/main/java/org/apache/calcite/rel/rules/CalcRelSplitter.java
index b5bbe403c2..2e7699a89d 100644
--- a/core/src/main/java/org/apache/calcite/rel/rules/CalcRelSplitter.java
+++ b/core/src/main/java/org/apache/calcite/rel/rules/CalcRelSplitter.java
@@ -43,7 +43,6 @@ import org.apache.calcite.util.graph.DefaultEdge;
 import org.apache.calcite.util.graph.DirectedGraph;
 import org.apache.calcite.util.graph.TopologicalOrderIterator;
 
-import com.google.common.base.Preconditions;
 import com.google.common.primitives.Ints;
 
 import org.checkerframework.checker.nullness.qual.Nullable;
@@ -57,6 +56,8 @@ import java.util.Collections;
 import java.util.List;
 import java.util.Set;
 
+import static com.google.common.base.Preconditions.checkArgument;
+
 /**
  * CalcRelSplitter operates on a
  * {@link org.apache.calcite.rel.core.Calc} with multiple {@link RexCall}
@@ -242,8 +243,7 @@ public abstract class CalcRelSplitter {
       inputExprOrdinals = projectExprOrdinals;
     }
 
-    Preconditions.checkArgument(doneCondition || (conditionRef == null),
-        "unhandled condition");
+    checkArgument(doneCondition || conditionRef == null, "unhandled condition");
     return rel;
   }
 
diff --git a/core/src/main/java/org/apache/calcite/rel/rules/ProjectToWindowRule.java b/core/src/main/java/org/apache/calcite/rel/rules/ProjectToWindowRule.java
index f97584b364..303a57fce6 100644
--- a/core/src/main/java/org/apache/calcite/rel/rules/ProjectToWindowRule.java
+++ b/core/src/main/java/org/apache/calcite/rel/rules/ProjectToWindowRule.java
@@ -45,7 +45,6 @@ import org.apache.calcite.util.graph.DefaultEdge;
 import org.apache.calcite.util.graph.DirectedGraph;
 import org.apache.calcite.util.graph.TopologicalOrderIterator;
 
-import com.google.common.base.Preconditions;
 import com.google.common.collect.ImmutableList;
 
 import org.immutables.value.Value;
@@ -57,6 +56,8 @@ import java.util.HashSet;
 import java.util.List;
 import java.util.Set;
 
+import static com.google.common.base.Preconditions.checkArgument;
+
 /**
  * Planner rule that slices a
  * {@link org.apache.calcite.rel.core.Project}
@@ -255,7 +256,7 @@ public abstract class ProjectToWindowRule
 
           @Override protected RelNode makeRel(RelOptCluster cluster, RelTraitSet traitSet,
               RelBuilder relBuilder, RelNode input, RexProgram program) {
-            Preconditions.checkArgument(program.getCondition() == null,
+            checkArgument(program.getCondition() == null,
                 "WindowedAggregateRel cannot accept a condition");
             return LogicalWindow.create(cluster, traitSet, relBuilder, input,
                 program);
diff --git a/core/src/main/java/org/apache/calcite/rel/rules/materialize/MaterializedViewAggregateRule.java b/core/src/main/java/org/apache/calcite/rel/rules/materialize/MaterializedViewAggregateRule.java
index 225055e512..289c088a8f 100644
--- a/core/src/main/java/org/apache/calcite/rel/rules/materialize/MaterializedViewAggregateRule.java
+++ b/core/src/main/java/org/apache/calcite/rel/rules/materialize/MaterializedViewAggregateRule.java
@@ -58,7 +58,6 @@ import org.apache.calcite.util.mapping.Mapping;
 import org.apache.calcite.util.mapping.MappingType;
 import org.apache.calcite.util.mapping.Mappings;
 
-import com.google.common.base.Preconditions;
 import com.google.common.collect.ArrayListMultimap;
 import com.google.common.collect.BiMap;
 import com.google.common.collect.ImmutableList;
@@ -77,6 +76,8 @@ import java.util.List;
 import java.util.Map;
 import java.util.Set;
 
+import static com.google.common.base.Preconditions.checkArgument;
+
 import static java.util.Objects.requireNonNull;
 
 /** Materialized view rewriting for aggregate.
@@ -751,7 +752,7 @@ public abstract class MaterializedViewAggregateRule<C extends MaterializedViewAg
       BiMap<RelTableRef, RelTableRef> tableMapping,
       EquivalenceClasses sourceEC,
       List<RexNode> additionalExprs) {
-    Preconditions.checkArgument(additionalExprs.isEmpty());
+    checkArgument(additionalExprs.isEmpty());
     Multimap<Integer, Integer> m = ArrayListMultimap.create();
     Map<RexTableInputRef, Set<RexTableInputRef>> equivalenceClassesMap =
         sourceEC.getEquivalenceClassesMap();
diff --git a/core/src/main/java/org/apache/calcite/rex/RexBuilder.java b/core/src/main/java/org/apache/calcite/rex/RexBuilder.java
index 69149c1679..dab524f5ee 100644
--- a/core/src/main/java/org/apache/calcite/rex/RexBuilder.java
+++ b/core/src/main/java/org/apache/calcite/rex/RexBuilder.java
@@ -51,7 +51,6 @@ import org.apache.calcite.util.TimeString;
 import org.apache.calcite.util.TimestampString;
 import org.apache.calcite.util.Util;
 
-import com.google.common.base.Preconditions;
 import com.google.common.collect.ImmutableList;
 import com.google.common.collect.ImmutableRangeSet;
 import com.google.common.collect.Range;
@@ -76,6 +75,7 @@ import java.util.Objects;
 import java.util.function.IntPredicate;
 import java.util.stream.Collectors;
 
+import static com.google.common.base.Preconditions.checkArgument;
 import static com.google.common.base.Verify.verifyNotNull;
 import static com.google.common.collect.ImmutableList.toImmutableList;
 
@@ -351,7 +351,7 @@ public class RexBuilder {
       boolean indicator, List<AggregateCall> aggCalls,
       Map<AggregateCall, RexNode> aggCallMapping,
       final @Nullable List<RelDataType> aggArgTypes) {
-    Preconditions.checkArgument(!indicator,
+    checkArgument(!indicator,
         "indicator is deprecated, use GROUPING function instead");
     return addAggCall(aggCall, groupCount, aggCalls,
         aggCallMapping, aggArgTypes);
@@ -422,7 +422,7 @@ public class RexBuilder {
               makeNullLiteral(type));
     }
     if (!allowPartial) {
-      Preconditions.checkArgument(rows, "DISALLOW PARTIAL over RANGE");
+      checkArgument(rows, "DISALLOW PARTIAL over RANGE");
       final RelDataType bigintType =
           typeFactory.createSqlType(SqlTypeName.BIGINT);
       // todo: read bound
diff --git a/core/src/main/java/org/apache/calcite/rex/RexFieldAccess.java b/core/src/main/java/org/apache/calcite/rex/RexFieldAccess.java
index 0f09672f38..9b7439a203 100644
--- a/core/src/main/java/org/apache/calcite/rex/RexFieldAccess.java
+++ b/core/src/main/java/org/apache/calcite/rex/RexFieldAccess.java
@@ -20,10 +20,10 @@ import org.apache.calcite.rel.type.RelDataType;
 import org.apache.calcite.rel.type.RelDataTypeField;
 import org.apache.calcite.sql.SqlKind;
 
-import com.google.common.base.Preconditions;
-
 import org.checkerframework.checker.nullness.qual.Nullable;
 
+import static com.google.common.base.Preconditions.checkArgument;
+
 /**
  * Access to a field of a row-expression.
  *
@@ -72,8 +72,7 @@ public class RexFieldAccess extends RexNode {
   private static void checkValid(RexNode expr, RelDataTypeField field) {
     RelDataType exprType = expr.getType();
     int fieldIdx = field.getIndex();
-    Preconditions.checkArgument(
-        fieldIdx >= 0 && fieldIdx < exprType.getFieldList().size()
+    checkArgument(fieldIdx >= 0 && fieldIdx < exprType.getFieldList().size()
             && exprType.getFieldList().get(fieldIdx).equals(field),
         "Field %s does not exist for expression %s", field, expr);
   }
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 4bf9073082..30f03669ed 100644
--- a/core/src/main/java/org/apache/calcite/rex/RexLiteral.java
+++ b/core/src/main/java/org/apache/calcite/rex/RexLiteral.java
@@ -42,7 +42,6 @@ import org.apache.calcite.util.TimeString;
 import org.apache.calcite.util.TimestampString;
 import org.apache.calcite.util.Util;
 
-import com.google.common.base.Preconditions;
 import com.google.common.collect.ImmutableList;
 
 import org.checkerframework.checker.initialization.qual.UnknownInitialization;
@@ -64,6 +63,8 @@ import java.util.Map;
 import java.util.Objects;
 import java.util.TimeZone;
 
+import static com.google.common.base.Preconditions.checkArgument;
+
 import static org.apache.calcite.linq4j.Nullness.castNonNull;
 import static org.apache.calcite.rel.type.RelDataTypeImpl.NON_NULLABLE_SUFFIX;
 
@@ -228,9 +229,9 @@ public class RexLiteral extends RexNode {
     this.value = value;
     this.type = requireNonNull(type, "type");
     this.typeName = requireNonNull(typeName, "typeName");
-    Preconditions.checkArgument(valueMatchesType(value, typeName, true));
-    Preconditions.checkArgument((value == null) == type.isNullable());
-    Preconditions.checkArgument(typeName != SqlTypeName.ANY);
+    checkArgument(valueMatchesType(value, typeName, true));
+    checkArgument((value == null) == type.isNullable());
+    checkArgument(typeName != SqlTypeName.ANY);
     this.digest = computeDigest(RexDigestIncludeType.OPTIONAL);
   }
 
diff --git a/core/src/main/java/org/apache/calcite/rex/RexOver.java b/core/src/main/java/org/apache/calcite/rex/RexOver.java
index b93d94a837..792beae6a5 100644
--- a/core/src/main/java/org/apache/calcite/rex/RexOver.java
+++ b/core/src/main/java/org/apache/calcite/rex/RexOver.java
@@ -22,13 +22,13 @@ import org.apache.calcite.sql.SqlWindow;
 import org.apache.calcite.util.ControlFlowException;
 import org.apache.calcite.util.Util;
 
-import com.google.common.base.Preconditions;
-
 import org.checkerframework.checker.nullness.qual.Nullable;
 
 import java.util.List;
 import java.util.Objects;
 
+import static com.google.common.base.Preconditions.checkArgument;
+
 /**
  * Call to an aggregate function over a window.
  */
@@ -70,7 +70,7 @@ public class RexOver extends RexCall {
       boolean distinct,
       boolean ignoreNulls) {
     super(type, op, operands);
-    Preconditions.checkArgument(op.isAggregator());
+    checkArgument(op.isAggregator());
     this.window = Objects.requireNonNull(window, "window");
     this.distinct = distinct;
     this.ignoreNulls = ignoreNulls;
diff --git a/core/src/main/java/org/apache/calcite/rex/RexSubQuery.java b/core/src/main/java/org/apache/calcite/rex/RexSubQuery.java
index 609a4a5a01..61d10174f8 100644
--- a/core/src/main/java/org/apache/calcite/rex/RexSubQuery.java
+++ b/core/src/main/java/org/apache/calcite/rex/RexSubQuery.java
@@ -28,7 +28,6 @@ import org.apache.calcite.sql.fun.SqlStdOperatorTable;
 import org.apache.calcite.sql.type.SqlTypeName;
 import org.apache.calcite.sql.type.SqlTypeUtil;
 
-import com.google.common.base.Preconditions;
 import com.google.common.collect.ImmutableList;
 
 import org.checkerframework.checker.nullness.qual.Nullable;
@@ -36,6 +35,8 @@ import org.checkerframework.checker.nullness.qual.Nullable;
 import java.util.List;
 import java.util.Objects;
 
+import static com.google.common.base.Preconditions.checkArgument;
+
 /**
  * Scalar expression that represents an IN, EXISTS or scalar sub-query.
  */
@@ -146,7 +147,7 @@ public class RexSubQuery extends RexCall {
   public static RexSubQuery map(RelNode rel) {
     final RelDataTypeFactory typeFactory = rel.getCluster().getTypeFactory();
     final RelDataType rowType = rel.getRowType();
-    Preconditions.checkArgument(rowType.getFieldCount() == 2,
+    checkArgument(rowType.getFieldCount() == 2,
         "MAP requires exactly two fields, got %s; row type %s",
         rowType.getFieldCount(), rowType);
     final List<RelDataTypeField> fieldList = rowType.getFieldList();
diff --git a/core/src/main/java/org/apache/calcite/rex/RexWindow.java b/core/src/main/java/org/apache/calcite/rex/RexWindow.java
index 2607169181..ecf5391163 100644
--- a/core/src/main/java/org/apache/calcite/rex/RexWindow.java
+++ b/core/src/main/java/org/apache/calcite/rex/RexWindow.java
@@ -18,7 +18,6 @@ package org.apache.calcite.rex;
 
 import org.apache.calcite.util.Pair;
 
-import com.google.common.base.Preconditions;
 import com.google.common.collect.ImmutableList;
 
 import org.checkerframework.checker.nullness.qual.Nullable;
@@ -26,6 +25,8 @@ import org.checkerframework.checker.nullness.qual.Nullable;
 import java.util.List;
 import java.util.Objects;
 
+import static com.google.common.base.Preconditions.checkArgument;
+
 /**
  * Specification of the window of rows over which a {@link RexOver} windowed
  * aggregate is evaluated.
@@ -83,7 +84,7 @@ public class RexWindow {
     this.isRows = isRows;
     this.nodeCount = computeCodeCount();
     this.digest = computeDigest();
-    Preconditions.checkArgument(
+    checkArgument(
         !(lowerBound.isUnbounded() && lowerBound.isPreceding()
             && upperBound.isUnbounded() && upperBound.isFollowing() && isRows),
         "use RANGE for unbounded, not ROWS");
diff --git a/core/src/main/java/org/apache/calcite/runtime/AutomatonBuilder.java b/core/src/main/java/org/apache/calcite/runtime/AutomatonBuilder.java
index 0d9a686c53..2785321b05 100644
--- a/core/src/main/java/org/apache/calcite/runtime/AutomatonBuilder.java
+++ b/core/src/main/java/org/apache/calcite/runtime/AutomatonBuilder.java
@@ -21,7 +21,6 @@ import org.apache.calcite.runtime.Automaton.State;
 import org.apache.calcite.runtime.Automaton.SymbolTransition;
 import org.apache.calcite.runtime.Automaton.Transition;
 
-import com.google.common.base.Preconditions;
 import com.google.common.collect.ImmutableList;
 
 import java.util.ArrayList;
@@ -31,6 +30,7 @@ import java.util.List;
 import java.util.Map;
 import java.util.Objects;
 
+import static com.google.common.base.Preconditions.checkArgument;
 import static com.google.common.collect.ImmutableList.toImmutableList;
 
 /** Builds a state-transition graph for deterministic finite automaton. */
@@ -210,9 +210,9 @@ public class AutomatonBuilder {
     // fromState ---> state0 ---> state1 ---> state2 ---> state3 ---> toState
     //            e        pattern     pattern     pattern        e
     //
-    Preconditions.checkArgument(0 <= minRepeat);
-    Preconditions.checkArgument(minRepeat <= maxRepeat);
-    Preconditions.checkArgument(1 <= maxRepeat);
+    checkArgument(0 <= minRepeat);
+    checkArgument(minRepeat <= maxRepeat);
+    checkArgument(1 <= maxRepeat);
     State prevState = fromState;
     for (int i = 0; i <= maxRepeat; i++) {
       final State s = createState();
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 73a55c5de6..fb491b9f0c 100644
--- a/core/src/main/java/org/apache/calcite/runtime/CalciteException.java
+++ b/core/src/main/java/org/apache/calcite/runtime/CalciteException.java
@@ -18,6 +18,7 @@ package org.apache.calcite.runtime;
 
 import org.apache.calcite.config.CalciteSystemProperty;
 
+import org.checkerframework.checker.nullness.qual.Nullable;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -55,7 +56,7 @@ public class CalciteException extends RuntimeException {
   @SuppressWarnings({"argument.type.incompatible", "method.invocation.invalid"})
   public CalciteException(
       String message,
-      Throwable cause) {
+      @Nullable Throwable cause) {
     super(message, cause);
 
     // TODO: Force the caller to pass in a Logger as a trace argument for
diff --git a/core/src/main/java/org/apache/calcite/runtime/Pattern.java b/core/src/main/java/org/apache/calcite/runtime/Pattern.java
index 48d430825f..370eb02d6d 100644
--- a/core/src/main/java/org/apache/calcite/runtime/Pattern.java
+++ b/core/src/main/java/org/apache/calcite/runtime/Pattern.java
@@ -16,13 +16,14 @@
  */
 package org.apache.calcite.runtime;
 
-import com.google.common.base.Preconditions;
 import com.google.common.collect.ImmutableList;
 
 import java.util.Objects;
 import java.util.Stack;
 import java.util.stream.Collectors;
 
+import static com.google.common.base.Preconditions.checkArgument;
+
 /** Regular expression, to be compiled into an {@link Automaton}. */
 public interface Pattern {
   default Automaton toAutomaton() {
@@ -181,8 +182,8 @@ public interface Pattern {
 
     OpPattern(Op op, Pattern... patterns) {
       super(op);
-      Preconditions.checkArgument(patterns.length >= op.minArity);
-      Preconditions.checkArgument(op.maxArity == -1
+      checkArgument(patterns.length >= op.minArity);
+      checkArgument(op.maxArity == -1
           || patterns.length <= op.maxArity);
       this.patterns = ImmutableList.copyOf(patterns);
     }
diff --git a/core/src/main/java/org/apache/calcite/schema/Schemas.java b/core/src/main/java/org/apache/calcite/schema/Schemas.java
index 4795473729..1fafb23123 100644
--- a/core/src/main/java/org/apache/calcite/schema/Schemas.java
+++ b/core/src/main/java/org/apache/calcite/schema/Schemas.java
@@ -44,7 +44,6 @@ import org.apache.calcite.util.BuiltInMethod;
 import org.apache.calcite.util.Pair;
 import org.apache.calcite.util.Util;
 
-import com.google.common.base.Preconditions;
 import com.google.common.collect.ImmutableList;
 import com.google.common.collect.ImmutableMap;
 
@@ -60,6 +59,8 @@ import java.util.Iterator;
 import java.util.List;
 import java.util.Map;
 
+import static com.google.common.base.Preconditions.checkState;
+
 import static org.apache.calcite.jdbc.CalciteSchema.LatticeEntry;
 
 import static java.util.Objects.requireNonNull;
@@ -567,7 +568,7 @@ public final class Schemas {
     if (!rootSchema.name.isEmpty()) {
       // If path starts with the name of the root schema, ignore the first step
       // in the path.
-      Preconditions.checkState(rootSchema.name.equals(iterator.next()));
+      checkState(rootSchema.name.equals(iterator.next()));
     }
     for (;;) {
       final String name = iterator.next();
diff --git a/core/src/main/java/org/apache/calcite/sql/SqlDialect.java b/core/src/main/java/org/apache/calcite/sql/SqlDialect.java
index 30c912dcb8..845d351cd5 100644
--- a/core/src/main/java/org/apache/calcite/sql/SqlDialect.java
+++ b/core/src/main/java/org/apache/calcite/sql/SqlDialect.java
@@ -43,7 +43,6 @@ import org.apache.calcite.sql.validate.SqlConformanceEnum;
 import org.apache.calcite.util.format.FormatModel;
 import org.apache.calcite.util.format.FormatModels;
 
-import com.google.common.base.Preconditions;
 import com.google.common.base.Suppliers;
 import com.google.common.collect.ImmutableSet;
 
@@ -61,6 +60,8 @@ import java.util.Locale;
 import java.util.Set;
 import java.util.function.Supplier;
 
+import static com.google.common.base.Preconditions.checkArgument;
+
 import static org.apache.calcite.util.DateTimeStringUtils.getDateFormatter;
 
 import static java.util.Objects.requireNonNull;
@@ -997,7 +998,7 @@ public class SqlDialect {
    * fetch ROWS ONLY" syntax. */
   protected static void unparseFetchUsingAnsi(SqlWriter writer, @Nullable SqlNode offset,
       @Nullable SqlNode fetch) {
-    Preconditions.checkArgument(fetch != null || offset != null);
+    checkArgument(fetch != null || offset != null);
     if (offset != null) {
       writer.newlineAndIndent();
       final SqlWriter.Frame offsetFrame =
@@ -1023,7 +1024,7 @@ public class SqlDialect {
   /** Unparses offset/fetch using "LIMIT fetch OFFSET offset" syntax. */
   protected static void unparseFetchUsingLimit(SqlWriter writer, @Nullable SqlNode offset,
       @Nullable SqlNode fetch) {
-    Preconditions.checkArgument(fetch != null || offset != null);
+    checkArgument(fetch != null || offset != null);
     unparseLimit(writer, fetch);
     unparseOffset(writer, offset);
   }
diff --git a/core/src/main/java/org/apache/calcite/sql/SqlGroupedWindowFunction.java b/core/src/main/java/org/apache/calcite/sql/SqlGroupedWindowFunction.java
index e7b9a3a6d6..2a9192595c 100644
--- a/core/src/main/java/org/apache/calcite/sql/SqlGroupedWindowFunction.java
+++ b/core/src/main/java/org/apache/calcite/sql/SqlGroupedWindowFunction.java
@@ -22,13 +22,14 @@ import org.apache.calcite.sql.type.SqlOperandTypeInference;
 import org.apache.calcite.sql.type.SqlReturnTypeInference;
 import org.apache.calcite.sql.validate.SqlMonotonicity;
 
-import com.google.common.base.Preconditions;
 import com.google.common.collect.ImmutableList;
 
 import org.checkerframework.checker.nullness.qual.Nullable;
 
 import java.util.List;
 
+import static com.google.common.base.Preconditions.checkArgument;
+
 /**
  * SQL function that computes keys by which rows can be partitioned and
  * aggregated.
@@ -66,11 +67,12 @@ public class SqlGroupedWindowFunction extends SqlFunction {
       @Nullable SqlGroupedWindowFunction groupFunction,
       SqlReturnTypeInference returnTypeInference,
       @Nullable SqlOperandTypeInference operandTypeInference,
-      @Nullable SqlOperandTypeChecker operandTypeChecker, SqlFunctionCategory category) {
+      @Nullable SqlOperandTypeChecker operandTypeChecker,
+      SqlFunctionCategory category) {
     super(name, kind, returnTypeInference, operandTypeInference,
         operandTypeChecker, category);
     this.groupFunction = groupFunction;
-    Preconditions.checkArgument(groupFunction == null
+    checkArgument(groupFunction == null
         || groupFunction.groupFunction == null);
   }
 
diff --git a/core/src/main/java/org/apache/calcite/sql/SqlJoin.java b/core/src/main/java/org/apache/calcite/sql/SqlJoin.java
index 75706adaa1..ab08f2d1c9 100644
--- a/core/src/main/java/org/apache/calcite/sql/SqlJoin.java
+++ b/core/src/main/java/org/apache/calcite/sql/SqlJoin.java
@@ -22,13 +22,13 @@ import org.apache.calcite.sql.util.SqlString;
 import org.apache.calcite.util.ImmutableNullableList;
 import org.apache.calcite.util.Util;
 
-import com.google.common.base.Preconditions;
-
 import org.checkerframework.checker.nullness.qual.Nullable;
 
 import java.util.List;
 import java.util.function.UnaryOperator;
 
+import static com.google.common.base.Preconditions.checkArgument;
+
 import static java.util.Objects.requireNonNull;
 
 /**
@@ -75,7 +75,7 @@ public class SqlJoin extends SqlCall {
     this.conditionType = requireNonNull(conditionType, "conditionType");
     this.condition = condition;
 
-    Preconditions.checkArgument(natural.getTypeName() == SqlTypeName.BOOLEAN);
+    checkArgument(natural.getTypeName() == SqlTypeName.BOOLEAN);
     conditionType.getValueAs(JoinConditionType.class);
     joinType.getValueAs(JoinType.class);
   }
diff --git a/core/src/main/java/org/apache/calcite/sql/SqlMatchRecognize.java b/core/src/main/java/org/apache/calcite/sql/SqlMatchRecognize.java
index 970539d132..24de92d989 100644
--- a/core/src/main/java/org/apache/calcite/sql/SqlMatchRecognize.java
+++ b/core/src/main/java/org/apache/calcite/sql/SqlMatchRecognize.java
@@ -23,13 +23,13 @@ import org.apache.calcite.sql.validate.SqlValidator;
 import org.apache.calcite.sql.validate.SqlValidatorScope;
 import org.apache.calcite.util.ImmutableNullableList;
 
-import com.google.common.base.Preconditions;
-
 import org.checkerframework.checker.nullness.qual.Nullable;
 
 import java.util.List;
 import java.util.Objects;
 
+import static com.google.common.base.Preconditions.checkArgument;
+
 /**
  * SqlNode for MATCH_RECOGNIZE clause.
  */
@@ -82,11 +82,11 @@ public class SqlMatchRecognize extends SqlCall {
     this.strictStart = strictStart;
     this.strictEnd = strictEnd;
     this.patternDefList = Objects.requireNonNull(patternDefList, "patternDefList");
-    Preconditions.checkArgument(patternDefList.size() > 0);
+    checkArgument(!patternDefList.isEmpty());
     this.measureList = Objects.requireNonNull(measureList, "measureList");
     this.after = after;
     this.subsetList = subsetList;
-    Preconditions.checkArgument(rowsPerMatch == null
+    checkArgument(rowsPerMatch == null
         || rowsPerMatch.value instanceof RowsPerMatchOption);
     this.rowsPerMatch = rowsPerMatch;
     this.partitionList = Objects.requireNonNull(partitionList, "partitionList");
@@ -137,7 +137,7 @@ public class SqlMatchRecognize extends SqlCall {
       break;
     case OPERAND_PATTERN_DEFINES:
       patternDefList = Objects.requireNonNull((SqlNodeList) operand);
-      Preconditions.checkArgument(patternDefList.size() > 0);
+      checkArgument(!patternDefList.isEmpty());
       break;
     case OPERAND_MEASURES:
       measureList = Objects.requireNonNull((SqlNodeList) operand);
@@ -150,7 +150,7 @@ public class SqlMatchRecognize extends SqlCall {
       break;
     case OPERAND_ROWS_PER_MATCH:
       rowsPerMatch = (SqlLiteral) operand;
-      Preconditions.checkArgument(rowsPerMatch == null
+      checkArgument(rowsPerMatch == null
           || rowsPerMatch.value instanceof RowsPerMatchOption);
       break;
     case OPERAND_PARTITION_BY:
diff --git a/core/src/main/java/org/apache/calcite/sql/SqlNullTreatmentOperator.java b/core/src/main/java/org/apache/calcite/sql/SqlNullTreatmentOperator.java
index 590aac2ec9..28ad44956c 100644
--- a/core/src/main/java/org/apache/calcite/sql/SqlNullTreatmentOperator.java
+++ b/core/src/main/java/org/apache/calcite/sql/SqlNullTreatmentOperator.java
@@ -23,10 +23,10 @@ import org.apache.calcite.sql.validate.SqlValidator;
 import org.apache.calcite.sql.validate.SqlValidatorScope;
 import org.apache.calcite.util.ImmutableNullableList;
 
-import com.google.common.base.Preconditions;
-
 import org.checkerframework.checker.nullness.qual.Nullable;
 
+import static com.google.common.base.Preconditions.checkArgument;
+
 import static org.apache.calcite.util.Static.RESOURCE;
 
 /**
@@ -41,7 +41,7 @@ import static org.apache.calcite.util.Static.RESOURCE;
 public class SqlNullTreatmentOperator extends SqlSpecialOperator {
   public SqlNullTreatmentOperator(SqlKind kind) {
     super(kind.sql, kind, 20, true, ReturnTypes.ARG0, null, OperandTypes.ANY);
-    Preconditions.checkArgument(kind == SqlKind.RESPECT_NULLS
+    checkArgument(kind == SqlKind.RESPECT_NULLS
         || kind == SqlKind.IGNORE_NULLS);
   }
 
diff --git a/core/src/main/java/org/apache/calcite/sql/SqlTimeLiteral.java b/core/src/main/java/org/apache/calcite/sql/SqlTimeLiteral.java
index b1ff7af7fa..953ca8611f 100644
--- a/core/src/main/java/org/apache/calcite/sql/SqlTimeLiteral.java
+++ b/core/src/main/java/org/apache/calcite/sql/SqlTimeLiteral.java
@@ -20,10 +20,10 @@ import org.apache.calcite.sql.parser.SqlParserPos;
 import org.apache.calcite.sql.type.SqlTypeName;
 import org.apache.calcite.util.TimeString;
 
-import com.google.common.base.Preconditions;
-
 import java.util.Objects;
 
+import static com.google.common.base.Preconditions.checkArgument;
+
 /**
  * A SQL literal representing a TIME value, for example <code>TIME
  * '14:33:44.567'</code>.
@@ -36,7 +36,7 @@ public class SqlTimeLiteral extends SqlAbstractDateTimeLiteral {
   SqlTimeLiteral(TimeString t, int precision, boolean hasTimeZone,
       SqlParserPos pos) {
     super(t, hasTimeZone, SqlTypeName.TIME, precision, pos);
-    Preconditions.checkArgument(this.precision >= 0);
+    checkArgument(this.precision >= 0);
   }
 
   //~ Methods ----------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/calcite/sql/SqlTimestampLiteral.java b/core/src/main/java/org/apache/calcite/sql/SqlTimestampLiteral.java
index ac169cad30..d70b677279 100644
--- a/core/src/main/java/org/apache/calcite/sql/SqlTimestampLiteral.java
+++ b/core/src/main/java/org/apache/calcite/sql/SqlTimestampLiteral.java
@@ -20,10 +20,10 @@ import org.apache.calcite.sql.parser.SqlParserPos;
 import org.apache.calcite.sql.type.SqlTypeName;
 import org.apache.calcite.util.TimestampString;
 
-import com.google.common.base.Preconditions;
-
 import java.util.Objects;
 
+import static com.google.common.base.Preconditions.checkArgument;
+
 /**
  * A SQL literal representing a TIMESTAMP value, for example <code>TIMESTAMP
  * '1969-07-21 03:15 GMT'</code>.
@@ -36,8 +36,8 @@ public class SqlTimestampLiteral extends SqlAbstractDateTimeLiteral {
   SqlTimestampLiteral(TimestampString ts, int precision,
       SqlTypeName typeName, SqlParserPos pos) {
     super(ts, false, typeName, precision, pos);
-    Preconditions.checkArgument(this.precision >= 0);
-    Preconditions.checkArgument(typeName == SqlTypeName.TIMESTAMP
+    checkArgument(this.precision >= 0);
+    checkArgument(typeName == SqlTypeName.TIMESTAMP
         || typeName == SqlTypeName.TIMESTAMP_WITH_LOCAL_TIME_ZONE);
   }
 
diff --git a/core/src/main/java/org/apache/calcite/sql/SqlWindowTableFunction.java b/core/src/main/java/org/apache/calcite/sql/SqlWindowTableFunction.java
index f826fdce09..6decf5b119 100644
--- a/core/src/main/java/org/apache/calcite/sql/SqlWindowTableFunction.java
+++ b/core/src/main/java/org/apache/calcite/sql/SqlWindowTableFunction.java
@@ -29,7 +29,6 @@ import org.apache.calcite.sql.type.SqlTypeUtil;
 import org.apache.calcite.sql.validate.SqlNameMatcher;
 import org.apache.calcite.sql.validate.SqlValidator;
 
-import com.google.common.base.Preconditions;
 import com.google.common.collect.ImmutableList;
 
 import org.checkerframework.checker.nullness.qual.Nullable;
@@ -37,6 +36,8 @@ import org.checkerframework.checker.nullness.qual.Nullable;
 import java.util.Collections;
 import java.util.List;
 
+import static com.google.common.base.Preconditions.checkArgument;
+
 import static org.apache.calcite.util.Static.RESOURCE;
 
 /**
@@ -124,7 +125,7 @@ public class SqlWindowTableFunction extends SqlFunction
         int mandatoryParamCount) {
       this.paramNames = ImmutableList.copyOf(paramNames);
       this.mandatoryParamCount = mandatoryParamCount;
-      Preconditions.checkArgument(mandatoryParamCount >= 0
+      checkArgument(mandatoryParamCount >= 0
           && mandatoryParamCount <= paramNames.size());
     }
 
diff --git a/core/src/main/java/org/apache/calcite/sql/advise/SqlAdvisorValidator.java b/core/src/main/java/org/apache/calcite/sql/advise/SqlAdvisorValidator.java
index a4d157fd7d..ddcfe9a6a9 100644
--- a/core/src/main/java/org/apache/calcite/sql/advise/SqlAdvisorValidator.java
+++ b/core/src/main/java/org/apache/calcite/sql/advise/SqlAdvisorValidator.java
@@ -185,7 +185,7 @@ public class SqlAdvisorValidator extends SqlValidatorImpl {
 
   @Override protected void validateNamespace(final SqlValidatorNamespace namespace,
       RelDataType targetRowType) {
-    // Only attempt to validate each namespace once. Otherwise if
+    // Only attempt to validate each namespace once. Otherwise, if
     // validation fails, we may end up cycling.
     if (activeNamespaces.add(namespace)) {
       super.validateNamespace(namespace, targetRowType);
diff --git a/core/src/main/java/org/apache/calcite/sql/ddl/SqlCreateForeignSchema.java b/core/src/main/java/org/apache/calcite/sql/ddl/SqlCreateForeignSchema.java
index 38b4d85c67..4612918174 100644
--- a/core/src/main/java/org/apache/calcite/sql/ddl/SqlCreateForeignSchema.java
+++ b/core/src/main/java/org/apache/calcite/sql/ddl/SqlCreateForeignSchema.java
@@ -28,7 +28,6 @@ import org.apache.calcite.sql.parser.SqlParserPos;
 import org.apache.calcite.util.ImmutableNullableList;
 import org.apache.calcite.util.Pair;
 
-import com.google.common.base.Preconditions;
 import com.google.common.collect.ImmutableList;
 
 import org.checkerframework.checker.nullness.qual.Nullable;
@@ -37,6 +36,8 @@ import java.util.AbstractList;
 import java.util.List;
 import java.util.Objects;
 
+import static com.google.common.base.Preconditions.checkArgument;
+
 import static org.apache.calcite.linq4j.Nullness.castNonNull;
 
 /**
@@ -60,7 +61,7 @@ public class SqlCreateForeignSchema extends SqlCreate {
     this.name = Objects.requireNonNull(name, "name");
     this.type = type;
     this.library = library;
-    Preconditions.checkArgument((type == null) != (library == null),
+    checkArgument((type == null) != (library == null),
         "of type and library, exactly one must be specified");
     this.optionList = optionList; // may be null
   }
diff --git a/core/src/main/java/org/apache/calcite/sql/ddl/SqlCreateFunction.java b/core/src/main/java/org/apache/calcite/sql/ddl/SqlCreateFunction.java
index 245236f658..7395187554 100644
--- a/core/src/main/java/org/apache/calcite/sql/ddl/SqlCreateFunction.java
+++ b/core/src/main/java/org/apache/calcite/sql/ddl/SqlCreateFunction.java
@@ -29,12 +29,12 @@ import org.apache.calcite.sql.parser.SqlParserPos;
 import org.apache.calcite.util.Pair;
 import org.apache.calcite.util.Util;
 
-import com.google.common.base.Preconditions;
-
 import java.util.Arrays;
 import java.util.List;
 import java.util.Objects;
 
+import static com.google.common.base.Preconditions.checkArgument;
+
 /**
  * Parse tree for {@code CREATE FUNCTION} statement.
  */
@@ -54,7 +54,7 @@ public class SqlCreateFunction extends SqlCreate {
     this.name = Objects.requireNonNull(name, "name");
     this.className = className;
     this.usingList = Objects.requireNonNull(usingList, "usingList");
-    Preconditions.checkArgument(usingList.size() % 2 == 0);
+    checkArgument(usingList.size() % 2 == 0);
   }
 
   @Override public void unparse(SqlWriter writer, int leftPrec,
@@ -67,7 +67,7 @@ public class SqlCreateFunction extends SqlCreate {
     name.unparse(writer, 0, 0);
     writer.keyword("AS");
     className.unparse(writer, 0, 0);
-    if (usingList.size() > 0) {
+    if (!usingList.isEmpty()) {
       writer.keyword("USING");
       final SqlWriter.Frame frame =
           writer.startList(SqlWriter.FrameTypeEnum.SIMPLE);
diff --git a/core/src/main/java/org/apache/calcite/sql/ddl/SqlCreateTableLike.java b/core/src/main/java/org/apache/calcite/sql/ddl/SqlCreateTableLike.java
index c291de2fe3..957f87531d 100644
--- a/core/src/main/java/org/apache/calcite/sql/ddl/SqlCreateTableLike.java
+++ b/core/src/main/java/org/apache/calcite/sql/ddl/SqlCreateTableLike.java
@@ -29,13 +29,13 @@ import org.apache.calcite.sql.Symbolizable;
 import org.apache.calcite.sql.parser.SqlParserPos;
 import org.apache.calcite.util.ImmutableNullableList;
 
-import com.google.common.base.Preconditions;
-
 import java.util.HashSet;
 import java.util.List;
 import java.util.Set;
 import java.util.stream.Collectors;
 
+import static com.google.common.base.Preconditions.checkArgument;
+
 /**
  * Parse tree for {@code CREATE TABLE LIKE} statement.
  */
@@ -69,24 +69,22 @@ public class SqlCreateTableLike extends SqlCreate {
 
     // validate like options
     if (includingOptions.contains(LikeOption.ALL.symbol(SqlParserPos.ZERO))) {
-      Preconditions.checkArgument(
-          includingOptions.size() == 1 && excludingOptions.isEmpty(),
+      checkArgument(includingOptions.size() == 1 && excludingOptions.isEmpty(),
           "ALL cannot be used with other options");
     } else if (excludingOptions.contains(LikeOption.ALL.symbol(SqlParserPos.ZERO))) {
-      Preconditions.checkArgument(
-          excludingOptions.size() == 1 && includingOptions.isEmpty(),
+      checkArgument(excludingOptions.size() == 1 && includingOptions.isEmpty(),
           "ALL cannot be used with other options");
     }
 
-    includingOptions.forEach(option -> {
-      Preconditions.checkArgument(
-          !excludingOptions.contains(option),
-          "Cannot include and exclude option %s at same time", option.toString());
-    });
+    includingOptions.forEach(option ->
+        checkArgument(!excludingOptions.contains(option),
+            "Cannot include and exclude option %s at same time",
+            option.toString()));
   }
 
   @Override public List<SqlNode> getOperandList() {
-    return ImmutableNullableList.of(name, sourceTable, includingOptions, excludingOptions);
+    return ImmutableNullableList.of(name, sourceTable, includingOptions,
+        excludingOptions);
   }
 
   public Set<LikeOption> options() {
diff --git a/core/src/main/java/org/apache/calcite/sql/dialect/PrestoSqlDialect.java b/core/src/main/java/org/apache/calcite/sql/dialect/PrestoSqlDialect.java
index ddf2a10f6f..d96b898784 100644
--- a/core/src/main/java/org/apache/calcite/sql/dialect/PrestoSqlDialect.java
+++ b/core/src/main/java/org/apache/calcite/sql/dialect/PrestoSqlDialect.java
@@ -34,7 +34,6 @@ import org.apache.calcite.sql.fun.SqlStdOperatorTable;
 import org.apache.calcite.sql.parser.SqlParserPos;
 import org.apache.calcite.util.RelToSqlConverterUtil;
 
-import com.google.common.base.Preconditions;
 import com.google.common.collect.ImmutableList;
 
 import org.checkerframework.checker.nullness.qual.Nullable;
@@ -42,6 +41,8 @@ import org.checkerframework.checker.nullness.qual.Nullable;
 import java.util.ArrayList;
 import java.util.List;
 
+import static com.google.common.base.Preconditions.checkArgument;
+
 /**
  * A <code>SqlDialect</code> implementation for the Presto database.
  */
@@ -85,7 +86,7 @@ public class PrestoSqlDialect extends SqlDialect {
   /** Unparses offset/fetch using "OFFSET offset LIMIT fetch " syntax. */
   private static void unparseUsingLimit(SqlWriter writer, @Nullable SqlNode offset,
       @Nullable SqlNode fetch) {
-    Preconditions.checkArgument(fetch != null || offset != null);
+    checkArgument(fetch != null || offset != null);
     unparseOffset(writer, offset);
     unparseLimit(writer, fetch);
   }
diff --git a/core/src/main/java/org/apache/calcite/sql/fun/SqlAnyValueAggFunction.java b/core/src/main/java/org/apache/calcite/sql/fun/SqlAnyValueAggFunction.java
index 4117a84e2e..f83e4f129f 100644
--- a/core/src/main/java/org/apache/calcite/sql/fun/SqlAnyValueAggFunction.java
+++ b/core/src/main/java/org/apache/calcite/sql/fun/SqlAnyValueAggFunction.java
@@ -24,10 +24,10 @@ import org.apache.calcite.sql.type.OperandTypes;
 import org.apache.calcite.sql.type.ReturnTypes;
 import org.apache.calcite.util.Optionality;
 
-import com.google.common.base.Preconditions;
-
 import org.checkerframework.checker.nullness.qual.Nullable;
 
+import static com.google.common.base.Preconditions.checkArgument;
+
 /**
  * Definition of the <code>ANY_VALUE</code> aggregate functions,
  * returning any one of the values which go into it.
@@ -50,7 +50,7 @@ public class SqlAnyValueAggFunction extends SqlAggFunction {
         false,
         false,
         Optionality.FORBIDDEN);
-    Preconditions.checkArgument(kind == SqlKind.ANY_VALUE);
+    checkArgument(kind == SqlKind.ANY_VALUE);
   }
 
   //~ Methods ----------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/calcite/sql/fun/SqlAvgAggFunction.java b/core/src/main/java/org/apache/calcite/sql/fun/SqlAvgAggFunction.java
index 35e0163729..97358c8dc4 100644
--- a/core/src/main/java/org/apache/calcite/sql/fun/SqlAvgAggFunction.java
+++ b/core/src/main/java/org/apache/calcite/sql/fun/SqlAvgAggFunction.java
@@ -24,7 +24,7 @@ import org.apache.calcite.sql.type.OperandTypes;
 import org.apache.calcite.sql.type.ReturnTypes;
 import org.apache.calcite.util.Optionality;
 
-import com.google.common.base.Preconditions;
+import static com.google.common.base.Preconditions.checkArgument;
 
 /**
  * <code>Avg</code> is an aggregator which returns the average of the values
@@ -54,7 +54,7 @@ public class SqlAvgAggFunction extends SqlAggFunction {
         false,
         false,
         Optionality.FORBIDDEN);
-    Preconditions.checkArgument(SqlKind.AVG_AGG_FUNCTIONS.contains(kind),
+    checkArgument(SqlKind.AVG_AGG_FUNCTIONS.contains(kind),
         "unsupported sql kind");
   }
 
diff --git a/core/src/main/java/org/apache/calcite/sql/fun/SqlBitOpAggFunction.java b/core/src/main/java/org/apache/calcite/sql/fun/SqlBitOpAggFunction.java
index 808724d02d..2f60a11859 100644
--- a/core/src/main/java/org/apache/calcite/sql/fun/SqlBitOpAggFunction.java
+++ b/core/src/main/java/org/apache/calcite/sql/fun/SqlBitOpAggFunction.java
@@ -24,10 +24,10 @@ import org.apache.calcite.sql.type.OperandTypes;
 import org.apache.calcite.sql.type.ReturnTypes;
 import org.apache.calcite.util.Optionality;
 
-import com.google.common.base.Preconditions;
-
 import org.checkerframework.checker.nullness.qual.Nullable;
 
+import static com.google.common.base.Preconditions.checkArgument;
+
 /**
  * Definition of the <code>BIT_AND</code> and <code>BIT_OR</code> aggregate functions,
  * returning the bitwise AND/OR of all non-null input values, or null if none.
@@ -51,7 +51,7 @@ public class SqlBitOpAggFunction extends SqlAggFunction {
         false,
         false,
         Optionality.FORBIDDEN);
-    Preconditions.checkArgument(kind == SqlKind.BIT_AND
+    checkArgument(kind == SqlKind.BIT_AND
         || kind == SqlKind.BIT_OR
         || kind == SqlKind.BIT_XOR);
   }
@@ -68,7 +68,7 @@ public class SqlBitOpAggFunction extends SqlAggFunction {
         false,
         false,
         Optionality.FORBIDDEN);
-    Preconditions.checkArgument(kind == SqlKind.BIT_AND
+    checkArgument(kind == SqlKind.BIT_AND
         || kind == SqlKind.BIT_OR
         || kind == SqlKind.BIT_XOR);
   }
diff --git a/core/src/main/java/org/apache/calcite/sql/fun/SqlCovarAggFunction.java b/core/src/main/java/org/apache/calcite/sql/fun/SqlCovarAggFunction.java
index 446a2901dc..6486e47ecd 100644
--- a/core/src/main/java/org/apache/calcite/sql/fun/SqlCovarAggFunction.java
+++ b/core/src/main/java/org/apache/calcite/sql/fun/SqlCovarAggFunction.java
@@ -24,7 +24,7 @@ import org.apache.calcite.sql.type.OperandTypes;
 import org.apache.calcite.sql.type.ReturnTypes;
 import org.apache.calcite.util.Optionality;
 
-import com.google.common.base.Preconditions;
+import static com.google.common.base.Preconditions.checkArgument;
 
 /**
  * <code>Covar</code> is an aggregator which returns the Covariance of the
@@ -51,7 +51,7 @@ public class SqlCovarAggFunction extends SqlAggFunction {
         false,
         false,
         Optionality.FORBIDDEN);
-    Preconditions.checkArgument(SqlKind.COVAR_AVG_AGG_FUNCTIONS.contains(kind),
+    checkArgument(SqlKind.COVAR_AVG_AGG_FUNCTIONS.contains(kind),
         "unsupported sql kind: " + kind);
   }
 
diff --git a/core/src/main/java/org/apache/calcite/sql/fun/SqlFirstLastValueAggFunction.java b/core/src/main/java/org/apache/calcite/sql/fun/SqlFirstLastValueAggFunction.java
index 100639ca4a..8630ccc49d 100644
--- a/core/src/main/java/org/apache/calcite/sql/fun/SqlFirstLastValueAggFunction.java
+++ b/core/src/main/java/org/apache/calcite/sql/fun/SqlFirstLastValueAggFunction.java
@@ -26,11 +26,12 @@ import org.apache.calcite.sql.type.ReturnTypes;
 import org.apache.calcite.sql.type.SqlTypeName;
 import org.apache.calcite.util.Optionality;
 
-import com.google.common.base.Preconditions;
 import com.google.common.collect.ImmutableList;
 
 import java.util.List;
 
+import static com.google.common.base.Preconditions.checkArgument;
+
 /**
  * <code>FIRST_VALUE</code> and <code>LAST_VALUE</code> aggregate functions
  * return the first or the last value in a list of values that are input to the
@@ -51,8 +52,7 @@ public class SqlFirstLastValueAggFunction extends SqlAggFunction {
         false,
         true,
         Optionality.FORBIDDEN);
-    Preconditions.checkArgument(kind == SqlKind.FIRST_VALUE
-        || kind == SqlKind.LAST_VALUE);
+    checkArgument(kind == SqlKind.FIRST_VALUE || kind == SqlKind.LAST_VALUE);
   }
 
   @Deprecated // to be removed before 2.0
diff --git a/core/src/main/java/org/apache/calcite/sql/fun/SqlFloorFunction.java b/core/src/main/java/org/apache/calcite/sql/fun/SqlFloorFunction.java
index 77321bc0fe..784cf4d227 100644
--- a/core/src/main/java/org/apache/calcite/sql/fun/SqlFloorFunction.java
+++ b/core/src/main/java/org/apache/calcite/sql/fun/SqlFloorFunction.java
@@ -37,10 +37,10 @@ import org.apache.calcite.sql.validate.SqlMonotonicity;
 import org.apache.calcite.sql.validate.SqlValidator;
 import org.apache.calcite.sql.validate.SqlValidatorScope;
 
-import com.google.common.base.Preconditions;
-
 import org.checkerframework.checker.nullness.qual.Nullable;
 
+import static com.google.common.base.Preconditions.checkArgument;
+
 /**
  * Definition of the "FLOOR" and "CEIL" built-in SQL functions.
  */
@@ -62,7 +62,7 @@ public class SqlFloorFunction extends SqlMonotonicUnaryFunction {
                 OperandTypes.DATETIME,
                 OperandTypes.ANY)),
         SqlFunctionCategory.NUMERIC);
-    Preconditions.checkArgument(kind == SqlKind.FLOOR || kind == SqlKind.CEIL);
+    checkArgument(kind == SqlKind.FLOOR || kind == SqlKind.CEIL);
   }
 
   public SqlFloorFunction withName(String name) {
diff --git a/core/src/main/java/org/apache/calcite/sql/fun/SqlLeadLagAggFunction.java b/core/src/main/java/org/apache/calcite/sql/fun/SqlLeadLagAggFunction.java
index 9a15d54545..63b9dc14b1 100644
--- a/core/src/main/java/org/apache/calcite/sql/fun/SqlLeadLagAggFunction.java
+++ b/core/src/main/java/org/apache/calcite/sql/fun/SqlLeadLagAggFunction.java
@@ -29,7 +29,7 @@ import org.apache.calcite.sql.type.SqlTypeTransform;
 import org.apache.calcite.sql.type.SqlTypeTransforms;
 import org.apache.calcite.util.Optionality;
 
-import com.google.common.base.Preconditions;
+import static com.google.common.base.Preconditions.checkArgument;
 
 /**
  * <code>LEAD</code> and <code>LAG</code> aggregate functions
@@ -56,8 +56,7 @@ public class SqlLeadLagAggFunction extends SqlAggFunction {
         false,
         true,
         Optionality.FORBIDDEN);
-    Preconditions.checkArgument(kind == SqlKind.LEAD
-        || kind == SqlKind.LAG);
+    checkArgument(kind == SqlKind.LEAD || kind == SqlKind.LAG);
   }
 
   @Deprecated // to be removed before 2.0
diff --git a/core/src/main/java/org/apache/calcite/sql/fun/SqlLibrary.java b/core/src/main/java/org/apache/calcite/sql/fun/SqlLibrary.java
index 3f95150608..164e7cbb98 100644
--- a/core/src/main/java/org/apache/calcite/sql/fun/SqlLibrary.java
+++ b/core/src/main/java/org/apache/calcite/sql/fun/SqlLibrary.java
@@ -18,7 +18,6 @@ package org.apache.calcite.sql.fun;
 
 import org.apache.calcite.config.CalciteConnectionProperty;
 
-import com.google.common.base.Preconditions;
 import com.google.common.collect.ImmutableList;
 import com.google.common.collect.ImmutableMap;
 
@@ -30,6 +29,8 @@ import java.util.Locale;
 import java.util.Map;
 import java.util.Set;
 
+import static com.google.common.base.Preconditions.checkArgument;
+
 import static java.util.Objects.requireNonNull;
 
 /**
@@ -90,8 +91,7 @@ public enum SqlLibrary {
   SqlLibrary(String abbrev, String fun) {
     this.abbrev = requireNonNull(abbrev, "abbrev");
     this.fun = requireNonNull(fun, "fun");
-    Preconditions.checkArgument(
-        fun.equals(name().toLowerCase(Locale.ROOT).replace("_", "")));
+    checkArgument(fun.equals(name().toLowerCase(Locale.ROOT).replace("_", "")));
   }
 
   @SuppressWarnings("SwitchStatementWithTooFewBranches")
diff --git a/core/src/main/java/org/apache/calcite/sql/fun/SqlMinMaxAggFunction.java b/core/src/main/java/org/apache/calcite/sql/fun/SqlMinMaxAggFunction.java
index 5750b2bed6..2196a3647c 100644
--- a/core/src/main/java/org/apache/calcite/sql/fun/SqlMinMaxAggFunction.java
+++ b/core/src/main/java/org/apache/calcite/sql/fun/SqlMinMaxAggFunction.java
@@ -27,13 +27,14 @@ import org.apache.calcite.sql.type.ReturnTypes;
 import org.apache.calcite.sql.type.SqlOperandTypeChecker;
 import org.apache.calcite.util.Optionality;
 
-import com.google.common.base.Preconditions;
 import com.google.common.collect.ImmutableList;
 
 import org.checkerframework.checker.nullness.qual.Nullable;
 
 import java.util.List;
 
+import static com.google.common.base.Preconditions.checkArgument;
+
 /**
  * Definition of the <code>MIN</code> and <code>MAX</code> aggregate functions,
  * returning the returns the smallest/largest of the values which go into it.
@@ -89,8 +90,7 @@ public class SqlMinMaxAggFunction extends SqlAggFunction {
         Optionality.FORBIDDEN);
     this.argTypes = ImmutableList.of();
     this.minMaxKind = MINMAX_COMPARABLE;
-    Preconditions.checkArgument(kind == SqlKind.MIN
-        || kind == SqlKind.MAX);
+    checkArgument(kind == SqlKind.MIN || kind == SqlKind.MAX);
   }
 
   @Deprecated // to be removed before 2.0
diff --git a/core/src/main/java/org/apache/calcite/sql/fun/SqlQuantifyOperator.java b/core/src/main/java/org/apache/calcite/sql/fun/SqlQuantifyOperator.java
index f259627fe6..1ba3f599c4 100644
--- a/core/src/main/java/org/apache/calcite/sql/fun/SqlQuantifyOperator.java
+++ b/core/src/main/java/org/apache/calcite/sql/fun/SqlQuantifyOperator.java
@@ -26,13 +26,13 @@ import org.apache.calcite.sql.type.SqlTypeUtil;
 import org.apache.calcite.sql.validate.SqlValidator;
 import org.apache.calcite.sql.validate.SqlValidatorScope;
 
-import com.google.common.base.Preconditions;
-
 import org.checkerframework.checker.nullness.qual.Nullable;
 
 import java.util.List;
 import java.util.Objects;
 
+import static com.google.common.base.Preconditions.checkArgument;
+
 /**
  * Definition of the SQL <code>ALL</code> and <code>SOME</code>operators.
  *
@@ -61,13 +61,13 @@ public class SqlQuantifyOperator extends SqlInOperator {
   SqlQuantifyOperator(SqlKind kind, SqlKind comparisonKind) {
     super(comparisonKind.sql + " " + kind, kind);
     this.comparisonKind = Objects.requireNonNull(comparisonKind, "comparisonKind");
-    Preconditions.checkArgument(comparisonKind == SqlKind.EQUALS
+    checkArgument(comparisonKind == SqlKind.EQUALS
         || comparisonKind == SqlKind.NOT_EQUALS
         || comparisonKind == SqlKind.LESS_THAN_OR_EQUAL
         || comparisonKind == SqlKind.LESS_THAN
         || comparisonKind == SqlKind.GREATER_THAN_OR_EQUAL
         || comparisonKind == SqlKind.GREATER_THAN);
-    Preconditions.checkArgument(kind == SqlKind.SOME
+    checkArgument(kind == SqlKind.SOME
         || kind == SqlKind.ALL);
   }
 
diff --git a/core/src/main/java/org/apache/calcite/sql/fun/SqlRegrCountAggFunction.java b/core/src/main/java/org/apache/calcite/sql/fun/SqlRegrCountAggFunction.java
index 3e74da0cc9..28023ed83d 100644
--- a/core/src/main/java/org/apache/calcite/sql/fun/SqlRegrCountAggFunction.java
+++ b/core/src/main/java/org/apache/calcite/sql/fun/SqlRegrCountAggFunction.java
@@ -19,7 +19,7 @@ package org.apache.calcite.sql.fun;
 import org.apache.calcite.sql.SqlKind;
 import org.apache.calcite.sql.type.OperandTypes;
 
-import com.google.common.base.Preconditions;
+import static com.google.common.base.Preconditions.checkArgument;
 
 /**
  * Definition of the SQL <code>REGR_COUNT</code> aggregation function.
@@ -30,6 +30,6 @@ import com.google.common.base.Preconditions;
 public class SqlRegrCountAggFunction extends SqlCountAggFunction {
   public SqlRegrCountAggFunction(SqlKind kind) {
     super("REGR_COUNT", OperandTypes.NUMERIC_NUMERIC);
-    Preconditions.checkArgument(SqlKind.REGR_COUNT == kind, "unsupported sql kind: " + kind);
+    checkArgument(SqlKind.REGR_COUNT == kind, "unsupported sql kind: " + kind);
   }
 }
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 e4b8ef2b41..ca3c0a7084 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
@@ -48,7 +48,6 @@ import org.apache.calcite.util.TimestampString;
 import org.apache.calcite.util.Util;
 import org.apache.calcite.util.trace.CalciteTrace;
 
-import com.google.common.base.Preconditions;
 import com.google.common.collect.ImmutableList;
 
 import org.checkerframework.checker.nullness.qual.Nullable;
@@ -69,6 +68,8 @@ import java.util.StringTokenizer;
 import java.util.function.Predicate;
 import java.util.regex.Pattern;
 
+import static com.google.common.base.Preconditions.checkArgument;
+
 import static org.apache.calcite.util.Static.RESOURCE;
 
 import static java.lang.Integer.parseInt;
@@ -442,7 +443,7 @@ public final class SqlParserUtil {
   public static long intervalToMillis(
       String literal,
       SqlIntervalQualifier intervalQualifier) {
-    Preconditions.checkArgument(!intervalQualifier.isYearMonth(),
+    checkArgument(!intervalQualifier.isYearMonth(),
         "interval must be day time");
     int[] ret;
     try {
@@ -480,10 +481,9 @@ public final class SqlParserUtil {
         interval.getIntervalQualifier());
   }
 
-  public static long intervalToMonths(
-      String literal,
+  public static long intervalToMonths(String literal,
       SqlIntervalQualifier intervalQualifier) {
-    Preconditions.checkArgument(intervalQualifier.isYearMonth(),
+    checkArgument(intervalQualifier.isYearMonth(),
         "interval must be year month");
     int[] ret;
     try {
@@ -818,7 +818,7 @@ public final class SqlParserUtil {
       int end,
       T o) {
     requireNonNull(list, "list");
-    Preconditions.checkArgument(start < end);
+    checkArgument(start < end);
     for (int i = end - 1; i > start; --i) {
       list.remove(i);
     }
diff --git a/core/src/main/java/org/apache/calcite/sql/pretty/SqlPrettyWriter.java b/core/src/main/java/org/apache/calcite/sql/pretty/SqlPrettyWriter.java
index ee1c52d9b8..db9b38afad 100644
--- a/core/src/main/java/org/apache/calcite/sql/pretty/SqlPrettyWriter.java
+++ b/core/src/main/java/org/apache/calcite/sql/pretty/SqlPrettyWriter.java
@@ -29,7 +29,6 @@ import org.apache.calcite.sql.util.SqlString;
 import org.apache.calcite.util.Util;
 import org.apache.calcite.util.trace.CalciteLogger;
 
-import com.google.common.base.Preconditions;
 import com.google.common.collect.ImmutableList;
 
 import org.checkerframework.checker.nullness.qual.Nullable;
@@ -49,6 +48,8 @@ import java.util.Properties;
 import java.util.Set;
 import java.util.function.Consumer;
 
+import static com.google.common.base.Preconditions.checkArgument;
+
 import static java.util.Objects.requireNonNull;
 
 /**
@@ -881,7 +882,7 @@ public class SqlPrettyWriter implements SqlWriter {
 
   @Override public void endList(@Nullable Frame frame) {
     FrameImpl endedFrame = (FrameImpl) frame;
-    Preconditions.checkArgument(frame == this.frame,
+    checkArgument(frame == this.frame,
         "Frame does not match current frame");
     if (endedFrame == null) {
       throw new RuntimeException("No list started");
diff --git a/core/src/main/java/org/apache/calcite/sql/type/BasicSqlType.java b/core/src/main/java/org/apache/calcite/sql/type/BasicSqlType.java
index 9428ad409a..847e596286 100644
--- a/core/src/main/java/org/apache/calcite/sql/type/BasicSqlType.java
+++ b/core/src/main/java/org/apache/calcite/sql/type/BasicSqlType.java
@@ -20,13 +20,13 @@ import org.apache.calcite.rel.type.RelDataTypeSystem;
 import org.apache.calcite.sql.SqlCollation;
 import org.apache.calcite.util.SerializableCharset;
 
-import com.google.common.base.Preconditions;
-
 import org.checkerframework.checker.nullness.qual.Nullable;
 
 import java.nio.charset.Charset;
 import java.util.Objects;
 
+import static com.google.common.base.Preconditions.checkArgument;
+
 /**
  * BasicSqlType represents a standard atomic SQL type (excluding interval
  * types).
@@ -140,7 +140,7 @@ public class BasicSqlType extends AbstractSqlType {
    */
   BasicSqlType createWithCharsetAndCollation(Charset charset,
       SqlCollation collation) {
-    Preconditions.checkArgument(SqlTypeUtil.inCharFamily(this));
+    checkArgument(SqlTypeUtil.inCharFamily(this));
     return new BasicSqlType(this.typeSystem, this.typeName, this.isNullable,
         this.precision, this.scale, collation,
         SerializableCharset.forCharset(charset));
diff --git a/core/src/main/java/org/apache/calcite/sql/type/MatchReturnTypeInference.java b/core/src/main/java/org/apache/calcite/sql/type/MatchReturnTypeInference.java
index ad653069c5..1426c51c3e 100644
--- a/core/src/main/java/org/apache/calcite/sql/type/MatchReturnTypeInference.java
+++ b/core/src/main/java/org/apache/calcite/sql/type/MatchReturnTypeInference.java
@@ -19,13 +19,14 @@ package org.apache.calcite.sql.type;
 import org.apache.calcite.rel.type.RelDataType;
 import org.apache.calcite.sql.SqlOperatorBinding;
 
-import com.google.common.base.Preconditions;
 import com.google.common.collect.ImmutableList;
 
 import org.checkerframework.checker.nullness.qual.Nullable;
 
 import java.util.List;
 
+import static com.google.common.base.Preconditions.checkArgument;
+
 /**
  * Returns the first type that matches a set of given {@link SqlTypeName}s. If
  * no match could be found, null is returned.
@@ -53,10 +54,10 @@ public class MatchReturnTypeInference implements SqlReturnTypeInference {
    * position start (zero based).
    */
   public MatchReturnTypeInference(int start, Iterable<SqlTypeName> typeNames) {
-    Preconditions.checkArgument(start >= 0);
+    checkArgument(start >= 0);
     this.start = start;
     this.typeNames = ImmutableList.copyOf(typeNames);
-    Preconditions.checkArgument(!this.typeNames.isEmpty());
+    checkArgument(!this.typeNames.isEmpty());
   }
 
   //~ Methods ----------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/calcite/sql/type/ReturnTypes.java b/core/src/main/java/org/apache/calcite/sql/type/ReturnTypes.java
index f8696893b0..fd46977ca8 100644
--- a/core/src/main/java/org/apache/calcite/sql/type/ReturnTypes.java
+++ b/core/src/main/java/org/apache/calcite/sql/type/ReturnTypes.java
@@ -34,12 +34,12 @@ import org.apache.calcite.sql.validate.SqlValidatorNamespace;
 import org.apache.calcite.util.Glossary;
 import org.apache.calcite.util.Util;
 
-import com.google.common.base.Preconditions;
-
 import java.util.AbstractList;
 import java.util.List;
 import java.util.function.UnaryOperator;
 
+import static com.google.common.base.Preconditions.checkArgument;
+
 import static org.apache.calcite.sql.type.NonNullableAccessors.getCharset;
 import static org.apache.calcite.sql.type.NonNullableAccessors.getCollation;
 import static org.apache.calcite.sql.validate.SqlNonNullableAccessors.getNamespace;
@@ -955,8 +955,7 @@ public abstract class ReturnTypes {
             && !containsNullType
             && !(SqlTypeUtil.inCharOrBinaryFamilies(argType0)
             && SqlTypeUtil.inCharOrBinaryFamilies(argType1))) {
-          Preconditions.checkArgument(
-              SqlTypeUtil.sameNamedType(argType0, argType1));
+          checkArgument(SqlTypeUtil.sameNamedType(argType0, argType1));
         }
         SqlCollation pickedCollation = null;
         if (!containsAnyType
diff --git a/core/src/main/java/org/apache/calcite/sql/type/SqlOperandCountRanges.java b/core/src/main/java/org/apache/calcite/sql/type/SqlOperandCountRanges.java
index f8494e95f3..b0d0f18ca4 100644
--- a/core/src/main/java/org/apache/calcite/sql/type/SqlOperandCountRanges.java
+++ b/core/src/main/java/org/apache/calcite/sql/type/SqlOperandCountRanges.java
@@ -18,7 +18,7 @@ package org.apache.calcite.sql.type;
 
 import org.apache.calcite.sql.SqlOperandCountRange;
 
-import com.google.common.base.Preconditions;
+import static com.google.common.base.Preconditions.checkArgument;
 
 /**
  * Helpers for {@link SqlOperandCountRange}.
@@ -48,8 +48,8 @@ public abstract class SqlOperandCountRanges {
     RangeImpl(int min, int max) {
       this.min = min;
       this.max = max;
-      Preconditions.checkArgument(min <= max || max == -1);
-      Preconditions.checkArgument(min >= 0);
+      checkArgument(min <= max || max == -1);
+      checkArgument(min >= 0);
     }
 
     @Override public boolean isValidCount(int count) {
diff --git a/core/src/main/java/org/apache/calcite/sql/type/SqlReturnTypeInferenceChain.java b/core/src/main/java/org/apache/calcite/sql/type/SqlReturnTypeInferenceChain.java
index 6be969eef2..3ed9875b18 100644
--- a/core/src/main/java/org/apache/calcite/sql/type/SqlReturnTypeInferenceChain.java
+++ b/core/src/main/java/org/apache/calcite/sql/type/SqlReturnTypeInferenceChain.java
@@ -19,11 +19,12 @@ package org.apache.calcite.sql.type;
 import org.apache.calcite.rel.type.RelDataType;
 import org.apache.calcite.sql.SqlOperatorBinding;
 
-import com.google.common.base.Preconditions;
 import com.google.common.collect.ImmutableList;
 
 import org.checkerframework.checker.nullness.qual.Nullable;
 
+import static com.google.common.base.Preconditions.checkArgument;
+
 /**
  * Strategy to infer the type of an operator call from the type of the operands
  * by using a series of {@link SqlReturnTypeInference} rules in a given order.
@@ -44,7 +45,7 @@ public class SqlReturnTypeInferenceChain implements SqlReturnTypeInference {
    * Use {@link org.apache.calcite.sql.type.ReturnTypes#chain}.
    */
   SqlReturnTypeInferenceChain(SqlReturnTypeInference... rules) {
-    Preconditions.checkArgument(rules.length > 1);
+    checkArgument(rules.length > 1);
     this.rules = ImmutableList.copyOf(rules);
   }
 
diff --git a/core/src/main/java/org/apache/calcite/sql/type/SqlTypeTransformCascade.java b/core/src/main/java/org/apache/calcite/sql/type/SqlTypeTransformCascade.java
index b8015a282d..f007884612 100644
--- a/core/src/main/java/org/apache/calcite/sql/type/SqlTypeTransformCascade.java
+++ b/core/src/main/java/org/apache/calcite/sql/type/SqlTypeTransformCascade.java
@@ -19,13 +19,14 @@ package org.apache.calcite.sql.type;
 import org.apache.calcite.rel.type.RelDataType;
 import org.apache.calcite.sql.SqlOperatorBinding;
 
-import com.google.common.base.Preconditions;
 import com.google.common.collect.ImmutableList;
 
 import org.checkerframework.checker.nullness.qual.Nullable;
 
 import java.util.Objects;
 
+import static com.google.common.base.Preconditions.checkArgument;
+
 /**
  * Strategy to infer the type of an operator call from the type of the operands
  * by using one {@link SqlReturnTypeInference} rule and a combination of
@@ -46,7 +47,7 @@ public class SqlTypeTransformCascade implements SqlReturnTypeInference {
   public SqlTypeTransformCascade(
       SqlReturnTypeInference rule,
       SqlTypeTransform... transforms) {
-    Preconditions.checkArgument(transforms.length > 0);
+    checkArgument(transforms.length > 0);
     this.rule = Objects.requireNonNull(rule, "rule");
     this.transforms = ImmutableList.copyOf(transforms);
   }
diff --git a/core/src/main/java/org/apache/calcite/sql/type/SqlTypeUtil.java b/core/src/main/java/org/apache/calcite/sql/type/SqlTypeUtil.java
index f8ccdb92e2..8149b22dad 100644
--- a/core/src/main/java/org/apache/calcite/sql/type/SqlTypeUtil.java
+++ b/core/src/main/java/org/apache/calcite/sql/type/SqlTypeUtil.java
@@ -43,7 +43,6 @@ import org.apache.calcite.util.NumberUtil;
 import org.apache.calcite.util.Pair;
 import org.apache.calcite.util.Util;
 
-import com.google.common.base.Preconditions;
 import com.google.common.collect.ImmutableList;
 import com.google.common.collect.Sets;
 
@@ -62,6 +61,8 @@ import java.util.Map;
 import java.util.function.Function;
 import java.util.stream.Collectors;
 
+import static com.google.common.base.Preconditions.checkArgument;
+
 import static org.apache.calcite.rel.type.RelDataTypeImpl.NON_NULLABLE_SUFFIX;
 import static org.apache.calcite.sql.type.NonNullableAccessors.getCharset;
 import static org.apache.calcite.sql.type.NonNullableAccessors.getCollation;
@@ -1192,7 +1193,7 @@ public abstract class SqlTypeUtil {
    * two fields. */
   public static RelDataType createMapTypeFromRecord(
       RelDataTypeFactory typeFactory, RelDataType type) {
-    Preconditions.checkArgument(type.getFieldCount() == 2,
+    checkArgument(type.getFieldCount() == 2,
         "MAP requires exactly two fields, got %s; row type %s",
         type.getFieldCount(), type);
     return createMapType(typeFactory, type.getFieldList().get(0).getType(),
@@ -1309,10 +1310,8 @@ public abstract class SqlTypeUtil {
       RelDataTypeFactory factory,
       RelDataType type1,
       RelDataType type2) {
-    Preconditions.checkArgument(isCollection(type1),
-        "Input type1 must be collection type");
-    Preconditions.checkArgument(isCollection(type2),
-        "Input type2 must be collection type");
+    checkArgument(isCollection(type1), "Input type1 must be collection type");
+    checkArgument(isCollection(type2), "Input type2 must be collection type");
 
     return (type1 == type2)
         || (type1.getSqlTypeName() == type2.getSqlTypeName()
@@ -1334,8 +1333,8 @@ public abstract class SqlTypeUtil {
       RelDataTypeFactory factory,
       RelDataType type1,
       RelDataType type2) {
-    Preconditions.checkArgument(isMap(type1), "Input type1 must be map type");
-    Preconditions.checkArgument(isMap(type2), "Input type2 must be map type");
+    checkArgument(isMap(type1), "Input type1 must be map type");
+    checkArgument(isMap(type2), "Input type2 must be map type");
 
     MapSqlType mType1 = (MapSqlType) type1;
     MapSqlType mType2 = (MapSqlType) type2;
@@ -1362,8 +1361,8 @@ public abstract class SqlTypeUtil {
       RelDataType type1,
       RelDataType type2,
       @Nullable SqlNameMatcher nameMatcher) {
-    Preconditions.checkArgument(type1.isStruct(), "Input type1 must be struct type");
-    Preconditions.checkArgument(type2.isStruct(), "Input type2 must be struct type");
+    checkArgument(type1.isStruct(), "Input type1 must be struct type");
+    checkArgument(type2.isStruct(), "Input type2 must be struct type");
 
     if (type1 == type2) {
       return true;
diff --git a/core/src/main/java/org/apache/calcite/sql/validate/AbstractNamespace.java b/core/src/main/java/org/apache/calcite/sql/validate/AbstractNamespace.java
index 40c16bee84..3f16078314 100644
--- a/core/src/main/java/org/apache/calcite/sql/validate/AbstractNamespace.java
+++ b/core/src/main/java/org/apache/calcite/sql/validate/AbstractNamespace.java
@@ -23,13 +23,15 @@ import org.apache.calcite.sql.SqlNode;
 import org.apache.calcite.util.Pair;
 import org.apache.calcite.util.Util;
 
-import com.google.common.base.Preconditions;
 import com.google.common.collect.ImmutableList;
 
 import org.checkerframework.checker.nullness.qual.Nullable;
 
 import java.util.List;
-import java.util.Objects;
+
+import static com.google.common.base.Preconditions.checkArgument;
+
+import static java.util.Objects.requireNonNull;
 
 /**
  * Abstract implementation of {@link SqlValidatorNamespace}.
@@ -83,11 +85,10 @@ abstract class AbstractNamespace implements SqlValidatorNamespace {
     case UNVALIDATED:
       try {
         status = SqlValidatorImpl.Status.IN_PROGRESS;
-        Preconditions.checkArgument(rowType == null,
+        checkArgument(rowType == null,
             "Namespace.rowType must be null before validate has been called");
         RelDataType type = validateImpl(targetRowType);
-        Preconditions.checkArgument(type != null,
-            "validateImpl() returned null");
+        requireNonNull(type, "validateImpl() returned null");
         setType(type);
       } finally {
         status = SqlValidatorImpl.Status.VALID;
@@ -107,17 +108,16 @@ abstract class AbstractNamespace implements SqlValidatorNamespace {
    * External users should call {@link #validate}, which uses the
    * {@link #status} field to protect against cycles.
    *
-   * @return record data type, never null
-   *
    * @param targetRowType Desired row type, must not be null, may be the data
    *                      type 'unknown'.
+   * @return record data type, never null
    */
   protected abstract RelDataType validateImpl(RelDataType targetRowType);
 
   @Override public RelDataType getRowType() {
     if (rowType == null) {
       validator.validateNamespace(this, validator.unknownType);
-      Objects.requireNonNull(rowType, "validate must set rowType");
+      requireNonNull(rowType, "validate must set rowType");
     }
     return rowType;
   }
@@ -128,7 +128,7 @@ abstract class AbstractNamespace implements SqlValidatorNamespace {
 
   @Override public RelDataType getType() {
     Util.discard(getRowType());
-    return Objects.requireNonNull(type, "type");
+    return requireNonNull(type, "type");
   }
 
   @Override public void setType(RelDataType type) {
@@ -179,7 +179,7 @@ abstract class AbstractNamespace implements SqlValidatorNamespace {
     return true;
   }
 
-  @Override public <T extends Object> T unwrap(Class<T> clazz) {
+  @Override public <T> T unwrap(Class<T> clazz) {
     return clazz.cast(this);
   }
 
@@ -219,9 +219,7 @@ abstract class AbstractNamespace implements SqlValidatorNamespace {
       return type;
     }
     return validator.getTypeFactory().builder()
-        .add(
-            SqlValidatorUtil.alias(Objects.requireNonNull(unnest, "unnest"), 0),
-            type)
+        .add(SqlValidatorUtil.alias(requireNonNull(unnest, "unnest"), 0), type)
         .build();
   }
 }
diff --git a/core/src/main/java/org/apache/calcite/sql/validate/DelegatingNamespace.java b/core/src/main/java/org/apache/calcite/sql/validate/DelegatingNamespace.java
index a5aee4e79e..21f59a3dfd 100644
--- a/core/src/main/java/org/apache/calcite/sql/validate/DelegatingNamespace.java
+++ b/core/src/main/java/org/apache/calcite/sql/validate/DelegatingNamespace.java
@@ -104,7 +104,7 @@ public abstract class DelegatingNamespace implements SqlValidatorNamespace {
   @Override public void makeNullable() {
   }
 
-  @Override public <T extends Object> T unwrap(Class<T> clazz) {
+  @Override public <T> T unwrap(Class<T> clazz) {
     if (clazz.isInstance(this)) {
       return clazz.cast(this);
     } else {
diff --git a/core/src/main/java/org/apache/calcite/sql/validate/DelegatingScope.java b/core/src/main/java/org/apache/calcite/sql/validate/DelegatingScope.java
index 935e9bc14b..a038bbe980 100644
--- a/core/src/main/java/org/apache/calcite/sql/validate/DelegatingScope.java
+++ b/core/src/main/java/org/apache/calcite/sql/validate/DelegatingScope.java
@@ -35,7 +35,6 @@ import org.apache.calcite.sql.type.SqlTypeName;
 import org.apache.calcite.util.Pair;
 import org.apache.calcite.util.Util;
 
-import com.google.common.base.Preconditions;
 import com.google.common.base.Suppliers;
 import com.google.common.collect.ImmutableList;
 
@@ -50,6 +49,8 @@ import java.util.List;
 import java.util.Map;
 import java.util.function.Supplier;
 
+import static com.google.common.base.Preconditions.checkArgument;
+
 import static org.apache.calcite.util.Static.RESOURCE;
 
 import static java.util.Objects.requireNonNull;
@@ -605,8 +606,7 @@ public abstract class DelegatingScope implements SqlValidatorScope {
   }
 
   private AggregatingSelectScope.Resolved resolve() {
-    Preconditions.checkArgument(groupAnalyzer == null,
-        "resolve already in progress");
+    checkArgument(groupAnalyzer == null, "resolve already in progress");
     SqlValidatorUtil.GroupAnalyzer groupAnalyzer = new SqlValidatorUtil.GroupAnalyzer();
     this.groupAnalyzer = groupAnalyzer;
     try {
diff --git a/core/src/main/java/org/apache/calcite/sql/validate/IdentifierNamespace.java b/core/src/main/java/org/apache/calcite/sql/validate/IdentifierNamespace.java
index 8bd130f282..c3fab93146 100644
--- a/core/src/main/java/org/apache/calcite/sql/validate/IdentifierNamespace.java
+++ b/core/src/main/java/org/apache/calcite/sql/validate/IdentifierNamespace.java
@@ -31,13 +31,12 @@ import com.google.common.collect.ImmutableList;
 import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
 import org.checkerframework.checker.nullness.qual.Nullable;
 
-import java.util.ArrayList;
-import java.util.Collections;
 import java.util.List;
-import java.util.Objects;
 
 import static org.apache.calcite.util.Static.RESOURCE;
 
+import static java.util.Objects.requireNonNull;
+
 /**
  * Namespace whose contents are defined by the type of an
  * {@link org.apache.calcite.sql.SqlIdentifier identifier}.
@@ -77,7 +76,7 @@ public class IdentifierNamespace extends AbstractNamespace {
     super(validator, enclosingNode);
     this.id = id;
     this.extendList = extendList;
-    this.parentScope = Objects.requireNonNull(parentScope, "parentScope");
+    this.parentScope = requireNonNull(parentScope, "parentScope");
   }
 
   IdentifierNamespace(SqlValidatorImpl validator, SqlNode node,
@@ -187,30 +186,27 @@ public class IdentifierNamespace extends AbstractNamespace {
 
   @Override public RelDataType validateImpl(RelDataType targetRowType) {
     resolvedNamespace = resolveImpl(id);
-    if (resolvedNamespace instanceof TableNamespace) {
-      SqlValidatorTable table = ((TableNamespace) resolvedNamespace).getTable();
-      if (validator.config().identifierExpansion()) {
+    validator.validateNamespace(resolvedNamespace, targetRowType);
+
+    if (validator.config().identifierExpansion()) {
+      SqlValidatorTable table = resolvedNamespace.getTable();
+      if (table != null) {
         // TODO:  expand qualifiers for column references also
         List<String> qualifiedNames = table.getQualifiedName();
-        if (qualifiedNames != null) {
-          // Assign positions to the components of the fully-qualified
-          // identifier, as best we can. We assume that qualification
-          // adds names to the front, e.g. FOO.BAR becomes BAZ.FOO.BAR.
-          List<SqlParserPos> poses =
-              new ArrayList<>(
-                  Collections.nCopies(
-                      qualifiedNames.size(), id.getParserPosition()));
-          int offset = qualifiedNames.size() - id.names.size();
-
-          // Test offset in case catalog supports fewer qualifiers than catalog
-          // reader.
-          if (offset >= 0) {
-            for (int i = 0; i < id.names.size(); i++) {
-              poses.set(i + offset, id.getComponentParserPosition(i));
-            }
-          }
-          id.setNames(qualifiedNames, poses);
+        // Assign positions to the components of the fully-qualified
+        // identifier, as best we can. We assume that qualification
+        // adds names to the front, e.g. FOO.BAR becomes BAZ.FOO.BAR.
+        // Test offset in case catalog supports fewer qualifiers than catalog
+        // reader.
+        ImmutableList.Builder<SqlParserPos> positions =
+            ImmutableList.builder();
+        int offset = qualifiedNames.size() - id.names.size();
+        for (int i = 0; i < qualifiedNames.size(); i++) {
+          positions.add(offset >= 0 && i >= offset
+              ? id.getComponentParserPosition(i - offset)
+              : id.getParserPosition());
         }
+        id.setNames(qualifiedNames, positions.build());
       }
     }
 
diff --git a/core/src/main/java/org/apache/calcite/sql/validate/ListScope.java b/core/src/main/java/org/apache/calcite/sql/validate/ListScope.java
index e91a476dca..0d83ccd6bf 100644
--- a/core/src/main/java/org/apache/calcite/sql/validate/ListScope.java
+++ b/core/src/main/java/org/apache/calcite/sql/validate/ListScope.java
@@ -36,6 +36,8 @@ import java.util.Objects;
 
 import static org.apache.calcite.util.Static.RESOURCE;
 
+import static java.util.Objects.requireNonNull;
+
 /**
  * Abstract base for a scope which is defined by a list of child namespaces and
  * which inherits from a parent scope.
@@ -58,7 +60,7 @@ public abstract class ListScope extends DelegatingScope {
 
   @Override public void addChild(SqlValidatorNamespace ns, String alias,
       boolean nullable) {
-    Objects.requireNonNull(alias, "alias");
+    requireNonNull(alias, "alias");
     children.add(new ScopeChild(children.size(), alias, ns, nullable));
   }
 
diff --git a/core/src/main/java/org/apache/calcite/sql/validate/SqlLambdaScope.java b/core/src/main/java/org/apache/calcite/sql/validate/SqlLambdaScope.java
index ac7e1eac54..02fb615c76 100644
--- a/core/src/main/java/org/apache/calcite/sql/validate/SqlLambdaScope.java
+++ b/core/src/main/java/org/apache/calcite/sql/validate/SqlLambdaScope.java
@@ -23,13 +23,13 @@ import org.apache.calcite.sql.SqlNode;
 import org.apache.calcite.sql.type.SqlTypeName;
 import org.apache.calcite.util.Litmus;
 
-import com.google.common.base.Preconditions;
-
 import org.checkerframework.checker.nullness.qual.Nullable;
 
 import java.util.HashMap;
 import java.util.Map;
 
+import static com.google.common.base.Preconditions.checkArgument;
+
 import static org.apache.calcite.util.Static.RESOURCE;
 
 /**
@@ -69,7 +69,7 @@ public class SqlLambdaScope extends ListScope {
   }
 
   @Override public @Nullable RelDataType resolveColumn(String columnName, SqlNode ctx) {
-    Preconditions.checkArgument(parameterTypes.containsKey(columnName),
+    checkArgument(parameterTypes.containsKey(columnName),
         "column %s not found", columnName);
     return parameterTypes.get(columnName);
   }
diff --git a/core/src/main/java/org/apache/calcite/sql/validate/SqlQualified.java b/core/src/main/java/org/apache/calcite/sql/validate/SqlQualified.java
index 9742f1510b..48bb492de2 100644
--- a/core/src/main/java/org/apache/calcite/sql/validate/SqlQualified.java
+++ b/core/src/main/java/org/apache/calcite/sql/validate/SqlQualified.java
@@ -47,7 +47,7 @@ public class SqlQualified {
   }
 
   @Override public String toString() {
-    return "{id: " + identifier.toString() + ", prefix: " + prefixLength + "}";
+    return "{id: " + identifier + ", prefix: " + prefixLength + "}";
   }
 
   public static SqlQualified create(@Nullable SqlValidatorScope scope, int prefixLength,
diff --git a/core/src/main/java/org/apache/calcite/sql/validate/SqlValidatorImpl.java b/core/src/main/java/org/apache/calcite/sql/validate/SqlValidatorImpl.java
index 81f2140b6a..03389814c3 100644
--- a/core/src/main/java/org/apache/calcite/sql/validate/SqlValidatorImpl.java
+++ b/core/src/main/java/org/apache/calcite/sql/validate/SqlValidatorImpl.java
@@ -117,7 +117,6 @@ import org.apache.calcite.util.Static;
 import org.apache.calcite.util.Util;
 import org.apache.calcite.util.trace.CalciteTrace;
 
-import com.google.common.base.Preconditions;
 import com.google.common.collect.ImmutableList;
 import com.google.common.collect.ImmutableSet;
 import com.google.common.collect.Sets;
@@ -154,7 +153,11 @@ import java.util.function.Supplier;
 import java.util.function.UnaryOperator;
 import java.util.stream.Collectors;
 
+import static com.google.common.base.Preconditions.checkArgument;
+import static com.google.common.base.Preconditions.checkState;
+
 import static org.apache.calcite.linq4j.Nullness.castNonNull;
+import static org.apache.calcite.linq4j.Ord.forEach;
 import static org.apache.calcite.sql.SqlUtil.stripAs;
 import static org.apache.calcite.sql.type.NonNullableAccessors.getCharset;
 import static org.apache.calcite.sql.type.NonNullableAccessors.getCollation;
@@ -163,6 +166,7 @@ import static org.apache.calcite.sql.validate.SqlNonNullableAccessors.getTable;
 import static org.apache.calcite.util.Static.RESOURCE;
 import static org.apache.calcite.util.Util.first;
 
+import static java.util.Collections.emptyList;
 import static java.util.Objects.requireNonNull;
 
 /**
@@ -746,7 +750,7 @@ public class SqlValidatorImpl implements SqlValidatorWithHints {
   private static int calculatePermuteOffset(List<SqlNode> selectItems) {
     for (int i = 0; i < selectItems.size(); i++) {
       SqlNode selectItem = selectItems.get(i);
-      SqlNode col = SqlUtil.stripAs(selectItem);
+      SqlNode col = stripAs(selectItem);
       if (col.getKind() == SqlKind.IDENTIFIER
           && selectItem.getKind() != SqlKind.AS) {
         return i;
@@ -1914,9 +1918,7 @@ public class SqlValidatorImpl implements SqlValidatorWithHints {
       return ns.getType();
     }
     type = deriveTypeImpl(scope, expr);
-    Preconditions.checkArgument(
-        type != null,
-        "SqlValidator.deriveTypeInternal returned null");
+    requireNonNull(type, "SqlValidator.deriveTypeInternal returned null");
     setValidatedNodeType(expr, type);
     return type;
   }
@@ -2745,7 +2747,7 @@ public class SqlValidatorImpl implements SqlValidatorWithHints {
       SqlNode enclosingNode,
       @Nullable String alias,
       boolean forceNullable) {
-    Preconditions.checkArgument(usingScope == null || alias != null);
+    checkArgument(usingScope == null || alias != null);
     registerQuery(
         parentScope,
         usingScope,
@@ -2778,7 +2780,7 @@ public class SqlValidatorImpl implements SqlValidatorWithHints {
       boolean checkUpdate) {
     requireNonNull(node, "node");
     requireNonNull(enclosingNode, "enclosingNode");
-    Preconditions.checkArgument(usingScope == null || alias != null);
+    checkArgument(usingScope == null || alias != null);
 
     SqlCall call;
     List<SqlNode> operands;
@@ -3623,7 +3625,7 @@ public class SqlValidatorImpl implements SqlValidatorWithHints {
     // Validate condition.
     switch (conditionType) {
     case NONE:
-      Preconditions.checkArgument(join.getCondition() == null);
+      checkArgument(join.getCondition() == null);
       break;
     case ON:
       final SqlNode condition = expand(getCondition(join), joinScope);
@@ -3636,7 +3638,7 @@ public class SqlValidatorImpl implements SqlValidatorWithHints {
           (List) getCondition(join);
 
       // Parser ensures that using clause is not empty.
-      Preconditions.checkArgument(!list.isEmpty(), "Empty USING clause");
+      checkArgument(!list.isEmpty(), "Empty USING clause");
       for (SqlIdentifier id : list) {
         validateCommonJoinColumn(id, left, right, scope, natural);
       }
@@ -3741,7 +3743,7 @@ public class SqlValidatorImpl implements SqlValidatorWithHints {
   }
 
   private RelDataType checkAndDeriveDataType(SqlIdentifier id, SqlNode node) {
-    Preconditions.checkArgument(id.names.size() == 1);
+    checkArgument(id.names.size() == 1);
     String name = id.names.get(0);
     SqlNameMatcher nameMatcher = getCatalogReader().nameMatcher();
     RelDataType rowType = getNamespaceOrThrow(node).getRowType();
@@ -3755,7 +3757,7 @@ public class SqlValidatorImpl implements SqlValidatorWithHints {
    * NATURAL join, in the left or right input to the join. */
   private RelDataType validateCommonInputJoinColumn(SqlIdentifier id,
       SqlNode leftOrRight, SqlValidatorScope scope, boolean natural) {
-    Preconditions.checkArgument(id.names.size() == 1);
+    checkArgument(id.names.size() == 1);
     final String name = id.names.get(0);
     final SqlValidatorNamespace namespace = getNamespaceOrThrow(leftOrRight);
     final RelDataType rowType = namespace.getRowType();
@@ -3790,7 +3792,8 @@ public class SqlValidatorImpl implements SqlValidatorWithHints {
   protected void validateSelect(
       SqlSelect select,
       RelDataType targetRowType) {
-    assert targetRowType != null;
+    requireNonNull(targetRowType, "targetRowType");
+
     // Namespace is either a select namespace or a wrapper around one.
     final SelectNamespace ns =
         getNamespaceOrThrow(select).unwrap(SelectNamespace.class);
@@ -3844,12 +3847,13 @@ public class SqlValidatorImpl implements SqlValidatorWithHints {
           RESOURCE.fromAliasDuplicate(child.name));
     }
 
-    if (select.getFrom() == null) {
+    final SqlNode from = select.getFrom();
+    if (from == null) {
       if (this.config.conformance().isFromRequired()) {
         throw newValidationError(select, RESOURCE.selectMissingFrom());
       }
     } else {
-      validateFrom(select.getFrom(), fromType, fromScope);
+      validateFrom(from, fromType, fromScope);
     }
 
     validateWhereClause(select);
@@ -3871,7 +3875,7 @@ public class SqlValidatorImpl implements SqlValidatorWithHints {
     // "SELECT empno AS x FROM emp ORDER BY x"
     validateOrderList(select);
 
-    if (shouldCheckForRollUp(select.getFrom())) {
+    if (shouldCheckForRollUp(from)) {
       checkRollUpInSelectList(select);
       checkRollUp(null, select, select.getWhere(), getWhereScope(select));
       checkRollUp(null, select, select.getHaving(), getHavingScope(select));
@@ -4624,7 +4628,7 @@ public class SqlValidatorImpl implements SqlValidatorWithHints {
   private static boolean isReturnBooleanType(RelDataType relDataType) {
     if (relDataType instanceof RelRecordType) {
       RelRecordType recordType = (RelRecordType) relDataType;
-      Preconditions.checkState(recordType.getFieldList().size() == 1,
+      checkState(recordType.getFieldList().size() == 1,
           "sub-query as condition must return only one column");
       RelDataTypeField recordField = recordType.getFieldList().get(0);
       return SqlTypeUtil.inBooleanFamily(recordField.getType());
@@ -5795,12 +5799,13 @@ public class SqlValidatorImpl implements SqlValidatorWithHints {
       }
     });
 
-    final RelDataType rowType = typeBuilder.build();
-    if (matchRecognize.getMeasureList().size() == 0) {
-      ns.setType(getNamespaceOrThrow(matchRecognize.getTableRef()).getRowType());
+    final RelDataType rowType;
+    if (matchRecognize.getMeasureList().isEmpty()) {
+      rowType = getNamespaceOrThrow(matchRecognize.getTableRef()).getRowType();
     } else {
-      ns.setType(rowType);
+      rowType = typeBuilder.build();
     }
+    ns.setType(rowType);
   }
 
   private PairList<String, RelDataType> validateMeasure(SqlMatchRecognize mr,
@@ -6043,7 +6048,7 @@ public class SqlValidatorImpl implements SqlValidatorWithHints {
 
     // Gather the name and type of each measure.
     final PairList<String, RelDataType> measureNameTypes = PairList.of();
-    Ord.forEach(unpivot.measureList, (measure, i) -> {
+    forEach(unpivot.measureList, (measure, i) -> {
       final String measureName = ((SqlIdentifier) measure).getSimple();
       final List<RelDataType> types = new ArrayList<>();
       final List<SqlNode> nodes = new ArrayList<>();
@@ -6080,7 +6085,7 @@ public class SqlValidatorImpl implements SqlValidatorWithHints {
     // ('CLERK', 'ANALYST'), namely VARCHAR(7). The derived type of 'deptno' is
     // the type of values (10, 20), namely INTEGER.
     final PairList<String, RelDataType> axisNameTypes = PairList.of();
-    Ord.forEach(unpivot.axisList, (axis, i) -> {
+    forEach(unpivot.axisList, (axis, i) -> {
       final String axisName = ((SqlIdentifier) axis).getSimple();
       final List<RelDataType> types = new ArrayList<>();
       unpivot.forEachNameValues((aliasList, valueList) ->
@@ -6183,7 +6188,7 @@ public class SqlValidatorImpl implements SqlValidatorWithHints {
     final SqlAggFunction op = (SqlAggFunction) aggCall.getOperator();
     switch (op.requiresGroupOrder()) {
     case MANDATORY:
-      if (orderList == null || orderList.size() == 0) {
+      if (orderList == null || orderList.isEmpty()) {
         throw newValidationError(aggCall,
             RESOURCE.aggregateMissingWithinGroupClause(op.getName()));
       }
@@ -6197,7 +6202,7 @@ public class SqlValidatorImpl implements SqlValidatorWithHints {
       }
       break;
     case FORBIDDEN:
-      if (orderList != null && orderList.size() != 0) {
+      if (orderList != null && !orderList.isEmpty()) {
         throw newValidationError(aggCall,
             RESOURCE.withinGroupClauseIllegalInAggregate(op.getName()));
       }
@@ -6350,7 +6355,7 @@ public class SqlValidatorImpl implements SqlValidatorWithHints {
 
   @Override public List<@Nullable List<String>> getFieldOrigins(SqlNode sqlQuery) {
     if (sqlQuery instanceof SqlExplain) {
-      return Collections.emptyList();
+      return emptyList();
     }
     final RelDataType rowType = getValidatedNodeType(sqlQuery);
     final int fieldCount = rowType.getFieldCount();
@@ -6575,7 +6580,7 @@ public class SqlValidatorImpl implements SqlValidatorWithHints {
     }
 
     @Override public Void visit(SqlIdentifier id) {
-      Preconditions.checkArgument(id.isSimple());
+      checkArgument(id.isSimple());
       scope.addPatternVar(id.getSimple());
       return null;
     }
@@ -7031,7 +7036,8 @@ public class SqlValidatorImpl implements SqlValidatorWithHints {
 
             // SQL ordinals are 1-based, but Sort's are 0-based
             int ordinal = intValue - 1;
-            return SqlUtil.stripAs(SqlNonNullableAccessors.getSelectList(select).get(ordinal));
+            return stripAs(SqlNonNullableAccessors.getSelectList(select)
+                .get(ordinal));
           }
           break;
         default:
diff --git a/core/src/main/java/org/apache/calcite/sql/validate/SqlValidatorNamespace.java b/core/src/main/java/org/apache/calcite/sql/validate/SqlValidatorNamespace.java
index 3de29d403e..ddcaceefb4 100644
--- a/core/src/main/java/org/apache/calcite/sql/validate/SqlValidatorNamespace.java
+++ b/core/src/main/java/org/apache/calcite/sql/validate/SqlValidatorNamespace.java
@@ -184,7 +184,7 @@ public interface SqlValidatorNamespace {
    * @return This namespace cast to desired type
    * @throws ClassCastException if no such interface is available
    */
-  <T extends Object> T unwrap(Class<T> clazz);
+  <T> T unwrap(Class<T> clazz);
 
   /**
    * Returns whether this namespace implements a given interface, or wraps a
diff --git a/core/src/main/java/org/apache/calcite/sql/validate/SqlValidatorUtil.java b/core/src/main/java/org/apache/calcite/sql/validate/SqlValidatorUtil.java
index 6d1119c9a4..3c4565bb2f 100644
--- a/core/src/main/java/org/apache/calcite/sql/validate/SqlValidatorUtil.java
+++ b/core/src/main/java/org/apache/calcite/sql/validate/SqlValidatorUtil.java
@@ -63,7 +63,6 @@ import org.apache.calcite.util.Pair;
 import org.apache.calcite.util.Util;
 
 import com.google.common.annotations.VisibleForTesting;
-import com.google.common.base.Preconditions;
 import com.google.common.collect.ImmutableList;
 import com.google.common.collect.ImmutableMap;
 import com.google.common.collect.Iterables;
@@ -84,6 +83,8 @@ import java.util.Properties;
 import java.util.Set;
 import java.util.TreeSet;
 
+import static com.google.common.base.Preconditions.checkArgument;
+
 import static org.apache.calcite.linq4j.Nullness.castNonNullList;
 import static org.apache.calcite.sql.type.NonNullableAccessors.getCharset;
 import static org.apache.calcite.sql.type.NonNullableAccessors.getCollation;
@@ -329,7 +330,7 @@ public class SqlValidatorUtil {
    * "expr$<i>ordinal</i>"; never null
    */
   public static String alias(SqlNode node, int ordinal) {
-    Preconditions.checkArgument(ordinal >= 0);
+    checkArgument(ordinal >= 0);
     return requireNonNull(alias_(node, ordinal), "alias");
   }
 
@@ -1540,11 +1541,11 @@ public class SqlValidatorUtil {
         @Nullable SqlCall distinctCall, @Nullable SqlCall orderCall) {
       this.aggregateCall =
           Objects.requireNonNull(aggregateCall, "aggregateCall");
-      Preconditions.checkArgument(filterCall == null
+      checkArgument(filterCall == null
           || filterCall.getKind() == SqlKind.FILTER);
-      Preconditions.checkArgument(distinctCall == null
+      checkArgument(distinctCall == null
           || distinctCall.getKind() == SqlKind.WITHIN_DISTINCT);
-      Preconditions.checkArgument(orderCall == null
+      checkArgument(orderCall == null
           || orderCall.getKind() == SqlKind.WITHIN_GROUP);
       this.filterCall = filterCall;
       this.filter = filterCall == null ? null : filterCall.operand(1);
diff --git a/core/src/main/java/org/apache/calcite/sql2rel/ReflectiveConvertletTable.java b/core/src/main/java/org/apache/calcite/sql2rel/ReflectiveConvertletTable.java
index 47be8816dd..1b7077d53a 100644
--- a/core/src/main/java/org/apache/calcite/sql2rel/ReflectiveConvertletTable.java
+++ b/core/src/main/java/org/apache/calcite/sql2rel/ReflectiveConvertletTable.java
@@ -22,8 +22,6 @@ import org.apache.calcite.sql.SqlNode;
 import org.apache.calcite.sql.SqlOperator;
 import org.apache.calcite.sql.parser.SqlParserPos;
 
-import com.google.common.base.Preconditions;
-
 import org.checkerframework.checker.initialization.qual.UnderInitialization;
 import org.checkerframework.checker.nullness.qual.Nullable;
 import org.checkerframework.checker.nullness.qual.RequiresNonNull;
@@ -33,6 +31,8 @@ import java.lang.reflect.Method;
 import java.util.HashMap;
 import java.util.Map;
 
+import static com.google.common.base.Preconditions.checkArgument;
+
 import static org.apache.calcite.util.ReflectUtil.isPublic;
 
 import static java.util.Objects.requireNonNull;
@@ -208,8 +208,7 @@ public class ReflectiveConvertletTable implements SqlRexConvertletTable {
       final SqlOperator alias, final SqlOperator target) {
     map.put(
         alias, (SqlRexConvertlet) (cx, call) -> {
-          Preconditions.checkArgument(call.getOperator() == alias,
-              "call to wrong operator");
+          checkArgument(call.getOperator() == alias, "call to wrong operator");
           final SqlCall newCall =
               target.createCall(SqlParserPos.ZERO, call.getOperandList());
           cx.getValidator().setValidatedNodeType(newCall,
diff --git a/core/src/main/java/org/apache/calcite/sql2rel/SqlNodeToRexConverterImpl.java b/core/src/main/java/org/apache/calcite/sql2rel/SqlNodeToRexConverterImpl.java
index afdfe92fe9..313fda132c 100644
--- a/core/src/main/java/org/apache/calcite/sql2rel/SqlNodeToRexConverterImpl.java
+++ b/core/src/main/java/org/apache/calcite/sql2rel/SqlNodeToRexConverterImpl.java
@@ -34,10 +34,10 @@ import org.apache.calcite.util.TimeString;
 import org.apache.calcite.util.TimestampString;
 import org.apache.calcite.util.Util;
 
-import com.google.common.base.Preconditions;
-
 import java.math.BigDecimal;
 
+import static com.google.common.base.Preconditions.checkArgument;
+
 /**
  * Standard implementation of {@link SqlNodeToRexConverter}.
  */
@@ -108,8 +108,7 @@ public class SqlNodeToRexConverterImpl implements SqlNodeToRexConverter {
       return rexBuilder.makeLiteral(literal.getValueAs(Boolean.class));
     case BINARY:
       final BitString bitString = literal.getValueAs(BitString.class);
-      Preconditions.checkArgument((bitString.getBitCount() % 8) == 0,
-          "incomplete octet");
+      checkArgument((bitString.getBitCount() % 8) == 0, "incomplete octet");
 
       // An even number of hexits (e.g. X'ABCD') makes whole number
       // of bytes.
diff --git a/core/src/main/java/org/apache/calcite/sql2rel/StandardConvertletTable.java b/core/src/main/java/org/apache/calcite/sql2rel/StandardConvertletTable.java
index ccd946c437..9211f9778c 100644
--- a/core/src/main/java/org/apache/calcite/sql2rel/StandardConvertletTable.java
+++ b/core/src/main/java/org/apache/calcite/sql2rel/StandardConvertletTable.java
@@ -82,7 +82,6 @@ import org.apache.calcite.sql.validate.SqlValidator;
 import org.apache.calcite.util.Pair;
 import org.apache.calcite.util.Util;
 
-import com.google.common.base.Preconditions;
 import com.google.common.collect.ImmutableList;
 
 import org.checkerframework.checker.initialization.qual.UnknownInitialization;
@@ -1840,7 +1839,7 @@ public class StandardConvertletTable extends ReflectiveConvertletTable {
 
     SubstrConvertlet(SqlLibrary library) {
       this.library = library;
-      Preconditions.checkArgument(library == SqlLibrary.ORACLE
+      checkArgument(library == SqlLibrary.ORACLE
           || library == SqlLibrary.MYSQL
           || library == SqlLibrary.BIG_QUERY
           || library == SqlLibrary.POSTGRESQL);
diff --git a/core/src/main/java/org/apache/calcite/tools/Hoist.java b/core/src/main/java/org/apache/calcite/tools/Hoist.java
index f2ac5dba04..3fceb10b5f 100644
--- a/core/src/main/java/org/apache/calcite/tools/Hoist.java
+++ b/core/src/main/java/org/apache/calcite/tools/Hoist.java
@@ -25,7 +25,6 @@ import org.apache.calcite.sql.parser.SqlParserUtil;
 import org.apache.calcite.sql.type.SqlTypeName;
 import org.apache.calcite.sql.util.SqlShuttle;
 
-import com.google.common.base.Preconditions;
 import com.google.common.collect.ImmutableList;
 import com.google.common.collect.Lists;
 
@@ -38,6 +37,8 @@ import java.util.List;
 import java.util.Objects;
 import java.util.function.Function;
 
+import static com.google.common.base.Preconditions.checkArgument;
+
 /**
  * Utility that extracts constants from a SQL query.
  *
@@ -154,10 +155,10 @@ public class Hoist {
           SqlParserUtil.lineColToIndex(originalSql,
               pos.getEndLineNum(), pos.getEndColumnNum()) + 1;
 
-      Preconditions.checkArgument(ordinal >= 0);
-      Preconditions.checkArgument(start >= 0);
-      Preconditions.checkArgument(start <= end);
-      Preconditions.checkArgument(end <= originalSql.length());
+      checkArgument(ordinal >= 0);
+      checkArgument(start >= 0);
+      checkArgument(start <= end);
+      checkArgument(end <= originalSql.length());
     }
 
     /** Returns SQL text of the region of the statement covered by this
diff --git a/core/src/main/java/org/apache/calcite/tools/RelBuilder.java b/core/src/main/java/org/apache/calcite/tools/RelBuilder.java
index 757e81265f..8d8d48bd07 100644
--- a/core/src/main/java/org/apache/calcite/tools/RelBuilder.java
+++ b/core/src/main/java/org/apache/calcite/tools/RelBuilder.java
@@ -118,7 +118,6 @@ import org.apache.calcite.util.Util;
 import org.apache.calcite.util.mapping.Mapping;
 import org.apache.calcite.util.mapping.Mappings;
 
-import com.google.common.base.Preconditions;
 import com.google.common.collect.ImmutableList;
 import com.google.common.collect.ImmutableMap;
 import com.google.common.collect.ImmutableSet;
@@ -155,6 +154,7 @@ import java.util.function.Function;
 import java.util.function.UnaryOperator;
 import java.util.stream.Collectors;
 
+import static com.google.common.base.Preconditions.checkArgument;
 import static com.google.common.collect.ImmutableList.toImmutableList;
 
 import static org.apache.calcite.linq4j.Nullness.castNonNull;
@@ -2270,7 +2270,7 @@ public class RelBuilder {
    */
   public RelBuilder rename(List<? extends @Nullable String> fieldNames) {
     final List<String> oldFieldNames = peek().getRowType().getFieldNames();
-    Preconditions.checkArgument(fieldNames.size() <= oldFieldNames.size(),
+    checkArgument(fieldNames.size() <= oldFieldNames.size(),
         "More names than fields");
     final List<String> newFieldNames = new ArrayList<>(oldFieldNames);
     for (int i = 0; i < fieldNames.size(); i++) {
diff --git a/core/src/main/java/org/apache/calcite/util/DateString.java b/core/src/main/java/org/apache/calcite/util/DateString.java
index 2dc19b5def..5ae741400a 100644
--- a/core/src/main/java/org/apache/calcite/util/DateString.java
+++ b/core/src/main/java/org/apache/calcite/util/DateString.java
@@ -21,13 +21,14 @@ import org.apache.calcite.avatica.util.DateTimeUtils;
 import com.fasterxml.jackson.annotation.JsonCreator;
 import com.fasterxml.jackson.annotation.JsonIgnore;
 import com.fasterxml.jackson.annotation.JsonProperty;
-import com.google.common.base.Preconditions;
 
 import org.checkerframework.checker.nullness.qual.Nullable;
 
 import java.util.Calendar;
 import java.util.regex.Pattern;
 
+import static com.google.common.base.Preconditions.checkArgument;
+
 /**
  * Date literal.
  *
@@ -48,13 +49,13 @@ public class DateString implements Comparable<DateString> {
   @SuppressWarnings("method.invocation.invalid")
   public DateString(String v) {
     this(v, false);
-    Preconditions.checkArgument(PATTERN.matcher(v).matches(),
+    checkArgument(PATTERN.matcher(v).matches(),
         "Invalid date format:", v);
-    Preconditions.checkArgument(getYear() >= 1 && getYear() <= 9999,
+    checkArgument(getYear() >= 1 && getYear() <= 9999,
         "Year out of range:", getYear());
-    Preconditions.checkArgument(getMonth() >= 1 && getMonth() <= 12,
+    checkArgument(getMonth() >= 1 && getMonth() <= 12,
         "Month out of range:", getMonth());
-    Preconditions.checkArgument(getDay() >= 1 && getDay() <= 31,
+    checkArgument(getDay() >= 1 && getDay() <= 31,
         "Day out of range:", getDay());
   }
 
@@ -65,11 +66,11 @@ public class DateString implements Comparable<DateString> {
 
   /** Validates a year-month-date and converts to a string. */
   private static String ymd(int year, int month, int day) {
-    Preconditions.checkArgument(year >= 1 && year <= 9999,
+    checkArgument(year >= 1 && year <= 9999,
         "Year out of range:", year);
-    Preconditions.checkArgument(month >= 1 && month <= 12,
+    checkArgument(month >= 1 && month <= 12,
         "Month out of range:", month);
-    Preconditions.checkArgument(day >= 1 && day <= 31,
+    checkArgument(day >= 1 && day <= 31,
         "Day out of range:", day);
     final StringBuilder b = new StringBuilder();
     DateTimeStringUtils.ymd(b, year, month, day);
diff --git a/core/src/main/java/org/apache/calcite/util/JdbcTypeImpl.java b/core/src/main/java/org/apache/calcite/util/JdbcTypeImpl.java
index 6cff5d61ba..aa8d4853de 100644
--- a/core/src/main/java/org/apache/calcite/util/JdbcTypeImpl.java
+++ b/core/src/main/java/org/apache/calcite/util/JdbcTypeImpl.java
@@ -16,14 +16,14 @@
  */
 package org.apache.calcite.util;
 
-import com.google.common.base.Preconditions;
-
 import org.checkerframework.checker.nullness.qual.Nullable;
 
 import java.math.BigDecimal;
 import java.sql.ResultSet;
 import java.sql.SQLException;
 
+import static com.google.common.base.Preconditions.checkArgument;
+
 import static java.util.Objects.requireNonNull;
 
 /**
@@ -52,7 +52,7 @@ enum JdbcTypeImpl implements JdbcType {
     @Override public Boolean get(int column,
         ResultSet resultSet) throws SQLException {
       boolean v = resultSet.getBoolean(column);
-      Preconditions.checkArgument(v || !resultSet.wasNull());
+      checkArgument(v || !resultSet.wasNull());
       return v;
     }
   },
@@ -69,7 +69,7 @@ enum JdbcTypeImpl implements JdbcType {
     @Override public Double get(int column,
         ResultSet resultSet) throws SQLException {
       double v = resultSet.getDouble(column);
-      Preconditions.checkArgument(v != 0 || !resultSet.wasNull());
+      checkArgument(v != 0 || !resultSet.wasNull());
       return v;
     }
   },
@@ -86,7 +86,7 @@ enum JdbcTypeImpl implements JdbcType {
     @Override public Integer get(int column,
         ResultSet resultSet) throws SQLException {
       int v = resultSet.getInt(column);
-      Preconditions.checkArgument(v != 0 || !resultSet.wasNull());
+      checkArgument(v != 0 || !resultSet.wasNull());
       return v;
     }
   },
diff --git a/core/src/main/java/org/apache/calcite/util/TimeWithTimeZoneString.java b/core/src/main/java/org/apache/calcite/util/TimeWithTimeZoneString.java
index a533e2493d..a57e949cdc 100644
--- a/core/src/main/java/org/apache/calcite/util/TimeWithTimeZoneString.java
+++ b/core/src/main/java/org/apache/calcite/util/TimeWithTimeZoneString.java
@@ -18,8 +18,6 @@ package org.apache.calcite.util;
 
 import org.apache.calcite.avatica.util.DateTimeUtils;
 
-import com.google.common.base.Preconditions;
-
 import org.checkerframework.checker.nullness.qual.Nullable;
 
 import java.text.SimpleDateFormat;
@@ -27,6 +25,8 @@ import java.util.Calendar;
 import java.util.Locale;
 import java.util.TimeZone;
 
+import static com.google.common.base.Preconditions.checkArgument;
+
 import static java.lang.Math.floorMod;
 
 /**
@@ -52,7 +52,7 @@ public class TimeWithTimeZoneString implements Comparable<TimeWithTimeZoneString
   public TimeWithTimeZoneString(String v) {
     this.localTime = new TimeString(v.substring(0, 8));
     String timeZoneString = v.substring(9);
-    Preconditions.checkArgument(DateTimeStringUtils.isValidTimeZone(timeZoneString));
+    checkArgument(DateTimeStringUtils.isValidTimeZone(timeZoneString));
     this.timeZone = TimeZone.getTimeZone(timeZoneString);
     this.v = v;
   }
@@ -70,7 +70,7 @@ public class TimeWithTimeZoneString implements Comparable<TimeWithTimeZoneString
    * {@code new TimeWithTimeZoneString(1970, 1, 1, 2, 3, 4, "UTC").withMillis(56)}
    * yields {@code TIME WITH LOCAL TIME ZONE '1970-01-01 02:03:04.056 UTC'}. */
   public TimeWithTimeZoneString withMillis(int millis) {
-    Preconditions.checkArgument(millis >= 0 && millis < 1000);
+    checkArgument(millis >= 0 && millis < 1000);
     return withFraction(DateTimeStringUtils.pad(3, millis));
   }
 
@@ -81,7 +81,7 @@ public class TimeWithTimeZoneString implements Comparable<TimeWithTimeZoneString
    * {@code new TimeWithTimeZoneString(1970, 1, 1, 2, 3, 4, "UTC").withNanos(56789)}
    * yields {@code TIME WITH LOCAL TIME ZONE '1970-01-01 02:03:04.000056789 UTC'}. */
   public TimeWithTimeZoneString withNanos(int nanos) {
-    Preconditions.checkArgument(nanos >= 0 && nanos < 1000000000);
+    checkArgument(nanos >= 0 && nanos < 1000000000);
     return withFraction(DateTimeStringUtils.pad(9, nanos));
   }
 
@@ -165,7 +165,7 @@ public class TimeWithTimeZoneString implements Comparable<TimeWithTimeZoneString
   }
 
   public TimeWithTimeZoneString round(int precision) {
-    Preconditions.checkArgument(precision >= 0);
+    checkArgument(precision >= 0);
     return new TimeWithTimeZoneString(
         localTime.round(precision), timeZone);
   }
@@ -179,7 +179,7 @@ public class TimeWithTimeZoneString implements Comparable<TimeWithTimeZoneString
   /** Converts this TimeWithTimeZoneString to a string, truncated or padded with
    * zeros to a given precision. */
   public String toString(int precision) {
-    Preconditions.checkArgument(precision >= 0);
+    checkArgument(precision >= 0);
     return localTime.toString(precision) + " " + timeZone.getID();
   }
 
diff --git a/core/src/main/java/org/apache/calcite/util/TimestampString.java b/core/src/main/java/org/apache/calcite/util/TimestampString.java
index fccd59b936..45d7eb9cc1 100644
--- a/core/src/main/java/org/apache/calcite/util/TimestampString.java
+++ b/core/src/main/java/org/apache/calcite/util/TimestampString.java
@@ -111,7 +111,7 @@ public class TimestampString implements Comparable<TimestampString> {
     while (fraction.endsWith("0")) {
       fraction = fraction.substring(0, fraction.length() - 1);
     }
-    if (fraction.length() > 0) {
+    if (!fraction.isEmpty()) {
       v = v + "." + fraction;
     }
     return new TimestampString(v);
diff --git a/core/src/main/java/org/apache/calcite/util/TimestampWithTimeZoneString.java b/core/src/main/java/org/apache/calcite/util/TimestampWithTimeZoneString.java
index 752fa12f25..8e31656a65 100644
--- a/core/src/main/java/org/apache/calcite/util/TimestampWithTimeZoneString.java
+++ b/core/src/main/java/org/apache/calcite/util/TimestampWithTimeZoneString.java
@@ -18,8 +18,6 @@ package org.apache.calcite.util;
 
 import org.apache.calcite.avatica.util.DateTimeUtils;
 
-import com.google.common.base.Preconditions;
-
 import org.checkerframework.checker.nullness.qual.Nullable;
 
 import java.text.SimpleDateFormat;
@@ -27,6 +25,8 @@ import java.util.Calendar;
 import java.util.Locale;
 import java.util.TimeZone;
 
+import static com.google.common.base.Preconditions.checkArgument;
+
 import static java.lang.Math.floorMod;
 
 /**
@@ -53,7 +53,7 @@ public class TimestampWithTimeZoneString
   public TimestampWithTimeZoneString(String v) {
     this.localDateTime = new TimestampString(v.substring(0, v.indexOf(' ', 11)));
     String timeZoneString = v.substring(v.indexOf(' ', 11) + 1);
-    Preconditions.checkArgument(DateTimeStringUtils.isValidTimeZone(timeZoneString));
+    checkArgument(DateTimeStringUtils.isValidTimeZone(timeZoneString));
     this.timeZone = TimeZone.getTimeZone(timeZoneString);
     this.v = v;
   }
@@ -73,7 +73,7 @@ public class TimestampWithTimeZoneString
    * {@code new TimestampWithTimeZoneString(1970, 1, 1, 2, 3, 4, "GMT").withMillis(56)}
    * yields {@code TIMESTAMP WITH LOCAL TIME ZONE '1970-01-01 02:03:04.056 GMT'}. */
   public TimestampWithTimeZoneString withMillis(int millis) {
-    Preconditions.checkArgument(millis >= 0 && millis < 1000);
+    checkArgument(millis >= 0 && millis < 1000);
     return withFraction(DateTimeStringUtils.pad(3, millis));
   }
 
@@ -84,7 +84,7 @@ public class TimestampWithTimeZoneString
    * {@code new TimestampWithTimeZoneString(1970, 1, 1, 2, 3, 4, "GMT").withNanos(56789)}
    * yields {@code TIMESTAMP WITH LOCAL TIME ZONE '1970-01-01 02:03:04.000056789 GMT'}. */
   public TimestampWithTimeZoneString withNanos(int nanos) {
-    Preconditions.checkArgument(nanos >= 0 && nanos < 1000000000);
+    checkArgument(nanos >= 0 && nanos < 1000000000);
     return withFraction(DateTimeStringUtils.pad(9, nanos));
   }
 
@@ -161,7 +161,7 @@ public class TimestampWithTimeZoneString
   }
 
   public TimestampWithTimeZoneString round(int precision) {
-    Preconditions.checkArgument(precision >= 0);
+    checkArgument(precision >= 0);
     return new TimestampWithTimeZoneString(
         localDateTime.round(precision), timeZone);
   }
@@ -177,7 +177,7 @@ public class TimestampWithTimeZoneString
   /** Converts this TimestampWithTimeZoneString to a string, truncated or padded with
    * zeros to a given precision. */
   public String toString(int precision) {
-    Preconditions.checkArgument(precision >= 0);
+    checkArgument(precision >= 0);
     return localDateTime.toString(precision) + " " + timeZone.getID();
   }
 
diff --git a/core/src/test/java/org/apache/calcite/test/SqlValidatorFeatureTest.java b/core/src/test/java/org/apache/calcite/test/SqlValidatorFeatureTest.java
index 56a7d39fcd..24cdf1935d 100644
--- a/core/src/test/java/org/apache/calcite/test/SqlValidatorFeatureTest.java
+++ b/core/src/test/java/org/apache/calcite/test/SqlValidatorFeatureTest.java
@@ -25,10 +25,13 @@ import org.apache.calcite.sql.parser.SqlParserPos;
 import org.apache.calcite.sql.validate.SqlValidatorCatalogReader;
 import org.apache.calcite.sql.validate.SqlValidatorImpl;
 
+import org.checkerframework.checker.nullness.qual.Nullable;
 import org.junit.jupiter.api.Test;
 
 import static org.apache.calcite.util.Static.RESOURCE;
 
+import static java.util.Objects.requireNonNull;
+
 /**
  * SqlValidatorFeatureTest verifies that features can be independently enabled
  * or disabled.
@@ -36,7 +39,7 @@ import static org.apache.calcite.util.Static.RESOURCE;
 class SqlValidatorFeatureTest extends SqlValidatorTestCase {
   private static final String FEATURE_DISABLED = "feature_disabled";
 
-  private Feature disabledFeature;
+  private @Nullable Feature disabledFeature;
 
   @Override public SqlValidatorFixture fixture() {
     return super.fixture()
@@ -117,22 +120,20 @@ class SqlValidatorFeatureTest extends SqlValidatorTestCase {
 
     protected void validateFeature(
         Feature feature,
-        SqlParserPos context) {
+        SqlParserPos pos) {
+      requireNonNull(pos, "pos");
       if (feature.equals(disabledFeature)) {
         CalciteException ex =
             new CalciteException(
                 FEATURE_DISABLED,
                 null);
-        if (context == null) {
-          throw ex;
-        }
         throw new CalciteContextException(
             "location",
             ex,
-            context.getLineNum(),
-            context.getColumnNum(),
-            context.getEndLineNum(),
-            context.getEndColumnNum());
+            pos.getLineNum(),
+            pos.getColumnNum(),
+            pos.getEndLineNum(),
+            pos.getEndColumnNum());
       }
     }
   }
diff --git a/druid/src/main/java/org/apache/calcite/adapter/druid/DruidTable.java b/druid/src/main/java/org/apache/calcite/adapter/druid/DruidTable.java
index 58d844ce11..f04c9be34b 100644
--- a/druid/src/main/java/org/apache/calcite/adapter/druid/DruidTable.java
+++ b/druid/src/main/java/org/apache/calcite/adapter/druid/DruidTable.java
@@ -37,7 +37,6 @@ import org.apache.calcite.sql.SqlSelectKeyword;
 import org.apache.calcite.sql.fun.SqlStdOperatorTable;
 import org.apache.calcite.sql.type.SqlTypeName;
 
-import com.google.common.base.Preconditions;
 import com.google.common.collect.ImmutableList;
 import com.google.common.collect.ImmutableMap;
 import com.google.common.collect.ImmutableSet;
@@ -53,6 +52,8 @@ import java.util.Map;
 import java.util.Objects;
 import java.util.Set;
 
+import static com.google.common.base.Preconditions.checkArgument;
+
 /**
  * Table mapped onto a Druid table.
  */
@@ -235,8 +236,8 @@ public class DruidTable extends AbstractTable implements TranslatableTable {
   @Override public RelDataType getRowType(RelDataTypeFactory typeFactory) {
     final RelDataType rowType = protoRowType.apply(typeFactory);
     final List<String> fieldNames = rowType.getFieldNames();
-    Preconditions.checkArgument(fieldNames.contains(timestampFieldName));
-    Preconditions.checkArgument(fieldNames.containsAll(metricFieldNames));
+    checkArgument(fieldNames.contains(timestampFieldName));
+    checkArgument(fieldNames.containsAll(metricFieldNames));
     return rowType;
   }
 
diff --git a/elasticsearch/src/main/java/org/apache/calcite/adapter/elasticsearch/ElasticsearchSchema.java b/elasticsearch/src/main/java/org/apache/calcite/adapter/elasticsearch/ElasticsearchSchema.java
index 02a6bf20fb..c0f34e4ec8 100644
--- a/elasticsearch/src/main/java/org/apache/calcite/adapter/elasticsearch/ElasticsearchSchema.java
+++ b/elasticsearch/src/main/java/org/apache/calcite/adapter/elasticsearch/ElasticsearchSchema.java
@@ -22,7 +22,6 @@ import org.apache.calcite.schema.impl.AbstractSchema;
 import com.fasterxml.jackson.databind.JsonNode;
 import com.fasterxml.jackson.databind.ObjectMapper;
 import com.google.common.annotations.VisibleForTesting;
-import com.google.common.base.Preconditions;
 import com.google.common.collect.ImmutableMap;
 import com.google.common.collect.Sets;
 
@@ -43,6 +42,8 @@ import java.util.Spliterators;
 import java.util.stream.Collectors;
 import java.util.stream.StreamSupport;
 
+import static com.google.common.base.Preconditions.checkArgument;
+
 /**
  * Each table in the schema is an ELASTICSEARCH index.
  */
@@ -76,7 +77,7 @@ public class ElasticsearchSchema extends AbstractSchema {
     super();
     this.client = Objects.requireNonNull(client, "client");
     this.mapper = Objects.requireNonNull(mapper, "mapper");
-    Preconditions.checkArgument(fetchSize > 0,
+    checkArgument(fetchSize > 0,
         "invalid fetch size. Expected %s > 0", fetchSize);
     this.fetchSize = fetchSize;
 
diff --git a/elasticsearch/src/main/java/org/apache/calcite/adapter/elasticsearch/ElasticsearchSchemaFactory.java b/elasticsearch/src/main/java/org/apache/calcite/adapter/elasticsearch/ElasticsearchSchemaFactory.java
index d1cc87f721..052ddfb0b8 100644
--- a/elasticsearch/src/main/java/org/apache/calcite/adapter/elasticsearch/ElasticsearchSchemaFactory.java
+++ b/elasticsearch/src/main/java/org/apache/calcite/adapter/elasticsearch/ElasticsearchSchemaFactory.java
@@ -30,7 +30,6 @@ import org.apache.http.impl.client.BasicCredentialsProvider;
 import com.fasterxml.jackson.core.JsonParser;
 import com.fasterxml.jackson.core.type.TypeReference;
 import com.fasterxml.jackson.databind.ObjectMapper;
-import com.google.common.base.Preconditions;
 import com.google.common.base.Strings;
 import com.google.common.cache.Cache;
 import com.google.common.cache.CacheBuilder;
@@ -56,6 +55,8 @@ import java.util.stream.Collectors;
 import javax.net.ssl.SSLContext;
 import javax.net.ssl.TrustManager;
 
+import static com.google.common.base.Preconditions.checkArgument;
+
 /**
  * Factory that creates an {@link ElasticsearchSchema}.
  *
@@ -195,7 +196,7 @@ public class ElasticsearchSchemaFactory implements SchemaFactory {
                                     boolean disableSSLVerification) {
 
     Objects.requireNonNull(hosts, "hosts or coordinates");
-    Preconditions.checkArgument(!hosts.isEmpty(), "no ES hosts specified");
+    checkArgument(!hosts.isEmpty(), "no ES hosts specified");
     // Two lists are considered equal when all of their corresponding elements are equal
     // making a list of RestClient params a suitable cache key.
     List cacheKey = ImmutableList.of(hosts, pathPrefix, username, password);
diff --git a/elasticsearch/src/main/java/org/apache/calcite/adapter/elasticsearch/PredicateAnalyzer.java b/elasticsearch/src/main/java/org/apache/calcite/adapter/elasticsearch/PredicateAnalyzer.java
index 95d829f4d5..9b9796857c 100644
--- a/elasticsearch/src/main/java/org/apache/calcite/adapter/elasticsearch/PredicateAnalyzer.java
+++ b/elasticsearch/src/main/java/org/apache/calcite/adapter/elasticsearch/PredicateAnalyzer.java
@@ -32,7 +32,6 @@ import org.apache.calcite.sql.type.SqlTypeName;
 import org.apache.calcite.util.NlsString;
 import org.apache.calcite.util.Sarg;
 
-import com.google.common.base.Preconditions;
 import com.google.common.base.Throwables;
 import com.google.common.collect.Range;
 
@@ -45,6 +44,9 @@ import java.util.Map;
 import java.util.Objects;
 import java.util.Set;
 
+import static com.google.common.base.Preconditions.checkArgument;
+import static com.google.common.base.Preconditions.checkState;
+
 import static org.apache.calcite.adapter.elasticsearch.QueryBuilders.boolQuery;
 import static org.apache.calcite.adapter.elasticsearch.QueryBuilders.existsQuery;
 import static org.apache.calcite.adapter.elasticsearch.QueryBuilders.rangeQuery;
@@ -283,7 +285,7 @@ class PredicateAnalyzer {
 
     private static String convertQueryString(List<Expression> fields, Expression query) {
       int index = 0;
-      Preconditions.checkArgument(query instanceof LiteralExpression,
+      checkArgument(query instanceof LiteralExpression,
           "Query string must be a string literal");
       String queryString = ((LiteralExpression) query).stringValue();
       @SuppressWarnings("ModifiedButNotUsed")
@@ -303,7 +305,7 @@ class PredicateAnalyzer {
     }
 
     private QueryExpression prefix(RexCall call) {
-      Preconditions.checkArgument(call.getKind() == SqlKind.NOT,
+      checkArgument(call.getKind() == SqlKind.NOT,
           "Expected %s got %s", SqlKind.NOT, call.getKind());
 
       if (call.getOperands().size() != 1) {
@@ -316,7 +318,7 @@ class PredicateAnalyzer {
     }
 
     private QueryExpression postfix(RexCall call) {
-      Preconditions.checkArgument(call.getKind() == SqlKind.IS_NULL
+      checkArgument(call.getKind() == SqlKind.IS_NULL
           || call.getKind() == SqlKind.IS_NOT_NULL);
       if (call.getOperands().size() != 1) {
         String message = String.format(Locale.ROOT, "Unsupported operator: [%s]", call);
@@ -349,7 +351,7 @@ class PredicateAnalyzer {
 
       checkForIncompatibleDateTimeOperands(call);
 
-      Preconditions.checkState(call.getOperands().size() == 2);
+      checkState(call.getOperands().size() == 2);
       final Expression a = call.getOperands().get(0).accept(this);
       final Expression b = call.getOperands().get(1).accept(this);
 
diff --git a/elasticsearch/src/main/java/org/apache/calcite/adapter/elasticsearch/Scrolling.java b/elasticsearch/src/main/java/org/apache/calcite/adapter/elasticsearch/Scrolling.java
index a75c061df8..d44d32e507 100644
--- a/elasticsearch/src/main/java/org/apache/calcite/adapter/elasticsearch/Scrolling.java
+++ b/elasticsearch/src/main/java/org/apache/calcite/adapter/elasticsearch/Scrolling.java
@@ -17,7 +17,6 @@
 package org.apache.calcite.adapter.elasticsearch;
 
 import com.fasterxml.jackson.databind.node.ObjectNode;
-import com.google.common.base.Preconditions;
 import com.google.common.collect.AbstractSequentialIterator;
 import com.google.common.collect.Iterators;
 
@@ -26,6 +25,8 @@ import java.util.Iterator;
 import java.util.Objects;
 import java.util.function.Consumer;
 
+import static com.google.common.base.Preconditions.checkArgument;
+
 /**
  * "Iterator" which retrieves results lazily and in batches. Uses
  * <a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/search-request-scroll.html">Elastic Scrolling API</a>
@@ -41,7 +42,7 @@ class Scrolling {
   Scrolling(ElasticsearchTransport transport) {
     this.transport = Objects.requireNonNull(transport, "transport");
     final int fetchSize = transport.fetchSize;
-    Preconditions.checkArgument(fetchSize > 0,
+    checkArgument(fetchSize > 0,
         "invalid fetch size. Expected %s > 0", fetchSize);
     this.fetchSize = fetchSize;
   }
@@ -148,7 +149,7 @@ class Scrolling {
         final ElasticsearchTransport transport, final long limit) {
       super(first);
       this.transport = transport;
-      Preconditions.checkArgument(limit >= 0,
+      checkArgument(limit >= 0,
           "limit: %s >= 0", limit);
       this.limit = limit;
     }
diff --git a/elasticsearch/src/test/java/org/apache/calcite/adapter/elasticsearch/EmbeddedElasticsearchNode.java b/elasticsearch/src/test/java/org/apache/calcite/adapter/elasticsearch/EmbeddedElasticsearchNode.java
index e79e9f33dc..f17d56a75e 100644
--- a/elasticsearch/src/test/java/org/apache/calcite/adapter/elasticsearch/EmbeddedElasticsearchNode.java
+++ b/elasticsearch/src/test/java/org/apache/calcite/adapter/elasticsearch/EmbeddedElasticsearchNode.java
@@ -18,8 +18,6 @@ package org.apache.calcite.adapter.elasticsearch;
 
 import org.apache.calcite.util.TestUtil;
 
-import com.google.common.base.Preconditions;
-
 import org.elasticsearch.action.admin.cluster.node.info.NodeInfo;
 import org.elasticsearch.action.admin.cluster.node.info.NodesInfoResponse;
 import org.elasticsearch.client.Client;
@@ -40,6 +38,8 @@ import java.util.Arrays;
 import java.util.Collection;
 import java.util.Objects;
 
+import static com.google.common.base.Preconditions.checkState;
+
 import static java.util.Collections.emptyMap;
 
 /**
@@ -107,7 +107,7 @@ class EmbeddedElasticsearchNode implements AutoCloseable {
 
   /** Starts the current node. */
   public void start() {
-    Preconditions.checkState(!isStarted, "already started");
+    checkState(!isStarted, "already started");
     try {
       node.start();
       this.isStarted = true;
@@ -122,7 +122,7 @@ class EmbeddedElasticsearchNode implements AutoCloseable {
    * @return hostname/port for HTTP connection
    */
   public TransportAddress httpAddress() {
-    Preconditions.checkState(isStarted, "node is not started");
+    checkState(isStarted, "node is not started");
 
     NodesInfoResponse response =  client().admin().cluster().prepareNodesInfo()
         .execute().actionGet();
@@ -143,7 +143,7 @@ class EmbeddedElasticsearchNode implements AutoCloseable {
    * @return current elastic search client
    */
   public Client client() {
-    Preconditions.checkState(isStarted, "node is not started");
+    checkState(isStarted, "node is not started");
     return node.client();
   }
 
diff --git a/geode/src/main/java/org/apache/calcite/adapter/geode/rel/GeodeFilter.java b/geode/src/main/java/org/apache/calcite/adapter/geode/rel/GeodeFilter.java
index 0a401fdfc0..cf549b5870 100644
--- a/geode/src/main/java/org/apache/calcite/adapter/geode/rel/GeodeFilter.java
+++ b/geode/src/main/java/org/apache/calcite/adapter/geode/rel/GeodeFilter.java
@@ -37,8 +37,6 @@ import org.apache.calcite.util.TimeString;
 import org.apache.calcite.util.TimestampString;
 import org.apache.calcite.util.Util;
 
-import com.google.common.base.Preconditions;
-
 import org.checkerframework.checker.nullness.qual.Nullable;
 
 import java.util.ArrayList;
@@ -49,6 +47,8 @@ import java.util.Locale;
 import java.util.Set;
 import java.util.stream.Collectors;
 
+import static com.google.common.base.Preconditions.checkArgument;
+
 import static org.apache.calcite.sql.type.SqlTypeName.CHAR;
 
 /**
@@ -219,8 +219,7 @@ public class GeodeFilter extends Filter implements GeodeRel {
 
     /** Creates OQL {@code IN SET} predicate string. */
     private String translateInSet(List<RexNode> disjunctions) {
-      Preconditions.checkArgument(
-          !disjunctions.isEmpty(), "empty disjunctions");
+      checkArgument(!disjunctions.isEmpty(), "empty disjunctions");
 
       RexNode firstNode = disjunctions.get(0);
       RexCall firstCall = (RexCall) firstNode;
diff --git a/geode/src/main/java/org/apache/calcite/adapter/geode/rel/GeodeRules.java b/geode/src/main/java/org/apache/calcite/adapter/geode/rel/GeodeRules.java
index b407d36808..cff828e736 100644
--- a/geode/src/main/java/org/apache/calcite/adapter/geode/rel/GeodeRules.java
+++ b/geode/src/main/java/org/apache/calcite/adapter/geode/rel/GeodeRules.java
@@ -40,7 +40,6 @@ import org.apache.calcite.sql.fun.SqlStdOperatorTable;
 import org.apache.calcite.sql.type.SqlTypeName;
 import org.apache.calcite.sql.validate.SqlValidatorUtil;
 
-import com.google.common.base.Preconditions;
 import com.google.common.collect.ImmutableList;
 
 import org.immutables.value.Value;
@@ -48,6 +47,8 @@ import org.immutables.value.Value;
 import java.util.ArrayList;
 import java.util.List;
 
+import static com.google.common.base.Preconditions.checkArgument;
+
 /**
  * Rules and relational operators for {@link GeodeRel#CONVENTION}
  * calling convention.
@@ -153,7 +154,7 @@ public class GeodeRules {
 
     @Override public RelNode convert(RelNode rel) {
       final LogicalProject project = (LogicalProject) rel;
-      Preconditions.checkArgument(project.getVariablesSet().isEmpty(),
+      checkArgument(project.getVariablesSet().isEmpty(),
           "GeodeProject does now allow variables");
       final RelTraitSet traitSet =
           project.getTraitSet().replace(getOutConvention());
diff --git a/geode/src/test/java/org/apache/calcite/adapter/geode/rel/GeodeEmbeddedPolicy.java b/geode/src/test/java/org/apache/calcite/adapter/geode/rel/GeodeEmbeddedPolicy.java
index 0191d2e9e6..5e1d893a7d 100644
--- a/geode/src/test/java/org/apache/calcite/adapter/geode/rel/GeodeEmbeddedPolicy.java
+++ b/geode/src/test/java/org/apache/calcite/adapter/geode/rel/GeodeEmbeddedPolicy.java
@@ -21,8 +21,6 @@ import org.apache.geode.cache.CacheFactory;
 import org.apache.geode.distributed.AbstractLauncher;
 import org.apache.geode.distributed.ServerLauncher;
 
-import com.google.common.base.Preconditions;
-
 import org.junit.jupiter.api.extension.AfterAllCallback;
 import org.junit.jupiter.api.extension.BeforeAllCallback;
 import org.junit.jupiter.api.extension.ExtensionContext;
@@ -35,6 +33,8 @@ import java.nio.file.Paths;
 import java.util.Objects;
 import java.util.concurrent.atomic.AtomicInteger;
 
+import static com.google.common.base.Preconditions.checkState;
+
 /**
  * Manages embedded Geode instance using native {@link ServerLauncher}.
  */
@@ -44,7 +44,7 @@ public class GeodeEmbeddedPolicy implements BeforeAllCallback, AfterAllCallback
 
   private GeodeEmbeddedPolicy(final ServerLauncher launcher) {
     Objects.requireNonNull(launcher, "launcher");
-    Preconditions.checkState(!launcher.isRunning(), "Launcher process is already running");
+    checkState(!launcher.isRunning(), "Launcher process is already running");
     this.launcher = launcher;
   }
 
@@ -92,7 +92,7 @@ public class GeodeEmbeddedPolicy implements BeforeAllCallback, AfterAllCallback
 
   private void requireStatus(AbstractLauncher.Status expected) {
     final AbstractLauncher.Status current = launcher.status().getStatus();
-    Preconditions.checkState(current == expected,
+    checkState(current == expected,
         "Expected state %s but got %s", expected, current);
   }
 
diff --git a/innodb/src/main/java/org/apache/calcite/adapter/innodb/IndexCondition.java b/innodb/src/main/java/org/apache/calcite/adapter/innodb/IndexCondition.java
index d650318a86..7797dcda58 100644
--- a/innodb/src/main/java/org/apache/calcite/adapter/innodb/IndexCondition.java
+++ b/innodb/src/main/java/org/apache/calcite/adapter/innodb/IndexCondition.java
@@ -166,7 +166,7 @@ public class IndexCondition {
    */
   private static RelCollation deduceImplicitCollation(List<String> fieldNames,
       List<String> indexColumnNames) {
-    checkState(fieldNames != null, "field names cannot be null");
+    requireNonNull(fieldNames, "field names must not be null");
     List<RelFieldCollation> keyCollations = new ArrayList<>(indexColumnNames.size());
     for (String keyColumnName : indexColumnNames) {
       int fieldIndex = fieldNames.indexOf(keyColumnName);
diff --git a/linq4j/src/main/java/org/apache/calcite/linq4j/ModularInteger.java b/linq4j/src/main/java/org/apache/calcite/linq4j/ModularInteger.java
index 12cc470c46..638b1f5f91 100644
--- a/linq4j/src/main/java/org/apache/calcite/linq4j/ModularInteger.java
+++ b/linq4j/src/main/java/org/apache/calcite/linq4j/ModularInteger.java
@@ -16,10 +16,10 @@
  */
 package org.apache.calcite.linq4j;
 
-import com.google.common.base.Preconditions;
-
 import org.checkerframework.checker.nullness.qual.Nullable;
 
+import static com.google.common.base.Preconditions.checkArgument;
+
 /**
  * Represents an integer in modular arithmetic.
  * Its {@code value} is between 0 and {@code m - 1} for some modulus {@code m}.
@@ -32,7 +32,7 @@ class ModularInteger {
 
   /** Creates a ModularInteger. */
   ModularInteger(int value, int modulus) {
-    Preconditions.checkArgument(value >= 0 && value < modulus);
+    checkArgument(value >= 0 && value < modulus);
     this.value = value;
     this.modulus = modulus;
   }
diff --git a/pig/src/main/java/org/apache/calcite/adapter/pig/PigFilter.java b/pig/src/main/java/org/apache/calcite/adapter/pig/PigFilter.java
index 7726bcf589..9c720aeb84 100644
--- a/pig/src/main/java/org/apache/calcite/adapter/pig/PigFilter.java
+++ b/pig/src/main/java/org/apache/calcite/adapter/pig/PigFilter.java
@@ -27,11 +27,11 @@ import org.apache.calcite.rex.RexInputRef;
 import org.apache.calcite.rex.RexLiteral;
 import org.apache.calcite.rex.RexNode;
 
-import com.google.common.base.Preconditions;
-
 import java.util.ArrayList;
 import java.util.List;
 
+import static com.google.common.base.Preconditions.checkState;
+
 import static org.apache.calcite.sql.SqlKind.INPUT_REF;
 import static org.apache.calcite.sql.SqlKind.LITERAL;
 
@@ -70,7 +70,7 @@ public class PigFilter extends Filter implements PigRel {
    * </blockquote>
    */
   private String getPigFilterStatement(Implementor implementor) {
-    Preconditions.checkState(containsOnlyConjunctions(condition));
+    checkState(containsOnlyConjunctions(condition));
     String relationAlias = implementor.getPigRelationAlias(this);
     List<String> filterConditionsConjunction = new ArrayList<>();
     for (RexNode node : RelOptUtil.conjunctions(condition)) {
diff --git a/pig/src/main/java/org/apache/calcite/adapter/pig/PigRelFactories.java b/pig/src/main/java/org/apache/calcite/adapter/pig/PigRelFactories.java
index 991925d17c..b855efda4f 100644
--- a/pig/src/main/java/org/apache/calcite/adapter/pig/PigRelFactories.java
+++ b/pig/src/main/java/org/apache/calcite/adapter/pig/PigRelFactories.java
@@ -31,12 +31,13 @@ import org.apache.calcite.rex.RexNode;
 import org.apache.calcite.util.ImmutableBitSet;
 import org.apache.calcite.util.Util;
 
-import com.google.common.base.Preconditions;
 import com.google.common.collect.ImmutableList;
 
 import java.util.List;
 import java.util.Set;
 
+import static com.google.common.base.Preconditions.checkArgument;
+
 /** Implementations of factories in {@link RelFactories}
  * for the Pig adapter. */
 public class PigRelFactories {
@@ -78,7 +79,7 @@ public class PigRelFactories {
 
     @Override public RelNode createFilter(RelNode input, RexNode condition,
         Set<CorrelationId> variablesSet) {
-      Preconditions.checkArgument(variablesSet.isEmpty(),
+      checkArgument(variablesSet.isEmpty(),
           "PigFilter does not allow variables");
       final RelTraitSet traitSet =
           input.getTraitSet().replace(PigRel.CONVENTION);
diff --git a/redis/src/main/java/org/apache/calcite/adapter/redis/RedisSchemaFactory.java b/redis/src/main/java/org/apache/calcite/adapter/redis/RedisSchemaFactory.java
index bfc36ec2bb..6829714bb0 100644
--- a/redis/src/main/java/org/apache/calcite/adapter/redis/RedisSchemaFactory.java
+++ b/redis/src/main/java/org/apache/calcite/adapter/redis/RedisSchemaFactory.java
@@ -20,11 +20,11 @@ import org.apache.calcite.schema.Schema;
 import org.apache.calcite.schema.SchemaFactory;
 import org.apache.calcite.schema.SchemaPlus;
 
-import com.google.common.base.Preconditions;
-
 import java.util.List;
 import java.util.Map;
 
+import static com.google.common.base.Preconditions.checkArgument;
+
 /**
  * Factory that creates a {@link RedisSchema}.
  *
@@ -39,13 +39,13 @@ public class RedisSchemaFactory implements SchemaFactory {
 
   @Override public Schema create(SchemaPlus schema, String name,
       Map<String, Object> operand) {
-    Preconditions.checkArgument(operand.get("tables") != null,
+    checkArgument(operand.get("tables") != null,
         "tables must be specified");
-    Preconditions.checkArgument(operand.get("host") != null,
+    checkArgument(operand.get("host") != null,
         "host must be specified");
-    Preconditions.checkArgument(operand.get("port") != null,
+    checkArgument(operand.get("port") != null,
         "port must be specified");
-    Preconditions.checkArgument(operand.get("database") != null,
+    checkArgument(operand.get("database") != null,
         "database must be specified");
 
     @SuppressWarnings("unchecked") List<Map<String, Object>> tables =
diff --git a/server/src/main/java/org/apache/calcite/server/ServerDdlExecutor.java b/server/src/main/java/org/apache/calcite/server/ServerDdlExecutor.java
index a0808c9f63..a2a326ca6b 100644
--- a/server/src/main/java/org/apache/calcite/server/ServerDdlExecutor.java
+++ b/server/src/main/java/org/apache/calcite/server/ServerDdlExecutor.java
@@ -88,7 +88,6 @@ import org.apache.calcite.util.NlsString;
 import org.apache.calcite.util.Pair;
 import org.apache.calcite.util.Util;
 
-import com.google.common.base.Preconditions;
 import com.google.common.collect.ImmutableList;
 
 import org.checkerframework.checker.nullness.qual.Nullable;
@@ -105,6 +104,8 @@ import java.util.Map;
 import java.util.Objects;
 import java.util.Set;
 
+import static com.google.common.base.Preconditions.checkArgument;
+
 import static org.apache.calcite.util.Static.RESOURCE;
 
 /** Executes DDL commands.
@@ -260,7 +261,7 @@ public class ServerDdlExecutor extends DdlExecutorImpl {
     final Schema subSchema;
     final String libraryName;
     if (create.type != null) {
-      Preconditions.checkArgument(create.library == null);
+      checkArgument(create.library == null);
       final String typeName = (String) value(create.type);
       final JsonSchema.Type type =
           Util.enumVal(JsonSchema.Type.class,
@@ -282,7 +283,7 @@ public class ServerDdlExecutor extends DdlExecutorImpl {
                 Arrays.toString(JsonSchema.Type.values())));
       }
     } else {
-      Preconditions.checkArgument(create.library != null);
+      checkArgument(create.library != null);
       libraryName = (String) value(create.library);
     }
     final SchemaFactory schemaFactory =
@@ -716,7 +717,7 @@ public class ServerDdlExecutor extends DdlExecutorImpl {
       this.expr = expr;
       this.type = type;
       this.strategy = Objects.requireNonNull(strategy, "strategy");
-      Preconditions.checkArgument(
+      checkArgument(
           strategy == ColumnStrategy.NULLABLE
               || strategy == ColumnStrategy.NOT_NULLABLE
               || expr != null);
diff --git a/testkit/src/main/java/org/apache/calcite/test/Matchers.java b/testkit/src/main/java/org/apache/calcite/test/Matchers.java
index 4a7b448155..0013437031 100644
--- a/testkit/src/main/java/org/apache/calcite/test/Matchers.java
+++ b/testkit/src/main/java/org/apache/calcite/test/Matchers.java
@@ -24,7 +24,6 @@ import org.apache.calcite.rex.RexNode;
 import org.apache.calcite.util.TestUtil;
 import org.apache.calcite.util.Util;
 
-import com.google.common.base.Preconditions;
 import com.google.common.collect.Lists;
 import com.google.common.collect.RangeSet;
 
@@ -49,6 +48,7 @@ import java.util.function.Function;
 import java.util.regex.Pattern;
 import java.util.stream.StreamSupport;
 
+import static com.google.common.base.Preconditions.checkArgument;
 import static com.google.common.collect.ImmutableList.toImmutableList;
 
 import static org.hamcrest.CoreMatchers.equalTo;
@@ -413,7 +413,7 @@ public class Matchers {
     private final double epsilon;
 
     public IsWithin(T expectedValue, double epsilon) {
-      Preconditions.checkArgument(epsilon >= 0D);
+      checkArgument(epsilon >= 0D);
       this.expectedValue = expectedValue;
       this.epsilon = epsilon;
     }
diff --git a/testkit/src/main/java/org/apache/calcite/test/RelMetadataFixture.java b/testkit/src/main/java/org/apache/calcite/test/RelMetadataFixture.java
index 63f478429d..31a636b6c8 100644
--- a/testkit/src/main/java/org/apache/calcite/test/RelMetadataFixture.java
+++ b/testkit/src/main/java/org/apache/calcite/test/RelMetadataFixture.java
@@ -40,7 +40,6 @@ import org.apache.calcite.sql.test.SqlTester;
 import org.apache.calcite.tools.RelBuilder;
 import org.apache.calcite.util.ImmutableBitSet;
 
-import com.google.common.base.Preconditions;
 import com.google.common.collect.ImmutableMap;
 import com.google.common.collect.ImmutableSortedSet;
 import com.google.common.collect.Iterables;
@@ -58,6 +57,8 @@ import java.util.function.Function;
 import java.util.function.Supplier;
 import java.util.function.UnaryOperator;
 
+import static com.google.common.base.Preconditions.checkArgument;
+
 import static org.hamcrest.CoreMatchers.equalTo;
 import static org.hamcrest.CoreMatchers.is;
 import static org.hamcrest.CoreMatchers.not;
@@ -196,7 +197,7 @@ public class RelMetadataFixture {
     metadataConfig.applyMetadata(rel.getCluster());
     if (convertAsCalc) {
       Project project = (Project) rel;
-      Preconditions.checkArgument(project.getVariablesSet().isEmpty(),
+      checkArgument(project.getVariablesSet().isEmpty(),
           "Calc does not allow variables");
       RexProgram program =
           RexProgram.create(project.getInput().getRowType(),
diff --git a/testkit/src/main/java/org/apache/calcite/test/SqlValidatorFixture.java b/testkit/src/main/java/org/apache/calcite/test/SqlValidatorFixture.java
index 059db989be..71558b5cc3 100644
--- a/testkit/src/main/java/org/apache/calcite/test/SqlValidatorFixture.java
+++ b/testkit/src/main/java/org/apache/calcite/test/SqlValidatorFixture.java
@@ -46,14 +46,14 @@ import org.apache.calcite.test.catalog.MockCatalogReaderExtended;
 import org.apache.calcite.util.TestUtil;
 import org.apache.calcite.util.Util;
 
-import com.google.common.base.Preconditions;
-
 import org.hamcrest.Matcher;
 
 import java.nio.charset.Charset;
 import java.util.List;
 import java.util.function.UnaryOperator;
 
+import static com.google.common.base.Preconditions.checkArgument;
+
 import static org.apache.calcite.sql.SqlUtil.stripAs;
 
 import static org.hamcrest.CoreMatchers.is;
@@ -182,7 +182,7 @@ public class SqlValidatorFixture {
   }
 
   public SqlValidatorFixture withWhole(boolean whole) {
-    Preconditions.checkArgument(sap.cursor < 0);
+    checkArgument(sap.cursor < 0);
     final StringAndPos sap = StringAndPos.of("^" + this.sap.sql + "^");
     return new SqlValidatorFixture(tester, factory, sap, expression, whole);
   }
diff --git a/testkit/src/main/java/org/apache/calcite/test/catalog/MockCatalogReader.java b/testkit/src/main/java/org/apache/calcite/test/catalog/MockCatalogReader.java
index 8f7e8f5ca9..8b489f2bb0 100644
--- a/testkit/src/main/java/org/apache/calcite/test/catalog/MockCatalogReader.java
+++ b/testkit/src/main/java/org/apache/calcite/test/catalog/MockCatalogReader.java
@@ -105,6 +105,8 @@ import java.util.List;
 import java.util.Map;
 import java.util.Set;
 
+import static java.util.Objects.requireNonNull;
+
 /**
  * Mock implementation of {@link SqlValidatorCatalogReader} which returns tables
  * "EMP", "DEPT", "BONUS", "SALGRADE" (same as Oracle's SCOTT schema).
@@ -316,7 +318,7 @@ public abstract class MockCatalogReader extends CalciteCatalogReader {
     protected final Double maxRowCount;
     protected final Set<String> monotonicColumnSet = new HashSet<>();
     protected StructKind kind = StructKind.FULLY_QUALIFIED;
-    protected final ColumnResolver resolver;
+    protected final @Nullable ColumnResolver resolver;
     private final boolean temporal;
     protected final InitializerExpressionFactory initializerFactory;
     protected final Set<String> rolledUpColumns = new HashSet<>();
@@ -328,7 +330,7 @@ public abstract class MockCatalogReader extends CalciteCatalogReader {
 
     public MockTable(MockCatalogReader catalogReader, String catalogName,
         String schemaName, String name, boolean stream, boolean temporal,
-        double rowCount, ColumnResolver resolver,
+        double rowCount, @Nullable ColumnResolver resolver,
         InitializerExpressionFactory initializerFactory) {
       this(catalogReader, ImmutableList.of(catalogName, schemaName, name),
           stream, temporal, rowCount, resolver, initializerFactory,
@@ -350,7 +352,7 @@ public abstract class MockCatalogReader extends CalciteCatalogReader {
 
     private MockTable(MockCatalogReader catalogReader, List<String> names,
         boolean stream, boolean temporal, double rowCount,
-        ColumnResolver resolver,
+        @Nullable ColumnResolver resolver,
         InitializerExpressionFactory initializerFactory, List<Object> wraps,
         Double maxRowCount) {
       this.catalogReader = catalogReader;
@@ -666,11 +668,13 @@ public abstract class MockCatalogReader extends CalciteCatalogReader {
 
       ModifiableTableWithCustomColumnResolving(String tableName) {
         super(tableName);
+        requireNonNull(resolver, "resolver");
       }
 
       @Override public List<Pair<RelDataTypeField, List<String>>> resolveColumn(
           RelDataType rowType, RelDataTypeFactory typeFactory,
           List<String> names) {
+        requireNonNull(resolver, "resolver");
         return resolver.resolveColumn(rowType, typeFactory, names);
       }
     }
@@ -700,7 +704,8 @@ public abstract class MockCatalogReader extends CalciteCatalogReader {
         MockCatalogReader catalogReader, boolean stream, double rowCount,
         List<Map.Entry<String, RelDataType>> columnList, List<Integer> keyList,
         RelDataType rowType, List<RelCollation> collationList, List<String> names,
-        Set<String> monotonicColumnSet, StructKind kind, ColumnResolver resolver,
+        Set<String> monotonicColumnSet, StructKind kind,
+        @Nullable ColumnResolver resolver,
         InitializerExpressionFactory initializerFactory) {
       super(catalogReader, stream, false, rowCount, columnList, keyList,
           rowType, collationList, names,
@@ -911,9 +916,13 @@ public abstract class MockCatalogReader extends CalciteCatalogReader {
      */
     private class ModifiableViewWithCustomColumnResolving
         extends ModifiableView implements CustomColumnResolvingTable, Wrapper {
+      ModifiableViewWithCustomColumnResolving() {
+        requireNonNull(resolver, "resolver");
+      }
 
       @Override public List<Pair<RelDataTypeField, List<String>>> resolveColumn(
           RelDataType rowType, RelDataTypeFactory typeFactory, List<String> names) {
+        requireNonNull(resolver, "resolver");
         return resolver.resolveColumn(rowType, typeFactory, names);
       }
 
@@ -968,7 +977,8 @@ public abstract class MockCatalogReader extends CalciteCatalogReader {
   }
 
   /**
-   * Mock implementation of {@link AbstractQueryableTable} with dynamic record type.
+   * Mock implementation of {@link AbstractQueryableTable} with dynamic record
+   * type.
    */
   public static class MockDynamicTable
       extends AbstractQueryableTable implements TranslatableTable {
diff --git a/ubenchmark/src/jmh/java/org/apache/calcite/benchmarks/PreconditionTest.java b/ubenchmark/src/jmh/java/org/apache/calcite/benchmarks/PreconditionTest.java
index 8f8ca19701..e4975dd2c8 100644
--- a/ubenchmark/src/jmh/java/org/apache/calcite/benchmarks/PreconditionTest.java
+++ b/ubenchmark/src/jmh/java/org/apache/calcite/benchmarks/PreconditionTest.java
@@ -16,8 +16,6 @@
  */
 package org.apache.calcite.benchmarks;
 
-import com.google.common.base.Preconditions;
-
 import org.openjdk.jmh.annotations.Benchmark;
 import org.openjdk.jmh.annotations.BenchmarkMode;
 import org.openjdk.jmh.annotations.Mode;
@@ -29,6 +27,8 @@ import org.openjdk.jmh.runner.RunnerException;
 import org.openjdk.jmh.runner.options.Options;
 import org.openjdk.jmh.runner.options.OptionsBuilder;
 
+import static com.google.common.base.Preconditions.checkState;
+
 /**
  * Checks if silent precondition has noticeable overhead.
  */
@@ -40,7 +40,7 @@ public class PreconditionTest {
 
   @Benchmark
   public void testPrecondition() {
-    Preconditions.checkState(fire, "Hello %s", param);
+    checkState(fire, "Hello %s", param);
   }
 
   public static void main(String[] args) throws RunnerException {


(calcite) 02/02: [CALCITE-6219] 'Must-filter' columns

Posted by jh...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

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

commit 2558c13cdb8b6a8e1608112a902b1bf9d97b5386
Author: Oliver Lee <ol...@google.com>
AuthorDate: Mon Jan 29 19:27:35 2024 +0000

    [CALCITE-6219] 'Must-filter' columns
    
    A table can declare that some of its columns must be filtered
    by implementing `interface SemanticTable`. If such columns
    are not filtered in a WHERE or HAVING clause, the validator
    throws.
    
    There are several purposes of these columns, one of which is
    to prevent expensive full-table scans (for example, reading
    all Orders without restricting on orderDate).
    
    Implementation is via the method
    SqlValidatorNamespace.getMustFilterFields(). For a table
    namespace, that method returns the declared must-filter
    fields. For a query namespce, that method returns any
    must-filter fields that have not been filtered in that query;
    such fields become the responsibility of the enclosing query.
    
    If a field is must-filter and is not in the SELECT clause of a
    sub-query, that is also an error, because of course it is now
    impossible for the enclosing query to filter it.
    
    Close apache/calcite#3688
    
    Co-authored-by: Julian Hyde <jh...@apache.org>
---
 .../apache/calcite/runtime/CalciteResource.java    |   3 +
 .../calcite/sql/validate/AbstractNamespace.java    |  10 +
 .../calcite/sql/validate/IdentifierNamespace.java  |   1 +
 .../apache/calcite/sql/validate/SemanticTable.java |  47 +++++
 .../apache/calcite/sql/validate/SqlQualified.java  |  25 +++
 .../calcite/sql/validate/SqlValidatorImpl.java     |  96 ++++++++-
 .../sql/validate/SqlValidatorNamespace.java        |   7 +
 .../calcite/sql/validate/SqlValidatorUtil.java     |   3 +-
 .../calcite/sql/validate/TableNamespace.java       |  11 +
 .../calcite/sql/validate/WithItemNamespace.java    |   1 +
 .../apache/calcite/sql/validate/WithNamespace.java |   6 +
 .../calcite/runtime/CalciteResource.properties     |   1 +
 .../org/apache/calcite/test/SqlValidatorTest.java  | 223 +++++++++++++++++++++
 .../calcite/test/catalog/MockCatalogReader.java    |  45 +++++
 .../test/catalog/MustFilterMockCatalogReader.java  |  84 ++++++++
 15 files changed, 560 insertions(+), 3 deletions(-)

diff --git a/core/src/main/java/org/apache/calcite/runtime/CalciteResource.java b/core/src/main/java/org/apache/calcite/runtime/CalciteResource.java
index 5a3c6e4b55..86e67797f8 100644
--- a/core/src/main/java/org/apache/calcite/runtime/CalciteResource.java
+++ b/core/src/main/java/org/apache/calcite/runtime/CalciteResource.java
@@ -1085,6 +1085,9 @@ public interface CalciteResource {
   @BaseMessage("A table function at most has one input table with row semantics. Table function ''{0}'' has multiple input tables with row semantics")
   ExInst<SqlValidatorException> multipleRowSemanticsTables(String funcName);
 
+  @BaseMessage("SQL statement did not contain filters on the following fields: {0}")
+  ExInst<SqlValidatorException> mustFilterFieldsMissing(String mustFilterFields);
+
   @BaseMessage("BIT_GET/GETBIT error: negative position {0,number} not allowed")
   ExInst<CalciteException> illegalNegativeBitGetPosition(int position);
 
diff --git a/core/src/main/java/org/apache/calcite/sql/validate/AbstractNamespace.java b/core/src/main/java/org/apache/calcite/sql/validate/AbstractNamespace.java
index 3f16078314..4ce24bd5dd 100644
--- a/core/src/main/java/org/apache/calcite/sql/validate/AbstractNamespace.java
+++ b/core/src/main/java/org/apache/calcite/sql/validate/AbstractNamespace.java
@@ -20,6 +20,7 @@ import org.apache.calcite.rel.type.RelDataType;
 import org.apache.calcite.rel.type.RelDataTypeFactory;
 import org.apache.calcite.rel.type.RelDataTypeField;
 import org.apache.calcite.sql.SqlNode;
+import org.apache.calcite.util.ImmutableBitSet;
 import org.apache.calcite.util.Pair;
 import org.apache.calcite.util.Util;
 
@@ -57,6 +58,10 @@ abstract class AbstractNamespace implements SqlValidatorNamespace {
   /** As {@link #rowType}, but not necessarily a struct. */
   protected @Nullable RelDataType type;
 
+  /** Ordinals of fields that must be filtered. Initially the empty set, but
+   * should typically be re-assigned on validate. */
+  protected ImmutableBitSet mustFilterFields = ImmutableBitSet.of();
+
   protected final @Nullable SqlNode enclosingNode;
 
   //~ Constructors -----------------------------------------------------------
@@ -159,6 +164,11 @@ abstract class AbstractNamespace implements SqlValidatorNamespace {
     return ImmutableList.of();
   }
 
+  @Override public ImmutableBitSet getMustFilterFields() {
+    return requireNonNull(mustFilterFields,
+        "mustFilterFields (maybe validation is not complete?)");
+  }
+
   @Override public SqlMonotonicity getMonotonicity(String columnName) {
     return SqlMonotonicity.NOT_MONOTONIC;
   }
diff --git a/core/src/main/java/org/apache/calcite/sql/validate/IdentifierNamespace.java b/core/src/main/java/org/apache/calcite/sql/validate/IdentifierNamespace.java
index c3fab93146..770f8b9d2a 100644
--- a/core/src/main/java/org/apache/calcite/sql/validate/IdentifierNamespace.java
+++ b/core/src/main/java/org/apache/calcite/sql/validate/IdentifierNamespace.java
@@ -210,6 +210,7 @@ public class IdentifierNamespace extends AbstractNamespace {
       }
     }
 
+    this.mustFilterFields = resolvedNamespace.getMustFilterFields();
     RelDataType rowType = resolvedNamespace.getRowType();
 
     if (extendList != null) {
diff --git a/core/src/main/java/org/apache/calcite/sql/validate/SemanticTable.java b/core/src/main/java/org/apache/calcite/sql/validate/SemanticTable.java
new file mode 100644
index 0000000000..b115dbb4cc
--- /dev/null
+++ b/core/src/main/java/org/apache/calcite/sql/validate/SemanticTable.java
@@ -0,0 +1,47 @@
+/*
+ * 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.sql.validate;
+
+import org.checkerframework.checker.nullness.qual.Nullable;
+
+/**
+ * Extension to {@link SqlValidatorTable} with extra, optional metadata.
+ *
+ * <p>Used to flag individual columns as 'must-filter'.
+ */
+public interface SemanticTable {
+  /** Returns the filter expression for {@code column}
+   * if it is a {@link #mustFilter(int) must-filter} column,
+   * or null if it is not a must-filter column.
+   *
+   * @param column Column ordinal (0-based)
+   *
+   * @throws IndexOutOfBoundsException if column ordinal is out of range */
+  default @Nullable String getFilter(int column) {
+    return null;
+  }
+
+  /** Returns whether {@code column} must be filtered in any query
+   * that references this table.
+   *
+   * @param column Column ordinal (0-based)
+   *
+   * @throws IndexOutOfBoundsException if column ordinal is out of range */
+  default boolean mustFilter(int column) {
+    return getFilter(column) != null;
+  }
+}
diff --git a/core/src/main/java/org/apache/calcite/sql/validate/SqlQualified.java b/core/src/main/java/org/apache/calcite/sql/validate/SqlQualified.java
index 48bb492de2..2ec1099a23 100644
--- a/core/src/main/java/org/apache/calcite/sql/validate/SqlQualified.java
+++ b/core/src/main/java/org/apache/calcite/sql/validate/SqlQualified.java
@@ -23,6 +23,8 @@ import org.checkerframework.checker.nullness.qual.Nullable;
 
 import java.util.List;
 
+import static java.util.Objects.hash;
+
 /**
  * Fully-qualified identifier.
  *
@@ -46,6 +48,29 @@ public class SqlQualified {
     this.identifier = identifier;
   }
 
+  @Override public int hashCode() {
+    return hash(identifier.names, prefixLength);
+  }
+
+  @Override public boolean equals(@Nullable Object obj) {
+    // Two SqlQualified instances are equivalent if they are of the same
+    // identifier and same prefix length. Thus, in
+    //
+    //  SELECT e.address, e.address.zipcode
+    //  FROM employees AS e
+    //
+    // "e.address" is {identifier=[e, address], prefixLength=1}
+    // and is distinct from "e.address.zipcode".
+    //
+    // We assume that all SqlQualified instances being compared are resolved
+    // from the same SqlValidatorScope, and therefore we do not need to look
+    // at namespace to distinguish them.
+    return this == obj
+        || obj instanceof SqlQualified
+        && prefixLength == ((SqlQualified) obj).prefixLength
+        && identifier.names.equals(((SqlQualified) obj).identifier.names);
+  }
+
   @Override public String toString() {
     return "{id: " + identifier + ", prefix: " + prefixLength + "}";
   }
diff --git a/core/src/main/java/org/apache/calcite/sql/validate/SqlValidatorImpl.java b/core/src/main/java/org/apache/calcite/sql/validate/SqlValidatorImpl.java
index 03389814c3..8612da78a9 100644
--- a/core/src/main/java/org/apache/calcite/sql/validate/SqlValidatorImpl.java
+++ b/core/src/main/java/org/apache/calcite/sql/validate/SqlValidatorImpl.java
@@ -135,6 +135,7 @@ import java.util.AbstractList;
 import java.util.ArrayDeque;
 import java.util.ArrayList;
 import java.util.Arrays;
+import java.util.BitSet;
 import java.util.Calendar;
 import java.util.Collection;
 import java.util.Collections;
@@ -143,15 +144,19 @@ import java.util.GregorianCalendar;
 import java.util.HashMap;
 import java.util.HashSet;
 import java.util.IdentityHashMap;
+import java.util.LinkedHashSet;
 import java.util.List;
 import java.util.Locale;
 import java.util.Map;
 import java.util.Objects;
 import java.util.Set;
+import java.util.TreeSet;
 import java.util.function.BiFunction;
+import java.util.function.Consumer;
 import java.util.function.Supplier;
 import java.util.function.UnaryOperator;
 import java.util.stream.Collectors;
+import java.util.stream.StreamSupport;
 
 import static com.google.common.base.Preconditions.checkArgument;
 import static com.google.common.base.Preconditions.checkState;
@@ -1160,6 +1165,23 @@ public class SqlValidatorImpl implements SqlValidatorWithHints {
     SqlNode node = namespace.getNode();
     if (node != null) {
       setValidatedNodeType(node, namespace.getType());
+
+      if (node == top) {
+        // A top-level namespace must not return any must-filter fields.
+        // A non-top-level namespace (e.g. a subquery) may return must-filter
+        // fields; these are neutralized if the consuming query filters on them.
+        final ImmutableBitSet mustFilterFields =
+            namespace.getMustFilterFields();
+        if (!mustFilterFields.isEmpty()) {
+          // Set of field names, sorted alphabetically for determinism.
+          Set<String> fieldNameSet =
+              StreamSupport.stream(mustFilterFields.spliterator(), false)
+                  .map(namespace.getRowType().getFieldNames()::get)
+                  .collect(Collectors.toCollection(TreeSet::new));
+          throw newValidationError(node,
+              RESOURCE.mustFilterFieldsMissing(fieldNameSet.toString()));
+        }
+      }
     }
   }
 
@@ -2740,7 +2762,7 @@ public class SqlValidatorImpl implements SqlValidatorWithHints {
    * @param alias       Name of this query within its parent. Must be specified
    *                    if usingScope != null
    */
-  private void registerQuery(
+  protected void registerQuery(
       SqlValidatorScope parentScope,
       @Nullable SqlValidatorScope usingScope,
       SqlNode node,
@@ -3870,6 +3892,65 @@ public class SqlValidatorImpl implements SqlValidatorWithHints {
         validateSelectList(selectItems, select, targetRowType);
     ns.setType(rowType);
 
+    // Deduce which columns must be filtered.
+    ns.mustFilterFields = ImmutableBitSet.of();
+    if (from != null) {
+      final Set<SqlQualified> qualifieds = new LinkedHashSet<>();
+      for (ScopeChild child : fromScope.children) {
+        final List<String> fieldNames =
+            child.namespace.getRowType().getFieldNames();
+        child.namespace.getMustFilterFields()
+            .forEachInt(i ->
+                qualifieds.add(
+                    SqlQualified.create(fromScope, 1, child.namespace,
+                        new SqlIdentifier(
+                            ImmutableList.of(child.name, fieldNames.get(i)),
+                            SqlParserPos.ZERO))));
+      }
+      if (!qualifieds.isEmpty()) {
+        if (select.getWhere() != null) {
+          forEachQualified(select.getWhere(), getWhereScope(select),
+              qualifieds::remove);
+        }
+        if (select.getHaving() != null) {
+          forEachQualified(select.getHaving(), getHavingScope(select),
+              qualifieds::remove);
+        }
+
+        // Each of the must-filter fields identified must be returned as a
+        // SELECT item, which is then flagged as must-filter.
+        final BitSet mustFilterFields = new BitSet();
+        final List<SqlNode> expandedSelectItems =
+            requireNonNull(fromScope.getExpandedSelectList(),
+                "expandedSelectList");
+        forEach(expandedSelectItems, (selectItem, i) -> {
+          selectItem = stripAs(selectItem);
+          if (selectItem instanceof SqlIdentifier) {
+            SqlQualified qualified =
+                fromScope.fullyQualify((SqlIdentifier) selectItem);
+            if (qualifieds.remove(qualified)) {
+              // SELECT item #i referenced a must-filter column that was not
+              // filtered in the WHERE or HAVING. It becomes a must-filter
+              // column for our consumer.
+              mustFilterFields.set(i);
+            }
+          }
+        });
+
+        // If there are must-filter fields that are not in the SELECT clause,
+        // this is an error.
+        if (!qualifieds.isEmpty()) {
+          throw newValidationError(select,
+              RESOURCE.mustFilterFieldsMissing(
+                  qualifieds.stream()
+                      .map(q -> q.suffix().get(0))
+                      .collect(Collectors.toCollection(TreeSet::new))
+                      .toString()));
+        }
+        ns.mustFilterFields = ImmutableBitSet.fromBitSet(mustFilterFields);
+      }
+    }
+
     // Validate ORDER BY after we have set ns.rowType because in some
     // dialects you can refer to columns of the select list, e.g.
     // "SELECT empno AS x FROM emp ORDER BY x"
@@ -3885,6 +3966,19 @@ public class SqlValidatorImpl implements SqlValidatorWithHints {
     }
   }
 
+  /** For each identifier in an expression, resolves it to a qualified name
+   * and calls the provided action. */
+  private static void forEachQualified(SqlNode node, SqlValidatorScope scope,
+      Consumer<SqlQualified> consumer) {
+    node.accept(new SqlBasicVisitor<Void>() {
+      @Override public Void visit(SqlIdentifier id) {
+        final SqlQualified qualified = scope.fullyQualify(id);
+        consumer.accept(qualified);
+        return null;
+      }
+    });
+  }
+
   private void checkRollUpInSelectList(SqlSelect select) {
     SqlValidatorScope scope = getSelectScope(select);
     for (SqlNode item : SqlNonNullableAccessors.getSelectList(select)) {
diff --git a/core/src/main/java/org/apache/calcite/sql/validate/SqlValidatorNamespace.java b/core/src/main/java/org/apache/calcite/sql/validate/SqlValidatorNamespace.java
index ddcaceefb4..77a8dc070e 100644
--- a/core/src/main/java/org/apache/calcite/sql/validate/SqlValidatorNamespace.java
+++ b/core/src/main/java/org/apache/calcite/sql/validate/SqlValidatorNamespace.java
@@ -19,6 +19,7 @@ package org.apache.calcite.sql.validate;
 import org.apache.calcite.rel.type.RelDataType;
 import org.apache.calcite.rel.type.RelDataTypeField;
 import org.apache.calcite.sql.SqlNode;
+import org.apache.calcite.util.ImmutableBitSet;
 import org.apache.calcite.util.Pair;
 
 import org.checkerframework.checker.nullness.qual.Nullable;
@@ -212,4 +213,10 @@ public interface SqlValidatorNamespace {
    * @param modality Modality
    */
   boolean supportsModality(SqlModality modality);
+
+  /** Returns the ordinals (in the row type) of the "must-filter" fields,
+   * fields that that must be filtered in a query. */
+  default ImmutableBitSet getMustFilterFields() {
+    return ImmutableBitSet.of();
+  }
 }
diff --git a/core/src/main/java/org/apache/calcite/sql/validate/SqlValidatorUtil.java b/core/src/main/java/org/apache/calcite/sql/validate/SqlValidatorUtil.java
index 3c4565bb2f..fd18c2d7b1 100644
--- a/core/src/main/java/org/apache/calcite/sql/validate/SqlValidatorUtil.java
+++ b/core/src/main/java/org/apache/calcite/sql/validate/SqlValidatorUtil.java
@@ -381,8 +381,7 @@ public class SqlValidatorUtil {
       SqlValidatorCatalogReader catalogReader,
       RelDataTypeFactory typeFactory,
       SqlValidator.Config config) {
-    return new SqlValidatorImpl(opTab, catalogReader, typeFactory,
-        config);
+    return new SqlValidatorImpl(opTab, catalogReader, typeFactory, config);
   }
 
   /**
diff --git a/core/src/main/java/org/apache/calcite/sql/validate/TableNamespace.java b/core/src/main/java/org/apache/calcite/sql/validate/TableNamespace.java
index 06da097639..8e8ab27e3c 100644
--- a/core/src/main/java/org/apache/calcite/sql/validate/TableNamespace.java
+++ b/core/src/main/java/org/apache/calcite/sql/validate/TableNamespace.java
@@ -26,6 +26,7 @@ import org.apache.calcite.schema.impl.ModifiableViewTable;
 import org.apache.calcite.sql.SqlIdentifier;
 import org.apache.calcite.sql.SqlNode;
 import org.apache.calcite.sql.SqlNodeList;
+import org.apache.calcite.util.ImmutableBitSet;
 import org.apache.calcite.util.Util;
 
 import com.google.common.collect.ImmutableList;
@@ -36,6 +37,7 @@ import org.checkerframework.checker.nullness.qual.Nullable;
 import java.util.List;
 import java.util.Map;
 
+import static org.apache.calcite.util.ImmutableBitSet.toImmutableBitSet;
 import static org.apache.calcite.util.Static.RESOURCE;
 
 import static java.util.Objects.requireNonNull;
@@ -58,6 +60,15 @@ class TableNamespace extends AbstractNamespace {
   }
 
   @Override protected RelDataType validateImpl(RelDataType targetRowType) {
+    this.mustFilterFields = ImmutableBitSet.of();
+    table.maybeUnwrap(SemanticTable.class)
+        .ifPresent(semanticTable ->
+            this.mustFilterFields =
+                table.getRowType().getFieldList().stream()
+                    .map(RelDataTypeField::getIndex)
+                    .filter(semanticTable::mustFilter)
+                    .collect(toImmutableBitSet()));
+
     if (extendedFields.isEmpty()) {
       return table.getRowType();
     }
diff --git a/core/src/main/java/org/apache/calcite/sql/validate/WithItemNamespace.java b/core/src/main/java/org/apache/calcite/sql/validate/WithItemNamespace.java
index 92c7e8f67f..5c0a85756f 100644
--- a/core/src/main/java/org/apache/calcite/sql/validate/WithItemNamespace.java
+++ b/core/src/main/java/org/apache/calcite/sql/validate/WithItemNamespace.java
@@ -41,6 +41,7 @@ class WithItemNamespace extends AbstractNamespace {
     final SqlValidatorNamespace childNs =
         validator.getNamespaceOrThrow(getQuery());
     final RelDataType rowType = childNs.getRowTypeSansSystemColumns();
+    mustFilterFields = childNs.getMustFilterFields();
     SqlNodeList columnList = withItem.columnList;
     if (columnList == null) {
       return rowType;
diff --git a/core/src/main/java/org/apache/calcite/sql/validate/WithNamespace.java b/core/src/main/java/org/apache/calcite/sql/validate/WithNamespace.java
index 7ae775b180..bec57b715b 100644
--- a/core/src/main/java/org/apache/calcite/sql/validate/WithNamespace.java
+++ b/core/src/main/java/org/apache/calcite/sql/validate/WithNamespace.java
@@ -24,6 +24,8 @@ import org.apache.calcite.util.Util;
 
 import org.checkerframework.checker.nullness.qual.Nullable;
 
+import static java.util.Objects.requireNonNull;
+
 /**
  * Namespace for <code>WITH</code> clause.
  */
@@ -56,9 +58,13 @@ public class WithNamespace extends AbstractNamespace {
     }
     final SqlValidatorScope scope2 =
         validator.getWithScope(Util.last(with.withList));
+    final SqlValidatorNamespace bodyNamespace =
+        requireNonNull(validator.getNamespace(with.body), "namespace");
+
     validator.validateQuery(with.body, scope2, targetRowType);
     final RelDataType rowType = validator.getValidatedNodeType(with.body);
     validator.setValidatedNodeType(with, rowType);
+    mustFilterFields = bodyNamespace.getMustFilterFields();
     return rowType;
   }
 
diff --git a/core/src/main/resources/org/apache/calcite/runtime/CalciteResource.properties b/core/src/main/resources/org/apache/calcite/runtime/CalciteResource.properties
index d4294403e7..684e6c7a42 100644
--- a/core/src/main/resources/org/apache/calcite/runtime/CalciteResource.properties
+++ b/core/src/main/resources/org/apache/calcite/runtime/CalciteResource.properties
@@ -354,6 +354,7 @@ InvalidPartitionKeys=Only tables with set semantics may be partitioned. Invalid
 InvalidOrderBy=Only tables with set semantics may be ordered. Invalid ORDER BY clause in the {0,number,#}-th operand of table function ''{1}''
 MultipleRowSemanticsTables=A table function at most has one input table with row semantics. Table function ''{0}'' has multiple input tables with row semantics
 NoOperator=No operator for ''{0}'' with kind: ''{1}'', syntax: ''{2}'' during JSON deserialization
+MustFilterFieldsMissing=SQL statement did not contain filters on the following fields: {0}
 IllegalNegativeBitGetPosition=BIT_GET/GETBIT error: negative position {0,number} not allowed
 IllegalBitGetPositionExceedsLimit=BIT_GET/GETBIT error: position {0,number} exceeds the bit upper limit {1,number}
 # End CalciteResource.properties
diff --git a/core/src/test/java/org/apache/calcite/test/SqlValidatorTest.java b/core/src/test/java/org/apache/calcite/test/SqlValidatorTest.java
index f888d4e3ea..1308aa9c1b 100644
--- a/core/src/test/java/org/apache/calcite/test/SqlValidatorTest.java
+++ b/core/src/test/java/org/apache/calcite/test/SqlValidatorTest.java
@@ -51,6 +51,7 @@ import org.apache.calcite.sql.validate.SqlValidatorCatalogReader;
 import org.apache.calcite.sql.validate.SqlValidatorImpl;
 import org.apache.calcite.sql.validate.SqlValidatorUtil;
 import org.apache.calcite.test.catalog.CountingFactory;
+import org.apache.calcite.test.catalog.MustFilterMockCatalogReader;
 import org.apache.calcite.testlib.annotations.LocaleEnUs;
 import org.apache.calcite.tools.ValidationException;
 import org.apache.calcite.util.Bug;
@@ -69,12 +70,14 @@ import org.slf4j.LoggerFactory;
 import java.io.StringReader;
 import java.lang.reflect.InvocationTargetException;
 import java.lang.reflect.Method;
+import java.util.Arrays;
 import java.util.Comparator;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Locale;
 import java.util.Map;
 import java.util.Objects;
+import java.util.TreeSet;
 import java.util.function.BiConsumer;
 import java.util.function.Consumer;
 
@@ -11765,6 +11768,226 @@ public class SqlValidatorTest extends SqlValidatorTestCase {
     assertThat(resultType, hasToString("INTEGER"));
   }
 
+  /**
+   * Tests validation of must-filter columns.
+   *
+   * <p>If a table that implements
+   * {@link org.apache.calcite.sql.validate.SemanticTable} tags fields as
+   * 'must-filter', and the SQL query does not contain a WHERE or HAVING clause
+   * on each of the tagged columns, the validator should throw an error.
+   */
+  @Test void testMustFilterColumns() {
+    final SqlValidatorFixture fixture = fixture()
+        .withParserConfig(c -> c.withQuoting(Quoting.BACK_TICK))
+        .withOperatorTable(operatorTableFor(SqlLibrary.BIG_QUERY))
+        .withCatalogReader(MustFilterMockCatalogReader::create);
+    // Basic query
+    fixture.withSql("select empno\n"
+            + "from emp\n"
+            + "where job = 'doctor'\n"
+            + "and empno = 1")
+        .ok();
+    fixture.withSql("^select *\n"
+            + "from emp\n"
+            + "where concat(emp.empno, ' ') = 'abc'^")
+        .fails(missingFilters("JOB"));
+
+    // SUBQUERIES
+    fixture.withSql("select * from (\n"
+            + "  select * from emp where empno = 1)\n"
+            + "where job = 'doctor'")
+        .ok();
+    // Deceitful alias #1. Filter on 'j' is a filter on the underlying 'job'.
+    fixture.withSql("select * from (\n"
+            + "  select job as j, ename as job\n"
+            + "  from emp\n"
+            + "  where empno = 1)\n"
+            + "where j = 'doctor'")
+        .ok();
+      // Deceitful alias #2. Filter on 'job' is a filter on the underlying
+      // 'ename', so the underlying 'job' is missing a filter.
+    fixture.withSql("^select * from (\n"
+            + "  select job as j, ename as job\n"
+            + "  from emp\n"
+            + "  where empno = 1)\n"
+            + "where job = 'doctor'^")
+        .fails(missingFilters("J"));
+    fixture.withSql("select * from (\n"
+            + "  select * from emp where job = 'doctor')\n"
+            + "where empno = 1")
+        .ok();
+    fixture.withSql("select * from (\n"
+            + "  select empno from emp where job = 'doctor')\n"
+            + "where empno = 1")
+        .ok();
+    fixture.withSql("^select * from (\n"
+            + "  select * from emp where empno = 1)^")
+        .fails(missingFilters("JOB"));
+    fixture.withSql("^select * from (select * from `SALES`.`EMP`) as a1^ ")
+        .fails(missingFilters("EMPNO", "JOB"));
+
+    // JOINs
+    fixture.withSql("^select *\n"
+            + "from emp\n"
+            + "join dept on emp.deptno = dept.deptno^")
+        .fails(missingFilters("EMPNO", "JOB", "NAME"));
+    fixture.withSql("^select *\n"
+            + "from emp\n"
+            + "join dept on emp.deptno = dept.deptno\n"
+            + "where emp.empno = 1^")
+        .fails(missingFilters("JOB", "NAME"));
+    fixture.withSql("select *\n"
+            + "from emp\n"
+            + "join dept on emp.deptno = dept.deptno\n"
+            + "where emp.empno = 1\n"
+            + "and emp.job = 'doctor'\n"
+            + "and dept.name = 'ACCOUNTING'")
+        .ok();
+    fixture.withSql("select *\n"
+            + "from emp\n"
+            + "join dept on emp.deptno = dept.deptno\n"
+            + "where empno = 1\n"
+            + "and job = 'doctor'\n"
+            + "and dept.name = 'ACCOUNTING'")
+        .ok();
+
+    // Self-join
+    fixture.withSql("^select *\n"
+            + "from `SALES`.emp a1\n"
+            + "join `SALES`.emp a2 on a1.empno = a2.empno^")
+        .fails(missingFilters("EMPNO", "EMPNO0", "JOB", "JOB0"));
+    fixture.withSql("^select *\n"
+            + "from emp a1\n"
+            + "join emp a2 on a1.empno = a2.empno\n"
+            + "where a2.empno = 1\n"
+            + "and a1.empno = 1\n"
+            + "and a2.job = 'doctor'^")
+        // There are two JOB columns but only one is filtered
+        .fails(missingFilters("JOB"));
+    fixture.withSql("select *\n"
+            + "from emp a1\n"
+            + "join emp a2 on a1.empno = a2.empno\n"
+            + "where a1.empno = 1\n"
+            + "and a1.job = 'doctor'\n"
+            + "and a2.empno = 2\n"
+            + "and a2.job = 'undertaker'\n")
+        .ok();
+    fixture.withSql("^select *\n"
+            + " from (select * from `SALES`.`EMP`) as a1\n"
+            + "join (select * from `SALES`.`EMP`) as a2\n"
+            + "  on a1.`EMPNO` = a2.`EMPNO`^")
+        .fails(missingFilters("EMPNO", "EMPNO0", "JOB", "JOB0"));
+
+
+    // USING
+    fixture.withSql("^select *\n"
+            + "from emp\n"
+            + "join dept using(deptno)\n"
+            + "where emp.empno = 1^")
+        .fails(missingFilters("JOB", "NAME"));
+    fixture.withSql("select *\n"
+            + "from emp\n"
+            + "join dept using(deptno)\n"
+            + "where emp.empno = 1\n"
+            + "and emp.job = 'doctor'\n"
+            + "and dept.name = 'ACCOUNTING'")
+        .ok();
+
+    // GROUP BY (HAVING)
+    fixture.withSql("select *\n"
+            + "from dept\n"
+            + "group by deptno, name\n"
+            + "having name = 'accounting_dept'")
+        .ok();
+    fixture.withSql("^select *\n"
+            + "from dept\n"
+            + "group by deptno, name^")
+        .fails(missingFilters("NAME"));
+    fixture.withSql("select name\n"
+            + "from dept\n"
+            + "group by name\n"
+            + "having name = 'accounting'")
+        .ok();
+    fixture.withSql("^select name\n"
+            + "from dept\n"
+            + "group by name^ ")
+        .fails(missingFilters("NAME"));
+    fixture.withSql("select sum(sal)\n"
+            + "from emp\n"
+            + "where empno > 10\n"
+            + "and job = 'doctor'\n"
+            + "group by empno\n"
+            + "having sum(sal) > 100")
+        .ok();
+    fixture.withSql("^select sum(sal)\n"
+            + "from emp\n"
+            + "where empno > 10\n"
+            + "group by empno\n"
+            + "having sum(sal) > 100^")
+        .fails(missingFilters("JOB"));
+
+    // CTE
+    fixture.withSql("^WITH cte AS (\n"
+            + "  select * from emp order by empno)^\n"
+            + "SELECT * from cte")
+        .fails(missingFilters("EMPNO", "JOB"));
+    fixture.withSql("^WITH cte AS (\n"
+            + "  select * from emp where empno = 1)^\n"
+            + "SELECT * from cte")
+        .fails(missingFilters("JOB"));
+    fixture.withSql("WITH cte AS (\n"
+            + "  select *\n"
+            + "  from emp\n"
+            + "  where empno = 1\n"
+            + "  and job = 'doctor')\n"
+            + "SELECT * from cte")
+        .ok();
+    fixture.withSql("^WITH cte AS (\n"
+            + "  select * from emp)^\n"
+            + "SELECT *\n"
+            + "from cte\n"
+            + "where empno = 1")
+        .fails(missingFilters("JOB"));
+    fixture.withSql("WITH cte AS (\n"
+            + "  select * from emp)\n"
+            + "SELECT *\n"
+            + "from cte\n"
+            + "where empno = 1\n"
+            + "and job = 'doctor'")
+        .ok();
+    fixture.withSql("WITH cte AS (\n"
+        + "  select * from emp where empno = 1)\n"
+        + "SELECT *\n"
+        + "from cte\n"
+        + "where job = 'doctor'")
+        .ok();
+    fixture.withSql("WITH cte AS (\n"
+            + "  select empno, job from emp)\n"
+            + "SELECT *\n"
+            + "from cte\n"
+            + "where empno = 1\n"
+            + "and job = 'doctor'")
+        .ok();
+
+    // Filters are missing on EMPNO and JOB, but the error message only
+    // complains about JOB because EMPNO is in the SELECT clause, and could
+    // theoretically be filtered by an enclosing query.
+    fixture.withSql("^select empno\n"
+            + "from emp^")
+        .fails(missingFilters("JOB"));
+    fixture.withSql("^select empno,\n"
+            + "  sum(sal) over (order by mgr)\n"
+            + "from emp^")
+        .fails(missingFilters("JOB"));
+  }
+
+  /** Returns a message that the particular columns are not filtered. */
+  private static String missingFilters(String... args) {
+    return "SQL statement did not contain filters on the following fields: \\["
+        + String.join(", ", new TreeSet<>(Arrays.asList(args)))
+        + "\\]";
+  }
+
   @Test void testAccessingNestedFieldsOfNullableRecord() {
     sql("select ROW_COLUMN_ARRAY[0].NOT_NULL_FIELD from NULLABLEROWS.NR_T1")
         .withExtendedCatalog()
diff --git a/testkit/src/main/java/org/apache/calcite/test/catalog/MockCatalogReader.java b/testkit/src/main/java/org/apache/calcite/test/catalog/MockCatalogReader.java
index 8b489f2bb0..a467ab2bc8 100644
--- a/testkit/src/main/java/org/apache/calcite/test/catalog/MockCatalogReader.java
+++ b/testkit/src/main/java/org/apache/calcite/test/catalog/MockCatalogReader.java
@@ -74,6 +74,7 @@ import org.apache.calcite.sql.SqlAccessType;
 import org.apache.calcite.sql.SqlCall;
 import org.apache.calcite.sql.SqlKind;
 import org.apache.calcite.sql.SqlNode;
+import org.apache.calcite.sql.validate.SemanticTable;
 import org.apache.calcite.sql.validate.SqlModality;
 import org.apache.calcite.sql.validate.SqlMonotonicity;
 import org.apache.calcite.sql.validate.SqlNameMatcher;
@@ -90,6 +91,7 @@ import org.apache.calcite.util.Pair;
 import org.apache.calcite.util.Util;
 
 import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableMap;
 import com.google.common.collect.ImmutableSet;
 import com.google.common.collect.Iterables;
 
@@ -1005,6 +1007,49 @@ public abstract class MockCatalogReader extends CalciteCatalogReader {
     }
   }
 
+  /** Mock implementation of {@link MockTable} that supports must-filter fields.
+   *
+   * <p>Must-filter fields are declared via methods in the {@link SemanticTable}
+   * interface. */
+  public static class MustFilterMockTable
+      extends MockTable implements SemanticTable {
+    private final Map<String, String> fieldFilters;
+
+    MustFilterMockTable(MockCatalogReader catalogReader, String catalogName,
+        String schemaName, String name, boolean stream, boolean temporal,
+        double rowCount, @Nullable ColumnResolver resolver,
+        InitializerExpressionFactory initializerExpressionFactory,
+        Map<String, String> fieldFilters) {
+      super(catalogReader, catalogName, schemaName, name, stream, temporal,
+          rowCount, resolver, initializerExpressionFactory);
+      this.fieldFilters = ImmutableMap.copyOf(fieldFilters);
+    }
+
+    /** Creates a MustFilterMockTable. */
+    public static MustFilterMockTable create(MockCatalogReader catalogReader,
+        MockSchema schema, String name, boolean stream, double rowCount,
+        @Nullable ColumnResolver resolver,
+        InitializerExpressionFactory initializerExpressionFactory,
+        boolean temporal, Map<String, String> fieldFilters) {
+      MustFilterMockTable table =
+          new MustFilterMockTable(catalogReader, schema.getCatalogName(),
+              schema.name, name, stream, temporal, rowCount, resolver,
+              initializerExpressionFactory, fieldFilters);
+      schema.addTable(name);
+      return table;
+    }
+
+    @Override public @Nullable String getFilter(int column) {
+      String columnName = columnList.get(column).getKey();
+      return fieldFilters.get(columnName);
+    }
+
+    @Override public boolean mustFilter(int column) {
+      String columnName = columnList.get(column).getKey();
+      return fieldFilters.containsKey(columnName);
+    }
+  }
+
   /** Wrapper around a {@link MockTable}, giving it a {@link Table} interface.
    * You can get the {@code MockTable} by calling {@link #unwrap(Class)}. */
   private static class WrapperTable implements Table, Wrapper {
diff --git a/testkit/src/main/java/org/apache/calcite/test/catalog/MustFilterMockCatalogReader.java b/testkit/src/main/java/org/apache/calcite/test/catalog/MustFilterMockCatalogReader.java
new file mode 100644
index 0000000000..69cc3efaf7
--- /dev/null
+++ b/testkit/src/main/java/org/apache/calcite/test/catalog/MustFilterMockCatalogReader.java
@@ -0,0 +1,84 @@
+/*
+ * 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.test.catalog;
+
+import org.apache.calcite.rel.type.RelDataType;
+import org.apache.calcite.rel.type.RelDataTypeFactory;
+import org.apache.calcite.sql.type.SqlTypeName;
+import org.apache.calcite.sql.validate.SqlValidatorCatalogReader;
+import org.apache.calcite.sql2rel.NullInitializerExpressionFactory;
+
+import com.google.common.collect.ImmutableMap;
+
+/**
+ * Mock catalog reader that tags a few columns in the tables as must-filter.
+ *
+ * <p>Used for testing must-filter validation.
+ * See {@code org.apache.calcite.test.SqlValidatorTest#testMustFilterColumns()}.
+ */
+public class MustFilterMockCatalogReader extends MockCatalogReader {
+
+  MustFilterMockCatalogReader(RelDataTypeFactory typeFactory,
+      boolean caseSensitive) {
+    super(typeFactory, caseSensitive);
+  }
+
+  public static SqlValidatorCatalogReader create(RelDataTypeFactory typeFactory,
+      boolean caseSensitive) {
+    return new MustFilterMockCatalogReader(typeFactory, caseSensitive).init();
+  }
+
+  @Override public MockCatalogReader init() {
+    MockSchema salesSchema = new MockSchema("SALES");
+    registerSchema(salesSchema);
+
+    // Register "EMP" table. Must-filter fields are "EMPNO", "JOB".
+    MustFilterMockTable empTable =
+        MustFilterMockTable.create(this, salesSchema, "EMP",
+            false, 14, null, NullInitializerExpressionFactory.INSTANCE,
+            false, ImmutableMap.of("EMPNO", "10", "JOB", "JOB_1"));
+
+    final RelDataType integerType =
+        typeFactory.createSqlType(SqlTypeName.INTEGER);
+    final RelDataType timestampType =
+        typeFactory.createSqlType(SqlTypeName.TIMESTAMP);
+    final RelDataType varcharType =
+        typeFactory.createSqlType(SqlTypeName.VARCHAR);
+    final RelDataType booleanType =
+        typeFactory.createSqlType(SqlTypeName.BOOLEAN);
+    empTable.addColumn("EMPNO", integerType, true);
+    empTable.addColumn("ENAME", varcharType);
+    empTable.addColumn("JOB", varcharType);
+    empTable.addColumn("MGR", integerType);
+    empTable.addColumn("HIREDATE", timestampType);
+    empTable.addColumn("SAL", integerType);
+    empTable.addColumn("COMM", integerType);
+    empTable.addColumn("DEPTNO", integerType);
+    empTable.addColumn("SLACKER", booleanType);
+    registerTable(empTable);
+
+    // Register "DEPT" table. "NAME" is a must-filter field.
+    MustFilterMockTable deptTable =
+        MustFilterMockTable.create(this, salesSchema, "DEPT",
+            false, 14, null, NullInitializerExpressionFactory.INSTANCE,
+            false, ImmutableMap.of("NAME", "ACCOUNTING_DEPT"));
+    deptTable.addColumn("DEPTNO", integerType, true);
+    deptTable.addColumn("NAME", varcharType);
+    registerTable(deptTable);
+    return this;
+  }
+}