Skip to content

Commit b1efcb1

Browse files
dehowefjrgemignani
authored andcommitted
Add support for chained expressions in CASE (#1431)
Adds logic that implements CASE in chained expressions. Adds regression tests for CASE chained expression logic.
1 parent b4a0473 commit b1efcb1

File tree

3 files changed

+303
-0
lines changed

3 files changed

+303
-0
lines changed

Diff for: regress/expected/expr.out

+185
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', $$

Diff for: regress/sql/expr.sql

+95
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(*)

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

+23
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)