diff --git a/.travis.yml b/.travis.yml
index b56b510c..af0c9e6e 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -36,6 +36,7 @@ jobs:
fast_finish: true
allow_failures:
- env: srv=build
+ - env: srv=xpand
include:
- stage: Minimal
env: srv=mariadb v=10.6 local=1
@@ -55,6 +56,8 @@ jobs:
name: "SkySQL"
- env: srv=skysql-ha
name: "SkySQL with replication"
+ - env: srv=xpand
+ name: "Xpand"
- stage: Community
env: srv=mariadb v=10.6
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 8b1cfba7..0062054c 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,21 @@
# Change Log
+## [1.1.4](https://github.com/mariadb-corporation/mariadb-connector-r2dbc/tree/1.1.4) (16 Mar 2023)
+[Full Changelog](https://github.com/mariadb-corporation/mariadb-connector-r2dbc/compare/1.1.3...1.1.4)
+
+Bugs Fixed:
+
+* [R2DBC-76] Wrong MEDIUM field binary decoding
+* [R2DBC-77] Metadata is null when using returnGeneratedValues on server before 10.5
+* [R2DBC-79] Wrong client side parsing for named parameter when using user variable
+* [R2DBC-80] add option to disable hostname verification for SslMode.TUNNEL. thanks to @shubha-rajan
+* [R2DBC-81] missing parsing/builder variables for option restrictedAuth,rsaPublicKey,cachingRsaPublicKey and allowPublicKeyRetrievalString
+* [R2DBC-82] wrong transactionIsolation level set/get with server without session tracking
+* [R2DBC-85] adding hint in order to execute text command when useServerPrepStmts option is set
+* [R2DBC-83] support xpand 0000-00-00 timestamp/date encoding
+
+
+
## [1.1.3](https://github.com/mariadb-corporation/mariadb-connector-r2dbc/tree/1.1.3) (22 Dec 2022)
[Full Changelog](https://github.com/mariadb-corporation/mariadb-connector-r2dbc/compare/1.1.2...1.1.3)
diff --git a/README.md b/README.md
index b75c1a0b..61071d1d 100644
--- a/README.md
+++ b/README.md
@@ -32,7 +32,7 @@ The MariaDB Connector is available through maven using :
org.mariadb
r2dbc-mariadb
- 1.1.3
+ 1.1.4
```
@@ -78,39 +78,40 @@ Basic example:
### Connection options
-|option| description |type|default|
-|---:|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|:---:|:---:|
-| **`username`** | User to access database. |*string* |
-| **`password`** | User password. |*string* |
-| **`host`** | IP address or DNS of the database server. Multiple host can be set, separate by comma. If first host is not reachable (timeout is connectTimeout), driver use next hosts.*Not used when using option `socketPath`*. |*string*| "localhost"|
-| **`port`** | Database server port number. *Not used when using option `socketPath`* |*integer*| 3306|
-| **`database`** | Default database to use when establishing the connection. | *string* |
-| **`connectTimeout`** | Sets the connection timeout | *Duration* | 10s|
-| **`socketTimeout`** | Sets the socket timeout | *Duration* | |
-| **`tcpKeepAlive`** | Sets socket keep alive | *Boolean* | false|
-| **`tcpAbortiveClose`** | This option can be used in environments where connections are created and closed in rapid succession. Often, it is not possible to create a socket in such an environment after a while, since all local “ephemeral” ports are used up by TCP connections in TCP_WAIT state. Using tcpAbortiveClose works around this problem by resetting TCP connections (abortive or hard close) rather than doing an orderly close. | *boolean* | false|
-| **`socket`** | Permits connections to the database through the Unix domain socket for faster connection whe server is local. | *string* |
-| **`allowMultiQueries`** | Allows you to issue several SQL statements in a single call. (That is, `INSERT INTO a VALUES('b'); INSERT INTO c VALUES('d');`).
This may be a **security risk** as it allows for SQL Injection attacks. | *boolean* | false|
-| **`connectionAttributes`** | When performance_schema is active, permit to send server some client information.
Those information can be retrieved on server within tables performance_schema.session_connect_attrs and performance_schema.session_account_connect_attrs. This can permit from server an identification of client/application per connection |*Map* |
-| **`sessionVariables`** | Permits to set session variables upon successful connection | *Map* |
-| **`tlsProtocol`** | Force TLS/SSL protocol to a specific set of TLS versions (example "TLSv1.2", "TLSv1.3"). |*List*| java default|
-| **`serverSslCert`** | Permits providing server's certificate in DER form, or server's CA certificate.
This permits a self-signed certificate to be trusted. Can be used in one of 3 forms : - serverSslCert=/path/to/cert.pem (full path to certificate)
- serverSslCert=classpath:relative/cert.pem (relative to current classpath)
- as verbatim DER-encoded certificate string "------BEGIN CERTIFICATE-----"
|*String*| |
-| **`clientSslCert`** | Permits providing client's certificate in DER form (use only for mutual authentication). Can be used in one of 3 forms : - clientSslCert=/path/to/cert.pem (full path to certificate)
- clientSslCert=classpath:relative/cert.pem (relative to current classpath)
- as verbatim DER-encoded certificate string "------BEGIN CERTIFICATE-----"
|*String*| |
-| **`clientSslKey`** | client private key path(for mutual authentication) |*String* | |
-| **`clientSslPassword`** | client private key password |*charsequence* | |
-| **`sslMode`** | ssl requirement. Possible value are - DISABLE, // NO SSL
- TRUST, // Encryption, but no certificate and hostname validation (DEVELOPMENT ONLY)
- VERIFY_CA, // Encryption, certificates validation, BUT no hostname validation
- VERIFY_FULL, // Standard SSL use: Encryption, certificate validation and hostname validation
- TUNNEL, // Connect over a pre-created SSL tunnel. See sslContextBuilderCustomizer options
| SslMode |DISABLE|
-| **`rsaPublicKey`** | only for MySQL server
Server RSA public key, for SHA256 authentication |*String* | |
-| **`cachingRsaPublicKey`** | only for MySQL server
Server caching RSA public key, for cachingSHA256 authentication |*String* | |
-| **`allowPublicKeyRetrieval`** | only for MySQL server
Permit retrieved Server RSA public key from server. This can create a security issue |*boolean* | true |
-| **`allowPipelining`** | Permit to send queries to server without waiting for previous query to finish |*boolean* | true |
-| **`useServerPrepStmts`** | Permit to indicate to use text or binary protocol for query with parameter |*boolean* | false |
-| **`prepareCacheSize`** | if useServerPrepStmts = true, cache the prepared informations in a LRU cache to avoid re-preparation of command. Next use of that command, only prepared identifier and parameters (if any) will be sent to server. This mainly permit for server to avoid reparsing query. |*int* |256 |
-| **`pamOtherPwd`** | Permit to provide additional password for PAM authentication with multiple authentication step. If multiple passwords, value must be URL encoded. |*string* | |
-| **`autocommit`** | Set default autocommit value on connection initialization" |*boolean* | true |
-| **`tinyInt1isBit`** | Convert Bit(1)/TINYINT(1) default to boolean type |*boolean* | true |
-| **`restrictedAuth`** | if set, restrict authentication plugin to secure list. Default provided plugins are mysql_native_password, mysql_clear_password, client_ed25519, dialog, sha256_password and caching_sha2_password |*string* | |
-| **`loopResources`** | permits to share netty EventLoopGroup among multiple async libraries/framework |*LoopResources* | |
-| **`sslContextBuilderCustomizer`** | Permits to customized SSL context builder. |*UnaryOperator* | |
+| option | description | type |default|
+|-------------------------------------:|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|:----------------------------------:|:---:|
+| **`username`** | User to access database. | *string* |
+| **`password`** | User password. | *string* |
+| **`host`** | IP address or DNS of the database server. Multiple host can be set, separate by comma. If first host is not reachable (timeout is connectTimeout), driver use next hosts.*Not used when using option `socketPath`*. | *string* | "localhost"|
+| **`port`** | Database server port number. *Not used when using option `socketPath`* | *integer* | 3306|
+| **`database`** | Default database to use when establishing the connection. | *string* |
+| **`connectTimeout`** | Sets the connection timeout | *Duration* | 10s|
+| **`socketTimeout`** | Sets the socket timeout | *Duration* | |
+| **`tcpKeepAlive`** | Sets socket keep alive | *Boolean* | false|
+| **`tcpAbortiveClose`** | This option can be used in environments where connections are created and closed in rapid succession. Often, it is not possible to create a socket in such an environment after a while, since all local “ephemeral” ports are used up by TCP connections in TCP_WAIT state. Using tcpAbortiveClose works around this problem by resetting TCP connections (abortive or hard close) rather than doing an orderly close. | *boolean* | false|
+| **`socket`** | Permits connections to the database through the Unix domain socket for faster connection whe server is local. | *string* |
+| **`allowMultiQueries`** | Allows you to issue several SQL statements in a single call. (That is, `INSERT INTO a VALUES('b'); INSERT INTO c VALUES('d');`).
This may be a **security risk** as it allows for SQL Injection attacks. | *boolean* | false|
+| **`connectionAttributes`** | When performance_schema is active, permit to send server some client information.
Those information can be retrieved on server within tables performance_schema.session_connect_attrs and performance_schema.session_account_connect_attrs. This can permit from server an identification of client/application per connection | *Map* |
+| **`sessionVariables`** | Permits to set session variables upon successful connection | *Map* |
+| **`tlsProtocol`** | Force TLS/SSL protocol to a specific set of TLS versions (example "TLSv1.2", "TLSv1.3"). | *List* | java default|
+| **`serverSslCert`** | Permits providing server's certificate in DER form, or server's CA certificate.
This permits a self-signed certificate to be trusted. Can be used in one of 3 forms : - serverSslCert=/path/to/cert.pem (full path to certificate)
- serverSslCert=classpath:relative/cert.pem (relative to current classpath)
- as verbatim DER-encoded certificate string "------BEGIN CERTIFICATE-----"
| *String* | |
+| **`clientSslCert`** | Permits providing client's certificate in DER form (use only for mutual authentication). Can be used in one of 3 forms : - clientSslCert=/path/to/cert.pem (full path to certificate)
- clientSslCert=classpath:relative/cert.pem (relative to current classpath)
- as verbatim DER-encoded certificate string "------BEGIN CERTIFICATE-----"
| *String* | |
+| **`clientSslKey`** | client private key path(for mutual authentication) | *String* | |
+| **`clientSslPassword`** | client private key password | *charsequence* | |
+| **`sslMode`** | ssl requirement. Possible value are - DISABLE, // NO SSL
- TRUST, // Encryption, but no certificate and hostname validation (DEVELOPMENT ONLY)
- VERIFY_CA, // Encryption, certificates validation, BUT no hostname validation
- VERIFY_FULL, // Standard SSL use: Encryption, certificate validation and hostname validation
- TUNNEL, // Connect over a pre-created SSL tunnel. See sslContextBuilderCustomizer options and sslTunnelDisableHostVerification
| SslMode |DISABLE|
+| **`rsaPublicKey`** | only for MySQL server
Server RSA public key, for SHA256 authentication | *String* | |
+| **`cachingRsaPublicKey`** | only for MySQL server
Server caching RSA public key, for cachingSHA256 authentication | *String* | |
+| **`allowPublicKeyRetrieval`** | only for MySQL server
Permit retrieved Server RSA public key from server. This can create a security issue | *boolean* | true |
+| **`allowPipelining`** | Permit to send queries to server without waiting for previous query to finish | *boolean* | true |
+| **`useServerPrepStmts`** | Permit to indicate to use text or binary protocol for query with parameter | *boolean* | false |
+| **`prepareCacheSize`** | if useServerPrepStmts = true, cache the prepared informations in a LRU cache to avoid re-preparation of command. Next use of that command, only prepared identifier and parameters (if any) will be sent to server. This mainly permit for server to avoid reparsing query. | *int* |256 |
+| **`pamOtherPwd`** | Permit to provide additional password for PAM authentication with multiple authentication step. If multiple passwords, value must be URL encoded. | *string* | |
+| **`autocommit`** | Set default autocommit value on connection initialization" | *boolean* | true |
+| **`tinyInt1isBit`** | Convert Bit(1)/TINYINT(1) default to boolean type | *boolean* | true |
+| **`restrictedAuth`** | if set, restrict authentication plugin to secure list. Default provided plugins are mysql_native_password, mysql_clear_password, client_ed25519, dialog, sha256_password and caching_sha2_password | *string* | |
+| **`loopResources`** | permits to share netty EventLoopGroup among multiple async libraries/framework | *LoopResources* | |
+| **`sslContextBuilderCustomizer`** | Permits to customized SSL context builder. | *UnaryOperator* | |
+| **`sslTunnelDisableHostVerification`** | Disable hostname verification during SSLHandshake when SslMode.TUNNEL is set | *boolean* | |
## Failover
diff --git a/pom.xml b/pom.xml
index 0609bcab..88687382 100644
--- a/pom.xml
+++ b/pom.xml
@@ -11,7 +11,7 @@
4.0.0
org.mariadb
r2dbc-mariadb
- 1.1.3
+ 1.1.4
jar
https://github.com/mariadb-corporation/mariadb-connector-r2dbc
diff --git a/src/main/java/org/mariadb/r2dbc/MariadbConnection.java b/src/main/java/org/mariadb/r2dbc/MariadbConnection.java
index a8c08a3e..d01585e3 100644
--- a/src/main/java/org/mariadb/r2dbc/MariadbConnection.java
+++ b/src/main/java/org/mariadb/r2dbc/MariadbConnection.java
@@ -98,7 +98,7 @@ public MariadbStatement createStatement(String sql) {
throw new IllegalArgumentException("Statement cannot be empty.");
}
- if (this.configuration.useServerPrepStmts() || sql.contains("call")) {
+ if ((this.configuration.useServerPrepStmts() || sql.contains("call")) && !sql.startsWith("/*text*/")) {
return new MariadbServerParameterizedQueryStatement(this.client, sql, this.configuration);
}
return new MariadbClientParameterizedQueryStatement(this.client, sql, this.configuration);
@@ -112,7 +112,7 @@ public MariadbConnectionMetadata getMetadata() {
@Override
public IsolationLevel getTransactionIsolationLevel() {
if (isolationLevel != null) return isolationLevel;
- if ((client.getContext().getClientCapabilities() | Capabilities.CLIENT_SESSION_TRACK) > 0
+ if ((client.getContext().getClientCapabilities() & Capabilities.CLIENT_SESSION_TRACK) > 0
&& client.getContext().getIsolationLevel() != null)
return client.getContext().getIsolationLevel();
return this.sessionIsolationLevel;
@@ -221,7 +221,7 @@ public Mono setStatementTimeout(Duration timeout) {
public Mono setTransactionIsolationLevel(IsolationLevel isolationLevel) {
Assert.requireNonNull(isolationLevel, "isolationLevel must not be null");
- if ((client.getContext().getClientCapabilities() | Capabilities.CLIENT_SESSION_TRACK) > 0
+ if ((client.getContext().getClientCapabilities() & Capabilities.CLIENT_SESSION_TRACK) > 0
&& client.getContext().getIsolationLevel() != null
&& client.getContext().getIsolationLevel().equals(isolationLevel)) return Mono.empty();
diff --git a/src/main/java/org/mariadb/r2dbc/MariadbConnectionConfiguration.java b/src/main/java/org/mariadb/r2dbc/MariadbConnectionConfiguration.java
index b561e634..c6855f5e 100644
--- a/src/main/java/org/mariadb/r2dbc/MariadbConnectionConfiguration.java
+++ b/src/main/java/org/mariadb/r2dbc/MariadbConnectionConfiguration.java
@@ -95,7 +95,8 @@ private MariadbConnectionConfiguration(
boolean tinyInt1isBit,
String restrictedAuth,
@Nullable LoopResources loopResources,
- @Nullable UnaryOperator sslContextBuilderCustomizer) {
+ @Nullable UnaryOperator sslContextBuilderCustomizer,
+ boolean sslTunnelDisableHostVerification) {
this.haMode = haMode == null ? HaMode.NONE : HaMode.from(haMode);
this.connectTimeout = connectTimeout == null ? Duration.ofSeconds(10) : connectTimeout;
this.tcpKeepAlive = tcpKeepAlive == null ? Boolean.FALSE : tcpKeepAlive;
@@ -128,6 +129,7 @@ private MariadbConnectionConfiguration(
clientSslKey,
clientSslPassword,
tlsProtocol,
+ sslTunnelDisableHostVerification,
sslContextBuilderCustomizer);
}
this.rsaPublicKey = rsaPublicKey;
@@ -195,6 +197,28 @@ public static Builder fromOptions(ConnectionFactoryOptions connectionFactoryOpti
connectionFactoryOptions.getValue(MariadbConnectionFactoryProvider.TCP_KEEP_ALIVE)));
}
+ if (connectionFactoryOptions.hasOption(
+ MariadbConnectionFactoryProvider.ALLOW_PUBLIC_KEY_RETRIEVAL)) {
+ builder.allowPublicKeyRetrieval(
+ boolValue(
+ connectionFactoryOptions.getValue(
+ MariadbConnectionFactoryProvider.ALLOW_PUBLIC_KEY_RETRIEVAL)));
+ }
+
+ if (connectionFactoryOptions.hasOption(
+ MariadbConnectionFactoryProvider.CACHING_RSA_PUBLIC_KEY)) {
+ builder.cachingRsaPublicKey(
+ (String)
+ connectionFactoryOptions.getValue(
+ MariadbConnectionFactoryProvider.CACHING_RSA_PUBLIC_KEY));
+ }
+
+ if (connectionFactoryOptions.hasOption(MariadbConnectionFactoryProvider.RSA_PUBLIC_KEY)) {
+ builder.rsaPublicKey(
+ (String)
+ connectionFactoryOptions.getValue(MariadbConnectionFactoryProvider.RSA_PUBLIC_KEY));
+ }
+
if (connectionFactoryOptions.hasOption(MariadbConnectionFactoryProvider.TCP_ABORTIVE_CLOSE)) {
builder.tcpAbortiveClose(
boolValue(
@@ -316,6 +340,13 @@ public static Builder fromOptions(ConnectionFactoryOptions connectionFactoryOpti
}
builder.pamOtherPwd(pairs);
}
+
+ if (connectionFactoryOptions.hasOption(MariadbConnectionFactoryProvider.RESTRICTED_AUTH)) {
+ builder.restrictedAuth(
+ (String)
+ connectionFactoryOptions.getValue(MariadbConnectionFactoryProvider.RESTRICTED_AUTH));
+ }
+
if (connectionFactoryOptions.hasOption(MariadbConnectionFactoryProvider.LOOP_RESOURCES)) {
LoopResources loopResources =
(LoopResources)
@@ -323,6 +354,14 @@ public static Builder fromOptions(ConnectionFactoryOptions connectionFactoryOpti
builder.loopResources(loopResources);
}
+ if (connectionFactoryOptions.hasOption(
+ MariadbConnectionFactoryProvider.SSL_TUNNEL_DISABLE_HOST_VERIFICATION)) {
+ builder.sslTunnelDisableHostVerification(
+ boolValue(
+ connectionFactoryOptions.getValue(
+ MariadbConnectionFactoryProvider.SSL_TUNNEL_DISABLE_HOST_VERIFICATION)));
+ }
+
if (connectionFactoryOptions.hasOption(
MariadbConnectionFactoryProvider.SSL_CONTEXT_BUILDER_CUSTOMIZER)) {
builder.sslContextBuilderCustomizer(
@@ -539,7 +578,7 @@ public String toString() {
+ ", pamOtherPwd="
+ hiddenPamPwd
+ ", restrictedAuth="
- + restrictedAuth
+ + (restrictedAuth == null ? "" : Arrays.toString(restrictedAuth))
+ '}';
}
@@ -587,6 +626,8 @@ public static final class Builder implements Cloneable {
private Builder() {}
+ private boolean sslTunnelDisableHostVerification;
+
/**
* Returns a configured {@link MariadbConnectionConfiguration}.
*
@@ -641,7 +682,8 @@ public MariadbConnectionConfiguration build() {
this.tinyInt1isBit,
this.restrictedAuth,
this.loopResources,
- this.sslContextBuilderCustomizer);
+ this.sslContextBuilderCustomizer,
+ this.sslTunnelDisableHostVerification);
}
/**
@@ -976,6 +1018,11 @@ public Builder sslContextBuilderCustomizer(
return this;
}
+ public Builder sslTunnelDisableHostVerification(boolean sslTunnelDisableHostVerification) {
+ this.sslTunnelDisableHostVerification = sslTunnelDisableHostVerification;
+ return this;
+ }
+
@Override
public Builder clone() throws CloneNotSupportedException {
return (Builder) super.clone();
@@ -1054,6 +1101,8 @@ public String toString() {
+ clientSslPassword
+ ", sslMode="
+ sslMode
+ + ", sslTunnelDisableHostVerification="
+ + sslTunnelDisableHostVerification
+ ", pamOtherPwd="
+ hiddenPamPwd
+ ", tinyInt1isBit="
diff --git a/src/main/java/org/mariadb/r2dbc/MariadbConnectionFactoryProvider.java b/src/main/java/org/mariadb/r2dbc/MariadbConnectionFactoryProvider.java
index 571e69d9..c603a229 100644
--- a/src/main/java/org/mariadb/r2dbc/MariadbConnectionFactoryProvider.java
+++ b/src/main/java/org/mariadb/r2dbc/MariadbConnectionFactoryProvider.java
@@ -25,7 +25,7 @@ public final class MariadbConnectionFactoryProvider implements ConnectionFactory
public static final Option ALLOW_PIPELINING = Option.valueOf("allowPipelining");
public static final Option USE_SERVER_PREPARE = Option.valueOf("useServerPrepStmts");
public static final Option ISOLATION_LEVEL = Option.valueOf("isolationLevel");
- public static final Option AUTO_COMMIT = Option.valueOf("autoCommit");
+ public static final Option AUTO_COMMIT = Option.valueOf("autocommit");
public static final Option TINY_IS_BIT = Option.valueOf("tinyInt1isBit");
public static final Option PREPARE_CACHE_SIZE = Option.valueOf("prepareCacheSize");
public static final Option SSL_MODE = Option.valueOf("sslMode");
@@ -38,8 +38,18 @@ public final class MariadbConnectionFactoryProvider implements ConnectionFactory
public static final Option TCP_ABORTIVE_CLOSE = Option.valueOf("tcpAbortiveClose");
public static final Option SESSION_VARIABLES = Option.valueOf("sessionVariables");
public static final Option LOOP_RESOURCES = Option.valueOf("loopResources");
+ public static final Option ALLOW_PUBLIC_KEY_RETRIEVAL =
+ Option.valueOf("allowPublicKeyRetrieval");
+
+ public static final Option CACHING_RSA_PUBLIC_KEY = Option.valueOf("cachingRsaPublicKey");
+ public static final Option RSA_PUBLIC_KEY = Option.valueOf("rsaPublicKey");
+
+ public static final Option RESTRICTED_AUTH = Option.valueOf("restrictedAuth");
+
public static final Option> SSL_CONTEXT_BUILDER_CUSTOMIZER =
Option.valueOf("sslContextBuilderCustomizer");
+ public static final Option SSL_TUNNEL_DISABLE_HOST_VERIFICATION =
+ Option.valueOf("sslTunnelDisableHostVerification");
static MariadbConnectionConfiguration createConfiguration(
ConnectionFactoryOptions connectionFactoryOptions) {
diff --git a/src/main/java/org/mariadb/r2dbc/authentication/standard/Sha256PasswordPluginFlow.java b/src/main/java/org/mariadb/r2dbc/authentication/standard/Sha256PasswordPluginFlow.java
index 4daa5c1f..6cbaa9b6 100644
--- a/src/main/java/org/mariadb/r2dbc/authentication/standard/Sha256PasswordPluginFlow.java
+++ b/src/main/java/org/mariadb/r2dbc/authentication/standard/Sha256PasswordPluginFlow.java
@@ -113,7 +113,7 @@ public ClientMessage next(
} else {
if (!configuration.allowPublicKeyRetrieval()) {
throw new R2dbcNonTransientResourceException(
- "RSA public key is not available client side (option " + "serverRsaPublicKeyFile)",
+ "RSA public key is not available client side (option serverRsaPublicKeyFile)",
"S1009");
}
state = State.REQUEST_SERVER_KEY;
diff --git a/src/main/java/org/mariadb/r2dbc/client/SimpleClient.java b/src/main/java/org/mariadb/r2dbc/client/SimpleClient.java
index 0784b281..bd297aaf 100644
--- a/src/main/java/org/mariadb/r2dbc/client/SimpleClient.java
+++ b/src/main/java/org/mariadb/r2dbc/client/SimpleClient.java
@@ -106,7 +106,9 @@ protected SimpleClient(
sslContext.newEngine(
connection.channel().alloc(), hostAddress.getHost(), hostAddress.getPort());
SSLParameters sslParameters = engine.getSSLParameters();
- sslParameters.setEndpointIdentificationAlgorithm("HTTPS");
+ if (!configuration.getSslConfig().tunnelHostVerificationDisabled()) {
+ sslParameters.setEndpointIdentificationAlgorithm("HTTPS");
+ }
engine.setSSLParameters(sslParameters);
} else {
engine = sslContext.newEngine(connection.channel().alloc());
diff --git a/src/main/java/org/mariadb/r2dbc/codec/list/BigDecimalCodec.java b/src/main/java/org/mariadb/r2dbc/codec/list/BigDecimalCodec.java
index a031395d..910c07a6 100644
--- a/src/main/java/org/mariadb/r2dbc/codec/list/BigDecimalCodec.java
+++ b/src/main/java/org/mariadb/r2dbc/codec/list/BigDecimalCodec.java
@@ -109,10 +109,10 @@ public BigDecimal decodeBinary(
return BigDecimal.valueOf((int) buf.readShortLE());
case MEDIUMINT:
- if (!column.isSigned()) {
- return BigDecimal.valueOf((buf.readUnsignedMediumLE()));
- }
- return BigDecimal.valueOf(buf.readMediumLE());
+ BigDecimal v =
+ BigDecimal.valueOf(column.isSigned() ? buf.readMediumLE() : buf.readUnsignedMediumLE());
+ buf.readByte(); // needed since binary protocol exchange for medium are on 4 bytes
+ return v;
case INTEGER:
if (!column.isSigned()) {
diff --git a/src/main/java/org/mariadb/r2dbc/codec/list/BigIntegerCodec.java b/src/main/java/org/mariadb/r2dbc/codec/list/BigIntegerCodec.java
index a505f3b8..c2b66662 100644
--- a/src/main/java/org/mariadb/r2dbc/codec/list/BigIntegerCodec.java
+++ b/src/main/java/org/mariadb/r2dbc/codec/list/BigIntegerCodec.java
@@ -120,10 +120,10 @@ public BigInteger decodeBinary(
return BigInteger.valueOf((int) buf.readShortLE());
case MEDIUMINT:
- if (!column.isSigned()) {
- return BigInteger.valueOf((buf.readUnsignedMediumLE()));
- }
- return BigInteger.valueOf(buf.readMediumLE());
+ BigInteger v =
+ BigInteger.valueOf(column.isSigned() ? buf.readMediumLE() : buf.readUnsignedMediumLE());
+ buf.readByte(); // needed since binary protocol exchange for medium are on 4 bytes
+ return v;
case INTEGER:
if (!column.isSigned()) {
diff --git a/src/main/java/org/mariadb/r2dbc/codec/list/BooleanCodec.java b/src/main/java/org/mariadb/r2dbc/codec/list/BooleanCodec.java
index c1fc5e5e..87933d88 100644
--- a/src/main/java/org/mariadb/r2dbc/codec/list/BooleanCodec.java
+++ b/src/main/java/org/mariadb/r2dbc/codec/list/BooleanCodec.java
@@ -109,7 +109,10 @@ public Boolean decodeBinary(
return buf.readShortLE() != 0;
case MEDIUMINT:
- return buf.readMediumLE() != 0;
+ boolean b = buf.readMediumLE() != 0;
+ buf.readByte(); // needed since binary protocol exchange for medium are on 4 bytes
+ return b;
+
case INTEGER:
return buf.readIntLE() != 0;
case BIGINT:
diff --git a/src/main/java/org/mariadb/r2dbc/codec/list/ByteCodec.java b/src/main/java/org/mariadb/r2dbc/codec/list/ByteCodec.java
index 1958c86a..949213ef 100644
--- a/src/main/java/org/mariadb/r2dbc/codec/list/ByteCodec.java
+++ b/src/main/java/org/mariadb/r2dbc/codec/list/ByteCodec.java
@@ -139,6 +139,7 @@ public Byte decodeBinary(
case MEDIUMINT:
result = column.isSigned() ? buf.readMediumLE() : buf.readUnsignedMediumLE();
+ buf.readByte(); // needed since binary protocol exchange for medium are on 4 bytes
break;
case INTEGER:
diff --git a/src/main/java/org/mariadb/r2dbc/codec/list/DoubleCodec.java b/src/main/java/org/mariadb/r2dbc/codec/list/DoubleCodec.java
index 0b67e257..4b65168b 100644
--- a/src/main/java/org/mariadb/r2dbc/codec/list/DoubleCodec.java
+++ b/src/main/java/org/mariadb/r2dbc/codec/list/DoubleCodec.java
@@ -101,10 +101,9 @@ public Double decodeBinary(
return (double) buf.readShortLE();
case MEDIUMINT:
- if (!column.isSigned()) {
- return (double) buf.readUnsignedMediumLE();
- }
- return (double) buf.readMediumLE();
+ double v = column.isSigned() ? buf.readMediumLE() : buf.readUnsignedMediumLE();
+ buf.readByte(); // needed since binary protocol exchange for medium are on 4 bytes
+ return v;
case INTEGER:
if (!column.isSigned()) {
diff --git a/src/main/java/org/mariadb/r2dbc/codec/list/FloatCodec.java b/src/main/java/org/mariadb/r2dbc/codec/list/FloatCodec.java
index fec8d9ff..7304dc59 100644
--- a/src/main/java/org/mariadb/r2dbc/codec/list/FloatCodec.java
+++ b/src/main/java/org/mariadb/r2dbc/codec/list/FloatCodec.java
@@ -102,10 +102,9 @@ public Float decodeBinary(
return (float) buf.readShortLE();
case MEDIUMINT:
- if (!column.isSigned()) {
- return (float) buf.readUnsignedMediumLE();
- }
- return (float) buf.readMediumLE();
+ float v = column.isSigned() ? buf.readMediumLE() : buf.readUnsignedMediumLE();
+ buf.readByte(); // needed since binary protocol exchange for medium are on 4 bytes
+ return v;
case INTEGER:
if (!column.isSigned()) {
diff --git a/src/main/java/org/mariadb/r2dbc/codec/list/IntCodec.java b/src/main/java/org/mariadb/r2dbc/codec/list/IntCodec.java
index 392f63ca..8f2b344b 100644
--- a/src/main/java/org/mariadb/r2dbc/codec/list/IntCodec.java
+++ b/src/main/java/org/mariadb/r2dbc/codec/list/IntCodec.java
@@ -123,6 +123,7 @@ public Integer decodeBinary(
case MEDIUMINT:
result = column.isSigned() ? buf.readMediumLE() : buf.readUnsignedMediumLE();
+ buf.readByte(); // needed since binary protocol exchange for medium are on 4 bytes
break;
case BIGINT:
diff --git a/src/main/java/org/mariadb/r2dbc/codec/list/LocalDateCodec.java b/src/main/java/org/mariadb/r2dbc/codec/list/LocalDateCodec.java
index 25a7f1a8..9d7b575b 100644
--- a/src/main/java/org/mariadb/r2dbc/codec/list/LocalDateCodec.java
+++ b/src/main/java/org/mariadb/r2dbc/codec/list/LocalDateCodec.java
@@ -143,6 +143,7 @@ public LocalDate decodeBinary(
if (length > 4) {
buf.skipBytes(length - 4);
}
+ if (year == 0 && month == 0 && dayOfMonth == 0) return null;
return LocalDate.of(year, month, dayOfMonth);
}
return null;
diff --git a/src/main/java/org/mariadb/r2dbc/codec/list/LocalDateTimeCodec.java b/src/main/java/org/mariadb/r2dbc/codec/list/LocalDateTimeCodec.java
index 37d8682b..517e9f85 100644
--- a/src/main/java/org/mariadb/r2dbc/codec/list/LocalDateTimeCodec.java
+++ b/src/main/java/org/mariadb/r2dbc/codec/list/LocalDateTimeCodec.java
@@ -182,6 +182,12 @@ public LocalDateTime decodeBinary(
microseconds = buf.readUnsignedIntLE();
}
}
+ if (year == 0
+ && month == 0
+ && dayOfMonth == 0
+ && hour == 0
+ && minutes == 0
+ && seconds == 0) return null;
} else return null;
break;
diff --git a/src/main/java/org/mariadb/r2dbc/codec/list/LongCodec.java b/src/main/java/org/mariadb/r2dbc/codec/list/LongCodec.java
index 7ce52cc4..41c5ab65 100644
--- a/src/main/java/org/mariadb/r2dbc/codec/list/LongCodec.java
+++ b/src/main/java/org/mariadb/r2dbc/codec/list/LongCodec.java
@@ -179,10 +179,9 @@ public Long decodeBinary(
return (long) buf.readShortLE();
case MEDIUMINT:
- if (!column.isSigned()) {
- return (long) buf.readUnsignedMediumLE();
- }
- return (long) buf.readMediumLE();
+ long v = column.isSigned() ? buf.readMediumLE() : buf.readUnsignedMediumLE();
+ buf.readByte(); // needed since binary protocol exchange for medium are on 4 bytes
+ return v;
case INTEGER:
if (!column.isSigned()) {
diff --git a/src/main/java/org/mariadb/r2dbc/codec/list/ShortCodec.java b/src/main/java/org/mariadb/r2dbc/codec/list/ShortCodec.java
index 0d01387b..f7bcf7ed 100644
--- a/src/main/java/org/mariadb/r2dbc/codec/list/ShortCodec.java
+++ b/src/main/java/org/mariadb/r2dbc/codec/list/ShortCodec.java
@@ -112,6 +112,7 @@ public Short decodeBinary(
case MEDIUMINT:
result = column.isSigned() ? buf.readMediumLE() : buf.readUnsignedMediumLE();
+ buf.readByte(); // needed since binary protocol exchange for medium are on 4 bytes
break;
case INTEGER:
diff --git a/src/main/java/org/mariadb/r2dbc/util/ClientParser.java b/src/main/java/org/mariadb/r2dbc/util/ClientParser.java
index 053c9d88..31bf9d09 100644
--- a/src/main/java/org/mariadb/r2dbc/util/ClientParser.java
+++ b/src/main/java/org/mariadb/r2dbc/util/ClientParser.java
@@ -124,7 +124,6 @@ public static ClientParser parameterPartsCheckReturning(
case ':':
if (state == LexState.Normal) {
int beginPos = i;
- paramPositions.add(i);
while (++i < queryLength
&& (car = query[i]) != ' '
&& ((car >= '0' && car <= '9')
@@ -132,7 +131,13 @@ public static ClientParser parameterPartsCheckReturning(
|| (car >= 'a' && car <= 'z')
|| car == '-'
|| car == '_')) {}
+ if (beginPos + 1 == i) {
+ // this is a ":" not followed by name or index
+ // so not a parameter
+ break;
+ }
paramNameList.add(new String(query, beginPos + 1, i - (beginPos + 1)));
+ paramPositions.add(beginPos);
paramPositions.add(i);
}
break;
@@ -358,7 +363,6 @@ public static ClientParser parameterParts(String queryString, boolean noBackslas
case ':':
if (state == LexState.Normal) {
int beginPos = i;
- paramPositions.add(i);
while (++i < queryLength
&& (car = query[i]) != ' '
&& ((car >= '0' && car <= '9')
@@ -366,7 +370,13 @@ public static ClientParser parameterParts(String queryString, boolean noBackslas
|| (car >= 'a' && car <= 'z')
|| car == '-'
|| car == '_')) {}
+ if (beginPos + 1 == i) {
+ // this is a ":" not followed by name or index
+ // so not a parameter
+ break;
+ }
paramNameList.add(new String(query, beginPos + 1, i - (beginPos + 1)));
+ paramPositions.add(beginPos);
paramPositions.add(i);
}
break;
@@ -489,6 +499,7 @@ public static boolean hasParameter(String queryString, boolean noBackslashEscape
case ':':
if (state == LexState.Normal) {
+ int beginPos = i;
while (++i < queryLength
&& (car = query[i]) != ' '
&& ((car >= '0' && car <= '9')
@@ -496,6 +507,11 @@ public static boolean hasParameter(String queryString, boolean noBackslashEscape
|| (car >= 'a' && car <= 'z')
|| car == '-'
|| car == '_')) {}
+ if (beginPos + 1 == i) {
+ // this is a ":" not followed by name or index
+ // so not a parameter
+ break;
+ }
return true;
}
break;
diff --git a/src/main/java/org/mariadb/r2dbc/util/SslConfig.java b/src/main/java/org/mariadb/r2dbc/util/SslConfig.java
index 3b545a50..79500feb 100644
--- a/src/main/java/org/mariadb/r2dbc/util/SslConfig.java
+++ b/src/main/java/org/mariadb/r2dbc/util/SslConfig.java
@@ -7,7 +7,11 @@
import io.netty.handler.ssl.SslContextBuilder;
import io.netty.handler.ssl.util.InsecureTrustManagerFactory;
import io.r2dbc.spi.R2dbcTransientResourceException;
-import java.io.*;
+import java.io.ByteArrayInputStream;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.InputStream;
import java.util.List;
import java.util.function.UnaryOperator;
import javax.net.ssl.SSLException;
@@ -26,6 +30,8 @@ public class SslConfig {
private SslContextBuilder sslContextBuilder;
private UnaryOperator sslContextBuilderCustomizer;
+ private boolean disableHostVerification;
+
public SslConfig(
SslMode sslMode,
String serverSslCert,
@@ -33,6 +39,7 @@ public SslConfig(
String clientSslKey,
CharSequence clientSslPassword,
List tlsProtocol,
+ boolean disableHostVerification,
UnaryOperator sslContextBuilderCustomizer)
throws R2dbcTransientResourceException {
this.sslMode = sslMode;
@@ -41,6 +48,7 @@ public SslConfig(
this.tlsProtocol = tlsProtocol;
this.clientSslKey = clientSslKey;
this.clientSslPassword = clientSslPassword;
+ this.disableHostVerification = disableHostVerification;
this.sslContextBuilderCustomizer = sslContextBuilderCustomizer;
if (sslMode != SslMode.DISABLE) {
this.sslContextBuilder = getSslContextBuilder();
@@ -55,6 +63,10 @@ public SslMode getSslMode() {
return sslMode;
}
+ public boolean tunnelHostVerificationDisabled() {
+ return this.disableHostVerification;
+ }
+
private SslContextBuilder getSslContextBuilder() throws R2dbcTransientResourceException {
final SslContextBuilder sslCtxBuilder = SslContextBuilder.forClient();
diff --git a/src/test/java/org/mariadb/r2dbc/BaseConnectionTest.java b/src/test/java/org/mariadb/r2dbc/BaseConnectionTest.java
index dbe24a14..36d5cdef 100644
--- a/src/test/java/org/mariadb/r2dbc/BaseConnectionTest.java
+++ b/src/test/java/org/mariadb/r2dbc/BaseConnectionTest.java
@@ -27,7 +27,7 @@ public class BaseConnectionTest {
public static final boolean isWindows =
System.getProperty("os.name").toLowerCase().contains("win");
- public static int initialConnectionNumber = -1;
+ public static Integer initialConnectionNumber = -1;
public static TcpProxy proxy;
private static final Random rand = new Random();
public static final Boolean backslashEscape =
@@ -48,12 +48,14 @@ public void assertThrows(
private class Follow implements BeforeEachCallback, AfterEachCallback {
@Override
public void beforeEach(ExtensionContext extensionContext) throws Exception {
- initialConnectionNumber =
- sharedConn
- .createStatement("SHOW STATUS WHERE `variable_name` = 'Threads_connected'")
- .execute()
- .flatMap(r -> r.map((row, metadata) -> row.get(1, Integer.class)))
- .blockLast();
+ if (!isXpand()) {
+ initialConnectionNumber =
+ sharedConn
+ .createStatement("SHOW STATUS WHERE `variable_name` = 'Threads_connected'")
+ .execute()
+ .flatMap(r -> r.map((row, metadata) -> row.get(1, Integer.class)))
+ .blockLast();
+ }
initialTest = Instant.now();
System.out.println(
" test : " + extensionContext.getTestMethod().get().getName() + " begin");
@@ -61,44 +63,45 @@ public void beforeEach(ExtensionContext extensionContext) throws Exception {
@AfterEach
public void afterEach(ExtensionContext extensionContext) throws Exception {
- int finalConnectionNumber =
- sharedConn
- .createStatement("SHOW STATUS WHERE `variable_name` = 'Threads_connected'")
- .execute()
- .flatMap(r -> r.map((row, metadata) -> row.get(1, Integer.class)))
- .onErrorResume(
- t -> {
- t.printStackTrace();
- return Mono.just(-999999);
- })
- .blockLast();
- if (finalConnectionNumber - initialConnectionNumber != 0) {
- int retry = 5;
- do {
- Thread.sleep(50);
- finalConnectionNumber =
- sharedConn
- .createStatement("SHOW STATUS WHERE `variable_name` = 'Threads_connected'")
- .execute()
- .flatMap(r -> r.map((row, metadata) -> row.get(1, Integer.class)))
- .onErrorResume(
- t -> {
- t.printStackTrace();
- return Mono.just(-999999);
- })
- .blockLast();
- } while (retry-- > 0 && finalConnectionNumber != initialConnectionNumber);
-
- if (finalConnectionNumber - initialConnectionNumber != 0) {
- System.err.printf(
- "%s: Error connection not ended : changed=%s (initial:%s ended:%s)%n",
- extensionContext.getTestMethod().get(),
- (finalConnectionNumber - initialConnectionNumber),
- initialConnectionNumber,
- finalConnectionNumber);
+ if (!isXpand()) {
+ Integer finalConnectionNumber =
+ sharedConn
+ .createStatement("SHOW STATUS WHERE `variable_name` = 'Threads_connected'")
+ .execute()
+ .flatMap(r -> r.map((row, metadata) -> row.get(1, Integer.class)))
+ .onErrorResume(
+ t -> {
+ t.printStackTrace();
+ return Mono.just(-999999);
+ })
+ .blockLast();
+ if (finalConnectionNumber != null && finalConnectionNumber - initialConnectionNumber != 0) {
+ int retry = 5;
+ do {
+ Thread.sleep(50);
+ finalConnectionNumber =
+ sharedConn
+ .createStatement("SHOW STATUS WHERE `variable_name` = 'Threads_connected'")
+ .execute()
+ .flatMap(r -> r.map((row, metadata) -> row.get(1, Integer.class)))
+ .onErrorResume(
+ t -> {
+ t.printStackTrace();
+ return Mono.just(-999999);
+ })
+ .blockLast();
+ } while (retry-- > 0 && finalConnectionNumber != initialConnectionNumber);
+
+ if (finalConnectionNumber - initialConnectionNumber != 0) {
+ System.err.printf(
+ "%s: Error connection not ended : changed=%s (initial:%s ended:%s)%n",
+ extensionContext.getTestMethod().get(),
+ (finalConnectionNumber - initialConnectionNumber),
+ initialConnectionNumber,
+ finalConnectionNumber);
+ }
}
}
-
System.out.println(
" test : "
+ extensionContext.getTestMethod().get().getName()
@@ -120,6 +123,7 @@ public void afterEach(ExtensionContext extensionContext) throws Exception {
public static void beforeAll() throws Exception {
sharedConn = factory.create().block();
+
MariadbConnectionConfiguration confPipeline =
TestConfiguration.defaultBuilder.clone().useServerPrepStmts(true).build();
sharedConnPrepare = new MariadbConnectionFactory(confPipeline).create().block();
@@ -187,6 +191,11 @@ public static boolean isMariaDBServer() {
return meta.isMariaDBServer();
}
+ public static boolean isXpand() {
+ MariadbConnectionMetadata meta = sharedConn.getMetadata();
+ return meta.getDatabaseVersion().toLowerCase().contains("xpand");
+ }
+
public static boolean minVersion(int major, int minor, int patch) {
MariadbConnectionMetadata meta = sharedConn.getMetadata();
return meta.minVersion(major, minor, patch);
diff --git a/src/test/java/org/mariadb/r2dbc/integration/ConfigurationTest.java b/src/test/java/org/mariadb/r2dbc/integration/ConfigurationTest.java
index a6b4f86d..a0c3838b 100644
--- a/src/test/java/org/mariadb/r2dbc/integration/ConfigurationTest.java
+++ b/src/test/java/org/mariadb/r2dbc/integration/ConfigurationTest.java
@@ -336,11 +336,11 @@ void confStringValue() {
builder.pamOtherPwd(new String[] {"fff", "ddd"});
builder.tlsProtocol((String[]) null);
Assertions.assertEquals(
- "Builder{rsaPublicKey=null, cachingRsaPublicKey=null, allowPublicKeyRetrieval=false, username=admin, connectTimeout=null, tcpKeepAlive=null, tcpAbortiveClose=null, transactionReplay=null, database=dbname, host=localhost, sessionVariables=null, connectionAttributes=null, password=*, restrictedAuth=null, port=3306, hosts={}, socket=null, allowMultiQueries=false, allowPipelining=true, useServerPrepStmts=false, prepareCacheSize=null, isolationLevel=null, tlsProtocol=null, serverSslCert=null, clientSslCert=null, clientSslKey=null, clientSslPassword=null, sslMode=TRUST, pamOtherPwd=*,*, tinyInt1isBit=false, autoCommit=true}",
+ "Builder{rsaPublicKey=null, cachingRsaPublicKey=null, allowPublicKeyRetrieval=false, username=admin, connectTimeout=null, tcpKeepAlive=null, tcpAbortiveClose=null, transactionReplay=null, database=dbname, host=localhost, sessionVariables=null, connectionAttributes=null, password=*, restrictedAuth=null, port=3306, hosts={}, socket=null, allowMultiQueries=false, allowPipelining=true, useServerPrepStmts=false, prepareCacheSize=null, isolationLevel=null, tlsProtocol=null, serverSslCert=null, clientSslCert=null, clientSslKey=null, clientSslPassword=null, sslMode=TRUST, sslTunnelDisableHostVerification=false, pamOtherPwd=*,*, tinyInt1isBit=false, autoCommit=true}",
builder.toString());
builder.tlsProtocol((String) null);
Assertions.assertEquals(
- "Builder{rsaPublicKey=null, cachingRsaPublicKey=null, allowPublicKeyRetrieval=false, username=admin, connectTimeout=null, tcpKeepAlive=null, tcpAbortiveClose=null, transactionReplay=null, database=dbname, host=localhost, sessionVariables=null, connectionAttributes=null, password=*, restrictedAuth=null, port=3306, hosts={}, socket=null, allowMultiQueries=false, allowPipelining=true, useServerPrepStmts=false, prepareCacheSize=null, isolationLevel=null, tlsProtocol=null, serverSslCert=null, clientSslCert=null, clientSslKey=null, clientSslPassword=null, sslMode=TRUST, pamOtherPwd=*,*, tinyInt1isBit=false, autoCommit=true}",
+ "Builder{rsaPublicKey=null, cachingRsaPublicKey=null, allowPublicKeyRetrieval=false, username=admin, connectTimeout=null, tcpKeepAlive=null, tcpAbortiveClose=null, transactionReplay=null, database=dbname, host=localhost, sessionVariables=null, connectionAttributes=null, password=*, restrictedAuth=null, port=3306, hosts={}, socket=null, allowMultiQueries=false, allowPipelining=true, useServerPrepStmts=false, prepareCacheSize=null, isolationLevel=null, tlsProtocol=null, serverSslCert=null, clientSslCert=null, clientSslKey=null, clientSslPassword=null, sslMode=TRUST, sslTunnelDisableHostVerification=false, pamOtherPwd=*,*, tinyInt1isBit=false, autoCommit=true}",
builder.toString());
MariadbConnectionConfiguration conf = builder.build();
Assertions.assertEquals(
diff --git a/src/test/java/org/mariadb/r2dbc/integration/ConnectionMetadataTest.java b/src/test/java/org/mariadb/r2dbc/integration/ConnectionMetadataTest.java
index 70caa211..1b0f7465 100644
--- a/src/test/java/org/mariadb/r2dbc/integration/ConnectionMetadataTest.java
+++ b/src/test/java/org/mariadb/r2dbc/integration/ConnectionMetadataTest.java
@@ -18,7 +18,7 @@ public class ConnectionMetadataTest extends BaseConnectionTest {
void connectionMeta() {
ConnectionMetadata meta = sharedConn.getMetadata();
assertEquals(meta.getDatabaseProductName(), isMariaDBServer() ? "MariaDB" : "MySQL");
- if (isMariaDBServer()) {
+ if (isMariaDBServer() && !isXpand()) {
assertTrue(meta.getDatabaseVersion().contains("10."));
} else {
assertTrue(
diff --git a/src/test/java/org/mariadb/r2dbc/integration/ConnectionTest.java b/src/test/java/org/mariadb/r2dbc/integration/ConnectionTest.java
index bfc8ae0f..051d7a8a 100644
--- a/src/test/java/org/mariadb/r2dbc/integration/ConnectionTest.java
+++ b/src/test/java/org/mariadb/r2dbc/integration/ConnectionTest.java
@@ -444,6 +444,7 @@ void multipleBeginWithIsolation(
@Test
void beginTransactionWithIsolation() throws Exception {
+ Assumptions.assumeFalse(isXpand());
TransactionDefinition transactionDefinition =
MariadbTransactionDefinition.READ_ONLY.isolationLevel(IsolationLevel.READ_COMMITTED);
TransactionDefinition transactionDefinition2 =
@@ -509,20 +510,28 @@ void queryAfterClose() throws Exception {
}
private void consume(Connection connection) {
- int numberOfUserCol = 41;
- Statement statement = connection.createStatement("select * FROM mysql.user LIMIT 1");
- Flux.from(statement.execute())
- .flatMap(
- it ->
- it.map(
- (row, rowMetadata) -> {
- Object[] objs = new Object[numberOfUserCol];
- for (int i = 0; i < numberOfUserCol; i++) {
- objs[i] = row.get(i);
- }
- return objs;
- }))
- .blockLast();
+ if (isXpand()) {
+ Statement statement = connection.createStatement("select 1");
+ Flux.from(statement.execute())
+ .flatMap(it -> it.map((row, rowMetadata) -> row.get(0)))
+ .blockLast();
+
+ } else {
+ int numberOfUserCol = 41;
+ Statement statement = connection.createStatement("select * FROM mysql.user LIMIT 1");
+ Flux.from(statement.execute())
+ .flatMap(
+ it ->
+ it.map(
+ (row, rowMetadata) -> {
+ Object[] objs = new Object[numberOfUserCol];
+ for (int i = 0; i < numberOfUserCol; i++) {
+ objs[i] = row.get(i);
+ }
+ return objs;
+ }))
+ .blockLast();
+ }
}
@Test
@@ -703,6 +712,7 @@ void getTransactionIsolationLevel() {
@Test
void getDatabase() {
+ Assumptions.assumeFalse(isXpand());
MariadbConnection connection =
new MariadbConnectionFactory(TestConfiguration.defaultBuilder.build()).create().block();
assertEquals(TestConfiguration.database, connection.getDatabase());
@@ -821,10 +831,14 @@ void useTransaction(MariadbConnection conn) {
@Test
void wrongSavePoint() {
sharedConn.createStatement("START TRANSACTION").execute().blockLast();
- assertThrows(
- Exception.class,
- () -> sharedConn.rollbackTransactionToSavepoint("wrong").block(),
- "SAVEPOINT wrong does not exist");
+ try {
+ sharedConn.rollbackTransactionToSavepoint("wrong").block();
+ Assertions.fail("Must have thrown error");
+ } catch (Exception e) {
+ Assertions.assertTrue(
+ e.getMessage().contains("Savepoint does not exist")
+ || e.getMessage().contains("SAVEPOINT wrong does not exist"));
+ }
sharedConn.rollbackTransaction().block();
}
@@ -891,6 +905,7 @@ public void isolationLevel() {
Assertions.assertThrows(
Exception.class, () -> connection.setTransactionIsolationLevel(null).block());
for (IsolationLevel level : levels) {
+ System.out.println(level);
connection.setTransactionIsolationLevel(level).block();
assertEquals(level, connection.getTransactionIsolationLevel());
}
@@ -971,7 +986,8 @@ public void errorOnConnection() throws Throwable {
Assumptions.assumeTrue(
!"maxscale".equals(System.getenv("srv"))
&& !"skysql-ha".equals(System.getenv("srv"))
- && !"skysql".equals(System.getenv("srv")));
+ && !"skysql".equals(System.getenv("srv"))
+ && !isXpand());
BigInteger maxConn =
sharedConn
@@ -1065,7 +1081,8 @@ public void queryTimeout() throws Throwable {
Assumptions.assumeTrue(
!"maxscale".equals(System.getenv("srv"))
&& !"skysql".equals(System.getenv("srv"))
- && !"skysql-ha".equals(System.getenv("srv")));
+ && !"skysql-ha".equals(System.getenv("srv"))
+ && !isXpand());
MariadbConnection connection =
new MariadbConnectionFactory(TestConfiguration.defaultBuilder.clone().build())
.create()
diff --git a/src/test/java/org/mariadb/r2dbc/integration/ErrorTest.java b/src/test/java/org/mariadb/r2dbc/integration/ErrorTest.java
index 646f542f..22dca512 100644
--- a/src/test/java/org/mariadb/r2dbc/integration/ErrorTest.java
+++ b/src/test/java/org/mariadb/r2dbc/integration/ErrorTest.java
@@ -56,9 +56,8 @@ void permissionDenied() throws Exception {
.expectErrorMatches(
throwable ->
throwable instanceof R2dbcNonTransientResourceException
- && (throwable
- .getMessage()
- .contains("Access denied for user 'userWithoutRight'")))
+ && (throwable.getMessage().contains("Access denied for user 'userWithoutRight'")
+ || throwable.getMessage().contains("Insufficient user permissions")))
.verify();
conf =
@@ -75,10 +74,11 @@ void permissionDenied() throws Exception {
throwable ->
throwable instanceof R2dbcNonTransientResourceException
&& throwable.getMessage().contains("Fail to establish connection to")
- && throwable
- .getCause()
- .getMessage()
- .contains("Access denied for user 'userWithoutRight'"))
+ && (throwable
+ .getCause()
+ .getMessage()
+ .contains("Access denied for user 'userWithoutRight'")
+ || throwable.getMessage().contains("Access denied")))
.verify();
}
@@ -105,7 +105,8 @@ void rollbackException() {
Assumptions.assumeTrue(
!"maxscale".equals(System.getenv("srv"))
&& !"skysql".equals(System.getenv("srv"))
- && !"skysql-ha".equals(System.getenv("srv")));
+ && !"skysql-ha".equals(System.getenv("srv"))
+ && !isXpand());
MariadbConnection connection = null;
MariadbConnection connection2 = null;
try {
diff --git a/src/test/java/org/mariadb/r2dbc/integration/FailoverConnectionTest.java b/src/test/java/org/mariadb/r2dbc/integration/FailoverConnectionTest.java
index 9d700b86..87facf85 100644
--- a/src/test/java/org/mariadb/r2dbc/integration/FailoverConnectionTest.java
+++ b/src/test/java/org/mariadb/r2dbc/integration/FailoverConnectionTest.java
@@ -199,7 +199,8 @@ void transactionReplayFailingDuringCmd() throws Exception {
Assumptions.assumeTrue(
!"maxscale".equals(System.getenv("srv"))
&& !"skysql".equals(System.getenv("srv"))
- && !"skysql-ha".equals(System.getenv("srv")));
+ && !"skysql-ha".equals(System.getenv("srv"))
+ && !isXpand());
transactionReplayFailingDuringCmd(
createFailoverProxyConnection(HaMode.SEQUENTIAL, true, false));
diff --git a/src/test/java/org/mariadb/r2dbc/integration/LoggingTest.java b/src/test/java/org/mariadb/r2dbc/integration/LoggingTest.java
index c8a13278..7116ebe2 100644
--- a/src/test/java/org/mariadb/r2dbc/integration/LoggingTest.java
+++ b/src/test/java/org/mariadb/r2dbc/integration/LoggingTest.java
@@ -14,6 +14,7 @@
import java.nio.file.Files;
import java.nio.file.Paths;
import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Assumptions;
import org.junit.jupiter.api.Test;
import org.mariadb.r2dbc.BaseConnectionTest;
import org.mariadb.r2dbc.MariadbConnectionConfiguration;
@@ -28,6 +29,7 @@ public class LoggingTest extends BaseConnectionTest {
@Test
void basicLogging() throws IOException {
+ Assumptions.assumeFalse(isXpand());
File tempFile = File.createTempFile("log", ".tmp");
Logger logger = (Logger) LoggerFactory.getLogger("org.mariadb.r2dbc");
diff --git a/src/test/java/org/mariadb/r2dbc/integration/MultiQueriesTest.java b/src/test/java/org/mariadb/r2dbc/integration/MultiQueriesTest.java
index 2a75bb2d..354a26e8 100644
--- a/src/test/java/org/mariadb/r2dbc/integration/MultiQueriesTest.java
+++ b/src/test/java/org/mariadb/r2dbc/integration/MultiQueriesTest.java
@@ -19,7 +19,9 @@ public class MultiQueriesTest extends BaseConnectionTest {
@Test
void multiQueryDefault() {
Assumptions.assumeTrue(
- !"maxscale".equals(System.getenv("srv")) && !"skysql-ha".equals(System.getenv("srv")));
+ !"maxscale".equals(System.getenv("srv"))
+ && !"skysql-ha".equals(System.getenv("srv"))
+ && !isXpand());
sharedConn
.createStatement("SELECT 1; SELECT 'a'")
.execute()
@@ -50,7 +52,9 @@ void multiQueryEnable() throws Exception {
@Test
void multiQueryDisable() throws Exception {
Assumptions.assumeTrue(
- !"maxscale".equals(System.getenv("srv")) && !"skysql-ha".equals(System.getenv("srv")));
+ !"maxscale".equals(System.getenv("srv"))
+ && !"skysql-ha".equals(System.getenv("srv"))
+ && !isXpand());
MariadbConnectionConfiguration conf =
TestConfiguration.defaultBuilder.clone().allowMultiQueries(false).build();
@@ -71,7 +75,9 @@ void multiQueryDisable() throws Exception {
@Test
void multiQueryWithParameterDefault() {
Assumptions.assumeTrue(
- !"maxscale".equals(System.getenv("srv")) && !"skysql-ha".equals(System.getenv("srv")));
+ !"maxscale".equals(System.getenv("srv"))
+ && !"skysql-ha".equals(System.getenv("srv"))
+ && !isXpand());
sharedConn
.createStatement("SELECT CAST(? as CHAR); SELECT ?")
@@ -107,7 +113,9 @@ void multiQueryWithParameterEnable() throws Exception {
@Test
void multiQueryWithParameterDisable() throws Exception {
Assumptions.assumeTrue(
- !"maxscale".equals(System.getenv("srv")) && !"skysql-ha".equals(System.getenv("srv")));
+ !"maxscale".equals(System.getenv("srv"))
+ && !"skysql-ha".equals(System.getenv("srv"))
+ && !isXpand());
MariadbConnectionConfiguration conf =
TestConfiguration.defaultBuilder.clone().allowMultiQueries(false).build();
diff --git a/src/test/java/org/mariadb/r2dbc/integration/PrepareResultSetTest.java b/src/test/java/org/mariadb/r2dbc/integration/PrepareResultSetTest.java
index d1395a40..dc17fd08 100644
--- a/src/test/java/org/mariadb/r2dbc/integration/PrepareResultSetTest.java
+++ b/src/test/java/org/mariadb/r2dbc/integration/PrepareResultSetTest.java
@@ -394,7 +394,13 @@ public void returningBefore105() {
.bind(0, "test1")
.returnGeneratedValues("id")
.execute()
- .flatMap(r -> r.map((row, metadata) -> row.get(0, String.class)))
+ .flatMap(
+ r ->
+ r.map(
+ (row, metadata) -> {
+ Assertions.assertEquals("id", metadata.getColumnMetadata(0).getName());
+ return row.get(0, String.class);
+ }))
.as(StepVerifier::create)
.expectNext("3")
.verifyComplete();
@@ -404,7 +410,14 @@ public void returningBefore105() {
.bind(0, "test3")
.returnGeneratedValues("TEST_COL_NAME")
.execute()
- .flatMap(r -> r.map((row, metadata) -> row.get("TEST_COL_NAME", String.class)))
+ .flatMap(
+ r ->
+ r.map(
+ (row, metadata) -> {
+ Assertions.assertEquals(
+ "TEST_COL_NAME", metadata.getColumnMetadata(0).getName());
+ return row.get("TEST_COL_NAME", String.class);
+ }))
.as(StepVerifier::create)
.expectNext("4")
.verifyComplete();
@@ -481,6 +494,7 @@ void cannotPrepare() throws Throwable {
// unexpected error "unexpected message received when no command was send: 0x48000002"
Assumptions.assumeTrue(
!"maxscale".equals(System.getenv("srv")) && !"skysql-ha".equals(System.getenv("srv")));
+ Assumptions.assumeFalse(isXpand());
MariadbConnectionConfiguration confPipeline =
TestConfiguration.defaultBuilder.clone().useServerPrepStmts(true).build();
MariadbConnection conn = new MariadbConnectionFactory(confPipeline).create().block();
@@ -548,6 +562,8 @@ void parameterNull() {
@Test
void prepareReuse() {
+ // https://jira.mariadb.org/browse/XPT-599 XPand doesn't support DO
+ Assumptions.assumeFalse(isXpand());
MariadbStatement stmt = sharedConnPrepare.createStatement("DO 1 = ?");
assertThrows(
IndexOutOfBoundsException.class,
@@ -715,7 +731,8 @@ void cacheReuse() throws Throwable {
// Com_stmt_prepare
if (!"maxscale".equals(System.getenv("srv"))
&& !"skysql-ha".equals(System.getenv("srv"))
- && (isMariaDBServer() || !minVersion(8, 0, 0))) {
+ && (isMariaDBServer() || !minVersion(8, 0, 0))
+ && !isXpand()) {
Assertions.assertEquals("5", endingStatus.get(1), endingStatus.get(1));
}
diff --git a/src/test/java/org/mariadb/r2dbc/integration/ProcedureResultsetTest.java b/src/test/java/org/mariadb/r2dbc/integration/ProcedureResultsetTest.java
index ecc622be..3edd2108 100644
--- a/src/test/java/org/mariadb/r2dbc/integration/ProcedureResultsetTest.java
+++ b/src/test/java/org/mariadb/r2dbc/integration/ProcedureResultsetTest.java
@@ -10,12 +10,10 @@
import java.time.LocalDateTime;
import java.util.List;
import java.util.NoSuchElementException;
-import org.junit.jupiter.api.AfterAll;
-import org.junit.jupiter.api.Assertions;
-import org.junit.jupiter.api.BeforeAll;
-import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.*;
import org.mariadb.r2dbc.BaseConnectionTest;
import reactor.core.publisher.Flux;
+import reactor.test.StepVerifier;
public class ProcedureResultsetTest extends BaseConnectionTest {
@@ -34,15 +32,25 @@ public static void before2() {
+ "END")
.execute()
.blockLast();
+ sharedConn
+ .createStatement(
+ "CREATE PROCEDURE no_out_proc (IN t1 INT, IN t2 INT) BEGIN \n"
+ + "DO t1 + t2;\n"
+ + "END")
+ .execute()
+ .blockLast();
}
@AfterAll
public static void dropAll() {
sharedConn.createStatement("DROP PROCEDURE IF EXISTS basic_proc").execute().blockLast();
+ sharedConn.createStatement("DROP PROCEDURE IF EXISTS no_out_proc").execute().blockLast();
}
@Test
void outputParameter() {
+ // https://jira.mariadb.org/browse/XPT-268
+ Assumptions.assumeFalse(isXpand());
List> l =
sharedConn
.createStatement("call basic_proc(?,?,?,?,?,?,?)")
@@ -102,5 +110,58 @@ void outputParameter() {
Assertions.assertEquals("test", l.get(1).get(4));
}
Assertions.assertEquals(LocalDateTime.parse("2003-12-31T12:00:00"), l.get(1).get(3));
+
+ List> l2 =
+ sharedConn
+ .createStatement("/*text*/ call basic_proc(?,?,?,?,?,?,?)")
+ .bind(0, 2)
+ .bind(1, Parameters.inOut(2))
+ .bind(2, Parameters.out(R2dbcType.INTEGER))
+ .bind(3, 10)
+ .bind(4, Parameters.out(R2dbcType.VARCHAR))
+ .bind(5, Parameters.out(R2dbcType.TIMESTAMP))
+ .bind(6, Parameters.out(R2dbcType.VARCHAR))
+ .execute()
+ .flatMap(
+ r ->
+ Flux.from(
+ r.filter(Result.OutSegment.class::isInstance)
+ .flatMap(
+ seg -> {
+ return Flux.just(
+ ((Result.OutSegment) seg).outParameters().get(0),
+ ((Result.OutSegment) seg).outParameters().get(1),
+ ((Result.OutSegment) seg).outParameters().get(2),
+ ((Result.OutSegment) seg).outParameters().get(3),
+ ((Result.OutSegment) seg).outParameters().get(4));
+ }))
+ .collectList())
+ .collectList()
+ .block();
+
+ Assertions.assertEquals(1, l2.size());
}
+ @Test
+ void inParameter() {
+ Assumptions.assumeFalse(isXpand());
+ sharedConn
+ .createStatement("call no_out_proc(?,?)")
+ .bind(0, 2)
+ .bind(1, 10)
+ .execute()
+ .flatMap(it -> it.getRowsUpdated())
+ .as(StepVerifier::create)
+ .expectNext(0L)
+ .verifyComplete();
+ sharedConn
+ .createStatement("/*text*/ call no_out_proc(?,?)")
+ .bind(0, 2)
+ .bind(1, 10)
+ .execute()
+ .flatMap(it -> it.getRowsUpdated())
+ .as(StepVerifier::create)
+ .expectNext(0L)
+ .verifyComplete();
+ }
+
}
diff --git a/src/test/java/org/mariadb/r2dbc/integration/RowMetadataTest.java b/src/test/java/org/mariadb/r2dbc/integration/RowMetadataTest.java
index 069dbd89..6a860faf 100644
--- a/src/test/java/org/mariadb/r2dbc/integration/RowMetadataTest.java
+++ b/src/test/java/org/mariadb/r2dbc/integration/RowMetadataTest.java
@@ -96,8 +96,10 @@ void rowMeta() {
assertEquals("t1", t1Meta.getColumn());
assertEquals("rowmeta", t1Meta.getTable());
assertEquals("rowMetaAlias", t1Meta.getTableAlias());
- assertTrue(t1Meta.getCharset() == 224 || t1Meta.getCharset() == 45);
- assertEquals(256, t1Meta.getDisplaySize());
+ if (!isXpand()) {
+ assertTrue(t1Meta.getCharset() == 224 || t1Meta.getCharset() == 45);
+ assertEquals(256, t1Meta.getDisplaySize());
+ }
assertFalse(t1Meta.isBinary());
assertFalse(t1Meta.isBlob());
assertFalse(t1Meta.isMultipleKey());
@@ -107,7 +109,9 @@ void rowMeta() {
assertFalse(t1Meta.isUniqueKey());
colMeta = metadata.getColumnMetadata("t2");
- assertEquals(Long.class, colMeta.getJavaType());
+ if (!isXpand()) {
+ assertEquals(Long.class, colMeta.getJavaType());
+ }
assertEquals("t2", colMeta.getName());
this.assertThrows(
@@ -116,10 +120,13 @@ void rowMeta() {
"Column name 'wrongName' does not exist in column names ");
colMeta = metadata.getColumnMetadata(1);
- assertEquals(Long.class, colMeta.getJavaType());
- assertEquals("t2", colMeta.getName());
- assertEquals(Nullability.NULLABLE, colMeta.getNullability());
- assertEquals(10, colMeta.getPrecision());
+ if (!isXpand()) {
+
+ assertEquals(Long.class, colMeta.getJavaType());
+ assertEquals("t2", colMeta.getName());
+ assertEquals(Nullability.NULLABLE, colMeta.getNullability());
+ assertEquals(10, colMeta.getPrecision());
+ }
assertEquals(0, colMeta.getScale());
assertEquals(
ColumnDefinitionPacket.class, colMeta.getNativeTypeMetadata().getClass());
@@ -133,14 +140,18 @@ void rowMeta() {
assertEquals("rowmeta", t2Meta.getTable());
assertEquals("rowMetaAlias", t2Meta.getTableAlias());
- assertEquals(10, t2Meta.getDisplaySize());
- assertEquals(63, t2Meta.getCharset());
+ if (!isXpand()) {
+ assertEquals(10, t2Meta.getDisplaySize());
+ assertEquals(63, t2Meta.getCharset());
+ }
assertTrue(t2Meta.isBinary());
assertFalse(t2Meta.isBlob());
assertFalse(t2Meta.isMultipleKey());
assertFalse(t2Meta.isPrimaryKey());
- assertFalse(t2Meta.isSigned());
- assertTrue(t2Meta.isZeroFill());
+ if (!isXpand()) {
+ assertFalse(t2Meta.isSigned());
+ assertTrue(t2Meta.isZeroFill());
+ }
assertFalse(t2Meta.isUniqueKey());
colMeta = metadata.getColumnMetadata(2);
diff --git a/src/test/java/org/mariadb/r2dbc/integration/StatementTest.java b/src/test/java/org/mariadb/r2dbc/integration/StatementTest.java
index 23e7bb8c..2db8fe96 100644
--- a/src/test/java/org/mariadb/r2dbc/integration/StatementTest.java
+++ b/src/test/java/org/mariadb/r2dbc/integration/StatementTest.java
@@ -90,6 +90,17 @@ public static void dropAll() {
sharedConn.createStatement("DROP TABLE IF EXISTS returningBefore105").execute().blockLast();
}
+ @Test
+ void basicSetter() {
+ sharedConn
+ .createStatement("SELECT @amount := 10")
+ .execute()
+ .flatMap(r -> r.map((row, metadata) -> row.get(0, String.class)))
+ .as(StepVerifier::create)
+ .expectNext("10")
+ .verifyComplete();
+ }
+
@Test
void bindOnStatementWithoutParameter() {
Statement stmt = sharedConn.createStatement("INSERT INTO someTable values (1,2)");
@@ -329,7 +340,7 @@ public void dupplicate() {
@Test
public void sinkEndCheck() throws Throwable {
- Assumptions.assumeTrue(isMariaDBServer());
+ Assumptions.assumeTrue(isMariaDBServer() && !isXpand());
AtomicReference d = new AtomicReference<>();
AtomicReference d2 = new AtomicReference<>();
MariadbConnection connection = factory.create().block();
@@ -370,7 +381,7 @@ public void sinkEndCheck() throws Throwable {
@Test
public void sinkFirstOnly() throws Throwable {
- Assumptions.assumeTrue(isMariaDBServer());
+ Assumptions.assumeTrue(isMariaDBServer() && !isXpand());
AtomicReference d2 = new AtomicReference<>();
MariadbConnection connection = factory.create().block();
connection.beginTransaction().block();
diff --git a/src/test/java/org/mariadb/r2dbc/integration/TlsTest.java b/src/test/java/org/mariadb/r2dbc/integration/TlsTest.java
index dd99d77f..0c193842 100644
--- a/src/test/java/org/mariadb/r2dbc/integration/TlsTest.java
+++ b/src/test/java/org/mariadb/r2dbc/integration/TlsTest.java
@@ -31,6 +31,7 @@ public class TlsTest extends BaseConnectionTest {
@BeforeAll
public static void before2() {
+ Assumptions.assumeTrue(!isXpand());
serverSslCert = System.getenv("TEST_DB_SERVER_CERT");
clientSslCert = System.getenv("TEST_DB_CLIENT_CERT");
clientSslKey = System.getenv("TEST_DB_CLIENT_KEY");
diff --git a/src/test/java/org/mariadb/r2dbc/integration/authentication/Sha256PluginTest.java b/src/test/java/org/mariadb/r2dbc/integration/authentication/Sha256PluginTest.java
index e329002d..847e3661 100644
--- a/src/test/java/org/mariadb/r2dbc/integration/authentication/Sha256PluginTest.java
+++ b/src/test/java/org/mariadb/r2dbc/integration/authentication/Sha256PluginTest.java
@@ -249,7 +249,8 @@ public void sha256PluginTestWrongServerRsaKey() throws Exception {
public void sha256PluginTestWithoutServerRsaKey() throws Exception {
Assumptions.assumeTrue(!isWindows && !isMariaDBServer() && (minVersion(8, 0, 0)));
// mysql 8.0.31 broken public key retrieval, so avoid FLUSHING for now
- Assumptions.assumeTrue(!isMariaDBServer() && !exactVersion(8, 0, 31));
+ Assumptions.assumeTrue(
+ !isMariaDBServer() && !exactVersion(8, 0, 31) && !exactVersion(8, 0, 32));
MariadbConnectionConfiguration conf =
TestConfiguration.defaultBuilder
diff --git a/src/test/java/org/mariadb/r2dbc/integration/codec/BigIntegerParseTest.java b/src/test/java/org/mariadb/r2dbc/integration/codec/BigIntegerParseTest.java
index 3c3d0cd1..1167da10 100644
--- a/src/test/java/org/mariadb/r2dbc/integration/codec/BigIntegerParseTest.java
+++ b/src/test/java/org/mariadb/r2dbc/integration/codec/BigIntegerParseTest.java
@@ -499,7 +499,10 @@ private void stringValue(MariadbConnection connection) {
.flatMap(r -> r.map((row, metadata) -> Optional.ofNullable(row.get(0, String.class))))
.as(StepVerifier::create)
.expectNext(
- Optional.of("0002"), Optional.of("0020"), Optional.of("0120"), Optional.of("1250"))
+ Optional.of(isXpand() ? "2" : "0002"),
+ Optional.of(isXpand() ? "20" : "0020"),
+ Optional.of(isXpand() ? "120" : "0120"),
+ Optional.of("1250"))
.verifyComplete();
connection
diff --git a/src/test/java/org/mariadb/r2dbc/integration/codec/DateParseTest.java b/src/test/java/org/mariadb/r2dbc/integration/codec/DateParseTest.java
index f4b06a1b..a8ae3d49 100644
--- a/src/test/java/org/mariadb/r2dbc/integration/codec/DateParseTest.java
+++ b/src/test/java/org/mariadb/r2dbc/integration/codec/DateParseTest.java
@@ -82,10 +82,17 @@ void localDateValuePrepare() {
private void localDateValue(MariadbConnection connection) {
connection
- .createStatement("SELECT t1 FROM DateTable WHERE 1 = ?")
+ .createStatement("SELECT t1,t2 FROM DateTable WHERE 1 = ?")
.bind(0, 1)
.execute()
- .flatMap(r -> r.map((row, metadata) -> Optional.ofNullable(row.get(0, LocalDate.class))))
+ .flatMap(
+ r ->
+ r.map(
+ (row, metadata) -> {
+ row.get(0, LocalDate.class);
+ row.get(1);
+ return Optional.ofNullable(row.get(0, LocalDate.class));
+ }))
.as(StepVerifier::create)
.expectNext(
Optional.of(LocalDate.parse("2010-01-12")),
diff --git a/src/test/java/org/mariadb/r2dbc/integration/codec/DateTimeParseTest.java b/src/test/java/org/mariadb/r2dbc/integration/codec/DateTimeParseTest.java
index 2a3968a7..6f0b9c3e 100644
--- a/src/test/java/org/mariadb/r2dbc/integration/codec/DateTimeParseTest.java
+++ b/src/test/java/org/mariadb/r2dbc/integration/codec/DateTimeParseTest.java
@@ -113,6 +113,7 @@ void localTimeValue() {
@Test
void localTimeValuePrepare() {
+ Assumptions.assumeFalse(isXpand());
localTimeValue(sharedConnPrepare);
}
@@ -121,7 +122,13 @@ private void localTimeValue(MariadbConnection connection) {
.createStatement("SELECT t1 FROM DateTimeTable WHERE 1 = ?")
.bind(0, 1)
.execute()
- .flatMap(r -> r.map((row, metadata) -> Optional.ofNullable(row.get(0, LocalTime.class))))
+ .flatMap(
+ r ->
+ r.map(
+ (row, metadata) -> {
+ System.out.println(row.get(0, LocalTime.class));
+ return Optional.ofNullable(row.get(0, LocalTime.class));
+ }))
.as(StepVerifier::create)
.expectNext(
Optional.of(LocalTime.parse("12:50:05.012300")),
@@ -379,6 +386,7 @@ void stringValue() {
@Test
void stringValuePrepare() {
+ Assumptions.assumeFalse(isXpand());
stringValue(
sharedConnPrepare,
Optional.of("2013-07-22 12:50:05.012300"),
diff --git a/src/test/java/org/mariadb/r2dbc/integration/codec/IntParseTest.java b/src/test/java/org/mariadb/r2dbc/integration/codec/IntParseTest.java
index cf545772..2c289562 100644
--- a/src/test/java/org/mariadb/r2dbc/integration/codec/IntParseTest.java
+++ b/src/test/java/org/mariadb/r2dbc/integration/codec/IntParseTest.java
@@ -491,8 +491,8 @@ private void stringValue(MariadbConnection connection) {
.flatMap(r -> r.map((row, metadata) -> Optional.ofNullable(row.get(0, String.class))))
.as(StepVerifier::create)
.expectNext(
- Optional.of("0000000000"),
- Optional.of("0000000010"),
+ Optional.of(isXpand() ? "0" : "0000000000"),
+ Optional.of(isXpand() ? "10" : "0000000010"),
Optional.of("1294967295"),
Optional.empty())
.verifyComplete();
diff --git a/src/test/java/org/mariadb/r2dbc/integration/codec/MediumIntParseTest.java b/src/test/java/org/mariadb/r2dbc/integration/codec/MediumIntParseTest.java
index 719f6fa9..d17690ce 100644
--- a/src/test/java/org/mariadb/r2dbc/integration/codec/MediumIntParseTest.java
+++ b/src/test/java/org/mariadb/r2dbc/integration/codec/MediumIntParseTest.java
@@ -9,6 +9,7 @@
import java.math.BigInteger;
import java.util.Optional;
import org.junit.jupiter.api.AfterAll;
+import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
import org.mariadb.r2dbc.BaseConnectionTest;
@@ -401,9 +402,9 @@ private void stringValue(MariadbConnection connection) {
.flatMap(r -> r.map((row, metadata) -> Optional.ofNullable(row.get(0, String.class))))
.as(StepVerifier::create)
.expectNext(
- Optional.of("00000000"),
- Optional.of("00000010"),
- Optional.of("00000100"),
+ Optional.of(isXpand() ? "0" : "00000000"),
+ Optional.of(isXpand() ? "10" : "00000010"),
+ Optional.of(isXpand() ? "100" : "00000100"),
Optional.empty())
.verifyComplete();
@@ -440,6 +441,42 @@ private void decimalValue(MariadbConnection connection) {
Optional.of(BigDecimal.valueOf(-1)),
Optional.empty())
.verifyComplete();
+
+ connection
+ .createStatement("SELECT t1, t2 FROM MediumIntTable WHERE 1 = ?")
+ .bind(0, 1)
+ .execute()
+ .flatMap(
+ r ->
+ r.map(
+ (row, metadata) -> {
+ return new BigDecimal[] {
+ row.get(0, BigDecimal.class), row.get(1, BigDecimal.class)
+ };
+ }))
+ .as(StepVerifier::create)
+ .assertNext(
+ r -> {
+ Assertions.assertEquals(0, r[0].intValue());
+ Assertions.assertEquals(0, r[1].intValue());
+ })
+ .assertNext(
+ r -> {
+ Assertions.assertEquals(1, r[0].intValue());
+ Assertions.assertEquals(10, r[1].intValue());
+ })
+ .assertNext(
+ r -> {
+ Assertions.assertEquals(-1, r[0].intValue());
+ Assertions.assertEquals(100, r[1].intValue());
+ })
+ .assertNext(
+ r -> {
+ Assertions.assertNull(r[0]);
+ Assertions.assertNull(r[1]);
+ })
+ .verifyComplete();
+
connection
.createStatement("SELECT t1 FROM MediumIntUnsignedTable WHERE 1 = ?")
.bind(0, 1)
diff --git a/src/test/java/org/mariadb/r2dbc/integration/codec/ShortParseTest.java b/src/test/java/org/mariadb/r2dbc/integration/codec/ShortParseTest.java
index ae945522..e6cd5ad8 100644
--- a/src/test/java/org/mariadb/r2dbc/integration/codec/ShortParseTest.java
+++ b/src/test/java/org/mariadb/r2dbc/integration/codec/ShortParseTest.java
@@ -448,7 +448,10 @@ private void stringValue(MariadbConnection connection) {
.flatMap(r -> r.map((row, metadata) -> Optional.ofNullable(row.get(0, String.class))))
.as(StepVerifier::create)
.expectNext(
- Optional.of("00000"), Optional.of("00010"), Optional.of("00100"), Optional.empty())
+ Optional.of(isXpand() ? "0" : "00000"),
+ Optional.of(isXpand() ? "10" : "00010"),
+ Optional.of(isXpand() ? "100" : "00100"),
+ Optional.empty())
.verifyComplete();
connection
diff --git a/src/test/java/org/mariadb/r2dbc/integration/codec/StringParseTest.java b/src/test/java/org/mariadb/r2dbc/integration/codec/StringParseTest.java
index e20f8107..39ff4ce1 100644
--- a/src/test/java/org/mariadb/r2dbc/integration/codec/StringParseTest.java
+++ b/src/test/java/org/mariadb/r2dbc/integration/codec/StringParseTest.java
@@ -123,25 +123,26 @@ private void defaultValue(MariadbConnection connection) {
.verifyComplete();
}
-
@Test
void tt() {
- String b = "0xFFBF0F23485930303054686520636C69656E742077617320646973636F6E6E656374656420627920746865207365727665722062656361757365206F6620696E61637469766974792E2053656520776169745F74696D656F757420616E6420696E7465726163746976655F74696D656F757420666F7220636F6E6669677572696E672074686973206265686176696F722E";
+ String b =
+ "0xFFBF0F23485930303054686520636C69656E742077617320646973636F6E6E656374656420627920746865207365727665722062656361757365206F6620696E61637469766974792E2053656520776169745F74696D656F757420616E6420696E7465726163746976655F74696D656F757420666F7220636F6E6669677572696E672074686973206265686176696F722E";
byte[] bytes = hexStringToByteArray(b);
String st = new String(bytes, StandardCharsets.UTF_8);
System.out.println(st);
-
}
public static byte[] hexStringToByteArray(String hex) {
int l = hex.length();
byte[] data = new byte[l / 2];
for (int i = 0; i < l; i += 2) {
- data[i / 2] = (byte) ((Character.digit(hex.charAt(i), 16) << 4)
- + Character.digit(hex.charAt(i + 1), 16));
+ data[i / 2] =
+ (byte)
+ ((Character.digit(hex.charAt(i), 16) << 4) + Character.digit(hex.charAt(i + 1), 16));
}
return data;
}
+
@Test
void defaultValueBinary() {
defaultValueBinary(sharedConn);
diff --git a/src/test/java/org/mariadb/r2dbc/integration/codec/TimeParseTest.java b/src/test/java/org/mariadb/r2dbc/integration/codec/TimeParseTest.java
index b6f862c8..6e707524 100644
--- a/src/test/java/org/mariadb/r2dbc/integration/codec/TimeParseTest.java
+++ b/src/test/java/org/mariadb/r2dbc/integration/codec/TimeParseTest.java
@@ -12,6 +12,7 @@
import java.time.LocalTime;
import java.util.Optional;
import org.junit.jupiter.api.AfterAll;
+import org.junit.jupiter.api.Assumptions;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
import org.mariadb.r2dbc.BaseConnectionTest;
@@ -415,6 +416,7 @@ void stringValue() {
@Test
void stringValuePrepare() {
+ Assumptions.assumeFalse(isXpand());
stringValue(
sharedConnPrepare,
"90:00:00.012340",
diff --git a/src/test/java/org/mariadb/r2dbc/integration/codec/TimestampParseTest.java b/src/test/java/org/mariadb/r2dbc/integration/codec/TimestampParseTest.java
index 99d285f3..3d7d2b04 100644
--- a/src/test/java/org/mariadb/r2dbc/integration/codec/TimestampParseTest.java
+++ b/src/test/java/org/mariadb/r2dbc/integration/codec/TimestampParseTest.java
@@ -179,9 +179,14 @@ private void booleanValue(MariadbConnection connection) {
.expectErrorMatches(
throwable ->
throwable instanceof R2dbcTransientResourceException
- && throwable
- .getMessage()
- .equals("No decoder for type java.lang.Boolean and column type TIMESTAMP"))
+ && (throwable
+ .getMessage()
+ .equals(
+ "No decoder for type java.lang.Boolean and column type TIMESTAMP")
+ || throwable
+ .getMessage()
+ .equals(
+ "No decoder for type java.lang.Boolean and column type DATETIME")))
.verify();
}
@@ -205,9 +210,12 @@ private void byteArrayValue(MariadbConnection connection) {
.expectErrorMatches(
throwable ->
throwable instanceof R2dbcTransientResourceException
- && throwable
+ && (throwable
+ .getMessage()
+ .equals("No decoder for type byte[] and column type TIMESTAMP"))
+ || throwable
.getMessage()
- .equals("No decoder for type byte[] and column type TIMESTAMP"))
+ .equals("No decoder for type byte[] and column type DATETIME"))
.verify();
}
@@ -231,9 +239,12 @@ private void ByteValue(MariadbConnection connection) {
.expectErrorMatches(
throwable ->
throwable instanceof R2dbcTransientResourceException
- && throwable
- .getMessage()
- .equals("No decoder for type java.lang.Byte and column type TIMESTAMP"))
+ && (throwable
+ .getMessage()
+ .equals("No decoder for type java.lang.Byte and column type TIMESTAMP")
+ || throwable
+ .getMessage()
+ .equals("No decoder for type java.lang.Byte and column type DATETIME")))
.verify();
}
@@ -257,9 +268,12 @@ private void byteValue(MariadbConnection connection) {
.expectErrorMatches(
throwable ->
throwable instanceof R2dbcTransientResourceException
- && throwable
- .getMessage()
- .equals("No decoder for type byte and column type TIMESTAMP"))
+ && (throwable
+ .getMessage()
+ .equals("No decoder for type byte and column type TIMESTAMP")
+ || throwable
+ .getMessage()
+ .equals("No decoder for type byte and column type DATETIME")))
.verify();
}
@@ -283,9 +297,13 @@ private void shortValue(MariadbConnection connection) {
.expectErrorMatches(
throwable ->
throwable instanceof R2dbcTransientResourceException
- && throwable
- .getMessage()
- .equals("No decoder for type java.lang.Short and column type TIMESTAMP"))
+ && (throwable
+ .getMessage()
+ .equals("No decoder for type java.lang.Short and column type TIMESTAMP")
+ || throwable
+ .getMessage()
+ .equals(
+ "No decoder for type java.lang.Short and column type DATETIME")))
.verify();
}
@@ -309,9 +327,14 @@ private void intValue(MariadbConnection connection) {
.expectErrorMatches(
throwable ->
throwable instanceof R2dbcTransientResourceException
- && throwable
- .getMessage()
- .equals("No decoder for type java.lang.Integer and column type TIMESTAMP"))
+ && (throwable
+ .getMessage()
+ .equals(
+ "No decoder for type java.lang.Integer and column type TIMESTAMP")
+ || throwable
+ .getMessage()
+ .equals(
+ "No decoder for type java.lang.Integer and column type DATETIME")))
.verify();
}
@@ -335,9 +358,12 @@ private void longValue(MariadbConnection connection) {
.expectErrorMatches(
throwable ->
throwable instanceof R2dbcTransientResourceException
- && throwable
- .getMessage()
- .equals("No decoder for type java.lang.Long and column type TIMESTAMP"))
+ && (throwable
+ .getMessage()
+ .equals("No decoder for type java.lang.Long and column type TIMESTAMP")
+ || throwable
+ .getMessage()
+ .equals("No decoder for type java.lang.Long and column type DATETIME")))
.verify();
}
@@ -361,9 +387,13 @@ private void floatValue(MariadbConnection connection) {
.expectErrorMatches(
throwable ->
throwable instanceof R2dbcTransientResourceException
- && throwable
- .getMessage()
- .equals("No decoder for type java.lang.Float and column type TIMESTAMP"))
+ && (throwable
+ .getMessage()
+ .equals("No decoder for type java.lang.Float and column type TIMESTAMP")
+ || throwable
+ .getMessage()
+ .equals(
+ "No decoder for type java.lang.Float and column type DATETIME")))
.verify();
}
@@ -387,9 +417,14 @@ private void doubleValue(MariadbConnection connection) {
.expectErrorMatches(
throwable ->
throwable instanceof R2dbcTransientResourceException
- && throwable
- .getMessage()
- .equals("No decoder for type java.lang.Double and column type TIMESTAMP"))
+ && (throwable
+ .getMessage()
+ .equals(
+ "No decoder for type java.lang.Double and column type TIMESTAMP")
+ || throwable
+ .getMessage()
+ .equals(
+ "No decoder for type java.lang.Double and column type DATETIME")))
.verify();
}
@@ -434,10 +469,14 @@ private void decimalValue(MariadbConnection connection) {
.expectErrorMatches(
throwable ->
throwable instanceof R2dbcTransientResourceException
- && throwable
- .getMessage()
- .equals(
- "No decoder for type java.math.BigDecimal and column type TIMESTAMP"))
+ && (throwable
+ .getMessage()
+ .equals(
+ "No decoder for type java.math.BigDecimal and column type TIMESTAMP")
+ || throwable
+ .getMessage()
+ .equals(
+ "No decoder for type java.math.BigDecimal and column type DATETIME")))
.verify();
}
@@ -461,10 +500,14 @@ private void bigintValue(MariadbConnection connection) {
.expectErrorMatches(
throwable ->
throwable instanceof R2dbcTransientResourceException
- && throwable
- .getMessage()
- .equals(
- "No decoder for type java.math.BigInteger and column type TIMESTAMP"))
+ && (throwable
+ .getMessage()
+ .equals(
+ "No decoder for type java.math.BigInteger and column type TIMESTAMP")
+ || throwable
+ .getMessage()
+ .equals(
+ "No decoder for type java.math.BigInteger and column type DATETIME")))
.verify();
}
diff --git a/src/test/java/org/mariadb/r2dbc/integration/codec/TinyIntParseTest.java b/src/test/java/org/mariadb/r2dbc/integration/codec/TinyIntParseTest.java
index 9d39d174..4086dc9e 100644
--- a/src/test/java/org/mariadb/r2dbc/integration/codec/TinyIntParseTest.java
+++ b/src/test/java/org/mariadb/r2dbc/integration/codec/TinyIntParseTest.java
@@ -449,7 +449,11 @@ private void stringValue(MariadbConnection connection) {
.execute()
.flatMap(r -> r.map((row, metadata) -> Optional.ofNullable(row.get(0, String.class))))
.as(StepVerifier::create)
- .expectNext(Optional.of("000"), Optional.of("010"), Optional.of("100"), Optional.empty())
+ .expectNext(
+ Optional.of(isXpand() ? "0" : "000"),
+ Optional.of(isXpand() ? "10" : "010"),
+ Optional.of("100"),
+ Optional.empty())
.verifyComplete();
connection
diff --git a/src/test/java/org/mariadb/r2dbc/integration/codec/YearParseTest.java b/src/test/java/org/mariadb/r2dbc/integration/codec/YearParseTest.java
index 31045df2..c13758f1 100644
--- a/src/test/java/org/mariadb/r2dbc/integration/codec/YearParseTest.java
+++ b/src/test/java/org/mariadb/r2dbc/integration/codec/YearParseTest.java
@@ -10,6 +10,7 @@
import java.time.LocalDate;
import java.util.Optional;
import org.junit.jupiter.api.AfterAll;
+import org.junit.jupiter.api.Assumptions;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
import org.mariadb.r2dbc.BaseConnectionTest;
@@ -23,6 +24,8 @@ public class YearParseTest extends BaseConnectionTest {
@BeforeAll
public static void before2() {
+ // xpand doesn't support YEAR 2
+ Assumptions.assumeFalse(isXpand());
afterAll2();
sharedConn.beginTransaction().block();
String sqlCreate = "CREATE TABLE YearTable (t1 YEAR(4), t2 YEAR(2))";
diff --git a/src/test/java/org/mariadb/r2dbc/integration/parameter/BigIntegerParameterTest.java b/src/test/java/org/mariadb/r2dbc/integration/parameter/BigIntegerParameterTest.java
index 0650f22e..48f88b7d 100644
--- a/src/test/java/org/mariadb/r2dbc/integration/parameter/BigIntegerParameterTest.java
+++ b/src/test/java/org/mariadb/r2dbc/integration/parameter/BigIntegerParameterTest.java
@@ -362,6 +362,7 @@ private void LongValue(MariadbConnection connection) {
@Test
void localDateTimeValue() {
+ Assumptions.assumeFalse(isXpand());
localDateTimeValue(sharedConn);
}
@@ -406,6 +407,7 @@ void localDateTimeValuePrepare() {
@Test
void localDateValue() {
+ Assumptions.assumeFalse(isXpand());
localDateValue(sharedConn);
}
@@ -451,6 +453,7 @@ private void localDateValue(MariadbConnection connection) {
@Test
void localTimeValue() {
+ Assumptions.assumeFalse(isXpand());
localTimeValue(sharedConn);
}
diff --git a/src/test/java/org/mariadb/r2dbc/integration/parameter/BlobParameterTest.java b/src/test/java/org/mariadb/r2dbc/integration/parameter/BlobParameterTest.java
index 6118f537..080213e7 100644
--- a/src/test/java/org/mariadb/r2dbc/integration/parameter/BlobParameterTest.java
+++ b/src/test/java/org/mariadb/r2dbc/integration/parameter/BlobParameterTest.java
@@ -407,7 +407,7 @@ void localDateTimeValue() {
@Test
void localDateTimeValuePrepare() {
-
+ Assumptions.assumeFalse(isXpand());
localDateTimeValue(
sharedConnPrepare,
meta.isMariaDBServer() ? "2013-07-22 12:50:05.012300" : "2013-07-22 12:50:05",
diff --git a/src/test/java/org/mariadb/r2dbc/integration/parameter/DateParameterTest.java b/src/test/java/org/mariadb/r2dbc/integration/parameter/DateParameterTest.java
index a8459be3..e75fbdcb 100644
--- a/src/test/java/org/mariadb/r2dbc/integration/parameter/DateParameterTest.java
+++ b/src/test/java/org/mariadb/r2dbc/integration/parameter/DateParameterTest.java
@@ -399,6 +399,7 @@ private void localDateValue(MariadbConnection connection) {
@Test
void localTimeValue() {
+ Assumptions.assumeFalse(isXpand());
localTimeValue(sharedConn);
}
diff --git a/src/test/java/org/mariadb/r2dbc/integration/parameter/DateTimeParameterTest.java b/src/test/java/org/mariadb/r2dbc/integration/parameter/DateTimeParameterTest.java
index 3066fa82..cac16e7f 100644
--- a/src/test/java/org/mariadb/r2dbc/integration/parameter/DateTimeParameterTest.java
+++ b/src/test/java/org/mariadb/r2dbc/integration/parameter/DateTimeParameterTest.java
@@ -401,11 +401,13 @@ private void localDateValue(MariadbConnection connection) {
@Test
void localTimeValue() {
+ Assumptions.assumeFalse(isXpand());
localTimeValue(sharedConn);
}
@Test
void localTimeValuePrepare() {
+ Assumptions.assumeFalse(isXpand());
LocalTime localTime = LocalTime.parse("05:08:10.123456");
LocalDateTime localDateTime =
LocalDateTime.now().withHour(5).withMinute(8).withSecond(10).withNano(123456 * 1000);
diff --git a/src/test/java/org/mariadb/r2dbc/integration/parameter/FloatParameterTest.java b/src/test/java/org/mariadb/r2dbc/integration/parameter/FloatParameterTest.java
index e71847b2..dea6255f 100644
--- a/src/test/java/org/mariadb/r2dbc/integration/parameter/FloatParameterTest.java
+++ b/src/test/java/org/mariadb/r2dbc/integration/parameter/FloatParameterTest.java
@@ -266,6 +266,7 @@ private void longValue(MariadbConnection connection) {
@Test
void localDateTimeValue() {
+ Assumptions.assumeFalse(isXpand());
localDateTimeValue(sharedConn);
}
@@ -287,6 +288,7 @@ private void localDateTimeValue(MariadbConnection connection) {
@Test
void localDateValue() {
+ Assumptions.assumeFalse(isXpand());
localDateValue(sharedConn);
}
@@ -308,6 +310,7 @@ private void localDateValue(MariadbConnection connection) {
@Test
void localTimeValue() {
+ Assumptions.assumeFalse(isXpand());
localTimeValue(sharedConn);
}
diff --git a/src/test/java/org/mariadb/r2dbc/integration/parameter/IntParameterTest.java b/src/test/java/org/mariadb/r2dbc/integration/parameter/IntParameterTest.java
index bd61deae..a1f9438e 100644
--- a/src/test/java/org/mariadb/r2dbc/integration/parameter/IntParameterTest.java
+++ b/src/test/java/org/mariadb/r2dbc/integration/parameter/IntParameterTest.java
@@ -261,7 +261,10 @@ void localDateTimeValue() {
.expectErrorMatches(
throwable ->
throwable instanceof R2dbcTransientResourceException
- && ((R2dbcTransientResourceException) throwable).getSqlState().equals("01000"))
+ && (((R2dbcTransientResourceException) throwable).getSqlState().equals("01000")
+ || ((R2dbcTransientResourceException) throwable)
+ .getMessage()
+ .contains("truncated for conversion to INT")))
.verify();
}
@@ -278,7 +281,10 @@ void localDateValue() {
.expectErrorMatches(
throwable ->
throwable instanceof R2dbcTransientResourceException
- && ((R2dbcTransientResourceException) throwable).getSqlState().equals("01000"))
+ && (((R2dbcTransientResourceException) throwable).getSqlState().equals("01000")
+ || ((R2dbcTransientResourceException) throwable)
+ .getMessage()
+ .contains("truncated for conversion to INT")))
.verify();
}
@@ -295,7 +301,10 @@ void localTimeValue() {
.expectErrorMatches(
throwable ->
throwable instanceof R2dbcTransientResourceException
- && ((R2dbcTransientResourceException) throwable).getSqlState().equals("01000"))
+ && (((R2dbcTransientResourceException) throwable).getSqlState().equals("01000")
+ || ((R2dbcTransientResourceException) throwable)
+ .getMessage()
+ .contains("truncated for conversion to INT")))
.verify();
}
diff --git a/src/test/java/org/mariadb/r2dbc/integration/parameter/MediumIntParameterTest.java b/src/test/java/org/mariadb/r2dbc/integration/parameter/MediumIntParameterTest.java
index 906f5b00..c4cc8e94 100644
--- a/src/test/java/org/mariadb/r2dbc/integration/parameter/MediumIntParameterTest.java
+++ b/src/test/java/org/mariadb/r2dbc/integration/parameter/MediumIntParameterTest.java
@@ -10,10 +10,7 @@
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.util.Optional;
-import org.junit.jupiter.api.AfterAll;
-import org.junit.jupiter.api.BeforeAll;
-import org.junit.jupiter.api.BeforeEach;
-import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.*;
import org.mariadb.r2dbc.BaseConnectionTest;
import org.mariadb.r2dbc.api.MariadbConnection;
import reactor.core.publisher.Flux;
@@ -250,6 +247,7 @@ private void longValue(MariadbConnection connection) {
@Test
void localDateTimeValue() {
+ Assumptions.assumeFalse(isXpand());
sharedConn
.createStatement("INSERT INTO MediumIntParam VALUES (?,?,?)")
.bind(0, LocalDateTime.now())
@@ -267,6 +265,7 @@ void localDateTimeValue() {
@Test
void localDateValue() {
+ Assumptions.assumeFalse(isXpand());
sharedConn
.createStatement("INSERT INTO MediumIntParam VALUES (?,?,?)")
.bind(0, LocalDate.now())
@@ -284,6 +283,7 @@ void localDateValue() {
@Test
void localTimeValue() {
+ Assumptions.assumeFalse(isXpand());
sharedConn
.createStatement("INSERT INTO MediumIntParam VALUES (?,?,?)")
.bind(0, LocalTime.now())
diff --git a/src/test/java/org/mariadb/r2dbc/integration/parameter/ShortParameterTest.java b/src/test/java/org/mariadb/r2dbc/integration/parameter/ShortParameterTest.java
index b4437d86..6e672d60 100644
--- a/src/test/java/org/mariadb/r2dbc/integration/parameter/ShortParameterTest.java
+++ b/src/test/java/org/mariadb/r2dbc/integration/parameter/ShortParameterTest.java
@@ -10,10 +10,7 @@
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.util.Optional;
-import org.junit.jupiter.api.AfterAll;
-import org.junit.jupiter.api.BeforeAll;
-import org.junit.jupiter.api.BeforeEach;
-import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.*;
import org.mariadb.r2dbc.BaseConnectionTest;
import org.mariadb.r2dbc.api.MariadbConnection;
import reactor.core.publisher.Flux;
@@ -277,6 +274,7 @@ private void longValue(MariadbConnection connection) {
@Test
void localDateTimeValue() {
+ Assumptions.assumeFalse(isXpand());
sharedConn
.createStatement("INSERT INTO SmallIntParam VALUES (?,?,?)")
.bind(0, LocalDateTime.now())
@@ -294,6 +292,7 @@ void localDateTimeValue() {
@Test
void localDateValue() {
+ Assumptions.assumeFalse(isXpand());
sharedConn
.createStatement("INSERT INTO SmallIntParam VALUES (?,?,?)")
.bind(0, LocalDate.now())
@@ -311,6 +310,7 @@ void localDateValue() {
@Test
void localTimeValue() {
+ Assumptions.assumeFalse(isXpand());
sharedConn
.createStatement("INSERT INTO SmallIntParam VALUES (?,?,?)")
.bind(0, LocalTime.now())
diff --git a/src/test/java/org/mariadb/r2dbc/integration/parameter/StringParameterTest.java b/src/test/java/org/mariadb/r2dbc/integration/parameter/StringParameterTest.java
index ab27747a..0f6f6875 100644
--- a/src/test/java/org/mariadb/r2dbc/integration/parameter/StringParameterTest.java
+++ b/src/test/java/org/mariadb/r2dbc/integration/parameter/StringParameterTest.java
@@ -459,7 +459,10 @@ void durationValue() {
void durationValuePrepare() {
durationValue(sharedConnPrepare);
if (meta.isMariaDBServer()) {
- validate(Optional.of("90:00:00.012340"), Optional.of("00:08:00"), Optional.of("00:00:22"));
+ validate(
+ Optional.of("90:00:00.012340"),
+ Optional.of(isXpand() ? "00:08:00.000000" : "00:08:00"),
+ Optional.of(isXpand() ? "00:00:22.000000" : "00:00:22"));
} else {
validate(Optional.of("90:00:00"), Optional.of("00:08:00"), Optional.of("00:00:22"));
}
diff --git a/src/test/java/org/mariadb/r2dbc/integration/parameter/TimeParameterTest.java b/src/test/java/org/mariadb/r2dbc/integration/parameter/TimeParameterTest.java
index 711fb1c0..7fa074a5 100644
--- a/src/test/java/org/mariadb/r2dbc/integration/parameter/TimeParameterTest.java
+++ b/src/test/java/org/mariadb/r2dbc/integration/parameter/TimeParameterTest.java
@@ -326,6 +326,7 @@ private void localDateTimeValue(MariadbConnection connection) {
@Test
void localDateValue() {
+ Assumptions.assumeFalse(isXpand());
localDateValue(sharedConn);
}
diff --git a/src/test/java/org/mariadb/r2dbc/integration/parameter/TimeStampParameterTest.java b/src/test/java/org/mariadb/r2dbc/integration/parameter/TimeStampParameterTest.java
index e455f7c6..7dfd131f 100644
--- a/src/test/java/org/mariadb/r2dbc/integration/parameter/TimeStampParameterTest.java
+++ b/src/test/java/org/mariadb/r2dbc/integration/parameter/TimeStampParameterTest.java
@@ -376,6 +376,7 @@ private void localDateValue(MariadbConnection connection) {
@Test
void localTimeValue() {
+ Assumptions.assumeFalse(isXpand());
localTimeValue(sharedConn);
}
diff --git a/src/test/java/org/mariadb/r2dbc/integration/parameter/TinyIntParameterTest.java b/src/test/java/org/mariadb/r2dbc/integration/parameter/TinyIntParameterTest.java
index 0db37b25..97769e07 100644
--- a/src/test/java/org/mariadb/r2dbc/integration/parameter/TinyIntParameterTest.java
+++ b/src/test/java/org/mariadb/r2dbc/integration/parameter/TinyIntParameterTest.java
@@ -343,6 +343,7 @@ private void localDateValue(MariadbConnection connection) {
@Test
void localTimeValue() {
+ Assumptions.assumeFalse(isXpand());
localTimeValue(sharedConn);
}
diff --git a/src/test/java/org/mariadb/r2dbc/unit/MariadbConnectionConfigurationTest.java b/src/test/java/org/mariadb/r2dbc/unit/MariadbConnectionConfigurationTest.java
new file mode 100644
index 00000000..80ea8454
--- /dev/null
+++ b/src/test/java/org/mariadb/r2dbc/unit/MariadbConnectionConfigurationTest.java
@@ -0,0 +1,96 @@
+package org.mariadb.r2dbc.unit;
+
+import io.r2dbc.spi.ConnectionFactoryOptions;
+import io.r2dbc.spi.IsolationLevel;
+import java.time.Duration;
+import java.util.Map;
+import java.util.TreeMap;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Test;
+import org.mariadb.r2dbc.MariadbConnectionConfiguration;
+import org.mariadb.r2dbc.SslMode;
+import reactor.netty.resources.LoopResources;
+
+public class MariadbConnectionConfigurationTest {
+ @Test
+ public void builder() {
+ TreeMap connectionAttributes = new TreeMap<>();
+ connectionAttributes.put("entry1", "val1");
+ connectionAttributes.put("entry2", "val2");
+
+ MariadbConnectionConfiguration conf =
+ MariadbConnectionConfiguration.builder()
+ .connectTimeout(Duration.ofMillis(150))
+ .haMode("LOADBALANCE")
+ .restrictedAuth("mysql_native_password,client_ed25519")
+ .tcpKeepAlive(true)
+ .tcpAbortiveClose(true)
+ .transactionReplay(true)
+ .connectionAttributes(connectionAttributes)
+ .sessionVariables(Map.of("timezone", "Europe/Paris"))
+ .pamOtherPwd(new String[] {"otherPwd"})
+ .database("MyDB")
+ .password("MyPassword")
+ .tlsProtocol("TLSv1.2", "TLSv1.3")
+ .serverSslCert("/path/to/serverCert")
+ .prepareCacheSize(125)
+ .clientSslKey("clientSecretKey")
+ .clientSslPassword("ClientSecretPwd")
+ .sslMode(SslMode.TRUST)
+ .rsaPublicKey("/path/to/publicRSAKey")
+ .cachingRsaPublicKey("cachingRSAPublicKey")
+ .allowPublicKeyRetrieval(true)
+ .useServerPrepStmts(true)
+ .isolationLevel(IsolationLevel.SERIALIZABLE)
+ .autocommit(false)
+ .tinyInt1isBit(false)
+ .allowPipelining(false)
+ .allowMultiQueries(true)
+ .socket("/path/to/mysocket")
+ .username("MyUSer")
+ .loopResources(LoopResources.create("mariadb"))
+ .sslContextBuilderCustomizer((b) -> b)
+ .sslTunnelDisableHostVerification(true)
+ .build();
+ Assertions.assertEquals(
+ "MariadbConnectionConfiguration{database='MyDB', hosts={[localhost:3306]}, connectTimeout=PT0.15S, tcpKeepAlive=true, tcpAbortiveClose=true, transactionReplay=true, password=*, prepareCacheSize=125, socket='/path/to/mysocket', username='MyUSer', allowMultiQueries=true, allowPipelining=false, connectionAttributes={entry1=val1, entry2=val2}, sessionVariables={timezone=Europe/Paris}, sslConfig=SslConfig{sslMode=TRUST, serverSslCert=/path/to/serverCert, clientSslCert=null, tlsProtocol=[TLSv1.2, TLSv1.3], clientSslKey=clientSecretKey}, rsaPublicKey='/path/to/publicRSAKey', cachingRsaPublicKey='cachingRSAPublicKey', allowPublicKeyRetrieval=true, isolationLevel=IsolationLevel{sql='SERIALIZABLE'}, useServerPrepStmts=false, autocommit=false, tinyInt1isBit=false, pamOtherPwd=*, restrictedAuth=[mysql_native_password, client_ed25519]}",
+ conf.toString());
+ }
+
+ @Test
+ public void connectionString() {
+ ConnectionFactoryOptions options =
+ ConnectionFactoryOptions.parse(
+ "r2dbc:mariadb://ro%3Aot:pw%3Ad@localhost:3306/db?connectTimeout=PT0.15S"
+ + "&haMode=LOADBALANCE"
+ + "&restrictedAuth=mysql_native_password,client_ed25519"
+ + "&tcpKeepAlive=true"
+ + "&tcpAbortiveClose=true"
+ + "&transactionReplay=true"
+ + "&connectionAttributes=entry1=val1,entry2=val2"
+ + "&sessionVariables=timezone=Europe/Paris"
+ + "&pamOtherPwd=otherPwd"
+ + "&tlsProtocol=TLSv1.2,TLSv1.3"
+ + "&serverSslCert=/path/to/serverCert"
+ + "&prepareCacheSize=125"
+ + "&clientSslKey=clientSecretKey"
+ + "&clientSslPassword=ClientSecretPwd"
+ + "&sslMode=TRUST"
+ + "&rsaPublicKey=/path/to/publicRSAKey"
+ + "&cachingRsaPublicKey=cachingRSAPublicKey"
+ + "&allowPublicKeyRetrieval=true"
+ + "&useServerPrepStmts=true"
+ + "&isolationLevel=SERIALIZABLE"
+ + "&autocommit=false"
+ + "&tinyInt1isBit=false"
+ + "&allowPipelining=false"
+ + "&allowMultiQueries=true"
+ + "&socket=/path/to/mysocket"
+ + "&sslTunnelDisableHostVerification=true");
+ MariadbConnectionConfiguration conf =
+ MariadbConnectionConfiguration.fromOptions(options).build();
+ Assertions.assertEquals(
+ "MariadbConnectionConfiguration{database='db', hosts={[localhost:3306]}, connectTimeout=PT0.15S, tcpKeepAlive=true, tcpAbortiveClose=true, transactionReplay=true, password=*, prepareCacheSize=125, socket='/path/to/mysocket', username='ro:ot', allowMultiQueries=true, allowPipelining=false, connectionAttributes={entry1=val1, entry2=val2}, sessionVariables={timezone=Europe/Paris}, sslConfig=SslConfig{sslMode=TRUST, serverSslCert=/path/to/serverCert, clientSslCert=null, tlsProtocol=[TLSv1.2, TLSv1.3], clientSslKey=clientSecretKey}, rsaPublicKey='/path/to/publicRSAKey', cachingRsaPublicKey='cachingRSAPublicKey', allowPublicKeyRetrieval=true, isolationLevel=IsolationLevel{sql='SERIALIZABLE'}, useServerPrepStmts=false, autocommit=false, tinyInt1isBit=false, pamOtherPwd=*, restrictedAuth=[mysql_native_password, client_ed25519]}",
+ conf.toString());
+ }
+}
diff --git a/src/test/java/org/mariadb/r2dbc/unit/util/ClientPrepareResultTest.java b/src/test/java/org/mariadb/r2dbc/unit/util/ClientPrepareResultTest.java
index 7cfa9d61..fdfbaed8 100644
--- a/src/test/java/org/mariadb/r2dbc/unit/util/ClientPrepareResultTest.java
+++ b/src/test/java/org/mariadb/r2dbc/unit/util/ClientPrepareResultTest.java
@@ -151,6 +151,19 @@ public void stringEscapeParsing() throws Exception {
});
}
+ @Test
+ public void clientNoParameterParsing() {
+ checkParsing(
+ "SELECT @amount := 10",
+ 0,
+ 0,
+ true,
+ false,
+ false,
+ new String[] {"SELECT @amount := 10"},
+ new String[] {"SELECT @amount := 10"});
+ }
+
@Test
public void stringReturningParsing() throws Exception {
checkParsing(