- All Implemented Interfaces:
- DiagnosticsListener
DiagnosticsListener that logs
 diagnostics.- Author:
- Lukas Eder
- 
Constructor SummaryConstructors
- 
Method SummaryModifier and TypeMethodDescriptionvoidString concatenation was encountered in predicates.voidSimilar JDBC statements are repeated consecutively with differing aggregation.voidThe executed JDBC statement has duplicates.voidANULLcondition was encountered, which is almost always a mistake.voidA possibly wrong expression was encountered.voidThe executed JDBC statement is repeated consecutively on the same JDBCConnection.voidThe fetched JDBCResultSetreturned more columns than necessary.voidThe fetched JDBCResultSetreturned more rows than necessary.voidASettings.isTransformPatterns()pattern has been matched.voidA trivial condition was encountered, which can be replaced by aNULLpredicate, or even byDSL.trueCondition()orDSL.falseCondition(), but it is more likely just a typo.Methods inherited from class java.lang.Objectclone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, waitMethods inherited from interface org.jooq.DiagnosticsListenerexception, missingWasNullCall, unnecessaryWasNullCall
- 
Constructor Details- 
LoggingDiagnosticsListenerpublic LoggingDiagnosticsListener()
 
- 
- 
Method Details- 
duplicateStatementsDescription copied from interface:DiagnosticsListenerThe executed JDBC statement has duplicates.Many databases maintain an execution plan cache, which remembers execution plans for a given SQL string. These caches often use the verbatim SQL string (or a hash thereof) as a key, meaning that "similar" but not identical statements will produce different keys. This may be desired in rare cases when querying skewed data, as a hack to force the optimiser to calculate a new plan for a given "similar" but not identical query, but mostly, this is not desirable as calculating execution plans can turn out to be expensive. Examples of such duplicate statements include: Whitespace differencesSELECT * FROM actor; SELECT * FROM actor;Inline bind valuesSELECT * FROM actor WHERE id = 1; SELECT * FROM actor WHERE id = 2;Aliasing and qualificationSELECT a1.* FROM actor a1 WHERE id = ?; SELECT * FROM actor a2 WHERE a2.id = ?;Examples of identical statements (which are not considered duplicate, but DiagnosticsListener.repeatedStatements(DiagnosticsContext), if on the sameConnection) are:SELECT * FROM actor WHERE id = ?; SELECT * FROM actor WHERE id = ?;This is a system-wide diagnostic that is not specific to individual Connectioninstances. Its caches are located in theConfigurationthat this listener pertains to.This diagnostic can be turned off using Settings.isDiagnosticsDuplicateStatements().Advanced duplicate statement recognition can be turned off using Settings.isDiagnosticsDuplicateStatementsUsingTransformPatterns().- Specified by:
- duplicateStatementsin interface- DiagnosticsListener
- Parameters:
- ctx- The context containing information about the diagnostic.
 
- 
repeatedStatementsDescription copied from interface:DiagnosticsListenerThe executed JDBC statement is repeated consecutively on the same JDBCConnection.This problem goes by many names, the most famous one being the N + 1 problem, when a single (1) query for a parent entity requires many (N) subsequent queries for child entities. This could have been prevented by rewriting the parent query to use a JOIN. If such a rewrite is not possible (or not easy), the subsequent N queries could at least profit (depending on the exact query): - From reusing the PreparedStatement
- From being batched
- From being re-written as a bulk fetch or write query
 This problem can be aggravated if combined with the DiagnosticsListener.duplicateStatements(DiagnosticsContext)problem, in case of which the repeated statements might not be diagnosed as easily.Repeated statements may or may not be "identical". In the following example, there are two repeated and identical statements: SELECT * FROM actor WHERE id = ?; SELECT * FROM actor WHERE id = ?;In this example, we have three repeated statements, only some of which are also identical: SELECT * FROM actor WHERE id = ?; SELECT * FROM actor WHERE id = ?; SELECT * FROM actor WHERE id = ?;This is a Connection-specific diagnostic that is reset every timeConnection.close()is called for explicitly createdDSLContext.diagnosticsConnection(), or ifDiagnosticsConnection.ONis specified, also globally on aTransactionContextlevel (if available), orConfigurationlevel.This diagnostic can be turned off using Settings.isDiagnosticsRepeatedStatements().- Specified by:
- repeatedStatementsin interface- DiagnosticsListener
- Parameters:
- ctx- The context containing information about the diagnostic.
 
- From reusing the 
- 
tooManyColumnsFetchedDescription copied from interface:DiagnosticsListenerThe fetched JDBCResultSetreturned more columns than necessary.An event indicating that a JDBC ResultSetwas fetched withAcolumns, but onlyB(B < A) were consumed.Typically, this problem can be remedied by not running a SELECT *query when this isn't strictly required.This diagnostic can be turned off using Settings.isDiagnosticsTooManyColumnsFetched().- Specified by:
- tooManyColumnsFetchedin interface- DiagnosticsListener
- Parameters:
- ctx- The context containing information about the diagnostic.
 
