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;
}