This is an automated email from the ASF dual-hosted git repository.
zhangliang pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/shardingsphere.git
The following commit(s) were added to refs/heads/master by this push:
new 0c36db69526 Add
DialectDatabaseMetaData.isSupportAutoCommitInNestedTransaction (#35170)
0c36db69526 is described below
commit 0c36db69526b8174cf526c0bc6ae3b2c29201837
Author: Liang Zhang <[email protected]>
AuthorDate: Sat Apr 12 21:11:08 2025 +0800
Add DialectDatabaseMetaData.isSupportAutoCommitInNestedTransaction (#35170)
* Add DialectDatabaseMetaData.isSupportAutoCommitInNestedTransaction
* Add DialectDatabaseMetaData.isSupportAutoCommitInNestedTransaction
* Add DialectDatabaseMetaData.isSupportAutoCommitInNestedTransaction
* Add DialectDatabaseMetaData.isSupportAutoCommitInNestedTransaction
---
.../metadata/database/DialectDatabaseMetaData.java | 9 ++++++++
.../metadata/database/MySQLDatabaseMetaData.java | 5 +++++
.../transaction/TransactionBackendHandler.java | 25 +++++++++++-----------
.../handler/ProxyBackendHandlerFactoryTest.java | 1 +
.../TransactionBackendHandlerFactoryTest.java | 6 ++++++
.../transaction/TransactionBackendHandlerTest.java | 5 +++++
6 files changed, 38 insertions(+), 13 deletions(-)
diff --git
a/infra/database/core/src/main/java/org/apache/shardingsphere/infra/database/core/metadata/database/DialectDatabaseMetaData.java
b/infra/database/core/src/main/java/org/apache/shardingsphere/infra/database/core/metadata/database/DialectDatabaseMetaData.java
index 00a2f9fa792..4157a607c00 100644
---
a/infra/database/core/src/main/java/org/apache/shardingsphere/infra/database/core/metadata/database/DialectDatabaseMetaData.java
+++
b/infra/database/core/src/main/java/org/apache/shardingsphere/infra/database/core/metadata/database/DialectDatabaseMetaData.java
@@ -148,6 +148,15 @@ public interface DialectDatabaseMetaData extends
DatabaseTypedSPI {
return false;
}
+ /**
+ * Whether support auto commit when nested transaction.
+ *
+ * @return support or not
+ */
+ default boolean isSupportAutoCommitInNestedTransaction() {
+ return false;
+ }
+
/**
* Whether support DDL in XA transaction.
*
diff --git
a/infra/database/type/mysql/src/main/java/org/apache/shardingsphere/infra/database/mysql/metadata/database/MySQLDatabaseMetaData.java
b/infra/database/type/mysql/src/main/java/org/apache/shardingsphere/infra/database/mysql/metadata/database/MySQLDatabaseMetaData.java
index 973dad7d180..b0eb71727d8 100644
---
a/infra/database/type/mysql/src/main/java/org/apache/shardingsphere/infra/database/mysql/metadata/database/MySQLDatabaseMetaData.java
+++
b/infra/database/type/mysql/src/main/java/org/apache/shardingsphere/infra/database/mysql/metadata/database/MySQLDatabaseMetaData.java
@@ -93,6 +93,11 @@ public final class MySQLDatabaseMetaData implements
DialectDatabaseMetaData {
return true;
}
+ @Override
+ public boolean isSupportAutoCommitInNestedTransaction() {
+ return true;
+ }
+
@Override
public String getDatabaseType() {
return "MySQL";
diff --git
a/proxy/backend/core/src/main/java/org/apache/shardingsphere/proxy/backend/handler/transaction/TransactionBackendHandler.java
b/proxy/backend/core/src/main/java/org/apache/shardingsphere/proxy/backend/handler/transaction/TransactionBackendHandler.java
index 13fdcacb897..d7e521e0552 100644
---
a/proxy/backend/core/src/main/java/org/apache/shardingsphere/proxy/backend/handler/transaction/TransactionBackendHandler.java
+++
b/proxy/backend/core/src/main/java/org/apache/shardingsphere/proxy/backend/handler/transaction/TransactionBackendHandler.java
@@ -17,8 +17,8 @@
package org.apache.shardingsphere.proxy.backend.handler.transaction;
+import
org.apache.shardingsphere.infra.database.core.metadata.database.DialectDatabaseMetaData;
import org.apache.shardingsphere.infra.database.core.type.DatabaseTypeRegistry;
-import org.apache.shardingsphere.infra.database.mysql.type.MySQLDatabaseType;
import
org.apache.shardingsphere.infra.exception.core.ShardingSpherePreconditions;
import
org.apache.shardingsphere.infra.exception.dialect.exception.transaction.InTransactionException;
import org.apache.shardingsphere.proxy.backend.connector.TransactionManager;
@@ -44,7 +44,7 @@ import java.sql.SQLException;
import java.sql.SQLFeatureNotSupportedException;
/**
- * Do transaction operation.
+ * Transaction backend handler.
*/
public final class TransactionBackendHandler implements ProxyBackendHandler {
@@ -52,14 +52,17 @@ public final class TransactionBackendHandler implements
ProxyBackendHandler {
private final TransactionOperationType operationType;
- private final TransactionManager backendTransactionManager;
-
private final ConnectionSession connectionSession;
+ private final DialectDatabaseMetaData dialectDatabaseMetaData;
+
+ private final TransactionManager backendTransactionManager;
+
public TransactionBackendHandler(final TCLStatement tclStatement, final
TransactionOperationType operationType, final ConnectionSession
connectionSession) {
this.tclStatement = tclStatement;
this.operationType = operationType;
this.connectionSession = connectionSession;
+ dialectDatabaseMetaData = new
DatabaseTypeRegistry(connectionSession.getProtocolType()).getDialectDatabaseMetaData();
backendTransactionManager = new
BackendTransactionManager(connectionSession.getDatabaseConnectionManager());
}
@@ -96,9 +99,9 @@ public final class TransactionBackendHandler implements
ProxyBackendHandler {
private void handleBegin() throws SQLException {
if (connectionSession.getTransactionStatus().isInTransaction()) {
- if (connectionSession.getProtocolType() instanceof
MySQLDatabaseType) {
+ if
(dialectDatabaseMetaData.isSupportAutoCommitInNestedTransaction()) {
backendTransactionManager.commit();
- } else if (isSchemaSupportedDatabaseType()) {
+ } else if (dialectDatabaseMetaData.getDefaultSchema().isPresent())
{
throw new InTransactionException();
}
}
@@ -106,27 +109,23 @@ public final class TransactionBackendHandler implements
ProxyBackendHandler {
}
private void handleSavepoint() throws SQLException {
-
ShardingSpherePreconditions.checkState(connectionSession.getTransactionStatus().isInTransaction()
|| !isSchemaSupportedDatabaseType(),
+
ShardingSpherePreconditions.checkState(connectionSession.getTransactionStatus().isInTransaction()
|| !dialectDatabaseMetaData.getDefaultSchema().isPresent(),
() -> new SQLFeatureNotSupportedException("SAVEPOINT can only
be used in transaction blocks"));
backendTransactionManager.setSavepoint(((SavepointStatement)
tclStatement).getSavepointName());
}
private void handleRollbackToSavepoint() throws SQLException {
-
ShardingSpherePreconditions.checkState(connectionSession.getTransactionStatus().isInTransaction()
|| !isSchemaSupportedDatabaseType(),
+
ShardingSpherePreconditions.checkState(connectionSession.getTransactionStatus().isInTransaction()
|| !dialectDatabaseMetaData.getDefaultSchema().isPresent(),
() -> new SQLFeatureNotSupportedException("ROLLBACK TO
SAVEPOINT can only be used in transaction blocks"));
backendTransactionManager.rollbackTo(((RollbackStatement)
tclStatement).getSavepointName().get());
}
private void handleReleaseSavepoint() throws SQLException {
-
ShardingSpherePreconditions.checkState(connectionSession.getTransactionStatus().isInTransaction()
|| !isSchemaSupportedDatabaseType(),
+
ShardingSpherePreconditions.checkState(connectionSession.getTransactionStatus().isInTransaction()
|| !dialectDatabaseMetaData.getDefaultSchema().isPresent(),
() -> new SQLFeatureNotSupportedException("RELEASE SAVEPOINT
can only be used in transaction blocks"));
backendTransactionManager.releaseSavepoint(((ReleaseSavepointStatement)
tclStatement).getSavepointName());
}
- private boolean isSchemaSupportedDatabaseType() {
- return new
DatabaseTypeRegistry(connectionSession.getProtocolType()).getDialectDatabaseMetaData().getDefaultSchema().isPresent();
- }
-
private SQLStatement getSQLStatementByCommit() {
SQLStatement result = tclStatement;
if
(connectionSession.getConnectionContext().getTransactionContext().isExceptionOccur())
{
diff --git
a/proxy/backend/core/src/test/java/org/apache/shardingsphere/proxy/backend/handler/ProxyBackendHandlerFactoryTest.java
b/proxy/backend/core/src/test/java/org/apache/shardingsphere/proxy/backend/handler/ProxyBackendHandlerFactoryTest.java
index 4a8a642adbe..79326507500 100644
---
a/proxy/backend/core/src/test/java/org/apache/shardingsphere/proxy/backend/handler/ProxyBackendHandlerFactoryTest.java
+++
b/proxy/backend/core/src/test/java/org/apache/shardingsphere/proxy/backend/handler/ProxyBackendHandlerFactoryTest.java
@@ -99,6 +99,7 @@ class ProxyBackendHandlerFactoryTest {
ProxyDatabaseConnectionManager databaseConnectionManager =
mock(ProxyDatabaseConnectionManager.class);
when(databaseConnectionManager.getConnectionSession()).thenReturn(connectionSession);
when(connectionSession.getDatabaseConnectionManager()).thenReturn(databaseConnectionManager);
+ when(connectionSession.getProtocolType()).thenReturn(databaseType);
ContextManager contextManager = mockContextManager();
when(contextManager.getStateContext().getState()).thenReturn(ShardingSphereState.OK);
when(ProxyContext.getInstance().getContextManager()).thenReturn(contextManager);
diff --git
a/proxy/backend/core/src/test/java/org/apache/shardingsphere/proxy/backend/handler/transaction/TransactionBackendHandlerFactoryTest.java
b/proxy/backend/core/src/test/java/org/apache/shardingsphere/proxy/backend/handler/transaction/TransactionBackendHandlerFactoryTest.java
index b325704dab8..212e3ee40de 100644
---
a/proxy/backend/core/src/test/java/org/apache/shardingsphere/proxy/backend/handler/transaction/TransactionBackendHandlerFactoryTest.java
+++
b/proxy/backend/core/src/test/java/org/apache/shardingsphere/proxy/backend/handler/transaction/TransactionBackendHandlerFactoryTest.java
@@ -19,11 +19,13 @@ package
org.apache.shardingsphere.proxy.backend.handler.transaction;
import lombok.SneakyThrows;
import
org.apache.shardingsphere.infra.binder.context.statement.SQLStatementContext;
+import org.apache.shardingsphere.infra.database.core.type.DatabaseType;
import org.apache.shardingsphere.infra.metadata.ShardingSphereMetaData;
import org.apache.shardingsphere.infra.metadata.database.rule.RuleMetaData;
import org.apache.shardingsphere.infra.session.connection.ConnectionContext;
import
org.apache.shardingsphere.infra.session.connection.transaction.TransactionConnectionContext;
import org.apache.shardingsphere.infra.session.query.QueryContext;
+import org.apache.shardingsphere.infra.spi.type.typed.TypedSPILoader;
import org.apache.shardingsphere.mode.manager.ContextManager;
import org.apache.shardingsphere.proxy.backend.connector.DatabaseConnector;
import
org.apache.shardingsphere.proxy.backend.connector.DatabaseConnectorFactory;
@@ -62,11 +64,14 @@ import static org.mockito.Mockito.when;
@StaticMockSettings({ProxyContext.class, DatabaseConnectorFactory.class})
class TransactionBackendHandlerFactoryTest {
+ private final DatabaseType databaseType =
TypedSPILoader.getService(DatabaseType.class, "FIXTURE");
+
@Test
void
assertTransactionBackendHandlerReturnedWhenTCLStatementInstanceOfCommitStatement()
{
ConnectionSession connectionSession = mock(ConnectionSession.class,
Answers.RETURNS_DEEP_STUBS);
ProxyDatabaseConnectionManager databaseConnectionManager =
mock(ProxyDatabaseConnectionManager.class);
when(connectionSession.getDatabaseConnectionManager()).thenReturn(databaseConnectionManager);
+ when(connectionSession.getProtocolType()).thenReturn(databaseType);
when(databaseConnectionManager.getConnectionSession()).thenReturn(connectionSession);
when(databaseConnectionManager.getConnectionSession().getConnectionContext().getTransactionContext()).thenReturn(new
TransactionConnectionContext());
SQLStatementContext context = mock(SQLStatementContext.class);
@@ -85,6 +90,7 @@ class TransactionBackendHandlerFactoryTest {
ConnectionSession connectionSession = mock(ConnectionSession.class,
Answers.RETURNS_DEEP_STUBS);
ProxyDatabaseConnectionManager databaseConnectionManager =
mock(ProxyDatabaseConnectionManager.class);
when(connectionSession.getDatabaseConnectionManager()).thenReturn(databaseConnectionManager);
+ when(connectionSession.getProtocolType()).thenReturn(databaseType);
when(databaseConnectionManager.getConnectionSession()).thenReturn(connectionSession);
when(databaseConnectionManager.getConnectionSession().getConnectionContext().getTransactionContext()).thenReturn(new
TransactionConnectionContext());
when(connectionSession.getDatabaseConnectionManager().getConnectionSession().getConnectionContext().getTransactionContext()).thenReturn(new
TransactionConnectionContext());
diff --git
a/proxy/backend/core/src/test/java/org/apache/shardingsphere/proxy/backend/handler/transaction/TransactionBackendHandlerTest.java
b/proxy/backend/core/src/test/java/org/apache/shardingsphere/proxy/backend/handler/transaction/TransactionBackendHandlerTest.java
index 4ab0b3005b6..182b9a5b9f7 100644
---
a/proxy/backend/core/src/test/java/org/apache/shardingsphere/proxy/backend/handler/transaction/TransactionBackendHandlerTest.java
+++
b/proxy/backend/core/src/test/java/org/apache/shardingsphere/proxy/backend/handler/transaction/TransactionBackendHandlerTest.java
@@ -17,7 +17,9 @@
package org.apache.shardingsphere.proxy.backend.handler.transaction;
+import org.apache.shardingsphere.infra.database.core.type.DatabaseType;
import org.apache.shardingsphere.infra.metadata.database.rule.RuleMetaData;
+import org.apache.shardingsphere.infra.spi.type.typed.TypedSPILoader;
import org.apache.shardingsphere.mode.manager.ContextManager;
import
org.apache.shardingsphere.proxy.backend.connector.ProxyDatabaseConnectionManager;
import org.apache.shardingsphere.proxy.backend.context.ProxyContext;
@@ -45,12 +47,15 @@ import static org.mockito.Mockito.when;
@StaticMockSettings(ProxyContext.class)
class TransactionBackendHandlerTest {
+ private final DatabaseType databaseType =
TypedSPILoader.getService(DatabaseType.class, "FIXTURE");
+
private final ConnectionSession connectionSession =
mock(ConnectionSession.class, RETURNS_DEEP_STUBS);
@Test
void assertExecute() throws SQLException {
ProxyDatabaseConnectionManager databaseConnectionManager =
mock(ProxyDatabaseConnectionManager.class);
when(connectionSession.getDatabaseConnectionManager()).thenReturn(databaseConnectionManager);
+ when(connectionSession.getProtocolType()).thenReturn(databaseType);
when(databaseConnectionManager.getConnectionSession()).thenReturn(connectionSession);
ContextManager contextManager = mockContextManager();
when(ProxyContext.getInstance().getContextManager()).thenReturn(contextManager);