Skip to content
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
90 changes: 78 additions & 12 deletions regress/expected/expr.out
Original file line number Diff line number Diff line change
Expand Up @@ -6514,8 +6514,8 @@ SELECT * FROM cypher('case_statement', $$
WHEN 1 THEN count(*)
ELSE 'not count'
END
$$ ) AS (j agtype, case_statement agtype);
j | case_statement
$$ ) AS (n agtype, case_statement agtype);
n | case_statement
------------------------------------------------------------------------------------------------+----------------
{"id": 281474976710658, "label": "", "properties": {"i": "a", "j": "b", "id": 2}}::vertex | "not count"
{"id": 281474976710661, "label": "", "properties": {"i": [], "j": [0, 1, 2], "id": 5}}::vertex | "not count"
Expand All @@ -6532,8 +6532,8 @@ SELECT * FROM cypher('case_statement', $$
WHEN 1 THEN count(*)
ELSE 'not count'
END
$$ ) AS (j agtype, case_statement agtype);
j | case_statement
$$ ) AS (n agtype, case_statement agtype);
n | case_statement
------------------------------------------------------------------------------------------------+----------------
{"id": 281474976710658, "label": "", "properties": {"i": "a", "j": "b", "id": 2}}::vertex | "not count"
{"id": 281474976710661, "label": "", "properties": {"i": [], "j": [0, 1, 2], "id": 5}}::vertex | "not count"
Expand All @@ -6550,8 +6550,8 @@ SELECT * FROM cypher('case_statement', $$
WHEN 1 THEN count(n)
ELSE 'not count'
END
$$ ) AS (j agtype, case_statement agtype);
j | case_statement
$$ ) AS (n agtype, case_statement agtype);
n | case_statement
------------------------------------------------------------------------------------------------+----------------
{"id": 281474976710658, "label": "", "properties": {"i": "a", "j": "b", "id": 2}}::vertex | "not count"
{"id": 281474976710661, "label": "", "properties": {"i": [], "j": [0, 1, 2], "id": 5}}::vertex | "not count"
Expand All @@ -6568,8 +6568,8 @@ SELECT * FROM cypher('case_statement', $$
WHEN 1 THEN count(n)
ELSE 'not count'
END
$$ ) AS (j agtype, case_statement agtype);
j | case_statement
$$ ) AS (n agtype, case_statement agtype);
n | case_statement
------------------------------------------------------------------------------------------------+----------------
{"id": 281474976710658, "label": "", "properties": {"i": "a", "j": "b", "id": 2}}::vertex | "not count"
{"id": 281474976710661, "label": "", "properties": {"i": [], "j": [0, 1, 2], "id": 5}}::vertex | "not count"
Expand All @@ -6586,8 +6586,8 @@ SELECT * FROM cypher('case_statement', $$
WHEN 1 THEN count(1)
ELSE 'not count'
END
$$ ) AS (j agtype, case_statement agtype);
j | case_statement
$$ ) AS (n agtype, case_statement agtype);
n | case_statement
------------------------------------------------------------------------------------------------+----------------
{"id": 281474976710658, "label": "", "properties": {"i": "a", "j": "b", "id": 2}}::vertex | "not count"
{"id": 281474976710661, "label": "", "properties": {"i": [], "j": [0, 1, 2], "id": 5}}::vertex | "not count"
Expand All @@ -6604,8 +6604,8 @@ SELECT * FROM cypher('case_statement', $$
WHEN 1 THEN count(1)
ELSE 'not count'
END
$$ ) AS (j agtype, case_statement agtype);
j | case_statement
$$ ) AS (n agtype, case_statement agtype);
n | case_statement
------------------------------------------------------------------------------------------------+----------------
{"id": 281474976710658, "label": "", "properties": {"i": "a", "j": "b", "id": 2}}::vertex | "not count"
{"id": 281474976710661, "label": "", "properties": {"i": [], "j": [0, 1, 2], "id": 5}}::vertex | "not count"
Expand All @@ -6615,6 +6615,72 @@ $$ ) AS (j agtype, case_statement agtype);
{"id": 281474976710662, "label": "", "properties": {"i": {}, "j": {"i": 1}, "id": 6}}::vertex | "not count"
(6 rows)

--CASE with EXISTS()
--exists(n.property)
SELECT * FROM cypher('case_statement', $$
MATCH (n)
RETURN n, CASE exists(n.j)
WHEN true THEN 'property j exists'
ELSE 'property j does not exist'
END
$$ ) AS (n agtype, case_statement agtype);
n | case_statement
------------------------------------------------------------------------------------------------+-----------------------------
{"id": 281474976710657, "label": "", "properties": {"i": 1, "id": 1}}::vertex | "property j does not exist"
{"id": 281474976710658, "label": "", "properties": {"i": "a", "j": "b", "id": 2}}::vertex | "property j exists"
{"id": 281474976710659, "label": "", "properties": {"i": 0, "j": 1, "id": 3}}::vertex | "property j exists"
{"id": 281474976710660, "label": "", "properties": {"i": true, "j": false, "id": 4}}::vertex | "property j exists"
{"id": 281474976710661, "label": "", "properties": {"i": [], "j": [0, 1, 2], "id": 5}}::vertex | "property j exists"
{"id": 281474976710662, "label": "", "properties": {"i": {}, "j": {"i": 1}, "id": 6}}::vertex | "property j exists"
(6 rows)

