This is an automated email from the ASF dual-hosted git repository. lujingshang 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 820dd5cc4a4 Support executing truncate in XA and postgreSQL (#19746) 820dd5cc4a4 is described below commit 820dd5cc4a493d2545650ed9df68f9257ada884b Author: ZhangCheng <flyin...@outlook.com> AuthorDate: Thu Aug 4 17:57:19 2022 +0800 Support executing truncate in XA and postgreSQL (#19746) * Support executing truncate in XA and postgreSQL * Add truncate it tests * Add truncate it tests * Add truncate it tests * Add truncate it tests * Simplified verification --- .../backend/communication/ProxySQLExecutor.java | 24 +++++-- .../communication/ReactiveProxySQLExecutor.java | 17 ++++- .../communication/ProxySQLExecutorTest.java | 39 +++++++++++ .../cases/truncate/MySQLLocalTruncateTestCase.java | 81 ++++++++++++++++++++++ .../cases/truncate/MySQLXATruncateTestCase.java | 77 ++++++++++++++++++++ .../PostgresSQLAndOpenGaussTruncateTestCase.java | 80 +++++++++++++++++++++ .../src/test/resources/env/common/command.xml | 2 +- .../env/jdbc/mysql/config-sharding-local.yaml | 2 +- .../jdbc/mysql/config-sharding-xa-atomikos.yaml | 2 +- .../env/jdbc/opengauss/config-sharding-local.yaml | 2 +- .../opengauss/config-sharding-xa-atomikos.yaml | 2 +- .../env/jdbc/postgresql/config-sharding-local.yaml | 2 +- .../postgresql/config-sharding-xa-atomikos.yaml | 2 +- .../resources/env/transaction-it-env.properties | 2 +- 14 files changed, 320 insertions(+), 14 deletions(-) diff --git a/shardingsphere-proxy/shardingsphere-proxy-backend/src/main/java/org/apache/shardingsphere/proxy/backend/communication/ProxySQLExecutor.java b/shardingsphere-proxy/shardingsphere-proxy-backend/src/main/java/org/apache/shardingsphere/proxy/backend/communication/ProxySQLExecutor.java index 08f59af24bb..7a2acea1035 100644 --- a/shardingsphere-proxy/shardingsphere-proxy-backend/src/main/java/org/apache/shardingsphere/proxy/backend/communication/ProxySQLExecutor.java +++ b/shardingsphere-proxy/shardingsphere-proxy-backend/src/main/java/org/apache/shardingsphere/proxy/backend/communication/ProxySQLExecutor.java @@ -49,6 +49,7 @@ import org.apache.shardingsphere.sql.parser.sql.common.statement.ddl.CloseStatem import org.apache.shardingsphere.sql.parser.sql.common.statement.ddl.DDLStatement; import org.apache.shardingsphere.sql.parser.sql.common.statement.ddl.FetchStatement; import org.apache.shardingsphere.sql.parser.sql.common.statement.ddl.MoveStatement; +import org.apache.shardingsphere.sql.parser.sql.common.statement.ddl.TruncateStatement; import org.apache.shardingsphere.sql.parser.sql.dialect.statement.mysql.dml.MySQLInsertStatement; import org.apache.shardingsphere.sql.parser.sql.dialect.statement.opengauss.OpenGaussStatement; import org.apache.shardingsphere.sql.parser.sql.dialect.statement.opengauss.ddl.OpenGaussCursorStatement; @@ -100,15 +101,30 @@ public final class ProxySQLExecutor { private boolean isExecuteDDLInXATransaction(final SQLStatement sqlStatement) { TransactionStatus transactionStatus = backendConnection.getConnectionSession().getTransactionStatus(); - return TransactionType.XA == transactionStatus.getTransactionType() && sqlStatement instanceof DDLStatement && transactionStatus.isInTransaction(); + return TransactionType.XA == transactionStatus.getTransactionType() && isUnsupportedDDLStatement(sqlStatement) && transactionStatus.isInTransaction(); } private boolean isExecuteDDLInPostgreSQLOpenGaussTransaction(final SQLStatement sqlStatement) { // TODO implement DDL statement commit/rollback in PostgreSQL/openGauss transaction - boolean isPostgreSQLOpenGaussStatement = sqlStatement instanceof PostgreSQLStatement || sqlStatement instanceof OpenGaussStatement; - boolean isCursorStatement = sqlStatement instanceof OpenGaussCursorStatement + boolean isPostgreSQLOpenGaussStatement = isPostgreSQLOrOpenGaussStatement(sqlStatement); + boolean isSupportedStatement = isCursorStatement(sqlStatement) || sqlStatement instanceof TruncateStatement; + return sqlStatement instanceof DDLStatement && !isSupportedStatement && isPostgreSQLOpenGaussStatement && backendConnection.getConnectionSession().getTransactionStatus().isInTransaction(); + } + + private boolean isCursorStatement(final SQLStatement sqlStatement) { + return sqlStatement instanceof OpenGaussCursorStatement || sqlStatement instanceof CloseStatement || sqlStatement instanceof MoveStatement || sqlStatement instanceof FetchStatement; - return sqlStatement instanceof DDLStatement && !isCursorStatement && isPostgreSQLOpenGaussStatement && backendConnection.getConnectionSession().getTransactionStatus().isInTransaction(); + } + + private boolean isUnsupportedDDLStatement(final SQLStatement sqlStatement) { + if (isPostgreSQLOrOpenGaussStatement(sqlStatement) && sqlStatement instanceof TruncateStatement) { + return false; + } + return sqlStatement instanceof DDLStatement; + } + + private boolean isPostgreSQLOrOpenGaussStatement(final SQLStatement sqlStatement) { + return sqlStatement instanceof PostgreSQLStatement || sqlStatement instanceof OpenGaussStatement; } /** diff --git a/shardingsphere-proxy/shardingsphere-proxy-backend/src/main/java/org/apache/shardingsphere/proxy/backend/communication/ReactiveProxySQLExecutor.java b/shardingsphere-proxy/shardingsphere-proxy-backend/src/main/java/org/apache/shardingsphere/proxy/backend/communication/ReactiveProxySQLExecutor.java index 960acb4ff4d..99c3dca3783 100644 --- a/shardingsphere-proxy/shardingsphere-proxy-backend/src/main/java/org/apache/shardingsphere/proxy/backend/communication/ReactiveProxySQLExecutor.java +++ b/shardingsphere-proxy/shardingsphere-proxy-backend/src/main/java/org/apache/shardingsphere/proxy/backend/communication/ReactiveProxySQLExecutor.java @@ -39,6 +39,7 @@ import org.apache.shardingsphere.proxy.backend.exception.TableModifyInTransactio import org.apache.shardingsphere.proxy.backend.session.transaction.TransactionStatus; import org.apache.shardingsphere.sql.parser.sql.common.statement.SQLStatement; import org.apache.shardingsphere.sql.parser.sql.common.statement.ddl.DDLStatement; +import org.apache.shardingsphere.sql.parser.sql.common.statement.ddl.TruncateStatement; import org.apache.shardingsphere.sql.parser.sql.dialect.statement.opengauss.OpenGaussStatement; import org.apache.shardingsphere.sql.parser.sql.dialect.statement.postgresql.PostgreSQLStatement; import org.apache.shardingsphere.transaction.core.TransactionType; @@ -79,13 +80,25 @@ public final class ReactiveProxySQLExecutor { private boolean isExecuteDDLInXATransaction(final SQLStatement sqlStatement) { TransactionStatus transactionStatus = backendConnection.getConnectionSession().getTransactionStatus(); - return TransactionType.XA == transactionStatus.getTransactionType() && sqlStatement instanceof DDLStatement && transactionStatus.isInTransaction(); + return TransactionType.XA == transactionStatus.getTransactionType() && isUnsupportedDDLStatement(sqlStatement) && transactionStatus.isInTransaction(); } private boolean isExecuteDDLInPostgreSQLOpenGaussTransaction(final SQLStatement sqlStatement) { // TODO implement DDL statement commit/rollback in PostgreSQL/openGauss transaction boolean isPostgreSQLOpenGaussStatement = sqlStatement instanceof PostgreSQLStatement || sqlStatement instanceof OpenGaussStatement; - return sqlStatement instanceof DDLStatement && isPostgreSQLOpenGaussStatement && backendConnection.getConnectionSession().getTransactionStatus().isInTransaction(); + boolean isSupportedDDLStatement = sqlStatement instanceof TruncateStatement; + return sqlStatement instanceof DDLStatement && !isSupportedDDLStatement && isPostgreSQLOpenGaussStatement && backendConnection.getConnectionSession().getTransactionStatus().isInTransaction(); + } + + private boolean isUnsupportedDDLStatement(final SQLStatement sqlStatement) { + if (isPostgreSQLOrOpenGaussStatement(sqlStatement) && sqlStatement instanceof TruncateStatement) { + return false; + } + return sqlStatement instanceof DDLStatement; + } + + private boolean isPostgreSQLOrOpenGaussStatement(final SQLStatement sqlStatement) { + return sqlStatement instanceof PostgreSQLStatement || sqlStatement instanceof OpenGaussStatement; } /** diff --git a/shardingsphere-proxy/shardingsphere-proxy-backend/src/test/java/org/apache/shardingsphere/proxy/backend/communication/ProxySQLExecutorTest.java b/shardingsphere-proxy/shardingsphere-proxy-backend/src/test/java/org/apache/shardingsphere/proxy/backend/communication/ProxySQLExecutorTest.java index 35cc640ef5f..1477f12c9c5 100644 --- a/shardingsphere-proxy/shardingsphere-proxy-backend/src/test/java/org/apache/shardingsphere/proxy/backend/communication/ProxySQLExecutorTest.java +++ b/shardingsphere-proxy/shardingsphere-proxy-backend/src/test/java/org/apache/shardingsphere/proxy/backend/communication/ProxySQLExecutorTest.java @@ -18,7 +18,9 @@ package org.apache.shardingsphere.proxy.backend.communication; import org.apache.shardingsphere.infra.binder.LogicSQL; +import org.apache.shardingsphere.infra.binder.statement.SQLStatementContext; import org.apache.shardingsphere.infra.binder.statement.ddl.CreateTableStatementContext; +import org.apache.shardingsphere.infra.binder.statement.ddl.TruncateStatementContext; import org.apache.shardingsphere.infra.binder.statement.dml.InsertStatementContext; import org.apache.shardingsphere.infra.database.DefaultDatabase; import org.apache.shardingsphere.infra.executor.sql.context.ExecutionContext; @@ -41,8 +43,10 @@ import org.apache.shardingsphere.sql.parser.sql.common.segment.generic.table.Sim import org.apache.shardingsphere.sql.parser.sql.common.segment.generic.table.TableNameSegment; import org.apache.shardingsphere.sql.parser.sql.common.value.identifier.IdentifierValue; import org.apache.shardingsphere.sql.parser.sql.dialect.statement.mysql.ddl.MySQLCreateTableStatement; +import org.apache.shardingsphere.sql.parser.sql.dialect.statement.mysql.ddl.MySQLTruncateStatement; import org.apache.shardingsphere.sql.parser.sql.dialect.statement.mysql.dml.MySQLInsertStatement; import org.apache.shardingsphere.sql.parser.sql.dialect.statement.postgresql.ddl.PostgreSQLCreateTableStatement; +import org.apache.shardingsphere.sql.parser.sql.dialect.statement.postgresql.ddl.PostgreSQLTruncateStatement; import org.apache.shardingsphere.sql.parser.sql.dialect.statement.postgresql.dml.PostgreSQLInsertStatement; import org.apache.shardingsphere.transaction.core.TransactionType; import org.junit.Before; @@ -84,6 +88,21 @@ public final class ProxySQLExecutorTest extends ProxyContextRestorer { new ProxySQLExecutor(JDBCDriverType.STATEMENT, backendConnection, mock(JDBCDatabaseCommunicationEngine.class)).checkExecutePrerequisites(executionContext); } + @Test(expected = TableModifyInTransactionException.class) + public void assertCheckExecutePrerequisitesWhenExecuteTruncateInMySQLXATransaction() { + ExecutionContext executionContext = new ExecutionContext( + new LogicSQL(createMySQLTruncateStatementContext(), "", Collections.emptyList()), Collections.emptyList(), mock(RouteContext.class)); + new ProxySQLExecutor(JDBCDriverType.STATEMENT, backendConnection, mock(JDBCDatabaseCommunicationEngine.class)).checkExecutePrerequisites(executionContext); + } + + @Test + public void assertCheckExecutePrerequisitesWhenExecuteTruncateInMySQLLocalTransaction() { + when(connectionSession.getTransactionStatus().getTransactionType()).thenReturn(TransactionType.LOCAL); + ExecutionContext executionContext = new ExecutionContext( + new LogicSQL(createMySQLTruncateStatementContext(), "", Collections.emptyList()), Collections.emptyList(), mock(RouteContext.class)); + new ProxySQLExecutor(JDBCDriverType.STATEMENT, backendConnection, mock(JDBCDatabaseCommunicationEngine.class)).checkExecutePrerequisites(executionContext); + } + @Test public void assertCheckExecutePrerequisitesWhenExecuteDMLInXATransaction() { ExecutionContext executionContext = new ExecutionContext( @@ -115,6 +134,14 @@ public final class ProxySQLExecutorTest extends ProxyContextRestorer { new ProxySQLExecutor(JDBCDriverType.STATEMENT, backendConnection, mock(JDBCDatabaseCommunicationEngine.class)).checkExecutePrerequisites(executionContext); } + @Test + public void assertCheckExecutePrerequisitesWhenExecuteTruncateInPostgreSQLTransaction() { + when(connectionSession.getTransactionStatus().getTransactionType()).thenReturn(TransactionType.LOCAL); + ExecutionContext executionContext = new ExecutionContext( + new LogicSQL(createPostgreSQLTruncateStatementContext(), "", Collections.emptyList()), Collections.emptyList(), mock(RouteContext.class)); + new ProxySQLExecutor(JDBCDriverType.STATEMENT, backendConnection, mock(JDBCDatabaseCommunicationEngine.class)).checkExecutePrerequisites(executionContext); + } + @Test public void assertCheckExecutePrerequisitesWhenExecuteDMLInPostgreSQLTransaction() { when(connectionSession.getTransactionStatus().getTransactionType()).thenReturn(TransactionType.LOCAL); @@ -146,6 +173,18 @@ public final class ProxySQLExecutorTest extends ProxyContextRestorer { return new CreateTableStatementContext(sqlStatement); } + private TruncateStatementContext createMySQLTruncateStatementContext() { + MySQLTruncateStatement sqlStatement = new MySQLTruncateStatement(); + sqlStatement.getTables().add(new SimpleTableSegment(new TableNameSegment(0, 0, new IdentifierValue("t_order")))); + return new TruncateStatementContext(sqlStatement); + } + + private SQLStatementContext<?> createPostgreSQLTruncateStatementContext() { + PostgreSQLTruncateStatement sqlStatement = new PostgreSQLTruncateStatement(); + sqlStatement.getTables().add(new SimpleTableSegment(new TableNameSegment(0, 0, new IdentifierValue("t_order")))); + return new TruncateStatementContext(sqlStatement); + } + private InsertStatementContext createMySQLInsertStatementContext() { MySQLInsertStatement sqlStatement = new MySQLInsertStatement(); sqlStatement.setTable(new SimpleTableSegment(new TableNameSegment(0, 0, new IdentifierValue("t_order")))); diff --git a/shardingsphere-test/shardingsphere-integration-test/shardingsphere-integration-test-transaction/src/test/java/org/apache/shardingsphere/integration/transaction/cases/truncate/MySQLLocalTruncateTestCase.java b/shardingsphere-test/shardingsphere-integration-test/shardingsphere-integration-test-transaction/src/test/java/org/apache/shardingsphere/integration/transaction/cases/truncate/MySQLLocalTruncateTestCase.java new file mode 100644 index 00000000000..7e6936c2a06 --- /dev/null +++ b/shardingsphere-test/shardingsphere-integration-test/shardingsphere-integration-test-transaction/src/test/java/org/apache/shardingsphere/integration/transaction/cases/truncate/MySQLLocalTruncateTestCase.java @@ -0,0 +1,81 @@ +/* + * 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.integration.transaction.cases.truncate; + +import lombok.SneakyThrows; +import lombok.extern.slf4j.Slf4j; +import org.apache.shardingsphere.integration.transaction.cases.base.BaseTransactionTestCase; +import org.apache.shardingsphere.integration.transaction.engine.base.BaseTransactionITCase; +import org.apache.shardingsphere.integration.transaction.engine.base.TransactionTestCase; +import org.apache.shardingsphere.integration.transaction.engine.constants.TransactionTestConstants; +import org.apache.shardingsphere.transaction.core.TransactionType; + +import javax.sql.DataSource; +import java.sql.Connection; +import java.sql.SQLException; + +/** + * MySQL truncate local transaction integration test. + */ +@Slf4j +@TransactionTestCase(dbTypes = {TransactionTestConstants.MYSQL}, transactionTypes = {TransactionType.LOCAL}) +public final class MySQLLocalTruncateTestCase extends BaseTransactionTestCase { + + public MySQLLocalTruncateTestCase(final BaseTransactionITCase baseTransactionITCase, final DataSource dataSource) { + super(baseTransactionITCase, dataSource); + } + + @Override + @SneakyThrows(SQLException.class) + public void executeTest() { + assertTruncateRollback(); + assertTruncateCommit(); + } + + private void assertTruncateRollback() throws SQLException { + prepare(); + Connection conn = getDataSource().getConnection(); + conn.setAutoCommit(false); + assertAccountRowCount(conn, 8); + executeWithLog(conn, "truncate account;"); + assertAccountRowCount(conn, 0); + conn.rollback(); + // Expected truncate operation cannot be rolled back in MySQL local transaction + assertAccountRowCount(conn, 0); + conn.close(); + } + + public void assertTruncateCommit() throws SQLException { + prepare(); + Connection conn = getDataSource().getConnection(); + conn.setAutoCommit(false); + assertAccountRowCount(conn, 8); + executeWithLog(conn, "truncate account;"); + assertAccountRowCount(conn, 0); + conn.commit(); + assertAccountRowCount(conn, 0); + conn.close(); + } + + private void prepare() throws SQLException { + Connection conn = getDataSource().getConnection(); + executeWithLog(conn, "delete from account;"); + executeWithLog(conn, "insert into account(id, balance, transaction_id) values(1, 1, 1),(2, 2, 2),(3, 3, 3),(4, 4, 4),(5, 5, 5),(6, 6, 6),(7, 7, 7),(8, 8, 8);"); + conn.close(); + } +} diff --git a/shardingsphere-test/shardingsphere-integration-test/shardingsphere-integration-test-transaction/src/test/java/org/apache/shardingsphere/integration/transaction/cases/truncate/MySQLXATruncateTestCase.java b/shardingsphere-test/shardingsphere-integration-test/shardingsphere-integration-test-transaction/src/test/java/org/apache/shardingsphere/integration/transaction/cases/truncate/MySQLXATruncateTestCase.java new file mode 100644 index 00000000000..a0a00dbe218 --- /dev/null +++ b/shardingsphere-test/shardingsphere-integration-test/shardingsphere-integration-test-transaction/src/test/java/org/apache/shardingsphere/integration/transaction/cases/truncate/MySQLXATruncateTestCase.java @@ -0,0 +1,77 @@ +/* + * 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.integration.transaction.cases.truncate; + +import lombok.SneakyThrows; +import lombok.extern.slf4j.Slf4j; +import org.apache.shardingsphere.integration.transaction.cases.base.BaseTransactionTestCase; +import org.apache.shardingsphere.integration.transaction.engine.base.BaseTransactionITCase; +import org.apache.shardingsphere.integration.transaction.engine.base.TransactionTestCase; +import org.apache.shardingsphere.integration.transaction.engine.constants.TransactionTestConstants; +import org.apache.shardingsphere.proxy.backend.exception.TableModifyInTransactionException; +import org.apache.shardingsphere.transaction.core.TransactionType; + +import javax.sql.DataSource; +import java.sql.Connection; +import java.sql.SQLException; + +import static org.junit.Assert.fail; + +/** + * MySQL truncate XA transaction integration test. + */ +@Slf4j +@TransactionTestCase(dbTypes = {TransactionTestConstants.MYSQL}, adapters = {TransactionTestConstants.PROXY}, transactionTypes = {TransactionType.XA}) +public final class MySQLXATruncateTestCase extends BaseTransactionTestCase { + + public MySQLXATruncateTestCase(final BaseTransactionITCase baseTransactionITCase, final DataSource dataSource) { + super(baseTransactionITCase, dataSource); + } + + @Override + @SneakyThrows(SQLException.class) + public void executeTest() { + assertTruncateInMySQLXATransaction(); + } + + private void assertTruncateInMySQLXATransaction() throws SQLException { + // TODO This test case may cause bad effects to other test cases in JDBC adapter + prepare(); + Connection conn = getDataSource().getConnection(); + conn.setAutoCommit(false); + assertAccountRowCount(conn, 8); + try { + conn.createStatement().execute("truncate account;"); + fail("Expect exception, but no exception report."); + } catch (TableModifyInTransactionException ex) { + log.info("Exception for expected in Proxy: {}", ex.getMessage()); + } catch (SQLException ex) { + log.info("Exception for expected in JDBC: {}", ex.getMessage()); + } finally { + conn.rollback(); + conn.close(); + } + } + + private void prepare() throws SQLException { + Connection conn = getDataSource().getConnection(); + executeWithLog(conn, "delete from account;"); + executeWithLog(conn, "insert into account(id, balance, transaction_id) values(1, 1, 1),(2, 2, 2),(3, 3, 3),(4, 4, 4),(5, 5, 5),(6, 6, 6),(7, 7, 7),(8, 8, 8);"); + conn.close(); + } +} diff --git a/shardingsphere-test/shardingsphere-integration-test/shardingsphere-integration-test-transaction/src/test/java/org/apache/shardingsphere/integration/transaction/cases/truncate/PostgresSQLAndOpenGaussTruncateTestCase.java b/shardingsphere-test/shardingsphere-integration-test/shardingsphere-integration-test-transaction/src/test/java/org/apache/shardingsphere/integration/transaction/cases/truncate/PostgresSQLAndOpenGaussTruncateTestCase.java new file mode 100644 index 00000000000..b5be524b68d --- /dev/null +++ b/shardingsphere-test/shardingsphere-integration-test/shardingsphere-integration-test-transaction/src/test/java/org/apache/shardingsphere/integration/transaction/cases/truncate/PostgresSQLAndOpenGaussTruncateTestCase.java @@ -0,0 +1,80 @@ +/* + * 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.integration.transaction.cases.truncate; + +import lombok.SneakyThrows; +import lombok.extern.slf4j.Slf4j; +import org.apache.shardingsphere.integration.transaction.cases.base.BaseTransactionTestCase; +import org.apache.shardingsphere.integration.transaction.engine.base.BaseTransactionITCase; +import org.apache.shardingsphere.integration.transaction.engine.base.TransactionTestCase; +import org.apache.shardingsphere.integration.transaction.engine.constants.TransactionTestConstants; + +import javax.sql.DataSource; +import java.sql.Connection; +import java.sql.SQLException; + +/** + * PostgresSQL and OpenGauss truncate transaction integration test. + */ +@Slf4j +@TransactionTestCase(dbTypes = {TransactionTestConstants.POSTGRESQL, TransactionTestConstants.OPENGAUSS}) +public final class PostgresSQLAndOpenGaussTruncateTestCase extends BaseTransactionTestCase { + + public PostgresSQLAndOpenGaussTruncateTestCase(final BaseTransactionITCase baseTransactionITCase, final DataSource dataSource) { + super(baseTransactionITCase, dataSource); + } + + @Override + @SneakyThrows(SQLException.class) + public void executeTest() { + assertTruncateRollback(); + assertTruncateCommit(); + } + + private void assertTruncateRollback() throws SQLException { + prepare(); + Connection conn = getDataSource().getConnection(); + conn.setAutoCommit(false); + assertAccountRowCount(conn, 8); + executeWithLog(conn, "truncate account;"); + assertAccountRowCount(conn, 0); + conn.rollback(); + // Expected truncate operation can be rolled back in PostgreSQL & OpenGauss + assertAccountRowCount(conn, 8); + conn.close(); + } + + public void assertTruncateCommit() throws SQLException { + prepare(); + Connection conn = getDataSource().getConnection(); + conn.setAutoCommit(false); + assertAccountRowCount(conn, 8); + executeWithLog(conn, "truncate account;"); + assertAccountRowCount(conn, 0); + conn.commit(); + assertAccountRowCount(conn, 0); + conn.close(); + } + + private void prepare() throws SQLException { + Connection conn = getDataSource().getConnection(); + executeWithLog(conn, "delete from account;"); + executeWithLog(conn, "insert into account(id, balance, transaction_id) values(1, 1, 1),(2, 2, 2),(3, 3, 3),(4, 4, 4),(5, 5, 5),(6, 6, 6),(7, 7, 7),(8, 8, 8);"); + conn.close(); + } +} diff --git a/shardingsphere-test/shardingsphere-integration-test/shardingsphere-integration-test-transaction/src/test/resources/env/common/command.xml b/shardingsphere-test/shardingsphere-integration-test/shardingsphere-integration-test-transaction/src/test/resources/env/common/command.xml index 6d3e41c49c8..467e973ad7c 100644 --- a/shardingsphere-test/shardingsphere-integration-test/shardingsphere-integration-test-transaction/src/test/resources/env/common/command.xml +++ b/shardingsphere-test/shardingsphere-integration-test/shardingsphere-integration-test-transaction/src/test/resources/env/common/command.xml @@ -42,7 +42,7 @@ <create-account-sharding-algorithm> CREATE SHARDING ALGORITHM account_inline ( - TYPE(NAME=INLINE,PROPERTIES("algorithm-expression"="account_${id % 2}")) + TYPE(NAME=INLINE,PROPERTIES("algorithm-expression"="account_${Math.floorMod(Math.floorDiv(id.longValue(), 2L), 2L)}")) ) </create-account-sharding-algorithm> diff --git a/shardingsphere-test/shardingsphere-integration-test/shardingsphere-integration-test-transaction/src/test/resources/env/jdbc/mysql/config-sharding-local.yaml b/shardingsphere-test/shardingsphere-integration-test/shardingsphere-integration-test-transaction/src/test/resources/env/jdbc/mysql/config-sharding-local.yaml index 51c01e70f9f..733ffe4fbb7 100644 --- a/shardingsphere-test/shardingsphere-integration-test/shardingsphere-integration-test-transaction/src/test/resources/env/jdbc/mysql/config-sharding-local.yaml +++ b/shardingsphere-test/shardingsphere-integration-test/shardingsphere-integration-test-transaction/src/test/resources/env/jdbc/mysql/config-sharding-local.yaml @@ -87,7 +87,7 @@ rules: account_inline: type: INLINE props: - algorithm-expression: account_${id % 2} + algorithm-expression: account_${Math.floorMod(Math.floorDiv(id.longValue(), 2L), 2L)} keyGenerators: snowflake: diff --git a/shardingsphere-test/shardingsphere-integration-test/shardingsphere-integration-test-transaction/src/test/resources/env/jdbc/mysql/config-sharding-xa-atomikos.yaml b/shardingsphere-test/shardingsphere-integration-test/shardingsphere-integration-test-transaction/src/test/resources/env/jdbc/mysql/config-sharding-xa-atomikos.yaml index d76760f284d..949ad464755 100644 --- a/shardingsphere-test/shardingsphere-integration-test/shardingsphere-integration-test-transaction/src/test/resources/env/jdbc/mysql/config-sharding-xa-atomikos.yaml +++ b/shardingsphere-test/shardingsphere-integration-test/shardingsphere-integration-test-transaction/src/test/resources/env/jdbc/mysql/config-sharding-xa-atomikos.yaml @@ -88,7 +88,7 @@ rules: account_inline: type: INLINE props: - algorithm-expression: account_${id % 2} + algorithm-expression: account_${Math.floorMod(Math.floorDiv(id.longValue(), 2L), 2L)} keyGenerators: snowflake: diff --git a/shardingsphere-test/shardingsphere-integration-test/shardingsphere-integration-test-transaction/src/test/resources/env/jdbc/opengauss/config-sharding-local.yaml b/shardingsphere-test/shardingsphere-integration-test/shardingsphere-integration-test-transaction/src/test/resources/env/jdbc/opengauss/config-sharding-local.yaml index 51c01e70f9f..733ffe4fbb7 100644 --- a/shardingsphere-test/shardingsphere-integration-test/shardingsphere-integration-test-transaction/src/test/resources/env/jdbc/opengauss/config-sharding-local.yaml +++ b/shardingsphere-test/shardingsphere-integration-test/shardingsphere-integration-test-transaction/src/test/resources/env/jdbc/opengauss/config-sharding-local.yaml @@ -87,7 +87,7 @@ rules: account_inline: type: INLINE props: - algorithm-expression: account_${id % 2} + algorithm-expression: account_${Math.floorMod(Math.floorDiv(id.longValue(), 2L), 2L)} keyGenerators: snowflake: diff --git a/shardingsphere-test/shardingsphere-integration-test/shardingsphere-integration-test-transaction/src/test/resources/env/jdbc/opengauss/config-sharding-xa-atomikos.yaml b/shardingsphere-test/shardingsphere-integration-test/shardingsphere-integration-test-transaction/src/test/resources/env/jdbc/opengauss/config-sharding-xa-atomikos.yaml index d76760f284d..949ad464755 100644 --- a/shardingsphere-test/shardingsphere-integration-test/shardingsphere-integration-test-transaction/src/test/resources/env/jdbc/opengauss/config-sharding-xa-atomikos.yaml +++ b/shardingsphere-test/shardingsphere-integration-test/shardingsphere-integration-test-transaction/src/test/resources/env/jdbc/opengauss/config-sharding-xa-atomikos.yaml @@ -88,7 +88,7 @@ rules: account_inline: type: INLINE props: - algorithm-expression: account_${id % 2} + algorithm-expression: account_${Math.floorMod(Math.floorDiv(id.longValue(), 2L), 2L)} keyGenerators: snowflake: diff --git a/shardingsphere-test/shardingsphere-integration-test/shardingsphere-integration-test-transaction/src/test/resources/env/jdbc/postgresql/config-sharding-local.yaml b/shardingsphere-test/shardingsphere-integration-test/shardingsphere-integration-test-transaction/src/test/resources/env/jdbc/postgresql/config-sharding-local.yaml index 51c01e70f9f..733ffe4fbb7 100644 --- a/shardingsphere-test/shardingsphere-integration-test/shardingsphere-integration-test-transaction/src/test/resources/env/jdbc/postgresql/config-sharding-local.yaml +++ b/shardingsphere-test/shardingsphere-integration-test/shardingsphere-integration-test-transaction/src/test/resources/env/jdbc/postgresql/config-sharding-local.yaml @@ -87,7 +87,7 @@ rules: account_inline: type: INLINE props: - algorithm-expression: account_${id % 2} + algorithm-expression: account_${Math.floorMod(Math.floorDiv(id.longValue(), 2L), 2L)} keyGenerators: snowflake: diff --git a/shardingsphere-test/shardingsphere-integration-test/shardingsphere-integration-test-transaction/src/test/resources/env/jdbc/postgresql/config-sharding-xa-atomikos.yaml b/shardingsphere-test/shardingsphere-integration-test/shardingsphere-integration-test-transaction/src/test/resources/env/jdbc/postgresql/config-sharding-xa-atomikos.yaml index d76760f284d..949ad464755 100644 --- a/shardingsphere-test/shardingsphere-integration-test/shardingsphere-integration-test-transaction/src/test/resources/env/jdbc/postgresql/config-sharding-xa-atomikos.yaml +++ b/shardingsphere-test/shardingsphere-integration-test/shardingsphere-integration-test-transaction/src/test/resources/env/jdbc/postgresql/config-sharding-xa-atomikos.yaml @@ -88,7 +88,7 @@ rules: account_inline: type: INLINE props: - algorithm-expression: account_${id % 2} + algorithm-expression: account_${Math.floorMod(Math.floorDiv(id.longValue(), 2L), 2L)} keyGenerators: snowflake: diff --git a/shardingsphere-test/shardingsphere-integration-test/shardingsphere-integration-test-transaction/src/test/resources/env/transaction-it-env.properties b/shardingsphere-test/shardingsphere-integration-test/shardingsphere-integration-test-transaction/src/test/resources/env/transaction-it-env.properties index df6fee6d852..76f5fd1150d 100644 --- a/shardingsphere-test/shardingsphere-integration-test/shardingsphere-integration-test-transaction/src/test/resources/env/transaction-it-env.properties +++ b/shardingsphere-test/shardingsphere-integration-test/shardingsphere-integration-test-transaction/src/test/resources/env/transaction-it-env.properties @@ -17,7 +17,7 @@ # transaction.it.type=DOCKER,NATIVE transaction.it.env.type= # transaction.it.env.cases= MySQLAutoCommitTestCase, PostgresSQLAutoCommitTestCase, ClassicTransferTestCase, MultiTableCommitAndRollbackTestCase, SingleTableCommitAndRollbackTestCase, MySQLSetReadOnlyTestCase, MySQLSavePointTestCase, PostgreSQLSavePointTestCase -transaction.it.env.cases=PostgresSQLAutoCommitTestCase, MultiTableCommitAndRollbackTestCase, SingleTableCommitAndRollbackTestCase, MySQLSetReadOnlyTestCase, MySQLSavePointTestCase, AddResourceTestCase, CloseResourceTestCase +transaction.it.env.cases=PostgresSQLAutoCommitTestCase, MultiTableCommitAndRollbackTestCase, SingleTableCommitAndRollbackTestCase, MySQLSetReadOnlyTestCase, MySQLSavePointTestCase, AddResourceTestCase, CloseResourceTestCase, PostgresSQLAndOpenGaussTruncateTestCase, MySQLLocalTruncateTestCase, MySQLXATruncateTestCase # transaction.it.env.transtypes=LOCAL, XA, BASE transaction.it.env.transtypes=LOCAL, XA # transaction.it.env.xa.providers=Atomikos, Bitronix, Narayana