[jOOQ/jOOQ#11564] Fix GENERATE_SERIES for WITH RECURSIVE dialects

This commit is contained in:
Lukas Eder 2021-03-04 16:08:39 +01:00
parent ef59a15ddc
commit 5f546619da

View File

@ -37,6 +37,7 @@
*/
package org.jooq.impl;
import static org.jooq.SQLDialect.*;
import static org.jooq.conf.ParamType.INLINED;
import static org.jooq.impl.DSL.inline;
// ...
@ -52,11 +53,15 @@ import static org.jooq.impl.Names.N_SYSTEM_RANGE;
import static org.jooq.impl.SQLDataType.INTEGER;
import static org.jooq.impl.Tools.visitSubquery;
import java.util.Set;
import org.jooq.Clause;
import org.jooq.Context;
import org.jooq.Field;
import org.jooq.Name;
// ...
import org.jooq.Record1;
import org.jooq.SQLDialect;
import org.jooq.Table;
import org.jooq.TableOptions;
import org.jooq.conf.ParamType;
@ -69,67 +74,9 @@ final class GenerateSeries extends AbstractTable<Record1<Integer>> implements Au
/**
* Generated UID
*/
private static final long serialVersionUID = 2385574114457239818L;
private final Field<Integer> from;
private final Field<Integer> to;
private final Field<Integer> step;
GenerateSeries(Field<Integer> from, Field<Integer> to) {
this(from, to, null);
}
GenerateSeries(Field<Integer> from, Field<Integer> to, Field<Integer> step) {
super(TableOptions.expression(), N_GENERATE_SERIES);
this.from = from;
this.to = to;
this.step = step;
}
@Override
public final void accept(Context<?> ctx) {
switch (ctx.family()) {
case FIREBIRD:
case HSQLDB:
case SQLITE:
case MARIADB:
case MYSQL: {
Name v = unquotedName("v");
Field<Integer> f = DSL.field(v, INTEGER);
visitSubquery(
ctx,
withRecursive(N_GENERATE_SERIES, v)
.as(select(from).unionAll(select(iadd(f, step == null ? inline(1) : step)).from(N_GENERATE_SERIES).where(f.lt(to))))
.select(f.as(N_GENERATE_SERIES)).from(N_GENERATE_SERIES),
true
);
break;
}
case H2: {
if (step == null) {
ctx.visit(N_SYSTEM_RANGE).sql('(').visit(from).sql(", ").visit(to).sql(')');
}
// Work around https://github.com/h2database/h2database/issues/3046
else {
ctx.visit(N_SYSTEM_RANGE).sql('(').visit(from).sql(", ").visit(to).sql(", ");
ctx.paramType(INLINED, c -> c.visit(step));
ctx.sql(')');
}
break;
}
private static final long serialVersionUID = 2385574114457239818L;
private static final Set<SQLDialect> EMULATE_WITH_RECURSIVE = SQLDialect.supportedBy(FIREBIRD, HSQLDB, MARIADB, MYSQL, SQLITE);
private static final Set<SQLDialect> EMULATE_SYSTEM_RANGE = SQLDialect.supportedBy(H2);
@ -155,13 +102,48 @@ final class GenerateSeries extends AbstractTable<Record1<Integer>> implements Au
case POSTGRES:
default: {
if (step == null)
ctx.visit(N_GENERATE_SERIES).sql('(').visit(from).sql(", ").visit(to).sql(')');
else
ctx.visit(N_GENERATE_SERIES).sql('(').visit(from).sql(", ").visit(to).sql(", ").visit(step).sql(')');
}
else {
if (step == null)
ctx.visit(N_GENERATE_SERIES).sql('(').visit(from).sql(", ").visit(to).sql(')');
else
ctx.visit(N_GENERATE_SERIES).sql('(').visit(from).sql(", ").visit(to).sql(", ").visit(step).sql(')');
}
}
@ -183,11 +165,10 @@ final class GenerateSeries extends AbstractTable<Record1<Integer>> implements Au
@Override
public final Table<Record1<Integer>> autoAlias(Context<?> ctx) {
switch (ctx.family()) {
case H2:
return as(N_GENERATE_SERIES, N_GENERATE_SERIES);
default:
return null;
}
if (EMULATE_WITH_RECURSIVE.contains(ctx.dialect()) ||
EMULATE_SYSTEM_RANGE.contains(ctx.dialect()))
return as(N_GENERATE_SERIES, N_GENERATE_SERIES);
else
return null;
}
}