[CALCITE-4279] SEARCH operator cannot be pushed into Druid

Re-enable tests that were disabled in [CALCITE-4270].

Close apache/calcite#2183
diff --git a/core/src/main/java/org/apache/calcite/util/Bug.java b/core/src/main/java/org/apache/calcite/util/Bug.java
index 25ca437..85531a2 100644
--- a/core/src/main/java/org/apache/calcite/util/Bug.java
+++ b/core/src/main/java/org/apache/calcite/util/Bug.java
@@ -201,11 +201,6 @@
    * fixed. */
   public static final boolean CALCITE_4213_FIXED = false;
 
-  /** Whether
-   * <a href="https://issues.apache.org/jira/browse/CALCITE-4279">[CALCITE-4279]
-   * SEARCH operator cannot be pushed into Druid</a> is fixed. */
-  public static final boolean CALCITE_4279_FIXED = false;
-
   /**
    * Use this to flag temporary code.
    */
diff --git a/druid/src/main/java/org/apache/calcite/adapter/druid/DruidJsonFilter.java b/druid/src/main/java/org/apache/calcite/adapter/druid/DruidJsonFilter.java
index bbde69c..9882254 100644
--- a/druid/src/main/java/org/apache/calcite/adapter/druid/DruidJsonFilter.java
+++ b/druid/src/main/java/org/apache/calcite/adapter/druid/DruidJsonFilter.java
@@ -17,9 +17,11 @@
 package org.apache.calcite.adapter.druid;
 
 import org.apache.calcite.rel.type.RelDataType;
+import org.apache.calcite.rex.RexBuilder;
 import org.apache.calcite.rex.RexCall;
 import org.apache.calcite.rex.RexLiteral;
 import org.apache.calcite.rex.RexNode;
+import org.apache.calcite.rex.RexUtil;
 import org.apache.calcite.sql.SqlKind;
 import org.apache.calcite.sql.type.SqlTypeFamily;
 import org.apache.calcite.sql.type.SqlTypeName;
@@ -376,13 +378,15 @@
    * @param rexNode    RexNode to translate to Druid Filter
    * @param rowType    Row type of filter input
    * @param druidQuery Druid query
+   * @param rexBuilder Rex builder
    *
    * @return Druid Json filters, or null when cannot translate to valid Druid
    * filters
    */
   @Nullable
