Skip to content
This repository has been archived by the owner on Jan 17, 2024. It is now read-only.

Commit

Permalink
[#10] Support CASE
Browse files Browse the repository at this point in the history
This includes:
- CASE abbreviations
- CASE simple
- CASE searched
  • Loading branch information
lukaseder committed Jan 23, 2023
1 parent 1ddd933 commit b7b6925
Show file tree
Hide file tree
Showing 2 changed files with 112 additions and 1 deletion.
37 changes: 37 additions & 0 deletions src/main/java/org/neo4j/sql2cypher/Translator.java
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@
import org.jooq.impl.DefaultConfiguration;
import org.jooq.impl.QOM;
import org.jooq.impl.QOM.TableAlias;
import org.neo4j.cypherdsl.core.Case;
import org.neo4j.cypherdsl.core.Condition;
import org.neo4j.cypherdsl.core.Cypher;
import org.neo4j.cypherdsl.core.Expression;
Expand Down Expand Up @@ -354,6 +355,42 @@ else if (f instanceof QOM.Nvl<?> e) {
return Functions.coalesce(expression(e.$arg1()), expression(e.$arg2()));
}

// https://neo4j.com/docs/cypher-manual/current/syntax/expressions/
else if (f instanceof QOM.Nullif<?> e) {
return Cypher.caseExpression().when(expression(e.$arg1()).eq(expression(e.$arg2())))
.then(Cypher.literalNull()).elseDefault(expression(e.$arg1()));
}
else if (f instanceof QOM.Nvl2<?> e) {
return Cypher.caseExpression().when(expression(e.$arg1()).isNotNull()).then(expression(e.$arg2()))
.elseDefault(expression(e.$arg3()));
}
else if (f instanceof QOM.CaseSimple<?, ?> e) {
Case c = Cypher.caseExpression(expression(e.$value()));

for (var w : e.$when()) {
c = c.when(expression(w.$1())).then(expression(w.$2()));
}

if (e.$else() != null) {
c = ((Case.CaseEnding) c).elseDefault(expression(e.$else()));
}

return c;
}
else if (f instanceof QOM.CaseSearched<?> e) {
Case c = Cypher.caseExpression();

for (var w : e.$when()) {
c = c.when(condition(w.$1())).then(expression(w.$2()));
}

if (e.$else() != null) {
c = ((Case.CaseEnding) c).elseDefault(expression(e.$else()));
}

return c;
}

// Others
else if (f instanceof QOM.Cast<?> e) {
if (e.$dataType().isString()) {
Expand Down
76 changes: 75 additions & 1 deletion src/test/resources/expressions.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,18 @@ The input

[source,sql,id=t6_0,name=select_with_string_functions]
----
SELECT coalesce(1, 2), coalesce(1, 2, 3), nvl(1, 2), cast('1' as boolean), cast(1 as float), cast(1 as double precision), cast(1 as real), cast(1 as tinyint), cast(1 as smallint), cast(1 as int), cast(1 as bigint)
SELECT
coalesce(1, 2),
coalesce(1, 2, 3),
nvl(1, 2),
cast('1' as boolean),
cast(1 as float),
cast(1 as double precision),
cast(1 as real),
cast(1 as tinyint),
cast(1 as smallint),
cast(1 as int),
cast(1 as bigint)
----

will be transpiled to
Expand All @@ -118,3 +129,66 @@ will be transpiled to
----
RETURN coalesce(1, 2), coalesce(1, 2, 3), coalesce(1, 2), toBoolean('1'), toFloat(1), toFloat(1), toFloat(1), toInteger(1), toInteger(1), toInteger(1), toInteger(1)
----


== Query syntax expressions

See https://neo4j.com/docs/cypher-manual/current/syntax/expressions

=== `CASE` simple

The input

[source,sql,id=t7_0,name=select_with_string_functions]
----
SELECT
CASE 1 WHEN 2 THEN 3 END,
CASE 1 WHEN 2 THEN 3 ELSE 4 END,
CASE 1 WHEN 2 THEN 3 WHEN 4 THEN 5 END,
CASE 1 WHEN 2 THEN 3 WHEN 4 THEN 5 ELSE 6 END
----

will be transpiled to

[source,cypher,id=t7_0_expected]
----
RETURN CASE 1 WHEN 2 THEN 3 END, CASE 1 WHEN 2 THEN 3 ELSE 4 END, CASE 1 WHEN 2 THEN 3 WHEN 4 THEN 5 END, CASE 1 WHEN 2 THEN 3 WHEN 4 THEN 5 ELSE 6 END
----

=== `CASE` searched

The input

[source,sql,id=t7_1,name=select_with_string_functions]
----
SELECT
CASE WHEN 1 = 2 THEN 3 END,
CASE WHEN 1 = 2 THEN 3 ELSE 4 END,
CASE WHEN 1 = 2 THEN 3 WHEN 4 = 5 THEN 6 END,
CASE WHEN 1 = 2 THEN 3 WHEN 4 = 5 THEN 6 ELSE 7 END
----

will be transpiled to

[source,cypher,id=t7_1_expected]
----
RETURN CASE WHEN 1 = 2 THEN 3 END, CASE WHEN 1 = 2 THEN 3 ELSE 4 END, CASE WHEN 1 = 2 THEN 3 WHEN 4 = 5 THEN 6 END, CASE WHEN 1 = 2 THEN 3 WHEN 4 = 5 THEN 6 ELSE 7 END
----

=== `CASE` abbreviations (which aren't `COALESCE` or `NVL`)

The input

[source,sql,id=t7_2,name=select_with_string_functions]
----
SELECT
nullif(1, 2),
nvl2(1, 2, 3)
----

will be transpiled to

[source,cypher,id=t7_2_expected]
----
RETURN CASE WHEN 1 = 2 THEN NULL ELSE 1 END, CASE WHEN 1 IS NOT NULL THEN 2 ELSE 3 END
----

1 comment on commit b7b6925

@jexp
Copy link
Member

@jexp jexp commented on b7b6925 Jan 23, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice! 👍

Please sign in to comment.