calcite-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From jh...@apache.org
Subject [1/7] incubator-calcite git commit: [CALCITE-740] Redundant WHERE clause causes wrong result in MongoDB adapter
Date Sat, 13 Jun 2015 00:38:05 GMT
Repository: incubator-calcite
Updated Branches:
  refs/heads/master dbdb091dc -> 468a161bb


[CALCITE-740] Redundant WHERE clause causes wrong result in MongoDB adapter


Project: http://git-wip-us.apache.org/repos/asf/incubator-calcite/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-calcite/commit/6ece12a8
Tree: http://git-wip-us.apache.org/repos/asf/incubator-calcite/tree/6ece12a8
Diff: http://git-wip-us.apache.org/repos/asf/incubator-calcite/diff/6ece12a8

Branch: refs/heads/master
Commit: 6ece12a862d9fb03f2be77c0d60880a30fbd79b1
Parents: dbdb091
Author: Julian Hyde <jhyde@apache.org>
Authored: Mon Jun 8 12:05:44 2015 -0700
Committer: Julian Hyde <jhyde@apache.org>
Committed: Mon Jun 8 12:07:48 2015 -0700

----------------------------------------------------------------------
 .../calcite/adapter/mongodb/MongoFilter.java    | 34 ++++++++++++++++--
 .../org/apache/calcite/test/MongoAdapterIT.java | 36 ++++++++++++++++++++
 2 files changed, 67 insertions(+), 3 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-calcite/blob/6ece12a8/mongodb/src/main/java/org/apache/calcite/adapter/mongodb/MongoFilter.java
----------------------------------------------------------------------
diff --git a/mongodb/src/main/java/org/apache/calcite/adapter/mongodb/MongoFilter.java b/mongodb/src/main/java/org/apache/calcite/adapter/mongodb/MongoFilter.java
index 5f717d7..45b4baf 100644
--- a/mongodb/src/main/java/org/apache/calcite/adapter/mongodb/MongoFilter.java
+++ b/mongodb/src/main/java/org/apache/calcite/adapter/mongodb/MongoFilter.java
@@ -116,20 +116,48 @@ public class MongoFilter extends Filter implements MongoRel {
       Map<String, Object> map = builder.map();
       for (Map.Entry<String, RexLiteral> entry : eqMap.entrySet()) {
         multimap.removeAll(entry.getKey());
-        map.put(entry.getKey(), literalToString(entry.getValue()));
+        map.put(entry.getKey(), literalValue(entry.getValue()));
       }
       for (Map.Entry<String, Collection<Pair<String, RexLiteral>>> entry
           : multimap.asMap().entrySet()) {
         Map<String, Object> map2 = builder.map();
         for (Pair<String, RexLiteral> s : entry.getValue()) {
-          map2.put(s.left, literalToString(s.right));
+          addPredicate(map2, s.left, literalValue(s.right));
         }
         map.put(entry.getKey(), map2);
       }
       return map;
     }
 
-    private static Object literalToString(RexLiteral literal) {
+    private void addPredicate(Map<String, Object> map, String op, Object v) {
+      if (map.containsKey(op) && stronger(op, map.get(op), v)) {
+        return;
+      }
+      map.put(op, v);
+    }
+
+    /** Returns whether {@code v0} is a stronger value for operator {@code key}
+     * than {@code v1}.
+     *
+     * <p>For example, {@code stronger("$lt", 100, 200)} returns true, because
+     * "&lt; 100" is a more powerful condition than "&lt; 200".
+     */
+    private boolean stronger(String key, Object v0, Object v1) {
+      if (key.equals("$lt") || key.equals("$lte")) {
+        if (v0 instanceof Number && v1 instanceof Number) {
+          return ((Number) v0).doubleValue() < ((Number) v1).doubleValue();
+        }
+        if (v0 instanceof String && v1 instanceof String) {
+          return v0.toString().compareTo(v1.toString()) < 0;
+        }
+      }
+      if (key.equals("$gt") || key.equals("$gte")) {
+        return stronger("$lt", v1, v0);
+      }
+      return false;
+    }
+
+    private static Object literalValue(RexLiteral literal) {
       return literal.getValue2();
     }
 

http://git-wip-us.apache.org/repos/asf/incubator-calcite/blob/6ece12a8/mongodb/src/test/java/org/apache/calcite/test/MongoAdapterIT.java
----------------------------------------------------------------------
diff --git a/mongodb/src/test/java/org/apache/calcite/test/MongoAdapterIT.java b/mongodb/src/test/java/org/apache/calcite/test/MongoAdapterIT.java
index f994142..2393660 100644
--- a/mongodb/src/test/java/org/apache/calcite/test/MongoAdapterIT.java
+++ b/mongodb/src/test/java/org/apache/calcite/test/MongoAdapterIT.java
@@ -716,6 +716,42 @@ public class MongoAdapterIT {
             + "STATE=WV; CITY=ATHENS\n");
   }
 
+  /** MongoDB's predicates are handed (they can only accept literals on the
+   * right-hand size) so it's worth testing that we handle them right both
+   * ways around.
+   *
+   * <p>Test case for
+   * <a href="https://issues.apache.org/jira/browse/CALCITE-740">[CALCITE-740]
+   * Redundant WHERE clause causes wrong result in MongoDB adapter</a>. */
+  @Test public void testFilterPair() {
+    final int gt9k = 8125;
+    final int lt9k = 21227;
+    final int gt8k = 8707;
+    final int lt8k = 20645;
+    checkPredicate(gt9k, "where pop > 8000 and pop > 9000");
+    checkPredicate(gt9k, "where pop > 9000");
+    checkPredicate(lt9k, "where pop < 9000");
+    checkPredicate(gt8k, "where pop > 8000");
+    checkPredicate(lt8k, "where pop < 8000");
+    checkPredicate(gt9k, "where pop > 9000 and pop > 8000");
+    checkPredicate(gt8k, "where pop > 9000 or pop > 8000");
+    checkPredicate(gt8k, "where pop > 8000 or pop > 9000");
+    checkPredicate(lt8k, "where pop < 8000 and pop < 9000");
+  }
+
+  private void checkPredicate(int expected, String q) {
+    CalciteAssert.that()
+        .enable(enabled())
+        .with(ZIPS)
+        .query("select count(*) as c from zips\n" + q)
+        .returns("C=" + expected + "\n");
+    CalciteAssert.that()
+        .enable(enabled())
+        .with(ZIPS)
+        .query("select * from zips\n" + q)
+        .returnsCount(expected);
+  }
+
   @Ignore
   @Test public void testFoodmartQueries() {
     final List<Pair<String, String>> queries = JdbcTest.getFoodmartQueries();


Mime
View raw message