Repository: alibaba/GraphScope (language: python)

Issue:
[BUG] Gremlin traversal from GlobalId fails 
The following query fails to find vertex with global id larger than i32
```gremlin
g.V(0, 72057594037927937) 
```

But the following query is ok
```gremlin
g.V(72057594037927937)
g.V(72057594037927937, 0)
```

And the log of compiler:

for g.V(0, 72057594037927937) 
```bash
# 
  "opr": {
        "opr": {
          "Scan": {
            "scan_opt": 0,
            "alias": null,
            "params": {
              "tables": [
                {
                  "item": {
                    "Id": 0
                  }
                },
                {
                  "item": {
                    "Id": 1
                  }
                }
              ],
              "columns": [],
              "is_all_columns": false,
              "limit": null,
              "predicate": null,
              "sample_ratio": 1.0,
              "extra": {}
            },
            "idx_predicate": {
              "or_predicates": [
                {
                  "predicates": [
                    {
                      "key": {
                        "item": {
                          "Id": {}
                        }
                      },
                      "cmp": 6,
                      "value": {
                        "Const": {
                          "item": {
                            "I32Array": {
                              "item": [
                                0,
                                0
                              ]
                            }
                          }
                        }
                      }
                    }
                  ]
                }
              ]
            },
```

for g.V(72057594037927937, 0) 
```bash
  "opr": {
        "opr": {
          "Scan": {
            "scan_opt": 0,
            "alias": null,
            "params": {
              "tables": [
                {
                  "item": {
                    "Id": 0
                  }
                },
                {
                  "item": {
                    "Id": 1
                  }
                }
              ],
              "columns": [],
              "is_all_columns": false,
              "limit": null,
              "predicate": null,
              "sample_ratio": 1.0,
              "extra": {}
            },
            "idx_predicate": {
              "or_predicates": [
                {
                  "predicates": [
                    {
                      "key": {
                        "item": {
                          "Id": {}
                        }
                      },
                      "cmp": 6,
                      "value": {
                        "Const": {
                          "item": {
                            "I64Array": {
                              "item": [
                                72057594037927937,
                                0
                              ]
                            }
                          }
                        }
                      }
                    }
                  ]
                }
              ]
            },
```


Discussion / hints:
Gremlin test `g_VX1X_out_hasXid_2_3X`.


Fix patch:
diff --git a/interactive_engine/compiler/src/main/java/com/alibaba/graphscope/common/ir/tools/GraphRexBuilder.java b/interactive_engine/compiler/src/main/java/com/alibaba/graphscope/common/ir/tools/GraphRexBuilder.java
index 593ccb25b675..844196b3ad7d 100644
--- a/interactive_engine/compiler/src/main/java/com/alibaba/graphscope/common/ir/tools/GraphRexBuilder.java
+++ b/interactive_engine/compiler/src/main/java/com/alibaba/graphscope/common/ir/tools/GraphRexBuilder.java
@@ -21,6 +21,17 @@
 import org.apache.calcite.rel.type.RelDataType;
 import org.apache.calcite.rel.type.RelDataTypeFactory;
 import org.apache.calcite.rex.RexBuilder;
