/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #ifndef AG_CYPHER_NODE_H #define AG_CYPHER_NODE_H #include "postgres.h" #include "nodes/extensible.h" #include "nodes/parsenodes.h" #include "nodes/pg_list.h" #include "nodes/ag_nodes.h" /* cypher sub patterns */ typedef enum csp_kind { CSP_EXISTS, CSP_SIZE, CSP_FINDPATH /* shortestpath, allshortestpaths, dijkstra */ } csp_kind; typedef struct cypher_sub_pattern { ExtensibleNode extensible; csp_kind kind; List *pattern; } cypher_sub_pattern; /* * clauses */ typedef struct cypher_return { ExtensibleNode extensible; bool distinct; List *items; // a list of ResTarget's List *order_by; Node *skip; Node *limit; bool all_or_distinct; SetOperation op; List *larg; /* lefthand argument of the unions */ List *rarg; /*righthand argument of the unions */ } cypher_return; typedef struct cypher_with { ExtensibleNode extensible; bool distinct; List *items; // a list of ResTarget's List *order_by; Node *skip; Node *limit; Node *where; } cypher_with; typedef struct cypher_match { ExtensibleNode extensible; List *pattern; // a list of cypher_paths Node *where; // optional WHERE subclause (expression) bool optional; // OPTIONAL MATCH } cypher_match; typedef struct cypher_create { ExtensibleNode extensible; List *pattern; // a list of cypher_paths } cypher_create; typedef struct cypher_set { ExtensibleNode extensible; List *items; // a list of cypher_set_items bool is_remove; // true if this is REMOVE clause int location; } cypher_set; typedef struct cypher_set_item { ExtensibleNode extensible; Node *prop; // LHS Node *expr; // RHS bool is_add; // true if this is += int location; } cypher_set_item; typedef struct cypher_delete { ExtensibleNode extensible; bool detach; // true if DETACH is specified List *exprs; // targets of this deletion int location; } cypher_delete; typedef struct cypher_unwind { ExtensibleNode extensible; ResTarget *target; } cypher_unwind; typedef struct cypher_merge { ExtensibleNode extensible; Node *path; } cypher_merge; /* * pattern */ typedef struct cypher_path { ExtensibleNode extensible; List *path; // [ node ( , relationship , node , ... ) ] char *var_name; char *parsed_var_name; int location; } cypher_path; // ( name :label props ) typedef struct cypher_node { ExtensibleNode extensible; char *name; char *parsed_name; char *label; char *parsed_label; Node *props; // map or parameter int location; } cypher_node; typedef enum { CYPHER_REL_DIR_NONE = 0, CYPHER_REL_DIR_LEFT = -1, CYPHER_REL_DIR_RIGHT = 1 } cypher_rel_dir; // -[ name :label props ]- typedef struct cypher_relationship { ExtensibleNode extensible; char *name; char *parsed_name; char *label; char *parsed_label; Node *props; // map or parameter Node *varlen; // variable length relationships (A_Indices) cypher_rel_dir dir; int location; } cypher_relationship; /* * expression */ typedef struct cypher_bool_const { ExtensibleNode extensible; bool boolean; int location; } cypher_bool_const; typedef struct cypher_integer_const { ExtensibleNode extensible; int64 integer; int location; } cypher_integer_const; typedef struct cypher_param { ExtensibleNode extensible; char *name; int location; } cypher_param; typedef struct cypher_map { ExtensibleNode extensible; List *keyvals; int location; bool keep_null; // if false, keyvals with null value are removed } cypher_map; typedef struct cypher_list { ExtensibleNode extensible; List *elems; int location; } cypher_list; enum cypher_string_match_op { CSMO_STARTS_WITH, CSMO_ENDS_WITH, CSMO_CONTAINS }; typedef struct cypher_string_match { ExtensibleNode extensible; enum cypher_string_match_op operation; Node *lhs; Node *rhs; int location; } cypher_string_match; typedef struct cypher_create_target_nodes { ExtensibleNode extensible; List *paths; uint32 flags; uint32 graph_oid; } cypher_create_target_nodes; typedef struct cypher_create_path { ExtensibleNode extensible; List *target_nodes; AttrNumber path_attr_num; char *var_name; } cypher_create_path; /* * comparison expressions */ typedef struct cypher_comparison_aexpr { ExtensibleNode extensible; A_Expr_Kind kind; /* see above */ List *name; /* possibly-qualified name of operator */ Node *lexpr; /* left argument, or NULL if none */ Node *rexpr; /* right argument, or NULL if none */ int location; /* token location, or -1 if unknown */ } cypher_comparison_aexpr; typedef struct cypher_comparison_boolexpr { ExtensibleNode extensible; BoolExprType boolop; List *args; /* arguments to this expression */ int location; /* token location, or -1 if unknown */ } cypher_comparison_boolexpr; /* * procedure call */ typedef struct cypher_call { ExtensibleNode extensible; FuncCall *funccall; /*from the parser */ FuncExpr *funcexpr; /*transformed */ Node *where; List *yield_items; // optional yield subclause } cypher_call; #define CYPHER_CLAUSE_FLAG_NONE 0x0000 #define CYPHER_CLAUSE_FLAG_TERMINAL 0x0001 #define CYPHER_CLAUSE_FLAG_PREVIOUS_CLAUSE 0x0002 #define CYPHER_CLAUSE_IS_TERMINAL(flags) \ (flags & CYPHER_CLAUSE_FLAG_TERMINAL) #define CYPHER_CLAUSE_HAS_PREVIOUS_CLAUSE(flags) \ (flags & CYPHER_CLAUSE_FLAG_PREVIOUS_CLAUSE) /* * Structure that contains all information to create * a new entity in the create clause, or where to access * this information if it doesn't need to be created. * * NOTE: This structure may be used for the MERGE clause as * well */ typedef struct cypher_target_node { ExtensibleNode extensible; // 'v' for vertex or 'e' for edge char type; // flags defined below, prefaced with CYPHER_TARGET_NODE_FLAG_* uint32 flags; // if an edge, denotes direction cypher_rel_dir dir; /* * Used to create the id for the vertex/edge, * if the CYPHER_TARGET_NODE_FLAG_INSERT flag * is set. Doing it this way will protect us when * rescan gets implemented. By calling the function * that creates the id ourselves, we won't have an * issue where the id could be created then not used. * Since there is a limited number of ids available, we * don't want to waste them. */ Expr *id_expr; ExprState *id_expr_state; Expr *prop_expr; ExprState *prop_expr_state; /* * Attribute Number that this entity's properties * are stored in the CustomScanState's child TupleTableSlot */ AttrNumber prop_attr_num; // RelInfo for the table this entity will be stored in ResultRelInfo *resultRelInfo; // elemTupleSlot used to insert the entity into its table TupleTableSlot *elemTupleSlot; // relid that the label stores its entity Oid relid; // label this entity belongs to. char *label_name; // variable name for this entity char *variable_name; /* * Attribute number this entity needs to be stored in * for parent execution nodes to reference it. If the * entity is a variable (CYPHER_TARGET_NODE_IS_VAR). */ AttrNumber tuple_position; } cypher_target_node; #define CYPHER_TARGET_NODE_FLAG_NONE 0x0000 // node must insert data #define CYPHER_TARGET_NODE_FLAG_INSERT 0x0001 /* * Flag that denotes if this target node is referencing * a variable that was already created AND created in the * same clause. */ #define EXISTING_VARIABLE_DECLARED_SAME_CLAUSE 0x0002 //node is the first instance of a declared variable #define CYPHER_TARGET_NODE_IS_VAR 0x0004 // node is an element in a path variable #define CYPHER_TARGET_NODE_IN_PATH_VAR 0x0008 #define CYPHER_TARGET_NODE_MERGE_EXISTS 0x0010 #define CYPHER_TARGET_NODE_OUTPUT(flags) \ (flags & (CYPHER_TARGET_NODE_IS_VAR | CYPHER_TARGET_NODE_IN_PATH_VAR)) #define CYPHER_TARGET_NODE_IN_PATH(flags) \ (flags & CYPHER_TARGET_NODE_IN_PATH_VAR) #define CYPHER_TARGET_NODE_IS_VARIABLE(flags) \ (flags & CYPHER_TARGET_NODE_IS_VAR) /* * When a vertex is created and is reference in the same clause * later. We don't need to check to see if the vertex still exists. */ #define SAFE_TO_SKIP_EXISTENCE_CHECK(flags) \ (flags & EXISTING_VARIABLE_DECLARED_SAME_CLAUSE) #define CYPHER_TARGET_NODE_INSERT_ENTITY(flags) \ (flags & CYPHER_TARGET_NODE_FLAG_INSERT) #define UPDATE_CLAUSE_SET "SET" #define UPDATE_CLAUSE_REMOVE "REMOVE" /* Data Structures that contain information about a vertices and edges the need to be updated */ typedef struct cypher_update_information { ExtensibleNode extensible; List *set_items; uint32 flags; AttrNumber tuple_position; char *graph_name; char *clause_name; } cypher_update_information; typedef struct cypher_update_item { ExtensibleNode extensible; AttrNumber prop_position; AttrNumber entity_position; char *var_name; char *prop_name; List *qualified_name; bool remove_item; bool is_add; } cypher_update_item; typedef struct cypher_delete_information { ExtensibleNode extensible; List *delete_items; uint32 flags; char *graph_name; uint32 graph_oid; bool detach; } cypher_delete_information; typedef struct cypher_delete_item { ExtensibleNode extensible; Value *entity_position; char *var_name; } cypher_delete_item; typedef struct cypher_merge_information { ExtensibleNode extensible; uint32 flags; uint32 graph_oid; AttrNumber merge_function_attr; cypher_create_path *path; } cypher_merge_information; /* grammar node for typecasts */ typedef struct cypher_typecast { ExtensibleNode extensible; Node *expr; char *typecast; int location; } cypher_typecast; #endif