4040#include "utils/ag_cache.h"
4141#include "utils/traversal.h"
4242
43- /*
44- * When executing the children of the CREATE, SET, REMOVE, and
45- * DELETE clasues, we need to alter the command id in the estate
46- * and the snapshot. That way we can hide the modified tuples from
47- * the sub clauses that should not know what their parent clauses are
48- * doing.
49- */
50- #define Increment_Estate_CommandId (estate ) \
43+ #define AdvanceCmdId (estate ) \
5144 estate->es_output_cid++; \
5245 estate->es_snapshot->curcid++;
5346
54- #define Decrement_Estate_CommandId (estate ) \
47+ #define RollbackCmdId (estate ) \
5548 estate->es_output_cid--; \
5649 estate->es_snapshot->curcid--;
5750
@@ -71,23 +64,12 @@ typedef struct cypher_create_custom_scan_state
7164
7265static HeapTuple insert_entity_tuple (ResultRelInfo * resultRelInfo ,
7366 TupleTableSlot * elemTupleSlot ,
74- EState * estate );
75- static bool entity_exists (EState * estate , Oid graph_oid , graphid id );
67+ EState * estate );\
7668static void begin_cypher_create (CustomScanState * node , EState * estate , int eflags );
7769static TupleTableSlot * exec_cypher_create (CustomScanState * node );
7870static void end_cypher_create (CustomScanState * node );
7971static void rescan_cypher_create (CustomScanState * node );
8072
81- static void insert_edge (cypher_create_custom_scan_state * css ,
82- cypher_target_node * node , Datum prev_vertex_id ,
83- ListCell * next , List * list );
84-
85- static void insert_vertex (cypher_create_custom_scan_state * css ,
86- cypher_target_node * node , ListCell * next , List * list );
87-
88- static void process_pattern (cypher_create_custom_scan_state * css );
89-
90-
9173const CustomExecMethods cypher_create_exec_methods = {CREATE_SCAN_STATE_NAME ,
9274 begin_cypher_create ,
9375 exec_cypher_create ,
@@ -164,15 +146,13 @@ static void begin_cypher_create(CustomScanState *node, EState *estate, int eflag
164146
165147 cypher_create_path * path = linitial (css -> pattern );
166148
167-
168-
169149 css -> vertex_ids = palloc (sizeof (graphid * ) * list_length (css -> pattern ));
170150 css -> vertex_ids [0 ] = palloc (sizeof (graphid ) * ((list_length (path -> target_nodes )/ 2 ) + 1 ) );
171151
172152 if (path -> target_nodes ) {
173153 css -> edge_ids = palloc (sizeof (graphid * ) * list_length (css -> pattern ));
174- css -> edge_ids [0 ] = palloc (sizeof (graphid ) * ((list_length (path -> target_nodes )/ 2 ) ) );
175- }
154+ css -> edge_ids [0 ] = palloc (sizeof (graphid ) * ((list_length (path -> target_nodes ) / 2 ) ) );
155+ }
176156
177157 ListCell * lc1 ;
178158 int i = 0 ;
@@ -201,10 +181,8 @@ static void begin_cypher_create(CustomScanState *node, EState *estate, int eflag
201181 cypher_node -> adj_resultRelInfo = makeNode (ResultRelInfo );
202182 InitResultRelInfo (cypher_node -> adj_resultRelInfo , adj_rel , list_length (estate -> es_range_table ), NULL , estate -> es_instrument );
203183
204- // Open all indexes for the relation
205184 ExecOpenIndices (cypher_node -> adj_resultRelInfo , false);
206185
207-
208186 // Setup the relation's tuple slot
209187 cypher_node -> adj_elemTupleSlot = table_slot_create (adj_rel , & estate -> es_tupleTable );
210188
@@ -215,49 +193,7 @@ static void begin_cypher_create(CustomScanState *node, EState *estate, int eflag
215193 if (estate -> es_output_cid == 0 )
216194 estate -> es_output_cid = estate -> es_snapshot -> curcid ;
217195
218- Increment_Estate_CommandId (estate );
219- }
220-
221- /*
222- * CREATE the vertices and edges for a CREATE clause pattern.
223- */
224- static void process_pattern (cypher_create_custom_scan_state * css )
225- {
226- ListCell * lc2 ;
227-
228- foreach (lc2 , css -> pattern )
229- {
230- cypher_create_path * path = lfirst (lc2 );
231-
232- ListCell * lc = list_head (path -> target_nodes );
233-
234- /*
235- * Create the first vertex. The create_vertex function will
236- * create the rest of the path, if necessary.
237- */
238- insert_vertex (css , lfirst (lc ), lnext (path -> target_nodes , lc ), path -> target_nodes );
239-
240- /*
241- * If this path is a variable, take the list that was accumulated
242- * in the vertex/edge creation, create a path datum, and add to the
243- * scantuple slot.
244- */
245- if (path -> path_attr_num != InvalidAttrNumber )
246- {
247- TupleTableSlot * scantuple ;
248- PlanState * ps ;
249- Datum result ;
250-
251- ps = css -> css .ss .ps .lefttree ;
252- scantuple = ps -> ps_ExprContext -> ecxt_scantuple ;
253-
254- result = create_traversal (css -> path_values );
255- scantuple -> tts_values [path -> path_attr_num - 1 ] = result ;
256- scantuple -> tts_isnull [path -> path_attr_num - 1 ] = false;
257- }
258-
259- css -> path_values = NIL ;
260- }
196+ AdvanceCmdId (estate );
261197}
262198
263199static TupleTableSlot * exec_cypher_create (CustomScanState * csnode )
@@ -267,10 +203,11 @@ static TupleTableSlot *exec_cypher_create(CustomScanState *csnode)
267203 EState * estate = css -> css .ss .ps .state ;
268204 ExprContext * econtext = css -> css .ss .ps .ps_ExprContext ;
269205
270- //TupleTableSlot *scanTupleSlot = econtext->ecxt_scantuple;
271- //econtext->ecxt_scantuple =
272- // csnode->ss.ps.lefttree->ps_ProjInfo->pi_exprContext->ecxt_scantuple;
206+
207+ RollbackCmdId (estate );
273208 TupleTableSlot * slot = ExecProcNode (csnode -> ss .ps .lefttree );
209+ AdvanceCmdId (estate );
210+
274211 slot = csnode -> ss .ps .lefttree -> ps_ProjInfo -> pi_exprContext -> ecxt_scantuple ;
275212 slot -> tts_ops -> materialize (slot );
276213 if (list_length (css -> pattern ) != 1 )
@@ -311,18 +248,27 @@ static TupleTableSlot *exec_cypher_create(CustomScanState *csnode)
311248 // get the next graphid for this vertex.
312249 elemTupleSlot -> tts_values [0 ] = css -> vertex_ids [0 ][i ];
313250 elemTupleSlot -> tts_isnull [0 ] = false;
251+ if (node -> id_attr_num != InvalidAttrNumber ) {
252+ slot -> tts_values [node -> id_attr_num - 1 ] = GRAPHID_GET_DATUM (css -> vertex_ids [0 ][i ]);
253+ slot -> tts_isnull [node -> id_attr_num - 1 ] = false;
254+ }
314255
315256 // get the properties for this vertex
316257 if (node -> prop_attr_num == InvalidAttrNumber ) {
317258 elemTupleSlot -> tts_values [1 ] = NULL ;
318259 elemTupleSlot -> tts_isnull [1 ] = true;
319260 } else {
320- //TupleTableSlot *scanTupleSlot = csnode->ss.ss_ScanTupleSlot;
321- //ereport(WARNING, errmsg("adsf %i", scanTupleSlot->tts_values[node->prop_attr_num]));
322- elemTupleSlot -> tts_values [1 ] = slot -> tts_values [node -> prop_attr_num - 1 ];
261+ elemTupleSlot -> tts_values [1 ] = slot -> tts_values [node -> prop_attr_num - 1 ];
323262 elemTupleSlot -> tts_isnull [1 ] = slot -> tts_isnull [node -> prop_attr_num - 1 ];
324263 }
325264
265+ if (node -> tuple_position != InvalidAttrNumber ) {
266+ create_vertex (
267+ GRAPHID_GET_DATUM (slot -> tts_values [node -> id_attr_num - 1 ]),
268+ css -> graph_oid ,
269+ node -> prop_attr_num == InvalidAttrNumber ? NULL : DATUM_GET_GTYPE_P (slot -> tts_values [node -> prop_attr_num - 1 ]));
270+ }
271+
326272 // Insert the new vertex
327273 insert_entity_tuple (resultRelInfo , elemTupleSlot , estate );
328274
@@ -341,7 +287,7 @@ static TupleTableSlot *exec_cypher_create(CustomScanState *csnode)
341287 elemTupleSlot -> tts_values [1 ] = css -> vertex_ids [0 ][node -> dir == CYPHER_REL_DIR_RIGHT ? i : i + 1 ];
342288 elemTupleSlot -> tts_isnull [1 ] = false;
343289
344- elemTupleSlot -> tts_values [2 ] = css -> vertex_ids [0 ][node -> dir == CYPHER_REL_DIR_RIGHT ? i + 1 : i ];
290+ elemTupleSlot -> tts_values [2 ] = css -> vertex_ids [0 ][node -> dir == CYPHER_REL_DIR_RIGHT ? i + 1 : i ];
345291 elemTupleSlot -> tts_isnull [2 ] = false;
346292
347293
@@ -350,8 +296,8 @@ static TupleTableSlot *exec_cypher_create(CustomScanState *csnode)
350296 elemTupleSlot -> tts_isnull [3 ] = true;
351297 } else {
352298 //TupleTableSlot *scanTupleSlot = econtext->ecxt_scantuple;
353- elemTupleSlot -> tts_values [3 ] = slot -> tts_values [node -> prop_attr_num ];
354- elemTupleSlot -> tts_isnull [3 ] = slot -> tts_isnull [node -> prop_attr_num ];
299+ elemTupleSlot -> tts_values [3 ] = slot -> tts_values [node -> prop_attr_num - 1 ];
300+ elemTupleSlot -> tts_isnull [3 ] = slot -> tts_isnull [node -> prop_attr_num - 1 ];
355301 }
356302
357303 // Insert the new vertex
@@ -430,52 +376,6 @@ Node *create_cypher_create_plan_state(CustomScan *cscan)
430376 return (Node * )cypher_css ;
431377}
432378
433-
434- /*
435- * Creates the vertex entity, returns the vertex's id in case the caller is
436- * the create_edge function.
437- */
438- static void insert_vertex (cypher_create_custom_scan_state * css ,
439- cypher_target_node * node , ListCell * next , List * list )
440- {
441- bool isNull ;
442- Datum id ;
443- EState * estate = css -> css .ss .ps .state ;
444- ExprContext * econtext = css -> css .ss .ps .ps_ExprContext ;
445- ResultRelInfo * resultRelInfo = node -> resultRelInfo ;
446- TupleTableSlot * elemTupleSlot = node -> elemTupleSlot ;
447- TupleTableSlot * scanTupleSlot = econtext -> ecxt_scantuple ;
448-
449- /*
450- * Vertices in a path might already exists. If they do get the id
451- * to pass to the edges before and after it. Otherwise, insert the
452- * new vertex into it's table and then pass the id along.
453- */
454- ResultRelInfo * * old_estate_es_result_relations_info = NULL ;
455-
456- old_estate_es_result_relations_info = estate -> es_result_relations ;
457-
458- estate -> es_result_relations = & resultRelInfo ;
459-
460- ExecClearTuple (elemTupleSlot );
461-
462- // get the next graphid for this vertex.
463- id = ExecEvalExpr (node -> id_expr_state , econtext , & isNull );
464- elemTupleSlot -> tts_values [0 ] = id ;
465- elemTupleSlot -> tts_isnull [0 ] = isNull ;
466-
467- // get the properties for this vertex
468- elemTupleSlot -> tts_values [1 ] = NULL ;
469- elemTupleSlot -> tts_isnull [1 ] = true;
470-
471- // Insert the new vertex
472- insert_entity_tuple (resultRelInfo , elemTupleSlot , estate );
473-
474- /* restore the old result relation info */
475- estate -> es_result_relations = old_estate_es_result_relations_info ;
476- }
477-
478-
479379/*
480380 * Insert the edge/vertex tuple into the table and indices. Check that the
481381 * table's constraints have not been violated.
@@ -511,48 +411,3 @@ HeapTuple insert_entity_tuple(ResultRelInfo *resultRelInfo,
511411
512412 return NULL ;
513413}
514-
515-
516- /*
517- * Find out if the entity still exists. This is for 'implicit' deletion
518- * of an entity.
519- */
520- bool entity_exists (EState * estate , Oid graph_oid , graphid id )
521- {
522- label_cache_data * label ;
523- ScanKeyData scan_keys [1 ];
524- TableScanDesc scan_desc ;
525- HeapTuple tuple ;
526- Relation rel ;
527- bool result = true;
528-
529- /*
530- * Extract the label id from the graph id and get the table name
531- * the entity is part of.
532- */
533- label = search_label_graph_oid_cache (graph_oid , GET_LABEL_ID (id ));
534-
535- // Setup the scan key to be the graphid
536- ScanKeyInit (& scan_keys [0 ], 1 , BTEqualStrategyNumber ,
537- F_GRAPHIDEQ , GRAPHID_GET_DATUM (id ));
538-
539- rel = table_open (label -> relation , RowExclusiveLock );
540- scan_desc = table_beginscan (rel , estate -> es_snapshot , 1 , scan_keys );
541-
542- tuple = heap_getnext (scan_desc , ForwardScanDirection );
543-
544- /*
545- * If a single tuple was returned, the tuple is still valid, otherwise'
546- * set to false.
547- */
548- if (!HeapTupleIsValid (tuple ))
549- {
550- result = false;
551- }
552-
553- table_endscan (scan_desc );
554- table_close (rel , RowExclusiveLock );
555-
556- return result ;
557- }
558-
0 commit comments