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 f8a77fc  add savepoint support for sharding-jdbc (#16434)
f8a77fc is described below

commit f8a77fcd0b7ea4203f045ec617f10c6a81293fe9
Author: JingShang Lu <[email protected]>
AuthorDate: Wed Mar 30 20:53:28 2022 +0800

    add savepoint support for sharding-jdbc (#16434)
    
    * add savepoint support for sharding-jdbc
---
 .../driver/jdbc/core/ShardingSphereSavepoint.java  | 67 ++++++++++++++++++++++
 .../jdbc/core/connection/ConnectionManager.java    | 67 ++++++++++++++++++++++
 .../core/connection/ShardingSphereConnection.java  | 31 ++++++++++
 .../AbstractUnsupportedOperationConnection.java    | 21 -------
 .../connection/CircuitBreakerConnection.java       | 23 ++++++++
 .../UnsupportedOperationConnectionTest.java        | 20 -------
 6 files changed, 188 insertions(+), 41 deletions(-)

diff --git 
a/shardingsphere-jdbc/shardingsphere-jdbc-core/src/main/java/org/apache/shardingsphere/driver/jdbc/core/ShardingSphereSavepoint.java
 
b/shardingsphere-jdbc/shardingsphere-jdbc-core/src/main/java/org/apache/shardingsphere/driver/jdbc/core/ShardingSphereSavepoint.java
new file mode 100644
index 0000000..ce88854
--- /dev/null
+++ 
b/shardingsphere-jdbc/shardingsphere-jdbc-core/src/main/java/org/apache/shardingsphere/driver/jdbc/core/ShardingSphereSavepoint.java
@@ -0,0 +1,67 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.shardingsphere.driver.jdbc.core;
+
+import java.rmi.server.UID;
+import java.sql.SQLException;
+import java.sql.Savepoint;
+
+/**
+ * ShardingSphere savepoint.
+ */
+public final class ShardingSphereSavepoint implements Savepoint {
+    
+    private final String savepointName;
+    
+    public ShardingSphereSavepoint() {
+        savepointName = getUniqueId();
+    }
+    
+    public ShardingSphereSavepoint(final String name) throws SQLException {
+        if (null == name || 0 == name.length()) {
+            throw new SQLException("Savepoint name can not be NULL or empty");
+        }
+        savepointName = name;
+    }
+    
+    @Override
+    public int getSavepointId() throws SQLException {
+        throw new SQLException("Only named savepoint are supported.");
+    }
+    
+    @Override
+    public String getSavepointName() {
+        return savepointName;
+    }
+    
+    private static String getUniqueId() {
+        String uidStr = new UID().toString();
+        int uidLength = uidStr.length();
+        StringBuilder safeString = new StringBuilder(uidLength + 1);
+        safeString.append('_');
+        for (int i = 0; i < uidLength; i++) {
+            char c = uidStr.charAt(i);
+            if (Character.isLetter(c) || Character.isDigit(c)) {
+                safeString.append(c);
+            } else {
+                safeString.append('_');
+            }
+        }
+        return safeString.toString();
+    }
+}
diff --git 
a/shardingsphere-jdbc/shardingsphere-jdbc-core/src/main/java/org/apache/shardingsphere/driver/jdbc/core/connection/ConnectionManager.java
 
b/shardingsphere-jdbc/shardingsphere-jdbc-core/src/main/java/org/apache/shardingsphere/driver/jdbc/core/connection/ConnectionManager.java
index ac4701a..c9474ac 100644
--- 
a/shardingsphere-jdbc/shardingsphere-jdbc-core/src/main/java/org/apache/shardingsphere/driver/jdbc/core/connection/ConnectionManager.java
+++ 
b/shardingsphere-jdbc/shardingsphere-jdbc-core/src/main/java/org/apache/shardingsphere/driver/jdbc/core/connection/ConnectionManager.java
@@ -24,6 +24,7 @@ import com.google.common.collect.Sets;
 import lombok.Getter;
 import 
org.apache.shardingsphere.driver.jdbc.adapter.executor.ForceExecuteTemplate;
 import 
org.apache.shardingsphere.driver.jdbc.adapter.invocation.MethodInvocationRecorder;
+import org.apache.shardingsphere.driver.jdbc.core.ShardingSphereSavepoint;
 import 
org.apache.shardingsphere.infra.datasource.pool.creator.DataSourcePoolCreator;
 import org.apache.shardingsphere.infra.datasource.props.DataSourceProperties;
 import 
org.apache.shardingsphere.infra.executor.sql.execute.engine.ConnectionMode;
@@ -34,6 +35,7 @@ import 
org.apache.shardingsphere.infra.metadata.user.ShardingSphereUser;
 import org.apache.shardingsphere.mode.manager.ContextManager;
 import org.apache.shardingsphere.mode.metadata.persist.MetaDataPersistService;
 import org.apache.shardingsphere.traffic.rule.TrafficRule;
+import org.apache.shardingsphere.transaction.ConnectionSavepointManager;
 import org.apache.shardingsphere.transaction.ConnectionTransaction;
 import org.apache.shardingsphere.transaction.core.TransactionType;
 import org.apache.shardingsphere.transaction.core.TransactionTypeHolder;
@@ -43,6 +45,7 @@ import javax.sql.DataSource;
 import java.security.SecureRandom;
 import java.sql.Connection;
 import java.sql.SQLException;
+import java.sql.Savepoint;
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.Collections;
@@ -169,6 +172,70 @@ public final class ConnectionManager implements 
ExecutorJDBCConnectionManager, A
     }
     
     /**
+     * Rollback to savepoint.
+     *
+     * @param savepoint savepoint
+     * @throws SQLException SQL exception
+     */
+    public void rollback(final Savepoint savepoint) throws SQLException {
+        for (Connection each : cachedConnections.values()) {
+            ConnectionSavepointManager.getInstance().rollbackToSavepoint(each, 
savepoint.getSavepointName());
+        }
+    }
+    
+    /**
+     * Set savepoint.
+     *
+     * @param savepointName savepoint name
+     * @return savepoint savepoint
+     * @throws SQLException SQL exception
+     */
+    public Savepoint setSavepoint(final String savepointName) throws 
SQLException {
+        if (!connectionTransaction.isInTransaction()) {
+            throw new SQLException("Savepoint can only be used in transaction 
blocks.");
+        }
+        ShardingSphereSavepoint result = new 
ShardingSphereSavepoint(savepointName);
+        for (Connection each : cachedConnections.values()) {
+            ConnectionSavepointManager.getInstance().setSavepoint(each, 
savepointName);
+        }
+        methodInvocationRecorder.record("setSavepoint", target -> 
ConnectionSavepointManager.getInstance().setSavepoint(target, savepointName));
+        return result;
+    }
+    
+    /**
+     * Set savepoint.
+     *
+     * @return savepoint savepoint
+     * @throws SQLException SQL exception
+     */
+    public Savepoint setSavepoint() throws SQLException {
+        if (!connectionTransaction.isInTransaction()) {
+            throw new SQLException("Savepoint can only be used in transaction 
blocks.");
+        }
+        ShardingSphereSavepoint result = new ShardingSphereSavepoint();
+        for (Connection each : cachedConnections.values()) {
+            ConnectionSavepointManager.getInstance().setSavepoint(each, 
result.getSavepointName());
+        }
+        methodInvocationRecorder.record("setSavepoint", target -> 
ConnectionSavepointManager.getInstance().setSavepoint(target, 
result.getSavepointName()));
+        return result;
+    }
+    
+    /**
+     * Release savepoint.
+     *
+     * @param savepoint savepoint
+     * @throws SQLException SQL exception
+     */
+    public void releaseSavepoint(final Savepoint savepoint) throws 
SQLException {
+        if (!connectionTransaction.isInTransaction()) {
+            return;
+        }
+        for (Connection each : cachedConnections.values()) {
+            ConnectionSavepointManager.getInstance().releaseSavepoint(each, 
savepoint.getSavepointName());
+        }
+    }
+    
+    /**
      * Get transaction isolation.
      * 
      * @return transaction isolation level
diff --git 
a/shardingsphere-jdbc/shardingsphere-jdbc-core/src/main/java/org/apache/shardingsphere/driver/jdbc/core/connection/ShardingSphereConnection.java
 
b/shardingsphere-jdbc/shardingsphere-jdbc-core/src/main/java/org/apache/shardingsphere/driver/jdbc/core/connection/ShardingSphereConnection.java
index 838c1b4..b12f67c 100644
--- 
a/shardingsphere-jdbc/shardingsphere-jdbc-core/src/main/java/org/apache/shardingsphere/driver/jdbc/core/connection/ShardingSphereConnection.java
+++ 
b/shardingsphere-jdbc/shardingsphere-jdbc-core/src/main/java/org/apache/shardingsphere/driver/jdbc/core/connection/ShardingSphereConnection.java
@@ -30,6 +30,7 @@ import java.sql.Array;
 import java.sql.DatabaseMetaData;
 import java.sql.PreparedStatement;
 import java.sql.SQLException;
+import java.sql.Savepoint;
 import java.sql.Statement;
 
 /**
@@ -178,6 +179,36 @@ public final class ShardingSphereConnection extends 
AbstractConnectionAdapter {
         }
     }
     
+    @Override
+    public void rollback(final Savepoint savepoint) throws SQLException {
+        checkClose();
+        connectionManager.rollback(savepoint);
+    }
+    
+    @Override
+    public Savepoint setSavepoint(final String name) throws SQLException {
+        checkClose();
+        return connectionManager.setSavepoint(name);
+    }
+    
+    @Override
+    public Savepoint setSavepoint() throws SQLException {
+        checkClose();
+        return connectionManager.setSavepoint();
+    }
+    
+    @Override
+    public void releaseSavepoint(final Savepoint savepoint) throws 
SQLException {
+        checkClose();
+        connectionManager.releaseSavepoint(savepoint);
+    }
+    
+    private void checkClose() throws SQLException {
+        if (isClosed()) {
+            throw new SQLException("This connection has been closed");
+        }
+    }
+    
     @SuppressWarnings("MagicConstant")
     @Override
     public int getTransactionIsolation() throws SQLException {
diff --git 
a/shardingsphere-jdbc/shardingsphere-jdbc-core/src/main/java/org/apache/shardingsphere/driver/jdbc/unsupported/AbstractUnsupportedOperationConnection.java
 
b/shardingsphere-jdbc/shardingsphere-jdbc-core/src/main/java/org/apache/shardingsphere/driver/jdbc/unsupported/AbstractUnsupportedOperationConnection.java
index 575370f..3fda4fc 100644
--- 
a/shardingsphere-jdbc/shardingsphere-jdbc-core/src/main/java/org/apache/shardingsphere/driver/jdbc/unsupported/AbstractUnsupportedOperationConnection.java
+++ 
b/shardingsphere-jdbc/shardingsphere-jdbc-core/src/main/java/org/apache/shardingsphere/driver/jdbc/unsupported/AbstractUnsupportedOperationConnection.java
@@ -27,7 +27,6 @@ import java.sql.NClob;
 import java.sql.SQLException;
 import java.sql.SQLFeatureNotSupportedException;
 import java.sql.SQLXML;
-import java.sql.Savepoint;
 import java.sql.Struct;
 import java.util.Map;
 import java.util.Properties;
@@ -59,26 +58,6 @@ public abstract class AbstractUnsupportedOperationConnection 
extends WrapperAdap
     }
     
     @Override
-    public final Savepoint setSavepoint() throws SQLException {
-        throw new SQLFeatureNotSupportedException("setSavepoint");
-    }
-    
-    @Override
-    public final Savepoint setSavepoint(final String name) throws SQLException 
{
-        throw new SQLFeatureNotSupportedException("setSavepoint name");
-    }
-    
-    @Override
-    public final void releaseSavepoint(final Savepoint savepoint) throws 
SQLException {
-        throw new SQLFeatureNotSupportedException("releaseSavepoint");
-    }
-    
-    @Override
-    public final void rollback(final Savepoint savepoint) throws SQLException {
-        throw new SQLFeatureNotSupportedException("rollback savepoint");
-    }
-    
-    @Override
     public final void abort(final Executor executor) throws SQLException {
         throw new SQLFeatureNotSupportedException("abort");
     }
diff --git 
a/shardingsphere-jdbc/shardingsphere-jdbc-core/src/main/java/org/apache/shardingsphere/driver/state/circuit/connection/CircuitBreakerConnection.java
 
b/shardingsphere-jdbc/shardingsphere-jdbc-core/src/main/java/org/apache/shardingsphere/driver/state/circuit/connection/CircuitBreakerConnection.java
index a79dd81..dce8fae 100644
--- 
a/shardingsphere-jdbc/shardingsphere-jdbc-core/src/main/java/org/apache/shardingsphere/driver/state/circuit/connection/CircuitBreakerConnection.java
+++ 
b/shardingsphere-jdbc/shardingsphere-jdbc-core/src/main/java/org/apache/shardingsphere/driver/state/circuit/connection/CircuitBreakerConnection.java
@@ -26,7 +26,10 @@ import 
org.apache.shardingsphere.driver.jdbc.unsupported.AbstractUnsupportedOper
 import java.sql.Connection;
 import java.sql.DatabaseMetaData;
 import java.sql.PreparedStatement;
+import java.sql.SQLException;
+import java.sql.SQLFeatureNotSupportedException;
 import java.sql.SQLWarning;
+import java.sql.Savepoint;
 import java.sql.Statement;
 
 /**
@@ -93,6 +96,26 @@ public final class CircuitBreakerConnection extends 
AbstractUnsupportedOperation
     }
     
     @Override
+    public void rollback(final Savepoint savepoint) throws SQLException {
+        throw new SQLFeatureNotSupportedException("rollback savepoint");
+    }
+    
+    @Override
+    public Savepoint setSavepoint() throws SQLException {
+        throw new SQLFeatureNotSupportedException("setSavepoint");
+    }
+
+    @Override
+    public Savepoint setSavepoint(final String name) throws SQLException {
+        throw new SQLFeatureNotSupportedException("setSavepoint name");
+    }
+
+    @Override
+    public void releaseSavepoint(final Savepoint savepoint) throws 
SQLException {
+        throw new SQLFeatureNotSupportedException("releaseSavepoint");
+    }
+    
+    @Override
     public void setHoldability(final int holdability) {
     }
     
diff --git 
a/shardingsphere-jdbc/shardingsphere-jdbc-core/src/test/java/org/apache/shardingsphere/driver/jdbc/unsupported/UnsupportedOperationConnectionTest.java
 
b/shardingsphere-jdbc/shardingsphere-jdbc-core/src/test/java/org/apache/shardingsphere/driver/jdbc/unsupported/UnsupportedOperationConnectionTest.java
index 96fad7d..ba17978 100644
--- 
a/shardingsphere-jdbc/shardingsphere-jdbc-core/src/test/java/org/apache/shardingsphere/driver/jdbc/unsupported/UnsupportedOperationConnectionTest.java
+++ 
b/shardingsphere-jdbc/shardingsphere-jdbc-core/src/test/java/org/apache/shardingsphere/driver/jdbc/unsupported/UnsupportedOperationConnectionTest.java
@@ -63,26 +63,6 @@ public final class UnsupportedOperationConnectionTest {
     }
     
     @Test(expected = SQLFeatureNotSupportedException.class)
-    public void assertSetSavepoint() throws SQLException {
-        shardingSphereConnection.setSavepoint();
-    }
-    
-    @Test(expected = SQLFeatureNotSupportedException.class)
-    public void assertSetSavepointWithName() throws SQLException {
-        shardingSphereConnection.setSavepoint("");
-    }
-    
-    @Test(expected = SQLFeatureNotSupportedException.class)
-    public void assertReleaseSavepoint() throws SQLException {
-        shardingSphereConnection.releaseSavepoint(null);
-    }
-    
-    @Test(expected = SQLFeatureNotSupportedException.class)
-    public void assertRollback() throws SQLException {
-        shardingSphereConnection.rollback(null);
-    }
-    
-    @Test(expected = SQLFeatureNotSupportedException.class)
     public void assertAbort() throws SQLException {
         shardingSphereConnection.abort(null);
     }

Reply via email to