in src/backend/parser/cypher_clause.c [121:425]
static void transform_match_pattern(cypher_parsestate *cpstate, Query *query,
List *pattern, Node *where);
static List *transform_match_path(cypher_parsestate *cpstate, Query *query,
cypher_path *path);
static Expr *transform_cypher_edge(cypher_parsestate *cpstate,
cypher_relationship *rel,
List **target_list, bool valid_label);
static Expr *transform_cypher_node(cypher_parsestate *cpstate,
cypher_node *node, List **target_list,
bool output_node, bool valid_label);
static bool match_check_valid_label(cypher_match *match,
cypher_parsestate *cpstate);
static Node *make_vertex_expr(cypher_parsestate *cpstate,
ParseNamespaceItem *pnsi);
static Node *make_edge_expr(cypher_parsestate *cpstate,
ParseNamespaceItem *pnsi);
static Node *make_qual(cypher_parsestate *cpstate,
transform_entity *entity, char *name);
static TargetEntry *
transform_match_create_path_variable(cypher_parsestate *cpstate,
cypher_path *path, List *entities);
static List *make_path_join_quals(cypher_parsestate *cpstate, List *entities);
static List *make_directed_edge_join_conditions(
cypher_parsestate *cpstate, transform_entity *prev_entity,
transform_entity *next_entity, Node *prev_qual, Node *next_qual,
char *prev_node_label, char *next_node_label);
static List *join_to_entity(cypher_parsestate *cpstate,
transform_entity *entity, Node *qual,
enum transform_entity_join_side side);
static List *make_join_condition_for_edge(cypher_parsestate *cpstate,
transform_entity *prev_edge,
transform_entity *prev_node,
transform_entity *entity,
transform_entity *next_node,
transform_entity *next_edge);
static List *make_edge_quals(cypher_parsestate *cpstate,
transform_entity *edge,
enum transform_entity_join_side side);
static A_Expr *filter_vertices_on_label_id(cypher_parsestate *cpstate,
Node *id_field, char *label);
static Node *transform_map_to_ind(cypher_parsestate *cpstate,
transform_entity *entity, cypher_map *map);
static List *transform_map_to_ind_recursive(cypher_parsestate *cpstate,
transform_entity *entity,
cypher_map *map,
List *parent_fields);
static List *transform_map_to_ind_top_level(cypher_parsestate *cpstate,
transform_entity *entity,
cypher_map *map);
static Node *create_property_constraints(cypher_parsestate *cpstate,
transform_entity *entity,
Node *property_constraints,
Node *prop_expr);
static TargetEntry *findTarget(List *targetList, char *resname);
static transform_entity *transform_VLE_edge_entity(cypher_parsestate *cpstate,
cypher_relationship *rel,
Query *query);
/* create clause */
static Query *transform_cypher_create(cypher_parsestate *cpstate,
cypher_clause *clause);
static List *transform_cypher_create_pattern(cypher_parsestate *cpstate,
Query *query, List *pattern);
static cypher_create_path *
transform_cypher_create_path(cypher_parsestate *cpstate, List **target_list,
cypher_path *cp);
static cypher_target_node *
transform_create_cypher_node(cypher_parsestate *cpstate, List **target_list,
cypher_node *node, bool has_edge);
static cypher_target_node *
transform_create_cypher_new_node(cypher_parsestate *cpstate,
List **target_list, cypher_node *node);
static cypher_target_node *transform_create_cypher_existing_node(
cypher_parsestate *cpstate, List **target_list, bool declared_in_current_clause,
cypher_node *node);
static cypher_target_node *
transform_create_cypher_edge(cypher_parsestate *cpstate, List **target_list,
cypher_relationship *edge);
static Expr *cypher_create_properties(cypher_parsestate *cpstate,
cypher_target_node *rel,
Relation label_relation, Node *props,
enum transform_entity_type type);
static Expr *add_volatile_wrapper(Expr *node);
static bool variable_exists(cypher_parsestate *cpstate, char *name);
static void add_volatile_wrapper_to_target_entry(List *target_list, int resno);
static int get_target_entry_resno(List *target_list, char *name);
static void handle_prev_clause(cypher_parsestate *cpstate, Query *query,
cypher_clause *clause, bool first_rte);
static TargetEntry *placeholder_target_entry(cypher_parsestate *cpstate,
char *name);
static Query *transform_cypher_sub_pattern(cypher_parsestate *cpstate,
cypher_clause *clause);
static Query *transform_cypher_sub_query(cypher_parsestate *cpstate,
cypher_clause *clause);
/* set and remove clause */
static Query *transform_cypher_set(cypher_parsestate *cpstate,
cypher_clause *clause);
static cypher_update_information *transform_cypher_set_item_list(cypher_parsestate *cpstate,
List *set_item_list,
Query *query);
static cypher_update_information *transform_cypher_remove_item_list(cypher_parsestate *cpstate,
List *remove_item_list,
Query *query);
/* delete */
static Query *transform_cypher_delete(cypher_parsestate *cpstate,
cypher_clause *clause);
static List *transform_cypher_delete_item_list(cypher_parsestate *cpstate,
List *delete_item_list,
Query *query);
/* set operators */
static cypher_clause *make_cypher_clause(List *stmt);
static Query *transform_cypher_union(cypher_parsestate *cpstate,
cypher_clause *clause);
static Node * transform_cypher_union_tree(cypher_parsestate *cpstate,
cypher_clause *clause,
bool isTopLevel,
List **targetlist);
Query *cypher_parse_sub_analyze_union(cypher_clause *clause,
cypher_parsestate *cpstate,
CommonTableExpr *parentCTE,
bool locked_from_parent,
bool resolve_unknowns);
static void get_res_cols(ParseState *pstate, ParseNamespaceItem *l_pnsi,
ParseNamespaceItem *r_pnsi, List **res_colnames,
List **res_colvars);
/* unwind */
static Query *transform_cypher_unwind(cypher_parsestate *cpstate,
cypher_clause *clause);
/* merge */
static Query *transform_cypher_merge(cypher_parsestate *cpstate,
cypher_clause *clause);
static cypher_create_path *
transform_merge_make_lateral_join(cypher_parsestate *cpstate, Query *query,
cypher_clause *clause,
cypher_clause *isolated_merge_clause);
static cypher_create_path *
transform_cypher_merge_path(cypher_parsestate *cpstate, List **target_list,
cypher_path *path);
static cypher_target_node *
transform_merge_cypher_edge(cypher_parsestate *cpstate, List **target_list,
cypher_relationship *edge);
static cypher_target_node *
transform_merge_cypher_node(cypher_parsestate *cpstate, List **target_list,
cypher_node *node, bool has_edge);
static Node *transform_clause_for_join(cypher_parsestate *cpstate,
cypher_clause *clause,
RangeTblEntry **rte,
ParseNamespaceItem **nsitem,
Alias* alias);
static cypher_clause *convert_merge_to_match(cypher_merge *merge);
static void
transform_cypher_merge_mark_tuple_position(cypher_parsestate *cpstate,
List *target_list,
cypher_create_path *path);
static cypher_target_node *get_referenced_variable(ParseState *pstate,
Node *node,
List *transformed_path);
/* call...[yield] */
static Query *transform_cypher_call_stmt(cypher_parsestate *cpstate,
cypher_clause *clause);
static Query *transform_cypher_call_subquery(cypher_parsestate *cpstate,
cypher_clause *clause);
/* transform */
#define PREV_CYPHER_CLAUSE_ALIAS AGE_DEFAULT_ALIAS_PREFIX"previous_cypher_clause"
#define CYPHER_OPT_RIGHT_ALIAS AGE_DEFAULT_ALIAS_PREFIX"cypher_optional_right"
#define transform_prev_cypher_clause(cpstate, prev_clause, add_rte_to_query) \
transform_cypher_clause_as_subquery(cpstate, transform_cypher_clause, \
prev_clause, NULL, add_rte_to_query)
ParseNamespaceItem
*transform_cypher_clause_as_subquery(cypher_parsestate *cpstate,
transform_method transform,
cypher_clause *clause,
Alias *alias,
bool add_rte_to_query);
static Query *analyze_cypher_clause(transform_method transform,
cypher_clause *clause,
cypher_parsestate *parent_cpstate);
static List *transform_group_clause(cypher_parsestate *cpstate,
List *grouplist, List **groupingSets,
List **targetlist, List *sortClause,
ParseExprKind exprKind);
static Node *flatten_grouping_sets(Node *expr, bool toplevel,
bool *hasGroupingSets);
static Index transform_group_clause_expr(List **flatresult,
Bitmapset *seen_local,
cypher_parsestate *cpstate,
Node *gexpr, List **targetlist,
List *sortClause,
ParseExprKind exprKind,
bool toplevel);
static List *add_target_to_group_list(cypher_parsestate *cpstate,
TargetEntry *tle, List *grouplist,
List *targetlist, int location);
static void advance_transform_entities_to_next_clause(List *entities);
static ParseNamespaceItem *get_namespace_item(ParseState *pstate,
RangeTblEntry *rte);
static List *make_target_list_from_join(ParseState *pstate,
RangeTblEntry *rte);
static FuncExpr *make_clause_func_expr(char *function_name,
Node *clause_information);
static void markRelsAsNulledBy(ParseState *pstate, Node *n, int jindex);
/* for VLE support */
static ParseNamespaceItem *transform_RangeFunction(cypher_parsestate *cpstate,
RangeFunction *r);
static Node *transform_VLE_Function(cypher_parsestate *cpstate, Node *n,
RangeTblEntry **top_rte, int *top_rti,
List **namespace);
static ParseNamespaceItem *append_VLE_Func_to_FromClause(cypher_parsestate *cpstate,
Node *n);
static void setNamespaceLateralState(List *namespace, bool lateral_only,
bool lateral_ok);
static bool isa_special_VLE_case(cypher_path *path);
static ParseNamespaceItem *find_pnsi(cypher_parsestate *cpstate, char *varname);
/*
* transform a cypher_clause
*/
Query *transform_cypher_clause(cypher_parsestate *cpstate,
cypher_clause *clause)
{
Node *self = clause->self;
Query *result;
/* examine the type of clause and call the transform logic for it */
if (is_ag_node(self, cypher_return))
{
cypher_return *n = (cypher_return *) self;
if (n->op == SETOP_NONE)
{
result = transform_cypher_return(cpstate, clause);
}
else if (n->op == SETOP_UNION)
{
result = transform_cypher_union(cpstate, clause);
}
else
{
ereport(ERROR, (errmsg_internal("unexpected Node for cypher_return")));
}
}
else if (is_ag_node(self, cypher_with))
{
result = transform_cypher_with(cpstate, clause);
}
else if (is_ag_node(self, cypher_match))
{
result = transform_cypher_match(cpstate, clause);
}
else if (is_ag_node(self, cypher_create))
{
result = transform_cypher_create(cpstate, clause);
}
else if (is_ag_node(self, cypher_set))
{
result = transform_cypher_set(cpstate, clause);
}
else if (is_ag_node(self, cypher_delete))
{
result = transform_cypher_delete(cpstate, clause);
}
else if (is_ag_node(self, cypher_merge))
{
result = transform_cypher_merge(cpstate, clause);
}
else if (is_ag_node(self, cypher_sub_pattern))
{
result = transform_cypher_sub_pattern(cpstate, clause);
}
else if (is_ag_node(self, cypher_sub_query))
{
result = transform_cypher_sub_query(cpstate, clause);
}
else if (is_ag_node(self, cypher_unwind))
{
cypher_unwind *n = (cypher_unwind *) self;
if (n->collect != NULL)
{
cpstate->p_list_comp = true;
}
result = transform_cypher_clause_with_where(cpstate,
transform_cypher_unwind,
clause, n->where);
}
else if (is_ag_node(self, cypher_call))
{
result = transform_cypher_call_stmt(cpstate, clause);
}
else
{
ereport(ERROR, (errmsg_internal("unexpected Node for cypher_clause")));
}
result->querySource = QSRC_ORIGINAL;
result->canSetTag = true;
return result;
}