Skip to content

Commit 4832a01

Browse files
committed
Add support for chained expressions in CASE (apache#1431)
Adds logic that implements CASE in chained expressions. Adds regression tests for CASE chained expression logic.
1 parent 88bd5a8 commit 4832a01

File tree

3 files changed

+301
-0
lines changed

3 files changed

+301
-0
lines changed

regress/expected/expr.out

Lines changed: 185 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6519,6 +6519,191 @@ $$ ) AS (case_statement agtype);
65196519
{"id": 844424930131970, "label": "connected_to", "end_id": 281474976710660, "start_id": 281474976710659, "properties": {"k": 1, "id": 2}}::edge
65206520
(2 rows)
65216521

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

regress/sql/expr.sql

Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2698,6 +2698,101 @@ SELECT * FROM cypher('case_statement', $$
26982698
END
26992699
$$ ) AS (case_statement agtype);
27002700

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

27032798
--count(*)

src/backend/parser/cypher_expr.c

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1355,6 +1355,16 @@ static Node *transform_CaseExpr(cypher_parsestate *cpstate, CaseExpr
13551355
warg = (Node *) w->expr;
13561356
if (placeholder)
13571357
{
1358+
if(is_ag_node(warg, cypher_comparison_aexpr) ||
1359+
is_ag_node(warg, cypher_comparison_boolexpr) )
1360+
{
1361+
List *funcname = list_make1(makeString("ag_catalog"));
1362+
funcname = lappend(funcname, makeString("bool_to_agtype"));
1363+
1364+
warg = (Node *) makeFuncCall(funcname, list_make1(warg),
1365+
cexpr->location);
1366+
}
1367+
13581368
/* shorthand form was specified, so expand... */
13591369
warg = (Node *) makeSimpleA_Expr(AEXPR_OP, "=",
13601370
(Node *) placeholder,
@@ -1368,6 +1378,17 @@ static Node *transform_CaseExpr(cypher_parsestate *cpstate, CaseExpr
13681378
"CASE/WHEN");
13691379

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

0 commit comments

Comments
 (0)