You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@pinot.apache.org by ki...@apache.org on 2020/11/01 01:10:14 UTC

[incubator-pinot] branch json-indexing updated (bdfd3f1 -> ee6714c)

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

kishoreg pushed a change to branch json-indexing
in repository https://gitbox.apache.org/repos/asf/incubator-pinot.git.


 discard bdfd3f1  Adding index creator and reader
     new ee6714c  Adding index creator and reader

This update added new revisions after undoing existing revisions.
That is to say, some revisions that were in the old version of the
branch are not in the new version.  This situation occurs
when a user --force pushes a change and generates a repository
containing something like this:

 * -- * -- B -- O -- O -- O   (bdfd3f1)
            \
             N -- N -- N   refs/heads/json-indexing (ee6714c)

You should already have received notification emails for all of the O
revisions, and so the following emails describe only the N revisions
from the common base, B.

Any revisions marked "omit" are not gone; other references still
refer to them.  Any revisions marked "discard" are gone forever.

The 1 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:
 .../antlr4/org/apache/pinot/pql/parsers/PQL2.g4    |   4 +
 .../pinot/common/request/AggregationInfo.java      |  52 ++-
 .../apache/pinot/common/request/BrokerRequest.java | 353 ++++++++++-----------
 .../apache/pinot/common/request/DataSource.java    |  11 +-
 .../apache/pinot/common/request/Expression.java    |  35 +-
 .../pinot/common/request/ExpressionType.java       |   4 +-
 .../pinot/common/request/FilterOperator.java       |  11 +-
 .../apache/pinot/common/request/FilterQuery.java   |  46 +--
 .../pinot/common/request/FilterQueryMap.java       |  11 +-
 .../org/apache/pinot/common/request/Function.java  |  21 +-
 .../org/apache/pinot/common/request/GroupBy.java   |  85 +++--
 .../pinot/common/request/HavingFilterQuery.java    |  46 +--
 .../pinot/common/request/HavingFilterQueryMap.java |  11 +-
 .../apache/pinot/common/request/Identifier.java    |  16 +-
 .../pinot/common/request/InstanceRequest.java      |  76 ++---
 .../org/apache/pinot/common/request/Literal.java   |   4 +-
 .../apache/pinot/common/request/PinotQuery.java    |  61 ++--
 .../apache/pinot/common/request/QuerySource.java   |  11 +-
 .../org/apache/pinot/common/request/QueryType.java |  31 +-
 .../org/apache/pinot/common/request/Selection.java |  94 +++---
 .../apache/pinot/common/request/SelectionSort.java |  16 +-
 .../pinot/common/response/ProcessingException.java | 283 +++++++----------
 .../apache/pinot/parsers/utils/ParserUtils.java    |   1 +
 .../parsers/PinotQuery2BrokerRequestConverter.java |   1 +
 .../pinot/pql/parsers/pql2/ast/FilterKind.java     |   3 +-
 .../apache/pinot/sql/parsers/CalciteSqlParser.java |   8 +-
 pinot-common/src/thrift/request.thrift             |   3 +-
 .../org/apache/pinot/core/common/DataSource.java   |   7 +
 .../indexsegment/mutable/MutableSegmentImpl.java   |  12 +-
 .../operator/filter/JSONMatchFilterOperator.java   |  26 +-
 .../org/apache/pinot/core/plan/FilterPlanNode.java |  15 +
 .../context/utils/QueryContextConverterUtils.java  |   4 +
 .../segment/creator/impl/inv/JSONIndexCreator.java |  12 +-
 .../segment/index/column/ColumnIndexContainer.java |   7 +
 .../index/column/PhysicalColumnIndexContainer.java |  15 +
 .../segment/index/datasource/BaseDataSource.java   |  13 +-
 .../index/datasource/ImmutableDataSource.java      |   5 +-
 .../index/datasource/MutableDataSource.java        |   5 +-
 .../segment/index/loader/IndexLoadingConfig.java   |   2 +-
 .../loader/invertedindex/JSONIndexHandler.java     |  33 +-
 .../segment/index/readers/JSONIndexReader.java     |  15 +-
 .../virtualcolumn/VirtualColumnIndexContainer.java |   6 +
 .../core/startree/v2/store/StarTreeDataSource.java |   3 +-
 .../command/JSONQuickstart.java}                   | 146 ++++-----
 44 files changed, 793 insertions(+), 831 deletions(-)
 copy pinot-tools/src/main/java/org/apache/pinot/tools/{Quickstart.java => admin/command/JSONQuickstart.java} (54%)


---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@pinot.apache.org
For additional commands, e-mail: commits-help@pinot.apache.org


[incubator-pinot] 01/01: Adding index creator and reader

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

kishoreg pushed a commit to branch json-indexing
in repository https://gitbox.apache.org/repos/asf/incubator-pinot.git

commit ee6714c2ac4b6eea174d48e862fb7020494b6c1d
Author: kishoreg <g....@gmail.com>
AuthorDate: Sun Oct 18 22:05:51 2020 -0700

    Adding index creator and reader
---
 .../antlr4/org/apache/pinot/pql/parsers/PQL2.g4    |   4 +
 .../pinot/common/request/AggregationInfo.java      |  52 +-
 .../apache/pinot/common/request/BrokerRequest.java | 353 ++++++-----
 .../apache/pinot/common/request/DataSource.java    |  11 +-
 .../apache/pinot/common/request/Expression.java    |  35 +-
 .../pinot/common/request/ExpressionType.java       |   4 +-
 .../pinot/common/request/FilterOperator.java       |  11 +-
 .../apache/pinot/common/request/FilterQuery.java   |  46 +-
 .../pinot/common/request/FilterQueryMap.java       |  11 +-
 .../org/apache/pinot/common/request/Function.java  |  21 +-
 .../org/apache/pinot/common/request/GroupBy.java   |  85 ++-
 .../pinot/common/request/HavingFilterQuery.java    |  46 +-
 .../pinot/common/request/HavingFilterQueryMap.java |  11 +-
 .../apache/pinot/common/request/Identifier.java    |  16 +-
 .../pinot/common/request/InstanceRequest.java      |  76 ++-
 .../org/apache/pinot/common/request/Literal.java   |   4 +-
 .../apache/pinot/common/request/PinotQuery.java    |  61 +-
 .../apache/pinot/common/request/QuerySource.java   |  11 +-
 .../org/apache/pinot/common/request/QueryType.java |  31 +-
 .../org/apache/pinot/common/request/Selection.java |  94 ++-
 .../apache/pinot/common/request/SelectionSort.java |  16 +-
 .../pinot/common/response/ProcessingException.java | 283 ++++-----
 .../apache/pinot/parsers/utils/ParserUtils.java    |   1 +
 .../parsers/PinotQuery2BrokerRequestConverter.java |   1 +
 .../pinot/pql/parsers/pql2/ast/FilterKind.java     |   3 +-
 .../apache/pinot/sql/parsers/CalciteSqlParser.java |   8 +-
 pinot-common/src/thrift/request.thrift             |   3 +-
 .../org/apache/pinot/core/common/DataSource.java   |   7 +
 .../indexsegment/mutable/MutableSegmentImpl.java   |  12 +-
 .../io/util/VarLengthBytesValueReaderWriter.java   |  28 +-
 .../operator/filter/BitmapBasedFilterOperator.java |   4 +-
 .../core/operator/filter/FilterOperatorUtils.java  |   2 +-
 .../operator/filter/JSONMatchFilterOperator.java   | 148 +++++
 .../transform/function/CastTransformFunction.java  |   2 +-
 .../org/apache/pinot/core/plan/FilterPlanNode.java |  15 +
 .../{Predicate.java => JSONMatchPredicate.java}    |  57 +-
 .../query/request/context/predicate/Predicate.java |   3 +-
 .../context/utils/QueryContextConverterUtils.java  |   4 +
 .../core/segment/creator/impl/V1Constants.java     |   1 +
 .../segment/creator/impl/inv/JSONIndexCreator.java | 658 +++++++++++++++++++++
 .../creator/impl/inv/NestedObjectIndexCreator.java | 158 -----
 .../segment/index/column/ColumnIndexContainer.java |   7 +
 .../index/column/PhysicalColumnIndexContainer.java |  15 +
 .../segment/index/datasource/BaseDataSource.java   |  13 +-
 .../index/datasource/ImmutableDataSource.java      |   5 +-
 .../index/datasource/MutableDataSource.java        |   5 +-
 .../segment/index/loader/IndexLoadingConfig.java   |  10 +
 .../segment/index/loader/SegmentPreProcessor.java  |   6 +
 .../loader/invertedindex/JSONIndexHandler.java     | 216 +++++++
 .../segment/index/readers/JSONIndexReader.java     | 160 +++++
 .../pinot/core/segment/store/ColumnIndexType.java  |   3 +-
 .../core/segment/store/FilePerIndexDirectory.java  |   5 +
 .../virtualcolumn/VirtualColumnIndexContainer.java |   6 +
 .../core/startree/v2/store/StarTreeDataSource.java |   3 +-
 .../pinot/spi/config/table/IndexingConfig.java     |   9 +
 .../java/org/apache/pinot/spi/data/FieldSpec.java  |   2 +-
 .../pinot/tools/admin/command/JSONQuickstart.java  | 224 +++++++
 57 files changed, 2167 insertions(+), 919 deletions(-)

diff --git a/pinot-common/src/main/antlr4/org/apache/pinot/pql/parsers/PQL2.g4 b/pinot-common/src/main/antlr4/org/apache/pinot/pql/parsers/PQL2.g4
index 7a2c816..e96e575 100644
--- a/pinot-common/src/main/antlr4/org/apache/pinot/pql/parsers/PQL2.g4
+++ b/pinot-common/src/main/antlr4/org/apache/pinot/pql/parsers/PQL2.g4
@@ -78,6 +78,7 @@ predicate:
   | isClause                              # IsPredicate
   | regexpLikeClause                      # RegexpLikePredicate
   | textMatchClause                       # TextMatchPredicate
+  | jsonMatchClause                       # JsonMatchPredicate
   ;
 
 inClause:
@@ -99,6 +100,9 @@ regexpLikeClause:
 textMatchClause:
   TEXT_MATCH '(' expression ',' literal ')';
 
+jsonMatchClause:
+  JSON_MATCH '(' expression ',' literal ')';
+
 booleanOperator: OR | AND;
 
 groupByClause: GROUP BY groupByList;
diff --git a/pinot-common/src/main/java/org/apache/pinot/common/request/AggregationInfo.java b/pinot-common/src/main/java/org/apache/pinot/common/request/AggregationInfo.java
index d3eb2f1..7aa8d93 100644
--- a/pinot-common/src/main/java/org/apache/pinot/common/request/AggregationInfo.java
+++ b/pinot-common/src/main/java/org/apache/pinot/common/request/AggregationInfo.java
@@ -17,7 +17,7 @@
  * under the License.
  */
 /**
- * Autogenerated by Thrift Compiler (0.12.0)
+ * Autogenerated by Thrift Compiler (0.13.0)
  *
  * DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING
  *  @generated
@@ -28,9 +28,9 @@ package org.apache.pinot.common.request;
 /**
  * AUTO GENERATED: DO NOT EDIT
  *  Aggregation
- *
+ * 
  */
