Repository: alibaba/GraphScope (language: python)

Issue:
[BUG] Interactive fail to create procedure
Compiling fails when the procedure description includes special characters like commas, and others.


Discussion / hints:

Fix patch:
diff --git a/.github/workflows/interactive.yml b/.github/workflows/interactive.yml
index 18929079486f..34a3dadb8991 100644
--- a/.github/workflows/interactive.yml
+++ b/.github/workflows/interactive.yml
@@ -226,6 +226,23 @@ jobs:
           eval ${cmd} || exit 1
         done
 
+        # test graph_algo plugin building
+        sed -i 's/default_graph: movies/default_graph: graph_algo/g' ../tests/hqps/engine_config_test.yaml
+        cypher_files=$(ls ${GITHUB_WORKSPACE}/flex/interactive/examples/graph_algo/*.cypher)
+        for cypher_file in ${cypher_files};
+        do
+          cmd="./load_plan_and_gen.sh -e=hqps -i=${cypher_file} -w=/tmp/codegen/"
+          cmd=${cmd}" -o=/tmp/plugin --ir_conf=../tests/hqps/engine_config_test.yaml "
+          cmd=${cmd}" --graph_schema_path=${INTERACTIVE_WORKSPACE}/data/graph_algo/graph.yaml"
+          cmd=${cmd}" --procedure_name=$(basename ${cypher_file} .cypher)"
+          cmd=${cmd}" --procedure_desc=\"This is test procedure, change the description if needed.\""
+          echo $cmd
+          eval ${cmd} || exit 1
+        done
+
+        #set back
+        sed -i 's/default_graph: graph_algo/default_graph: ldbc/g' ../tests/hqps/engine_config_test.yaml
+
     - name: Test cypher&cpp procedure generation and loading
       env:
         TMP_INTERACTIVE_WORKSPACE: /tmp/temp_workspace
@@ -248,7 +265,8 @@ jobs:
         ./load_plan_and_gen.sh -e=hqps -i=../tests/interactive/plus_one.cc -w=/tmp/codegen \
           --ir_conf=${GITHUB_WORKSPACE}/flex/tests/hqps/engine_config_test.yaml -o=${PLUGIN_DIR} \
           --procedure_name=plus_one \
-          --graph_schema_path=../interactive/examples/modern_graph/graph.yaml
+          --graph_schema_path=../interactive/examples/modern_graph/graph.yaml \
+          --procedure_desc="This is test procedure, and the input is a number, and the output is the number plus one."
         
         ./load_plan_and_gen.sh -e=hqps -i=../interactive/sdk/java/src/test/resources/sample_app.cc -w=/tmp/codegen \
           --ir_conf=${GITHUB_WORKSPACE}/flex/tests/hqps/engine_config_test.yaml -o=${PLUGIN_DIR} \
@@ -265,7 +283,7 @@ jobs:
         # plus_one: (num: int64) -> (num: int64), CppEncoder
         # sample_app: (num: int64) -> (num: int64), kCypherJson
 
-        sed -i 's/default_graph: movies/default_graph: modern_graph/g' ${GITHUB_WORKSPACE}/flex/tests/hqps/engine_config_test.yaml
+        sed -i 's/default_graph: ldbc/default_graph: modern_graph/g' ${GITHUB_WORKSPACE}/flex/tests/hqps/engine_config_test.yaml
         sed -i 's/interactive_workspace/temp_workspace/g' ${GITHUB_WORKSPACE}/flex/tests/hqps/engine_config_test.yaml
         cd ${GITHUB_WORKSPACE}/flex/tests/interactive/
         bash test_plugin_loading.sh ${TMP_INTERACTIVE_WORKSPACE} modern_graph \
diff --git a/flex/bin/load_plan_and_gen.sh b/flex/bin/load_plan_and_gen.sh
index da698c09fe48..a497ab6a8e02 100755
--- a/flex/bin/load_plan_and_gen.sh
+++ b/flex/bin/load_plan_and_gen.sh
@@ -161,15 +161,18 @@ cypher_to_plan() {
     err "Compiler jar = ${COMPILER_JAR} not exists."
     exit 1
   fi
-  # add extra_key_value_config
-  extra_config="name:${procedure_name}"
-  extra_config="${extra_config},description:${procedure_description}"
-  extra_config="${extra_config},type:cypher"
+  # dump extra_key_value_config to a temp yaml, containing the extra config
+  extra_arg_config_file="${real_output_yaml}_extra_config.yaml"
+  cat <<EOM > ${extra_arg_config_file}
+name: ${procedure_name}
+description: "${procedure_description}"
+type: cypher
+EOM
 
   cmd="java -cp ${COMPILER_LIB_DIR}/*:${COMPILER_JAR}"
   cmd="${cmd} -Dgraph.schema=${graph_schema_path}"
   cmd="${cmd} -Djna.library.path=${IR_CORE_LIB_DIR}"
-  cmd="${cmd} com.alibaba.graphscope.common.ir.tools.GraphPlanner ${ir_compiler_properties} ${real_input_path} ${real_output_path} ${real_output_yaml} '${extra_config}'"
+  cmd="${cmd} com.alibaba.graphscope.common.ir.tools.GraphPlanner ${ir_compiler_properties} ${real_input_path} ${real_output_path} ${real_output_yaml} ${extra_arg_config_file}"
   info "running physical plan generation with ${cmd}"
   eval ${cmd}
 
diff --git a/flex/interactive/examples/graph_algo/0_count_paper.cypher b/flex/interactive/examples/graph_algo/0_count_paper.cypher
index 4289037a286c..ba049faa9334 100644
--- a/flex/interactive/examples/graph_algo/0_count_paper.cypher
+++ b/flex/interactive/examples/graph_algo/0_count_paper.cypher
@@ -1,4 +1,2 @@
-MATCH (p:Paper)-[:WorkOn]->(:Algorithm)-[:Belong]->(ca:Category)
-WITH distinct ca, count(p) as paperCount
-RETURN ca.category, paperCount
-ORDER BY paperCount desc;
\ No newline at end of file
+MATCH (p:Paper)
+RETURN COUNT(p) AS cnt;
\ No newline at end of file
diff --git a/flex/interactive/examples/graph_algo/1_challenge_strategy.cypher b/flex/interactive/examples/graph_algo/1_challenge_strategy.cypher
deleted file mode 100644
index 04a9a7cfc617..000000000000
--- a/flex/interactive/examples/graph_algo/1_challenge_strategy.cypher
+++ /dev/null
@@ -1,6 +0,0 @@
-MATCH (ca:Category)<-[:Belong]-(a:Algorithm),
-       (a)<-[:WorkOn]-(p:Paper)-[:Use]->(s:Strategy),
-       (s)-[:ApplyOn]->(ch:Challenge)
-WITH ca, ch, count(p) AS num
-RETURN ca.category AS category, ch.challenge AS challenge, num
-ORDER BY num DESC LIMIT 5;
\ No newline at end of file
diff --git a/flex/interactive/examples/graph_algo/1_count_topics.cypher b/flex/interactive/examples/graph_algo/1_count_topics.cypher
new file mode 100644
index 000000000000..8b40c8247eee
--- /dev/null
+++ b/flex/interactive/examples/graph_algo/1_count_topics.cypher
@@ -0,0 +1,2 @@
+MATCH (t: Topic)
+RETURN t.topic AS topic;
\ No newline at end of file
diff --git a/flex/interactive/examples/graph_algo/2_get_edge_type.cypher b/flex/interactive/examples/graph_algo/2_get_edge_type.cypher
deleted file mode 100644
index f0126e21c2b2..000000000000
--- a/flex/interactive/examples/graph_algo/2_get_edge_type.cypher
+++ /dev/null
@@ -1,1 +0,0 @@
-MATCH(c: CCFField)<-[e]-(p:Paper) return type(e) As edgeType ORDER BY edgeType ASC LIMIT 10;
\ No newline at end of file
diff --git a/flex/interactive/examples/graph_algo/2_get_topic_papers_hist.cypher b/flex/interactive/examples/graph_algo/2_get_topic_papers_hist.cypher
new file mode 100644
index 000000000000..bd5f2abd7dae
--- /dev/null
+++ b/flex/interactive/examples/graph_algo/2_get_topic_papers_hist.cypher
@@ -0,0 +1,4 @@
+MATCH (p:Paper)-[:WorkOn]->(:Task)-[:Belong]->(t:Topic)
+WITH DISTINCT t, COUNT(p) AS paperCount
+RETURN t.topic AS topic, paperCount
+ORDER BY paperCount DESC;
diff --git a/flex/interactive/examples/graph_algo/3_get_challenges.cypher b/flex/interactive/examples/graph_algo/3_get_challenges.cypher
new file mode 100644
index 000000000000..e1b6934d0ef3
--- /dev/null
+++ b/flex/interactive/examples/graph_algo/3_get_challenges.cypher
@@ -0,0 +1,2 @@
+MATCH (c: Challenge)
+RETURN c.challenge AS challenge;
\ No newline at end of file
diff --git a/flex/interactive/examples/graph_algo/3_get_distinct_edge_type.cypher b/flex/interactive/examples/graph_algo/3_get_distinct_edge_type.cypher
deleted file mode 100644
index 44ffcb3da538..000000000000
--- a/flex/interactive/examples/graph_algo/3_get_distinct_edge_type.cypher
+++ /dev/null
@@ -1,1 +0,0 @@
-MATCH(v)-[e]-() return distinct type(e) AS edgeType order by edgeType ASC;
\ No newline at end of file
diff --git a/flex/interactive/examples/graph_algo/4_filter_edge.cypher b/flex/interactive/examples/graph_algo/4_filter_edge.cypher
deleted file mode 100644
index bde3745b429c..000000000000
--- a/flex/interactive/examples/graph_algo/4_filter_edge.cypher
+++ /dev/null
@@ -1,1 +0,0 @@
-MATCH(c: CCFField)<-[e]-(p:Paper) where type(e) = 6 return type(e) As edgeType ORDER BY edgeType ASC LIMIT 10;
\ No newline at end of file
diff --git a/flex/interactive/examples/graph_algo/4_get_solutions_of_challenges.cypher b/flex/interactive/examples/graph_algo/4_get_solutions_of_challenges.cypher
new file mode 100644
index 000000000000..42f53ef78751
--- /dev/null
+++ b/flex/interactive/examples/graph_algo/4_get_solutions_of_challenges.cypher
@@ -0,0 +1,3 @@
+MATCH (s: Solution)-[:ApplyOn]->(c: Challenge)
+WHERE c.challenge = $challenge
+RETURN c.challenge AS challenge, s.solution AS solution;
diff --git a/flex/interactive/examples/graph_algo/5.cypher b/flex/interactive/examples/graph_algo/5.cypher
deleted file mode 100644
index 7cd3be3b552e..000000000000
--- a/flex/interactive/examples/graph_algo/5.cypher
+++ /dev/null
@@ -1,4 +0,0 @@
-MATCH (p:Paper)-[:Resolve]->(ch:Challenge),
-              (p1:Paper)-[:Resolve]->(ch),
-               (p)-[c:Citation]->(p1)
-RETURN COUNT(distinct c);
\ No newline at end of file
diff --git a/flex/interactive/examples/graph_algo/5_get_challenge_paper_hist_of_topic.cypher b/flex/interactive/examples/graph_algo/5_get_challenge_paper_hist_of_topic.cypher
new file mode 100644
index 000000000000..0aeb847365cc
--- /dev/null
+++ b/flex/interactive/examples/graph_algo/5_get_challenge_paper_hist_of_topic.cypher
@@ -0,0 +1,7 @@
+MATCH (t:Topic)<-[:Belong]-(ta:Task),
+       (ta)<-[:WorkOn]-(p:Paper)-[:Use]->(s:Solution),
+       (s)-[:ApplyOn]->(ch:Challenge)
+WHERE t.topic = $topic
+WITH t, ch, count(p) AS num
+RETURN t.topic AS topic, ch.challenge AS challenge, num
+ORDER BY num DESC;
diff --git a/flex/interactive/examples/graph_algo/6.cypher b/flex/interactive/examples/graph_algo/6.cypher
deleted file mode 100644
index c1e472f179cf..000000000000
--- a/flex/interactive/examples/graph_algo/6.cypher
+++ /dev/null
@@ -1,6 +0,0 @@
-MATCH (p:Paper)-[:Resolve]->(ch:Challenge),
-              (p1:Paper)-[:Resolve]->(ch),
-               (p)-[c:Citation]->(p1)
-WITH DISTINCT p, c, p1
-WITH p.id As paperId, p1.id As citationId
-RETURN paperId, citationId ORDER BY paperId ASC, citationId ASC;
\ No newline at end of file
diff --git a/flex/interactive/examples/graph_algo/7.cypher b/flex/interactive/examples/graph_algo/7.cypher
deleted file mode 100644
index 65453aa90967..000000000000
--- a/flex/interactive/examples/graph_algo/7.cypher
+++ /dev/null
@@ -1,5 +0,0 @@
-MATCH (p:Paper)-[:HasField]->(c:CCFField),
-              (p1:Paper)-[:HasField]->(c),
-               (p)-[b:Citation]-(p1)
-WITH distinct p, p1
-RETURN p.CCFField, p1.CCFField;
\ No newline at end of file
diff --git a/flex/interactive/examples/graph_algo/8.cypher b/flex/interactive/examples/graph_algo/8.cypher
deleted file mode 100644
index 4478008fb744..000000000000
--- a/flex/interactive/examples/graph_algo/8.cypher
+++ /dev/null
@@ -1,5 +0,0 @@
-MATCH (p:Paper)-[:HasField]->(f1:CCFField),
-              (p1:Paper)-[:HasField]->(f2:CCFField),
-               (p)-[c:Citation]->(p1)
-WHERE f1.id = 0 AND f2.id <> f1.id
-RETURN distinct p, p1;
\ No newline at end of file
diff --git a/flex/interactive/examples/graph_algo/9.cypher b/flex/interactive/examples/graph_algo/9.cypher
deleted file mode 100644
index 7a490274710e..000000000000
--- a/flex/interactive/examples/graph_algo/9.cypher
+++ /dev/null
@@ -1,4 +0,0 @@
-MATCH (p:Paper)-[:Resolve]->(ch:Challenge),
-              (p1:Paper)-[:Resolve]->(ch),
-               (p)-[c:Citation]-(p1)
-RETURN COUNT(distinct p, p1);
\ No newline at end of file
diff --git a/flex/interactive/examples/graph_algo/graph.yaml b/flex/interactive/examples/graph_algo/graph.yaml
index b6548038aa1f..f93cf3a2f9f7 100644
--- a/flex/interactive/examples/graph_algo/graph.yaml
+++ b/flex/interactive/examples/graph_algo/graph.yaml
@@ -44,7 +44,7 @@ schema:
         - property_name: id
           property_type:
             primitive_type: DT_SIGNED_INT64
-        - property_name: category
+        - property_name: topic
           property_type:
             string:
               long_text:
diff --git a/flex/interactive/examples/graph_algo/topic_challenge_hist.cypher b/flex/interactive/examples/graph_algo/topic_challenge_hist.cypher
index 3a4d33d378b4..330728455f34 100644
--- a/flex/interactive/examples/graph_algo/topic_challenge_hist.cypher
+++ b/flex/interactive/examples/graph_algo/topic_challenge_hist.cypher
@@ -1,5 +1,5 @@
 MATCH (t: Topic)<-[:Belong]-(a:Task),
     (a)<-[:WorkOn]-(p:Paper)-[:Use]->(s:Solution),
     (s)-[:ApplyOn]->(ch:Challenge)
-WHERE t.category = $topic_name
-RETURN t.category, ch.challenge, COUNT(p);
\ No newline at end of file
+WHERE t.topic = $topic_name
+RETURN t.topic, ch.challenge, COUNT(p);
\ No newline at end of file
diff --git a/flex/interactive/examples/graph_algo/topic_paper_hist.cypher b/flex/interactive/examples/graph_algo/topic_paper_hist.cypher
index 552d946a20d8..a66187426548 100644
--- a/flex/interactive/examples/graph_algo/topic_paper_hist.cypher
+++ b/flex/interactive/examples/graph_algo/topic_paper_hist.cypher
@@ -1,2 +1,2 @@
 MATCH (p:Paper)-[:WorkOn]->(a:Task),(a)-[:Belong]->(t: Topic)
-RETURN t.category,COUNT(p);
\ No newline at end of file
+RETURN t.topic,COUNT(p);
\ No newline at end of file
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 fe74f13d63c1..8a1d9ab3bc29 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
@@ -38,7 +38,6 @@
 import com.alibaba.graphscope.common.ir.type.GraphTypeFactoryImpl;
 import com.alibaba.graphscope.cypher.antlr4.parser.CypherAntlr4Parser;
 import com.alibaba.graphscope.cypher.antlr4.visitor.LogicalPlanVisitor;
-import com.google.common.base.Preconditions;
 import com.google.common.collect.Maps;
 
 import org.apache.calcite.plan.GraphOptCluster;
@@ -50,6 +49,7 @@
 import org.checkerframework.checker.nullness.qual.Nullable;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
+import org.yaml.snakeyaml.Yaml;
 
 import java.io.File;
 import java.io.FileOutputStream;
@@ -179,16 +179,19 @@ public PhysicalPlan getPhysicalPlan() {
         }
     }
 
-    private static Configs createExtraConfigs(@Nullable String keyValues) {
+    private static Configs createExtraConfigs(@Nullable String extraYamlFile) throws Exception {
         Map<String, String> keyValueMap = Maps.newHashMap();
-        if (!StringUtils.isEmpty(keyValues)) {
-            String[] pairs = keyValues.split(",");
-            for (String pair : pairs) {
-                String[] kv = pair.trim().split(":");
-                Preconditions.checkArgument(
-                        kv.length == 2, "invalid key value pair: " + pair + " in " + keyValues);
-                keyValueMap.put(kv[0], kv[1]);
-            }
+        if (!StringUtils.isEmpty(extraYamlFile)) {
+            String extraYaml =
+                    FileUtils.readFileToString(new File(extraYamlFile), StandardCharsets.UTF_8);
+            Yaml yaml = new Yaml();
+            Map<String, Object> yamlMap = yaml.load(extraYaml);
+            yamlMap.forEach(
+                    (k, v) -> {
+                        if (v != null) {
+                            keyValueMap.put(k, v.toString());
+                        }
+                    });
         }
         return new Configs(keyValueMap);
     }
@@ -214,7 +217,7 @@ public static void main(String[] args) throws Exception {
             throw new IllegalArgumentException(
                     "usage: GraphPlanner '<path_to_config_file>' '<path_to_query_file>' "
                             + " '<path_to_physical_output_file>' '<path_to_procedure_file>'"
-                            + " 'optional <extra_key_value_config_pairs>'");
+                            + " 'optional <extra_key_value_config_file>'");
         }
         Configs configs = Configs.Factory.create(args[0]);
         GraphRelOptimizer optimizer = new GraphRelOptimizer(configs);
diff --git a/interactive_engine/compiler/src/main/java/com/alibaba/graphscope/cypher/integration/suite/graphAlgo/GraphAlgoQueries.java b/interactive_engine/compiler/src/main/java/com/alibaba/graphscope/cypher/integration/suite/graphAlgo/GraphAlgoQueries.java
index f6683b4673d6..79e0c94024c4 100644
--- a/interactive_engine/compiler/src/main/java/com/alibaba/graphscope/cypher/integration/suite/graphAlgo/GraphAlgoQueries.java
+++ b/interactive_engine/compiler/src/main/java/com/alibaba/graphscope/cypher/integration/suite/graphAlgo/GraphAlgoQueries.java
@@ -25,41 +25,40 @@ public class GraphAlgoQueries {
 
     public static QueryContext get_graph_algo_test1() {
         String query =
-                "MATCH (p:Paper)-[:WorkOn]->(:Task)-[:Belong]->(ca:Topic)\n"
-                        + "WITH distinct ca, count(p) as paperCount\n"
-                        + "RETURN ca.category, paperCount\n "
+                "MATCH (p:Paper)-[:WorkOn]->(:Task)-[:Belong]->(topic:Topic)\n"
+                        + "WITH distinct topic, count(p) as paperCount\n"
+                        + "RETURN topic.topic, paperCount\n "
                         + "ORDER BY paperCount desc;";
         List<String> expected =
                 Arrays.asList(
-                        "Record<{category: \"Pattern Matching\", paperCount: 30}>",
-                        "Record<{category: \"Traversal\", paperCount:" + " 29}>",
-                        "Record<{category: \"Centrality\", paperCount: 18}>",
-                        "Record<{category: \"Covering\", paperCount: 14}>",
-                        "Record<{category: \"Community Detection\", paperCount: 13}>",
-                        "Record<{category: \"Cohesive Subgraph\", paperCount: 12}>",
-                        "Record<{category: \"Similarity\", paperCount: 7}>");
+                        "Record<{topic: \"Pattern Matching\", paperCount: 30}>",
+                        "Record<{topic: \"Traversal\", paperCount:" + " 29}>",
+                        "Record<{topic: \"Centrality\", paperCount: 18}>",
+                        "Record<{topic: \"Covering\", paperCount: 14}>",
+                        "Record<{topic: \"Community Detection\", paperCount: 13}>",
+                        "Record<{topic: \"Cohesive Subgraph\", paperCount: 12}>",
+                        "Record<{topic: \"Similarity\", paperCount: 7}>");
         return new QueryContext(query, expected);
     }
 
     public static QueryContext get_graph_algo_test2() {
         String query =
-                "MATCH (ca:Topic)<-[:Belong]-(a:Task),\n"
+                "MATCH (t:Topic)<-[:Belong]-(a:Task),\n"
                         + "(a)<-[:WorkOn]-(p:Paper)-[:Use]->(s:Solution),\n"
                         + "(s)-[:ApplyOn]->(ch:Challenge)\n"
-                        + "WITH ca, ch, count(p) AS num \n"
-                        + "RETURN ca.category AS category, ch.challenge AS challenge, num\n"
+                        + "WITH t, ch, count(p) AS num \n"
+                        + "RETURN t.topic AS topic, ch.challenge AS challenge, num\n"
                         + "ORDER BY num DESC LIMIT 5;";
         List<String> expected =
                 Arrays.asList(
-                        "Record<{category: \"Pattern Matching\", challenge:"
+                        "Record<{topic: \"Pattern Matching\", challenge:"
                                 + " \"Communication Overhead\", num: 22}>",
-                        "Record<{category: \"Pattern Matching\", challenge:"
+                        "Record<{topic: \"Pattern Matching\", challenge:"
                                 + " \"Load Balance\", num: 16}>",
-                        "Record<{category: \"Traversal\", challenge:"
+                        "Record<{topic: \"Traversal\", challenge:"
                                 + " \"Communication Overhead\", num: 13}>",
-                        "Record<{category: \"Traversal\", challenge: \"Parallelism"
-                                + "\", num: 12}>",
-                        "Record<{category: \"Centrality\", challenge: \"Parallelism\", num:"
+                        "Record<{topic: \"Traversal\", challenge: \"Parallelism" + "\", num: 12}>",
+                        "Record<{topic: \"Centrality\", challenge: \"Parallelism\", num:"
                                 + " 11}>");
         return new QueryContext(query, expected);
     }
@@ -180,16 +179,16 @@ public static QueryContext get_graph_algo_test11() {
     public static QueryContext get_graph_algo_test12() {
         String query =
                 "MATCH (p:Paper)-[:WorkOn]->(a:Task),(a)-[:Belong]->(t: Topic)\n"
-                        + " RETURN t.category,COUNT(p);";
+                        + " RETURN t.topic,COUNT(p);";
         List expected =
                 Arrays.asList(
-                        "Record<{category: \"Centrality\", $f1: 18}>",
-                        "Record<{category: \"Community Detection\", $f1: 13}>",
-                        "Record<{category: \"Similarity\", $f1: 7}>",
-                        "Record<{category: \"Cohesive Subgraph\", $f1: 12}>",
-                        "Record<{category: \"Pattern Matching\", $f1: 30}>",
-                        "Record<{category: \"Traversal\", $f1: 29}>",
-                        "Record<{category: \"Covering\", $f1: 14}>");
+                        "Record<{topic: \"Centrality\", $f1: 18}>",
+                        "Record<{topic: \"Community Detection\", $f1: 13}>",
+                        "Record<{topic: \"Similarity\", $f1: 7}>",
+                        "Record<{topic: \"Cohesive Subgraph\", $f1: 12}>",
+                        "Record<{topic: \"Pattern Matching\", $f1: 30}>",
+                        "Record<{topic: \"Traversal\", $f1: 29}>",
+                        "Record<{topic: \"Covering\", $f1: 14}>");
         return new QueryContext(query, expected);
     }
 
@@ -198,47 +197,47 @@ public static QueryContext get_graph_algo_test13() {
                 "MATCH (t: Topic)<-[:Belong]-(a:Task),\n"
                         + " (a)<-[:WorkOn]-(p:Paper)-[:Use]->(s:Solution),\n"
                         + " (s)-[:ApplyOn]->(ch:Challenge)\n"
-                        + " RETURN t.category, ch.challenge, COUNT(p);";
+                        + " RETURN t.topic, ch.challenge, COUNT(p);";
         List expected =
                 Arrays.asList(
-                        "Record<{category: \"Centrality\", challenge: \"Parallelism\", $f2: 11}>",
-                        "Record<{category: \"Centrality\", challenge: \"Bandwidth\", $f2: 5}>",
-                        "Record<{category: \"Centrality\", challenge: \"Communication Overhead\","
+                        "Record<{topic: \"Centrality\", challenge: \"Parallelism\", $f2: 11}>",
+                        "Record<{topic: \"Centrality\", challenge: \"Bandwidth\", $f2: 5}>",
+                        "Record<{topic: \"Centrality\", challenge: \"Communication Overhead\","
                                 + " $f2: 9}>",
-                        "Record<{category: \"Centrality\", challenge: \"Load Balance\", $f2: 4}>",
-                        "Record<{category: \"Community Detection\", challenge: \"Communication"
+                        "Record<{topic: \"Centrality\", challenge: \"Load Balance\", $f2: 4}>",
+                        "Record<{topic: \"Community Detection\", challenge: \"Communication"
                                 + " Overhead\", $f2: 9}>",
-                        "Record<{category: \"Community Detection\", challenge: \"Load Balance\","
+                        "Record<{topic: \"Community Detection\", challenge: \"Load Balance\","
                                 + " $f2: 4}>",
-                        "Record<{category: \"Community Detection\", challenge: \"Parallelism\","
+                        "Record<{topic: \"Community Detection\", challenge: \"Parallelism\","
                                 + " $f2: 4}>",
-                        "Record<{category: \"Similarity\", challenge: \"Communication Overhead\","
+                        "Record<{topic: \"Similarity\", challenge: \"Communication Overhead\","
                                 + " $f2: 7}>",
-                        "Record<{category: \"Similarity\", challenge: \"Parallelism\", $f2: 2}>",
-                        "Record<{category: \"Similarity\", challenge: \"Load Balance\", $f2: 1}>",
-                        "Record<{category: \"Cohesive Subgraph\", challenge: \"Parallelism\", $f2:"
+                        "Record<{topic: \"Similarity\", challenge: \"Parallelism\", $f2: 2}>",
+                        "Record<{topic: \"Similarity\", challenge: \"Load Balance\", $f2: 1}>",
+                        "Record<{topic: \"Cohesive Subgraph\", challenge: \"Parallelism\", $f2:"
                                 + " 7}>",
-                        "Record<{category: \"Cohesive Subgraph\", challenge: \"Communication"
+                        "Record<{topic: \"Cohesive Subgraph\", challenge: \"Communication"
                                 + " Overhead\", $f2: 9}>",
-                        "Record<{category: \"Cohesive Subgraph\", challenge: \"Load Balance\", $f2:"
+                        "Record<{topic: \"Cohesive Subgraph\", challenge: \"Load Balance\", $f2:"
                                 + " 4}>",
-                        "Record<{category: \"Pattern Matching\", challenge: \"Load Balance\", $f2:"
+                        "Record<{topic: \"Pattern Matching\", challenge: \"Load Balance\", $f2:"
                                 + " 16}>",
-                        "Record<{category: \"Pattern Matching\", challenge: \"Communication"
+                        "Record<{topic: \"Pattern Matching\", challenge: \"Communication"
                                 + " Overhead\", $f2: 22}>",
-                        "Record<{category: \"Pattern Matching\", challenge: \"Parallelism\", $f2:"
+                        "Record<{topic: \"Pattern Matching\", challenge: \"Parallelism\", $f2:"
                                 + " 1}>",
-                        "Record<{category: \"Pattern Matching\", challenge: \"Bandwidth\", $f2:"
+                        "Record<{topic: \"Pattern Matching\", challenge: \"Bandwidth\", $f2:"
                                 + " 6}>",
-                        "Record<{category: \"Traversal\", challenge: \"Parallelism\", $f2: 12}>",
-                        "Record<{category: \"Traversal\", challenge: \"Communication Overhead\","
+                        "Record<{topic: \"Traversal\", challenge: \"Parallelism\", $f2: 12}>",
+                        "Record<{topic: \"Traversal\", challenge: \"Communication Overhead\","
                                 + " $f2: 13}>",
-                        "Record<{category: \"Traversal\", challenge: \"Load Balance\", $f2: 8}>",
-                        "Record<{category: \"Traversal\", challenge: \"Bandwidth\", $f2: 2}>",
-                        "Record<{category: \"Covering\", challenge: \"Parallelism\", $f2: 9}>",
-                        "Record<{category: \"Covering\", challenge: \"Communication Overhead\","
+                        "Record<{topic: \"Traversal\", challenge: \"Load Balance\", $f2: 8}>",
+                        "Record<{topic: \"Traversal\", challenge: \"Bandwidth\", $f2: 2}>",
+                        "Record<{topic: \"Covering\", challenge: \"Parallelism\", $f2: 9}>",
+                        "Record<{topic: \"Covering\", challenge: \"Communication Overhead\","
                                 + " $f2: 4}>",
-                        "Record<{category: \"Covering\", challenge: \"Load Balance\", $f2: 1}>");
+                        "Record<{topic: \"Covering\", challenge: \"Load Balance\", $f2: 1}>");
         return new QueryContext(query, expected);
     }
 }
diff --git a/interactive_engine/compiler/src/main/java/org/apache/calcite/sql/type/GraphFamilyOperandTypeChecker.java b/interactive_engine/compiler/src/main/java/org/apache/calcite/sql/type/GraphFamilyOperandTypeChecker.java
index 1eb5e5f54fb4..f9cf010f9e65 100644
--- a/interactive_engine/compiler/src/main/java/org/apache/calcite/sql/type/GraphFamilyOperandTypeChecker.java
+++ b/interactive_engine/compiler/src/main/java/org/apache/calcite/sql/type/GraphFamilyOperandTypeChecker.java
@@ -53,7 +53,8 @@ protected GraphFamilyOperandTypeChecker(
     public boolean checkOperandTypes(SqlCallBinding callBinding, boolean throwOnFailure) {
         if (expectedFamilies.size() != callBinding.getOperandCount()) {
             Litmus.THROW.fail(
-                    "wrong operand count {} for {}",
+                    "Expect {} operands, but got {} operands, expected operands of types {}",
+                    expectedFamilies.size(),
                     callBinding.getOperandCount(),
                     expectedFamilies);
         }


Test patch:
diff --git a/flex/tests/interactive/graph_algo_test.yaml b/flex/tests/interactive/graph_algo_test.yaml
index 9b358a927c56..e1f0737d6fe2 100644
--- a/flex/tests/interactive/graph_algo_test.yaml
+++ b/flex/tests/interactive/graph_algo_test.yaml
@@ -58,7 +58,7 @@ schema:
           property_type:
             primitive_type: DT_SIGNED_INT64
         - property_id: 1
-          property_name: category
+          property_name: topic
           property_type:
             string:
               long_text: