Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix Issue 1988: How to update a property which is a keyword (#2005) #2015

Merged
merged 1 commit into from
Aug 6, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
137 changes: 137 additions & 0 deletions regress/expected/expr.out
Original file line number Diff line number Diff line change
Expand Up @@ -8465,9 +8465,146 @@ SELECT * FROM cypher('issue_1953', $$ RETURN is_valid_label_name('issue_1953')[0
ERROR: A_indirection could not convert type boolean to agtype
LINE 1: ...cypher('issue_1953', $$ RETURN is_valid_label_name('issue_19...
^
--
-- Issue 1988: How to update a property which is a keyword.
--
SELECT * FROM create_graph('issue_1988');
NOTICE: graph "issue_1988" has been created
create_graph
--------------

(1 row)

SELECT * from cypher('issue_1988', $$
CREATE (p1:Part {part_num: 123}),
(p2:Part {part_num: 345}),
(p3:Part {part_num: 456}),
(p4:Part {part_num: 789}) $$) as (a agtype);
a
---
(0 rows)

SELECT * FROM cypher('issue_1988', $$
MATCH (p) RETURN p $$) as (p agtype);
p
-----------------------------------------------------------------------------------
{"id": 844424930131969, "label": "Part", "properties": {"part_num": 123}}::vertex
{"id": 844424930131970, "label": "Part", "properties": {"part_num": 345}}::vertex
{"id": 844424930131971, "label": "Part", "properties": {"part_num": 456}}::vertex
{"id": 844424930131972, "label": "Part", "properties": {"part_num": 789}}::vertex
(4 rows)

SELECT * from cypher('issue_1988', $$
MATCH (p1:Part {part_num: 123}), (p2:Part {part_num: 345})
CREATE (p1)-[u:used_by { quantity: 1 }]->(p2) RETURN p1, u, p2 $$) as (p1 agtype, u agtype, p2 agtype);
p1 | u | p2
-----------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------+-----------------------------------------------------------------------------------
{"id": 844424930131969, "label": "Part", "properties": {"part_num": 123}}::vertex | {"id": 1125899906842625, "label": "used_by", "end_id": 844424930131970, "start_id": 844424930131969, "properties": {"quantity": 1}}::edge | {"id": 844424930131970, "label": "Part", "properties": {"part_num": 345}}::vertex
(1 row)

-- should fail
SELECT * FROM cypher('issue_1988', $$
MATCH (p:Part { part_num: 123 }) SET p.match = 'xyz' RETURN p $$) as (p agtype);
ERROR: syntax error at or near "="
LINE 2: MATCH (p:Part { part_num: 123 }) SET p.match = 'xyz' RET...
^
-- should succeed
SELECT * FROM cypher('issue_1988', $$
MATCH (p:Part { part_num: 123 }) SET p.`match` = 'xyz' RETURN p $$) as (p agtype);
p
---------------------------------------------------------------------------------------------------
{"id": 844424930131969, "label": "Part", "properties": {"match": "xyz", "part_num": 123}}::vertex
(1 row)

SELECT * FROM cypher('issue_1988', $$
MATCH (p:Part { part_num: 123 }) SET p.`set` = 'xyz' RETURN p $$) as (p agtype);
p
-----------------------------------------------------------------------------------------------------------------
{"id": 844424930131969, "label": "Part", "properties": {"set": "xyz", "match": "xyz", "part_num": 123}}::vertex
(1 row)

SELECT * FROM cypher('issue_1988', $$
MATCH (p:Part { part_num: 123 }) SET p.`delete` = 'xyz' RETURN p $$) as (p agtype);
p
----------------------------------------------------------------------------------------------------------------------------------
{"id": 844424930131969, "label": "Part", "properties": {"set": "xyz", "match": "xyz", "delete": "xyz", "part_num": 123}}::vertex
(1 row)

SELECT * FROM cypher('issue_1988', $$
MATCH (p:Part { part_num: 123 }) SET p.`merge` = 'xyz' RETURN p $$) as (p agtype);
p
--------------------------------------------------------------------------------------------------------------------------------------------------
{"id": 844424930131969, "label": "Part", "properties": {"set": "xyz", "match": "xyz", "merge": "xyz", "delete": "xyz", "part_num": 123}}::vertex
(1 row)

SELECT * FROM cypher('issue_1988', $$
MATCH (p:Part { part_num: 123 }) SET p.`create` = 'xyz' RETURN p $$) as (p agtype);
p
-------------------------------------------------------------------------------------------------------------------------------------------------------------------
{"id": 844424930131969, "label": "Part", "properties": {"set": "xyz", "match": "xyz", "merge": "xyz", "create": "xyz", "delete": "xyz", "part_num": 123}}::vertex
(1 row)

-- should succeed
SELECT * FROM cypher('issue_1988', $$
MATCH (p:Part { part_num: 123 }) SET p.`match` = 'match' RETURN p $$) as (p agtype);
p
---------------------------------------------------------------------------------------------------------------------------------------------------------------------
{"id": 844424930131969, "label": "Part", "properties": {"set": "xyz", "match": "match", "merge": "xyz", "create": "xyz", "delete": "xyz", "part_num": 123}}::vertex
(1 row)

SELECT * FROM cypher('issue_1988', $$
MATCH (p:Part { part_num: 123 }) SET p.`set` = 'set' RETURN p $$) as (p agtype);
p
---------------------------------------------------------------------------------------------------------------------------------------------------------------------
{"id": 844424930131969, "label": "Part", "properties": {"set": "set", "match": "match", "merge": "xyz", "create": "xyz", "delete": "xyz", "part_num": 123}}::vertex
(1 row)

SELECT * FROM cypher('issue_1988', $$
MATCH (p:Part { part_num: 123 }) SET p.`delete` = 'delete' RETURN p $$) as (p agtype);
p
------------------------------------------------------------------------------------------------------------------------------------------------------------------------
{"id": 844424930131969, "label": "Part", "properties": {"set": "set", "match": "match", "merge": "xyz", "create": "xyz", "delete": "delete", "part_num": 123}}::vertex
(1 row)

SELECT * FROM cypher('issue_1988', $$
MATCH (p:Part { part_num: 123 }) SET p.`merge` = 'merge' RETURN p $$) as (p agtype);
p
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------
{"id": 844424930131969, "label": "Part", "properties": {"set": "set", "match": "match", "merge": "merge", "create": "xyz", "delete": "delete", "part_num": 123}}::vertex
(1 row)

SELECT * FROM cypher('issue_1988', $$
MATCH (p:Part { part_num: 123 }) SET p.`create` = 'create' RETURN p $$) as (p agtype);
p
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------
{"id": 844424930131969, "label": "Part", "properties": {"set": "set", "match": "match", "merge": "merge", "create": "create", "delete": "delete", "part_num": 123}}::vertex
(1 row)

SELECT * FROM cypher('issue_1988', $$
MATCH (p) RETURN p $$) as (p agtype);
p
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------
{"id": 844424930131970, "label": "Part", "properties": {"part_num": 345}}::vertex
{"id": 844424930131971, "label": "Part", "properties": {"part_num": 456}}::vertex
{"id": 844424930131972, "label": "Part", "properties": {"part_num": 789}}::vertex
{"id": 844424930131969, "label": "Part", "properties": {"set": "set", "match": "match", "merge": "merge", "create": "create", "delete": "delete", "part_num": 123}}::vertex
(4 rows)

--
-- Cleanup
--
SELECT * FROM drop_graph('issue_1988', true);
NOTICE: drop cascades to 4 other objects
DETAIL: drop cascades to table issue_1988._ag_label_vertex
drop cascades to table issue_1988._ag_label_edge
drop cascades to table issue_1988."Part"
drop cascades to table issue_1988.used_by
NOTICE: graph "issue_1988" has been dropped
drop_graph
------------

(1 row)

SELECT * FROM drop_graph('issue_1953', true);
NOTICE: drop cascades to 2 other objects
DETAIL: drop cascades to table issue_1953._ag_label_vertex
Expand Down
47 changes: 47 additions & 0 deletions regress/sql/expr.sql
Original file line number Diff line number Diff line change
Expand Up @@ -3445,9 +3445,56 @@ SELECT * FROM cypher('issue_1953', $$ RETURN is_valid_label_name('issue_1953')[{
SELECT * FROM cypher('issue_1953', $$ RETURN is_valid_label_name('issue_1953')[0] $$) AS (result agtype);
SELECT * FROM cypher('issue_1953', $$ RETURN is_valid_label_name('issue_1953')[0..1] $$) AS (result agtype);

--
-- Issue 1988: How to update a property which is a keyword.
--
SELECT * FROM create_graph('issue_1988');
SELECT * from cypher('issue_1988', $$
CREATE (p1:Part {part_num: 123}),
(p2:Part {part_num: 345}),
(p3:Part {part_num: 456}),
(p4:Part {part_num: 789}) $$) as (a agtype);
SELECT * FROM cypher('issue_1988', $$
MATCH (p) RETURN p $$) as (p agtype);

SELECT * from cypher('issue_1988', $$
MATCH (p1:Part {part_num: 123}), (p2:Part {part_num: 345})
CREATE (p1)-[u:used_by { quantity: 1 }]->(p2) RETURN p1, u, p2 $$) as (p1 agtype, u agtype, p2 agtype);

-- should fail
SELECT * FROM cypher('issue_1988', $$
MATCH (p:Part { part_num: 123 }) SET p.match = 'xyz' RETURN p $$) as (p agtype);

-- should succeed
SELECT * FROM cypher('issue_1988', $$
MATCH (p:Part { part_num: 123 }) SET p.`match` = 'xyz' RETURN p $$) as (p agtype);
SELECT * FROM cypher('issue_1988', $$
MATCH (p:Part { part_num: 123 }) SET p.`set` = 'xyz' RETURN p $$) as (p agtype);
SELECT * FROM cypher('issue_1988', $$
MATCH (p:Part { part_num: 123 }) SET p.`delete` = 'xyz' RETURN p $$) as (p agtype);
SELECT * FROM cypher('issue_1988', $$
MATCH (p:Part { part_num: 123 }) SET p.`merge` = 'xyz' RETURN p $$) as (p agtype);
SELECT * FROM cypher('issue_1988', $$
MATCH (p:Part { part_num: 123 }) SET p.`create` = 'xyz' RETURN p $$) as (p agtype);
-- should succeed
SELECT * FROM cypher('issue_1988', $$
MATCH (p:Part { part_num: 123 }) SET p.`match` = 'match' RETURN p $$) as (p agtype);
SELECT * FROM cypher('issue_1988', $$
MATCH (p:Part { part_num: 123 }) SET p.`set` = 'set' RETURN p $$) as (p agtype);
SELECT * FROM cypher('issue_1988', $$
MATCH (p:Part { part_num: 123 }) SET p.`delete` = 'delete' RETURN p $$) as (p agtype);
SELECT * FROM cypher('issue_1988', $$
MATCH (p:Part { part_num: 123 }) SET p.`merge` = 'merge' RETURN p $$) as (p agtype);
SELECT * FROM cypher('issue_1988', $$
MATCH (p:Part { part_num: 123 }) SET p.`create` = 'create' RETURN p $$) as (p agtype);

SELECT * FROM cypher('issue_1988', $$
MATCH (p) RETURN p $$) as (p agtype);

--
-- Cleanup
--
SELECT * FROM drop_graph('issue_1988', true);
SELECT * FROM drop_graph('issue_1953', true);
SELECT * FROM drop_graph('expanded_map', true);
SELECT * FROM drop_graph('issue_1124', true);
Expand Down
2 changes: 1 addition & 1 deletion src/backend/parser/ag_scanner.l
Original file line number Diff line number Diff line change
Expand Up @@ -628,7 +628,7 @@ ag_token token;
scan_errposition()));
}

token.type = AG_TOKEN_IDENTIFIER;
token.type = AG_TOKEN_BQIDENT;
token.value.s = strbuf_get_str(&yyextra.literal_buf);
token.location = get_location();
return token;
Expand Down
8 changes: 5 additions & 3 deletions src/backend/parser/cypher_gram.y
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,8 @@

%token <string> IDENTIFIER
%token <string> PARAMETER
%token <string> BQIDENT
%token <character> CHAR

/* operators that have more than 1 character */
%token NOT_EQ LT_EQ GT_EQ DOT_DOT TYPECAST PLUS_EQ EQ_TILDE CONCAT
Expand Down Expand Up @@ -656,7 +658,7 @@ subquery_stmt_no_return:
single_subquery:
subquery_part_init reading_clause_list return
{
$$ = list_concat($1, lappend($2, $3));
$$ = list_concat($1, lappend($2, $3));
}
;

Expand Down Expand Up @@ -3281,7 +3283,7 @@ static Node *verify_rule_as_list_comprehension(Node *expr, Node *expr2,
int where_loc, int mapping_loc)
{
Node *result = NULL;

/*
* If the first expression is a ColumnRef, then we can build a
* list_comprehension node.
Expand Down Expand Up @@ -3360,4 +3362,4 @@ static Node *build_list_comprehension_node(ColumnRef *cref, Node *expr,

/* return the UNWIND node */
return (Node *)unwind;
}
}
16 changes: 15 additions & 1 deletion src/backend/parser/cypher_parser.c
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,9 @@ int cypher_yylex(YYSTYPE *lvalp, YYLTYPE *llocp, ag_scanner_t scanner)
ACCESS_PATH,
ANY_EXISTS,
ALL_EXISTS,
CONCAT
CONCAT,
CHAR,
BQIDENT
};

ag_token token;
Expand Down Expand Up @@ -93,6 +95,18 @@ int cypher_yylex(YYSTYPE *lvalp, YYLTYPE *llocp, ag_scanner_t scanner)
lvalp->string = ident;
break;
}
case AG_TOKEN_BQIDENT:
{
char *ident;

/* these are identifiers, just back ticked */
token.type = AG_TOKEN_IDENTIFIER;

ident = pstrdup(token.value.s);
truncate_identifier(ident, strlen(ident), true);
lvalp->string = ident;
break;
}
case AG_TOKEN_PARAMETER:
lvalp->string = pstrdup(token.value.s);
break;
Expand Down
1 change: 1 addition & 0 deletions src/include/parser/ag_scanner.h
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ typedef enum ag_token_type
AG_TOKEN_ALL_EXISTS,
AG_TOKEN_CONCAT,
AG_TOKEN_CHAR,
AG_TOKEN_BQIDENT
} ag_token_type;

/*
Expand Down
Loading