Skip to content

Commit 5656047

Browse files
committed
Cleanup Expression logic
1 parent e2a1e77 commit 5656047

File tree

13 files changed

+405
-7151
lines changed

13 files changed

+405
-7151
lines changed

Makefile

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -36,13 +36,10 @@ OBJS = src/backend/postgraph.o \
3636
src/backend/parser/ag_scanner.o \
3737
src/backend/parser/cypher_analyze.o \
3838
src/backend/parser/cypher_clause.o \
39-
src/backend/parser/sql_expr.o \
4039
src/backend/parser/cypher_expr.o \
4140
src/backend/parser/cypher_gram.o \
42-
src/backend/parser/cypher_grouping.o \
4341
src/backend/parser/cypher_item.o \
4442
src/backend/parser/cypher_keywords.o \
45-
src/backend/parser/cypher_parse_agg.o \
4643
src/backend/parser/cypher_parse_node.o \
4744
src/backend/parser/cypher_parser.o \
4845
src/backend/utils/adt/gtype.o \

regress/sql/cypher_create.sql

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,10 @@ MATCH (a:test) RETURN a;
4848

4949
CREATE ()-[]->();
5050

51+
CREATE (a)-[]->();
52+
53+
CREATE (a)-[]->() RETURN a;
54+
5155
CREATE ()-[:elabel]->();
5256

5357
MATCH ()-[]->() RETURN 1;

src/backend/executor/cypher_create.c

Lines changed: 25 additions & 170 deletions
Original file line numberDiff line numberDiff line change
@@ -40,18 +40,11 @@
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

7265
static 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);\
7668
static void begin_cypher_create(CustomScanState *node, EState *estate, int eflags);
7769
static TupleTableSlot *exec_cypher_create(CustomScanState *node);
7870
static void end_cypher_create(CustomScanState *node);
7971
static 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-
9173
const 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

263199
static 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-

src/backend/parser/cypher_analyze.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1216,6 +1216,7 @@ cypher_parse_analyze(RawStmt *parseTree, const char *sourceText,
12161216
cpstate->graph_name = gcd->name.data;
12171217
cpstate->graph_oid = graph_oid;
12181218

1219+
12191220
explainStmt->query = analyze_cypher(explainStmt->query, pstate, sourceText, 0, gcd->name.data, graph_oid, NULL);
12201221
Query *result;
12211222

@@ -1347,7 +1348,9 @@ analyze_cypher(List *stmt, ParseState *parent_pstate, const char *query_str, int
13471348
cpstate->params = params;
13481349
cpstate->default_alias_num = 0;
13491350

1351+
parsing_cypher = true;
13501352
Query *query = transform_cypher_clause(cpstate, clause);
1353+
parsing_cypher = false;
13511354

13521355
free_cypher_parsestate(cpstate);
13531356

0 commit comments

Comments
 (0)