- 
tooManyRowsFetchedDescription copied from interface:DiagnosticsListenerThe fetched JDBCResultSetreturned more rows than necessary.An event indicating that a JDBC ResultSetwas fetched withArows, but onlyBrows (B < A) were consumed.Typically, this problem can be remedied by applying the appropriate LIMITclause in SQL, orSelectLimitStep.limit(Number)clause in jOOQ.This diagnostic can be turned off using Settings.isDiagnosticsTooManyRowsFetched().- Specified by:
- tooManyRowsFetchedin interface- DiagnosticsListener
- Parameters:
- ctx- The context containing information about the diagnostic.
 
- 
consecutiveAggregationDescription copied from interface:DiagnosticsListenerSimilar JDBC statements are repeated consecutively with differing aggregation.Developers are often unaware of the fact that they can place multiple aggregate functions (even with filters) in a single query, rather than running separate queries producing separate round trips and load in the database. In the following example, there are three similar statements aggregating the same data: SELECT count(*) FROM actor; SELECT count(*) FROM actor WHERE last_name LIKE ?; SELECT count(DISTINCT last_name) FROM actor; SELECT count(DISTINCT last_name) FROM actor WHERE last_name LIKE ?;It would be more efficient to run this query in a single statement: SELECT count(*), count(*) FILTER (WHERE last_name LIKE ?), count(DISTINCT last_name), count(DISTINCT last_name) FILTER (WHERE last_name LIKE ?) FROM actor;This is a Connection-specific diagnostic that is reset every timeConnection.close()is called for explicitly createdDSLContext.diagnosticsConnection(), or ifDiagnosticsConnection.ONis specified, also globally on aTransactionContextlevel (if available), orConfigurationlevel.This diagnostic can be turned off using Settings.isDiagnosticsConsecutiveAggregation().This is a commercial edition only diagnostic. - Specified by:
- consecutiveAggregationin interface- DiagnosticsListener
- Parameters:
- ctx- The context containing information about the diagnostic.
 
- 
concatenationInPredicateDescription copied from interface:DiagnosticsListenerString concatenation was encountered in predicates.A predicate of the following form (or similar) was encountered: SELECT * FROM actor WHERE first_name || last_name = ?; SELECT * FROM actor WHERE first_name || last_name IN ( SELECT first_name || last_name FROM customer );While it is possible in some RDBMS to define function based indexes on such expressions, it's usually better (because indexes are more reusable), and more correct (because concatenation produces ambiguous values, e.g. 'John Taylor' || 'Doe'is the same value as'John' || 'Taylor Doe') to work with separate columns, e.g.:SELECT * FROM actor WHERE (first_name, last_name) = (?, ?); SELECT * FROM actor WHERE (first_name, last_name) IN ( SELECT first_name, last_name FROM customer );This diagnostic can be turned off using Settings.isDiagnosticsConcatenationInPredicate().This is a commercial edition only diagnostic. - Specified by:
- concatenationInPredicatein interface- DiagnosticsListener
- Parameters:
- ctx- The context containing information about the diagnostic.
 
- 
possiblyWrongExpressionDescription copied from interface:DiagnosticsListenerA possibly wrong expression was encountered.Some expressions may be correct in most cases, but wrong in edge cases that developers may have overlooked. Examples include: - MOD(x, 2) = 1instead of- MOD(x, 2) != 0. The former will not be true for negative numbers.
 This diagnostic can be turned off using Settings.isDiagnosticsPossiblyWrongExpression().This is a commercial edition only diagnostic. - Specified by:
- possiblyWrongExpressionin interface- DiagnosticsListener
- Parameters:
- ctx- The context containing information about the diagnostic.
 
- 
trivialConditionDescription copied from interface:DiagnosticsListenerA trivial condition was encountered, which can be replaced by aNULLpredicate, or even byDSL.trueCondition()orDSL.falseCondition(), but it is more likely just a typo.A trivial condition might compare a column to itself, e.g. SELECT * FROM actor a JOIN film_actor fa ON a.actor_id = a.actor_idThe above JOINpredicate is effectivelya.actor_id IS NOT NULL, but what the author probably meant was to writea.actor_id = fa.actor_idinstead.This mistake can often be very subtle, especially when comparing columns of composite constraints. In many cases, it's a bug, and if it isn't there's probably a more straightforward way to declare the condition. This diagnostic can be turned off using Settings.isDiagnosticsTrivialCondition().This is a commercial edition only diagnostic. - Specified by:
- trivialConditionin interface- DiagnosticsListener
- Parameters:
- ctx- The context containing information about the diagnostic.
 
- 
nullConditionDescription copied from interface:DiagnosticsListenerANULLcondition was encountered, which is almost always a mistake.A NULLcondition may appear when users accidentally compare values withNULLSELECT * FROM actor a WHERE last_name = NULLThe above predicate will never evaluate to TRUE, even when thelast_namecolumn is indeedNULL. TheField.isNull()predicate should have been used instead.This diagnostic can be turned off using Settings.isDiagnosticsNullCondition().This is a commercial edition only diagnostic. - Specified by:
- nullConditionin interface- DiagnosticsListener
- Parameters:
- ctx- The context containing information about the diagnostic.
 
- 
transformPatternDescription copied from interface:DiagnosticsListenerASettings.isTransformPatterns()pattern has been matched.This diagnostic can be turned off using Settings.isDiagnosticsPatterns().This is a commercial edition only diagnostic. - Specified by:
- transformPatternin interface- DiagnosticsListener
- Parameters:
- ctx- The context containing information about the diagnostic.
- See Also:
 
 
-