--CASE evaluates to boolean true, is not a boolean, should hit ELSE
SELECT * FROM cypher('case_statement', $$
MATCH (n)
RETURN n, CASE exists(n.j)
WHEN 1 THEN 'should not output me'
ELSE '1 is not a boolean'
END
$$ ) AS (n agtype, case_statement agtype);
n | case_statement
------------------------------------------------------------------------------------------------+----------------------
{"id": 281474976710657, "label": "", "properties": {"i": 1, "id": 1}}::vertex | "1 is not a boolean"
{"id": 281474976710658, "label": "", "properties": {"i": "a", "j": "b", "id": 2}}::vertex | "1 is not a boolean"
{"id": 281474976710659, "label": "", "properties": {"i": 0, "j": 1, "id": 3}}::vertex | "1 is not a boolean"
{"id": 281474976710660, "label": "", "properties": {"i": true, "j": false, "id": 4}}::vertex | "1 is not a boolean"
{"id": 281474976710661, "label": "", "properties": {"i": [], "j": [0, 1, 2], "id": 5}}::vertex | "1 is not a boolean"
{"id": 281474976710662, "label": "", "properties": {"i": {}, "j": {"i": 1}, "id": 6}}::vertex | "1 is not a boolean"
(6 rows)

--exists in WHEN, vacuously false because exists(n.j) evaluates to a boolean, n is a vertex
SELECT * FROM cypher('case_statement', $$
MATCH (n)
RETURN n, CASE n
WHEN exists(n.j) THEN 'should not output me'
ELSE 'n is a vertex, not a boolean'
END
$$ ) AS (j agtype, case_statement agtype);
j | case_statement
------------------------------------------------------------------------------------------------+--------------------------------
{"id": 281474976710657, "label": "", "properties": {"i": 1, "id": 1}}::vertex | "n is a vertex, not a boolean"
{"id": 281474976710658, "label": "", "properties": {"i": "a", "j": "b", "id": 2}}::vertex | "n is a vertex, not a boolean"
{"id": 281474976710659, "label": "", "properties": {"i": 0, "j": 1, "id": 3}}::vertex | "n is a vertex, not a boolean"
{"id": 281474976710660, "label": "", "properties": {"i": true, "j": false, "id": 4}}::vertex | "n is a vertex, not a boolean"
{"id": 281474976710661, "label": "", "properties": {"i": [], "j": [0, 1, 2], "id": 5}}::vertex | "n is a vertex, not a boolean"
{"id": 281474976710662, "label": "", "properties": {"i": {}, "j": {"i": 1}, "id": 6}}::vertex | "n is a vertex, not a boolean"
(6 rows)

--exists(*) (should fail)
SELECT * FROM cypher('case_statement', $$
MATCH (n)
RETURN n, CASE n.j
WHEN 1 THEN exists(*)
ELSE 'not count'
END
$$ ) AS (j agtype, case_statement agtype);
ERROR: syntax error at or near "*"
LINE 4: WHEN 1 THEN exists(*)
^
-- RETURN * and (u)--(v) optional forms
SELECT create_graph('opt_forms');
NOTICE: graph "opt_forms" has been created
Expand Down
50 changes: 45 additions & 5 deletions regress/sql/expr.sql
Original file line number Diff line number Diff line change
Expand Up @@ -2726,7 +2726,7 @@ SELECT * FROM cypher('case_statement', $$
WHEN 1 THEN count(*)
ELSE 'not count'
END
$$ ) AS (j agtype, case_statement agtype);
$$ ) AS (n agtype, case_statement agtype);

--concatenated
SELECT * FROM cypher('case_statement', $$
Expand All @@ -2735,7 +2735,7 @@ SELECT * FROM cypher('case_statement', $$
WHEN 1 THEN count(*)
ELSE 'not count'
END
$$ ) AS (j agtype, case_statement agtype);
$$ ) AS (n agtype, case_statement agtype);

--count(n)
SELECT * FROM cypher('case_statement', $$
Expand All @@ -2744,7 +2744,7 @@ SELECT * FROM cypher('case_statement', $$
WHEN 1 THEN count(n)
ELSE 'not count'
END
$$ ) AS (j agtype, case_statement agtype);
$$ ) AS (n agtype, case_statement agtype);

--concatenated
SELECT * FROM cypher('case_statement', $$
Expand All @@ -2753,7 +2753,7 @@ SELECT * FROM cypher('case_statement', $$
WHEN 1 THEN count(n)
ELSE 'not count'
END
$$ ) AS (j agtype, case_statement agtype);
$$ ) AS (n agtype, case_statement agtype);

