From 07228b0fd799b30d76c32b8b3ab047830b6cbeff Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tam=C3=A1s=20Michelberger?= Date: Thu, 17 Feb 2022 13:16:09 +0100 Subject: [PATCH] Fix NPE for Slf4JSqlLogger#logAfterExecution StatementContext for Batch does not have ParsedSql. Both logAfterExecution and logException checks whether StatementContext#getParsedSql returns null or not to avoid an NPE. --- .../v3/core/statement/Slf4JSqlLogger.java | 19 +++-- .../v3/core/statement/TestSlf4JSqlLogger.java | 71 +++++++++++++++++++ 2 files changed, 83 insertions(+), 7 deletions(-) create mode 100644 core/src/test/java/org/jdbi/v3/core/statement/TestSlf4JSqlLogger.java diff --git a/core/src/main/java/org/jdbi/v3/core/statement/Slf4JSqlLogger.java b/core/src/main/java/org/jdbi/v3/core/statement/Slf4JSqlLogger.java index 4156090a67..43d9d6eb62 100644 --- a/core/src/main/java/org/jdbi/v3/core/statement/Slf4JSqlLogger.java +++ b/core/src/main/java/org/jdbi/v3/core/statement/Slf4JSqlLogger.java @@ -15,7 +15,6 @@ import java.sql.SQLException; import java.time.Duration; -import java.util.Optional; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -41,7 +40,7 @@ public void logAfterExecution(StatementContext context) { if (log.isDebugEnabled()) { log.debug("Executed in {} '{}' with parameters '{}'", format(Duration.between(context.getExecutionMoment(), context.getCompletionMoment())), - context.getParsedSql().getSql(), + getSql(context), context.getBinding()); } } @@ -50,14 +49,20 @@ public void logAfterExecution(StatementContext context) { public void logException(StatementContext context, SQLException ex) { if (log.isErrorEnabled()) { log.error("Exception while executing '{}' with parameters '{}'", - Optional.ofNullable(context.getParsedSql()) - .map(ParsedSql::getSql) - .orElse(""), - context.getBinding(), - ex); + getSql(context), + context.getBinding(), + ex); } } + private static String getSql(StatementContext context) { + ParsedSql parsedSql = context.getParsedSql(); + if (parsedSql != null) { + return parsedSql.getSql(); + } + return ""; + } + private static String format(Duration duration) { final long totalSeconds = duration.getSeconds(); final long h = totalSeconds / 3600; diff --git a/core/src/test/java/org/jdbi/v3/core/statement/TestSlf4JSqlLogger.java b/core/src/test/java/org/jdbi/v3/core/statement/TestSlf4JSqlLogger.java new file mode 100644 index 0000000000..9e22e92f87 --- /dev/null +++ b/core/src/test/java/org/jdbi/v3/core/statement/TestSlf4JSqlLogger.java @@ -0,0 +1,71 @@ +/* + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jdbi.v3.core.statement; + +import org.jdbi.v3.core.Handle; +import org.jdbi.v3.core.junit5.H2DatabaseExtension; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.RegisterExtension; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; +import static org.junit.jupiter.api.Assertions.assertThrows; + +class TestSlf4JSqlLogger { + private static final String CREATE = "create table foo(bar int primary key not null)"; + private static final String INSERT = "insert into foo values (1)"; + private static final String LOGGER_PROPERTY = "org.slf4j.simpleLogger.log.org.jdbi.sql.test"; + + @RegisterExtension + public H2DatabaseExtension h2Extension = H2DatabaseExtension.instance(); + + @BeforeEach + public void before() { + String oldLevel = null; + Logger logger; + try { + oldLevel = System.getProperty(LOGGER_PROPERTY); + System.setProperty(LOGGER_PROPERTY, "debug"); + logger = LoggerFactory.getLogger("org.jdbi.sql.test"); + } finally { + if (oldLevel != null) { + System.setProperty(LOGGER_PROPERTY, oldLevel); + } + } + + h2Extension.getJdbi().getConfig(SqlStatements.class).setSqlLogger(new Slf4JSqlLogger(logger)); + } + + @Test + void testLogAfterExecutionForBatch() { + try (Handle handle = h2Extension.getJdbi().open()) { + handle.execute(CREATE); + + Batch batch = handle.createBatch(); + batch.add(INSERT); + assertDoesNotThrow(batch::execute); + } + } + + @Test + void testLogExceptionForBatch() { + try (Handle handle = h2Extension.getJdbi().open()) { + Batch batch = handle.createBatch(); + batch.add(INSERT); + assertThrows(UnableToExecuteStatementException.class, batch::execute); + } + } +}