Skip to content

Commit a72fce3

Browse files
committed
Support Edge Labels in CREATE Clause
1 parent 1f23178 commit a72fce3

3 files changed

Lines changed: 67 additions & 19 deletions

File tree

regress/expected/cypher_create.out

Lines changed: 37 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -143,13 +143,26 @@ MATCH (a) RETURN a;
143143
{"id": 1688849860263937, "label": "test2", "properties": {}}
144144
(3 rows)
145145

146+
MATCH (a:test) RETURN a;
147+
a
148+
-------------------------------------------------------------
149+
{"id": 1125899906842625, "label": "test", "properties": {}}
150+
(1 row)
151+
146152
CREATE ()-[]->();
147153
WARNING: relcache reference leak: relation "_ag_label_vertex" not closed
148154
WARNING: relcache reference leak: relation "_ag_label_vertex" not closed
149155
WARNING: relcache reference leak: relation "_ag_label_edge" not closed
150156
--
151157
(0 rows)
152158

159+
CREATE ()-[:elabel]->();
160+
WARNING: relcache reference leak: relation "_ag_label_vertex" not closed
161+
WARNING: relcache reference leak: relation "_ag_label_vertex" not closed
162+
WARNING: relcache reference leak: relation "elabel" not closed
163+
--
164+
(0 rows)
165+
153166
EXPLAIN MATCH ()-[]->() RETURN 1;
154167
QUERY PLAN
155168
-----------------------------------------------------------------------------------------------------
@@ -164,43 +177,48 @@ EXPLAIN MATCH ()-[]->() RETURN 1;
164177
EXPLAIN ANALYZE MATCH ()-[]->() RETURN 1;
165178
QUERY PLAN
166179
-----------------------------------------------------------------------------------------------------------------------------------------------
167-
Nested Loop (cost=12.50..50471.30 rows=2520000 width=32) (actual time=0.046..0.207 rows=1 loops=1)
168-
-> Append (cost=0.00..58.80 rows=2520 width=8) (actual time=0.005..0.013 rows=5 loops=1)
169-
-> Seq Scan on _ag_label_vertex _age_default_alias_0_1 (cost=0.00..2.20 rows=120 width=8) (actual time=0.005..0.006 rows=3 loops=1)
170-
-> Seq Scan on test _age_default_alias_0_2 (cost=0.00..22.00 rows=1200 width=8) (actual time=0.001..0.002 rows=1 loops=1)
171-
-> Seq Scan on test2 _age_default_alias_0_3 (cost=0.00..22.00 rows=1200 width=8) (actual time=0.002..0.002 rows=1 loops=1)
172-
-> Function Scan on edge_search _age_default_alias_1 (cost=12.50..22.50 rows=1000 width=0) (actual time=0.037..0.037 rows=0 loops=5)
173-
Planning Time: 0.093 ms
174-
Execution Time: 0.231 ms
180+
Nested Loop (cost=12.50..50471.30 rows=2520000 width=32) (actual time=0.057..0.302 rows=2 loops=1)
181+
-> Append (cost=0.00..58.80 rows=2520 width=8) (actual time=0.009..0.018 rows=7 loops=1)
182+
-> Seq Scan on _ag_label_vertex _age_default_alias_0_1 (cost=0.00..2.20 rows=120 width=8) (actual time=0.008..0.010 rows=5 loops=1)
183+
-> Seq Scan on test _age_default_alias_0_2 (cost=0.00..22.00 rows=1200 width=8) (actual time=0.002..0.003 rows=1 loops=1)
184+
-> Seq Scan on test2 _age_default_alias_0_3 (cost=0.00..22.00 rows=1200 width=8) (actual time=0.002..0.003 rows=1 loops=1)
185+
-> Function Scan on edge_search _age_default_alias_1 (cost=12.50..22.50 rows=1000 width=0) (actual time=0.039..0.039 rows=0 loops=7)
186+
Planning Time: 0.126 ms
187+
Execution Time: 0.332 ms
175188
(8 rows)
176189

177190
MATCH ()-[]->() RETURN 1;
178191
?column?
179192
----------
180193
1
181-
(1 row)
194+
1
195+
(2 rows)
182196

183197
SELECT * FROM cypher_create._ag_label_vertex;
184198
id | properties
185199
--------+------------
186200
(1, 1) |
187201
(1, 2) |
188202
(1, 3) |
203+
(1, 4) |
204+
(1, 5) |
189205
(4, 1) |
190206
(6, 1) |
191-
(5 rows)
207+
(7 rows)
192208

193209
SELECT * FROM cypher_create._adj__adj__ag_label_vertex;
194210
id | start_id | end_id | properties
195211
---------------+----------+--------+------------
196-
(0, 25304768) | (1, 2) | (1, 3) |
197-
(1 row)
212+
(0, 36327104) | (1, 2) | (1, 3) |
213+
(0, 35832480) | (1, 4) | (1, 5) |
214+
(2 rows)
198215

