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 <zhangli...@apache.org>
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);

Reply via email to