diff --git a/.github/workflows/cd-release.yml b/.github/workflows/cd-release.yml
index a57a2e58e..75b75ccde 100644
--- a/.github/workflows/cd-release.yml
+++ b/.github/workflows/cd-release.yml
@@ -118,9 +118,9 @@ jobs:
with:
servers: |
[{
- "id": "ossrh-staging",
- "username": "${{ secrets.OSSRH_USERNAME }}",
- "password": "${{ secrets.OSSRH_PASSWORD }}"
+ "id": "central",
+ "username": "${{ secrets.CENTRAL_USERNAME }}",
+ "password": "${{ secrets.CENTRAL_PASSWORD }}"
}]
- name: Create Local Deploy Directory
diff --git a/.github/workflows/cd-snapshot.yml b/.github/workflows/cd-snapshot.yml
index a04976b28..8cd96d40c 100644
--- a/.github/workflows/cd-snapshot.yml
+++ b/.github/workflows/cd-snapshot.yml
@@ -46,9 +46,9 @@ jobs:
with:
servers: |
[{
- "id": "ossrh-snapshots",
- "username": "${{ secrets.OSSRH_USERNAME }}",
- "password": "${{ secrets.OSSRH_PASSWORD }}"
+ "id": "central-portal-snapshots",
+ "username": "${{ secrets.CENTRAL_USERNAME }}",
+ "password": "${{ secrets.CENTRAL_PASSWORD }}"
}]
- name: Prepare Internal Dependencies
diff --git a/.github/workflows/ci-integration-tests.yml b/.github/workflows/ci-integration-tests.yml
index 1ef3cdb0e..3ac7fb159 100644
--- a/.github/workflows/ci-integration-tests.yml
+++ b/.github/workflows/ci-integration-tests.yml
@@ -10,7 +10,7 @@ jobs:
strategy:
matrix:
mysql-version:
- [5.5, 5.6.45, 5.6, 5.7.28, 5.7, 8.0, 8.1, 8.2, 8.3, 8.4, 9.0]
+ ['5.5', '5.6.45', '5.6', '5.7.28', '5.7', '8.0', '8.1', '8.2', '8.3', '8.4', '9.0', '9.1', '9.2']
name: Integration test with MySQL ${{ matrix.mysql-version }}
steps:
- uses: actions/checkout@v3
diff --git a/.github/workflows/ci-mariadb-intergration-tests.yml b/.github/workflows/ci-mariadb-intergration-tests.yml
index 25cf0e498..fcf38e35c 100644
--- a/.github/workflows/ci-mariadb-intergration-tests.yml
+++ b/.github/workflows/ci-mariadb-intergration-tests.yml
@@ -10,7 +10,7 @@ jobs:
strategy:
matrix:
mariadb-version:
- [10.0, 10.1, 10.2.15, 10.2, 10.3.7, 10.3, 10.5.1, 10.5, 10.6, 10.11]
+ ['10.0', '10.1', '10.2.15', '10.2', '10.3.7', '10.3', '10.5.1', '10.5', '10.6', '10.11']
name: Integration test with MariaDB ${{ matrix.mariadb-version }}
steps:
- uses: actions/checkout@v3
diff --git a/README.md b/README.md
index 2a9e75b77..85039510a 100644
--- a/README.md
+++ b/README.md
@@ -16,7 +16,7 @@ Refer to the table below to determine the appropriate version of r2dbc-mysql for
| spring-boot-starter-data-r2dbc | spring-data-r2dbc | r2dbc-spi | r2dbc-mysql(recommended) |
|--------------------------------|-------------------|---------------|------------------------------|
-| 3.0.* and above | 3.0.* and above | 1.0.0.RELEASE | io.asyncer:r2dbc-mysql:1.3.1 |
+| 3.0.* and above | 3.0.* and above | 1.0.0.RELEASE | io.asyncer:r2dbc-mysql:1.4.0 |
| 2.7.* | 1.5.* | 0.9.1.RELEASE | io.asyncer:r2dbc-mysql:0.9.7 |
| 2.6.* and below | 1.4.* and below | 0.8.6.RELEASE | dev.miku:r2dbc-mysql:0.8.2 |
@@ -64,7 +64,7 @@ However, Docker-certified images do not have these versions lower than 5.5.0, so
io.asyncer
r2dbc-mysql
- 1.3.1
+ 1.4.0
```
@@ -74,7 +74,7 @@ However, Docker-certified images do not have these versions lower than 5.5.0, so
```groovy
dependencies {
- implementation 'io.asyncer:r2dbc-mysql:1.3.1'
+ implementation 'io.asyncer:r2dbc-mysql:1.4.0'
}
```
@@ -83,7 +83,7 @@ dependencies {
```kotlin
dependencies {
// Maybe should to use `compile` instead of `implementation` on the lower version of Gradle.
- implementation("io.asyncer:r2dbc-mysql:1.3.1")
+ implementation("io.asyncer:r2dbc-mysql:1.4.0")
}
```
diff --git a/r2dbc-mysql/pom.xml b/r2dbc-mysql/pom.xml
index 90e184254..a903116a8 100644
--- a/r2dbc-mysql/pom.xml
+++ b/r2dbc-mysql/pom.xml
@@ -19,7 +19,7 @@
io.asyncer
r2dbc-mysql
- 1.4.0
+ 1.4.2-SNAPSHOT
Reactive Relational Database Connectivity - MySQL
https://github.com/asyncer-io/r2dbc-mysql
@@ -61,7 +61,7 @@
scm:git:git://github.com/asyncer-io/r2dbc-mysql.git
scm:git:ssh://git@github.com/asyncer-io/r2dbc-mysql.git
https://github.com/asyncer-io/r2dbc-mysql
- r2dbc-mysql-1.4.0
+ HEAD
@@ -82,7 +82,7 @@
4.11.0
8.3.0
3.3.3
- 1.19.7
+ 1.21.0
4.0.3
5.3.32
2.16.1
@@ -448,6 +448,14 @@
+
+ org.sonatype.central
+ central-publishing-maven-plugin
+ 0.7.0
+
+ central
+
+
@@ -558,16 +566,9 @@
-
-
- false
-
-
- true
-
- ossrh-snapshots
- Sonatype Nexus Snapshots
- https://s01.oss.sonatype.org/content/repositories/snapshots/
-
+
+ central-portal-snapshots
+ https://central.sonatype.com/repository/maven-snapshots/
+
diff --git a/r2dbc-mysql/src/main/java/io/asyncer/r2dbc/mysql/MySqlConnectionConfiguration.java b/r2dbc-mysql/src/main/java/io/asyncer/r2dbc/mysql/MySqlConnectionConfiguration.java
index 3857451a1..39fb91eb6 100644
--- a/r2dbc-mysql/src/main/java/io/asyncer/r2dbc/mysql/MySqlConnectionConfiguration.java
+++ b/r2dbc-mysql/src/main/java/io/asyncer/r2dbc/mysql/MySqlConnectionConfiguration.java
@@ -418,7 +418,7 @@ private String buildCommonToStringPart() {
", passwordPublisher=" + passwordPublisher +
", resolver=" + resolver +
", metrics=" + metrics +
- ", tinyint1isBit=" + tinyInt1isBit;
+ ", tinyInt1isBit=" + tinyInt1isBit;
}
/**
diff --git a/r2dbc-mysql/src/main/java/io/asyncer/r2dbc/mysql/client/ReactorNettyClient.java b/r2dbc-mysql/src/main/java/io/asyncer/r2dbc/mysql/client/ReactorNettyClient.java
index 8e926f21e..5054f3631 100644
--- a/r2dbc-mysql/src/main/java/io/asyncer/r2dbc/mysql/client/ReactorNettyClient.java
+++ b/r2dbc-mysql/src/main/java/io/asyncer/r2dbc/mysql/client/ReactorNettyClient.java
@@ -379,17 +379,17 @@ public void error(Throwable e) {
@Override
public void next(ServerMessage message) {
- if (message instanceof WarningMessage) {
- int warnings = ((WarningMessage) message).getWarnings();
- if (warnings == 0) {
- if (DEBUG_ENABLED) {
+ if (DEBUG_ENABLED) {
+ if (message instanceof WarningMessage) {
+ final int warnings = ((WarningMessage) message).getWarnings();
+ if (warnings == 0) {
logger.debug("Response: {}", message);
+ } else {
+ logger.debug("Response: {}, reports {} warning(s)", message, warnings);
}
- } else if (INFO_ENABLED) {
- logger.info("Response: {}, reports {} warning(s)", message, warnings);
+ } else {
+ logger.debug("Response: {}", message);
}
- } else if (DEBUG_ENABLED) {
- logger.debug("Response: {}", message);
}
responseProcessor.emitNext(message, EmitFailureHandler.FAIL_FAST);
diff --git a/r2dbc-mysql/src/main/java/io/asyncer/r2dbc/mysql/codec/ByteArrayInputStreamCodec.java b/r2dbc-mysql/src/main/java/io/asyncer/r2dbc/mysql/codec/ByteArrayInputStreamCodec.java
new file mode 100644
index 000000000..c31261f5a
--- /dev/null
+++ b/r2dbc-mysql/src/main/java/io/asyncer/r2dbc/mysql/codec/ByteArrayInputStreamCodec.java
@@ -0,0 +1,150 @@
+/*
+ * Copyright 2025 asyncer.io projects
+ *
+ * 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
+ *
+ * https://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 io.asyncer.r2dbc.mysql.codec;
+
+import io.asyncer.r2dbc.mysql.MySqlParameter;
+import io.asyncer.r2dbc.mysql.ParameterWriter;
+import io.asyncer.r2dbc.mysql.api.MySqlReadableMetadata;
+import io.asyncer.r2dbc.mysql.constant.MySqlType;
+import io.asyncer.r2dbc.mysql.internal.util.VarIntUtils;
+import io.netty.buffer.ByteBuf;
+import io.netty.buffer.ByteBufAllocator;
+import reactor.core.publisher.Mono;
+
+import java.io.ByteArrayInputStream;
+import java.io.InputStream;
+
+import static io.asyncer.r2dbc.mysql.internal.util.InternalArrays.EMPTY_BYTES;
+
+/**
+ * Codec for {@link InputStream}.
+ */
+final class ByteArrayInputStreamCodec extends AbstractClassedCodec {
+
+ static final ByteArrayInputStreamCodec INSTANCE = new ByteArrayInputStreamCodec();
+
+ private ByteArrayInputStreamCodec() {
+ super(ByteArrayInputStream.class);
+ }
+
+ @Override
+ public ByteArrayInputStream decode(ByteBuf value, MySqlReadableMetadata metadata, Class> target, boolean binary,
+ CodecContext context) {
+ if (!value.isReadable()) {
+ return new ByteArrayInputStream(EMPTY_BYTES);
+ }
+ return new ByteArrayInputStream(value.array());
+ }
+
+ @Override
+ protected boolean doCanDecode(MySqlReadableMetadata metadata) {
+ return metadata.getType().isBinary();
+ }
+
+ @Override
+ public boolean canEncode(Object value) {
+ return value instanceof ByteArrayInputStream;
+ }
+
+ @Override
+ public MySqlParameter encode(Object value, CodecContext context) {
+ return new ByteArrayInputStreamMysqlParameter((ByteArrayInputStream) value);
+ }
+
+ private static final class ByteArrayInputStreamMysqlParameter extends AbstractMySqlParameter {
+
+ private final ByteArrayInputStream value;
+
+ private ByteArrayInputStreamMysqlParameter(ByteArrayInputStream value) {
+ this.value = value;
+ }
+
+ @Override
+ public Mono publishBinary(ByteBufAllocator allocator) {
+ return Mono.fromSupplier(() -> {
+ int size = value.available();
+ if (size == 0) {
+ return allocator.buffer(Byte.BYTES).writeByte(0);
+ }
+
+ int addedSize = VarIntUtils.varIntBytes(size);
+ ByteBuf buf = allocator.buffer(addedSize + size);
+
+ try {
+ VarIntUtils.writeVarInt(buf, size);
+ int readBytes = buf.writeBytes(value, size);
+ if (readBytes != size) {
+ buf.release();
+ throw new IllegalStateException("Expected to read " + size + " bytes, but got " + readBytes);
+ }
+
+ return buf;
+ } catch (Exception e) {
+ buf.release();
+ throw new RuntimeException(e);
+ }
+ });
+ }
+
+ @Override
+ public Mono publishText(ParameterWriter writer) {
+ return Mono.fromRunnable(() -> {
+ try {
+ int size = value.available();
+ byte[] byteArray = new byte[size];
+ int readBytes = value.read(byteArray);
+
+ if (size != 0 && readBytes != size) {
+ throw new IllegalStateException("Expected to read " + size + " bytes, but got " + readBytes);
+ }
+
+ writer.writeHex(byteArray);
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+ });
+ }
+
+ @Override
+ public String toString() {
+ return value.toString();
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) {
+ return true;
+ }
+ if (!(o instanceof ByteArrayInputStreamMysqlParameter)) {
+ return false;
+ }
+
+ ByteArrayInputStreamMysqlParameter that = (ByteArrayInputStreamMysqlParameter) o;
+ return value.equals(that.value);
+ }
+
+ @Override
+ public int hashCode() {
+ return value.hashCode();
+ }
+
+ @Override
+ public MySqlType getType() {
+ return MySqlType.VARBINARY;
+ }
+ }
+}
diff --git a/r2dbc-mysql/src/main/java/io/asyncer/r2dbc/mysql/codec/DefaultCodecs.java b/r2dbc-mysql/src/main/java/io/asyncer/r2dbc/mysql/codec/DefaultCodecs.java
index 34f2c67c1..01e47348c 100644
--- a/r2dbc-mysql/src/main/java/io/asyncer/r2dbc/mysql/codec/DefaultCodecs.java
+++ b/r2dbc-mysql/src/main/java/io/asyncer/r2dbc/mysql/codec/DefaultCodecs.java
@@ -81,7 +81,8 @@ final class DefaultCodecs implements Codecs {
BlobCodec.INSTANCE,
ByteBufferCodec.INSTANCE,
- ByteArrayCodec.INSTANCE
+ ByteArrayCodec.INSTANCE,
+ ByteArrayInputStreamCodec.INSTANCE
);
private final List> codecs;
diff --git a/r2dbc-mysql/src/test/java/io/asyncer/r2dbc/mysql/codec/ByteArrayInputStreamCodecTest.java b/r2dbc-mysql/src/test/java/io/asyncer/r2dbc/mysql/codec/ByteArrayInputStreamCodecTest.java
new file mode 100644
index 000000000..8c7e8b847
--- /dev/null
+++ b/r2dbc-mysql/src/test/java/io/asyncer/r2dbc/mysql/codec/ByteArrayInputStreamCodecTest.java
@@ -0,0 +1,68 @@
+/*
+ * Copyright 2025 asyncer.io projects
+ *
+ * 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
+ *
+ * https://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 io.asyncer.r2dbc.mysql.codec;
+
+import io.netty.buffer.ByteBuf;
+import io.netty.buffer.Unpooled;
+import org.testcontainers.shaded.org.bouncycastle.util.encoders.Hex;
+
+import java.io.ByteArrayInputStream;
+import java.nio.charset.Charset;
+import java.nio.charset.StandardCharsets;
+import java.util.Arrays;
+
+/**
+ * Unit tests for {@link ByteArrayInputStreamCodec}.
+ */
+public class ByteArrayInputStreamCodecTest implements CodecTestSupport {
+
+ private final byte[][] rawData = {
+ new byte[0],
+ new byte[] { 0x7F },
+ new byte[] { 0x12, 34, 0x56, 78, (byte) 0x9A },
+ "Hello world!".getBytes(StandardCharsets.US_ASCII),
+ new byte[] { (byte) 0xFE, (byte) 0xDC, (byte) 0xBA },
+ };
+
+ private final ByteArrayInputStream[] data = Arrays.stream(rawData)
+ .map(ByteArrayInputStream::new)
+ .toArray(ByteArrayInputStream[]::new);
+
+ @Override
+ public Codec getCodec() {
+ return ByteArrayInputStreamCodec.INSTANCE;
+ }
+
+ @Override
+ public ByteArrayInputStream[] originParameters() {
+ return data;
+ }
+
+ @Override
+ public Object[] stringifyParameters() {
+ return Arrays.stream(rawData)
+ .map(bytes -> String.format("x'%s'", Hex.toHexString(bytes)))
+ .toArray();
+ }
+
+ @Override
+ public ByteBuf[] binaryParameters(Charset charset) {
+ return Arrays.stream(rawData)
+ .map(Unpooled::wrappedBuffer)
+ .toArray(ByteBuf[]::new);
+ }
+}
diff --git a/test-native-image/pom.xml b/test-native-image/pom.xml
index e260321f2..36b13f6b0 100644
--- a/test-native-image/pom.xml
+++ b/test-native-image/pom.xml
@@ -5,7 +5,7 @@
4.0.0
io.asyncer
test-native-image
- 1.4.1-SNAPSHOT
+ 1.4.2-SNAPSHOT
UTF-8