From fc1d70e0ac2cbba44e2c48eff999d4fed44d1842 Mon Sep 17 00:00:00 2001 From: kekbur Date: Sat, 25 Jul 2020 00:20:12 +0300 Subject: [PATCH] Binary data representation can be customized according to database dialect (#502) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Binary data representation can be customized according to database dialect * BinaryFormat#toString wraps its return value in quotes if needed Co-authored-by: Jonne JyrylÀ --- docs/configandusage.md | 6 ++ .../assembly/individualFiles/spy.properties | 6 ++ .../java/com/p6spy/engine/common/Value.java | 56 +++++++----------- .../engine/logging/format/BinaryFormat.java | 31 ++++++++++ .../format/HexEncodedBinaryFormat.java | 57 +++++++++++++++++++ .../logging/format/MySQLBinaryFormat.java | 43 ++++++++++++++ .../format/PostgreSQLBinaryFormat.java | 48 ++++++++++++++++ .../engine/spy/P6SpyLoadableOptions.java | 7 +++ .../com/p6spy/engine/spy/P6SpyOptions.java | 37 ++++++++++++ .../p6spy/engine/spy/P6SpyOptionsMBean.java | 10 ++++ .../engine/spy/P6TestResultSetWithBinary.java | 55 ++++++++++++++++++ 11 files changed, 321 insertions(+), 35 deletions(-) create mode 100644 src/main/java/com/p6spy/engine/logging/format/BinaryFormat.java create mode 100644 src/main/java/com/p6spy/engine/logging/format/HexEncodedBinaryFormat.java create mode 100644 src/main/java/com/p6spy/engine/logging/format/MySQLBinaryFormat.java create mode 100644 src/main/java/com/p6spy/engine/logging/format/PostgreSQLBinaryFormat.java diff --git a/docs/configandusage.md b/docs/configandusage.md index 28a1e18d15..1ddf9bf9cc 100644 --- a/docs/configandusage.md +++ b/docs/configandusage.md @@ -162,6 +162,12 @@ in section: [Configuration and Usage](#configuration-and-usage)): # format that is used for logging booleans, possible values: boolean, numeric # (default is boolean) #databaseDialectBooleanFormat=boolean + + # Specifies the format for logging binary data. Not applicable if excludebinary is true. + # (default is com.p6spy.engine.logging.format.HexEncodedBinaryFormat) + #databaseDialectBinaryFormat=com.p6spy.engine.logging.format.PostgreSQLBinaryFormat + #databaseDialectBinaryFormat=com.p6spy.engine.logging.format.MySQLBinaryFormat + #databaseDialectBinaryFormat=com.p6spy.engine.logging.format.HexEncodedBinaryFormat # whether to expose options via JMX or not # (default is true) diff --git a/src/main/assembly/individualFiles/spy.properties b/src/main/assembly/individualFiles/spy.properties index 719dc145f9..66e7964f95 100644 --- a/src/main/assembly/individualFiles/spy.properties +++ b/src/main/assembly/individualFiles/spy.properties @@ -124,6 +124,12 @@ # (default is boolean) # databaseDialectBooleanFormat=boolean +# Specifies the format for logging binary data. Not applicable if excludebinary is true. +# (default is com.p6spy.engine.logging.format.HexEncodedBinaryFormat) +#databaseDialectBinaryFormat=com.p6spy.engine.logging.format.PostgreSQLBinaryFormat +#databaseDialectBinaryFormat=com.p6spy.engine.logging.format.MySQLBinaryFormat +#databaseDialectBinaryFormat=com.p6spy.engine.logging.format.HexEncodedBinaryFormat + # whether to expose options via JMX or not # (default is true) #jmx=true diff --git a/src/main/java/com/p6spy/engine/common/Value.java b/src/main/java/com/p6spy/engine/common/Value.java index d813d40f23..d91d552d46 100644 --- a/src/main/java/com/p6spy/engine/common/Value.java +++ b/src/main/java/com/p6spy/engine/common/Value.java @@ -19,6 +19,7 @@ import com.p6spy.engine.logging.P6LogLoadableOptions; import com.p6spy.engine.logging.P6LogOptions; +import com.p6spy.engine.logging.format.BinaryFormat; import com.p6spy.engine.spy.P6SpyOptions; import java.sql.Timestamp; @@ -35,9 +36,6 @@ */ public class Value { - private static final char[] HEX_CHARS = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', - 'F' }; - /** * Value itself. */ @@ -70,8 +68,8 @@ public String toString() { * @@ -81,27 +79,21 @@ public String toString() { */ public String convertToString(Object value) { String result; + if (value == null) { result = "NULL"; } else { - if (value instanceof Timestamp) { - result = new SimpleDateFormat(P6SpyOptions.getActiveInstance().getDatabaseDialectTimestampFormat()).format(value); - } else if (value instanceof Date) { - result = new SimpleDateFormat(P6SpyOptions.getActiveInstance().getDatabaseDialectDateFormat()).format(value); - } else if (value instanceof Boolean) { - if ("numeric".equals(P6SpyOptions.getActiveInstance().getDatabaseDialectBooleanFormat())) { - result = Boolean.FALSE.equals(value) ? "0" : "1"; - } else { - result = value.toString(); - } - } else if (value instanceof byte[]) { + if (value instanceof byte[]) { // P6LogFactory may not be registered P6LogLoadableOptions logOptions = P6LogOptions.getActiveInstance(); if (logOptions != null && logOptions.getExcludebinary()) { result = "[binary]"; } else { - result = toHexString((byte[]) value); + BinaryFormat binaryFormat = P6SpyOptions.getActiveInstance().getDatabaseDialectBinaryFormatInstance(); + + // return early because BinaryFormat#toString wraps the value in quotes if needed + return binaryFormat.toString((byte[]) value); } // we should not do ((Blob) value).getBinaryStream(). ... @@ -113,6 +105,16 @@ public String convertToString(Object value) { // } else { // result = value.toString(); // } + } else if (value instanceof Timestamp) { + result = new SimpleDateFormat(P6SpyOptions.getActiveInstance().getDatabaseDialectTimestampFormat()).format(value); + } else if (value instanceof Date) { + result = new SimpleDateFormat(P6SpyOptions.getActiveInstance().getDatabaseDialectDateFormat()).format(value); + } else if (value instanceof Boolean) { + if ("numeric".equals(P6SpyOptions.getActiveInstance().getDatabaseDialectBooleanFormat())) { + result = Boolean.FALSE.equals(value) ? "0" : "1"; + } else { + result = value.toString(); + } } else { result = value.toString(); } @@ -123,23 +125,6 @@ public String convertToString(Object value) { return result; } - /** - * @param bytes - * the bytes value to convert to {@link String} - * @return the hexadecimal {@link String} representation of the given - * {@code bytes}. - */ - private String toHexString(byte[] bytes) { - char[] result = new char[bytes.length * 2]; - int idx = 0; - for (byte b : bytes) { - int temp = (int) b & 0xFF; - result[idx++] = HEX_CHARS[temp / 16]; - result[idx++] = HEX_CHARS[temp % 16]; - } - return new String(result); - } - /** * Qoutes the passed {@code stringValue} if it's needed. * @@ -153,7 +138,8 @@ private String quoteIfNeeded(String stringValue, Object obj) { } /* - * The following types do not get quoted: numeric, boolean + * The following types do not get quoted: numeric, boolean. + * Binary data is quoted only if the supplied binaryFormat requires that. * * It is tempting to use ParameterMetaData.getParameterType() for this * purpose as it would be safer. However, this method will fail with some diff --git a/src/main/java/com/p6spy/engine/logging/format/BinaryFormat.java b/src/main/java/com/p6spy/engine/logging/format/BinaryFormat.java new file mode 100644 index 0000000000..a466ee5b4a --- /dev/null +++ b/src/main/java/com/p6spy/engine/logging/format/BinaryFormat.java @@ -0,0 +1,31 @@ +/** + * P6Spy + * + * Copyright (C) 2002 - 2020 P6Spy + * + * 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 com.p6spy.engine.logging.format; + +public interface BinaryFormat { + /** + * Transforms the supplied binary data to a string representation. + * Wraps the value in quotes if the database dialect requires them. + * + * @param input + * the binary data input value to convert to {@link String} + * @return + * the {@link String} representation of the given bytes + */ + public String toString(byte[] input); +} diff --git a/src/main/java/com/p6spy/engine/logging/format/HexEncodedBinaryFormat.java b/src/main/java/com/p6spy/engine/logging/format/HexEncodedBinaryFormat.java new file mode 100644 index 0000000000..05e4870388 --- /dev/null +++ b/src/main/java/com/p6spy/engine/logging/format/HexEncodedBinaryFormat.java @@ -0,0 +1,57 @@ +/** + * P6Spy + * + * Copyright (C) 2002 - 2020 P6Spy + * + * 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 com.p6spy.engine.logging.format; + +/** + * Transforms binary data to hex encoded strings. + */ +public class HexEncodedBinaryFormat implements BinaryFormat { + private static final char[] HEX_CHARS = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', + 'F' }; + + /** + * The space needed for the opening and closing quote character. + */ + private static final int QUOTE_COUNT = 2; + + @Override + public String toString(byte[] input) { + char[] result = new char[QUOTE_COUNT + input.length * 2]; + int i = 0; + result[i++] = '\''; // add opening quote + hexEncode(input, result, i); + result[result.length - 1] = '\''; // add closing quote + return new String(result); + } + + /** + * Hex encodes the supplied input bytes to the supplied output array. + * Writes two {@code char}s of output for every {@code byte} of input. + * @param input the input array + * @param output the output array + * @param outputOffset the offset of the output array to start writing from + */ + static void hexEncode(byte[] input, char[] output, int outputOffset) { + int idx = outputOffset; + for (byte b : input) { + int temp = (int) b & 0xFF; + output[idx++] = HEX_CHARS[temp / 16]; + output[idx++] = HEX_CHARS[temp % 16]; + } + } +} diff --git a/src/main/java/com/p6spy/engine/logging/format/MySQLBinaryFormat.java b/src/main/java/com/p6spy/engine/logging/format/MySQLBinaryFormat.java new file mode 100644 index 0000000000..76fddd6c91 --- /dev/null +++ b/src/main/java/com/p6spy/engine/logging/format/MySQLBinaryFormat.java @@ -0,0 +1,43 @@ +/** + * P6Spy + * + * Copyright (C) 2002 - 2020 P6Spy + * + * 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 com.p6spy.engine.logging.format; + +/** + * Transforms binary data to MySQL hex encoded strings, for example {@code 0x8088BAD639F}. + * Such strings are not quoted when used in queries. + * + * @see MySQL documentation + */ +public class MySQLBinaryFormat implements BinaryFormat { + + /** + * Reserve space for the two prefix chars 0 and x + */ + private static final int PREFIX_LENGTH = 2; + + @Override + public String toString(byte[] input) { + + char[] result = new char[PREFIX_LENGTH + input.length * 2]; + int i = 0; + result[i++] = '0'; + result[i++] = 'x'; + HexEncodedBinaryFormat.hexEncode(input, result, i); + return new String(result); + } +} diff --git a/src/main/java/com/p6spy/engine/logging/format/PostgreSQLBinaryFormat.java b/src/main/java/com/p6spy/engine/logging/format/PostgreSQLBinaryFormat.java new file mode 100644 index 0000000000..3f1bcbe9d4 --- /dev/null +++ b/src/main/java/com/p6spy/engine/logging/format/PostgreSQLBinaryFormat.java @@ -0,0 +1,48 @@ +/** + * P6Spy + * + * Copyright (C) 2002 - 2020 P6Spy + * + * 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 com.p6spy.engine.logging.format; + +/** + * Transforms binary data to PostgreSQL hex encoded strings, for example {@code \x8088BAD639F} + * + * @see PostgreSQL documentation + */ +public class PostgreSQLBinaryFormat implements BinaryFormat { + + /** + * Reserve space for the two prefix chars \ and x + */ + private static final int PREFIX_LENGTH = 2; + + /** + * The space needed for the opening and closing quote character. + */ + private static final int QUOTE_COUNT = 2; + + @Override + public String toString(byte[] input) { + char[] result = new char[PREFIX_LENGTH + QUOTE_COUNT + input.length * 2]; + int i = 0; + result[i++] = '\''; // opening quote + result[i++] = '\\'; // PostgreSQL binary... + result[i++] = 'x'; // ...data prefix + HexEncodedBinaryFormat.hexEncode(input, result, i); + result[result.length - 1] = '\''; // closing quote + return new String(result); + } +} diff --git a/src/main/java/com/p6spy/engine/spy/P6SpyLoadableOptions.java b/src/main/java/com/p6spy/engine/spy/P6SpyLoadableOptions.java index 0af12da7d0..c749726f5a 100644 --- a/src/main/java/com/p6spy/engine/spy/P6SpyLoadableOptions.java +++ b/src/main/java/com/p6spy/engine/spy/P6SpyLoadableOptions.java @@ -19,6 +19,7 @@ import java.util.Set; +import com.p6spy.engine.logging.format.BinaryFormat; import com.p6spy.engine.spy.appender.MessageFormattingStrategy; import com.p6spy.engine.spy.appender.P6Logger; @@ -37,6 +38,12 @@ public interface P6SpyLoadableOptions extends P6LoadableOptions, P6SpyOptionsMBe void setAppend(String append); P6Logger getAppenderInstance(); + + /** + * Gets an instance of the database dialect {@link BinaryFormat} the implementing class of which is + * set by {@link P6SpyOptionsMBean#setDatabaseDialectBinaryFormat}. + */ + BinaryFormat getDatabaseDialectBinaryFormatInstance(); MessageFormattingStrategy getLogMessageFormatInstance(); diff --git a/src/main/java/com/p6spy/engine/spy/P6SpyOptions.java b/src/main/java/com/p6spy/engine/spy/P6SpyOptions.java index 1a812cc3f8..dfc9b00fe6 100644 --- a/src/main/java/com/p6spy/engine/spy/P6SpyOptions.java +++ b/src/main/java/com/p6spy/engine/spy/P6SpyOptions.java @@ -25,6 +25,8 @@ import com.p6spy.engine.common.P6Util; import com.p6spy.engine.logging.P6LogFactory; +import com.p6spy.engine.logging.format.BinaryFormat; +import com.p6spy.engine.logging.format.HexEncodedBinaryFormat; import com.p6spy.engine.spy.appender.*; import com.p6spy.engine.spy.option.P6OptionsRepository; @@ -52,6 +54,8 @@ public class P6SpyOptions extends StandardMBean implements P6SpyLoadableOptions public static final String DATABASE_DIALECT_DATE_FORMAT = "databaseDialectDateFormat"; public static final String DATABASE_DIALECT_TIMESTAMP_FORMAT = "databaseDialectTimestampFormat"; public static final String DATABASE_DIALECT_BOOLEAN_FORMAT = "databaseDialectBooleanFormat"; + public static final String DATABASE_DIALECT_BINARY_FORMAT = "databaseDialectBinaryFormat"; + public static final String DATABASE_DIALECT_BINARY_FORMAT_INSTANCE = "databaseDialectBinaryFormatInstance"; public static final String JMX = "jmx"; public static final String JMX_PREFIX = "jmxPrefix"; @@ -78,6 +82,7 @@ public class P6SpyOptions extends StandardMBean implements P6SpyLoadableOptions defaults.put(DATABASE_DIALECT_DATE_FORMAT, "yyyy-MM-dd'T'HH:mm:ss.SSSZ"); defaults.put(DATABASE_DIALECT_TIMESTAMP_FORMAT, "yyyy-MM-dd'T'HH:mm:ss.SSSZ"); defaults.put(DATABASE_DIALECT_BOOLEAN_FORMAT, "boolean"); + defaults.put(DATABASE_DIALECT_BINARY_FORMAT, HexEncodedBinaryFormat.class.getName()); defaults.put(CUSTOM_LOG_MESSAGE_FORMAT, String.format("%s|%s|%s|connection%s|%s", CustomLineFormat.CURRENT_TIME, CustomLineFormat.EXECUTION_TIME, CustomLineFormat.CATEGORY, CustomLineFormat.CONNECTION_ID, CustomLineFormat.SQL_SINGLE_LINE)); @@ -114,6 +119,7 @@ public void load(Map options) { setDatabaseDialectDateFormat(options.get(DATABASE_DIALECT_DATE_FORMAT)); setDatabaseDialectTimestampFormat(options.get(DATABASE_DIALECT_TIMESTAMP_FORMAT)); setDatabaseDialectBooleanFormat(options.get(DATABASE_DIALECT_BOOLEAN_FORMAT)); + setDatabaseDialectBinaryFormat(options.get(DATABASE_DIALECT_BINARY_FORMAT)); setCustomLogMessageFormat(options.get(CUSTOM_LOG_MESSAGE_FORMAT)); setJmx(options.get(JMX)); setJmxPrefix(options.get(JMX_PREFIX)); @@ -349,6 +355,37 @@ public String getDatabaseDialectBooleanFormat() { public void setDatabaseDialectBooleanFormat(String databaseDialectBooleanFormat) { optionsRepository.set(String.class, DATABASE_DIALECT_BOOLEAN_FORMAT, databaseDialectBooleanFormat); } + + /** + * Returns the class name of the database dialect binary format. + * + * @return String + */ + @Override + public String getDatabaseDialectBinaryFormat() { + return optionsRepository.get(String.class, DATABASE_DIALECT_BINARY_FORMAT); + } + + /** + * Sets the class name of the database dialect binary format. + * + * @param className The class name to set + */ + @Override + public void setDatabaseDialectBinaryFormat(String className) { + optionsRepository.set(String.class, DATABASE_DIALECT_BINARY_FORMAT, className); + optionsRepository.set(BinaryFormat.class, DATABASE_DIALECT_BINARY_FORMAT_INSTANCE, className); + } + + /** + * Returns the class name of the database dialect binary format. + * + * @return String + */ + @Override + public BinaryFormat getDatabaseDialectBinaryFormatInstance() { + return optionsRepository.get(BinaryFormat.class, DATABASE_DIALECT_BINARY_FORMAT_INSTANCE); + } /** * Returns the customLogMessageFormat. diff --git a/src/main/java/com/p6spy/engine/spy/P6SpyOptionsMBean.java b/src/main/java/com/p6spy/engine/spy/P6SpyOptionsMBean.java index 195c817587..7a89005fa5 100644 --- a/src/main/java/com/p6spy/engine/spy/P6SpyOptionsMBean.java +++ b/src/main/java/com/p6spy/engine/spy/P6SpyOptionsMBean.java @@ -97,7 +97,17 @@ public interface P6SpyOptionsMBean { String getDatabaseDialectBooleanFormat(); void setDatabaseDialectBooleanFormat(String databaseDialectBooleanFormat); + + /** + * Gets the class name of the database dialect binary formatter. + */ + String getDatabaseDialectBinaryFormat(); + /** + * Sets the class name of the database dialect binary formatter. + */ + void setDatabaseDialectBinaryFormat(String className); + String getCustomLogMessageFormat(); void setCustomLogMessageFormat(String customLogMessageFormat); diff --git a/src/test/java/com/p6spy/engine/spy/P6TestResultSetWithBinary.java b/src/test/java/com/p6spy/engine/spy/P6TestResultSetWithBinary.java index 3b24deb368..05a089bcd3 100644 --- a/src/test/java/com/p6spy/engine/spy/P6TestResultSetWithBinary.java +++ b/src/test/java/com/p6spy/engine/spy/P6TestResultSetWithBinary.java @@ -34,6 +34,9 @@ import org.junit.runners.Parameterized; import com.p6spy.engine.logging.P6LogOptions; +import com.p6spy.engine.logging.format.HexEncodedBinaryFormat; +import com.p6spy.engine.logging.format.MySQLBinaryFormat; +import com.p6spy.engine.logging.format.PostgreSQLBinaryFormat; import com.p6spy.engine.test.P6TestFramework; @RunWith(Parameterized.class) @@ -42,6 +45,7 @@ public class P6TestResultSetWithBinary extends P6TestFramework { ResultSet resultSet = null; private boolean originalExcludeBinaryFlag; + private String originalDatabaseDialectBinaryFormat; public P6TestResultSetWithBinary(String db) throws SQLException, IOException { super(db); @@ -50,11 +54,13 @@ public P6TestResultSetWithBinary(String db) throws SQLException, IOException { @Before public void before() { this.originalExcludeBinaryFlag = P6LogOptions.getActiveInstance().getExcludebinary(); + this.originalDatabaseDialectBinaryFormat = P6SpyOptions.getActiveInstance().getDatabaseDialectBinaryFormat(); } @After public void after() { P6LogOptions.getActiveInstance().setExcludebinary(this.originalExcludeBinaryFlag); + P6SpyOptions.getActiveInstance().setDatabaseDialectBinaryFormat(this.originalDatabaseDialectBinaryFormat); } @Before @@ -117,10 +123,12 @@ public void binaryExcludedTrue() throws SQLException { @Test public void binaryExcludedFalse() throws SQLException { boolean original = P6LogOptions.getActiveInstance().getExcludebinary(); + String originalBinaryFormat = P6SpyOptions.getActiveInstance().getDatabaseDialectBinaryFormat(); try { // given P6LogOptions.getActiveInstance().setExcludebinary(false); + P6SpyOptions.getActiveInstance().setDatabaseDialectBinaryFormat(HexEncodedBinaryFormat.class.getName()); resultSet.next(); // when @@ -131,6 +139,53 @@ public void binaryExcludedFalse() throws SQLException { assertTrue(super.getLastLogEntry().contains("val = '666F6F'")); } finally { P6LogOptions.getActiveInstance().setExcludebinary(original); + P6SpyOptions.getActiveInstance().setDatabaseDialectBinaryFormat(originalBinaryFormat); + } + } + + @Test + public void postgreSQLBinaryFormat() throws SQLException { + boolean originalExclude = P6LogOptions.getActiveInstance().getExcludebinary(); + String originalBinaryFormat = P6SpyOptions.getActiveInstance().getDatabaseDialectBinaryFormat(); + + try { + // given + P6LogOptions.getActiveInstance().setExcludebinary(false); + P6SpyOptions.getActiveInstance().setDatabaseDialectBinaryFormat(PostgreSQLBinaryFormat.class.getName()); + resultSet.next(); + + // when + resultSet.getBytes("val"); + resultSet.next(); + + // then + assertTrue(super.getLastLogEntry().contains("val = '\\x666F6F'")); + } finally { + P6LogOptions.getActiveInstance().setExcludebinary(originalExclude); + P6SpyOptions.getActiveInstance().setDatabaseDialectBinaryFormat(originalBinaryFormat); + } + } + + @Test + public void mySQLBinaryFormat() throws SQLException { + boolean originalExclude = P6LogOptions.getActiveInstance().getExcludebinary(); + String originalBinaryFormat = P6SpyOptions.getActiveInstance().getDatabaseDialectBinaryFormat(); + + try { + // given + P6LogOptions.getActiveInstance().setExcludebinary(false); + P6SpyOptions.getActiveInstance().setDatabaseDialectBinaryFormat(MySQLBinaryFormat.class.getName()); + resultSet.next(); + + // when + resultSet.getBytes("val"); + resultSet.next(); + + // then + assertTrue(super.getLastLogEntry().contains("val = 0x666F6F")); + } finally { + P6LogOptions.getActiveInstance().setExcludebinary(originalExclude); + P6SpyOptions.getActiveInstance().setDatabaseDialectBinaryFormat(originalBinaryFormat); } }