Skip to content

Commit d25fb46

Browse files
authored
Add support for chained expressions in CASE (#1431) (#1434)
Adds logic that implements CASE in chained expressions. Adds regression tests for CASE chained expression logic.
1 parent c7700e6 commit d25fb46

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
@@ -6528,6 +6528,191 @@ $$ ) AS (case_statement agtype);
65286528
{"id": 844424930131970, "label": "connected_to", "end_id": 281474976710660, "start_id": 281474976710659, "properties": {"k": 1, "id": 2}}::edge
65296529
(2 rows)
65306530

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

+23
Original file line numberDiff line numberDiff line change
@@ -1368,6 +1368,17 @@ static Node *transform_CaseExpr(cypher_parsestate *cpstate, CaseExpr
13681368
warg = (Node *) w->expr;
13691369
if (placeholder)
13701370
{
1371+
if(is_ag_node(warg, cypher_comparison_aexpr) ||
1372+
is_ag_node(warg, cypher_comparison_boolexpr) )
1373+
{
1374+
List *funcname = list_make1(makeString("ag_catalog"));
1375+
funcname = lappend(funcname, makeString("bool_to_agtype"));
1376+
1377+
warg = (Node *) makeFuncCall(funcname, list_make1(warg),
1378+
COERCE_EXPLICIT_CAST,
1379+
cexpr->location);
1380+
}
1381+
13711382
/* shorthand form was specified, so expand... */
13721383
warg = (Node *) makeSimpleA_Expr(AEXPR_OP, "=",
13731384
(Node *) placeholder,
@@ -1381,6 +1392,18 @@ static Node *transform_CaseExpr(cypher_parsestate *cpstate, CaseExpr
13811392
"CASE/WHEN");
13821393

13831394
warg = (Node *) w->result;
1395+
1396+
if(is_ag_node(warg, cypher_comparison_aexpr) ||
1397+
is_ag_node(warg, cypher_comparison_boolexpr) )
1398+
{
1399+
List *funcname = list_make1(makeString("ag_catalog"));
1400+
funcname = lappend(funcname, makeString("bool_to_agtype"));
1401+
1402+
warg = (Node *) makeFuncCall(funcname, list_make1(warg),
1403+
COERCE_EXPLICIT_CAST,
1404+
cexpr->location);
1405+
}
1406+
13841407
neww->result = (Expr *) transform_cypher_expr_recurse(cpstate, warg);
13851408
neww->location = w->location;
13861409

0 commit comments

Comments
 (0)