From 0f19a087573a3b7351c6d32e31cd4f7f95c89251 Mon Sep 17 00:00:00 2001 From: Scott Leberknight <174812+sleberknight@users.noreply.github.com> Date: Sat, 7 Oct 2023 16:55:20 -0400 Subject: [PATCH] Add long-to-boolean conversion methods to KiwiJdbc * Add overloaded booleanFromLong methods. Both accept a ResultSet and a String columnName, but one accepts a BooleanConversionOption argument while the other doesn't. The one that does not accept a BooleanConversionOption uses the ZERO_OR_ONE option. Closes #1045 --- .../java/org/kiwiproject/jdbc/KiwiJdbc.java | 32 ++++++++++ .../org/kiwiproject/jdbc/KiwiJdbcTest.java | 62 +++++++++++++++++++ 2 files changed, 94 insertions(+) diff --git a/src/main/java/org/kiwiproject/jdbc/KiwiJdbc.java b/src/main/java/org/kiwiproject/jdbc/KiwiJdbc.java index f947e0af..049bbeae 100644 --- a/src/main/java/org/kiwiproject/jdbc/KiwiJdbc.java +++ b/src/main/java/org/kiwiproject/jdbc/KiwiJdbc.java @@ -5,6 +5,8 @@ import lombok.experimental.UtilityClass; import org.checkerframework.checker.nullness.qual.Nullable; +import org.kiwiproject.base.KiwiPrimitives; +import org.kiwiproject.base.KiwiPrimitives.BooleanConversionOption; import java.sql.PreparedStatement; import java.sql.ResultSet; @@ -301,6 +303,36 @@ public static > Optional enumValueOrEmpty(ResultSet rs, Str return isNull(enumName) ? Optional.empty() : Optional.of(Enum.valueOf(enumType, enumName)); } + /** + * Converts a long value in the specified column to a boolean. The database value must be zero, one + * or NULL. + * + * @param rs the ResultSet + * @param columnName the column name + * @return true if the database value is one, or false if it is zero or NULL + * @throws IllegalArgumentException if the value in the column is not zero, one, or NULL + * @throws SQLException if there is any error getting the value from the database + * @see #booleanFromLong(ResultSet, String, BooleanConversionOption) + */ + public static boolean booleanFromLong(ResultSet rs, String columnName) throws SQLException { + return booleanFromLong(rs, columnName, BooleanConversionOption.ZERO_OR_ONE); + } + + /** + * Converts a long value in the specified column to a boolean using the given {@link BooleanConversionOption}. + * + * @param rs the ResultSet + * @param columnName the column name + * @param option how to convert the long value into a boolean + * @return the converted value, determined using the conversion option + * @throws SQLException if there is any error getting the value from the database + */ + public static boolean booleanFromLong(ResultSet rs, String columnName, BooleanConversionOption option) + throws SQLException { + + return KiwiPrimitives.booleanFromLong(rs.getLong(columnName), option); + } + /** * Sets the {@link Timestamp} value in a null-safe manner by using the {@link PreparedStatement#setNull(int, int)} * method for {@code null} values. Uses {@link Types#TIMESTAMP} as the SQL type. diff --git a/src/test/java/org/kiwiproject/jdbc/KiwiJdbcTest.java b/src/test/java/org/kiwiproject/jdbc/KiwiJdbcTest.java index 4e03ca8b..7568b1e8 100644 --- a/src/test/java/org/kiwiproject/jdbc/KiwiJdbcTest.java +++ b/src/test/java/org/kiwiproject/jdbc/KiwiJdbcTest.java @@ -12,7 +12,10 @@ import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.Test; import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.CsvSource; import org.junit.jupiter.params.provider.EnumSource; +import org.junit.jupiter.params.provider.ValueSource; +import org.kiwiproject.base.KiwiPrimitives.BooleanConversionOption; import java.sql.PreparedStatement; import java.sql.ResultSet; @@ -526,6 +529,65 @@ enum Season { WINTER, SPRING, SUMMER, FALL } + @Nested + class BooleanFromLong { + + @ParameterizedTest + @CsvSource(textBlock = """ + 1, true, + 0, false + """) + void shouldConvert_WithZeroOrOneConversionOption(long value, boolean expectedResult) throws SQLException { + var resultSet = newMockResultSet(); + when(resultSet.getLong(anyString())).thenReturn(value); + + assertThat(KiwiJdbc.booleanFromLong(resultSet, "is_admin")) + .isEqualTo(expectedResult); + + verify(resultSet).getLong("is_admin"); + verifyNoMoreInteractions(resultSet); + } + + @ParameterizedTest + @ValueSource(longs = { -1, 2, 4, 42 }) + void shouldThrowIllegalArgument_WhenValueFromResultSet_IsNotZeroOrOne_WithZeroOrOneConversionOption(long value) + throws SQLException { + + var resultSet = newMockResultSet(); + when(resultSet.getLong(anyString())).thenReturn(value); + + assertThatIllegalArgumentException() + .isThrownBy(() -> KiwiJdbc.booleanFromLong(resultSet, "is_active")) + .withMessage("value must be 0 or 1, but found %d", value); + + verify(resultSet).getLong("is_active"); + verifyNoMoreInteractions(resultSet); + } + + @ParameterizedTest + @CsvSource(textBlock = """ + 1, ZERO_OR_ONE, true, + 1, NON_ZERO_AS_TRUE, true, + -1, NON_ZERO_AS_TRUE, true, + 2, NON_ZERO_AS_TRUE, true, + 1000, NON_ZERO_AS_TRUE, true, + 0, ZERO_OR_ONE, false, + 0, NON_ZERO_AS_TRUE, false + """) + void shouldConvert_WithBooleanConversionOption(long value, + BooleanConversionOption option, + boolean expectedResult) throws SQLException { + var resultSet = newMockResultSet(); + when(resultSet.getLong(anyString())).thenReturn(value); + + assertThat(KiwiJdbc.booleanFromLong(resultSet, "is_admin", option)) + .isEqualTo(expectedResult); + + verify(resultSet).getLong("is_admin"); + verifyNoMoreInteractions(resultSet); + } + } + @Nested class NullSafeSetInt {