40
40
#include "utils/ag_cache.h"
41
41
#include "utils/traversal.h"
42
42
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 ) \
51
44
estate->es_output_cid++; \
52
45
estate->es_snapshot->curcid++;
53
46
54
- #define Decrement_Estate_CommandId (estate ) \
47
+ #define RollbackCmdId (estate ) \
55
48
estate->es_output_cid--; \
56
49
estate->es_snapshot->curcid--;
57
50
@@ -71,23 +64,12 @@ typedef struct cypher_create_custom_scan_state
71
64
72
65
static HeapTuple insert_entity_tuple (ResultRelInfo * resultRelInfo ,
73
66
TupleTableSlot * elemTupleSlot ,
74
- EState * estate );
75
- static bool entity_exists (EState * estate , Oid graph_oid , graphid id );
67
+ EState * estate );\
76
68
static void begin_cypher_create (CustomScanState * node , EState * estate , int eflags );
77
69
static TupleTableSlot * exec_cypher_create (CustomScanState * node );
78
70
static void end_cypher_create (CustomScanState * node );
79
71
static void rescan_cypher_create (CustomScanState * node );
80
72
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
-
91
73
const CustomExecMethods cypher_create_exec_methods = {CREATE_SCAN_STATE_NAME ,
92
74
begin_cypher_create ,
93
75
exec_cypher_create ,
@@ -164,15 +146,13 @@ static void begin_cypher_create(CustomScanState *node, EState *estate, int eflag
164
146
165
147
cypher_create_path * path = linitial (css -> pattern );
166
148
167
-
168
-
169
149
css -> vertex_ids = palloc (sizeof (graphid * ) * list_length (css -> pattern ));
170
150
css -> vertex_ids [0 ] = palloc (sizeof (graphid ) * ((list_length (path -> target_nodes )/ 2 ) + 1 ) );
171
151
172
152
if (path -> target_nodes ) {
173
153
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
+ }
176
156
177
157
ListCell * lc1 ;
178
158
int i = 0 ;
@@ -201,10 +181,8 @@ static void begin_cypher_create(CustomScanState *node, EState *estate, int eflag
201
181
cypher_node -> adj_resultRelInfo = makeNode (ResultRelInfo );
202
182
InitResultRelInfo (cypher_node -> adj_resultRelInfo , adj_rel , list_length (estate -> es_range_table ), NULL , estate -> es_instrument );
203
183
204
- // Open all indexes for the relation
205
184
ExecOpenIndices (cypher_node -> adj_resultRelInfo , false);
206
185
207
-
208
186
// Setup the relation's tuple slot
209
187
cypher_node -> adj_elemTupleSlot = table_slot_create (adj_rel , & estate -> es_tupleTable );
210
188
@@ -215,49 +193,7 @@ static void begin_cypher_create(CustomScanState *node, EState *estate, int eflag
215
193
if (estate -> es_output_cid == 0 )
216
194
estate -> es_output_cid = estate -> es_snapshot -> curcid ;
217
195
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 );
261
197
}
262
198
263
199
static TupleTableSlot * exec_cypher_create (CustomScanState * csnode )
@@ -267,10 +203,11 @@ static TupleTableSlot *exec_cypher_create(CustomScanState *csnode)
267
203
EState * estate = css -> css .ss .ps .state ;
268
204
ExprContext * econtext = css -> css .ss .ps .ps_ExprContext ;
269
205
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 );
273
208
TupleTableSlot * slot = ExecProcNode (csnode -> ss .ps .lefttree );
209
+ AdvanceCmdId (estate );
210
+
274
211
slot = csnode -> ss .ps .lefttree -> ps_ProjInfo -> pi_exprContext -> ecxt_scantuple ;
275
212
slot -> tts_ops -> materialize (slot );
276
213
if (list_length (css -> pattern ) != 1 )
@@ -311,18 +248,27 @@ static TupleTableSlot *exec_cypher_create(CustomScanState *csnode)
311
248
// get the next graphid for this vertex.
312
249
elemTupleSlot -> tts_values [0 ] = css -> vertex_ids [0 ][i ];
313
250
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
+ }
314
255
315
256
// get the properties for this vertex
316
257
if (node -> prop_attr_num == InvalidAttrNumber ) {
317
258
elemTupleSlot -> tts_values [1 ] = NULL ;
318
259
elemTupleSlot -> tts_isnull [1 ] = true;
319
260
} 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 ];
323
262
elemTupleSlot -> tts_isnull [1 ] = slot -> tts_isnull [node -> prop_attr_num - 1 ];
324
263
}
325
264
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
+
326
272
// Insert the new vertex
327
273
insert_entity_tuple (resultRelInfo , elemTupleSlot , estate );
328
274
@@ -341,7 +287,7 @@ static TupleTableSlot *exec_cypher_create(CustomScanState *csnode)
341
287
elemTupleSlot -> tts_values [1 ] = css -> vertex_ids [0 ][node -> dir == CYPHER_REL_DIR_RIGHT ? i : i + 1 ];
342
288
elemTupleSlot -> tts_isnull [1 ] = false;
343
289
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 ];
345
291
elemTupleSlot -> tts_isnull [2 ] = false;
346
292
347
293
@@ -350,8 +296,8 @@ static TupleTableSlot *exec_cypher_create(CustomScanState *csnode)
350
296
elemTupleSlot -> tts_isnull [3 ] = true;
351
297
} else {
352
298
//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 ];
355
301
}
356
302
357
303
// Insert the new vertex
@@ -430,52 +376,6 @@ Node *create_cypher_create_plan_state(CustomScan *cscan)
430
376
return (Node * )cypher_css ;
431
377
}
432
378
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
-
479
379
/*
480
380
* Insert the edge/vertex tuple into the table and indices. Check that the
481
381
* table's constraints have not been violated.
@@ -511,48 +411,3 @@ HeapTuple insert_entity_tuple(ResultRelInfo *resultRelInfo,
511
411
512
412
return NULL ;
513
413
}
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