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

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


The following commit(s) were added to refs/heads/master by this push:
     new e93522a  [CALCITE-2863] ElasticSearch Adapter. "select *" may return 
empty dictionary for document table
e93522a is described below

commit e93522a8f374d9269e6657cd23603377762b4bc1
Author: Andrei Sereda <[email protected]>
AuthorDate: Mon Feb 25 23:04:55 2019 -0500

    [CALCITE-2863] ElasticSearch Adapter. "select *" may return empty 
dictionary for document table
    
    In some circumstances (eg. order by clause) `select *` would return `{}`.
---
 .../elasticsearch/ElasticsearchConstants.java      |  9 ++++++++
 .../elasticsearch/ElasticsearchEnumerators.java    |  8 +++----
 .../adapter/elasticsearch/ElasticsearchJson.java   |  6 +++++
 .../elasticsearch/ElasticsearchProject.java        |  2 +-
 .../elasticsearch/ElasticSearchAdapterTest.java    |  9 +++++---
 .../adapter/elasticsearch/Projection2Test.java     | 26 ++++++++++++++++++++--
 6 files changed, 50 insertions(+), 10 deletions(-)

diff --git 
a/elasticsearch/src/main/java/org/apache/calcite/adapter/elasticsearch/ElasticsearchConstants.java
 
b/elasticsearch/src/main/java/org/apache/calcite/adapter/elasticsearch/ElasticsearchConstants.java
index da875d5..678cab5 100644
--- 
a/elasticsearch/src/main/java/org/apache/calcite/adapter/elasticsearch/ElasticsearchConstants.java
+++ 
b/elasticsearch/src/main/java/org/apache/calcite/adapter/elasticsearch/ElasticsearchConstants.java
@@ -40,6 +40,15 @@ interface ElasticsearchConstants {
 
   Set<String> META_COLUMNS = ImmutableSet.of(UID, ID, TYPE, INDEX);
 
+  /**
+   * Detects {@code select * from elastic} types of field name (select star).
+   * @param name name of the field
+   * @return {@code true} if this field represents whole raw, {@code false} 
otherwise
+   */
+  static boolean isSelectAll(String name) {
+    return "_MAP".equals(name);
+  }
+
 }
 
 // End ElasticsearchConstants.java
diff --git 
a/elasticsearch/src/main/java/org/apache/calcite/adapter/elasticsearch/ElasticsearchEnumerators.java
 
b/elasticsearch/src/main/java/org/apache/calcite/adapter/elasticsearch/ElasticsearchEnumerators.java
index 054d85c..16da626 100644
--- 
a/elasticsearch/src/main/java/org/apache/calcite/adapter/elasticsearch/ElasticsearchEnumerators.java
+++ 
b/elasticsearch/src/main/java/org/apache/calcite/adapter/elasticsearch/ElasticsearchEnumerators.java
@@ -23,6 +23,7 @@ import org.apache.calcite.linq4j.tree.Primitive;
 import java.util.Date;
 import java.util.List;
 import java.util.Map;
+import java.util.Objects;
 
 /**
  * Util functions which convert
@@ -101,13 +102,12 @@ class ElasticsearchEnumerators {
 
   static Function1<ElasticsearchJson.SearchHit, Object> getter(
       List<Map.Entry<String, Class>> fields, Map<String, String> mapping) {
+    Objects.requireNonNull(fields, "fields");
     //noinspection unchecked
     final Function1 getter;
-    if (fields == null || fields.size() == 1 && 
"_MAP".equals(fields.get(0).getKey())) {
-      // select * from table
-      getter = mapGetter();
-    } else if (fields.size() == 1) {
+    if (fields.size() == 1) {
       // select foo from table
+      // select * from table
       getter = singletonGetter(fields.get(0).getKey(), 
fields.get(0).getValue(), mapping);
     } else {
       // select a, b, c from table
diff --git 
a/elasticsearch/src/main/java/org/apache/calcite/adapter/elasticsearch/ElasticsearchJson.java
 
b/elasticsearch/src/main/java/org/apache/calcite/adapter/elasticsearch/ElasticsearchJson.java
index eb9c011..320a32b 100644
--- 
a/elasticsearch/src/main/java/org/apache/calcite/adapter/elasticsearch/ElasticsearchJson.java
+++ 
b/elasticsearch/src/main/java/org/apache/calcite/adapter/elasticsearch/ElasticsearchJson.java
@@ -318,6 +318,12 @@ final class ElasticsearchJson {
 
     Object valueOrNull(String name) {
       Objects.requireNonNull(name, "name");
+
+      // for "select *" return whole document
+      if (ElasticsearchConstants.isSelectAll(name)) {
+        return sourceOrFields();
+      }
+
       if (fields != null && fields.containsKey(name)) {
         Object field = fields.get(name);
         if (field instanceof Iterable) {
diff --git 
a/elasticsearch/src/main/java/org/apache/calcite/adapter/elasticsearch/ElasticsearchProject.java
 
b/elasticsearch/src/main/java/org/apache/calcite/adapter/elasticsearch/ElasticsearchProject.java
index 82aff25..0fffd49 100644
--- 
a/elasticsearch/src/main/java/org/apache/calcite/adapter/elasticsearch/ElasticsearchProject.java
+++ 
b/elasticsearch/src/main/java/org/apache/calcite/adapter/elasticsearch/ElasticsearchProject.java
@@ -73,7 +73,7 @@ public class ElasticsearchProject extends Project implements 
ElasticsearchRel {
         implementor.addExpressionItemMapping(name, 
ElasticsearchRules.stripQuotes(expr));
       }
 
-      hasSelectStar |= "_MAP".equals(name);
+      hasSelectStar |= ElasticsearchConstants.isSelectAll(name);
 
       if (expr.equals(name)) {
         fields.add(name);
diff --git 
a/elasticsearch/src/test/java/org/apache/calcite/adapter/elasticsearch/ElasticSearchAdapterTest.java
 
b/elasticsearch/src/test/java/org/apache/calcite/adapter/elasticsearch/ElasticSearchAdapterTest.java
index 794cbe0..26812cb 100644
--- 
a/elasticsearch/src/test/java/org/apache/calcite/adapter/elasticsearch/ElasticSearchAdapterTest.java
+++ 
b/elasticsearch/src/test/java/org/apache/calcite/adapter/elasticsearch/ElasticSearchAdapterTest.java
@@ -263,7 +263,7 @@ public class ElasticSearchAdapterTest {
   }
 
   /**
-   * Sorting directly on items without a view.
+   * Sorting (and aggregating) directly on items without a view.
    *
    * Queries of type: {@code select _MAP['a'] from elastic order by _MAP['b']}
    */
