linhongyu510 commented on code in PR #2559:
URL: https://github.com/apache/age/pull/2559#discussion_r4371915567
##########
src/backend/parser/cypher_clause.c:
##########
@@ -4621,6 +4629,132 @@ static ParseNamespaceItem
*transform_RangeFunction(cypher_parsestate *cpstate,
return pnsi;
}
+static const char *find_static_edge_label(List *pattern,
+ const char *variable_name)
+{
+ ListCell *path_cell;
+ const char *label = NULL;
+
+ foreach (path_cell, pattern)
+ {
+ cypher_path *path = lfirst(path_cell);
+ ListCell *entity_cell;
+
+ foreach (entity_cell, path->path)
+ {
+ Node *entity = lfirst(entity_cell);
+ cypher_relationship *rel;
+
+ if (!is_ag_node(entity, cypher_relationship))
+ continue;
+
+ rel = (cypher_relationship *)entity;
+ if (rel->name == NULL ||
+ strcmp(rel->name, variable_name) != 0)
+ continue;
+
+ if (rel->varlen != NULL || rel->parsed_label == NULL)
+ return NULL;
+
+ if (label != NULL && strcmp(label, rel->parsed_label) != 0)
+ return NULL;
+
+ label = rel->parsed_label;
+ }
+ }
+
+ return label;
+}
+
+static bool is_redundant_edge_type_qual(List *pattern, Node *qual)
+{
+ cypher_comparison_aexpr *comparison;
+ FuncCall *function;
+ ColumnRef *column;
+ A_Const *constant;
+ String *operator_name;
+ String *function_name;
+ String *variable_name;
+ const char *static_label;
+
+ if (qual == NULL || !is_ag_node(qual, cypher_comparison_aexpr))
+ return false;
+
+ comparison = (cypher_comparison_aexpr *)qual;
+ if (comparison->kind != AEXPR_OP ||
+ list_length(comparison->name) != 1)
+ return false;
+
+ operator_name = linitial(comparison->name);
+ if (!IsA(operator_name, String) ||
+ strcmp(strVal(operator_name), "=") != 0 ||
+ !IsA(comparison->lexpr, FuncCall) ||
+ !IsA(comparison->rexpr, A_Const))
+ return false;
+
+ function = (FuncCall *)comparison->lexpr;
+ constant = (A_Const *)comparison->rexpr;
+ if (list_length(function->funcname) != 1 ||
+ list_length(function->args) != 1 ||
+ constant->isnull ||
+ constant->val.sval.type != T_String)
+ return false;
+
+ function_name = linitial(function->funcname);
+ if (!IsA(function_name, String) ||
+ pg_strcasecmp(strVal(function_name), "type") != 0 ||
+ !IsA(linitial(function->args), ColumnRef))
+ return false;
+
+ column = linitial(function->args);
+ if (list_length(column->fields) != 1 ||
+ !IsA(linitial(column->fields), String))
+ return false;
+
+ variable_name = linitial(column->fields);
+ static_label = find_static_edge_label(pattern, strVal(variable_name));
+
+ return static_label != NULL &&
+ strcmp(static_label, strVal(&constant->val)) == 0;
+}
+
+static Node *simplify_redundant_edge_type_qual(List *pattern, Node *where)
+{
+ BoolExpr *expression;
+ List *args = NIL;
+ ListCell *cell;
+
+ if (where == NULL)
+ return NULL;
+
+ if (is_redundant_edge_type_qual(pattern, where))
+ return NULL;
+
+ if (!IsA(where, BoolExpr))
+ return where;
+
+ expression = (BoolExpr *)where;
+ if (expression->boolop != AND_EXPR)
+ return where;
+
+ foreach (cell, expression->args)
+ {
+ Node *arg = lfirst(cell);
+
+ if (!is_redundant_edge_type_qual(pattern, arg))
Review Comment:
Done in 917b68ea: `simplify_redundant_edge_type_qual` now recurses into
nested `AND_EXPR` groups (stopping at `OR_EXPR`/`NOT_EXPR` boundaries to avoid
over-elision), so `r.v > 0 AND (type(r) = 'P' AND r.v < 4)` elides just like
the flat form. A `changed` flag rebuilds the outer conjunction when elision
happens inside a nested group.
Added regress cases for the nested-AND count, its EXPLAIN (type() gone,
siblings preserved), and a parenthesized OR-group guard confirming the
predicate is NOT elided there.
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: [email protected]
For queries about this service, please contact Infrastructure at:
[email protected]