DRILL-8296: Possible type mismatch bug in SplunkBatchReader (#2700)

diff --git a/contrib/storage-splunk/src/main/java/org/apache/drill/exec/store/splunk/SplunkBatchReader.java b/contrib/storage-splunk/src/main/java/org/apache/drill/exec/store/splunk/SplunkBatchReader.java
index cba9e3d..11a0ce9 100644
--- a/contrib/storage-splunk/src/main/java/org/apache/drill/exec/store/splunk/SplunkBatchReader.java
+++ b/contrib/storage-splunk/src/main/java/org/apache/drill/exec/store/splunk/SplunkBatchReader.java
@@ -35,7 +35,6 @@
 import org.apache.drill.exec.record.metadata.SchemaBuilder;
 import org.apache.drill.exec.record.metadata.TupleMetadata;
 import org.apache.drill.exec.store.base.filter.ExprNode;
-import org.apache.drill.exec.util.Utilities;
 import org.apache.drill.exec.vector.ValueVector;
 import org.apache.drill.exec.vector.accessor.ScalarWriter;
 import org.apache.drill.shaded.guava.com.google.common.base.Stopwatch;
@@ -214,28 +213,6 @@
   }
 
   /**
-   * Checks to see whether the query is a star query. For our purposes, the star query is
-   * anything that contains only the ** and the SPECIAL_COLUMNS which are not projected.
-   * @return true if it is a star query, false if not.
-   */
-  private boolean isStarQuery() {
-    if (Utilities.isStarQuery(projectedColumns)) {
-      return true;
-    }
-
-    List<SplunkUtils.SPECIAL_FIELDS> specialFields = Arrays.asList(SplunkUtils.SPECIAL_FIELDS.values());
-
-    for (SchemaPath path: projectedColumns) {
-      if (path.nameEquals("**")) {
-        return true;
-      } else {
-        return specialFields.contains(path.getAsNamePart());
-      }
-    }
-    return false;
-  }
-
-  /**
    * Determines whether a field is a Splunk multifield.
    * @param fieldValue The field to be tested
    * @return True if a multifield, false if not.
@@ -312,9 +289,9 @@
       filters.remove("sourcetype");
     }
 
-    // Pushdown the selected fields for non star queries.
-    if (! isStarQuery()) {
-      builder.addField(projectedColumns);
+    // Add projected columns, skipping star and specials.
+    for (SchemaPath projectedColumn: projectedColumns) {
+      builder.addField(projectedColumn.getAsUnescapedPath());
     }
 
     // Apply filters
diff --git a/contrib/storage-splunk/src/main/java/org/apache/drill/exec/store/splunk/SplunkQueryBuilder.java b/contrib/storage-splunk/src/main/java/org/apache/drill/exec/store/splunk/SplunkQueryBuilder.java
index c13c08e..0d83fdd 100644
--- a/contrib/storage-splunk/src/main/java/org/apache/drill/exec/store/splunk/SplunkQueryBuilder.java
+++ b/contrib/storage-splunk/src/main/java/org/apache/drill/exec/store/splunk/SplunkQueryBuilder.java
@@ -23,7 +23,6 @@
 import org.apache.drill.exec.store.base.filter.RelOp;
 import org.apache.drill.shaded.guava.com.google.common.base.Strings;
 
-import java.util.List;
 import java.util.Map;
 
 public class SplunkQueryBuilder {
@@ -36,7 +35,7 @@
 
   private String query;
   private String sourceTypes;
-  private String fieldList;
+  private String concatenatedFields;
   private String filters;
   private int sourcetypeCount;
   private int limit;
@@ -69,35 +68,21 @@
    * Splunk accepts arguments in the format | fields foo, bar, car.  This function adds these fields to the query.
    * As an error preventative measure, this function will ignore ** from Drill.
    * @param field The field to be added to the query
+   * @return true if the field was added, false if it was skipped
    */
