From c091335358030c18cd2a6fdac8a7912d186c0d14 Mon Sep 17 00:00:00 2001 From: Ram Sin Date: Mon, 21 Oct 2024 12:15:32 +1100 Subject: [PATCH 01/10] Changed BooleanCodec/Test --- .../r2dbc/mysql/codec/BooleanCodec.java | 17 ++++++++-- .../r2dbc/mysql/codec/BooleanCodecTest.java | 32 +++++++++++++++++++ 2 files changed, 46 insertions(+), 3 deletions(-) diff --git a/r2dbc-mysql/src/main/java/io/asyncer/r2dbc/mysql/codec/BooleanCodec.java b/r2dbc-mysql/src/main/java/io/asyncer/r2dbc/mysql/codec/BooleanCodec.java index f546ba751..a51dd937d 100644 --- a/r2dbc-mysql/src/main/java/io/asyncer/r2dbc/mysql/codec/BooleanCodec.java +++ b/r2dbc-mysql/src/main/java/io/asyncer/r2dbc/mysql/codec/BooleanCodec.java @@ -38,7 +38,18 @@ private BooleanCodec() { @Override public Boolean decode(ByteBuf value, MySqlReadableMetadata metadata, Class target, boolean binary, CodecContext context) { - return binary || metadata.getType() == MySqlType.BIT ? value.readBoolean() : value.readByte() != '0'; + MySqlType dataType = metadata.getType(); + if (dataType == MySqlType.VARCHAR) { + if (value.isReadable()) { + String stringVal = value.toString(metadata.getCharCollation(context).getCharset()); + if (stringVal.equalsIgnoreCase("true") || stringVal.equals("1")) { + return true; + } else if (stringVal.equalsIgnoreCase("false") || stringVal.equals("0")) { + return false; + } + } + } + return binary || dataType == MySqlType.BIT ? value.readBoolean() : value.readByte() != '0'; } @Override @@ -54,8 +65,8 @@ public MySqlParameter encode(Object value, CodecContext context) { @Override public boolean doCanDecode(MySqlReadableMetadata metadata) { MySqlType type = metadata.getType(); - return (type == MySqlType.BIT || type == MySqlType.TINYINT) && - Integer.valueOf(1).equals(metadata.getPrecision()); + return ((type == MySqlType.BIT || type == MySqlType.TINYINT) && + Integer.valueOf(1).equals(metadata.getPrecision())) || type == MySqlType.VARCHAR; } private static final class BooleanMySqlParameter extends AbstractMySqlParameter { diff --git a/r2dbc-mysql/src/test/java/io/asyncer/r2dbc/mysql/codec/BooleanCodecTest.java b/r2dbc-mysql/src/test/java/io/asyncer/r2dbc/mysql/codec/BooleanCodecTest.java index 999111de5..85955e731 100644 --- a/r2dbc-mysql/src/test/java/io/asyncer/r2dbc/mysql/codec/BooleanCodecTest.java +++ b/r2dbc-mysql/src/test/java/io/asyncer/r2dbc/mysql/codec/BooleanCodecTest.java @@ -16,12 +16,18 @@ package io.asyncer.r2dbc.mysql.codec; +import io.asyncer.r2dbc.mysql.ConnectionContextTest; +import io.asyncer.r2dbc.mysql.constant.MySqlType; import io.netty.buffer.ByteBuf; import io.netty.buffer.Unpooled; +import static org.assertj.core.api.Assertions.assertThat; + import java.nio.charset.Charset; import java.util.Arrays; +import org.junit.jupiter.api.Test; + /** * Unit tests for {@link BooleanCodec}. */ @@ -55,4 +61,30 @@ public ByteBuf[] binaryParameters(Charset charset) { public ByteBuf sized(ByteBuf value) { return value; } + + @Test + void decodeString() { + Codec codec = getCodec(); + Charset c = ConnectionContextTest.mock().getClientCollation().getCharset(); + Decoding d1 = new Decoding(Unpooled.copiedBuffer("true", c), "true", MySqlType.VARCHAR); + Decoding d2 = new Decoding(Unpooled.copiedBuffer("false", c), "false", MySqlType.VARCHAR); + Decoding d3 = new Decoding(Unpooled.copiedBuffer("1", c), "1", MySqlType.VARCHAR); + Decoding d4 = new Decoding(Unpooled.copiedBuffer("0", c), "0", MySqlType.VARCHAR); + + assertThat(codec.decode(d1.content(), d1.metadata(), Boolean.class, false, ConnectionContextTest.mock())) + .as("Decode failed, %s", d1) + .isEqualTo(true); + + assertThat(codec.decode(d2.content(), d2.metadata(), Boolean.class, false, ConnectionContextTest.mock())) + .as("Decode failed, %s", d2) + .isEqualTo(false); + + assertThat(codec.decode(d3.content(), d3.metadata(), Boolean.class, false, ConnectionContextTest.mock())) + .as("Decode failed, %s", d3) + .isEqualTo(true); + + assertThat(codec.decode(d4.content(), d4.metadata(), Boolean.class, false, ConnectionContextTest.mock())) + .as("Decode failed, %s", d4) + .isEqualTo(false); + } } From a0a0820f2a36555da0d6b3702a6074fc134d4204 Mon Sep 17 00:00:00 2001 From: Ram Sin Date: Mon, 18 Nov 2024 15:45:19 +1100 Subject: [PATCH 02/10] Changed decode to align with mysql connector/j --- .../r2dbc/mysql/codec/BooleanCodec.java | 46 ++++++++++++++----- .../r2dbc/mysql/codec/BooleanCodecTest.java | 36 +++++++++++++++ 2 files changed, 70 insertions(+), 12 deletions(-) diff --git a/r2dbc-mysql/src/main/java/io/asyncer/r2dbc/mysql/codec/BooleanCodec.java b/r2dbc-mysql/src/main/java/io/asyncer/r2dbc/mysql/codec/BooleanCodec.java index a51dd937d..30c8e076e 100644 --- a/r2dbc-mysql/src/main/java/io/asyncer/r2dbc/mysql/codec/BooleanCodec.java +++ b/r2dbc-mysql/src/main/java/io/asyncer/r2dbc/mysql/codec/BooleanCodec.java @@ -16,6 +16,8 @@ package io.asyncer.r2dbc.mysql.codec; +import java.math.BigInteger; + import io.asyncer.r2dbc.mysql.MySqlParameter; import io.asyncer.r2dbc.mysql.ParameterWriter; import io.asyncer.r2dbc.mysql.api.MySqlReadableMetadata; @@ -38,18 +40,27 @@ private BooleanCodec() { @Override public Boolean decode(ByteBuf value, MySqlReadableMetadata metadata, Class target, boolean binary, CodecContext context) { - MySqlType dataType = metadata.getType(); - if (dataType == MySqlType.VARCHAR) { - if (value.isReadable()) { - String stringVal = value.toString(metadata.getCharCollation(context).getCharset()); - if (stringVal.equalsIgnoreCase("true") || stringVal.equals("1")) { - return true; - } else if (stringVal.equalsIgnoreCase("false") || stringVal.equals("0")) { - return false; - } + if (!value.isReadable()) { + return createFromLong(0); + } + + String s = value.toString(metadata.getCharCollation(context).getCharset()); + + if (s.equalsIgnoreCase("Y") || s.equalsIgnoreCase("yes") || + s.equalsIgnoreCase("T") || s.equalsIgnoreCase("true")) { + return createFromLong(1); + } else if (s.equalsIgnoreCase("N") || s.equalsIgnoreCase("no") || + s.equalsIgnoreCase("F") || s.equalsIgnoreCase("false")) { + return createFromLong(0); + } else if (s.contains("e") || s.contains("E") || s.matches("-?\\d*\\.\\d*")) { + return createFromDouble(Double.parseDouble(s)); + } else if (s.matches("-?\\d+")) { + if (!CodecUtils.isGreaterThanLongMax(s)) { + return createFromLong(CodecUtils.parseLong(value)); } + return createFromBigInteger(new BigInteger(s)); } - return binary || dataType == MySqlType.BIT ? value.readBoolean() : value.readByte() != '0'; + throw new IllegalArgumentException("Unable to interpret string: " + s); } @Override @@ -65,8 +76,19 @@ public MySqlParameter encode(Object value, CodecContext context) { @Override public boolean doCanDecode(MySqlReadableMetadata metadata) { MySqlType type = metadata.getType(); - return ((type == MySqlType.BIT || type == MySqlType.TINYINT) && - Integer.valueOf(1).equals(metadata.getPrecision())) || type == MySqlType.VARCHAR; + return type == MySqlType.BIT || type == MySqlType.VARCHAR || type.isNumeric(); + } + + public Boolean createFromLong(long l) { + return (l == -1 || l > 0); + } + + public Boolean createFromDouble(double d) { + return (d == -1.0d || d > 0); + } + + public Boolean createFromBigInteger(BigInteger b) { + return b.compareTo(BigInteger.valueOf(0)) > 0 || b.compareTo(BigInteger.valueOf(-1)) == 0; } private static final class BooleanMySqlParameter extends AbstractMySqlParameter { diff --git a/r2dbc-mysql/src/test/java/io/asyncer/r2dbc/mysql/codec/BooleanCodecTest.java b/r2dbc-mysql/src/test/java/io/asyncer/r2dbc/mysql/codec/BooleanCodecTest.java index 85955e731..9e32bc74f 100644 --- a/r2dbc-mysql/src/test/java/io/asyncer/r2dbc/mysql/codec/BooleanCodecTest.java +++ b/r2dbc-mysql/src/test/java/io/asyncer/r2dbc/mysql/codec/BooleanCodecTest.java @@ -22,6 +22,7 @@ import io.netty.buffer.Unpooled; import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; import java.nio.charset.Charset; import java.util.Arrays; @@ -70,6 +71,14 @@ void decodeString() { Decoding d2 = new Decoding(Unpooled.copiedBuffer("false", c), "false", MySqlType.VARCHAR); Decoding d3 = new Decoding(Unpooled.copiedBuffer("1", c), "1", MySqlType.VARCHAR); Decoding d4 = new Decoding(Unpooled.copiedBuffer("0", c), "0", MySqlType.VARCHAR); + Decoding d5 = new Decoding(Unpooled.copiedBuffer("Y", c), "Y", MySqlType.VARCHAR); + Decoding d6 = new Decoding(Unpooled.copiedBuffer("no", c), "no", MySqlType.VARCHAR); + Decoding d7 = new Decoding(Unpooled.copyDouble(26.57d), 26.57d, MySqlType.DOUBLE); + Decoding d8 = new Decoding(Unpooled.copyLong(-57L), -57L, MySqlType.TINYINT); + Decoding d9 = new Decoding(Unpooled.copyLong(100000L), 100000L, MySqlType.BIGINT); + Decoding d10 = new Decoding(Unpooled.copiedBuffer("-12345678901234567890", c), + "-12345678901234567890", MySqlType.VARCHAR); + Decoding d11 = new Decoding(Unpooled.copiedBuffer("Banana", c), "Banana", MySqlType.VARCHAR); assertThat(codec.decode(d1.content(), d1.metadata(), Boolean.class, false, ConnectionContextTest.mock())) .as("Decode failed, %s", d1) @@ -86,5 +95,32 @@ void decodeString() { assertThat(codec.decode(d4.content(), d4.metadata(), Boolean.class, false, ConnectionContextTest.mock())) .as("Decode failed, %s", d4) .isEqualTo(false); + + assertThat(codec.decode(d5.content(), d5.metadata(), Boolean.class, false, ConnectionContextTest.mock())) + .as("Decode failed, %s", d5) + .isEqualTo(true); + + assertThat(codec.decode(d6.content(), d6.metadata(), Boolean.class, false, ConnectionContextTest.mock())) + .as("Decode failed, %s", d6) + .isEqualTo(false); + + assertThat(codec.decode(d7.content(), d7.metadata(), Boolean.class, false, ConnectionContextTest.mock())) + .as("Decode failed, %s", d7) + .isEqualTo(true); + + assertThat(codec.decode(d8.content(), d8.metadata(), Boolean.class, false, ConnectionContextTest.mock())) + .as("Decode failed, %s", d8) + .isEqualTo(false); + + assertThat(codec.decode(d9.content(), d9.metadata(), Boolean.class, false, ConnectionContextTest.mock())) + .as("Decode failed, %s", d9) + .isEqualTo(true); + + assertThat(codec.decode(d10.content(), d10.metadata(), Boolean.class, false, ConnectionContextTest.mock())) + .as("Decode failed, %s", d10) + .isEqualTo(false); + + assertThatThrownBy(() -> {codec.decode(d11.content(), d11.metadata(), Boolean.class, false, ConnectionContextTest.mock());}) + .isInstanceOf(IllegalArgumentException.class); } } From 0e96856a9f23b68104e06935306f425ef4ad1073 Mon Sep 17 00:00:00 2001 From: Ram Sin Date: Mon, 18 Nov 2024 15:49:56 +1100 Subject: [PATCH 03/10] Changed decode to align with mysql connector/j --- .../main/java/io/asyncer/r2dbc/mysql/codec/BooleanCodec.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/r2dbc-mysql/src/main/java/io/asyncer/r2dbc/mysql/codec/BooleanCodec.java b/r2dbc-mysql/src/main/java/io/asyncer/r2dbc/mysql/codec/BooleanCodec.java index 30c8e076e..c8f641ccb 100644 --- a/r2dbc-mysql/src/main/java/io/asyncer/r2dbc/mysql/codec/BooleanCodec.java +++ b/r2dbc-mysql/src/main/java/io/asyncer/r2dbc/mysql/codec/BooleanCodec.java @@ -46,10 +46,10 @@ public Boolean decode(ByteBuf value, MySqlReadableMetadata metadata, Class ta String s = value.toString(metadata.getCharCollation(context).getCharset()); - if (s.equalsIgnoreCase("Y") || s.equalsIgnoreCase("yes") || + if (s.equalsIgnoreCase("Y") || s.equalsIgnoreCase("yes") || s.equalsIgnoreCase("T") || s.equalsIgnoreCase("true")) { return createFromLong(1); - } else if (s.equalsIgnoreCase("N") || s.equalsIgnoreCase("no") || + } else if (s.equalsIgnoreCase("N") || s.equalsIgnoreCase("no") || s.equalsIgnoreCase("F") || s.equalsIgnoreCase("false")) { return createFromLong(0); } else if (s.contains("e") || s.contains("E") || s.matches("-?\\d*\\.\\d*")) { From 9300ce244cab4e128e803c1de66a3cb9e74c4745 Mon Sep 17 00:00:00 2001 From: Ram Sin Date: Mon, 18 Nov 2024 15:58:20 +1100 Subject: [PATCH 04/10] Changed decode to align with mysql connector/j --- .../java/io/asyncer/r2dbc/mysql/codec/BooleanCodecTest.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/r2dbc-mysql/src/test/java/io/asyncer/r2dbc/mysql/codec/BooleanCodecTest.java b/r2dbc-mysql/src/test/java/io/asyncer/r2dbc/mysql/codec/BooleanCodecTest.java index 9e32bc74f..141467105 100644 --- a/r2dbc-mysql/src/test/java/io/asyncer/r2dbc/mysql/codec/BooleanCodecTest.java +++ b/r2dbc-mysql/src/test/java/io/asyncer/r2dbc/mysql/codec/BooleanCodecTest.java @@ -73,9 +73,9 @@ void decodeString() { Decoding d4 = new Decoding(Unpooled.copiedBuffer("0", c), "0", MySqlType.VARCHAR); Decoding d5 = new Decoding(Unpooled.copiedBuffer("Y", c), "Y", MySqlType.VARCHAR); Decoding d6 = new Decoding(Unpooled.copiedBuffer("no", c), "no", MySqlType.VARCHAR); - Decoding d7 = new Decoding(Unpooled.copyDouble(26.57d), 26.57d, MySqlType.DOUBLE); - Decoding d8 = new Decoding(Unpooled.copyLong(-57L), -57L, MySqlType.TINYINT); - Decoding d9 = new Decoding(Unpooled.copyLong(100000L), 100000L, MySqlType.BIGINT); + Decoding d7 = new Decoding(Unpooled.copyDouble(26.57), 26.57, MySqlType.DOUBLE); + Decoding d8 = new Decoding(Unpooled.copyLong(-57), -57, MySqlType.TINYINT); + Decoding d9 = new Decoding(Unpooled.copyLong(100000), 100000, MySqlType.BIGINT); Decoding d10 = new Decoding(Unpooled.copiedBuffer("-12345678901234567890", c), "-12345678901234567890", MySqlType.VARCHAR); Decoding d11 = new Decoding(Unpooled.copiedBuffer("Banana", c), "Banana", MySqlType.VARCHAR); From 074dcc87d8bfda93ee8d90de110d55a173b9ea3a Mon Sep 17 00:00:00 2001 From: Ram Sin Date: Fri, 22 Nov 2024 19:13:32 +1100 Subject: [PATCH 05/10] Altered boolean decode --- .../r2dbc/mysql/codec/BooleanCodec.java | 45 +++++++++++-------- .../r2dbc/mysql/codec/BooleanCodecTest.java | 37 +++++++++++++-- 2 files changed, 60 insertions(+), 22 deletions(-) diff --git a/r2dbc-mysql/src/main/java/io/asyncer/r2dbc/mysql/codec/BooleanCodec.java b/r2dbc-mysql/src/main/java/io/asyncer/r2dbc/mysql/codec/BooleanCodec.java index c8f641ccb..15dbdc19d 100644 --- a/r2dbc-mysql/src/main/java/io/asyncer/r2dbc/mysql/codec/BooleanCodec.java +++ b/r2dbc-mysql/src/main/java/io/asyncer/r2dbc/mysql/codec/BooleanCodec.java @@ -40,27 +40,33 @@ private BooleanCodec() { @Override public Boolean decode(ByteBuf value, MySqlReadableMetadata metadata, Class target, boolean binary, CodecContext context) { - if (!value.isReadable()) { - return createFromLong(0); - } + MySqlType dataType = metadata.getType(); + + if (dataType == MySqlType.VARCHAR) { + if (!value.isReadable()) { + return createFromLong(0); + } - String s = value.toString(metadata.getCharCollation(context).getCharset()); - - if (s.equalsIgnoreCase("Y") || s.equalsIgnoreCase("yes") || - s.equalsIgnoreCase("T") || s.equalsIgnoreCase("true")) { - return createFromLong(1); - } else if (s.equalsIgnoreCase("N") || s.equalsIgnoreCase("no") || - s.equalsIgnoreCase("F") || s.equalsIgnoreCase("false")) { - return createFromLong(0); - } else if (s.contains("e") || s.contains("E") || s.matches("-?\\d*\\.\\d*")) { - return createFromDouble(Double.parseDouble(s)); - } else if (s.matches("-?\\d+")) { - if (!CodecUtils.isGreaterThanLongMax(s)) { - return createFromLong(CodecUtils.parseLong(value)); + String s = value.toString(metadata.getCharCollation(context).getCharset()); + + if (s.equalsIgnoreCase("Y") || s.equalsIgnoreCase("yes") || + s.equalsIgnoreCase("T") || s.equalsIgnoreCase("true")) { + return createFromLong(1); + } else if (s.equalsIgnoreCase("N") || s.equalsIgnoreCase("no") || + s.equalsIgnoreCase("F") || s.equalsIgnoreCase("false")) { + return createFromLong(0); + } else if (s.contains("e") || s.contains("E") || s.matches("-?\\d*\\.\\d*")) { + return createFromDouble(Double.parseDouble(s)); + } else if (s.matches("-?\\d+")) { + if (!CodecUtils.isGreaterThanLongMax(s)) { + return createFromLong(CodecUtils.parseLong(value)); + } + return createFromBigInteger(new BigInteger(s)); } - return createFromBigInteger(new BigInteger(s)); + throw new IllegalArgumentException("Unable to interpret string: " + s); } - throw new IllegalArgumentException("Unable to interpret string: " + s); + + return binary || dataType == MySqlType.BIT ? value.readBoolean() : value.readByte() != '0'; } @Override @@ -76,7 +82,8 @@ public MySqlParameter encode(Object value, CodecContext context) { @Override public boolean doCanDecode(MySqlReadableMetadata metadata) { MySqlType type = metadata.getType(); - return type == MySqlType.BIT || type == MySqlType.VARCHAR || type.isNumeric(); + return ((type == MySqlType.BIT || type == MySqlType.TINYINT) && + Integer.valueOf(1).equals(metadata.getPrecision())) || type == MySqlType.VARCHAR; } public Boolean createFromLong(long l) { diff --git a/r2dbc-mysql/src/test/java/io/asyncer/r2dbc/mysql/codec/BooleanCodecTest.java b/r2dbc-mysql/src/test/java/io/asyncer/r2dbc/mysql/codec/BooleanCodecTest.java index 141467105..3150bb37f 100644 --- a/r2dbc-mysql/src/test/java/io/asyncer/r2dbc/mysql/codec/BooleanCodecTest.java +++ b/r2dbc-mysql/src/test/java/io/asyncer/r2dbc/mysql/codec/BooleanCodecTest.java @@ -29,6 +29,8 @@ import org.junit.jupiter.api.Test; +import java.nio.ByteBuffer; + /** * Unit tests for {@link BooleanCodec}. */ @@ -67,18 +69,27 @@ public ByteBuf sized(ByteBuf value) { void decodeString() { Codec codec = getCodec(); Charset c = ConnectionContextTest.mock().getClientCollation().getCharset(); + byte[] bOne = new byte[]{(byte)1}; + byte[] bZero = new byte[]{(byte)0}; + ByteBuffer bitValOne = ByteBuffer.wrap(bOne); + ByteBuffer bitValZero = ByteBuffer.wrap(bZero); Decoding d1 = new Decoding(Unpooled.copiedBuffer("true", c), "true", MySqlType.VARCHAR); Decoding d2 = new Decoding(Unpooled.copiedBuffer("false", c), "false", MySqlType.VARCHAR); Decoding d3 = new Decoding(Unpooled.copiedBuffer("1", c), "1", MySqlType.VARCHAR); Decoding d4 = new Decoding(Unpooled.copiedBuffer("0", c), "0", MySqlType.VARCHAR); Decoding d5 = new Decoding(Unpooled.copiedBuffer("Y", c), "Y", MySqlType.VARCHAR); Decoding d6 = new Decoding(Unpooled.copiedBuffer("no", c), "no", MySqlType.VARCHAR); - Decoding d7 = new Decoding(Unpooled.copyDouble(26.57), 26.57, MySqlType.DOUBLE); - Decoding d8 = new Decoding(Unpooled.copyLong(-57), -57, MySqlType.TINYINT); - Decoding d9 = new Decoding(Unpooled.copyLong(100000), 100000, MySqlType.BIGINT); + Decoding d7 = new Decoding(Unpooled.copiedBuffer("26.57", c), "26.57", MySqlType.VARCHAR); + Decoding d8 = new Decoding(Unpooled.copiedBuffer("-57", c), "=57", MySqlType.VARCHAR); + Decoding d9 = new Decoding(Unpooled.copiedBuffer("100000", c), "100000", MySqlType.VARCHAR); Decoding d10 = new Decoding(Unpooled.copiedBuffer("-12345678901234567890", c), "-12345678901234567890", MySqlType.VARCHAR); Decoding d11 = new Decoding(Unpooled.copiedBuffer("Banana", c), "Banana", MySqlType.VARCHAR); + Decoding d12 = new Decoding(Unpooled.copiedBuffer(bitValOne), bitValOne, MySqlType.BIT); + Decoding d13 = new Decoding(Unpooled.copiedBuffer(bitValZero), bitValZero, MySqlType.BIT); + Decoding d14 = new Decoding(Unpooled.copyDouble(26.57d), 26.57d, MySqlType.DOUBLE); + Decoding d15 = new Decoding(Unpooled.copiedBuffer(bOne), bOne, MySqlType.TINYINT); + Decoding d16 = new Decoding(Unpooled.copiedBuffer(bZero), bZero, MySqlType.TINYINT); assertThat(codec.decode(d1.content(), d1.metadata(), Boolean.class, false, ConnectionContextTest.mock())) .as("Decode failed, %s", d1) @@ -122,5 +133,25 @@ void decodeString() { assertThatThrownBy(() -> {codec.decode(d11.content(), d11.metadata(), Boolean.class, false, ConnectionContextTest.mock());}) .isInstanceOf(IllegalArgumentException.class); + + assertThat(codec.decode(d12.content(), d12.metadata(), Boolean.class, false, ConnectionContextTest.mock())) + .as("Decode failed, %s", d12) + .isEqualTo(true); + + assertThat(codec.decode(d13.content(), d13.metadata(), Boolean.class, false, ConnectionContextTest.mock())) + .as("Decode failed, %s", d13) + .isEqualTo(false); + + assertThat(codec.decode(d14.content(), d14.metadata(), Boolean.class, false, ConnectionContextTest.mock())) + .as("Decode failed, %s", d14) + .isEqualTo(true); + + assertThat(codec.decode(d15.content(), d15.metadata(), Boolean.class, true, ConnectionContextTest.mock())) + .as("Decode failed, %s", d15) + .isEqualTo(true); + + assertThat(codec.decode(d16.content(), d16.metadata(), Boolean.class, true, ConnectionContextTest.mock())) + .as("Decode failed, %s", d14) + .isEqualTo(false); } } From cc94d63253fd10a1e7d088c0a92c74d2ca6ba3de Mon Sep 17 00:00:00 2001 From: Ram Sin Date: Fri, 22 Nov 2024 19:16:40 +1100 Subject: [PATCH 06/10] Altered boolean decode --- .../main/java/io/asyncer/r2dbc/mysql/codec/BooleanCodec.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/r2dbc-mysql/src/main/java/io/asyncer/r2dbc/mysql/codec/BooleanCodec.java b/r2dbc-mysql/src/main/java/io/asyncer/r2dbc/mysql/codec/BooleanCodec.java index 15dbdc19d..877fb4cab 100644 --- a/r2dbc-mysql/src/main/java/io/asyncer/r2dbc/mysql/codec/BooleanCodec.java +++ b/r2dbc-mysql/src/main/java/io/asyncer/r2dbc/mysql/codec/BooleanCodec.java @@ -65,7 +65,7 @@ public Boolean decode(ByteBuf value, MySqlReadableMetadata metadata, Class ta } throw new IllegalArgumentException("Unable to interpret string: " + s); } - + return binary || dataType == MySqlType.BIT ? value.readBoolean() : value.readByte() != '0'; } From 9d050080ce552c283678e78ec7b3db0e51914d90 Mon Sep 17 00:00:00 2001 From: Ram Sin Date: Fri, 22 Nov 2024 20:09:09 +1100 Subject: [PATCH 07/10] Altered boolean decode --- .../main/java/io/asyncer/r2dbc/mysql/codec/BooleanCodec.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/r2dbc-mysql/src/main/java/io/asyncer/r2dbc/mysql/codec/BooleanCodec.java b/r2dbc-mysql/src/main/java/io/asyncer/r2dbc/mysql/codec/BooleanCodec.java index 877fb4cab..07978ac64 100644 --- a/r2dbc-mysql/src/main/java/io/asyncer/r2dbc/mysql/codec/BooleanCodec.java +++ b/r2dbc-mysql/src/main/java/io/asyncer/r2dbc/mysql/codec/BooleanCodec.java @@ -55,7 +55,7 @@ public Boolean decode(ByteBuf value, MySqlReadableMetadata metadata, Class ta } else if (s.equalsIgnoreCase("N") || s.equalsIgnoreCase("no") || s.equalsIgnoreCase("F") || s.equalsIgnoreCase("false")) { return createFromLong(0); - } else if (s.contains("e") || s.contains("E") || s.matches("-?\\d*\\.\\d*")) { + } else if (s.matches("-?\\d*\\.\\d*") || s.matches("-?\\d*\\.\\d+[eE]-?\\d+")) { return createFromDouble(Double.parseDouble(s)); } else if (s.matches("-?\\d+")) { if (!CodecUtils.isGreaterThanLongMax(s)) { From 2186982f534ee077b19f2a917b699aa8eeb61ebc Mon Sep 17 00:00:00 2001 From: Ram Sin Date: Fri, 29 Nov 2024 19:25:08 +1100 Subject: [PATCH 08/10] Added tests, changed exception --- .../asyncer/r2dbc/mysql/codec/BooleanCodec.java | 7 +++++-- .../r2dbc/mysql/codec/BooleanCodecTest.java | 17 ++++++++++++++++- 2 files changed, 21 insertions(+), 3 deletions(-) diff --git a/r2dbc-mysql/src/main/java/io/asyncer/r2dbc/mysql/codec/BooleanCodec.java b/r2dbc-mysql/src/main/java/io/asyncer/r2dbc/mysql/codec/BooleanCodec.java index 07978ac64..59ed42579 100644 --- a/r2dbc-mysql/src/main/java/io/asyncer/r2dbc/mysql/codec/BooleanCodec.java +++ b/r2dbc-mysql/src/main/java/io/asyncer/r2dbc/mysql/codec/BooleanCodec.java @@ -24,6 +24,7 @@ import io.asyncer.r2dbc.mysql.constant.MySqlType; import io.netty.buffer.ByteBuf; import io.netty.buffer.ByteBufAllocator; +import io.r2dbc.spi.R2dbcNonTransientResourceException; import reactor.core.publisher.Mono; /** @@ -55,7 +56,8 @@ public Boolean decode(ByteBuf value, MySqlReadableMetadata metadata, Class ta } else if (s.equalsIgnoreCase("N") || s.equalsIgnoreCase("no") || s.equalsIgnoreCase("F") || s.equalsIgnoreCase("false")) { return createFromLong(0); - } else if (s.matches("-?\\d*\\.\\d*") || s.matches("-?\\d*\\.\\d+[eE]-?\\d+")) { + } else if (s.matches("-?\\d*\\.\\d*") || s.matches("-?\\d*\\.\\d+[eE]-?\\d+") + || s.matches("-?\\d*[eE]-?\\d+")) { return createFromDouble(Double.parseDouble(s)); } else if (s.matches("-?\\d+")) { if (!CodecUtils.isGreaterThanLongMax(s)) { @@ -63,7 +65,8 @@ public Boolean decode(ByteBuf value, MySqlReadableMetadata metadata, Class ta } return createFromBigInteger(new BigInteger(s)); } - throw new IllegalArgumentException("Unable to interpret string: " + s); + throw new R2dbcNonTransientResourceException("The value '" + s + "' of type '" + dataType + + "' cannot be encoded into a Boolean.", "22018"); } return binary || dataType == MySqlType.BIT ? value.readBoolean() : value.readByte() != '0'; diff --git a/r2dbc-mysql/src/test/java/io/asyncer/r2dbc/mysql/codec/BooleanCodecTest.java b/r2dbc-mysql/src/test/java/io/asyncer/r2dbc/mysql/codec/BooleanCodecTest.java index 3150bb37f..166f7aac5 100644 --- a/r2dbc-mysql/src/test/java/io/asyncer/r2dbc/mysql/codec/BooleanCodecTest.java +++ b/r2dbc-mysql/src/test/java/io/asyncer/r2dbc/mysql/codec/BooleanCodecTest.java @@ -90,6 +90,9 @@ void decodeString() { Decoding d14 = new Decoding(Unpooled.copyDouble(26.57d), 26.57d, MySqlType.DOUBLE); Decoding d15 = new Decoding(Unpooled.copiedBuffer(bOne), bOne, MySqlType.TINYINT); Decoding d16 = new Decoding(Unpooled.copiedBuffer(bZero), bZero, MySqlType.TINYINT); + Decoding d17 = new Decoding(Unpooled.copiedBuffer("1e4", c), "1e4", MySqlType.VARCHAR); + Decoding d18 = new Decoding(Unpooled.copiedBuffer("-1.34e10", c), "-1.34e10", MySqlType.VARCHAR); + Decoding d19 = new Decoding(Unpooled.copiedBuffer("-0", c), "-0", MySqlType.VARCHAR); assertThat(codec.decode(d1.content(), d1.metadata(), Boolean.class, false, ConnectionContextTest.mock())) .as("Decode failed, %s", d1) @@ -151,7 +154,19 @@ void decodeString() { .isEqualTo(true); assertThat(codec.decode(d16.content(), d16.metadata(), Boolean.class, true, ConnectionContextTest.mock())) - .as("Decode failed, %s", d14) + .as("Decode failed, %s", d16) + .isEqualTo(false); + + assertThat(codec.decode(d17.content(), d17.metadata(), Boolean.class, false, ConnectionContextTest.mock())) + .as("Decode failed, %s", d17) + .isEqualTo(true); + + assertThat(codec.decode(d18.content(), d18.metadata(), Boolean.class, false, ConnectionContextTest.mock())) + .as("Decode failed, %s", d18) + .isEqualTo(false); + + assertThat(codec.decode(d19.content(), d19.metadata(), Boolean.class, false, ConnectionContextTest.mock())) + .as("Decode failed, %s", d19) .isEqualTo(false); } } From 25c8706583c8d1fc8729d3028f6bca1900720797 Mon Sep 17 00:00:00 2001 From: Ram Sin Date: Fri, 29 Nov 2024 19:27:03 +1100 Subject: [PATCH 09/10] Added tests, changed exception --- .../main/java/io/asyncer/r2dbc/mysql/codec/BooleanCodec.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/r2dbc-mysql/src/main/java/io/asyncer/r2dbc/mysql/codec/BooleanCodec.java b/r2dbc-mysql/src/main/java/io/asyncer/r2dbc/mysql/codec/BooleanCodec.java index 59ed42579..0a59265c3 100644 --- a/r2dbc-mysql/src/main/java/io/asyncer/r2dbc/mysql/codec/BooleanCodec.java +++ b/r2dbc-mysql/src/main/java/io/asyncer/r2dbc/mysql/codec/BooleanCodec.java @@ -65,7 +65,7 @@ public Boolean decode(ByteBuf value, MySqlReadableMetadata metadata, Class ta } return createFromBigInteger(new BigInteger(s)); } - throw new R2dbcNonTransientResourceException("The value '" + s + "' of type '" + dataType + + throw new R2dbcNonTransientResourceException("The value '" + s + "' of type '" + dataType + "' cannot be encoded into a Boolean.", "22018"); } From 71f6757394e7e1151130aee4bc68307ea65cff3d Mon Sep 17 00:00:00 2001 From: Ram Sin Date: Fri, 29 Nov 2024 19:31:46 +1100 Subject: [PATCH 10/10] Added tests, changed exception --- .../java/io/asyncer/r2dbc/mysql/codec/BooleanCodecTest.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/r2dbc-mysql/src/test/java/io/asyncer/r2dbc/mysql/codec/BooleanCodecTest.java b/r2dbc-mysql/src/test/java/io/asyncer/r2dbc/mysql/codec/BooleanCodecTest.java index 166f7aac5..dbfd5c104 100644 --- a/r2dbc-mysql/src/test/java/io/asyncer/r2dbc/mysql/codec/BooleanCodecTest.java +++ b/r2dbc-mysql/src/test/java/io/asyncer/r2dbc/mysql/codec/BooleanCodecTest.java @@ -20,6 +20,7 @@ import io.asyncer.r2dbc.mysql.constant.MySqlType; import io.netty.buffer.ByteBuf; import io.netty.buffer.Unpooled; +import io.r2dbc.spi.R2dbcNonTransientException; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatThrownBy; @@ -135,7 +136,7 @@ void decodeString() { .isEqualTo(false); assertThatThrownBy(() -> {codec.decode(d11.content(), d11.metadata(), Boolean.class, false, ConnectionContextTest.mock());}) - .isInstanceOf(IllegalArgumentException.class); + .isInstanceOf(R2dbcNonTransientException.class); assertThat(codec.decode(d12.content(), d12.metadata(), Boolean.class, false, ConnectionContextTest.mock())) .as("Decode failed, %s", d12)