199216
SELECT * FROM cypher_create._adj__ag_label_vertex;
200217
id | start_id | end_id | properties
201218
---------------+----------+--------+------------
202-
(0, 25304768) | (1, 2) | (1, 3) |
203-
(1 row)
219+
(0, 36327104) | (1, 2) | (1, 3) |
220+
(0, 35832480) | (1, 4) | (1, 5) |
221+
(2 rows)
204222

205223
MATCH () RETURN 1;
206224
?column?
@@ -210,7 +228,9 @@ MATCH () RETURN 1;
210228
1
211229
1
212230
1
213-
(5 rows)
231+
1
232+
1
233+
(7 rows)
214234

215235
CYPHER WITH 1 as a
216236
CREATE ();
@@ -221,7 +241,7 @@ ERROR: CREATE doesn't work with next clauses
221241
-- Clean up
222242
--
223243
DROP GRAPH cypher_create CASCADE;
224-
NOTICE: drop cascades to 10 other objects
244+
NOTICE: drop cascades to 11 other objects
225245
DETAIL: drop cascades to table cypher_create._ag_label_vertex
226246
drop cascades to table cypher_create._adj__ag_label_vertex
227247
drop cascades to table cypher_create._adj__adj__ag_label_vertex
@@ -232,6 +252,7 @@ drop cascades to table cypher_create._adj__adj_test
232252
drop cascades to table cypher_create.test2
233253
drop cascades to table cypher_create._adj_test2
234254
drop cascades to table cypher_create._adj__adj_test2
255+
drop cascades to table cypher_create.elabel
235256
NOTICE: graph "cypher_create" has been dropped
236257
drop_graph
237258
------------

regress/sql/cypher_create.sql

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,8 +46,13 @@ MATCH () RETURN 1;
4646

4747
MATCH (a) RETURN a;
4848

49+
MATCH (a:test) RETURN a;
50+
4951
CREATE ()-[]->();
5052

53+
CREATE ()-[:elabel]->();
54+
55+
5156
EXPLAIN MATCH ()-[]->() RETURN 1;
5257

5358
EXPLAIN ANALYZE MATCH ()-[]->() RETURN 1;

src/backend/parser/cypher_clause.c

Lines changed: 25 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -336,6 +336,26 @@ static Expr *add_volatile_wrapper(Expr *node) {
336336
return (Expr *)makeFuncExpr(oid, GTYPEOID, list_make1(node), InvalidOid, InvalidOid, COERCE_EXPLICIT_CALL);
337337
}
338338

339+
static void validate_or_create_elabel(cypher_parsestate *cpstate, cypher_relationship *edge) {
340+
ParseState *pstate = (ParseState *)cpstate;
341+
label_cache_data *lcd = search_label_name_graph_cache(edge->label, cpstate->graph_oid);
342+
343+
if (lcd && lcd->kind != LABEL_KIND_EDGE) {
344+
ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
345+
errmsg("label %s is for vertices, not edges", edge->label),
346+
parser_errposition(pstate, edge->location)));
347+
} else if (!lcd) {
348+
List *parent;
349+
RangeVar *rv;
350+
351+
rv = get_label_range_var(cpstate->graph_name, cpstate->graph_oid, AG_DEFAULT_LABEL_EDGE);
352+
353+
parent = list_make1(rv);
354+
355+
create_label(cpstate->graph_name, edge->label, LABEL_TYPE_EDGE, parent, NULL);
356+
}
357+
}
358+
339359
static void validate_or_create_vlabel(cypher_parsestate *cpstate, cypher_node *node) {
340360
ParseState *pstate = (ParseState *)cpstate;
341361
label_cache_data *lcd = search_label_name_graph_cache(node->label, cpstate->graph_oid);
@@ -423,7 +443,7 @@ static Query *transform_cypher_create(cypher_parsestate *cpstate, cypher_clause
423443
cypher_relationship *edge = lfirst(lc2);
424444

425445
if (edge->label)
426-
ereport(ERROR, (errmsg_internal("edges in CREATE cannot have labels")));
446+
validate_or_create_elabel(cpstate, edge);
427447
else
428448
edge->label = AG_DEFAULT_LABEL_EDGE;
429449

@@ -1190,10 +1210,12 @@ static void transform_match_pattern(cypher_parsestate *cpstate, Query *query, Li
11901210
node->name = get_next_default_alias(cpstate);
11911211

11921212
bool is_default_label = true;
1193-
if (node->label)
1213+
if (node->label && i != 1)
11941214
ereport(ERROR,
11951215
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
11961216
errmsg("MATCH labels are not supported")));
1217+
else if (node->label)
1218+
is_default_label = false;
11971219
else
11981220
node->label = AG_DEFAULT_LABEL_VERTEX;
11991221

@@ -1281,7 +1303,7 @@ static void transform_match_pattern(cypher_parsestate *cpstate, Query *query, Li
12811303
} else {
12821304
continue;
12831305
}
1284-
//edge_pnsi = pnsi;
1306+
12851307
}
12861308

12871309
// id field

0 commit comments

Comments
 (0)