diff --git a/jOOQ/src/main/java/org/jooq/conf/Settings.java b/jOOQ/src/main/java/org/jooq/conf/Settings.java index 1eabad0380..262fc8be49 100644 --- a/jOOQ/src/main/java/org/jooq/conf/Settings.java +++ b/jOOQ/src/main/java/org/jooq/conf/Settings.java @@ -102,6 +102,8 @@ public class Settings protected Boolean debugInfoOnStackTrace = true; @XmlElement(defaultValue = "false") protected Boolean inListPadding = false; + @XmlElement(defaultValue = "2") + protected Integer inListPadBase = 2; @XmlElement(defaultValue = ";") protected String delimiter = ";"; @XmlElement(defaultValue = "LOG_DEBUG") @@ -871,7 +873,7 @@ public class Settings } /** - * [#5600] Whether IN lists in IN predicates should be padded to powers of 2. + * [#5600] Whether IN lists in IN predicates should be padded to powers of inListPadBase (default 2). * * @return * possible object is @@ -894,6 +896,30 @@ public class Settings this.inListPadding = value; } + /** + * [#7095] The base to use to calculate the powers of when applying in list padding. + * + * @return + * possible object is + * {@link Integer } + * + */ + public Integer getInListPadBase() { + return inListPadBase; + } + + /** + * Sets the value of the inListPadBase property. + * + * @param value + * allowed object is + * {@link Integer } + * + */ + public void setInListPadBase(Integer value) { + this.inListPadBase = value; + } + /** * [#5826] The delimiter character to be used to delimit statements in batches. * @@ -1121,6 +1147,11 @@ public class Settings return this; } + public Settings withInListPadBase(Integer value) { + setInListPadBase(value); + return this; + } + public Settings withDelimiter(String value) { setDelimiter(value); return this; diff --git a/jOOQ/src/main/java/org/jooq/impl/DiagnosticsConnection.java b/jOOQ/src/main/java/org/jooq/impl/DiagnosticsConnection.java index d0ff548412..e9d7abd88d 100644 --- a/jOOQ/src/main/java/org/jooq/impl/DiagnosticsConnection.java +++ b/jOOQ/src/main/java/org/jooq/impl/DiagnosticsConnection.java @@ -66,7 +66,7 @@ final class DiagnosticsConnection extends DefaultConnection { static final Map> DUPLICATE_SQL = Collections.synchronizedMap(new LRU()); final Configuration configuration; - final RenderContext forceIndexed; + final RenderContext duplicates; final Parser parser; final DiagnosticsListeners listeners; @@ -75,7 +75,16 @@ final class DiagnosticsConnection extends DefaultConnection { super(configuration.connectionProvider().acquire()); this.configuration = configuration; - this.forceIndexed = configuration.derive(SettingsTools.clone(configuration.settings()).withParamType(FORCE_INDEXED)).dsl().renderContext(); + this.duplicates = configuration.derive( + SettingsTools.clone(configuration.settings()) + + // Forcing all inline parameters to be indexed helps find opportunities to use bind variables + .withParamType(FORCE_INDEXED) + + // Padding IN lists shows duplicates that arise from arbitrary-length dynamic IN lists + .withInListPadding(true) + .withInListPadBase(16) + ).dsl().renderContext(); this.parser = configuration.dsl().parser(); this.listeners = DiagnosticsListeners.get(configuration); } @@ -145,7 +154,6 @@ final class DiagnosticsConnection extends DefaultConnection { configuration.connectionProvider().release(getDelegate()); } - @SuppressWarnings("deprecation") final String parse(String sql) { Queries queries; @@ -156,7 +164,7 @@ final class DiagnosticsConnection extends DefaultConnection { return sql; } - String normalised = forceIndexed.render(queries); + String normalised = duplicates.render(queries); List duplicates = null; synchronized (DUPLICATE_SQL) { diff --git a/jOOQ/src/main/java/org/jooq/impl/InCondition.java b/jOOQ/src/main/java/org/jooq/impl/InCondition.java index 05ea9c7ddc..1e1b93154f 100644 --- a/jOOQ/src/main/java/org/jooq/impl/InCondition.java +++ b/jOOQ/src/main/java/org/jooq/impl/InCondition.java @@ -39,6 +39,12 @@ package org.jooq.impl; import static java.lang.Boolean.TRUE; +import static java.lang.Math.ceil; +import static java.lang.Math.log; +import static java.lang.Math.max; +import static java.lang.Math.min; +import static java.lang.Math.pow; +import static java.lang.Math.round; import static org.jooq.Clause.CONDITION; import static org.jooq.Clause.CONDITION_IN; import static org.jooq.Clause.CONDITION_NOT_IN; @@ -52,6 +58,7 @@ import static org.jooq.impl.DSL.falseCondition; import static org.jooq.impl.DSL.trueCondition; import static org.jooq.impl.Keywords.K_AND; import static org.jooq.impl.Keywords.K_OR; +import static org.jooq.tools.StringUtils.defaultIfNull; import java.util.AbstractList; import java.util.Arrays; @@ -156,7 +163,8 @@ final class InCondition extends AbstractCondition { return ctx.paramType() == INDEXED && TRUE.equals(ctx.settings().isInListPadding()) ? new PaddedList>(list, REQUIRES_IN_LIMIT.contains(ctx.family()) ? IN_LIMIT - : Integer.MAX_VALUE) + : Integer.MAX_VALUE, + defaultIfNull(ctx.settings().getInListPadBase(), 2)) : list; } @@ -196,11 +204,12 @@ final class InCondition extends AbstractCondition { private final int realSize; private final int padSize; - PaddedList(List delegate, int maxPadding) { + PaddedList(List delegate, int maxPadding, int padBase) { + int b = max(2, padBase); + this.delegate = delegate; this.realSize = delegate.size(); - int r = Integer.highestOneBit(realSize); - this.padSize = Math.min(maxPadding, r == realSize ? realSize : r << 1); + this.padSize = min(maxPadding, (int) round(pow(b, ceil(log(realSize) / log(b))))); } @Override diff --git a/jOOQ/src/main/resources/xsd/jooq-runtime-3.11.0.xsd b/jOOQ/src/main/resources/xsd/jooq-runtime-3.11.0.xsd index f17496bab6..694a0ac7ce 100644 --- a/jOOQ/src/main/resources/xsd/jooq-runtime-3.11.0.xsd +++ b/jOOQ/src/main/resources/xsd/jooq-runtime-3.11.0.xsd @@ -172,7 +172,11 @@ jOOQ queries, for which no specific fetchSize value was specified.]]> - + + + + +