bool has_a_cypher_list_comprehension_node()

in src/backend/parser/cypher_item.c [70:201]


bool has_a_cypher_list_comprehension_node(Node *expr)
{
    /* return false on NULL input */
    if (expr == NULL)
    {
        return false;
    }

    /* since this function recurses, it could be driven to stack overflow */
    check_stack_depth();

    switch (nodeTag(expr))
    {
    case T_A_Expr:
    {
        /*
         * We need to recurse into the left and right nodes
         * to check if there is an unwind node in there
         */
        A_Expr *a_expr = (A_Expr *)expr;

        return (has_a_cypher_list_comprehension_node(a_expr->lexpr) ||
                has_a_cypher_list_comprehension_node(a_expr->rexpr));
    }
    case T_BoolExpr:
    {
        BoolExpr *bexpr = (BoolExpr *)expr;
        ListCell *lc;

        /* is any of the boolean expression argument a list comprehension? */
        foreach(lc, bexpr->args)
        {
            Node *arg = lfirst(lc);

            if (has_a_cypher_list_comprehension_node(arg))
            {
                return true;
            }
        }
        break;
    }
    case T_A_Indirection:
    {
        /* set expr to the object of the indirection */
        expr = ((A_Indirection *)expr)->arg;

        /* check the object of the indirection */
        return has_a_cypher_list_comprehension_node(expr);
    }
    case T_ExtensibleNode:
    {
        if (is_ag_node(expr, cypher_unwind))
        {
            cypher_unwind *cu = (cypher_unwind *)expr;

            /* it is a list comprehension if it has a collect node */
            return cu->collect != NULL;
        }
        else if (is_ag_node(expr, cypher_map))
        {
            cypher_map *map;
            int i;

            map = (cypher_map *)expr;

            if (map->keyvals == NULL || map->keyvals->length == 0)
            {
                return false;
            }

            /* check each key and value for a list comprehension */
            for (i = 0; i < map->keyvals->length; i += 2)
            {
                Node *val;

                /* get the value */
                val = (Node *)map->keyvals->elements[i + 1].ptr_value;

                /* check the value */
                if (has_a_cypher_list_comprehension_node(val))
                {
                    return true;
                }
            }
        }
        else if (is_ag_node(expr, cypher_string_match))
        {
            cypher_string_match *csm_match = (cypher_string_match *)expr;

            /* is lhs or rhs of the string match a list comprehension? */
            return (has_a_cypher_list_comprehension_node(csm_match->lhs) ||
                    has_a_cypher_list_comprehension_node(csm_match->rhs));
        }
        else if (is_ag_node(expr, cypher_typecast))
        {
            cypher_typecast *ctypecast = (cypher_typecast *)expr;

            /* is expr being typecasted a list comprehension? */
            return has_a_cypher_list_comprehension_node(ctypecast->expr);
        }
        else if (is_ag_node(expr, cypher_comparison_aexpr))
        {
            cypher_comparison_aexpr *aexpr = (cypher_comparison_aexpr *)expr;

            /* is left or right argument a list comprehension? */
            return (has_a_cypher_list_comprehension_node(aexpr->lexpr) ||
                    has_a_cypher_list_comprehension_node(aexpr->rexpr));
        }
        else if (is_ag_node(expr, cypher_comparison_boolexpr))
        {
            cypher_comparison_boolexpr *bexpr = (cypher_comparison_boolexpr *)expr;
            ListCell *lc;

            /* is any of the boolean expression argument a list comprehension? */
            foreach(lc, bexpr->args)
            {
                Node *arg = lfirst(lc);

                if (has_a_cypher_list_comprehension_node(arg))
                {
                    return true;
                }
            }
        }
        break;
    }
    default:
        break;
    }
    /* otherwise, return false */
    return false;
}