+import org.apache.calcite.rex.RexNode;
+import org.apache.calcite.rex.RexUnknownAs;
+import org.apache.calcite.rex.RexUtil;
+import org.apache.calcite.sql.fun.SqlStdOperatorTable;
+import org.apache.calcite.util.Sarg;
+import org.apache.calcite.util.Util;
+
+import java.lang.reflect.Method;
+import java.util.List;
+import java.util.Objects;
+import java.util.stream.Collectors;
 
 public class GraphRexBuilder extends RexBuilder {
     public GraphRexBuilder(RelDataTypeFactory typeFactory) {
@@ -35,4 +46,53 @@ public RexGraphDynamicParam makeGraphDynamicParam(
             RelDataType dataType, String name, int index) {
         return new RexGraphDynamicParam(dataType, name, index);
     }
+
+    /**
+     * fix bug in calcite-1.32.0, type of {@code Sarg} should be inferred as the least restrictive type of all literals in ranges
+     * instead of the first literal, which is the original implementation.
+     * @param arg
+     * @param ranges
+     * @return
+     */
+    @Override
+    public RexNode makeIn(RexNode arg, List<? extends RexNode> ranges) {
+        Method m1 = getMethod("areAssignable", RexNode.class, List.class);
+        if ((boolean) invoke(m1, arg, ranges)) {
+            Method m2 = getMethod("toSarg", Class.class, List.class, RexUnknownAs.class);
+            final Sarg sarg = (Sarg) invoke(m2, Comparable.class, ranges, RexUnknownAs.UNKNOWN);
+            if (sarg != null) {
+                final List<RelDataType> types =
+                        ranges.stream().map(RexNode::getType).collect(Collectors.toList());
+                RelDataType sargType =
+                        Objects.requireNonNull(
+                                typeFactory.leastRestrictive(types),
+                                () -> "Can't find leastRestrictive type for SARG among " + types);
+                return makeCall(
+                        SqlStdOperatorTable.SEARCH, arg, makeSearchArgumentLiteral(sarg, sargType));
+            }
+        }
+        return RexUtil.composeDisjunction(
+                this,
+                ranges.stream()
+                        .map(r -> makeCall(SqlStdOperatorTable.EQUALS, arg, r))
+                        .collect(Util.toImmutableList()));
+    }
+
+    private Method getMethod(String methodName, Class<?>... parameterTypes) {
+        try {
+            Method method = RexBuilder.class.getDeclaredMethod(methodName, parameterTypes);
+            method.setAccessible(true);
+            return method;
+        } catch (Exception e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+    private Object invoke(Method method, Object... args) {
+        try {
+            return method.invoke(null, args);
+        } catch (Exception e) {
+            throw new RuntimeException(e);
+        }
+    }
 }


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
index 6335f89b08d5..46639514e044 100644
--- 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
@@ -17,12 +17,22 @@
 package com.alibaba.graphscope.gremlin.antlr4x;
 
 import com.alibaba.graphscope.common.ir.Utils;
+import com.alibaba.graphscope.common.ir.runtime.proto.RexToProtoConverter;
 import com.alibaba.graphscope.common.ir.tools.GraphBuilder;
+import com.alibaba.graphscope.common.ir.tools.config.GraphOpt;
+import com.alibaba.graphscope.common.ir.tools.config.SourceConfig;
+import com.alibaba.graphscope.common.ir.type.GraphProperty;
+import com.alibaba.graphscope.common.utils.FileUtils;
+import com.alibaba.graphscope.gaia.proto.OuterExpression;
 import com.alibaba.graphscope.gremlin.antlr4x.parser.GremlinAntlr4Parser;
 import com.alibaba.graphscope.gremlin.antlr4x.visitor.GraphBuilderVisitor;
+import com.google.common.collect.ImmutableList;
+import com.google.protobuf.util.JsonFormat;
 
 import org.antlr.v4.runtime.tree.ParseTree;
 import org.apache.calcite.rel.RelNode;
+import org.apache.calcite.rex.RexBuilder;
+import org.apache.calcite.rex.RexNode;
 import org.junit.Assert;
 import org.junit.Test;
 
@@ -644,4 +654,21 @@ public void g_V_dedup_by_a_b_name_test() {
                     + " person]}], alias=[a], opt=[VERTEX])",
                 node.explain().trim());
     }
+
+    // ~id within [0, 72057594037927937]
+    @Test
+    public void id_in_list_expr_test() throws Exception {
+        GraphBuilder builder = Utils.mockGraphBuilder();
+        RexBuilder rexBuilder = Utils.rexBuilder;
+        RexNode expr =
+                rexBuilder.makeIn(
+                        builder.source(new SourceConfig(GraphOpt.Source.VERTEX))
+                                .variable(null, GraphProperty.ID_KEY),
+                        ImmutableList.of(builder.literal(0), builder.literal(72057594037927937L)));
+        OuterExpression.Expression exprProto =
+                expr.accept(new RexToProtoConverter(true, false, rexBuilder));
+        Assert.assertEquals(
+                FileUtils.readJsonFromResource("proto/id_in_list_expr.json"),
+                JsonFormat.printer().print(exprProto));
+    }
 }
diff --git a/interactive_engine/compiler/src/test/resources/proto/id_in_list_expr.json b/interactive_engine/compiler/src/test/resources/proto/id_in_list_expr.json
new file mode 100644
index 000000000000..4b954a82154d
--- /dev/null
+++ b/interactive_engine/compiler/src/test/resources/proto/id_in_list_expr.json
@@ -0,0 +1,30 @@
+{
+  "operators": [{
+    "var": {
+      "property": {
+        "id": {
+        }
+      },
+      "nodeType": {
+        "dataType": "INT64"
+      }
+    },
+    "nodeType": {
+      "dataType": "INT64"
+    }
+  }, {
+    "logical": "WITHIN",
+    "nodeType": {
+      "dataType": "BOOLEAN"
+    }
+  }, {
+    "const": {
+      "i64Array": {
+        "item": ["0", "72057594037927937"]
+      }
+    },
+    "nodeType": {
+      "dataType": "INT64"
+    }
+  }]
+}