Repository: alibaba/GraphScope (language: python)

Issue:
feat (interactive): Migrating Gremlin compilation into the `Calsite`-based IR layer
The GIE IR layer is re-factored based on Calsite, which has now been used to compile the Cypher language into multiple runtime. However, the compilation of Gremlin is still in the pre-IR route, making the dual-language support of GIE in an inconsistent state, and the Gremlin path can not benefit from the on-going developing features of IR, including new optimization rules. 

It's now ready to initiate the migration.  


Discussion / hints:

Fix patch:
diff --git a/charts/gie-standalone/templates/frontend/statefulset.yaml b/charts/gie-standalone/templates/frontend/statefulset.yaml
index 6830216eb8e3..889172c334ac 100644
--- a/charts/gie-standalone/templates/frontend/statefulset.yaml
+++ b/charts/gie-standalone/templates/frontend/statefulset.yaml
@@ -125,6 +125,8 @@ spec:
               value: {{ .Values.pegasusOutputCapacity | quote }}
             - name: FRONTEND_QUERY_PER_SECOND_LIMIT
               value: {{ .Values.frontendQueryPerSecondLimit | quote }}
+            - name: GREMLIN_SCRIPT_LANGUAGE_NAME
+              value: {{ .Values.gremlinScriptLanguageName }}
           ports:
             - name: gremlin
               containerPort: {{ .Values.frontend.service.gremlinPort }}
diff --git a/charts/gie-standalone/values.yaml b/charts/gie-standalone/values.yaml
index 45ada8a5a6db..32e503290708 100644
--- a/charts/gie-standalone/values.yaml
+++ b/charts/gie-standalone/values.yaml
@@ -44,6 +44,8 @@ pegasusOutputCapacity: 16
 
 frontendQueryPerSecondLimit: 2147483647
 
+gremlinScriptLanguageName: "antlr_gremlin_traversal"
+
 ## need by vineyard in distributed env
 etcdEndpoint: "etcd-for-vineyard.default.svc.cluster.local:2379"
 
diff --git a/docs/interactive_engine/deployment.md b/docs/interactive_engine/deployment.md
index 34ff41c7c457..e3ce6f9ce9f6 100644
--- a/docs/interactive_engine/deployment.md
+++ b/docs/interactive_engine/deployment.md
@@ -194,3 +194,4 @@ We've listed useful configuration keys in the following:
 | pegasusBatchSize            | the maximum size of streaming records can be output for an operator   |              1024               |
 | pegasusOutputCapacity       | the maximum number of streaming records can be output for an operator |               16                |
 | frontendQueryPerSecondLimit | the maximum qps can be handled by frontend service                    | 2147483647 (without limitation) |
+| gremlinScriptLanguageName | the option allows you to choose different Gremlin compilations based on different IR layer, either Traversal-based ('antlr_gremlin_traversal') or Calcite-based ('antlr_gremlin_calcite') | antlr_gremlin_traversal |
diff --git a/interactive_engine/compiler/Makefile b/interactive_engine/compiler/Makefile
index 48be24b4bf8d..04f0970c2390 100644
--- a/interactive_engine/compiler/Makefile
+++ b/interactive_engine/compiler/Makefile
@@ -47,6 +47,9 @@ test:
 gremlin_test:
 	mvn test -Dtest=com.alibaba.graphscope.gremlin.integration.standard.IrGremlinTest
 
+gremlin_calcite_test:
+	mvn test -Dtest=com.alibaba.graphscope.gremlin.integration.standard.calcite.IrGremlinTest
+
 run:
 	cd $(CUR_DIR) && $(java) \
 	  -cp ".:./target/libs/*:./target/compiler-0.0.1-SNAPSHOT.jar" \
diff --git a/interactive_engine/compiler/conf/ir.compiler.properties b/interactive_engine/compiler/conf/ir.compiler.properties
index a0e348ae0abd..851f6c0eaf17 100644
--- a/interactive_engine/compiler/conf/ir.compiler.properties
+++ b/interactive_engine/compiler/conf/ir.compiler.properties
@@ -49,3 +49,6 @@ calcite.default.charset: UTF-8
 # frontend.query.per.second.limit: 2147483647
 
 # graph.type.inference.enabled: true
+
+# antlr_gremlin_traversal(default) or antlr_gremlin_calcite
+# gremlin.script.language.name: antlr_gremlin_traversal
diff --git a/interactive_engine/compiler/ir_exprimental_ci.sh b/interactive_engine/compiler/ir_exprimental_ci.sh
index af2a14b47063..7b8a8938636e 100755
--- a/interactive_engine/compiler/ir_exprimental_ci.sh
+++ b/interactive_engine/compiler/ir_exprimental_ci.sh
@@ -9,15 +9,30 @@ sleep 5s
 # run gremlin standard tests
 cd ${base_dir} && make gremlin_test
 exit_code=$?
-# clean service
-ps -ef | grep "com.alibaba.graphscope.GraphServer" | grep -v grep | awk '{print $2}' | xargs kill -9 || true
-ps -ef | grep "start_rpc_server" | grep -v grep | awk '{print $2}' | xargs kill -9
 # report test result
 if [ $exit_code -ne 0 ]; then
     echo "ir gremlin integration test on experimental store fail"
     exit 1
 fi
 
+# restart compiler service
+ps -ef | grep "com.alibaba.graphscope.GraphServer" | grep -v grep | awk '{print $2}' | xargs kill -9 || true
+export gremlin.script.language.name=antlr_gremlin_calcite
+cd ${base_dir} && make run &
+sleep 5s
+# run gremlin standard tests to test calcite-based IR layer
+cd ${base_dir} && make gremlin_calcite_test
+exit_code=$?
+# report test result
+if [ $exit_code -ne 0 ]; then
+    echo "ir\(calcite-based\) gremlin integration test on experimental store fail"
+    exit 1
+fi
+
+# clean service
+ps -ef | grep "com.alibaba.graphscope.GraphServer" | grep -v grep | awk '{print $2}' | xargs kill -9 || true
+ps -ef | grep "start_rpc_server" | grep -v grep | awk '{print $2}' | xargs kill -9
+
 cd ${base_dir}/../executor/ir/target/release && DATA_PATH=/tmp/gstest/movie_graph_exp_bin RUST_LOG=info ./start_rpc_server --config ${base_dir}/../executor/ir/integrated/config &
 sleep 5s
 # start compiler service
diff --git a/interactive_engine/compiler/set_properties.sh b/interactive_engine/compiler/set_properties.sh
index 3f854c31ba4b..d3c0bf416e03 100755
--- a/interactive_engine/compiler/set_properties.sh
+++ b/interactive_engine/compiler/set_properties.sh
@@ -32,6 +32,8 @@ cypher_server_port="neo4j.bolt.server.port: $CYPHER_SERVER_PORT";
 
 frontend_query_per_second_limit="frontend.query.per.second.limit: $FRONTEND_QUERY_PER_SECOND_LIMIT"
 
+gremlin_script_language_name="gremlin.script.language.name: $GREMLIN_SCRIPT_LANGUAGE_NAME"
+
 count=1;
 while (($count<$SERVERSSIZE))
 do
@@ -43,6 +45,6 @@ done
 
 graph_schema="graph.schema: $GRAPH_SCHEMA"
 
-properties="$worker_num\n$timeout\n$batch_size\n$output_capacity\n$hosts\n$server_num\n$graph_schema\n$gremlin_server_port\n$cypher_server_port\n$frontend_query_per_second_limit"
+properties="$worker_num\n$timeout\n$batch_size\n$output_capacity\n$hosts\n$server_num\n$graph_schema\n$gremlin_server_port\n$cypher_server_port\n$frontend_query_per_second_limit\n$gremlin_script_language_name"
 
 echo -e $properties > ./conf/ir.compiler.properties
diff --git a/interactive_engine/compiler/src/main/java/com/alibaba/graphscope/GraphServer.java b/interactive_engine/compiler/src/main/java/com/alibaba/graphscope/GraphServer.java
index 54a339b88afc..b27cc62169fc 100644
--- a/interactive_engine/compiler/src/main/java/com/alibaba/graphscope/GraphServer.java
+++ b/interactive_engine/compiler/src/main/java/com/alibaba/graphscope/GraphServer.java
@@ -24,16 +24,15 @@
 import com.alibaba.graphscope.common.config.FrontendConfig;
 import com.alibaba.graphscope.common.config.GraphConfig;
 import com.alibaba.graphscope.common.ir.meta.reader.LocalMetaDataReader;
-import com.alibaba.graphscope.common.ir.tools.GraphBuilder;
-import com.alibaba.graphscope.common.ir.tools.GraphPlanner;
-import com.alibaba.graphscope.common.ir.tools.LogicalPlanFactory;
-import com.alibaba.graphscope.common.ir.tools.QueryCache;
+import com.alibaba.graphscope.common.ir.tools.*;
 import com.alibaba.graphscope.common.manager.IrMetaQueryCallback;
 import com.alibaba.graphscope.common.store.ExperimentalMetaFetcher;
 import com.alibaba.graphscope.common.store.IrMeta;
 import com.alibaba.graphscope.cypher.antlr4.parser.CypherAntlr4Parser;
 import com.alibaba.graphscope.cypher.antlr4.visitor.LogicalPlanVisitor;
 import com.alibaba.graphscope.cypher.service.CypherBootstrapper;
+import com.alibaba.graphscope.gremlin.antlr4x.parser.GremlinAntlr4Parser;
+import com.alibaba.graphscope.gremlin.antlr4x.visitor.GraphBuilderVisitor;
 import com.alibaba.graphscope.gremlin.integration.result.GraphProperties;
 import com.alibaba.graphscope.gremlin.integration.result.TestGraphFactory;
 import com.alibaba.graphscope.gremlin.service.IrGremlinServer;
@@ -75,22 +74,39 @@ public GraphServer(
 
     public void start() throws Exception {
         ExecutionClient executionClient = ExecutionClient.Factory.create(configs, channelFetcher);
-        LogicalPlanFactory planFactory =
-                (GraphBuilder builder, IrMeta irMeta, String query) ->
-                        new LogicalPlanVisitor(builder, irMeta)
-                                .visit(new CypherAntlr4Parser().parse(query));
-        GraphPlanner graphPlanner = new GraphPlanner(configs, planFactory);
-        QueryCache queryCache = new QueryCache(configs, graphPlanner);
+        QueryIdGenerator idGenerator = new QueryIdGenerator(configs);
         if (!FrontendConfig.GREMLIN_SERVER_DISABLED.get(configs)) {
+            GraphPlanner graphPlanner =
+                    new GraphPlanner(
+                            configs,
+                            (GraphBuilder builder, IrMeta irMeta, String query) ->
+                                    new LogicalPlan(
+                                            new GraphBuilderVisitor(builder)
+                                                    .visit(new GremlinAntlr4Parser().parse(query))
+                                                    .build()));
+            QueryCache queryCache = new QueryCache(configs, graphPlanner);
             this.gremlinServer =
                     new IrGremlinServer(
-                            configs, graphPlanner, channelFetcher, metaQueryCallback, testGraph);
+                            configs,
+                            idGenerator,
+                            queryCache,
+                            executionClient,
+                            channelFetcher,
+                            metaQueryCallback,
+                            testGraph);
             this.gremlinServer.start();
         }
         if (!FrontendConfig.NEO4J_BOLT_SERVER_DISABLED.get(configs)) {
+            GraphPlanner graphPlanner =
+                    new GraphPlanner(
+                            configs,
+                            (GraphBuilder builder, IrMeta irMeta, String query) ->
+                                    new LogicalPlanVisitor(builder, irMeta)
+                                            .visit(new CypherAntlr4Parser().parse(query)));
+            QueryCache queryCache = new QueryCache(configs, graphPlanner);
             this.cypherBootstrapper =
                     new CypherBootstrapper(
-                            configs, graphPlanner, metaQueryCallback, executionClient, queryCache);
+                            configs, idGenerator, metaQueryCallback, executionClient, queryCache);
             Path neo4jHomePath = getNeo4jHomePath();
             this.cypherBootstrapper.start(
                     neo4jHomePath,
diff --git a/interactive_engine/compiler/src/main/java/com/alibaba/graphscope/common/config/FrontendConfig.java b/interactive_engine/compiler/src/main/java/com/alibaba/graphscope/common/config/FrontendConfig.java
index 29af6ab35851..b5fea9963013 100644
--- a/interactive_engine/compiler/src/main/java/com/alibaba/graphscope/common/config/FrontendConfig.java
+++ b/interactive_engine/compiler/src/main/java/com/alibaba/graphscope/common/config/FrontendConfig.java
@@ -51,4 +51,7 @@ public class FrontendConfig {
 
     public static final Config<Boolean> GRAPH_TYPE_INFERENCE_ENABLED =
             Config.boolConfig("graph.type.inference.enabled", true);
+
+    public static final Config<String> GREMLIN_SCRIPT_LANGUAGE_NAME =
+            Config.stringConfig("gremlin.script.language.name", "antlr_gremlin_traversal");
 }
diff --git a/interactive_engine/compiler/src/main/java/com/alibaba/graphscope/common/ir/rel/GraphLogicalDedupBy.java b/interactive_engine/compiler/src/main/java/com/alibaba/graphscope/common/ir/rel/GraphLogicalDedupBy.java
new file mode 100644
index 000000000000..81f478582656
--- /dev/null
+++ b/interactive_engine/compiler/src/main/java/com/alibaba/graphscope/common/ir/rel/GraphLogicalDedupBy.java
@@ -0,0 +1,63 @@
+/*
+ * Copyright 2020 Alibaba Group Holding Limited.
+ *
+ * Licensed 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 com.alibaba.graphscope.common.ir.rel;
+
+import org.apache.calcite.plan.GraphOptCluster;
+import org.apache.calcite.plan.RelOptCluster;
+import org.apache.calcite.plan.RelTraitSet;
+import org.apache.calcite.rel.RelNode;
+import org.apache.calcite.rel.RelWriter;
+import org.apache.calcite.rel.SingleRel;
+import org.apache.calcite.rex.RexNode;
+import org.apache.commons.lang3.ObjectUtils;
+
+import java.util.Collections;
+import java.util.List;
+
+// this class is dedicated to supporting `dedup` operator in Gremlin, which is equivalent to the
+// combination of `group` and `project` in SQL
+public class GraphLogicalDedupBy extends SingleRel {
+    private final List<RexNode> dedupByKeys;
+
+    protected GraphLogicalDedupBy(
+            RelOptCluster cluster, RelTraitSet traits, RelNode input, List<RexNode> dedupByKeys) {
+        super(cluster, traits, input);
+        this.dedupByKeys =
+                ObjectUtils.requireNonEmpty(
+                        dedupByKeys, "there should be at least one key in dedup by");
+    }
+
+    public static GraphLogicalDedupBy create(
+            GraphOptCluster cluster, RelNode input, List<RexNode> dedupByKeys) {
+        return new GraphLogicalDedupBy(cluster, RelTraitSet.createEmpty(), input, dedupByKeys);
+    }
+
+    public List<RexNode> getDedupByKeys() {
+        return Collections.unmodifiableList(this.dedupByKeys);
+    }
+
+    @Override
+    public RelWriter explainTerms(RelWriter pw) {
+        return super.explainTerms(pw).item("dedupByKeys", dedupByKeys);
+    }
+
+    @Override
+    public RelNode copy(RelTraitSet traitSet, List<RelNode> inputs) {
+        return new GraphLogicalDedupBy(
+                this.getCluster(), traitSet, inputs.get(0), this.dedupByKeys);
+    }
+}
diff --git a/interactive_engine/compiler/src/main/java/com/alibaba/graphscope/common/ir/rel/GraphRelShuttle.java b/interactive_engine/compiler/src/main/java/com/alibaba/graphscope/common/ir/rel/GraphRelShuttle.java
index 0dd4fb382356..7b8203a26119 100644
--- a/interactive_engine/compiler/src/main/java/com/alibaba/graphscope/common/ir/rel/GraphRelShuttle.java
+++ b/interactive_engine/compiler/src/main/java/com/alibaba/graphscope/common/ir/rel/GraphRelShuttle.java
@@ -51,4 +51,6 @@ public interface GraphRelShuttle {
     RelNode visit(GraphLogicalMultiMatch match);
 
     RelNode visit(LogicalJoin join);
+
+    RelNode visit(GraphLogicalDedupBy dedupBy);
 }
diff --git a/interactive_engine/compiler/src/main/java/com/alibaba/graphscope/common/ir/rel/GraphRelShuttleWrapper.java b/interactive_engine/compiler/src/main/java/com/alibaba/graphscope/common/ir/rel/GraphRelShuttleWrapper.java
index 428550ccfebe..be11d98cc1d1 100644
--- a/interactive_engine/compiler/src/main/java/com/alibaba/graphscope/common/ir/rel/GraphRelShuttleWrapper.java
+++ b/interactive_engine/compiler/src/main/java/com/alibaba/graphscope/common/ir/rel/GraphRelShuttleWrapper.java
@@ -77,6 +77,8 @@ public RelNode visit(RelNode relNode) {
             return relShuttle.visit((GraphLogicalPathExpand) relNode);
         } else if (relNode instanceof GraphLogicalExpandDegree) {
             return relShuttle.visit((GraphLogicalExpandDegree) relNode);
+        } else if (relNode instanceof GraphLogicalDedupBy) {
+            return relShuttle.visit((GraphLogicalDedupBy) relNode);
         } else {
             throw new UnsupportedOperationException(
                     "relNode " + relNode.getClass() + " can not be visited in shuttle");
diff --git a/interactive_engine/compiler/src/main/java/com/alibaba/graphscope/common/ir/rel/graph/GraphLogicalExpand.java b/interactive_engine/compiler/src/main/java/com/alibaba/graphscope/common/ir/rel/graph/GraphLogicalExpand.java
index 798d8d28809d..d2c12d851dce 100644
--- a/interactive_engine/compiler/src/main/java/com/alibaba/graphscope/common/ir/rel/graph/GraphLogicalExpand.java
+++ b/interactive_engine/compiler/src/main/java/com/alibaba/graphscope/common/ir/rel/graph/GraphLogicalExpand.java
@@ -27,6 +27,7 @@
 import org.apache.calcite.rel.RelShuttle;
 import org.apache.calcite.rel.RelWriter;
 import org.apache.calcite.rel.hint.RelHint;
+import org.apache.commons.lang3.ObjectUtils;
 import org.checkerframework.checker.nullness.qual.Nullable;
 
 import java.util.List;
@@ -68,14 +69,19 @@ public RelWriter explainTerms(RelWriter pw) {
 
     @Override
     public GraphLogicalExpand copy(RelTraitSet traitSet, List<RelNode> inputs) {
-        return new GraphLogicalExpand(
-                (GraphOptCluster) getCluster(),
-                getHints(),
-                inputs.get(0),
-                this.getOpt(),
-                this.tableConfig,
-                this.getAliasName(),
-                this.getStartAlias());
+        GraphLogicalExpand copy =
+                new GraphLogicalExpand(
+                        (GraphOptCluster) getCluster(),
+                        getHints(),
+                        inputs.get(0),
+                        this.getOpt(),
+                        this.tableConfig,
+                        this.getAliasName(),
+                        this.getStartAlias());
+        if (ObjectUtils.isNotEmpty(this.getFilters())) {
+            copy.setFilters(this.getFilters());
+        }
+        return copy;
     }
 
     @Override
diff --git a/interactive_engine/compiler/src/main/java/com/alibaba/graphscope/common/ir/rel/graph/GraphLogicalGetV.java b/interactive_engine/compiler/src/main/java/com/alibaba/graphscope/common/ir/rel/graph/GraphLogicalGetV.java
index d4f896e6aec3..cfc94f954940 100644
--- a/interactive_engine/compiler/src/main/java/com/alibaba/graphscope/common/ir/rel/graph/GraphLogicalGetV.java
+++ b/interactive_engine/compiler/src/main/java/com/alibaba/graphscope/common/ir/rel/graph/GraphLogicalGetV.java
@@ -27,6 +27,7 @@
 import org.apache.calcite.rel.RelShuttle;
 import org.apache.calcite.rel.RelWriter;
 import org.apache.calcite.rel.hint.RelHint;
+import org.apache.commons.lang3.ObjectUtils;
 import org.checkerframework.checker.nullness.qual.Nullable;
 
 import java.util.List;
@@ -68,14 +69,19 @@ public RelWriter explainTerms(RelWriter pw) {
 
     @Override
     public GraphLogicalGetV copy(RelTraitSet traitSet, List<RelNode> inputs) {
-        return new GraphLogicalGetV(
-                (GraphOptCluster) getCluster(),
-                getHints(),
-                inputs.get(0),
-                this.getOpt(),
-                this.tableConfig,
-                this.getAliasName(),
-                this.getStartAlias());
+        GraphLogicalGetV copy =
+                new GraphLogicalGetV(
+                        (GraphOptCluster) getCluster(),
+                        getHints(),
+                        inputs.get(0),
+                        this.getOpt(),
+                        this.tableConfig,
+                        this.getAliasName(),
+                        this.getStartAlias());
+        if (ObjectUtils.isNotEmpty(this.getFilters())) {
+            copy.setFilters(this.getFilters());
+        }
+        return copy;
     }
 
     @Override
diff --git a/interactive_engine/compiler/src/main/java/com/alibaba/graphscope/common/ir/rel/type/AliasNameWithId.java b/interactive_engine/compiler/src/main/java/com/alibaba/graphscope/common/ir/rel/type/AliasNameWithId.java
index c45db4a48fe3..092b8a67ad08 100644
--- a/interactive_engine/compiler/src/main/java/com/alibaba/graphscope/common/ir/rel/type/AliasNameWithId.java
+++ b/interactive_engine/compiler/src/main/java/com/alibaba/graphscope/common/ir/rel/type/AliasNameWithId.java
@@ -18,6 +18,8 @@
 
 import com.alibaba.graphscope.common.ir.tools.AliasInference;
 
+import java.util.Objects;
+
 public class AliasNameWithId {
     public static final AliasNameWithId DEFAULT =
             new AliasNameWithId(AliasInference.DEFAULT_NAME, AliasInference.DEFAULT_ID);
@@ -37,4 +39,17 @@ public String getAliasName() {
     public int getAliasId() {
         return aliasId;
     }
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) return true;
+        if (o == null || getClass() != o.getClass()) return false;
+        AliasNameWithId that = (AliasNameWithId) o;
+        return aliasId == that.aliasId && Objects.equals(aliasName, that.aliasName);
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hash(aliasName, aliasId);
+    }
 }
diff --git a/interactive_engine/compiler/src/main/java/com/alibaba/graphscope/common/ir/runtime/ffi/FfiPhysicalBuilder.java b/interactive_engine/compiler/src/main/java/com/alibaba/graphscope/common/ir/runtime/ffi/FfiPhysicalBuilder.java
index 1f8123c34a27..2c875c275244 100644
--- a/interactive_engine/compiler/src/main/java/com/alibaba/graphscope/common/ir/runtime/ffi/FfiPhysicalBuilder.java
+++ b/interactive_engine/compiler/src/main/java/com/alibaba/graphscope/common/ir/runtime/ffi/FfiPhysicalBuilder.java
@@ -19,11 +19,16 @@
 import com.alibaba.graphscope.common.config.Configs;
 import com.alibaba.graphscope.common.config.FrontendConfig;
 import com.alibaba.graphscope.common.config.PegasusConfig;
+import com.alibaba.graphscope.common.ir.rel.*;
 import com.alibaba.graphscope.common.ir.rel.GraphLogicalAggregate;
 import com.alibaba.graphscope.common.ir.rel.GraphLogicalProject;
 import com.alibaba.graphscope.common.ir.rel.GraphLogicalSort;
 import com.alibaba.graphscope.common.ir.rel.GraphRelShuttleWrapper;
 import com.alibaba.graphscope.common.ir.rel.graph.*;
+import com.alibaba.graphscope.common.ir.rel.graph.GraphLogicalExpand;
+import com.alibaba.graphscope.common.ir.rel.graph.GraphLogicalGetV;
+import com.alibaba.graphscope.common.ir.rel.graph.GraphLogicalPathExpand;
+import com.alibaba.graphscope.common.ir.rel.graph.GraphLogicalSource;
 import com.alibaba.graphscope.common.ir.rel.graph.match.GraphLogicalMultiMatch;
 import com.alibaba.graphscope.common.ir.rel.graph.match.GraphLogicalSingleMatch;
 import com.alibaba.graphscope.common.ir.runtime.PhysicalPlan;
@@ -115,6 +120,9 @@ public void appendNode(PhysicalNode<Pointer> node) {
                         LIB.appendGroupbyOperator(
                                 ptrPlan, node.getNode(), oprIdx.getValue(), oprIdx));
             }
+        } else if (original instanceof GraphLogicalDedupBy) {
+            checkFfiResult(
+                    LIB.appendDedupOperator(ptrPlan, node.getNode(), oprIdx.getValue(), oprIdx));
         } else if (original instanceof GraphLogicalSort) {
             if (((GraphLogicalSort) original).getCollation().getFieldCollations().isEmpty()) {
                 checkFfiResult(
diff --git a/interactive_engine/compiler/src/main/java/com/alibaba/graphscope/common/ir/runtime/ffi/RelToFfiConverter.java b/interactive_engine/compiler/src/main/java/com/alibaba/graphscope/common/ir/runtime/ffi/RelToFfiConverter.java
index 54305f7a8a3c..d0b08d0677c9 100644
--- a/interactive_engine/compiler/src/main/java/com/alibaba/graphscope/common/ir/runtime/ffi/RelToFfiConverter.java
+++ b/interactive_engine/compiler/src/main/java/com/alibaba/graphscope/common/ir/runtime/ffi/RelToFfiConverter.java
@@ -18,10 +18,7 @@
 
 import com.alibaba.graphscope.common.config.Configs;
 import com.alibaba.graphscope.common.intermediate.ArgUtils;
-import com.alibaba.graphscope.common.ir.rel.GraphLogicalAggregate;
-import com.alibaba.graphscope.common.ir.rel.GraphLogicalProject;
-import com.alibaba.graphscope.common.ir.rel.GraphLogicalSort;
-import com.alibaba.graphscope.common.ir.rel.GraphRelShuttle;
+import com.alibaba.graphscope.common.ir.rel.*;
 import com.alibaba.graphscope.common.ir.rel.graph.*;
 import com.alibaba.graphscope.common.ir.rel.graph.match.GraphLogicalMultiMatch;
 import com.alibaba.graphscope.common.ir.rel.graph.match.GraphLogicalSingleMatch;
@@ -413,6 +410,27 @@ public PhysicalNode visit(GraphLogicalAggregate aggregate) {
         return new PhysicalNode(aggregate, ptrGroup);
     }
 
+    @Override
+    public PhysicalNode visit(GraphLogicalDedupBy dedupBy) {
+        Preconditions.checkArgument(
+                !dedupBy.getDedupByKeys().isEmpty(), "dedup by keys should not be empty");
+        Pointer ptrDedup = LIB.initDedupOperator();
+        for (RexNode key : dedupBy.getDedupByKeys()) {
+            Preconditions.checkArgument(
+                    key instanceof RexGraphVariable,
+                    "each dedup by key should be type %s, but is %s",
+                    RexGraphVariable.class,
+                    key.getClass());
+            OuterExpression.Variable var =
+                    key.accept(new RexToProtoConverter(true, isColumnId, this.rexBuilder))
+                            .getOperators(0)
+                            .getVar();
+            checkFfiResult(
+                    LIB.addDedupKeyPb(ptrDedup, new FfiPbPointer.ByValue(var.toByteArray())));
+        }
+        return new PhysicalNode(dedupBy, ptrDedup);
+    }
+
     @Override
     public PhysicalNode visit(GraphLogicalSort sort) {
         List<RelFieldCollation> collations = sort.getCollation().getFieldCollations();
diff --git a/interactive_engine/compiler/src/main/java/com/alibaba/graphscope/common/ir/tools/GraphBuilder.java b/interactive_engine/compiler/src/main/java/com/alibaba/graphscope/common/ir/tools/GraphBuilder.java
index 975af3eb75c8..1b1aeae98f2f 100644
--- a/interactive_engine/compiler/src/main/java/com/alibaba/graphscope/common/ir/tools/GraphBuilder.java
+++ b/interactive_engine/compiler/src/main/java/com/alibaba/graphscope/common/ir/tools/GraphBuilder.java
@@ -22,10 +22,7 @@
 import com.alibaba.graphscope.common.config.FrontendConfig;
 import com.alibaba.graphscope.common.ir.meta.schema.GraphOptSchema;
 import com.alibaba.graphscope.common.ir.meta.schema.IrGraphSchema;
-import com.alibaba.graphscope.common.ir.rel.GraphLogicalAggregate;
-import com.alibaba.graphscope.common.ir.rel.GraphLogicalProject;
-import com.alibaba.graphscope.common.ir.rel.GraphLogicalSort;
-import com.alibaba.graphscope.common.ir.rel.PushFilterVisitor;
+import com.alibaba.graphscope.common.ir.rel.*;
 import com.alibaba.graphscope.common.ir.rel.graph.*;
 import com.alibaba.graphscope.common.ir.rel.graph.match.AbstractLogicalMatch;
 import com.alibaba.graphscope.common.ir.rel.graph.match.GraphLogicalMultiMatch;
@@ -71,6 +68,7 @@
 import java.math.BigDecimal;
 import java.util.*;
 import java.util.function.Predicate;
+import java.util.regex.Pattern;
 import java.util.stream.Collectors;
 
 /**
@@ -736,7 +734,8 @@ private boolean isCurrentSupported(SqlOperator operator) {
                 || sqlKind == SqlKind.IS_NOT_NULL
                 || sqlKind == SqlKind.EXTRACT
                 || sqlKind == SqlKind.SEARCH
-                || sqlKind == SqlKind.POSIX_REGEX_CASE_SENSITIVE;
+                || sqlKind == SqlKind.POSIX_REGEX_CASE_SENSITIVE
+                || sqlKind == SqlKind.AS;
     }
 
     @Override
@@ -1102,11 +1101,55 @@ public GraphBuilder project(
                 nodeList.set(i, simplifier.simplifyPreservingType(nodeList.get(i)));
             }
         }
-        fieldNameList =
-                AliasInference.inferProject(
-                        nodeList,
-                        fieldNameList,
-                        AliasInference.getUniqueAliasList(input, isAppend));
+
+        PREPARE_PROJECT_ARGS:
+        {
+            // if project denotes the `select('a')` in gremlin, give a default alias to skip the
+            // real projection
+            if (projectOneTag(nodeList, fieldNameList, isAppend) != null) {
+                fieldNameList = ImmutableList.of(AliasInference.DEFAULT_NAME);
+                break PREPARE_PROJECT_ARGS;
+            } else if (input instanceof Project) {
+                // fuse the project with the previous node if meets the following requirements :
+                // 1. the input is project
+                // 2. the expressions in the current project all start from the tags in the input
+                // 3. the input denotes the `select('a')` in gremlin
+                AliasNameWithId inputOneTag =
+                        projectOneTag(
+                                ((Project) input).getProjects(),
+                                input.getRowType().getFieldNames(),
+                                ((GraphLogicalProject) input).isAppend());
+                if (inputOneTag != null) {
+                    AliasNameWithId defaultAlias =
+                            new AliasNameWithId(
+                                    AliasInference.DEFAULT_NAME, AliasInference.DEFAULT_ID);
+                    List<AliasNameWithId> inputTags = Lists.newArrayList(inputOneTag, defaultAlias);
+                    if (projectPropertyOfTags(nodeList, inputTags)) {
+                        inputTags.removeAll(Lists.newArrayList(defaultAlias));
+                        if (inputTags.size() == 1) {
+                            RexVariableAliasConverter converter =
+                                    new RexVariableAliasConverter(
+                                            true,
+                                            this,
+                                            inputTags.get(0).getAliasName(),
+                                            inputTags.get(0).getAliasId());
+                            nodeList =
+                                    nodeList.stream()
+                                            .map(k -> k.accept(converter))
+                                            .collect(Collectors.toList());
+                        }
+                        // remove the input project
+                        input = input.getInput(0);
+                    }
+                }
+            }
+            fieldNameList =
+                    AliasInference.inferProject(
+                            nodeList,
+                            fieldNameList,
+                            AliasInference.getUniqueAliasList(input, isAppend));
+        }
+
         RelNode project =
                 GraphLogicalProject.create(
                         (GraphOptCluster) getCluster(),
@@ -1119,6 +1162,50 @@ public GraphBuilder project(
         return this;
     }
 
+    /**
+     * check if the {@code exprs} are actually the pattern of `select('a')` in gremlin, return the tag if it is.
+     * @param exprs
+     * @param aliases
+     * @return
+     */
+    private @Nullable AliasNameWithId projectOneTag(
+            List<RexNode> exprs, List<String> aliases, boolean isAppend) {
+        if (isAppend
+                && exprs.size() == 1
+                && exprs.get(0) instanceof RexGraphVariable
+                && ((RexGraphVariable) exprs.get(0)).getProperty() == null
+                && (aliases.isEmpty()
+                        || aliases.get(0) == null
+                        || aliases.get(0) == AliasInference.DEFAULT_NAME)) {
+            RexVariableAliasCollector<AliasNameWithId> collector =
+                    new RexVariableAliasCollector<>(
+                            true,
+                            (RexGraphVariable var) -> {
+                                String[] splits =
+                                        var.getName()
+                                                .split(Pattern.quote(AliasInference.DELIMITER));
+                                String aliasName =
+                                        splits.length > 0 ? splits[0] : AliasInference.DEFAULT_NAME;
+                                return new AliasNameWithId(aliasName, var.getAliasId());
+                            });
+            return exprs.get(0).accept(collector).get(0);
+        }
+        return null;
+    }
+
+    /**
+     * check if the {@code exprs} denotes the properties projection of the specified {@code tags}, return true if it is.
+     * @param exprs
+     * @param tags
+     * @return
+     */
+    private boolean projectPropertyOfTags(List<RexNode> exprs, List<AliasNameWithId> tags) {
+        List<Integer> tagIds = tags.stream().map(k -> k.getAliasId()).collect(Collectors.toList());
+        RexVariableAliasCollector<Integer> collector =
+                new RexVariableAliasCollector<>(true, (RexGraphVariable var) -> var.getAliasId());
+        return exprs.stream().allMatch(k -> tagIds.containsAll(k.accept(collector)));
+    }
+
     /**
      * derive {@code RelDataType} of project operators
      *
@@ -1423,6 +1510,47 @@ public GraphBuilder sortLimit(
         return this;
     }
 
+    public GraphBuilder dedupBy(Iterable<? extends RexNode> nodes) {
+        RelNode input = requireNonNull(peek(), "frame stack is empty");
+
+        List<RelDataTypeField> originalFields = input.getRowType().getFieldList();
+
+        Registrar registrar = new Registrar(this, input, true);
+        List<RexNode> registerNodes = registrar.registerExpressions(ImmutableList.copyOf(nodes));
+
+        // expressions need to be projected in advance
+        if (!registrar.getExtraNodes().isEmpty()) {
+            project(registrar.getExtraNodes(), registrar.getExtraAliases(), registrar.isAppend());
+            RexTmpVariableConverter converter = new RexTmpVariableConverter(true, this);
+            registerNodes =
+                    registerNodes.stream()
+                            .map(k -> k.accept(converter))
+                            .collect(Collectors.toList());
+            input = requireNonNull(peek(), "frame stack is empty");
+        }
+
+        // if dedup by keys is empty, use 'HEAD' variable by default
+        if (registerNodes.isEmpty()) {
+            registerNodes.add(variable((String) null));
+        }
+        RelNode dedupBy =
+                GraphLogicalDedupBy.create(
+                        (GraphOptCluster) this.getCluster(), input, registerNodes);
+        replaceTop(dedupBy);
+
+        // to remove the extra columns we have added
+        if (!registrar.getExtraAliases().isEmpty()) {
+            List<RexNode> originalExprs = new ArrayList<>();
+            List<String> originalAliases = new ArrayList<>();
+            for (RelDataTypeField field : originalFields) {
+                originalExprs.add(variable(field.getName()));
+                originalAliases.add(field.getName());
+            }
+            project(originalExprs, originalAliases, false);
+        }
+        return this;
+    }
+
     @Override
     public RelBuilder join(
             JoinRelType joinType, RexNode condition, Set<CorrelationId> variablesSet) {
diff --git a/interactive_engine/compiler/src/main/java/com/alibaba/graphscope/common/ir/tools/GraphPlanner.java b/interactive_engine/compiler/src/main/java/com/alibaba/graphscope/common/ir/tools/GraphPlanner.java
index 38cadbc3d3bb..d6808af22879 100644
--- a/interactive_engine/compiler/src/main/java/com/alibaba/graphscope/common/ir/tools/GraphPlanner.java
+++ b/interactive_engine/compiler/src/main/java/com/alibaba/graphscope/common/ir/tools/GraphPlanner.java
@@ -17,7 +17,6 @@
 package com.alibaba.graphscope.common.ir.tools;
 
 import com.alibaba.graphscope.common.config.Configs;
-import com.alibaba.graphscope.common.config.FrontendConfig;
 import com.alibaba.graphscope.common.config.PlannerConfig;
 import com.alibaba.graphscope.common.ir.meta.procedure.StoredProcedureMeta;
 import com.alibaba.graphscope.common.ir.meta.reader.LocalMetaDataReader;
@@ -61,7 +60,6 @@
 import java.util.List;
 import java.util.Map;
 import java.util.Objects;
-import java.util.concurrent.atomic.AtomicLong;
 import java.util.function.Function;
 
 /**
@@ -73,7 +71,6 @@ public class GraphPlanner {
     private final PlannerConfig plannerConfig;
     private final RelOptPlanner optPlanner;
     private final RexBuilder rexBuilder;
-    private final AtomicLong idGenerator;
     private final LogicalPlanFactory logicalPlanFactory;
 
     public static final Function<Configs, RexBuilder> rexBuilderFactory =
@@ -86,7 +83,6 @@ public GraphPlanner(Configs graphConfig, LogicalPlanFactory logicalPlanFactory)
         this.optPlanner =
                 createRelOptPlanner(this.plannerConfig, new GraphBuilderFactory(this.graphConfig));
         this.rexBuilder = rexBuilderFactory.apply(graphConfig);
-        this.idGenerator = new AtomicLong(FrontendConfig.FRONTEND_SERVER_ID.get(graphConfig));
         this.logicalPlanFactory = logicalPlanFactory;
     }
 
@@ -95,15 +91,6 @@ public PlannerInstance instance(String query, IrMeta irMeta) {
         return new PlannerInstance(query, optCluster, irMeta);
     }
 
-    public long generateUniqueId() {
-        long delta = FrontendConfig.FRONTEND_SERVER_NUM.get(graphConfig);
-        return idGenerator.getAndAdd(delta);
-    }
-
-    public String generateUniqueName(long uniqueId) {
-        return "ir_plan_" + uniqueId;
-    }
-
     public class PlannerInstance {
         private final String query;
         private final GraphOptCluster optCluster;
@@ -116,10 +103,8 @@ public PlannerInstance(String query, GraphOptCluster optCluster, IrMeta irMeta)
         }
 
         public Summary plan() {
-            long jobId = generateUniqueId();
             LogicalPlan logicalPlan = planLogical();
-            return new Summary(
-                    jobId, generateUniqueName(jobId), logicalPlan, planPhysical(logicalPlan));
+            return new Summary(logicalPlan, planPhysical(logicalPlan));
         }
 
         public LogicalPlan planLogical() {
@@ -167,26 +152,14 @@ public PhysicalPlan planPhysical(LogicalPlan logicalPlan) {
     }
 
     public static class Summary {
-        private final long id;
-        private final String name;
         private final LogicalPlan logicalPlan;
         private final PhysicalPlan physicalPlan;
 
-        public Summary(long id, String name, LogicalPlan logicalPlan, PhysicalPlan physicalPlan) {
-            this.id = id;
-            this.name = name;
+        public Summary(LogicalPlan logicalPlan, PhysicalPlan physicalPlan) {
             this.logicalPlan = Objects.requireNonNull(logicalPlan);
             this.physicalPlan = Objects.requireNonNull(physicalPlan);
         }
 
-        public long getId() {
-            return id;
-        }
-
-        public String getName() {
-            return name;
-        }
-
         public LogicalPlan getLogicalPlan() {
             return logicalPlan;
         }
diff --git a/interactive_engine/compiler/src/main/java/com/alibaba/graphscope/common/ir/tools/QueryCache.java b/interactive_engine/compiler/src/main/java/com/alibaba/graphscope/common/ir/tools/QueryCache.java
index 26bed3fc0c5e..1e40971112b8 100644
--- a/interactive_engine/compiler/src/main/java/com/alibaba/graphscope/common/ir/tools/QueryCache.java
+++ b/interactive_engine/compiler/src/main/java/com/alibaba/graphscope/common/ir/tools/QueryCache.java
@@ -48,10 +48,7 @@ public QueryCache(Configs configs, GraphPlanner graphPlanner) {
                                                             key.logicalPlan);
                                             GraphPlanner.Summary summary =
                                                     new GraphPlanner.Summary(
-                                                            0,
-                                                            "query_cache_0",
-                                                            key.logicalPlan,
-                                                            physicalPlan);
+                                                            key.logicalPlan, physicalPlan);
                                             return new Value(summary, null);
                                         }));
     }
diff --git a/interactive_engine/compiler/src/main/java/com/alibaba/graphscope/common/ir/tools/QueryIdGenerator.java b/interactive_engine/compiler/src/main/java/com/alibaba/graphscope/common/ir/tools/QueryIdGenerator.java
new file mode 100644
index 000000000000..c245c6e9b10f
--- /dev/null
+++ b/interactive_engine/compiler/src/main/java/com/alibaba/graphscope/common/ir/tools/QueryIdGenerator.java
@@ -0,0 +1,41 @@
+/*
+ * Copyright 2020 Alibaba Group Holding Limited.
+ *
+ * Licensed 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 com.alibaba.graphscope.common.ir.tools;
+
+import com.alibaba.graphscope.common.config.Configs;
+import com.alibaba.graphscope.common.config.FrontendConfig;
+
+import java.util.concurrent.atomic.AtomicLong;
+
+public class QueryIdGenerator {
+    private final Configs configs;
+    private final AtomicLong idGenerator;
+
+    public QueryIdGenerator(Configs configs) {
+        this.configs = configs;
+        this.idGenerator = new AtomicLong(FrontendConfig.FRONTEND_SERVER_ID.get(configs));
+    }
+
+    public long generateId() {
+        long delta = FrontendConfig.FRONTEND_SERVER_NUM.get(configs);
+        return idGenerator.getAndAdd(delta);
+    }
+
+    public String generateName(long uniqueId) {
+        return "ir_plan_" + uniqueId;
+    }
+}
diff --git a/interactive_engine/compiler/src/main/java/com/alibaba/graphscope/common/ir/type/GraphTypeFactoryImpl.java b/interactive_engine/compiler/src/main/java/com/alibaba/graphscope/common/ir/type/GraphTypeFactoryImpl.java
index c73ac7e6a1ca..ebd688285340 100644
--- a/interactive_engine/compiler/src/main/java/com/alibaba/graphscope/common/ir/type/GraphTypeFactoryImpl.java
+++ b/interactive_engine/compiler/src/main/java/com/alibaba/graphscope/common/ir/type/GraphTypeFactoryImpl.java
@@ -21,6 +21,7 @@
 
 import org.apache.calcite.jdbc.JavaTypeFactoryImpl;
 import org.apache.calcite.rel.type.RelDataType;
+import org.checkerframework.checker.nullness.qual.Nullable;
 
 import java.nio.charset.Charset;
 import java.util.List;
@@ -74,4 +75,15 @@ public RelDataType createArbitraryMapType(
             List<RelDataType> keyTypes, List<RelDataType> valueTypes, boolean isNullable) {
         return new ArbitraryMapType(keyTypes, valueTypes, isNullable);
     }
+
+    @Override
+    public @Nullable RelDataType leastRestrictive(List<RelDataType> types) {
+        if (types.stream().anyMatch(t -> t instanceof GraphLabelType)) {
+            for (RelDataType type : types) {
+                if (!(type instanceof GraphLabelType)) return null;
+            }
+            return types.get(0);
+        }
+        return super.leastRestrictive(types);
+    }
 }
diff --git a/interactive_engine/compiler/src/main/java/com/alibaba/graphscope/common/result/Utils.java b/interactive_engine/compiler/src/main/java/com/alibaba/graphscope/common/result/Utils.java
new file mode 100644
index 000000000000..693139231834
--- /dev/null
+++ b/interactive_engine/compiler/src/main/java/com/alibaba/graphscope/common/result/Utils.java
@@ -0,0 +1,161 @@
+/*
+ * Copyright 2020 Alibaba Group Holding Limited.
+ *
+ * Licensed 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 com.alibaba.graphscope.common.result;
+
+import com.alibaba.graphscope.common.ir.type.GraphLabelType;
+import com.alibaba.graphscope.common.ir.type.GraphPathType;
+import com.alibaba.graphscope.common.ir.type.GraphSchemaType;
+import com.alibaba.graphscope.gaia.proto.Common;
+import com.google.common.base.Predicate;
+import com.google.common.collect.Lists;
+
+import org.apache.calcite.rel.type.RelDataType;
+import org.apache.calcite.rel.type.RelDataTypeField;
+import org.checkerframework.checker.nullness.qual.Nullable;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class Utils {
+    private static final Logger logger = LoggerFactory.getLogger(Utils.class);
+
+    public static String getLabelName(
+            Common.NameOrId nameOrId, @Nullable GraphLabelType labelTypes) {
+        switch (nameOrId.getItemCase()) {
+            case NAME:
+                return nameOrId.getName();
+            case ID:
+            default:
+                List<Integer> labelIds = new ArrayList<>();
+                if (labelTypes != null) {
+                    for (GraphLabelType.Entry labelType : labelTypes.getLabelsEntry()) {
+                        if (labelType.getLabelId() == nameOrId.getId()) {
+                            return labelType.getLabel();
+                        }
+                        labelIds.add(labelType.getLabelId());
+                    }
+                }
+                logger.warn(
+                        "label id={} not found, expected ids are {}", nameOrId.getId(), labelIds);
+                return String.valueOf(nameOrId.getId());
+        }
+    }
+
+    public static String getSrcLabelName(
+            Common.NameOrId nameOrId, @Nullable GraphLabelType labelTypes) {
+        switch (nameOrId.getItemCase()) {
+            case NAME:
+                return nameOrId.getName();
+            case ID:
+            default:
+                List<Integer> labelIds = new ArrayList<>();
+                if (labelTypes != null) {
+                    for (GraphLabelType.Entry labelType : labelTypes.getLabelsEntry()) {
+                        if (labelType.getSrcLabelId() == nameOrId.getId()) {
+                            return labelType.getSrcLabel();
+                        }
+                    }
+                }
+                logger.warn(
+                        "src label id={} not found, expected ids are {}",
+                        nameOrId.getId(),
+                        labelIds);
+                return String.valueOf(nameOrId.getId());
+        }
+    }
+
+    public static String getDstLabelName(
+            Common.NameOrId nameOrId, @Nullable GraphLabelType labelTypes) {
+        switch (nameOrId.getItemCase()) {
+            case NAME:
+                return nameOrId.getName();
+            case ID:
+            default:
+                List<Integer> labelIds = new ArrayList<>();
+                if (labelTypes != null) {
+                    for (GraphLabelType.Entry labelType : labelTypes.getLabelsEntry()) {
+                        if (labelType.getDstLabelId() == nameOrId.getId()) {
+                            return labelType.getDstLabel();
+                        }
+                    }
+                }
+                logger.warn(
+                        "dst label id={} not found, expected ids are {}",
+                        nameOrId.getId(),
+                        labelIds);
+                return String.valueOf(nameOrId.getId());
+        }
+    }
+
+    public static @Nullable GraphLabelType getLabelTypes(RelDataType dataType) {
+        if (dataType instanceof GraphSchemaType) {
+            return ((GraphSchemaType) dataType).getLabelType();
+        } else {
+            return null;
+        }
+    }
+
+    public static RelDataType getVertexType(RelDataType graphPathType) {
+        return (graphPathType instanceof GraphPathType)
+                ? ((GraphPathType) graphPathType).getComponentType().getGetVType()
+                : graphPathType;
+    }
+
+    public static RelDataType getEdgeType(RelDataType graphPathType) {
+        return (graphPathType instanceof GraphPathType)
+                ? ((GraphPathType) graphPathType).getComponentType().getExpandType()
+                : graphPathType;
+    }
+
+    public static String parseLabelValue(Common.Value value, GraphLabelType type) {
+        switch (value.getItemCase()) {
+            case STR:
+                return value.getStr();
+            case I32:
+                return parseLabelValue(value.getI32(), type);
+            case I64:
+                return parseLabelValue(value.getI64(), type);
+            default:
+                throw new IllegalArgumentException(
+                        "cannot parse label value with type=" + value.getItemCase().name());
+        }
+    }
+
+    public static String parseLabelValue(long labelId, GraphLabelType type) {
+        List<Object> expectedLabelIds = Lists.newArrayList();
+        for (GraphLabelType.Entry entry : type.getLabelsEntry()) {
+            if (entry.getLabelId() == labelId) {
+                return entry.getLabel();
+            }
+            expectedLabelIds.add(entry.getLabelId());
+        }
+        throw new IllegalArgumentException(
+                "cannot parse label value="
+                        + labelId
+                        + " from expected type="
+                        + type
+                        + ", expected ids are "
+                        + expectedLabelIds);
+    }
+
+    public static RelDataTypeField findFieldByPredicate(
+            Predicate<RelDataTypeField> p, List<RelDataTypeField> typeFields) {
+        return typeFields.stream().filter(k -> p.test(k)).findFirst().orElse(null);
+    }
+}
diff --git a/interactive_engine/compiler/src/main/java/com/alibaba/graphscope/cypher/executor/GraphQueryExecutor.java b/interactive_engine/compiler/src/main/java/com/alibaba/graphscope/cypher/executor/GraphQueryExecutor.java
index 26a1b7c04a45..a710578ad492 100644
--- a/interactive_engine/compiler/src/main/java/com/alibaba/graphscope/cypher/executor/GraphQueryExecutor.java
+++ b/interactive_engine/compiler/src/main/java/com/alibaba/graphscope/cypher/executor/GraphQueryExecutor.java
@@ -16,7 +16,6 @@
 
 package com.alibaba.graphscope.cypher.executor;
 
-import com.alibaba.graphscope.common.antlr4.Antlr4Parser;
 import com.alibaba.graphscope.common.client.ExecutionClient;
 import com.alibaba.graphscope.common.client.type.ExecutionRequest;
 import com.alibaba.graphscope.common.client.type.ExecutionResponseListener;
@@ -24,6 +23,7 @@
 import com.alibaba.graphscope.common.config.QueryTimeoutConfig;
 import com.alibaba.graphscope.common.ir.tools.GraphPlanner;
 import com.alibaba.graphscope.common.ir.tools.QueryCache;
+import com.alibaba.graphscope.common.ir.tools.QueryIdGenerator;
 import com.alibaba.graphscope.common.manager.IrMetaQueryCallback;
 import com.alibaba.graphscope.common.store.IrMeta;
 import com.alibaba.graphscope.gaia.proto.IrResult;
@@ -53,11 +53,10 @@ public class GraphQueryExecutor extends FabricExecutor {
             "CALL dbms.routing.getRoutingTable($routingContext, $databaseName)";
     private static String PING_STATEMENT = "CALL db.ping()";
     private final Configs graphConfig;
-    private final Antlr4Parser antlr4Parser;
     private final IrMetaQueryCallback metaQueryCallback;
     private final ExecutionClient client;
 
-    private final GraphPlanner graphPlanner;
+    private final QueryIdGenerator idGenerator;
     private final FabricConfig fabricConfig;
     private final QueryCache queryCache;
 
@@ -70,8 +69,7 @@ public GraphQueryExecutor(
             FabricStatementLifecycles statementLifecycles,
             Executor fabricWorkerExecutor,
             Configs graphConfig,
-            Antlr4Parser antlr4Parser,
-            GraphPlanner graphPlanner,
+            QueryIdGenerator idGenerator,
             IrMetaQueryCallback metaQueryCallback,
             ExecutionClient client,
             QueryCache queryCache) {
@@ -85,8 +83,7 @@ public GraphQueryExecutor(
                 fabricWorkerExecutor);
         this.fabricConfig = config;
         this.graphConfig = graphConfig;
-        this.antlr4Parser = antlr4Parser;
-        this.graphPlanner = graphPlanner;
+        this.idGenerator = idGenerator;
         this.metaQueryCallback = metaQueryCallback;
         this.client = client;
         this.queryCache = queryCache;
@@ -117,18 +114,17 @@ public StatementResult run(
             Preconditions.checkArgument(
                     cacheValue != null,
                     "value should have been loaded automatically in query cache");
-            long jobId = graphPlanner.generateUniqueId();
+            long jobId = idGenerator.generateId();
+            String jobName = idGenerator.generateName(jobId);
             GraphPlanner.Summary planSummary =
                     new GraphPlanner.Summary(
-                            jobId,
-                            graphPlanner.generateUniqueName(jobId),
                             cacheValue.summary.getLogicalPlan(),
                             cacheValue.summary.getPhysicalPlan());
             logger.debug(
                     "cypher query \"{}\", job conf name \"{}\", calcite logical plan {}, hash id"
                             + " {}",
                     statement,
-                    planSummary.getName(),
+                    jobName,
                     planSummary.getLogicalPlan().explain(),
                     cacheKey.hashCode());
             if (planSummary.getLogicalPlan().isReturnEmpty()) {
@@ -137,7 +133,7 @@ public StatementResult run(
             logger.info(
                     "cypher query \"{}\", job conf name \"{}\", ir core logical plan {}",
                     statement,
-                    planSummary.getName(),
+                    jobName,
                     planSummary.getPhysicalPlan().explain());
             StatementResults.SubscribableExecution execution;
             if (cacheValue.result != null && cacheValue.result.isCompleted) {
@@ -158,8 +154,8 @@ protected void execute(ExecutionResponseListener listener)
                                     throws Exception {
                                 ExecutionRequest request =
                                         new ExecutionRequest(
-                                                planSummary.getId(),
-                                                planSummary.getName(),
+                                                jobId,
+                                                jobName,
                                                 planSummary.getLogicalPlan(),
                                                 planSummary.getPhysicalPlan());
                                 QueryTimeoutConfig timeoutConfig = getQueryTimeoutConfig();
diff --git a/interactive_engine/compiler/src/main/java/com/alibaba/graphscope/cypher/result/CypherRecordParser.java b/interactive_engine/compiler/src/main/java/com/alibaba/graphscope/cypher/result/CypherRecordParser.java
index c8c3f65ef09a..212c5c27825d 100644
--- a/interactive_engine/compiler/src/main/java/com/alibaba/graphscope/cypher/result/CypherRecordParser.java
+++ b/interactive_engine/compiler/src/main/java/com/alibaba/graphscope/cypher/result/CypherRecordParser.java
@@ -16,12 +16,15 @@
 
 package com.alibaba.graphscope.cypher.result;
 
-import com.alibaba.graphscope.common.ir.type.*;
+import com.alibaba.graphscope.common.ir.type.ArbitraryArrayType;
+import com.alibaba.graphscope.common.ir.type.ArbitraryMapType;
+import com.alibaba.graphscope.common.ir.type.GraphLabelType;
+import com.alibaba.graphscope.common.ir.type.GraphPathType;
 import com.alibaba.graphscope.common.result.RecordParser;
+import com.alibaba.graphscope.common.result.Utils;
 import com.alibaba.graphscope.gaia.proto.Common;
 import com.alibaba.graphscope.gaia.proto.IrResult;
 import com.google.common.base.Preconditions;
-import com.google.common.base.Predicate;
 import com.google.common.collect.Lists;
 import com.google.common.collect.Maps;
 
@@ -212,7 +215,8 @@ protected AnyValue parseKeyValues(
     protected NodeValue parseVertex(IrResult.Vertex vertex, @Nullable RelDataType dataType) {
         return VirtualValues.nodeValue(
                 vertex.getId(),
-                Values.stringArray(getLabelName(vertex.getLabel(), getLabelTypes(dataType))),
+                Values.stringArray(
+                        Utils.getLabelName(vertex.getLabel(), Utils.getLabelTypes(dataType))),
                 parseProperties(vertex.getPropertiesList(), dataType));
     }
 
@@ -222,14 +226,17 @@ protected RelationshipValue parseEdge(IrResult.Edge edge, @Nullable RelDataType
                 VirtualValues.nodeValue(
                         edge.getSrcId(),
                         Values.stringArray(
-                                getSrcLabelName(edge.getSrcLabel(), getLabelTypes(dataType))),
+                                Utils.getSrcLabelName(
+                                        edge.getSrcLabel(), Utils.getLabelTypes(dataType))),
                         MapValue.EMPTY),
                 VirtualValues.nodeValue(
                         edge.getDstId(),
                         Values.stringArray(
-                                getDstLabelName(edge.getDstLabel(), getLabelTypes(dataType))),
+                                Utils.getDstLabelName(
+                                        edge.getDstLabel(), Utils.getLabelTypes(dataType))),
                         MapValue.EMPTY),
-                Values.stringValue(getLabelName(edge.getLabel(), getLabelTypes(dataType))),
+                Values.stringValue(
+                        Utils.getLabelName(edge.getLabel(), Utils.getLabelTypes(dataType))),
                 parseProperties(edge.getPropertiesList(), dataType));
     }
 
@@ -247,7 +254,7 @@ private MapValue parseProperties(List<IrResult.Property> properties, RelDataType
                         case NAME:
                             // find target field in typeFields by property name
                             field =
-                                    findFieldByPredicate(
+                                    Utils.findFieldByPredicate(
                                             k1 -> k1.getName().equals(key.getName()), typeFields);
                             keyStr = key.getName();
                             break;
@@ -255,7 +262,7 @@ private MapValue parseProperties(List<IrResult.Property> properties, RelDataType
                         default:
                             // find target field in typeFields by property id
                             field =
-                                    findFieldByPredicate(
+                                    Utils.findFieldByPredicate(
                                             k1 -> k1.getIndex() == key.getId(), typeFields);
                             keyStr =
                                     (field != null) ? field.getName() : String.valueOf(key.getId());
@@ -267,11 +274,6 @@ private MapValue parseProperties(List<IrResult.Property> properties, RelDataType
         return VirtualValues.fromMap(valueMap, valueMap.size(), 0);
     }
 
-    private RelDataTypeField findFieldByPredicate(
-            Predicate<RelDataTypeField> p, List<RelDataTypeField> typeFields) {
-        return typeFields.stream().filter(k -> p.test(k)).findFirst().orElse(null);
-    }
-
     protected AnyValue parseGraphPath(IrResult.GraphPath path, @Nullable RelDataType dataType) {
         List<NodeValue> nodes = Lists.newArrayList();
         List<RelationshipValue> relationships = Lists.newArrayList();
@@ -280,11 +282,13 @@ protected AnyValue parseGraphPath(IrResult.GraphPath path, @Nullable RelDataType
                         k -> {
                             switch (k.getInnerCase()) {
                                 case VERTEX:
-                                    nodes.add(parseVertex(k.getVertex(), getVertexType(dataType)));
+                                    nodes.add(
+                                            parseVertex(
+                                                    k.getVertex(), Utils.getVertexType(dataType)));
                                     break;
                                 case EDGE:
                                     relationships.add(
-                                            parseEdge(k.getEdge(), getEdgeType(dataType)));
+                                            parseEdge(k.getEdge(), Utils.getEdgeType(dataType)));
                                     break;
                             }
                         });
@@ -294,7 +298,7 @@ protected AnyValue parseGraphPath(IrResult.GraphPath path, @Nullable RelDataType
 
     protected AnyValue parseValue(Common.Value value, @Nullable RelDataType dataType) {
         if (dataType instanceof GraphLabelType) {
-            return Values.stringValue(parseLabelValue(value, (GraphLabelType) dataType));
+            return Values.stringValue(Utils.parseLabelValue(value, (GraphLabelType) dataType));
         }
         switch (value.getItemCase()) {
             case BOOLEAN:
@@ -346,120 +350,4 @@ protected AnyValue parseValue(Common.Value value, @Nullable RelDataType dataType
                 throw new NotImplementedException(value.getItemCase() + " is unsupported yet");
         }
     }
-
-    private String getLabelName(Common.NameOrId nameOrId, @Nullable GraphLabelType labelTypes) {
-        switch (nameOrId.getItemCase()) {
-            case NAME:
-                return nameOrId.getName();
-            case ID:
-            default:
-                List<Integer> labelIds = new ArrayList<>();
-                if (labelTypes != null) {
-                    for (GraphLabelType.Entry labelType : labelTypes.getLabelsEntry()) {
-                        if (labelType.getLabelId() == nameOrId.getId()) {
-                            return labelType.getLabel();
-                        }
-                        labelIds.add(labelType.getLabelId());
-                    }
-                }
-                logger.warn(
-                        "label id={} not found, expected ids are {}", nameOrId.getId(), labelIds);
-                return String.valueOf(nameOrId.getId());
-        }
-    }
-
-    private String getSrcLabelName(Common.NameOrId nameOrId, @Nullable GraphLabelType labelTypes) {
-        switch (nameOrId.getItemCase()) {
-            case NAME:
-                return nameOrId.getName();
-            case ID:
-            default:
-                List<Integer> labelIds = new ArrayList<>();
-                if (labelTypes != null) {
-                    for (GraphLabelType.Entry labelType : labelTypes.getLabelsEntry()) {
-                        if (labelType.getSrcLabelId() == nameOrId.getId()) {
-                            return labelType.getSrcLabel();
-                        }
-                    }
-                }
-                logger.warn(
-                        "src label id={} not found, expected ids are {}",
-                        nameOrId.getId(),
-                        labelIds);
-                return String.valueOf(nameOrId.getId());
-        }
-    }
-
-    private String getDstLabelName(Common.NameOrId nameOrId, @Nullable GraphLabelType labelTypes) {
-        switch (nameOrId.getItemCase()) {
-            case NAME:
-                return nameOrId.getName();
-            case ID:
-            default:
-                List<Integer> labelIds = new ArrayList<>();
-                if (labelTypes != null) {
-                    for (GraphLabelType.Entry labelType : labelTypes.getLabelsEntry()) {
-                        if (labelType.getDstLabelId() == nameOrId.getId()) {
-                            return labelType.getDstLabel();
-                        }
-                    }
-                }
-                logger.warn(
-                        "dst label id={} not found, expected ids are {}",
-                        nameOrId.getId(),
-                        labelIds);
-                return String.valueOf(nameOrId.getId());
-        }
-    }
-
-    private @Nullable GraphLabelType getLabelTypes(RelDataType dataType) {
-        if (dataType instanceof GraphSchemaType) {
-            return ((GraphSchemaType) dataType).getLabelType();
-        } else {
-            return null;
-        }
-    }
-
-    private RelDataType getVertexType(RelDataType graphPathType) {
-        return (graphPathType instanceof GraphPathType)
-                ? ((GraphPathType) graphPathType).getComponentType().getGetVType()
-                : graphPathType;
-    }
-
-    private RelDataType getEdgeType(RelDataType graphPathType) {
-        return (graphPathType instanceof GraphPathType)
-                ? ((GraphPathType) graphPathType).getComponentType().getExpandType()
-                : graphPathType;
-    }
-
-    private String parseLabelValue(Common.Value value, GraphLabelType type) {
-        switch (value.getItemCase()) {
-            case STR:
-                return value.getStr();
-            case I32:
-                return parseLabelValue(value.getI32(), type);
-            case I64:
-                return parseLabelValue(value.getI64(), type);
-            default:
-                throw new IllegalArgumentException(
-                        "cannot parse label value with type=" + value.getItemCase().name());
-        }
-    }
-
-    private String parseLabelValue(long labelId, GraphLabelType type) {
-        List<Object> expectedLabelIds = Lists.newArrayList();
-        for (GraphLabelType.Entry entry : type.getLabelsEntry()) {
-            if (entry.getLabelId() == labelId) {
-                return entry.getLabel();
-            }
-            expectedLabelIds.add(entry.getLabelId());
-        }
-        throw new IllegalArgumentException(
-                "cannot parse label value="
-                        + labelId
-                        + " from expected type="
-                        + type
-                        + ", expected ids are "
-                        + expectedLabelIds);
-    }
 }
diff --git a/interactive_engine/compiler/src/main/java/com/alibaba/graphscope/cypher/service/CypherBootstrapper.java b/interactive_engine/compiler/src/main/java/com/alibaba/graphscope/cypher/service/CypherBootstrapper.java
index f31d0c0406f6..768c8a0bbce3 100644
--- a/interactive_engine/compiler/src/main/java/com/alibaba/graphscope/cypher/service/CypherBootstrapper.java
+++ b/interactive_engine/compiler/src/main/java/com/alibaba/graphscope/cypher/service/CypherBootstrapper.java
@@ -16,13 +16,11 @@
 
 package com.alibaba.graphscope.cypher.service;
 
-import com.alibaba.graphscope.common.antlr4.Antlr4Parser;
 import com.alibaba.graphscope.common.client.ExecutionClient;
 import com.alibaba.graphscope.common.config.Configs;
-import com.alibaba.graphscope.common.ir.tools.GraphPlanner;
 import com.alibaba.graphscope.common.ir.tools.QueryCache;
+import com.alibaba.graphscope.common.ir.tools.QueryIdGenerator;
 import com.alibaba.graphscope.common.manager.IrMetaQueryCallback;
-import com.alibaba.graphscope.cypher.antlr4.parser.CypherAntlr4Parser;
 import com.alibaba.graphscope.gremlin.Utils;
 
 import org.neo4j.collection.Dependencies;
@@ -54,24 +52,18 @@ public class CypherBootstrapper extends CommunityBootstrapper {
 
     public CypherBootstrapper(
             Configs graphConfig,
-            GraphPlanner graphPlanner,
+            QueryIdGenerator idGenerator,
             IrMetaQueryCallback queryCallback,
             ExecutionClient client,
             QueryCache queryCache) {
         this.client = client;
         this.externalDependencies =
                 createExternalDependencies(
-                        graphConfig,
-                        new CypherAntlr4Parser(),
-                        graphPlanner,
-                        queryCallback,
-                        client,
-                        queryCache);
+                        graphConfig, idGenerator, queryCallback, client, queryCache);
         this.externalClassTypes =
                 Arrays.asList(
                         Configs.class,
-                        Antlr4Parser.class,
-                        GraphPlanner.class,
+                        QueryIdGenerator.class,
                         IrMetaQueryCallback.class,
                         ExecutionClient.class,
                         QueryCache.class);
@@ -99,14 +91,12 @@ protected DatabaseManagementService createNeo(
 
     private Dependencies createExternalDependencies(
             Configs configs,
-            Antlr4Parser cypherParser,
-            GraphPlanner graphPlanner,
+            QueryIdGenerator idGenerator,
             IrMetaQueryCallback queryCallback,
             ExecutionClient client,
             QueryCache queryCache) {
         Dependencies dependencies = new Dependencies();
-        dependencies.satisfyDependencies(
-                configs, cypherParser, graphPlanner, queryCallback, client, queryCache);
+        dependencies.satisfyDependencies(configs, idGenerator, queryCallback, client, queryCache);
         return dependencies;
     }
 
diff --git a/interactive_engine/compiler/src/main/java/com/alibaba/graphscope/cypher/service/CypherQueryServiceBootstrap.java b/interactive_engine/compiler/src/main/java/com/alibaba/graphscope/cypher/service/CypherQueryServiceBootstrap.java
index 9d36a37039ca..38700b7cb3db 100644
--- a/interactive_engine/compiler/src/main/java/com/alibaba/graphscope/cypher/service/CypherQueryServiceBootstrap.java
+++ b/interactive_engine/compiler/src/main/java/com/alibaba/graphscope/cypher/service/CypherQueryServiceBootstrap.java
@@ -20,11 +20,10 @@
 import static org.neo4j.scheduler.Group.FABRIC_WORKER;
 import static org.neo4j.scheduler.JobMonitoringParams.systemJob;
 
-import com.alibaba.graphscope.common.antlr4.Antlr4Parser;
 import com.alibaba.graphscope.common.client.ExecutionClient;
 import com.alibaba.graphscope.common.config.Configs;
-import com.alibaba.graphscope.common.ir.tools.GraphPlanner;
 import com.alibaba.graphscope.common.ir.tools.QueryCache;
+import com.alibaba.graphscope.common.ir.tools.QueryIdGenerator;
 import com.alibaba.graphscope.common.manager.IrMetaQueryCallback;
 import com.alibaba.graphscope.cypher.executor.GraphQueryExecutor;
 import com.alibaba.graphscope.gremlin.Utils;
@@ -161,8 +160,7 @@ public void bootstrapServices() {
         Executor fabricWorkerExecutor = jobScheduler.executor(FABRIC_WORKER);
         // gie config
         var graphConfig = (Configs) resolve(Configs.class);
-        var antlr4Parser = (Antlr4Parser) resolve(Antlr4Parser.class);
-        var graphPlanner = (GraphPlanner) resolve(GraphPlanner.class);
+        var idGenerator = (QueryIdGenerator) resolve(QueryIdGenerator.class);
         var metaQueryCallback = (IrMetaQueryCallback) resolve(IrMetaQueryCallback.class);
         var executionClient = (ExecutionClient) resolve(ExecutionClient.class);
         var queryCache = (QueryCache) resolve(QueryCache.class);
@@ -176,8 +174,7 @@ public void bootstrapServices() {
                         statementLifecycles,
                         fabricWorkerExecutor,
                         graphConfig,
-                        antlr4Parser,
-                        graphPlanner,
+                        idGenerator,
                         metaQueryCallback,
                         executionClient,
                         queryCache);
diff --git a/interactive_engine/compiler/src/main/java/com/alibaba/graphscope/gremlin/antlr4x/parser/GremlinAntlr4Parser.java b/interactive_engine/compiler/src/main/java/com/alibaba/graphscope/gremlin/antlr4x/parser/GremlinAntlr4Parser.java
new file mode 100644
index 000000000000..24c8c718427a
--- /dev/null
+++ b/interactive_engine/compiler/src/main/java/com/alibaba/graphscope/gremlin/antlr4x/parser/GremlinAntlr4Parser.java
@@ -0,0 +1,49 @@
+/*
+ * Copyright 2020 Alibaba Group Holding Limited.
+ *
+ * Licensed 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 com.alibaba.graphscope.gremlin.antlr4x.parser;
+
+import com.alibaba.graphscope.common.antlr4.Antlr4Parser;
+import com.alibaba.graphscope.common.antlr4.SyntaxErrorListener;
+import com.alibaba.graphscope.grammar.GremlinGSLexer;
+import com.alibaba.graphscope.grammar.GremlinGSParser;
+
+import org.antlr.v4.runtime.CharStreams;
+import org.antlr.v4.runtime.CommonTokenStream;
+import org.antlr.v4.runtime.DefaultErrorStrategy;
+import org.antlr.v4.runtime.atn.PredictionMode;
+import org.antlr.v4.runtime.tree.ParseTree;
+
+/**
+ * parse gremlin DSL to antlr tree
+ */
+public class GremlinAntlr4Parser implements Antlr4Parser {
+    @Override
+    public ParseTree parse(String statement) {
+        GremlinGSLexer lexer = new GremlinGSLexer(CharStreams.fromString(statement));
+        // reset error listeners on lexer
+        lexer.removeErrorListeners();
+        lexer.addErrorListener(new SyntaxErrorListener());
+        final GremlinGSParser parser = new GremlinGSParser(new CommonTokenStream(lexer));
+        // setup error handler on parser
+        parser.setErrorHandler(new DefaultErrorStrategy());
+        // reset error listeners on parser
+        parser.removeErrorListeners();
+        parser.addErrorListener(new SyntaxErrorListener());
+        parser.getInterpreter().setPredictionMode(PredictionMode.LL);
+        return parser.query();
+    }
+}
diff --git a/interactive_engine/compiler/src/main/java/com/alibaba/graphscope/gremlin/antlr4x/visitor/ExpressionVisitor.java b/interactive_engine/compiler/src/main/java/com/alibaba/graphscope/gremlin/antlr4x/visitor/ExpressionVisitor.java
new file mode 100644
index 000000000000..530c334a55fd
--- /dev/null
+++ b/interactive_engine/compiler/src/main/java/com/alibaba/graphscope/gremlin/antlr4x/visitor/ExpressionVisitor.java
@@ -0,0 +1,267 @@
+/*
+ * Copyright 2020 Alibaba Group Holding Limited.
+ *
+ * Licensed 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 com.alibaba.graphscope.gremlin.antlr4x.visitor;
+
+import com.alibaba.graphscope.common.ir.tools.GraphBuilder;
+import com.alibaba.graphscope.common.ir.tools.GraphStdOperatorTable;
+import com.alibaba.graphscope.grammar.GremlinGSBaseVisitor;
+import com.alibaba.graphscope.grammar.GremlinGSParser;
+import com.alibaba.graphscope.gremlin.antlr4.GenericLiteralVisitor;
+import com.alibaba.graphscope.gremlin.exception.UnsupportedEvalException;
+
+import org.apache.calcite.rex.RexNode;
+
+import java.math.BigDecimal;
+import java.util.Arrays;
+import java.util.Objects;
+import java.util.stream.Collectors;
+
+public class ExpressionVisitor extends GremlinGSBaseVisitor<RexNode> {
+    protected final RexNode propertyKey;
+    protected final GraphBuilder builder;
+
+    public static final int SIMPLE_PREDICATE_CHILD_COUNT = 1, CONNECTIVE_PREDICATE_CHILD_COUNT = 6;
+
+    public ExpressionVisitor(GraphBuilder builder, RexNode propertyKey) {
+        this.builder = Objects.requireNonNull(builder);
+        this.propertyKey = Objects.requireNonNull(propertyKey);
+    }
+
+    @Override
+    public RexNode visitTraversalPredicate(GremlinGSParser.TraversalPredicateContext ctx) {
+        switch (ctx.getChildCount()) {
+            case SIMPLE_PREDICATE_CHILD_COUNT:
+                // handle simple predicate
+                return visitChildren(ctx);
+            case CONNECTIVE_PREDICATE_CHILD_COUNT: // simple predicates are connected by and/or
+                final int childIndexOfParameterOperator = 2;
+                final int childIndexOfCaller = 0;
+                final int childIndexOfArgument = 4;
+
+                if (ctx.getChild(childIndexOfParameterOperator).getText().equals("or")) {
+                    // handle or
+                    return builder.call(
+                            GraphStdOperatorTable.OR,
+                            visit(ctx.getChild(childIndexOfCaller)),
+                            visit(ctx.getChild(childIndexOfArgument)));
+                } else {
+                    // handle and
+                    return builder.call(
+                            GraphStdOperatorTable.AND,
+                            visit(ctx.getChild(childIndexOfCaller)),
+                            visit(ctx.getChild(childIndexOfArgument)));
+                }
+            default:
+                throw new UnsupportedEvalException(
+                        ctx.getClass(),
+                        "unexpected number of children in TraversalPredicateContext "
+                                + ctx.getChildCount());
+        }
+    }
+
+    @Override
+    public RexNode visitTraversalPredicate_eq(GremlinGSParser.TraversalPredicate_eqContext ctx) {
+        return builder.call(
+                GraphStdOperatorTable.EQUALS,
+                propertyKey,
+                builder.literal(
+                        GenericLiteralVisitor.getInstance()
+                                .visitGenericLiteral(ctx.genericLiteral())));
+    }
+
+    @Override
+    public RexNode visitTraversalPredicate_neq(GremlinGSParser.TraversalPredicate_neqContext ctx) {
+        return builder.call(
+                GraphStdOperatorTable.NOT_EQUALS,
+                propertyKey,
+                builder.literal(
+                        GenericLiteralVisitor.getInstance()
+                                .visitGenericLiteral(ctx.genericLiteral())));
+    }
+
+    @Override
+    public RexNode visitTraversalPredicate_lt(GremlinGSParser.TraversalPredicate_ltContext ctx) {
+        return builder.call(
+                GraphStdOperatorTable.LESS_THAN,
+                propertyKey,
+                builder.literal(
+                        GenericLiteralVisitor.getInstance()
+                                .visitGenericLiteral(ctx.genericLiteral())));
+    }
+
+    @Override
+    public RexNode visitTraversalPredicate_lte(GremlinGSParser.TraversalPredicate_lteContext ctx) {
+        return builder.call(
+                GraphStdOperatorTable.LESS_THAN_OR_EQUAL,
+                propertyKey,
+                builder.literal(
+                        GenericLiteralVisitor.getInstance()
+                                .visitGenericLiteral(ctx.genericLiteral())));
+    }
+
+    @Override
+    public RexNode visitTraversalPredicate_gt(GremlinGSParser.TraversalPredicate_gtContext ctx) {
+        return builder.call(
+                GraphStdOperatorTable.GREATER_THAN,
+                propertyKey,
+                builder.literal(
+                        GenericLiteralVisitor.getInstance()
+                                .visitGenericLiteral(ctx.genericLiteral())));
+    }
+
+    @Override
+    public RexNode visitTraversalPredicate_gte(GremlinGSParser.TraversalPredicate_gteContext ctx) {
+        return builder.call(
+                GraphStdOperatorTable.GREATER_THAN_OR_EQUAL,
+                propertyKey,
+                builder.literal(
+                        GenericLiteralVisitor.getInstance()
+                                .visitGenericLiteral(ctx.genericLiteral())));
+    }
+
+    @Override
+    public RexNode visitTraversalPredicate_within(
+            GremlinGSParser.TraversalPredicate_withinContext ctx) {
+        Object[] points = GenericLiteralVisitor.getGenericLiteralList(ctx.genericLiteralList());
+        return builder.getRexBuilder()
+                .makeIn(
+                        propertyKey,
+                        Arrays.asList(points).stream()
+                                .map(k -> builder.literal(k))
+                                .collect(Collectors.toList()));
+    }
+
+    @Override
+    public RexNode visitTraversalPredicate_without(
+            GremlinGSParser.TraversalPredicate_withoutContext ctx) {
+        Object[] points = GenericLiteralVisitor.getGenericLiteralList(ctx.genericLiteralList());
+        return builder.not(
+                builder.getRexBuilder()
+                        .makeIn(
+                                propertyKey,
+                                Arrays.asList(points).stream()
+                                        .map(k -> builder.literal(k))
+                                        .collect(Collectors.toList())));
+    }
+
+    @Override
+    public RexNode visitTraversalPredicate_not(GremlinGSParser.TraversalPredicate_notContext ctx) {
+        return builder.not(visitTraversalPredicate(ctx.traversalPredicate()));
+    }
+
+    @Override
+    public RexNode visitTraversalPredicate_inside(
+            GremlinGSParser.TraversalPredicate_insideContext ctx) {
+        Number lower =
+                (Number)
+                        GenericLiteralVisitor.getInstance()
+                                .visitGenericLiteral(ctx.genericLiteral(0));
+        Number upper =
+                (Number)
+                        GenericLiteralVisitor.getInstance()
+                                .visitGenericLiteral(ctx.genericLiteral(1));
+        return builder.getRexBuilder()
+                .makeBetween(
+                        propertyKey,
+                        builder.literal(new BigDecimal(lower.longValue() + 1)),
+                        builder.literal(new BigDecimal(upper.longValue() - 1)));
+    }
+
+    @Override
+    public RexNode visitTraversalPredicate_outside(
+            GremlinGSParser.TraversalPredicate_outsideContext ctx) {
+        Number lower =
+                (Number)
+                        GenericLiteralVisitor.getInstance()
+                                .visitGenericLiteral(ctx.genericLiteral(0));
+        Number upper =
+                (Number)
+                        GenericLiteralVisitor.getInstance()
+                                .visitGenericLiteral(ctx.genericLiteral(1));
+        return builder.not(
+                builder.getRexBuilder()
+                        .makeBetween(
+                                propertyKey,
+                                builder.literal(new BigDecimal(lower.longValue() + 1)),
+                                builder.literal(new BigDecimal(upper.longValue() - 1))));
+    }
+
+    @Override
+    public RexNode visitTraversalPredicate_startingWith(
+            GremlinGSParser.TraversalPredicate_startingWithContext ctx) {
+        String posixRegex = "^" + GenericLiteralVisitor.getStringLiteral(ctx.stringLiteral());
+        return builder.call(
+                GraphStdOperatorTable.POSIX_REGEX_CASE_SENSITIVE,
+                propertyKey,
+                builder.literal(posixRegex));
+    }
+
+    @Override
+    public RexNode visitTraversalPredicate_notStartingWith(
+            GremlinGSParser.TraversalPredicate_notStartingWithContext ctx) {
+        String posixRegex = "^" + GenericLiteralVisitor.getStringLiteral(ctx.stringLiteral());
+        return builder.not(
+                builder.call(
+                        GraphStdOperatorTable.POSIX_REGEX_CASE_SENSITIVE,
+                        propertyKey,
+                        builder.literal(posixRegex)));
+    }
+
+    @Override
+    public RexNode visitTraversalPredicate_endingWith(
+            GremlinGSParser.TraversalPredicate_endingWithContext ctx) {
+        String posixRegex = GenericLiteralVisitor.getStringLiteral(ctx.stringLiteral()) + "$";
+        return builder.call(
+                GraphStdOperatorTable.POSIX_REGEX_CASE_SENSITIVE,
+                propertyKey,
+                builder.literal(posixRegex));
+    }
+
+    @Override
+    public RexNode visitTraversalPredicate_notEndingWith(
+            GremlinGSParser.TraversalPredicate_notEndingWithContext ctx) {
+        String posixRegex = GenericLiteralVisitor.getStringLiteral(ctx.stringLiteral()) + "$";
+        return builder.not(
+                builder.call(
+                        GraphStdOperatorTable.POSIX_REGEX_CASE_SENSITIVE,
+                        propertyKey,
+                        builder.literal(posixRegex)));
+    }
+
+    @Override
+    public RexNode visitTraversalPredicate_containing(
+            GremlinGSParser.TraversalPredicate_containingContext ctx) {
+        String posixRegex =
+                ".*" + GenericLiteralVisitor.getStringLiteral(ctx.stringLiteral()) + ".*";
+        return builder.call(
+                GraphStdOperatorTable.POSIX_REGEX_CASE_SENSITIVE,
+                propertyKey,
+                builder.literal(posixRegex));
+    }
+
+    @Override
+    public RexNode visitTraversalPredicate_notContaining(
+            GremlinGSParser.TraversalPredicate_notContainingContext ctx) {
+        String posixRegex =
+                ".*" + GenericLiteralVisitor.getStringLiteral(ctx.stringLiteral()) + ".*";
+        return builder.not(
+                builder.call(
+                        GraphStdOperatorTable.POSIX_REGEX_CASE_SENSITIVE,
+                        propertyKey,
+                        builder.literal(posixRegex)));
+    }
+}
diff --git a/interactive_engine/compiler/src/main/java/com/alibaba/graphscope/gremlin/antlr4x/visitor/GraphBuilderVisitor.java b/interactive_engine/compiler/src/main/java/com/alibaba/graphscope/gremlin/antlr4x/visitor/GraphBuilderVisitor.java
new file mode 100644
index 000000000000..c6cc194996f8
--- /dev/null
+++ b/interactive_engine/compiler/src/main/java/com/alibaba/graphscope/gremlin/antlr4x/visitor/GraphBuilderVisitor.java
@@ -0,0 +1,1109 @@
+/*
+ * Copyright 2020 Alibaba Group Holding Limited.
+ *
+ * Licensed 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 com.alibaba.graphscope.gremlin.antlr4x.visitor;
+
+import com.alibaba.graphscope.common.ir.rel.GraphLogicalProject;
+import com.alibaba.graphscope.common.ir.rel.graph.GraphLogicalExpand;
+import com.alibaba.graphscope.common.ir.rel.graph.GraphLogicalPathExpand;
+import com.alibaba.graphscope.common.ir.rel.type.group.GraphAggCall;
+import com.alibaba.graphscope.common.ir.rex.RexGraphVariable;
+import com.alibaba.graphscope.common.ir.tools.AliasInference;
+import com.alibaba.graphscope.common.ir.tools.GraphBuilder;
+import com.alibaba.graphscope.common.ir.tools.GraphStdOperatorTable;
+import com.alibaba.graphscope.common.ir.tools.config.*;
+import com.alibaba.graphscope.common.ir.type.GraphProperty;
+import com.alibaba.graphscope.common.ir.type.GraphSchemaType;
+import com.alibaba.graphscope.grammar.GremlinGSBaseVisitor;
+import com.alibaba.graphscope.grammar.GremlinGSParser;
+import com.alibaba.graphscope.gremlin.antlr4.GenericLiteralVisitor;
+import com.alibaba.graphscope.gremlin.antlr4.TraversalEnumParser;
+import com.alibaba.graphscope.gremlin.exception.InvalidGremlinScriptException;
+import com.alibaba.graphscope.gremlin.exception.UnsupportedEvalException;
+import com.google.common.base.Preconditions;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.Lists;
+import com.google.common.collect.Maps;
+
+import org.antlr.v4.runtime.tree.ParseTree;
+import org.apache.calcite.rel.RelNode;
+import org.apache.calcite.rel.core.Aggregate;
+import org.apache.calcite.rel.core.Project;
+import org.apache.calcite.rel.type.RelDataType;
+import org.apache.calcite.rel.type.RelDataTypeField;
+import org.apache.calcite.rex.RexCall;
+import org.apache.calcite.rex.RexNode;
+import org.apache.calcite.tools.RelBuilder;
+import org.apache.commons.lang3.ObjectUtils;
+import org.apache.tinkerpop.gremlin.process.traversal.Order;
+import org.apache.tinkerpop.gremlin.structure.Column;
+import org.apache.tinkerpop.gremlin.structure.T;
+import org.checkerframework.checker.nullness.qual.Nullable;
+import org.javatuples.Pair;
+
+import java.util.Arrays;
+import java.util.List;
+import java.util.Map;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+
+public class GraphBuilderVisitor extends GremlinGSBaseVisitor<GraphBuilder> {
+    private final GraphBuilder builder;
+
+    public GraphBuilderVisitor(GraphBuilder builder) {
+        this.builder = builder;
+    }
+
+    @Override
+    public GraphBuilder visitQuery(GremlinGSParser.QueryContext ctx) {
+        super.visitQuery(ctx);
+        // append tail project to indicate the columns to be output
+        return appendTailProject();
+    }
+
+    @Override
+    public GraphBuilder visitTraversalSourceSpawnMethod_V(
+            GremlinGSParser.TraversalSourceSpawnMethod_VContext ctx) {
+        builder.source(
+                new SourceConfig(
+                        GraphOpt.Source.VERTEX,
+                        new LabelConfig(true),
+                        getNextTag(
+                                new TraversalMethodIterator(
+                                        (GremlinGSParser.TraversalSourceSpawnMethodContext)
+                                                ctx.getParent()))));
+        if (ctx.integerLiteralList() != null) {
+            Object[] ids = GenericLiteralVisitor.getIntegerLiteralList(ctx.integerLiteralList());
+            if (ids.length == 1) {
+                return builder.filter(
+                        builder.call(
+                                GraphStdOperatorTable.EQUALS,
+                                builder.variable(null, GraphProperty.ID_KEY),
+                                builder.literal(ids[0])));
+            } else if (ids.length > 1) {
+                List<RexNode> literals =
+                        Arrays.asList(ids).stream()
+                                .map(k -> builder.literal(k))
+                                .collect(Collectors.toList());
+                return builder.filter(
+                        builder.getRexBuilder()
+                                .makeIn(builder.variable(null, GraphProperty.ID_KEY), literals));
+            }
+        }
+        return builder;
+    }
+
+    @Override
+    public GraphBuilder visitTraversalSourceSpawnMethod_E(
+            GremlinGSParser.TraversalSourceSpawnMethod_EContext ctx) {
+        builder.source(
+                new SourceConfig(
+                        GraphOpt.Source.EDGE,
+                        new LabelConfig(true),
+                        getNextTag(
+                                new TraversalMethodIterator(
+                                        (GremlinGSParser.TraversalSourceSpawnMethodContext)
+                                                ctx.getParent()))));
+        if (ctx.integerLiteralList() != null) {
+            Object[] ids = GenericLiteralVisitor.getIntegerLiteralList(ctx.integerLiteralList());
+            if (ids.length == 1) {
+                return builder.filter(
+                        builder.call(
+                                GraphStdOperatorTable.EQUALS,
+                                builder.variable(null, GraphProperty.ID_KEY),
+                                builder.literal(ids[0])));
+            } else if (ids.length > 1) {
+                List<RexNode> literals =
+                        Arrays.asList(ids).stream()
+                                .map(k -> builder.literal(k))
+                                .collect(Collectors.toList());
+                return builder.filter(
+                        builder.getRexBuilder()
+                                .makeIn(builder.variable(null, GraphProperty.ID_KEY), literals));
+            }
+        }
+        return builder;
+    }
+
+    @Override
+    public GraphBuilder visitTraversalMethod_hasLabel(
+            GremlinGSParser.TraversalMethod_hasLabelContext ctx) {
+        if (ctx.stringLiteral() != null) {
+            String label = GenericLiteralVisitor.getStringLiteral(ctx.stringLiteral());
+            if (ObjectUtils.isEmpty(ctx.stringLiteralList())) {
+                return builder.filter(
+                        builder.call(
+                                GraphStdOperatorTable.EQUALS,
+                                builder.variable(null, GraphProperty.LABEL_KEY),
+                                builder.literal(label)));
+            } else {
+                List<RexNode> labelNodes = Lists.newArrayList(builder.literal(label));
+                String[] otherLabels =
+                        GenericLiteralVisitor.getStringLiteralList(ctx.stringLiteralList());
+                for (String other : otherLabels) {
+                    labelNodes.add(builder.literal(other));
+                }
+                RexNode labelFilters =
+                        builder.getRexBuilder()
+                                .makeIn(
+                                        builder.variable(null, GraphProperty.LABEL_KEY),
+                                        labelNodes);
+                return builder.filter(labelFilters);
+            }
+        }
+        throw new UnsupportedEvalException(
+                ctx.getClass(), "supported pattern is [hasLabel('str')] or hasLabel('str1', ...)");
+    }
+
+    @Override
+    public GraphBuilder visitTraversalMethod_hasId(
+            GremlinGSParser.TraversalMethod_hasIdContext ctx) {
+        Object[] ids =
+                GenericLiteralVisitor.getIntegerLiteralExpr(
+                        ctx.nonEmptyIntegerLiteralList().integerLiteralExpr());
+        if (ids.length == 1) {
+            return builder.filter(
+                    builder.call(
+                            GraphStdOperatorTable.EQUALS,
+                            builder.variable(null, GraphProperty.ID_KEY),
+                            builder.literal(ids[0])));
+        } else if (ids.length > 1) {
+            List<RexNode> idNodes =
+                    Arrays.asList(ids).stream()
+                            .map(k -> builder.literal(k))
+                            .collect(Collectors.toList());
+            RexNode idFilters =
+                    builder.getRexBuilder()
+                            .makeIn(builder.variable(null, GraphProperty.ID_KEY), idNodes);
+            return builder.filter(idFilters);
+        }
+        throw new UnsupportedEvalException(
+                ctx.getClass(), "supported pattern is [hasId(1)] or hasId(1, 2, ...)");
+    }
+
+    @Override
+    public GraphBuilder visitTraversalMethod_has(GremlinGSParser.TraversalMethod_hasContext ctx) {
+        String notice =
+                "supported pattern is [has('key', 'value')] or [has('key', P)] or [has('label',"
+                        + " 'key', 'value')] or [has('label', 'key', P)]";
+        int childCount = ctx.getChildCount();
+        if (childCount == 6 && ctx.genericLiteral() != null) { // g.V().has("name", "marko")
+            String propertyKey = GenericLiteralVisitor.getStringLiteral(ctx.stringLiteral(0));
+            Object propertyValue =
+                    GenericLiteralVisitor.getInstance().visitGenericLiteral(ctx.genericLiteral());
+            return builder.filter(
+                    builder.call(
+                            GraphStdOperatorTable.EQUALS,
+                            builder.variable(null, propertyKey),
+                            builder.literal(propertyValue)));
+        } else if (childCount == 6
+                && ctx.traversalPredicate() != null) { // g.V().has("name", P.eq("marko"))
+            String propertyKey = GenericLiteralVisitor.getStringLiteral(ctx.stringLiteral(0));
+            ExpressionVisitor exprVisitor =
+                    new ExpressionVisitor(this.builder, builder.variable(null, propertyKey));
+            return builder.filter(exprVisitor.visitTraversalPredicate(ctx.traversalPredicate()));
+        } else if (childCount == 8
+                && ctx.genericLiteral() != null) { // g.V().has("person", "name", "marko")
+            String labelValue = GenericLiteralVisitor.getStringLiteral(ctx.stringLiteral(0));
+            String propertyKey = GenericLiteralVisitor.getStringLiteral(ctx.stringLiteral(1));
+            Object propertyValue =
+                    GenericLiteralVisitor.getInstance().visitGenericLiteral(ctx.genericLiteral());
+            return builder.filter(
+                    builder.call(
+                            GraphStdOperatorTable.AND,
+                            builder.call(
+                                    GraphStdOperatorTable.EQUALS,
+                                    builder.variable(null, GraphProperty.LABEL_KEY),
+                                    builder.literal(labelValue)),
+                            builder.call(
+                                    GraphStdOperatorTable.EQUALS,
+                                    builder.variable(null, propertyKey),
+                                    builder.literal(propertyValue))));
+        } else if (childCount == 8
+                && ctx.traversalPredicate() != null) { // g.V().has("person", "name", P.eq("marko"))
+            String labelValue = GenericLiteralVisitor.getStringLiteral(ctx.stringLiteral(0));
+            String propertyKey = GenericLiteralVisitor.getStringLiteral(ctx.stringLiteral(1));
+            ExpressionVisitor exprVisitor =
+                    new ExpressionVisitor(this.builder, builder.variable(null, propertyKey));
+            return builder.filter(
+                    builder.call(
+                            GraphStdOperatorTable.AND,
+                            builder.call(
+                                    GraphStdOperatorTable.EQUALS,
+                                    builder.variable(null, GraphProperty.LABEL_KEY),
+                                    builder.literal(labelValue)),
+                            exprVisitor.visitTraversalPredicate(ctx.traversalPredicate())));
+        } else if (childCount == 4 && ctx.stringLiteral() != null) { // g.V().has("name")
+            String propertyKey = GenericLiteralVisitor.getStringLiteral(ctx.stringLiteral(0));
+            return builder.filter(
+                    builder.call(
+                            GraphStdOperatorTable.IS_NOT_NULL,
+                            builder.variable(null, propertyKey)));
+        } else {
+            throw new UnsupportedEvalException(ctx.getClass(), notice);
+        }
+    }
+
+    @Override
+    public GraphBuilder visitTraversalMethod_hasNot(
+            GremlinGSParser.TraversalMethod_hasNotContext ctx) {
+        // g.V().hasNot("name")
+        String propertyKey = GenericLiteralVisitor.getStringLiteral(ctx.stringLiteral());
+        return builder.filter(
+                builder.call(GraphStdOperatorTable.IS_NULL, builder.variable(null, propertyKey)));
+    }
+
+    @Override
+    public GraphBuilder visitTraversalMethod_outE(GremlinGSParser.TraversalMethod_outEContext ctx) {
+        builder.expand(
+                new ExpandConfig(
+                        GraphOpt.Expand.OUT,
+                        getLabelConfig(ctx.stringLiteralList()),
+                        getNextTag(
+                                new TraversalMethodIterator(
+                                        (GremlinGSParser.TraversalMethodContext)
+                                                ctx.getParent()))));
+        if (ctx.traversalMethod_inV() != null) {
+            visitTraversalMethod_inV(ctx.traversalMethod_inV());
+        }
+        return builder;
+    }
+
+    @Override
+    public GraphBuilder visitTraversalMethod_inE(GremlinGSParser.TraversalMethod_inEContext ctx) {
+        builder.expand(
+                new ExpandConfig(
+                        GraphOpt.Expand.IN,
+                        getLabelConfig(ctx.stringLiteralList()),
+                        getNextTag(
+                                new TraversalMethodIterator(
+                                        (GremlinGSParser.TraversalMethodContext)
+                                                ctx.getParent()))));
+        if (ctx.traversalMethod_outV() != null) {
+            visitTraversalMethod_outV(ctx.traversalMethod_outV());
+        }
+        return builder;
+    }
+
+    @Override
+    public GraphBuilder visitTraversalMethod_bothE(
+            GremlinGSParser.TraversalMethod_bothEContext ctx) {
+        builder.expand(
+                new ExpandConfig(
+                        GraphOpt.Expand.BOTH,
+                        getLabelConfig(ctx.stringLiteralList()),
+                        getNextTag(
+                                new TraversalMethodIterator(
+                                        (GremlinGSParser.TraversalMethodContext)
+                                                ctx.getParent()))));
+        if (ctx.traversalMethod_otherV() != null) {
+            visitTraversalMethod_otherV(ctx.traversalMethod_otherV());
+        }
+        return builder;
+    }
+
+    @Override
+    public GraphBuilder visitTraversalMethod_outV(GremlinGSParser.TraversalMethod_outVContext ctx) {
+        ParseTree parent = ctx.getParent();
+        if (parent instanceof GremlinGSParser.TraversalMethod_inEContext) {
+            parent = parent.getParent();
+        }
+        return builder.getV(
+                new GetVConfig(
+                        GraphOpt.GetV.START,
+                        new LabelConfig(true),
+                        getNextTag(
+                                new TraversalMethodIterator(
+                                        (GremlinGSParser.TraversalMethodContext) parent))));
+    }
+
+    @Override
+    public GraphBuilder visitTraversalMethod_inV(GremlinGSParser.TraversalMethod_inVContext ctx) {
+        ParseTree parent = ctx.getParent();
+        if (parent instanceof GremlinGSParser.TraversalMethod_outEContext) {
+            parent = parent.getParent();
+        }
+        return builder.getV(
+                new GetVConfig(
+                        GraphOpt.GetV.END,
+                        new LabelConfig(true),
+                        getNextTag(
+                                new TraversalMethodIterator(
+                                        (GremlinGSParser.TraversalMethodContext) parent))));
+    }
+
+    @Override
+    public GraphBuilder visitTraversalMethod_otherV(
+            GremlinGSParser.TraversalMethod_otherVContext ctx) {
+        ParseTree parent = ctx.getParent();
+        if (parent instanceof GremlinGSParser.TraversalMethod_bothEContext) {
+            parent = parent.getParent();
+        }
+        return builder.getV(
+                new GetVConfig(
+                        GraphOpt.GetV.OTHER,
+                        new LabelConfig(true),
+                        getNextTag(
+                                new TraversalMethodIterator(
+                                        (GremlinGSParser.TraversalMethodContext) parent))));
+    }
+
+    @Override
+    public GraphBuilder visitTraversalMethod_endV(GremlinGSParser.TraversalMethod_endVContext ctx) {
+        RelNode peek = builder.peek();
+        if (peek instanceof GraphLogicalPathExpand) {
+            GraphLogicalPathExpand pathExpand = (GraphLogicalPathExpand) peek;
+            GraphLogicalExpand expand = (GraphLogicalExpand) pathExpand.getExpand();
+            String tag =
+                    getNextTag(
+                            new TraversalMethodIterator(
+                                    (GremlinGSParser.TraversalMethodContext) ctx.getParent()));
+            switch (expand.getOpt()) {
+                case OUT:
+                    return builder.getV(
+                            new GetVConfig(GraphOpt.GetV.END, new LabelConfig(true), tag));
+                case IN:
+                    return builder.getV(
+                            new GetVConfig(GraphOpt.GetV.START, new LabelConfig(true), tag));
+                case BOTH:
+                default:
+                    return builder.getV(
+                            new GetVConfig(GraphOpt.GetV.OTHER, new LabelConfig(true), tag));
+            }
+        }
+        throw new InvalidGremlinScriptException("endV should follow with path expand");
+    }
+
+    @Override
+    public GraphBuilder visitTraversalMethod_out(GremlinGSParser.TraversalMethod_outContext ctx) {
+        if (pathExpandPattern(ctx.stringLiteralList())) {
+            return builder.pathExpand(
+                    new PathExpandBuilderVisitor(this).visitTraversalMethod_out(ctx).build());
+        } else {
+            return builder.expand(
+                            new ExpandConfig(
+                                    GraphOpt.Expand.OUT, getLabelConfig(ctx.stringLiteralList())))
+                    .getV(
+                            new GetVConfig(
+                                    GraphOpt.GetV.END,
+                                    new LabelConfig(true),
+                                    getNextTag(
+                                            new TraversalMethodIterator(
+                                                    (GremlinGSParser.TraversalMethodContext)
+                                                            ctx.getParent()))));
+        }
+    }
+
+    @Override
+    public GraphBuilder visitTraversalMethod_in(GremlinGSParser.TraversalMethod_inContext ctx) {
+        if (pathExpandPattern(ctx.stringLiteralList())) {
+            return builder.pathExpand(
+                    new PathExpandBuilderVisitor(this).visitTraversalMethod_in(ctx).build());
+        } else {
+            return builder.expand(
+                            new ExpandConfig(
+                                    GraphOpt.Expand.IN, getLabelConfig(ctx.stringLiteralList())))
+                    .getV(
+                            new GetVConfig(
+                                    GraphOpt.GetV.START,
+                                    new LabelConfig(true),
+                                    getNextTag(
+                                            new TraversalMethodIterator(
+                                                    (GremlinGSParser.TraversalMethodContext)
+                                                            ctx.getParent()))));
+        }
+    }
+
+    @Override
+    public GraphBuilder visitTraversalMethod_both(GremlinGSParser.TraversalMethod_bothContext ctx) {
+        if (pathExpandPattern(ctx.stringLiteralList())) {
+            return builder.pathExpand(
+                    new PathExpandBuilderVisitor(this).visitTraversalMethod_both(ctx).build());
+        } else {
+            return builder.expand(
+                            new ExpandConfig(
+                                    GraphOpt.Expand.BOTH, getLabelConfig(ctx.stringLiteralList())))
+                    .getV(
+                            new GetVConfig(
+                                    GraphOpt.GetV.OTHER,
+                                    new LabelConfig(true),
+                                    getNextTag(
+                                            new TraversalMethodIterator(
+                                                    (GremlinGSParser.TraversalMethodContext)
+                                                            ctx.getParent()))));
+        }
+    }
+
+    @Override
+    public GraphBuilder visitTraversalMethod_with(GremlinGSParser.TraversalMethod_withContext ctx) {
+        return builder;
+    }
+
+    @Override
+    public GraphBuilder visitTraversalMethod_as(GremlinGSParser.TraversalMethod_asContext ctx) {
+        return builder;
+    }
+
+    @Override
+    public GraphBuilder visitTraversalMethod_valueMap(
+            GremlinGSParser.TraversalMethod_valueMapContext ctx) {
+        RexNode expr =
+                builder.call(
+                        GraphStdOperatorTable.MAP_VALUE_CONSTRUCTOR,
+                        getProperties(ctx, null).stream()
+                                .flatMap(
+                                        k ->
+                                                Stream.of(
+                                                        builder.literal(k),
+                                                        builder.variable(null, k)))
+                                .collect(Collectors.toList()));
+        String tag =
+                getNextTag(
+                        new TraversalMethodIterator(
+                                (GremlinGSParser.TraversalMethodContext) ctx.getParent()));
+        return builder.project(
+                ImmutableList.of(expr),
+                tag == null ? ImmutableList.of() : ImmutableList.of(tag),
+                true);
+    }
+
+    @Override
+    public GraphBuilder visitTraversalMethod_values(
+            GremlinGSParser.TraversalMethod_valuesContext ctx) {
+        if (ctx.getChildCount() == 4 && ctx.stringLiteral() != null) {
+            RexNode expr =
+                    builder.variable(
+                            null, GenericLiteralVisitor.getStringLiteral(ctx.stringLiteral()));
+            String tag =
+                    (ctx.getParent() instanceof GremlinGSParser.TraversalMethodContext)
+                            ? getNextTag(
+                                    new TraversalMethodIterator(
+                                            (GremlinGSParser.TraversalMethodContext)
+                                                    ctx.getParent()))
+                            : null;
+            return builder.project(
+                    ImmutableList.of(expr),
+                    tag == null ? ImmutableList.of() : ImmutableList.of(tag),
+                    true);
+        }
+        throw new UnsupportedEvalException(ctx.getClass(), "supported pattern is [values('..')]");
+    }
+
+    @Override
+    public GraphBuilder visitTraversalMethod_elementMap(
+            GremlinGSParser.TraversalMethod_elementMapContext ctx) {
+        RexNode expr =
+                builder.call(
+                        GraphStdOperatorTable.MAP_VALUE_CONSTRUCTOR,
+                        getProperties(ctx, null).stream()
+                                .flatMap(
+                                        k ->
+                                                Stream.of(
+                                                        builder.literal(k),
+                                                        builder.variable(null, k)))
+                                .collect(Collectors.toList()));
+        String tag =
+                getNextTag(
+                        new TraversalMethodIterator(
+                                (GremlinGSParser.TraversalMethodContext) ctx.getParent()));
+        return builder.project(
+                ImmutableList.of(expr),
+                tag == null ? ImmutableList.of() : ImmutableList.of(tag),
+                true);
+    }
+
+    @Override
+    public GraphBuilder visitTraversalMethod_select(
+            GremlinGSParser.TraversalMethod_selectContext ctx) {
+        String tag =
+                (ctx.getParent() instanceof GremlinGSParser.TraversalMethodContext)
+                        ? getNextTag(
+                                new TraversalMethodIterator(
+                                        (GremlinGSParser.TraversalMethodContext) ctx.getParent()))
+                        : null;
+        RexNode expr;
+        if (ctx.stringLiteral() != null) {
+            List<String> selectTags =
+                    Lists.newArrayList(GenericLiteralVisitor.getStringLiteral(ctx.stringLiteral()));
+            if (ctx.stringLiteralList() != null) {
+                String[] tags = GenericLiteralVisitor.getStringLiteralList(ctx.stringLiteralList());
+                selectTags.addAll(Arrays.asList(tags));
+            }
+            GremlinGSParser.TraversalMethod_selectby_listContext listCtx =
+                    ctx.traversalMethod_selectby_list();
+            List<GremlinGSParser.TraversalMethod_selectbyContext> byCtxs =
+                    listCtx == null
+                            ? ImmutableList.of()
+                            : listCtx.getRuleContexts(
+                                    GremlinGSParser.TraversalMethod_selectbyContext.class);
+            Map<String, RexNode> keyValueMap = Maps.newLinkedHashMap();
+            for (int i = 0; i < selectTags.size(); ++i) {
+                String selectTag = selectTags.get(i);
+                keyValueMap.put(selectTag, convertSelectByCtx(byCtxs, i, selectTag));
+            }
+            Preconditions.checkArgument(
+                    !keyValueMap.isEmpty(), "keyValue should not be empty in select");
+
+            if (keyValueMap.size() == 1) {
+                expr = keyValueMap.entrySet().iterator().next().getValue();
+            } else {
+                List<RexNode> mapParameters = Lists.newArrayList();
+                keyValueMap.forEach(
+                        (k, v) -> {
+                            mapParameters.add(builder.literal(k));
+                            mapParameters.add(v);
+                        });
+                expr = builder.call(GraphStdOperatorTable.MAP_VALUE_CONSTRUCTOR, mapParameters);
+            }
+        } else if (ctx.traversalColumn() != null) {
+            Column column =
+                    TraversalEnumParser.parseTraversalEnumFromContext(
+                            Column.class, ctx.traversalColumn());
+            expr = builder.variable(column.name());
+        } else {
+            throw new UnsupportedEvalException(
+                    GremlinGSParser.TraversalMethod_selectbyContext.class,
+                    ctx.getText() + " is unsupported yet");
+        }
+        return builder.project(
+                ImmutableList.of(expr),
+                tag == null ? ImmutableList.of() : ImmutableList.of(tag),
+                true);
+    }
+
+    @Override
+    public GraphBuilder visitTraversalMethod_order(
+            GremlinGSParser.TraversalMethod_orderContext ctx) {
+        GremlinGSParser.TraversalMethod_orderby_listContext listCtx =
+                ctx.traversalMethod_orderby_list();
+        List<GremlinGSParser.TraversalMethod_orderbyContext> byCtxs =
+                listCtx == null
+                        ? ImmutableList.of()
+                        : listCtx.getRuleContexts(
+                                GremlinGSParser.TraversalMethod_orderbyContext.class);
+        List<RexNode> exprs = Lists.newArrayList();
+        if (byCtxs.isEmpty()) {
+            exprs.add(builder.variable((String) null));
+        } else {
+            for (GremlinGSParser.TraversalMethod_orderbyContext byCtx : byCtxs) {
+                List<RexNode> byExprs = convertOrderByCtx(byCtx);
+                Order orderOpt = Order.asc;
+                if (byCtx.traversalOrder() != null) {
+                    orderOpt =
+                            TraversalEnumParser.parseTraversalEnumFromContext(
+                                    Order.class, byCtx.traversalOrder());
+                }
+                for (RexNode expr : byExprs) {
+                    if (orderOpt == Order.desc) {
+                        exprs.add(builder.desc(expr));
+                    } else if (orderOpt == Order.asc) {
+                        exprs.add(expr);
+                    }
+                }
+            }
+        }
+        return builder.sortLimit(null, null, exprs);
+    }
+
+    @Override
+    public GraphBuilder visitTraversalMethod_limit(
+            GremlinGSParser.TraversalMethod_limitContext ctx) {
+        Number limit =
+                (Number)
+                        GenericLiteralVisitor.getInstance()
+                                .visitIntegerLiteral(ctx.integerLiteral());
+        return (GraphBuilder) builder.limit(0, limit.intValue());
+    }
+
+    @Override
+    public GraphBuilder visitTraversalMethod_group(
+            GremlinGSParser.TraversalMethod_groupContext ctx) {
+        return builder.aggregate(
+                convertGroupKeyBy(ctx.traversalMethod_group_keyby()),
+                convertGroupValueBy(ctx.traversalMethod_group_valueby()));
+    }
+
+    @Override
+    public GraphBuilder visitTraversalMethod_groupCount(
+            GremlinGSParser.TraversalMethod_groupCountContext ctx) {
+        return (GraphBuilder)
+                builder.aggregate(
+                        convertGroupKeyBy(ctx.traversalMethod_group_keyby()),
+                        builder.count(
+                                false, Column.values.name(), builder.variable((String) null)));
+    }
+
+    @Override
+    public GraphBuilder visitTraversalMethod_count(
+            GremlinGSParser.TraversalMethod_countContext ctx) {
+        ParseTree aggCtx = ctx.getParent();
+        String alias =
+                aggCtx != null
+                                && aggCtx.getParent()
+                                        instanceof GremlinGSParser.TraversalMethodContext
+                        ? getNextTag(
+                                new TraversalMethodIterator(
+                                        (GremlinGSParser.TraversalMethodContext)
+                                                aggCtx.getParent()))
+                        : null;
+        return (GraphBuilder) builder.aggregate(builder.groupKey(), builder.countStar(alias));
+    }
+
+    @Override
+    public GraphBuilder visitTraversalMethod_fold(GremlinGSParser.TraversalMethod_foldContext ctx) {
+        ParseTree aggCtx = ctx.getParent();
+        String alias =
+                aggCtx != null
+                                && aggCtx.getParent()
+                                        instanceof GremlinGSParser.TraversalMethodContext
+                        ? getNextTag(
+                                new TraversalMethodIterator(
+                                        (GremlinGSParser.TraversalMethodContext)
+                                                aggCtx.getParent()))
+                        : null;
+        return (GraphBuilder) builder.aggregate(builder.groupKey(), builder.collect(false, alias));
+    }
+
+    @Override
+    public GraphBuilder visitTraversalMethod_sum(GremlinGSParser.TraversalMethod_sumContext ctx) {
+        ParseTree aggCtx = ctx.getParent();
+        String alias =
+                aggCtx != null
+                                && aggCtx.getParent()
+                                        instanceof GremlinGSParser.TraversalMethodContext
+                        ? getNextTag(
+                                new TraversalMethodIterator(
+                                        (GremlinGSParser.TraversalMethodContext)
+                                                aggCtx.getParent()))
+                        : null;
+        return (GraphBuilder)
+                builder.aggregate(
+                        builder.groupKey(),
+                        builder.sum(false, alias, builder.variable((String) null)));
+    }
+
+    @Override
+    public GraphBuilder visitTraversalMethod_min(GremlinGSParser.TraversalMethod_minContext ctx) {
+        ParseTree aggCtx = ctx.getParent();
+        String alias =
+                aggCtx != null
+                                && aggCtx.getParent()
+                                        instanceof GremlinGSParser.TraversalMethodContext
+                        ? getNextTag(
+                                new TraversalMethodIterator(
+                                        (GremlinGSParser.TraversalMethodContext)
+                                                aggCtx.getParent()))
+                        : null;
+        return (GraphBuilder)
+                builder.aggregate(
+                        builder.groupKey(), builder.min(alias, builder.variable((String) null)));
+    }
+
+    @Override
+    public GraphBuilder visitTraversalMethod_max(GremlinGSParser.TraversalMethod_maxContext ctx) {
+        ParseTree aggCtx = ctx.getParent();
+        String alias =
+                aggCtx != null
+                                && aggCtx.getParent()
+                                        instanceof GremlinGSParser.TraversalMethodContext
+                        ? getNextTag(
+                                new TraversalMethodIterator(
+                                        (GremlinGSParser.TraversalMethodContext)
+                                                aggCtx.getParent()))
+                        : null;
+        return (GraphBuilder)
+                builder.aggregate(
+                        builder.groupKey(), builder.max(alias, builder.variable((String) null)));
+    }
+
+    @Override
+    public GraphBuilder visitTraversalMethod_mean(GremlinGSParser.TraversalMethod_meanContext ctx) {
+        ParseTree aggCtx = ctx.getParent();
+        String alias =
+                aggCtx != null
+                                && aggCtx.getParent()
+                                        instanceof GremlinGSParser.TraversalMethodContext
+                        ? getNextTag(
+                                new TraversalMethodIterator(
+                                        (GremlinGSParser.TraversalMethodContext)
+                                                aggCtx.getParent()))
+                        : null;
+        return (GraphBuilder)
+                builder.aggregate(
+                        builder.groupKey(),
+                        builder.avg(false, alias, builder.variable((String) null)));
+    }
+
+    @Override
+    public GraphBuilder visitTraversalMethod_dedup(
+            GremlinGSParser.TraversalMethod_dedupContext ctx) {
+        String[] tagArray = GenericLiteralVisitor.getStringLiteralList(ctx.stringLiteralList());
+        List<String> dedupTags = Lists.newArrayList();
+        if (tagArray.length == 0) {
+            dedupTags.add(null);
+        } else {
+            for (String tag : tagArray) {
+                dedupTags.add(tag);
+            }
+        }
+        List<RexNode> dedupByKeys =
+                dedupTags.stream()
+                        .map(k -> convertDedupByCtx(ctx.traversalMethod_dedupby(), k))
+                        .collect(Collectors.toList());
+        return builder.dedupBy(dedupByKeys);
+    }
+
+    @Override
+    public GraphBuilder visitTraversalMethod_where(
+            GremlinGSParser.TraversalMethod_whereContext ctx) {
+        WherePredicateVisitor.Ring whereByRing =
+                new WherePredicateVisitor.Ring(ctx.traversalMethod_whereby_list());
+        if (ctx.stringLiteral() != null && ctx.traversalPredicate() != null) {
+            return builder.filter(
+                    new WherePredicateVisitor(
+                                    builder,
+                                    GenericLiteralVisitor.getStringLiteral(ctx.stringLiteral()),
+                                    whereByRing)
+                            .visitTraversalPredicate(ctx.traversalPredicate()));
+        } else if (ctx.traversalPredicate() != null) {
+            return builder.filter(
+                    new WherePredicateVisitor(builder, null, whereByRing)
+                            .visitTraversalPredicate(ctx.traversalPredicate()));
+        }
+        throw new UnsupportedEvalException(ctx.getClass(), ctx.getText() + " is unsupported");
+    }
+
+    @Override
+    public GraphBuilder visitTraversalMethod_is(GremlinGSParser.TraversalMethod_isContext ctx) {
+        if (ctx.genericLiteral() != null) {
+            return builder.filter(
+                    builder.equals(
+                            builder.variable((String) null),
+                            builder.literal(
+                                    GenericLiteralVisitor.getInstance()
+                                            .visitGenericLiteral(ctx.genericLiteral()))));
+        } else if (ctx.traversalPredicate() != null) {
+            return builder.filter(
+                    new ExpressionVisitor(builder, builder.variable((String) null))
+                            .visitTraversalPredicate(ctx.traversalPredicate()));
+        }
+        throw new UnsupportedEvalException(ctx.getClass(), ctx.getText() + " is unsupported");
+    }
+
+    @Override
+    public GraphBuilder visitTraversalMethod_label(
+            GremlinGSParser.TraversalMethod_labelContext ctx) {
+        String tag =
+                getNextTag(
+                        new TraversalMethodIterator(
+                                (GremlinGSParser.TraversalMethodContext) ctx.getParent()));
+        return builder.project(
+                ImmutableList.of(builder.variable(null, T.label.getAccessor())),
+                tag == null ? ImmutableList.of() : ImmutableList.of(tag),
+                true);
+    }
+
+    @Override
+    public GraphBuilder visitTraversalMethod_id(GremlinGSParser.TraversalMethod_idContext ctx) {
+        String tag =
+                getNextTag(
+                        new TraversalMethodIterator(
+                                (GremlinGSParser.TraversalMethodContext) ctx.getParent()));
+        return builder.project(
+                ImmutableList.of(builder.variable(null, T.id.getAccessor())),
+                tag == null ? ImmutableList.of() : ImmutableList.of(tag),
+                true);
+    }
+
+    public GraphBuilder getGraphBuilder() {
+        return this.builder;
+    }
+
+    private RelBuilder.GroupKey convertGroupKeyBy(
+            GremlinGSParser.TraversalMethod_group_keybyContext keyCtx) {
+        String defaultAlias = Column.keys.name();
+        if (keyCtx != null) {
+            if (keyCtx.stringLiteral() != null) {
+                return builder.groupKey(
+                        ImmutableList.of(
+                                builder.variable(
+                                        null,
+                                        GenericLiteralVisitor.getStringLiteral(
+                                                keyCtx.stringLiteral()))),
+                        ImmutableList.of(defaultAlias));
+            } else if (keyCtx.nonStringKeyByList() != null) {
+                List<RexNode> exprs = Lists.newArrayList();
+                List<@Nullable String> aliases = Lists.newArrayList();
+                for (int i = 0; i < keyCtx.nonStringKeyByList().getChildCount(); ++i) {
+                    GremlinGSParser.NonStringKeyByContext byCtx =
+                            keyCtx.nonStringKeyByList().nonStringKeyBy(i);
+                    if (byCtx == null) continue;
+                    Pair<RexNode, @Nullable String> exprWithAlias =
+                            Utils.convertExprToPair(
+                                    new NestedTraversalVisitor(this.builder, null)
+                                            .visitNestedTraversal(byCtx.nestedTraversal()));
+                    exprs.add(exprWithAlias.getValue0());
+                    String alias = exprWithAlias.getValue1();
+                    aliases.add(alias == AliasInference.DEFAULT_NAME ? null : alias);
+                }
+                if (exprs.size() == 1) {
+                    if (aliases.isEmpty()) {
+                        aliases.add(defaultAlias);
+                    } else if (aliases.get(0) == null) {
+                        aliases.set(0, defaultAlias);
+                    }
+                }
+                return builder.groupKey(exprs, aliases);
+            }
+        }
+        return builder.groupKey(
+                ImmutableList.of(builder.variable((String) null)), ImmutableList.of(defaultAlias));
+    }
+
+    private List<RelBuilder.AggCall> convertGroupValueBy(
+            GremlinGSParser.TraversalMethod_group_valuebyContext valueCtx) {
+        String defaultAlias = Column.values.name();
+        if (valueCtx != null) {
+            if (valueCtx.stringLiteral() != null) {
+                return ImmutableList.of(
+                        builder.collect(
+                                false,
+                                defaultAlias,
+                                builder.variable(
+                                        null,
+                                        GenericLiteralVisitor.getStringLiteral(
+                                                valueCtx.stringLiteral()))));
+            } else if (valueCtx.nonStringValueByList() != null) {
+                List<RelBuilder.AggCall> aggCalls = Lists.newArrayList();
+                for (int i = 0; i < valueCtx.nonStringValueByList().getChildCount(); ++i) {
+                    GremlinGSParser.NonStringValueByContext byCtx =
+                            valueCtx.nonStringValueByList().nonStringValueBy(i);
+                    if (byCtx == null) continue;
+                    aggCalls.add(
+                            new NonStringValueByVisitor(this.builder).visitNonStringValueBy(byCtx));
+                }
+                if (aggCalls.size() == 1 && ((GraphAggCall) aggCalls.get(0)).getAlias() == null) {
+                    aggCalls.set(0, ((GraphAggCall) aggCalls.get(0)).as(defaultAlias));
+                }
+                return aggCalls;
+            }
+        }
+        return ImmutableList.of(
+                builder.collect(false, defaultAlias, builder.variable((String) null)));
+    }
+
+    private RexNode convertDedupByCtx(
+            GremlinGSParser.TraversalMethod_dedupbyContext byCtx, @Nullable String tag) {
+        if (byCtx == null) {
+            return builder.variable(tag);
+        } else if (byCtx.stringLiteral() != null) {
+            return builder.variable(
+                    tag, GenericLiteralVisitor.getStringLiteral(byCtx.stringLiteral()));
+        } else if (byCtx.traversalToken() != null) {
+            T token =
+                    TraversalEnumParser.parseTraversalEnumFromContext(
+                            T.class, byCtx.traversalToken());
+            return builder.variable(tag, token.getAccessor());
+        } else if (byCtx.nestedTraversal() != null) {
+            RexNode rex =
+                    Utils.convertExprToPair(
+                                    new NestedTraversalVisitor(this.builder, tag)
+                                            .visitNestedTraversal(byCtx.nestedTraversal()))
+                            .getValue0();
+            if (rex instanceof RexCall) {
+                throw new UnsupportedEvalException(
+                        byCtx.nestedTraversal().getClass(),
+                        "rex " + rex + " is unsupported yet in dedup by");
+            }
+            return rex;
+        } else {
+            throw new UnsupportedEvalException(
+                    byCtx.getClass(), byCtx.getText() + " is unsupported yet");
+        }
+    }
+
+    private List<RexNode> convertOrderByCtx(GremlinGSParser.TraversalMethod_orderbyContext byCtx) {
+        List<RexNode> exprs = Lists.newArrayList();
+        if (byCtx.stringLiteral() != null) {
+            exprs.add(
+                    builder.variable(
+                            null, GenericLiteralVisitor.getStringLiteral(byCtx.stringLiteral())));
+        } else if (byCtx.traversalMethod_values() != null
+                || byCtx.traversalMethod_select() != null) {
+            RelNode project =
+                    (byCtx.traversalMethod_values() != null)
+                            ? visitTraversalMethod_values(byCtx.traversalMethod_values()).build()
+                            : visitTraversalMethod_select(byCtx.traversalMethod_select()).build();
+            Preconditions.checkArgument(
+                    project instanceof Project, "rel=%s has invalid class type", project);
+            builder.push(((Project) project).getInput());
+            exprs.addAll(((Project) project).getProjects());
+        } else if (byCtx.nestedTraversal() != null) {
+            RexNode rex =
+                    Utils.convertExprToPair(
+                                    new NestedTraversalVisitor(this.builder, null)
+                                            .visitNestedTraversal(byCtx.nestedTraversal()))
+                            .getValue0();
+            // todo: RexCall need to be computed in advance which will change the current head
+            if (rex instanceof RexCall) {
+                throw new UnsupportedEvalException(
+                        byCtx.nestedTraversal().getClass(),
+                        "rex " + rex + " is unsupported yet in order by");
+            }
+            exprs.add(rex);
+        } else {
+            exprs.add(builder.variable((String) null));
+        }
+        return exprs;
+    }
+
+    private RexNode convertSelectByCtx(
+            List<GremlinGSParser.TraversalMethod_selectbyContext> byCtxs, int i, String tag) {
+        int ctxCnt = byCtxs.size();
+        if (ctxCnt == 0) {
+            return builder.variable(tag);
+        }
+        GremlinGSParser.TraversalMethod_selectbyContext byCtx = byCtxs.get(i % ctxCnt);
+        int byChildCount = byCtx.getChildCount();
+        if (byChildCount == 3) { // select(..).by()
+            return builder.variable(tag);
+        } else if (byChildCount == 4 && byCtx.stringLiteral() != null) { // select(..).by('name')
+            return builder.variable(
+                    tag, GenericLiteralVisitor.getStringLiteral(byCtx.stringLiteral()));
+        } else if (byChildCount == 4
+                && byCtx.traversalToken() != null) { // select(..).by(T.label/T.id)
+            T token =
+                    TraversalEnumParser.parseTraversalEnumFromContext(
+                            T.class, byCtx.traversalToken());
+            return builder.variable(tag, token.getAccessor());
+        } else if (byCtx.traversalMethod_valueMap() != null) { // select(..).by(valueMap('name'))
+            return builder.call(
+                    GraphStdOperatorTable.MAP_VALUE_CONSTRUCTOR,
+                    getProperties(byCtx.traversalMethod_valueMap(), tag).stream()
+                            .flatMap(k -> Stream.of(builder.literal(k), builder.variable(tag, k)))
+                            .collect(Collectors.toList()));
+        } else if (byCtx.traversalMethod_elementMap()
+                != null) { // select(..).by(elementMap('name'))
+            return builder.call(
+                    GraphStdOperatorTable.MAP_VALUE_CONSTRUCTOR,
+                    getProperties(byCtx.traversalMethod_elementMap(), tag).stream()
+                            .flatMap(k -> Stream.of(builder.literal(k), builder.variable(tag, k)))
+                            .collect(Collectors.toList()));
+        } else if (byCtx.nestedTraversal() != null) {
+            return Utils.convertExprToPair(
+                            (new NestedTraversalVisitor(this.builder, tag))
+                                    .visitNestedTraversal(byCtx.nestedTraversal()))
+                    .getValue0();
+        }
+        throw new UnsupportedEvalException(
+                GremlinGSParser.TraversalMethod_selectbyContext.class,
+                byCtx.getText() + " is unsupported yet in select");
+    }
+
+    private boolean pathExpandPattern(GremlinGSParser.StringLiteralListContext ctx) {
+        String[] labels = GenericLiteralVisitor.getStringLiteralList(ctx);
+        return labels != null && labels.length > 0 && rangeExpression(labels[0]);
+    }
+
+    private boolean rangeExpression(String label) {
+        return label.matches("^\\d+\\.\\.\\d+");
+    }
+
+    private LabelConfig getLabelConfig(GremlinGSParser.StringLiteralListContext ctx) {
+        String[] labels = GenericLiteralVisitor.getStringLiteralList(ctx);
+        if (labels == null || labels.length == 0) {
+            return new LabelConfig(true);
+        } else {
+            LabelConfig labelConfig = new LabelConfig(false);
+            for (int i = 0; i < labels.length; ++i) {
+                labelConfig.addLabel(labels[i]);
+            }
+            return labelConfig;
+        }
+    }
+
+    private List<String> getProperties(
+            GremlinGSParser.TraversalMethod_valueMapContext ctx, @Nullable String tag) {
+        String[] properties = GenericLiteralVisitor.getStringLiteralList(ctx.stringLiteralList());
+        return (properties == null || properties.length == 0)
+                ? getAllProperties(tag)
+                : Arrays.asList(properties);
+    }
+
+    private List<String> getProperties(
+            GremlinGSParser.TraversalMethod_elementMapContext ctx, @Nullable String tag) {
+        String[] properties = GenericLiteralVisitor.getStringLiteralList(ctx.stringLiteralList());
+        List<String> propertyList =
+                Lists.newArrayList(GraphProperty.LABEL_KEY, GraphProperty.ID_KEY);
+        if (properties == null || properties.length == 0) {
+            propertyList.addAll(getAllProperties(tag));
+        } else {
+            propertyList.addAll(Arrays.asList(properties));
+        }
+        return propertyList;
+    }
+
+    private List<String> getAllProperties(@Nullable String tag) {
+        RexGraphVariable curVar = builder.variable(tag);
+        RelDataType dataType = curVar.getType();
+        Preconditions.checkArgument(
+                dataType instanceof GraphSchemaType, "can not get property from type=", dataType);
+        return dataType.getFieldList().stream().map(k -> k.getName()).collect(Collectors.toList());
+    }
+
+    protected @Nullable String getNextTag(TraversalMethodIterator methodIterator) {
+        List<String> tags = Lists.newArrayList();
+        while (methodIterator.hasNext()) {
+            GremlinGSParser.TraversalMethodContext next = methodIterator.next();
+            if (next.traversalMethod_as() != null) {
+                tags.add(
+                        GenericLiteralVisitor.getStringLiteral(
+                                next.traversalMethod_as().stringLiteral()));
+            } else if (next.traversalMethod_has() != null
+                    || next.traversalMethod_hasId() != null
+                    || next.traversalMethod_hasLabel() != null
+                    || next.traversalMethod_hasNot() != null
+                    || next.traversalMethod_is() != null
+                    || next.traversalMethod_where() != null
+                    || next.traversalMethod_not() != null
+                    || next.traversalMethod_identity() != null
+                    || next.traversalMethod_limit() != null
+                    || next.traversalMethod_order() != null
+                    || next.traversalMethod_dedup() != null
+                    || next.traversalMethod_with() != null) {
+                // continue
+            } else {
+                break;
+            }
+        }
+        return tags.isEmpty() ? null : tags.get(tags.size() - 1);
+    }
+
+    private GraphBuilder appendTailProject() {
+        Preconditions.checkArgument(builder.size() > 0, "builder should not be empty");
+        RelNode top = builder.peek();
+        if ((top instanceof Aggregate)
+                || (top instanceof GraphLogicalProject)
+                        && ((GraphLogicalProject) top).isAppend() == false) return builder;
+        List<RexNode> exprs = Lists.newArrayList();
+        List<String> aliases = Lists.newArrayList();
+        for (RelDataTypeField field : top.getRowType().getFieldList()) {
+            exprs.add(builder.variable(field.getName()));
+            aliases.add(field.getName() == AliasInference.DEFAULT_NAME ? null : field.getName());
+        }
+        return builder.project(exprs, aliases);
+    }
+}
diff --git a/interactive_engine/compiler/src/main/java/com/alibaba/graphscope/gremlin/antlr4x/visitor/NestedTraversalVisitor.java b/interactive_engine/compiler/src/main/java/com/alibaba/graphscope/gremlin/antlr4x/visitor/NestedTraversalVisitor.java
new file mode 100644
index 000000000000..68a9118868a3
--- /dev/null
+++ b/interactive_engine/compiler/src/main/java/com/alibaba/graphscope/gremlin/antlr4x/visitor/NestedTraversalVisitor.java
@@ -0,0 +1,72 @@
+/*
+ * Copyright 2020 Alibaba Group Holding Limited.
+ *
+ * Licensed 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 com.alibaba.graphscope.gremlin.antlr4x.visitor;
+
+import com.alibaba.graphscope.common.ir.tools.GraphBuilder;
+import com.alibaba.graphscope.grammar.GremlinGSBaseVisitor;
+import com.alibaba.graphscope.grammar.GremlinGSParser;
+import com.alibaba.graphscope.gremlin.exception.UnsupportedEvalException;
+import com.google.common.base.Preconditions;
+import com.google.common.collect.ImmutableList;
+
+import org.apache.calcite.plan.GraphOptCluster;
+import org.apache.calcite.rel.RelNode;
+import org.apache.calcite.rel.core.Project;
+import org.apache.calcite.rex.RexNode;
+import org.checkerframework.checker.nullness.qual.Nullable;
+
+public class NestedTraversalVisitor extends GremlinGSBaseVisitor<RexNode> {
+    private final GraphBuilder parentBuilder;
+    private final GraphBuilder nestedBuilder;
+    private final @Nullable String tag;
+
+    public NestedTraversalVisitor(GraphBuilder parentBuilder, @Nullable String tag) {
+        this.parentBuilder = parentBuilder;
+        this.nestedBuilder =
+                GraphBuilder.create(
+                        this.parentBuilder.getContext(),
+                        (GraphOptCluster) this.parentBuilder.getCluster(),
+                        this.parentBuilder.getRelOptSchema());
+        this.tag = tag;
+    }
+
+    @Override
+    public RexNode visitNestedTraversal(GremlinGSParser.NestedTraversalContext ctx) {
+        Preconditions.checkArgument(parentBuilder.size() > 0, "parent builder should not be empty");
+        RelNode commonRel = parentBuilder.peek();
+        nestedBuilder.push(commonRel);
+        if (tag != null) {
+            nestedBuilder.project(
+                    ImmutableList.of(nestedBuilder.variable(tag)), ImmutableList.of(), true);
+        }
+        GraphBuilderVisitor visitor = new GraphBuilderVisitor(nestedBuilder);
+        RelNode subRel = visitor.visitNestedTraversal(ctx).build();
+        if (new SubQueryChecker(commonRel).test(subRel)) {
+            // todo: return sub query in RexSubQuery
+            throw new UnsupportedEvalException(
+                    GremlinGSParser.NestedTraversalContext.class, "sub query is unsupported yet");
+        }
+        // convert subRel to expression
+        Project project = (Project) subRel;
+        Preconditions.checkArgument(
+                project.getProjects().size() == 1,
+                "value returned from sub query should be single value");
+        RexNode expr = project.getProjects().get(0);
+        String alias = project.getRowType().getFieldList().get(0).getName();
+        return nestedBuilder.alias(expr, alias);
+    }
+}
diff --git a/interactive_engine/compiler/src/main/java/com/alibaba/graphscope/gremlin/antlr4x/visitor/NonStringValueByVisitor.java b/interactive_engine/compiler/src/main/java/com/alibaba/graphscope/gremlin/antlr4x/visitor/NonStringValueByVisitor.java
new file mode 100644
index 000000000000..4d4eff00d91e
--- /dev/null
+++ b/interactive_engine/compiler/src/main/java/com/alibaba/graphscope/gremlin/antlr4x/visitor/NonStringValueByVisitor.java
@@ -0,0 +1,125 @@
+/*
+ * Copyright 2020 Alibaba Group Holding Limited.
+ *
+ * Licensed 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 com.alibaba.graphscope.gremlin.antlr4x.visitor;
+
+import com.alibaba.graphscope.common.ir.rel.GraphLogicalDedupBy;
+import com.alibaba.graphscope.common.ir.tools.GraphBuilder;
+import com.alibaba.graphscope.grammar.GremlinGSBaseVisitor;
+import com.alibaba.graphscope.grammar.GremlinGSParser;
+import com.alibaba.graphscope.gremlin.antlr4.GenericLiteralVisitor;
+import com.alibaba.graphscope.gremlin.exception.UnsupportedEvalException;
+import com.google.common.base.Preconditions;
+
+import org.apache.calcite.plan.GraphOptCluster;
+import org.apache.calcite.rel.RelNode;
+import org.apache.calcite.rel.core.Project;
+import org.apache.calcite.rex.RexNode;
+import org.apache.calcite.tools.RelBuilder;
+
+public class NonStringValueByVisitor extends GremlinGSBaseVisitor<RelBuilder.AggCall> {
+    private final GraphBuilder builder;
+
+    public NonStringValueByVisitor(GraphBuilder builder) {
+        this.builder = builder;
+    }
+
+    @Override
+    public RelBuilder.AggCall visitNonStringValueBy(GremlinGSParser.NonStringValueByContext byCtx) {
+        String alias =
+                (byCtx.traversalMethod_as() != null)
+                        ? GenericLiteralVisitor.getStringLiteral(
+                                byCtx.traversalMethod_as().stringLiteral())
+                        : null;
+        if (byCtx.traversalMethod_dedup() != null) {
+            GraphBuilder nestedBuilder =
+                    GraphBuilder.create(
+                            builder.getContext(),
+                            (GraphOptCluster) builder.getCluster(),
+                            builder.getRelOptSchema());
+            Preconditions.checkArgument(builder.size() > 0, "parent builder should not be empty");
+            GraphBuilderVisitor nestedVisitor =
+                    new GraphBuilderVisitor(nestedBuilder.push(this.builder.peek()));
+            GraphLogicalDedupBy dedupBy =
+                    (GraphLogicalDedupBy)
+                            nestedVisitor
+                                    .visitTraversalMethod_dedup(byCtx.traversalMethod_dedup())
+                                    .build();
+            if (byCtx.traversalMethod_count() != null) {
+                return builder.count(true, alias, dedupBy.getDedupByKeys());
+            } else if (byCtx.traversalMethod_fold() != null) {
+                return builder.collect(true, alias, dedupBy.getDedupByKeys());
+            }
+            throw new UnsupportedEvalException(
+                    byCtx.getClass(), byCtx.getText() + " is unsupported yet in group value by");
+        } else if (byCtx.traversalMethod_aggregate_func() != null) {
+            RexNode expr;
+            if (byCtx.traversalMethod_select() != null || byCtx.traversalMethod_values() != null) {
+                GraphBuilder nestedBuilder =
+                        GraphBuilder.create(
+                                builder.getContext(),
+                                (GraphOptCluster) builder.getCluster(),
+                                builder.getRelOptSchema());
+                Preconditions.checkArgument(
+                        builder.size() > 0, "parent builder should not be empty");
+                GraphBuilderVisitor nestedVisitor =
+                        new GraphBuilderVisitor(nestedBuilder.push(this.builder.peek()));
+                if (byCtx.traversalMethod_select() != null) {
+                    nestedVisitor.visitTraversalMethod_select(byCtx.traversalMethod_select());
+                }
+                if (byCtx.traversalMethod_values() != null) {
+                    nestedVisitor.visitTraversalMethod_values(byCtx.traversalMethod_values());
+                }
+                RelNode subRel = nestedBuilder.build();
+                if (new SubQueryChecker(builder.peek()).test(subRel)) {
+                    throw new UnsupportedEvalException(
+                            byCtx.getClass(),
+                            "sub query " + byCtx.getText() + "is unsupported yet");
+                }
+                // convert subRel to expression
+                Project project = (Project) subRel;
+                Preconditions.checkArgument(
+                        project.getInputs().size() == 1,
+                        "value returned from sub query should be single value");
+                expr = project.getProjects().get(0);
+            } else {
+                expr = builder.variable((String) null);
+            }
+            GremlinGSParser.TraversalMethod_aggregate_funcContext aggCtx =
+                    byCtx.traversalMethod_aggregate_func();
+            if (aggCtx.traversalMethod_count() != null) {
+                return builder.count(false, alias, expr);
+            } else if (aggCtx.traversalMethod_fold() != null) {
+                return builder.collect(false, alias, expr);
+            } else if (aggCtx.traversalMethod_sum() != null) {
+                return builder.sum(false, alias, expr);
+            } else if (aggCtx.traversalMethod_max() != null) {
+                return builder.max(alias, expr);
+            } else if (aggCtx.traversalMethod_min() != null) {
+                return builder.min(alias, expr);
+            } else if (aggCtx.traversalMethod_mean() != null) {
+                return builder.avg(false, alias, expr);
+            } else {
+                throw new IllegalArgumentException(
+                        "invalid aggregate function " + aggCtx.getText());
+            }
+        } else {
+            throw new UnsupportedEvalException(
+                    byCtx.getClass(),
+                    "group value by context " + byCtx.getText() + " is unsupported yet");
+        }
+    }
+}
diff --git a/interactive_engine/compiler/src/main/java/com/alibaba/graphscope/gremlin/antlr4x/visitor/PathExpandBuilderVisitor.java b/interactive_engine/compiler/src/main/java/com/alibaba/graphscope/gremlin/antlr4x/visitor/PathExpandBuilderVisitor.java
new file mode 100644
index 000000000000..aec29f295d64
--- /dev/null
+++ b/interactive_engine/compiler/src/main/java/com/alibaba/graphscope/gremlin/antlr4x/visitor/PathExpandBuilderVisitor.java
@@ -0,0 +1,157 @@
+/*
+ * Copyright 2020 Alibaba Group Holding Limited.
+ *
+ * Licensed 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 com.alibaba.graphscope.gremlin.antlr4x.visitor;
+
+import com.alibaba.graphscope.common.ir.tools.config.*;
+import com.alibaba.graphscope.grammar.GremlinGSBaseVisitor;
+import com.alibaba.graphscope.grammar.GremlinGSParser;
+import com.alibaba.graphscope.gremlin.Utils;
+import com.alibaba.graphscope.gremlin.antlr4.GenericLiteralVisitor;
+import com.google.common.base.Preconditions;
+import com.google.common.collect.Lists;
+
+import java.util.List;
+import java.util.Objects;
+
+public class PathExpandBuilderVisitor extends GremlinGSBaseVisitor<PathExpandConfig.Builder> {
+    private final GraphBuilderVisitor parent;
+    private final PathExpandConfig.Builder builder;
+
+    public PathExpandBuilderVisitor(GraphBuilderVisitor parent) {
+        this.parent = Objects.requireNonNull(parent);
+        // PATH_OPT = ARBITRARY and RESULT_OPT = END_V are set by default
+        this.builder = PathExpandConfig.newBuilder(parent.getGraphBuilder());
+    }
+
+    @Override
+    public PathExpandConfig.Builder visitTraversalMethod_out(
+            GremlinGSParser.TraversalMethod_outContext ctx) {
+        String[] labels = GenericLiteralVisitor.getStringLiteralList(ctx.stringLiteralList());
+        Preconditions.checkArgument(
+                labels != null && labels.length > 0, "arguments can not be empty in path expand");
+        String[] ranges = labels[0].split("\\.\\.");
+        int lower = Integer.valueOf(ranges[0]);
+        int upper = Integer.valueOf(ranges[1]);
+        // set path_opt and result_opt
+        List<GremlinGSParser.TraversalMethod_withContext> nextWith =
+                getNextWith((GremlinGSParser.TraversalMethodContext) ctx.getParent());
+        nextWith.forEach(k -> visitTraversalMethod_with(k));
+        // set expand config, getV config, range, alias
+        String alias =
+                parent.getNextTag(
+                        new TraversalMethodIterator(
+                                (GremlinGSParser.TraversalMethodContext) ctx.getParent()));
+        return builder.expand(new ExpandConfig(GraphOpt.Expand.OUT, getExpandLabelConfig(labels)))
+                .getV(new GetVConfig(GraphOpt.GetV.END))
+                .range(lower, upper - lower)
+                .alias(alias);
+    }
+
+    @Override
+    public PathExpandConfig.Builder visitTraversalMethod_in(
+            GremlinGSParser.TraversalMethod_inContext ctx) {
+        String[] labels = GenericLiteralVisitor.getStringLiteralList(ctx.stringLiteralList());
+        Preconditions.checkArgument(
+                labels != null && labels.length > 0, "arguments can not be empty in path expand");
+        String[] ranges = labels[0].split("\\.\\.");
+        int lower = Integer.valueOf(ranges[0]);
+        int upper = Integer.valueOf(ranges[1]);
+        // set path_opt and result_opt
+        List<GremlinGSParser.TraversalMethod_withContext> nextWith =
+                getNextWith((GremlinGSParser.TraversalMethodContext) ctx.getParent());
+        nextWith.forEach(k -> visitTraversalMethod_with(k));
+        // set expand config, getV config, range, alias
+        String alias =
+                parent.getNextTag(
+                        new TraversalMethodIterator(
+                                (GremlinGSParser.TraversalMethodContext) ctx.getParent()));
+        return builder.expand(new ExpandConfig(GraphOpt.Expand.IN, getExpandLabelConfig(labels)))
+                .getV(new GetVConfig(GraphOpt.GetV.START))
+                .range(lower, upper - lower)
+                .alias(alias);
+    }
+
+    @Override
+    public PathExpandConfig.Builder visitTraversalMethod_both(
+            GremlinGSParser.TraversalMethod_bothContext ctx) {
+        String[] labels = GenericLiteralVisitor.getStringLiteralList(ctx.stringLiteralList());
+        Preconditions.checkArgument(
+                labels != null && labels.length > 0, "arguments can not be empty in path expand");
+        String[] ranges = labels[0].split("\\.\\.");
+        int lower = Integer.valueOf(ranges[0]);
+        int upper = Integer.valueOf(ranges[1]);
+        // set path_opt and result_opt
+        List<GremlinGSParser.TraversalMethod_withContext> nextWith =
+                getNextWith((GremlinGSParser.TraversalMethodContext) ctx.getParent());
+        nextWith.forEach(k -> visitTraversalMethod_with(k));
+        // set expand config, getV config, range, alias
+        String alias =
+                parent.getNextTag(
+                        new TraversalMethodIterator(
+                                (GremlinGSParser.TraversalMethodContext) ctx.getParent()));
+        return builder.expand(new ExpandConfig(GraphOpt.Expand.BOTH, getExpandLabelConfig(labels)))
+                .getV(new GetVConfig(GraphOpt.GetV.OTHER))
+                .range(lower, upper - lower)
+                .alias(alias);
+    }
+
+    @Override
+    public PathExpandConfig.Builder visitTraversalMethod_with(
+            GremlinGSParser.TraversalMethod_withContext ctx) {
+        String optKey = GenericLiteralVisitor.getStringLiteral(ctx.stringLiteral());
+        Object optValue =
+                GenericLiteralVisitor.getInstance().visitGenericLiteral(ctx.genericLiteral());
+        switch (optKey.toUpperCase()) {
+            case "PATH_OPT":
+                return builder.pathOpt(
+                        GraphOpt.PathExpandPath.valueOf(String.valueOf(optValue).toUpperCase()));
+            case "RESULT_OPT":
+                return builder.resultOpt(
+                        GraphOpt.PathExpandResult.valueOf(String.valueOf(optValue).toUpperCase()));
+            default:
+                return builder;
+        }
+    }
+
+    private List<GremlinGSParser.TraversalMethod_withContext> getNextWith(
+            GremlinGSParser.TraversalMethodContext curCtx) {
+        List<GremlinGSParser.TraversalMethod_withContext> nextWith = Lists.newArrayList();
+        TraversalMethodIterator methodIterator = new TraversalMethodIterator(curCtx);
+        while (methodIterator.hasNext()) {
+            GremlinGSParser.TraversalMethodContext next = methodIterator.next();
+            if (next.traversalMethod_with() != null) {
+                nextWith.add(next.traversalMethod_with());
+            } else {
+                break;
+            }
+        }
+        return nextWith;
+    }
+
+    private LabelConfig getExpandLabelConfig(String[] labels) {
+        if (labels.length <= 1) {
+            return new LabelConfig(true);
+        } else {
+            labels = Utils.removeStringEle(0, labels);
+            LabelConfig expandLabels = new LabelConfig(false);
+            for (int i = 0; i < labels.length; ++i) {
+                expandLabels.addLabel(labels[i]);
+            }
+            return expandLabels;
+        }
+    }
+}
diff --git a/interactive_engine/compiler/src/main/java/com/alibaba/graphscope/gremlin/antlr4x/visitor/SubQueryChecker.java b/interactive_engine/compiler/src/main/java/com/alibaba/graphscope/gremlin/antlr4x/visitor/SubQueryChecker.java
new file mode 100644
index 000000000000..c9bbf496d815
--- /dev/null
+++ b/interactive_engine/compiler/src/main/java/com/alibaba/graphscope/gremlin/antlr4x/visitor/SubQueryChecker.java
@@ -0,0 +1,37 @@
+/*
+ * Copyright 2020 Alibaba Group Holding Limited.
+ *
+ * Licensed 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 com.alibaba.graphscope.gremlin.antlr4x.visitor;
+
+import org.apache.calcite.rel.RelNode;
+import org.apache.calcite.rel.core.Project;
+
+import java.util.function.Predicate;
+
+public class SubQueryChecker implements Predicate<RelNode> {
+    private final RelNode commonRel;
+
+    public SubQueryChecker(RelNode commonRel) {
+        this.commonRel = commonRel;
+    }
+
+    @Override
+    public boolean test(RelNode rel) {
+        return !(!rel.getInputs().isEmpty()
+                && rel.getInput(0).equals(commonRel)
+                && rel instanceof Project);
+    }
+}
diff --git a/interactive_engine/compiler/src/main/java/com/alibaba/graphscope/gremlin/antlr4x/visitor/TraversalMethodIterator.java b/interactive_engine/compiler/src/main/java/com/alibaba/graphscope/gremlin/antlr4x/visitor/TraversalMethodIterator.java
new file mode 100644
index 000000000000..c48a2a5b1e8b
--- /dev/null
+++ b/interactive_engine/compiler/src/main/java/com/alibaba/graphscope/gremlin/antlr4x/visitor/TraversalMethodIterator.java
@@ -0,0 +1,87 @@
+/*
+ * Copyright 2020 Alibaba Group Holding Limited.
+ *
+ * Licensed 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 com.alibaba.graphscope.gremlin.antlr4x.visitor;
+
+import com.alibaba.graphscope.grammar.GremlinGSParser;
+
+import org.antlr.v4.runtime.tree.ParseTree;
+import org.checkerframework.checker.nullness.qual.Nullable;
+
+import java.util.Iterator;
+import java.util.Objects;
+
+public class TraversalMethodIterator implements Iterator<GremlinGSParser.TraversalMethodContext> {
+    private GremlinGSParser.TraversalMethodContext next;
+    private GremlinGSParser.TraversalSourceSpawnMethodContext sourceNext;
+
+    public TraversalMethodIterator(GremlinGSParser.TraversalMethodContext next) {
+        this.next = Objects.requireNonNull(next);
+    }
+
+    public TraversalMethodIterator(GremlinGSParser.TraversalSourceSpawnMethodContext sourceNext) {
+        this.sourceNext = Objects.requireNonNull(sourceNext);
+        this.next = null;
+    }
+
+    @Override
+    public boolean hasNext() {
+        if (this.next == null) {
+            GremlinGSParser.RootTraversalContext rootCtx =
+                    (GremlinGSParser.RootTraversalContext) sourceNext.getParent();
+            return rootCtx != null && rootCtx.chainedTraversal() != null;
+        }
+        ParseTree parent = getParent(getParent(next));
+        return parent != null && parent.getChildCount() >= 3;
+    }
+
+    @Override
+    public GremlinGSParser.TraversalMethodContext next() {
+        if (this.next == null) {
+            GremlinGSParser.RootTraversalContext rootCtx =
+                    (GremlinGSParser.RootTraversalContext) sourceNext.getParent();
+            if (rootCtx == null || rootCtx.chainedTraversal() == null) return null;
+            next = leftDfs(rootCtx.chainedTraversal());
+            return next;
+        }
+        ParseTree parent = getParent(getParent(next));
+        if (parent == null || parent.getChildCount() < 3) return null;
+        next = (GremlinGSParser.TraversalMethodContext) parent.getChild(2);
+        return next;
+    }
+
+    private @Nullable ParseTree getParent(ParseTree child) {
+        Class<? extends ParseTree> parentClass = GremlinGSParser.ChainedTraversalContext.class;
+        while (child != null
+                && child.getParent() != null
+                && !child.getParent().getClass().equals(parentClass)) {
+            child = child.getParent();
+        }
+        return (child != null
+                        && child.getParent() != null
+                        && child.getParent().getClass().equals(parentClass))
+                ? child.getParent()
+                : null;
+    }
+
+    private GremlinGSParser.TraversalMethodContext leftDfs(
+            GremlinGSParser.ChainedTraversalContext root) {
+        if (root.chainedTraversal() != null) {
+            return leftDfs(root.chainedTraversal());
+        }
+        return root.traversalMethod();
+    }
+}
diff --git a/interactive_engine/compiler/src/main/java/com/alibaba/graphscope/gremlin/antlr4x/visitor/Utils.java b/interactive_engine/compiler/src/main/java/com/alibaba/graphscope/gremlin/antlr4x/visitor/Utils.java
new file mode 100644
index 000000000000..5df232216755
--- /dev/null
+++ b/interactive_engine/compiler/src/main/java/com/alibaba/graphscope/gremlin/antlr4x/visitor/Utils.java
@@ -0,0 +1,41 @@
+/*
+ * Copyright 2020 Alibaba Group Holding Limited.
+ *
+ * Licensed 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 com.alibaba.graphscope.gremlin.antlr4x.visitor;
+
+import org.apache.calcite.rex.RexCall;
+import org.apache.calcite.rex.RexLiteral;
+import org.apache.calcite.rex.RexNode;
+import org.apache.calcite.sql.SqlKind;
+import org.checkerframework.checker.nullness.qual.Nullable;
+import org.javatuples.Pair;
+
+import java.util.List;
+
+public class Utils {
+    public static Pair<RexNode, @Nullable String> convertExprToPair(RexNode rex) {
+        if (rex.getKind() == SqlKind.AS) {
+            List<RexNode> operands = ((RexCall) rex).getOperands();
+            return Pair.with(
+                    operands.get(0),
+                    (String)
+                            com.alibaba.graphscope.common.ir.tools.Utils.getValuesAsList(
+                                            ((RexLiteral) operands.get(1)).getValue())
+                                    .get(0));
+        }
+        return Pair.with(rex, null);
+    }
+}
diff --git a/interactive_engine/compiler/src/main/java/com/alibaba/graphscope/gremlin/antlr4x/visitor/WherePredicateVisitor.java b/interactive_engine/compiler/src/main/java/com/alibaba/graphscope/gremlin/antlr4x/visitor/WherePredicateVisitor.java
new file mode 100644
index 000000000000..cd3a84efea50
--- /dev/null
+++ b/interactive_engine/compiler/src/main/java/com/alibaba/graphscope/gremlin/antlr4x/visitor/WherePredicateVisitor.java
@@ -0,0 +1,230 @@
+/*
+ * Copyright 2020 Alibaba Group Holding Limited.
+ *
+ * Licensed 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 com.alibaba.graphscope.gremlin.antlr4x.visitor;
+
+import com.alibaba.graphscope.common.ir.tools.GraphBuilder;
+import com.alibaba.graphscope.common.ir.tools.GraphStdOperatorTable;
+import com.alibaba.graphscope.grammar.GremlinGSParser;
+import com.alibaba.graphscope.gremlin.antlr4.GenericLiteralVisitor;
+import com.alibaba.graphscope.gremlin.exception.UnsupportedEvalException;
+import com.google.common.collect.ImmutableList;
+
+import org.apache.calcite.rex.RexNode;
+import org.checkerframework.checker.nullness.qual.Nullable;
+
+import java.util.List;
+
+public class WherePredicateVisitor extends ExpressionVisitor {
+    private final Ring whereByRing;
+
+    public WherePredicateVisitor(
+            GraphBuilder builder, @Nullable String startTag, Ring wherebyRing) {
+        super(builder, visitTraversalMethod_whereby(builder, startTag, wherebyRing.next()));
+        this.whereByRing = wherebyRing;
+    }
+
+    @Override
+    public RexNode visitTraversalPredicate_eq(GremlinGSParser.TraversalPredicate_eqContext ctx) {
+        return builder.call(
+                GraphStdOperatorTable.EQUALS,
+                propertyKey,
+                visitTraversalMethod_whereby(
+                        builder,
+                        (String)
+                                GenericLiteralVisitor.getInstance()
+                                        .visitGenericLiteral(ctx.genericLiteral()),
+                        whereByRing.next()));
+    }
+
+    @Override
+    public RexNode visitTraversalPredicate_neq(GremlinGSParser.TraversalPredicate_neqContext ctx) {
+        return builder.call(
+                GraphStdOperatorTable.NOT_EQUALS,
+                propertyKey,
+                visitTraversalMethod_whereby(
+                        builder,
+                        (String)
+                                GenericLiteralVisitor.getInstance()
+                                        .visitGenericLiteral(ctx.genericLiteral()),
+                        whereByRing.next()));
+    }
+
+    @Override
+    public RexNode visitTraversalPredicate_lt(GremlinGSParser.TraversalPredicate_ltContext ctx) {
+        return builder.call(
+                GraphStdOperatorTable.LESS_THAN,
+                propertyKey,
+                visitTraversalMethod_whereby(
+                        builder,
+                        (String)
+                                GenericLiteralVisitor.getInstance()
+                                        .visitGenericLiteral(ctx.genericLiteral()),
+                        whereByRing.next()));
+    }
+
+    @Override
+    public RexNode visitTraversalPredicate_lte(GremlinGSParser.TraversalPredicate_lteContext ctx) {
+        return builder.call(
+                GraphStdOperatorTable.LESS_THAN_OR_EQUAL,
+                propertyKey,
+                visitTraversalMethod_whereby(
+                        builder,
+                        (String)
+                                GenericLiteralVisitor.getInstance()
+                                        .visitGenericLiteral(ctx.genericLiteral()),
+                        whereByRing.next()));
+    }
+
+    @Override
+    public RexNode visitTraversalPredicate_gt(GremlinGSParser.TraversalPredicate_gtContext ctx) {
+        return builder.call(
+                GraphStdOperatorTable.GREATER_THAN,
+                propertyKey,
+                visitTraversalMethod_whereby(
+                        builder,
+                        (String)
+                                GenericLiteralVisitor.getInstance()
+                                        .visitGenericLiteral(ctx.genericLiteral()),
+                        whereByRing.next()));
+    }
+
+    @Override
+    public RexNode visitTraversalPredicate_gte(GremlinGSParser.TraversalPredicate_gteContext ctx) {
+        return builder.call(
+                GraphStdOperatorTable.GREATER_THAN_OR_EQUAL,
+                propertyKey,
+                visitTraversalMethod_whereby(
+                        builder,
+                        (String)
+                                GenericLiteralVisitor.getInstance()
+                                        .visitGenericLiteral(ctx.genericLiteral()),
+                        whereByRing.next()));
+    }
+
+    @Override
+    public RexNode visitTraversalPredicate_within(
+            GremlinGSParser.TraversalPredicate_withinContext ctx) {
+        throw new UnsupportedEvalException(
+                ctx.getClass(), ctx.getText() + " is unsupported in where predicate");
+    }
+
+    @Override
+    public RexNode visitTraversalPredicate_without(
+            GremlinGSParser.TraversalPredicate_withoutContext ctx) {
+        throw new UnsupportedEvalException(
+                ctx.getClass(), ctx.getText() + " is unsupported in where predicate");
+    }
+
+    @Override
+    public RexNode visitTraversalPredicate_inside(
+            GremlinGSParser.TraversalPredicate_insideContext ctx) {
+        throw new UnsupportedEvalException(
+                ctx.getClass(), ctx.getText() + " is unsupported in where predicate");
+    }
+
+    @Override
+    public RexNode visitTraversalPredicate_outside(
+            GremlinGSParser.TraversalPredicate_outsideContext ctx) {
+        throw new UnsupportedEvalException(
+                ctx.getClass(), ctx.getText() + " is unsupported in where predicate");
+    }
+
+    @Override
+    public RexNode visitTraversalPredicate_startingWith(
+            GremlinGSParser.TraversalPredicate_startingWithContext ctx) {
+        throw new UnsupportedEvalException(
+                ctx.getClass(), ctx.getText() + " is unsupported in where predicate");
+    }
+
+    @Override
+    public RexNode visitTraversalPredicate_notStartingWith(
+            GremlinGSParser.TraversalPredicate_notStartingWithContext ctx) {
+        throw new UnsupportedEvalException(
+                ctx.getClass(), ctx.getText() + " is unsupported in where predicate");
+    }
+
+    @Override
+    public RexNode visitTraversalPredicate_endingWith(
+            GremlinGSParser.TraversalPredicate_endingWithContext ctx) {
+        throw new UnsupportedEvalException(
+                ctx.getClass(), ctx.getText() + " is unsupported in where predicate");
+    }
+
+    @Override
+    public RexNode visitTraversalPredicate_notEndingWith(
+            GremlinGSParser.TraversalPredicate_notEndingWithContext ctx) {
+        throw new UnsupportedEvalException(
+                ctx.getClass(), ctx.getText() + " is unsupported in where predicate");
+    }
+
+    @Override
+    public RexNode visitTraversalPredicate_containing(
+            GremlinGSParser.TraversalPredicate_containingContext ctx) {
+        throw new UnsupportedEvalException(
+                ctx.getClass(), ctx.getText() + " is unsupported in where predicate");
+    }
+
+    @Override
+    public RexNode visitTraversalPredicate_notContaining(
+            GremlinGSParser.TraversalPredicate_notContainingContext ctx) {
+        throw new UnsupportedEvalException(
+                ctx.getClass(), ctx.getText() + " is unsupported in where predicate");
+    }
+
+    private static RexNode visitTraversalMethod_whereby(
+            GraphBuilder builder,
+            @Nullable String tag,
+            GremlinGSParser.TraversalMethod_wherebyContext byCtx) {
+        if (byCtx == null || byCtx.getChildCount() == 3) { // by()
+            return builder.variable(tag);
+        } else if (byCtx.stringLiteral() != null) {
+            return builder.variable(
+                    tag, GenericLiteralVisitor.getStringLiteral(byCtx.stringLiteral()));
+        } else if (byCtx.traversalMethod_values() != null) {
+            return builder.variable(
+                    tag,
+                    GenericLiteralVisitor.getStringLiteral(
+                            byCtx.traversalMethod_values().stringLiteral()));
+        } else if (byCtx.nestedTraversal() != null) {
+            return Utils.convertExprToPair(
+                            new NestedTraversalVisitor(builder, tag)
+                                    .visitNestedTraversal(byCtx.nestedTraversal()))
+                    .getValue0();
+        }
+        throw new UnsupportedEvalException(
+                byCtx.getClass(), byCtx.getText() + " is unsupported in where predicate");
+    }
+
+    public static class Ring {
+        private final List<GremlinGSParser.TraversalMethod_wherebyContext> byCtxs;
+        private int index;
+
+        public Ring(GremlinGSParser.TraversalMethod_whereby_listContext listCtx) {
+            this.byCtxs =
+                    listCtx == null
+                            ? ImmutableList.of()
+                            : listCtx.getRuleContexts(
+                                    GremlinGSParser.TraversalMethod_wherebyContext.class);
+            this.index = 0;
+        }
+
+        public GremlinGSParser.TraversalMethod_wherebyContext next() {
+            if (byCtxs.isEmpty()) return null;
+            return byCtxs.get((index++) % byCtxs.size());
+        }
+    }
+}
diff --git a/interactive_engine/compiler/src/main/java/com/alibaba/graphscope/gremlin/exception/UnsupportedEvalException.java b/interactive_engine/compiler/src/main/java/com/alibaba/graphscope/gremlin/exception/UnsupportedEvalException.java
index 921e2f78f557..d0db8d5626b6 100644
--- a/interactive_engine/compiler/src/main/java/com/alibaba/graphscope/gremlin/exception/UnsupportedEvalException.java
+++ b/interactive_engine/compiler/src/main/java/com/alibaba/graphscope/gremlin/exception/UnsupportedEvalException.java
@@ -22,7 +22,7 @@ public class UnsupportedEvalException extends UnsupportedOperationException {
     public UnsupportedEvalException(Class<? extends ParseTree> antlrCtx, String error) {
         super(
                 String.format(
-                        "antlr context {%s} parsing to traversal is unsupported, error is {%s}",
+                        "antlr context {%s} parsing is unsupported, error is {%s}",
                         antlrCtx, error));
     }
 }
diff --git a/interactive_engine/compiler/src/main/java/com/alibaba/graphscope/gremlin/integration/graph/RemoteTestGraph.java b/interactive_engine/compiler/src/main/java/com/alibaba/graphscope/gremlin/integration/graph/RemoteTestGraph.java
index 432f340667df..6556b8cff818 100644
--- a/interactive_engine/compiler/src/main/java/com/alibaba/graphscope/gremlin/integration/graph/RemoteTestGraph.java
+++ b/interactive_engine/compiler/src/main/java/com/alibaba/graphscope/gremlin/integration/graph/RemoteTestGraph.java
@@ -1001,7 +1001,7 @@
         method = "g_V_asXaX_out_asXbX_out_asXcX_path_fromXbX_toXcX_byXnameX",
         reason = "unsupported")
 
-// TODO(siyuan): vineyard edge id has been changed
+// todo(siyuan): vineyard edge id has been changed
 @Graph.OptOut(
         test = "org.apache.tinkerpop.gremlin.process.traversal.step.map.VertexTest",
         method = "g_E",
diff --git a/interactive_engine/compiler/src/main/java/com/alibaba/graphscope/gremlin/integration/graph/calcite/RemoteTestGraph.java b/interactive_engine/compiler/src/main/java/com/alibaba/graphscope/gremlin/integration/graph/calcite/RemoteTestGraph.java
new file mode 100644
index 000000000000..0a4d92befb0d
--- /dev/null
+++ b/interactive_engine/compiler/src/main/java/com/alibaba/graphscope/gremlin/integration/graph/calcite/RemoteTestGraph.java
@@ -0,0 +1,1704 @@
+/*
+ * Copyright 2020 Alibaba Group Holding Limited.
+ *
+ * Licensed 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 com.alibaba.graphscope.gremlin.integration.graph.calcite;
+
+import org.apache.commons.configuration2.Configuration;
+import org.apache.tinkerpop.gremlin.structure.Graph;
+import org.checkerframework.checker.nullness.qual.Nullable;
+
+@Graph.OptIn(
+        "com.alibaba.graphscope.gremlin.integration.suite.standard.additional.IrAdditionalGraphTestSuite")
+@Graph.OptIn("com.alibaba.graphscope.gremlin.integration.suite.standard.IrGremlinTestSuite")
+@Graph.OptIn("com.alibaba.graphscope.gremlin.integration.suite.ldbc.IrLdbcTestSuite")
+@Graph.OptIn("com.alibaba.graphscope.gremlin.integration.suite.pattern.IrPatternTestSuite")
+@Graph.OptOut(
+        test = "org.apache.tinkerpop.gremlin.process.traversal.step.filter.DedupTest",
+        method = "g_V_groupCount_selectXvaluesX_unfold_dedup",
+        reason = "unsupported")
+@Graph.OptOut(
+        test = "org.apache.tinkerpop.gremlin.process.traversal.step.filter.DedupTest",
+        method = "g_V_repeatXdedupX_timesX2X_count",
+        reason = "unsupported")
+@Graph.OptOut(
+        test = "org.apache.tinkerpop.gremlin.process.traversal.step.filter.DedupTest",
+        method = "g_V_out_in_valuesXnameX_fold_dedupXlocalX_unfold",
+        reason = "unsupported")
+@Graph.OptOut(
+        test = "org.apache.tinkerpop.gremlin.process.traversal.step.filter.DedupTest",
+        method = "g_V_group_byXlabelX_byXbothE_weight_dedup_foldX",
+        reason = "unsupported")
+@Graph.OptOut(
+        test = "org.apache.tinkerpop.gremlin.process.traversal.step.filter.HasTest",
+        method = "g_V_hasIdXwithoutXemptyXX_count",
+        reason = "unsupported")
+// @Graph.OptOut(
+//        test = "org.apache.tinkerpop.gremlin.process.traversal.step.filter.HasTest",
+//        method = "g_V_hasNotXageX_name",
+//        reason = "unsupported")
+// @Graph.OptOut(
+//        test = "org.apache.tinkerpop.gremlin.process.traversal.step.filter.HasTest",
+//        method = "g_V_hasXname_containingXarkXX",
+//        reason = "unsupported")
+// @Graph.OptOut(
+//        test = "org.apache.tinkerpop.gremlin.process.traversal.step.filter.HasTest",
+//        method = "g_V_hasXname_endingWithXasXX",
+//        reason = "unsupported")
+// @Graph.OptOut(
+//        test = "org.apache.tinkerpop.gremlin.process.traversal.step.filter.HasTest",
+//        method = "g_V_hasXname_startingWithXmarXX",
+//        reason = "unsupported")
+@Graph.OptOut(
+        test = "org.apache.tinkerpop.gremlin.process.traversal.step.filter.HasTest",
+        method = "g_V_hasXlocationX",
+        reason = "unsupported")
+@Graph.OptOut(
+        test = "org.apache.tinkerpop.gremlin.process.traversal.step.filter.HasTest",
+        method = "g_V_hasXlabel_isXsoftwareXX",
+        reason = "unsupported")
+@Graph.OptOut(
+        test = "org.apache.tinkerpop.gremlin.process.traversal.step.filter.HasTest",
+        method = "g_VX1AsStringX_out_hasXid_2AsStringX",
+        reason = "unsupported")
+@Graph.OptOut(
+        test = "org.apache.tinkerpop.gremlin.process.traversal.step.filter.HasTest",
+        method = "g_V_outXcreatedX_hasXname__mapXlengthX_isXgtX3XXX_name",
+        reason = "unsupported")
+// @Graph.OptOut(
+//        test = "org.apache.tinkerpop.gremlin.process.traversal.step.filter.HasTest",
+//        method = "g_V_hasXperson_name_containingXoX_andXltXmXXX",
+//        reason = "unsupported")
+// @Graph.OptOut(
+//        test = "org.apache.tinkerpop.gremlin.process.traversal.step.filter.HasTest",
+//        method = "g_V_hasXname_not_startingWithXmarXX",
+//        reason = "unsupported")
+// @Graph.OptOut(
+//        test = "org.apache.tinkerpop.gremlin.process.traversal.step.filter.HasTest",
+//        method = "g_V_hasXname_not_containingXarkXX",
+//        reason = "unsupported")
+@Graph.OptOut(
+        test = "org.apache.tinkerpop.gremlin.process.traversal.step.filter.HasTest",
+        method = "g_V_bothE_properties_dedup_hasKeyXweightX_hasValueXltX0d3XX_value",
+        reason = "unsupported")
+@Graph.OptOut(
+        test = "org.apache.tinkerpop.gremlin.process.traversal.step.filter.HasTest",
+        method = "g_VX1X_out_hasXid_2AsString_3AsStringX",
+        reason = "unsupported")
+@Graph.OptOut(
+        test = "org.apache.tinkerpop.gremlin.process.traversal.step.filter.HasTest",
+        method = "g_V_hasLabelXperson_software_blahX",
+        reason = "unsupported")
+// @Graph.OptOut(
+//        test = "org.apache.tinkerpop.gremlin.process.traversal.step.filter.HasTest",
+//        method = "g_V_hasXname_not_endingWithXasXX",
+//        reason = "unsupported")
+// @Graph.OptOut(
+//        test = "org.apache.tinkerpop.gremlin.process.traversal.step.filter.HasTest",
+//        method = "g_V_hasXname_gtXmX_andXcontainingXoXXX",
+//        reason = "unsupported")
+@Graph.OptOut(
+        test = "org.apache.tinkerpop.gremlin.process.traversal.step.filter.HasTest",
+        method = "g_V_both_dedup_properties_hasKeyXageX_hasValueXgtX30XX_value",
+        reason = "unsupported")
+@Graph.OptOut(
+        test = "org.apache.tinkerpop.gremlin.process.traversal.step.filter.HasTest",
+        method = "g_EX11X_outV_outE_hasXid_10X",
+        reason = "unsupported")
+@Graph.OptOut(
+        test = "org.apache.tinkerpop.gremlin.process.traversal.step.filter.HasTest",
+        method = "g_V_notXhasIdXwithinXemptyXXX_count",
+        reason = "unsupported")
+@Graph.OptOut(
+        test = "org.apache.tinkerpop.gremlin.process.traversal.step.filter.HasTest",
+        method = "g_VX1X_out_hasXid_lt_3X",
+        reason = "unsupported")
+@Graph.OptOut(
+        test = "org.apache.tinkerpop.gremlin.process.traversal.step.filter.HasTest",
+        method =
+                "g_V_hasLabelXpersonX_hasXage_notXlteX10X_andXnotXbetweenX11_20XXXX_andXltX29X_orXeqX35XXXX_name",
+        reason = "unsupported")
+@Graph.OptOut(
+        test = "org.apache.tinkerpop.gremlin.process.traversal.step.filter.HasTest",
+        method = "g_V_both_dedup_properties_hasKeyXageX_value",
+        reason = "unsupported")
+@Graph.OptOut(
+        test = "org.apache.tinkerpop.gremlin.process.traversal.step.filter.HasTest",
+        method = "g_V_bothE_properties_dedup_hasKeyXweightX_value",
+        reason = "unsupported")
+@Graph.OptOut(
+        test = "org.apache.tinkerpop.gremlin.process.traversal.step.filter.HasTest",
+        method = "g_V_hasIdXemptyX_count",
+        reason = "unsupported")
+@Graph.OptOut(
+        test = "org.apache.tinkerpop.gremlin.process.traversal.step.filter.HasTest",
+        method = "g_V_hasIdXwithinXemptyXX_count",
+        reason = "unsupported")
+@Graph.OptOut(
+        test = "org.apache.tinkerpop.gremlin.process.traversal.step.filter.HasTest",
+        method = "g_E_hasLabelXuses_traversesX",
+        reason = "unsupported")
+@Graph.OptOut(
+        test = "org.apache.tinkerpop.gremlin.process.traversal.step.filter.HasTest",
+        method = "g_EX11X_outV_outE_hasXid_10AsStringX",
+        reason = "unsupported")
+// @Graph.OptOut(
+//        test = "org.apache.tinkerpop.gremlin.process.traversal.step.filter.IsTest",
+//        method = "g_V_whereXinXcreatedX_count_isX1XX_valuesXnameX",
+//        reason = "unsupported")
+// @Graph.OptOut(
+//        test = "org.apache.tinkerpop.gremlin.process.traversal.step.filter.IsTest",
+//        method = "g_V_whereXinXcreatedX_count_isXgte_2XX_valuesXnameX",
+//        reason = "unsupported")
+@Graph.OptOut(
+        test = "org.apache.tinkerpop.gremlin.process.traversal.step.filter.RangeTest",
+        method = "g_V_outE_valuesXweightX_fold_orderXlocalX_skipXlocal_2X",
+        reason = "unsupported")
+@Graph.OptOut(
+        test = "org.apache.tinkerpop.gremlin.process.traversal.step.filter.RangeTest",
+        method =
+                "g_V_asXaX_in_asXaX_in_asXaX_selectXmixed_aX_byXunfold_valuesXnameX_foldX_limitXlocal_1X",
+        reason = "unsupported")
+@Graph.OptOut(
+        test = "org.apache.tinkerpop.gremlin.process.traversal.step.filter.RangeTest",
+        method =
+                "g_V_asXaX_in_asXaX_in_asXaX_selectXmixed_aX_byXunfold_valuesXnameX_foldX_limitXlocal_2X",
+        reason = "unsupported")
+@Graph.OptOut(
+        test = "org.apache.tinkerpop.gremlin.process.traversal.step.filter.RangeTest",
+        method = "g_V_hasLabelXpersonX_order_byXageX_valuesXnameX_skipX1X",
+        reason = "unsupported")
+@Graph.OptOut(
+        test = "org.apache.tinkerpop.gremlin.process.traversal.step.filter.RangeTest",
+        method =
+                "g_V_asXaX_out_asXaX_out_asXaX_selectXmixed_aX_byXunfold_valuesXnameX_foldX_rangeXlocal_1_2X",
+        reason = "unsupported")
+@Graph.OptOut(
+        test = "org.apache.tinkerpop.gremlin.process.traversal.step.filter.RangeTest",
+        method =
+                "g_V_asXaX_out_asXaX_out_asXaX_selectXmixed_aX_byXunfold_valuesXnameX_foldX_rangeXlocal_1_3X",
+        reason = "unsupported")
+@Graph.OptOut(
+        test = "org.apache.tinkerpop.gremlin.process.traversal.step.filter.RangeTest",
+        method =
+                "g_V_asXaX_out_asXaX_out_asXaX_selectXmixed_aX_byXunfold_valuesXnameX_foldX_rangeXlocal_4_5X",
+        reason = "unsupported")
+@Graph.OptOut(
+        test = "org.apache.tinkerpop.gremlin.process.traversal.step.filter.RangeTest",
+        method = "g_VX1X_outXcreatedX_inXcreatedX_rangeX1_3X",
+        reason = "unsupported")
+@Graph.OptOut(
+        test = "org.apache.tinkerpop.gremlin.process.traversal.step.filter.RangeTest",
+        method = "g_V_repeatXbothX_timesX3X_rangeX5_11X",
+        reason = "unsupported")
+@Graph.OptOut(
+        test = "org.apache.tinkerpop.gremlin.process.traversal.step.filter.RangeTest",
+        method = "g_V_asXaX_in_asXbX_in_asXcX_selectXa_b_cX_byXnameX_limitXlocal_1X",
+        reason = "unsupported")
+@Graph.OptOut(
+        test = "org.apache.tinkerpop.gremlin.process.traversal.step.filter.RangeTest",
+        method = "g_V_asXaX_in_asXbX_in_asXcX_selectXa_b_cX_byXnameX_limitXlocal_2X",
+        reason = "unsupported")
+@Graph.OptOut(
+        test = "org.apache.tinkerpop.gremlin.process.traversal.step.filter.RangeTest",
+        method = "g_V_localXoutE_limitX1X_inVX_limitX3X",
+        reason = "unsupported")
+@Graph.OptOut(
+        test = "org.apache.tinkerpop.gremlin.process.traversal.step.filter.RangeTest",
+        method = "g_V_hasLabelXpersonX_order_byXageX_skipX1X_valuesXnameX",
+        reason = "unsupported")
+@Graph.OptOut(
+        test = "org.apache.tinkerpop.gremlin.process.traversal.step.filter.RangeTest",
+        method = "g_VX1X_outXcreatedX_inEXcreatedX_rangeX1_3X_outV",
+        reason = "unsupported")
+@Graph.OptOut(
+        test = "org.apache.tinkerpop.gremlin.process.traversal.step.filter.RangeTest",
+        method = "g_V_asXaX_out_asXbX_out_asXcX_selectXa_b_cX_byXnameX_rangeXlocal_1_2X",
+        reason = "unsupported")
+@Graph.OptOut(
+        test = "org.apache.tinkerpop.gremlin.process.traversal.step.filter.RangeTest",
+        method = "g_V_asXaX_out_asXbX_out_asXcX_selectXa_b_cX_byXnameX_rangeXlocal_1_3X",
+        reason = "unsupported")
+@Graph.OptOut(
+        test = "org.apache.tinkerpop.gremlin.process.traversal.step.filter.SimplePathTest",
+        method = "g_V_asXaX_out_asXbX_out_asXcX_simplePath_byXlabelX_fromXbX_toXcX_path_byXnameX",
+        reason = "unsupported")
+@Graph.OptOut(
+        test = "org.apache.tinkerpop.gremlin.process.traversal.step.filter.WhereTest",
+        method =
+                "g_V_asXaX_out_asXbX_whereXandXasXaX_outXknowsX_asXbX__orXasXbX_outXcreatedX_hasXname_rippleX__asXbX_inXknowsX_count_isXnotXeqX0XXXXX_selectXa_bX",
+        reason = "unsupported")
+// @Graph.OptOut(test = "org.apache.tinkerpop.gremlin.process.traversal.step.filter.WhereTest",
+//        method = "g_V_hasXageX_asXaX_out_in_hasXageX_asXbX_selectXa_bX_whereXa_eqXbXX",
+//        reason = "unsupported")
+@Graph.OptOut(
+        test = "org.apache.tinkerpop.gremlin.process.traversal.step.filter.WhereTest",
+        method =
+                "g_withSideEffectXa_josh_peterX_VX1X_outXcreatedX_inXcreatedX_name_whereXwithinXaXX",
+        reason = "unsupported")
+// @Graph.OptOut(test = "org.apache.tinkerpop.gremlin.process.traversal.step.filter.WhereTest",
+//        method = "g_V_hasXageX_asXaX_out_in_hasXageX_asXbX_selectXa_bX_whereXa_outXknowsX_bX",
+//        reason = "unsupported")
+@Graph.OptOut(
+        test = "org.apache.tinkerpop.gremlin.process.traversal.step.filter.WhereTest",
+        method = "g_V_whereXoutXcreatedX_and_outXknowsX_or_inXknowsXX_valuesXnameX",
+        reason = "unsupported")
+// @Graph.OptOut(test = "org.apache.tinkerpop.gremlin.process.traversal.step.filter.WhereTest",
+//        method = "g_V_whereXnotXoutXcreatedXXX_name",
+//        reason = "unsupported")
+@Graph.OptOut(
+        test = "org.apache.tinkerpop.gremlin.process.traversal.step.filter.WhereTest",
+        method =
+                "g_V_asXaX_out_asXbX_whereXin_count_isXeqX3XX_or_whereXoutXcreatedX_and_hasXlabel_personXXX_selectXa_bX",
+        reason = "unsupported")
+@Graph.OptOut(
+        test = "org.apache.tinkerpop.gremlin.process.traversal.step.filter.WhereTest",
+        method = "g_withSideEffectXa_g_VX2XX_VX1X_out_whereXneqXaXX",
+        reason = "unsupported")
+@Graph.OptOut(
+        test = "org.apache.tinkerpop.gremlin.process.traversal.step.filter.WhereTest",
+        method =
+                "g_V_asXaX_outEXcreatedX_asXbX_inV_asXcX_inXcreatedX_asXdX_whereXa_ltXbX_orXgtXcXX_andXneqXdXXX_byXageX_byXweightX_byXinXcreatedX_valuesXageX_minX_selectXa_c_dX",
+        reason = "unsupported")
+// @Graph.OptOut(test = "org.apache.tinkerpop.gremlin.process.traversal.step.filter.WhereTest",
+//        method = "g_V_hasXageX_asXaX_out_in_hasXageX_asXbX_selectXa_bX_whereXb_hasXname_markoXX",
+//        reason = "unsupported")
+@Graph.OptOut(
+        test = "org.apache.tinkerpop.gremlin.process.traversal.step.filter.WhereTest",
+        method = "g_VX1X_out_aggregateXxX_out_whereXnotXwithinXaXXX",
+        reason = "unsupported")
+@Graph.OptOut(
+        test = "org.apache.tinkerpop.gremlin.process.traversal.step.filter.WhereTest",
+        method =
+                "g_V_asXaX_outXcreatedX_asXbX_whereXandXasXbX_in__notXasXaX_outXcreatedX_hasXname_rippleXXX_selectXa_bX",
+        reason = "unsupported")
+@Graph.OptOut(
+        test = "org.apache.tinkerpop.gremlin.process.traversal.step.filter.WhereTest",
+        method = "g_VX1X_repeatXbothEXcreatedX_whereXwithoutXeXX_aggregateXeX_otherVX_emit_path",
+        reason = "unsupported")
+// @Graph.OptOut(test = "org.apache.tinkerpop.gremlin.process.traversal.step.filter.WhereTest",
+//        method = "g_V_hasXageX_asXaX_out_in_hasXageX_asXbX_selectXa_bX_whereXa_neqXbXX",
+//        reason = "unsupported")
+@Graph.OptOut(
+        test = "org.apache.tinkerpop.gremlin.process.traversal.step.map.CountTest",
+        method = "g_V_fold_countXlocalX",
+        reason = "unsupported")
+@Graph.OptOut(
+        test = "org.apache.tinkerpop.gremlin.process.traversal.step.map.CountTest",
+        method = "g_V_repeatXoutX_timesX5X_asXaX_outXwrittenByX_asXbX_selectXa_bX_count",
+        reason = "unsupported")
+@Graph.OptOut(
+        test = "org.apache.tinkerpop.gremlin.process.traversal.step.map.CountTest",
+        method = "g_V_both_both_count",
+        reason = "unsupported")
+// @Graph.OptOut(
+//        test = "org.apache.tinkerpop.gremlin.process.traversal.step.map.CountTest",
+//        method = "g_V_whereXinXkknowsX_outXcreatedX_count_is_0XX_name",
+//        reason = "unsupported")
+@Graph.OptOut(
+        test = "org.apache.tinkerpop.gremlin.process.traversal.step.map.GraphTest",
+        method = "g_V_hasLabelXpersonX_asXpX_VXsoftwareX_addInEXuses_pX",
+        reason = "unsupported")
+@Graph.OptOut(
+        test = "org.apache.tinkerpop.gremlin.process.traversal.step.map.GraphTest",
+        method = "g_V_outXknowsX_V_name",
+        reason = "unsupported")
+@Graph.OptOut(
+        test = "org.apache.tinkerpop.gremlin.process.traversal.step.map.GraphTest",
+        method =
+                "g_V_hasXname_GarciaX_inXsungByX_asXsongX_V_hasXname_Willie_DixonX_inXwrittenByX_whereXeqXsongXX_name",
+        reason = "unsupported")
+@Graph.OptOut(
+        test = "org.apache.tinkerpop.gremlin.process.traversal.step.map.OrderTest",
+        method = "g_V_group_byXlabelX_byXname_order_byXdescX_foldX",
+        reason = "unsupported")
+@Graph.OptOut(
+        test = "org.apache.tinkerpop.gremlin.process.traversal.step.map.OrderTest",
+        method = "g_V_hasLabelXsongX_order_byXperformances_descX_byXnameX_rangeX110_120X_name",
+        reason = "unsupported")
+@Graph.OptOut(
+        test = "org.apache.tinkerpop.gremlin.process.traversal.step.map.OrderTest",
+        method =
+                "g_V_asXvX_mapXbothE_weight_foldX_sumXlocalX_asXsX_selectXv_sX_order_byXselectXsX_descX",
+        reason = "unsupported")
+@Graph.OptOut(
+        test = "org.apache.tinkerpop.gremlin.process.traversal.step.map.OrderTest",
+        method = "g_V_mapXbothE_weight_foldX_order_byXsumXlocalX_descX",
+        reason = "unsupported")
+@Graph.OptOut(
+        test = "org.apache.tinkerpop.gremlin.process.traversal.step.map.OrderTest",
+        method = "g_V_hasLabelXpersonX_fold_orderXlocalX_byXageX",
+        reason = "unsupported")
+@Graph.OptOut(
+        test = "org.apache.tinkerpop.gremlin.process.traversal.step.map.OrderTest",
+        method =
+                "g_V_hasXsong_name_OHBOYX_outXfollowedByX_outXfollowedByX_order_byXperformancesX_byXsongType_descX",
+        reason = "unsupported")
+@Graph.OptOut(
+        test = "org.apache.tinkerpop.gremlin.process.traversal.step.map.OrderTest",
+        method = "g_V_hasLabelXpersonX_group_byXnameX_byXoutE_weight_sumX_orderXlocalX_byXvaluesX",
+        reason = "unsupported")
+@Graph.OptOut(
+        test = "org.apache.tinkerpop.gremlin.process.traversal.step.map.OrderTest",
+        method =
+                "g_VX1X_hasXlabel_personX_mapXmapXint_ageXX_orderXlocalX_byXvalues_descX_byXkeys_ascX",
+        reason = "unsupported")
+@Graph.OptOut(
+        test = "org.apache.tinkerpop.gremlin.process.traversal.step.map.OrderTest",
+        method = "g_V_name_order_byXa1_b1X_byXb2_a2X",
+        reason = "unsupported")
+@Graph.OptOut(
+        test = "org.apache.tinkerpop.gremlin.process.traversal.step.map.OrderTest",
+        method = "g_V_properties_order_byXkey_descX_key",
+        reason = "unsupported")
+@Graph.OptOut(
+        test = "org.apache.tinkerpop.gremlin.process.traversal.step.map.OrderTest",
+        method = "g_V_hasLabelXpersonX_order_byXvalueXageX_descX_name",
+        reason = "unsupported")
+@Graph.OptOut(
+        test = "org.apache.tinkerpop.gremlin.process.traversal.step.map.OrderTest",
+        method = "g_VX1X_elementMap_orderXlocalX_byXkeys_descXunfold",
+        reason = "unsupported")
+@Graph.OptOut(
+        test = "org.apache.tinkerpop.gremlin.process.traversal.step.map.OrderTest",
+        method =
+                "g_V_hasLabelXpersonX_group_byXnameX_byXoutE_weight_sumX_unfold_order_byXvalues_descX",
+        reason = "unsupported")
+@Graph.OptOut(
+        test = "org.apache.tinkerpop.gremlin.process.traversal.step.map.OrderTest",
+        method = "g_V_both_hasLabelXpersonX_order_byXage_descX_name",
+        reason = "unsupported")
+// @Graph.OptOut(test = "org.apache.tinkerpop.gremlin.process.traversal.step.map.OrderTest",
+//        method = "g_V_order_byXname_incrX_name",
+//        reason = "unsupported")
+// @Graph.OptOut(
+//        test = "org.apache.tinkerpop.gremlin.process.traversal.step.map.OrderTest",
+//        method = "g_V_order_byXoutE_count_descX",
+//        reason = "unsupported")
+@Graph.OptOut(
+        test = "org.apache.tinkerpop.gremlin.process.traversal.step.map.OrderTest",
+        method = "g_V_order_byXname_a1_b1X_byXname_b2_a2X_name",
+        reason = "unsupported")
+// @Graph.OptOut(test = "org.apache.tinkerpop.gremlin.process.traversal.step.map.OrderTest",
+//        method = "g_V_outE_order_byXweight_decrX_weight",
+//        reason = "unsupported")
+@Graph.OptOut(
+        test = "org.apache.tinkerpop.gremlin.process.traversal.step.map.PropertiesTest",
+        method = "g_V_hasXageX_propertiesXage_nameX_value",
+        reason = "unsupported")
+@Graph.OptOut(
+        test = "org.apache.tinkerpop.gremlin.process.traversal.step.map.PropertiesTest",
+        method = "g_V_hasXageX_properties_hasXid_nameIdX_value",
+        reason = "unsupported")
+@Graph.OptOut(
+        test = "org.apache.tinkerpop.gremlin.process.traversal.step.map.PropertiesTest",
+        method = "g_injectXg_VX1X_propertiesXnameX_nextX_value",
+        reason = "unsupported")
+@Graph.OptOut(
+        test = "org.apache.tinkerpop.gremlin.process.traversal.step.map.PropertiesTest",
+        method = "g_V_hasXageX_properties_hasXid_nameIdAsStringX_value",
+        reason = "unsupported")
+@Graph.OptOut(
+        test = "org.apache.tinkerpop.gremlin.process.traversal.step.map.PropertiesTest",
+        method = "g_V_hasXageX_propertiesXname_ageX_value",
+        reason = "unsupported")
+@Graph.OptOut(
+        test = "org.apache.tinkerpop.gremlin.process.traversal.step.map.PropertiesTest",
+        method = "g_V_hasXageX_propertiesXnameX",
+        reason = "unsupported")
+@Graph.OptOut(
+        test = "org.apache.tinkerpop.gremlin.process.traversal.step.map.SelectTest",
+        method = "g_V_hasXperson_name_markoX_barrier_asXaX_outXknows_selectXaX",
+        reason = "unsupported")
+@Graph.OptOut(
+        test = "org.apache.tinkerpop.gremlin.process.traversal.step.map.SelectTest",
+        method =
+                "g_V_hasXperson_name_markoX_elementMapXnameX_asXaX_unionXidentity_identityX_selectXaX_selectXnameX",
+        reason = "unsupported")
+@Graph.OptOut(
+        test = "org.apache.tinkerpop.gremlin.process.traversal.step.map.SelectTest",
+        method = "g_V_valueMap_selectXall_aX",
+        reason = "unsupported")
+@Graph.OptOut(
+        test = "org.apache.tinkerpop.gremlin.process.traversal.step.map.SelectTest",
+        method = "g_V_selectXlast_a_bX",
+        reason = "unsupported")
+@Graph.OptOut(
+        test = "org.apache.tinkerpop.gremlin.process.traversal.step.map.SelectTest",
+        method = "g_V_untilXout_outX_repeatXin_asXaX_in_asXbXX_selectXa_bX_byXnameX",
+        reason = "unsupported")
+@Graph.OptOut(
+        test = "org.apache.tinkerpop.gremlin.process.traversal.step.map.SelectTest",
+        method = "g_V_valueMap_selectXfirst_aX",
+        reason = "unsupported")
+@Graph.OptOut(
+        test = "org.apache.tinkerpop.gremlin.process.traversal.step.map.SelectTest",
+        method = "g_V_asXaX_out_aggregateXxX_asXbX_selectXa_bX_byXnameX",
+        reason = "unsupported")
+@Graph.OptOut(
+        test = "org.apache.tinkerpop.gremlin.process.traversal.step.map.SelectTest",
+        method = "g_V_label_groupCount_asXxX_selectXxX",
+        reason = "unsupported")
+@Graph.OptOut(
+        test = "org.apache.tinkerpop.gremlin.process.traversal.step.map.SelectTest",
+        method = "g_V_valueMap_selectXfirst_a_bX",
+        reason = "unsupported")
+@Graph.OptOut(
+        test = "org.apache.tinkerpop.gremlin.process.traversal.step.map.SelectTest",
+        method =
+                "g_V_outXcreatedX_unionXasXprojectX_inXcreatedX_hasXname_markoX_selectXprojectX__asXprojectX_inXcreatedX_inXknowsX_hasXname_markoX_selectXprojectXX_groupCount_byXnameX",
+        reason = "unsupported")
+@Graph.OptOut(
+        test = "org.apache.tinkerpop.gremlin.process.traversal.step.map.SelectTest",
+        method = "g_V_valueMap_selectXlast_a_bX",
+        reason = "unsupported")
+@Graph.OptOut(
+        test = "org.apache.tinkerpop.gremlin.process.traversal.step.map.SelectTest",
+        method = "g_V_hasLabelXpersonX_asXpX_mapXbothE_label_groupCountX_asXrX_selectXp_rX",
+        reason = "unsupported")
+@Graph.OptOut(
+        test = "org.apache.tinkerpop.gremlin.process.traversal.step.map.SelectTest",
+        method =
+                "g_V_chooseXoutE_count_isX0X__asXaX__asXbXX_chooseXselectXaX__selectXaX__selectXbXX",
+        reason = "unsupported")
+@Graph.OptOut(
+        test = "org.apache.tinkerpop.gremlin.process.traversal.step.map.SelectTest",
+        method = "g_V_outE_weight_groupCount_selectXkeysX_unfold",
+        reason = "unsupported")
+@Graph.OptOut(
+        test = "org.apache.tinkerpop.gremlin.process.traversal.step.map.SelectTest",
+        method = "g_V_outE_weight_groupCount_unfold_selectXvaluesX_unfold",
+        reason = "unsupported")
+@Graph.OptOut(
+        test = "org.apache.tinkerpop.gremlin.process.traversal.step.map.SelectTest",
+        method = "g_V_selectXfirst_aX",
+        reason = "unsupported")
+@Graph.OptOut(
+        test = "org.apache.tinkerpop.gremlin.process.traversal.step.map.SelectTest",
+        method = "g_V_outE_weight_groupCount_unfold_selectXkeysX_unfold",
+        reason = "unsupported")
+@Graph.OptOut(
+        test = "org.apache.tinkerpop.gremlin.process.traversal.step.map.SelectTest",
+        method = "g_V_valueMap_selectXlast_aX",
+        reason = "unsupported")
+@Graph.OptOut(
+        test = "org.apache.tinkerpop.gremlin.process.traversal.step.map.SelectTest",
+        method = "g_V_selectXall_aX",
+        reason = "unsupported")
+@Graph.OptOut(
+        test = "org.apache.tinkerpop.gremlin.process.traversal.step.map.SelectTest",
+        method = "g_V_hasXperson_name_markoX_path_asXaX_unionXidentity_identityX_selectXaX_unfold",
+        reason = "unsupported")
+@Graph.OptOut(
+        test = "org.apache.tinkerpop.gremlin.process.traversal.step.map.SelectTest",
+        method = "g_V_asXaX_groupXmX_by_byXbothE_countX_barrier_selectXmX_selectXselectXaXX",
+        reason = "unsupported")
+@Graph.OptOut(
+        test = "org.apache.tinkerpop.gremlin.process.traversal.step.map.SelectTest",
+        method =
+                "g_V_asXaX_groupXmX_by_byXbothE_countX_barrier_selectXmX_selectXselectXaXX_byXmathX_plus_XX",
+        reason = "unsupported")
+@Graph.OptOut(
+        test = "org.apache.tinkerpop.gremlin.process.traversal.step.map.SelectTest",
+        method = "g_V_asXaX_outXknowsX_asXbX_localXselectXa_bX_byXnameXX",
+        reason = "unsupported")
+// @Graph.OptOut(
+//        test = "org.apache.tinkerpop.gremlin.process.traversal.step.map.SelectTest",
+//        method = "g_V_selectXa_bX",
+//        reason = "unsupported")
+@Graph.OptOut(
+        test = "org.apache.tinkerpop.gremlin.process.traversal.step.map.SelectTest",
+        method =
+                "g_V_hasXname_gremlinX_inEXusesX_order_byXskill_ascX_asXaX_outV_asXbX_selectXa_bX_byXskillX_byXnameX",
+        reason = "unsupported")
+@Graph.OptOut(
+        test = "org.apache.tinkerpop.gremlin.process.traversal.step.map.SelectTest",
+        method = "g_V_selectXlast_aX",
+        reason = "unsupported")
+@Graph.OptOut(
+        test = "org.apache.tinkerpop.gremlin.process.traversal.step.map.SelectTest",
+        method = "g_V_untilXout_outX_repeatXin_asXaXX_selectXaX_byXtailXlocalX_nameX",
+        reason = "unsupported")
+@Graph.OptOut(
+        test = "org.apache.tinkerpop.gremlin.process.traversal.step.map.SelectTest",
+        method = "g_V_asXa_bX_out_asXcX_path_selectXkeysX",
+        reason = "unsupported")
+@Graph.OptOut(
+        test = "org.apache.tinkerpop.gremlin.process.traversal.step.map.SelectTest",
+        method = "g_VX1X_groupXaX_byXconstantXaXX_byXnameX_selectXaX_selectXaX",
+        reason = "unsupported")
+// @Graph.OptOut(
+//        test = "org.apache.tinkerpop.gremlin.process.traversal.step.map.SelectTest",
+//        method = "g_V_selectXaX_count",
+//        reason = "unsupported")
+@Graph.OptOut(
+        test = "org.apache.tinkerpop.gremlin.process.traversal.step.map.SelectTest",
+        method = "g_V_asXaX_outXknowsX_asXaX_selectXall_constantXaXX",
+        reason = "unsupported")
+@Graph.OptOut(
+        test = "org.apache.tinkerpop.gremlin.process.traversal.step.map.SelectTest",
+        method =
+                "g_V_outE_weight_groupCount_selectXvaluesX_unfold_groupCount_selectXvaluesX_unfold",
+        reason = "unsupported")
+// @Graph.OptOut(
+//        test = "org.apache.tinkerpop.gremlin.process.traversal.step.map.SelectTest",
+//        method = "g_V_selectXaX",
+//        reason = "unsupported")
+@Graph.OptOut(
+        test = "org.apache.tinkerpop.gremlin.process.traversal.step.map.SelectTest",
+        method = "g_V_valueMap_selectXall_a_bX",
+        reason = "unsupported")
+// @Graph.OptOut(
+//        test = "org.apache.tinkerpop.gremlin.process.traversal.step.map.SelectTest",
+//        method = "g_V_valueMap_selectXa_bX",
+//        reason = "unsupported")
+@Graph.OptOut(
+        test = "org.apache.tinkerpop.gremlin.process.traversal.step.map.SelectTest",
+        method =
+                "g_V_hasLabelXsoftwareX_asXnameX_asXlanguageX_asXcreatorsX_selectXname_language_creatorsX_byXnameX_byXlangX_byXinXcreatedX_name_fold_orderXlocalXX",
+        reason = "unsupported")
+@Graph.OptOut(
+        test = "org.apache.tinkerpop.gremlin.process.traversal.step.map.SelectTest",
+        method = "g_V_selectXfirst_a_bX",
+        reason = "unsupported")
+@Graph.OptOut(
+        test = "org.apache.tinkerpop.gremlin.process.traversal.step.map.SelectTest",
+        method = "g_VX1X_asXaX_repeatXout_asXaXX_timesX2X_selectXfirst_aX",
+        reason = "unsupported")
+@Graph.OptOut(
+        test = "org.apache.tinkerpop.gremlin.process.traversal.step.map.SelectTest",
+        method = "g_V_selectXall_a_bX",
+        reason = "unsupported")
+@Graph.OptOut(
+        test = "org.apache.tinkerpop.gremlin.process.traversal.step.map.SelectTest",
+        method = "g_V_hasXperson_name_markoX_count_asXaX_unionXidentity_identityX_selectXaX",
+        reason = "unsupported")
+@Graph.OptOut(
+        test = "org.apache.tinkerpop.gremlin.process.traversal.step.map.SelectTest",
+        method = "g_V_outE_weight_groupCount_selectXvaluesX_unfold",
+        reason = "unsupported")
+// @Graph.OptOut(
+//        test = "org.apache.tinkerpop.gremlin.process.traversal.step.map.SelectTest",
+//        method = "g_V_valueMap_selectXaX",
+//        reason = "unsupported")
+@Graph.OptOut(
+        test = "org.apache.tinkerpop.gremlin.process.traversal.step.map.VertexTest",
+        method = "g_VX4X_bothE_hasXweight_lt_1X_otherV",
+        reason = "unsupported")
+@Graph.OptOut(
+        test = "org.apache.tinkerpop.gremlin.process.traversal.step.map.VertexTest",
+        method = "g_V_hasLabelXloopsX_bothEXselfX",
+        reason = "unsupported")
+@Graph.OptOut(
+        test = "org.apache.tinkerpop.gremlin.process.traversal.step.map.VertexTest",
+        method = "g_VX1_2_3_4X_name",
+        reason = "unsupported")
+@Graph.OptOut(
+        test = "org.apache.tinkerpop.gremlin.process.traversal.step.map.VertexTest",
+        method = "g_V_hasLabelXpersonX_V_hasLabelXsoftwareX_name",
+        reason = "unsupported")
+@Graph.OptOut(
+        test = "org.apache.tinkerpop.gremlin.process.traversal.step.map.VertexTest",
+        method = "g_VX1X_outEXknowsX_bothV_name",
+        reason = "unsupported")
+@Graph.OptOut(
+        test = "org.apache.tinkerpop.gremlin.process.traversal.step.map.VertexTest",
+        method = "g_V_hasLabelXloopsX_bothXselfX",
+        reason = "unsupported")
+@Graph.OptOut(
+        test = "org.apache.tinkerpop.gremlin.process.traversal.step.map.UnfoldTest",
+        method = "g_V_valueMap_unfold_mapXkeyX",
+        reason = "unsupported")
+@Graph.OptOut(
+        test = "org.apache.tinkerpop.gremlin.process.traversal.step.map.UnfoldTest",
+        method = "g_V_localXoutE_foldX_unfold",
+        reason = "unsupported")
+@Graph.OptOut(
+        test = "org.apache.tinkerpop.gremlin.process.traversal.step.map.UnfoldTest",
+        method = "g_VX1X_repeatXboth_simplePathX_untilXhasIdX6XX_path_byXnameX_unfold",
+        reason = "unsupported")
+@Graph.OptOut(
+        test = "org.apache.tinkerpop.gremlin.process.traversal.step.sideEffect.GroupTest",
+        method = "g_V_group_byXnameX",
+        reason = "unsupported")
+@Graph.OptOut(
+        test = "org.apache.tinkerpop.gremlin.process.traversal.step.sideEffect.GroupTest",
+        method = "g_V_repeatXbothXfollowedByXX_timesX2X_groupXaX_byXsongTypeX_byXcountX_capXaX",
+        reason = "unsupported")
+@Graph.OptOut(
+        test = "org.apache.tinkerpop.gremlin.process.traversal.step.sideEffect.GroupTest",
+        method =
+                "g_withSideEffectXa__marko_666_noone_blahX_V_groupXaX_byXnameX_byXoutE_label_foldX_capXaX",
+        reason = "unsupported")
+@Graph.OptOut(
+        test = "org.apache.tinkerpop.gremlin.process.traversal.step.sideEffect.GroupTest",
+        method = "g_V_repeatXout_groupXaX_byXnameX_byXcountX_timesX2X_capXaX",
+        reason = "unsupported")
+@Graph.OptOut(
+        test = "org.apache.tinkerpop.gremlin.process.traversal.step.sideEffect.GroupTest",
+        method = "g_V_group_byXnameX_by",
+        reason = "unsupported")
+@Graph.OptOut(
+        test = "org.apache.tinkerpop.gremlin.process.traversal.step.sideEffect.GroupTest",
+        method = "g_V_group_byXlabelX_byXbothE_groupXaX_byXlabelX_byXweight_sumX_weight_sumX",
+        reason = "unsupported")
+@Graph.OptOut(
+        test = "org.apache.tinkerpop.gremlin.process.traversal.step.sideEffect.GroupTest",
+        method =
+                "g_V_hasLabelXpersonX_asXpX_outXcreatedX_group_byXnameX_byXselectXpX_valuesXageX_sumX",
+        reason = "unsupported")
+@Graph.OptOut(
+        test = "org.apache.tinkerpop.gremlin.process.traversal.step.sideEffect.GroupTest",
+        method =
+                "g_V_hasLabelXsongX_groupXaX_byXnameX_byXproperties_groupCount_byXlabelXX_out_capXaX",
+        reason = "unsupported")
+@Graph.OptOut(
+        test = "org.apache.tinkerpop.gremlin.process.traversal.step.sideEffect.GroupTest",
+        method = "g_V_hasXlangX_groupXaX_byXlangX_byXnameX_out_capXaX",
+        reason = "unsupported")
+// @Graph.OptOut(
+//        test = "org.apache.tinkerpop.gremlin.process.traversal.step.sideEffect.GroupTest",
+//        method = "g_V_group_byXoutE_countX_byXnameX",
+//        reason = "unsupported")
+@Graph.OptOut(
+        test = "org.apache.tinkerpop.gremlin.process.traversal.step.sideEffect.GroupTest",
+        method = "g_V_groupXaX_byXlabelX_byXoutE_weight_sumX_capXaX",
+        reason = "unsupported")
+@Graph.OptOut(
+        test = "org.apache.tinkerpop.gremlin.process.traversal.step.sideEffect.GroupCountTest",
+        method =
+                "g_V_unionXoutXknowsX__outXcreatedX_inXcreatedXX_groupCount_selectXvaluesX_unfold_sum",
+        reason = "unsupported")
+@Graph.OptOut(
+        test = "org.apache.tinkerpop.gremlin.process.traversal.step.sideEffect.GroupCountTest",
+        method =
+                "g_V_unionXrepeatXoutX_timesX2X_groupCountXmX_byXlangXX__repeatXinX_timesX2X_groupCountXmX_byXnameXX_capXmX",
+        reason = "unsupported")
+// @Graph.OptOut(
+//        test = "org.apache.tinkerpop.gremlin.process.traversal.step.sideEffect.GroupCountTest",
+//        method = "g_V_groupCount_byXbothE_countX",
+//        reason = "unsupported")
+@Graph.OptOut(
+        test = "org.apache.tinkerpop.gremlin.process.traversal.step.sideEffect.GroupCountTest",
+        method = "g_V_repeatXout_groupCountXaX_byXnameXX_timesX2X_capXaX",
+        reason = "unsupported")
+// @Graph.OptOut(
+//        test = "org.apache.tinkerpop.gremlin.process.traversal.step.sideEffect.GroupCountTest",
+//        method = "g_V_outXcreatedX_groupCount_byXnameX",
+//        reason = "unsupported")
+@Graph.OptOut(
+        test = "org.apache.tinkerpop.gremlin.process.traversal.step.sideEffect.GroupCountTest",
+        method = "g_V_outXcreatedX_groupCountXxX_capXxX",
+        reason = "unsupported")
+@Graph.OptOut(
+        test = "org.apache.tinkerpop.gremlin.process.traversal.step.sideEffect.GroupCountTest",
+        method = "g_V_both_groupCountXaX_out_capXaX_selectXkeysX_unfold_both_groupCountXaX_capXaX",
+        reason = "unsupported")
+// @Graph.OptOut(
+//        test = "org.apache.tinkerpop.gremlin.process.traversal.step.sideEffect.GroupCountTest",
+//        method = "g_V_outXcreatedX_name_groupCount",
+//        reason = "unsupported")
+@Graph.OptOut(
+        test = "org.apache.tinkerpop.gremlin.process.traversal.step.sideEffect.GroupCountTest",
+        method = "g_V_outXcreatedX_groupCountXaX_byXnameX_capXaX",
+        reason = "unsupported")
+@Graph.OptOut(
+        test = "org.apache.tinkerpop.gremlin.process.traversal.step.sideEffect.GroupCountTest",
+        method = "g_V_outXcreatedX_name_groupCountXaX_capXaX",
+        reason = "unsupported")
+@Graph.OptOut(
+        test = "org.apache.tinkerpop.gremlin.process.traversal.step.sideEffect.GroupCountTest",
+        method =
+                "g_V_both_groupCountXaX_byXlabelX_asXbX_barrier_whereXselectXaX_selectXsoftwareX_isXgtX2XXX_selectXbX_name",
+        reason = "unsupported")
+@Graph.OptOut(
+        test = "org.apache.tinkerpop.gremlin.process.traversal.step.sideEffect.GroupCountTest",
+        method = "g_V_hasXnoX_groupCountXaX_capXaX",
+        reason = "unsupported")
+@Graph.OptOut(
+        test = "org.apache.tinkerpop.gremlin.process.traversal.step.branch.RepeatTest",
+        method =
+                "g_V_repeatXoutXknowsXX_untilXrepeatXoutXcreatedXX_emitXhasXname_lopXXX_path_byXnameX",
+        reason = "unsupported")
+@Graph.OptOut(
+        test = "org.apache.tinkerpop.gremlin.process.traversal.step.branch.RepeatTest",
+        method = "g_V_repeatXoutX_timesX2X_emit_path",
+        reason = "unsupported")
+@Graph.OptOut(
+        test = "org.apache.tinkerpop.gremlin.process.traversal.step.branch.RepeatTest",
+        method = "g_V_repeatXout_repeatXoutX_timesX1XX_timesX1X_limitX1X_path_by_name",
+        reason = "unsupported")
+@Graph.OptOut(
+        test = "org.apache.tinkerpop.gremlin.process.traversal.step.branch.RepeatTest",
+        method = "g_V_emit_repeatXoutX_timesX2X_path",
+        reason = "unsupported")
+@Graph.OptOut(
+        test = "org.apache.tinkerpop.gremlin.process.traversal.step.branch.RepeatTest",
+        method = "g_VX1X_repeatXoutX_untilXoutE_count_isX0XX_name",
+        reason = "unsupported")
+@Graph.OptOut(
+        test = "org.apache.tinkerpop.gremlin.process.traversal.step.branch.RepeatTest",
+        method = "g_V_repeatXbothX_untilXname_eq_marko_or_loops_gt_1X_groupCount_byXnameX",
+        reason = "unsupported")
+@Graph.OptOut(
+        test = "org.apache.tinkerpop.gremlin.process.traversal.step.branch.RepeatTest",
+        method = "g_VX1X_repeatXgroupCountXmX_byXloopsX_outX_timesX3X_capXmX",
+        reason = "unsupported")
+@Graph.OptOut(
+        test = "org.apache.tinkerpop.gremlin.process.traversal.step.branch.RepeatTest",
+        method =
+                "g_VX1X_repeatXrepeatXunionXout_uses_out_traversesXX_whereXloops_isX0X_timesX1X_timeX2X_name",
+        reason = "unsupported")
+@Graph.OptOut(
+        test = "org.apache.tinkerpop.gremlin.process.traversal.step.branch.RepeatTest",
+        method = "g_VX1X_emitXhasXlabel_personXX_repeatXoutX_name",
+        reason = "unsupported")
+@Graph.OptOut(
+        test = "org.apache.tinkerpop.gremlin.process.traversal.step.branch.RepeatTest",
+        method =
+                "g_V_hasXname_markoX_repeatXoutE_inV_simplePathX_untilXhasXname_rippleXX_path_byXnameX_byXlabelX",
+        reason = "unsupported")
+@Graph.OptOut(
+        test = "org.apache.tinkerpop.gremlin.process.traversal.step.branch.RepeatTest",
+        method =
+                "g_V_untilXconstantXtrueXX_repeatXrepeatXout_createdXX_untilXhasXname_rippleXXXemit_lang",
+        reason = "unsupported")
+@Graph.OptOut(
+        test = "org.apache.tinkerpop.gremlin.process.traversal.step.branch.RepeatTest",
+        method =
+                "g_VX6X_repeatXa_bothXcreatedX_simplePathX_emitXrepeatXb_bothXknowsXX_untilXloopsXbX_asXb_whereXloopsXaX_asXbX_hasXname_vadasXX_dedup_name",
+        reason = "unsupported")
+@Graph.OptOut(
+        test = "org.apache.tinkerpop.gremlin.process.traversal.step.branch.RepeatTest",
+        method =
+                "g_VX3X_repeatXbothX_createdXX_untilXloops_is_40XXemit_repeatXin_knowsXX_emit_loopsXisX1Xdedup_values",
+        reason = "unsupported")
+@Graph.OptOut(
+        test = "org.apache.tinkerpop.gremlin.process.traversal.step.branch.RepeatTest",
+        method = "g_V_hasXloop_name_loopX_repeatXinX_timesX5X_path_by_name",
+        reason = "unsupported")
+@Graph.OptOut(
+        test = "org.apache.tinkerpop.gremlin.process.traversal.step.branch.RepeatTest",
+        method = "g_V_repeatXgroupCountXmX_byXnameX_outX_timesX2X_capXmX",
+        reason = "unsupported")
+@Graph.OptOut(
+        test = "org.apache.tinkerpop.gremlin.process.traversal.step.branch.RepeatTest",
+        method = "g_V_repeatXrepeatXout_createdXX_untilXhasXname_rippleXXXemit_lang",
+        reason = "unsupported")
+@Graph.OptOut(
+        test = "org.apache.tinkerpop.gremlin.process.traversal.step.branch.RepeatTest",
+        method = "g_V_emit_repeatXa_outXknows_filterXloops_isX0XX_lang",
+        reason = "unsupported")
+@Graph.OptOut(
+        test = "org.apache.tinkerpop.gremlin.process.traversal.step.branch.RepeatTest",
+        method = "g_V_repeatXoutX_timesX2X_emit",
+        reason = "unsupported")
+@Graph.OptOut(
+        test = "org.apache.tinkerpop.gremlin.process.traversal.step.branch.RepeatTest",
+        method = "g_V_emit_timesX2X_repeatXoutX_path",
+        reason = "unsupported")
+@Graph.OptOut(
+        test = "org.apache.tinkerpop.gremlin.process.traversal.step.branch.UnionTest",
+        method = "g_VX1_2X_localXunionXoutE_count__inE_count__outE_weight_sumXX",
+        reason = "unsupported")
+@Graph.OptOut(
+        test = "org.apache.tinkerpop.gremlin.process.traversal.step.branch.UnionTest",
+        method = "g_V_chooseXlabel_is_person__unionX__out_lang__out_nameX__in_labelX",
+        reason = "unsupported")
+@Graph.OptOut(
+        test = "org.apache.tinkerpop.gremlin.process.traversal.step.branch.UnionTest",
+        method = "g_VX1_2X_localXunionXcountXX",
+        reason = "unsupported")
+@Graph.OptOut(
+        test = "org.apache.tinkerpop.gremlin.process.traversal.step.branch.UnionTest",
+        method = "g_V_chooseXlabel_is_person__unionX__out_lang__out_nameX__in_labelX_groupCount",
+        reason = "unsupported")
+@Graph.OptOut(
+        test = "org.apache.tinkerpop.gremlin.process.traversal.step.branch.UnionTest",
+        method =
+                "g_V_unionXrepeatXunionXoutXcreatedX__inXcreatedXX_timesX2X__repeatXunionXinXcreatedX__outXcreatedXX_timesX2XX_label_groupCount",
+        reason = "unsupported")
+@Graph.OptOut(
+        test = "org.apache.tinkerpop.gremlin.process.traversal.step.filter.DedupTest",
+        method =
+                "g_V_asXaX_repeatXbothX_timesX3X_emit_name_asXbX_group_byXselectXaXX_byXselectXbX_dedup_order_foldX_selectXvaluesX_unfold_dedup",
+        reason = "unsupported")
+// @Graph.OptOut(
+//        test = "org.apache.tinkerpop.gremlin.process.traversal.step.filter.DedupTest",
+//        method = "g_V_both_both_dedup_byXlabelX",
+//        reason = "unsupported")
+@Graph.OptOut(
+        test = "org.apache.tinkerpop.gremlin.process.traversal.step.filter.DedupTest",
+        method = "g_V_both_hasXlabel_softwareX_dedup_byXlangX_name",
+        reason = "unsupported")
+@Graph.OptOut(
+        test = "org.apache.tinkerpop.gremlin.process.traversal.step.filter.DedupTest",
+        method = "g_V_out_asXxX_in_asXyX_selectXx_yX_byXnameX_fold_dedupXlocal_x_yX_unfold",
+        reason = "unsupported")
+@Graph.OptOut(
+        test = "org.apache.tinkerpop.gremlin.process.traversal.step.filter.DedupTest",
+        method = "g_V_both_name_order_byXa_bX_dedup_value",
+        reason = "unsupported")
+@Graph.OptOut(
+        test = "org.apache.tinkerpop.gremlin.process.traversal.step.filter.DedupTest",
+        method = "g_V_asXaX_outXcreatedX_asXbX_inXcreatedX_asXcX_dedupXa_bX_path",
+        reason = "unsupported")
+@Graph.OptOut(
+        test = "org.apache.tinkerpop.gremlin.process.traversal.step.filter.DedupTest",
+        method = "g_V_both_both_dedup_byXoutE_countX_name",
+        reason = "unsupported")
+// @Graph.OptOut(
+//        test = "org.apache.tinkerpop.gremlin.process.traversal.step.filter.DedupTest",
+//        method = "g_V_asXaX_both_asXbX_dedupXa_bX_byXlabelX_selectXa_bX",
+//        reason = "unsupported")
+@Graph.OptOut(
+        test = "org.apache.tinkerpop.gremlin.process.traversal.step.filter.DedupTest",
+        method =
+                "g_V_both_group_by_byXout_dedup_foldX_unfold_selectXvaluesX_unfold_out_order_byXnameX_limitX1X_valuesXnameX",
+        reason = "unsupported")
+@Graph.OptOut(
+        test = "org.apache.tinkerpop.gremlin.process.traversal.step.filter.FilterTest",
+        method = "g_V_filterXfalseX",
+        reason = "unsupported")
+@Graph.OptOut(
+        test = "org.apache.tinkerpop.gremlin.process.traversal.step.filter.FilterTest",
+        method = "g_VX1X_out_filterXage_gt_30X",
+        reason = "unsupported")
+@Graph.OptOut(
+        test = "org.apache.tinkerpop.gremlin.process.traversal.step.filter.FilterTest",
+        method = "g_E_filterXfalseX",
+        reason = "unsupported")
+@Graph.OptOut(
+        test = "org.apache.tinkerpop.gremlin.process.traversal.step.filter.FilterTest",
+        method = "g_VX1X_filterXage_gt_30X",
+        reason = "unsupported")
+@Graph.OptOut(
+        test = "org.apache.tinkerpop.gremlin.process.traversal.step.filter.FilterTest",
+        method = "g_V_filterXname_startsWith_m_OR_name_startsWith_pX",
+        reason = "unsupported")
+@Graph.OptOut(
+        test = "org.apache.tinkerpop.gremlin.process.traversal.step.filter.FilterTest",
+        method = "g_V_filterXtrueX",
+        reason = "unsupported")
+@Graph.OptOut(
+        test = "org.apache.tinkerpop.gremlin.process.traversal.step.filter.FilterTest",
+        method = "g_E_filterXtrueX",
+        reason = "unsupported")
+@Graph.OptOut(
+        test = "org.apache.tinkerpop.gremlin.process.traversal.step.filter.FilterTest",
+        method = "g_V_filterXlang_eq_javaX",
+        reason = "unsupported")
+@Graph.OptOut(
+        test = "org.apache.tinkerpop.gremlin.process.traversal.step.filter.FilterTest",
+        method = "g_VX2X_filterXage_gt_30X",
+        reason = "unsupported")
+@Graph.OptOut(
+        test = "org.apache.tinkerpop.gremlin.process.traversal.step.sideEffect.GroupTest",
+        method = "g_V_repeatXbothXfollowedByXX_timesX2X_group_byXsongTypeX_byXcountX",
+        reason = "unsupported")
+@Graph.OptOut(
+        test = "org.apache.tinkerpop.gremlin.process.traversal.step.sideEffect.GroupTest",
+        method = "g_V_groupXaX_byXnameX_capXaX",
+        reason = "unsupported")
+@Graph.OptOut(
+        test = "org.apache.tinkerpop.gremlin.process.traversal.step.sideEffect.GroupTest",
+        method = "g_V_out_group_byXlabelX_selectXpersonX_unfold_outXcreatedX_name_limitX2X",
+        reason = "unsupported")
+@Graph.OptOut(
+        test = "org.apache.tinkerpop.gremlin.process.traversal.step.sideEffect.GroupTest",
+        method =
+                "g_V_repeatXunionXoutXknowsX_groupXaX_byXageX__outXcreatedX_groupXbX_byXnameX_byXcountXX_groupXaX_byXnameXX_timesX2X_capXa_bX",
+        reason = "unsupported")
+@Graph.OptOut(
+        test = "org.apache.tinkerpop.gremlin.process.traversal.step.sideEffect.GroupTest",
+        method = "g_V_hasLabelXsongX_group_byXnameX_byXproperties_groupCount_byXlabelXX",
+        reason = "unsupported")
+@Graph.OptOut(
+        test = "org.apache.tinkerpop.gremlin.process.traversal.step.sideEffect.GroupTest",
+        method = "g_V_group_byXname_substring_1X_byXconstantX1XX",
+        reason = "unsupported")
+@Graph.OptOut(
+        test = "org.apache.tinkerpop.gremlin.process.traversal.step.sideEffect.GroupTest",
+        method = "g_V_groupXmX_byXnameX_byXinXknowsX_nameX_capXmX",
+        reason = "unsupported")
+@Graph.OptOut(
+        test = "org.apache.tinkerpop.gremlin.process.traversal.step.sideEffect.GroupTest",
+        method = "g_V_groupXaX_byXname_substring_1X_byXconstantX1XX_capXaX",
+        reason = "unsupported")
+@Graph.OptOut(
+        test = "org.apache.tinkerpop.gremlin.process.traversal.step.sideEffect.GroupTest",
+        method = "g_V_outXfollowedByX_group_byXsongTypeX_byXbothE_group_byXlabelX_byXweight_sumXX",
+        reason = "unsupported")
+@Graph.OptOut(
+        test = "org.apache.tinkerpop.gremlin.process.traversal.step.map.CountTest",
+        method = "g_V_hasXnoX_count",
+        reason = "unsupported")
+@Graph.OptOut(
+        test = "org.apache.tinkerpop.gremlin.process.traversal.step.map.PathTest",
+        method = "g_VX1X_name_path",
+        reason = "unsupported")
+@Graph.OptOut(
+        test = "org.apache.tinkerpop.gremlin.process.traversal.step.sideEffect.GroupTest",
+        method = "g_V_group_byXbothE_countX_byXgroup_byXlabelXX",
+        reason = "unsupported")
+@Graph.OptOut(
+        test = "org.apache.tinkerpop.gremlin.process.traversal.step.sideEffect.GroupCountTest",
+        method = "g_V_hasXnoX_groupCount",
+        reason = "unsupported")
+@Graph.OptOut(
+        test = "org.apache.tinkerpop.gremlin.process.traversal.step.filter.CyclicPathTest",
+        method = "g_VX1X_asXaX_outXcreatedX_asXbX_inXcreatedX_asXcX_cyclicPath_fromXaX_toXbX_path",
+        reason = "unsupported")
+@Graph.OptOut(
+        test = "org.apache.tinkerpop.gremlin.process.traversal.step.map.CountTest",
+        method = "g_V_repeatXoutX_timesX3X_count",
+        reason = "unsupported")
+@Graph.OptOut(
+        test = "org.apache.tinkerpop.gremlin.process.traversal.step.map.CountTest",
+        method = "g_V_repeatXoutX_timesX8X_count",
+        reason = "unsupported")
+@Graph.OptOut(
+        test = "org.apache.tinkerpop.gremlin.process.traversal.step.map.PathTest",
+        method = "g_V_asXaX_hasXname_markoX_asXbX_hasXage_29X_asXcX_path",
+        reason = "unsupported")
+@Graph.OptOut(
+        test = "org.apache.tinkerpop.gremlin.process.traversal.step.map.PathTest",
+        method = "g_V_out_out_path_byXnameX_byXageX",
+        reason = "unsupported")
+@Graph.OptOut(
+        test = "org.apache.tinkerpop.gremlin.process.traversal.step.map.PathTest",
+        method = "g_V_repeatXoutX_timesX2X_path_byXitX_byXnameX_byXlangX",
+        reason = "unsupported")
+@Graph.OptOut(
+        test = "org.apache.tinkerpop.gremlin.process.traversal.step.map.PathTest",
+        method = "g_VX1X_out_path_byXageX_byXnameX",
+        reason = "unsupported")
+@Graph.OptOut(
+        test = "org.apache.tinkerpop.gremlin.process.traversal.step.map.PathTest",
+        method = "g_V_asXaX_out_asXbX_out_asXcX_path_fromXbX_toXcX_byXnameX",
+        reason = "unsupported")
+
+// todo(siyuan): vineyard edge id has been changed
+@Graph.OptOut(
+        test = "org.apache.tinkerpop.gremlin.process.traversal.step.map.VertexTest",
+        method = "g_E",
+        reason = "edge id from vineyard has been changed")
+@Graph.OptOut(
+        test = "org.apache.tinkerpop.gremlin.process.traversal.step.map.VertexTest",
+        method = "g_VX1X_outE",
+        reason = "edge id from vineyard has been changed")
+@Graph.OptOut(
+        test = "org.apache.tinkerpop.gremlin.process.traversal.step.map.VertexTest",
+        method = "g_VX4X_bothE",
+        reason = "edge id from vineyard has been changed")
+
+// todo: return label is integer
+// @Graph.OptOut(
+//        test = "org.apache.tinkerpop.gremlin.process.traversal.step.map.VertexTest",
+//        method = "g_VX1X_outE",
+//        reason = "returned label is id")
+// @Graph.OptOut(
+//        test = "org.apache.tinkerpop.gremlin.process.traversal.step.map.VertexTest",
+//        method = "g_VX4X_bothEXcreatedX",
+//        reason = "returned label is id")
+// @Graph.OptOut(
+//        test = "org.apache.tinkerpop.gremlin.process.traversal.step.map.VertexTest",
+//        method = "g_VX4X_bothE",
+//        reason = "returned label is id")
+// @Graph.OptOut(
+//        test = "org.apache.tinkerpop.gremlin.process.traversal.step.filter.HasTest",
+//        method = "g_E_hasXlabelXknowsX",
+//        reason = "returned label is id")
+// @Graph.OptOut(
+//        test = "org.apache.tinkerpop.gremlin.process.traversal.step.map.VertexTest",
+//        method = "g_VX2X_inE",
+//        reason = "returned label is id")
+// @Graph.OptOut(
+//        method =
+//
+// "g_VX1X_outEXknowsX_asXhereX_hasXweight_1X_asXfakeX_inV_hasXname_joshX_selectXhereX",
+//        test = "org.apache.tinkerpop.gremlin.process.traversal.step.map.SelectTest",
+//        reason = "returned label is id")
+// @Graph.OptOut(
+//        method = "g_VX1X_outEXknowsX_asXhereX_hasXweight_1X_inV_hasXname_joshX_selectXhereX",
+//        test = "org.apache.tinkerpop.gremlin.process.traversal.step.map.SelectTest",
+//        reason = "returned label is id")
+// @Graph.OptOut(
+//        method = "g_VX1X_outEXknowsX_hasXweight_1X_asXhereX_inV_hasXname_joshX_selectXhereX",
+//        test = "org.apache.tinkerpop.gremlin.process.traversal.step.map.SelectTest",
+//        reason = "returned label is id")
+// @Graph.OptOut(
+//        method = "g_VX1X_outE_asXhereX_inV_hasXname_vadasX_selectXhereX",
+//        test = "org.apache.tinkerpop.gremlin.process.traversal.step.map.SelectTest",
+//        reason = "returned label is id")
+
+// add more ignored tests which are out of ir range
+@Graph.OptOut(
+        test = "org.apache.tinkerpop.gremlin.process.traversal.step.branch.RepeatTest",
+        method = "g_V_repeatXoutX_timesX2X",
+        reason = "repeat is unsupported")
+@Graph.OptOut(
+        test = "org.apache.tinkerpop.gremlin.process.traversal.step.branch.RepeatTest",
+        method = "g_VX1X_timesX2X_repeatXoutX_name",
+        reason = "repeat is unsupported")
+@Graph.OptOut(
+        test = "org.apache.tinkerpop.gremlin.process.traversal.step.branch.RepeatTest",
+        method = "g_V_repeatXbothX_timesX10X_asXaX_out_asXbX_selectXa_bX",
+        reason = "repeat is unsupported")
+@Graph.OptOut(
+        test = "org.apache.tinkerpop.gremlin.process.traversal.step.branch.RepeatTest",
+        method = "g_V_repeatXoutX_timesX2X_repeatXinX_timesX2X_name",
+        reason = "repeat is unsupported")
+@Graph.OptOut(
+        test = "org.apache.tinkerpop.gremlin.process.traversal.step.branch.UnionTest",
+        method = "g_VX1X_unionXrepeatXoutX_timesX2X__outX_name",
+        reason = "repeat is unsupported")
+@Graph.OptOut(
+        test = "org.apache.tinkerpop.gremlin.process.traversal.step.filter.CyclicPathTest",
+        method = "g_VX1X_outXcreatedX_inXcreatedX_cyclicPath_path",
+        reason = "cyclicPath is unsupported")
+@Graph.OptOut(
+        test = "org.apache.tinkerpop.gremlin.process.traversal.step.filter.CyclicPathTest",
+        method = "g_VX1X_outXcreatedX_inXcreatedX_cyclicPath",
+        reason = "cyclicPath is unsupported")
+@Graph.OptOut(
+        test = "org.apache.tinkerpop.gremlin.process.traversal.step.filter.DedupTest",
+        method = "g_V_both_properties_dedup_count",
+        reason = "properties is unsupported")
+@Graph.OptOut(
+        test = "org.apache.tinkerpop.gremlin.process.traversal.step.filter.DedupTest",
+        method = "g_V_bothE_properties_dedup_count",
+        reason = "properties is unsupported")
+@Graph.OptOut(
+        test = "org.apache.tinkerpop.gremlin.process.traversal.step.filter.DedupTest",
+        method = "g_V_both_properties_properties_dedup_count",
+        reason = "properties is unsupported")
+@Graph.OptOut(
+        test = "org.apache.tinkerpop.gremlin.process.traversal.step.filter.HasTest",
+        method = "g_VXv1X_hasXage_gt_30X",
+        reason = "object id is unsupported")
+@Graph.OptOut(
+        test = "org.apache.tinkerpop.gremlin.process.traversal.step.filter.HasTest",
+        method = "g_VXv4X_hasXage_gt_30X",
+        reason = "object id is unsupported")
+@Graph.OptOut(
+        test = "org.apache.tinkerpop.gremlin.process.traversal.step.filter.HasTest",
+        method = "g_V_hasXk_withinXcXX_valuesXkX",
+        reason = "addV is unsupported")
+@Graph.OptOut(
+        test = "org.apache.tinkerpop.gremlin.process.traversal.step.filter.SimplePathTest",
+        method = "g_VX1X_outXcreatedX_inXcreatedX_simplePath",
+        reason = "simplePath is unsupported")
+@Graph.OptOut(
+        test = "org.apache.tinkerpop.gremlin.process.traversal.step.filter.SimplePathTest",
+        method = "g_V_repeatXboth_simplePathX_timesX3X_path",
+        reason = "simplePath is unsupported")
+@Graph.OptOut(
+        test = "org.apache.tinkerpop.gremlin.process.traversal.step.map.GraphTest",
+        method = "g_VX1X_V_valuesXnameX",
+        reason = "g.V().V() is unsupported")
+@Graph.OptOut(
+        test = "org.apache.tinkerpop.gremlin.process.traversal.step.map.SelectTest",
+        method = "g_VX1X_asXaX_repeatXout_asXaXX_timesX2X_selectXlast_aX",
+        reason = "repeat is unsupported")
+@Graph.OptOut(
+        test = "org.apache.tinkerpop.gremlin.process.traversal.step.map.VertexTest",
+        method = "g_VXv1X_out",
+        reason = "object id is unsupported")
+@Graph.OptOut(
+        test = "org.apache.tinkerpop.gremlin.process.traversal.step.map.VertexTest",
+        method = "g_VX1X_to_XOUT_knowsX",
+        reason = "to(Direction.OUT,\"knows\") is unsupported")
+@Graph.OptOut(
+        test = "org.apache.tinkerpop.gremlin.process.traversal.step.map.VertexTest",
+        method = "g_VXlistXv1_v2_v3XX_name",
+        reason = "object id is unsupported")
+@Graph.OptOut(
+        test = "org.apache.tinkerpop.gremlin.process.traversal.step.map.ValueMapTest",
+        method = "g_VX1X_valueMapXname_locationX_byXunfoldX_by",
+        reason = "valueMap().by(...) is unsupported")
+@Graph.OptOut(
+        test = "org.apache.tinkerpop.gremlin.process.traversal.step.map.ValueMapTest",
+        method = "g_V_valueMap_withXtokensX",
+        reason = "valueMap(true) is unsupported")
+@Graph.OptOut(
+        test = "org.apache.tinkerpop.gremlin.process.traversal.step.map.ValueMapTest",
+        method = "g_V_valueMapXname_ageX_withXtokensX",
+        reason = "valueMap(true) is unsupported")
+@Graph.OptOut(
+        test = "org.apache.tinkerpop.gremlin.process.traversal.step.map.ValueMapTest",
+        method = "g_V_valueMapXname_ageX_withXtokens_idsX_byXunfoldX",
+        reason = "valueMap().with(...) is unsupported")
+@Graph.OptOut(
+        test = "org.apache.tinkerpop.gremlin.process.traversal.step.map.ValueMapTest",
+        method = "g_V_hasLabelXpersonX_filterXoutEXcreatedXX_valueMap_withXtokensX",
+        reason = "valueMap().with(...) is unsupported")
+@Graph.OptOut(
+        test = "org.apache.tinkerpop.gremlin.process.traversal.step.map.ValueMapTest",
+        method = "g_V_valueMapXname_ageX_withXtokens_labelsX_byXunfoldX",
+        reason = "valueMap().with(...) is unsupported")
+@Graph.OptOut(
+        test = "org.apache.tinkerpop.gremlin.process.traversal.step.sideEffect.GroupTest",
+        method = "g_V_groupXmX_byXlabelX_byXlabel_countX_capXmX",
+        reason = "group side effect is unsupported")
+@Graph.OptOut(
+        test = "org.apache.tinkerpop.gremlin.process.traversal.step.sideEffect.GroupCountTest",
+        method = "g_V_hasXperson_name_markoX_bothXknowsX_groupCount_byXvaluesXnameX_foldX",
+        reason = "fold() excluding group().by(...).by(fold()) is unsupported")
+// @Graph.OptOut(method="g_V_outE_asXeX_inV_asXvX_selectXeX_order_byXweight_ascX_selectXvX_valuesXnameX_dedup" , test="org.apache.tinkerpop.gremlin.process.traversal.step.filter.DedupTest", reason = "will be supported")
+// @Graph.OptOut(method="g_V_hasXperson_name_markoX_age" ,
+// test="org.apache.tinkerpop.gremlin.process.traversal.step.filter.HasTest", reason = "will be
+// supported")
+@Graph.OptOut(
+        method = "g_V_in_hasIdXneqX1XX",
+        test = "org.apache.tinkerpop.gremlin.process.traversal.step.filter.HasTest",
+        reason = "will be supported")
+@Graph.OptOut(
+        method = "g_V_hasXage_isXgt_30XX",
+        test = "org.apache.tinkerpop.gremlin.process.traversal.step.filter.HasTest",
+        reason = "will be supported")
+@Graph.OptOut(
+        method = "g_EX7X_hasXlabelXknowsX",
+        test = "org.apache.tinkerpop.gremlin.process.traversal.step.filter.HasTest",
+        reason = "will be supported")
+@Graph.OptOut(
+        method = "g_VX1X_outE_hasXweight_inside_0_06X_inV",
+        test = "org.apache.tinkerpop.gremlin.process.traversal.step.filter.HasTest",
+        reason = "will be supported")
+// @Graph.OptOut(method="g_V_valuesXageX_isXgte_29X_isXlt_34X" ,
+// test="org.apache.tinkerpop.gremlin.process.traversal.step.filter.IsTest", reason = "will be
+// supported")
+// @Graph.OptOut(method="g_V_valuesXageX_isXlte_30X" ,
+// test="org.apache.tinkerpop.gremlin.process.traversal.step.filter.IsTest", reason = "will be
+// supported")
+// @Graph.OptOut(method="g_V_valuesXageX_isX32X" ,
+// test="org.apache.tinkerpop.gremlin.process.traversal.step.filter.IsTest", reason = "will be
+// supported")
+// @Graph.OptOut(method="g_VX1X_out_limitX2X" ,
+// test="org.apache.tinkerpop.gremlin.process.traversal.step.filter.RangeTest", reason = "will be
+// supported")
+@Graph.OptOut(
+        method = "g_VX1X_outXknowsX_outEXcreatedX_rangeX0_1X_inV",
+        test = "org.apache.tinkerpop.gremlin.process.traversal.step.filter.RangeTest",
+        reason = "range is unsupported, use limit instead")
+@Graph.OptOut(
+        method = "g_VX1X_outXknowsX_outXcreatedX_rangeX0_1X",
+        test = "org.apache.tinkerpop.gremlin.process.traversal.step.filter.RangeTest",
+        reason = "range is unsupported, use limit instead")
+// @Graph.OptOut(method="g_VX1X_asXaX_outXcreatedX_inXcreatedX_whereXeqXaXX_name" ,
+// test="org.apache.tinkerpop.gremlin.process.traversal.step.filter.WhereTest", reason = "will be
+// supported")
+// @Graph.OptOut(method="g_V_asXaX_outEXcreatedX_asXbX_inV_asXcX_whereXa_gtXbX_orXeqXbXXX_byXageX_byXweightX_byXweightX_selectXa_cX_byXnameX" , test="org.apache.tinkerpop.gremlin.process.traversal.step.filter.WhereTest", reason = "will be supported")
+// @Graph.OptOut(method="g_VX1X_asXaX_outXcreatedX_inXcreatedX_whereXneqXaXX_name" ,
+// test="org.apache.tinkerpop.gremlin.process.traversal.step.filter.WhereTest", reason = "will be
+// supported")
+@Graph.OptOut(
+        method =
+                "g_VX1X_asXaX_outXcreatedX_inXcreatedX_asXbX_whereXasXbX_outXcreatedX_hasXname_rippleXX_valuesXage_nameX",
+        test = "org.apache.tinkerpop.gremlin.process.traversal.step.filter.WhereTest",
+        reason = "values('age', 'name') is unsupported")
+// @Graph.OptOut(method="g_VX1X_asXaX_outXcreatedX_inXcreatedX_asXbX_whereXa_neqXbXX_name" ,
+// test="org.apache.tinkerpop.gremlin.process.traversal.step.filter.WhereTest", reason = "will be
+// supported")
+// @Graph.OptOut(method="g_V_asXaX_outXcreatedX_whereXasXaX_name_isXjoshXX_inXcreatedX_name" ,
+// test="org.apache.tinkerpop.gremlin.process.traversal.step.filter.WhereTest", reason = "will be
+// supported")
+// @Graph.OptOut(method="g_V_asXaX_outXcreatedX_asXbX_inXcreatedX_asXcX_bothXknowsX_bothXknowsX_asXdX_whereXc__notXeqXaX_orXeqXdXXXX_selectXa_b_c_dX" , test="org.apache.tinkerpop.gremlin.process.traversal.step.filter.WhereTest", reason = "will be supported")
+// @Graph.OptOut(method="g_V_asXaX_outXcreatedX_inXcreatedX_asXbX_whereXa_gtXbXX_byXageX_selectXa_bX_byXnameX" , test="org.apache.tinkerpop.gremlin.process.traversal.step.filter.WhereTest", reason = "will be supported")
+// @Graph.OptOut(method="g_V_hasLabelXpersonX_order_byXageX" ,
+// test="org.apache.tinkerpop.gremlin.process.traversal.step.map.OrderTest", reason = "will be
+// supported")
+// @Graph.OptOut(method="g_V_asXaX_outXcreatedX_asXbX_order_byXshuffleX_selectXa_bX" ,
+// test="org.apache.tinkerpop.gremlin.process.traversal.step.map.OrderTest", reason = "will be
+// supported")
+// @Graph.OptOut(method="g_V_order_byXname_ascX_name" ,
+// test="org.apache.tinkerpop.gremlin.process.traversal.step.map.OrderTest", reason = "will be
+// supported")
+// @Graph.OptOut(method="g_V_order_byXnameX_name" ,
+// test="org.apache.tinkerpop.gremlin.process.traversal.step.map.OrderTest", reason = "will be
+// supported")
+// @Graph.OptOut(method="g_V_outE_order_byXweight_descX_weight" ,
+// test="org.apache.tinkerpop.gremlin.process.traversal.step.map.OrderTest", reason = "will be
+// supported")
+// @Graph.OptOut(method="g_V_both_hasLabelXpersonX_order_byXage_descX_limitX5X_name" ,
+// test="org.apache.tinkerpop.gremlin.process.traversal.step.map.OrderTest", reason = "will be
+// supported")
+@Graph.OptOut(
+        method = "g_VX1X_outEXcreatedX_inV_inE_outV_path",
+        test = "org.apache.tinkerpop.gremlin.process.traversal.step.map.PathTest",
+        reason = "will be supported")
+@Graph.OptOut(
+        method = "g_EX11X_propertiesXweightX_asXaX_selectXaX_byXkeyX",
+        test = "org.apache.tinkerpop.gremlin.process.traversal.step.map.SelectTest",
+        reason = "will be supported")
+@Graph.OptOut(
+        method = "g_V_asXaX_hasXname_markoX_asXbX_asXcX_selectXa_b_cX_by_byXnameX_byXageX",
+        test = "org.apache.tinkerpop.gremlin.process.traversal.step.map.SelectTest",
+        reason = "one object can only have one alias")
+// @Graph.OptOut(method="g_VX1X_asXaX_outXknowsX_asXbX_selectXa_bX" ,
+// test="org.apache.tinkerpop.gremlin.process.traversal.step.map.SelectTest", reason = "will be
+// supported")
+@Graph.OptOut(
+        method = "g_V_hasXname_isXmarkoXX_asXaX_selectXaX",
+        test = "org.apache.tinkerpop.gremlin.process.traversal.step.map.SelectTest",
+        reason = "will be supported")
+// @Graph.OptOut(method="g_V_asXaX_name_order_asXbX_selectXa_bX_byXnameX_by_XitX" ,
+// test="org.apache.tinkerpop.gremlin.process.traversal.step.map.SelectTest", reason = "will be
+// supported")
+// @Graph.OptOut(method="g_V_asXaX_whereXoutXknowsXX_selectXaX" ,
+// test="org.apache.tinkerpop.gremlin.process.traversal.step.map.SelectTest", reason = "will be
+// supported")
+@Graph.OptOut(
+        method = "g_EX11X_propertiesXweightX_asXaX_selectXaX_byXvalueX",
+        test = "org.apache.tinkerpop.gremlin.process.traversal.step.map.SelectTest",
+        reason = "will be supported")
+// @Graph.OptOut(method="g_VX1X_outE_otherV" ,
+// test="org.apache.tinkerpop.gremlin.process.traversal.step.map.VertexTest", reason = "will be
+// supported")
+@Graph.OptOut(
+        method = "g_VX1AsStringX_outXknowsX",
+        test = "org.apache.tinkerpop.gremlin.process.traversal.step.map.VertexTest",
+        reason = "will be supported")
+// @Graph.OptOut(method="g_V_out_outE_inV_inE_inV_both_name" ,
+// test="org.apache.tinkerpop.gremlin.process.traversal.step.map.VertexTest", reason = "will be
+// supported")
+@Graph.OptOut(
+        method = "g_EXe11X",
+        test = "org.apache.tinkerpop.gremlin.process.traversal.step.map.VertexTest",
+        reason = "will be supported")
+// @Graph.OptOut(method="g_EX11X" ,
+// test="org.apache.tinkerpop.gremlin.process.traversal.step.map.VertexTest", reason = "will be
+// supported")
+// @Graph.OptOut(method="g_V_outE_hasXweight_1X_outV" ,
+// test="org.apache.tinkerpop.gremlin.process.traversal.step.map.VertexTest", reason = "will be
+// supported")
+@Graph.OptOut(
+        method = "g_EXlistXe7_e11XX",
+        test = "org.apache.tinkerpop.gremlin.process.traversal.step.map.VertexTest",
+        reason = "will be supported")
+@Graph.OptOut(
+        method = "g_EX11AsStringX",
+        test = "org.apache.tinkerpop.gremlin.process.traversal.step.map.VertexTest",
+        reason = "will be supported")
+@Graph.OptOut(
+        method = "g_EXe7_e11X",
+        test = "org.apache.tinkerpop.gremlin.process.traversal.step.map.VertexTest",
+        reason = "will be supported")
+// @Graph.OptOut(method="g_V_valueMapXname_ageX" ,
+// test="org.apache.tinkerpop.gremlin.process.traversal.step.map.ValueMapTest", reason = "will be
+// supported")
+@Graph.OptOut(
+        method = "g_VX1X_outXcreatedX_valueMap",
+        test = "org.apache.tinkerpop.gremlin.process.traversal.step.map.ValueMapTest",
+        reason = "will be supported")
+@Graph.OptOut(
+        method = "g_V_valueMap",
+        test = "org.apache.tinkerpop.gremlin.process.traversal.step.map.ValueMapTest",
+        reason = "will be supported")
+@Graph.OptOut(
+        method = "g_V_group_byXlabelX_byXlabel_countX",
+        test = "org.apache.tinkerpop.gremlin.process.traversal.step.sideEffect.GroupTest",
+        reason = "will be supported")
+// @Graph.OptOut(method="g_V_group_byXageX" ,
+// test="org.apache.tinkerpop.gremlin.process.traversal.step.sideEffect.GroupTest", reason = "will
+// be supported")
+
+// @Graph.OptOut(method="g_V_hasXp_neqXvXX" ,
+// test="org.apache.tinkerpop.gremlin.process.traversal.step.filter.HasTest", reason = "existence of
+// property is unsupported")
+// @Graph.OptOut(method="g_V_hasXage_withoutX27X_count" ,
+// test="org.apache.tinkerpop.gremlin.process.traversal.step.filter.HasTest", reason = "existence of
+// property is unsupported")
+// @Graph.OptOut(method="g_VX1X_hasXcircumferenceX" ,
+// test="org.apache.tinkerpop.gremlin.process.traversal.step.filter.HasTest", reason = "existence of
+// property is unsupported")
+// @Graph.OptOut(method="g_V_hasXage_withoutX27_29X_count" ,
+// test="org.apache.tinkerpop.gremlin.process.traversal.step.filter.HasTest", reason = "existence of
+// property is unsupported")
+// @Graph.OptOut(method="g_VX1X_hasXnameX" ,
+// test="org.apache.tinkerpop.gremlin.process.traversal.step.filter.HasTest", reason = "existence of
+// property is unsupported")
+// @Graph.OptOut(method="g_V_hasXblahX" ,
+// test="org.apache.tinkerpop.gremlin.process.traversal.step.filter.HasTest", reason = "existence of
+// property is unsupported")
+// @Graph.OptOut(method="g_V_hasXlangX_group_byXlangX_byXcountX" ,
+// test="org.apache.tinkerpop.gremlin.process.traversal.step.sideEffect.GroupTest", reason =
+// "existence of property is unsupported")
+// @Graph.OptOut(method="g_VX1X_asXaX_out_hasXageX_whereXgtXaXX_byXageX_name" ,
+// test="org.apache.tinkerpop.gremlin.process.traversal.step.filter.WhereTest", reason = "existence
+// of property is unsupported")
+
+// complex steps nested in match is unsupported yet, i.e. where(eq)/count/order/match
+@Graph.OptOut(
+        method =
+                "g_V_matchXa_whereXa_neqXcXX__a_created_b__orXa_knows_vadas__a_0knows_and_a_hasXlabel_personXX__b_0created_c__b_0created_count_isXgtX1XXX_selectXa_b_cX_byXidX",
+        test = "org.apache.tinkerpop.gremlin.process.traversal.step.map.MatchTest",
+        reason = "unsupported")
+@Graph.OptOut(
+        method = "g_V_matchXa_created_lop_b__b_0created_29_c__c_whereXrepeatXoutX_timesX2XXX",
+        test = "org.apache.tinkerpop.gremlin.process.traversal.step.map.MatchTest",
+        reason = "unsupported")
+@Graph.OptOut(
+        method =
+                "g_V_matchXa_knows_b__andXa_created_c__b_created_c__andXb_created_count_d__a_knows_count_dXXX",
+        test = "org.apache.tinkerpop.gremlin.process.traversal.step.map.MatchTest",
+        reason = "unsupported")
+@Graph.OptOut(
+        method =
+                "g_V_matchXa_hasXsong_name_sunshineX__a_mapX0followedBy_weight_meanX_b__a_0followedBy_c__c_filterXweight_whereXgteXbXXX_outV_dX_selectXdX_byXnameX",
+        test = "org.apache.tinkerpop.gremlin.process.traversal.step.map.MatchTest",
+        reason = "unsupported")
+@Graph.OptOut(
+        method = "g_V_matchXa_created_b__a_repeatXoutX_timesX2XX_selectXa_bX",
+        test = "org.apache.tinkerpop.gremlin.process.traversal.step.map.MatchTest",
+        reason = "unsupported")
+@Graph.OptOut(
+        method =
+                "g_V_matchXa_knows_b__b_created_lop__b_matchXb_created_d__d_0created_cX_selectXcX_cX_selectXa_b_cX",
+        test = "org.apache.tinkerpop.gremlin.process.traversal.step.map.MatchTest",
+        reason = "unsupported")
+@Graph.OptOut(
+        method =
+                "g_V_matchXa_followedBy_count_isXgtX10XX_b__a_0followedBy_count_isXgtX10XX_bX_count",
+        test = "org.apache.tinkerpop.gremlin.process.traversal.step.map.MatchTest",
+        reason = "unsupported")
+@Graph.OptOut(
+        method =
+                "g_V_asXaX_out_asXbX_matchXa_out_count_c__orXa_knows_b__b_in_count_c__and__c_isXgtX2XXXX",
+        test = "org.apache.tinkerpop.gremlin.process.traversal.step.map.MatchTest",
+        reason = "unsupported")
+@Graph.OptOut(
+        method =
+                "g_V_matchXa_outEXcreatedX_order_byXweight_descX_limitX1X_inV_b__b_hasXlang_javaXX_selectXa_bX_byXnameX",
+        test = "org.apache.tinkerpop.gremlin.process.traversal.step.map.MatchTest",
+        reason = "unsupported")
+@Graph.OptOut(
+        method =
+                "g_V_matchXa_created_lop_b__b_0created_29_cX_whereXc_repeatXoutX_timesX2XX_selectXa_b_cX",
+        test = "org.apache.tinkerpop.gremlin.process.traversal.step.map.MatchTest",
+        reason = "unsupported")
+@Graph.OptOut(
+        method = "g_V_asXaX_out_asXbX_matchXa_out_count_c__b_in_count_cX",
+        test = "org.apache.tinkerpop.gremlin.process.traversal.step.map.MatchTest",
+        reason = "unsupported")
+@Graph.OptOut(
+        method =
+                "g_V_matchXwhereXandXa_created_b__b_0created_count_isXeqX3XXXX__a_both_b__whereXb_inXX",
+        test = "org.apache.tinkerpop.gremlin.process.traversal.step.map.MatchTest",
+        reason = "unsupported")
+@Graph.OptOut(
+        method = "g_V_matchXa_knows_count_bX_selectXbX",
+        test = "org.apache.tinkerpop.gremlin.process.traversal.step.map.MatchTest",
+        reason = "unsupported")
+@Graph.OptOut(
+        method = "g_V_valueMap_matchXa_selectXnameX_bX",
+        test = "org.apache.tinkerpop.gremlin.process.traversal.step.map.MatchTest",
+        reason = "unsupported")
+
+// steps nested in match is unsupported yet, will be supported latter, i.e values('name')
+@Graph.OptOut(
+        method = "g_V_notXmatchXa_age_b__a_name_cX_whereXb_eqXcXX_selectXaXX_name",
+        test = "org.apache.tinkerpop.gremlin.process.traversal.step.map.MatchTest",
+        reason = "unsupported")
+@Graph.OptOut(
+        method = "g_V_hasLabelXsongsX_matchXa_name_b__a_performances_cX_selectXb_cX_count",
+        test = "org.apache.tinkerpop.gremlin.process.traversal.step.map.MatchTest",
+        reason = "unsupported")
+@Graph.OptOut(
+        method = "g_V_matchXa_outXknowsX_name_bX_identity",
+        test = "org.apache.tinkerpop.gremlin.process.traversal.step.map.MatchTest",
+        reason = "unsupported")
+
+// will be supported in the first milestone, i.e dedup('a', 'b')
+@Graph.OptOut(
+        method = "g_V_matchXa__a_both_b__b_both_cX_dedupXa_bX",
+        test = "org.apache.tinkerpop.gremlin.process.traversal.step.map.MatchTest",
+        reason = "unsupported")
+// @Graph.OptOut(
+//        method = "g_V_matchXa_both_b__b_both_cX_dedupXa_bX_byXlabelX",
+//        test = "org.apache.tinkerpop.gremlin.process.traversal.step.map.MatchTest",
+//        reason = "unsupported")
+@Graph.OptOut(
+        method = "g_V_matchXd_0knows_a__d_hasXname_vadasX__a_knows_b__b_created_cX",
+        test = "org.apache.tinkerpop.gremlin.process.traversal.step.map.MatchTest",
+        reason = "unsupported")
+// @Graph.OptOut(
+//        method = "g_V_matchXa_out_bX_selectXb_idX",
+//        test = "org.apache.tinkerpop.gremlin.process.traversal.step.map.MatchTest",
+//        reason = "unsupported")
+// @Graph.OptOut(
+//        method = "g_V_matchXa_knows_b__b_created_c__a_created_cX_dedupXa_b_cX_selectXaX_byXnameX",
+//        test = "org.apache.tinkerpop.gremlin.process.traversal.step.map.MatchTest",
+//        reason = "unsupported")
+
+// need grateful graph
+@Graph.OptOut(
+        method = "g_V_matchXa_hasXname_GarciaX__a_0writtenBy_b__a_0sungBy_bX",
+        test = "org.apache.tinkerpop.gremlin.process.traversal.step.map.MatchTest",
+        reason = "unsupported")
+@Graph.OptOut(
+        method =
+                "g_V_matchXa_0sungBy_b__a_0sungBy_c__b_writtenBy_d__c_writtenBy_e__d_hasXname_George_HarisonX__e_hasXname_Bob_MarleyXX",
+        test = "org.apache.tinkerpop.gremlin.process.traversal.step.map.MatchTest",
+        reason = "unsupported")
+@Graph.OptOut(
+        method =
+                "g_V_matchXa_hasXname_GarciaX__a_0writtenBy_b__b_followedBy_c__c_writtenBy_d__whereXd_neqXaXXX",
+        test = "org.apache.tinkerpop.gremlin.process.traversal.step.map.MatchTest",
+        reason = "unsupported")
+@Graph.OptOut(
+        method =
+                "g_V_matchXa_0sungBy_b__a_0writtenBy_c__b_writtenBy_dX_whereXc_sungBy_dX_whereXd_hasXname_GarciaXX",
+        test = "org.apache.tinkerpop.gremlin.process.traversal.step.map.MatchTest",
+        reason = "unsupported")
+@Graph.OptOut(
+        method =
+                "g_V_matchXa_0sungBy_b__a_0writtenBy_c__b_writtenBy_d__c_sungBy_d__d_hasXname_GarciaXX",
+        test = "org.apache.tinkerpop.gremlin.process.traversal.step.map.MatchTest",
+        reason = "unsupported")
+@Graph.OptOut(
+        method = "g_V_order_byXnameX_name",
+        test = "org.apache.tinkerpop.gremlin.process.traversal.step.map.OrderTest",
+        reason = "Projection may introduce additional shuffling that can break the order.")
+@Graph.OptOut(
+        method = "g_V_order_byXname_ascX_name",
+        test = "org.apache.tinkerpop.gremlin.process.traversal.step.map.OrderTest",
+        reason = "Projection may introduce additional shuffling that can break the order.")
+@Graph.OptOut(
+        method = "g_V_outE_order_byXweight_descX_weight",
+        test = "org.apache.tinkerpop.gremlin.process.traversal.step.map.OrderTest",
+        reason = "Projection may introduce additional shuffling that can break the order.")
+@Graph.OptOut(
+        method = "g_V_both_hasLabelXpersonX_order_byXage_descX_limitX5X_name",
+        test = "org.apache.tinkerpop.gremlin.process.traversal.step.map.OrderTest",
+        reason = "Projection may introduce additional shuffling that can break the order.")
+
+// cases unsupported in groot
+// @Graph.OptOut(
+//        test = "org.apache.tinkerpop.gremlin.process.traversal.step.filter.HasTest",
+//        method = "g_VX1X_out_hasXid_2_3X",
+//        reason = "unsupported")
+@Graph.OptOut(
+        test = "org.apache.tinkerpop.gremlin.process.traversal.step.filter.HasTest",
+        method = "g_V_hasXp_neqXvXX",
+        reason = "unsupported")
+@Graph.OptOut(
+        test = "org.apache.tinkerpop.gremlin.process.traversal.step.filter.HasTest",
+        method = "g_V_hasXblahX",
+        reason = "unsupported")
+@Graph.OptOut(
+        test = "org.apache.tinkerpop.gremlin.process.traversal.step.filter.HasTest",
+        method = "g_VX1X_hasXcircumferenceX",
+        reason = "unsupported")
+@Graph.OptOut(
+        test = "org.apache.tinkerpop.gremlin.process.traversal.step.map.VertexTest",
+        method = "g_EX11X",
+        reason = "unsupported")
+@Graph.OptOut(
+        test = "org.apache.tinkerpop.gremlin.process.traversal.step.map.ElementMapTest",
+        method = "g_EX11X_elementMap",
+        reason = "cannot get label and id for out and in vertices")
+@Graph.OptOut(
+        test = "org.apache.tinkerpop.gremlin.process.traversal.step.map.ElementMapTest",
+        method = "g_V_elementMap",
+        reason = "cannot get label and id for out and in vertices")
+// @Graph.OptOut(
+//        test = "org.apache.tinkerpop.gremlin.process.traversal.step.map.ValueMapTest",
+//        method = "g_V_valueMapXname_ageX",
+//        reason = "unsupported")
+
+@Graph.OptOut(
+        method = "g_V_unionXout__inX_name",
+        test = "org.apache.tinkerpop.gremlin.process.traversal.step.branch.UnionTest",
+        reason = "union is unsupported yet")
+@Graph.OptOut(
+        test = "org.apache.tinkerpop.gremlin.process.traversal.step.branch.UnionTest",
+        method = "g_VX1_2X_unionXoutE_count__inE_count__outE_weight_sumX",
+        reason = "union is unsupported yet")
+@Graph.OptOut(
+        method = "g_V_haslabel_union_identity_out_values",
+        test = "com.alibaba.graphscope.gremlin.integration.suite.standard.IrGremlinQueryTest",
+        reason = "union is unsupported yet")
+@Graph.OptOut(
+        test = "org.apache.tinkerpop.gremlin.process.traversal.step.filter.HasTest",
+        method = "g_V_hasLabelXpersonX_hasLabelXsoftwareX",
+        reason = "throw schema errors instead of returning empty results")
+@Graph.OptOut(
+        test = "org.apache.tinkerpop.gremlin.process.traversal.step.filter.IsTest",
+        method = "g_V_whereXinXcreatedX_count_isX1XX_valuesXnameX",
+        reason = "sub query is unsupported yet")
+@Graph.OptOut(
+        test = "org.apache.tinkerpop.gremlin.process.traversal.step.filter.IsTest",
+        method = "g_V_whereXinXcreatedX_count_isXgte_2XX_valuesXnameX",
+        reason = "sub query is unsupported yet")
+@Graph.OptOut(
+        test = "org.apache.tinkerpop.gremlin.process.traversal.step.filter.WhereTest",
+        method = "g_V_hasXageX_asXaX_out_in_hasXageX_asXbX_selectXa_bX_whereXa_outXknowsX_bX",
+        reason = "sub query is unsupported yet")
+@Graph.OptOut(
+        test = "org.apache.tinkerpop.gremlin.process.traversal.step.filter.WhereTest",
+        method = "g_V_whereXnotXoutXcreatedXXX_name",
+        reason = "sub query is unsupported yet")
+@Graph.OptOut(
+        method = "g_V_asXaX_outXcreatedX_whereXasXaX_name_isXjoshXX_inXcreatedX_name",
+        test = "org.apache.tinkerpop.gremlin.process.traversal.step.filter.WhereTest",
+        reason = "sub query is unsupported yet")
+@Graph.OptOut(
+        test = "org.apache.tinkerpop.gremlin.process.traversal.step.filter.WhereTest",
+        method = "g_V_hasXageX_asXaX_out_in_hasXageX_asXbX_selectXa_bX_whereXb_hasXname_markoXX",
+        reason = "sub query is unsupported yet")
+@Graph.OptOut(
+        test = "org.apache.tinkerpop.gremlin.process.traversal.step.map.CountTest",
+        method = "g_V_whereXinXkknowsX_outXcreatedX_count_is_0XX_name",
+        reason = "sub query is unsupported yet")
+@Graph.OptOut(
+        test = "org.apache.tinkerpop.gremlin.process.traversal.step.map.OrderTest",
+        method = "g_V_order_byXoutE_count_descX",
+        reason = "sub query is unsupported yet")
+@Graph.OptOut(
+        test = "com.alibaba.graphscope.gremlin.integration.suite.standard.IrGremlinQueryTest",
+        method = "g_V_group_by_outE_count_test",
+        reason = "sub query is unsupported yet")
+@Graph.OptOut(
+        method = "g_V_asXaX_whereXoutXknowsXX_selectXaX",
+        test = "org.apache.tinkerpop.gremlin.process.traversal.step.map.SelectTest",
+        reason = "sub query is unsupported yet")
+@Graph.OptOut(
+        test = "org.apache.tinkerpop.gremlin.process.traversal.step.sideEffect.GroupTest",
+        method = "g_V_group_byXoutE_countX_byXnameX",
+        reason = "sub query is unsupported yet")
+@Graph.OptOut(
+        test = "org.apache.tinkerpop.gremlin.process.traversal.step.sideEffect.GroupCountTest",
+        method = "g_V_groupCount_byXbothE_countX",
+        reason = "sub query is unsupported yet")
+@Graph.OptOut(
+        method =
+                "g_VX1X_outEXknowsX_asXhereX_hasXweight_1X_asXfakeX_inV_hasXname_joshX_selectXhereX",
+        test = "org.apache.tinkerpop.gremlin.process.traversal.step.map.SelectTest",
+        reason = "throw alias not found errors instead of returning empty results")
+@Graph.OptOut(
+        test = "org.apache.tinkerpop.gremlin.process.traversal.step.map.SelectTest",
+        method = "g_V_selectXa_bX",
+        reason = "throw alias not found errors instead of returning empty results")
+@Graph.OptOut(
+        test = "org.apache.tinkerpop.gremlin.process.traversal.step.map.SelectTest",
+        method = "g_V_selectXaX_count",
+        reason = "throw alias not found errors instead of returning empty results")
+@Graph.OptOut(
+        test = "org.apache.tinkerpop.gremlin.process.traversal.step.map.SelectTest",
+        method = "g_V_selectXaX_count",
+        reason = "throw alias not found errors instead of returning empty results")
+@Graph.OptOut(
+        test = "org.apache.tinkerpop.gremlin.process.traversal.step.map.SelectTest",
+        method = "g_V_valueMap_selectXa_bX",
+        reason = "throw alias not found errors instead of returning empty results")
+@Graph.OptOut(
+        test = "org.apache.tinkerpop.gremlin.process.traversal.step.map.SelectTest",
+        method = "g_V_valueMap_selectXaX",
+        reason = "throw alias not found errors instead of returning empty results")
+@Graph.OptOut(
+        test = "org.apache.tinkerpop.gremlin.process.traversal.step.map.SelectTest",
+        method = "g_V_selectXaX",
+        reason = "throw alias not found errors instead of returning empty results")
+@Graph.OptOut(
+        method = "g_V_valueMapXname_ageX",
+        test = "org.apache.tinkerpop.gremlin.process.traversal.step.map.ValueMapTest",
+        reason = "results of the valueMap are inconsistent with the official gremlin")
+@Graph.OptOut(
+        method = "g_V_matchXb_created_c__a_knows_bX",
+        test = "org.apache.tinkerpop.gremlin.process.traversal.step.map.MatchTest",
+        reason = "match is unsupported yet")
+@Graph.OptOut(
+        method = "g_V_matchXa_out_bX",
+        test = "org.apache.tinkerpop.gremlin.process.traversal.step.map.MatchTest",
+        reason = "match is unsupported yet")
+@Graph.OptOut(
+        method = "g_V_matchXa_created_b__b_0created_aX",
+        test = "org.apache.tinkerpop.gremlin.process.traversal.step.map.MatchTest",
+        reason = "match is unsupported yet")
+@Graph.OptOut(
+        method = "g_V_matchXa_both_b__b_both_cX_dedupXa_bX_byXlabelX",
+        test = "org.apache.tinkerpop.gremlin.process.traversal.step.map.MatchTest",
+        reason = "match is unsupported yet")
+@Graph.OptOut(
+        method = "g_V_matchXa__a_out_b__notXa_created_bXX",
+        test = "org.apache.tinkerpop.gremlin.process.traversal.step.map.MatchTest",
+        reason = "match is unsupported yet")
+@Graph.OptOut(
+        method = "g_V_matchXa_knows_b__a_created_cX",
+        test = "org.apache.tinkerpop.gremlin.process.traversal.step.map.MatchTest",
+        reason = "match is unsupported yet")
+@Graph.OptOut(
+        method = "g_V_matchXa_knows_b__b_created_cX",
+        test = "org.apache.tinkerpop.gremlin.process.traversal.step.map.MatchTest",
+        reason = "match is unsupported yet")
+@Graph.OptOut(
+        method = "g_V_matchXa_created_b__b_0created_cX_whereXa_neq_cX_selectXa_cX",
+        test = "org.apache.tinkerpop.gremlin.process.traversal.step.map.MatchTest",
+        reason = "match is unsupported yet")
+@Graph.OptOut(
+        method = "g_V_matchXa_knows_b__b_created_c__a_created_cX_dedupXa_b_cX_selectXaX_byXnameX",
+        test = "org.apache.tinkerpop.gremlin.process.traversal.step.map.MatchTest",
+        reason = "match is unsupported yet")
+@Graph.OptOut(
+        method = "g_V_matchXa_in_b__b_out_c__not_c_out_aX",
+        test = "com.alibaba.graphscope.gremlin.integration.suite.standard.IrGremlinQueryTest",
+        reason = "match is unsupported yet")
+@Graph.OptOut(
+        method = "g_V_has_fold_select_as_unfold_select_unfold_values",
+        test = "com.alibaba.graphscope.gremlin.integration.suite.standard.IrGremlinQueryTest",
+        reason = "unfold is unsupported yet")
+@Graph.OptOut(
+        method = "g_V_has_fold_select_as_unfold_values",
+        test = "com.alibaba.graphscope.gremlin.integration.suite.standard.IrGremlinQueryTest",
+        reason = "unfold is unsupported yet")
+@Graph.OptOut(
+        method = "g_V_has_select_unfold_values",
+        test = "com.alibaba.graphscope.gremlin.integration.suite.standard.IrGremlinQueryTest",
+        reason = "unfold is unsupported yet")
+@Graph.OptOut(
+        method = "g_V_fold_a_unfold_values",
+        test = "com.alibaba.graphscope.gremlin.integration.suite.standard.IrGremlinQueryTest",
+        reason = "unfold is unsupported yet")
+@Graph.OptOut(
+        method = "g_V_fold_unfold_values",
+        test = "com.alibaba.graphscope.gremlin.integration.suite.standard.IrGremlinQueryTest",
+        reason = "unfold is unsupported yet")
+@Graph.OptOut(
+        method = "g_V_fold_a_unfold_select_a_unfold_values",
+        test = "com.alibaba.graphscope.gremlin.integration.suite.standard.IrGremlinQueryTest",
+        reason = "unfold is unsupported yet")
+@Graph.OptOut(
+        method = "g_V_a_out_b_select_by_elementMap",
+        test = "com.alibaba.graphscope.gremlin.integration.suite.standard.IrGremlinQueryTest",
+        reason = "nested map is unsupported in runtime")
+@Graph.OptOut(
+        method = "g_V_sample_by_2",
+        test = "com.alibaba.graphscope.gremlin.integration.suite.standard.IrGremlinQueryTest",
+        reason = "sample is unsupported yet")
+@Graph.OptOut(
+        method = "g_V_sample_by_7",
+        test = "com.alibaba.graphscope.gremlin.integration.suite.standard.IrGremlinQueryTest",
+        reason = "sample is unsupported yet")
+@Graph.OptOut(
+        method = "g_V_coin_by_ratio",
+        test = "com.alibaba.graphscope.gremlin.integration.suite.standard.IrGremlinQueryTest",
+        reason = "coin is unsupported yet")
+public class RemoteTestGraph
+        extends com.alibaba.graphscope.gremlin.integration.graph.RemoteTestGraph {
+    public RemoteTestGraph(@Nullable Configuration configuration) {
+        super(configuration);
+    }
+}
diff --git a/interactive_engine/compiler/src/main/java/com/alibaba/graphscope/gremlin/integration/processor/IrTestOpProcessor.java b/interactive_engine/compiler/src/main/java/com/alibaba/graphscope/gremlin/integration/processor/IrTestOpProcessor.java
index 8266f2935d33..ceb52311aee6 100644
--- a/interactive_engine/compiler/src/main/java/com/alibaba/graphscope/gremlin/integration/processor/IrTestOpProcessor.java
+++ b/interactive_engine/compiler/src/main/java/com/alibaba/graphscope/gremlin/integration/processor/IrTestOpProcessor.java
@@ -16,17 +16,28 @@
 
 package com.alibaba.graphscope.gremlin.integration.processor;
 
+import com.alibaba.graphscope.common.client.ExecutionClient;
 import com.alibaba.graphscope.common.client.channel.ChannelFetcher;
+import com.alibaba.graphscope.common.client.type.ExecutionRequest;
+import com.alibaba.graphscope.common.client.type.ExecutionResponseListener;
 import com.alibaba.graphscope.common.config.Configs;
+import com.alibaba.graphscope.common.config.FrontendConfig;
 import com.alibaba.graphscope.common.config.QueryTimeoutConfig;
 import com.alibaba.graphscope.common.ir.tools.GraphPlanner;
+import com.alibaba.graphscope.common.ir.tools.QueryCache;
+import com.alibaba.graphscope.common.ir.tools.QueryIdGenerator;
 import com.alibaba.graphscope.common.manager.IrMetaQueryCallback;
 import com.alibaba.graphscope.common.store.IrMeta;
+import com.alibaba.graphscope.gaia.proto.IrResult;
 import com.alibaba.graphscope.gremlin.integration.result.GraphProperties;
-import com.alibaba.graphscope.gremlin.integration.result.GremlinTestResultProcessor;
+import com.alibaba.graphscope.gremlin.integration.resultx.GremlinTestRecordParser;
+import com.alibaba.graphscope.gremlin.integration.resultx.GremlinTestResultProcessor;
 import com.alibaba.graphscope.gremlin.plugin.QueryStatusCallback;
 import com.alibaba.graphscope.gremlin.plugin.processor.IrStandardOpProcessor;
 import com.alibaba.graphscope.gremlin.plugin.script.AntlrGremlinScriptEngine;
+import com.alibaba.graphscope.gremlin.plugin.script.AntlrGremlinScriptEngineFactory;
+import com.alibaba.graphscope.gremlin.plugin.script.GremlinCalciteScriptEngineFactory;
+import com.alibaba.graphscope.gremlin.resultx.ResultSchema;
 
 import org.apache.tinkerpop.gremlin.driver.Tokens;
 import org.apache.tinkerpop.gremlin.driver.message.RequestMessage;
@@ -59,13 +70,23 @@ public class IrTestOpProcessor extends IrStandardOpProcessor {
 
     public IrTestOpProcessor(
             Configs configs,
-            GraphPlanner graphPlanner,
+            QueryIdGenerator idGenerator,
+            QueryCache queryCache,
+            ExecutionClient executionClient,
             ChannelFetcher fetcher,
             IrMetaQueryCallback metaQueryCallback,
             Graph graph,
             GraphTraversalSource g,
             GraphProperties testGraph) {
-        super(configs, graphPlanner, fetcher, metaQueryCallback, graph, g);
+        super(
+                configs,
+                idGenerator,
+                queryCache,
+                executionClient,
+                fetcher,
+                metaQueryCallback,
+                graph,
+                g);
         this.context = new SimpleScriptContext();
         Bindings globalBindings = new SimpleBindings();
         globalBindings.put("g", g);
@@ -91,27 +112,68 @@ public ThrowingConsumer<Context> select(Context ctx) {
                             Bytecode byteCode =
                                     (Bytecode) message.getArgs().get(Tokens.ARGS_GREMLIN);
                             String script = getScript(byteCode);
-                            Traversal traversal =
-                                    (Traversal) scriptEngine.eval(script, this.context);
-                            applyStrategies(traversal);
-                            long jobId = graphPlanner.generateUniqueId();
+                            long queryId = idGenerator.generateId();
+                            String queryName = idGenerator.generateName(queryId);
                             IrMeta irMeta = metaQueryCallback.beforeExec();
                             QueryStatusCallback statusCallback =
-                                    createQueryStatusCallback(script, jobId);
+                                    createQueryStatusCallback(script, queryId);
                             QueryTimeoutConfig timeoutConfig =
-                                    new QueryTimeoutConfig(ctx.getRequestTimeout());
-                            processTraversal(
-                                    traversal,
-                                    new GremlinTestResultProcessor(
-                                            ctx,
+                                    new QueryTimeoutConfig(
+                                            FrontendConfig.QUERY_EXECUTION_TIMEOUT_MS.get(configs));
+                            String language =
+                                    FrontendConfig.GREMLIN_SCRIPT_LANGUAGE_NAME.get(configs);
+                            switch (language) {
+                                case AntlrGremlinScriptEngineFactory.LANGUAGE_NAME:
+                                    Traversal traversal =
+                                            (Traversal) scriptEngine.eval(script, this.context);
+                                    applyStrategies(traversal);
+                                    processTraversal(
                                             traversal,
-                                            statusCallback,
-                                            testGraph,
-                                            this.configs,
-                                            timeoutConfig),
-                                    irMeta,
-                                    new QueryTimeoutConfig(ctx.getRequestTimeout()),
-                                    statusCallback.getQueryLogger());
+                                            new com.alibaba.graphscope.gremlin.integration.result
+                                                    .GremlinTestResultProcessor(
+                                                    ctx,
+                                                    traversal,
+                                                    statusCallback,
+                                                    testGraph,
+                                                    this.configs,
+                                                    timeoutConfig),
+                                            irMeta,
+                                            new QueryTimeoutConfig(ctx.getRequestTimeout()),
+                                            statusCallback.getQueryLogger());
+                                    break;
+                                case GremlinCalciteScriptEngineFactory.LANGUAGE_NAME:
+                                    QueryCache.Value value =
+                                            queryCache.get(queryCache.createKey(script, irMeta));
+                                    GraphPlanner.Summary summary = value.summary;
+                                    ResultSchema resultSchema =
+                                            new ResultSchema(summary.getLogicalPlan());
+                                    ExecutionResponseListener listener =
+                                            new GremlinTestResultProcessor(
+                                                    ctx,
+                                                    statusCallback,
+                                                    new GremlinTestRecordParser(
+                                                            resultSchema,
+                                                            testGraph.getProperties(configs)),
+                                                    resultSchema);
+                                    if (value.result != null && value.result.isCompleted) {
+                                        List<IrResult.Results> records = value.result.records;
+                                        records.forEach(k -> listener.onNext(k.getRecord()));
+                                        listener.onCompleted();
+                                    } else {
+                                        executionClient.submit(
+                                                new ExecutionRequest(
+                                                        queryId,
+                                                        queryName,
+                                                        summary.getLogicalPlan(),
+                                                        summary.getPhysicalPlan()),
+                                                listener,
+                                                timeoutConfig);
+                                    }
+                                    break;
+                                default:
+                                    throw new IllegalArgumentException(
+                                            "invalid script language name: " + language);
+                            }
                             metaQueryCallback.afterExec(irMeta);
                         });
                 return op;
diff --git a/interactive_engine/compiler/src/main/java/com/alibaba/graphscope/gremlin/integration/resultx/GremlinTestRecordParser.java b/interactive_engine/compiler/src/main/java/com/alibaba/graphscope/gremlin/integration/resultx/GremlinTestRecordParser.java
new file mode 100644
index 000000000000..9c8aed5234fa
--- /dev/null
+++ b/interactive_engine/compiler/src/main/java/com/alibaba/graphscope/gremlin/integration/resultx/GremlinTestRecordParser.java
@@ -0,0 +1,69 @@
+/*
+ * Copyright 2020 Alibaba Group Holding Limited.
+ *
+ * Licensed 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 com.alibaba.graphscope.gremlin.integration.resultx;
+
+import com.alibaba.graphscope.gaia.proto.IrResult;
+import com.alibaba.graphscope.gremlin.resultx.GremlinRecordParser;
+import com.alibaba.graphscope.gremlin.resultx.ResultSchema;
+import com.google.common.collect.ImmutableMap;
+
+import org.apache.calcite.rel.type.RelDataType;
+
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+
+public class GremlinTestRecordParser extends GremlinRecordParser {
+    private static final String VERTEX_PROPERTIES = "vertex_properties";
+    private static final String EDGE_PROPERTIES = "edge_properties";
+    private final Map<String, Object> cachedProperties;
+
+    public GremlinTestRecordParser(
+            ResultSchema resultSchema, Map<String, Object> cachedProperties) {
+        super(resultSchema);
+        this.cachedProperties = cachedProperties;
+    }
+
+    @Override
+    protected Map<String, Object> parseVertexProperties(IrResult.Vertex vertex, RelDataType type) {
+        Map<String, Object> vertexProperties =
+                (Map<String, Object>) cachedProperties.get(VERTEX_PROPERTIES);
+        String idAsStr = String.valueOf(vertex.getId());
+        Map<String, Object> properties = (Map<String, Object>) vertexProperties.get(idAsStr);
+        if (properties != null) {
+            Map<String, Object> formatProperties = new HashMap<>();
+            properties.forEach(
+                    (k, v) -> {
+                        formatProperties.put(
+                                k,
+                                Collections.singletonList(ImmutableMap.of("id", 1L, "value", v)));
+                    });
+            return formatProperties;
+        } else {
+            return Collections.emptyMap();
+        }
+    }
+
+    @Override
+    protected Map<String, Object> parseEdgeProperties(IrResult.Edge edge, RelDataType type) {
+        Map<String, Object> edgeProperties =
+                (Map<String, Object>) cachedProperties.get(EDGE_PROPERTIES);
+        String idAsStr = String.valueOf(edge.getId());
+        Map<String, Object> properties = (Map<String, Object>) edgeProperties.get(idAsStr);
+        return (properties == null) ? Collections.emptyMap() : properties;
+    }
+}
diff --git a/interactive_engine/compiler/src/main/java/com/alibaba/graphscope/gremlin/integration/resultx/GremlinTestResultProcessor.java b/interactive_engine/compiler/src/main/java/com/alibaba/graphscope/gremlin/integration/resultx/GremlinTestResultProcessor.java
new file mode 100644
index 000000000000..1fe4935d593a
--- /dev/null
+++ b/interactive_engine/compiler/src/main/java/com/alibaba/graphscope/gremlin/integration/resultx/GremlinTestResultProcessor.java
@@ -0,0 +1,79 @@
+/*
+ * Copyright 2020 Alibaba Group Holding Limited.
+ *
+ * Licensed 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 com.alibaba.graphscope.gremlin.integration.resultx;
+
+import com.alibaba.graphscope.common.result.RecordParser;
+import com.alibaba.graphscope.gaia.proto.IrResult;
+import com.alibaba.graphscope.gremlin.plugin.QueryStatusCallback;
+import com.alibaba.graphscope.gremlin.resultx.GremlinResultProcessor;
+import com.alibaba.graphscope.gremlin.resultx.ResultSchema;
+import com.google.common.collect.Lists;
+
+import org.apache.tinkerpop.gremlin.driver.message.ResponseMessage;
+import org.apache.tinkerpop.gremlin.driver.message.ResponseStatusCode;
+import org.apache.tinkerpop.gremlin.process.remote.traversal.DefaultRemoteTraverser;
+import org.apache.tinkerpop.gremlin.server.Context;
+
+import java.util.List;
+import java.util.Map;
+import java.util.stream.Collectors;
+
+public class GremlinTestResultProcessor extends GremlinResultProcessor {
+    public GremlinTestResultProcessor(
+            Context ctx,
+            QueryStatusCallback statusCallback,
+            RecordParser recordParser,
+            ResultSchema resultSchema) {
+        super(ctx, statusCallback, recordParser, resultSchema);
+    }
+
+    @Override
+    public void onNext(IrResult.Record record) {
+        List<Object> results = recordParser.parseFrom(record);
+        if (resultSchema.isGroupBy && !results.isEmpty()) {
+            if (results.stream().anyMatch(k -> !(k instanceof Map))) {
+                throw new IllegalArgumentException(
+                        "cannot reduce results " + results + " into a single map");
+            }
+            for (Object result : results) {
+                reducer.putAll((Map) result);
+            }
+        } else if (!resultSchema.isGroupBy) {
+            ctx.writeAndFlush(
+                    ResponseMessage.build(ctx.getRequestMessage())
+                            .code(ResponseStatusCode.PARTIAL_CONTENT)
+                            .result(
+                                    results.stream()
+                                            .map(k -> new DefaultRemoteTraverser(k, 1L))
+                                            .collect(Collectors.toList()))
+                            .create());
+        }
+    }
+
+    @Override
+    public void onCompleted() {
+        List<Object> results = Lists.newArrayList();
+        if (resultSchema.isGroupBy) {
+            results.add(new DefaultRemoteTraverser(reducer, 1L));
+        }
+        ctx.writeAndFlush(
+                ResponseMessage.build(ctx.getRequestMessage())
+                        .code(ResponseStatusCode.SUCCESS)
+                        .result(results)
+                        .create());
+    }
+}
diff --git a/interactive_engine/compiler/src/main/java/com/alibaba/graphscope/gremlin/plugin/processor/IrStandardOpProcessor.java b/interactive_engine/compiler/src/main/java/com/alibaba/graphscope/gremlin/plugin/processor/IrStandardOpProcessor.java
index 0161dc8ec494..f01d46b1ed2a 100644
--- a/interactive_engine/compiler/src/main/java/com/alibaba/graphscope/gremlin/plugin/processor/IrStandardOpProcessor.java
+++ b/interactive_engine/compiler/src/main/java/com/alibaba/graphscope/gremlin/plugin/processor/IrStandardOpProcessor.java
@@ -26,12 +26,15 @@
 package com.alibaba.graphscope.gremlin.plugin.processor;
 
 import com.alibaba.graphscope.common.IrPlan;
+import com.alibaba.graphscope.common.client.ExecutionClient;
 import com.alibaba.graphscope.common.client.channel.ChannelFetcher;
 import com.alibaba.graphscope.common.config.Configs;
+import com.alibaba.graphscope.common.config.FrontendConfig;
 import com.alibaba.graphscope.common.config.PegasusConfig;
 import com.alibaba.graphscope.common.config.QueryTimeoutConfig;
 import com.alibaba.graphscope.common.intermediate.InterOpCollection;
-import com.alibaba.graphscope.common.ir.tools.GraphPlanner;
+import com.alibaba.graphscope.common.ir.tools.QueryCache;
+import com.alibaba.graphscope.common.ir.tools.QueryIdGenerator;
 import com.alibaba.graphscope.common.manager.IrMetaQueryCallback;
 import com.alibaba.graphscope.common.store.IrMeta;
 import com.alibaba.graphscope.gremlin.InterOpCollectionBuilder;
@@ -40,6 +43,7 @@
 import com.alibaba.graphscope.gremlin.plugin.QueryLogger;
 import com.alibaba.graphscope.gremlin.plugin.QueryStatusCallback;
 import com.alibaba.graphscope.gremlin.plugin.script.AntlrGremlinScriptEngineFactory;
+import com.alibaba.graphscope.gremlin.plugin.script.GremlinCalciteScriptEngineFactory;
 import com.alibaba.graphscope.gremlin.plugin.strategy.ExpandFusionStepStrategy;
 import com.alibaba.graphscope.gremlin.plugin.strategy.RemoveUselessStepStrategy;
 import com.alibaba.graphscope.gremlin.plugin.strategy.ScanFusionStepStrategy;
@@ -86,20 +90,24 @@
 import javax.script.SimpleBindings;
 
 public class IrStandardOpProcessor extends StandardOpProcessor {
-    protected Graph graph;
-    protected GraphTraversalSource g;
-    protected Configs configs;
+    protected final Graph graph;
+    protected final GraphTraversalSource g;
+    protected final Configs configs;
     /**
      * todo: replace with {@link com.alibaba.graphscope.common.client.ExecutionClient} after unifying Gremlin into the Calcite stack
      */
-    protected RpcClient rpcClient;
+    protected final RpcClient rpcClient;
 
-    protected IrMetaQueryCallback metaQueryCallback;
-    protected final GraphPlanner graphPlanner;
+    protected final IrMetaQueryCallback metaQueryCallback;
+    protected final QueryIdGenerator idGenerator;
+    protected final QueryCache queryCache;
+    protected final ExecutionClient executionClient;
 
     public IrStandardOpProcessor(
             Configs configs,
-            GraphPlanner graphPlanner,
+            QueryIdGenerator idGenerator,
+            QueryCache queryCache,
+            ExecutionClient executionClient,
             ChannelFetcher fetcher,
             IrMetaQueryCallback metaQueryCallback,
             Graph graph,
@@ -109,7 +117,9 @@ public IrStandardOpProcessor(
         this.configs = configs;
         this.rpcClient = new RpcClient(fetcher.fetch());
         this.metaQueryCallback = metaQueryCallback;
-        this.graphPlanner = graphPlanner;
+        this.idGenerator = idGenerator;
+        this.queryCache = queryCache;
+        this.executionClient = executionClient;
     }
 
     @Override
@@ -128,15 +138,37 @@ protected void evalOpInternal(
             ctx.writeAndFlush(ResponseMessage.build(msg).code(ResponseStatusCode.SUCCESS).create());
             return;
         }
-
-        String language = AntlrGremlinScriptEngineFactory.LANGUAGE_NAME;
-
-        long jobId = graphPlanner.generateUniqueId();
+        long jobId = idGenerator.generateId();
+        String jobName = idGenerator.generateName(jobId);
         IrMeta irMeta = metaQueryCallback.beforeExec();
         QueryStatusCallback statusCallback = createQueryStatusCallback(script, jobId);
-        GremlinExecutor.LifeCycle lifeCycle =
-                createLifeCycle(
-                        ctx, gremlinExecutorSupplier, bindingsSupplier, irMeta, statusCallback);
+        String language = FrontendConfig.GREMLIN_SCRIPT_LANGUAGE_NAME.get(configs);
+        GremlinExecutor.LifeCycle lifeCycle;
+        switch (language) {
+            case AntlrGremlinScriptEngineFactory.LANGUAGE_NAME:
+                lifeCycle =
+                        createLifeCycle(
+                                ctx,
+                                gremlinExecutorSupplier,
+                                bindingsSupplier,
+                                irMeta,
+                                statusCallback);
+                break;
+            case GremlinCalciteScriptEngineFactory.LANGUAGE_NAME:
+                lifeCycle =
+                        new LifeCycleSupplier(
+                                        ctx,
+                                        queryCache,
+                                        executionClient,
+                                        jobId,
+                                        jobName,
+                                        irMeta,
+                                        statusCallback)
+                                .get();
+                break;
+            default:
+                throw new IllegalArgumentException("invalid script language name: " + language);
+        }
         try {
             CompletableFuture<Object> evalFuture =
                     gremlinExecutor.eval(script, language, new SimpleBindings(), lifeCycle);
diff --git a/interactive_engine/compiler/src/main/java/com/alibaba/graphscope/gremlin/plugin/processor/LifeCycleSupplier.java b/interactive_engine/compiler/src/main/java/com/alibaba/graphscope/gremlin/plugin/processor/LifeCycleSupplier.java
new file mode 100644
index 000000000000..a74255a8afa5
--- /dev/null
+++ b/interactive_engine/compiler/src/main/java/com/alibaba/graphscope/gremlin/plugin/processor/LifeCycleSupplier.java
@@ -0,0 +1,117 @@
+/*
+ * Copyright 2020 Alibaba Group Holding Limited.
+ *
+ * Licensed 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 com.alibaba.graphscope.gremlin.plugin.processor;
+
+import com.alibaba.graphscope.common.client.ExecutionClient;
+import com.alibaba.graphscope.common.client.type.ExecutionRequest;
+import com.alibaba.graphscope.common.client.type.ExecutionResponseListener;
+import com.alibaba.graphscope.common.config.QueryTimeoutConfig;
+import com.alibaba.graphscope.common.ir.tools.GraphPlanner;
+import com.alibaba.graphscope.common.ir.tools.QueryCache;
+import com.alibaba.graphscope.common.store.IrMeta;
+import com.alibaba.graphscope.gaia.proto.IrResult;
+import com.alibaba.graphscope.gremlin.plugin.QueryStatusCallback;
+import com.alibaba.graphscope.gremlin.resultx.GremlinRecordParser;
+import com.alibaba.graphscope.gremlin.resultx.GremlinResultProcessor;
+import com.alibaba.graphscope.gremlin.resultx.ResultSchema;
+import com.google.common.base.Preconditions;
+
+import org.apache.tinkerpop.gremlin.groovy.engine.GremlinExecutor;
+import org.apache.tinkerpop.gremlin.server.Context;
+
+import java.util.List;
+import java.util.function.Supplier;
+
+public class LifeCycleSupplier implements Supplier<GremlinExecutor.LifeCycle> {
+    private final QueryCache queryCache;
+    private final ExecutionClient client;
+    private final Context ctx;
+    private final long queryId;
+    private final String queryName;
+    private final IrMeta meta;
+    private final QueryStatusCallback statusCallback;
+
+    public LifeCycleSupplier(
+            Context ctx,
+            QueryCache queryCache,
+            ExecutionClient client,
+            long queryId,
+            String queryName,
+            IrMeta meta,
+            QueryStatusCallback statusCallback) {
+        this.ctx = ctx;
+        this.queryCache = queryCache;
+        this.client = client;
+        this.queryId = queryId;
+        this.queryName = queryName;
+        this.meta = meta;
+        this.statusCallback = statusCallback;
+    }
+
+    @Override
+    public GremlinExecutor.LifeCycle get() {
+        QueryTimeoutConfig timeoutConfig = new QueryTimeoutConfig(ctx.getRequestTimeout());
+        return GremlinExecutor.LifeCycle.build()
+                .evaluationTimeoutOverride(timeoutConfig.getExecutionTimeoutMS())
+                .beforeEval(
+                        b -> {
+                            b.put("graph.query.cache", queryCache);
+                            b.put("graph.meta", meta);
+                        })
+                .withResult(
+                        o -> {
+                            try {
+                                Preconditions.checkArgument(
+                                        o instanceof QueryCache.Value,
+                                        "input of 'withResult' is invalid, expect type=%s, actual"
+                                                + " type=%s",
+                                        QueryCache.Value.class,
+                                        o.getClass());
+                                QueryCache.Value value = (QueryCache.Value) o;
+                                GraphPlanner.Summary summary = value.summary;
+                                statusCallback
+                                        .getQueryLogger()
+                                        .info("ir plan {}", summary.getPhysicalPlan().explain());
+                                ResultSchema resultSchema =
+                                        new ResultSchema(summary.getLogicalPlan());
+                                ExecutionResponseListener listener =
+                                        new GremlinResultProcessor(
+                                                ctx,
+                                                statusCallback,
+                                                new GremlinRecordParser(resultSchema),
+                                                resultSchema);
+                                if (value.result != null && value.result.isCompleted) {
+                                    List<IrResult.Results> records = value.result.records;
+                                    records.forEach(k -> listener.onNext(k.getRecord()));
+                                    listener.onCompleted();
+                                } else {
+                                    this.client.submit(
+                                            new ExecutionRequest(
+                                                    queryId,
+                                                    queryName,
+                                                    summary.getLogicalPlan(),
+                                                    summary.getPhysicalPlan()),
+                                            listener,
+                                            timeoutConfig);
+                                }
+                            } catch (Exception e) {
+                                throw new RuntimeException(e);
+                            }
+                        })
+                .create();
+    }
+}
diff --git a/interactive_engine/compiler/src/main/java/com/alibaba/graphscope/gremlin/plugin/script/AntlrGremlinScriptEngineFactory.java b/interactive_engine/compiler/src/main/java/com/alibaba/graphscope/gremlin/plugin/script/AntlrGremlinScriptEngineFactory.java
index 462ee5b5345a..9eb6aab6bbda 100644
--- a/interactive_engine/compiler/src/main/java/com/alibaba/graphscope/gremlin/plugin/script/AntlrGremlinScriptEngineFactory.java
+++ b/interactive_engine/compiler/src/main/java/com/alibaba/graphscope/gremlin/plugin/script/AntlrGremlinScriptEngineFactory.java
@@ -36,7 +36,7 @@ public class AntlrGremlinScriptEngineFactory extends AbstractGremlinScriptEngine
     private static final String PLAIN = "plain";
     private static final List<String> EXTENSIONS = Collections.singletonList("gremlin");
 
-    public static final String LANGUAGE_NAME = "antlr_gremlin";
+    public static final String LANGUAGE_NAME = "antlr_gremlin_traversal";
 
     public AntlrGremlinScriptEngineFactory() {
         super(LANGUAGE_NAME, LANGUAGE_NAME, EXTENSIONS, Collections.singletonList(PLAIN));
diff --git a/interactive_engine/compiler/src/main/java/com/alibaba/graphscope/gremlin/plugin/script/GremlinCalciteScriptEngineFactory.java b/interactive_engine/compiler/src/main/java/com/alibaba/graphscope/gremlin/plugin/script/GremlinCalciteScriptEngineFactory.java
new file mode 100644
index 000000000000..b9609c73f891
--- /dev/null
+++ b/interactive_engine/compiler/src/main/java/com/alibaba/graphscope/gremlin/plugin/script/GremlinCalciteScriptEngineFactory.java
@@ -0,0 +1,107 @@
+/*
+ * Copyright 2020 Alibaba Group Holding Limited.
+ *
+ * Licensed 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 com.alibaba.graphscope.gremlin.plugin.script;
+
+import com.alibaba.graphscope.common.ir.tools.QueryCache;
+import com.alibaba.graphscope.common.store.IrMeta;
+
+import org.apache.tinkerpop.gremlin.jsr223.AbstractGremlinScriptEngineFactory;
+import org.apache.tinkerpop.gremlin.jsr223.GremlinScriptEngine;
+import org.apache.tinkerpop.gremlin.jsr223.GremlinScriptEngineFactory;
+import org.apache.tinkerpop.gremlin.process.traversal.Bytecode;
+import org.apache.tinkerpop.gremlin.process.traversal.Traversal;
+
+import java.io.Reader;
+import java.util.Collections;
+import java.util.List;
+import java.util.concurrent.ExecutionException;
+
+import javax.script.AbstractScriptEngine;
+import javax.script.Bindings;
+import javax.script.ScriptContext;
+import javax.script.ScriptException;
+
+public class GremlinCalciteScriptEngineFactory extends AbstractGremlinScriptEngineFactory {
+    private static final String PLAIN = "plain";
+    private static final List<String> EXTENSIONS = Collections.singletonList("gremlin");
+
+    public static final String LANGUAGE_NAME = "antlr_gremlin_calcite";
+
+    public GremlinCalciteScriptEngineFactory() {
+        super(LANGUAGE_NAME, LANGUAGE_NAME, EXTENSIONS, Collections.singletonList(PLAIN));
+    }
+
+    @Override
+    public String getMethodCallSyntax(String obj, String m, String... args) {
+        return null;
+    }
+
+    @Override
+    public String getOutputStatement(String toDisplay) {
+        return null;
+    }
+
+    @Override
+    public GremlinScriptEngine getScriptEngine() {
+        return new ScriptEngine();
+    }
+
+    public static class ScriptEngine extends AbstractScriptEngine implements GremlinScriptEngine {
+        private volatile GremlinScriptEngineFactory factory;
+
+        @Override
+        public Object eval(String script, ScriptContext ctx) throws ScriptException {
+            try {
+                Bindings globalBindings = ctx.getBindings(ScriptContext.ENGINE_SCOPE);
+                QueryCache queryCache = (QueryCache) globalBindings.get("graph.query.cache");
+                IrMeta irMeta = (IrMeta) globalBindings.get("graph.meta");
+                QueryCache.Key cacheKey = queryCache.createKey(script, irMeta);
+                return queryCache.get(cacheKey);
+            } catch (ExecutionException e) {
+                return new RuntimeException(e);
+            }
+        }
+
+        @Override
+        public Object eval(Reader reader, ScriptContext context) throws ScriptException {
+            return null;
+        }
+
+        @Override
+        public Bindings createBindings() {
+            return null;
+        }
+
+        @Override
+        public GremlinScriptEngineFactory getFactory() {
+            if (this.factory == null) {
+                synchronized (this) {
+                    if (this.factory == null) {
+                        this.factory = new GremlinCalciteScriptEngineFactory();
+                    }
+                }
+            }
+            return this.factory;
+        }
+
+        @Override
+        public Traversal.Admin eval(Bytecode bytecode, Bindings bindings, String traversalSource)
+                throws ScriptException {
+            return null;
+        }
+    }
+}
diff --git a/interactive_engine/compiler/src/main/java/com/alibaba/graphscope/gremlin/resultx/GremlinRecordParser.java b/interactive_engine/compiler/src/main/java/com/alibaba/graphscope/gremlin/resultx/GremlinRecordParser.java
new file mode 100644
index 000000000000..5068e2d7e540
--- /dev/null
+++ b/interactive_engine/compiler/src/main/java/com/alibaba/graphscope/gremlin/resultx/GremlinRecordParser.java
@@ -0,0 +1,297 @@
+/*
+ * Copyright 2020 Alibaba Group Holding Limited.
+ *
+ * Licensed 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 com.alibaba.graphscope.gremlin.resultx;
+
+import com.alibaba.graphscope.common.ir.type.ArbitraryArrayType;
+import com.alibaba.graphscope.common.ir.type.ArbitraryMapType;
+import com.alibaba.graphscope.common.ir.type.GraphLabelType;
+import com.alibaba.graphscope.common.ir.type.GraphPathType;
+import com.alibaba.graphscope.common.result.RecordParser;
+import com.alibaba.graphscope.common.result.Utils;
+import com.alibaba.graphscope.gaia.proto.Common;
+import com.alibaba.graphscope.gaia.proto.IrResult;
+import com.alibaba.graphscope.gremlin.exception.GremlinResultParserException;
+import com.google.common.base.Preconditions;
+import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.Lists;
+import com.google.common.collect.Maps;
+
+import org.apache.calcite.rel.type.RelDataType;
+import org.apache.calcite.rel.type.RelDataTypeField;
+import org.apache.commons.lang3.NotImplementedException;
+import org.apache.tinkerpop.gremlin.structure.Edge;
+import org.apache.tinkerpop.gremlin.structure.Element;
+import org.apache.tinkerpop.gremlin.structure.T;
+import org.apache.tinkerpop.gremlin.structure.Vertex;
+import org.apache.tinkerpop.gremlin.structure.util.detached.DetachedEdge;
+import org.apache.tinkerpop.gremlin.structure.util.detached.DetachedVertex;
+import org.checkerframework.checker.nullness.qual.Nullable;
+
+import java.util.List;
+import java.util.Map;
+import java.util.stream.Collectors;
+
+public class GremlinRecordParser implements RecordParser<Object> {
+    protected final ResultSchema resultSchema;
+
+    public GremlinRecordParser(ResultSchema resultSchema) {
+        this.resultSchema = resultSchema;
+    }
+
+    @Override
+    public List<Object> parseFrom(IrResult.Record record) {
+        RelDataType outputType = resultSchema.outputType;
+        Preconditions.checkArgument(
+                record.getColumnsCount() == outputType.getFieldCount(),
+                "column size of results "
+                        + record.getColumnsCount()
+                        + " should be consistent with output type "
+                        + outputType.getFieldCount());
+        Map<Object, Object> mapValue = Maps.newLinkedHashMap();
+        if (resultSchema.isGroupBy) {
+            Preconditions.checkArgument(
+                    resultSchema.groupKeyCount <= outputType.getFieldCount(),
+                    "invalid group key count " + resultSchema.groupKeyCount);
+            List<Object> groupKeys = Lists.newArrayList();
+            for (int i = 0; i < resultSchema.groupKeyCount; i++) {
+                IrResult.Column column = record.getColumns(i);
+                RelDataTypeField field = outputType.getFieldList().get(i);
+                groupKeys.add(parseEntry(column.getEntry(), field.getType()));
+            }
+            List<Object> groupValues = Lists.newArrayList();
+            for (int i = resultSchema.groupKeyCount; i < record.getColumnsCount(); i++) {
+                IrResult.Column column = record.getColumns(i);
+                RelDataTypeField field = outputType.getFieldList().get(i);
+                Object value = parseEntry(column.getEntry(), field.getType());
+                if (value != null) {
+                    groupValues.add(value);
+                }
+            }
+            if (!groupValues.isEmpty() && !groupKeys.isEmpty()) {
+                mapValue.put(
+                        groupKeys.size() == 1 ? groupKeys.get(0) : groupKeys,
+                        groupValues.size() == 1 ? groupValues.get(0) : groupValues);
+            }
+        } else {
+            for (int i = 0; i < record.getColumnsCount(); i++) {
+                IrResult.Column column = record.getColumns(i);
+                RelDataTypeField field = outputType.getFieldList().get(i);
+                mapValue.put(field.getName(), parseEntry(column.getEntry(), field.getType()));
+            }
+        }
+        return Lists.newArrayList(
+                !resultSchema.isGroupBy && mapValue.size() == 1
+                        ? mapValue.values().iterator().next()
+                        : mapValue);
+    }
+
+    @Override
+    public RelDataType schema() {
+        return this.resultSchema.outputType;
+    }
+
+    private Object parseEntry(IrResult.Entry entry, RelDataType type) {
+        if (type instanceof GraphPathType) {
+            return parseElement(entry.getElement(), type);
+        }
+        switch (type.getSqlTypeName()) {
+            case MULTISET:
+            case ARRAY:
+                if (type instanceof ArbitraryArrayType) {
+                    return parseCollection(
+                            entry.getCollection(), ((ArbitraryArrayType) type).getComponentTypes());
+                } else {
+                    return parseCollection(entry.getCollection(), type.getComponentType());
+                }
+            case MAP:
+                if (type instanceof ArbitraryMapType) {
+                    return parseKeyValues(
+                            entry.getMap(),
+                            ((ArbitraryMapType) type).getKeyTypes(),
+                            ((ArbitraryMapType) type).getValueTypes());
+                } else {
+                    return parseKeyValues(entry.getMap(), type.getKeyType(), type.getValueType());
+                }
+            default:
+                return parseElement(entry.getElement(), type);
+        }
+    }
+
+    private List<Object> parseCollection(
+            IrResult.Collection collection, RelDataType componentType) {
+        return collection.getCollectionList().stream()
+                .map(k -> parseElement(k, componentType))
+                .collect(Collectors.toList());
+    }
+
+    private List<Object> parseCollection(
+            IrResult.Collection collection, List<RelDataType> componentTypes) {
+        List<IrResult.Element> elements = collection.getCollectionList();
+        Preconditions.checkArgument(
+                elements.size() == componentTypes.size(),
+                "Collection element size="
+                        + elements.size()
+                        + " is not consistent with type size="
+                        + componentTypes.size());
+        List<Object> values = Lists.newArrayList();
+        for (int i = 0; i < elements.size(); ++i) {
+            values.add(parseElement(elements.get(i), componentTypes.get(i)));
+        }
+        return values;
+    }
+
+    private Map<Object, Object> parseKeyValues(
+            IrResult.KeyValues keyValues, RelDataType keyType, RelDataType valueType) {
+        Map<Object, Object> valueMap = Maps.newLinkedHashMap();
+        keyValues
+                .getKeyValuesList()
+                .forEach(
+                        entry -> {
+                            Object value = parseElement(entry.getValue(), valueType);
+                            if (value != null) {
+                                valueMap.put(parseMapKey(entry.getKey().getStr()), value);
+                            }
+                        });
+        return valueMap;
+    }
+
+    private Map<Object, Object> parseKeyValues(
+            IrResult.KeyValues keyValues,
+            List<RelDataType> keyTypes,
+            List<RelDataType> valueTypes) {
+        List<IrResult.KeyValues.KeyValue> entries = keyValues.getKeyValuesList();
+        Preconditions.checkArgument(
+                entries.size() == valueTypes.size(),
+                "KeyValues entry size="
+                        + entries.size()
+                        + " is not consistent with value type size="
+                        + valueTypes.size());
+        Map<Object, Object> valueMap = Maps.newLinkedHashMap();
+        for (int i = 0; i < entries.size(); ++i) {
+            IrResult.KeyValues.KeyValue entry = entries.get(i);
+            Object value = parseElement(entry.getValue(), valueTypes.get(i));
+            if (value != null) {
+                valueMap.put(parseMapKey(entry.getKey().getStr()), value);
+            }
+        }
+        return valueMap;
+    }
+
+    private Object parseMapKey(String mapKey) {
+        if (mapKey.equals(T.id.getAccessor())) {
+            return T.id;
+        } else if (mapKey.equals(T.label.getAccessor())) {
+            return T.label;
+        } else if (mapKey.equals(T.key.getAccessor())) {
+            return T.key;
+        } else if (mapKey.equals(T.value.getAccessor())) {
+            return T.value;
+        } else {
+            return mapKey;
+        }
+    }
+
+    private Object parseElement(IrResult.Element element, RelDataType type) {
+        switch (element.getInnerCase()) {
+            case VERTEX:
+                return parseVertex(element.getVertex(), type);
+            case EDGE:
+                return parseEdge(element.getEdge(), type);
+            case GRAPH_PATH:
+                return parseGraphPath(element.getGraphPath(), type);
+            case OBJECT:
+            default:
+                return parseValue(element.getObject(), type);
+        }
+    }
+
+    private Vertex parseVertex(IrResult.Vertex vertex, RelDataType type) {
+        return new DetachedVertex(
+                vertex.getId(),
+                Utils.getLabelName(vertex.getLabel(), Utils.getLabelTypes(type)),
+                parseVertexProperties(vertex, type));
+    }
+
+    private Edge parseEdge(IrResult.Edge edge, RelDataType type) {
+        GraphLabelType labelType = Utils.getLabelTypes(type);
+        return new DetachedEdge(
+                edge.getId(),
+                Utils.getLabelName(edge.getLabel(), labelType),
+                parseEdgeProperties(edge, type),
+                edge.getSrcId(),
+                Utils.getSrcLabelName(edge.getSrcLabel(), labelType),
+                edge.getDstId(),
+                Utils.getDstLabelName(edge.getDstLabel(), labelType));
+    }
+
+    protected Map<String, Object> parseVertexProperties(IrResult.Vertex vertex, RelDataType type) {
+        return ImmutableMap.of();
+    }
+
+    protected Map<String, Object> parseEdgeProperties(IrResult.Edge edge, RelDataType type) {
+        return ImmutableMap.of();
+    }
+
+    private List<Element> parseGraphPath(IrResult.GraphPath path, @Nullable RelDataType dataType) {
+        return path.getPathList().stream()
+                .map(
+                        k -> {
+                            switch (k.getInnerCase()) {
+                                case VERTEX:
+                                    return parseVertex(
+                                            k.getVertex(), Utils.getVertexType(dataType));
+                                case EDGE:
+                                    return parseEdge(k.getEdge(), Utils.getEdgeType(dataType));
+                                default:
+                                    throw new GremlinResultParserException(
+                                            k.getInnerCase() + " is invalid");
+                            }
+                        })
+                .collect(Collectors.toList());
+    }
+
+    protected @Nullable Object parseValue(Common.Value value, @Nullable RelDataType dataType) {
+        if (dataType instanceof GraphLabelType) {
+            return Utils.parseLabelValue(value, (GraphLabelType) dataType);
+        }
+        switch (value.getItemCase()) {
+            case BOOLEAN:
+                return value.getBoolean();
+            case I32:
+                return value.getI32();
+            case I64:
+                return value.getI64();
+            case F64:
+                return value.getF64();
+            case STR:
+                return value.getStr();
+            case I32_ARRAY:
+                return value.getI32Array().getItemList();
+            case I64_ARRAY:
+                return value.getI64Array().getItemList();
+            case F64_ARRAY:
+                return value.getF64Array().getItemList();
+            case STR_ARRAY:
+                return value.getStrArray().getItemList();
+            case NONE:
+                return null;
+                // todo: support temporal types
+            default:
+                throw new NotImplementedException(value.getItemCase() + " is unsupported yet");
+        }
+    }
+}
diff --git a/interactive_engine/compiler/src/main/java/com/alibaba/graphscope/gremlin/resultx/GremlinResultProcessor.java b/interactive_engine/compiler/src/main/java/com/alibaba/graphscope/gremlin/resultx/GremlinResultProcessor.java
new file mode 100644
index 000000000000..138419f256d1
--- /dev/null
+++ b/interactive_engine/compiler/src/main/java/com/alibaba/graphscope/gremlin/resultx/GremlinResultProcessor.java
@@ -0,0 +1,93 @@
+/*
+ * Copyright 2020 Alibaba Group Holding Limited.
+ *
+ * Licensed 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 com.alibaba.graphscope.gremlin.resultx;
+
+import com.alibaba.graphscope.common.client.type.ExecutionResponseListener;
+import com.alibaba.graphscope.common.result.RecordParser;
+import com.alibaba.graphscope.gaia.proto.IrResult;
+import com.alibaba.graphscope.gremlin.plugin.QueryStatusCallback;
+import com.google.common.collect.Lists;
+import com.google.common.collect.Maps;
+
+import org.apache.tinkerpop.gremlin.driver.message.ResponseMessage;
+import org.apache.tinkerpop.gremlin.driver.message.ResponseStatusCode;
+import org.apache.tinkerpop.gremlin.server.Context;
+
+import java.util.List;
+import java.util.Map;
+
+public class GremlinResultProcessor implements ExecutionResponseListener {
+    protected final Context ctx;
+    protected final QueryStatusCallback statusCallback;
+    protected final RecordParser<Object> recordParser;
+    protected final ResultSchema resultSchema;
+    protected final Map<Object, Object> reducer;
+
+    public GremlinResultProcessor(
+            Context ctx,
+            QueryStatusCallback statusCallback,
+            RecordParser recordParser,
+            ResultSchema resultSchema) {
+        this.ctx = ctx;
+        this.statusCallback = statusCallback;
+        this.recordParser = recordParser;
+        this.resultSchema = resultSchema;
+        this.reducer = Maps.newLinkedHashMap();
+    }
+
+    @Override
+    public void onNext(IrResult.Record record) {
+        List<Object> results = recordParser.parseFrom(record);
+        if (resultSchema.isGroupBy && !results.isEmpty()) {
+            if (results.stream().anyMatch(k -> !(k instanceof Map))) {
+                throw new IllegalArgumentException(
+                        "cannot reduce results " + results + " into a single map");
+            }
+            for (Object result : results) {
+                reducer.putAll((Map) result);
+            }
+        } else if (!resultSchema.isGroupBy) {
+            ctx.writeAndFlush(
+                    ResponseMessage.build(ctx.getRequestMessage())
+                            .code(ResponseStatusCode.PARTIAL_CONTENT)
+                            .result(results)
+                            .create());
+        }
+    }
+
+    @Override
+    public void onCompleted() {
+        List<Object> results = Lists.newArrayList();
+        if (resultSchema.isGroupBy) {
+            results.add(reducer);
+        }
+        ctx.writeAndFlush(
+                ResponseMessage.build(ctx.getRequestMessage())
+                        .code(ResponseStatusCode.SUCCESS)
+                        .result(results)
+                        .create());
+    }
+
+    @Override
+    public void onError(Throwable t) {
+        ctx.writeAndFlush(
+                ResponseMessage.build(ctx.getRequestMessage())
+                        .code(ResponseStatusCode.SERVER_ERROR)
+                        .statusMessage(t.getMessage())
+                        .create());
+    }
+}
diff --git a/interactive_engine/compiler/src/main/java/com/alibaba/graphscope/gremlin/resultx/ResultSchema.java b/interactive_engine/compiler/src/main/java/com/alibaba/graphscope/gremlin/resultx/ResultSchema.java
new file mode 100644
index 000000000000..8ec0888a35f6
--- /dev/null
+++ b/interactive_engine/compiler/src/main/java/com/alibaba/graphscope/gremlin/resultx/ResultSchema.java
@@ -0,0 +1,62 @@
+/*
+ * Copyright 2020 Alibaba Group Holding Limited.
+ *
+ * Licensed 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 com.alibaba.graphscope.gremlin.resultx;
+
+import com.alibaba.graphscope.common.ir.rel.GraphLogicalAggregate;
+import com.alibaba.graphscope.common.ir.tools.LogicalPlan;
+import com.google.common.collect.Lists;
+
+import org.apache.calcite.rel.RelNode;
+import org.apache.calcite.rel.type.RelDataType;
+import org.checkerframework.checker.nullness.qual.Nullable;
+
+import java.util.List;
+
+public class ResultSchema {
+    public final RelDataType outputType;
+    public final boolean isGroupBy;
+    public final int groupKeyCount;
+
+    public ResultSchema(LogicalPlan plan) {
+        this.outputType = plan.getOutputType();
+        GraphLogicalAggregate aggregate = tailAggregate(plan);
+        this.isGroupBy = aggregate != null;
+        this.groupKeyCount = getGroupKeyCount(aggregate);
+    }
+
+    private @Nullable GraphLogicalAggregate tailAggregate(LogicalPlan logicalPlan) {
+        RelNode top = logicalPlan.getRegularQuery();
+        List<RelNode> queue = Lists.newArrayList(top);
+        while (!queue.isEmpty()) {
+            RelNode node = queue.remove(0);
+            if (!node.getInputs().isEmpty()
+                    && node.getInput(0).getRowType().equals(node.getRowType())) {
+                queue.addAll(node.getInputs());
+            } else if (node instanceof GraphLogicalAggregate
+                    && !((GraphLogicalAggregate) node).getAggCalls().isEmpty()
+                    && ((GraphLogicalAggregate) node).getGroupKey().groupKeyCount() != 0) {
+                return (GraphLogicalAggregate) node;
+            }
+        }
+        return null;
+    }
+
+    private int getGroupKeyCount(@Nullable GraphLogicalAggregate aggregate) {
+        if (aggregate == null) return 0;
+        return aggregate.getGroupKey().groupKeyCount();
+    }
+}
diff --git a/interactive_engine/compiler/src/main/java/com/alibaba/graphscope/gremlin/service/IrGremlinServer.java b/interactive_engine/compiler/src/main/java/com/alibaba/graphscope/gremlin/service/IrGremlinServer.java
index 5db959a2e684..cd7744b0ec1d 100644
--- a/interactive_engine/compiler/src/main/java/com/alibaba/graphscope/gremlin/service/IrGremlinServer.java
+++ b/interactive_engine/compiler/src/main/java/com/alibaba/graphscope/gremlin/service/IrGremlinServer.java
@@ -16,10 +16,12 @@
 
 package com.alibaba.graphscope.gremlin.service;
 
+import com.alibaba.graphscope.common.client.ExecutionClient;
 import com.alibaba.graphscope.common.client.channel.ChannelFetcher;
 import com.alibaba.graphscope.common.config.Configs;
 import com.alibaba.graphscope.common.config.FrontendConfig;
-import com.alibaba.graphscope.common.ir.tools.GraphPlanner;
+import com.alibaba.graphscope.common.ir.tools.QueryCache;
+import com.alibaba.graphscope.common.ir.tools.QueryIdGenerator;
 import com.alibaba.graphscope.common.manager.IrMetaQueryCallback;
 import com.alibaba.graphscope.common.manager.RateLimitExecutor;
 import com.alibaba.graphscope.gremlin.Utils;
@@ -46,7 +48,8 @@
 
 public class IrGremlinServer implements AutoCloseable {
     private final Configs configs;
-    private final GraphPlanner graphPlanner;
+    private final QueryCache queryCache;
+    private final ExecutionClient executionClient;
     private final ChannelFetcher channelFetcher;
     private final IrMetaQueryCallback metaQueryCallback;
     private final GraphProperties testGraph;
@@ -56,14 +59,20 @@ public class IrGremlinServer implements AutoCloseable {
     private final Graph graph;
     private final GraphTraversalSource g;
 
+    private final QueryIdGenerator idGenerator;
+
     public IrGremlinServer(
             Configs configs,
-            GraphPlanner graphPlanner,
+            QueryIdGenerator idGenerator,
+            QueryCache queryCache,
+            ExecutionClient executionClient,
             ChannelFetcher channelFetcher,
             IrMetaQueryCallback metaQueryCallback,
             GraphProperties testGraph) {
         this.configs = configs;
-        this.graphPlanner = graphPlanner;
+        this.idGenerator = idGenerator;
+        this.queryCache = queryCache;
+        this.executionClient = executionClient;
         this.channelFetcher = channelFetcher;
         this.metaQueryCallback = metaQueryCallback;
         this.testGraph = testGraph;
@@ -83,12 +92,21 @@ public IrGremlinServer(
     public void start() throws Exception {
         AbstractOpProcessor standardProcessor =
                 new IrStandardOpProcessor(
-                        configs, graphPlanner, channelFetcher, metaQueryCallback, graph, g);
+                        configs,
+                        idGenerator,
+                        queryCache,
+                        executionClient,
+                        channelFetcher,
+                        metaQueryCallback,
+                        graph,
+                        g);
         IrOpLoader.addProcessor(standardProcessor.getName(), standardProcessor);
         AbstractOpProcessor testProcessor =
                 new IrTestOpProcessor(
                         configs,
-                        graphPlanner,
+                        idGenerator,
+                        queryCache,
+                        executionClient,
                         channelFetcher,
                         metaQueryCallback,
                         graph,
diff --git a/interactive_engine/compiler/src/main/resources/META-INF/services/org.apache.tinkerpop.gremlin.jsr223.GremlinScriptEngineFactory b/interactive_engine/compiler/src/main/resources/META-INF/services/org.apache.tinkerpop.gremlin.jsr223.GremlinScriptEngineFactory
index 55d68fd6b02f..36a5e9769f03 100644
--- a/interactive_engine/compiler/src/main/resources/META-INF/services/org.apache.tinkerpop.gremlin.jsr223.GremlinScriptEngineFactory
+++ b/interactive_engine/compiler/src/main/resources/META-INF/services/org.apache.tinkerpop.gremlin.jsr223.GremlinScriptEngineFactory
@@ -1,1 +1,2 @@
 com.alibaba.graphscope.gremlin.plugin.script.AntlrGremlinScriptEngineFactory
+com.alibaba.graphscope.gremlin.plugin.script.GremlinCalciteScriptEngineFactory


Test patch:
diff --git a/interactive_engine/compiler/src/test/java/com/alibaba/graphscope/gremlin/antlr4x/GraphBuilderTest.java b/interactive_engine/compiler/src/test/java/com/alibaba/graphscope/gremlin/antlr4x/GraphBuilderTest.java
new file mode 100644
index 000000000000..6335f89b08d5
--- /dev/null
+++ b/interactive_engine/compiler/src/test/java/com/alibaba/graphscope/gremlin/antlr4x/GraphBuilderTest.java
@@ -0,0 +1,647 @@
+/*
+ * Copyright 2020 Alibaba Group Holding Limited.
+ *
+ * Licensed 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 com.alibaba.graphscope.gremlin.antlr4x;
+
+import com.alibaba.graphscope.common.ir.Utils;
+import com.alibaba.graphscope.common.ir.tools.GraphBuilder;
+import com.alibaba.graphscope.gremlin.antlr4x.parser.GremlinAntlr4Parser;
+import com.alibaba.graphscope.gremlin.antlr4x.visitor.GraphBuilderVisitor;
+
+import org.antlr.v4.runtime.tree.ParseTree;
+import org.apache.calcite.rel.RelNode;
+import org.junit.Assert;
+import org.junit.Test;
+
+public class GraphBuilderTest {
+    public static RelNode eval(String query) {
+        GraphBuilder builder = Utils.mockGraphBuilder();
+        GraphBuilderVisitor visitor = new GraphBuilderVisitor(builder);
+        ParseTree parseTree = new GremlinAntlr4Parser().parse(query);
+        return visitor.visit(parseTree).build();
+    }
+
+    @Test
+    public void g_V_test() {
+        RelNode node = eval("g.V()");
+        Assert.assertEquals(
+                "GraphLogicalProject(DEFAULT=[DEFAULT], isAppend=[false])\n"
+                    + "  GraphLogicalSource(tableConfig=[{isAll=true, tables=[software, person]}],"
+                    + " alias=[DEFAULT], opt=[VERTEX])",
+                node.explain().trim());
+    }
+
+    @Test
+    public void g_V_id_test() {
+        RelNode node = eval("g.V(1, 2, 3)");
+        Assert.assertEquals(
+                "GraphLogicalProject(DEFAULT=[DEFAULT], isAppend=[false])\n"
+                    + "  GraphLogicalSource(tableConfig=[{isAll=true, tables=[software, person]}],"
+                    + " alias=[DEFAULT], opt=[VERTEX], uniqueKeyFilters=[SEARCH(DEFAULT.~id,"
+                    + " Sarg[1, 2, 3])])",
+                node.explain().trim());
+    }
+
+    @Test
+    public void g_V_hasLabel_test() {
+        RelNode node = eval("g.V().hasLabel('person')");
+        Assert.assertEquals(
+                "GraphLogicalProject(DEFAULT=[DEFAULT], isAppend=[false])\n"
+                        + "  GraphLogicalSource(tableConfig=[{isAll=false, tables=[person]}],"
+                        + " alias=[DEFAULT], opt=[VERTEX])",
+                node.explain().trim());
+    }
+
+    @Test
+    public void g_V_hasLabel_as_test() {
+        RelNode node = eval("g.V().hasLabel('person').as('a')");
+        Assert.assertEquals(
+                "GraphLogicalProject(a=[a], isAppend=[false])\n"
+                        + "  GraphLogicalSource(tableConfig=[{isAll=false, tables=[person]}],"
+                        + " alias=[a], opt=[VERTEX])",
+                node.explain().trim());
+    }
+
+    @Test
+    public void g_V_hasLabels_as_test() {
+        RelNode node = eval("g.V().hasLabel('person', 'software').as('a')");
+        Assert.assertEquals(
+                "GraphLogicalProject(a=[a], isAppend=[false])\n"
+                    + "  GraphLogicalSource(tableConfig=[{isAll=true, tables=[software, person]}],"
+                    + " alias=[a], opt=[VERTEX])",
+                node.explain().trim());
+    }
+
+    @Test
+    public void g_V_hasLabel_error_test() {
+        try {
+            RelNode node = eval("g.V().hasLabel('person').hasLabel('software')");
+        } catch (IllegalArgumentException e) {
+            Assert.assertEquals(
+                    "cannot find common labels between values= [software] and label="
+                            + " [[VertexLabel(person)]]",
+                    e.getMessage());
+            return;
+        }
+        Assert.fail();
+    }
+
+    @Test
+    public void g_V_hasId_test() {
+        RelNode node = eval("g.V().hasId(1)");
+        Assert.assertEquals(
+                "GraphLogicalProject(DEFAULT=[DEFAULT], isAppend=[false])\n"
+                    + "  GraphLogicalSource(tableConfig=[{isAll=true, tables=[software, person]}],"
+                    + " alias=[DEFAULT], opt=[VERTEX], uniqueKeyFilters=[=(DEFAULT.~id, 1)])",
+                node.explain().trim());
+    }
+
+    @Test
+    public void g_V_hasIds_test() {
+        RelNode node = eval("g.V().hasId(1, 2, 3)");
+        Assert.assertEquals(
+                "GraphLogicalProject(DEFAULT=[DEFAULT], isAppend=[false])\n"
+                    + "  GraphLogicalSource(tableConfig=[{isAll=true, tables=[software, person]}],"
+                    + " alias=[DEFAULT], opt=[VERTEX], uniqueKeyFilters=[SEARCH(DEFAULT.~id,"
+                    + " Sarg[1, 2, 3])])",
+                node.explain().trim());
+    }
+
+    @Test
+    public void g_V_has_name_marko_test() {
+        RelNode node = eval("g.V().has('name', 'marko')");
+        Assert.assertEquals(
+                "GraphLogicalProject(DEFAULT=[DEFAULT], isAppend=[false])\n"
+                    + "  GraphLogicalSource(tableConfig=[{isAll=true, tables=[software, person]}],"
+                    + " alias=[DEFAULT], fusedFilter=[[=(DEFAULT.name, _UTF-8'marko')]],"
+                    + " opt=[VERTEX])",
+                node.explain().trim());
+    }
+
+    @Test
+    public void g_V_has_name_eq_marko_test() {
+        RelNode node = eval("g.V().has('name', eq('marko'))");
+        Assert.assertEquals(
+                "GraphLogicalProject(DEFAULT=[DEFAULT], isAppend=[false])\n"
+                    + "  GraphLogicalSource(tableConfig=[{isAll=true, tables=[software, person]}],"
+                    + " alias=[DEFAULT], fusedFilter=[[=(DEFAULT.name, _UTF-8'marko')]],"
+                    + " opt=[VERTEX])",
+                node.explain().trim());
+    }
+
+    @Test
+    public void g_V_has_name_neq_marko_test() {
+        RelNode node = eval("g.V().has('name', neq('marko'))");
+        Assert.assertEquals(
+                "GraphLogicalProject(DEFAULT=[DEFAULT], isAppend=[false])\n"
+                    + "  GraphLogicalSource(tableConfig=[{isAll=true, tables=[software, person]}],"
+                    + " alias=[DEFAULT], fusedFilter=[[<>(DEFAULT.name, _UTF-8'marko')]],"
+                    + " opt=[VERTEX])",
+                node.explain().trim());
+    }
+
+    @Test
+    public void g_V_has_age_gt_17_test() {
+        RelNode node = eval("g.V().has('age', gt(17))");
+        Assert.assertEquals(
+                "GraphLogicalProject(DEFAULT=[DEFAULT], isAppend=[false])\n"
+                    + "  GraphLogicalSource(tableConfig=[{isAll=true, tables=[software, person]}],"
+                    + " alias=[DEFAULT], fusedFilter=[[>(DEFAULT.age, 17)]], opt=[VERTEX])",
+                node.explain().trim());
+    }
+
+    // hasNot('age') -> age is null
+    @Test
+    public void g_V_hasNot_age_test() {
+        RelNode node = eval("g.V().hasNot('age')");
+        Assert.assertEquals(
+                "GraphLogicalProject(DEFAULT=[DEFAULT], isAppend=[false])\n"
+                    + "  GraphLogicalSource(tableConfig=[{isAll=true, tables=[software, person]}],"
+                    + " alias=[DEFAULT], fusedFilter=[[IS NULL(DEFAULT.age)]], opt=[VERTEX])",
+                node.explain().trim());
+    }
+
+    @Test
+    public void g_V_has_age_inside_17_20_test() {
+        RelNode node = eval("g.V().has('age', inside(17, 20))");
+        Assert.assertEquals(
+                "GraphLogicalProject(DEFAULT=[DEFAULT], isAppend=[false])\n"
+                    + "  GraphLogicalSource(tableConfig=[{isAll=true, tables=[software, person]}],"
+                    + " alias=[DEFAULT], fusedFilter=[[SEARCH(DEFAULT.age, Sarg[[18..19]])]],"
+                    + " opt=[VERTEX])",
+                node.explain().trim());
+    }
+
+    @Test
+    public void g_V_has_age_outside_17_20_test() {
+        RelNode node = eval("g.V().has('age', outside(17, 20))");
+        Assert.assertEquals(
+                "GraphLogicalProject(DEFAULT=[DEFAULT], isAppend=[false])\n"
+                    + "  GraphLogicalSource(tableConfig=[{isAll=true, tables=[software, person]}],"
+                    + " alias=[DEFAULT], fusedFilter=[[SEARCH(DEFAULT.age, Sarg[(-∞..18),"
+                    + " (19..+∞)])]], opt=[VERTEX])",
+                node.explain().trim());
+    }
+
+    @Test
+    public void g_V_has_age_within_test() {
+        RelNode node = eval("g.V().has('age', within(17, 20))");
+        Assert.assertEquals(
+                "GraphLogicalProject(DEFAULT=[DEFAULT], isAppend=[false])\n"
+                    + "  GraphLogicalSource(tableConfig=[{isAll=true, tables=[software, person]}],"
+                    + " alias=[DEFAULT], fusedFilter=[[SEARCH(DEFAULT.age, Sarg[17, 20])]],"
+                    + " opt=[VERTEX])",
+                node.explain().trim());
+    }
+
+    @Test
+    public void g_V_has_age_without_test() {
+        RelNode node = eval("g.V().has('age', without(17, 20))");
+        Assert.assertEquals(
+                "GraphLogicalProject(DEFAULT=[DEFAULT], isAppend=[false])\n"
+                    + "  GraphLogicalSource(tableConfig=[{isAll=true, tables=[software, person]}],"
+                    + " alias=[DEFAULT], fusedFilter=[[SEARCH(DEFAULT.age, Sarg[(-∞..17), (17..20),"
+                    + " (20..+∞)])]], opt=[VERTEX])",
+                node.explain().trim());
+    }
+
+    @Test
+    public void g_V_has_name_endingWith_test() {
+        RelNode node = eval("g.V().has('name', endingWith('mar'))");
+        Assert.assertEquals(
+                "GraphLogicalProject(DEFAULT=[DEFAULT], isAppend=[false])\n"
+                    + "  GraphLogicalSource(tableConfig=[{isAll=true, tables=[software, person]}],"
+                    + " alias=[DEFAULT], fusedFilter=[[POSIX REGEX CASE SENSITIVE(DEFAULT.name,"
+                    + " _UTF-8'mar$')]], opt=[VERTEX])",
+                node.explain().trim());
+    }
+
+    @Test
+    public void g_V_has_name_not_endingWith_test() {
+        RelNode node = eval("g.V().has('name', notEndingWith('mar'))");
+        Assert.assertEquals(
+                "GraphLogicalProject(DEFAULT=[DEFAULT], isAppend=[false])\n"
+                    + "  GraphLogicalSource(tableConfig=[{isAll=true, tables=[software, person]}],"
+                    + " alias=[DEFAULT], fusedFilter=[[NOT(POSIX REGEX CASE SENSITIVE(DEFAULT.name,"
+                    + " _UTF-8'mar$'))]], opt=[VERTEX])",
+                node.explain().trim());
+    }
+
+    @Test
+    public void g_V_has_name_containing_test() {
+        RelNode node = eval("g.V().has('name', containing('mar'))");
+        Assert.assertEquals(
+                "GraphLogicalProject(DEFAULT=[DEFAULT], isAppend=[false])\n"
+                    + "  GraphLogicalSource(tableConfig=[{isAll=true, tables=[software, person]}],"
+                    + " alias=[DEFAULT], fusedFilter=[[POSIX REGEX CASE SENSITIVE(DEFAULT.name,"
+                    + " _UTF-8'.*mar.*')]], opt=[VERTEX])",
+                node.explain().trim());
+    }
+
+    @Test
+    public void g_V_has_name_not_containing_test() {
+        RelNode node = eval("g.V().has('name', notContaining('mar'))");
+        Assert.assertEquals(
+                "GraphLogicalProject(DEFAULT=[DEFAULT], isAppend=[false])\n"
+                    + "  GraphLogicalSource(tableConfig=[{isAll=true, tables=[software, person]}],"
+                    + " alias=[DEFAULT], fusedFilter=[[NOT(POSIX REGEX CASE SENSITIVE(DEFAULT.name,"
+                    + " _UTF-8'.*mar.*'))]], opt=[VERTEX])",
+                node.explain().trim());
+    }
+
+    @Test
+    public void g_V_has_name_startingWith_test() {
+        RelNode node = eval("g.V().has('name', startingWith('mar'))");
+        Assert.assertEquals(
+                "GraphLogicalProject(DEFAULT=[DEFAULT], isAppend=[false])\n"
+                    + "  GraphLogicalSource(tableConfig=[{isAll=true, tables=[software, person]}],"
+                    + " alias=[DEFAULT], fusedFilter=[[POSIX REGEX CASE SENSITIVE(DEFAULT.name,"
+                    + " _UTF-8'^mar')]], opt=[VERTEX])",
+                node.explain().trim());
+    }
+
+    @Test
+    public void g_V_has_name_not_startingWith_test() {
+        RelNode node = eval("g.V().has('name', notStartingWith('mar'))");
+        Assert.assertEquals(
+                "GraphLogicalProject(DEFAULT=[DEFAULT], isAppend=[false])\n"
+                    + "  GraphLogicalSource(tableConfig=[{isAll=true, tables=[software, person]}],"
+                    + " alias=[DEFAULT], fusedFilter=[[NOT(POSIX REGEX CASE SENSITIVE(DEFAULT.name,"
+                    + " _UTF-8'^mar'))]], opt=[VERTEX])",
+                node.explain().trim());
+    }
+
+    @Test
+    public void g_V_has_name_marko_age_17_has_label_test() {
+        RelNode node = eval("g.V().has('name', 'marko').has('age', 17).hasLabel('person')");
+        Assert.assertEquals(
+                "GraphLogicalProject(DEFAULT=[DEFAULT], isAppend=[false])\n"
+                        + "  GraphLogicalSource(tableConfig=[{isAll=false, tables=[person]}],"
+                        + " alias=[DEFAULT], fusedFilter=[[AND(=(DEFAULT.name, _UTF-8'marko'),"
+                        + " =(DEFAULT.age, 17))]], opt=[VERTEX])",
+                node.explain().trim());
+    }
+
+    @Test
+    public void g_V_has_name_marko_age_17_has_label_error_test() {
+        try {
+            RelNode node = eval("g.V().has('name', 'marko').has('age', 17).hasLabel('software')");
+        } catch (IllegalArgumentException e) {
+            Assert.assertEquals(
+                    "{property=age} not found; expected properties are: [id, name, lang,"
+                            + " creationDate]",
+                    e.getMessage());
+            return;
+        }
+        Assert.fail();
+    }
+
+    @Test
+    public void g_V_out_test() {
+        RelNode node = eval("g.V().out()");
+        Assert.assertEquals(
+                "GraphLogicalProject(DEFAULT=[DEFAULT], isAppend=[false])\n"
+                    + "  GraphLogicalGetV(tableConfig=[{isAll=true, tables=[software, person]}],"
+                    + " alias=[DEFAULT], opt=[END])\n"
+                    + "    GraphLogicalExpand(tableConfig=[{isAll=true, tables=[created, knows]}],"
+                    + " alias=[DEFAULT], opt=[OUT])\n"
+                    + "      GraphLogicalSource(tableConfig=[{isAll=true, tables=[software,"
+                    + " person]}], alias=[DEFAULT], opt=[VERTEX])",
+                node.explain().trim());
+    }
+
+    @Test
+    public void g_V_out_label_test() {
+        RelNode node = eval("g.V().out('knows')");
+        Assert.assertEquals(
+                "GraphLogicalProject(DEFAULT=[DEFAULT], isAppend=[false])\n"
+                    + "  GraphLogicalGetV(tableConfig=[{isAll=true, tables=[software, person]}],"
+                    + " alias=[DEFAULT], opt=[END])\n"
+                    + "    GraphLogicalExpand(tableConfig=[{isAll=false, tables=[knows]}],"
+                    + " alias=[DEFAULT], opt=[OUT])\n"
+                    + "      GraphLogicalSource(tableConfig=[{isAll=true, tables=[software,"
+                    + " person]}], alias=[DEFAULT], opt=[VERTEX])",
+                node.explain().trim());
+    }
+
+    @Test
+    public void g_V_out_label_as_test() {
+        RelNode node = eval("g.V().as('a').out().as('b')");
+        Assert.assertEquals(
+                "GraphLogicalProject(b=[b], isAppend=[false])\n"
+                    + "  GraphLogicalGetV(tableConfig=[{isAll=true, tables=[software, person]}],"
+                    + " alias=[b], opt=[END])\n"
+                    + "    GraphLogicalExpand(tableConfig=[{isAll=true, tables=[created, knows]}],"
+                    + " alias=[DEFAULT], opt=[OUT])\n"
+                    + "      GraphLogicalSource(tableConfig=[{isAll=true, tables=[software,"
+                    + " person]}], alias=[a], opt=[VERTEX])",
+                node.explain().trim());
+    }
+
+    @Test
+    public void g_V_path_expand_test() {
+        RelNode node =
+                eval(
+                        "g.V().as('a').out('1..2', 'knows').with('path_opt',"
+                                + " 'simple').with('result_opt', 'all_v').as('b').endV().as('c')");
+        Assert.assertEquals(
+                "GraphLogicalProject(c=[c], isAppend=[false])\n"
+                    + "  GraphLogicalGetV(tableConfig=[{isAll=true, tables=[software, person]}],"
+                    + " alias=[c], opt=[END])\n"
+                    + "    GraphLogicalPathExpand(expand=[GraphLogicalExpand(tableConfig=[{isAll=false,"
+                    + " tables=[knows]}], alias=[DEFAULT], opt=[OUT])\n"
+                    + "], getV=[GraphLogicalGetV(tableConfig=[{isAll=true, tables=[software,"
+                    + " person]}], alias=[DEFAULT], opt=[END])\n"
+                    + "], offset=[1], fetch=[1], path_opt=[SIMPLE], result_opt=[ALL_V],"
+                    + " alias=[b])\n"
+                    + "      GraphLogicalSource(tableConfig=[{isAll=true, tables=[software,"
+                    + " person]}], alias=[a], opt=[VERTEX])",
+                node.explain().trim());
+    }
+
+    @Test
+    public void g_V_values_name_test() {
+        RelNode node = eval("g.V().values('name').as('a')");
+        Assert.assertEquals(
+                "GraphLogicalProject(a=[a], isAppend=[false])\n"
+                        + "  GraphLogicalProject(a=[DEFAULT.name], isAppend=[true])\n"
+                        + "    GraphLogicalSource(tableConfig=[{isAll=true, tables=[software,"
+                        + " person]}], alias=[DEFAULT], opt=[VERTEX])",
+                node.explain().trim());
+    }
+
+    @Test
+    public void g_V_valueMap_name_test() {
+        RelNode node = eval("g.V().valueMap('name').as('a')");
+        Assert.assertEquals(
+                "GraphLogicalProject(a=[a], isAppend=[false])\n"
+                        + "  GraphLogicalProject(a=[MAP(_UTF-8'name', DEFAULT.name)],"
+                        + " isAppend=[true])\n"
+                        + "    GraphLogicalSource(tableConfig=[{isAll=true, tables=[software,"
+                        + " person]}], alias=[DEFAULT], opt=[VERTEX])",
+                node.explain().trim());
+    }
+
+    @Test
+    public void g_V_valueMap_all_test() {
+        RelNode node = eval("g.V().valueMap().as('a')");
+        Assert.assertEquals(
+                "GraphLogicalProject(a=[a], isAppend=[false])\n"
+                        + "  GraphLogicalProject(a=[MAP(_UTF-8'id', DEFAULT.id, _UTF-8'name',"
+                        + " DEFAULT.name, _UTF-8'lang', DEFAULT.lang, _UTF-8'creationDate',"
+                        + " DEFAULT.creationDate, _UTF-8'age', DEFAULT.age)], isAppend=[true])\n"
+                        + "    GraphLogicalSource(tableConfig=[{isAll=true, tables=[software,"
+                        + " person]}], alias=[DEFAULT], opt=[VERTEX])",
+                node.explain().trim());
+    }
+
+    @Test
+    public void g_V_elementMap_all_test() {
+        RelNode node = eval("g.V().elementMap().as('a')");
+        Assert.assertEquals(
+                "GraphLogicalProject(a=[a], isAppend=[false])\n"
+                    + "  GraphLogicalProject(a=[MAP(_UTF-8'~label', DEFAULT.~label, _UTF-8'~id',"
+                    + " DEFAULT.~id, _UTF-8'id', DEFAULT.id, _UTF-8'name', DEFAULT.name,"
+                    + " _UTF-8'lang', DEFAULT.lang, _UTF-8'creationDate', DEFAULT.creationDate,"
+                    + " _UTF-8'age', DEFAULT.age)], isAppend=[true])\n"
+                    + "    GraphLogicalSource(tableConfig=[{isAll=true, tables=[software,"
+                    + " person]}], alias=[DEFAULT], opt=[VERTEX])",
+                node.explain().trim());
+    }
+
+    // todo: optimize select('a'), provide a tag representing 'NONE'
+    @Test
+    public void g_V_select_a_test() {
+        RelNode node = eval("g.V().as('a').select('a')");
+        Assert.assertEquals(
+                "GraphLogicalProject(a=[a], isAppend=[false])\n"
+                    + "  GraphLogicalSource(tableConfig=[{isAll=true, tables=[software, person]}],"
+                    + " alias=[a], opt=[VERTEX])",
+                node.explain().trim());
+    }
+
+    @Test
+    public void g_V_select_a_by_name_test() {
+        RelNode node = eval("g.V().as('a').select('a').by('name')");
+        Assert.assertEquals(
+                "GraphLogicalProject(name=[name], isAppend=[false])\n"
+                        + "  GraphLogicalProject(name=[a.name], isAppend=[true])\n"
+                        + "    GraphLogicalSource(tableConfig=[{isAll=true, tables=[software,"
+                        + " person]}], alias=[a], opt=[VERTEX])",
+                node.explain().trim());
+    }
+
+    @Test
+    public void g_V_select_a_by_valueMap_test() {
+        RelNode node = eval("g.V().as('a').select('a').by(valueMap())");
+        Assert.assertEquals(
+                "GraphLogicalProject($f0=[$f0], isAppend=[false])\n"
+                    + "  GraphLogicalProject($f0=[MAP(_UTF-8'id', a.id, _UTF-8'name', a.name,"
+                    + " _UTF-8'lang', a.lang, _UTF-8'creationDate', a.creationDate, _UTF-8'age',"
+                    + " a.age)], isAppend=[true])\n"
+                    + "    GraphLogicalSource(tableConfig=[{isAll=true, tables=[software,"
+                    + " person]}], alias=[a], opt=[VERTEX])",
+                node.explain().trim());
+    }
+
+    @Test
+    public void g_V_select_a_b_test() {
+        RelNode node = eval("g.V().as('a').out().as('b').select('a', 'b')");
+        Assert.assertEquals(
+                "GraphLogicalProject($f0=[$f0], isAppend=[false])\n"
+                    + "  GraphLogicalProject($f0=[MAP(_UTF-8'a', a, _UTF-8'b', b)],"
+                    + " isAppend=[true])\n"
+                    + "    GraphLogicalGetV(tableConfig=[{isAll=true, tables=[software, person]}],"
+                    + " alias=[b], opt=[END])\n"
+                    + "      GraphLogicalExpand(tableConfig=[{isAll=true, tables=[created,"
+                    + " knows]}], alias=[DEFAULT], opt=[OUT])\n"
+                    + "        GraphLogicalSource(tableConfig=[{isAll=true, tables=[software,"
+                    + " person]}], alias=[a], opt=[VERTEX])",
+                node.explain().trim());
+    }
+
+    @Test
+    public void g_V_select_a_b_by_name_valueMap_test() {
+        RelNode node =
+                eval("g.V().as('a').out().as('b').select('a', 'b').by('name').by(valueMap())");
+        Assert.assertEquals(
+                "GraphLogicalProject($f0=[$f0], isAppend=[false])\n"
+                    + "  GraphLogicalProject($f0=[MAP(_UTF-8'a', a.name, _UTF-8'b', MAP(_UTF-8'id',"
+                    + " b.id, _UTF-8'name', b.name, _UTF-8'lang', b.lang, _UTF-8'creationDate',"
+                    + " b.creationDate, _UTF-8'age', b.age))], isAppend=[true])\n"
+                    + "    GraphLogicalGetV(tableConfig=[{isAll=true, tables=[software, person]}],"
+                    + " alias=[b], opt=[END])\n"
+                    + "      GraphLogicalExpand(tableConfig=[{isAll=true, tables=[created,"
+                    + " knows]}], alias=[DEFAULT], opt=[OUT])\n"
+                    + "        GraphLogicalSource(tableConfig=[{isAll=true, tables=[software,"
+                    + " person]}], alias=[a], opt=[VERTEX])",
+                node.explain().trim());
+    }
+
+    @Test
+    public void g_V_order_test() {
+        RelNode node = eval("g.V().order()");
+        Assert.assertEquals(
+                "GraphLogicalProject(DEFAULT=[DEFAULT], isAppend=[false])\n"
+                        + "  GraphLogicalSort(sort0=[DEFAULT], dir0=[ASC])\n"
+                        + "    GraphLogicalSource(tableConfig=[{isAll=true, tables=[software,"
+                        + " person]}], alias=[DEFAULT], opt=[VERTEX])",
+                node.explain().trim());
+    }
+
+    @Test
+    public void g_V_order_by_name_age_test() {
+        RelNode node = eval("g.V().order().by('name', desc).by('age', asc)");
+        Assert.assertEquals(
+                "GraphLogicalProject(DEFAULT=[DEFAULT], isAppend=[false])\n"
+                    + "  GraphLogicalSort(sort0=[DEFAULT.name], sort1=[DEFAULT.age], dir0=[DESC],"
+                    + " dir1=[ASC])\n"
+                    + "    GraphLogicalSource(tableConfig=[{isAll=true, tables=[software,"
+                    + " person]}], alias=[DEFAULT], opt=[VERTEX])",
+                node.explain().trim());
+    }
+
+    @Test
+    public void g_V_order_by_select_test() {
+        RelNode node = eval("g.V().as('a').order().by(select('a').by('name'))");
+        Assert.assertEquals(
+                "GraphLogicalProject(a=[a], isAppend=[false])\n"
+                        + "  GraphLogicalSort(sort0=[a.name], dir0=[ASC])\n"
+                        + "    GraphLogicalSource(tableConfig=[{isAll=true, tables=[software,"
+                        + " person]}], alias=[a], opt=[VERTEX])",
+                node.explain().trim());
+    }
+
+    @Test
+    public void g_V_limit_test() {
+        RelNode node = eval("g.V().limit(10)");
+        Assert.assertEquals(
+                "GraphLogicalProject(DEFAULT=[DEFAULT], isAppend=[false])\n"
+                        + "  GraphLogicalSort(fetch=[10])\n"
+                        + "    GraphLogicalSource(tableConfig=[{isAll=true, tables=[software,"
+                        + " person]}], alias=[DEFAULT], opt=[VERTEX])",
+                node.explain().trim());
+    }
+
+    @Test
+    public void g_V_order_limit_test() {
+        RelNode node = eval("g.V().order().by('name', desc).by('age', asc).limit(10)");
+        Assert.assertEquals(
+                "GraphLogicalProject(DEFAULT=[DEFAULT], isAppend=[false])\n"
+                    + "  GraphLogicalSort(sort0=[DEFAULT.name], sort1=[DEFAULT.age], dir0=[DESC],"
+                    + " dir1=[ASC], fetch=[10])\n"
+                    + "    GraphLogicalSource(tableConfig=[{isAll=true, tables=[software,"
+                    + " person]}], alias=[DEFAULT], opt=[VERTEX])",
+                node.explain().trim());
+    }
+
+    @Test
+    public void g_V_group_test() {
+        RelNode node = eval("g.V().group()");
+        Assert.assertEquals(
+                "GraphLogicalAggregate(keys=[{variables=[DEFAULT], aliases=[keys]}],"
+                    + " values=[[{operands=[DEFAULT], aggFunction=COLLECT, alias='values',"
+                    + " distinct=false}]])\n"
+                    + "  GraphLogicalSource(tableConfig=[{isAll=true, tables=[software, person]}],"
+                    + " alias=[DEFAULT], opt=[VERTEX])",
+                node.explain().trim());
+    }
+
+    @Test
+    public void g_V_group_by_label_by_name_test() {
+        RelNode node = eval("g.V().group().by('~label').by('name')");
+        Assert.assertEquals(
+                "GraphLogicalAggregate(keys=[{variables=[DEFAULT.~label], aliases=[keys]}],"
+                    + " values=[[{operands=[DEFAULT.name], aggFunction=COLLECT, alias='values',"
+                    + " distinct=false}]])\n"
+                    + "  GraphLogicalSource(tableConfig=[{isAll=true, tables=[software, person]}],"
+                    + " alias=[DEFAULT], opt=[VERTEX])",
+                node.explain().trim());
+    }
+
+    @Test
+    public void g_V_group_by_select_a_name_by_count_test() {
+        RelNode node =
+                eval(
+                        "g.V().as('a').group().by(select('a').by('name').as('b')).by(select('a').count().as('c'))");
+        Assert.assertEquals(
+                "GraphLogicalAggregate(keys=[{variables=[a.name], aliases=[b]}],"
+                    + " values=[[{operands=[a], aggFunction=COUNT, alias='c', distinct=false}]])\n"
+                    + "  GraphLogicalSource(tableConfig=[{isAll=true, tables=[software, person]}],"
+                    + " alias=[a], opt=[VERTEX])",
+                node.explain().trim());
+    }
+
+    @Test
+    public void g_V_groupCount_by_name_test() {
+        RelNode node = eval("g.V().groupCount().by('name')");
+        Assert.assertEquals(
+                "GraphLogicalAggregate(keys=[{variables=[DEFAULT.name], aliases=[keys]}],"
+                    + " values=[[{operands=[DEFAULT], aggFunction=COUNT, alias='values',"
+                    + " distinct=false}]])\n"
+                    + "  GraphLogicalSource(tableConfig=[{isAll=true, tables=[software, person]}],"
+                    + " alias=[DEFAULT], opt=[VERTEX])",
+                node.explain().trim());
+    }
+
+    @Test
+    public void g_V_dedup_test() {
+        RelNode node = eval("g.V().dedup()");
+        Assert.assertEquals(
+                "GraphLogicalProject(DEFAULT=[DEFAULT], isAppend=[false])\n"
+                        + "  GraphLogicalDedupBy(dedupByKeys=[[DEFAULT]])\n"
+                        + "    GraphLogicalSource(tableConfig=[{isAll=true, tables=[software,"
+                        + " person]}], alias=[DEFAULT], opt=[VERTEX])",
+                node.explain().trim());
+    }
+
+    @Test
+    public void g_V_dedup_by_name_test() {
+        RelNode node = eval("g.V().dedup().by('name')");
+        Assert.assertEquals(
+                "GraphLogicalProject(DEFAULT=[DEFAULT], isAppend=[false])\n"
+                        + "  GraphLogicalDedupBy(dedupByKeys=[[DEFAULT.name]])\n"
+                        + "    GraphLogicalSource(tableConfig=[{isAll=true, tables=[software,"
+                        + " person]}], alias=[DEFAULT], opt=[VERTEX])",
+                node.explain().trim());
+    }
+
+    @Test
+    public void g_V_dedup_by_a_name_test() {
+        RelNode node = eval("g.V().as('a').dedup('a').by('name')");
+        Assert.assertEquals(
+                "GraphLogicalProject(a=[a], isAppend=[false])\n"
+                        + "  GraphLogicalDedupBy(dedupByKeys=[[a.name]])\n"
+                        + "    GraphLogicalSource(tableConfig=[{isAll=true, tables=[software,"
+                        + " person]}], alias=[a], opt=[VERTEX])",
+                node.explain().trim());
+    }
+
+    @Test
+    public void g_V_dedup_by_a_b_name_test() {
+        RelNode node = eval("g.V().as('a').out().as('b').dedup('a', 'b').by('name')");
+        Assert.assertEquals(
+                "GraphLogicalProject(b=[b], isAppend=[false])\n"
+                    + "  GraphLogicalDedupBy(dedupByKeys=[[a.name, b.name]])\n"
+                    + "    GraphLogicalGetV(tableConfig=[{isAll=true, tables=[software, person]}],"
+                    + " alias=[b], opt=[END])\n"
+                    + "      GraphLogicalExpand(tableConfig=[{isAll=true, tables=[created,"
+                    + " knows]}], alias=[DEFAULT], opt=[OUT])\n"
+                    + "        GraphLogicalSource(tableConfig=[{isAll=true, tables=[software,"
+                    + " person]}], alias=[a], opt=[VERTEX])",
+                node.explain().trim());
+    }
+}
diff --git a/interactive_engine/compiler/src/test/java/com/alibaba/graphscope/gremlin/integration/standard/calcite/IrGremlinTest.java b/interactive_engine/compiler/src/test/java/com/alibaba/graphscope/gremlin/integration/standard/calcite/IrGremlinTest.java
new file mode 100644
index 000000000000..75eb05e2ab9d
--- /dev/null
+++ b/interactive_engine/compiler/src/test/java/com/alibaba/graphscope/gremlin/integration/standard/calcite/IrGremlinTest.java
@@ -0,0 +1,28 @@
+/*
+ * Copyright 2020 Alibaba Group Holding Limited.
+ *
+ * Licensed 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 com.alibaba.graphscope.gremlin.integration.standard.calcite;
+
+import com.alibaba.graphscope.gremlin.integration.graph.RemoteTestGraphProvider;
+import com.alibaba.graphscope.gremlin.integration.graph.calcite.RemoteTestGraph;
+import com.alibaba.graphscope.gremlin.integration.suite.standard.IrGremlinTestSuite;
+
+import org.apache.tinkerpop.gremlin.GraphProviderClass;
+import org.junit.runner.RunWith;
+
+@RunWith(IrGremlinTestSuite.class)
+@GraphProviderClass(provider = RemoteTestGraphProvider.class, graph = RemoteTestGraph.class)
+public class IrGremlinTest {}