jrgemignani commented on code in PR #1751:
URL: https://github.com/apache/age/pull/1751#discussion_r1569686861


##########
src/backend/parser/cypher_analyze.c:
##########
@@ -653,6 +660,381 @@ static int get_query_location(const int location, const 
char *source_str)
     return strchr(p + 1, '$') - source_str + 1;
 }
 
+/*
+ * This is a specialized expression tree walker for finding exprs of a 
specified
+ * type. Create a function that checks for the type you want, and this function
+ * will iterate through the tree.
+ */
+
+bool expr_contains_node(cypher_expression_condition is_expr, Node *expr)
+{
+    if (!expr)
+    {
+        return false;
+    }
+
+    switch (nodeTag(expr))
+    {
+    case T_A_Const:
+    case T_ColumnRef:
+    case T_A_Indirection:
+        {
+            break;
+        }
+    case T_A_Expr:
+    {
+        A_Expr *a = (A_Expr *)expr;
+
+        switch (a->kind)
+        {
+        case AEXPR_OP:
+        case AEXPR_IN:
+            {
+                if (expr_contains_node(is_expr, a->lexpr) ||
+                    expr_contains_node(is_expr, a->rexpr))
+                {
+                    return true;
+                }
+                break;
+            }
+        default:
+            ereport(ERROR, (errmsg_internal("unrecognized A_Expr kind: %d",
+                                            a->kind)));
+        }
+        break;
+    }
+    case T_BoolExpr:
+    {
+        BoolExpr *b = (BoolExpr *)expr;
+        ListCell *la;
+
+        foreach(la, b->args)
+        {
+            Node *arg = lfirst(la);
+
+            if (expr_contains_node(is_expr, arg))
+            {
+                return true;
+            }
+        }
+        break;
+    }
+    case T_NullTest:
+    {
+        NullTest *n = (NullTest *)expr;
+
+        if (expr_contains_node(is_expr, (Node *)n->arg))
+        {
+            return true;
+        }
+        break;
+    }
+    case T_CaseExpr:
+    {
+        CaseExpr *cexpr = (CaseExpr *)expr;
+        ListCell   *l;
+
+        if (cexpr->arg && expr_contains_node(is_expr, (Node *) cexpr->arg))
+        {
+            return true;
+        }
+
+        foreach(l, cexpr->args)
+        {
+            CaseWhen *w = lfirst_node(CaseWhen, l);
+            Node *warg;
+
+            warg = (Node *) w->expr;
+
+            if (expr_contains_node(is_expr, warg))
+            {
+                return true;
+            }
+            warg = (Node *)w->result;
+
+            if (expr_contains_node(is_expr, warg))
+            {
+                return true;
+            }
+        }
+
+        if (expr_contains_node(is_expr , (Node *)cexpr->defresult))
+        {
+            return true;
+        }
+
+        break;
+    }
+    case T_CaseTestExpr:
+    {
+        break;
+    }
+    case T_CoalesceExpr:
+    {
+        CoalesceExpr *cexpr = (CoalesceExpr *) expr;
+        ListCell *args;
+
+        foreach(args, cexpr->args)
+        {
+            Node *e = (Node *)lfirst(args);
+
+            if (expr_contains_node(is_expr, e))
+            {
+                return true;
+            }
+        }
+        break;
+    }
+    case T_ExtensibleNode:
+    {
+        if (is_ag_node(expr, cypher_bool_const))
+        {
+            return is_expr(expr);
+        }
+        if (is_ag_node(expr, cypher_integer_const))
+        {
+            return is_expr(expr);
+        }
+        if (is_ag_node(expr, cypher_param))
+        {
+            return is_expr(expr);
+        }
+        if (is_ag_node(expr, cypher_map))
+        {
+            cypher_map *cm = (cypher_map *)expr;
+            ListCell *le;
+
+            Assert(list_length(cm->keyvals) % 2 == 0);
+
+            le = list_head(cm->keyvals);
+
+            while(le != NULL)
+            {
+                Node *val;
+
+                le = lnext(cm->keyvals, le);
+
+                val = lfirst(le);
+
+                if (expr_contains_node(is_expr, val))
+                {
+                    return true;
+                }
+
+                le = lnext(cm->keyvals, le);
+
+            }
+            break;
+        }
+        if (is_ag_node(expr, cypher_map_projection))
+        {
+            cypher_map_projection *cmp = (cypher_map_projection *)expr;
+            ListCell *lc;
+
+            foreach(lc, cmp->map_elements)
+            {
+                cypher_map_projection_element *elem;
+
+                elem = lfirst(lc);
+
+                if (expr_contains_node(is_expr, elem->value))
+                {
+                    return true;
+                }
+            }
+
+            break;
+        }
+        if (is_ag_node(expr, cypher_list))
+        {
+            cypher_list *cl = (cypher_list *)expr;
+            ListCell *le = NULL;
+
+            foreach(le, cl->elems)
+            {
+                Node *texpr = lfirst(le);
+
+                if (expr_contains_node(is_expr, texpr))
+                {
+                    return true;
+                }
+            }
+            break;
+        }
+        if (is_ag_node(expr, cypher_string_match))
+        {
+            cypher_string_match *csm = (cypher_string_match *)expr;
+
+            if (expr_contains_node(is_expr, csm->lhs) ||
+                expr_contains_node(is_expr, csm->rhs))
+            {
+                return true;
+            }
+            break;
+        }
+        if (is_ag_node(expr, cypher_typecast))
+        {
+            cypher_typecast *t = (cypher_typecast *) expr;
+
+            if (expr_contains_node(is_expr, t->expr))
+            {
+                return true;
+            }
+            break;
+        }
+        if (is_ag_node(expr, cypher_comparison_aexpr))
+        {
+            cypher_comparison_aexpr *a = (cypher_comparison_aexpr *) expr;
+
+            if (expr_contains_node(is_expr, a->lexpr) ||
+                expr_contains_node(is_expr, a->rexpr))
+            {
+                return true;
+            }
+            break;
+        }
+        if (is_ag_node(expr, cypher_comparison_boolexpr))
+        {
+            cypher_comparison_boolexpr *b = (cypher_comparison_boolexpr *) 
expr;
+            ListCell *la;
+
+            foreach(la, b->args)
+            {
+                Node *arg = lfirst(la);
+
+                if (expr_contains_node(is_expr, arg))
+                {
+                    return true;
+                }
+            }
+            break;
+        }
+        if (is_ag_node(expr, cypher_unwind))
+        {
+            cypher_unwind* lc = (cypher_unwind *)expr;
+
+            if (expr_contains_node(is_expr, lc->where) ||
+                expr_contains_node(is_expr, lc->collect))
+            {
+                return true;
+            }
+            break;
+        }
+
+        if (is_ag_node(expr, cypher_sub_pattern))
+        {
+            break;
+        }
+
+        if (is_ag_node(expr, cypher_sub_query))
+        {
+            break;
+        }
+
+        ereport(ERROR,
+                (errmsg_internal("unrecognized ExtensibleNode: %s",
+                                 ((ExtensibleNode *)expr)->extnodename)));
+
+        break;
+    }
+    case T_FuncCall:
+    {
+        FuncCall *fn = (FuncCall *)expr;
+        ListCell *arg;
+
+        foreach(arg, fn->args)
+        {
+            Node *farg = NULL;
+
+            farg = (Node *)lfirst(arg);
+
+            if (expr_contains_node(is_expr, farg))
+            {
+                return true;
+            }
+        }
+        break;
+    }
+    case T_SubLink:
+    {
+       SubLink *s = (SubLink *)expr;
+
+        if (expr_contains_node(is_expr, s->subselect))
+        {
+            return true;
+        }
+      break;
+    }
+    default:
+        ereport(ERROR, (errmsg_internal("unrecognized node type: %d",
+                                        nodeTag(expr))));
+    }
+
+    return (is_expr(expr));
+}
+
+/*
+ * Function that checks if an expr is a cypher_sub_query. Used in tandem with
+ * expr_contains_node. Can write more similar to this to find similar nodes.
+ */
+
+bool expr_has_subquery(Node * expr)
+{
+    if (expr == NULL)
+    {
+        return false;
+    }
+
+    if (IsA(expr, ExtensibleNode))
+    {
+        if (is_ag_node(expr, cypher_sub_query))
+        {
+            return true;
+        }
+    }
+    return false;
+}
+
+/*
+ * This function constructs an intermediate WITH node for processing subqueries
+ */
+cypher_clause *build_subquery_node(cypher_clause *next)
+{
+    cypher_match *match = (cypher_match *)next->self;
+    cypher_clause *where_container_clause;
+    cypher_with *with_clause = make_ag_node(cypher_with);
+    ColumnRef *cr;
+    ResTarget *rt;
+
+    /* construct the column ref star */
+    cr = makeNode(ColumnRef);
+    cr->fields = list_make1(makeNode(A_Star));
+    //cr->location = @1;

Review Comment:
   Comment?



##########
src/backend/parser/cypher_analyze.c:
##########
@@ -653,6 +660,381 @@ static int get_query_location(const int location, const 
char *source_str)
     return strchr(p + 1, '$') - source_str + 1;
 }
 