--count(1)
SELECT * FROM cypher('case_statement', $$
Expand All @@ -2762,7 +2762,7 @@ SELECT * FROM cypher('case_statement', $$
WHEN 1 THEN count(1)
ELSE 'not count'
END
$$ ) AS (j agtype, case_statement agtype);
$$ ) AS (n agtype, case_statement agtype);

--concatenated
SELECT * FROM cypher('case_statement', $$
Expand All @@ -2771,8 +2771,48 @@ SELECT * FROM cypher('case_statement', $$
WHEN 1 THEN count(1)
ELSE 'not count'
END
$$ ) AS (n agtype, case_statement agtype);

--CASE with EXISTS()

--exists(n.property)
SELECT * FROM cypher('case_statement', $$
MATCH (n)
RETURN n, CASE exists(n.j)
WHEN true THEN 'property j exists'
ELSE 'property j does not exist'
END
$$ ) AS (n agtype, case_statement agtype);

--CASE evaluates to boolean true, is not a boolean, should hit ELSE
SELECT * FROM cypher('case_statement', $$
MATCH (n)
RETURN n, CASE exists(n.j)
WHEN 1 THEN 'should not output me'
ELSE '1 is not a boolean'
END
$$ ) AS (n agtype, case_statement agtype);

--exists in WHEN, vacuously false because exists(n.j) evaluates to a boolean, n is a vertex
SELECT * FROM cypher('case_statement', $$
MATCH (n)
RETURN n, CASE n
WHEN exists(n.j) THEN 'should not output me'
ELSE 'n is a vertex, not a boolean'
END
$$ ) AS (j agtype, case_statement agtype);

--exists(*) (should fail)
SELECT * FROM cypher('case_statement', $$
MATCH (n)
RETURN n, CASE n.j
WHEN 1 THEN exists(*)
ELSE 'not count'
END
$$ ) AS (j agtype, case_statement agtype);




-- RETURN * and (u)--(v) optional forms
SELECT create_graph('opt_forms');
Expand Down
20 changes: 12 additions & 8 deletions src/backend/parser/cypher_gram.y
Original file line number Diff line number Diff line change
Expand Up @@ -227,7 +227,7 @@ static Node *make_typecast_expr(Node *expr, char *typecast, int location);
static Node *make_function_expr(List *func_name, List *exprs, int location);
static Node *make_star_function_expr(List *func_name, List *exprs, int location);
static Node *make_distinct_function_expr(List *func_name, List *exprs, int location);
static FuncCall *wrap_pg_funccall_to_agtype(Node* fnode, char *type, int location);
static FuncCall *node_to_agtype(Node* fnode, char *type, int location);

// setops
static Node *make_set_op(SetOperation op, bool all_or_distinct, List *larg,
Expand Down Expand Up @@ -1742,12 +1742,16 @@ expr_func_subexpr:
n->operName = NIL;
n->subselect = (Node *) sub;
n->location = @1;
$$ = (Node *) n;
$$ = (Node *)node_to_agtype((Node *)n, "boolean", @1);
}
| EXISTS '(' property_value ')'
{
$$ = make_function_expr(list_make1(makeString("exists")),
list_make1($3), @2);
FuncCall *n;
n = makeFuncCall(list_make1(makeString("exists")),
list_make1($3), COERCE_SQL_SYNTAX, @2);

$$ = (Node *)node_to_agtype((Node *)n, "boolean", @2);

}
;

Expand Down Expand Up @@ -2289,7 +2293,7 @@ static Node *make_function_expr(List *func_name, List *exprs, int location)
fnode = makeFuncCall(funcname, exprs, COERCE_SQL_SYNTAX, location);

/* build the cast to wrap the function call to return agtype. */
fnode = wrap_pg_funccall_to_agtype((Node *)fnode, "integer", location);
fnode = node_to_agtype((Node *)fnode, "integer", location);

return (Node *)fnode;
}
Expand Down Expand Up @@ -2345,7 +2349,7 @@ static Node *make_star_function_expr(List *func_name, List *exprs, int location)
fnode->agg_star = true;

/* build the cast to wrap the function call to return agtype. */
fnode = wrap_pg_funccall_to_agtype((Node *)fnode, "integer", location);
fnode = node_to_agtype((Node *)fnode, "integer", location);

return (Node *)fnode;
}
Expand Down Expand Up @@ -2403,7 +2407,7 @@ static Node *make_distinct_function_expr(List *func_name, List *exprs, int locat
fnode->agg_distinct = true;

/* build the cast to wrap the function call to return agtype. */
fnode = wrap_pg_funccall_to_agtype((Node *)fnode, "integer", location);
fnode = node_to_agtype((Node *)fnode, "integer", location);
return (Node *)fnode;
}
else
Expand Down Expand Up @@ -2434,7 +2438,7 @@ static Node *make_distinct_function_expr(List *func_name, List *exprs, int locat
* helper function to wrap pg_function in the appropiate typecast function to
* interface with AGE components
*/
static FuncCall *wrap_pg_funccall_to_agtype(Node * fnode, char *type, int location)
static FuncCall *node_to_agtype(Node * fnode, char *type, int location)
{
List *funcname = list_make1(makeString("ag_catalog"));

Expand Down