Skip to content

Commit b8eb016

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 c9e313f commit b8eb016

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

6460+
--CASE chained expressions
6461+
SELECT * FROM cypher('case_statement', $$
6462+
MATCH (n)
6463+
RETURN CASE
6464+
WHEN null THEN 'should not return me'
6465+
WHEN n.i = 1 = 1 THEN n
6466+
ELSE 'none'
6467+
END
6468+
$$ ) AS (case_statement agtype);
6469+
case_statement
6470+
-------------------------------------------------------------------------------
6471+
{"id": 281474976710657, "label": "", "properties": {"i": 1, "id": 1}}::vertex
6472+
"none"
6473+
"none"
6474+
"none"
6475+
"none"
6476+
"none"
6477+
(6 rows)
6478+
6479+
SELECT * FROM cypher('case_statement', $$
6480+
MATCH (n)
6481+
RETURN CASE
6482+
WHEN null THEN 'should not return me'
6483+
WHEN n.i = (1 = 1) THEN n
6484+
ELSE 'none'
6485+
END
6486+
$$ ) AS (case_statement agtype);
6487+
case_statement
6488+
----------------------------------------------------------------------------------------------
6489+
"none"
6490+
"none"
6491+
"none"
6492+
{"id": 281474976710660, "label": "", "properties": {"i": true, "j": false, "id": 4}}::vertex
6493+
"none"
6494+
"none"
6495+
(6 rows)
6496+
6497+
6498+
SELECT * FROM cypher('case_statement', $$
6499+
MATCH (n)
6500+
RETURN CASE n
6501+
WHEN null THEN 'should not return me'
6502+
WHEN n.i = 1 THEN n
6503+
ELSE 'none'
6504+
END
6505+
$$ ) AS (case_statement agtype);
6506+
case_statement
6507+
----------------
6508+
"none"
6509+
"none"
6510+
"none"
6511+
"none"
6512+
"none"
6513+
"none"
6514+
(6 rows)
6515+
6516+
SELECT * FROM cypher('case_statement', $$
6517+
MATCH (n)
6518+
RETURN CASE n = 1
6519+
WHEN null THEN 'should not return me'
6520+
WHEN n.i = 1 = 1 THEN n
6521+
ELSE 'none'
6522+
END
6523+
$$ ) AS (case_statement agtype);
6524+
case_statement
6525+
------------------------------------------------------------------------------------------------
6526+
"none"
6527+
{"id": 281474976710658, "label": "", "properties": {"i": "a", "j": "b", "id": 2}}::vertex
6528+
{"id": 281474976710659, "label": "", "properties": {"i": 0, "j": 1, "id": 3}}::vertex
6529+
{"id": 281474976710660, "label": "", "properties": {"i": true, "j": false, "id": 4}}::vertex
6530+
{"id": 281474976710661, "label": "", "properties": {"i": [], "j": [0, 1, 2], "id": 5}}::vertex
6531+
{"id": 281474976710662, "label": "", "properties": {"i": {}, "j": {"i": 1}, "id": 6}}::vertex
6532+
(6 rows)
6533+
6534+
SELECT * FROM cypher('case_statement', $$
6535+
MATCH (n)
6536+
RETURN CASE n = 1
6537+
WHEN null THEN 'should not return me'
6538+
WHEN n.i = (1 = 1) THEN n
6539+
ELSE 'none'
6540+
END
6541+
$$ ) AS (case_statement agtype);
6542+
case_statement
6543+
------------------------------------------------------------------------------------------------
6544+
{"id": 281474976710657, "label": "", "properties": {"i": 1, "id": 1}}::vertex
6545+
{"id": 281474976710658, "label": "", "properties": {"i": "a", "j": "b", "id": 2}}::vertex
6546+
{"id": 281474976710659, "label": "", "properties": {"i": 0, "j": 1, "id": 3}}::vertex
6547+
"none"
6548+
{"id": 281474976710661, "label": "", "properties": {"i": [], "j": [0, 1, 2], "id": 5}}::vertex
6549+
{"id": 281474976710662, "label": "", "properties": {"i": {}, "j": {"i": 1}, "id": 6}}::vertex
6550+
(6 rows)
6551+
6552+
--should return n
6553+
SELECT * FROM cypher('case_statement', $$
6554+
MATCH (n)
6555+
RETURN CASE n = 1
6556+
WHEN null THEN 'should not return me'
6557+
WHEN n = 1 = 1 THEN n
6558+
ELSE 'none'
6559+
END
6560+
$$ ) AS (case_statement agtype);
6561+
case_statement
6562+
------------------------------------------------------------------------------------------------
6563+
{"id": 281474976710657, "label": "", "properties": {"i": 1, "id": 1}}::vertex
6564+
{"id": 281474976710658, "label": "", "properties": {"i": "a", "j": "b", "id": 2}}::vertex
6565+
{"id": 281474976710659, "label": "", "properties": {"i": 0, "j": 1, "id": 3}}::vertex
6566+
{"id": 281474976710660, "label": "", "properties": {"i": true, "j": false, "id": 4}}::vertex
6567+
{"id": 281474976710661, "label": "", "properties": {"i": [], "j": [0, 1, 2], "id": 5}}::vertex
6568+
{"id": 281474976710662, "label": "", "properties": {"i": {}, "j": {"i": 1}, "id": 6}}::vertex
6569+
(6 rows)
6570+
6571+
--chained expression in THEN
6572+
SELECT * FROM cypher('case_statement', $$
6573+
MATCH (n)
6574+
RETURN CASE
6575+
WHEN null THEN 'should not return me'
6576+
WHEN n.i = 1 THEN n.i = 1 = 1
6577+
ELSE 'none'
6578+
END
6579+
$$ ) AS (case_statement agtype);
6580+
case_statement
6581+
----------------
6582+
true
6583+
"none"
6584+
"none"
6585+
"none"
6586+
"none"
6587+
"none"
6588+
(6 rows)
6589+
6590+
--order of operations in then
6591+
SELECT * FROM cypher('case_statement', $$
6592+
MATCH (n)
6593+
RETURN CASE n
6594+
WHEN null THEN 'should not return me'
6595+
WHEN n THEN (n.i = 1) = 1
6596+
ELSE 'none'
6597+
END
6598+
$$ ) AS (case_statement agtype);
6599+
case_statement
6600+
----------------
6601+
false
6602+
false
6603+
false
6604+
false
6605+
false
6606+
false
6607+
(6 rows)
6608+
6609+
SELECT * FROM cypher('case_statement', $$
6610+
MATCH (n)
6611+
RETURN CASE n
6612+
WHEN null THEN 'should not return me'
6613+
WHEN n THEN n.i = (1 = 1)
6614+
ELSE 'none'
6615+
END
6616+
$$ ) AS (case_statement agtype);
6617+
case_statement
6618+
----------------
6619+
false
6620+
false
6621+
false
6622+
true
6623+
false
6624+
false
6625+
(6 rows)
6626+
6627+
SELECT * FROM cypher('case_statement', $$
6628+
MATCH (n)
6629+
RETURN CASE n
6630+
WHEN null THEN 'should not return me'
6631+
WHEN n THEN n.i = (1 = 0)
6632+
ELSE 'none'
6633+
END
6634+
$$ ) AS (case_statement agtype);
6635+
case_statement
6636+
----------------
6637+
false
6638+
false
6639+
false
6640+
false
6641+
false
6642+
false
6643+
(6 rows)
6644+
64606645
--CASE with count()
64616646
--count(*)
64626647
SELECT * FROM cypher('case_statement', $$

regress/sql/expr.sql

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

2676+
--CASE chained expressions
2677+
2678+
SELECT * FROM cypher('case_statement', $$
2679+
MATCH (n)
2680+
RETURN CASE
2681+
WHEN null THEN 'should not return me'
2682+
WHEN n.i = 1 = 1 THEN n
2683+
ELSE 'none'
2684+
END
2685+
$$ ) AS (case_statement agtype);
2686+
2687+
SELECT * FROM cypher('case_statement', $$
2688+
MATCH (n)
2689+
RETURN CASE
2690+
WHEN null THEN 'should not return me'
2691+
WHEN n.i = (1 = 1) THEN n
2692+
ELSE 'none'
2693+
END
2694+
$$ ) AS (case_statement agtype);
2695+
2696+
SELECT * FROM cypher('case_statement', $$
2697+
MATCH (n)
2698+
RETURN CASE n
2699+
WHEN null THEN 'should not return me'
2700+
WHEN n.i = 1 THEN n
2701+
ELSE 'none'
2702+
END
2703+
$$ ) AS (case_statement agtype);
2704+
2705+
SELECT * FROM cypher('case_statement', $$
2706+
MATCH (n)
2707+
RETURN CASE n = 1
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 n = 1
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+
--should return n
2724+
SELECT * FROM cypher('case_statement', $$
2725+
MATCH (n)
2726+
RETURN CASE n = 1
2727+
WHEN null THEN 'should not return me'
2728+
WHEN n = 1 = 1 THEN n
2729+
ELSE 'none'
2730+
END
2731+
$$ ) AS (case_statement agtype);
2732+
2733+
--chained expression in THEN
2734+
SELECT * FROM cypher('case_statement', $$
2735+
MATCH (n)
2736+
RETURN CASE
2737+
WHEN null THEN 'should not return me'
2738+
WHEN n.i = 1 THEN n.i = 1 = 1
2739+
ELSE 'none'
2740+
END
2741+
$$ ) AS (case_statement agtype);
2742+
2743+
--order of operations in then
2744+
SELECT * FROM cypher('case_statement', $$
2745+
MATCH (n)
2746+
RETURN CASE n
2747+
WHEN null THEN 'should not return me'
2748+
WHEN n THEN (n.i = 1) = 1
2749+
ELSE 'none'
2750+
END
2751+
$$ ) AS (case_statement agtype);
2752+
2753+
SELECT * FROM cypher('case_statement', $$
2754+
MATCH (n)
2755+
RETURN CASE n
2756+
WHEN null THEN 'should not return me'
2757+
WHEN n THEN n.i = (1 = 1)
2758+
ELSE 'none'
2759+
END
2760+
$$ ) AS (case_statement agtype);
2761+
2762+
SELECT * FROM cypher('case_statement', $$
2763+
MATCH (n)
2764+
RETURN CASE n
2765+
WHEN null THEN 'should not return me'
2766+
WHEN n THEN n.i = (1 = 0)
2767+
ELSE 'none'
2768+
END
2769+
$$ ) AS (case_statement agtype);
2770+
26762771
--CASE with count()
26772772

26782773
--count(*)

src/backend/parser/cypher_expr.c

Lines changed: 23 additions & 0 deletions
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)