@@ -281,7 +281,10 @@ public class ElasticSearchAdapterTest {
             "query:{'constant_score':{filter:{term:{state:'NY'}}}}",
             "sort:[{city:'asc'}]",
             String.format(Locale.ROOT, "size:%s", 
ElasticsearchTransport.DEFAULT_FETCH_SIZE)))
-        .returnsCount(3);
+        .returnsOrdered(
+          "_MAP={id=11226, city=BROOKLYN, loc=[-73.956985, 40.646694], 
pop=111396, state=NY}",
+          "_MAP={id=11373, city=JACKSON HEIGHTS, loc=[-73.878551, 40.740388], 
pop=88241, state=NY}",
+          "_MAP={id=10021, city=NEW YORK, loc=[-73.958805, 40.768476], 
pop=106564, state=NY}");
 
     CalciteAssert.that()
         .with(newConnectionFactory())
@@ -322,7 +325,7 @@ public class ElasticSearchAdapterTest {
         .with(newConnectionFactory())
         .query("select max(_MAP['pop']), min(_MAP['pop']), _MAP['state'] from 
elastic.zips "
             + "where _MAP['state'] = 'NY' group by _MAP['state'] order by 
_MAP['state'] limit 3")
-        .returnsCount(1);
+        .returns("EXPR$0=111396.0; EXPR$1=88241.0; EXPR$2=NY\n");
   }
 
   /**
diff --git 
a/elasticsearch/src/test/java/org/apache/calcite/adapter/elasticsearch/Projection2Test.java
 
b/elasticsearch/src/test/java/org/apache/calcite/adapter/elasticsearch/Projection2Test.java
index ddbadc2..7731f2c 100644
--- 
a/elasticsearch/src/test/java/org/apache/calcite/adapter/elasticsearch/Projection2Test.java
+++ 
b/elasticsearch/src/test/java/org/apache/calcite/adapter/elasticsearch/Projection2Test.java
@@ -109,6 +109,21 @@ public class Projection2Test {
             .returns("EXPR$0=1; EXPR$1=2; EXPR$2=3; EXPR$3=foo; EXPR$4=null; 
EXPR$5=null\n");
   }
 
+  @Test
+  public void projection3() {
+    CalciteAssert.that()
+        .with(newConnectionFactory())
+        .query(
+            String.format(Locale.ROOT, "select * from \"elastic\".\"%s\"", 
NAME))
+        .returns("_MAP={a=1, b={a=2, b=3, c={a=foo}}}\n");
+
+    CalciteAssert.that()
+        .with(newConnectionFactory())
+        .query(
+            String.format(Locale.ROOT, "select *, _MAP['a'] from 
\"elastic\".\"%s\"", NAME))
+        .returns("_MAP={a=1, b={a=2, b=3, c={a=foo}}}; EXPR$1=1\n");
+  }
+
   /**
    * Test that {@code _id} field is available when queried explicitly.
    * @see <a 
href="https://www.elastic.co/guide/en/elasticsearch/reference/current/mapping-id-field.html";>ID
 Field</a>
@@ -163,10 +178,17 @@ public class Projection2Test {
         .returns(regexMatch("_id=\\p{Graph}+"));
 
     // _id field not available implicitly
-    final String sql5 = String.format(Locale.ROOT, "select * from 
\"elastic\".\"%s\"", NAME);
     factory
-        .query(sql5)
+        .query(
+            String.format(Locale.ROOT, "select * from \"elastic\".\"%s\"", 
NAME)
+        )
         .returns(regexMatch("_MAP={a=1, b={a=2, b=3, c={a=foo}}}"));
+
+    factory
+        .query(
+            String.format(Locale.ROOT, "select *, _MAP['_id'] from 
\"elastic\".\"%s\"", NAME)
+        )
+        .returns(regexMatch("_MAP={a=1, b={a=2, b=3, c={a=foo}}}; 
EXPR$1=\\p{Graph}+"));
   }
 
   /**

Reply via email to