[jOOQ/jOOQ#10572] Support parsing the HANA MAP function

This includes:

- [jOOQ/jOOQ#9085] Render DECODE by default
This commit is contained in:
Lukas Eder 2021-03-04 16:47:24 +01:00
parent 5f546619da
commit b29595ce06
4 changed files with 34 additions and 37 deletions

View File

@ -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<T, Z> extends AbstractField<Z> {
/**
* Generated UID
*/
private static final long serialVersionUID = -7273879239726265322L;
private static final long serialVersionUID = -7273879239726265322L;
private static final Set<SQLDialect> EMULATE_DISTINCT = SQLDialect.supportedBy(CUBRID, DERBY, FIREBIRD, HSQLDB, MARIADB, MYSQL, POSTGRES, SQLITE);
private final Field<T> field;
private final Field<T> search;
@ -71,44 +82,24 @@ final class Decode<T, Z> extends AbstractField<Z> {
@SuppressWarnings("unchecked")
@Override
public final void accept(Context<?> ctx) {
switch (ctx.family()) {
if (EMULATE_DISTINCT.contains(ctx.dialect())) {
CaseConditionStep<Z> when = DSL.choose().when(field.isNotDistinctFrom(search), result);
for (int i = 0; i + 1 < more.length; i += 2)
when = when.when(field.isNotDistinctFrom((Field<T>) more[i]), (Field<Z>) 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<Z> 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<T>) more[i]), (Field<Z>) more[i + 1]);
}
// trailing default value
else {
ctx.visit(when.otherwise((Field<Z>) more[i]));
return;
}
}
if (more.length % 2 == 0)
ctx.visit(when);
return;
else
ctx.visit(when.otherwise((Field<Z>) more[more.length - 1]));
}
else
ctx.visit(function(N_DECODE, getDataType(), Tools.combine(field, search, result, more)));
}
}

View File

@ -166,6 +166,9 @@ final class GenerateSeries extends AbstractTable<Record1<Integer>> implements Au
@Override
public final Table<Record1<Integer>> 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

View File

@ -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");

View File

@ -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<Field<?>> fields = parseList(',', ParseContext::parseField);
int size = fields.size();