-  static DruidJsonFilter toDruidFilters(final RexNode rexNode, RelDataType rowType,
-      DruidQuery druidQuery) {
+  static DruidJsonFilter toDruidFilters(RexNode rexNode, RelDataType rowType,
+      DruidQuery druidQuery, RexBuilder rexBuilder) {
+    rexNode = RexUtil.expandSearch(rexBuilder, null, rexNode);
     if (rexNode.isAlwaysTrue()) {
       return JsonExpressionFilter.alwaysTrue();
     }
@@ -392,12 +396,15 @@
     switch (rexNode.getKind()) {
     case IS_TRUE:
     case IS_NOT_FALSE:
-      return toDruidFilters(Iterables.getOnlyElement(((RexCall) rexNode).getOperands()), rowType,
-          druidQuery);
+      return toDruidFilters(
+          Iterables.getOnlyElement(((RexCall) rexNode).getOperands()), rowType,
+          druidQuery, rexBuilder);
     case IS_NOT_TRUE:
     case IS_FALSE:
-      final DruidJsonFilter simpleFilter = toDruidFilters(Iterables
-          .getOnlyElement(((RexCall) rexNode).getOperands()), rowType, druidQuery);
+      final DruidJsonFilter simpleFilter =
+          toDruidFilters(
+              Iterables.getOnlyElement(((RexCall) rexNode).getOperands()),
+              rowType, druidQuery, rexBuilder);
       return simpleFilter != null ? new JsonCompositeFilter(Type.NOT, simpleFilter)
           : simpleFilter;
     case AND:
@@ -406,7 +413,8 @@
       final RexCall call = (RexCall) rexNode;
       final List<DruidJsonFilter> jsonFilters = new ArrayList<>();
       for (final RexNode e : call.getOperands()) {
-        final DruidJsonFilter druidFilter = toDruidFilters(e, rowType, druidQuery);
+        final DruidJsonFilter druidFilter =
+            toDruidFilters(e, rowType, druidQuery, rexBuilder);
         if (druidFilter == null) {
           return null;
         }
diff --git a/druid/src/main/java/org/apache/calcite/adapter/druid/DruidQuery.java b/druid/src/main/java/org/apache/calcite/adapter/druid/DruidQuery.java
index fbdb8ec..bc30cfc 100644
--- a/druid/src/main/java/org/apache/calcite/adapter/druid/DruidQuery.java
+++ b/druid/src/main/java/org/apache/calcite/adapter/druid/DruidQuery.java
@@ -483,8 +483,10 @@
         }
         if (r instanceof Filter) {
           final Filter filter = (Filter) r;
-          final DruidJsonFilter druidJsonFilter = DruidJsonFilter
-              .toDruidFilters(filter.getCondition(), filter.getInput().getRowType(), this);
+          final DruidJsonFilter druidJsonFilter =
+              DruidJsonFilter.toDruidFilters(filter.getCondition(),
+                  filter.getInput().getRowType(), this,
+                  getCluster().getRexBuilder());
           if (druidJsonFilter == null) {
             return litmus.fail("invalid filter [{}]", filter.getCondition());
           }
@@ -723,20 +725,19 @@
    * Currently Filter rel input has to be Druid Table scan
    *
    * @param filterRel input filter rel
-   * @param druidQuery Druid query
    *
    * @return DruidJson Filter or null if cannot translate one of filters
    */
   @Nullable
-  private static DruidJsonFilter computeFilter(@Nullable Filter filterRel,
-      DruidQuery druidQuery) {
+  private DruidJsonFilter computeFilter(@Nullable Filter filterRel) {
     if (filterRel == null) {
       return null;
     }
     final RexNode filter = filterRel.getCondition();
     final RelDataType inputRowType = filterRel.getInput().getRowType();
     if (filter != null) {
-      return DruidJsonFilter.toDruidFilters(filter, inputRowType, druidQuery);
+      return DruidJsonFilter.toDruidFilters(filter, inputRowType, this,
+          getCluster().getRexBuilder());
     }
     return null;
   }
@@ -985,7 +986,7 @@
       ImmutableBitSet numericCollationIndexes, Integer fetch, Project postProject,
       Filter havingFilter) {
     // Handle filter
-    final DruidJsonFilter jsonFilter = computeFilter(filter, this);
+    final DruidJsonFilter jsonFilter = computeFilter(filter);
 
     if (groupSet == null) {
       // It is Scan Query since no Grouping
@@ -1040,8 +1041,10 @@
 
     final DruidJsonFilter havingJsonFilter;
     if (havingFilter != null) {
-      havingJsonFilter = DruidJsonFilter
-          .toDruidFilters(havingFilter.getCondition(), havingFilter.getInput().getRowType(), this);
+      havingJsonFilter =
+          DruidJsonFilter.toDruidFilters(havingFilter.getCondition(),
+              havingFilter.getInput().getRowType(), this,
+              getCluster().getRexBuilder());
     } else {
       havingJsonFilter = null;
     }
@@ -1460,8 +1463,10 @@
     }
     // translate filters
     if (filterNode != null) {
-      DruidJsonFilter druidFilter = DruidJsonFilter
-          .toDruidFilters(filterNode, druidQuery.table.getRowType(), druidQuery);
+      DruidJsonFilter druidFilter =
+          DruidJsonFilter.toDruidFilters(filterNode,
+              druidQuery.table.getRowType(), druidQuery,
+              druidQuery.getCluster().getRexBuilder());
       if (druidFilter == null) {
         // cannot translate filter
         return null;
diff --git a/druid/src/main/java/org/apache/calcite/adapter/druid/DruidRules.java b/druid/src/main/java/org/apache/calcite/adapter/druid/DruidRules.java
index fa72dc3..66a0078 100644
--- a/druid/src/main/java/org/apache/calcite/adapter/druid/DruidRules.java
+++ b/druid/src/main/java/org/apache/calcite/adapter/druid/DruidRules.java
@@ -198,8 +198,9 @@
       final RexNode cond =
           simplify.simplifyUnknownAsFalse(filter.getCondition());
       for (RexNode e : RelOptUtil.conjunctions(cond)) {
-        DruidJsonFilter druidJsonFilter = DruidJsonFilter
-            .toDruidFilters(e, filter.getInput().getRowType(), query);
+        DruidJsonFilter druidJsonFilter =
+            DruidJsonFilter.toDruidFilters(e, filter.getInput().getRowType(),
+                query, rexBuilder);
         if (druidJsonFilter != null) {
           validPreds.add(e);
         } else {
@@ -303,14 +304,17 @@
     @Override public void onMatch(RelOptRuleCall call) {
       final Filter filter = call.rel(0);
       final DruidQuery query = call.rel(1);
+      final RelOptCluster cluster = filter.getCluster();
+      final RexBuilder rexBuilder = cluster.getRexBuilder();
 
       if (!DruidQuery.isValidSignature(query.signature() + 'h')) {
         return;
       }
 
       final RexNode cond = filter.getCondition();
-      final DruidJsonFilter druidJsonFilter = DruidJsonFilter
-          .toDruidFilters(cond, query.getTopNode().getRowType(), query);
+      final DruidJsonFilter druidJsonFilter =
+          DruidJsonFilter.toDruidFilters(cond, query.getTopNode().getRowType(),
+              query, rexBuilder);
       if (druidJsonFilter != null) {
         final RelNode newFilter = filter
             .copy(filter.getTraitSet(), Util.last(query.rels), filter.getCondition());
diff --git a/druid/src/test/java/org/apache/calcite/adapter/druid/DruidQueryFilterTest.java b/druid/src/test/java/org/apache/calcite/adapter/druid/DruidQueryFilterTest.java
index b108166..ff3fa81 100644
--- a/druid/src/test/java/org/apache/calcite/adapter/druid/DruidQueryFilterTest.java
+++ b/druid/src/test/java/org/apache/calcite/adapter/druid/DruidQueryFilterTest.java
@@ -74,7 +74,7 @@
     RexNode inRexNode =
         f.rexBuilder.makeCall(SqlInternalOperators.DRUID_IN, listRexNodes);
     DruidJsonFilter returnValue = DruidJsonFilter
-        .toDruidFilters(inRexNode, f.varcharRowType, druidQuery);
+        .toDruidFilters(inRexNode, f.varcharRowType, druidQuery, f.rexBuilder);
     assertThat("Filter is null", returnValue, notNullValue());
     JsonFactory jsonFactory = new JsonFactory();
     final StringWriter sw = new StringWriter();
@@ -99,7 +99,7 @@
         SqlInternalOperators.DRUID_BETWEEN, listRexNodes);
 
     DruidJsonFilter returnValue = DruidJsonFilter
-        .toDruidFilters(betweenRexNode, f.varcharRowType, druidQuery);
+        .toDruidFilters(betweenRexNode, f.varcharRowType, druidQuery, f.rexBuilder);
     assertThat("Filter is null", returnValue, notNullValue());
     JsonFactory jsonFactory = new JsonFactory();
     final StringWriter sw = new StringWriter();
diff --git a/druid/src/test/java/org/apache/calcite/test/DruidAdapter2IT.java b/druid/src/test/java/org/apache/calcite/test/DruidAdapter2IT.java
index 913bd82..d487ce9 100644
--- a/druid/src/test/java/org/apache/calcite/test/DruidAdapter2IT.java
+++ b/druid/src/test/java/org/apache/calcite/test/DruidAdapter2IT.java
@@ -501,7 +501,6 @@
   /** Tests a query that contains no GROUP BY and is therefore executed as a
    * Druid "select" query. */
   @Test void testFilterSortDesc() {
-    Assumptions.assumeTrue(Bug.CALCITE_4279_FIXED, "CALCITE-4279");
     final String sql = "select \"product_name\" from \"foodmart\"\n"
         + "where \"product_id\" BETWEEN '1500' AND '1502'\n"
         + "order by \"state_province\" desc, \"product_id\"";
@@ -857,7 +856,6 @@
   }
 
   @Test void testGroupByMonthGranularityFiltered() {
-    Assumptions.assumeTrue(Bug.CALCITE_4279_FIXED, "CALCITE-4279");
     final String sql = "select sum(\"unit_sales\") as s,\n"
         + " count(\"store_sqft\") as c\n"
         + "from \"foodmart\"\n"
@@ -908,7 +906,6 @@
   }
 
   @Test void testTopNDayGranularityFiltered() {
-    Assumptions.assumeTrue(Bug.CALCITE_4279_FIXED, "CALCITE-4279");
     final String sql = "select sum(\"unit_sales\") as s,\n"
         + "max(\"unit_sales\") as m,\n"
         + "\"state_province\" as p\n"
@@ -1012,7 +1009,6 @@
   }
 
   @Test void testFilterDistinct() {
-    Assumptions.assumeTrue(Bug.CALCITE_4279_FIXED, "CALCITE-4279");
     final String sql = "select distinct \"state_province\", \"city\",\n"
         + "  \"product_name\"\n"
         + "from \"foodmart\"\n"
@@ -1027,13 +1023,13 @@
         + "'aggregations':[],"
         + "'intervals':['1900-01-09T00:00:00.000Z/2992-01-10T00:00:00.000Z']}";
     final String explain = "PLAN=EnumerableInterpreter\n"
-        + "  DruidQuery(table=[[foodmart, foodmart]], intervals=[[1900-01-09T00:00:00.000Z/"
-        + "2992-01-10T00:00:00.000Z]],"
-        + " filter=[AND(=($3, 'High Top Dried Mushrooms'),"
-        + " OR(=($87, 'Q2'),"
-        + " =($87, 'Q3')),"
-        + " =($30, 'WA'))],"
-        + " projects=[[$30, $29, $3]], groups=[{0, 1, 2}], aggs=[[]])\n";
+        + "  DruidQuery(table=[[foodmart, foodmart]], "
+        + "intervals=[[1900-01-09T00:00:00.000Z/2992-01-10T00:00:00.000Z]], "
+        + "filter=[AND("
+        + "SEARCH($3, Sarg['High Top Dried Mushrooms':VARCHAR]:VARCHAR), "
+        + "SEARCH($87, Sarg['Q2', 'Q3']:CHAR(2)), "
+        + "SEARCH($30, Sarg['WA':VARCHAR]:VARCHAR))], "
+        + "projects=[[$30, $29, $3]], groups=[{0, 1, 2}], aggs=[[]])\n";
     sql(sql)
         .queryContains(new DruidChecker(druidQuery1, druidQuery2))
         .explainContains(explain)
@@ -1051,7 +1047,6 @@
   }
 
   @Test void testFilter() {
-    Assumptions.assumeTrue(Bug.CALCITE_4279_FIXED, "CALCITE-4279");
     final String sql = "select \"state_province\", \"city\",\n"
         + "  \"product_name\"\n"
         + "from \"foodmart\"\n"
@@ -1072,8 +1067,10 @@
     final String explain = "PLAN=EnumerableInterpreter\n"
         + "  DruidQuery(table=[[foodmart, foodmart]], "
         + "intervals=[[1900-01-09T00:00:00.000Z/2992-01-10T00:00:00.000Z]], "
-        + "filter=[AND(=($3, 'High Top Dried Mushrooms'), "
-        + "OR(=($87, 'Q2'), =($87, 'Q3')), =($30, 'WA'))], "
+        + "filter=[AND("
+        + "SEARCH($3, Sarg['High Top Dried Mushrooms':VARCHAR]:VARCHAR), "
+        + "SEARCH($87, Sarg['Q2', 'Q3']:CHAR(2)), "
+        + "SEARCH($30, Sarg['WA':VARCHAR]:VARCHAR))], "
         + "projects=[[$30, $29, $3]])\n";
     sql(sql)
         .queryContains(new DruidChecker(druidQuery))
@@ -1164,7 +1161,6 @@
   }
 
   @Test void testPushAggregateOnTimeWithExtractYear() {
-    Assumptions.assumeTrue(Bug.CALCITE_4279_FIXED, "CALCITE-4279");
     String sql = "select EXTRACT( year from \"timestamp\") as \"year\",\"product_id\" from "
         + "\"foodmart\" where \"product_id\" = 1016 and "
         + "\"timestamp\" < cast('1999-01-02' as timestamp) and \"timestamp\" > cast"
@@ -1182,7 +1178,6 @@
   }
 
   @Test void testPushAggregateOnTimeWithExtractMonth() {
-    Assumptions.assumeTrue(Bug.CALCITE_4279_FIXED, "CALCITE-4279");
     String sql = "select EXTRACT( month from \"timestamp\") as \"month\",\"product_id\" from "
         + "\"foodmart\" where \"product_id\" = 1016 and "
         + "\"timestamp\" < cast('1997-06-02' as timestamp) and \"timestamp\" > cast"
@@ -1201,7 +1196,6 @@
   }
 
   @Test void testPushAggregateOnTimeWithExtractDay() {
-    Assumptions.assumeTrue(Bug.CALCITE_4279_FIXED, "CALCITE-4279");
     String sql = "select EXTRACT( day from \"timestamp\") as \"day\","
         + "\"product_id\" from \"foodmart\""
         + " where \"product_id\" = 1016 and "
@@ -1221,7 +1215,6 @@
   }
 
   @Test void testPushAggregateOnTimeWithExtractHourOfDay() {
-    Assumptions.assumeTrue(Bug.CALCITE_4279_FIXED, "CALCITE-4279");
     String sql =
         "select EXTRACT( hour from \"timestamp\") as \"hourOfDay\",\"product_id\"  from "
             + "\"foodmart\" where \"product_id\" = 1016 and "
@@ -1234,7 +1227,6 @@
   }
 
   @Test void testPushAggregateOnTimeWithExtractYearMonthDay() {
-    Assumptions.assumeTrue(Bug.CALCITE_4279_FIXED, "CALCITE-4279");
     String sql = "select EXTRACT( day from \"timestamp\") as \"day\", EXTRACT( month from "
         + "\"timestamp\") as \"month\",  EXTRACT( year from \"timestamp\") as \"year\",\""
         + "product_id\"  from \"foodmart\" where \"product_id\" = 1016 and "
@@ -1269,7 +1261,6 @@
   }
 
   @Test void testPushAggregateOnTimeWithExtractYearMonthDayWithOutRenaming() {
-    Assumptions.assumeTrue(Bug.CALCITE_4279_FIXED, "CALCITE-4279");
     String sql = "select EXTRACT( day from \"timestamp\"), EXTRACT( month from "
         + "\"timestamp\"), EXTRACT( year from \"timestamp\"),\""
         + "product_id\"  from \"foodmart\" where \"product_id\" = 1016 and "
@@ -1303,7 +1294,6 @@
   }
 
   @Test void testPushAggregateOnTimeWithExtractWithOutRenaming() {
-    Assumptions.assumeTrue(Bug.CALCITE_4279_FIXED, "CALCITE-4279");
     String sql = "select EXTRACT( day from \"timestamp\"), "
         + "\"product_id\" as \"dayOfMonth\" from \"foodmart\" "
         + "where \"product_id\" = 1016 and \"timestamp\" < cast('1997-01-20' as timestamp) "
@@ -1328,7 +1318,6 @@
   }
 
   @Test void testPushComplexFilter() {
-    Assumptions.assumeTrue(Bug.CALCITE_4279_FIXED, "CALCITE-4279");
     String sql = "select sum(\"store_sales\") from \"foodmart\" "
         + "where EXTRACT( year from \"timestamp\") = 1997 and "
         + "\"cases_per_pallet\" >= 8 and \"cases_per_pallet\" <= 10 and "
@@ -2048,7 +2037,6 @@
   }
 
   @Test void testOrderByOnMetricsInSelectDruidQuery() {
-    Assumptions.assumeTrue(Bug.CALCITE_4279_FIXED, "CALCITE-4279");
     final String sqlQuery = "select \"store_sales\" as a, \"store_cost\" as b, \"store_sales\" - "
         + "\"store_cost\" as c from \"foodmart\" where \"timestamp\" "
         + ">= '1997-01-01 00:00:00' and \"timestamp\" < '1997-09-01 00:00:00' order by c "
@@ -2251,7 +2239,6 @@
   /** Tests that multiple aggregates with filter clauses have their filters
   extracted to the outer filter field for data pruning. */
   @Test void testFilterClausesFactoredForPruning1() {
-    Assumptions.assumeTrue(Bug.CALCITE_4279_FIXED, "CALCITE-4279");
     String sql = "select "
         + "sum(\"store_sales\") filter (where \"store_state\" = 'CA'), "
         + "sum(\"store_sales\") filter (where \"store_state\" = 'WA') "
@@ -2276,7 +2263,6 @@
    * extracted to the outer filter field for data pruning in the presence of an
    * outer filter. */
   @Test void testFilterClausesFactoredForPruning2() {
-    Assumptions.assumeTrue(Bug.CALCITE_4279_FIXED, "CALCITE-4279");
     String sql = "select "
         + "sum(\"store_sales\") filter (where \"store_state\" = 'CA'), "
         + "sum(\"store_sales\") filter (where \"store_state\" = 'WA') "
@@ -2427,7 +2413,6 @@
   /** Tests that an aggregate with a nested filter clause has its filter
    * factored out. */
   @Test void testNestedFilterClauseFactored() {
-    Assumptions.assumeTrue(Bug.CALCITE_4279_FIXED, "CALCITE-4279");
     // Logically equivalent to
     // select sum("store_sales") from "foodmart" where "store_state" in ('CA', 'OR')
     String sql =
@@ -2718,7 +2703,6 @@
   }
 
   @Test void testFilterWithFloorOnTime() {
-    Assumptions.assumeTrue(Bug.CALCITE_4279_FIXED, "CALCITE-4279");
     // Test filter on floor on time column is pushed to druid
     final String sql =
         "Select floor(\"timestamp\" to MONTH) as t from \"foodmart\" where "
@@ -2773,7 +2757,6 @@
   }
 
   @Test void testFloorToDateRangeWithTimeZone() {
-    Assumptions.assumeTrue(Bug.CALCITE_4279_FIXED, "CALCITE-4279");
     final String sql = "Select floor(\"timestamp\" to MONTH) as t from "
         + "\"foodmart\" where floor(\"timestamp\" to MONTH) >= '1997-05-01 00:00:00' "
         + "and floor(\"timestamp\" to MONTH) < '1997-05-02 00:00:00' order by t"
@@ -3192,7 +3175,6 @@
 
 
   @Test void testCeilFilterExpression() {
-    Assumptions.assumeTrue(Bug.CALCITE_4279_FIXED, "CALCITE-4279");
     final String sql = "SELECT COUNT(*) FROM " + FOODMART_TABLE + " WHERE ceil(\"store_sales\") > 1"
         + " AND ceil(\"timestamp\" TO DAY) < CAST('1997-01-05' AS TIMESTAMP)"
         + " AND ceil(\"timestamp\" TO MONTH) < CAST('1997-03-01' AS TIMESTAMP)"
diff --git a/druid/src/test/java/org/apache/calcite/test/DruidAdapterIT.java b/druid/src/test/java/org/apache/calcite/test/DruidAdapterIT.java
index f1a0e68..192b1de 100644
--- a/druid/src/test/java/org/apache/calcite/test/DruidAdapterIT.java
+++ b/druid/src/test/java/org/apache/calcite/test/DruidAdapterIT.java
@@ -764,7 +764,6 @@
   /** Tests a query that contains no GROUP BY and is therefore executed as a
    * Druid "select" query. */
   @Test void testFilterSortDesc() {
-    Assumptions.assumeTrue(Bug.CALCITE_4279_FIXED, "CALCITE-4279");
     final String sql = "select \"product_name\" from \"foodmart\"\n"
         + "where \"product_id\" BETWEEN '1500' AND '1502'\n"
         + "order by \"state_province\" desc, \"product_id\"";
@@ -1122,7 +1121,6 @@
   }
 
   @Test void testGroupByMonthGranularityFiltered() {
-    Assumptions.assumeTrue(Bug.CALCITE_4279_FIXED, "CALCITE-4279");
     final String sql = "select sum(\"unit_sales\") as s,\n"
         + " count(\"store_sqft\") as c\n"
         + "from \"foodmart\"\n"
@@ -1173,7 +1171,6 @@
   }
 
   @Test void testTopNDayGranularityFiltered() {
-    Assumptions.assumeTrue(Bug.CALCITE_4279_FIXED, "CALCITE-4279");
     final String sql = "select sum(\"unit_sales\") as s,\n"
         + "max(\"unit_sales\") as m,\n"
         + "\"state_province\" as p\n"
@@ -1279,7 +1276,6 @@
   }
 
   @Test void testFilterDistinct() {
-    Assumptions.assumeTrue(Bug.CALCITE_4279_FIXED, "CALCITE-4279");
     final String sql = "select distinct \"state_province\", \"city\",\n"
         + "  \"product_name\"\n"
         + "from \"foodmart\"\n"
@@ -1294,13 +1290,13 @@
         + "'aggregations':[],"
         + "'intervals':['1900-01-09T00:00:00.000Z/2992-01-10T00:00:00.000Z']}";
     final String explain = "PLAN=EnumerableInterpreter\n"
-        + "  DruidQuery(table=[[foodmart, foodmart]], intervals=[[1900-01-09T00:00:00.000Z/"
-        + "2992-01-10T00:00:00.000Z]],"
-        + " filter=[AND(=($3, 'High Top Dried Mushrooms'),"
-        + " OR(=($87, 'Q2'),"
-        + " =($87, 'Q3')),"
-        + " =($30, 'WA'))],"
-        + " projects=[[$30, $29, $3]], groups=[{0, 1, 2}], aggs=[[]])\n";
+        + "  DruidQuery(table=[[foodmart, foodmart]], "
+        + "intervals=[[1900-01-09T00:00:00.000Z/2992-01-10T00:00:00.000Z]], "
+        + "filter=[AND("
+        + "SEARCH($3, Sarg['High Top Dried Mushrooms':VARCHAR]:VARCHAR), "
+        + "SEARCH($87, Sarg['Q2', 'Q3']:CHAR(2)), "
+        + "SEARCH($30, Sarg['WA':VARCHAR]:VARCHAR))], "
+        + "projects=[[$30, $29, $3]], groups=[{0, 1, 2}], aggs=[[]])\n";
     sql(sql)
         .queryContains(new DruidChecker(druidQuery1, druidQuery2))
         .explainContains(explain)
@@ -1318,7 +1314,6 @@
   }
 
   @Test void testFilter() {
-    Assumptions.assumeTrue(Bug.CALCITE_4279_FIXED, "CALCITE-4279");
     final String sql = "select \"state_province\", \"city\",\n"
         + "  \"product_name\"\n"
         + "from \"foodmart\"\n"
@@ -1339,8 +1334,10 @@
     final String explain = "PLAN=EnumerableInterpreter\n"
         + "  DruidQuery(table=[[foodmart, foodmart]], "
         + "intervals=[[1900-01-09T00:00:00.000Z/2992-01-10T00:00:00.000Z]], "
-        + "filter=[AND(=($3, 'High Top Dried Mushrooms'), "
-        + "OR(=($87, 'Q2'), =($87, 'Q3')), =($30, 'WA'))], "
+        + "filter=[AND("
+        + "SEARCH($3, Sarg['High Top Dried Mushrooms':VARCHAR]:VARCHAR), "
+        + "SEARCH($87, Sarg['Q2', 'Q3']:CHAR(2)), "
+        + "SEARCH($30, Sarg['WA':VARCHAR]:VARCHAR))], "
         + "projects=[[$30, $29, $3]])\n";
     sql(sql)
         .queryContains(new DruidChecker(druidQuery))
@@ -1399,7 +1396,6 @@
 
   /** Tests a query that exposed several bugs in the interpreter. */
   @Test void testWhereGroupBy() {
-    Assumptions.assumeTrue(Bug.CALCITE_4279_FIXED, "CALCITE-4279");
     String sql = "select \"wikipedia\".\"countryName\" as \"c0\",\n"
         + " sum(\"wikipedia\".\"count\") as \"m1\",\n"
         + " sum(\"wikipedia\".\"deleted\") as \"m2\",\n"
@@ -1449,7 +1445,6 @@
   }
 
   @Test void testPushAggregateOnTimeWithExtractYear() {
-    Assumptions.assumeTrue(Bug.CALCITE_4279_FIXED, "CALCITE-4279");
     String sql = "select EXTRACT( year from \"timestamp\") as \"year\",\"product_id\" from "
         + "\"foodmart\" where \"product_id\" = 1016 and "
         + "\"timestamp\" < cast('1999-01-02' as timestamp) and \"timestamp\" > cast"
@@ -1467,7 +1462,6 @@
   }
 
   @Test void testPushAggregateOnTimeWithExtractMonth() {
-    Assumptions.assumeTrue(Bug.CALCITE_4279_FIXED, "CALCITE-4279");
     String sql = "select EXTRACT( month from \"timestamp\") as \"month\",\"product_id\" from "
         + "\"foodmart\" where \"product_id\" = 1016 and "
         + "\"timestamp\" < cast('1997-06-02' as timestamp) and \"timestamp\" > cast"
@@ -1486,7 +1480,6 @@
   }
 
   @Test void testPushAggregateOnTimeWithExtractDay() {
-    Assumptions.assumeTrue(Bug.CALCITE_4279_FIXED, "CALCITE-4279");
     String sql = "select EXTRACT( day from \"timestamp\") as \"day\","
         + "\"product_id\" from \"foodmart\""
         + " where \"product_id\" = 1016 and "
@@ -1506,7 +1499,6 @@
   }
 
   @Test void testPushAggregateOnTimeWithExtractHourOfDay() {
-    Assumptions.assumeTrue(Bug.CALCITE_4279_FIXED, "CALCITE-4279");
     String sql =
         "select EXTRACT( hour from \"timestamp\") as \"hourOfDay\",\"product_id\"  from "
             + "\"foodmart\" where \"product_id\" = 1016 and "
@@ -1519,7 +1511,6 @@
   }
 
   @Test void testPushAggregateOnTimeWithExtractYearMonthDay() {
-    Assumptions.assumeTrue(Bug.CALCITE_4279_FIXED, "CALCITE-4279");
     String sql = "select EXTRACT( day from \"timestamp\") as \"day\", EXTRACT( month from "
         + "\"timestamp\") as \"month\",  EXTRACT( year from \"timestamp\") as \"year\",\""
         + "product_id\"  from \"foodmart\" where \"product_id\" = 1016 and "
@@ -1554,7 +1545,6 @@
   }
 
   @Test void testPushAggregateOnTimeWithExtractYearMonthDayWithOutRenaming() {
-    Assumptions.assumeTrue(Bug.CALCITE_4279_FIXED, "CALCITE-4279");
     String sql = "select EXTRACT( day from \"timestamp\"), EXTRACT( month from "
         + "\"timestamp\"), EXTRACT( year from \"timestamp\"),\""
         + "product_id\"  from \"foodmart\" where \"product_id\" = 1016 and "
@@ -1588,7 +1578,6 @@
   }
 
   @Test void testPushAggregateOnTimeWithExtractWithOutRenaming() {
-    Assumptions.assumeTrue(Bug.CALCITE_4279_FIXED, "CALCITE-4279");
     String sql = "select EXTRACT( day from \"timestamp\"), "
         + "\"product_id\" as \"dayOfMonth\" from \"foodmart\" "
         + "where \"product_id\" = 1016 and \"timestamp\" < cast('1997-01-20' as timestamp) "
@@ -1613,7 +1602,6 @@
   }
 
   @Test void testPushComplexFilter() {
-    Assumptions.assumeTrue(Bug.CALCITE_4279_FIXED, "CALCITE-4279");
     String sql = "select sum(\"store_sales\") from \"foodmart\" "
         + "where EXTRACT( year from \"timestamp\") = 1997 and "
         + "\"cases_per_pallet\" >= 8 and \"cases_per_pallet\" <= 10 and "
@@ -2349,7 +2337,6 @@
   }
 
   @Test void testOrderByOnMetricsInSelectDruidQuery() {
-    Assumptions.assumeTrue(Bug.CALCITE_4279_FIXED, "CALCITE-4279");
     final String sqlQuery = "select \"store_sales\" as a, \"store_cost\" as b, \"store_sales\" - "
             + "\"store_cost\" as c from \"foodmart\" where \"timestamp\" "
             + ">= '1997-01-01 00:00:00 UTC' and \"timestamp\" < '1997-09-01 00:00:00 UTC' order by c "
@@ -2552,7 +2539,6 @@
   /** Tests that multiple aggregates with filter clauses have their filters
    * extracted to the outer filter field for data pruning. */
   @Test void testFilterClausesFactoredForPruning1() {
-    Assumptions.assumeTrue(Bug.CALCITE_4279_FIXED, "CALCITE-4279");
     String sql = "select "
             + "sum(\"store_sales\") filter (where \"store_state\" = 'CA'), "
             + "sum(\"store_sales\") filter (where \"store_state\" = 'WA') "
@@ -2577,7 +2563,6 @@
    * extracted to the outer filter field for data pruning in the presence of an
    * outer filter. */
   @Test void testFilterClausesFactoredForPruning2() {
-    Assumptions.assumeTrue(Bug.CALCITE_4279_FIXED, "CALCITE-4279");
     String sql = "select "
             + "sum(\"store_sales\") filter (where \"store_state\" = 'CA'), "
             + "sum(\"store_sales\") filter (where \"store_state\" = 'WA') "
@@ -2727,7 +2712,6 @@
   /** Tests that an aggregate with a nested filter clause has its filter
    * factored out. */
   @Test void testNestedFilterClauseFactored() {
-    Assumptions.assumeTrue(Bug.CALCITE_4279_FIXED, "CALCITE-4279");
     // Logically equivalent to
     // select sum("store_sales") from "foodmart" where "store_state" in ('CA', 'OR')
     String sql =
@@ -3185,7 +3169,6 @@
   }
 
   @Test void testFilterWithFloorOnTime() {
-    Assumptions.assumeTrue(Bug.CALCITE_4279_FIXED, "CALCITE-4279");
     // Test filter on floor on time column is pushed to druid
     final String sql =
         "Select cast(floor(\"timestamp\" to MONTH) as timestamp) as t from \"foodmart\" where "
@@ -3313,7 +3296,6 @@
   }
 
   @Test void testFloorToDateRangeWithTimeZone() {
-    Assumptions.assumeTrue(Bug.CALCITE_4279_FIXED, "CALCITE-4279");
     final String sql = "Select cast(floor(\"timestamp\" to MONTH) as timestamp) as t from "
         + "\"foodmart\" where floor(\"timestamp\" to MONTH) >= '1997-05-01 00:00:00 Asia/Kolkata' "
         + "and floor(\"timestamp\" to MONTH) < '1997-05-02 00:00:00 Asia/Kolkata' order by t"
@@ -3817,7 +3799,6 @@
 
 
   @Test void testCeilFilterExpression() {
-    Assumptions.assumeTrue(Bug.CALCITE_4279_FIXED, "CALCITE-4279");
     final String sql = "SELECT COUNT(*) FROM " + FOODMART_TABLE + " WHERE ceil(\"store_sales\") > 1"
         + " AND ceil(\"timestamp\" TO DAY) < CAST('1997-01-05' AS TIMESTAMP)"
         + " AND ceil(\"timestamp\" TO MONTH) < CAST('1997-03-01' AS TIMESTAMP)"
@@ -4370,15 +4351,14 @@
         "SELECT \"product_id\" as prod_id1, \"product_id\" as prod_id2, "
             + "SUM(\"store_sales\") as S1, SUM(\"store_sales\") as S2 FROM " + FOODMART_TABLE
             + " GROUP BY \"product_id\" ORDER BY prod_id2 LIMIT 1";
-    CalciteAssert.AssertQuery q = sql(sql, FOODMART)
+    sql(sql, FOODMART)
         .explainContains("BindableProject(PROD_ID1=[$0], PROD_ID2=[$0], S1=[$1], S2=[$1])\n"
             + "    DruidQuery(table=[[foodmart, foodmart]], intervals=[[1900-01-09T00:00:00.000Z/"
             + "2992-01-10T00:00:00.000Z]], projects=[[$1, $90]], groups=[{0}], aggs=[[SUM($1)]], "
             + "sort0=[0], dir0=[ASC], fetch=[1])")
         .queryContains(
-            new DruidChecker("\"queryType\":\"groupBy\""));
-    Assumptions.assumeTrue(Bug.CALCITE_4204_FIXED, "CALCITE-4204");
-    q.returnsOrdered("PROD_ID1=1; PROD_ID2=1; S1=236.55; S2=236.55");
+            new DruidChecker("\"queryType\":\"groupBy\""))
+        .returnsOrdered("PROD_ID1=1; PROD_ID2=1; S1=236.55; S2=236.55");
   }
 
   @Test void testGroupBy1() {