Skip to content

Commit 0eb269c

Browse files
authored
Add support for chained expressions in CASE (#1431) (#1436)
Adds logic that implements CASE in chained expressions. Adds regression tests for CASE chained expression logic.
1 parent 56d0834 commit 0eb269c

File tree

3 files changed

+301
-0
lines changed

3 files changed

+301
-0
lines changed

Diff for: regress/expected/expr.out

+185
Original file line numberDiff line numberDiff line change
@@ -6520,6 +6520,191 @@ $$ ) AS (case_statement agtype);
65206520
{"id": 844424930131970, "label": "connected_to", "end_id": 281474976710660, "start_id": 281474976710659, "properties": {"k": 1, "id": 2}}::edge
65216521
(2 rows)
65226522

6523+
--CASE chained expressions
6524+
SELECT * FROM cypher('case_statement', $$
6525+
MATCH (n)
6526+
RETURN CASE
6527+
WHEN null THEN 'should not return me'
6528+
WHEN n.i = 1 = 1 THEN n
6529+
ELSE 'none'
6530+
END
6531+
$$ ) AS (case_statement agtype);
6532+
case_statement
6533+
-------------------------------------------------------------------------------
6534+
{"id": 281474976710657, "label": "", "properties": {"i": 1, "id": 1}}::vertex
6535+
"none"
6536+
"none"
6537+
"none"
6538+
"none"
6539+
"none"
6540+
(6 rows)
6541+
6542+
SELECT * FROM cypher('case_statement', $$
6543+
MATCH (n)
6544+
RETURN CASE
6545+
WHEN null THEN 'should not return me'
6546+
WHEN n.i = (1 = 1) THEN n
6547+
ELSE 'none'
6548+
END
6549+
$$ ) AS (case_statement agtype);
6550+
case_statement
6551+
----------------------------------------------------------------------------------------------
6552+
"none"
6553+
"none"
6554+
"none"
6555+
{"id": 281474976710660, "label": "", "properties": {"i": true, "j": false, "id": 4}}::vertex
6556+
"none"
6557+
"none"
6558+
(6 rows)
6559+
6560+
6561+
SELECT * FROM cypher('case_statement', $$
6562+
MATCH (n)
6563+
RETURN CASE n
6564+
WHEN null THEN 'should not return me'
6565+
WHEN n.i = 1 THEN n
6566+
ELSE 'none'
6567+
END
6568+
$$ ) AS (case_statement agtype);
6569+
case_statement
6570+
----------------
6571+
"none"
6572+
"none"
6573+
"none"
6574+
"none"
6575+
"none"
6576+
"none"
6577+
(6 rows)
6578+
6579+
SELECT * FROM cypher('case_statement', $$
6580+
MATCH (n)
6581+
RETURN CASE n = 1
6582+
WHEN null THEN 'should not return me'
6583+
WHEN n.i = 1 = 1 THEN n
6584+
ELSE 'none'
6585+
END
6586+
$$ ) AS (case_statement agtype);
6587+
case_statement
6588+
------------------------------------------------------------------------------------------------
6589+
"none"
6590+
{"id": 281474976710658, "label": "", "properties": {"i": "a", "j": "b", "id": 2}}::vertex
6591+
{"id": 281474976710659, "label": "", "properties": {"i": 0, "j": 1, "id": 3}}::vertex
6592+
{"id": 281474976710660, "label": "", "properties": {"i": true, "j": false, "id": 4}}::vertex
6593+
{"id": 281474976710661, "label": "", "properties": {"i": [], "j": [0, 1, 2], "id": 5}}::vertex
6594+
{"id": 281474976710662, "label": "", "properties": {"i": {}, "j": {"i": 1}, "id": 6}}::vertex
6595+
(6 rows)
6596+
6597+
SELECT * FROM cypher('case_statement', $$
6598+
MATCH (n)
6599+
RETURN CASE n = 1
6600+
WHEN null THEN 'should not return me'
6601+
WHEN n.i = (1 = 1) THEN n
6602+
ELSE 'none'
6603+
END
6604+
$$ ) AS (case_statement agtype);
6605+
case_statement
6606+
------------------------------------------------------------------------------------------------
6607+
{"id": 281474976710657, "label": "", "properties": {"i": 1, "id": 1}}::vertex
6608+
{"id": 281474976710658, "label": "", "properties": {"i": "a", "j": "b", "id": 2}}::vertex
6609+
{"id": 281474976710659, "label": "", "properties": {"i": 0, "j": 1, "id": 3}}::vertex
6610+
"none"
6611+
{"id": 281474976710661, "label": "", "properties": {"i": [], "j": [0, 1, 2], "id": 5}}::vertex
6612+
{"id": 281474976710662, "label": "", "properties": {"i": {}, "j": {"i": 1}, "id": 6}}::vertex
6613+
(6 rows)
6614+
6615+
--should return n
6616+
SELECT * FROM cypher('case_statement', $$
6617+
MATCH (n)
6618+
RETURN CASE n = 1
6619+
WHEN null THEN 'should not return me'
6620+
WHEN n = 1 = 1 THEN n
6621+
ELSE 'none'
6622+
END
6623+
$$ ) AS (case_statement agtype);
6624+
case_statement
6625+
------------------------------------------------------------------------------------------------
6626+
{"id": 281474976710657, "label": "", "properties": {"i": 1, "id": 1}}::vertex
6627+
{"id": 281474976710658, "label": "", "properties": {"i": "a", "j": "b", "id": 2}}::vertex
6628+
{"id": 281474976710659, "label": "", "properties": {"i": 0, "j": 1, "id": 3}}::vertex
6629+
{"id": 281474976710660, "label": "", "properties": {"i": true, "j": false, "id": 4}}::vertex
6630+
{"id": 281474976710661, "label": "", "properties": {"i": [], "j": [0, 1, 2], "id": 5}}::vertex
6631+
{"id": 281474976710662, "label": "", "properties": {"i": {}, "j": {"i": 1}, "id": 6}}::vertex
6632+
(6 rows)
6633+
6634+
--chained expression in THEN
6635+
SELECT * FROM cypher('case_statement', $$
6636+
MATCH (n)
6637+
RETURN CASE
6638+
WHEN null THEN 'should not return me'
6639+
WHEN n.i = 1 THEN n.i = 1 = 1
6640+
ELSE 'none'
6641+
END
6642+
$$ ) AS (case_statement agtype);
6643+
case_statement
6644+
----------------
6645+
true
6646+
"none"
6647+
"none"
6648+
"none"
6649+
"none"
6650+
"none"
6651+
(6 rows)
6652+
6653+
--order of operations in then
6654+
SELECT * FROM cypher('case_statement', $$
6655+
MATCH (n)
6656+
RETURN CASE n
6657+
WHEN null THEN 'should not return me'
6658+
WHEN n THEN (n.i = 1) = 1
6659+
ELSE 'none'
6660+
END
6661+
$$ ) AS (case_statement agtype);
6662+
case_statement
6663+
----------------
6664+
false
6665+
false
6666+
false
6667+
false
6668+
false
6669+
false
6670+
(6 rows)
6671+
6672+
SELECT * FROM cypher('case_statement', $$
6673+
MATCH (n)
6674+
RETURN CASE n
6675+
WHEN null THEN 'should not return me'
6676+
WHEN n THEN n.i = (1 = 1)
6677+
ELSE 'none'
6678+
END
6679+
$$ ) AS (case_statement agtype);
6680+
case_statement
6681+
----------------
6682+
false
6683+
false
6684+
false
6685+
true
6686+
false
6687+
false
6688+
(6 rows)
6689+
6690+
SELECT * FROM cypher('case_statement', $$
6691+
MATCH (n)
6692+
RETURN CASE n
6693+
WHEN null THEN 'should not return me'
6694+
WHEN n THEN n.i = (1 = 0)
6695+
ELSE 'none'
6696+
END
6697+
$$ ) AS (case_statement agtype);
6698+
case_statement
6699+
----------------
6700+
false
6701+
false
6702+
false
6703+
false
6704+
false
6705+
false
6706+
(6 rows)
6707+
65236708
--CASE with count()
65246709
--count(*)
65256710
SELECT * FROM cypher('case_statement', $$

Diff for: regress/sql/expr.sql

+95
Original file line numberDiff line numberDiff line change
@@ -2700,6 +2700,101 @@ SELECT * FROM cypher('case_statement', $$
27002700
END
27012701
$$ ) AS (case_statement agtype);
27022702

2703+
--CASE chained expressions
2704+
2705+
SELECT * FROM cypher('case_statement', $$
2706+
MATCH (n)
2707+
RETURN CASE
2708+
WHEN null THEN 'should not return me'
2709+
WHEN n.i = 1 = 1 THEN n
2710+
ELSE 'none'
2711+
END
2712+
$$ ) AS (case_statement agtype);
2713+
2714+
SELECT * FROM cypher('case_statement', $$
2715+
MATCH (n)
2716+
RETURN CASE
2717+
WHEN null THEN 'should not return me'
2718+
WHEN n.i = (1 = 1) THEN n
2719+
ELSE 'none'
2720+
END
2721+
$$ ) AS (case_statement agtype);
2722+
2723+
SELECT * FROM cypher('case_statement', $$
2724+
MATCH (n)
2725+
RETURN CASE n
2726+
WHEN null THEN 'should not return me'
2727+
WHEN n.i = 1 THEN n
2728+
ELSE 'none'
2729+
END
2730+
$$ ) AS (case_statement agtype);
2731+
2732+
SELECT * FROM cypher('case_statement', $$
2733+
MATCH (n)
2734+
RETURN CASE n = 1
2735+
WHEN null THEN 'should not return me'
2736+
WHEN n.i = 1 = 1 THEN n
2737+
ELSE 'none'
2738+
END
2739+
$$ ) AS (case_statement agtype);
2740+
2741+
SELECT * FROM cypher('case_statement', $$
2742+
MATCH (n)
2743+
RETURN CASE n = 1
2744+
WHEN null THEN 'should not return me'
2745+
WHEN n.i = (1 = 1) THEN n
2746+
ELSE 'none'
2747+
END
2748+
$$ ) AS (case_statement agtype);
2749+
2750+
--should return n
2751+
SELECT * FROM cypher('case_statement', $$
2752+
MATCH (n)
2753+
RETURN CASE n = 1
2754+
WHEN null THEN 'should not return me'
2755+
WHEN n = 1 = 1 THEN n
2756+
ELSE 'none'
2757+
END
2758+
$$ ) AS (case_statement agtype);
2759+
2760+
--chained expression in THEN
2761+
SELECT * FROM cypher('case_statement', $$
2762+
MATCH (n)
2763+
RETURN CASE
2764+
WHEN null THEN 'should not return me'
2765+
WHEN n.i = 1 THEN n.i = 1 = 1
2766+
ELSE 'none'
2767+
END
2768+
$$ ) AS (case_statement agtype);
2769+
2770+
--order of operations in then
2771+
SELECT * FROM cypher('case_statement', $$
2772+
MATCH (n)
2773+
RETURN CASE n
2774+
WHEN null THEN 'should not return me'
2775+
WHEN n THEN (n.i = 1) = 1
2776+
ELSE 'none'
2777+
END
2778+
$$ ) AS (case_statement agtype);
2779+
2780+
SELECT * FROM cypher('case_statement', $$
2781+
MATCH (n)
2782+
RETURN CASE n
2783+
WHEN null THEN 'should not return me'
2784+
WHEN n THEN n.i = (1 = 1)
2785+
ELSE 'none'
2786+
END
2787+
$$ ) AS (case_statement agtype);
2788+
2789+
SELECT * FROM cypher('case_statement', $$
2790+
MATCH (n)
2791+
RETURN CASE n
2792+
WHEN null THEN 'should not return me'
2793+
WHEN n THEN n.i = (1 = 0)
2794+
ELSE 'none'
2795+
END
2796+
$$ ) AS (case_statement agtype);
2797+
27032798
--CASE with count()
27042799

27052800
--count(*)

Diff for: src/backend/parser/cypher_expr.c

+21
Original file line numberDiff line numberDiff line change
@@ -1356,6 +1356,16 @@ static Node *transform_CaseExpr(cypher_parsestate *cpstate, CaseExpr
13561356
warg = (Node *) w->expr;
13571357
if (placeholder)
13581358
{
1359+
if(is_ag_node(warg, cypher_comparison_aexpr) ||
1360+
is_ag_node(warg, cypher_comparison_boolexpr) )
1361+
{
1362+
List *funcname = list_make1(makeString("ag_catalog"));
1363+
funcname = lappend(funcname, makeString("bool_to_agtype"));
1364+
1365+
warg = (Node *) makeFuncCall(funcname, list_make1(warg),
1366+
cexpr->location);
1367+
}
1368+
13591369
/* shorthand form was specified, so expand... */
13601370
warg = (Node *) makeSimpleA_Expr(AEXPR_OP, "=",
13611371
(Node *) placeholder,
@@ -1369,6 +1379,17 @@ static Node *transform_CaseExpr(cypher_parsestate *cpstate, CaseExpr
13691379
"CASE/WHEN");
13701380

13711381
warg = (Node *) w->result;
1382+
1383+
if(is_ag_node(warg, cypher_comparison_aexpr) ||
1384+
is_ag_node(warg, cypher_comparison_boolexpr) )
1385+
{
1386+
List *funcname = list_make1(makeString("ag_catalog"));
1387+
funcname = lappend(funcname, makeString("bool_to_agtype"));
1388+
1389+
warg = (Node *) makeFuncCall(funcname, list_make1(warg),
1390+
cexpr->location);
1391+
}
1392+
13721393
neww->result = (Expr *) transform_cypher_expr_recurse(cpstate, warg);
13731394
neww->location = w->location;
13741395

0 commit comments

Comments
 (0)