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 94a4f13190e Implement Firebird XA transaction support (#34360)
94a4f13190e is described below

commit 94a4f13190e0c0352e4d385588f1cb71a9b10563
Author: Maxim Sentyabrskiy <[email protected]>
AuthorDate: Tue Jan 21 13:59:16 2025 +0300

    Implement Firebird XA transaction support (#34360)
    
    * Implement Firebird XA transaction support: Added 
FirebirdXADataSourceDefinition and FirebirdXAConnectionWrapper
    
    * Refactor
    
    * fix checkstyle
    
    * fix spotless-check
    
    * refactor
    
    * refactor
---
 kernel/transaction/type/xa/core/pom.xml            |  4 ++
 .../dialect/FirebirdXAConnectionWrapper.java       | 75 ++++++++++++++++++++++
 .../dialect/FirebirdXADataSourceDefinition.java    | 39 +++++++++++
 ...ansaction.xa.jta.connection.XAConnectionWrapper |  1 +
 ...ta.datasource.properties.XADataSourceDefinition |  1 +
 .../transaction/xa/fixture/DataSourceUtils.java    |  2 +
 .../dialect/FirebirdXAConnectionWrapperTest.java   | 64 ++++++++++++++++++
 .../FirebirdXADataSourceDefinitionTest.java        | 33 ++++++++++
 8 files changed, 219 insertions(+)

diff --git a/kernel/transaction/type/xa/core/pom.xml 
b/kernel/transaction/type/xa/core/pom.xml
index 391c5bc2142..d43f7fd4dfc 100644
--- a/kernel/transaction/type/xa/core/pom.xml
+++ b/kernel/transaction/type/xa/core/pom.xml
@@ -79,6 +79,10 @@
             <groupId>com.h2database</groupId>
             <artifactId>h2</artifactId>
         </dependency>
+        <dependency>
+            <groupId>org.firebirdsql.jdbc</groupId>
+            <artifactId>jaybird</artifactId>
+        </dependency>
         
         <dependency>
             <groupId>com.zaxxer</groupId>
diff --git 
a/kernel/transaction/type/xa/core/src/main/java/org/apache/shardingsphere/transaction/xa/jta/connection/dialect/FirebirdXAConnectionWrapper.java
 
b/kernel/transaction/type/xa/core/src/main/java/org/apache/shardingsphere/transaction/xa/jta/connection/dialect/FirebirdXAConnectionWrapper.java
new file mode 100644
index 00000000000..2a2bd941b5b
--- /dev/null
+++ 
b/kernel/transaction/type/xa/core/src/main/java/org/apache/shardingsphere/transaction/xa/jta/connection/dialect/FirebirdXAConnectionWrapper.java
@@ -0,0 +1,75 @@
+/*
+ * 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.transaction.xa.jta.connection.dialect;
+
+import lombok.SneakyThrows;
+import 
org.apache.shardingsphere.transaction.xa.jta.connection.XAConnectionWrapper;
+
+import javax.sql.XAConnection;
+import javax.sql.XADataSource;
+import java.lang.reflect.Constructor;
+import java.sql.Connection;
+import java.sql.SQLException;
+import java.util.Properties;
+
+/**
+ * XA connection wrapper for Firebird.
+ */
+public final class FirebirdXAConnectionWrapper implements XAConnectionWrapper {
+    
+    private Class<Connection> jdbcConnectionClass;
+    
+    private Constructor<?> xaConnectionConstructor;
+    
+    @Override
+    public XAConnection wrap(final XADataSource xaDataSource, final Connection 
connection) throws SQLException {
+        return createXAConnection(connection.unwrap(jdbcConnectionClass));
+    }
+    
+    @Override
+    public void init(final Properties props) {
+        loadReflection();
+    }
+    
+    private void loadReflection() {
+        jdbcConnectionClass = getJDBCConnectionClass();
+        xaConnectionConstructor = getXAConnectionConstructor();
+    }
+    
+    @SuppressWarnings("unchecked")
+    @SneakyThrows(ReflectiveOperationException.class)
+    private Class<Connection> getJDBCConnectionClass() {
+        return (Class<Connection>) 
Class.forName("org.firebirdsql.jdbc.FBConnection");
+    }
+    
+    @SneakyThrows(ReflectiveOperationException.class)
+    private Constructor<?> getXAConnectionConstructor() {
+        return 
Class.forName("org.firebirdsql.ds.FBXAConnection").getDeclaredConstructor(Class.forName("org.firebirdsql.jdbc.FBConnection"));
+    }
+    
+    @SneakyThrows(ReflectiveOperationException.class)
+    private XAConnection createXAConnection(final Connection connection) {
+        xaConnectionConstructor.setAccessible(true);
+        return (XAConnection) xaConnectionConstructor.newInstance(connection);
+    }
+    
+    @Override
+    public String getDatabaseType() {
+        return "Firebird";
+    }
+}
diff --git 
a/kernel/transaction/type/xa/core/src/main/java/org/apache/shardingsphere/transaction/xa/jta/datasource/properties/dialect/FirebirdXADataSourceDefinition.java
 
b/kernel/transaction/type/xa/core/src/main/java/org/apache/shardingsphere/transaction/xa/jta/datasource/properties/dialect/FirebirdXADataSourceDefinition.java
new file mode 100644
index 00000000000..c6e2f81d851
--- /dev/null
+++ 
b/kernel/transaction/type/xa/core/src/main/java/org/apache/shardingsphere/transaction/xa/jta/datasource/properties/dialect/FirebirdXADataSourceDefinition.java
@@ -0,0 +1,39 @@
+/*
+ * 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.transaction.xa.jta.datasource.properties.dialect;
+
+import 
org.apache.shardingsphere.transaction.xa.jta.datasource.properties.XADataSourceDefinition;
+
+import java.util.Collection;
+import java.util.Collections;
+
+/**
+ * XA data source definition for Firebird.
+ */
+public final class FirebirdXADataSourceDefinition implements 
XADataSourceDefinition {
+    
+    @Override
+    public Collection<String> getXADriverClassNames() {
+        return Collections.singletonList("org.firebirdsql.ds.FBXADataSource");
+    }
+    
+    @Override
+    public String getDatabaseType() {
+        return "Firebird";
+    }
+}
diff --git 
a/kernel/transaction/type/xa/core/src/main/resources/META-INF/services/org.apache.shardingsphere.transaction.xa.jta.connection.XAConnectionWrapper
 
b/kernel/transaction/type/xa/core/src/main/resources/META-INF/services/org.apache.shardingsphere.transaction.xa.jta.connection.XAConnectionWrapper
index 5c609dfbdd7..52085f06e7d 100644
--- 
a/kernel/transaction/type/xa/core/src/main/resources/META-INF/services/org.apache.shardingsphere.transaction.xa.jta.connection.XAConnectionWrapper
+++ 
b/kernel/transaction/type/xa/core/src/main/resources/META-INF/services/org.apache.shardingsphere.transaction.xa.jta.connection.XAConnectionWrapper
@@ -21,3 +21,4 @@ 
org.apache.shardingsphere.transaction.xa.jta.connection.dialect.OpenGaussXAConne
 
org.apache.shardingsphere.transaction.xa.jta.connection.dialect.MySQLXAConnectionWrapper
 
org.apache.shardingsphere.transaction.xa.jta.connection.dialect.MariaDBXAConnectionWrapper
 
org.apache.shardingsphere.transaction.xa.jta.connection.dialect.H2XAConnectionWrapper
+org.apache.shardingsphere.transaction.xa.jta.connection.dialect.FirebirdXAConnectionWrapper
diff --git 
a/kernel/transaction/type/xa/core/src/main/resources/META-INF/services/org.apache.shardingsphere.transaction.xa.jta.datasource.properties.XADataSourceDefinition
 
b/kernel/transaction/type/xa/core/src/main/resources/META-INF/services/org.apache.shardingsphere.transaction.xa.jta.datasource.properties.XADataSourceDefinition
index 6e707a86168..1246fcc76f5 100644
--- 
a/kernel/transaction/type/xa/core/src/main/resources/META-INF/services/org.apache.shardingsphere.transaction.xa.jta.datasource.properties.XADataSourceDefinition
+++ 
b/kernel/transaction/type/xa/core/src/main/resources/META-INF/services/org.apache.shardingsphere.transaction.xa.jta.datasource.properties.XADataSourceDefinition
@@ -22,3 +22,4 @@ 
org.apache.shardingsphere.transaction.xa.jta.datasource.properties.dialect.OpenG
 
org.apache.shardingsphere.transaction.xa.jta.datasource.properties.dialect.OracleXADataSourceDefinition
 
org.apache.shardingsphere.transaction.xa.jta.datasource.properties.dialect.SQLServerXADataSourceDefinition
 
org.apache.shardingsphere.transaction.xa.jta.datasource.properties.dialect.H2XADataSourceDefinition
+org.apache.shardingsphere.transaction.xa.jta.datasource.properties.dialect.FirebirdXADataSourceDefinition
diff --git 
a/kernel/transaction/type/xa/core/src/test/java/org/apache/shardingsphere/transaction/xa/fixture/DataSourceUtils.java
 
b/kernel/transaction/type/xa/core/src/test/java/org/apache/shardingsphere/transaction/xa/fixture/DataSourceUtils.java
index ae60d42255c..7c1ae8ee9d3 100644
--- 
a/kernel/transaction/type/xa/core/src/test/java/org/apache/shardingsphere/transaction/xa/fixture/DataSourceUtils.java
+++ 
b/kernel/transaction/type/xa/core/src/test/java/org/apache/shardingsphere/transaction/xa/fixture/DataSourceUtils.java
@@ -89,6 +89,8 @@ public final class DataSourceUtils {
                 return 
String.format("jdbc:sqlserver://localhost:1433;DatabaseName=%s", databaseName);
             case "H2":
                 return 
String.format("jdbc:h2:mem:%s;DB_CLOSE_DELAY=-1;DATABASE_TO_UPPER=false;MODE=MYSQL",
 databaseName);
+            case "Firebird":
+                return String.format("jdbc:firebirdsql://localhost:3050/%s", 
databaseName);
             default:
                 throw new 
UnsupportedSQLOperationException(databaseType.getType());
         }
diff --git 
a/kernel/transaction/type/xa/core/src/test/java/org/apache/shardingsphere/transaction/xa/jta/connection/dialect/FirebirdXAConnectionWrapperTest.java
 
b/kernel/transaction/type/xa/core/src/test/java/org/apache/shardingsphere/transaction/xa/jta/connection/dialect/FirebirdXAConnectionWrapperTest.java
new file mode 100644
index 00000000000..d0df6086bb0
--- /dev/null
+++ 
b/kernel/transaction/type/xa/core/src/test/java/org/apache/shardingsphere/transaction/xa/jta/connection/dialect/FirebirdXAConnectionWrapperTest.java
@@ -0,0 +1,64 @@
+/*
+ * 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.transaction.xa.jta.connection.dialect;
+
+import com.zaxxer.hikari.HikariDataSource;
+import 
org.apache.shardingsphere.infra.database.core.spi.DatabaseTypedSPILoader;
+import org.apache.shardingsphere.infra.database.core.type.DatabaseType;
+import org.apache.shardingsphere.infra.spi.type.typed.TypedSPILoader;
+import org.apache.shardingsphere.transaction.xa.fixture.DataSourceUtils;
+import 
org.apache.shardingsphere.transaction.xa.jta.connection.XAConnectionWrapper;
+import 
org.apache.shardingsphere.transaction.xa.jta.datasource.properties.XADataSourceDefinition;
+import 
org.apache.shardingsphere.transaction.xa.jta.datasource.swapper.DataSourceSwapper;
+import org.firebirdsql.ds.FBXAConnection;
+import org.firebirdsql.jdbc.FBConnection;
+import org.junit.jupiter.api.Test;
+
+import javax.sql.DataSource;
+import javax.sql.XAConnection;
+import javax.sql.XADataSource;
+import java.sql.Connection;
+import java.sql.SQLException;
+
+import static org.hamcrest.CoreMatchers.instanceOf;
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+class FirebirdXAConnectionWrapperTest {
+    
+    private final DatabaseType databaseType = 
TypedSPILoader.getService(DatabaseType.class, "Firebird");
+    
+    @Test
+    void assertWrap() throws SQLException {
+        XAConnection actual = 
DatabaseTypedSPILoader.getService(XAConnectionWrapper.class, 
databaseType).wrap(createXADataSource(), mockConnection());
+        assertThat(actual, instanceOf(FBXAConnection.class));
+        // TODO Fix the error with getting XAResource 
assertThat(actual.getXAResource(), instanceOf(FBXAConnection.class));
+    }
+    
+    private XADataSource createXADataSource() {
+        DataSource dataSource = DataSourceUtils.build(HikariDataSource.class, 
databaseType, "foo_ds");
+        return new 
DataSourceSwapper(DatabaseTypedSPILoader.getService(XADataSourceDefinition.class,
 databaseType)).swap(dataSource);
+    }
+    
+    private Connection mockConnection() throws SQLException {
+        Connection result = mock(Connection.class);
+        
when(result.unwrap(FBConnection.class)).thenReturn(mock(FBConnection.class));
+        return result;
+    }
+}
diff --git 
a/kernel/transaction/type/xa/core/src/test/java/org/apache/shardingsphere/transaction/xa/jta/datasource/properties/dialect/FirebirdXADataSourceDefinitionTest.java
 
b/kernel/transaction/type/xa/core/src/test/java/org/apache/shardingsphere/transaction/xa/jta/datasource/properties/dialect/FirebirdXADataSourceDefinitionTest.java
new file mode 100644
index 00000000000..af55525c8b6
--- /dev/null
+++ 
b/kernel/transaction/type/xa/core/src/test/java/org/apache/shardingsphere/transaction/xa/jta/datasource/properties/dialect/FirebirdXADataSourceDefinitionTest.java
@@ -0,0 +1,33 @@
+/*
+ * 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.transaction.xa.jta.datasource.properties.dialect;
+
+import org.junit.jupiter.api.Test;
+
+import java.util.Collections;
+
+import static org.hamcrest.CoreMatchers.is;
+import static org.hamcrest.MatcherAssert.assertThat;
+
+class FirebirdXADataSourceDefinitionTest {
+    
+    @Test
+    void assertGetXADriverClassName() {
+        assertThat(new 
FirebirdXADataSourceDefinition().getXADriverClassNames(), 
is(Collections.singletonList("org.firebirdsql.ds.FBXADataSource")));
+    }
+}

Reply via email to