From b29595ce06fd05b7604a0391e0e7b9dc52492998 Mon Sep 17 00:00:00 2001 From: Lukas Eder Date: Thu, 4 Mar 2021 16:47:24 +0100 Subject: [PATCH] [jOOQ/jOOQ#10572] Support parsing the HANA MAP function This includes: - [jOOQ/jOOQ#9085] Render DECODE by default --- jOOQ/src/main/java/org/jooq/impl/Decode.java | 63 ++++++++----------- .../java/org/jooq/impl/GenerateSeries.java | 3 + jOOQ/src/main/java/org/jooq/impl/Names.java | 1 + .../main/java/org/jooq/impl/ParserImpl.java | 4 +- 4 files changed, 34 insertions(+), 37 deletions(-) diff --git a/jOOQ/src/main/java/org/jooq/impl/Decode.java b/jOOQ/src/main/java/org/jooq/impl/Decode.java index 0920f17505..69993efd15 100644 --- a/jOOQ/src/main/java/org/jooq/impl/Decode.java +++ b/jOOQ/src/main/java/org/jooq/impl/Decode.java @@ -37,12 +37,18 @@ */ package org.jooq.impl; +import static org.jooq.SQLDialect.*; import static org.jooq.impl.DSL.function; import static org.jooq.impl.Names.N_DECODE; +import static org.jooq.impl.Names.N_MAP; + +import java.util.Set; import org.jooq.CaseConditionStep; import org.jooq.Context; import org.jooq.Field; +// ... +import org.jooq.SQLDialect; /** * @author Lukas Eder @@ -52,7 +58,12 @@ final class Decode extends AbstractField { /** * Generated UID */ - private static final long serialVersionUID = -7273879239726265322L; + private static final long serialVersionUID = -7273879239726265322L; + private static final Set EMULATE_DISTINCT = SQLDialect.supportedBy(CUBRID, DERBY, FIREBIRD, HSQLDB, MARIADB, MYSQL, POSTGRES, SQLITE); + + + + private final Field field; private final Field search; @@ -71,44 +82,24 @@ final class Decode extends AbstractField { @SuppressWarnings("unchecked") @Override public final void accept(Context ctx) { - switch (ctx.family()) { + if (EMULATE_DISTINCT.contains(ctx.dialect())) { + CaseConditionStep when = DSL.choose().when(field.isNotDistinctFrom(search), result); + for (int i = 0; i + 1 < more.length; i += 2) + when = when.when(field.isNotDistinctFrom((Field) more[i]), (Field) more[i + 1]); - - - - - - - - - case H2: - case IGNITE: - ctx.visit(function("decode", getDataType(), Tools.combine(field, search, result, more))); - return; - - // Other dialects emulate it with a CASE ... WHEN expression - default: - CaseConditionStep when = DSL - .choose() - .when(field.isNotDistinctFrom(search), result); - - for (int i = 0; i < more.length; i += 2) { - - // search/result pair - if (i + 1 < more.length) { - when = when.when(field.isNotDistinctFrom((Field) more[i]), (Field) more[i + 1]); - } - - // trailing default value - else { - ctx.visit(when.otherwise((Field) more[i])); - return; - } - } - + if (more.length % 2 == 0) ctx.visit(when); - return; + else + ctx.visit(when.otherwise((Field) more[more.length - 1])); } + + + + + + + else + ctx.visit(function(N_DECODE, getDataType(), Tools.combine(field, search, result, more))); } } diff --git a/jOOQ/src/main/java/org/jooq/impl/GenerateSeries.java b/jOOQ/src/main/java/org/jooq/impl/GenerateSeries.java index f20d716fba..1fa7ac3bbb 100644 --- a/jOOQ/src/main/java/org/jooq/impl/GenerateSeries.java +++ b/jOOQ/src/main/java/org/jooq/impl/GenerateSeries.java @@ -166,6 +166,9 @@ final class GenerateSeries extends AbstractTable> implements Au @Override public final Table> autoAlias(Context ctx) { if (EMULATE_WITH_RECURSIVE.contains(ctx.dialect()) || + + + EMULATE_SYSTEM_RANGE.contains(ctx.dialect())) return as(N_GENERATE_SERIES, N_GENERATE_SERIES); else diff --git a/jOOQ/src/main/java/org/jooq/impl/Names.java b/jOOQ/src/main/java/org/jooq/impl/Names.java index e6a5bbb267..2288098f04 100644 --- a/jOOQ/src/main/java/org/jooq/impl/Names.java +++ b/jOOQ/src/main/java/org/jooq/impl/Names.java @@ -201,6 +201,7 @@ final class Names { static final Name N_LOWER = unquotedName("lower"); static final Name N_LPAD = unquotedName("lpad"); static final Name N_LTRIM = unquotedName("ltrim"); + static final Name N_MAP = unquotedName("map"); static final Name N_MAX = unquotedName("max"); static final Name N_MAXVALUE = unquotedName("maxvalue"); static final Name N_MD5 = unquotedName("md5"); diff --git a/jOOQ/src/main/java/org/jooq/impl/ParserImpl.java b/jOOQ/src/main/java/org/jooq/impl/ParserImpl.java index b7f7eb9350..d09ab21643 100644 --- a/jOOQ/src/main/java/org/jooq/impl/ParserImpl.java +++ b/jOOQ/src/main/java/org/jooq/impl/ParserImpl.java @@ -7410,6 +7410,8 @@ final class DefaultParseContext extends AbstractScope implements ParseContext { return field; else if ((field = parseFieldLeastIf()) != null) return field; + else if ((field = parseFieldDecodeIf()) != null) + return field; break; @@ -9808,7 +9810,7 @@ final class DefaultParseContext extends AbstractScope implements ParseContext { } private final Field parseFieldDecodeIf() { - if (parseFunctionNameIf("DECODE")) { + if (parseFunctionNameIf("DECODE", "MAP")) { parse('('); List> fields = parseList(',', ParseContext::parseField); int size = fields.size();