Skip to content

Commit

Permalink
d
Browse files Browse the repository at this point in the history
  • Loading branch information
jchrys committed Jan 18, 2024
1 parent 780b8e2 commit e839c69
Showing 1 changed file with 23 additions and 13 deletions.
36 changes: 23 additions & 13 deletions src/main/java/io/asyncer/r2dbc/mysql/MySqlConnection.java
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
import io.r2dbc.spi.Connection;
import io.r2dbc.spi.IsolationLevel;
import io.r2dbc.spi.Lifecycle;
import io.r2dbc.spi.R2dbcNonTransientResourceException;
import io.r2dbc.spi.TransactionDefinition;
import io.r2dbc.spi.ValidationDepth;
import org.jetbrains.annotations.Nullable;
Expand Down Expand Up @@ -74,6 +75,10 @@ public final class MySqlConnection implements Connection, Lifecycle, ConnectionS

private static final ServerVersion MYSQL_8 = ServerVersion.create(8, 0, 0);

private static final ServerVersion MYSQL_STATEMENT_TIMEOUT = ServerVersion.create(5, 7, 4);

private static final ServerVersion MARIA_STATEMENT_TIMEOUT = ServerVersion.create(10, 2, 0);

private static final BiConsumer<ServerMessage, SynchronousSink<Boolean>> PING = (message, sink) -> {
if (message instanceof ErrorMessage) {
ErrorMessage msg = (ErrorMessage) message;
Expand Down Expand Up @@ -396,21 +401,26 @@ public Mono<Void> setLockWaitTimeout(Duration timeout) {
@Override
public Mono<Void> setStatementTimeout(Duration timeout) {
requireNonNull(timeout, "timeout must not be null");
final ServerVersion supportedVersion = ServerVersion.create(5, 7, 4);
long time = timeout.toMillis();
ServerVersion serverVersion = context.getServerVersion();
boolean serverSupportTimeout = serverVersion.isGreaterThanOrEqualTo(supportedVersion);

if (!serverSupportTimeout) {
return Mono.defer(() -> Mono.error(new RuntimeException(
"Query timeout is not supported by the server. (Required MySQL 5.7.4+)")));
final boolean isMariaDb = context.getCapability().isMariaDb();
final ServerVersion serverVersion = context.getServerVersion();
final String sql = isMariaDb ? "SET max_statement_time=" + timeout.getSeconds()
: "SET SESSION MAX_EXECUTION_TIME=" + timeout.toMillis();

// mariadb: https://mariadb.com/kb/en/aborting-statements/
// mysql: https://dev.mysql.com/blog-archive/server-side-select-statement-timeouts/
if (isMariaDb && serverVersion.isGreaterThanOrEqualTo(MARIA_STATEMENT_TIMEOUT)
|| !isMariaDb && serverVersion.isGreaterThanOrEqualTo(MYSQL_STATEMENT_TIMEOUT)) {
return QueryFlow.executeVoid(client, sql);
}

String sqlStatement = String.format("SET SESSION MAX_EXECUTION_TIME=%s", time);
return QueryFlow.execute(client, sqlStatement)
.doOnError(error -> {
logger.error("Error setting statement timeout", error);
}).then();
return Mono.error(
new R2dbcNonTransientResourceException(
"Statement timeout is not supported by server version " + serverVersion,
"HY000",
-1,
sql
)
);
}

boolean isSessionAutoCommit() {
Expand Down

0 comments on commit e839c69

Please sign in to comment.