[jOOQ/jOOQ#7527] Added nullCondition diagnostic
This includes: - [jOOQ/jOOQ#14138] DiagnosticsConnection should store duplicate SQL strings in Configuration, not static variable
This commit is contained in:
parent
a167560143
commit
11481b2964
@ -209,6 +209,30 @@ public interface DiagnosticsListener {
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@ -130,6 +130,8 @@ public class Settings
|
||||
protected Boolean diagnosticsUnnecessaryWasNullCall = true;
|
||||
@XmlElement(defaultValue = "true")
|
||||
protected Boolean diagnosticsTrivialCondition = true;
|
||||
@XmlElement(defaultValue = "true")
|
||||
protected Boolean diagnosticsNullCondition = true;
|
||||
@XmlElement(defaultValue = "false")
|
||||
protected Boolean transformPatterns = false;
|
||||
@XmlElement(defaultValue = "true")
|
||||
@ -1435,6 +1437,35 @@ public class Settings
|
||||
this.diagnosticsTrivialCondition = value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether to run the {@link org.jooq.DiagnosticsListener#nullConditoin(org.jooq.DiagnosticsContext) diagnostic.
|
||||
* <p>
|
||||
* Diagnostics are turned off if no {@link org.jooq.Configuration#diagnosticsListenerProviders()} are configured.
|
||||
* Once configured, this diagnostic is turned on by default.
|
||||
* <p>
|
||||
* This feature is available in the commercial distribution only.
|
||||
*
|
||||
* @return
|
||||
* possible object is
|
||||
* {@link Boolean }
|
||||
*
|
||||
*/
|
||||
public Boolean isDiagnosticsNullCondition() {
|
||||
return diagnosticsNullCondition;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the value of the diagnosticsNullCondition property.
|
||||
*
|
||||
* @param value
|
||||
* allowed object is
|
||||
* {@link Boolean }
|
||||
*
|
||||
*/
|
||||
public void setDiagnosticsNullCondition(Boolean value) {
|
||||
this.diagnosticsNullCondition = value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Transform various syntax patterns to better versions, if possible.
|
||||
* <p>
|
||||
@ -4818,6 +4849,11 @@ public class Settings
|
||||
return this;
|
||||
}
|
||||
|
||||
public Settings withDiagnosticsNullCondition(Boolean value) {
|
||||
setDiagnosticsNullCondition(value);
|
||||
return this;
|
||||
}
|
||||
|
||||
public Settings withTransformPatterns(Boolean value) {
|
||||
setTransformPatterns(value);
|
||||
return this;
|
||||
@ -5854,6 +5890,7 @@ public class Settings
|
||||
builder.append("diagnosticsTooManyRowsFetched", diagnosticsTooManyRowsFetched);
|
||||
builder.append("diagnosticsUnnecessaryWasNullCall", diagnosticsUnnecessaryWasNullCall);
|
||||
builder.append("diagnosticsTrivialCondition", diagnosticsTrivialCondition);
|
||||
builder.append("diagnosticsNullCondition", diagnosticsNullCondition);
|
||||
builder.append("transformPatterns", transformPatterns);
|
||||
builder.append("transformPatternsLogging", transformPatternsLogging);
|
||||
builder.append("transformPatternsTrim", transformPatternsTrim);
|
||||
@ -6367,6 +6404,15 @@ public class Settings
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if (diagnosticsNullCondition == null) {
|
||||
if (other.diagnosticsNullCondition!= null) {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
if (!diagnosticsNullCondition.equals(other.diagnosticsNullCondition)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if (transformPatterns == null) {
|
||||
if (other.transformPatterns!= null) {
|
||||
return false;
|
||||
@ -7602,6 +7648,7 @@ public class Settings
|
||||
result = ((prime*result)+((diagnosticsTooManyRowsFetched == null)? 0 :diagnosticsTooManyRowsFetched.hashCode()));
|
||||
result = ((prime*result)+((diagnosticsUnnecessaryWasNullCall == null)? 0 :diagnosticsUnnecessaryWasNullCall.hashCode()));
|
||||
result = ((prime*result)+((diagnosticsTrivialCondition == null)? 0 :diagnosticsTrivialCondition.hashCode()));
|
||||
result = ((prime*result)+((diagnosticsNullCondition == null)? 0 :diagnosticsNullCondition.hashCode()));
|
||||
result = ((prime*result)+((transformPatterns == null)? 0 :transformPatterns.hashCode()));
|
||||
result = ((prime*result)+((transformPatternsLogging == null)? 0 :transformPatternsLogging.hashCode()));
|
||||
result = ((prime*result)+((transformPatternsTrim == null)? 0 :transformPatternsTrim.hashCode()));
|
||||
|
||||
@ -38,6 +38,7 @@
|
||||
package org.jooq.impl;
|
||||
|
||||
import static java.lang.Boolean.FALSE;
|
||||
import static java.util.Collections.synchronizedMap;
|
||||
// ...
|
||||
import static org.jooq.conf.ParamType.FORCE_INDEXED;
|
||||
|
||||
@ -46,20 +47,22 @@ import java.sql.PreparedStatement;
|
||||
import java.sql.SQLException;
|
||||
import java.sql.Statement;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.function.Predicate;
|
||||
import java.util.Set;
|
||||
import java.util.function.Predicate;
|
||||
|
||||
import org.jooq.Condition;
|
||||
import org.jooq.Configuration;
|
||||
import org.jooq.Parser;
|
||||
// ...
|
||||
import org.jooq.Queries;
|
||||
import org.jooq.QueryPart;
|
||||
import org.jooq.RenderContext;
|
||||
// ...
|
||||
import org.jooq.conf.Settings;
|
||||
import org.jooq.impl.QOM.Eq;
|
||||
import org.jooq.tools.jdbc.DefaultConnection;
|
||||
@ -73,7 +76,6 @@ final class DiagnosticsConnection extends DefaultConnection {
|
||||
static final int LRU_SIZE_GLOBAL = 50000;
|
||||
static final int LRU_SIZE_LOCAL = 500;
|
||||
static final int DUP_SIZE = 500;
|
||||
static final Map<String, Set<String>> DUPLICATE_SQL = Collections.synchronizedMap(new LRU<>(LRU_SIZE_GLOBAL));
|
||||
|
||||
final Map<String, List<String>> repeatedSQL = new LRU<>(LRU_SIZE_LOCAL);
|
||||
final Configuration configuration;
|
||||
@ -168,13 +170,27 @@ final class DiagnosticsConnection extends DefaultConnection {
|
||||
return !FALSE.equals(test.test(configuration.settings()));
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
final Map<String, Set<String>> duplicateSql() {
|
||||
return (Map<String, Set<String>>) configuration.data().computeIfAbsent(
|
||||
"org.jooq.diagnostics.duplicate-sql",
|
||||
k -> synchronizedMap(new LRU<>(LRU_SIZE_GLOBAL))
|
||||
);
|
||||
}
|
||||
|
||||
final String parse(String sql) {
|
||||
Queries queries = null;
|
||||
Queries transformed = null;
|
||||
String normalised;
|
||||
|
||||
try {
|
||||
queries = parser.parse(sql);
|
||||
normalised = normalisingRenderer.render(queries);
|
||||
|
||||
// [#14137] TODO: Avoid unnecessary work, depending on the Settings
|
||||
transformed = queries = parser.parse(sql);
|
||||
|
||||
|
||||
|
||||
normalised = normalisingRenderer.render(transformed);
|
||||
}
|
||||
catch (ParserException exception) {
|
||||
normalised = sql;
|
||||
@ -186,10 +202,7 @@ final class DiagnosticsConnection extends DefaultConnection {
|
||||
|
||||
try {
|
||||
if (check(Settings::isDiagnosticsDuplicateStatements)) {
|
||||
Set<String> duplicates = null;
|
||||
synchronized (DUPLICATE_SQL) {
|
||||
duplicates = duplicates(DUPLICATE_SQL, sql, normalised);
|
||||
}
|
||||
Set<String> duplicates = duplicates(duplicateSql(), sql, normalised);
|
||||
|
||||
if (duplicates != null)
|
||||
listeners.duplicateStatements(new DefaultDiagnosticsContext(
|
||||
@ -223,6 +236,11 @@ final class DiagnosticsConnection extends DefaultConnection {
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@ -244,16 +262,25 @@ final class DiagnosticsConnection extends DefaultConnection {
|
||||
return sql;
|
||||
}
|
||||
|
||||
private Set<String> duplicates(Map<String, Set<String>> map, String sql, String normalised) {
|
||||
Set<String> v = map.computeIfAbsent(normalised, k -> new HashSet<>());
|
||||
|
||||
if (v.size() >= DUP_SIZE || (v.add(sql) && v.size() > 1))
|
||||
return v;
|
||||
else
|
||||
return null;
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
private final Set<String> duplicates(Map<String, Set<String>> map, String sql, String normalised) {
|
||||
synchronized (map) {
|
||||
Set<String> v = map.computeIfAbsent(normalised, k -> new HashSet<>());
|
||||
|
||||
if (v.size() >= DUP_SIZE || (v.add(sql) && v.size() > 1))
|
||||
return v;
|
||||
else
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private List<String> repetitions(Map<String, List<String>> map, String sql, String normalised) {
|
||||
private final List<String> repetitions(Map<String, List<String>> map, String sql, String normalised) {
|
||||
List<String> v = map.computeIfAbsent(normalised, k -> new ArrayList<>());
|
||||
|
||||
if (v.size() >= DUP_SIZE || (v.add(sql) && v.size() > 1))
|
||||
@ -263,7 +290,7 @@ final class DiagnosticsConnection extends DefaultConnection {
|
||||
}
|
||||
|
||||
// See https://stackoverflow.com/a/1953516/521799
|
||||
static class LRU<V> extends LinkedHashMap<String, V> {
|
||||
static final class LRU<V> extends LinkedHashMap<String, V> {
|
||||
private final int size;
|
||||
|
||||
LRU(int size) {
|
||||
|
||||
@ -120,6 +120,13 @@ final class DiagnosticsListeners implements DiagnosticsListener {
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public final void exception(DiagnosticsContext ctx) {
|
||||
for (DiagnosticsListener listener : listeners)
|
||||
|
||||
@ -1683,6 +1683,9 @@ package org.jooq.impl;
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@ -330,6 +330,15 @@ Once configured, this diagnostic is turned on by default.
|
||||
This feature is available in the commercial distribution only.]]></jxb:javadoc></jxb:property></appinfo></annotation>
|
||||
</element>
|
||||
|
||||
<element name="diagnosticsNullCondition" type="boolean" minOccurs="0" maxOccurs="1" default="true">
|
||||
<annotation><appinfo><jxb:property><jxb:javadoc><![CDATA[Whether to run the {@link org.jooq.DiagnosticsListener#nullConditoin(org.jooq.DiagnosticsContext) diagnostic.
|
||||
<p>
|
||||
Diagnostics are turned off if no {@link org.jooq.Configuration#diagnosticsListenerProviders()} are configured.
|
||||
Once configured, this diagnostic is turned on by default.
|
||||
<p>
|
||||
This feature is available in the commercial distribution only.]]></jxb:javadoc></jxb:property></appinfo></annotation>
|
||||
</element>
|
||||
|
||||
<element name="transformPatterns" type="boolean" minOccurs="0" maxOccurs="1" default="false">
|
||||
<annotation><appinfo><jxb:property><jxb:javadoc><![CDATA[Transform various syntax patterns to better versions, if possible.
|
||||
<p>
|
||||
|
||||
Loading…
Reference in New Issue
Block a user