-@javax.annotation.Generated(value = "Autogenerated by Thrift Compiler (0.12.0)", date = "2020-04-19")
+@javax.annotation.Generated(value = "Autogenerated by Thrift Compiler (0.13.0)", date = "2020-10-31")
 public class AggregationInfo implements org.apache.thrift.TBase<AggregationInfo, AggregationInfo._Fields>, java.io.Serializable, Cloneable, Comparable<AggregationInfo> {
   private static final org.apache.thrift.protocol.TStruct STRUCT_DESC = new org.apache.thrift.protocol.TStruct("AggregationInfo");
 
@@ -42,10 +42,10 @@ public class AggregationInfo implements org.apache.thrift.TBase<AggregationInfo,
   private static final org.apache.thrift.scheme.SchemeFactory STANDARD_SCHEME_FACTORY = new AggregationInfoStandardSchemeFactory();
   private static final org.apache.thrift.scheme.SchemeFactory TUPLE_SCHEME_FACTORY = new AggregationInfoTupleSchemeFactory();
 
-  public @org.apache.thrift.annotation.Nullable java.lang.String aggregationType; // optional
-  public @org.apache.thrift.annotation.Nullable java.util.Map<java.lang.String,java.lang.String> aggregationParams; // optional
-  public boolean isInSelectList; // optional
-  public @org.apache.thrift.annotation.Nullable java.util.List<java.lang.String> expressions; // optional
+  private @org.apache.thrift.annotation.Nullable java.lang.String aggregationType; // optional
+  private @org.apache.thrift.annotation.Nullable java.util.Map<java.lang.String,java.lang.String> aggregationParams; // optional
+  private boolean isInSelectList; // optional
+  private @org.apache.thrift.annotation.Nullable java.util.List<java.lang.String> expressions; // optional
 
   /** The set of fields this struct contains, along with convenience methods for finding and manipulating them. */
   public enum _Fields implements org.apache.thrift.TFieldIdEnum {
@@ -123,16 +123,16 @@ public class AggregationInfo implements org.apache.thrift.TBase<AggregationInfo,
   public static final java.util.Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> metaDataMap;
   static {
     java.util.Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> tmpMap = new java.util.EnumMap<_Fields, org.apache.thrift.meta_data.FieldMetaData>(_Fields.class);
-    tmpMap.put(_Fields.AGGREGATION_TYPE, new org.apache.thrift.meta_data.FieldMetaData("aggregationType", org.apache.thrift.TFieldRequirementType.OPTIONAL,
+    tmpMap.put(_Fields.AGGREGATION_TYPE, new org.apache.thrift.meta_data.FieldMetaData("aggregationType", org.apache.thrift.TFieldRequirementType.OPTIONAL, 
         new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.STRING)));
-    tmpMap.put(_Fields.AGGREGATION_PARAMS, new org.apache.thrift.meta_data.FieldMetaData("aggregationParams", org.apache.thrift.TFieldRequirementType.OPTIONAL,
-        new org.apache.thrift.meta_data.MapMetaData(org.apache.thrift.protocol.TType.MAP,
-            new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.STRING),
+    tmpMap.put(_Fields.AGGREGATION_PARAMS, new org.apache.thrift.meta_data.FieldMetaData("aggregationParams", org.apache.thrift.TFieldRequirementType.OPTIONAL, 
+        new org.apache.thrift.meta_data.MapMetaData(org.apache.thrift.protocol.TType.MAP, 
+            new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.STRING), 
             new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.STRING))));
-    tmpMap.put(_Fields.IS_IN_SELECT_LIST, new org.apache.thrift.meta_data.FieldMetaData("isInSelectList", org.apache.thrift.TFieldRequirementType.OPTIONAL,
+    tmpMap.put(_Fields.IS_IN_SELECT_LIST, new org.apache.thrift.meta_data.FieldMetaData("isInSelectList", org.apache.thrift.TFieldRequirementType.OPTIONAL, 
         new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.BOOL)));
-    tmpMap.put(_Fields.EXPRESSIONS, new org.apache.thrift.meta_data.FieldMetaData("expressions", org.apache.thrift.TFieldRequirementType.OPTIONAL,
-        new org.apache.thrift.meta_data.ListMetaData(org.apache.thrift.protocol.TType.LIST,
+    tmpMap.put(_Fields.EXPRESSIONS, new org.apache.thrift.meta_data.FieldMetaData("expressions", org.apache.thrift.TFieldRequirementType.OPTIONAL, 
+        new org.apache.thrift.meta_data.ListMetaData(org.apache.thrift.protocol.TType.LIST, 
             new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.STRING))));
     metaDataMap = java.util.Collections.unmodifiableMap(tmpMap);
     org.apache.thrift.meta_data.FieldMetaData.addStructMetaDataMap(AggregationInfo.class, metaDataMap);
@@ -178,9 +178,8 @@ public class AggregationInfo implements org.apache.thrift.TBase<AggregationInfo,
     return this.aggregationType;
   }
 
-  public AggregationInfo setAggregationType(@org.apache.thrift.annotation.Nullable java.lang.String aggregationType) {
+  public void setAggregationType(@org.apache.thrift.annotation.Nullable java.lang.String aggregationType) {
     this.aggregationType = aggregationType;
-    return this;
   }
 
   public void unsetAggregationType() {
@@ -214,9 +213,8 @@ public class AggregationInfo implements org.apache.thrift.TBase<AggregationInfo,
     return this.aggregationParams;
   }
 
-  public AggregationInfo setAggregationParams(@org.apache.thrift.annotation.Nullable java.util.Map<java.lang.String,java.lang.String> aggregationParams) {
+  public void setAggregationParams(@org.apache.thrift.annotation.Nullable java.util.Map<java.lang.String,java.lang.String> aggregationParams) {
     this.aggregationParams = aggregationParams;
-    return this;
   }
 
   public void unsetAggregationParams() {
@@ -238,10 +236,9 @@ public class AggregationInfo implements org.apache.thrift.TBase<AggregationInfo,
     return this.isInSelectList;
   }
 
-  public AggregationInfo setIsInSelectList(boolean isInSelectList) {
+  public void setIsInSelectList(boolean isInSelectList) {
     this.isInSelectList = isInSelectList;
     setIsInSelectListIsSet(true);
-    return this;
   }
 
   public void unsetIsInSelectList() {
@@ -278,9 +275,8 @@ public class AggregationInfo implements org.apache.thrift.TBase<AggregationInfo,
     return this.expressions;
   }
 
-  public AggregationInfo setExpressions(@org.apache.thrift.annotation.Nullable java.util.List<java.lang.String> expressions) {
+  public void setExpressions(@org.apache.thrift.annotation.Nullable java.util.List<java.lang.String> expressions) {
     this.expressions = expressions;
-    return this;
   }
 
   public void unsetExpressions() {
@@ -595,7 +591,7 @@ public class AggregationInfo implements org.apache.thrift.TBase<AggregationInfo,
       while (true)
       {
         schemeField = iprot.readFieldBegin();
-        if (schemeField.type == org.apache.thrift.protocol.TType.STOP) {
+        if (schemeField.type == org.apache.thrift.protocol.TType.STOP) { 
           break;
         }
         switch (schemeField.id) {
@@ -603,7 +599,7 @@ public class AggregationInfo implements org.apache.thrift.TBase<AggregationInfo,
             if (schemeField.type == org.apache.thrift.protocol.TType.STRING) {
               struct.aggregationType = iprot.readString();
               struct.setAggregationTypeIsSet(true);
-            } else {
+            } else { 
               org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
             }
             break;
@@ -623,7 +619,7 @@ public class AggregationInfo implements org.apache.thrift.TBase<AggregationInfo,
                 iprot.readMapEnd();
               }
               struct.setAggregationParamsIsSet(true);
-            } else {
+            } else { 
               org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
             }
             break;
@@ -631,7 +627,7 @@ public class AggregationInfo implements org.apache.thrift.TBase<AggregationInfo,
             if (schemeField.type == org.apache.thrift.protocol.TType.BOOL) {
               struct.isInSelectList = iprot.readBool();
               struct.setIsInSelectListIsSet(true);
-            } else {
+            } else { 
               org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
             }
             break;
@@ -649,7 +645,7 @@ public class AggregationInfo implements org.apache.thrift.TBase<AggregationInfo,
                 iprot.readListEnd();
               }
               struct.setExpressionsIsSet(true);
-            } else {
+            } else { 
               org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
             }
             break;
@@ -659,8 +655,6 @@ public class AggregationInfo implements org.apache.thrift.TBase<AggregationInfo,
         iprot.readFieldEnd();
       }
       iprot.readStructEnd();
-
-      // check for required fields of primitive type, which can't be checked in the validate method
       struct.validate();
     }
 
diff --git a/pinot-common/src/main/java/org/apache/pinot/common/request/BrokerRequest.java b/pinot-common/src/main/java/org/apache/pinot/common/request/BrokerRequest.java
index f3ff93a..a902118 100644
--- a/pinot-common/src/main/java/org/apache/pinot/common/request/BrokerRequest.java
+++ b/pinot-common/src/main/java/org/apache/pinot/common/request/BrokerRequest.java
@@ -17,7 +17,7 @@
  * under the License.
  */
 /**
- * Autogenerated by Thrift Compiler (0.12.0)
+ * Autogenerated by Thrift Compiler (0.13.0)
  *
  * DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING
  *  @generated
@@ -28,9 +28,9 @@ package org.apache.pinot.common.request;
 /**
  * AUTO GENERATED: DO NOT EDIT
  * Broker Query
- *
+ * 
  */
-@javax.annotation.Generated(value = "Autogenerated by Thrift Compiler (0.12.0)", date = "2019-08-16")
+@javax.annotation.Generated(value = "Autogenerated by Thrift Compiler (0.13.0)", date = "2020-10-31")
 public class BrokerRequest implements org.apache.thrift.TBase<BrokerRequest, BrokerRequest._Fields>, java.io.Serializable, Cloneable, Comparable<BrokerRequest> {
   private static final org.apache.thrift.protocol.TStruct STRUCT_DESC = new org.apache.thrift.protocol.TStruct("BrokerRequest");
 
@@ -57,25 +57,25 @@ public class BrokerRequest implements org.apache.thrift.TBase<BrokerRequest, Bro
   private static final org.apache.thrift.scheme.SchemeFactory STANDARD_SCHEME_FACTORY = new BrokerRequestStandardSchemeFactory();
   private static final org.apache.thrift.scheme.SchemeFactory TUPLE_SCHEME_FACTORY = new BrokerRequestTupleSchemeFactory();
 
-  public @org.apache.thrift.annotation.Nullable QueryType queryType; // optional
-  public @org.apache.thrift.annotation.Nullable QuerySource querySource; // optional
-  public @org.apache.thrift.annotation.Nullable java.lang.String timeInterval; // optional
-  public @org.apache.thrift.annotation.Nullable java.lang.String duration; // optional
-  public @org.apache.thrift.annotation.Nullable FilterQuery filterQuery; // optional
-  public @org.apache.thrift.annotation.Nullable java.util.List<AggregationInfo> aggregationsInfo; // optional
-  public @org.apache.thrift.annotation.Nullable GroupBy groupBy; // optional
-  public @org.apache.thrift.annotation.Nullable Selection selections; // optional
-  public @org.apache.thrift.annotation.Nullable FilterQueryMap filterSubQueryMap; // optional
-  public @org.apache.thrift.annotation.Nullable java.lang.String bucketHashKey; // optional
-  public boolean enableTrace; // optional
-  public @org.apache.thrift.annotation.Nullable java.lang.String responseFormat; // optional
-  public @org.apache.thrift.annotation.Nullable java.util.Map<java.lang.String,java.lang.String> debugOptions; // optional
-  public @org.apache.thrift.annotation.Nullable java.util.Map<java.lang.String,java.lang.String> queryOptions; // optional
-  public @org.apache.thrift.annotation.Nullable HavingFilterQuery havingFilterQuery; // optional
-  public @org.apache.thrift.annotation.Nullable HavingFilterQueryMap havingFilterSubQueryMap; // optional
-  public @org.apache.thrift.annotation.Nullable org.apache.pinot.common.request.PinotQuery pinotQuery; // optional
-  public @org.apache.thrift.annotation.Nullable java.util.List<SelectionSort> orderBy; // optional
-  public int limit; // optional
+  private @org.apache.thrift.annotation.Nullable QueryType queryType; // optional
+  private @org.apache.thrift.annotation.Nullable QuerySource querySource; // optional
+  private @org.apache.thrift.annotation.Nullable java.lang.String timeInterval; // optional
+  private @org.apache.thrift.annotation.Nullable java.lang.String duration; // optional
+  private @org.apache.thrift.annotation.Nullable FilterQuery filterQuery; // optional
+  private @org.apache.thrift.annotation.Nullable java.util.List<AggregationInfo> aggregationsInfo; // optional
+  private @org.apache.thrift.annotation.Nullable GroupBy groupBy; // optional
+  private @org.apache.thrift.annotation.Nullable Selection selections; // optional
+  private @org.apache.thrift.annotation.Nullable FilterQueryMap filterSubQueryMap; // optional
+  private @org.apache.thrift.annotation.Nullable java.lang.String bucketHashKey; // optional
+  private boolean enableTrace; // optional
+  private @org.apache.thrift.annotation.Nullable java.lang.String responseFormat; // optional
+  private @org.apache.thrift.annotation.Nullable java.util.Map<java.lang.String,java.lang.String> debugOptions; // optional
+  private @org.apache.thrift.annotation.Nullable java.util.Map<java.lang.String,java.lang.String> queryOptions; // optional
+  private @org.apache.thrift.annotation.Nullable HavingFilterQuery havingFilterQuery; // optional
+  private @org.apache.thrift.annotation.Nullable HavingFilterQueryMap havingFilterSubQueryMap; // optional
+  private @org.apache.thrift.annotation.Nullable org.apache.pinot.common.request.PinotQuery pinotQuery; // optional
+  private @org.apache.thrift.annotation.Nullable java.util.List<SelectionSort> orderBy; // optional
+  private int limit; // optional
 
   /** The set of fields this struct contains, along with convenience methods for finding and manipulating them. */
   public enum _Fields implements org.apache.thrift.TFieldIdEnum {
@@ -199,49 +199,49 @@ public class BrokerRequest implements org.apache.thrift.TBase<BrokerRequest, Bro
   public static final java.util.Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> metaDataMap;
   static {
     java.util.Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> tmpMap = new java.util.EnumMap<_Fields, org.apache.thrift.meta_data.FieldMetaData>(_Fields.class);
-    tmpMap.put(_Fields.QUERY_TYPE, new org.apache.thrift.meta_data.FieldMetaData("queryType", org.apache.thrift.TFieldRequirementType.OPTIONAL,
+    tmpMap.put(_Fields.QUERY_TYPE, new org.apache.thrift.meta_data.FieldMetaData("queryType", org.apache.thrift.TFieldRequirementType.OPTIONAL, 
         new org.apache.thrift.meta_data.StructMetaData(org.apache.thrift.protocol.TType.STRUCT, QueryType.class)));
-    tmpMap.put(_Fields.QUERY_SOURCE, new org.apache.thrift.meta_data.FieldMetaData("querySource", org.apache.thrift.TFieldRequirementType.OPTIONAL,
+    tmpMap.put(_Fields.QUERY_SOURCE, new org.apache.thrift.meta_data.FieldMetaData("querySource", org.apache.thrift.TFieldRequirementType.OPTIONAL, 
         new org.apache.thrift.meta_data.StructMetaData(org.apache.thrift.protocol.TType.STRUCT, QuerySource.class)));
-    tmpMap.put(_Fields.TIME_INTERVAL, new org.apache.thrift.meta_data.FieldMetaData("timeInterval", org.apache.thrift.TFieldRequirementType.OPTIONAL,
+    tmpMap.put(_Fields.TIME_INTERVAL, new org.apache.thrift.meta_data.FieldMetaData("timeInterval", org.apache.thrift.TFieldRequirementType.OPTIONAL, 
         new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.STRING)));
-    tmpMap.put(_Fields.DURATION, new org.apache.thrift.meta_data.FieldMetaData("duration", org.apache.thrift.TFieldRequirementType.OPTIONAL,
+    tmpMap.put(_Fields.DURATION, new org.apache.thrift.meta_data.FieldMetaData("duration", org.apache.thrift.TFieldRequirementType.OPTIONAL, 
         new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.STRING)));
-    tmpMap.put(_Fields.FILTER_QUERY, new org.apache.thrift.meta_data.FieldMetaData("filterQuery", org.apache.thrift.TFieldRequirementType.OPTIONAL,
+    tmpMap.put(_Fields.FILTER_QUERY, new org.apache.thrift.meta_data.FieldMetaData("filterQuery", org.apache.thrift.TFieldRequirementType.OPTIONAL, 
         new org.apache.thrift.meta_data.StructMetaData(org.apache.thrift.protocol.TType.STRUCT, FilterQuery.class)));
-    tmpMap.put(_Fields.AGGREGATIONS_INFO, new org.apache.thrift.meta_data.FieldMetaData("aggregationsInfo", org.apache.thrift.TFieldRequirementType.OPTIONAL,
-        new org.apache.thrift.meta_data.ListMetaData(org.apache.thrift.protocol.TType.LIST,
+    tmpMap.put(_Fields.AGGREGATIONS_INFO, new org.apache.thrift.meta_data.FieldMetaData("aggregationsInfo", org.apache.thrift.TFieldRequirementType.OPTIONAL, 
+        new org.apache.thrift.meta_data.ListMetaData(org.apache.thrift.protocol.TType.LIST, 
             new org.apache.thrift.meta_data.StructMetaData(org.apache.thrift.protocol.TType.STRUCT, AggregationInfo.class))));
-    tmpMap.put(_Fields.GROUP_BY, new org.apache.thrift.meta_data.FieldMetaData("groupBy", org.apache.thrift.TFieldRequirementType.OPTIONAL,
+    tmpMap.put(_Fields.GROUP_BY, new org.apache.thrift.meta_data.FieldMetaData("groupBy", org.apache.thrift.TFieldRequirementType.OPTIONAL, 
         new org.apache.thrift.meta_data.StructMetaData(org.apache.thrift.protocol.TType.STRUCT, GroupBy.class)));
-    tmpMap.put(_Fields.SELECTIONS, new org.apache.thrift.meta_data.FieldMetaData("selections", org.apache.thrift.TFieldRequirementType.OPTIONAL,
+    tmpMap.put(_Fields.SELECTIONS, new org.apache.thrift.meta_data.FieldMetaData("selections", org.apache.thrift.TFieldRequirementType.OPTIONAL, 
         new org.apache.thrift.meta_data.StructMetaData(org.apache.thrift.protocol.TType.STRUCT, Selection.class)));
-    tmpMap.put(_Fields.FILTER_SUB_QUERY_MAP, new org.apache.thrift.meta_data.FieldMetaData("filterSubQueryMap", org.apache.thrift.TFieldRequirementType.OPTIONAL,
+    tmpMap.put(_Fields.FILTER_SUB_QUERY_MAP, new org.apache.thrift.meta_data.FieldMetaData("filterSubQueryMap", org.apache.thrift.TFieldRequirementType.OPTIONAL, 
         new org.apache.thrift.meta_data.StructMetaData(org.apache.thrift.protocol.TType.STRUCT, FilterQueryMap.class)));
-    tmpMap.put(_Fields.BUCKET_HASH_KEY, new org.apache.thrift.meta_data.FieldMetaData("bucketHashKey", org.apache.thrift.TFieldRequirementType.OPTIONAL,
+    tmpMap.put(_Fields.BUCKET_HASH_KEY, new org.apache.thrift.meta_data.FieldMetaData("bucketHashKey", org.apache.thrift.TFieldRequirementType.OPTIONAL, 
         new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.STRING)));
-    tmpMap.put(_Fields.ENABLE_TRACE, new org.apache.thrift.meta_data.FieldMetaData("enableTrace", org.apache.thrift.TFieldRequirementType.OPTIONAL,
+    tmpMap.put(_Fields.ENABLE_TRACE, new org.apache.thrift.meta_data.FieldMetaData("enableTrace", org.apache.thrift.TFieldRequirementType.OPTIONAL, 
         new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.BOOL)));
-    tmpMap.put(_Fields.RESPONSE_FORMAT, new org.apache.thrift.meta_data.FieldMetaData("responseFormat", org.apache.thrift.TFieldRequirementType.OPTIONAL,
+    tmpMap.put(_Fields.RESPONSE_FORMAT, new org.apache.thrift.meta_data.FieldMetaData("responseFormat", org.apache.thrift.TFieldRequirementType.OPTIONAL, 
         new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.STRING)));
-    tmpMap.put(_Fields.DEBUG_OPTIONS, new org.apache.thrift.meta_data.FieldMetaData("debugOptions", org.apache.thrift.TFieldRequirementType.OPTIONAL,
-        new org.apache.thrift.meta_data.MapMetaData(org.apache.thrift.protocol.TType.MAP,
-            new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.STRING),
+    tmpMap.put(_Fields.DEBUG_OPTIONS, new org.apache.thrift.meta_data.FieldMetaData("debugOptions", org.apache.thrift.TFieldRequirementType.OPTIONAL, 
+        new org.apache.thrift.meta_data.MapMetaData(org.apache.thrift.protocol.TType.MAP, 
+            new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.STRING), 
             new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.STRING))));
-    tmpMap.put(_Fields.QUERY_OPTIONS, new org.apache.thrift.meta_data.FieldMetaData("queryOptions", org.apache.thrift.TFieldRequirementType.OPTIONAL,
-        new org.apache.thrift.meta_data.MapMetaData(org.apache.thrift.protocol.TType.MAP,
-            new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.STRING),
+    tmpMap.put(_Fields.QUERY_OPTIONS, new org.apache.thrift.meta_data.FieldMetaData("queryOptions", org.apache.thrift.TFieldRequirementType.OPTIONAL, 
+        new org.apache.thrift.meta_data.MapMetaData(org.apache.thrift.protocol.TType.MAP, 
+            new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.STRING), 
             new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.STRING))));
-    tmpMap.put(_Fields.HAVING_FILTER_QUERY, new org.apache.thrift.meta_data.FieldMetaData("havingFilterQuery", org.apache.thrift.TFieldRequirementType.OPTIONAL,
+    tmpMap.put(_Fields.HAVING_FILTER_QUERY, new org.apache.thrift.meta_data.FieldMetaData("havingFilterQuery", org.apache.thrift.TFieldRequirementType.OPTIONAL, 
         new org.apache.thrift.meta_data.StructMetaData(org.apache.thrift.protocol.TType.STRUCT, HavingFilterQuery.class)));
-    tmpMap.put(_Fields.HAVING_FILTER_SUB_QUERY_MAP, new org.apache.thrift.meta_data.FieldMetaData("havingFilterSubQueryMap", org.apache.thrift.TFieldRequirementType.OPTIONAL,
+    tmpMap.put(_Fields.HAVING_FILTER_SUB_QUERY_MAP, new org.apache.thrift.meta_data.FieldMetaData("havingFilterSubQueryMap", org.apache.thrift.TFieldRequirementType.OPTIONAL, 
         new org.apache.thrift.meta_data.StructMetaData(org.apache.thrift.protocol.TType.STRUCT, HavingFilterQueryMap.class)));
-    tmpMap.put(_Fields.PINOT_QUERY, new org.apache.thrift.meta_data.FieldMetaData("pinotQuery", org.apache.thrift.TFieldRequirementType.OPTIONAL,
+    tmpMap.put(_Fields.PINOT_QUERY, new org.apache.thrift.meta_data.FieldMetaData("pinotQuery", org.apache.thrift.TFieldRequirementType.OPTIONAL, 
         new org.apache.thrift.meta_data.StructMetaData(org.apache.thrift.protocol.TType.STRUCT, org.apache.pinot.common.request.PinotQuery.class)));
-    tmpMap.put(_Fields.ORDER_BY, new org.apache.thrift.meta_data.FieldMetaData("orderBy", org.apache.thrift.TFieldRequirementType.OPTIONAL,
-        new org.apache.thrift.meta_data.ListMetaData(org.apache.thrift.protocol.TType.LIST,
+    tmpMap.put(_Fields.ORDER_BY, new org.apache.thrift.meta_data.FieldMetaData("orderBy", org.apache.thrift.TFieldRequirementType.OPTIONAL, 
+        new org.apache.thrift.meta_data.ListMetaData(org.apache.thrift.protocol.TType.LIST, 
             new org.apache.thrift.meta_data.StructMetaData(org.apache.thrift.protocol.TType.STRUCT, SelectionSort.class))));
-    tmpMap.put(_Fields.LIMIT, new org.apache.thrift.meta_data.FieldMetaData("limit", org.apache.thrift.TFieldRequirementType.OPTIONAL,
+    tmpMap.put(_Fields.LIMIT, new org.apache.thrift.meta_data.FieldMetaData("limit", org.apache.thrift.TFieldRequirementType.OPTIONAL, 
         new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.I32)));
     metaDataMap = java.util.Collections.unmodifiableMap(tmpMap);
     org.apache.thrift.meta_data.FieldMetaData.addStructMetaDataMap(BrokerRequest.class, metaDataMap);
@@ -356,9 +356,8 @@ public class BrokerRequest implements org.apache.thrift.TBase<BrokerRequest, Bro
     return this.queryType;
   }
 
-  public BrokerRequest setQueryType(@org.apache.thrift.annotation.Nullable QueryType queryType) {
+  public void setQueryType(@org.apache.thrift.annotation.Nullable QueryType queryType) {
     this.queryType = queryType;
-    return this;
   }
 
   public void unsetQueryType() {
@@ -381,9 +380,8 @@ public class BrokerRequest implements org.apache.thrift.TBase<BrokerRequest, Bro
     return this.querySource;
   }
 
-  public BrokerRequest setQuerySource(@org.apache.thrift.annotation.Nullable QuerySource querySource) {
+  public void setQuerySource(@org.apache.thrift.annotation.Nullable QuerySource querySource) {
     this.querySource = querySource;
-    return this;
   }
 
   public void unsetQuerySource() {
@@ -406,9 +404,8 @@ public class BrokerRequest implements org.apache.thrift.TBase<BrokerRequest, Bro
     return this.timeInterval;
   }
 
-  public BrokerRequest setTimeInterval(@org.apache.thrift.annotation.Nullable java.lang.String timeInterval) {
+  public void setTimeInterval(@org.apache.thrift.annotation.Nullable java.lang.String timeInterval) {
     this.timeInterval = timeInterval;
-    return this;
   }
 
   public void unsetTimeInterval() {
@@ -431,9 +428,8 @@ public class BrokerRequest implements org.apache.thrift.TBase<BrokerRequest, Bro
     return this.duration;
   }
 
-  public BrokerRequest setDuration(@org.apache.thrift.annotation.Nullable java.lang.String duration) {
+  public void setDuration(@org.apache.thrift.annotation.Nullable java.lang.String duration) {
     this.duration = duration;
-    return this;
   }
 
   public void unsetDuration() {
@@ -456,9 +452,8 @@ public class BrokerRequest implements org.apache.thrift.TBase<BrokerRequest, Bro
     return this.filterQuery;
   }
 
-  public BrokerRequest setFilterQuery(@org.apache.thrift.annotation.Nullable FilterQuery filterQuery) {
+  public void setFilterQuery(@org.apache.thrift.annotation.Nullable FilterQuery filterQuery) {
     this.filterQuery = filterQuery;
-    return this;
   }
 
   public void unsetFilterQuery() {
@@ -497,9 +492,8 @@ public class BrokerRequest implements org.apache.thrift.TBase<BrokerRequest, Bro
     return this.aggregationsInfo;
   }
 
-  public BrokerRequest setAggregationsInfo(@org.apache.thrift.annotation.Nullable java.util.List<AggregationInfo> aggregationsInfo) {
+  public void setAggregationsInfo(@org.apache.thrift.annotation.Nullable java.util.List<AggregationInfo> aggregationsInfo) {
     this.aggregationsInfo = aggregationsInfo;
-    return this;
   }
 
   public void unsetAggregationsInfo() {
@@ -522,9 +516,8 @@ public class BrokerRequest implements org.apache.thrift.TBase<BrokerRequest, Bro
     return this.groupBy;
   }
 
-  public BrokerRequest setGroupBy(@org.apache.thrift.annotation.Nullable GroupBy groupBy) {
+  public void setGroupBy(@org.apache.thrift.annotation.Nullable GroupBy groupBy) {
     this.groupBy = groupBy;
-    return this;
   }
 
   public void unsetGroupBy() {
@@ -547,9 +540,8 @@ public class BrokerRequest implements org.apache.thrift.TBase<BrokerRequest, Bro
     return this.selections;
   }
 
-  public BrokerRequest setSelections(@org.apache.thrift.annotation.Nullable Selection selections) {
+  public void setSelections(@org.apache.thrift.annotation.Nullable Selection selections) {
     this.selections = selections;
-    return this;
   }
 
   public void unsetSelections() {
@@ -572,9 +564,8 @@ public class BrokerRequest implements org.apache.thrift.TBase<BrokerRequest, Bro
     return this.filterSubQueryMap;
   }
 
-  public BrokerRequest setFilterSubQueryMap(@org.apache.thrift.annotation.Nullable FilterQueryMap filterSubQueryMap) {
+  public void setFilterSubQueryMap(@org.apache.thrift.annotation.Nullable FilterQueryMap filterSubQueryMap) {
     this.filterSubQueryMap = filterSubQueryMap;
-    return this;
   }
 
   public void unsetFilterSubQueryMap() {
@@ -597,9 +588,8 @@ public class BrokerRequest implements org.apache.thrift.TBase<BrokerRequest, Bro
     return this.bucketHashKey;
   }
 
-  public BrokerRequest setBucketHashKey(@org.apache.thrift.annotation.Nullable java.lang.String bucketHashKey) {
+  public void setBucketHashKey(@org.apache.thrift.annotation.Nullable java.lang.String bucketHashKey) {
     this.bucketHashKey = bucketHashKey;
-    return this;
   }
 
   public void unsetBucketHashKey() {
@@ -621,10 +611,9 @@ public class BrokerRequest implements org.apache.thrift.TBase<BrokerRequest, Bro
     return this.enableTrace;
   }
 
-  public BrokerRequest setEnableTrace(boolean enableTrace) {
+  public void setEnableTrace(boolean enableTrace) {
     this.enableTrace = enableTrace;
     setEnableTraceIsSet(true);
-    return this;
   }
 
   public void unsetEnableTrace() {
@@ -645,9 +634,8 @@ public class BrokerRequest implements org.apache.thrift.TBase<BrokerRequest, Bro
     return this.responseFormat;
   }
 
-  public BrokerRequest setResponseFormat(@org.apache.thrift.annotation.Nullable java.lang.String responseFormat) {
+  public void setResponseFormat(@org.apache.thrift.annotation.Nullable java.lang.String responseFormat) {
     this.responseFormat = responseFormat;
-    return this;
   }
 
   public void unsetResponseFormat() {
@@ -681,9 +669,8 @@ public class BrokerRequest implements org.apache.thrift.TBase<BrokerRequest, Bro
     return this.debugOptions;
   }
 
-  public BrokerRequest setDebugOptions(@org.apache.thrift.annotation.Nullable java.util.Map<java.lang.String,java.lang.String> debugOptions) {
+  public void setDebugOptions(@org.apache.thrift.annotation.Nullable java.util.Map<java.lang.String,java.lang.String> debugOptions) {
     this.debugOptions = debugOptions;
-    return this;
   }
 
   public void unsetDebugOptions() {
@@ -717,9 +704,8 @@ public class BrokerRequest implements org.apache.thrift.TBase<BrokerRequest, Bro
     return this.queryOptions;
   }
 
-  public BrokerRequest setQueryOptions(@org.apache.thrift.annotation.Nullable java.util.Map<java.lang.String,java.lang.String> queryOptions) {
+  public void setQueryOptions(@org.apache.thrift.annotation.Nullable java.util.Map<java.lang.String,java.lang.String> queryOptions) {
     this.queryOptions = queryOptions;
-    return this;
   }
 
   public void unsetQueryOptions() {
@@ -742,9 +728,8 @@ public class BrokerRequest implements org.apache.thrift.TBase<BrokerRequest, Bro
     return this.havingFilterQuery;
   }
 
-  public BrokerRequest setHavingFilterQuery(@org.apache.thrift.annotation.Nullable HavingFilterQuery havingFilterQuery) {
+  public void setHavingFilterQuery(@org.apache.thrift.annotation.Nullable HavingFilterQuery havingFilterQuery) {
     this.havingFilterQuery = havingFilterQuery;
-    return this;
   }
 
   public void unsetHavingFilterQuery() {
@@ -767,9 +752,8 @@ public class BrokerRequest implements org.apache.thrift.TBase<BrokerRequest, Bro
     return this.havingFilterSubQueryMap;
   }
 
-  public BrokerRequest setHavingFilterSubQueryMap(@org.apache.thrift.annotation.Nullable HavingFilterQueryMap havingFilterSubQueryMap) {
+  public void setHavingFilterSubQueryMap(@org.apache.thrift.annotation.Nullable HavingFilterQueryMap havingFilterSubQueryMap) {
     this.havingFilterSubQueryMap = havingFilterSubQueryMap;
-    return this;
   }
 
   public void unsetHavingFilterSubQueryMap() {
@@ -792,9 +776,8 @@ public class BrokerRequest implements org.apache.thrift.TBase<BrokerRequest, Bro
     return this.pinotQuery;
   }
 
-  public BrokerRequest setPinotQuery(@org.apache.thrift.annotation.Nullable org.apache.pinot.common.request.PinotQuery pinotQuery) {
+  public void setPinotQuery(@org.apache.thrift.annotation.Nullable org.apache.pinot.common.request.PinotQuery pinotQuery) {
     this.pinotQuery = pinotQuery;
-    return this;
   }
 
   public void unsetPinotQuery() {
@@ -833,9 +816,8 @@ public class BrokerRequest implements org.apache.thrift.TBase<BrokerRequest, Bro
     return this.orderBy;
   }
 
-  public BrokerRequest setOrderBy(@org.apache.thrift.annotation.Nullable java.util.List<SelectionSort> orderBy) {
+  public void setOrderBy(@org.apache.thrift.annotation.Nullable java.util.List<SelectionSort> orderBy) {
     this.orderBy = orderBy;
-    return this;
   }
 
   public void unsetOrderBy() {
@@ -857,10 +839,9 @@ public class BrokerRequest implements org.apache.thrift.TBase<BrokerRequest, Bro
     return this.limit;
   }
 
-  public BrokerRequest setLimit(int limit) {
+  public void setLimit(int limit) {
     this.limit = limit;
     setLimitIsSet(true);
-    return this;
   }
 
   public void unsetLimit() {
@@ -1886,7 +1867,7 @@ public class BrokerRequest implements org.apache.thrift.TBase<BrokerRequest, Bro
       while (true)
       {
         schemeField = iprot.readFieldBegin();
-        if (schemeField.type == org.apache.thrift.protocol.TType.STOP) {
+        if (schemeField.type == org.apache.thrift.protocol.TType.STOP) { 
           break;
         }
         switch (schemeField.id) {
@@ -1895,7 +1876,7 @@ public class BrokerRequest implements org.apache.thrift.TBase<BrokerRequest, Bro
               struct.queryType = new QueryType();
               struct.queryType.read(iprot);
               struct.setQueryTypeIsSet(true);
-            } else {
+            } else { 
               org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
             }
             break;
@@ -1904,7 +1885,7 @@ public class BrokerRequest implements org.apache.thrift.TBase<BrokerRequest, Bro
               struct.querySource = new QuerySource();
               struct.querySource.read(iprot);
               struct.setQuerySourceIsSet(true);
-            } else {
+            } else { 
               org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
             }
             break;
@@ -1912,7 +1893,7 @@ public class BrokerRequest implements org.apache.thrift.TBase<BrokerRequest, Bro
             if (schemeField.type == org.apache.thrift.protocol.TType.STRING) {
               struct.timeInterval = iprot.readString();
               struct.setTimeIntervalIsSet(true);
-            } else {
+            } else { 
               org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
             }
             break;
@@ -1920,7 +1901,7 @@ public class BrokerRequest implements org.apache.thrift.TBase<BrokerRequest, Bro
             if (schemeField.type == org.apache.thrift.protocol.TType.STRING) {
               struct.duration = iprot.readString();
               struct.setDurationIsSet(true);
-            } else {
+            } else { 
               org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
             }
             break;
@@ -1929,26 +1910,26 @@ public class BrokerRequest implements org.apache.thrift.TBase<BrokerRequest, Bro
               struct.filterQuery = new FilterQuery();
               struct.filterQuery.read(iprot);
               struct.setFilterQueryIsSet(true);
-            } else {
+            } else { 
               org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
             }
             break;
           case 6: // AGGREGATIONS_INFO
             if (schemeField.type == org.apache.thrift.protocol.TType.LIST) {
               {
-                org.apache.thrift.protocol.TList _list94 = iprot.readListBegin();
-                struct.aggregationsInfo = new java.util.ArrayList<AggregationInfo>(_list94.size);
-                @org.apache.thrift.annotation.Nullable AggregationInfo _elem95;
-                for (int _i96 = 0; _i96 < _list94.size; ++_i96)
+                org.apache.thrift.protocol.TList _list102 = iprot.readListBegin();
+                struct.aggregationsInfo = new java.util.ArrayList<AggregationInfo>(_list102.size);
+                @org.apache.thrift.annotation.Nullable AggregationInfo _elem103;
+                for (int _i104 = 0; _i104 < _list102.size; ++_i104)
                 {
-                  _elem95 = new AggregationInfo();
-                  _elem95.read(iprot);
-                  struct.aggregationsInfo.add(_elem95);
+                  _elem103 = new AggregationInfo();
+                  _elem103.read(iprot);
+                  struct.aggregationsInfo.add(_elem103);
                 }
                 iprot.readListEnd();
               }
               struct.setAggregationsInfoIsSet(true);
-            } else {
+            } else { 
               org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
             }
             break;
@@ -1957,7 +1938,7 @@ public class BrokerRequest implements org.apache.thrift.TBase<BrokerRequest, Bro
               struct.groupBy = new GroupBy();
               struct.groupBy.read(iprot);
               struct.setGroupByIsSet(true);
-            } else {
+            } else { 
               org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
             }
             break;
@@ -1966,7 +1947,7 @@ public class BrokerRequest implements org.apache.thrift.TBase<BrokerRequest, Bro
               struct.selections = new Selection();
               struct.selections.read(iprot);
               struct.setSelectionsIsSet(true);
-            } else {
+            } else { 
               org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
             }
             break;
@@ -1975,7 +1956,7 @@ public class BrokerRequest implements org.apache.thrift.TBase<BrokerRequest, Bro
               struct.filterSubQueryMap = new FilterQueryMap();
               struct.filterSubQueryMap.read(iprot);
               struct.setFilterSubQueryMapIsSet(true);
-            } else {
+            } else { 
               org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
             }
             break;
@@ -1983,7 +1964,7 @@ public class BrokerRequest implements org.apache.thrift.TBase<BrokerRequest, Bro
             if (schemeField.type == org.apache.thrift.protocol.TType.STRING) {
               struct.bucketHashKey = iprot.readString();
               struct.setBucketHashKeyIsSet(true);
-            } else {
+            } else { 
               org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
             }
             break;
@@ -1991,7 +1972,7 @@ public class BrokerRequest implements org.apache.thrift.TBase<BrokerRequest, Bro
             if (schemeField.type == org.apache.thrift.protocol.TType.BOOL) {
               struct.enableTrace = iprot.readBool();
               struct.setEnableTraceIsSet(true);
-            } else {
+            } else { 
               org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
             }
             break;
@@ -1999,47 +1980,47 @@ public class BrokerRequest implements org.apache.thrift.TBase<BrokerRequest, Bro
             if (schemeField.type == org.apache.thrift.protocol.TType.STRING) {
               struct.responseFormat = iprot.readString();
               struct.setResponseFormatIsSet(true);
-            } else {
+            } else { 
               org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
             }
             break;
           case 13: // DEBUG_OPTIONS
             if (schemeField.type == org.apache.thrift.protocol.TType.MAP) {
               {
-                org.apache.thrift.protocol.TMap _map97 = iprot.readMapBegin();
-                struct.debugOptions = new java.util.HashMap<java.lang.String,java.lang.String>(2*_map97.size);
-                @org.apache.thrift.annotation.Nullable java.lang.String _key98;
-                @org.apache.thrift.annotation.Nullable java.lang.String _val99;
-                for (int _i100 = 0; _i100 < _map97.size; ++_i100)
+                org.apache.thrift.protocol.TMap _map105 = iprot.readMapBegin();
+                struct.debugOptions = new java.util.HashMap<java.lang.String,java.lang.String>(2*_map105.size);
+                @org.apache.thrift.annotation.Nullable java.lang.String _key106;
+                @org.apache.thrift.annotation.Nullable java.lang.String _val107;
+                for (int _i108 = 0; _i108 < _map105.size; ++_i108)
                 {
-                  _key98 = iprot.readString();
-                  _val99 = iprot.readString();
-                  struct.debugOptions.put(_key98, _val99);
+                  _key106 = iprot.readString();
+                  _val107 = iprot.readString();
+                  struct.debugOptions.put(_key106, _val107);
                 }
                 iprot.readMapEnd();
               }
               struct.setDebugOptionsIsSet(true);
-            } else {
+            } else { 
               org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
             }
             break;
           case 14: // QUERY_OPTIONS
             if (schemeField.type == org.apache.thrift.protocol.TType.MAP) {
               {
-                org.apache.thrift.protocol.TMap _map101 = iprot.readMapBegin();
-                struct.queryOptions = new java.util.HashMap<java.lang.String,java.lang.String>(2*_map101.size);
-                @org.apache.thrift.annotation.Nullable java.lang.String _key102;
-                @org.apache.thrift.annotation.Nullable java.lang.String _val103;
-                for (int _i104 = 0; _i104 < _map101.size; ++_i104)
+                org.apache.thrift.protocol.TMap _map109 = iprot.readMapBegin();
+                struct.queryOptions = new java.util.HashMap<java.lang.String,java.lang.String>(2*_map109.size);
+                @org.apache.thrift.annotation.Nullable java.lang.String _key110;
+                @org.apache.thrift.annotation.Nullable java.lang.String _val111;
+                for (int _i112 = 0; _i112 < _map109.size; ++_i112)
                 {
-                  _key102 = iprot.readString();
-                  _val103 = iprot.readString();
-                  struct.queryOptions.put(_key102, _val103);
+                  _key110 = iprot.readString();
+                  _val111 = iprot.readString();
+                  struct.queryOptions.put(_key110, _val111);
                 }
                 iprot.readMapEnd();
               }
               struct.setQueryOptionsIsSet(true);
-            } else {
+            } else { 
               org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
             }
             break;
@@ -2048,7 +2029,7 @@ public class BrokerRequest implements org.apache.thrift.TBase<BrokerRequest, Bro
               struct.havingFilterQuery = new HavingFilterQuery();
               struct.havingFilterQuery.read(iprot);
               struct.setHavingFilterQueryIsSet(true);
-            } else {
+            } else { 
               org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
             }
             break;
@@ -2057,7 +2038,7 @@ public class BrokerRequest implements org.apache.thrift.TBase<BrokerRequest, Bro
               struct.havingFilterSubQueryMap = new HavingFilterQueryMap();
               struct.havingFilterSubQueryMap.read(iprot);
               struct.setHavingFilterSubQueryMapIsSet(true);
-            } else {
+            } else { 
               org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
             }
             break;
@@ -2066,26 +2047,26 @@ public class BrokerRequest implements org.apache.thrift.TBase<BrokerRequest, Bro
               struct.pinotQuery = new org.apache.pinot.common.request.PinotQuery();
               struct.pinotQuery.read(iprot);
               struct.setPinotQueryIsSet(true);
-            } else {
+            } else { 
               org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
             }
             break;
           case 18: // ORDER_BY
             if (schemeField.type == org.apache.thrift.protocol.TType.LIST) {
               {
-                org.apache.thrift.protocol.TList _list105 = iprot.readListBegin();
-                struct.orderBy = new java.util.ArrayList<SelectionSort>(_list105.size);
-                @org.apache.thrift.annotation.Nullable SelectionSort _elem106;
-                for (int _i107 = 0; _i107 < _list105.size; ++_i107)
+                org.apache.thrift.protocol.TList _list113 = iprot.readListBegin();
+                struct.orderBy = new java.util.ArrayList<SelectionSort>(_list113.size);
+                @org.apache.thrift.annotation.Nullable SelectionSort _elem114;
+                for (int _i115 = 0; _i115 < _list113.size; ++_i115)
                 {
-                  _elem106 = new SelectionSort();
-                  _elem106.read(iprot);
-                  struct.orderBy.add(_elem106);
+                  _elem114 = new SelectionSort();
+                  _elem114.read(iprot);
+                  struct.orderBy.add(_elem114);
                 }
                 iprot.readListEnd();
               }
               struct.setOrderByIsSet(true);
-            } else {
+            } else { 
               org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
             }
             break;
@@ -2093,7 +2074,7 @@ public class BrokerRequest implements org.apache.thrift.TBase<BrokerRequest, Bro
             if (schemeField.type == org.apache.thrift.protocol.TType.I32) {
               struct.limit = iprot.readI32();
               struct.setLimitIsSet(true);
-            } else {
+            } else { 
               org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
             }
             break;
@@ -2103,8 +2084,6 @@ public class BrokerRequest implements org.apache.thrift.TBase<BrokerRequest, Bro
         iprot.readFieldEnd();
       }
       iprot.readStructEnd();
-
-      // check for required fields of primitive type, which can't be checked in the validate method
       struct.validate();
     }
 
@@ -2152,9 +2131,9 @@ public class BrokerRequest implements org.apache.thrift.TBase<BrokerRequest, Bro
           oprot.writeFieldBegin(AGGREGATIONS_INFO_FIELD_DESC);
           {
             oprot.writeListBegin(new org.apache.thrift.protocol.TList(org.apache.thrift.protocol.TType.STRUCT, struct.aggregationsInfo.size()));
-            for (AggregationInfo _iter108 : struct.aggregationsInfo)
+            for (AggregationInfo _iter116 : struct.aggregationsInfo)
             {
-              _iter108.write(oprot);
+              _iter116.write(oprot);
             }
             oprot.writeListEnd();
           }
@@ -2206,10 +2185,10 @@ public class BrokerRequest implements org.apache.thrift.TBase<BrokerRequest, Bro
           oprot.writeFieldBegin(DEBUG_OPTIONS_FIELD_DESC);
           {
             oprot.writeMapBegin(new org.apache.thrift.protocol.TMap(org.apache.thrift.protocol.TType.STRING, org.apache.thrift.protocol.TType.STRING, struct.debugOptions.size()));
-            for (java.util.Map.Entry<java.lang.String, java.lang.String> _iter109 : struct.debugOptions.entrySet())
+            for (java.util.Map.Entry<java.lang.String, java.lang.String> _iter117 : struct.debugOptions.entrySet())
             {
-              oprot.writeString(_iter109.getKey());
-              oprot.writeString(_iter109.getValue());
+              oprot.writeString(_iter117.getKey());
+              oprot.writeString(_iter117.getValue());
             }
             oprot.writeMapEnd();
           }
@@ -2221,10 +2200,10 @@ public class BrokerRequest implements org.apache.thrift.TBase<BrokerRequest, Bro
           oprot.writeFieldBegin(QUERY_OPTIONS_FIELD_DESC);
           {
             oprot.writeMapBegin(new org.apache.thrift.protocol.TMap(org.apache.thrift.protocol.TType.STRING, org.apache.thrift.protocol.TType.STRING, struct.queryOptions.size()));
-            for (java.util.Map.Entry<java.lang.String, java.lang.String> _iter110 : struct.queryOptions.entrySet())
+            for (java.util.Map.Entry<java.lang.String, java.lang.String> _iter118 : struct.queryOptions.entrySet())
             {
-              oprot.writeString(_iter110.getKey());
-              oprot.writeString(_iter110.getValue());
+              oprot.writeString(_iter118.getKey());
+              oprot.writeString(_iter118.getValue());
             }
             oprot.writeMapEnd();
           }
@@ -2257,9 +2236,9 @@ public class BrokerRequest implements org.apache.thrift.TBase<BrokerRequest, Bro
           oprot.writeFieldBegin(ORDER_BY_FIELD_DESC);
           {
             oprot.writeListBegin(new org.apache.thrift.protocol.TList(org.apache.thrift.protocol.TType.STRUCT, struct.orderBy.size()));
-            for (SelectionSort _iter111 : struct.orderBy)
+            for (SelectionSort _iter119 : struct.orderBy)
             {
-              _iter111.write(oprot);
+              _iter119.write(oprot);
             }
             oprot.writeListEnd();
           }
@@ -2365,9 +2344,9 @@ public class BrokerRequest implements org.apache.thrift.TBase<BrokerRequest, Bro
       if (struct.isSetAggregationsInfo()) {
         {
           oprot.writeI32(struct.aggregationsInfo.size());
-          for (AggregationInfo _iter112 : struct.aggregationsInfo)
+          for (AggregationInfo _iter120 : struct.aggregationsInfo)
           {
-            _iter112.write(oprot);
+            _iter120.write(oprot);
           }
         }
       }
@@ -2392,20 +2371,20 @@ public class BrokerRequest implements org.apache.thrift.TBase<BrokerRequest, Bro
       if (struct.isSetDebugOptions()) {
         {
           oprot.writeI32(struct.debugOptions.size());
-          for (java.util.Map.Entry<java.lang.String, java.lang.String> _iter113 : struct.debugOptions.entrySet())
+          for (java.util.Map.Entry<java.lang.String, java.lang.String> _iter121 : struct.debugOptions.entrySet())
           {
-            oprot.writeString(_iter113.getKey());
-            oprot.writeString(_iter113.getValue());
+            oprot.writeString(_iter121.getKey());
+            oprot.writeString(_iter121.getValue());
           }
         }
       }
       if (struct.isSetQueryOptions()) {
         {
           oprot.writeI32(struct.queryOptions.size());
-          for (java.util.Map.Entry<java.lang.String, java.lang.String> _iter114 : struct.queryOptions.entrySet())
+          for (java.util.Map.Entry<java.lang.String, java.lang.String> _iter122 : struct.queryOptions.entrySet())
           {
-            oprot.writeString(_iter114.getKey());
-            oprot.writeString(_iter114.getValue());
+            oprot.writeString(_iter122.getKey());
+            oprot.writeString(_iter122.getValue());
           }
         }
       }
@@ -2421,9 +2400,9 @@ public class BrokerRequest implements org.apache.thrift.TBase<BrokerRequest, Bro
       if (struct.isSetOrderBy()) {
         {
           oprot.writeI32(struct.orderBy.size());
-          for (SelectionSort _iter115 : struct.orderBy)
+          for (SelectionSort _iter123 : struct.orderBy)
           {
-            _iter115.write(oprot);
+            _iter123.write(oprot);
           }
         }
       }
@@ -2461,14 +2440,14 @@ public class BrokerRequest implements org.apache.thrift.TBase<BrokerRequest, Bro
       }
       if (incoming.get(5)) {
         {
-          org.apache.thrift.protocol.TList _list116 = new org.apache.thrift.protocol.TList(org.apache.thrift.protocol.TType.STRUCT, iprot.readI32());
-          struct.aggregationsInfo = new java.util.ArrayList<AggregationInfo>(_list116.size);
-          @org.apache.thrift.annotation.Nullable AggregationInfo _elem117;
-          for (int _i118 = 0; _i118 < _list116.size; ++_i118)
+          org.apache.thrift.protocol.TList _list124 = new org.apache.thrift.protocol.TList(org.apache.thrift.protocol.TType.STRUCT, iprot.readI32());
+          struct.aggregationsInfo = new java.util.ArrayList<AggregationInfo>(_list124.size);
+          @org.apache.thrift.annotation.Nullable AggregationInfo _elem125;
+          for (int _i126 = 0; _i126 < _list124.size; ++_i126)
           {
-            _elem117 = new AggregationInfo();
-            _elem117.read(iprot);
-            struct.aggregationsInfo.add(_elem117);
+            _elem125 = new AggregationInfo();
+            _elem125.read(iprot);
+            struct.aggregationsInfo.add(_elem125);
           }
         }
         struct.setAggregationsInfoIsSet(true);
@@ -2502,30 +2481,30 @@ public class BrokerRequest implements org.apache.thrift.TBase<BrokerRequest, Bro
       }
       if (incoming.get(12)) {
         {
-          org.apache.thrift.protocol.TMap _map119 = new org.apache.thrift.protocol.TMap(org.apache.thrift.protocol.TType.STRING, org.apache.thrift.protocol.TType.STRING, iprot.readI32());
-          struct.debugOptions = new java.util.HashMap<java.lang.String,java.lang.String>(2*_map119.size);
-          @org.apache.thrift.annotation.Nullable java.lang.String _key120;
-          @org.apache.thrift.annotation.Nullable java.lang.String _val121;
-          for (int _i122 = 0; _i122 < _map119.size; ++_i122)
+          org.apache.thrift.protocol.TMap _map127 = new org.apache.thrift.protocol.TMap(org.apache.thrift.protocol.TType.STRING, org.apache.thrift.protocol.TType.STRING, iprot.readI32());
+          struct.debugOptions = new java.util.HashMap<java.lang.String,java.lang.String>(2*_map127.size);
+          @org.apache.thrift.annotation.Nullable java.lang.String _key128;
+          @org.apache.thrift.annotation.Nullable java.lang.String _val129;
+          for (int _i130 = 0; _i130 < _map127.size; ++_i130)
           {
-            _key120 = iprot.readString();
-            _val121 = iprot.readString();
-            struct.debugOptions.put(_key120, _val121);
+            _key128 = iprot.readString();
+            _val129 = iprot.readString();
+            struct.debugOptions.put(_key128, _val129);
           }
         }
         struct.setDebugOptionsIsSet(true);
       }
       if (incoming.get(13)) {
         {
-          org.apache.thrift.protocol.TMap _map123 = new org.apache.thrift.protocol.TMap(org.apache.thrift.protocol.TType.STRING, org.apache.thrift.protocol.TType.STRING, iprot.readI32());
-          struct.queryOptions = new java.util.HashMap<java.lang.String,java.lang.String>(2*_map123.size);
-          @org.apache.thrift.annotation.Nullable java.lang.String _key124;
-          @org.apache.thrift.annotation.Nullable java.lang.String _val125;
-          for (int _i126 = 0; _i126 < _map123.size; ++_i126)
+          org.apache.thrift.protocol.TMap _map131 = new org.apache.thrift.protocol.TMap(org.apache.thrift.protocol.TType.STRING, org.apache.thrift.protocol.TType.STRING, iprot.readI32());
+          struct.queryOptions = new java.util.HashMap<java.lang.String,java.lang.String>(2*_map131.size);
+          @org.apache.thrift.annotation.Nullable java.lang.String _key132;
+          @org.apache.thrift.annotation.Nullable java.lang.String _val133;
+          for (int _i134 = 0; _i134 < _map131.size; ++_i134)
           {
-            _key124 = iprot.readString();
-            _val125 = iprot.readString();
-            struct.queryOptions.put(_key124, _val125);
+            _key132 = iprot.readString();
+            _val133 = iprot.readString();
+            struct.queryOptions.put(_key132, _val133);
           }
         }
         struct.setQueryOptionsIsSet(true);
@@ -2547,14 +2526,14 @@ public class BrokerRequest implements org.apache.thrift.TBase<BrokerRequest, Bro
       }
       if (incoming.get(17)) {
         {
-          org.apache.thrift.protocol.TList _list127 = new org.apache.thrift.protocol.TList(org.apache.thrift.protocol.TType.STRUCT, iprot.readI32());
-          struct.orderBy = new java.util.ArrayList<SelectionSort>(_list127.size);
-          @org.apache.thrift.annotation.Nullable SelectionSort _elem128;
-          for (int _i129 = 0; _i129 < _list127.size; ++_i129)
+          org.apache.thrift.protocol.TList _list135 = new org.apache.thrift.protocol.TList(org.apache.thrift.protocol.TType.STRUCT, iprot.readI32());
+          struct.orderBy = new java.util.ArrayList<SelectionSort>(_list135.size);
+          @org.apache.thrift.annotation.Nullable SelectionSort _elem136;
+          for (int _i137 = 0; _i137 < _list135.size; ++_i137)
           {
-            _elem128 = new SelectionSort();
-            _elem128.read(iprot);
-            struct.orderBy.add(_elem128);
+            _elem136 = new SelectionSort();
+            _elem136.read(iprot);
+            struct.orderBy.add(_elem136);
           }
         }
         struct.setOrderByIsSet(true);
diff --git a/pinot-common/src/main/java/org/apache/pinot/common/request/DataSource.java b/pinot-common/src/main/java/org/apache/pinot/common/request/DataSource.java
index 9c7cff4..a5c903e 100644
--- a/pinot-common/src/main/java/org/apache/pinot/common/request/DataSource.java
+++ b/pinot-common/src/main/java/org/apache/pinot/common/request/DataSource.java
@@ -17,7 +17,7 @@
  * under the License.
  */
 /**
- * Autogenerated by Thrift Compiler (0.12.0)
+ * Autogenerated by Thrift Compiler (0.13.0)
  *
  * DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING
  *  @generated
@@ -25,7 +25,7 @@
 package org.apache.pinot.common.request;
 
 @SuppressWarnings({"cast", "rawtypes", "serial", "unchecked", "unused"})
-@javax.annotation.Generated(value = "Autogenerated by Thrift Compiler (0.12.0)", date = "2019-07-19")
+@javax.annotation.Generated(value = "Autogenerated by Thrift Compiler (0.13.0)", date = "2020-10-31")
 public class DataSource implements org.apache.thrift.TBase<DataSource, DataSource._Fields>, java.io.Serializable, Cloneable, Comparable<DataSource> {
   private static final org.apache.thrift.protocol.TStruct STRUCT_DESC = new org.apache.thrift.protocol.TStruct("DataSource");
 
@@ -34,7 +34,7 @@ public class DataSource implements org.apache.thrift.TBase<DataSource, DataSourc
   private static final org.apache.thrift.scheme.SchemeFactory STANDARD_SCHEME_FACTORY = new DataSourceStandardSchemeFactory();
   private static final org.apache.thrift.scheme.SchemeFactory TUPLE_SCHEME_FACTORY = new DataSourceTupleSchemeFactory();
 
-  public @org.apache.thrift.annotation.Nullable java.lang.String tableName; // optional
+  private @org.apache.thrift.annotation.Nullable java.lang.String tableName; // optional
 
   /** The set of fields this struct contains, along with convenience methods for finding and manipulating them. */
   public enum _Fields implements org.apache.thrift.TFieldIdEnum {
@@ -133,9 +133,8 @@ public class DataSource implements org.apache.thrift.TBase<DataSource, DataSourc
     return this.tableName;
   }
 
-  public DataSource setTableName(@org.apache.thrift.annotation.Nullable java.lang.String tableName) {
+  public void setTableName(@org.apache.thrift.annotation.Nullable java.lang.String tableName) {
     this.tableName = tableName;
-    return this;
   }
 
   public void unsetTableName() {
@@ -332,8 +331,6 @@ public class DataSource implements org.apache.thrift.TBase<DataSource, DataSourc
         iprot.readFieldEnd();
       }
       iprot.readStructEnd();
-
-      // check for required fields of primitive type, which can't be checked in the validate method
       struct.validate();
     }
 
diff --git a/pinot-common/src/main/java/org/apache/pinot/common/request/Expression.java b/pinot-common/src/main/java/org/apache/pinot/common/request/Expression.java
index 240b2bb..477c73d 100644
--- a/pinot-common/src/main/java/org/apache/pinot/common/request/Expression.java
+++ b/pinot-common/src/main/java/org/apache/pinot/common/request/Expression.java
@@ -17,7 +17,7 @@
  * under the License.
  */
 /**
- * Autogenerated by Thrift Compiler (0.12.0)
+ * Autogenerated by Thrift Compiler (0.13.0)
  *
  * DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING
  *  @generated
@@ -25,7 +25,7 @@
 package org.apache.pinot.common.request;
 
 @SuppressWarnings({"cast", "rawtypes", "serial", "unchecked", "unused"})
-@javax.annotation.Generated(value = "Autogenerated by Thrift Compiler (0.12.0)", date = "2019-07-19")
+@javax.annotation.Generated(value = "Autogenerated by Thrift Compiler (0.13.0)", date = "2020-10-31")
 public class Expression implements org.apache.thrift.TBase<Expression, Expression._Fields>, java.io.Serializable, Cloneable, Comparable<Expression> {
   private static final org.apache.thrift.protocol.TStruct STRUCT_DESC = new org.apache.thrift.protocol.TStruct("Expression");
 
@@ -37,14 +37,10 @@ public class Expression implements org.apache.thrift.TBase<Expression, Expressio
   private static final org.apache.thrift.scheme.SchemeFactory STANDARD_SCHEME_FACTORY = new ExpressionStandardSchemeFactory();
   private static final org.apache.thrift.scheme.SchemeFactory TUPLE_SCHEME_FACTORY = new ExpressionTupleSchemeFactory();
 
-  /**
-   * 
-   * @see ExpressionType
-   */
-  public @org.apache.thrift.annotation.Nullable ExpressionType type; // required
-  public @org.apache.thrift.annotation.Nullable Function functionCall; // optional
-  public @org.apache.thrift.annotation.Nullable Literal literal; // optional
-  public @org.apache.thrift.annotation.Nullable Identifier identifier; // optional
+  private @org.apache.thrift.annotation.Nullable ExpressionType type; // required
+  private @org.apache.thrift.annotation.Nullable Function functionCall; // optional
+  private @org.apache.thrift.annotation.Nullable Literal literal; // optional
+  private @org.apache.thrift.annotation.Nullable Identifier identifier; // optional
 
   /** The set of fields this struct contains, along with convenience methods for finding and manipulating them. */
   public enum _Fields implements org.apache.thrift.TFieldIdEnum {
@@ -189,9 +185,8 @@ public class Expression implements org.apache.thrift.TBase<Expression, Expressio
    * 
    * @see ExpressionType
    */
-  public Expression setType(@org.apache.thrift.annotation.Nullable ExpressionType type) {
+  public void setType(@org.apache.thrift.annotation.Nullable ExpressionType type) {
     this.type = type;
-    return this;
   }
 
   public void unsetType() {
@@ -214,9 +209,8 @@ public class Expression implements org.apache.thrift.TBase<Expression, Expressio
     return this.functionCall;
   }
 
-  public Expression setFunctionCall(@org.apache.thrift.annotation.Nullable Function functionCall) {
+  public void setFunctionCall(@org.apache.thrift.annotation.Nullable Function functionCall) {
     this.functionCall = functionCall;
-    return this;
   }
 
   public void unsetFunctionCall() {
@@ -239,9 +233,8 @@ public class Expression implements org.apache.thrift.TBase<Expression, Expressio
     return this.literal;
   }
 
-  public Expression setLiteral(@org.apache.thrift.annotation.Nullable Literal literal) {
+  public void setLiteral(@org.apache.thrift.annotation.Nullable Literal literal) {
     this.literal = literal;
-    return this;
   }
 
   public void unsetLiteral() {
@@ -264,9 +257,8 @@ public class Expression implements org.apache.thrift.TBase<Expression, Expressio
     return this.identifier;
   }
 
-  public Expression setIdentifier(@org.apache.thrift.annotation.Nullable Identifier identifier) {
+  public void setIdentifier(@org.apache.thrift.annotation.Nullable Identifier identifier) {
     this.identifier = identifier;
-    return this;
   }
 
   public void unsetIdentifier() {
@@ -548,9 +540,10 @@ public class Expression implements org.apache.thrift.TBase<Expression, Expressio
 
   public void validate() throws org.apache.thrift.TException {
     // check for required fields
-    if (type == null) {
-      throw new org.apache.thrift.protocol.TProtocolException("Required field 'type' was not present! Struct: " + toString());
+    if (!isSetType()) {
+      throw new org.apache.thrift.protocol.TProtocolException("Required field 'type' is unset! Struct:" + toString());
     }
+
     // check for sub-struct validity
   }
 
@@ -629,8 +622,6 @@ public class Expression implements org.apache.thrift.TBase<Expression, Expressio
         iprot.readFieldEnd();
       }
       iprot.readStructEnd();
-
-      // check for required fields of primitive type, which can't be checked in the validate method
       struct.validate();
     }
 
diff --git a/pinot-common/src/main/java/org/apache/pinot/common/request/ExpressionType.java b/pinot-common/src/main/java/org/apache/pinot/common/request/ExpressionType.java
index de06b54..80e0871 100644
--- a/pinot-common/src/main/java/org/apache/pinot/common/request/ExpressionType.java
+++ b/pinot-common/src/main/java/org/apache/pinot/common/request/ExpressionType.java
@@ -17,7 +17,7 @@
  * under the License.
  */
 /**
- * Autogenerated by Thrift Compiler (0.12.0)
+ * Autogenerated by Thrift Compiler (0.13.0)
  *
  * DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING
  *  @generated
@@ -25,7 +25,7 @@
 package org.apache.pinot.common.request;
 
 
-@javax.annotation.Generated(value = "Autogenerated by Thrift Compiler (0.12.0)", date = "2019-07-19")
+@javax.annotation.Generated(value = "Autogenerated by Thrift Compiler (0.13.0)", date = "2020-10-31")
 public enum ExpressionType implements org.apache.thrift.TEnum {
   LITERAL(0),
   IDENTIFIER(1),
diff --git a/pinot-common/src/main/java/org/apache/pinot/common/request/FilterOperator.java b/pinot-common/src/main/java/org/apache/pinot/common/request/FilterOperator.java
index b6ccc9e..fbf177b 100644
--- a/pinot-common/src/main/java/org/apache/pinot/common/request/FilterOperator.java
+++ b/pinot-common/src/main/java/org/apache/pinot/common/request/FilterOperator.java
@@ -28,9 +28,9 @@ package org.apache.pinot.common.request;
 /**
  * AUTO GENERATED: DO NOT EDIT
  * Filter Operator
- *
+ * 
  */
-@javax.annotation.Generated(value = "Autogenerated by Thrift Compiler (0.13.0)", date = "2020-01-16")
+@javax.annotation.Generated(value = "Autogenerated by Thrift Compiler (0.13.0)", date = "2020-10-31")
 public enum FilterOperator implements org.apache.thrift.TEnum {
   AND(0),
   OR(1),
@@ -42,7 +42,8 @@ public enum FilterOperator implements org.apache.thrift.TEnum {
   IN(7),
   IS_NULL(8),
   IS_NOT_NULL(9),
-  TEXT_MATCH(10);
+  TEXT_MATCH(10),
+  JSON_MATCH(11);
 
   private final int value;
 
@@ -62,7 +63,7 @@ public enum FilterOperator implements org.apache.thrift.TEnum {
    * @return null if the value is not found.
    */
   @org.apache.thrift.annotation.Nullable
-  public static FilterOperator findByValue(int value) {
+  public static FilterOperator findByValue(int value) { 
     switch (value) {
       case 0:
         return AND;
@@ -86,6 +87,8 @@ public enum FilterOperator implements org.apache.thrift.TEnum {
         return IS_NOT_NULL;
       case 10:
         return TEXT_MATCH;
+      case 11:
+        return JSON_MATCH;
       default:
         return null;
     }
diff --git a/pinot-common/src/main/java/org/apache/pinot/common/request/FilterQuery.java b/pinot-common/src/main/java/org/apache/pinot/common/request/FilterQuery.java
index 62c1e72..2261850 100644
--- a/pinot-common/src/main/java/org/apache/pinot/common/request/FilterQuery.java
+++ b/pinot-common/src/main/java/org/apache/pinot/common/request/FilterQuery.java
@@ -17,7 +17,7 @@
  * under the License.
  */
 /**
- * Autogenerated by Thrift Compiler (0.12.0)
+ * Autogenerated by Thrift Compiler (0.13.0)
  *
  * DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING
  *  @generated
@@ -30,7 +30,7 @@ package org.apache.pinot.common.request;
  * Filter query
  * 
  */
-@javax.annotation.Generated(value = "Autogenerated by Thrift Compiler (0.12.0)", date = "2019-07-19")
+@javax.annotation.Generated(value = "Autogenerated by Thrift Compiler (0.13.0)", date = "2020-10-31")
 public class FilterQuery implements org.apache.thrift.TBase<FilterQuery, FilterQuery._Fields>, java.io.Serializable, Cloneable, Comparable<FilterQuery> {
   private static final org.apache.thrift.protocol.TStruct STRUCT_DESC = new org.apache.thrift.protocol.TStruct("FilterQuery");
 
@@ -43,18 +43,11 @@ public class FilterQuery implements org.apache.thrift.TBase<FilterQuery, FilterQ
   private static final org.apache.thrift.scheme.SchemeFactory STANDARD_SCHEME_FACTORY = new FilterQueryStandardSchemeFactory();
   private static final org.apache.thrift.scheme.SchemeFactory TUPLE_SCHEME_FACTORY = new FilterQueryTupleSchemeFactory();
 
-  public int id; // required
-  /**
-   * This should be unique within a single request *
-   */
-  public @org.apache.thrift.annotation.Nullable java.lang.String column; // optional
-  public @org.apache.thrift.annotation.Nullable java.util.List<java.lang.String> value; // required
-  /**
-   * 
-   * @see FilterOperator
-   */
-  public @org.apache.thrift.annotation.Nullable FilterOperator operator; // optional
-  public @org.apache.thrift.annotation.Nullable java.util.List<java.lang.Integer> nestedFilterQueryIds; // required
+  private int id; // required
+  private @org.apache.thrift.annotation.Nullable java.lang.String column; // optional
+  private @org.apache.thrift.annotation.Nullable java.util.List<java.lang.String> value; // required
+  private @org.apache.thrift.annotation.Nullable FilterOperator operator; // optional
+  private @org.apache.thrift.annotation.Nullable java.util.List<java.lang.Integer> nestedFilterQueryIds; // required
 
   /** The set of fields this struct contains, along with convenience methods for finding and manipulating them. */
   public enum _Fields implements org.apache.thrift.TFieldIdEnum {
@@ -213,10 +206,9 @@ public class FilterQuery implements org.apache.thrift.TBase<FilterQuery, FilterQ
     return this.id;
   }
 
-  public FilterQuery setId(int id) {
+  public void setId(int id) {
     this.id = id;
     setIdIsSet(true);
-    return this;
   }
 
   public void unsetId() {
@@ -243,9 +235,8 @@ public class FilterQuery implements org.apache.thrift.TBase<FilterQuery, FilterQ
   /**
    * This should be unique within a single request *
    */
-  public FilterQuery setColumn(@org.apache.thrift.annotation.Nullable java.lang.String column) {
+  public void setColumn(@org.apache.thrift.annotation.Nullable java.lang.String column) {
     this.column = column;
-    return this;
   }
 
   public void unsetColumn() {
@@ -284,9 +275,8 @@ public class FilterQuery implements org.apache.thrift.TBase<FilterQuery, FilterQ
     return this.value;
   }
 
-  public FilterQuery setValue(@org.apache.thrift.annotation.Nullable java.util.List<java.lang.String> value) {
+  public void setValue(@org.apache.thrift.annotation.Nullable java.util.List<java.lang.String> value) {
     this.value = value;
-    return this;
   }
 
   public void unsetValue() {
@@ -317,9 +307,8 @@ public class FilterQuery implements org.apache.thrift.TBase<FilterQuery, FilterQ
    * 
    * @see FilterOperator
    */
-  public FilterQuery setOperator(@org.apache.thrift.annotation.Nullable FilterOperator operator) {
+  public void setOperator(@org.apache.thrift.annotation.Nullable FilterOperator operator) {
     this.operator = operator;
-    return this;
   }
 
   public void unsetOperator() {
@@ -358,9 +347,8 @@ public class FilterQuery implements org.apache.thrift.TBase<FilterQuery, FilterQ
     return this.nestedFilterQueryIds;
   }
 
-  public FilterQuery setNestedFilterQueryIds(@org.apache.thrift.annotation.Nullable java.util.List<java.lang.Integer> nestedFilterQueryIds) {
+  public void setNestedFilterQueryIds(@org.apache.thrift.annotation.Nullable java.util.List<java.lang.Integer> nestedFilterQueryIds) {
     this.nestedFilterQueryIds = nestedFilterQueryIds;
-    return this;
   }
 
   public void unsetNestedFilterQueryIds() {
@@ -678,7 +666,10 @@ public class FilterQuery implements org.apache.thrift.TBase<FilterQuery, FilterQ
 
   public void validate() throws org.apache.thrift.TException {
     // check for required fields
-    // alas, we cannot check 'id' because it's a primitive and you chose the non-beans generator.
+    if (!isSetId()) {
+      throw new org.apache.thrift.protocol.TProtocolException("Required field 'id' is unset! Struct:" + toString());
+    }
+
     // check for sub-struct validity
   }
 
@@ -784,11 +775,6 @@ public class FilterQuery implements org.apache.thrift.TBase<FilterQuery, FilterQ
         iprot.readFieldEnd();
       }
       iprot.readStructEnd();
-
-      // check for required fields of primitive type, which can't be checked in the validate method
-      if (!struct.isSetId()) {
-        throw new org.apache.thrift.protocol.TProtocolException("Required field 'id' was not found in serialized data! Struct: " + toString());
-      }
       struct.validate();
     }
 
diff --git a/pinot-common/src/main/java/org/apache/pinot/common/request/FilterQueryMap.java b/pinot-common/src/main/java/org/apache/pinot/common/request/FilterQueryMap.java
index fa9902b..fcafcbc 100644
--- a/pinot-common/src/main/java/org/apache/pinot/common/request/FilterQueryMap.java
+++ b/pinot-common/src/main/java/org/apache/pinot/common/request/FilterQueryMap.java
@@ -17,7 +17,7 @@
  * under the License.
  */
 /**
- * Autogenerated by Thrift Compiler (0.12.0)
+ * Autogenerated by Thrift Compiler (0.13.0)
  *
  * DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING
  *  @generated
@@ -30,7 +30,7 @@ package org.apache.pinot.common.request;
  * Filter Query is nested but thrift stable version does not support yet (The support is there in top of the trunk but no released jars. Two concerns : stability and onus of maintaining a stable point. Also, its pretty difficult to compile thrift in Linkedin software development environment which is not geared towards c++ dev. Hence, the )
  * 
  */
-@javax.annotation.Generated(value = "Autogenerated by Thrift Compiler (0.12.0)", date = "2019-07-19")
+@javax.annotation.Generated(value = "Autogenerated by Thrift Compiler (0.13.0)", date = "2020-10-31")
 public class FilterQueryMap implements org.apache.thrift.TBase<FilterQueryMap, FilterQueryMap._Fields>, java.io.Serializable, Cloneable, Comparable<FilterQueryMap> {
   private static final org.apache.thrift.protocol.TStruct STRUCT_DESC = new org.apache.thrift.protocol.TStruct("FilterQueryMap");
 
@@ -39,7 +39,7 @@ public class FilterQueryMap implements org.apache.thrift.TBase<FilterQueryMap, F
   private static final org.apache.thrift.scheme.SchemeFactory STANDARD_SCHEME_FACTORY = new FilterQueryMapStandardSchemeFactory();
   private static final org.apache.thrift.scheme.SchemeFactory TUPLE_SCHEME_FACTORY = new FilterQueryMapTupleSchemeFactory();
 
-  public @org.apache.thrift.annotation.Nullable java.util.Map<java.lang.Integer,FilterQuery> filterQueryMap; // optional
+  private @org.apache.thrift.annotation.Nullable java.util.Map<java.lang.Integer,FilterQuery> filterQueryMap; // optional
 
   /** The set of fields this struct contains, along with convenience methods for finding and manipulating them. */
   public enum _Fields implements org.apache.thrift.TFieldIdEnum {
@@ -163,9 +163,8 @@ public class FilterQueryMap implements org.apache.thrift.TBase<FilterQueryMap, F
     return this.filterQueryMap;
   }
 
-  public FilterQueryMap setFilterQueryMap(@org.apache.thrift.annotation.Nullable java.util.Map<java.lang.Integer,FilterQuery> filterQueryMap) {
+  public void setFilterQueryMap(@org.apache.thrift.annotation.Nullable java.util.Map<java.lang.Integer,FilterQuery> filterQueryMap) {
     this.filterQueryMap = filterQueryMap;
-    return this;
   }
 
   public void unsetFilterQueryMap() {
@@ -375,8 +374,6 @@ public class FilterQueryMap implements org.apache.thrift.TBase<FilterQueryMap, F
         iprot.readFieldEnd();
       }
       iprot.readStructEnd();
-
-      // check for required fields of primitive type, which can't be checked in the validate method
       struct.validate();
     }
 
diff --git a/pinot-common/src/main/java/org/apache/pinot/common/request/Function.java b/pinot-common/src/main/java/org/apache/pinot/common/request/Function.java
index 300dd3e..5010c53 100644
--- a/pinot-common/src/main/java/org/apache/pinot/common/request/Function.java
+++ b/pinot-common/src/main/java/org/apache/pinot/common/request/Function.java
@@ -17,7 +17,7 @@
  * under the License.
  */
 /**
- * Autogenerated by Thrift Compiler (0.12.0)
+ * Autogenerated by Thrift Compiler (0.13.0)
  *
  * DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING
  *  @generated
@@ -25,7 +25,7 @@
 package org.apache.pinot.common.request;
 
 @SuppressWarnings({"cast", "rawtypes", "serial", "unchecked", "unused"})
-@javax.annotation.Generated(value = "Autogenerated by Thrift Compiler (0.12.0)", date = "2019-07-19")
+@javax.annotation.Generated(value = "Autogenerated by Thrift Compiler (0.13.0)", date = "2020-10-31")
 public class Function implements org.apache.thrift.TBase<Function, Function._Fields>, java.io.Serializable, Cloneable, Comparable<Function> {
   private static final org.apache.thrift.protocol.TStruct STRUCT_DESC = new org.apache.thrift.protocol.TStruct("Function");
 
@@ -35,8 +35,8 @@ public class Function implements org.apache.thrift.TBase<Function, Function._Fie
   private static final org.apache.thrift.scheme.SchemeFactory STANDARD_SCHEME_FACTORY = new FunctionStandardSchemeFactory();
   private static final org.apache.thrift.scheme.SchemeFactory TUPLE_SCHEME_FACTORY = new FunctionTupleSchemeFactory();
 
-  public @org.apache.thrift.annotation.Nullable java.lang.String operator; // required
-  public @org.apache.thrift.annotation.Nullable java.util.List<Expression> operands; // optional
+  private @org.apache.thrift.annotation.Nullable java.lang.String operator; // required
+  private @org.apache.thrift.annotation.Nullable java.util.List<Expression> operands; // optional
 
   /** The set of fields this struct contains, along with convenience methods for finding and manipulating them. */
   public enum _Fields implements org.apache.thrift.TFieldIdEnum {
@@ -156,9 +156,8 @@ public class Function implements org.apache.thrift.TBase<Function, Function._Fie
     return this.operator;
   }
 
-  public Function setOperator(@org.apache.thrift.annotation.Nullable java.lang.String operator) {
+  public void setOperator(@org.apache.thrift.annotation.Nullable java.lang.String operator) {
     this.operator = operator;
-    return this;
   }
 
   public void unsetOperator() {
@@ -197,9 +196,8 @@ public class Function implements org.apache.thrift.TBase<Function, Function._Fie
     return this.operands;
   }
 
-  public Function setOperands(@org.apache.thrift.annotation.Nullable java.util.List<Expression> operands) {
+  public void setOperands(@org.apache.thrift.annotation.Nullable java.util.List<Expression> operands) {
     this.operands = operands;
-    return this;
   }
 
   public void unsetOperands() {
@@ -389,9 +387,10 @@ public class Function implements org.apache.thrift.TBase<Function, Function._Fie
 
   public void validate() throws org.apache.thrift.TException {
     // check for required fields
-    if (operator == null) {
-      throw new org.apache.thrift.protocol.TProtocolException("Required field 'operator' was not present! Struct: " + toString());
+    if (!isSetOperator()) {
+      throw new org.apache.thrift.protocol.TProtocolException("Required field 'operator' is unset! Struct:" + toString());
     }
+
     // check for sub-struct validity
   }
 
@@ -462,8 +461,6 @@ public class Function implements org.apache.thrift.TBase<Function, Function._Fie
         iprot.readFieldEnd();
       }
       iprot.readStructEnd();
-
-      // check for required fields of primitive type, which can't be checked in the validate method
       struct.validate();
     }
 
diff --git a/pinot-common/src/main/java/org/apache/pinot/common/request/GroupBy.java b/pinot-common/src/main/java/org/apache/pinot/common/request/GroupBy.java
index f055b11..08f255d 100644
--- a/pinot-common/src/main/java/org/apache/pinot/common/request/GroupBy.java
+++ b/pinot-common/src/main/java/org/apache/pinot/common/request/GroupBy.java
@@ -17,7 +17,7 @@
  * under the License.
  */
 /**
- * Autogenerated by Thrift Compiler (0.12.0)
+ * Autogenerated by Thrift Compiler (0.13.0)
  *
  * DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING
  *  @generated
@@ -30,7 +30,7 @@ package org.apache.pinot.common.request;
  * GroupBy
  * 
  */
-@javax.annotation.Generated(value = "Autogenerated by Thrift Compiler (0.12.0)", date = "2019-07-19")
+@javax.annotation.Generated(value = "Autogenerated by Thrift Compiler (0.13.0)", date = "2020-10-31")
 public class GroupBy implements org.apache.thrift.TBase<GroupBy, GroupBy._Fields>, java.io.Serializable, Cloneable, Comparable<GroupBy> {
   private static final org.apache.thrift.protocol.TStruct STRUCT_DESC = new org.apache.thrift.protocol.TStruct("GroupBy");
 
@@ -41,9 +41,9 @@ public class GroupBy implements org.apache.thrift.TBase<GroupBy, GroupBy._Fields
   private static final org.apache.thrift.scheme.SchemeFactory STANDARD_SCHEME_FACTORY = new GroupByStandardSchemeFactory();
   private static final org.apache.thrift.scheme.SchemeFactory TUPLE_SCHEME_FACTORY = new GroupByTupleSchemeFactory();
 
-  public @org.apache.thrift.annotation.Nullable java.util.List<java.lang.String> columns; // optional
-  public long topN; // optional
-  public @org.apache.thrift.annotation.Nullable java.util.List<java.lang.String> expressions; // optional
+  private @org.apache.thrift.annotation.Nullable java.util.List<java.lang.String> columns; // optional
+  private long topN; // optional
+  private @org.apache.thrift.annotation.Nullable java.util.List<java.lang.String> expressions; // optional
 
   /** The set of fields this struct contains, along with convenience methods for finding and manipulating them. */
   public enum _Fields implements org.apache.thrift.TFieldIdEnum {
@@ -182,9 +182,8 @@ public class GroupBy implements org.apache.thrift.TBase<GroupBy, GroupBy._Fields
     return this.columns;
   }
 
-  public GroupBy setColumns(@org.apache.thrift.annotation.Nullable java.util.List<java.lang.String> columns) {
+  public void setColumns(@org.apache.thrift.annotation.Nullable java.util.List<java.lang.String> columns) {
     this.columns = columns;
-    return this;
   }
 
   public void unsetColumns() {
@@ -206,10 +205,9 @@ public class GroupBy implements org.apache.thrift.TBase<GroupBy, GroupBy._Fields
     return this.topN;
   }
 
-  public GroupBy setTopN(long topN) {
+  public void setTopN(long topN) {
     this.topN = topN;
     setTopNIsSet(true);
-    return this;
   }
 
   public void unsetTopN() {
@@ -246,9 +244,8 @@ public class GroupBy implements org.apache.thrift.TBase<GroupBy, GroupBy._Fields
     return this.expressions;
   }
 
-  public GroupBy setExpressions(@org.apache.thrift.annotation.Nullable java.util.List<java.lang.String> expressions) {
+  public void setExpressions(@org.apache.thrift.annotation.Nullable java.util.List<java.lang.String> expressions) {
     this.expressions = expressions;
-    return this;
   }
 
   public void unsetExpressions() {
@@ -524,13 +521,13 @@ public class GroupBy implements org.apache.thrift.TBase<GroupBy, GroupBy._Fields
           case 1: // COLUMNS
             if (schemeField.type == org.apache.thrift.protocol.TType.LIST) {
               {
-                org.apache.thrift.protocol.TList _list62 = iprot.readListBegin();
-                struct.columns = new java.util.ArrayList<java.lang.String>(_list62.size);
-                @org.apache.thrift.annotation.Nullable java.lang.String _elem63;
-                for (int _i64 = 0; _i64 < _list62.size; ++_i64)
+                org.apache.thrift.protocol.TList _list70 = iprot.readListBegin();
+                struct.columns = new java.util.ArrayList<java.lang.String>(_list70.size);
+                @org.apache.thrift.annotation.Nullable java.lang.String _elem71;
+                for (int _i72 = 0; _i72 < _list70.size; ++_i72)
                 {
-                  _elem63 = iprot.readString();
-                  struct.columns.add(_elem63);
+                  _elem71 = iprot.readString();
+                  struct.columns.add(_elem71);
                 }
                 iprot.readListEnd();
               }
@@ -550,13 +547,13 @@ public class GroupBy implements org.apache.thrift.TBase<GroupBy, GroupBy._Fields
           case 3: // EXPRESSIONS
             if (schemeField.type == org.apache.thrift.protocol.TType.LIST) {
               {
-                org.apache.thrift.protocol.TList _list65 = iprot.readListBegin();
-                struct.expressions = new java.util.ArrayList<java.lang.String>(_list65.size);
-                @org.apache.thrift.annotation.Nullable java.lang.String _elem66;
-                for (int _i67 = 0; _i67 < _list65.size; ++_i67)
+                org.apache.thrift.protocol.TList _list73 = iprot.readListBegin();
+                struct.expressions = new java.util.ArrayList<java.lang.String>(_list73.size);
+                @org.apache.thrift.annotation.Nullable java.lang.String _elem74;
+                for (int _i75 = 0; _i75 < _list73.size; ++_i75)
                 {
-                  _elem66 = iprot.readString();
-                  struct.expressions.add(_elem66);
+                  _elem74 = iprot.readString();
+                  struct.expressions.add(_elem74);
                 }
                 iprot.readListEnd();
               }
@@ -571,8 +568,6 @@ public class GroupBy implements org.apache.thrift.TBase<GroupBy, GroupBy._Fields
         iprot.readFieldEnd();
       }
       iprot.readStructEnd();
-
-      // check for required fields of primitive type, which can't be checked in the validate method
       struct.validate();
     }
 
@@ -585,9 +580,9 @@ public class GroupBy implements org.apache.thrift.TBase<GroupBy, GroupBy._Fields
           oprot.writeFieldBegin(COLUMNS_FIELD_DESC);
           {
             oprot.writeListBegin(new org.apache.thrift.protocol.TList(org.apache.thrift.protocol.TType.STRING, struct.columns.size()));
-            for (java.lang.String _iter68 : struct.columns)
+            for (java.lang.String _iter76 : struct.columns)
             {
-              oprot.writeString(_iter68);
+              oprot.writeString(_iter76);
             }
             oprot.writeListEnd();
           }
@@ -604,9 +599,9 @@ public class GroupBy implements org.apache.thrift.TBase<GroupBy, GroupBy._Fields
           oprot.writeFieldBegin(EXPRESSIONS_FIELD_DESC);
           {
             oprot.writeListBegin(new org.apache.thrift.protocol.TList(org.apache.thrift.protocol.TType.STRING, struct.expressions.size()));
-            for (java.lang.String _iter69 : struct.expressions)
+            for (java.lang.String _iter77 : struct.expressions)
             {
-              oprot.writeString(_iter69);
+              oprot.writeString(_iter77);
             }
             oprot.writeListEnd();
           }
@@ -644,9 +639,9 @@ public class GroupBy implements org.apache.thrift.TBase<GroupBy, GroupBy._Fields
       if (struct.isSetColumns()) {
         {
           oprot.writeI32(struct.columns.size());
-          for (java.lang.String _iter70 : struct.columns)
+          for (java.lang.String _iter78 : struct.columns)
           {
-            oprot.writeString(_iter70);
+            oprot.writeString(_iter78);
           }
         }
       }
@@ -656,9 +651,9 @@ public class GroupBy implements org.apache.thrift.TBase<GroupBy, GroupBy._Fields
       if (struct.isSetExpressions()) {
         {
           oprot.writeI32(struct.expressions.size());
-          for (java.lang.String _iter71 : struct.expressions)
+          for (java.lang.String _iter79 : struct.expressions)
           {
-            oprot.writeString(_iter71);
+            oprot.writeString(_iter79);
           }
         }
       }
@@ -670,13 +665,13 @@ public class GroupBy implements org.apache.thrift.TBase<GroupBy, GroupBy._Fields
       java.util.BitSet incoming = iprot.readBitSet(3);
       if (incoming.get(0)) {
         {
-          org.apache.thrift.protocol.TList _list72 = new org.apache.thrift.protocol.TList(org.apache.thrift.protocol.TType.STRING, iprot.readI32());
-          struct.columns = new java.util.ArrayList<java.lang.String>(_list72.size);
-          @org.apache.thrift.annotation.Nullable java.lang.String _elem73;
-          for (int _i74 = 0; _i74 < _list72.size; ++_i74)
+          org.apache.thrift.protocol.TList _list80 = new org.apache.thrift.protocol.TList(org.apache.thrift.protocol.TType.STRING, iprot.readI32());
+          struct.columns = new java.util.ArrayList<java.lang.String>(_list80.size);
+          @org.apache.thrift.annotation.Nullable java.lang.String _elem81;
+          for (int _i82 = 0; _i82 < _list80.size; ++_i82)
           {
-            _elem73 = iprot.readString();
-            struct.columns.add(_elem73);
+            _elem81 = iprot.readString();
+            struct.columns.add(_elem81);
           }
         }
         struct.setColumnsIsSet(true);
@@ -687,13 +682,13 @@ public class GroupBy implements org.apache.thrift.TBase<GroupBy, GroupBy._Fields
       }
       if (incoming.get(2)) {
         {
-          org.apache.thrift.protocol.TList _list75 = new org.apache.thrift.protocol.TList(org.apache.thrift.protocol.TType.STRING, iprot.readI32());
-          struct.expressions = new java.util.ArrayList<java.lang.String>(_list75.size);
-          @org.apache.thrift.annotation.Nullable java.lang.String _elem76;
-          for (int _i77 = 0; _i77 < _list75.size; ++_i77)
+          org.apache.thrift.protocol.TList _list83 = new org.apache.thrift.protocol.TList(org.apache.thrift.protocol.TType.STRING, iprot.readI32());
+          struct.expressions = new java.util.ArrayList<java.lang.String>(_list83.size);
+          @org.apache.thrift.annotation.Nullable java.lang.String _elem84;
+          for (int _i85 = 0; _i85 < _list83.size; ++_i85)
           {
-            _elem76 = iprot.readString();
-            struct.expressions.add(_elem76);
+            _elem84 = iprot.readString();
+            struct.expressions.add(_elem84);
           }
         }
         struct.setExpressionsIsSet(true);
diff --git a/pinot-common/src/main/java/org/apache/pinot/common/request/HavingFilterQuery.java b/pinot-common/src/main/java/org/apache/pinot/common/request/HavingFilterQuery.java
index f2cda61..29aa39f 100644
--- a/pinot-common/src/main/java/org/apache/pinot/common/request/HavingFilterQuery.java
+++ b/pinot-common/src/main/java/org/apache/pinot/common/request/HavingFilterQuery.java
@@ -17,7 +17,7 @@
  * under the License.
  */
 /**
- * Autogenerated by Thrift Compiler (0.12.0)
+ * Autogenerated by Thrift Compiler (0.13.0)
  *
  * DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING
  *  @generated
@@ -30,7 +30,7 @@ package org.apache.pinot.common.request;
  * Having Filter query
  * 
  */
-@javax.annotation.Generated(value = "Autogenerated by Thrift Compiler (0.12.0)", date = "2019-07-19")
+@javax.annotation.Generated(value = "Autogenerated by Thrift Compiler (0.13.0)", date = "2020-10-31")
 public class HavingFilterQuery implements org.apache.thrift.TBase<HavingFilterQuery, HavingFilterQuery._Fields>, java.io.Serializable, Cloneable, Comparable<HavingFilterQuery> {
   private static final org.apache.thrift.protocol.TStruct STRUCT_DESC = new org.apache.thrift.protocol.TStruct("HavingFilterQuery");
 
@@ -43,18 +43,11 @@ public class HavingFilterQuery implements org.apache.thrift.TBase<HavingFilterQu
   private static final org.apache.thrift.scheme.SchemeFactory STANDARD_SCHEME_FACTORY = new HavingFilterQueryStandardSchemeFactory();
   private static final org.apache.thrift.scheme.SchemeFactory TUPLE_SCHEME_FACTORY = new HavingFilterQueryTupleSchemeFactory();
 
-  public int id; // required
-  /**
-   * This should be unique within a single request *
-   */
-  public @org.apache.thrift.annotation.Nullable AggregationInfo aggregationInfo; // optional
-  public @org.apache.thrift.annotation.Nullable java.util.List<java.lang.String> value; // required
-  /**
-   * 
-   * @see FilterOperator
-   */
-  public @org.apache.thrift.annotation.Nullable FilterOperator operator; // optional
-  public @org.apache.thrift.annotation.Nullable java.util.List<java.lang.Integer> nestedFilterQueryIds; // required
+  private int id; // required
+  private @org.apache.thrift.annotation.Nullable AggregationInfo aggregationInfo; // optional
+  private @org.apache.thrift.annotation.Nullable java.util.List<java.lang.String> value; // required
+  private @org.apache.thrift.annotation.Nullable FilterOperator operator; // optional
+  private @org.apache.thrift.annotation.Nullable java.util.List<java.lang.Integer> nestedFilterQueryIds; // required
 
   /** The set of fields this struct contains, along with convenience methods for finding and manipulating them. */
   public enum _Fields implements org.apache.thrift.TFieldIdEnum {
@@ -213,10 +206,9 @@ public class HavingFilterQuery implements org.apache.thrift.TBase<HavingFilterQu
     return this.id;
   }
 
-  public HavingFilterQuery setId(int id) {
+  public void setId(int id) {
     this.id = id;
     setIdIsSet(true);
-    return this;
   }
 
   public void unsetId() {
@@ -243,9 +235,8 @@ public class HavingFilterQuery implements org.apache.thrift.TBase<HavingFilterQu
   /**
    * This should be unique within a single request *
    */
-  public HavingFilterQuery setAggregationInfo(@org.apache.thrift.annotation.Nullable AggregationInfo aggregationInfo) {
+  public void setAggregationInfo(@org.apache.thrift.annotation.Nullable AggregationInfo aggregationInfo) {
     this.aggregationInfo = aggregationInfo;
-    return this;
   }
 
   public void unsetAggregationInfo() {
@@ -284,9 +275,8 @@ public class HavingFilterQuery implements org.apache.thrift.TBase<HavingFilterQu
     return this.value;
   }
 
-  public HavingFilterQuery setValue(@org.apache.thrift.annotation.Nullable java.util.List<java.lang.String> value) {
+  public void setValue(@org.apache.thrift.annotation.Nullable java.util.List<java.lang.String> value) {
     this.value = value;
-    return this;
   }
 
   public void unsetValue() {
@@ -317,9 +307,8 @@ public class HavingFilterQuery implements org.apache.thrift.TBase<HavingFilterQu
    * 
    * @see FilterOperator
    */
-  public HavingFilterQuery setOperator(@org.apache.thrift.annotation.Nullable FilterOperator operator) {
+  public void setOperator(@org.apache.thrift.annotation.Nullable FilterOperator operator) {
     this.operator = operator;
-    return this;
   }
 
   public void unsetOperator() {
@@ -358,9 +347,8 @@ public class HavingFilterQuery implements org.apache.thrift.TBase<HavingFilterQu
     return this.nestedFilterQueryIds;
   }
 
-  public HavingFilterQuery setNestedFilterQueryIds(@org.apache.thrift.annotation.Nullable java.util.List<java.lang.Integer> nestedFilterQueryIds) {
+  public void setNestedFilterQueryIds(@org.apache.thrift.annotation.Nullable java.util.List<java.lang.Integer> nestedFilterQueryIds) {
     this.nestedFilterQueryIds = nestedFilterQueryIds;
-    return this;
   }
 
   public void unsetNestedFilterQueryIds() {
@@ -678,7 +666,10 @@ public class HavingFilterQuery implements org.apache.thrift.TBase<HavingFilterQu
 
   public void validate() throws org.apache.thrift.TException {
     // check for required fields
-    // alas, we cannot check 'id' because it's a primitive and you chose the non-beans generator.
+    if (!isSetId()) {
+      throw new org.apache.thrift.protocol.TProtocolException("Required field 'id' is unset! Struct:" + toString());
+    }
+
     // check for sub-struct validity
   }
 
@@ -785,11 +776,6 @@ public class HavingFilterQuery implements org.apache.thrift.TBase<HavingFilterQu
         iprot.readFieldEnd();
       }
       iprot.readStructEnd();
-
-      // check for required fields of primitive type, which can't be checked in the validate method
-      if (!struct.isSetId()) {
-        throw new org.apache.thrift.protocol.TProtocolException("Required field 'id' was not found in serialized data! Struct: " + toString());
-      }
       struct.validate();
     }
 
diff --git a/pinot-common/src/main/java/org/apache/pinot/common/request/HavingFilterQueryMap.java b/pinot-common/src/main/java/org/apache/pinot/common/request/HavingFilterQueryMap.java
index 4dbb6f9..67af8d9 100644
--- a/pinot-common/src/main/java/org/apache/pinot/common/request/HavingFilterQueryMap.java
+++ b/pinot-common/src/main/java/org/apache/pinot/common/request/HavingFilterQueryMap.java
@@ -17,7 +17,7 @@
  * under the License.
  */
 /**
- * Autogenerated by Thrift Compiler (0.12.0)
+ * Autogenerated by Thrift Compiler (0.13.0)
  *
  * DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING
  *  @generated
@@ -25,7 +25,7 @@
 package org.apache.pinot.common.request;
 
 @SuppressWarnings({"cast", "rawtypes", "serial", "unchecked", "unused"})
-@javax.annotation.Generated(value = "Autogenerated by Thrift Compiler (0.12.0)", date = "2019-07-19")
+@javax.annotation.Generated(value = "Autogenerated by Thrift Compiler (0.13.0)", date = "2020-10-31")
 public class HavingFilterQueryMap implements org.apache.thrift.TBase<HavingFilterQueryMap, HavingFilterQueryMap._Fields>, java.io.Serializable, Cloneable, Comparable<HavingFilterQueryMap> {
   private static final org.apache.thrift.protocol.TStruct STRUCT_DESC = new org.apache.thrift.protocol.TStruct("HavingFilterQueryMap");
 
@@ -34,7 +34,7 @@ public class HavingFilterQueryMap implements org.apache.thrift.TBase<HavingFilte
   private static final org.apache.thrift.scheme.SchemeFactory STANDARD_SCHEME_FACTORY = new HavingFilterQueryMapStandardSchemeFactory();
   private static final org.apache.thrift.scheme.SchemeFactory TUPLE_SCHEME_FACTORY = new HavingFilterQueryMapTupleSchemeFactory();
 
-  public @org.apache.thrift.annotation.Nullable java.util.Map<java.lang.Integer,HavingFilterQuery> filterQueryMap; // optional
+  private @org.apache.thrift.annotation.Nullable java.util.Map<java.lang.Integer,HavingFilterQuery> filterQueryMap; // optional
 
   /** The set of fields this struct contains, along with convenience methods for finding and manipulating them. */
   public enum _Fields implements org.apache.thrift.TFieldIdEnum {
@@ -158,9 +158,8 @@ public class HavingFilterQueryMap implements org.apache.thrift.TBase<HavingFilte
     return this.filterQueryMap;
   }
 
-  public HavingFilterQueryMap setFilterQueryMap(@org.apache.thrift.annotation.Nullable java.util.Map<java.lang.Integer,HavingFilterQuery> filterQueryMap) {
+  public void setFilterQueryMap(@org.apache.thrift.annotation.Nullable java.util.Map<java.lang.Integer,HavingFilterQuery> filterQueryMap) {
     this.filterQueryMap = filterQueryMap;
-    return this;
   }
 
   public void unsetFilterQueryMap() {
@@ -370,8 +369,6 @@ public class HavingFilterQueryMap implements org.apache.thrift.TBase<HavingFilte
         iprot.readFieldEnd();
       }
       iprot.readStructEnd();
-
-      // check for required fields of primitive type, which can't be checked in the validate method
       struct.validate();
     }
 
diff --git a/pinot-common/src/main/java/org/apache/pinot/common/request/Identifier.java b/pinot-common/src/main/java/org/apache/pinot/common/request/Identifier.java
index 6ae7ab2..9fbb9b5 100644
--- a/pinot-common/src/main/java/org/apache/pinot/common/request/Identifier.java
+++ b/pinot-common/src/main/java/org/apache/pinot/common/request/Identifier.java
@@ -17,7 +17,7 @@
  * under the License.
  */
 /**
- * Autogenerated by Thrift Compiler (0.12.0)
+ * Autogenerated by Thrift Compiler (0.13.0)
  *
  * DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING
  *  @generated
@@ -25,7 +25,7 @@
 package org.apache.pinot.common.request;
 
 @SuppressWarnings({"cast", "rawtypes", "serial", "unchecked", "unused"})
-@javax.annotation.Generated(value = "Autogenerated by Thrift Compiler (0.12.0)", date = "2019-07-19")
+@javax.annotation.Generated(value = "Autogenerated by Thrift Compiler (0.13.0)", date = "2020-10-31")
 public class Identifier implements org.apache.thrift.TBase<Identifier, Identifier._Fields>, java.io.Serializable, Cloneable, Comparable<Identifier> {
   private static final org.apache.thrift.protocol.TStruct STRUCT_DESC = new org.apache.thrift.protocol.TStruct("Identifier");
 
@@ -34,7 +34,7 @@ public class Identifier implements org.apache.thrift.TBase<Identifier, Identifie
   private static final org.apache.thrift.scheme.SchemeFactory STANDARD_SCHEME_FACTORY = new IdentifierStandardSchemeFactory();
   private static final org.apache.thrift.scheme.SchemeFactory TUPLE_SCHEME_FACTORY = new IdentifierTupleSchemeFactory();
 
-  public @org.apache.thrift.annotation.Nullable java.lang.String name; // required
+  private @org.apache.thrift.annotation.Nullable java.lang.String name; // required
 
   /** The set of fields this struct contains, along with convenience methods for finding and manipulating them. */
   public enum _Fields implements org.apache.thrift.TFieldIdEnum {
@@ -139,9 +139,8 @@ public class Identifier implements org.apache.thrift.TBase<Identifier, Identifie
     return this.name;
   }
 
-  public Identifier setName(@org.apache.thrift.annotation.Nullable java.lang.String name) {
+  public void setName(@org.apache.thrift.annotation.Nullable java.lang.String name) {
     this.name = name;
-    return this;
   }
 
   public void unsetName() {
@@ -285,9 +284,10 @@ public class Identifier implements org.apache.thrift.TBase<Identifier, Identifie
 
   public void validate() throws org.apache.thrift.TException {
     // check for required fields
-    if (name == null) {
-      throw new org.apache.thrift.protocol.TProtocolException("Required field 'name' was not present! Struct: " + toString());
+    if (!isSetName()) {
+      throw new org.apache.thrift.protocol.TProtocolException("Required field 'name' is unset! Struct:" + toString());
     }
+
     // check for sub-struct validity
   }
 
@@ -339,8 +339,6 @@ public class Identifier implements org.apache.thrift.TBase<Identifier, Identifie
         iprot.readFieldEnd();
       }
       iprot.readStructEnd();
-
-      // check for required fields of primitive type, which can't be checked in the validate method
       struct.validate();
     }
 
diff --git a/pinot-common/src/main/java/org/apache/pinot/common/request/InstanceRequest.java b/pinot-common/src/main/java/org/apache/pinot/common/request/InstanceRequest.java
index 534b6bb..202cfdf 100644
--- a/pinot-common/src/main/java/org/apache/pinot/common/request/InstanceRequest.java
+++ b/pinot-common/src/main/java/org/apache/pinot/common/request/InstanceRequest.java
@@ -17,7 +17,7 @@
  * under the License.
  */
 /**
- * Autogenerated by Thrift Compiler (0.12.0)
+ * Autogenerated by Thrift Compiler (0.13.0)
  *
  * DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING
  *  @generated
@@ -30,7 +30,7 @@ package org.apache.pinot.common.request;
  * Instance Request
  * 
  */
-@javax.annotation.Generated(value = "Autogenerated by Thrift Compiler (0.12.0)", date = "2019-07-19")
+@javax.annotation.Generated(value = "Autogenerated by Thrift Compiler (0.13.0)", date = "2020-10-31")
 public class InstanceRequest implements org.apache.thrift.TBase<InstanceRequest, InstanceRequest._Fields>, java.io.Serializable, Cloneable, Comparable<InstanceRequest> {
   private static final org.apache.thrift.protocol.TStruct STRUCT_DESC = new org.apache.thrift.protocol.TStruct("InstanceRequest");
 
@@ -43,11 +43,11 @@ public class InstanceRequest implements org.apache.thrift.TBase<InstanceRequest,
   private static final org.apache.thrift.scheme.SchemeFactory STANDARD_SCHEME_FACTORY = new InstanceRequestStandardSchemeFactory();
   private static final org.apache.thrift.scheme.SchemeFactory TUPLE_SCHEME_FACTORY = new InstanceRequestTupleSchemeFactory();
 
-  public long requestId; // required
-  public @org.apache.thrift.annotation.Nullable BrokerRequest query; // required
-  public @org.apache.thrift.annotation.Nullable java.util.List<java.lang.String> searchSegments; // optional
-  public boolean enableTrace; // optional
-  public @org.apache.thrift.annotation.Nullable java.lang.String brokerId; // optional
+  private long requestId; // required
+  private @org.apache.thrift.annotation.Nullable BrokerRequest query; // required
+  private @org.apache.thrift.annotation.Nullable java.util.List<java.lang.String> searchSegments; // optional
+  private boolean enableTrace; // optional
+  private @org.apache.thrift.annotation.Nullable java.lang.String brokerId; // optional
 
   /** The set of fields this struct contains, along with convenience methods for finding and manipulating them. */
   public enum _Fields implements org.apache.thrift.TFieldIdEnum {
@@ -195,10 +195,9 @@ public class InstanceRequest implements org.apache.thrift.TBase<InstanceRequest,
     return this.requestId;
   }
 
-  public InstanceRequest setRequestId(long requestId) {
+  public void setRequestId(long requestId) {
     this.requestId = requestId;
     setRequestIdIsSet(true);
-    return this;
   }
 
   public void unsetRequestId() {
@@ -219,9 +218,8 @@ public class InstanceRequest implements org.apache.thrift.TBase<InstanceRequest,
     return this.query;
   }
 
-  public InstanceRequest setQuery(@org.apache.thrift.annotation.Nullable BrokerRequest query) {
+  public void setQuery(@org.apache.thrift.annotation.Nullable BrokerRequest query) {
     this.query = query;
-    return this;
   }
 
   public void unsetQuery() {
@@ -260,9 +258,8 @@ public class InstanceRequest implements org.apache.thrift.TBase<InstanceRequest,
     return this.searchSegments;
   }
 
-  public InstanceRequest setSearchSegments(@org.apache.thrift.annotation.Nullable java.util.List<java.lang.String> searchSegments) {
+  public void setSearchSegments(@org.apache.thrift.annotation.Nullable java.util.List<java.lang.String> searchSegments) {
     this.searchSegments = searchSegments;
-    return this;
   }
 
   public void unsetSearchSegments() {
@@ -284,10 +281,9 @@ public class InstanceRequest implements org.apache.thrift.TBase<InstanceRequest,
     return this.enableTrace;
   }
 
-  public InstanceRequest setEnableTrace(boolean enableTrace) {
+  public void setEnableTrace(boolean enableTrace) {
     this.enableTrace = enableTrace;
     setEnableTraceIsSet(true);
-    return this;
   }
 
   public void unsetEnableTrace() {
@@ -308,9 +304,8 @@ public class InstanceRequest implements org.apache.thrift.TBase<InstanceRequest,
     return this.brokerId;
   }
 
-  public InstanceRequest setBrokerId(@org.apache.thrift.annotation.Nullable java.lang.String brokerId) {
+  public void setBrokerId(@org.apache.thrift.annotation.Nullable java.lang.String brokerId) {
     this.brokerId = brokerId;
-    return this;
   }
 
   public void unsetBrokerId() {
@@ -626,10 +621,14 @@ public class InstanceRequest implements org.apache.thrift.TBase<InstanceRequest,
 
   public void validate() throws org.apache.thrift.TException {
     // check for required fields
-    // alas, we cannot check 'requestId' because it's a primitive and you chose the non-beans generator.
-    if (query == null) {
-      throw new org.apache.thrift.protocol.TProtocolException("Required field 'query' was not present! Struct: " + toString());
+    if (!isSetRequestId()) {
+      throw new org.apache.thrift.protocol.TProtocolException("Required field 'requestId' is unset! Struct:" + toString());
     }
+
+    if (!isSetQuery()) {
+      throw new org.apache.thrift.protocol.TProtocolException("Required field 'query' is unset! Struct:" + toString());
+    }
+
     // check for sub-struct validity
     if (query != null) {
       query.validate();
@@ -692,13 +691,13 @@ public class InstanceRequest implements org.apache.thrift.TBase<InstanceRequest,
           case 3: // SEARCH_SEGMENTS
             if (schemeField.type == org.apache.thrift.protocol.TType.LIST) {
               {
-                org.apache.thrift.protocol.TList _list130 = iprot.readListBegin();
-                struct.searchSegments = new java.util.ArrayList<java.lang.String>(_list130.size);
-                @org.apache.thrift.annotation.Nullable java.lang.String _elem131;
-                for (int _i132 = 0; _i132 < _list130.size; ++_i132)
+                org.apache.thrift.protocol.TList _list138 = iprot.readListBegin();
+                struct.searchSegments = new java.util.ArrayList<java.lang.String>(_list138.size);
+                @org.apache.thrift.annotation.Nullable java.lang.String _elem139;
+                for (int _i140 = 0; _i140 < _list138.size; ++_i140)
                 {
-                  _elem131 = iprot.readString();
-                  struct.searchSegments.add(_elem131);
+                  _elem139 = iprot.readString();
+                  struct.searchSegments.add(_elem139);
                 }
                 iprot.readListEnd();
               }
@@ -729,11 +728,6 @@ public class InstanceRequest implements org.apache.thrift.TBase<InstanceRequest,
         iprot.readFieldEnd();
       }
       iprot.readStructEnd();
-
-      // check for required fields of primitive type, which can't be checked in the validate method
-      if (!struct.isSetRequestId()) {
-        throw new org.apache.thrift.protocol.TProtocolException("Required field 'requestId' was not found in serialized data! Struct: " + toString());
-      }
       struct.validate();
     }
 
@@ -754,9 +748,9 @@ public class InstanceRequest implements org.apache.thrift.TBase<InstanceRequest,
           oprot.writeFieldBegin(SEARCH_SEGMENTS_FIELD_DESC);
           {
             oprot.writeListBegin(new org.apache.thrift.protocol.TList(org.apache.thrift.protocol.TType.STRING, struct.searchSegments.size()));
-            for (java.lang.String _iter133 : struct.searchSegments)
+            for (java.lang.String _iter141 : struct.searchSegments)
             {
-              oprot.writeString(_iter133);
+              oprot.writeString(_iter141);
             }
             oprot.writeListEnd();
           }
@@ -808,9 +802,9 @@ public class InstanceRequest implements org.apache.thrift.TBase<InstanceRequest,
       if (struct.isSetSearchSegments()) {
         {
           oprot.writeI32(struct.searchSegments.size());
-          for (java.lang.String _iter134 : struct.searchSegments)
+          for (java.lang.String _iter142 : struct.searchSegments)
           {
-            oprot.writeString(_iter134);
+            oprot.writeString(_iter142);
           }
         }
       }
@@ -833,13 +827,13 @@ public class InstanceRequest implements org.apache.thrift.TBase<InstanceRequest,
       java.util.BitSet incoming = iprot.readBitSet(3);
       if (incoming.get(0)) {
         {
-          org.apache.thrift.protocol.TList _list135 = new org.apache.thrift.protocol.TList(org.apache.thrift.protocol.TType.STRING, iprot.readI32());
-          struct.searchSegments = new java.util.ArrayList<java.lang.String>(_list135.size);
-          @org.apache.thrift.annotation.Nullable java.lang.String _elem136;
-          for (int _i137 = 0; _i137 < _list135.size; ++_i137)
+          org.apache.thrift.protocol.TList _list143 = new org.apache.thrift.protocol.TList(org.apache.thrift.protocol.TType.STRING, iprot.readI32());
+          struct.searchSegments = new java.util.ArrayList<java.lang.String>(_list143.size);
+          @org.apache.thrift.annotation.Nullable java.lang.String _elem144;
+          for (int _i145 = 0; _i145 < _list143.size; ++_i145)
           {
-            _elem136 = iprot.readString();
-            struct.searchSegments.add(_elem136);
+            _elem144 = iprot.readString();
+            struct.searchSegments.add(_elem144);
           }
         }
         struct.setSearchSegmentsIsSet(true);
diff --git a/pinot-common/src/main/java/org/apache/pinot/common/request/Literal.java b/pinot-common/src/main/java/org/apache/pinot/common/request/Literal.java
index 7761eb4..5d25563 100644
--- a/pinot-common/src/main/java/org/apache/pinot/common/request/Literal.java
+++ b/pinot-common/src/main/java/org/apache/pinot/common/request/Literal.java
@@ -17,7 +17,7 @@
  * under the License.
  */
 /**
- * Autogenerated by Thrift Compiler (0.12.0)
+ * Autogenerated by Thrift Compiler (0.13.0)
  *
  * DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING
  *  @generated
@@ -25,7 +25,7 @@
 package org.apache.pinot.common.request;
 
 @SuppressWarnings({"cast", "rawtypes", "serial", "unchecked", "unused"})
-@javax.annotation.Generated(value = "Autogenerated by Thrift Compiler (0.12.0)", date = "2019-07-19")
+@javax.annotation.Generated(value = "Autogenerated by Thrift Compiler (0.13.0)", date = "2020-10-31")
 public class Literal extends org.apache.thrift.TUnion<Literal, Literal._Fields> {
   private static final org.apache.thrift.protocol.TStruct STRUCT_DESC = new org.apache.thrift.protocol.TStruct("Literal");
   private static final org.apache.thrift.protocol.TField BOOL_VALUE_FIELD_DESC = new org.apache.thrift.protocol.TField("boolValue", org.apache.thrift.protocol.TType.BOOL, (short)1);
diff --git a/pinot-common/src/main/java/org/apache/pinot/common/request/PinotQuery.java b/pinot-common/src/main/java/org/apache/pinot/common/request/PinotQuery.java
index 10f1242..42cc48d 100644
--- a/pinot-common/src/main/java/org/apache/pinot/common/request/PinotQuery.java
+++ b/pinot-common/src/main/java/org/apache/pinot/common/request/PinotQuery.java
@@ -17,7 +17,7 @@
  * under the License.
  */
 /**
- * Autogenerated by Thrift Compiler (0.12.0)
+ * Autogenerated by Thrift Compiler (0.13.0)
  *
  * DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING
  *  @generated
@@ -25,7 +25,7 @@
 package org.apache.pinot.common.request;
 
 @SuppressWarnings({"cast", "rawtypes", "serial", "unchecked", "unused"})
-@javax.annotation.Generated(value = "Autogenerated by Thrift Compiler (0.12.0)", date = "2019-07-19")
+@javax.annotation.Generated(value = "Autogenerated by Thrift Compiler (0.13.0)", date = "2020-10-31")
 public class PinotQuery implements org.apache.thrift.TBase<PinotQuery, PinotQuery._Fields>, java.io.Serializable, Cloneable, Comparable<PinotQuery> {
   private static final org.apache.thrift.protocol.TStruct STRUCT_DESC = new org.apache.thrift.protocol.TStruct("PinotQuery");
 
@@ -44,17 +44,17 @@ public class PinotQuery implements org.apache.thrift.TBase<PinotQuery, PinotQuer
   private static final org.apache.thrift.scheme.SchemeFactory STANDARD_SCHEME_FACTORY = new PinotQueryStandardSchemeFactory();
   private static final org.apache.thrift.scheme.SchemeFactory TUPLE_SCHEME_FACTORY = new PinotQueryTupleSchemeFactory();
 
-  public int version; // optional
-  public @org.apache.thrift.annotation.Nullable DataSource dataSource; // optional
-  public @org.apache.thrift.annotation.Nullable java.util.List<Expression> selectList; // optional
-  public @org.apache.thrift.annotation.Nullable Expression filterExpression; // optional
-  public @org.apache.thrift.annotation.Nullable java.util.List<Expression> groupByList; // optional
-  public @org.apache.thrift.annotation.Nullable java.util.List<Expression> orderByList; // optional
-  public @org.apache.thrift.annotation.Nullable Expression havingExpression; // optional
-  public int limit; // optional
-  public int offset; // optional
-  public @org.apache.thrift.annotation.Nullable java.util.Map<java.lang.String,java.lang.String> debugOptions; // optional
-  public @org.apache.thrift.annotation.Nullable java.util.Map<java.lang.String,java.lang.String> queryOptions; // optional
+  private int version; // optional
+  private @org.apache.thrift.annotation.Nullable DataSource dataSource; // optional
+  private @org.apache.thrift.annotation.Nullable java.util.List<Expression> selectList; // optional
+  private @org.apache.thrift.annotation.Nullable Expression filterExpression; // optional
+  private @org.apache.thrift.annotation.Nullable java.util.List<Expression> groupByList; // optional
+  private @org.apache.thrift.annotation.Nullable java.util.List<Expression> orderByList; // optional
+  private @org.apache.thrift.annotation.Nullable Expression havingExpression; // optional
+  private int limit; // optional
+  private int offset; // optional
+  private @org.apache.thrift.annotation.Nullable java.util.Map<java.lang.String,java.lang.String> debugOptions; // optional
+  private @org.apache.thrift.annotation.Nullable java.util.Map<java.lang.String,java.lang.String> queryOptions; // optional
 
   /** The set of fields this struct contains, along with convenience methods for finding and manipulating them. */
   public enum _Fields implements org.apache.thrift.TFieldIdEnum {
@@ -269,10 +269,9 @@ public class PinotQuery implements org.apache.thrift.TBase<PinotQuery, PinotQuer
     return this.version;
   }
 
-  public PinotQuery setVersion(int version) {
+  public void setVersion(int version) {
     this.version = version;
     setVersionIsSet(true);
-    return this;
   }
 
   public void unsetVersion() {
@@ -293,9 +292,8 @@ public class PinotQuery implements org.apache.thrift.TBase<PinotQuery, PinotQuer
     return this.dataSource;
   }
 
-  public PinotQuery setDataSource(@org.apache.thrift.annotation.Nullable DataSource dataSource) {
+  public void setDataSource(@org.apache.thrift.annotation.Nullable DataSource dataSource) {
     this.dataSource = dataSource;
-    return this;
   }
 
   public void unsetDataSource() {
@@ -334,9 +332,8 @@ public class PinotQuery implements org.apache.thrift.TBase<PinotQuery, PinotQuer
     return this.selectList;
   }
 
-  public PinotQuery setSelectList(@org.apache.thrift.annotation.Nullable java.util.List<Expression> selectList) {
+  public void setSelectList(@org.apache.thrift.annotation.Nullable java.util.List<Expression> selectList) {
     this.selectList = selectList;
-    return this;
   }
 
   public void unsetSelectList() {
@@ -359,9 +356,8 @@ public class PinotQuery implements org.apache.thrift.TBase<PinotQuery, PinotQuer
     return this.filterExpression;
   }
 
-  public PinotQuery setFilterExpression(@org.apache.thrift.annotation.Nullable Expression filterExpression) {
+  public void setFilterExpression(@org.apache.thrift.annotation.Nullable Expression filterExpression) {
     this.filterExpression = filterExpression;
-    return this;
   }
 
   public void unsetFilterExpression() {
@@ -400,9 +396,8 @@ public class PinotQuery implements org.apache.thrift.TBase<PinotQuery, PinotQuer
     return this.groupByList;
   }
 
-  public PinotQuery setGroupByList(@org.apache.thrift.annotation.Nullable java.util.List<Expression> groupByList) {
+  public void setGroupByList(@org.apache.thrift.annotation.Nullable java.util.List<Expression> groupByList) {
     this.groupByList = groupByList;
-    return this;
   }
 
   public void unsetGroupByList() {
@@ -441,9 +436,8 @@ public class PinotQuery implements org.apache.thrift.TBase<PinotQuery, PinotQuer
     return this.orderByList;
   }
 
-  public PinotQuery setOrderByList(@org.apache.thrift.annotation.Nullable java.util.List<Expression> orderByList) {
+  public void setOrderByList(@org.apache.thrift.annotation.Nullable java.util.List<Expression> orderByList) {
     this.orderByList = orderByList;
-    return this;
   }
 
   public void unsetOrderByList() {
@@ -466,9 +460,8 @@ public class PinotQuery implements org.apache.thrift.TBase<PinotQuery, PinotQuer
     return this.havingExpression;
   }
 
-  public PinotQuery setHavingExpression(@org.apache.thrift.annotation.Nullable Expression havingExpression) {
+  public void setHavingExpression(@org.apache.thrift.annotation.Nullable Expression havingExpression) {
     this.havingExpression = havingExpression;
-    return this;
   }
 
   public void unsetHavingExpression() {
@@ -490,10 +483,9 @@ public class PinotQuery implements org.apache.thrift.TBase<PinotQuery, PinotQuer
     return this.limit;
   }
 
-  public PinotQuery setLimit(int limit) {
+  public void setLimit(int limit) {
     this.limit = limit;
     setLimitIsSet(true);
-    return this;
   }
 
   public void unsetLimit() {
@@ -513,10 +505,9 @@ public class PinotQuery implements org.apache.thrift.TBase<PinotQuery, PinotQuer
     return this.offset;
   }
 
-  public PinotQuery setOffset(int offset) {
+  public void setOffset(int offset) {
     this.offset = offset;
     setOffsetIsSet(true);
-    return this;
   }
 
   public void unsetOffset() {
@@ -548,9 +539,8 @@ public class PinotQuery implements org.apache.thrift.TBase<PinotQuery, PinotQuer
     return this.debugOptions;
   }
 
-  public PinotQuery setDebugOptions(@org.apache.thrift.annotation.Nullable java.util.Map<java.lang.String,java.lang.String> debugOptions) {
+  public void setDebugOptions(@org.apache.thrift.annotation.Nullable java.util.Map<java.lang.String,java.lang.String> debugOptions) {
     this.debugOptions = debugOptions;
-    return this;
   }
 
   public void unsetDebugOptions() {
@@ -584,9 +574,8 @@ public class PinotQuery implements org.apache.thrift.TBase<PinotQuery, PinotQuer
     return this.queryOptions;
   }
 
-  public PinotQuery setQueryOptions(@org.apache.thrift.annotation.Nullable java.util.Map<java.lang.String,java.lang.String> queryOptions) {
+  public void setQueryOptions(@org.apache.thrift.annotation.Nullable java.util.Map<java.lang.String,java.lang.String> queryOptions) {
     this.queryOptions = queryOptions;
-    return this;
   }
 
   public void unsetQueryOptions() {
@@ -1376,8 +1365,6 @@ public class PinotQuery implements org.apache.thrift.TBase<PinotQuery, PinotQuer
         iprot.readFieldEnd();
       }
       iprot.readStructEnd();
-
-      // check for required fields of primitive type, which can't be checked in the validate method
       struct.validate();
     }
 
diff --git a/pinot-common/src/main/java/org/apache/pinot/common/request/QuerySource.java b/pinot-common/src/main/java/org/apache/pinot/common/request/QuerySource.java
index 2ca4d62..49ca8ae 100644
--- a/pinot-common/src/main/java/org/apache/pinot/common/request/QuerySource.java
+++ b/pinot-common/src/main/java/org/apache/pinot/common/request/QuerySource.java
@@ -17,7 +17,7 @@
  * under the License.
  */
 /**
- * Autogenerated by Thrift Compiler (0.12.0)
+ * Autogenerated by Thrift Compiler (0.13.0)
  *
  * DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING
  *  @generated
@@ -30,7 +30,7 @@ package org.apache.pinot.common.request;
  * Query source
  * 
  */
-@javax.annotation.Generated(value = "Autogenerated by Thrift Compiler (0.12.0)", date = "2019-07-19")
+@javax.annotation.Generated(value = "Autogenerated by Thrift Compiler (0.13.0)", date = "2020-10-31")
 public class QuerySource implements org.apache.thrift.TBase<QuerySource, QuerySource._Fields>, java.io.Serializable, Cloneable, Comparable<QuerySource> {
   private static final org.apache.thrift.protocol.TStruct STRUCT_DESC = new org.apache.thrift.protocol.TStruct("QuerySource");
 
@@ -39,7 +39,7 @@ public class QuerySource implements org.apache.thrift.TBase<QuerySource, QuerySo
   private static final org.apache.thrift.scheme.SchemeFactory STANDARD_SCHEME_FACTORY = new QuerySourceStandardSchemeFactory();
   private static final org.apache.thrift.scheme.SchemeFactory TUPLE_SCHEME_FACTORY = new QuerySourceTupleSchemeFactory();
 
-  public @org.apache.thrift.annotation.Nullable java.lang.String tableName; // optional
+  private @org.apache.thrift.annotation.Nullable java.lang.String tableName; // optional
 
   /** The set of fields this struct contains, along with convenience methods for finding and manipulating them. */
   public enum _Fields implements org.apache.thrift.TFieldIdEnum {
@@ -138,9 +138,8 @@ public class QuerySource implements org.apache.thrift.TBase<QuerySource, QuerySo
     return this.tableName;
   }
 
-  public QuerySource setTableName(@org.apache.thrift.annotation.Nullable java.lang.String tableName) {
+  public void setTableName(@org.apache.thrift.annotation.Nullable java.lang.String tableName) {
     this.tableName = tableName;
-    return this;
   }
 
   public void unsetTableName() {
@@ -337,8 +336,6 @@ public class QuerySource implements org.apache.thrift.TBase<QuerySource, QuerySo
         iprot.readFieldEnd();
       }
       iprot.readStructEnd();
-
-      // check for required fields of primitive type, which can't be checked in the validate method
       struct.validate();
     }
 
diff --git a/pinot-common/src/main/java/org/apache/pinot/common/request/QueryType.java b/pinot-common/src/main/java/org/apache/pinot/common/request/QueryType.java
index d7acfac..5a5ecfd 100644
--- a/pinot-common/src/main/java/org/apache/pinot/common/request/QueryType.java
+++ b/pinot-common/src/main/java/org/apache/pinot/common/request/QueryType.java
@@ -17,7 +17,7 @@
  * under the License.
  */
 /**
- * Autogenerated by Thrift Compiler (0.12.0)
+ * Autogenerated by Thrift Compiler (0.13.0)
  *
  * DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING
  *  @generated
@@ -30,7 +30,7 @@ package org.apache.pinot.common.request;
  *  Query type
  * 
  */
-@javax.annotation.Generated(value = "Autogenerated by Thrift Compiler (0.12.0)", date = "2019-07-19")
+@javax.annotation.Generated(value = "Autogenerated by Thrift Compiler (0.13.0)", date = "2020-10-31")
 public class QueryType implements org.apache.thrift.TBase<QueryType, QueryType._Fields>, java.io.Serializable, Cloneable, Comparable<QueryType> {
   private static final org.apache.thrift.protocol.TStruct STRUCT_DESC = new org.apache.thrift.protocol.TStruct("QueryType");
 
@@ -43,11 +43,11 @@ public class QueryType implements org.apache.thrift.TBase<QueryType, QueryType._
   private static final org.apache.thrift.scheme.SchemeFactory STANDARD_SCHEME_FACTORY = new QueryTypeStandardSchemeFactory();
   private static final org.apache.thrift.scheme.SchemeFactory TUPLE_SCHEME_FACTORY = new QueryTypeTupleSchemeFactory();
 
-  public boolean hasSelection; // optional
-  public boolean hasFilter; // optional
-  public boolean hasAggregation; // optional
-  public boolean hasGroup_by; // optional
-  public boolean hasHaving; // optional
+  private boolean hasSelection; // optional
+  private boolean hasFilter; // optional
+  private boolean hasAggregation; // optional
+  private boolean hasGroup_by; // optional
+  private boolean hasHaving; // optional
 
   /** The set of fields this struct contains, along with convenience methods for finding and manipulating them. */
   public enum _Fields implements org.apache.thrift.TFieldIdEnum {
@@ -183,10 +183,9 @@ public class QueryType implements org.apache.thrift.TBase<QueryType, QueryType._
     return this.hasSelection;
   }
 
-  public QueryType setHasSelection(boolean hasSelection) {
+  public void setHasSelection(boolean hasSelection) {
     this.hasSelection = hasSelection;
     setHasSelectionIsSet(true);
-    return this;
   }
 
   public void unsetHasSelection() {
@@ -206,10 +205,9 @@ public class QueryType implements org.apache.thrift.TBase<QueryType, QueryType._
     return this.hasFilter;
   }
 
-  public QueryType setHasFilter(boolean hasFilter) {
+  public void setHasFilter(boolean hasFilter) {
     this.hasFilter = hasFilter;
     setHasFilterIsSet(true);
-    return this;
   }
 
   public void unsetHasFilter() {
@@ -229,10 +227,9 @@ public class QueryType implements org.apache.thrift.TBase<QueryType, QueryType._
     return this.hasAggregation;
   }
 
-  public QueryType setHasAggregation(boolean hasAggregation) {
+  public void setHasAggregation(boolean hasAggregation) {
     this.hasAggregation = hasAggregation;
     setHasAggregationIsSet(true);
-    return this;
   }
 
   public void unsetHasAggregation() {
@@ -252,10 +249,9 @@ public class QueryType implements org.apache.thrift.TBase<QueryType, QueryType._
     return this.hasGroup_by;
   }
 
-  public QueryType setHasGroup_by(boolean hasGroup_by) {
+  public void setHasGroup_by(boolean hasGroup_by) {
     this.hasGroup_by = hasGroup_by;
     setHasGroup_byIsSet(true);
-    return this;
   }
 
   public void unsetHasGroup_by() {
@@ -275,10 +271,9 @@ public class QueryType implements org.apache.thrift.TBase<QueryType, QueryType._
     return this.hasHaving;
   }
 
-  public QueryType setHasHaving(boolean hasHaving) {
+  public void setHasHaving(boolean hasHaving) {
     this.hasHaving = hasHaving;
     setHasHavingIsSet(true);
-    return this;
   }
 
   public void unsetHasHaving() {
@@ -671,8 +666,6 @@ public class QueryType implements org.apache.thrift.TBase<QueryType, QueryType._
         iprot.readFieldEnd();
       }
       iprot.readStructEnd();
-
-      // check for required fields of primitive type, which can't be checked in the validate method
       struct.validate();
     }
 
diff --git a/pinot-common/src/main/java/org/apache/pinot/common/request/Selection.java b/pinot-common/src/main/java/org/apache/pinot/common/request/Selection.java
index c607038..05b89b5 100644
--- a/pinot-common/src/main/java/org/apache/pinot/common/request/Selection.java
+++ b/pinot-common/src/main/java/org/apache/pinot/common/request/Selection.java
@@ -17,7 +17,7 @@
  * under the License.
  */
 /**
- * Autogenerated by Thrift Compiler (0.12.0)
+ * Autogenerated by Thrift Compiler (0.13.0)
  *
  * DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING
  *  @generated
@@ -30,7 +30,7 @@ package org.apache.pinot.common.request;
  * Selection
  * 
  */
-@javax.annotation.Generated(value = "Autogenerated by Thrift Compiler (0.12.0)", date = "2019-07-19")
+@javax.annotation.Generated(value = "Autogenerated by Thrift Compiler (0.13.0)", date = "2020-10-31")
 public class Selection implements org.apache.thrift.TBase<Selection, Selection._Fields>, java.io.Serializable, Cloneable, Comparable<Selection> {
   private static final org.apache.thrift.protocol.TStruct STRUCT_DESC = new org.apache.thrift.protocol.TStruct("Selection");
 
@@ -42,10 +42,10 @@ public class Selection implements org.apache.thrift.TBase<Selection, Selection._
   private static final org.apache.thrift.scheme.SchemeFactory STANDARD_SCHEME_FACTORY = new SelectionStandardSchemeFactory();
   private static final org.apache.thrift.scheme.SchemeFactory TUPLE_SCHEME_FACTORY = new SelectionTupleSchemeFactory();
 
-  public @org.apache.thrift.annotation.Nullable java.util.List<java.lang.String> selectionColumns; // optional
-  public @org.apache.thrift.annotation.Nullable java.util.List<SelectionSort> selectionSortSequence; // optional
-  public int offset; // optional
-  public int size; // optional
+  private @org.apache.thrift.annotation.Nullable java.util.List<java.lang.String> selectionColumns; // optional
+  private @org.apache.thrift.annotation.Nullable java.util.List<SelectionSort> selectionSortSequence; // optional
+  private int offset; // optional
+  private int size; // optional
 
   /** The set of fields this struct contains, along with convenience methods for finding and manipulating them. */
   public enum _Fields implements org.apache.thrift.TFieldIdEnum {
@@ -200,9 +200,8 @@ public class Selection implements org.apache.thrift.TBase<Selection, Selection._
     return this.selectionColumns;
   }
 
-  public Selection setSelectionColumns(@org.apache.thrift.annotation.Nullable java.util.List<java.lang.String> selectionColumns) {
+  public void setSelectionColumns(@org.apache.thrift.annotation.Nullable java.util.List<java.lang.String> selectionColumns) {
     this.selectionColumns = selectionColumns;
-    return this;
   }
 
   public void unsetSelectionColumns() {
@@ -241,9 +240,8 @@ public class Selection implements org.apache.thrift.TBase<Selection, Selection._
     return this.selectionSortSequence;
   }
 
-  public Selection setSelectionSortSequence(@org.apache.thrift.annotation.Nullable java.util.List<SelectionSort> selectionSortSequence) {
+  public void setSelectionSortSequence(@org.apache.thrift.annotation.Nullable java.util.List<SelectionSort> selectionSortSequence) {
     this.selectionSortSequence = selectionSortSequence;
-    return this;
   }
 
   public void unsetSelectionSortSequence() {
@@ -265,10 +263,9 @@ public class Selection implements org.apache.thrift.TBase<Selection, Selection._
     return this.offset;
   }
 
-  public Selection setOffset(int offset) {
+  public void setOffset(int offset) {
     this.offset = offset;
     setOffsetIsSet(true);
-    return this;
   }
 
   public void unsetOffset() {
@@ -288,10 +285,9 @@ public class Selection implements org.apache.thrift.TBase<Selection, Selection._
     return this.size;
   }
 
-  public Selection setSize(int size) {
+  public void setSize(int size) {
     this.size = size;
     setSizeIsSet(true);
-    return this;
   }
 
   public void unsetSize() {
@@ -607,13 +603,13 @@ public class Selection implements org.apache.thrift.TBase<Selection, Selection._
           case 1: // SELECTION_COLUMNS
             if (schemeField.type == org.apache.thrift.protocol.TType.LIST) {
               {
-                org.apache.thrift.protocol.TList _list78 = iprot.readListBegin();
-                struct.selectionColumns = new java.util.ArrayList<java.lang.String>(_list78.size);
-                @org.apache.thrift.annotation.Nullable java.lang.String _elem79;
-                for (int _i80 = 0; _i80 < _list78.size; ++_i80)
+                org.apache.thrift.protocol.TList _list86 = iprot.readListBegin();
+                struct.selectionColumns = new java.util.ArrayList<java.lang.String>(_list86.size);
+                @org.apache.thrift.annotation.Nullable java.lang.String _elem87;
+                for (int _i88 = 0; _i88 < _list86.size; ++_i88)
                 {
-                  _elem79 = iprot.readString();
-                  struct.selectionColumns.add(_elem79);
+                  _elem87 = iprot.readString();
+                  struct.selectionColumns.add(_elem87);
                 }
                 iprot.readListEnd();
               }
@@ -625,14 +621,14 @@ public class Selection implements org.apache.thrift.TBase<Selection, Selection._
           case 2: // SELECTION_SORT_SEQUENCE
             if (schemeField.type == org.apache.thrift.protocol.TType.LIST) {
               {
-                org.apache.thrift.protocol.TList _list81 = iprot.readListBegin();
-                struct.selectionSortSequence = new java.util.ArrayList<SelectionSort>(_list81.size);
-                @org.apache.thrift.annotation.Nullable SelectionSort _elem82;
-                for (int _i83 = 0; _i83 < _list81.size; ++_i83)
+                org.apache.thrift.protocol.TList _list89 = iprot.readListBegin();
+                struct.selectionSortSequence = new java.util.ArrayList<SelectionSort>(_list89.size);
+                @org.apache.thrift.annotation.Nullable SelectionSort _elem90;
+                for (int _i91 = 0; _i91 < _list89.size; ++_i91)
                 {
-                  _elem82 = new SelectionSort();
-                  _elem82.read(iprot);
-                  struct.selectionSortSequence.add(_elem82);
+                  _elem90 = new SelectionSort();
+                  _elem90.read(iprot);
+                  struct.selectionSortSequence.add(_elem90);
                 }
                 iprot.readListEnd();
               }
@@ -663,8 +659,6 @@ public class Selection implements org.apache.thrift.TBase<Selection, Selection._
         iprot.readFieldEnd();
       }
       iprot.readStructEnd();
-
-      // check for required fields of primitive type, which can't be checked in the validate method
       struct.validate();
     }
 
@@ -677,9 +671,9 @@ public class Selection implements org.apache.thrift.TBase<Selection, Selection._
           oprot.writeFieldBegin(SELECTION_COLUMNS_FIELD_DESC);
           {
             oprot.writeListBegin(new org.apache.thrift.protocol.TList(org.apache.thrift.protocol.TType.STRING, struct.selectionColumns.size()));
-            for (java.lang.String _iter84 : struct.selectionColumns)
+            for (java.lang.String _iter92 : struct.selectionColumns)
             {
-              oprot.writeString(_iter84);
+              oprot.writeString(_iter92);
             }
             oprot.writeListEnd();
           }
@@ -691,9 +685,9 @@ public class Selection implements org.apache.thrift.TBase<Selection, Selection._
           oprot.writeFieldBegin(SELECTION_SORT_SEQUENCE_FIELD_DESC);
           {
             oprot.writeListBegin(new org.apache.thrift.protocol.TList(org.apache.thrift.protocol.TType.STRUCT, struct.selectionSortSequence.size()));
-            for (SelectionSort _iter85 : struct.selectionSortSequence)
+            for (SelectionSort _iter93 : struct.selectionSortSequence)
             {
-              _iter85.write(oprot);
+              _iter93.write(oprot);
             }
             oprot.writeListEnd();
           }
@@ -744,18 +738,18 @@ public class Selection implements org.apache.thrift.TBase<Selection, Selection._
       if (struct.isSetSelectionColumns()) {
         {
           oprot.writeI32(struct.selectionColumns.size());
-          for (java.lang.String _iter86 : struct.selectionColumns)
+          for (java.lang.String _iter94 : struct.selectionColumns)
           {
-            oprot.writeString(_iter86);
+            oprot.writeString(_iter94);
           }
         }
       }
       if (struct.isSetSelectionSortSequence()) {
         {
           oprot.writeI32(struct.selectionSortSequence.size());
-          for (SelectionSort _iter87 : struct.selectionSortSequence)
+          for (SelectionSort _iter95 : struct.selectionSortSequence)
           {
-            _iter87.write(oprot);
+            _iter95.write(oprot);
           }
         }
       }
@@ -773,27 +767,27 @@ public class Selection implements org.apache.thrift.TBase<Selection, Selection._
       java.util.BitSet incoming = iprot.readBitSet(4);
       if (incoming.get(0)) {
         {
-          org.apache.thrift.protocol.TList _list88 = new org.apache.thrift.protocol.TList(org.apache.thrift.protocol.TType.STRING, iprot.readI32());
-          struct.selectionColumns = new java.util.ArrayList<java.lang.String>(_list88.size);
-          @org.apache.thrift.annotation.Nullable java.lang.String _elem89;
-          for (int _i90 = 0; _i90 < _list88.size; ++_i90)
+          org.apache.thrift.protocol.TList _list96 = new org.apache.thrift.protocol.TList(org.apache.thrift.protocol.TType.STRING, iprot.readI32());
+          struct.selectionColumns = new java.util.ArrayList<java.lang.String>(_list96.size);
+          @org.apache.thrift.annotation.Nullable java.lang.String _elem97;
+          for (int _i98 = 0; _i98 < _list96.size; ++_i98)
           {
-            _elem89 = iprot.readString();
-            struct.selectionColumns.add(_elem89);
+            _elem97 = iprot.readString();
+            struct.selectionColumns.add(_elem97);
           }
         }
         struct.setSelectionColumnsIsSet(true);
       }
       if (incoming.get(1)) {
         {
-          org.apache.thrift.protocol.TList _list91 = new org.apache.thrift.protocol.TList(org.apache.thrift.protocol.TType.STRUCT, iprot.readI32());
-          struct.selectionSortSequence = new java.util.ArrayList<SelectionSort>(_list91.size);
-          @org.apache.thrift.annotation.Nullable SelectionSort _elem92;
-          for (int _i93 = 0; _i93 < _list91.size; ++_i93)
+          org.apache.thrift.protocol.TList _list99 = new org.apache.thrift.protocol.TList(org.apache.thrift.protocol.TType.STRUCT, iprot.readI32());
+          struct.selectionSortSequence = new java.util.ArrayList<SelectionSort>(_list99.size);
+          @org.apache.thrift.annotation.Nullable SelectionSort _elem100;
+          for (int _i101 = 0; _i101 < _list99.size; ++_i101)
           {
-            _elem92 = new SelectionSort();
-            _elem92.read(iprot);
-            struct.selectionSortSequence.add(_elem92);
+            _elem100 = new SelectionSort();
+            _elem100.read(iprot);
+            struct.selectionSortSequence.add(_elem100);
           }
         }
         struct.setSelectionSortSequenceIsSet(true);
diff --git a/pinot-common/src/main/java/org/apache/pinot/common/request/SelectionSort.java b/pinot-common/src/main/java/org/apache/pinot/common/request/SelectionSort.java
index dc79a52..c9c599b 100644
--- a/pinot-common/src/main/java/org/apache/pinot/common/request/SelectionSort.java
+++ b/pinot-common/src/main/java/org/apache/pinot/common/request/SelectionSort.java
@@ -17,7 +17,7 @@
  * under the License.
  */
 /**
- * Autogenerated by Thrift Compiler (0.12.0)
+ * Autogenerated by Thrift Compiler (0.13.0)
  *
  * DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING
  *  @generated
@@ -31,7 +31,7 @@ package org.apache.pinot.common.request;
  * The results can be sorted based on one or multiple columns
  * 
  */
-@javax.annotation.Generated(value = "Autogenerated by Thrift Compiler (0.12.0)", date = "2019-07-19")
+@javax.annotation.Generated(value = "Autogenerated by Thrift Compiler (0.13.0)", date = "2020-10-31")
 public class SelectionSort implements org.apache.thrift.TBase<SelectionSort, SelectionSort._Fields>, java.io.Serializable, Cloneable, Comparable<SelectionSort> {
   private static final org.apache.thrift.protocol.TStruct STRUCT_DESC = new org.apache.thrift.protocol.TStruct("SelectionSort");
 
@@ -41,8 +41,8 @@ public class SelectionSort implements org.apache.thrift.TBase<SelectionSort, Sel
   private static final org.apache.thrift.scheme.SchemeFactory STANDARD_SCHEME_FACTORY = new SelectionSortStandardSchemeFactory();
   private static final org.apache.thrift.scheme.SchemeFactory TUPLE_SCHEME_FACTORY = new SelectionSortTupleSchemeFactory();
 
-  public @org.apache.thrift.annotation.Nullable java.lang.String column; // optional
-  public boolean isAsc; // optional
+  private @org.apache.thrift.annotation.Nullable java.lang.String column; // optional
+  private boolean isAsc; // optional
 
   /** The set of fields this struct contains, along with convenience methods for finding and manipulating them. */
   public enum _Fields implements org.apache.thrift.TFieldIdEnum {
@@ -152,9 +152,8 @@ public class SelectionSort implements org.apache.thrift.TBase<SelectionSort, Sel
     return this.column;
   }
 
-  public SelectionSort setColumn(@org.apache.thrift.annotation.Nullable java.lang.String column) {
+  public void setColumn(@org.apache.thrift.annotation.Nullable java.lang.String column) {
     this.column = column;
-    return this;
   }
 
   public void unsetColumn() {
@@ -176,10 +175,9 @@ public class SelectionSort implements org.apache.thrift.TBase<SelectionSort, Sel
     return this.isAsc;
   }
 
-  public SelectionSort setIsAsc(boolean isAsc) {
+  public void setIsAsc(boolean isAsc) {
     this.isAsc = isAsc;
     setIsAscIsSet(true);
-    return this;
   }
 
   public void unsetIsAsc() {
@@ -426,8 +424,6 @@ public class SelectionSort implements org.apache.thrift.TBase<SelectionSort, Sel
         iprot.readFieldEnd();
       }
       iprot.readStructEnd();
-
-      // check for required fields of primitive type, which can't be checked in the validate method
       struct.validate();
     }
 
diff --git a/pinot-common/src/main/java/org/apache/pinot/common/response/ProcessingException.java b/pinot-common/src/main/java/org/apache/pinot/common/response/ProcessingException.java
index 1338363..2ac8c04 100644
--- a/pinot-common/src/main/java/org/apache/pinot/common/response/ProcessingException.java
+++ b/pinot-common/src/main/java/org/apache/pinot/common/response/ProcessingException.java
@@ -17,65 +17,40 @@
  * under the License.
  */
 /**
- * Autogenerated by Thrift Compiler (0.9.3)
+ * Autogenerated by Thrift Compiler (0.13.0)
  *
  * DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING
  *  @generated
  */
 package org.apache.pinot.common.response;
 
-import java.util.ArrayList;
-import java.util.BitSet;
-import java.util.Collections;
-import java.util.EnumMap;
-import java.util.EnumSet;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import javax.annotation.Generated;
-import org.apache.thrift.EncodingUtils;
-import org.apache.thrift.TException;
-import org.apache.thrift.protocol.TTupleProtocol;
-import org.apache.thrift.scheme.IScheme;
-import org.apache.thrift.scheme.SchemeFactory;
-import org.apache.thrift.scheme.StandardScheme;
-import org.apache.thrift.scheme.TupleScheme;
-
-
-@SuppressWarnings({"cast", "rawtypes", "serial", "unchecked"})
+@SuppressWarnings({"cast", "rawtypes", "serial", "unchecked", "unused"})
 /**
  * Processing exception
- *
+ * 
  */
-@Generated(value = "Autogenerated by Thrift Compiler (0.9.3)", date = "2019-06-06")
-public class ProcessingException extends TException implements org.apache.thrift.TBase<ProcessingException, ProcessingException._Fields>, java.io.Serializable, Cloneable, Comparable<ProcessingException> {
-  private static final org.apache.thrift.protocol.TStruct STRUCT_DESC =
-      new org.apache.thrift.protocol.TStruct("ProcessingException");
-
-  private static final org.apache.thrift.protocol.TField ERROR_CODE_FIELD_DESC =
-      new org.apache.thrift.protocol.TField("errorCode", org.apache.thrift.protocol.TType.I32, (short) 1);
-  private static final org.apache.thrift.protocol.TField MESSAGE_FIELD_DESC =
-      new org.apache.thrift.protocol.TField("message", org.apache.thrift.protocol.TType.STRING, (short) 2);
+@javax.annotation.Generated(value = "Autogenerated by Thrift Compiler (0.13.0)", date = "2020-10-31")
+public class ProcessingException extends org.apache.thrift.TException implements org.apache.thrift.TBase<ProcessingException, ProcessingException._Fields>, java.io.Serializable, Cloneable, Comparable<ProcessingException> {
+  private static final org.apache.thrift.protocol.TStruct STRUCT_DESC = new org.apache.thrift.protocol.TStruct("ProcessingException");
 
-  private static final Map<Class<? extends IScheme>, SchemeFactory> schemes =
-      new HashMap<Class<? extends IScheme>, SchemeFactory>();
+  private static final org.apache.thrift.protocol.TField ERROR_CODE_FIELD_DESC = new org.apache.thrift.protocol.TField("errorCode", org.apache.thrift.protocol.TType.I32, (short)1);
+  private static final org.apache.thrift.protocol.TField MESSAGE_FIELD_DESC = new org.apache.thrift.protocol.TField("message", org.apache.thrift.protocol.TType.STRING, (short)2);
 
-  static {
-    schemes.put(StandardScheme.class, new ProcessingExceptionStandardSchemeFactory());
-    schemes.put(TupleScheme.class, new ProcessingExceptionTupleSchemeFactory());
-  }
+  private static final org.apache.thrift.scheme.SchemeFactory STANDARD_SCHEME_FACTORY = new ProcessingExceptionStandardSchemeFactory();
+  private static final org.apache.thrift.scheme.SchemeFactory TUPLE_SCHEME_FACTORY = new ProcessingExceptionTupleSchemeFactory();
 
   private int errorCode; // required
-  private String message; // optional
+  private @org.apache.thrift.annotation.Nullable java.lang.String message; // optional
 
   /** The set of fields this struct contains, along with convenience methods for finding and manipulating them. */
   public enum _Fields implements org.apache.thrift.TFieldIdEnum {
-    ERROR_CODE((short) 1, "errorCode"), MESSAGE((short) 2, "message");
+    ERROR_CODE((short)1, "errorCode"),
+    MESSAGE((short)2, "message");
 
-    private static final Map<String, _Fields> byName = new HashMap<String, _Fields>();
+    private static final java.util.Map<java.lang.String, _Fields> byName = new java.util.HashMap<java.lang.String, _Fields>();
 
     static {
-      for (_Fields field : EnumSet.allOf(_Fields.class)) {
+      for (_Fields field : java.util.EnumSet.allOf(_Fields.class)) {
         byName.put(field.getFieldName(), field);
       }
     }
@@ -83,8 +58,9 @@ public class ProcessingException extends TException implements org.apache.thrift
     /**
      * Find the _Fields constant that matches fieldId, or null if its not found.
      */
+    @org.apache.thrift.annotation.Nullable
     public static _Fields findByThriftId(int fieldId) {
-      switch (fieldId) {
+      switch(fieldId) {
         case 1: // ERROR_CODE
           return ERROR_CODE;
         case 2: // MESSAGE
@@ -100,23 +76,22 @@ public class ProcessingException extends TException implements org.apache.thrift
      */
     public static _Fields findByThriftIdOrThrow(int fieldId) {
       _Fields fields = findByThriftId(fieldId);
-      if (fields == null) {
-        throw new IllegalArgumentException("Field " + fieldId + " doesn't exist!");
-      }
+      if (fields == null) throw new java.lang.IllegalArgumentException("Field " + fieldId + " doesn't exist!");
       return fields;
     }
 
     /**
      * Find the _Fields constant that matches name, or null if its not found.
      */
-    public static _Fields findByName(String name) {
+    @org.apache.thrift.annotation.Nullable
+    public static _Fields findByName(java.lang.String name) {
       return byName.get(name);
     }
 
     private final short _thriftId;
-    private final String _fieldName;
+    private final java.lang.String _fieldName;
 
-    _Fields(short thriftId, String fieldName) {
+    _Fields(short thriftId, java.lang.String fieldName) {
       _thriftId = thriftId;
       _fieldName = fieldName;
     }
@@ -125,7 +100,7 @@ public class ProcessingException extends TException implements org.apache.thrift
       return _thriftId;
     }
 
-    public String getFieldName() {
+    public java.lang.String getFieldName() {
       return _fieldName;
     }
   }
@@ -134,25 +109,23 @@ public class ProcessingException extends TException implements org.apache.thrift
   private static final int __ERRORCODE_ISSET_ID = 0;
   private byte __isset_bitfield = 0;
   private static final _Fields optionals[] = {_Fields.MESSAGE};
-  public static final Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> metaDataMap;
-
+  public static final java.util.Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> metaDataMap;
   static {
-    Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> tmpMap =
-        new EnumMap<_Fields, org.apache.thrift.meta_data.FieldMetaData>(_Fields.class);
-    tmpMap.put(_Fields.ERROR_CODE,
-        new org.apache.thrift.meta_data.FieldMetaData("errorCode", org.apache.thrift.TFieldRequirementType.REQUIRED,
-            new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.I32)));
-    tmpMap.put(_Fields.MESSAGE,
-        new org.apache.thrift.meta_data.FieldMetaData("message", org.apache.thrift.TFieldRequirementType.OPTIONAL,
-            new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.STRING)));
-    metaDataMap = Collections.unmodifiableMap(tmpMap);
+    java.util.Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> tmpMap = new java.util.EnumMap<_Fields, org.apache.thrift.meta_data.FieldMetaData>(_Fields.class);
+    tmpMap.put(_Fields.ERROR_CODE, new org.apache.thrift.meta_data.FieldMetaData("errorCode", org.apache.thrift.TFieldRequirementType.REQUIRED, 
+        new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.I32)));
+    tmpMap.put(_Fields.MESSAGE, new org.apache.thrift.meta_data.FieldMetaData("message", org.apache.thrift.TFieldRequirementType.OPTIONAL, 
+        new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.STRING)));
+    metaDataMap = java.util.Collections.unmodifiableMap(tmpMap);
     org.apache.thrift.meta_data.FieldMetaData.addStructMetaDataMap(ProcessingException.class, metaDataMap);
   }
 
   public ProcessingException() {
   }
 
-  public ProcessingException(int errorCode) {
+  public ProcessingException(
+    int errorCode)
+  {
     this();
     this.errorCode = errorCode;
     setErrorCodeIsSet(true);
@@ -190,23 +163,24 @@ public class ProcessingException extends TException implements org.apache.thrift
   }
 
   public void unsetErrorCode() {
-    __isset_bitfield = EncodingUtils.clearBit(__isset_bitfield, __ERRORCODE_ISSET_ID);
+    __isset_bitfield = org.apache.thrift.EncodingUtils.clearBit(__isset_bitfield, __ERRORCODE_ISSET_ID);
   }
 
   /** Returns true if field errorCode is set (has been assigned a value) and false otherwise */
   public boolean isSetErrorCode() {
-    return EncodingUtils.testBit(__isset_bitfield, __ERRORCODE_ISSET_ID);
+    return org.apache.thrift.EncodingUtils.testBit(__isset_bitfield, __ERRORCODE_ISSET_ID);
   }
 
   public void setErrorCodeIsSet(boolean value) {
-    __isset_bitfield = EncodingUtils.setBit(__isset_bitfield, __ERRORCODE_ISSET_ID, value);
+    __isset_bitfield = org.apache.thrift.EncodingUtils.setBit(__isset_bitfield, __ERRORCODE_ISSET_ID, value);
   }
 
-  public String getMessage() {
+  @org.apache.thrift.annotation.Nullable
+  public java.lang.String getMessage() {
     return this.message;
   }
 
-  public void setMessage(String message) {
+  public void setMessage(@org.apache.thrift.annotation.Nullable java.lang.String message) {
     this.message = message;
   }
 
@@ -225,88 +199,86 @@ public class ProcessingException extends TException implements org.apache.thrift
     }
   }
 
-  public void setFieldValue(_Fields field, Object value) {
+  public void setFieldValue(_Fields field, @org.apache.thrift.annotation.Nullable java.lang.Object value) {
     switch (field) {
-      case ERROR_CODE:
-        if (value == null) {
-          unsetErrorCode();
-        } else {
-          setErrorCode((Integer) value);
-        }
-        break;
+    case ERROR_CODE:
+      if (value == null) {
+        unsetErrorCode();
+      } else {
+        setErrorCode((java.lang.Integer)value);
+      }
+      break;
+
+    case MESSAGE:
+      if (value == null) {
+        unsetMessage();
+      } else {
+        setMessage((java.lang.String)value);
+      }
+      break;
 
-      case MESSAGE:
-        if (value == null) {
-          unsetMessage();
-        } else {
-          setMessage((String) value);
-        }
-        break;
     }
   }
 
-  public Object getFieldValue(_Fields field) {
+  @org.apache.thrift.annotation.Nullable
+  public java.lang.Object getFieldValue(_Fields field) {
     switch (field) {
-      case ERROR_CODE:
-        return getErrorCode();
+    case ERROR_CODE:
+      return getErrorCode();
+
+    case MESSAGE:
+      return getMessage();
 
-      case MESSAGE:
-        return getMessage();
     }
-    throw new IllegalStateException();
+    throw new java.lang.IllegalStateException();
   }
 
   /** Returns true if field corresponding to fieldID is set (has been assigned a value) and false otherwise */
   public boolean isSet(_Fields field) {
     if (field == null) {
-      throw new IllegalArgumentException();
+      throw new java.lang.IllegalArgumentException();
     }
 
     switch (field) {
-      case ERROR_CODE:
-        return isSetErrorCode();
-      case MESSAGE:
-        return isSetMessage();
+    case ERROR_CODE:
+      return isSetErrorCode();
+    case MESSAGE:
+      return isSetMessage();
     }
-    throw new IllegalStateException();
+    throw new java.lang.IllegalStateException();
   }
 
   @Override
-  public boolean equals(Object that) {
-    if (that == null) {
+  public boolean equals(java.lang.Object that) {
+    if (that == null)
       return false;
-    }
-    if (that instanceof ProcessingException) {
-      return this.equals((ProcessingException) that);
-    }
+    if (that instanceof ProcessingException)
+      return this.equals((ProcessingException)that);
     return false;
   }
 
   public boolean equals(ProcessingException that) {
-    if (that == null) {
+    if (that == null)
       return false;
-    }
+    if (this == that)
+      return true;
 
     boolean this_present_errorCode = true;
     boolean that_present_errorCode = true;
     if (this_present_errorCode || that_present_errorCode) {
-      if (!(this_present_errorCode && that_present_errorCode)) {
+      if (!(this_present_errorCode && that_present_errorCode))
         return false;
-      }
-      if (this.errorCode != that.errorCode) {
+      if (this.errorCode != that.errorCode)
         return false;
-      }
     }
 
     boolean this_present_message = true && this.isSetMessage();
     boolean that_present_message = true && that.isSetMessage();
     if (this_present_message || that_present_message) {
-      if (!(this_present_message && that_present_message)) {
+      if (!(this_present_message && that_present_message))
         return false;
-      }
-      if (!this.message.equals(that.message)) {
+      if (!this.message.equals(that.message))
         return false;
-      }
     }
 
     return true;
@@ -314,21 +286,15 @@ public class ProcessingException extends TException implements org.apache.thrift
 
   @Override
   public int hashCode() {
-    List<Object> list = new ArrayList<Object>();
+    int hashCode = 1;
 
-    boolean present_errorCode = true;
-    list.add(present_errorCode);
-    if (present_errorCode) {
-      list.add(errorCode);
-    }
+    hashCode = hashCode * 8191 + errorCode;
 
-    boolean present_message = true && (isSetMessage());
-    list.add(present_message);
-    if (present_message) {
-      list.add(message);
-    }
+    hashCode = hashCode * 8191 + ((isSetMessage()) ? 131071 : 524287);
+    if (isSetMessage())
+      hashCode = hashCode * 8191 + message.hashCode();
 
-    return list.hashCode();
+    return hashCode;
   }
 
   @Override
@@ -339,7 +305,7 @@ public class ProcessingException extends TException implements org.apache.thrift
 
     int lastComparison = 0;
 
-    lastComparison = Boolean.valueOf(isSetErrorCode()).compareTo(other.isSetErrorCode());
+    lastComparison = java.lang.Boolean.valueOf(isSetErrorCode()).compareTo(other.isSetErrorCode());
     if (lastComparison != 0) {
       return lastComparison;
     }
@@ -349,7 +315,7 @@ public class ProcessingException extends TException implements org.apache.thrift
         return lastComparison;
       }
     }
-    lastComparison = Boolean.valueOf(isSetMessage()).compareTo(other.isSetMessage());
+    lastComparison = java.lang.Boolean.valueOf(isSetMessage()).compareTo(other.isSetMessage());
     if (lastComparison != 0) {
       return lastComparison;
     }
@@ -362,32 +328,29 @@ public class ProcessingException extends TException implements org.apache.thrift
     return 0;
   }
 
+  @org.apache.thrift.annotation.Nullable
   public _Fields fieldForId(int fieldId) {
     return _Fields.findByThriftId(fieldId);
   }
 
-  public void read(org.apache.thrift.protocol.TProtocol iprot)
-      throws org.apache.thrift.TException {
-    schemes.get(iprot.getScheme()).getScheme().read(iprot, this);
+  public void read(org.apache.thrift.protocol.TProtocol iprot) throws org.apache.thrift.TException {
+    scheme(iprot).read(iprot, this);
   }
 
-  public void write(org.apache.thrift.protocol.TProtocol oprot)
-      throws org.apache.thrift.TException {
-    schemes.get(oprot.getScheme()).getScheme().write(oprot, this);
+  public void write(org.apache.thrift.protocol.TProtocol oprot) throws org.apache.thrift.TException {
+    scheme(oprot).write(oprot, this);
   }
 
   @Override
-  public String toString() {
-    StringBuilder sb = new StringBuilder("ProcessingException(");
+  public java.lang.String toString() {
+    java.lang.StringBuilder sb = new java.lang.StringBuilder("ProcessingException(");
     boolean first = true;
 
     sb.append("errorCode:");
     sb.append(this.errorCode);
     first = false;
     if (isSetMessage()) {
-      if (!first) {
-        sb.append(", ");
-      }
+      if (!first) sb.append(", ");
       sb.append("message:");
       if (this.message == null) {
         sb.append("null");
@@ -400,19 +363,16 @@ public class ProcessingException extends TException implements org.apache.thrift
     return sb.toString();
   }
 
-  public void validate()
-      throws org.apache.thrift.TException {
+  public void validate() throws org.apache.thrift.TException {
     // check for required fields
     if (!isSetErrorCode()) {
-      throw new org.apache.thrift.protocol.TProtocolException(
-          "Required field 'errorCode' is unset! Struct:" + toString());
+      throw new org.apache.thrift.protocol.TProtocolException("Required field 'errorCode' is unset! Struct:" + toString());
     }
 
     // check for sub-struct validity
   }
 
-  private void writeObject(java.io.ObjectOutputStream out)
-      throws java.io.IOException {
+  private void writeObject(java.io.ObjectOutputStream out) throws java.io.IOException {
     try {
       write(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(out)));
     } catch (org.apache.thrift.TException te) {
@@ -420,8 +380,7 @@ public class ProcessingException extends TException implements org.apache.thrift
     }
   }
 
-  private void readObject(java.io.ObjectInputStream in)
-      throws java.io.IOException, ClassNotFoundException {
+  private void readObject(java.io.ObjectInputStream in) throws java.io.IOException, java.lang.ClassNotFoundException {
     try {
       // it doesn't seem like you should have to do this, but java serialization is wacky, and doesn't call the default constructor.
       __isset_bitfield = 0;
@@ -431,21 +390,21 @@ public class ProcessingException extends TException implements org.apache.thrift
     }
   }
 
-  private static class ProcessingExceptionStandardSchemeFactory implements SchemeFactory {
+  private static class ProcessingExceptionStandardSchemeFactory implements org.apache.thrift.scheme.SchemeFactory {
     public ProcessingExceptionStandardScheme getScheme() {
       return new ProcessingExceptionStandardScheme();
     }
   }
 
-  private static class ProcessingExceptionStandardScheme extends StandardScheme<ProcessingException> {
+  private static class ProcessingExceptionStandardScheme extends org.apache.thrift.scheme.StandardScheme<ProcessingException> {
 
-    public void read(org.apache.thrift.protocol.TProtocol iprot, ProcessingException struct)
-        throws org.apache.thrift.TException {
+    public void read(org.apache.thrift.protocol.TProtocol iprot, ProcessingException struct) throws org.apache.thrift.TException {
       org.apache.thrift.protocol.TField schemeField;
       iprot.readStructBegin();
-      while (true) {
+      while (true)
+      {
         schemeField = iprot.readFieldBegin();
-        if (schemeField.type == org.apache.thrift.protocol.TType.STOP) {
+        if (schemeField.type == org.apache.thrift.protocol.TType.STOP) { 
           break;
         }
         switch (schemeField.id) {
@@ -453,7 +412,7 @@ public class ProcessingException extends TException implements org.apache.thrift
             if (schemeField.type == org.apache.thrift.protocol.TType.I32) {
               struct.errorCode = iprot.readI32();
               struct.setErrorCodeIsSet(true);
-            } else {
+            } else { 
               org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
             }
             break;
@@ -461,7 +420,7 @@ public class ProcessingException extends TException implements org.apache.thrift
             if (schemeField.type == org.apache.thrift.protocol.TType.STRING) {
               struct.message = iprot.readString();
               struct.setMessageIsSet(true);
-            } else {
+            } else { 
               org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
             }
             break;
@@ -474,8 +433,7 @@ public class ProcessingException extends TException implements org.apache.thrift
       struct.validate();
     }
 
-    public void write(org.apache.thrift.protocol.TProtocol oprot, ProcessingException struct)
-        throws org.apache.thrift.TException {
+    public void write(org.apache.thrift.protocol.TProtocol oprot, ProcessingException struct) throws org.apache.thrift.TException {
       struct.validate();
 
       oprot.writeStructBegin(STRUCT_DESC);
@@ -492,22 +450,22 @@ public class ProcessingException extends TException implements org.apache.thrift
       oprot.writeFieldStop();
       oprot.writeStructEnd();
     }
+
   }
 
-  private static class ProcessingExceptionTupleSchemeFactory implements SchemeFactory {
+  private static class ProcessingExceptionTupleSchemeFactory implements org.apache.thrift.scheme.SchemeFactory {
     public ProcessingExceptionTupleScheme getScheme() {
       return new ProcessingExceptionTupleScheme();
     }
   }
 
-  private static class ProcessingExceptionTupleScheme extends TupleScheme<ProcessingException> {
+  private static class ProcessingExceptionTupleScheme extends org.apache.thrift.scheme.TupleScheme<ProcessingException> {
 
     @Override
-    public void write(org.apache.thrift.protocol.TProtocol prot, ProcessingException struct)
-        throws org.apache.thrift.TException {
-      TTupleProtocol oprot = (TTupleProtocol) prot;
+    public void write(org.apache.thrift.protocol.TProtocol prot, ProcessingException struct) throws org.apache.thrift.TException {
+      org.apache.thrift.protocol.TTupleProtocol oprot = (org.apache.thrift.protocol.TTupleProtocol) prot;
       oprot.writeI32(struct.errorCode);
-      BitSet optionals = new BitSet();
+      java.util.BitSet optionals = new java.util.BitSet();
       if (struct.isSetMessage()) {
         optionals.set(0);
       }
@@ -518,17 +476,20 @@ public class ProcessingException extends TException implements org.apache.thrift
     }
 
     @Override
-    public void read(org.apache.thrift.protocol.TProtocol prot, ProcessingException struct)
-        throws org.apache.thrift.TException {
-      TTupleProtocol iprot = (TTupleProtocol) prot;
+    public void read(org.apache.thrift.protocol.TProtocol prot, ProcessingException struct) throws org.apache.thrift.TException {
+      org.apache.thrift.protocol.TTupleProtocol iprot = (org.apache.thrift.protocol.TTupleProtocol) prot;
       struct.errorCode = iprot.readI32();
       struct.setErrorCodeIsSet(true);
-      BitSet incoming = iprot.readBitSet(1);
+      java.util.BitSet incoming = iprot.readBitSet(1);
       if (incoming.get(0)) {
         struct.message = iprot.readString();
         struct.setMessageIsSet(true);
       }
     }
   }
+
+  private static <S extends org.apache.thrift.scheme.IScheme> S scheme(org.apache.thrift.protocol.TProtocol proto) {
+    return (org.apache.thrift.scheme.StandardScheme.class.equals(proto.getScheme()) ? STANDARD_SCHEME_FACTORY : TUPLE_SCHEME_FACTORY).getScheme();
+  }
 }
 
diff --git a/pinot-common/src/main/java/org/apache/pinot/parsers/utils/ParserUtils.java b/pinot-common/src/main/java/org/apache/pinot/parsers/utils/ParserUtils.java
index 9614d33..c5e6d98 100644
--- a/pinot-common/src/main/java/org/apache/pinot/parsers/utils/ParserUtils.java
+++ b/pinot-common/src/main/java/org/apache/pinot/parsers/utils/ParserUtils.java
@@ -57,6 +57,7 @@ public class ParserUtils {
     FILTER_OPERATOR_MAP.put(FilterKind.IS_NULL, FilterOperator.IS_NULL);
     FILTER_OPERATOR_MAP.put(FilterKind.IS_NOT_NULL, FilterOperator.IS_NOT_NULL);
     FILTER_OPERATOR_MAP.put(FilterKind.TEXT_MATCH, FilterOperator.TEXT_MATCH);
+    FILTER_OPERATOR_MAP.put(FilterKind.JSON_MATCH, FilterOperator.JSON_MATCH);
   }
 
   /**
diff --git a/pinot-common/src/main/java/org/apache/pinot/pql/parsers/PinotQuery2BrokerRequestConverter.java b/pinot-common/src/main/java/org/apache/pinot/pql/parsers/PinotQuery2BrokerRequestConverter.java
index d0c7bb5..64fd640 100644
--- a/pinot-common/src/main/java/org/apache/pinot/pql/parsers/PinotQuery2BrokerRequestConverter.java
+++ b/pinot-common/src/main/java/org/apache/pinot/pql/parsers/PinotQuery2BrokerRequestConverter.java
@@ -271,6 +271,7 @@ public class PinotQuery2BrokerRequestConverter {
           case IN:
           case TEXT_MATCH:
           case RANGE:
+          case JSON_MATCH:
             //first operand is the always the column
             filterQuery.setColumn(ParserUtils.standardizeExpression(operands.get(0), false));
             filterQuery.setValue(ParserUtils.getFilterValues(filterKind, operands));
diff --git a/pinot-common/src/main/java/org/apache/pinot/pql/parsers/pql2/ast/FilterKind.java b/pinot-common/src/main/java/org/apache/pinot/pql/parsers/pql2/ast/FilterKind.java
index 4e861a0..7c12367 100644
--- a/pinot-common/src/main/java/org/apache/pinot/pql/parsers/pql2/ast/FilterKind.java
+++ b/pinot-common/src/main/java/org/apache/pinot/pql/parsers/pql2/ast/FilterKind.java
@@ -34,7 +34,8 @@ public enum FilterKind {
   REGEXP_LIKE,
   IS_NULL,
   IS_NOT_NULL,
-  TEXT_MATCH;
+  TEXT_MATCH,
+  JSON_MATCH;
 
   /**
    * Helper method that returns true if the enum maps to a Range.
diff --git a/pinot-common/src/main/java/org/apache/pinot/sql/parsers/CalciteSqlParser.java b/pinot-common/src/main/java/org/apache/pinot/sql/parsers/CalciteSqlParser.java
index 5275a1a..a69ac33 100644
--- a/pinot-common/src/main/java/org/apache/pinot/sql/parsers/CalciteSqlParser.java
+++ b/pinot-common/src/main/java/org/apache/pinot/sql/parsers/CalciteSqlParser.java
@@ -551,8 +551,10 @@ public class CalciteSqlParser {
     Identifier identifierKey = expression.getIdentifier();
     if (identifierKey != null && aliasMap.containsKey(identifierKey)) {
       Expression aliasExpression = aliasMap.get(identifierKey);
-      expression.setType(aliasExpression.getType()).setIdentifier(aliasExpression.getIdentifier())
-          .setFunctionCall(aliasExpression.getFunctionCall()).setLiteral(aliasExpression.getLiteral());
+      expression.setType(aliasExpression.getType());
+      expression.setIdentifier(aliasExpression.getIdentifier());
+      expression.setFunctionCall(aliasExpression.getFunctionCall());
+      expression.setLiteral(aliasExpression.getLiteral());
     }
     Function function = expression.getFunctionCall();
     if (function != null) {
@@ -651,7 +653,7 @@ public class CalciteSqlParser {
     while (iterator.hasNext()) {
       SqlNode next = iterator.next();
       Expression columnExpression = toExpression(next);
-      if (columnExpression.getType() == ExpressionType.IDENTIFIER && columnExpression.getIdentifier().name
+      if (columnExpression.getType() == ExpressionType.IDENTIFIER && columnExpression.getIdentifier().getName()
           .equals("*")) {
         throw new SqlCompilationException(
             "Syntax error: Pinot currently does not support DISTINCT with *. Please specify each column name after DISTINCT keyword");
diff --git a/pinot-common/src/thrift/request.thrift b/pinot-common/src/thrift/request.thrift
index 36518a7..b853456 100644
--- a/pinot-common/src/thrift/request.thrift
+++ b/pinot-common/src/thrift/request.thrift
@@ -34,7 +34,8 @@ enum FilterOperator {
   IN,
   IS_NULL,
   IS_NOT_NULL,
-  TEXT_MATCH
+  TEXT_MATCH,
+  JSON_MATCH
 }
 
 /**
diff --git a/pinot-core/src/main/java/org/apache/pinot/core/common/DataSource.java b/pinot-core/src/main/java/org/apache/pinot/core/common/DataSource.java
index 75f0513..e250443 100644
--- a/pinot-core/src/main/java/org/apache/pinot/core/common/DataSource.java
+++ b/pinot-core/src/main/java/org/apache/pinot/core/common/DataSource.java
@@ -23,6 +23,7 @@ import org.apache.pinot.core.segment.index.readers.BloomFilterReader;
 import org.apache.pinot.core.segment.index.readers.Dictionary;
 import org.apache.pinot.core.segment.index.readers.ForwardIndexReader;
 import org.apache.pinot.core.segment.index.readers.InvertedIndexReader;
+import org.apache.pinot.core.segment.index.readers.JSONIndexReader;
 import org.apache.pinot.core.segment.index.readers.NullValueVectorReader;
 import org.apache.pinot.core.segment.index.readers.TextIndexReader;
 
@@ -67,6 +68,12 @@ public interface DataSource {
   TextIndexReader getTextIndex();
 
   /**
+   * Returns the text index for the column if exists, or {@code null} if not.
+   */
+  @Nullable
+  JSONIndexReader getJSONIndex();
+
+  /**
    * Returns the bloom filter for the column if exists, or {@code null} if not.
    */
   @Nullable
diff --git a/pinot-core/src/main/java/org/apache/pinot/core/indexsegment/mutable/MutableSegmentImpl.java b/pinot-core/src/main/java/org/apache/pinot/core/indexsegment/mutable/MutableSegmentImpl.java
index 5b038b1..14d6e29 100644
--- a/pinot-core/src/main/java/org/apache/pinot/core/indexsegment/mutable/MutableSegmentImpl.java
+++ b/pinot-core/src/main/java/org/apache/pinot/core/indexsegment/mutable/MutableSegmentImpl.java
@@ -60,6 +60,7 @@ import org.apache.pinot.core.segment.index.metadata.SegmentMetadata;
 import org.apache.pinot.core.segment.index.metadata.SegmentMetadataImpl;
 import org.apache.pinot.core.segment.index.readers.BloomFilterReader;
 import org.apache.pinot.core.segment.index.readers.InvertedIndexReader;
+import org.apache.pinot.core.segment.index.readers.JSONIndexReader;
 import org.apache.pinot.core.segment.index.readers.MutableForwardIndex;
 import org.apache.pinot.core.segment.index.readers.ValidDocIndexReader;
 import org.apache.pinot.core.segment.index.readers.ValidDocIndexReaderImpl;
@@ -326,10 +327,10 @@ public class MutableSegmentImpl implements MutableSegment {
       // Null value vector
       MutableNullValueVector nullValueVector = _nullHandlingEnabled ? new MutableNullValueVector() : null;
 
-      // TODO: Support range index and bloom filter for mutable segment
+      // TODO: Support range index and bloom filter and json index for mutable segment
       _indexContainerMap.put(column,
           new IndexContainer(fieldSpec, partitionFunction, partitions, new NumValuesInfo(), forwardIndex, dictionary,
-              invertedIndexReader, null, textIndex, null, nullValueVector));
+              invertedIndexReader, null, textIndex, null, nullValueVector, null));
     }
 
     if (_realtimeLuceneReaders != null) {
@@ -1039,6 +1040,7 @@ public class MutableSegmentImpl implements MutableSegment {
     final RealtimeLuceneTextIndexReader _textIndex;
     final BloomFilterReader _bloomFilter;
     final MutableNullValueVector _nullValueVector;
+    final JSONIndexReader _jsonIndex;
 
     volatile Comparable _minValue;
     volatile Comparable _maxValue;
@@ -1051,7 +1053,8 @@ public class MutableSegmentImpl implements MutableSegment {
         @Nullable Set<Integer> partitions, NumValuesInfo numValuesInfo, MutableForwardIndex forwardIndex,
         @Nullable BaseMutableDictionary dictionary, @Nullable RealtimeInvertedIndexReader invertedIndex,
         @Nullable InvertedIndexReader rangeIndex, @Nullable RealtimeLuceneTextIndexReader textIndex,
-        @Nullable BloomFilterReader bloomFilter, @Nullable MutableNullValueVector nullValueVector) {
+        @Nullable BloomFilterReader bloomFilter, @Nullable MutableNullValueVector nullValueVector,
+        JSONIndexReader jsonIndex) {
       _fieldSpec = fieldSpec;
       _partitionFunction = partitionFunction;
       _partitions = partitions;
@@ -1063,12 +1066,13 @@ public class MutableSegmentImpl implements MutableSegment {
       _textIndex = textIndex;
       _bloomFilter = bloomFilter;
       _nullValueVector = nullValueVector;
+      _jsonIndex = jsonIndex;
     }
 
     DataSource toDataSource() {
       return new MutableDataSource(_fieldSpec, _numDocsIndexed, _numValuesInfo._numValues,
           _numValuesInfo._maxNumValuesPerMVEntry, _partitionFunction, _partitions, _minValue, _maxValue, _forwardIndex,
-          _dictionary, _invertedIndex, _rangeIndex, _textIndex, _bloomFilter, _nullValueVector);
+          _dictionary, _invertedIndex, _rangeIndex, _textIndex, _bloomFilter, _nullValueVector, _jsonIndex);
     }
 
     @Override
diff --git a/pinot-core/src/main/java/org/apache/pinot/core/io/util/VarLengthBytesValueReaderWriter.java b/pinot-core/src/main/java/org/apache/pinot/core/io/util/VarLengthBytesValueReaderWriter.java
index 5a6a25a..88f56f6 100644
--- a/pinot-core/src/main/java/org/apache/pinot/core/io/util/VarLengthBytesValueReaderWriter.java
+++ b/pinot-core/src/main/java/org/apache/pinot/core/io/util/VarLengthBytesValueReaderWriter.java
@@ -18,6 +18,9 @@
  */
 package org.apache.pinot.core.io.util;
 
+import java.io.ByteArrayOutputStream;
+import java.io.DataOutputStream;
+import java.io.IOException;
 import java.util.Arrays;
 import org.apache.pinot.common.utils.StringUtil;
 import org.apache.pinot.core.segment.memory.PinotDataBuffer;
@@ -63,19 +66,19 @@ public class VarLengthBytesValueReaderWriter implements ValueReader {
   /**
    * Magic bytes used to identify the dictionary files written in variable length bytes format.
    */
-  private static final byte[] MAGIC_BYTES = StringUtil.encodeUtf8(".vl;");
+  public static final byte[] MAGIC_BYTES = StringUtil.encodeUtf8(".vl;");
 
   /**
    * Increment this version if there are any structural changes in the store format and
    * deal with backward compatibility correctly based on old versions.
    */
-  private static final int VERSION = 1;
+  public static final int VERSION = 1;
 
   // Offsets of different fields in the header. Having as constants for readability.
-  private static final int VERSION_OFFSET = MAGIC_BYTES.length;
-  private static final int NUM_ELEMENTS_OFFSET = VERSION_OFFSET + Integer.BYTES;
-  private static final int DATA_SECTION_OFFSET_POSITION = NUM_ELEMENTS_OFFSET + Integer.BYTES;
-  private static final int HEADER_LENGTH = DATA_SECTION_OFFSET_POSITION + Integer.BYTES;
+  public static final int VERSION_OFFSET = MAGIC_BYTES.length;
+  public static final int NUM_ELEMENTS_OFFSET = VERSION_OFFSET + Integer.BYTES;
+  public static final int DATA_SECTION_OFFSET_POSITION = NUM_ELEMENTS_OFFSET + Integer.BYTES;
+  public static final int HEADER_LENGTH = DATA_SECTION_OFFSET_POSITION + Integer.BYTES;
 
   private final PinotDataBuffer _dataBuffer;
 
@@ -144,6 +147,19 @@ public class VarLengthBytesValueReaderWriter implements ValueReader {
     return false;
   }
 
+  public static byte[] getHeaderBytes(int numElements)
+      throws IOException {
+
+    ByteArrayOutputStream out = new ByteArrayOutputStream(HEADER_LENGTH);
+    DataOutputStream dos = new DataOutputStream(out);
+    dos.write(MAGIC_BYTES);
+    dos.writeInt(VERSION);
+    dos.writeInt(numElements);
+    dos.writeInt(HEADER_LENGTH);
+    dos.close();
+    return out.toByteArray();
+  }
+
   private void writeHeader() {
     for (int offset = 0; offset < MAGIC_BYTES.length; offset++) {
       _dataBuffer.putByte(offset, MAGIC_BYTES[offset]);
diff --git a/pinot-core/src/main/java/org/apache/pinot/core/operator/filter/BitmapBasedFilterOperator.java b/pinot-core/src/main/java/org/apache/pinot/core/operator/filter/BitmapBasedFilterOperator.java
index d9c25e1..9c307a3 100644
--- a/pinot-core/src/main/java/org/apache/pinot/core/operator/filter/BitmapBasedFilterOperator.java
+++ b/pinot-core/src/main/java/org/apache/pinot/core/operator/filter/BitmapBasedFilterOperator.java
@@ -38,9 +38,9 @@ public class BitmapBasedFilterOperator extends BaseFilterOperator {
   private final boolean _exclusive;
   private final int _numDocs;
 
-  BitmapBasedFilterOperator(PredicateEvaluator predicateEvaluator, DataSource dataSource, int numDocs) {
+  public BitmapBasedFilterOperator(PredicateEvaluator predicateEvaluator, InvertedIndexReader invertedIndexReader, int numDocs) {
     _predicateEvaluator = predicateEvaluator;
-    _invertedIndexReader = dataSource.getInvertedIndex();
+    _invertedIndexReader = invertedIndexReader;
     _docIds = null;
     _exclusive = predicateEvaluator.isExclusive();
     _numDocs = numDocs;
diff --git a/pinot-core/src/main/java/org/apache/pinot/core/operator/filter/FilterOperatorUtils.java b/pinot-core/src/main/java/org/apache/pinot/core/operator/filter/FilterOperatorUtils.java
index 3bc676e..5076ef6 100644
--- a/pinot-core/src/main/java/org/apache/pinot/core/operator/filter/FilterOperatorUtils.java
+++ b/pinot-core/src/main/java/org/apache/pinot/core/operator/filter/FilterOperatorUtils.java
@@ -65,7 +65,7 @@ public class FilterOperatorUtils {
         return new SortedIndexBasedFilterOperator(predicateEvaluator, dataSource, numDocs);
       }
       if (dataSource.getInvertedIndex() != null) {
-        return new BitmapBasedFilterOperator(predicateEvaluator, dataSource, numDocs);
+        return new BitmapBasedFilterOperator(predicateEvaluator, dataSource.getInvertedIndex(), numDocs);
       }
       return new ScanBasedFilterOperator(predicateEvaluator, dataSource, numDocs);
     }
diff --git a/pinot-core/src/main/java/org/apache/pinot/core/operator/filter/JSONMatchFilterOperator.java b/pinot-core/src/main/java/org/apache/pinot/core/operator/filter/JSONMatchFilterOperator.java
new file mode 100644
index 0000000..954f5f0
--- /dev/null
+++ b/pinot-core/src/main/java/org/apache/pinot/core/operator/filter/JSONMatchFilterOperator.java
@@ -0,0 +1,148 @@
+/**
+ * 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.pinot.core.operator.filter;
+
+import java.util.Iterator;
+import java.util.List;
+import java.util.stream.Collectors;
+import org.apache.pinot.core.operator.blocks.FilterBlock;
+import org.apache.pinot.core.operator.docidsets.BitmapDocIdSet;
+import org.apache.pinot.core.query.request.context.ExpressionContext;
+import org.apache.pinot.core.query.request.context.FilterContext;
+import org.apache.pinot.core.query.request.context.predicate.EqPredicate;
+import org.apache.pinot.core.query.request.context.predicate.InPredicate;
+import org.apache.pinot.core.query.request.context.predicate.NotEqPredicate;
+import org.apache.pinot.core.query.request.context.predicate.NotInPredicate;
+import org.apache.pinot.core.query.request.context.predicate.Predicate;
+import org.apache.pinot.core.segment.creator.impl.inv.JSONIndexCreator;
+import org.apache.pinot.core.segment.index.readers.JSONIndexReader;
+import org.roaringbitmap.buffer.ImmutableRoaringBitmap;
+import org.roaringbitmap.buffer.MutableRoaringBitmap;
+
+
+@SuppressWarnings("rawtypes")
+public class JSONMatchFilterOperator extends BaseFilterOperator {
+  private static final String OPERATOR_NAME = "JSONMatchFilterOperator";
+
+  private final JSONIndexReader _jsonIndexReader;
+  private final int _numDocs;
+  private String _column;
+  private final FilterContext _filterContext;
+
+  public JSONMatchFilterOperator(String column, FilterContext filterContext, JSONIndexReader jsonIndexReader,
+      int numDocs) {
+    _column = column;
+    _filterContext = filterContext;
+    _jsonIndexReader = jsonIndexReader;
+    _numDocs = numDocs;
+  }
+
+  @Override
+  protected FilterBlock getNextBlock() {
+    ImmutableRoaringBitmap flattenedDocIds = process(_filterContext);
+//    System.out.println("flattenedDocIds = " + flattenedDocIds);
+    MutableRoaringBitmap rootDocIds = new MutableRoaringBitmap();
+    Iterator<Integer> iterator = flattenedDocIds.iterator();
+    while (iterator.hasNext()) {
+      int flattenedDocId = iterator.next();
+      rootDocIds.add(_jsonIndexReader.getRootDocId(flattenedDocId));
+    }
+//    System.out.println("rootDocIds = " + rootDocIds);
+
+    return new FilterBlock(new BitmapDocIdSet(rootDocIds, _numDocs));
+  }
+
+  private MutableRoaringBitmap process(FilterContext filterContext) {
+    List<FilterContext> children = _filterContext.getChildren();
+    MutableRoaringBitmap resultBitmap = null;
+
+    switch (filterContext.getType()) {
+      case AND:
+        for (FilterContext child : children) {
+          if (resultBitmap == null) {
+            resultBitmap = process(child);
+          } else {
+            resultBitmap.and(process(child));
+          }
+        }
+        break;
+      case OR:
+        for (FilterContext child : children) {
+          if (resultBitmap == null) {
+            resultBitmap = process(child);
+          } else {
+            resultBitmap.or(process(child));
+          }
+        }
+        break;
+      case PREDICATE:
+        Predicate predicate = filterContext.getPredicate();
+        Predicate newPredicate = null;
+        switch (predicate.getType()) {
+
+          case EQ:
+            EqPredicate eqPredicate = (EqPredicate) predicate;
+            newPredicate = new EqPredicate(ExpressionContext.forIdentifier(_column),
+                eqPredicate.getLhs().getIdentifier() + JSONIndexCreator.POSTING_LIST_KEY_SEPARATOR + eqPredicate
+                    .getValue());
+            break;
+          case NOT_EQ:
+            NotEqPredicate nEqPredicate = (NotEqPredicate) predicate;
+            newPredicate = new NotEqPredicate(ExpressionContext.forIdentifier(_column),
+                nEqPredicate.getLhs().getIdentifier() + JSONIndexCreator.POSTING_LIST_KEY_SEPARATOR
+                    + nEqPredicate.getValue());
+            break;
+          case IN:
+            InPredicate inPredicate = (InPredicate) predicate;
+            List<String> newInValues = inPredicate.getValues().stream().map(
+                value -> inPredicate.getLhs().getIdentifier() + JSONIndexCreator.POSTING_LIST_KEY_SEPARATOR
+                    + value).collect(Collectors.toList());
+            newPredicate = new InPredicate(ExpressionContext.forIdentifier(_column), newInValues);
+            break;
+          case NOT_IN:
+            NotInPredicate notInPredicate = (NotInPredicate) predicate;
+            List<String> newNotInValues = notInPredicate.getValues().stream().map(
+                value -> notInPredicate.getLhs().getIdentifier() + JSONIndexCreator.POSTING_LIST_KEY_SEPARATOR
+                    + value).collect(Collectors.toList());
+            newPredicate = new InPredicate(ExpressionContext.forIdentifier(_column), newNotInValues);
+            break;
+          case IS_NULL:
+            newPredicate = predicate;
+            break;
+          case IS_NOT_NULL:
+            newPredicate = predicate;
+            break;
+          case RANGE:
+          case REGEXP_LIKE:
+          case TEXT_MATCH:
+            throw new UnsupportedOperationException("JSON Match does not support RANGE, REGEXP or TEXTMATCH");
+        }
+
+        resultBitmap = _jsonIndexReader.getMatchingDocIds(newPredicate);
+        break;
+    }
+
+    return resultBitmap;
+  }
+
+  @Override
+  public String getOperatorName() {
+    return OPERATOR_NAME;
+  }
+}
diff --git a/pinot-core/src/main/java/org/apache/pinot/core/operator/transform/function/CastTransformFunction.java b/pinot-core/src/main/java/org/apache/pinot/core/operator/transform/function/CastTransformFunction.java
index c826446..cb6227f 100644
--- a/pinot-core/src/main/java/org/apache/pinot/core/operator/transform/function/CastTransformFunction.java
+++ b/pinot-core/src/main/java/org/apache/pinot/core/operator/transform/function/CastTransformFunction.java
@@ -30,7 +30,7 @@ import org.apache.pinot.core.operator.transform.transformer.datetime.SDFToSDFTra
 import org.apache.pinot.core.plan.DocIdSetPlanNode;
 
 
-public class CastTransformFunction extends BaseTransformFunction {
+  public class CastTransformFunction extends BaseTransformFunction {
   public static final String FUNCTION_NAME = "cast";
 
   private TransformFunction _transformFunction;
diff --git a/pinot-core/src/main/java/org/apache/pinot/core/plan/FilterPlanNode.java b/pinot-core/src/main/java/org/apache/pinot/core/plan/FilterPlanNode.java
index 7e076e0..12cfc6f 100644
--- a/pinot-core/src/main/java/org/apache/pinot/core/plan/FilterPlanNode.java
+++ b/pinot-core/src/main/java/org/apache/pinot/core/plan/FilterPlanNode.java
@@ -23,6 +23,7 @@ import java.util.Arrays;
 import java.util.List;
 import java.util.Map;
 import javax.annotation.Nullable;
+import org.apache.calcite.sql.parser.SqlParseException;
 import org.apache.pinot.core.common.DataSource;
 import org.apache.pinot.core.indexsegment.IndexSegment;
 import org.apache.pinot.core.operator.filter.BaseFilterOperator;
@@ -30,6 +31,7 @@ import org.apache.pinot.core.operator.filter.BitmapBasedFilterOperator;
 import org.apache.pinot.core.operator.filter.EmptyFilterOperator;
 import org.apache.pinot.core.operator.filter.ExpressionFilterOperator;
 import org.apache.pinot.core.operator.filter.FilterOperatorUtils;
+import org.apache.pinot.core.operator.filter.JSONMatchFilterOperator;
 import org.apache.pinot.core.operator.filter.MatchAllFilterOperator;
 import org.apache.pinot.core.operator.filter.TextMatchFilterOperator;
 import org.apache.pinot.core.operator.filter.predicate.PredicateEvaluator;
@@ -37,11 +39,14 @@ import org.apache.pinot.core.operator.filter.predicate.PredicateEvaluatorProvide
 import org.apache.pinot.core.query.request.context.ExpressionContext;
 import org.apache.pinot.core.query.request.context.FilterContext;
 import org.apache.pinot.core.query.request.context.QueryContext;
+import org.apache.pinot.core.query.request.context.predicate.JSONMatchPredicate;
 import org.apache.pinot.core.query.request.context.predicate.Predicate;
 import org.apache.pinot.core.query.request.context.predicate.TextMatchPredicate;
+import org.apache.pinot.core.query.request.context.utils.QueryContextConverterUtils;
 import org.apache.pinot.core.segment.index.readers.NullValueVectorReader;
 import org.apache.pinot.core.segment.index.readers.ValidDocIndexReader;
 import org.apache.pinot.core.util.QueryOptions;
+import org.apache.pinot.sql.parsers.CalciteSqlParser;
 
 
 public class FilterPlanNode implements PlanNode {
@@ -129,6 +134,16 @@ public class FilterPlanNode implements PlanNode {
             case TEXT_MATCH:
               return new TextMatchFilterOperator(dataSource.getTextIndex(), ((TextMatchPredicate) predicate).getValue(),
                   _numDocs);
+            case JSON_MATCH:
+              FilterContext filterContext = null;
+              try {
+                filterContext = QueryContextConverterUtils
+                    .getFilter(CalciteSqlParser.compileToExpression(((JSONMatchPredicate) predicate).getValue()));
+              } catch (SqlParseException e) {
+                throw new RuntimeException("Unable to parse the filter expression for json_match:"+ ((JSONMatchPredicate) predicate).getValue());
+              }
+              return new JSONMatchFilterOperator(lhs.getIdentifier(), filterContext, dataSource.getJSONIndex(),
+                  _numDocs);
             case IS_NULL:
               NullValueVectorReader nullValueVector = dataSource.getNullValueVector();
               if (nullValueVector != null) {
diff --git a/pinot-core/src/main/java/org/apache/pinot/core/query/request/context/predicate/Predicate.java b/pinot-core/src/main/java/org/apache/pinot/core/query/request/context/predicate/JSONMatchPredicate.java
similarity index 50%
copy from pinot-core/src/main/java/org/apache/pinot/core/query/request/context/predicate/Predicate.java
copy to pinot-core/src/main/java/org/apache/pinot/core/query/request/context/predicate/JSONMatchPredicate.java
index 203e950..97ad787 100644
--- a/pinot-core/src/main/java/org/apache/pinot/core/query/request/context/predicate/Predicate.java
+++ b/pinot-core/src/main/java/org/apache/pinot/core/query/request/context/predicate/JSONMatchPredicate.java
@@ -18,30 +18,55 @@
  */
 package org.apache.pinot.core.query.request.context.predicate;
 
+import java.util.Objects;
 import org.apache.pinot.core.query.request.context.ExpressionContext;
 
 
 /**
- * The {@code Predicate} class represents the predicate in the filter.
- * <p>Currently the query engine only accepts string literals as the right-hand side of the predicate, so we store the
- * right-hand side of the predicate as string or list of strings.
+ * Predicate for JSON_MATCH.
  */
-public interface Predicate {
-  enum Type {
-    EQ, NOT_EQ, IN, NOT_IN, RANGE, REGEXP_LIKE, TEXT_MATCH, IS_NULL, IS_NOT_NULL;
+public class JSONMatchPredicate implements Predicate {
+  private final ExpressionContext _lhs;
+  private final String _value;
 
-    public boolean isExclusive() {
-      return this == NOT_EQ || this == NOT_IN || this == IS_NOT_NULL;
+  public JSONMatchPredicate(ExpressionContext lhs, String value) {
+    _lhs = lhs;
+    _value = value;
+  }
+
+  @Override
+  public Type getType() {
+    return Type.JSON_MATCH;
+  }
+
+  @Override
+  public ExpressionContext getLhs() {
+    return _lhs;
+  }
+
+  public String getValue() {
+    return _value;
+  }
+
+  @Override
+  public boolean equals(Object o) {
+    if (this == o) {
+      return true;
+    }
+    if (!(o instanceof JSONMatchPredicate)) {
+      return false;
     }
+    JSONMatchPredicate that = (JSONMatchPredicate) o;
+    return Objects.equals(_lhs, that._lhs) && Objects.equals(_value, that._value);
   }
 
-  /**
-   * Returns the type of the predicate.
-   */
-  Type getType();
+  @Override
+  public int hashCode() {
+    return Objects.hash(_lhs, _value);
+  }
 
-  /**
-   * Returns the left-hand side expression of the predicate.
-   */
-  ExpressionContext getLhs();
+  @Override
+  public String toString() {
+    return "json_match(" + _lhs + ",'" + _value + "')";
+  }
 }
diff --git a/pinot-core/src/main/java/org/apache/pinot/core/query/request/context/predicate/Predicate.java b/pinot-core/src/main/java/org/apache/pinot/core/query/request/context/predicate/Predicate.java
index 203e950..a204fc6 100644
--- a/pinot-core/src/main/java/org/apache/pinot/core/query/request/context/predicate/Predicate.java
+++ b/pinot-core/src/main/java/org/apache/pinot/core/query/request/context/predicate/Predicate.java
@@ -28,7 +28,7 @@ import org.apache.pinot.core.query.request.context.ExpressionContext;
  */
 public interface Predicate {
   enum Type {
-    EQ, NOT_EQ, IN, NOT_IN, RANGE, REGEXP_LIKE, TEXT_MATCH, IS_NULL, IS_NOT_NULL;
+    EQ, NOT_EQ, IN, NOT_IN, RANGE, REGEXP_LIKE, TEXT_MATCH, IS_NULL, IS_NOT_NULL, JSON_MATCH;
 
     public boolean isExclusive() {
       return this == NOT_EQ || this == NOT_IN || this == IS_NOT_NULL;
@@ -44,4 +44,5 @@ public interface Predicate {
    * Returns the left-hand side expression of the predicate.
    */
   ExpressionContext getLhs();
+
 }
diff --git a/pinot-core/src/main/java/org/apache/pinot/core/query/request/context/utils/QueryContextConverterUtils.java b/pinot-core/src/main/java/org/apache/pinot/core/query/request/context/utils/QueryContextConverterUtils.java
index 581735b..deef50f 100644
--- a/pinot-core/src/main/java/org/apache/pinot/core/query/request/context/utils/QueryContextConverterUtils.java
+++ b/pinot-core/src/main/java/org/apache/pinot/core/query/request/context/utils/QueryContextConverterUtils.java
@@ -37,6 +37,7 @@ import org.apache.pinot.core.query.request.context.predicate.EqPredicate;
 import org.apache.pinot.core.query.request.context.predicate.InPredicate;
 import org.apache.pinot.core.query.request.context.predicate.IsNotNullPredicate;
 import org.apache.pinot.core.query.request.context.predicate.IsNullPredicate;
+import org.apache.pinot.core.query.request.context.predicate.JSONMatchPredicate;
 import org.apache.pinot.core.query.request.context.predicate.NotEqPredicate;
 import org.apache.pinot.core.query.request.context.predicate.NotInPredicate;
 import org.apache.pinot.core.query.request.context.predicate.RangePredicate;
@@ -290,6 +291,9 @@ public class QueryContextConverterUtils {
       case TEXT_MATCH:
         return new FilterContext(FilterContext.Type.PREDICATE, null,
             new TextMatchPredicate(getExpression(node.getColumn()), node.getValue().get(0)));
+      case JSON_MATCH:
+        return new FilterContext(FilterContext.Type.PREDICATE, null,
+            new JSONMatchPredicate(getExpression(node.getColumn()), node.getValue().get(0)));
       case IS_NULL:
         return new FilterContext(FilterContext.Type.PREDICATE, null,
             new IsNullPredicate(getExpression(node.getColumn())));
diff --git a/pinot-core/src/main/java/org/apache/pinot/core/segment/creator/impl/V1Constants.java b/pinot-core/src/main/java/org/apache/pinot/core/segment/creator/impl/V1Constants.java
index 0498f8c..e745120 100644
--- a/pinot-core/src/main/java/org/apache/pinot/core/segment/creator/impl/V1Constants.java
+++ b/pinot-core/src/main/java/org/apache/pinot/core/segment/creator/impl/V1Constants.java
@@ -36,6 +36,7 @@ public class V1Constants {
     public static final String RAW_SV_FORWARD_INDEX_FILE_EXTENSION = ".sv.raw.fwd";
     public static final String UNSORTED_MV_FORWARD_INDEX_FILE_EXTENSION = ".mv.fwd";
     public static final String BITMAP_INVERTED_INDEX_FILE_EXTENSION = ".bitmap.inv";
+    public static final String JSON_INDEX_FILE_EXTENSION = ".json.idx";
     public static final String BITMAP_RANGE_INDEX_FILE_EXTENSION = ".bitmap.range";
     public static final String BLOOM_FILTER_FILE_EXTENSION = ".bloom";
     public static final String NULLVALUE_VECTOR_FILE_EXTENSION = ".bitmap.nullvalue";
diff --git a/pinot-core/src/main/java/org/apache/pinot/core/segment/creator/impl/inv/JSONIndexCreator.java b/pinot-core/src/main/java/org/apache/pinot/core/segment/creator/impl/inv/JSONIndexCreator.java
new file mode 100644
index 0000000..4917993
--- /dev/null
+++ b/pinot-core/src/main/java/org/apache/pinot/core/segment/creator/impl/inv/JSONIndexCreator.java
@@ -0,0 +1,658 @@
+/**
+ * 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.pinot.core.segment.creator.impl.inv;
+
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.github.wnameless.json.flattener.JsonFlattener;
+import com.google.common.io.Files;
+import com.google.common.primitives.UnsignedBytes;
+import java.io.BufferedInputStream;
+import java.io.BufferedOutputStream;
+import java.io.Closeable;
+import java.io.DataInputStream;
+import java.io.DataOutputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
+import java.nio.charset.Charset;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Comparator;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.PriorityQueue;
+import java.util.TreeMap;
+import java.util.stream.Collectors;
+import org.apache.commons.io.FileUtils;
+import org.apache.commons.lang3.tuple.ImmutablePair;
+import org.apache.pinot.core.common.BlockDocIdIterator;
+import org.apache.pinot.core.io.util.VarLengthBytesValueReaderWriter;
+import org.apache.pinot.core.operator.blocks.FilterBlock;
+import org.apache.pinot.core.operator.filter.JSONMatchFilterOperator;
+import org.apache.pinot.core.query.request.context.ExpressionContext;
+import org.apache.pinot.core.query.request.context.FilterContext;
+import org.apache.pinot.core.query.request.context.predicate.EqPredicate;
+import org.apache.pinot.core.query.request.context.predicate.Predicate;
+import org.apache.pinot.core.query.request.context.utils.QueryContextConverterUtils;
+import org.apache.pinot.core.segment.index.readers.JSONIndexReader;
+import org.apache.pinot.core.segment.memory.PinotDataBuffer;
+import org.apache.pinot.spi.data.DimensionFieldSpec;
+import org.apache.pinot.spi.data.FieldSpec;
+import org.apache.pinot.sql.parsers.CalciteSqlParser;
+import org.roaringbitmap.RoaringBitmap;
+import org.roaringbitmap.buffer.MutableRoaringBitmap;
+
+import static org.apache.pinot.core.segment.creator.impl.V1Constants.Indexes.JSON_INDEX_FILE_EXTENSION;
+
+
+public class JSONIndexCreator implements Closeable {
+
+  //separator used to join the key and value to create posting list key
+  public static String POSTING_LIST_KEY_SEPARATOR = "|";
+  static int FLUSH_THRESHOLD = 50_000;
+  static int VERSION = 1;
+  private final File flattenedDocId2RootDocIdMappingFile;
+  private final File postingListFile;
+  private File dictionaryheaderFile;
+  private File dictionaryOffsetFile;
+  private File dictionaryFile;
+  private File invertedIndexOffsetFile;
+  private File invertedIndexFile;
+  private File outputIndexFile;
+
+  private int docId = 0;
+  private int numFlatennedDocId = 0;
+  int chunkId = 0;
+
+  private DataOutputStream postingListWriter;
+  private DataOutputStream flattenedDocId2RootDocIdWriter;
+
+  Map<String, List<Integer>> postingListMap = new TreeMap<>();
+  List<Integer> flattenedDocIdList = new ArrayList<>();
+  List<Integer> postingListChunkOffsets = new ArrayList<>();
+  List<Integer> chunkLengths = new ArrayList<>();
+  private FieldSpec fieldSpec;
+
+  public JSONIndexCreator(File indexDir, FieldSpec fieldSpec)
+      throws IOException {
+    this.fieldSpec = fieldSpec;
+    System.out.println("indexDir = " + indexDir);
+
+    String name = fieldSpec.getName();
+    postingListFile = new File(indexDir + name + "_postingList.buf");
+    postingListWriter = new DataOutputStream(new BufferedOutputStream(new FileOutputStream(postingListFile)));
+    postingListChunkOffsets.add(postingListWriter.size());
+
+    dictionaryheaderFile = new File(indexDir, name + "_dictionaryHeader.buf");
+    dictionaryOffsetFile = new File(indexDir, name + "_dictionaryOffset.buf");
+    dictionaryFile = new File(indexDir, name + "_dictionary.buf");
+    invertedIndexOffsetFile = new File(indexDir, name + "_invertedIndexOffset.buf");
+    invertedIndexFile = new File(indexDir, name + "_invertedIndex.buf");
+    flattenedDocId2RootDocIdMappingFile = new File(indexDir, name + "_flattenedDocId.buf");
+    flattenedDocId2RootDocIdWriter =
+        new DataOutputStream(new BufferedOutputStream(new FileOutputStream(flattenedDocId2RootDocIdMappingFile)));
+
+    //output file
+    outputIndexFile = new File(indexDir, name + JSON_INDEX_FILE_EXTENSION);
+  }
+
+  public void add(byte[] data)
+      throws IOException {
+
+    JsonNode jsonNode = new ObjectMapper().readTree(data);
+    List<Map<String, String>> flattenedMapList = unnestJson(jsonNode);
+    for (Map<String, String> map : flattenedMapList) {
+      //
+      for (Map.Entry<String, String> entry : map.entrySet()) {
+        //handle key posting list
+        String key = entry.getKey();
+
+        List<Integer> keyPostingList = postingListMap.get(key);
+        if (keyPostingList == null) {
+          keyPostingList = new ArrayList<>();
+          postingListMap.put(key, keyPostingList);
+        }
+        keyPostingList.add(numFlatennedDocId);
+
+        //handle keyvalue posting list
+        String keyValue = key + POSTING_LIST_KEY_SEPARATOR + entry.getValue();
+        List<Integer> keyValuePostingList = postingListMap.get(keyValue);
+        if (keyValuePostingList == null) {
+          keyValuePostingList = new ArrayList<>();
+          postingListMap.put(keyValue, keyValuePostingList);
+        }
+        keyValuePostingList.add(numFlatennedDocId);
+      }
+      //flattenedDocId2RootDocIdMapping
+      flattenedDocIdList.add(docId);
+
+      numFlatennedDocId++;
+    }
+    docId++;
+
+    //flush data
+    if (docId % FLUSH_THRESHOLD == 0) {
+      flush();
+    }
+  }
+
+  /**
+   * Multi value
+   * @param dataArray
+   * @param length
+   * @throws IOException
+   */
+  public void add(byte[][] dataArray, int length)
+      throws IOException {
+
+    for (int i = 0; i < length; i++) {
+      byte[] data = dataArray[i];
+      JsonNode jsonNode = new ObjectMapper().readTree(data);
+      List<Map<String, String>> flattenedMapList = unnestJson(jsonNode);
+      for (Map<String, String> map : flattenedMapList) {
+        //
+        for (Map.Entry<String, String> entry : map.entrySet()) {
+          //handle key posting list
+          String key = entry.getKey();
+
+          List<Integer> keyPostingList = postingListMap.get(key);
+          if (keyPostingList == null) {
+            keyPostingList = new ArrayList<>();
+            postingListMap.put(key, keyPostingList);
+          }
+          keyPostingList.add(numFlatennedDocId);
+
+          //handle keyvalue posting list
+          String keyValue = key + POSTING_LIST_KEY_SEPARATOR + entry.getValue();
+          List<Integer> keyValuePostingList = postingListMap.get(keyValue);
+          if (keyValuePostingList == null) {
+            keyValuePostingList = new ArrayList<>();
+            postingListMap.put(keyValue, keyValuePostingList);
+          }
+          keyValuePostingList.add(numFlatennedDocId);
+        }
+        //flattenedDocId2RootDocIdMapping
+        flattenedDocIdList.add(numFlatennedDocId);
+
+        numFlatennedDocId++;
+      }
+    }
+    docId++;
+
+    //flush data
+    if (docId % FLUSH_THRESHOLD == 0) {
+      flush();
+    }
+  }
+
+  public void seal()
+      throws IOException {
+
+    flush();
+
+    flattenedDocId2RootDocIdWriter.close();
+    postingListWriter.close();
+
+    //key posting list merging
+    System.out.println("InvertedIndex");
+    System.out.println("=================");
+
+    int maxKeyLength = createInvertedIndex(postingListFile, postingListChunkOffsets, chunkLengths);
+    System.out.println("=================");
+
+    int flattenedDocid = 0;
+    DataInputStream flattenedDocId2RootDocIdReader =
+        new DataInputStream(new BufferedInputStream(new FileInputStream(flattenedDocId2RootDocIdMappingFile)));
+    int[] rootDocIdArray = new int[numFlatennedDocId];
+    while (flattenedDocid < numFlatennedDocId) {
+      rootDocIdArray[flattenedDocid++] = flattenedDocId2RootDocIdReader.readInt();
+    }
+    System.out.println("FlattenedDocId  to RootDocId Mapping = ");
+    System.out.println(Arrays.toString(rootDocIdArray));
+
+    //PUT all contents into one file
+
+    //header
+    // version + maxDictionaryLength + [store the offsets + length for each one (dictionary offset file, dictionaryFile, index offset file, index file, flattened docId to rootDocId file)]
+    long headerSize = 2 * Integer.BYTES + 6 * 2 * Long.BYTES;
+
+    long dataSize =
+        dictionaryheaderFile.length() + dictionaryOffsetFile.length() + dictionaryFile.length() + invertedIndexFile
+            .length() + invertedIndexOffsetFile.length() + flattenedDocId2RootDocIdMappingFile.length();
+
+    long totalSize = headerSize + dataSize;
+    PinotDataBuffer pinotDataBuffer =
+        PinotDataBuffer.mapFile(outputIndexFile, false, 0, totalSize, ByteOrder.BIG_ENDIAN, "Nested inverted index");
+
+    pinotDataBuffer.putInt(0, VERSION);
+    pinotDataBuffer.putInt(1 * Integer.BYTES, maxKeyLength);
+    long writtenBytes = headerSize;
+
+    //add dictionary header
+    int bufferId = 0;
+    pinotDataBuffer.putLong(getBufferStartOffset(bufferId), writtenBytes);
+    pinotDataBuffer.putLong(getBufferStartOffset(bufferId) + Long.BYTES, dictionaryheaderFile.length());
+    pinotDataBuffer.readFrom(writtenBytes, dictionaryheaderFile, 0, dictionaryheaderFile.length());
+    writtenBytes += dictionaryheaderFile.length();
+
+    //add dictionary offset
+    bufferId = bufferId + 1;
+    pinotDataBuffer.putLong(getBufferStartOffset(bufferId), writtenBytes);
+    pinotDataBuffer.putLong(getBufferStartOffset(bufferId) + Long.BYTES, dictionaryOffsetFile.length());
+    pinotDataBuffer.readFrom(writtenBytes, dictionaryOffsetFile, 0, dictionaryOffsetFile.length());
+    writtenBytes += dictionaryOffsetFile.length();
+
+    //add dictionary
+    bufferId = bufferId + 1;
+    pinotDataBuffer.putLong(getBufferStartOffset(bufferId), writtenBytes);
+    pinotDataBuffer.putLong(getBufferStartOffset(bufferId) + Long.BYTES, dictionaryFile.length());
+    pinotDataBuffer.readFrom(writtenBytes, dictionaryFile, 0, dictionaryFile.length());
+    writtenBytes += dictionaryFile.length();
+
+    //add index offset
+    bufferId = bufferId + 1;
+    pinotDataBuffer.putLong(getBufferStartOffset(bufferId), writtenBytes);
+    pinotDataBuffer.putLong(getBufferStartOffset(bufferId) + Long.BYTES, invertedIndexOffsetFile.length());
+    pinotDataBuffer.readFrom(writtenBytes, invertedIndexOffsetFile, 0, invertedIndexOffsetFile.length());
+    writtenBytes += invertedIndexOffsetFile.length();
+
+    //add index data
+    bufferId = bufferId + 1;
+    pinotDataBuffer.putLong(getBufferStartOffset(bufferId), writtenBytes);
+    pinotDataBuffer.putLong(getBufferStartOffset(bufferId) + Long.BYTES, invertedIndexFile.length());
+    pinotDataBuffer.readFrom(writtenBytes, invertedIndexFile, 0, invertedIndexFile.length());
+    writtenBytes += invertedIndexFile.length();
+
+    //add flattened docid to root doc id mapping
+    bufferId = bufferId + 1;
+    pinotDataBuffer.putLong(getBufferStartOffset(bufferId), writtenBytes);
+    pinotDataBuffer.putLong(getBufferStartOffset(bufferId) + Long.BYTES, flattenedDocId2RootDocIdMappingFile.length());
+    pinotDataBuffer
+        .readFrom(writtenBytes, flattenedDocId2RootDocIdMappingFile, 0, flattenedDocId2RootDocIdMappingFile.length());
+    writtenBytes += flattenedDocId2RootDocIdMappingFile.length();
+  }
+
+  private long getBufferStartOffset(int bufferId) {
+    return 2 * Integer.BYTES + 2 * bufferId * Long.BYTES;
+  }
+
+  private int createInvertedIndex(File postingListFile, List<Integer> postingListChunkOffsets,
+      List<Integer> chunkLengthList)
+      throws IOException {
+
+    List<Iterator<ImmutablePair<byte[], int[]>>> chunkIterators = new ArrayList<>();
+
+    for (int i = 0; i < chunkLengthList.size(); i++) {
+
+      final DataInputStream postingListFileReader =
+          new DataInputStream(new BufferedInputStream(new FileInputStream(postingListFile)));
+      postingListFileReader.skipBytes(postingListChunkOffsets.get(i));
+      final int length = chunkLengthList.get(i);
+      chunkIterators.add(new Iterator<ImmutablePair<byte[], int[]>>() {
+        int index = 0;
+
+        @Override
+        public boolean hasNext() {
+          return index < length;
+        }
+
+        @Override
+        public ImmutablePair<byte[], int[]> next() {
+          try {
+            int keyLength = postingListFileReader.readInt();
+            byte[] keyBytes = new byte[keyLength];
+            postingListFileReader.read(keyBytes);
+
+            int postingListLength = postingListFileReader.readInt();
+            int[] postingList = new int[postingListLength];
+            for (int i = 0; i < postingListLength; i++) {
+              postingList[i] = postingListFileReader.readInt();
+            }
+            index++;
+            return ImmutablePair.of(keyBytes, postingList);
+          } catch (Exception e) {
+            throw new RuntimeException(e);
+          }
+        }
+      });
+    }
+    final Comparator<byte[]> byteArrayComparator = UnsignedBytes.lexicographicalComparator();
+
+    PriorityQueue<ImmutablePair<Integer, ImmutablePair<byte[], int[]>>> queue =
+        new PriorityQueue<>(chunkLengthList.size(),
+            (o1, o2) -> byteArrayComparator.compare(o1.getRight().getLeft(), o2.getRight().getLeft()));
+    for (int i = 0; i < chunkIterators.size(); i++) {
+      Iterator<ImmutablePair<byte[], int[]>> iterator = chunkIterators.get(i);
+      if (iterator.hasNext()) {
+        queue.offer(ImmutablePair.of(i, iterator.next()));
+      }
+    }
+    byte[] prevKey = null;
+    RoaringBitmap roaringBitmap = new RoaringBitmap();
+
+    Writer writer = new Writer(dictionaryheaderFile, dictionaryOffsetFile, dictionaryFile, invertedIndexOffsetFile,
+        invertedIndexFile);
+    while (!queue.isEmpty()) {
+      ImmutablePair<Integer, ImmutablePair<byte[], int[]>> poll = queue.poll();
+      byte[] currKey = poll.getRight().getLeft();
+      if (prevKey != null && byteArrayComparator.compare(prevKey, currKey) != 0) {
+        System.out.println(new String(prevKey) + ":" + roaringBitmap);
+        writer.add(prevKey, roaringBitmap);
+        roaringBitmap.clear();
+      }
+
+      roaringBitmap.add(poll.getRight().getRight());
+      prevKey = currKey;
+
+      //add the next key from the chunk where the currKey was removed from
+      Iterator<ImmutablePair<byte[], int[]>> iterator = chunkIterators.get(poll.getLeft());
+      if (iterator.hasNext()) {
+        queue.offer(ImmutablePair.of(poll.getLeft(), iterator.next()));
+      }
+    }
+
+    if (prevKey != null) {
+      writer.add(prevKey, roaringBitmap);
+    }
+    writer.finish();
+    return writer.getMaxDictionaryValueLength();
+  }
+
+  private void flush()
+      throws IOException {
+    //write the key (length|actual bytes) - posting list(length, flattenedDocIds)
+    System.out.println("postingListMap = " + postingListMap);
+    for (Map.Entry<String, List<Integer>> entry : postingListMap.entrySet()) {
+      byte[] keyBytes = entry.getKey().getBytes(Charset.forName("UTF-8"));
+      postingListWriter.writeInt(keyBytes.length);
+      postingListWriter.write(keyBytes);
+      List<Integer> flattenedDocIdList = entry.getValue();
+      postingListWriter.writeInt(flattenedDocIdList.size());
+      for (int flattenedDocId : flattenedDocIdList) {
+        postingListWriter.writeInt(flattenedDocId);
+      }
+    }
+
+    //write flattened doc id to root docId mapping
+    for (int rootDocId : flattenedDocIdList) {
+      flattenedDocId2RootDocIdWriter.writeInt(rootDocId);
+    }
+    chunkLengths.add(postingListMap.size());
+    postingListChunkOffsets.add(postingListWriter.size());
+    postingListMap.clear();
+    flattenedDocIdList.clear();
+  }
+
+  private static List<Map<String, String>> unnestJson(JsonNode root) {
+    Iterator<Map.Entry<String, JsonNode>> fields = root.fields();
+    Map<String, String> flattenedSingleValuesMap = new TreeMap<>();
+    Map<String, JsonNode> arrNodes = new TreeMap<>();
+    Map<String, JsonNode> objectNodes = new TreeMap<>();
+    List<Map<String, String>> resultList = new ArrayList<>();
+    List<Map<String, String>> tempResultList = new ArrayList<>();
+    while (fields.hasNext()) {
+      Map.Entry<String, JsonNode> child = fields.next();
+      if (child.getValue().isValueNode()) {
+        //Normal value node
+        flattenedSingleValuesMap.put(child.getKey(), child.getValue().asText());
+      } else if (child.getValue().isArray()) {
+        //Array Node: Process these nodes later
+        arrNodes.put(child.getKey(), child.getValue());
+      } else {
+        //Object Node
+        objectNodes.put(child.getKey(), child.getValue());
+      }
+    }
+    for (String objectNodeKey : objectNodes.keySet()) {
+      JsonNode objectNode = objectNodes.get(objectNodeKey);
+      modifyKeysInMap(flattenedSingleValuesMap, tempResultList, objectNodeKey, objectNode);
+    }
+    if (tempResultList.isEmpty()) {
+      tempResultList.add(flattenedSingleValuesMap);
+    }
+    if (!arrNodes.isEmpty()) {
+      for (Map<String, String> flattenedMapElement : tempResultList) {
+        for (String arrNodeKey : arrNodes.keySet()) {
+          JsonNode arrNode = arrNodes.get(arrNodeKey);
+          for (JsonNode arrNodeElement : arrNode) {
+            modifyKeysInMap(flattenedMapElement, resultList, arrNodeKey, arrNodeElement);
+          }
+        }
+      }
+    } else {
+      resultList.addAll(tempResultList);
+    }
+    return resultList;
+  }
+
+  private static void modifyKeysInMap(Map<String, String> flattenedMap, List<Map<String, String>> resultList,
+      String arrNodeKey, JsonNode arrNode) {
+    List<Map<String, String>> objectResult = unnestJson(arrNode);
+    for (Map<String, String> flattenedObject : objectResult) {
+      Map<String, String> flattenedObjectCopy = new TreeMap<>(flattenedMap);
+      for (Map.Entry<String, String> entry : flattenedObject.entrySet()) {
+        flattenedObjectCopy.put(arrNodeKey + "." + entry.getKey(), entry.getValue());
+      }
+      resultList.add(flattenedObjectCopy);
+    }
+  }
+
+  @Override
+  public void close()
+      throws IOException {
+
+  }
+
+  private class Writer {
+    private DataOutputStream _dictionaryHeaderWriter;
+    private DataOutputStream _dictionaryOffsetWriter;
+    private File _dictionaryOffsetFile;
+    private DataOutputStream _dictionaryWriter;
+    private DataOutputStream _invertedIndexOffsetWriter;
+    private File _invertedIndexOffsetFile;
+    private DataOutputStream _invertedIndexWriter;
+    private int _dictId;
+    private int _dictOffset;
+    private int _invertedIndexOffset;
+    int _maxDictionaryValueLength = Integer.MIN_VALUE;
+
+    public Writer(File dictionaryheaderFile, File dictionaryOffsetFile, File dictionaryFile,
+        File invertedIndexOffsetFile, File invertedIndexFile)
+        throws IOException {
+      _dictionaryHeaderWriter =
+          new DataOutputStream(new BufferedOutputStream(new FileOutputStream(dictionaryheaderFile)));
+
+      _dictionaryOffsetWriter =
+          new DataOutputStream(new BufferedOutputStream(new FileOutputStream(dictionaryOffsetFile)));
+      _dictionaryOffsetFile = dictionaryOffsetFile;
+      _dictionaryWriter = new DataOutputStream(new BufferedOutputStream(new FileOutputStream(dictionaryFile)));
+      _invertedIndexOffsetWriter =
+          new DataOutputStream(new BufferedOutputStream(new FileOutputStream(invertedIndexOffsetFile)));
+      _invertedIndexOffsetFile = invertedIndexOffsetFile;
+      _invertedIndexWriter = new DataOutputStream(new BufferedOutputStream(new FileOutputStream(invertedIndexFile)));
+      _dictId = 0;
+      _dictOffset = 0;
+      _invertedIndexOffset = 0;
+    }
+
+    public void add(byte[] key, RoaringBitmap roaringBitmap)
+        throws IOException {
+      if (key.length > _maxDictionaryValueLength) {
+        _maxDictionaryValueLength = key.length;
+      }
+      //write the key to dictionary
+      _dictionaryOffsetWriter.writeInt(_dictOffset);
+      _dictionaryWriter.write(key);
+
+      //write the roaringBitmap to inverted index
+      _invertedIndexOffsetWriter.writeInt(_invertedIndexOffset);
+
+      int serializedSizeInBytes = roaringBitmap.serializedSizeInBytes();
+      byte[] serializedRoaringBitmap = new byte[serializedSizeInBytes];
+      ByteBuffer serializedRoaringBitmapBuffer = ByteBuffer.wrap(serializedRoaringBitmap);
+      roaringBitmap.serialize(serializedRoaringBitmapBuffer);
+      _invertedIndexWriter.write(serializedRoaringBitmap);
+      System.out.println(
+          "dictId = " + _dictId + ", dict offset:" + _dictOffset + ", valueLength:" + key.length + ", inv offset:"
+              + _invertedIndexOffset + ", serializedSizeInBytes:" + serializedSizeInBytes);
+
+      //increment offsets
+      _dictOffset = _dictOffset + key.length;
+      _invertedIndexOffset = _invertedIndexOffset + serializedSizeInBytes;
+      //increment the dictionary id
+      _dictId = _dictId + 1;
+    }
+
+    void finish()
+        throws IOException {
+      //InvertedIndexReader and VarlengthBytesValueReaderWriter needs one extra entry for offsets since it computes the length for index i using offset[i+1] - offset[i]
+      _invertedIndexOffsetWriter.writeInt(_invertedIndexOffset);
+      _dictionaryOffsetWriter.writeInt(_dictOffset);
+
+      byte[] headerBytes = VarLengthBytesValueReaderWriter.getHeaderBytes(_dictId);
+      _dictionaryHeaderWriter.write(headerBytes);
+      System.out.println("headerBytes = " + Arrays.toString(headerBytes));
+
+      _dictionaryHeaderWriter.close();
+      _dictionaryOffsetWriter.close();
+      _dictionaryWriter.close();
+      _invertedIndexOffsetWriter.close();
+      _invertedIndexWriter.close();
+
+      //data offsets started with zero but the actual dictionary and index will contain (header + offsets + data). so all the offsets must be adjusted ( i.e add size(header) + size(offset) to each offset value)
+      PinotDataBuffer dictionaryOffsetBuffer = PinotDataBuffer
+          .mapFile(dictionaryOffsetFile, false, 0, _dictionaryOffsetFile.length(), ByteOrder.BIG_ENDIAN,
+              "dictionary offset file");
+      int dictOffsetBase = _dictionaryHeaderWriter.size() + _dictionaryOffsetWriter.size();
+      for (int i = 0; i < _dictId + 1; i++) {
+        int offset = dictionaryOffsetBuffer.getInt(i * Integer.BYTES);
+        int newOffset = offset + dictOffsetBase;
+        dictionaryOffsetBuffer.putInt(i * Integer.BYTES, offset + dictOffsetBase);
+        System.out.println("dictId = " + i + ", offset = " + offset + ", newOffset = " + newOffset);
+      }
+
+      PinotDataBuffer invIndexOffsetBuffer = PinotDataBuffer
+          .mapFile(invertedIndexOffsetFile, false, 0, invertedIndexOffsetFile.length(), ByteOrder.BIG_ENDIAN,
+              "invertedIndexOffsetFile");
+      int invIndexOffsetBase = _invertedIndexOffsetWriter.size();
+      for (int i = 0; i < _dictId + 1; i++) {
+        int offset = invIndexOffsetBuffer.getInt(i * Integer.BYTES);
+        int newOffset = offset + invIndexOffsetBase;
+        System.out.println("offset = " + offset + ", newOffset = " + newOffset);
+
+        invIndexOffsetBuffer.putInt(i * Integer.BYTES, newOffset);
+      }
+
+      invIndexOffsetBuffer.close();
+      dictionaryOffsetBuffer.close();
+    }
+
+    public int getMaxDictionaryValueLength() {
+      return _maxDictionaryValueLength;
+    }
+  }
+
+  public static void main(String[] args)
+      throws Exception {
+
+    String json0 = " { \"a\" : { \"b\" : 1, \"c\": 3, \"d\": [{\"x\" : 1}, {\"y\" : 1}] }, \"e\": \"f\", \"g\":2.3 }";
+    String json1 =
+        " { \"name\" : \"adam\", \"age\": 30, \"country\": \"us\", \"address\": {\"number\" : 112, \"street\": \"main st\", \"country\": \"us\"  } }";
+    String json2 = " { \"name\" : \"adam\", \"age\": 30 }";
+    String json3 = "{\n" + "  \"name\" : \"adam\",\n" + "  \"age\" : 30,\n" + "  \"country\" : \"us\",\n"
+        + "  \"addresses\" : [{\n" + "    \"number\" : 1,\n" + "    \"street\" : \"main st\",\n"
+        + "    \"country\" : \"us\"\n" + "  }, {\n" + "    \"number\" : 2,\n" + "    \"street\" : \"second st\",\n"
+        + "    \"country\" : \"us\"\n" + "  }, {\n" + "    \"number\" : 3,\n" + "    \"street\" : \"third st\",\n"
+        + "    \"country\" : \"us\"\n" + "  }]\n" + "}\n";
+
+    String json4 =
+        "{\n" + "    \"year\": [\n" + "        2018\n" + "    ],\n" + "    \"customers\": [\n" + "        {\n"
+            + "            \"name\": \"John\",\n" + "            \"contact\": [\n" + "                {\n"
+            + "                    \"phone\": \"home\",\n" + "                    \"number\": \"333-3334\"\n"
+            + "                }\n" + "            ]\n" + "        },\n" + "        {\n"
+            + "            \"name\": \"Jane\",\n" + "            \"contact\": [\n" + "                {\n"
+            + "                    \"phone\": \"home\",\n" + "                    \"number\": \"555-5556\"\n"
+            + "                }\n" + "            ],\n" + "            \"surname\": \"Shaw\"\n" + "        }\n"
+            + "    ]\n" + "}";
+
+    String json5 = "{ \n" + "  \"accounting\" : [   \n" + "                     { \"firstName\" : \"John\",  \n"
+        + "                       \"lastName\"  : \"Doe\",\n" + "                       \"age\"       : 23 },\n" + "\n"
+        + "                     { \"firstName\" : \"Mary\",  \n" + "                       \"lastName\"  : \"Smith\",\n"
+        + "                        \"age\"      : 32 }\n" + "                 ],                            \n"
+        + "  \"sales\"      : [ \n" + "                     { \"firstName\" : \"Sally\", \n"
+        + "                       \"lastName\"  : \"Green\",\n" + "                        \"age\"      : 27 },\n"
+        + "\n" + "                     { \"firstName\" : \"Jim\",   \n"
+        + "                       \"lastName\"  : \"Galley\",\n" + "                       \"age\"       : 41 }\n"
+        + "                 ] \n" + "} ";
+
+    String json = json3;
+    System.out.println("json = " + json);
+    JsonNode rawJsonNode = new ObjectMapper().readTree(json);
+
+    System.out.println(
+        "rawJsonNode = " + new ObjectMapper().writerWithDefaultPrettyPrinter().writeValueAsString(rawJsonNode));
+    String flattenJson = JsonFlattener.flatten(json);
+
+    System.out.println("flattenJson = " + flattenJson);
+    JsonNode jsonNode = new ObjectMapper().readTree(flattenJson);
+
+    System.out
+        .println("jsonNode = " + new ObjectMapper().writerWithDefaultPrettyPrinter().writeValueAsString(jsonNode));
+    Map<String, Object> stringObjectMap = JsonFlattener.flattenAsMap(json);
+    System.out.println("JsonFlattener.flattenAsMap(json) = " + stringObjectMap);
+    FieldSpec fieldSpec = new DimensionFieldSpec();
+    fieldSpec.setName("person");
+    File tempDir = Files.createTempDir();
+    JSONIndexCreator creator = new JSONIndexCreator(tempDir, fieldSpec);
+    List<Map<String, String>> maps = creator.unnestJson(rawJsonNode);
+    System.out.println("maps = " + maps.toString().replaceAll("},", "}\n"));
+    creator.add(json.getBytes());
+
+    creator.seal();
+    System.out.println("Output Dir = " + tempDir);
+    System.out.println("FileUtils.listFiles(tempDir, null, true) = " + FileUtils.listFiles(tempDir, null, true).stream()
+        .map(file -> file.getName()).collect(Collectors.toList()));
+
+    //Test reader
+    PinotDataBuffer buffer =
+        PinotDataBuffer.mapReadOnlyBigEndianFile(new File(tempDir, fieldSpec.getName() + ".json.idx"));
+    JSONIndexReader reader = new JSONIndexReader(buffer);
+    ExpressionContext lhs = ExpressionContext.forIdentifier("person");
+    Predicate predicate = new EqPredicate(lhs, "addresses.street" + POSTING_LIST_KEY_SEPARATOR + "third st");
+    MutableRoaringBitmap matchingDocIds = reader.getMatchingDocIds(predicate);
+    System.out.println("matchingDocIds = " + matchingDocIds);
+
+    //Test filter operator
+    FilterContext filterContext = QueryContextConverterUtils
+        .getFilter(CalciteSqlParser.compileToExpression("name='adam' AND addresses.street='main st'"));
+    int numDocs = 1;
+    JSONMatchFilterOperator operator = new JSONMatchFilterOperator("person", filterContext, reader, numDocs);
+    FilterBlock filterBlock = operator.nextBlock();
+    BlockDocIdIterator iterator = filterBlock.getBlockDocIdSet().iterator();
+    int docId = -1;
+    while ((docId = iterator.next()) > 0) {
+      System.out.println("docId = " + docId);
+    }
+  }
+}
\ No newline at end of file
diff --git a/pinot-core/src/main/java/org/apache/pinot/core/segment/creator/impl/inv/NestedObjectIndexCreator.java b/pinot-core/src/main/java/org/apache/pinot/core/segment/creator/impl/inv/NestedObjectIndexCreator.java
deleted file mode 100644
index adfa19d..0000000
--- a/pinot-core/src/main/java/org/apache/pinot/core/segment/creator/impl/inv/NestedObjectIndexCreator.java
+++ /dev/null
@@ -1,158 +0,0 @@
-/**
- * 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.pinot.core.segment.creator.impl.inv;
-
-import com.fasterxml.jackson.databind.JsonNode;
-import com.fasterxml.jackson.databind.ObjectMapper;
-import com.github.wnameless.json.flattener.JsonFlattener;
-import java.io.File;
-import java.io.IOException;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Map;
-import java.util.TreeMap;
-import org.apache.pinot.spi.data.FieldSpec;
-
-
-public class NestedObjectIndexCreator {
-
-  public NestedObjectIndexCreator(File indexDir, FieldSpec fieldSpec, FieldSpec.DataType valueType) {
-
-  }
-
-  private static List<Map<String, String>> unnestJson(JsonNode root) {
-    Iterator<Map.Entry<String, JsonNode>> fields = root.fields();
-    Map<String, String> flattenedSingleValuesMap = new TreeMap<>();
-    Map<String, JsonNode> arrNodes = new TreeMap<>();
-    Map<String, JsonNode> objectNodes = new TreeMap<>();
-    List<Map<String, String>> resultList = new ArrayList<>();
-    List<Map<String, String>> tempResultList = new ArrayList<>();
-    while (fields.hasNext()) {
-      Map.Entry<String, JsonNode> child = fields.next();
-      if (child.getValue().isValueNode()) {
-        //Normal value node
-        flattenedSingleValuesMap.put(child.getKey(), child.getValue().asText());
-      } else if (child.getValue().isArray()) {
-        //Array Node: Process these nodes later
-        arrNodes.put(child.getKey(), child.getValue());
-      } else {
-        //Object Node
-        objectNodes.put(child.getKey(), child.getValue());
-      }
-    }
-    for (String objectNodeKey : objectNodes.keySet()) {
-      JsonNode objectNode = objectNodes.get(objectNodeKey);
-      modifyKeysInMap(flattenedSingleValuesMap, tempResultList, objectNodeKey, objectNode);
-    }
-    if (tempResultList.isEmpty()) {
-      tempResultList.add(flattenedSingleValuesMap);
-    }
-    if (!arrNodes.isEmpty()) {
-      for (Map<String, String> flattenedMapElement : tempResultList) {
-        for (String arrNodeKey : arrNodes.keySet()) {
-          JsonNode arrNode = arrNodes.get(arrNodeKey);
-          for (JsonNode arrNodeElement : arrNode) {
-            modifyKeysInMap(flattenedMapElement, resultList, arrNodeKey, arrNodeElement);
-          }
-        }
-      }
-    } else {
-      resultList.addAll(tempResultList);
-    }
-    return resultList;
-  }
-
-  private static void modifyKeysInMap(Map<String, String> flattenedMap, List<Map<String, String>> resultList,
-      String arrNodeKey, JsonNode arrNode) {
-    List<Map<String, String>> objectResult = unnestJson(arrNode);
-    for (Map<String, String> flattenedObject : objectResult) {
-      Map<String, String> flattenedObjectCopy = new TreeMap<>(flattenedMap);
-      for (Map.Entry<String, String> entry : flattenedObject.entrySet()) {
-        flattenedObjectCopy.put(arrNodeKey + "." + entry.getKey(), entry.getValue());
-      }
-      resultList.add(flattenedObjectCopy);
-    }
-  }
-
-  public void add(byte[] data)
-      throws IOException {
-
-    JsonNode jsonNode = new ObjectMapper().readTree(data);
-    List<Map<String, String>> flattenedMapList = unnestJson(jsonNode);
-    for (Map<String, String> map : flattenedMapList) {
-
-    }
-  }
-
-  public static void main(String[] args)
-      throws IOException {
-
-    String json0 = " { \"a\" : { \"b\" : 1, \"c\": 3, \"d\": [{\"x\" : 1}, {\"y\" : 1}] }, \"e\": \"f\", \"g\":2.3 }";
-    String json1 =
-        " { \"name\" : \"adam\", \"age\": 30, \"country\": \"us\", \"address\": {\"number\" : 112, \"street\": \"main st\", \"country\": \"us\"  } }";
-    String json2 = " { \"name\" : \"adam\", \"age\": 30 }";
-    String json3 = "{\n" + "  \"name\" : \"adam\",\n" + "  \"age\" : 30,\n" + "  \"country\" : \"us\",\n"
-        + "  \"addresses\" : [{\n" + "    \"number\" : 1,\n" + "    \"street\" : \"main st\",\n"
-        + "    \"country\" : \"us\"\n" + "  }, {\n" + "    \"number\" : 2,\n" + "    \"street\" : \"second st\",\n"
-        + "    \"country\" : \"us\"\n" + "  }, {\n" + "    \"number\" : 3,\n" + "    \"street\" : \"third st\",\n"
-        + "    \"country\" : \"us\"\n" + "  }]\n" + "}\n";
-
-    String json4 =
-        "{\n" + "    \"year\": [\n" + "        2018\n" + "    ],\n" + "    \"customers\": [\n" + "        {\n"
-            + "            \"name\": \"John\",\n" + "            \"contact\": [\n" + "                {\n"
-            + "                    \"phone\": \"home\",\n" + "                    \"number\": \"333-3334\"\n"
-            + "                }\n" + "            ]\n" + "        },\n" + "        {\n"
-            + "            \"name\": \"Jane\",\n" + "            \"contact\": [\n" + "                {\n"
-            + "                    \"phone\": \"home\",\n" + "                    \"number\": \"555-5556\"\n"
-            + "                }\n" + "            ],\n" + "            \"surname\": \"Shaw\"\n" + "        }\n"
-            + "    ]\n" + "}";
-
-    String json5 = "{ \n" + "  \"accounting\" : [   \n" + "                     { \"firstName\" : \"John\",  \n"
-        + "                       \"lastName\"  : \"Doe\",\n" + "                       \"age\"       : 23 },\n" + "\n"
-        + "                     { \"firstName\" : \"Mary\",  \n" + "                       \"lastName\"  : \"Smith\",\n"
-        + "                        \"age\"      : 32 }\n" + "                 ],                            \n"
-        + "  \"sales\"      : [ \n" + "                     { \"firstName\" : \"Sally\", \n"
-        + "                       \"lastName\"  : \"Green\",\n" + "                        \"age\"      : 27 },\n"
-        + "\n" + "                     { \"firstName\" : \"Jim\",   \n"
-        + "                       \"lastName\"  : \"Galley\",\n" + "                       \"age\"       : 41 }\n"
-        + "                 ] \n" + "} ";
-
-    String json = json3;
-    System.out.println("json = " + json);
-    JsonNode rawJsonNode = new ObjectMapper().readTree(json);
-
-    System.out.println(
-        "rawJsonNode = " + new ObjectMapper().writerWithDefaultPrettyPrinter().writeValueAsString(rawJsonNode));
-    String flattenJson = JsonFlattener.flatten(json);
-
-    System.out.println("flattenJson = " + flattenJson);
-    JsonNode jsonNode = new ObjectMapper().readTree(flattenJson);
-
-    System.out
-        .println("jsonNode = " + new ObjectMapper().writerWithDefaultPrettyPrinter().writeValueAsString(jsonNode));
-    Map<String, Object> stringObjectMap = JsonFlattener.flattenAsMap(json);
-    System.out.println("JsonFlattener.flattenAsMap(json) = " + stringObjectMap);
-    NestedObjectIndexCreator creator = new NestedObjectIndexCreator(null, null, null);
-    List<Map<String, String>> maps = creator.unnestJson(rawJsonNode);
-    System.out.println("maps = " + maps.toString().replaceAll("},", "}\n"));
-//    creator.add(json.getBytes());
-  }
-}
diff --git a/pinot-core/src/main/java/org/apache/pinot/core/segment/index/column/ColumnIndexContainer.java b/pinot-core/src/main/java/org/apache/pinot/core/segment/index/column/ColumnIndexContainer.java
index 087f4b2..909a669 100644
--- a/pinot-core/src/main/java/org/apache/pinot/core/segment/index/column/ColumnIndexContainer.java
+++ b/pinot-core/src/main/java/org/apache/pinot/core/segment/index/column/ColumnIndexContainer.java
@@ -23,6 +23,7 @@ import org.apache.pinot.core.segment.index.readers.BloomFilterReader;
 import org.apache.pinot.core.segment.index.readers.Dictionary;
 import org.apache.pinot.core.segment.index.readers.ForwardIndexReader;
 import org.apache.pinot.core.segment.index.readers.InvertedIndexReader;
+import org.apache.pinot.core.segment.index.readers.JSONIndexReader;
 import org.apache.pinot.core.segment.index.readers.NullValueVectorReaderImpl;
 import org.apache.pinot.core.segment.index.readers.TextIndexReader;
 
@@ -68,4 +69,10 @@ public interface ColumnIndexContainer extends Closeable {
    * @return Get the null value vector for the column, or {@code null} if it does not exist.
    */
   NullValueVectorReaderImpl getNullValueVector();
+
+  /**
+   *
+   * @return Get the JSON index for the column, or {@code null} if it does not exist.
+   */
+  JSONIndexReader getJSONIndex();
 }
diff --git a/pinot-core/src/main/java/org/apache/pinot/core/segment/index/column/PhysicalColumnIndexContainer.java b/pinot-core/src/main/java/org/apache/pinot/core/segment/index/column/PhysicalColumnIndexContainer.java
index 595a8e0..398623b 100644
--- a/pinot-core/src/main/java/org/apache/pinot/core/segment/index/column/PhysicalColumnIndexContainer.java
+++ b/pinot-core/src/main/java/org/apache/pinot/core/segment/index/column/PhysicalColumnIndexContainer.java
@@ -33,6 +33,7 @@ import org.apache.pinot.core.segment.index.readers.FloatDictionary;
 import org.apache.pinot.core.segment.index.readers.ForwardIndexReader;
 import org.apache.pinot.core.segment.index.readers.IntDictionary;
 import org.apache.pinot.core.segment.index.readers.InvertedIndexReader;
+import org.apache.pinot.core.segment.index.readers.JSONIndexReader;
 import org.apache.pinot.core.segment.index.readers.LongDictionary;
 import org.apache.pinot.core.segment.index.readers.NullValueVectorReaderImpl;
 import org.apache.pinot.core.segment.index.readers.OnHeapDoubleDictionary;
@@ -70,6 +71,7 @@ public final class PhysicalColumnIndexContainer implements ColumnIndexContainer
   private final BaseImmutableDictionary _dictionary;
   private final BloomFilterReader _bloomFilter;
   private final NullValueVectorReaderImpl _nullValueVectorReader;
+  private final JSONIndexReader _jsonIndex;
 
   public PhysicalColumnIndexContainer(SegmentDirectory.Reader segmentReader, ColumnMetadata metadata,
       IndexLoadingConfig indexLoadingConfig, File segmentIndexDir)
@@ -79,6 +81,7 @@ public final class PhysicalColumnIndexContainer implements ColumnIndexContainer
     boolean loadRangeIndex = indexLoadingConfig.getRangeIndexColumns().contains(columnName);
     boolean loadTextIndex = indexLoadingConfig.getTextIndexColumns().contains(columnName);
     boolean loadOnHeapDictionary = indexLoadingConfig.getOnHeapDictionaryColumns().contains(columnName);
+    boolean loadJSONIndex = indexLoadingConfig.getJsonIndexColumns().contains(columnName);
     BloomFilterConfig bloomFilterConfig = indexLoadingConfig.getBloomFilterConfigs().get(columnName);
 
     if (segmentReader.hasIndexFor(columnName, ColumnIndexType.NULLVALUE_VECTOR)) {
@@ -96,6 +99,13 @@ public final class PhysicalColumnIndexContainer implements ColumnIndexContainer
     } else {
       _textIndex = null;
     }
+    if (loadJSONIndex) {
+      Preconditions.checkState(segmentReader.hasIndexFor(columnName, ColumnIndexType.JSON_INDEX));
+      PinotDataBuffer jsonIndexBuffer = segmentReader.getIndexFor(columnName, ColumnIndexType.JSON_INDEX);
+      _jsonIndex = new JSONIndexReader(jsonIndexBuffer);
+    } else {
+      _jsonIndex = null;
+    }
 
     PinotDataBuffer fwdIndexBuffer = segmentReader.getIndexFor(columnName, ColumnIndexType.FORWARD_INDEX);
 
@@ -187,6 +197,11 @@ public final class PhysicalColumnIndexContainer implements ColumnIndexContainer
     return _nullValueVectorReader;
   }
 
+  @Override
+  public JSONIndexReader getJSONIndex() {
+    return _jsonIndex;
+  }
+
   //TODO: move this to a DictionaryLoader class
   public static BaseImmutableDictionary loadDictionary(PinotDataBuffer dictionaryBuffer, ColumnMetadata metadata,
       boolean loadOnHeap) {
diff --git a/pinot-core/src/main/java/org/apache/pinot/core/segment/index/datasource/BaseDataSource.java b/pinot-core/src/main/java/org/apache/pinot/core/segment/index/datasource/BaseDataSource.java
index 172e8e6..278b737 100644
--- a/pinot-core/src/main/java/org/apache/pinot/core/segment/index/datasource/BaseDataSource.java
+++ b/pinot-core/src/main/java/org/apache/pinot/core/segment/index/datasource/BaseDataSource.java
@@ -25,6 +25,7 @@ import org.apache.pinot.core.segment.index.readers.BloomFilterReader;
 import org.apache.pinot.core.segment.index.readers.Dictionary;
 import org.apache.pinot.core.segment.index.readers.ForwardIndexReader;
 import org.apache.pinot.core.segment.index.readers.InvertedIndexReader;
+import org.apache.pinot.core.segment.index.readers.JSONIndexReader;
 import org.apache.pinot.core.segment.index.readers.NullValueVectorReader;
 import org.apache.pinot.core.segment.index.readers.TextIndexReader;
 
@@ -38,11 +39,14 @@ public abstract class BaseDataSource implements DataSource {
   private final TextIndexReader _textIndex;
   private final BloomFilterReader _bloomFilter;
   private final NullValueVectorReader _nullValueVector;
+  @Nullable
+  private JSONIndexReader _jsonIndexReader;
 
   public BaseDataSource(DataSourceMetadata dataSourceMetadata, ForwardIndexReader<?> forwardIndex,
       @Nullable Dictionary dictionary, @Nullable InvertedIndexReader<?> invertedIndex,
       @Nullable InvertedIndexReader<?> rangeIndex, @Nullable TextIndexReader textIndex,
-      @Nullable BloomFilterReader bloomFilter, @Nullable NullValueVectorReader nullValueVector) {
+      @Nullable BloomFilterReader bloomFilter, @Nullable NullValueVectorReader nullValueVector,
+      @Nullable JSONIndexReader jsonIndexReader) {
     _dataSourceMetadata = dataSourceMetadata;
     _forwardIndex = forwardIndex;
     _dictionary = dictionary;
@@ -51,6 +55,7 @@ public abstract class BaseDataSource implements DataSource {
     _textIndex = textIndex;
     _bloomFilter = bloomFilter;
     _nullValueVector = nullValueVector;
+    _jsonIndexReader = jsonIndexReader;
   }
 
   @Override
@@ -98,4 +103,10 @@ public abstract class BaseDataSource implements DataSource {
   public NullValueVectorReader getNullValueVector() {
     return _nullValueVector;
   }
+
+  @Nullable
+  @Override
+  public JSONIndexReader getJSONIndex() {
+    return _jsonIndexReader;
+  }
 }
diff --git a/pinot-core/src/main/java/org/apache/pinot/core/segment/index/datasource/ImmutableDataSource.java b/pinot-core/src/main/java/org/apache/pinot/core/segment/index/datasource/ImmutableDataSource.java
index cc09adf..9af73a7 100644
--- a/pinot-core/src/main/java/org/apache/pinot/core/segment/index/datasource/ImmutableDataSource.java
+++ b/pinot-core/src/main/java/org/apache/pinot/core/segment/index/datasource/ImmutableDataSource.java
@@ -23,7 +23,9 @@ import javax.annotation.Nullable;
 import org.apache.pinot.core.common.DataSourceMetadata;
 import org.apache.pinot.core.data.partition.PartitionFunction;
 import org.apache.pinot.core.segment.index.column.ColumnIndexContainer;
+import org.apache.pinot.core.segment.index.datasource.BaseDataSource;
 import org.apache.pinot.core.segment.index.metadata.ColumnMetadata;
+import org.apache.pinot.core.segment.index.readers.JSONIndexReader;
 import org.apache.pinot.spi.data.FieldSpec;
 
 
@@ -36,9 +38,10 @@ public class ImmutableDataSource extends BaseDataSource {
     super(new ImmutableDataSourceMetadata(columnMetadata), columnIndexContainer.getForwardIndex(),
         columnIndexContainer.getDictionary(), columnIndexContainer.getInvertedIndex(),
         columnIndexContainer.getRangeIndex(), columnIndexContainer.getTextIndex(),
-        columnIndexContainer.getBloomFilter(), columnIndexContainer.getNullValueVector());
+        columnIndexContainer.getBloomFilter(), columnIndexContainer.getNullValueVector(), columnIndexContainer.getJSONIndex());
   }
 
+
   private static class ImmutableDataSourceMetadata implements DataSourceMetadata {
     final FieldSpec _fieldSpec;
     final boolean _sorted;
diff --git a/pinot-core/src/main/java/org/apache/pinot/core/segment/index/datasource/MutableDataSource.java b/pinot-core/src/main/java/org/apache/pinot/core/segment/index/datasource/MutableDataSource.java
index a927353..c38b1bb 100644
--- a/pinot-core/src/main/java/org/apache/pinot/core/segment/index/datasource/MutableDataSource.java
+++ b/pinot-core/src/main/java/org/apache/pinot/core/segment/index/datasource/MutableDataSource.java
@@ -26,6 +26,7 @@ import org.apache.pinot.core.segment.index.readers.BloomFilterReader;
 import org.apache.pinot.core.segment.index.readers.Dictionary;
 import org.apache.pinot.core.segment.index.readers.ForwardIndexReader;
 import org.apache.pinot.core.segment.index.readers.InvertedIndexReader;
+import org.apache.pinot.core.segment.index.readers.JSONIndexReader;
 import org.apache.pinot.core.segment.index.readers.NullValueVectorReader;
 import org.apache.pinot.core.segment.index.readers.TextIndexReader;
 import org.apache.pinot.spi.data.FieldSpec;
@@ -42,10 +43,10 @@ public class MutableDataSource extends BaseDataSource {
       @Nullable Comparable maxValue, ForwardIndexReader forwardIndex, @Nullable Dictionary dictionary,
       @Nullable InvertedIndexReader invertedIndex, @Nullable InvertedIndexReader rangeIndex,
       @Nullable TextIndexReader textIndex, @Nullable BloomFilterReader bloomFilter,
-      @Nullable NullValueVectorReader nullValueVector) {
+      @Nullable NullValueVectorReader nullValueVector, JSONIndexReader jsonIndex) {
     super(new MutableDataSourceMetadata(fieldSpec, numDocs, numValues, maxNumValuesPerMVEntry, partitionFunction,
             partitions, minValue, maxValue), forwardIndex, dictionary, invertedIndex, rangeIndex, textIndex, bloomFilter,
-        nullValueVector);
+        nullValueVector, jsonIndex);
   }
 
   private static class MutableDataSourceMetadata implements DataSourceMetadata {
diff --git a/pinot-core/src/main/java/org/apache/pinot/core/segment/index/loader/IndexLoadingConfig.java b/pinot-core/src/main/java/org/apache/pinot/core/segment/index/loader/IndexLoadingConfig.java
index a6817a0..24a799c 100644
--- a/pinot-core/src/main/java/org/apache/pinot/core/segment/index/loader/IndexLoadingConfig.java
+++ b/pinot-core/src/main/java/org/apache/pinot/core/segment/index/loader/IndexLoadingConfig.java
@@ -47,6 +47,7 @@ public class IndexLoadingConfig {
   private ReadMode _readMode = ReadMode.DEFAULT_MODE;
   private List<String> _sortedColumns = Collections.emptyList();
   private Set<String> _invertedIndexColumns = new HashSet<>();
+  private Set<String> _jsonIndexColumns = new HashSet<>();
   private Set<String> _textIndexColumns = new HashSet<>();
   private Set<String> _rangeIndexColumns = new HashSet<>();
   private Set<String> _noDictionaryColumns = new HashSet<>(); // TODO: replace this by _noDictionaryConfig.
@@ -92,6 +93,11 @@ public class IndexLoadingConfig {
       _invertedIndexColumns.addAll(invertedIndexColumns);
     }
 
+    List<String> jsonIndexColumns = indexingConfig.getJsonIndexColumns();
+    if (jsonIndexColumns != null) {
+      _jsonIndexColumns.addAll(jsonIndexColumns);
+    }
+
     List<String> rangeIndexColumns = indexingConfig.getRangeIndexColumns();
     if (rangeIndexColumns != null) {
       _rangeIndexColumns.addAll(rangeIndexColumns);
@@ -222,6 +228,10 @@ public class IndexLoadingConfig {
     return _invertedIndexColumns;
   }
 
+  public Set<String> getJsonIndexColumns() {
+    return _jsonIndexColumns;
+  }
+
   public Set<String> getRangeIndexColumns() {
     return _rangeIndexColumns;
   }
diff --git a/pinot-core/src/main/java/org/apache/pinot/core/segment/index/loader/SegmentPreProcessor.java b/pinot-core/src/main/java/org/apache/pinot/core/segment/index/loader/SegmentPreProcessor.java
index ca7f7e9..06a7adb 100644
--- a/pinot-core/src/main/java/org/apache/pinot/core/segment/index/loader/SegmentPreProcessor.java
+++ b/pinot-core/src/main/java/org/apache/pinot/core/segment/index/loader/SegmentPreProcessor.java
@@ -31,6 +31,7 @@ import org.apache.pinot.core.segment.index.loader.columnminmaxvalue.ColumnMinMax
 import org.apache.pinot.core.segment.index.loader.defaultcolumn.DefaultColumnHandler;
 import org.apache.pinot.core.segment.index.loader.defaultcolumn.DefaultColumnHandlerFactory;
 import org.apache.pinot.core.segment.index.loader.invertedindex.InvertedIndexHandler;
+import org.apache.pinot.core.segment.index.loader.invertedindex.JSONIndexHandler;
 import org.apache.pinot.core.segment.index.loader.invertedindex.RangeIndexHandler;
 import org.apache.pinot.core.segment.index.loader.invertedindex.TextIndexHandler;
 import org.apache.pinot.core.segment.index.metadata.SegmentMetadataImpl;
@@ -113,6 +114,11 @@ public class SegmentPreProcessor implements AutoCloseable {
           new RangeIndexHandler(_indexDir, _segmentMetadata, _indexLoadingConfig, segmentWriter);
       rangeIndexHandler.createRangeIndices();
 
+      // Create json range indices according to the index config.
+      JSONIndexHandler jsonIndexHandler =
+          new JSONIndexHandler(_indexDir, _segmentMetadata, _indexLoadingConfig, segmentWriter);
+      jsonIndexHandler.createJsonIndices();
+
       Set<String> textIndexColumns = _indexLoadingConfig.getTextIndexColumns();
       if (textIndexColumns.size() > 0) {
         TextIndexHandler textIndexHandler =
diff --git a/pinot-core/src/main/java/org/apache/pinot/core/segment/index/loader/invertedindex/JSONIndexHandler.java b/pinot-core/src/main/java/org/apache/pinot/core/segment/index/loader/invertedindex/JSONIndexHandler.java
new file mode 100644
index 0000000..64282de
--- /dev/null
+++ b/pinot-core/src/main/java/org/apache/pinot/core/segment/index/loader/invertedindex/JSONIndexHandler.java
@@ -0,0 +1,216 @@
+/**
+ * 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.pinot.core.segment.index.loader.invertedindex;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.HashSet;
+import java.util.Set;
+import org.apache.commons.io.FileUtils;
+import org.apache.pinot.core.indexsegment.generator.SegmentVersion;
+import org.apache.pinot.core.segment.creator.impl.inv.JSONIndexCreator;
+import org.apache.pinot.core.segment.index.column.PhysicalColumnIndexContainer;
+import org.apache.pinot.core.segment.index.loader.IndexLoadingConfig;
+import org.apache.pinot.core.segment.index.loader.LoaderUtils;
+import org.apache.pinot.core.segment.index.metadata.ColumnMetadata;
+import org.apache.pinot.core.segment.index.metadata.SegmentMetadataImpl;
+import org.apache.pinot.core.segment.index.readers.BaseImmutableDictionary;
+import org.apache.pinot.core.segment.index.readers.Dictionary;
+import org.apache.pinot.core.segment.index.readers.ForwardIndexReader;
+import org.apache.pinot.core.segment.index.readers.ForwardIndexReaderContext;
+import org.apache.pinot.core.segment.index.readers.forward.FixedBitMVForwardIndexReader;
+import org.apache.pinot.core.segment.index.readers.forward.FixedBitSVForwardIndexReader;
+import org.apache.pinot.core.segment.memory.PinotDataBuffer;
+import org.apache.pinot.core.segment.store.ColumnIndexType;
+import org.apache.pinot.core.segment.store.SegmentDirectory;
+import org.apache.pinot.spi.data.FieldSpec;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import static org.apache.pinot.core.segment.creator.impl.V1Constants.Indexes.JSON_INDEX_FILE_EXTENSION;
+
+
+@SuppressWarnings({"rawtypes", "unchecked"})
+public class JSONIndexHandler {
+  private static final Logger LOGGER = LoggerFactory.getLogger(JSONIndexHandler.class);
+
+  private final File _indexDir;
+  private final SegmentDirectory.Writer _segmentWriter;
+  private final String _segmentName;
+  private final SegmentVersion _segmentVersion;
+  private final Set<ColumnMetadata> _jsonIndexColumns = new HashSet<>();
+
+  public JSONIndexHandler(File indexDir, SegmentMetadataImpl segmentMetadata, IndexLoadingConfig indexLoadingConfig,
+      SegmentDirectory.Writer segmentWriter) {
+    _indexDir = indexDir;
+    _segmentWriter = segmentWriter;
+    _segmentName = segmentMetadata.getName();
+    _segmentVersion = SegmentVersion.valueOf(segmentMetadata.getVersion());
+
+    // Only create json index on dictionary-encoded unsorted columns
+    for (String column : indexLoadingConfig.getJsonIndexColumns()) {
+      ColumnMetadata columnMetadata = segmentMetadata.getColumnMetadataFor(column);
+      if (columnMetadata != null && !columnMetadata.isSorted()) {
+        _jsonIndexColumns.add(columnMetadata);
+      }
+    }
+  }
+
+  public void createJsonIndices()
+      throws IOException {
+    for (ColumnMetadata columnMetadata : _jsonIndexColumns) {
+      createJSONIndexForColumn(columnMetadata);
+    }
+  }
+
+  private void createJSONIndexForColumn(ColumnMetadata columnMetadata)
+      throws IOException {
+    String column = columnMetadata.getColumnName();
+
+    File inProgress = new File(_indexDir, column + JSON_INDEX_FILE_EXTENSION + ".inprogress");
+    File jsonIndexFile = new File(_indexDir, column + JSON_INDEX_FILE_EXTENSION);
+
+    if (!inProgress.exists()) {
+      // Marker file does not exist, which means last run ended normally.
+
+      if (_segmentWriter.hasIndexFor(column, ColumnIndexType.JSON_INDEX)) {
+        // Skip creating json index if already exists.
+
+        LOGGER.info("Found json index for segment: {}, column: {}", _segmentName, column);
+        return;
+      }
+
+      // Create a marker file.
+      FileUtils.touch(inProgress);
+    } else {
+      // Marker file exists, which means last run gets interrupted.
+
+      // Remove json index if exists.
+      // For v1 and v2, it's the actual json index. For v3, it's the temporary json index.
+      FileUtils.deleteQuietly(jsonIndexFile);
+    }
+
+    // Create new json index for the column.
+    LOGGER.info("Creating new json index for segment: {}, column: {}", _segmentName, column);
+    if (columnMetadata.hasDictionary()) {
+      handleDictionaryBasedColumn(columnMetadata);
+    } else {
+      handleNonDictionaryBasedColumn(columnMetadata);
+    }
+
+    // For v3, write the generated json index file into the single file and remove it.
+    if (_segmentVersion == SegmentVersion.v3) {
+      LoaderUtils.writeIndexToV3Format(_segmentWriter, column, jsonIndexFile, ColumnIndexType.JSON_INDEX);
+    }
+
+    // Delete the marker file.
+    FileUtils.deleteQuietly(inProgress);
+
+    LOGGER.info("Created json index for segment: {}, column: {}", _segmentName, column);
+  }
+
+  private void handleDictionaryBasedColumn(ColumnMetadata columnMetadata)
+      throws IOException {
+    int numDocs = columnMetadata.getTotalDocs();
+    try (ForwardIndexReader forwardIndexReader = getForwardIndexReader(columnMetadata, _segmentWriter);
+        ForwardIndexReaderContext readerContext = forwardIndexReader.createContext();
+        Dictionary dictionary = getDictionaryReader(columnMetadata, _segmentWriter);
+        JSONIndexCreator jsonIndexCreator = new JSONIndexCreator(_indexDir, columnMetadata.getFieldSpec())) {
+      if (columnMetadata.isSingleValue()) {
+        switch (columnMetadata.getDataType()) {
+          case STRING:
+            for (int i = 0; i < numDocs; i++) {
+              int dictId = forwardIndexReader.getDictId(i, readerContext);
+              jsonIndexCreator.add(dictionary.getStringValue(dictId).getBytes("UTF-8"));
+            }
+            break;
+          case BYTES:
+            // Single-value column
+            for (int i = 0; i < numDocs; i++) {
+              int dictId = forwardIndexReader.getDictId(i, readerContext);
+              jsonIndexCreator.add(dictionary.getBytesValue(dictId));
+            }
+            break;
+          default:
+            throw new IllegalStateException("Unsupported data type: " + columnMetadata.getDataType());
+        }
+      } else {
+        // Multi-value column
+        throw new IllegalStateException("JSON Indexing is not supported on multi-valued columns ");
+      }
+      jsonIndexCreator.seal();
+    }
+  }
+
+  private void handleNonDictionaryBasedColumn(ColumnMetadata columnMetadata)
+      throws IOException {
+    FieldSpec.DataType dataType = columnMetadata.getDataType();
+    if (dataType != FieldSpec.DataType.BYTES || dataType != FieldSpec.DataType.STRING) {
+      throw new UnsupportedOperationException(
+          "JSON indexing is only supported for STRING/BYTES datatype but found: " + dataType);
+    }
+    int numDocs = columnMetadata.getTotalDocs();
+    try (ForwardIndexReader forwardIndexReader = getForwardIndexReader(columnMetadata, _segmentWriter);
+        ForwardIndexReaderContext readerContext = forwardIndexReader.createContext();
+        JSONIndexCreator jsonIndexCreator = new JSONIndexCreator(_indexDir, columnMetadata.getFieldSpec())) {
+      if (columnMetadata.isSingleValue()) {
+        // Single-value column.
+        switch (dataType) {
+          case STRING:
+          case BYTES:
+            for (int i = 0; i < numDocs; i++) {
+              jsonIndexCreator.add(forwardIndexReader.getBytes(i, readerContext));
+            }
+            break;
+          default:
+            throw new IllegalStateException("JSON Indexing Unsupported for data type: " + dataType);
+        }
+      } else {
+        // Multi-value column
+        switch (dataType) {
+          default:
+            throw new IllegalStateException("JSON Indexing is not supported on multi-valued columns ");
+        }
+      }
+      jsonIndexCreator.seal();
+    }
+  }
+
+  private ForwardIndexReader<?> getForwardIndexReader(ColumnMetadata columnMetadata,
+      SegmentDirectory.Writer segmentWriter)
+      throws IOException {
+    PinotDataBuffer buffer = segmentWriter.getIndexFor(columnMetadata.getColumnName(), ColumnIndexType.FORWARD_INDEX);
+    int numRows = columnMetadata.getTotalDocs();
+    int numBitsPerValue = columnMetadata.getBitsPerElement();
+    if (columnMetadata.isSingleValue()) {
+      return new FixedBitSVForwardIndexReader(buffer, numRows, numBitsPerValue);
+    } else {
+      return new FixedBitMVForwardIndexReader(buffer, numRows, columnMetadata.getTotalNumberOfEntries(),
+          numBitsPerValue);
+    }
+  }
+
+  private BaseImmutableDictionary getDictionaryReader(ColumnMetadata columnMetadata,
+      SegmentDirectory.Writer segmentWriter)
+      throws IOException {
+    PinotDataBuffer buffer = segmentWriter.getIndexFor(columnMetadata.getColumnName(), ColumnIndexType.DICTIONARY);
+    BaseImmutableDictionary dictionary = PhysicalColumnIndexContainer.loadDictionary(buffer, columnMetadata, false);
+    return dictionary;
+  }
+}
diff --git a/pinot-core/src/main/java/org/apache/pinot/core/segment/index/readers/JSONIndexReader.java b/pinot-core/src/main/java/org/apache/pinot/core/segment/index/readers/JSONIndexReader.java
new file mode 100644
index 0000000..37c0948
--- /dev/null
+++ b/pinot-core/src/main/java/org/apache/pinot/core/segment/index/readers/JSONIndexReader.java
@@ -0,0 +1,160 @@
+/**
+ * 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.pinot.core.segment.index.readers;
+
+import com.google.common.base.Preconditions;
+import java.io.Closeable;
+import java.io.IOException;
+import java.util.Arrays;
+import org.apache.calcite.sql.parser.SqlParseException;
+import org.apache.pinot.common.utils.StringUtil;
+import org.apache.pinot.core.operator.blocks.FilterBlock;
+import org.apache.pinot.core.operator.docidsets.BitmapDocIdSet;
+import org.apache.pinot.core.operator.filter.BitmapBasedFilterOperator;
+import org.apache.pinot.core.operator.filter.predicate.PredicateEvaluator;
+import org.apache.pinot.core.operator.filter.predicate.PredicateEvaluatorProvider;
+import org.apache.pinot.core.query.request.context.FilterContext;
+import org.apache.pinot.core.query.request.context.predicate.Predicate;
+import org.apache.pinot.core.query.request.context.utils.QueryContextConverterUtils;
+import org.apache.pinot.core.segment.memory.PinotDataBuffer;
+import org.apache.pinot.spi.data.FieldSpec;
+import org.apache.pinot.sql.parsers.CalciteSqlParser;
+import org.roaringbitmap.buffer.ImmutableRoaringBitmap;
+import org.roaringbitmap.buffer.MutableRoaringBitmap;
+
+
+public class JSONIndexReader implements Closeable {
+
+  private static int EXPECTED_VERSION = 1;
+  private static int DICT_HEADER_INDEX = 0;
+  private static int DICT_OFFSET_INDEX = 1;
+  private static int DICT_DATA_INDEX = 2;
+  private static int INV_OFFSET_INDEX = 3;
+  private static int INV_DATA_INDEX = 4;
+  private static int FLATTENED_2_ROOT_INDEX = 5;
+
+  private final BitmapInvertedIndexReader invertedIndexReader;
+  private final StringDictionary dictionary;
+  private final long cardinality;
+  private final long numFlattenedDocs;
+  private final PinotDataBuffer flattened2RootDocIdBuffer;
+
+  public JSONIndexReader(PinotDataBuffer pinotDataBuffer) {
+
+    int version = pinotDataBuffer.getInt(0);
+    int maxKeyLength = pinotDataBuffer.getInt(1 * Integer.BYTES);
+
+    Preconditions.checkState(version == EXPECTED_VERSION, String
+        .format("Index version:{} is not supported by this reader. expected version:{}", version, EXPECTED_VERSION));
+
+    // dictionaryHeaderFile, dictionaryOffsetFile, dictionaryFile, invIndexOffsetFile, invIndexFile, FlattenedDocId2DocIdMappingFile
+    int numBuffers = 6;
+    long bufferStartOffsets[] = new long[numBuffers];
+    long bufferSizeArray[] = new long[numBuffers];
+    for (int i = 0; i < numBuffers; i++) {
+      bufferStartOffsets[i] = pinotDataBuffer.getLong(2 * Integer.BYTES + 2 * i * Long.BYTES);
+      bufferSizeArray[i] = pinotDataBuffer.getLong(2 * Integer.BYTES + 2 * i * Long.BYTES + Long.BYTES);
+    }
+    cardinality = bufferSizeArray[DICT_OFFSET_INDEX] / Integer.BYTES - 1;
+
+    long dictionaryStartOffset = bufferStartOffsets[DICT_HEADER_INDEX];
+    long dictionarySize =
+        bufferSizeArray[DICT_HEADER_INDEX] + bufferSizeArray[DICT_OFFSET_INDEX] + bufferSizeArray[DICT_DATA_INDEX];
+
+    //TODO: REMOVE DEBUG START
+    byte[] dictHeaderBytes = new byte[(int) bufferSizeArray[DICT_HEADER_INDEX]];
+    pinotDataBuffer.copyTo(bufferStartOffsets[DICT_HEADER_INDEX], dictHeaderBytes);
+    System.out.println("Arrays.toString(dictHeaderBytes) = " + Arrays.toString(dictHeaderBytes));
+    //TODO: REMOVE DEBUG  END
+
+    PinotDataBuffer dictionaryBuffer =
+        pinotDataBuffer.view(dictionaryStartOffset, dictionaryStartOffset + dictionarySize);
+    dictionary = new StringDictionary(dictionaryBuffer, (int) cardinality, maxKeyLength, Byte.valueOf("0"));
+
+    long invIndexStartOffset = bufferStartOffsets[INV_OFFSET_INDEX];
+    long invIndexSize = bufferSizeArray[INV_OFFSET_INDEX] + bufferSizeArray[INV_DATA_INDEX];
+
+    PinotDataBuffer invIndexBuffer = pinotDataBuffer.view(invIndexStartOffset, invIndexStartOffset + invIndexSize);
+    invertedIndexReader = new BitmapInvertedIndexReader(invIndexBuffer, (int) cardinality);
+
+    //TODO: REMOVE DEBUG START
+    for (int dictId = 0; dictId < dictionary.length(); dictId++) {
+      System.out.println("Key = " + new String(dictionary.getBytes(dictId)));
+      System.out.println("Posting List = " + invertedIndexReader.getDocIds(dictId));
+    }
+    //TODO: REMOVE DEBUG  END
+
+    long flattened2RootDocIdStartOffset = bufferStartOffsets[FLATTENED_2_ROOT_INDEX];
+    long flattened2RootDocIdBufferSize = bufferSizeArray[FLATTENED_2_ROOT_INDEX];
+    numFlattenedDocs = bufferSizeArray[FLATTENED_2_ROOT_INDEX] / Integer.BYTES;
+    flattened2RootDocIdBuffer = pinotDataBuffer.view(flattened2RootDocIdStartOffset, flattened2RootDocIdStartOffset + flattened2RootDocIdBufferSize);
+    //TODO: REMOVE DEBUG START
+    for (int i = 0; i < numFlattenedDocs; i++) {
+      System.out.println("flattenedDocId: " + i + " rootDodId:" + flattened2RootDocIdBuffer.getInt(i * Integer.BYTES));
+    }
+    //TODO: REMOVE DEBUG  END
+  }
+
+  /**
+   * Returns the matching document ids for the given search query.
+   */
+  public MutableRoaringBitmap getMatchingDocIds(Predicate predicate) {
+
+    PredicateEvaluator predicateEvaluator =
+        PredicateEvaluatorProvider.getPredicateEvaluator(predicate, dictionary, FieldSpec.DataType.BYTES);
+    boolean exclusive = predicateEvaluator.isExclusive();
+    int[] dictIds = exclusive ? predicateEvaluator.getNonMatchingDictIds() : predicateEvaluator.getMatchingDictIds();
+    int numDictIds = dictIds.length;
+
+    if (numDictIds == 1) {
+      ImmutableRoaringBitmap docIds = (ImmutableRoaringBitmap) invertedIndexReader.getDocIds(dictIds[0]);
+      if (exclusive) {
+        if (docIds instanceof MutableRoaringBitmap) {
+          MutableRoaringBitmap mutableRoaringBitmap = (MutableRoaringBitmap) docIds;
+          mutableRoaringBitmap.flip(0L, numFlattenedDocs);
+          return mutableRoaringBitmap;
+        } else {
+          return ImmutableRoaringBitmap.flip(docIds, 0L, numFlattenedDocs);
+        }
+      } else {
+        return docIds.toMutableRoaringBitmap();
+      }
+    } else {
+      ImmutableRoaringBitmap[] bitmaps = new ImmutableRoaringBitmap[numDictIds];
+      for (int i = 0; i < numDictIds; i++) {
+        bitmaps[i] = (ImmutableRoaringBitmap) invertedIndexReader.getDocIds(dictIds[i]);
+      }
+      MutableRoaringBitmap docIds = ImmutableRoaringBitmap.or(bitmaps);
+      if (exclusive) {
+        docIds.flip(0L, numFlattenedDocs);
+      }
+      return docIds;
+    }
+  }
+
+  @Override
+  public void close()
+      throws IOException {
+
+  }
+
+  public int getRootDocId(int flattenedDocId) {
+    return flattened2RootDocIdBuffer.getInt(flattenedDocId * Integer.BYTES);
+  }
+}
diff --git a/pinot-core/src/main/java/org/apache/pinot/core/segment/store/ColumnIndexType.java b/pinot-core/src/main/java/org/apache/pinot/core/segment/store/ColumnIndexType.java
index dcd21df..f9063b8 100644
--- a/pinot-core/src/main/java/org/apache/pinot/core/segment/store/ColumnIndexType.java
+++ b/pinot-core/src/main/java/org/apache/pinot/core/segment/store/ColumnIndexType.java
@@ -25,7 +25,8 @@ public enum ColumnIndexType {
   BLOOM_FILTER("bloom_filter"),
   NULLVALUE_VECTOR("nullvalue_vector"),
   TEXT_INDEX("text_index"),
-  RANGE_INDEX("range_index");
+  RANGE_INDEX("range_index"),
+  JSON_INDEX("json_index");
 
   private final String indexName;
 
diff --git a/pinot-core/src/main/java/org/apache/pinot/core/segment/store/FilePerIndexDirectory.java b/pinot-core/src/main/java/org/apache/pinot/core/segment/store/FilePerIndexDirectory.java
index 51dd2fb..4ffc133 100644
--- a/pinot-core/src/main/java/org/apache/pinot/core/segment/store/FilePerIndexDirectory.java
+++ b/pinot-core/src/main/java/org/apache/pinot/core/segment/store/FilePerIndexDirectory.java
@@ -26,6 +26,7 @@ import java.nio.ByteOrder;
 import java.util.HashMap;
 import java.util.Map;
 import org.apache.pinot.common.segment.ReadMode;
+import org.apache.pinot.core.segment.creator.impl.V1Constants;
 import org.apache.pinot.core.segment.creator.impl.text.LuceneTextIndexCreator;
 import org.apache.pinot.core.segment.index.metadata.SegmentMetadataImpl;
 import org.apache.pinot.core.segment.memory.PinotDataBuffer;
@@ -135,6 +136,10 @@ class FilePerIndexDirectory extends ColumnIndexDirectory {
       case TEXT_INDEX:
         filename = column + LuceneTextIndexCreator.LUCENE_TEXT_INDEX_FILE_EXTENSION;
         break;
+      case JSON_INDEX:
+        filename = column + V1Constants.Indexes.JSON_INDEX_FILE_EXTENSION;
+        break;
+
       default:
         throw new UnsupportedOperationException("Unknown index type: " + indexType.toString());
     }
diff --git a/pinot-core/src/main/java/org/apache/pinot/core/segment/virtualcolumn/VirtualColumnIndexContainer.java b/pinot-core/src/main/java/org/apache/pinot/core/segment/virtualcolumn/VirtualColumnIndexContainer.java
index dc67771..712de29 100644
--- a/pinot-core/src/main/java/org/apache/pinot/core/segment/virtualcolumn/VirtualColumnIndexContainer.java
+++ b/pinot-core/src/main/java/org/apache/pinot/core/segment/virtualcolumn/VirtualColumnIndexContainer.java
@@ -24,6 +24,7 @@ import org.apache.pinot.core.segment.index.readers.BloomFilterReader;
 import org.apache.pinot.core.segment.index.readers.Dictionary;
 import org.apache.pinot.core.segment.index.readers.ForwardIndexReader;
 import org.apache.pinot.core.segment.index.readers.InvertedIndexReader;
+import org.apache.pinot.core.segment.index.readers.JSONIndexReader;
 import org.apache.pinot.core.segment.index.readers.NullValueVectorReaderImpl;
 import org.apache.pinot.core.segment.index.readers.TextIndexReader;
 
@@ -79,6 +80,11 @@ public class VirtualColumnIndexContainer implements ColumnIndexContainer {
   }
 
   @Override
+  public JSONIndexReader getJSONIndex() {
+    return null;
+  }
+
+  @Override
   public void close()
       throws IOException {
     _forwardIndex.close();
diff --git a/pinot-core/src/main/java/org/apache/pinot/core/startree/v2/store/StarTreeDataSource.java b/pinot-core/src/main/java/org/apache/pinot/core/startree/v2/store/StarTreeDataSource.java
index c24fb04..868cb47 100644
--- a/pinot-core/src/main/java/org/apache/pinot/core/startree/v2/store/StarTreeDataSource.java
+++ b/pinot-core/src/main/java/org/apache/pinot/core/startree/v2/store/StarTreeDataSource.java
@@ -32,7 +32,8 @@ public class StarTreeDataSource extends BaseDataSource {
 
   public StarTreeDataSource(FieldSpec fieldSpec, int numDocs, ForwardIndexReader<?> forwardIndex,
       @Nullable Dictionary dictionary) {
-    super(new StarTreeDataSourceMetadata(fieldSpec, numDocs), forwardIndex, dictionary, null, null, null, null, null);
+    super(new StarTreeDataSourceMetadata(fieldSpec, numDocs), forwardIndex, dictionary, null, null, null, null, null,
+        null);
   }
 
   private static final class StarTreeDataSourceMetadata implements DataSourceMetadata {
diff --git a/pinot-spi/src/main/java/org/apache/pinot/spi/config/table/IndexingConfig.java b/pinot-spi/src/main/java/org/apache/pinot/spi/config/table/IndexingConfig.java
index 3dd137b..7965654 100644
--- a/pinot-spi/src/main/java/org/apache/pinot/spi/config/table/IndexingConfig.java
+++ b/pinot-spi/src/main/java/org/apache/pinot/spi/config/table/IndexingConfig.java
@@ -27,6 +27,7 @@ import org.apache.pinot.spi.config.BaseJsonConfig;
 public class IndexingConfig extends BaseJsonConfig {
   private List<String> _invertedIndexColumns;
   private List<String> _rangeIndexColumns;
+  private List<String> _jsonIndexColumns;
   private boolean _autoGeneratedInvertedIndex;
   private boolean _createInvertedIndexDuringSegmentGeneration;
   private List<String> _sortedColumn;
@@ -71,6 +72,14 @@ public class IndexingConfig extends BaseJsonConfig {
     _rangeIndexColumns = rangeIndexColumns;
   }
 
+  public List<String> getJsonIndexColumns() {
+    return _jsonIndexColumns;
+  }
+
+  public void setJsonIndexColumns(List<String> jsonIndexColumns) {
+    _jsonIndexColumns = jsonIndexColumns;
+  }
+
   public boolean isAutoGeneratedInvertedIndex() {
     return _autoGeneratedInvertedIndex;
   }
diff --git a/pinot-spi/src/main/java/org/apache/pinot/spi/data/FieldSpec.java b/pinot-spi/src/main/java/org/apache/pinot/spi/data/FieldSpec.java
index b04ecb7..c9c245b 100644
--- a/pinot-spi/src/main/java/org/apache/pinot/spi/data/FieldSpec.java
+++ b/pinot-spi/src/main/java/org/apache/pinot/spi/data/FieldSpec.java
@@ -337,7 +337,7 @@ public abstract class FieldSpec implements Comparable<FieldSpec> {
   public enum DataType {
     // LIST is for complex lists which is different from multi-value column of primitives
     // STRUCT, MAP and LIST are composable to form a COMPLEX field
-    INT, LONG, FLOAT, DOUBLE, BOOLEAN/* Stored as STRING */, STRING, BYTES, STRUCT, MAP, LIST;
+    INT, LONG, FLOAT, DOUBLE, BOOLEAN/* Stored as STRING */, STRING, BYTES, STRUCT, MAP, LIST, JSON;
 
     /**
      * Returns the data type stored in Pinot.
diff --git a/pinot-tools/src/main/java/org/apache/pinot/tools/admin/command/JSONQuickstart.java b/pinot-tools/src/main/java/org/apache/pinot/tools/admin/command/JSONQuickstart.java
new file mode 100644
index 0000000..3a5246d
--- /dev/null
+++ b/pinot-tools/src/main/java/org/apache/pinot/tools/admin/command/JSONQuickstart.java
@@ -0,0 +1,224 @@
+package org.apache.pinot.tools.admin.command;
+
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.node.ArrayNode;
+import com.fasterxml.jackson.databind.node.ObjectNode;
+import com.google.common.base.Preconditions;
+import com.google.common.collect.Lists;
+import java.io.BufferedWriter;
+import java.io.File;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.net.URL;
+import java.util.Random;
+import org.apache.commons.io.FileUtils;
+import org.apache.pinot.spi.data.readers.FileFormat;
+import org.apache.pinot.spi.plugin.PluginManager;
+import org.apache.pinot.tools.QuickstartTableRequest;
+
+
+public class JSONQuickstart {
+  private static final String TAB = "\t\t";
+  private static final String NEW_LINE = "\n";
+
+  public enum Color {
+    RESET("\u001B[0m"), GREEN("\u001B[32m"), YELLOW("\u001B[33m"), CYAN("\u001B[36m");
+
+    public String _code;
+
+    Color(String code) {
+      _code = code;
+    }
+  }
+
+  public static void printStatus(JSONQuickstart.Color color, String message) {
+    System.out.println(color._code + message + JSONQuickstart.Color.RESET._code);
+  }
+
+  public static String prettyPrintResponse(JsonNode response) {
+    StringBuilder responseBuilder = new StringBuilder();
+
+    // Sql Results
+    if (response.has("resultTable")) {
+      JsonNode columns = response.get("resultTable").get("dataSchema").get("columnNames");
+      int numColumns = columns.size();
+      for (int i = 0; i < numColumns; i++) {
+        responseBuilder.append(columns.get(i).asText()).append(TAB);
+      }
+      responseBuilder.append(NEW_LINE);
+      JsonNode rows = response.get("resultTable").get("rows");
+      for (int i = 0; i < rows.size(); i++) {
+        JsonNode row = rows.get(i);
+        for (int j = 0; j < numColumns; j++) {
+          responseBuilder.append(row.get(j).asText()).append(TAB);
+        }
+        responseBuilder.append(NEW_LINE);
+      }
+      return responseBuilder.toString();
+    }
+
+    // Selection query
+    if (response.has("selectionResults")) {
+      JsonNode columns = response.get("selectionResults").get("columns");
+      int numColumns = columns.size();
+      for (int i = 0; i < numColumns; i++) {
+        responseBuilder.append(columns.get(i).asText()).append(TAB);
+      }
+      responseBuilder.append(NEW_LINE);
+      JsonNode rows = response.get("selectionResults").get("results");
+      int numRows = rows.size();
+      for (int i = 0; i < numRows; i++) {
+        JsonNode row = rows.get(i);
+        for (int j = 0; j < numColumns; j++) {
+          responseBuilder.append(row.get(j).asText()).append(TAB);
+        }
+        responseBuilder.append(NEW_LINE);
+      }
+      return responseBuilder.toString();
+    }
+
+    // Aggregation only query
+    if (!response.get("aggregationResults").get(0).has("groupByResult")) {
+      JsonNode aggregationResults = response.get("aggregationResults");
+      int numAggregations = aggregationResults.size();
+      for (int i = 0; i < numAggregations; i++) {
+        responseBuilder.append(aggregationResults.get(i).get("function").asText()).append(TAB);
+      }
+      responseBuilder.append(NEW_LINE);
+      for (int i = 0; i < numAggregations; i++) {
+        responseBuilder.append(aggregationResults.get(i).get("value").asText()).append(TAB);
+      }
+      responseBuilder.append(NEW_LINE);
+      return responseBuilder.toString();
+    }
+
+    // Aggregation group-by query
+    JsonNode groupByResults = response.get("aggregationResults");
+    int numGroupBys = groupByResults.size();
+    for (int i = 0; i < numGroupBys; i++) {
+      JsonNode groupByResult = groupByResults.get(i);
+      responseBuilder.append(groupByResult.get("function").asText()).append(TAB);
+      JsonNode columns = groupByResult.get("groupByColumns");
+      int numColumns = columns.size();
+      for (int j = 0; j < numColumns; j++) {
+        responseBuilder.append(columns.get(j).asText()).append(TAB);
+      }
+      responseBuilder.append(NEW_LINE);
+      JsonNode rows = groupByResult.get("groupByResult");
+      int numRows = rows.size();
+      for (int j = 0; j < numRows; j++) {
+        JsonNode row = rows.get(j);
+        responseBuilder.append(row.get("value").asText()).append(TAB);
+        JsonNode columnValues = row.get("group");
+        for (int k = 0; k < numColumns; k++) {
+          responseBuilder.append(columnValues.get(k).asText()).append(TAB);
+        }
+        responseBuilder.append(NEW_LINE);
+      }
+    }
+    return responseBuilder.toString();
+  }
+
+  public void execute()
+      throws Exception {
+    File quickstartTmpDir = new File(FileUtils.getTempDirectory(), String.valueOf(System.currentTimeMillis()));
+    File configDir = new File(quickstartTmpDir, "configs");
+    File dataDir = new File(quickstartTmpDir, "data");
+    Preconditions.checkState(configDir.mkdirs());
+    Preconditions.checkState(dataDir.mkdirs());
+
+    File schemaFile = new File(configDir, "super_schema.json");
+    File dataFile = new File(configDir, "super_data.csv");
+    File tableConfigFile = new File(configDir, "super_offline_table_config.json");
+    File ingestionJobSpecFile = new File(configDir, "ingestionJobSpec.yaml");
+
+    ClassLoader classLoader = JSONQuickstart.class.getClassLoader();
+    URL resource = classLoader.getResource("examples/batch/super/super_schema.json");
+    com.google.common.base.Preconditions.checkNotNull(resource);
+    FileUtils.copyURLToFile(resource, schemaFile);
+    resource = classLoader.getResource("examples/batch/super/rawdata/super_data.csv");
+    com.google.common.base.Preconditions.checkNotNull(resource);
+    FileUtils.copyURLToFile(resource, dataFile);
+    resource = classLoader.getResource("examples/batch/super/ingestionJobSpec.yaml");
+    com.google.common.base.Preconditions.checkNotNull(resource);
+    FileUtils.copyURLToFile(resource, ingestionJobSpecFile);
+    resource = classLoader.getResource("examples/batch/super/super_offline_table_config.json");
+    com.google.common.base.Preconditions.checkNotNull(resource);
+    FileUtils.copyURLToFile(resource, tableConfigFile);
+
+    QuickstartTableRequest request =
+        new QuickstartTableRequest("super", schemaFile, tableConfigFile, ingestionJobSpecFile, FileFormat.CSV);
+    final QuickstartRunner runner = new QuickstartRunner(Lists.newArrayList(request), 1, 1, 1, dataDir);
+
+    printStatus(JSONQuickstart.Color.CYAN, "***** Starting Zookeeper, controller, broker and server *****");
+    runner.startAll();
+    Runtime.getRuntime().addShutdownHook(new Thread(() -> {
+      try {
+        printStatus(JSONQuickstart.Color.GREEN, "***** Shutting down offline quick start *****");
+        runner.stop();
+        FileUtils.deleteDirectory(quickstartTmpDir);
+      } catch (Exception e) {
+        e.printStackTrace();
+      }
+    }));
+    printStatus(JSONQuickstart.Color.CYAN, "***** Adding super table *****");
+    runner.addTable();
+    printStatus(JSONQuickstart.Color.CYAN,
+        "***** Launch data ingestion job to build index segment for super and push to controller *****");
+    runner.launchDataIngestionJob();
+    printStatus(JSONQuickstart.Color.CYAN,
+        "***** Waiting for 5 seconds for the server to fetch the assigned segment *****");
+    Thread.sleep(5000);
+
+    printStatus(JSONQuickstart.Color.YELLOW, "***** Offline quickstart setup complete *****");
+
+  }
+
+  public static void main(String[] args)
+      throws Exception {
+    PluginManager.get().init();
+//    generateFile(new File(
+//        "pinot-tools/src/main/resources/examples/batch/super/rawdata/super_data.csv"));
+
+    new JSONQuickstart().execute();
+  }
+
+  static void generateFile(File file)
+      throws IOException {
+    if(false) {
+      return;
+    }
+    ObjectMapper mapper = new ObjectMapper();
+    Random random = new Random();
+    file.delete();
+    BufferedWriter bw = new BufferedWriter(new FileWriter(file, false));
+//    CSVPrinter csvPrinter = new CSVPrinter(bw, CSVFormat.newFormat(',').withRecordSeparator('\n'));
+//    csvPrinter.printRecord("person");
+    bw.write("person");
+    bw.newLine();
+    for (int i = 0; i < 100; i++) {
+      ObjectNode person = mapper.createObjectNode();
+      person.put("name", "adam-" + i);
+      person.put("age", random.nextInt(100));
+      ArrayNode arrayNode = mapper.createArrayNode();
+      for (int j = 0; j < 3; j++) {
+        ObjectNode address = mapper.createObjectNode();
+        address.put("street", "street-" + i);
+        address.put("country", "us");
+        arrayNode.add(address);
+      }
+      person.set("addresses", arrayNode);
+      String personJSON = mapper.writer().writeValueAsString(person);
+//      csvPrinter.printRecord(personJSON.replaceAll("\"", "\"\""));
+      bw.write("\"");
+      bw.write(personJSON.replaceAll("\"", "\"\""));
+      bw.write("\"");
+      bw.newLine();
+
+    }
+//    csvPrinter.close();
+//    System.out.println("csvPrinter = " + csvPrinter);
+    bw.close();
+  }
+}


---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@pinot.apache.org
For additional commands, e-mail: commits-help@pinot.apache.org