-  public void addField (String field) {
+  public boolean addField(String field) {
     // Double Star fields cause errors and we will not add to the field list
-    if (field.equalsIgnoreCase("**") || Strings.isNullOrEmpty(field)) {
-      return;
+    if (SchemaPath.DYNAMIC_STAR.equals(field) || SplunkUtils.SPECIAL_FIELDS.includes(field)) {
+      return false;
     }
 
     // Case for first field
-    if (fieldList == null) {
-      this.fieldList = field;
+    if (concatenatedFields == null) {
+      this.concatenatedFields = field;
     } else {
-      this.fieldList += "," + field;
+      this.concatenatedFields += "," + field;
     }
-  }
-
-  /**
-   * Creates the field list of r
-   * As an error preventative measure, this function will ignore ** from Drill.
-   * @param columnList SchemaPath of columns to be added to the field list
-   */
-  public void addField (List<SchemaPath> columnList) {
-    for (SchemaPath column : columnList) {
-      String columnName = column.getAsUnescapedPath();
-      if (columnName.equalsIgnoreCase("**") || Strings.isNullOrEmpty(columnName)) {
-        continue;
-      } else {
-        addField(columnName);
-      }
-    }
+    return true;
   }
 
   /**
@@ -153,7 +138,7 @@
       String value = ((ExprNode.ColRelOpConstNode)filter.getValue()).value.value.toString();
 
       // Ignore special cases
-      if (SplunkUtils.isSpecialField(fieldName)) {
+      if (SplunkUtils.SPECIAL_FIELDS.includes(fieldName)) {
         // Sourcetypes are a special case and can be added via filter pushdown
         if (fieldName.equalsIgnoreCase("sourcetype")) {
           addSourceType(value);
@@ -226,8 +211,8 @@
     }
 
     // Add fields
-    if (! Strings.isNullOrEmpty(fieldList)) {
-      query += " | fields " + fieldList;
+    if (! Strings.isNullOrEmpty(concatenatedFields)) {
+      query += " | fields " + concatenatedFields;
     }
 
     // Add limit
@@ -236,10 +221,10 @@
     }
 
     // Add table logic. This tells Splunk to return the data in tabular form rather than the mess that it usually generates
-    if ( Strings.isNullOrEmpty(fieldList)) {
-      fieldList = "*";
+    if ( Strings.isNullOrEmpty(concatenatedFields)) {
+      concatenatedFields = "*";
     }
-    query += " | table " + fieldList;
+    query += " | table " + concatenatedFields;
 
     return query;
   }
diff --git a/contrib/storage-splunk/src/main/java/org/apache/drill/exec/store/splunk/SplunkUtils.java b/contrib/storage-splunk/src/main/java/org/apache/drill/exec/store/splunk/SplunkUtils.java
index f34f64d..a859f2c 100644
--- a/contrib/storage-splunk/src/main/java/org/apache/drill/exec/store/splunk/SplunkUtils.java
+++ b/contrib/storage-splunk/src/main/java/org/apache/drill/exec/store/splunk/SplunkUtils.java
@@ -18,6 +18,8 @@
 
 package org.apache.drill.exec.store.splunk;
 
+import java.util.Arrays;
+
 public class SplunkUtils {
   /**
    * These are special fields that alter the queries sent to Splunk.
@@ -46,19 +48,15 @@
       this.field = field;
     }
 
-  }
-
-  /**
-   * Indicates whether the field in question is a special field and should be pushed down to the query or not.
-   * @param unknownField The field to be pushed down
-   * @return true if the field is a special field, false if not.
-   */
-  public static boolean isSpecialField (String unknownField) {
-    for (SPECIAL_FIELDS specialFieldName : SPECIAL_FIELDS.values()) {
-      if (specialFieldName.field.equalsIgnoreCase(unknownField)) {
-        return true;
-      }
+    /**
+     * Indicates whether the field in question is a special field and should be
+     * pushed down to the query or not.
+     * @param unknownField The field to be pushed down
+     * @return true if the field is a special field, false if not.
+     */
+    public static boolean includes(String field) {
+      return Arrays.stream(SplunkUtils.SPECIAL_FIELDS.values())
+        .anyMatch(special -> field.equals(special.name()));
     }
-    return false;
   }
 }
diff --git a/contrib/storage-splunk/src/test/java/org/apache/drill/exec/store/splunk/SplunkTestSplunkUtils.java b/contrib/storage-splunk/src/test/java/org/apache/drill/exec/store/splunk/SplunkTestSplunkUtils.java
index f60dafb..a4a2e64 100644
--- a/contrib/storage-splunk/src/test/java/org/apache/drill/exec/store/splunk/SplunkTestSplunkUtils.java
+++ b/contrib/storage-splunk/src/test/java/org/apache/drill/exec/store/splunk/SplunkTestSplunkUtils.java
@@ -31,17 +31,17 @@
 
   @Test
   public void testIsSpecialField() {
-    assertTrue(SplunkUtils.isSpecialField("sourcetype"));
-    assertTrue(SplunkUtils.isSpecialField("earliestTime"));
-    assertTrue(SplunkUtils.isSpecialField("latestTime"));
-    assertTrue(SplunkUtils.isSpecialField("spl"));
+    assertTrue(SplunkUtils.SPECIAL_FIELDS.includes("sourcetype"));
+    assertTrue(SplunkUtils.SPECIAL_FIELDS.includes("earliestTime"));
+    assertTrue(SplunkUtils.SPECIAL_FIELDS.includes("latestTime"));
+    assertTrue(SplunkUtils.SPECIAL_FIELDS.includes("spl"));
   }
 
   @Test
   public void testIsNotSpecialField() {
-    assertFalse(SplunkUtils.isSpecialField("bob"));
-    assertFalse(SplunkUtils.isSpecialField("ip_address"));
-    assertFalse(SplunkUtils.isSpecialField("mac_address"));
-    assertFalse(SplunkUtils.isSpecialField("latest_Time"));
+    assertFalse(SplunkUtils.SPECIAL_FIELDS.includes("bob"));
+    assertFalse(SplunkUtils.SPECIAL_FIELDS.includes("ip_address"));
+    assertFalse(SplunkUtils.SPECIAL_FIELDS.includes("mac_address"));
+    assertFalse(SplunkUtils.SPECIAL_FIELDS.includes("latest_Time"));
   }
 }