Skip to content

Commit 2cb310d

Browse files
committed
Add support for chained expressions in CASE
Adds logic that implements CASE in chained expressions. Adds regression tests for CASE chained expression logic.
1 parent b2d616d commit 2cb310d

File tree

3 files changed

+303
-0
lines changed

3 files changed

+303
-0
lines changed

regress/expected/expr.out

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

6638+
--CASE chained expressions
6639+
SELECT * FROM cypher('case_statement', $$
6640+
MATCH (n)
6641+
RETURN CASE
6642+
WHEN null THEN 'should not return me'
6643+
WHEN n.i = 1 = 1 THEN n
6644+
ELSE 'none'
6645+
END
6646+
$$ ) AS (case_statement agtype);
6647+
case_statement
6648+
-------------------------------------------------------------------------------
6649+
{"id": 281474976710657, "label": "", "properties": {"i": 1, "id": 1}}::vertex
6650+
"none"
6651+
"none"
6652+
"none"
6653+
"none"
6654+
"none"
6655+
(6 rows)
6656+
6657+
SELECT * FROM cypher('case_statement', $$
6658+
MATCH (n)
6659+
RETURN CASE
6660+
WHEN null THEN 'should not return me'
6661+
WHEN n.i = (1 = 1) THEN n
6662+
ELSE 'none'
6663+
END
6664+
$$ ) AS (case_statement agtype);
6665+
case_statement
6666+
----------------------------------------------------------------------------------------------
6667+
"none"
6668+
"none"
6669+
"none"
6670+
{"id": 281474976710660, "label": "", "properties": {"i": true, "j": false, "id": 4}}::vertex
6671+
"none"
6672+
"none"
6673+
(6 rows)
6674+
6675+
6676+
SELECT * FROM cypher('case_statement', $$
6677+
MATCH (n)
6678+
RETURN CASE n
6679+
WHEN null THEN 'should not return me'
6680+
WHEN n.i = 1 THEN n
6681+
ELSE 'none'
6682+
END
6683+
$$ ) AS (case_statement agtype);
6684+
case_statement
6685+
----------------
6686+
"none"
6687+
"none"
6688+
"none"
6689+
"none"
6690+
"none"
6691+
"none"
6692+
(6 rows)
6693+
6694+
SELECT * FROM cypher('case_statement', $$
6695+
MATCH (n)
6696+
RETURN CASE n = 1
6697+
WHEN null THEN 'should not return me'
6698+
WHEN n.i = 1 = 1 THEN n
6699+
ELSE 'none'
6700+
END
6701+
$$ ) AS (case_statement agtype);
6702+
case_statement
6703+
------------------------------------------------------------------------------------------------
6704+
"none"
6705+
{"id": 281474976710658, "label": "", "properties": {"i": "a", "j": "b", "id": 2}}::vertex
6706+
{"id": 281474976710659, "label": "", "properties": {"i": 0, "j": 1, "id": 3}}::vertex
6707+
{"id": 281474976710660, "label": "", "properties": {"i": true, "j": false, "id": 4}}::vertex
6708+
{"id": 281474976710661, "label": "", "properties": {"i": [], "j": [0, 1, 2], "id": 5}}::vertex
6709+
{"id": 281474976710662, "label": "", "properties": {"i": {}, "j": {"i": 1}, "id": 6}}::vertex
6710+
(6 rows)
6711+
6712+
SELECT * FROM cypher('case_statement', $$
6713+
MATCH (n)
6714+
RETURN CASE n = 1
6715+
WHEN null THEN 'should not return me'
6716+
WHEN n.i = (1 = 1) THEN n
6717+
ELSE 'none'
6718+
END
6719+
$$ ) AS (case_statement agtype);
6720+
case_statement
6721+
------------------------------------------------------------------------------------------------
6722+
{"id": 281474976710657, "label": "", "properties": {"i": 1, "id": 1}}::vertex
6723+
{"id": 281474976710658, "label": "", "properties": {"i": "a", "j": "b", "id": 2}}::vertex
6724+
{"id": 281474976710659, "label": "", "properties": {"i": 0, "j": 1, "id": 3}}::vertex
6725+
"none"
6726+
{"id": 281474976710661, "label": "", "properties": {"i": [], "j": [0, 1, 2], "id": 5}}::vertex
6727+
{"id": 281474976710662, "label": "", "properties": {"i": {}, "j": {"i": 1}, "id": 6}}::vertex
6728+
(6 rows)
6729+
6730+
--should return n
6731+
SELECT * FROM cypher('case_statement', $$
6732+
MATCH (n)
6733+
RETURN CASE n = 1
6734+
WHEN null THEN 'should not return me'
6735+
WHEN n = 1 = 1 THEN n
6736+
ELSE 'none'
6737+
END
6738+
$$ ) AS (case_statement agtype);
6739+
case_statement
6740+
------------------------------------------------------------------------------------------------
6741+
{"id": 281474976710657, "label": "", "properties": {"i": 1, "id": 1}}::vertex
6742+
{"id": 281474976710658, "label": "", "properties": {"i": "a", "j": "b", "id": 2}}::vertex
6743+
{"id": 281474976710659, "label": "", "properties": {"i": 0, "j": 1, "id": 3}}::vertex
6744+
{"id": 281474976710660, "label": "", "properties": {"i": true, "j": false, "id": 4}}::vertex
6745+
{"id": 281474976710661, "label": "", "properties": {"i": [], "j": [0, 1, 2], "id": 5}}::vertex
6746+
{"id": 281474976710662, "label": "", "properties": {"i": {}, "j": {"i": 1}, "id": 6}}::vertex
6747+
(6 rows)
6748+
6749+
--chained expression in THEN
6750+
SELECT * FROM cypher('case_statement', $$
6751+
MATCH (n)
6752+
RETURN CASE
6753+
WHEN null THEN 'should not return me'
6754+
WHEN n.i = 1 THEN n.i = 1 = 1
6755+
ELSE 'none'
6756+
END
6757+
$$ ) AS (case_statement agtype);
6758+
case_statement
6759+
----------------
6760+
true
6761+
"none"
6762+
"none"
6763+
"none"
6764+
"none"
6765+
"none"
6766+
(6 rows)
6767+
6768+
--order of operations in then
6769+
SELECT * FROM cypher('case_statement', $$
6770+
MATCH (n)
6771+
RETURN CASE n
6772+
WHEN null THEN 'should not return me'
6773+
WHEN n THEN (n.i = 1) = 1
6774+
ELSE 'none'
6775+
END
6776+
$$ ) AS (case_statement agtype);
6777+
case_statement
6778+
----------------
6779+
false
6780+
false
6781+
false
6782+
false
6783+
false
6784+
false
6785+
(6 rows)
6786+
6787+
SELECT * FROM cypher('case_statement', $$
6788+
MATCH (n)
6789+
RETURN CASE n
6790+
WHEN null THEN 'should not return me'
6791+
WHEN n THEN n.i = (1 = 1)
6792+
ELSE 'none'
6793+
END
6794+
$$ ) AS (case_statement agtype);
6795+
case_statement
6796+
----------------
6797+
false
6798+
false
6799+
false
6800+
true
6801+
false
6802+
false
6803+
(6 rows)
6804+
6805+
SELECT * FROM cypher('case_statement', $$
6806+
MATCH (n)
6807+
RETURN CASE n
6808+
WHEN null THEN 'should not return me'
6809+
WHEN n THEN n.i = (1 = 0)
6810+
ELSE 'none'
6811+
END
6812+
$$ ) AS (case_statement agtype);
6813+
case_statement
6814+
----------------
6815+
false
6816+
false
6817+
false
6818+
false
6819+
false
6820+
false
6821+
(6 rows)
6822+
66386823
--CASE with count()
66396824
--count(*)
66406825
SELECT * FROM cypher('case_statement', $$

regress/sql/expr.sql

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

2745+
--CASE chained expressions
2746+
2747+
SELECT * FROM cypher('case_statement', $$
2748+
MATCH (n)
2749+
RETURN CASE
2750+
WHEN null THEN 'should not return me'
2751+
WHEN n.i = 1 = 1 THEN n
2752+
ELSE 'none'
2753+
END
2754+
$$ ) AS (case_statement agtype);
2755+
2756+
SELECT * FROM cypher('case_statement', $$
2757+
MATCH (n)
2758+
RETURN CASE
2759+
WHEN null THEN 'should not return me'
2760+
WHEN n.i = (1 = 1) THEN n
2761+
ELSE 'none'
2762+
END
2763+
$$ ) AS (case_statement agtype);
2764+
2765+
SELECT * FROM cypher('case_statement', $$
2766+
MATCH (n)
2767+
RETURN CASE n
2768+
WHEN null THEN 'should not return me'
2769+
WHEN n.i = 1 THEN n
2770+
ELSE 'none'
2771+
END
2772+
$$ ) AS (case_statement agtype);
2773+
2774+
SELECT * FROM cypher('case_statement', $$
2775+
MATCH (n)
2776+
RETURN CASE n = 1
2777+
WHEN null THEN 'should not return me'
2778+
WHEN n.i = 1 = 1 THEN n
2779+
ELSE 'none'
2780+
END
2781+
$$ ) AS (case_statement agtype);
2782+
2783+
SELECT * FROM cypher('case_statement', $$
2784+
MATCH (n)
2785+
RETURN CASE n = 1
2786+
WHEN null THEN 'should not return me'
2787+
WHEN n.i = (1 = 1) THEN n
2788+
ELSE 'none'
2789+
END
2790+
$$ ) AS (case_statement agtype);
2791+
2792+
--should return n
2793+
SELECT * FROM cypher('case_statement', $$
2794+
MATCH (n)
2795+
RETURN CASE n = 1
2796+
WHEN null THEN 'should not return me'
2797+
WHEN n = 1 = 1 THEN n
2798+
ELSE 'none'
2799+
END
2800+
$$ ) AS (case_statement agtype);
2801+
2802+
--chained expression in THEN
2803+
SELECT * FROM cypher('case_statement', $$
2804+
MATCH (n)
2805+
RETURN CASE
2806+
WHEN null THEN 'should not return me'
2807+
WHEN n.i = 1 THEN n.i = 1 = 1
2808+
ELSE 'none'
2809+
END
2810+
$$ ) AS (case_statement agtype);
2811+
2812+
--order of operations in then
2813+
SELECT * FROM cypher('case_statement', $$
2814+
MATCH (n)
2815+
RETURN CASE n
2816+
WHEN null THEN 'should not return me'
2817+
WHEN n THEN (n.i = 1) = 1
2818+
ELSE 'none'
2819+
END
2820+
$$ ) AS (case_statement agtype);
2821+
2822+
SELECT * FROM cypher('case_statement', $$
2823+
MATCH (n)
2824+
RETURN CASE n
2825+
WHEN null THEN 'should not return me'
2826+
WHEN n THEN n.i = (1 = 1)
2827+
ELSE 'none'
2828+
END
2829+
$$ ) AS (case_statement agtype);
2830+
2831+
SELECT * FROM cypher('case_statement', $$
2832+
MATCH (n)
2833+
RETURN CASE n
2834+
WHEN null THEN 'should not return me'
2835+
WHEN n THEN n.i = (1 = 0)
2836+
ELSE 'none'
2837+
END
2838+
$$ ) AS (case_statement agtype);
2839+
27452840
--CASE with count()
27462841

27472842
--count(*)

src/backend/parser/cypher_expr.c

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1493,6 +1493,17 @@ static Node *transform_CaseExpr(cypher_parsestate *cpstate, CaseExpr
14931493
warg = (Node *) w->expr;
14941494
if (placeholder)
14951495
{
1496+
if(is_ag_node(warg, cypher_comparison_aexpr) ||
1497+
is_ag_node(warg, cypher_comparison_boolexpr) )
1498+
{
1499+
List *funcname = list_make1(makeString("ag_catalog"));
1500+
funcname = lappend(funcname, makeString("bool_to_agtype"));
1501+
1502+
warg = (Node *) makeFuncCall(funcname, list_make1(warg),
1503+
COERCE_EXPLICIT_CAST,
1504+
cexpr->location);
1505+
}
1506+
14961507
/* shorthand form was specified, so expand... */
14971508
warg = (Node *) makeSimpleA_Expr(AEXPR_OP, "=",
14981509
(Node *) placeholder,
@@ -1506,6 +1517,18 @@ static Node *transform_CaseExpr(cypher_parsestate *cpstate, CaseExpr
15061517
"CASE/WHEN");
15071518

15081519
warg = (Node *) w->result;
1520+
1521+
if(is_ag_node(warg, cypher_comparison_aexpr) ||
1522+
is_ag_node(warg, cypher_comparison_boolexpr) )
1523+
{
1524+
List *funcname = list_make1(makeString("ag_catalog"));
1525+
funcname = lappend(funcname, makeString("bool_to_agtype"));
1526+
1527+
warg = (Node *) makeFuncCall(funcname, list_make1(warg),
1528+
COERCE_EXPLICIT_CAST,
1529+
cexpr->location);
1530+
}
1531+
15091532
neww->result = (Expr *) transform_cypher_expr_recurse(cpstate, warg);
15101533
neww->location = w->location;
15111534

0 commit comments

Comments
 (0)