+/*
+ * This is a specialized expression tree walker for finding exprs of a 
specified
+ * type. Create a function that checks for the type you want, and this function
+ * will iterate through the tree.
+ */
+
+bool expr_contains_node(cypher_expression_condition is_expr, Node *expr)
+{
+    if (!expr)
+    {
+        return false;
+    }
+
+    switch (nodeTag(expr))
+    {
+    case T_A_Const:
+    case T_ColumnRef:
+    case T_A_Indirection:
+        {
+            break;
+        }
+    case T_A_Expr:
+    {
+        A_Expr *a = (A_Expr *)expr;
+
+        switch (a->kind)
+        {
+        case AEXPR_OP:
+        case AEXPR_IN:
+            {
+                if (expr_contains_node(is_expr, a->lexpr) ||
+                    expr_contains_node(is_expr, a->rexpr))
+                {
+                    return true;
+                }
+                break;
+            }
+        default:
+            ereport(ERROR, (errmsg_internal("unrecognized A_Expr kind: %d",
+                                            a->kind)));
+        }
+        break;
+    }
+    case T_BoolExpr:
+    {
+        BoolExpr *b = (BoolExpr *)expr;
+        ListCell *la;
+
+        foreach(la, b->args)
+        {
+            Node *arg = lfirst(la);
+
+            if (expr_contains_node(is_expr, arg))
+            {
+                return true;
+            }
+        }
+        break;
+    }
+    case T_NullTest:
+    {
+        NullTest *n = (NullTest *)expr;
+
+        if (expr_contains_node(is_expr, (Node *)n->arg))
+        {
+            return true;
+        }
+        break;
+    }
+    case T_CaseExpr:
+    {
+        CaseExpr *cexpr = (CaseExpr *)expr;
+        ListCell   *l;
+
+        if (cexpr->arg && expr_contains_node(is_expr, (Node *) cexpr->arg))
+        {
+            return true;
+        }
+
+        foreach(l, cexpr->args)
+        {
+            CaseWhen *w = lfirst_node(CaseWhen, l);
+            Node *warg;
+
+            warg = (Node *) w->expr;
+
+            if (expr_contains_node(is_expr, warg))
+            {
+                return true;
+            }
+            warg = (Node *)w->result;
+
+            if (expr_contains_node(is_expr, warg))
+            {
+                return true;
+            }
+        }
+
+        if (expr_contains_node(is_expr , (Node *)cexpr->defresult))
+        {
+            return true;
+        }
+
+        break;
+    }
+    case T_CaseTestExpr:
+    {
+        break;
+    }
+    case T_CoalesceExpr:
+    {
+        CoalesceExpr *cexpr = (CoalesceExpr *) expr;
+        ListCell *args;
+
+        foreach(args, cexpr->args)
+        {
+            Node *e = (Node *)lfirst(args);
+
+            if (expr_contains_node(is_expr, e))
+            {
+                return true;
+            }
+        }
+        break;
+    }
+    case T_ExtensibleNode:
+    {
+        if (is_ag_node(expr, cypher_bool_const))
+        {
+            return is_expr(expr);
+        }
+        if (is_ag_node(expr, cypher_integer_const))
+        {
+            return is_expr(expr);
+        }
+        if (is_ag_node(expr, cypher_param))
+        {
+            return is_expr(expr);
+        }
+        if (is_ag_node(expr, cypher_map))
+        {
+            cypher_map *cm = (cypher_map *)expr;
+            ListCell *le;
+
+            Assert(list_length(cm->keyvals) % 2 == 0);
+
+            le = list_head(cm->keyvals);
+
+            while(le != NULL)
+            {
+                Node *val;
+
+                le = lnext(cm->keyvals, le);
+
+                val = lfirst(le);
+
+                if (expr_contains_node(is_expr, val))
+                {
+                    return true;
+                }
+
+                le = lnext(cm->keyvals, le);
+
+            }
+            break;
+        }
+        if (is_ag_node(expr, cypher_map_projection))
+        {
+            cypher_map_projection *cmp = (cypher_map_projection *)expr;
+            ListCell *lc;
+
+            foreach(lc, cmp->map_elements)
+            {
+                cypher_map_projection_element *elem;
+
+                elem = lfirst(lc);
+
+                if (expr_contains_node(is_expr, elem->value))
+                {
+                    return true;
+                }
+            }
+
+            break;
+        }
+        if (is_ag_node(expr, cypher_list))
+        {
+            cypher_list *cl = (cypher_list *)expr;
+            ListCell *le = NULL;
+
+            foreach(le, cl->elems)
+            {
+                Node *texpr = lfirst(le);
+
+                if (expr_contains_node(is_expr, texpr))
+                {
+                    return true;
+                }
+            }
+            break;
+        }
+        if (is_ag_node(expr, cypher_string_match))
+        {
+            cypher_string_match *csm = (cypher_string_match *)expr;
+
+            if (expr_contains_node(is_expr, csm->lhs) ||
+                expr_contains_node(is_expr, csm->rhs))
+            {
+                return true;
+            }
+            break;
+        }
+        if (is_ag_node(expr, cypher_typecast))
+        {
+            cypher_typecast *t = (cypher_typecast *) expr;
+
+            if (expr_contains_node(is_expr, t->expr))
+            {
+                return true;
+            }
+            break;
+        }
+        if (is_ag_node(expr, cypher_comparison_aexpr))
+        {
+            cypher_comparison_aexpr *a = (cypher_comparison_aexpr *) expr;
+
+            if (expr_contains_node(is_expr, a->lexpr) ||
+                expr_contains_node(is_expr, a->rexpr))
+            {
+                return true;
+            }
+            break;
+        }
+        if (is_ag_node(expr, cypher_comparison_boolexpr))
+        {
+            cypher_comparison_boolexpr *b = (cypher_comparison_boolexpr *) 
expr;
+            ListCell *la;
+
+            foreach(la, b->args)
+            {
+                Node *arg = lfirst(la);
+
+                if (expr_contains_node(is_expr, arg))
+                {
+                    return true;
+                }
+            }
+            break;
+        }
+        if (is_ag_node(expr, cypher_unwind))
+        {
+            cypher_unwind* lc = (cypher_unwind *)expr;
+
+            if (expr_contains_node(is_expr, lc->where) ||
+                expr_contains_node(is_expr, lc->collect))
+            {
+                return true;
+            }
+            break;
+        }
+
+        if (is_ag_node(expr, cypher_sub_pattern))
+        {
+            break;
+        }
+
+        if (is_ag_node(expr, cypher_sub_query))
+        {
+            break;
+        }
+
+        ereport(ERROR,
+                (errmsg_internal("unrecognized ExtensibleNode: %s",
+                                 ((ExtensibleNode *)expr)->extnodename)));
+
+        break;
+    }
+    case T_FuncCall:
+    {
+        FuncCall *fn = (FuncCall *)expr;
+        ListCell *arg;
+
+        foreach(arg, fn->args)
+        {
+            Node *farg = NULL;
+
+            farg = (Node *)lfirst(arg);
+
+            if (expr_contains_node(is_expr, farg))
+            {
+                return true;
+            }
+        }
+        break;
+    }
+    case T_SubLink:
+    {
+       SubLink *s = (SubLink *)expr;
+
+        if (expr_contains_node(is_expr, s->subselect))
+        {
+            return true;
+        }
+      break;
+    }
+    default:
+        ereport(ERROR, (errmsg_internal("unrecognized node type: %d",
+                                        nodeTag(expr))));
+    }
+
+    return (is_expr(expr));
+}
+
+/*
+ * Function that checks if an expr is a cypher_sub_query. Used in tandem with
+ * expr_contains_node. Can write more similar to this to find similar nodes.
+ */
+
+bool expr_has_subquery(Node * expr)
+{
+    if (expr == NULL)
+    {
+        return false;
+    }
+
+    if (IsA(expr, ExtensibleNode))
+    {
+        if (is_ag_node(expr, cypher_sub_query))
+        {
+            return true;
+        }
+    }
+    return false;
+}
+
+/*
+ * This function constructs an intermediate WITH node for processing subqueries
+ */
+cypher_clause *build_subquery_node(cypher_clause *next)
+{
+    cypher_match *match = (cypher_match *)next->self;
+    cypher_clause *where_container_clause;
+    cypher_with *with_clause = make_ag_node(cypher_with);
+    ColumnRef *cr;
+    ResTarget *rt;
+
+    /* construct the column ref star */
+    cr = makeNode(ColumnRef);
+    cr->fields = list_make1(makeNode(A_Star));
+    //cr->location = @1;
+
+    /*construct the restarget */
+    rt = makeNode(ResTarget);
+    rt->name = NULL;
+    rt->indirection = NIL;
+    rt->val = (Node *)cr;
+    //rt->location = @1;

Review Comment:
   Comment?



-- 
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]

Reply via email to