[jOOQ/jOOQ#7312] Auto-transform table lists to ansi join if needed

If (+) is encountered but not supported, automatically transform the table lists to ansi join.
This commit is contained in:
Lukas Eder 2020-09-17 11:17:09 +02:00
parent 9995378892
commit afc4474785
4 changed files with 66 additions and 19 deletions

View File

@ -4223,6 +4223,7 @@ extends
// ------------------------------------------------------------------------

View File

@ -54,7 +54,9 @@ import static org.jooq.impl.DSL.using;
import static org.jooq.impl.Tools.EMPTY_PARAM;
import static org.jooq.impl.Tools.blocking;
import static org.jooq.impl.Tools.consumeExceptions;
import static org.jooq.impl.Tools.maxForceSettingsAttempts;
import static org.jooq.impl.Tools.BooleanDataKey.DATA_COUNT_BIND_VALUES;
import static org.jooq.impl.Tools.BooleanDataKey.DATA_FORCE_SETTINGS;
import static org.jooq.impl.Tools.BooleanDataKey.DATA_FORCE_STATIC_STATEMENT;
import java.sql.PreparedStatement;
@ -78,7 +80,9 @@ import org.jooq.conf.QueryPoolable;
import org.jooq.conf.SettingsTools;
import org.jooq.conf.StatementType;
import org.jooq.exception.ControlFlowSignal;
import org.jooq.exception.DataAccessException;
import org.jooq.exception.DetachedException;
import org.jooq.impl.DefaultRenderContext.ForceSettingsSignal;
import org.jooq.tools.Ints;
import org.jooq.tools.JooqLogger;
@ -509,30 +513,47 @@ abstract class AbstractQuery extends AbstractQueryPart implements Query {
private final Rendered getSQL0(ExecuteContext ctx) {
Rendered result;
DefaultRenderContext render;
Configuration c = configuration;
// [#3542] [#4977] Some dialects do not support bind values in DDL statements
// [#6474] [#6929] Can this be communicated in a leaner way?
if (ctx.type() == DDL) {
ctx.data(DATA_FORCE_STATIC_STATEMENT, true);
DefaultRenderContext render = new DefaultRenderContext(configuration);
result = new Rendered(render.paramType(INLINED).visit(this).render(), null, render.peekSkipUpdateCounts());
}
else if (executePreparedStatements(configuration().settings())) {
int i = 0;
forceSettingsLoop:
for (;;) {
render = new DefaultRenderContext(c);
render.data(DATA_FORCE_SETTINGS, true);
try {
DefaultRenderContext render = new DefaultRenderContext(configuration);
render.data(DATA_COUNT_BIND_VALUES, true);
result = new Rendered(render.visit(this).render(), render.bindValues(), render.peekSkipUpdateCounts());
if (ctx.type() == DDL) {
ctx.data(DATA_FORCE_STATIC_STATEMENT, true);
result = new Rendered(render.paramType(INLINED).visit(this).render(), null, render.peekSkipUpdateCounts());
}
else if (executePreparedStatements(configuration().settings())) {
try {
render.data(DATA_COUNT_BIND_VALUES, true);
result = new Rendered(render.visit(this).render(), render.bindValues(), render.peekSkipUpdateCounts());
}
catch (DefaultRenderContext.ForceInlineSignal e) {
ctx.data(DATA_FORCE_STATIC_STATEMENT, true);
result = new Rendered(render.paramType(INLINED).visit(this).render(), null, render.peekSkipUpdateCounts());
}
}
else {
result = new Rendered(render.paramType(INLINED).visit(this).render(), null, render.peekSkipUpdateCounts());
}
break forceSettingsLoop;
}
catch (DefaultRenderContext.ForceInlineSignal e) {
ctx.data(DATA_FORCE_STATIC_STATEMENT, true);
DefaultRenderContext render = new DefaultRenderContext(configuration);
result = new Rendered(render.paramType(INLINED).visit(this).render(), null, render.peekSkipUpdateCounts());
catch (ForceSettingsSignal e) {
if (++i >= maxForceSettingsAttempts) {
log.warn("Infinite loop", "There was an infinite loop trying to render a SQL query, due to ForceSettingsSignal. Please consider reporting this bug here: https://github.com/jOOQ/jOOQ/issues/new/choose");
throw new DataAccessException("Too many force settings attempts");
}
c = c.derive(e.settings);
}
}
else {
DefaultRenderContext render = new DefaultRenderContext(configuration);
result = new Rendered(render.paramType(INLINED).visit(this).render(), null, render.peekSkipUpdateCounts());
}

View File

@ -956,4 +956,21 @@ class DefaultRenderContext extends AbstractContext<RenderContext> implements Ren
log.debug("Re-render query", "Forcing bind variable inlining as " + configuration().dialect() + " does not support " + params + " bind variables (or more) in a single query");
}
}
/**
* A query rendering signal to force re-rendering a query with different
* settings.
*/
static class ForceSettingsSignal extends ControlFlowSignal {
/**
* Generated UID
*/
private static final long serialVersionUID = -1530836969063166588L;
final Settings settings;
ForceSettingsSignal(Settings settings) {
this.settings = settings;
}
}
}

View File

@ -282,6 +282,7 @@ import org.jooq.exception.MappingException;
import org.jooq.exception.NoDataFoundException;
import org.jooq.exception.TemplatingException;
import org.jooq.exception.TooManyRowsException;
import org.jooq.impl.DefaultRenderContext.ForceSettingsSignal;
import org.jooq.impl.ResultsImpl.ResultOrRowsImpl;
import org.jooq.tools.Ints;
import org.jooq.tools.JooqLogger;
@ -372,6 +373,12 @@ final class Tools {
*/
DATA_FORCE_STATIC_STATEMENT,
/**
* [#7312] Allow for {@link ForceSettingsSignal} to be thrown in order
* to override user-defined settings.
*/
DATA_FORCE_SETTINGS,
/**
* [#2665] Omit the emission of clause events by {@link QueryPart}s.
* <p>
@ -711,8 +718,9 @@ final class Tools {
* {@link #consumeExceptions(Configuration, PreparedStatement, SQLException)}
* helps prevent infinite loops and {@link OutOfMemoryError}.
*/
private static int maxConsumedExceptions = 256;
private static int maxConsumedResults = 65536;
static int maxForceSettingsAttempts = 16;
static int maxConsumedExceptions = 256;
static int maxConsumedResults = 65536;
/**
* A pattern for the dash line syntax