From c486dbcddac83af147ad638bf2cf6b28497441ab Mon Sep 17 00:00:00 2001 From: hanshaohua Date: Wed, 18 Sep 2024 14:47:19 +0800 Subject: [PATCH 01/19] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E7=A5=9E=E9=80=9A?= =?UTF-8?q?=E6=95=B0=E6=8D=AE=E5=BA=93=E6=94=AF=E6=8C=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../apache/seata/common/util/PageUtil.java | 4 + .../seata/common/util/PageUtilTest.java | 2 + .../apache/seata/core/constants/DBType.java | 7 +- .../lock/DistributedLockSqlFactory.java | 2 +- .../db/sql/lock/LockStoreSqlFactory.java | 2 +- .../store/db/sql/lock/OscarLockStoreSql.java | 28 + .../store/db/sql/log/OscarLogStoreSqls.java | 27 + ....seata.core.store.db.sql.lock.LockStoreSql | 3 +- ...e.seata.core.store.db.sql.log.LogStoreSqls | 3 +- .../db/sql/lock/LockStoreSqlFactoryTest.java | 49 ++ .../db/sql/log/LogStoreSqlsFactoryTest.java | 36 + .../seata/rm/datasource/DataSourceProxy.java | 14 + .../exec/oscar/OscarInsertExecutor.java | 139 ++++ .../sql/handler/oscar/OscarEscapeHandler.java | 744 ++++++++++++++++++ .../sql/struct/cache/OscarTableMetaCache.java | 198 +++++ .../undo/oscar/OscarUndoDeleteExecutor.java | 79 ++ .../undo/oscar/OscarUndoExecutorHolder.java | 46 ++ .../undo/oscar/OscarUndoInsertExecutor.java | 86 ++ .../undo/oscar/OscarUndoLogManager.java | 105 +++ .../undo/oscar/OscarUndoUpdateExecutor.java | 80 ++ ...he.seata.rm.datasource.exec.InsertExecutor | 3 +- ...eata.rm.datasource.undo.UndoExecutorHolder | 3 +- ...he.seata.rm.datasource.undo.UndoLogManager | 3 +- .../org.apache.seata.sqlparser.EscapeHandler | 3 +- ...ache.seata.sqlparser.struct.TableMetaCache | 3 +- .../exec/OscarInsertExecutorTest.java | 445 +++++++++++ .../oscar/OscarDeleteRecognizerTest.java | 197 +++++ .../oscar/OscarInsertRecognizerTest.java | 129 +++ .../OscarSelectForUpdateRecognizerTest.java | 110 +++ .../oscar/OscarUpdateRecognizerTest.java | 156 ++++ script/client/at/db/oscar.sql | 27 + script/server/db/oscar.sql | 78 ++ .../seata/sqlparser/util/JdbcConstants.java | 2 + .../druid/oscar/BaseOscarRecognizer.java | 195 +++++ .../druid/oscar/OscarDeleteRecognizer.java | 137 ++++ .../druid/oscar/OscarInsertRecognizer.java | 159 ++++ .../oscar/OscarOperateRecognizerHolder.java | 55 ++ .../oscar/OscarSelectForUpdateRecognizer.java | 135 ++++ .../druid/oscar/OscarUpdateRecognizer.java | 181 +++++ ...sqlparser.druid.SQLOperateRecognizerHolder | 3 +- 40 files changed, 3667 insertions(+), 11 deletions(-) create mode 100644 core/src/main/java/org/apache/seata/core/store/db/sql/lock/OscarLockStoreSql.java create mode 100644 core/src/main/java/org/apache/seata/core/store/db/sql/log/OscarLogStoreSqls.java create mode 100644 rm-datasource/src/main/java/org/apache/seata/rm/datasource/exec/oscar/OscarInsertExecutor.java create mode 100644 rm-datasource/src/main/java/org/apache/seata/rm/datasource/sql/handler/oscar/OscarEscapeHandler.java create mode 100644 rm-datasource/src/main/java/org/apache/seata/rm/datasource/sql/struct/cache/OscarTableMetaCache.java create mode 100644 rm-datasource/src/main/java/org/apache/seata/rm/datasource/undo/oscar/OscarUndoDeleteExecutor.java create mode 100644 rm-datasource/src/main/java/org/apache/seata/rm/datasource/undo/oscar/OscarUndoExecutorHolder.java create mode 100644 rm-datasource/src/main/java/org/apache/seata/rm/datasource/undo/oscar/OscarUndoInsertExecutor.java create mode 100644 rm-datasource/src/main/java/org/apache/seata/rm/datasource/undo/oscar/OscarUndoLogManager.java create mode 100644 rm-datasource/src/main/java/org/apache/seata/rm/datasource/undo/oscar/OscarUndoUpdateExecutor.java create mode 100644 rm-datasource/src/test/java/org/apache/seata/rm/datasource/exec/OscarInsertExecutorTest.java create mode 100644 rm-datasource/src/test/java/org/apache/seata/rm/datasource/sql/druid/oscar/OscarDeleteRecognizerTest.java create mode 100644 rm-datasource/src/test/java/org/apache/seata/rm/datasource/sql/druid/oscar/OscarInsertRecognizerTest.java create mode 100644 rm-datasource/src/test/java/org/apache/seata/rm/datasource/sql/druid/oscar/OscarSelectForUpdateRecognizerTest.java create mode 100644 rm-datasource/src/test/java/org/apache/seata/rm/datasource/sql/druid/oscar/OscarUpdateRecognizerTest.java create mode 100644 script/client/at/db/oscar.sql create mode 100644 script/server/db/oscar.sql create mode 100644 sqlparser/seata-sqlparser-druid/src/main/java/org/apache/seata/sqlparser/druid/oscar/BaseOscarRecognizer.java create mode 100644 sqlparser/seata-sqlparser-druid/src/main/java/org/apache/seata/sqlparser/druid/oscar/OscarDeleteRecognizer.java create mode 100644 sqlparser/seata-sqlparser-druid/src/main/java/org/apache/seata/sqlparser/druid/oscar/OscarInsertRecognizer.java create mode 100644 sqlparser/seata-sqlparser-druid/src/main/java/org/apache/seata/sqlparser/druid/oscar/OscarOperateRecognizerHolder.java create mode 100644 sqlparser/seata-sqlparser-druid/src/main/java/org/apache/seata/sqlparser/druid/oscar/OscarSelectForUpdateRecognizer.java create mode 100644 sqlparser/seata-sqlparser-druid/src/main/java/org/apache/seata/sqlparser/druid/oscar/OscarUpdateRecognizer.java diff --git a/common/src/main/java/org/apache/seata/common/util/PageUtil.java b/common/src/main/java/org/apache/seata/common/util/PageUtil.java index 90ca42974cd..55b2aec5c35 100644 --- a/common/src/main/java/org/apache/seata/common/util/PageUtil.java +++ b/common/src/main/java/org/apache/seata/common/util/PageUtil.java @@ -111,6 +111,7 @@ public static String pageSql(String sourceSql, String dbType, int pageNum, int p case "postgresql": case "oceanbase": case "dm": + case "oscar": return LIMIT_TEMPLATE.replace(SOURCE_SQL_PLACE_HOLD, sourceSql) .replace(LIMIT_PLACE_HOLD, String.valueOf(pageSize)) .replace(OFFSET_PLACE_HOLD, String.valueOf((pageNum - 1) * pageSize)); @@ -141,6 +142,7 @@ public static String countSql(String sourceSql, String dbType) { case "oceanbase": case "oracle": case "dm": + case "oscar": return sourceSql.replaceAll("(?i)(?<=select)(.*)(?=from)", " count(1) "); case "postgresql": case "sqlserver": @@ -183,6 +185,7 @@ public static String getTimeStartSql(String dbType, String timeColumnName) { case "postgresql": case "sqlserver": case "dm": + case "oscar": return " and FLOOR(" + timeColumnName + "/1000) >= ? "; default: throw new IllegalArgumentException("The DB type :" + dbType + " is not supported yet"); @@ -202,6 +205,7 @@ public static String getTimeEndSql(String dbType, String timeColumnName) { case "postgresql": case "sqlserver": case "dm": + case "oscar": return " and FLOOR(" + timeColumnName + "/1000) <= ? "; default: throw new IllegalArgumentException("The DB type :" + dbType + " is not supported yet"); diff --git a/common/src/test/java/org/apache/seata/common/util/PageUtilTest.java b/common/src/test/java/org/apache/seata/common/util/PageUtilTest.java index 5fcdcfd5116..640fa037015 100644 --- a/common/src/test/java/org/apache/seata/common/util/PageUtilTest.java +++ b/common/src/test/java/org/apache/seata/common/util/PageUtilTest.java @@ -44,6 +44,7 @@ public void testPageSql() { assertEquals(PageUtil.pageSql(sourceSql, "postgresql", 1, 5), mysqlTargetSql); assertEquals(PageUtil.pageSql(sourceSql, "oceanbase", 1, 5), mysqlTargetSql); assertEquals(PageUtil.pageSql(sourceSql, "dm", 1, 5), mysqlTargetSql); + assertEquals(PageUtil.pageSql(sourceSql, "oscar", 1, 5), mysqlTargetSql); assertEquals(PageUtil.pageSql(sourceSql, "oracle", 1, 5), oracleTargetSql); assertEquals(PageUtil.pageSql(sourceSql, "sqlserver", 1, 5), sqlserverTargetSql); @@ -61,6 +62,7 @@ void testCountSql() { assertEquals(PageUtil.countSql(sourceSql, "postgresql"), targetSql); assertEquals(PageUtil.countSql(sourceSql, "oceanbase"), targetSql); assertEquals(PageUtil.countSql(sourceSql, "dm"), targetSql); + assertEquals(PageUtil.countSql(sourceSql, "oscar"), targetSql); assertEquals(PageUtil.countSql(sourceSql, "oracle"), targetSql); assertEquals(PageUtil.countSql(sourceSql, "sqlserver"), targetSql); diff --git a/core/src/main/java/org/apache/seata/core/constants/DBType.java b/core/src/main/java/org/apache/seata/core/constants/DBType.java index af0e82d312a..3521e3e4545 100644 --- a/core/src/main/java/org/apache/seata/core/constants/DBType.java +++ b/core/src/main/java/org/apache/seata/core/constants/DBType.java @@ -192,7 +192,12 @@ public enum DBType { /** * PolarDB db type. */ - POLARDB; + POLARDB, + + /** + * oscar db type. + */ + OSCAR; /** * Valueof db type. diff --git a/core/src/main/java/org/apache/seata/core/store/db/sql/distributed/lock/DistributedLockSqlFactory.java b/core/src/main/java/org/apache/seata/core/store/db/sql/distributed/lock/DistributedLockSqlFactory.java index 2072d4631c5..8f589780caa 100644 --- a/core/src/main/java/org/apache/seata/core/store/db/sql/distributed/lock/DistributedLockSqlFactory.java +++ b/core/src/main/java/org/apache/seata/core/store/db/sql/distributed/lock/DistributedLockSqlFactory.java @@ -34,7 +34,7 @@ public class DistributedLockSqlFactory { /** * get the lock store sql * - * @param dbType the dbType, support mysql/oracle/h2/postgre/oceanbase/dm/sqlserver ... + * @param dbType the dbType, support mysql/oracle/h2/postgre/oceanbase/dm/sqlserver/oscar ... * @return lock store sql */ public static DistributedLockSql getDistributedLogStoreSql(String dbType) { diff --git a/core/src/main/java/org/apache/seata/core/store/db/sql/lock/LockStoreSqlFactory.java b/core/src/main/java/org/apache/seata/core/store/db/sql/lock/LockStoreSqlFactory.java index dcf5781edc5..6fb7a61e335 100644 --- a/core/src/main/java/org/apache/seata/core/store/db/sql/lock/LockStoreSqlFactory.java +++ b/core/src/main/java/org/apache/seata/core/store/db/sql/lock/LockStoreSqlFactory.java @@ -34,7 +34,7 @@ public class LockStoreSqlFactory { /** * get the lock store sql * - * @param dbType the dbType, support mysql/oracle/h2/postgre/oceanbase/dm + * @param dbType the dbType, support mysql/oracle/h2/postgre/oceanbase/dm/oscar * @return lock store sql */ public static LockStoreSql getLogStoreSql(String dbType) { diff --git a/core/src/main/java/org/apache/seata/core/store/db/sql/lock/OscarLockStoreSql.java b/core/src/main/java/org/apache/seata/core/store/db/sql/lock/OscarLockStoreSql.java new file mode 100644 index 00000000000..175fab3fbe4 --- /dev/null +++ b/core/src/main/java/org/apache/seata/core/store/db/sql/lock/OscarLockStoreSql.java @@ -0,0 +1,28 @@ +/* + * Copyright 1999-2019 Seata.io Group. + * + * Licensed 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.seata.core.store.db.sql.lock; + + +import org.apache.seata.common.loader.LoadLevel; + +/** + * the database lock store shentong sql + * + * @author hsh + */ +@LoadLevel(name = "oscar") +public class OscarLockStoreSql extends OracleLockStoreSql { +} diff --git a/core/src/main/java/org/apache/seata/core/store/db/sql/log/OscarLogStoreSqls.java b/core/src/main/java/org/apache/seata/core/store/db/sql/log/OscarLogStoreSqls.java new file mode 100644 index 00000000000..2e7f7322f93 --- /dev/null +++ b/core/src/main/java/org/apache/seata/core/store/db/sql/log/OscarLogStoreSqls.java @@ -0,0 +1,27 @@ +/* + * Copyright 1999-2019 Seata.io Group. + * + * Licensed 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.seata.core.store.db.sql.log; + + +import org.apache.seata.common.loader.LoadLevel; + +/** + * Database log store oscar sql + * @author hsh + */ +@LoadLevel(name = "oscar") +public class OscarLogStoreSqls extends OracleLogStoreSqls { +} diff --git a/core/src/main/resources/META-INF/services/org.apache.seata.core.store.db.sql.lock.LockStoreSql b/core/src/main/resources/META-INF/services/org.apache.seata.core.store.db.sql.lock.LockStoreSql index fea6412761c..feb48b65f26 100644 --- a/core/src/main/resources/META-INF/services/org.apache.seata.core.store.db.sql.lock.LockStoreSql +++ b/core/src/main/resources/META-INF/services/org.apache.seata.core.store.db.sql.lock.LockStoreSql @@ -22,4 +22,5 @@ org.apache.seata.core.store.db.sql.lock.H2LockStoreSql org.apache.seata.core.store.db.sql.lock.SqlServerLockStoreSql org.apache.seata.core.store.db.sql.lock.MariadbLockStoreSql org.apache.seata.core.store.db.sql.lock.PolarDBXLockStoreSql -org.apache.seata.core.store.db.sql.lock.DmLockStoreSql \ No newline at end of file +org.apache.seata.core.store.db.sql.lock.DmLockStoreSql +org.apache.seata.core.store.db.sql.lock.OscarLockStoreSql \ No newline at end of file diff --git a/core/src/main/resources/META-INF/services/org.apache.seata.core.store.db.sql.log.LogStoreSqls b/core/src/main/resources/META-INF/services/org.apache.seata.core.store.db.sql.log.LogStoreSqls index 2f87cbe5aae..cb9ea45dddf 100644 --- a/core/src/main/resources/META-INF/services/org.apache.seata.core.store.db.sql.log.LogStoreSqls +++ b/core/src/main/resources/META-INF/services/org.apache.seata.core.store.db.sql.log.LogStoreSqls @@ -22,4 +22,5 @@ org.apache.seata.core.store.db.sql.log.H2LogStoreSqls org.apache.seata.core.store.db.sql.log.SqlServerLogStoreSqls org.apache.seata.core.store.db.sql.log.MariadbLogStoreSqls org.apache.seata.core.store.db.sql.log.PolarDBXLogStoreSqls -org.apache.seata.core.store.db.sql.log.DmLogStoreSqls \ No newline at end of file +org.apache.seata.core.store.db.sql.log.DmLogStoreSqls +org.apache.seata.core.store.db.sql.log.OscarLogStoreSqls \ No newline at end of file diff --git a/core/src/test/java/org/apache/seata/core/store/db/sql/lock/LockStoreSqlFactoryTest.java b/core/src/test/java/org/apache/seata/core/store/db/sql/lock/LockStoreSqlFactoryTest.java index 4a598bbe52a..a38f75644cb 100644 --- a/core/src/test/java/org/apache/seata/core/store/db/sql/lock/LockStoreSqlFactoryTest.java +++ b/core/src/test/java/org/apache/seata/core/store/db/sql/lock/LockStoreSqlFactoryTest.java @@ -40,6 +40,8 @@ public class LockStoreSqlFactoryTest { private static LockStoreSql DM_LOCK_STORE = LockStoreSqlFactory.getLogStoreSql("dm"); + private static LockStoreSql OSCAR_LOCK_STORE = LockStoreSqlFactory.getLogStoreSql("oscar"); + private static String GLOBAL_TABLE = "global_table"; private static String BRANCH_TABLE = "branch_table"; @@ -379,4 +381,51 @@ public void dmLockTest() { sql = DM_LOCK_STORE.getCheckLockableSql(BRANCH_TABLE, 3); Assertions.assertEquals(EXPECT_CHECK_BRANCH_LOCKABLE_SQL,sql); } + + + @Test + public void oscarLockTest() { + String sql; + // Get insert lock sql string. + sql = OSCAR_LOCK_STORE.getInsertLockSQL(GLOBAL_TABLE); + Assertions.assertNotNull(sql); + sql = OSCAR_LOCK_STORE.getInsertLockSQL(BRANCH_TABLE); + Assertions.assertNotNull(sql); + + // Get delete lock sql string. + sql = OSCAR_LOCK_STORE.getDeleteLockSql(GLOBAL_TABLE); + Assertions.assertNotNull(sql); + sql = OSCAR_LOCK_STORE.getDeleteLockSql(BRANCH_TABLE); + Assertions.assertNotNull(sql); + + // Get batch delete lock sql string. + sql = OSCAR_LOCK_STORE.getBatchDeleteLockSql(GLOBAL_TABLE, 3); + Assertions.assertEquals(EXPECT_BATCH_GLOBAL_DELETE_LOCK_SQL,sql); + sql = OSCAR_LOCK_STORE.getBatchDeleteLockSql(BRANCH_TABLE, 3); + Assertions.assertEquals(EXPECT_BATCH_BRANCH_DELETE_LOCK_SQL,sql); + + // Get batch delete lock sql string. + sql = OSCAR_LOCK_STORE.getBatchDeleteLockSqlByBranchId(GLOBAL_TABLE); + Assertions.assertNotNull(sql); + sql = OSCAR_LOCK_STORE.getBatchDeleteLockSqlByBranchId(BRANCH_TABLE); + Assertions.assertNotNull(sql); + + // Get batch delete lock sql string. + sql = OSCAR_LOCK_STORE.getBatchDeleteLockSqlByXid(GLOBAL_TABLE); + Assertions.assertEquals(EXPECT_BATCH_GLOBAL_DELETE_LOCK_BY_BRANCHS_SQL,sql); + sql = OSCAR_LOCK_STORE.getBatchDeleteLockSqlByXid(BRANCH_TABLE); + Assertions.assertEquals(EXPECT_BATCH_BRANCH_DELETE_LOCK_BY_BRANCHS_SQL,sql); + + // Get query lock sql string. + sql = OSCAR_LOCK_STORE.getQueryLockSql(GLOBAL_TABLE); + Assertions.assertNotNull(sql); + sql = OSCAR_LOCK_STORE.getQueryLockSql(BRANCH_TABLE); + Assertions.assertNotNull(sql); + + // Get check lock sql string. + sql = OSCAR_LOCK_STORE.getCheckLockableSql(GLOBAL_TABLE, 3); + Assertions.assertEquals(EXPECT_CHECK_GLOBAL_LOCKABLE_SQL,sql); + sql = OSCAR_LOCK_STORE.getCheckLockableSql(BRANCH_TABLE, 3); + Assertions.assertEquals(EXPECT_CHECK_BRANCH_LOCKABLE_SQL,sql); + } } diff --git a/core/src/test/java/org/apache/seata/core/store/db/sql/log/LogStoreSqlsFactoryTest.java b/core/src/test/java/org/apache/seata/core/store/db/sql/log/LogStoreSqlsFactoryTest.java index f3b9421862e..45c1aa3d101 100644 --- a/core/src/test/java/org/apache/seata/core/store/db/sql/log/LogStoreSqlsFactoryTest.java +++ b/core/src/test/java/org/apache/seata/core/store/db/sql/log/LogStoreSqlsFactoryTest.java @@ -34,6 +34,8 @@ public class LogStoreSqlsFactoryTest { private static LogStoreSqls dmLog = LogStoreSqlsFactory.getLogStoreSqls("dm"); + private static LogStoreSqls oscarLog = LogStoreSqlsFactory.getLogStoreSqls("oscar"); + private static String globalTable = "global_table"; private static String branchTable = "branch_table"; @@ -246,4 +248,38 @@ public void dmLogTest() { sql = dmLog.getQueryBranchMax(branchTable); Assertions.assertNotNull(sql); } + + @Test + public void oscarLogTest() { + String sql = oscarLog.getInsertGlobalTransactionSQL(globalTable); + Assertions.assertNotNull(sql); + sql = oscarLog.getUpdateGlobalTransactionStatusSQL(globalTable); + Assertions.assertNotNull(sql); + sql = oscarLog.getDeleteGlobalTransactionSQL(globalTable); + Assertions.assertNotNull(sql); + sql = oscarLog.getQueryGlobalTransactionSQL(globalTable); + Assertions.assertNotNull(sql); + sql = oscarLog.getQueryGlobalTransactionSQLByTransactionId(globalTable); + Assertions.assertNotNull(sql); + sql = oscarLog.getQueryGlobalTransactionSQLByStatus(globalTable, "1"); + Assertions.assertNotNull(sql); + sql = oscarLog.getQueryGlobalTransactionForRecoverySQL(globalTable); + Assertions.assertNotNull(sql); + sql = oscarLog.getInsertBranchTransactionSQL(branchTable); + Assertions.assertNotNull(sql); + sql = oscarLog.getUpdateBranchTransactionStatusSQL(branchTable); + Assertions.assertNotNull(sql); + sql = oscarLog.getDeleteBranchTransactionByBranchIdSQL(branchTable); + Assertions.assertNotNull(sql); + sql = oscarLog.getDeleteBranchTransactionByXId(branchTable); + Assertions.assertNotNull(sql); + sql = oscarLog.getQueryBranchTransaction(branchTable); + Assertions.assertNotNull(sql); + sql = oscarLog.getQueryBranchTransaction(branchTable, "1"); + Assertions.assertNotNull(sql); + sql = oscarLog.getQueryGlobalMax(globalTable); + Assertions.assertNotNull(sql); + sql = oscarLog.getQueryBranchMax(branchTable); + Assertions.assertNotNull(sql); + } } diff --git a/rm-datasource/src/main/java/org/apache/seata/rm/datasource/DataSourceProxy.java b/rm-datasource/src/main/java/org/apache/seata/rm/datasource/DataSourceProxy.java index dfab706294e..8868a0c964b 100644 --- a/rm-datasource/src/main/java/org/apache/seata/rm/datasource/DataSourceProxy.java +++ b/rm-datasource/src/main/java/org/apache/seata/rm/datasource/DataSourceProxy.java @@ -243,6 +243,8 @@ private void initResourceId() { initSqlServerResourceId(); } else if (JdbcConstants.DM.equals(dbType)) { initDMResourceId(); + } else if (JdbcConstants.OSCAR.equals(dbType)) { + initOscarResourceId(); } else { initDefaultResourceId(); } @@ -321,6 +323,18 @@ private void initDMResourceId() { } } + /** + * init the oscar resource id + * jdbc:oscar://192.168.x.xx:2003/OSRDB + */ + private void initOscarResourceId() { + if (jdbcUrl.contains("?")) { + resourceId = jdbcUrl.substring(0, jdbcUrl.indexOf('?')) + "/" + userName; + } else { + resourceId = jdbcUrl + "/" + userName; + } + } + /** * prevent pg sql url like * jdbc:postgresql://127.0.0.1:5432/seata?currentSchema=public diff --git a/rm-datasource/src/main/java/org/apache/seata/rm/datasource/exec/oscar/OscarInsertExecutor.java b/rm-datasource/src/main/java/org/apache/seata/rm/datasource/exec/oscar/OscarInsertExecutor.java new file mode 100644 index 00000000000..0585e030601 --- /dev/null +++ b/rm-datasource/src/main/java/org/apache/seata/rm/datasource/exec/oscar/OscarInsertExecutor.java @@ -0,0 +1,139 @@ +/* + * Copyright 1999-2019 Seata.io Group. + * + * Licensed 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.seata.rm.datasource.exec.oscar; + +import org.apache.seata.common.loader.LoadLevel; +import org.apache.seata.common.loader.Scope; +import org.apache.seata.common.util.CollectionUtils; +import org.apache.seata.rm.datasource.StatementProxy; +import org.apache.seata.rm.datasource.exec.BaseInsertExecutor; +import org.apache.seata.rm.datasource.exec.StatementCallback; +import org.apache.seata.sqlparser.SQLInsertRecognizer; +import org.apache.seata.sqlparser.SQLRecognizer; +import org.apache.seata.sqlparser.struct.Null; +import org.apache.seata.sqlparser.struct.Sequenceable; +import org.apache.seata.sqlparser.struct.SqlMethodExpr; +import org.apache.seata.sqlparser.struct.SqlSequenceExpr; +import org.apache.seata.sqlparser.util.ColumnUtils; +import org.apache.seata.sqlparser.util.JdbcConstants; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.sql.SQLException; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Set; + +/** + * The type Oscar insert executor. + * + * @author hsh + */ +@LoadLevel(name = JdbcConstants.OSCAR, scope = Scope.PROTOTYPE) +public class OscarInsertExecutor extends BaseInsertExecutor implements Sequenceable { + + private static final Logger LOGGER = LoggerFactory.getLogger(OscarInsertExecutor.class); + + /** + * Instantiates a new Abstract dml base executor. + * + * @param statementProxy the statement proxy + * @param statementCallback the statement callback + * @param sqlRecognizer the sql recognizer + */ + public OscarInsertExecutor(StatementProxy statementProxy, StatementCallback statementCallback, + SQLRecognizer sqlRecognizer) { + super(statementProxy, statementCallback, sqlRecognizer); + } + + /** + * 1. If the insert columns are not empty and do not contain any pk columns, + * it means that there is no pk value in the insert rows, then all the pk values should come from auto-increment. + *

+ * 2. The pk value exists in insert rows. The possible situations are: + *

+ * + * @return {@link Map}<{@link String}, {@link List}<{@link Object}>> + * @throws SQLException the sql exception + */ + @Override + public Map> getPkValues() throws SQLException { + List pkColumnNameList = getTableMeta().getPrimaryKeyOnlyName(); + Map> pkValuesMap = new HashMap<>(pkColumnNameList.size()); + + // first obtain the existing pk value from the insert rows (if exists) + if (!containsColumns() || containsAnyPk()) { + pkValuesMap.putAll(getPkValuesByColumn()); + } + // other from auto-increment + for (String columnName : pkColumnNameList) { + if (!pkValuesMap.containsKey(columnName)) { + pkValuesMap.put(columnName, getGeneratedKeys(columnName)); + } + } + return pkValuesMap; + } + + /** + * Whether the insert columns contain any pk columns + * + * @return true: contain at least one pk column. false: do not contain any pk columns + */ + public boolean containsAnyPk() { + SQLInsertRecognizer recognizer = (SQLInsertRecognizer)sqlRecognizer; + List insertColumns = recognizer.getInsertColumns(); + if (CollectionUtils.isEmpty(insertColumns)) { + return false; + } + List pkColumnNameList = getTableMeta().getPrimaryKeyOnlyName(); + if (CollectionUtils.isEmpty(pkColumnNameList)) { + return false; + } + List newColumns = ColumnUtils.delEscape(insertColumns, getDbType()); + return pkColumnNameList.stream().anyMatch(pkColumn -> newColumns.contains(pkColumn) + || CollectionUtils.toUpperList(newColumns).contains(pkColumn.toUpperCase())); + } + + @Override + public Map> getPkValuesByColumn() throws SQLException { + Map> pkValuesMap = parsePkValuesFromStatement(); + Set keySet = pkValuesMap.keySet(); + for (String pkKey : keySet) { + List pkValues = pkValuesMap.get(pkKey); + for (int i = 0; i < pkValues.size(); i++) { + if (!pkKey.isEmpty() && pkValues.get(i) instanceof SqlSequenceExpr) { + pkValues.set(i, getPkValuesBySequence((SqlSequenceExpr) pkValues.get(i), pkKey).get(0)); + } else if (!pkKey.isEmpty() && pkValues.get(i) instanceof SqlMethodExpr) { + pkValues.set(i, getGeneratedKeys(pkKey).get(0)); + } else if (!pkKey.isEmpty() && pkValues.get(i) instanceof Null) { + pkValues.set(i, getGeneratedKeys(pkKey).get(0)); + } + } + pkValuesMap.put(pkKey, pkValues); + } + return pkValuesMap; + } + + @Override + public String getSequenceSql(SqlSequenceExpr expr) { + return "SELECT " + expr.getSequence() + ".currval FROM DUAL"; + } + +} diff --git a/rm-datasource/src/main/java/org/apache/seata/rm/datasource/sql/handler/oscar/OscarEscapeHandler.java b/rm-datasource/src/main/java/org/apache/seata/rm/datasource/sql/handler/oscar/OscarEscapeHandler.java new file mode 100644 index 00000000000..aa07be7f26d --- /dev/null +++ b/rm-datasource/src/main/java/org/apache/seata/rm/datasource/sql/handler/oscar/OscarEscapeHandler.java @@ -0,0 +1,744 @@ +/* + * Copyright 1999-2019 Seata.io Group. + * + * Licensed 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.seata.rm.datasource.sql.handler.oscar; + +import java.util.Arrays; +import java.util.Set; +import java.util.stream.Collectors; + +import org.apache.seata.common.loader.LoadLevel; +import org.apache.seata.common.util.StringUtils; +import org.apache.seata.sqlparser.EscapeHandler; +import org.apache.seata.sqlparser.struct.ColumnMeta; +import org.apache.seata.sqlparser.struct.TableMeta; +import org.apache.seata.sqlparser.util.JdbcConstants; + +/** + * The type OSCAR keyword checker. + * + * @author hsh + */ +@LoadLevel(name = JdbcConstants.OSCAR) +public class OscarEscapeHandler implements EscapeHandler { + + protected Set keywordSet = Arrays.stream(OscarKeyword.values()).map(OscarKeyword::name).collect(Collectors.toSet()); + + /** + * OSCAR keyword + */ + private enum OscarKeyword { + ABORT("ABORT"), + ABSOLUTE("ABSOLUTE"), + ACCESS("ACCESS"), + ACCESSED("ACCESSED"), + ACTION("ACTION"), + ADD("ADD"), + ADMIN("ADMIN"), + ADVISOR("ADVISOR"), + AFTER("AFTER"), + AGGREGATE("AGGREGATE"), + ALTER("ALTER"), + ALWAYS("ALWAYS"), + ANALYSE("ANALYSE"), + ANALYZE("ANALYZE"), + ANALYZER("ANALYZER"), + APP("APP"), + ARCHIVE("ARCHIVE"), + ARCHIVELOG("ARCHIVELOG"), + ARE("ARE"), + ARRAY("ARRAY"), + ASC("ASC"), + ASSERTION("ASSERTION"), + ASSIGNMENT("ASSIGNMENT"), + AST("AST"), + ASYNC("ASYNC"), + ATTRIBUTES("ATTRIBUTES"), + AUDIT("AUDIT"), + AUDITFILE("AUDITFILE"), + AUTHID("AUTHID"), + AUTHORIZATION("AUTHORIZATION"), + AUTO("AUTO"), + AUTO_INCREMENT("AUTO_INCREMENT"), + AUTOEXTEND("AUTOEXTEND"), + BACKUP("BACKUP"), + BACKWARD("BACKWARD"), + BASICANALYZER("BASICANALYZER"), + BATCHSIZE("BATCHSIZE"), + BEFORE("BEFORE"), + BEGIN("BEGIN"), + BETWEEN("BETWEEN"), + BIGINT("BIGINT"), + BINARY("BINARY"), + BINLOG("BINLOG"), + BIT("BIT"), + BITMAP("BITMAP"), + BLOCK("BLOCK"), + BODY("BODY"), + BOOLEAN("BOOLEAN"), + BOTH("BOTH"), + BPCHAR("BPCHAR"), + BUFFER("BUFFER"), + BUFFER_CACHE("BUFFER_CACHE"), + BUFFER_POOL("BUFFER_POOL"), + BUILD("BUILD"), + BULK("BULK"), + BY("BY"), + BYTE("BYTE"), + CACHE("CACHE"), + CALL("CALL"), + CALLED("CALLED"), + CANCEL("CANCEL"), + CASCADED("CASCADED"), + CDC("CDC"), + CHAIN("CHAIN"), + CHANGE("CHANGE"), + CHARACTERISTICS("CHARACTERISTICS"), + CHARACTERSET("CHARACTERSET"), + CHEAT("CHEAT"), + CHECKPOINT("CHECKPOINT"), + CHINESEANALYZER("CHINESEANALYZER"), + CHUNK("CHUNK"), + CJKANALYZER("CJKANALYZER"), + CLASS("CLASS"), + CLEAN("CLEAN"), + CLOSE("CLOSE"), + CLUSTER("CLUSTER"), + COLUMNS("COLUMNS"), + COMMENT("COMMENT"), + COMMENTS("COMMENTS"), + COMMIT("COMMIT"), + COMMITTED("COMMITTED"), + COMPILE("COMPILE"), + COMPLETE("COMPLETE"), + COMPRESS("COMPRESS"), + CONCAT("CONCAT"), + CONFIGURATION("CONFIGURATION"), + CONNECT("CONNECT"), + CONNECT_BY_ISCYCLE("CONNECT_BY_ISCYCLE"), + CONNECT_BY_ISLEAF("CONNECT_BY_ISLEAF"), + CONNECT_BY_ROOT("CONNECT_BY_ROOT"), + CONSTRAINTS("CONSTRAINTS"), + CONTENT("CONTENT"), + CONTEXT("CONTEXT"), + CONTINUE("CONTINUE"), + CONTROLFILE("CONTROLFILE"), + CONVERSION("CONVERSION"), + COPY("COPY"), + CROSS("CROSS"), + CSV("CSV"), + CUBE("CUBE"), + CURRENT("CURRENT"), + CURRENT_USER("CURRENT_USER"), + CURSOR("CURSOR"), + CYCLE("CYCLE"), + DATA("DATA"), + DATABASE("DATABASE"), + DATABASELINK("DATABASELINK"), + DATAFILE("DATAFILE"), + DATAFILETYPE("DATAFILETYPE"), + DATE("DATE"), + DATE_ADD("DATE_ADD"), + DATE_SUB("DATE_SUB"), + DATEFORMAT("DATEFORMAT"), + DATETIME("DATETIME"), + DAY("DAY"), + DBA("DBA"), + DEALLOCATE("DEALLOCATE"), + DEBUG("DEBUG"), + DEC("DEC"), + DECLARE("DECLARE"), + DECODE("DECODE"), + DECRYPT("DECRYPT"), + DEFERRABLE("DEFERRABLE"), + DEFERRED("DEFERRED"), + DEFINER("DEFINER"), + DELETE("DELETE"), + DELIMITED("DELIMITED"), + DELIMITER("DELIMITER"), + DELIMITERS("DELIMITERS"), + DEMAND("DEMAND"), + DENSE_RANK("DENSE_RANK"), + DESC("DESC"), + DESCRIPTION("DESCRIPTION"), + DETERMINISTIC("DETERMINISTIC"), + DIRECTORY("DIRECTORY"), + DISABLE("DISABLE"), + DOCUMENT("DOCUMENT"), + DOMAIN("DOMAIN"), + DOUBLE("DOUBLE"), + DUMP("DUMP"), + EACH("EACH"), + ELOG("ELOG"), + ELT("ELT"), + EMPTY("EMPTY"), + ENABLE("ENABLE"), + ENCODING("ENCODING"), + ENCRYPT("ENCRYPT"), + ENCRYPTED("ENCRYPTED"), + ENCRYPTION("ENCRYPTION"), + END("END"), + ERROR("ERROR"), + ERRORS("ERRORS"), + ESCALATION("ESCALATION"), + ESCAPE("ESCAPE"), + EVENTS("EVENTS"), + EXCHANGE("EXCHANGE"), + EXCLUDING("EXCLUDING"), + EXCLUSIVE("EXCLUSIVE"), + EXEC("EXEC"), + EXECUTE("EXECUTE"), + EXPLAIN("EXPLAIN"), + EXPORT("EXPORT"), + EXTEND("EXTEND"), + EXTERNALLY("EXTERNALLY"), + FAILOVER("FAILOVER"), + FALSE("FALSE"), + FAR("FAR"), + FAST("FAST"), + FAULT("FAULT"), + FETCH("FETCH"), + FIELD("FIELD"), + FIELDS("FIELDS"), + FIELDTERMINATOR("FIELDTERMINATOR"), + FILE("FILE"), + FILESIZE("FILESIZE"), + FILL("FILL"), + FILTER("FILTER"), + FIRE_TRIGGERS("FIRE_TRIGGERS"), + FIRST("FIRST"), + FIRSTROW("FIRSTROW"), + FLUSH("FLUSH"), + FOLLOWING("FOLLOWING"), + FORCE("FORCE"), + FOREIGNKEY_CONSTRAINTS("FOREIGNKEY_CONSTRAINTS"), + FOREVER("FOREVER"), + FORMATFILE("FORMATFILE"), + FORWARD("FORWARD"), + FREELISTS("FREELISTS"), + FREEPOOLS("FREEPOOLS"), + FULL("FULL"), + FULLTEXT("FULLTEXT"), + FUNCTION("FUNCTION"), + G("G"), + GB("GB"), + GBK("GBK"), + GCOV("GCOV"), + GENERATED("GENERATED"), + GEOGRAPHY("GEOGRAPHY"), + GEOMETRY("GEOMETRY"), + GET("GET"), + GETCLOBVAL("GETCLOBVAL"), + GETSTRINGVAL("GETSTRINGVAL"), + GLOBAL("GLOBAL"), + GLOBAL_NAME("GLOBAL_NAME"), + GLOBALLY("GLOBALLY"), + GREATEST("GREATEST"), + GROUPING("GROUPING"), + GROUPING_ID("GROUPING_ID"), + GUARANTEE("GUARANTEE"), + HANDLER("HANDLER"), + HASH("HASH"), + HEADER("HEADER"), + HEAP("HEAP"), + HOLD("HOLD"), + HOUR("HOUR"), + IDENTIFIED("IDENTIFIED"), + IDENTITY("IDENTITY"), + IF("IF"), + IGNORE("IGNORE"), + ILIKE("ILIKE"), + IMMEDIATE("IMMEDIATE"), + IMMUTABLE("IMMUTABLE"), + IMPLICIT("IMPLICIT"), + IMPORT("IMPORT"), + IMPORT_POLCOL("IMPORT_POLCOL"), + INCREMENT("INCREMENT"), + INDEX("INDEX"), + INDEXES("INDEXES"), + INHERITS("INHERITS"), + INIT("INIT"), + INITIAL("INITIAL"), + INITIALIZED("INITIALIZED"), + INITIALLY("INITIALLY"), + INITRANS("INITRANS"), + INNER("INNER"), + INOUT("INOUT"), + INPUT("INPUT"), + INSENSITIVE("INSENSITIVE"), + INSERT("INSERT"), + INSTEAD("INSTEAD"), + INTERVAL("INTERVAL"), + INVALIDATE("INVALIDATE"), + INVISIBLE("INVISIBLE"), + INVOKER("INVOKER"), + IP("IP"), + IS("IS"), + ISNULL("ISNULL"), + ISOLATION("ISOLATION"), + JOIN("JOIN"), + JSON("JSON"), + JSON_TABLE("JSON_TABLE"), + JSON_VALUE("JSON_VALUE"), + K("K"), + KB("KB"), + KEEP("KEEP"), + KEEPIDENTITY("KEEPIDENTITY"), + KEEPNULLS("KEEPNULLS"), + KEY("KEY"), + KEYSTORE("KEYSTORE"), + KILL("KILL"), + KILOBYTES_PER_BATCH("KILOBYTES_PER_BATCH"), + KSTORE("KSTORE"), + LABEL("LABEL"), + LANCOMPILER("LANCOMPILER"), + LANGUAGE("LANGUAGE"), + LAST("LAST"), + LASTROW("LASTROW"), + LC_COLLATE("LC_COLLATE"), + LC_CTYPE("LC_CTYPE"), + LDRTRIM("LDRTRIM"), + LEADING("LEADING"), + LEAK("LEAK"), + LEAST("LEAST"), + LEFT("LEFT"), + LESS("LESS"), + LIFETIME("LIFETIME"), + LIKE("LIKE"), + LIMIT("LIMIT"), + LIST("LIST"), + LISTEN("LISTEN"), + LOAD("LOAD"), + LOB("LOB"), + LOCAL("LOCAL"), + LOCATION("LOCATION"), + LOCK("LOCK"), + LOCKED("LOCKED"), + LOG("LOG"), + LOGFILE("LOGFILE"), + LOGGING("LOGGING"), + LOGICAL("LOGICAL"), + LONG("LONG"), + LOOP("LOOP"), + LRTRIM("LRTRIM"), + LSN("LSN"), + LTRIM("LTRIM"), + M("M"), + MAINTAIN_INDEX("MAINTAIN_INDEX"), + MAINTENANCE("MAINTENANCE"), + MANUAL("MANUAL"), + MASKING("MASKING"), + MATCH("MATCH"), + MATCHED("MATCHED"), + MATERIALIZED("MATERIALIZED"), + MAX("MAX"), + MAXERRORS("MAXERRORS"), + MAXEXTENDS("MAXEXTENDS"), + MAXEXTENTS("MAXEXTENTS"), + MAXSIZE("MAXSIZE"), + MAXTRANS("MAXTRANS"), + MAXVALUE("MAXVALUE"), + MB("MB"), + MEMBER("MEMBER"), + MEMORY("MEMORY"), + MERGE("MERGE"), + MIN("MIN"), + MINEXTENDS("MINEXTENDS"), + MINEXTENTS("MINEXTENTS"), + MINSIZE("MINSIZE"), + MINUS("MINUS"), + MINUTE("MINUTE"), + MINVALUE("MINVALUE"), + MISSING("MISSING"), + MOD("MOD"), + MODE("MODE"), + MODIFY("MODIFY"), + MONEY("MONEY"), + MONTH("MONTH"), + MOUNT("MOUNT"), + MOVE("MOVE"), + MOVEMENT("MOVEMENT"), + MULTICOLUMN("MULTICOLUMN"), + MULTIPLE("MULTIPLE"), + NAME("NAME"), + NAMES("NAMES"), + NATURAL("NATURAL"), + NCHAR("NCHAR"), + NEVER("NEVER"), + NEWLINE("NEWLINE"), + NEXT("NEXT"), + NEXTVAL("NEXTVAL"), + NO("NO"), + NOARCHIVELOG("NOARCHIVELOG"), + NOAUDIT("NOAUDIT"), + NOCACHE("NOCACHE"), + NOCOMPRESS("NOCOMPRESS"), + NOCOPY("NOCOPY"), + NOCYCLE("NOCYCLE"), + NODE("NODE"), + NOGUARANTEE("NOGUARANTEE"), + NOLOGGING("NOLOGGING"), + NOMAXVALUE("NOMAXVALUE"), + NOMINVALUE("NOMINVALUE"), + NOMOUNT("NOMOUNT"), + NORMAL("NORMAL"), + NOTHING("NOTHING"), + NOTIFY("NOTIFY"), + NOTNULL("NOTNULL"), + NOTRIM("NOTRIM"), + NOVALIDATE("NOVALIDATE"), + NOWAIT("NOWAIT"), + NVARCHAR2("NVARCHAR2"), + NVL("NVL"), + NVL2("NVL2"), + OBJECT("OBJECT"), + OF("OF"), + OFF("OFF"), + OFFLINE("OFFLINE"), + OFFSET("OFFSET"), + OIDS("OIDS"), + ONLINE("ONLINE"), + OPEN("OPEN"), + OPERATOR("OPERATOR"), + OPTIMIZE("OPTIMIZE"), + OPTIMIZE_KSCACHE("OPTIMIZE_KSCACHE"), + OPTION("OPTION"), + ORACLE("ORACLE"), + ORDINALITY("ORDINALITY"), + ORGANIZATION("ORGANIZATION"), + OSCAR("OSCAR"), + OUT("OUT"), + OUTER("OUTER"), + OUTLINE("OUTLINE"), + OVER("OVER"), + OVERFLOW("OVERFLOW"), + OVERLAPS("OVERLAPS"), + OVERLAY("OVERLAY"), + OWNER("OWNER"), + PACKAGE("PACKAGE"), + PAGESIZE("PAGESIZE"), + PARALLEL("PARALLEL"), + PARAMETER("PARAMETER"), + PARAMINFO("PARAMINFO"), + PARTIAL("PARTIAL"), + PARTITION("PARTITION"), + PARTITIONS("PARTITIONS"), + PASSING("PASSING"), + PASSWORD("PASSWORD"), + PATH("PATH"), + PCTFREE("PCTFREE"), + PCTINCREASE("PCTINCREASE"), + PCTTHRESHOLD("PCTTHRESHOLD"), + PCTUSED("PCTUSED"), + PCTVERSION("PCTVERSION"), + PENDANT("PENDANT"), + PETENTION("PETENTION"), + PFILE("PFILE"), + PIPELINED("PIPELINED"), + PIVOT("PIVOT"), + PLACING("PLACING"), + PLS_INTEGER("PLS_INTEGER"), + POLICY("POLICY"), + PORT("PORT"), + POSITION("POSITION"), + PRECEDING("PRECEDING"), + PRECISION("PRECISION"), + PREPARE("PREPARE"), + PRESERVE("PRESERVE"), + PREVAL("PREVAL"), + PRIMARY("PRIMARY"), + PRIOR("PRIOR"), + PRIORITY("PRIORITY"), + PRIVILEGES("PRIVILEGES"), + PROCEDURAL("PROCEDURAL"), + PROCEDURE("PROCEDURE"), + PUBLIC("PUBLIC"), + PURGE("PURGE"), + QU("QU"), + QUERY("QUERY"), + QUICK("QUICK"), + QUOTE("QUOTE"), + RAC("RAC"), + RANGE("RANGE"), + RATIO_TO_REPORT("RATIO_TO_REPORT"), + RAW("RAW"), + READ("READ"), + READABLE("READABLE"), + READS("READS"), + READSIZE("READSIZE"), + REBUILD("REBUILD"), + RECHECK("RECHECK"), + RECORDS("RECORDS"), + RECOVERY("RECOVERY"), + RECREATE("RECREATE"), + RECURSIVE("RECURSIVE"), + RECYCLE("RECYCLE"), + REFRESH("REFRESH"), + REGEXP("REGEXP"), + REGION("REGION"), + REJECT("REJECT"), + RELATIVE("RELATIVE"), + REMOVE("REMOVE"), + RENAME("RENAME"), + REPEATABLE("REPEATABLE"), + REPLACE("REPLACE"), + RESET("RESET"), + RESIZE("RESIZE"), + RESOURCE("RESOURCE"), + RESTART("RESTART"), + RESTORE("RESTORE"), + RESTRICT("RESTRICT"), + RESULT("RESULT"), + RESUME("RESUME"), + RETENTION("RETENTION"), + RETURN("RETURN"), + RETURN_GENERATED_KEYS("RETURN_GENERATED_KEYS"), + RETURNING("RETURNING"), + RETURNS("RETURNS"), + REUSE("REUSE"), + REVERSE("REVERSE"), + REVOKE("REVOKE"), + REWRITE("REWRITE"), + RIGHT("RIGHT"), + ROLE("ROLE"), + ROLLBACK("ROLLBACK"), + ROLLUP("ROLLUP"), + ROW("ROW"), + ROWDESCRIPTION("ROWDESCRIPTION"), + ROWID("ROWID"), + ROWS("ROWS"), + ROWS_PER_BATCH("ROWS_PER_BATCH"), + ROWTERMINATOR("ROWTERMINATOR"), + ROWTYPE("ROWTYPE"), + RTRIM("RTRIM"), + RULE("RULE"), + SAMPLE("SAMPLE"), + SAVEPOINT("SAVEPOINT"), + SCAN("SCAN"), + SCHEMA("SCHEMA"), + SCN("SCN"), + SCROLL("SCROLL"), + SECOND("SECOND"), + SECURITY("SECURITY"), + SEGMENT("SEGMENT"), + SEPARATOR("SEPARATOR"), + SEQUENCE("SEQUENCE"), + SERIALIZABLE("SERIALIZABLE"), + SESSION("SESSION"), + SETS("SETS"), + SHARE("SHARE"), + SHOW("SHOW"), + SHRINK("SHRINK"), + SHRINKLOG("SHRINKLOG"), + SHUTDOWN("SHUTDOWN"), + SIBLINGS("SIBLINGS"), + SIGNED("SIGNED"), + SILENTLY("SILENTLY"), + SIMILAR("SIMILAR"), + SIMPLE("SIMPLE"), + SINGLE("SINGLE"), + SINGLEROW("SINGLEROW"), + SIZE("SIZE"), + SKIP("SKIP"), + SMALLINT("SMALLINT"), + SPACE("SPACE"), + SPLIT("SPLIT"), + STABLE("STABLE"), + STANDALONE("STANDALONE"), + STANDARDANALYZER("STANDARDANALYZER"), + START("START"), + STARTFILE("STARTFILE"), + STARTPOS("STARTPOS"), + STARTTIME("STARTTIME"), + STARTUP("STARTUP"), + STATEMENT("STATEMENT"), + STATIC("STATIC"), + STATISTICS("STATISTICS"), + STDIN("STDIN"), + STDOUT("STDOUT"), + STOP("STOP"), + STOPFILE("STOPFILE"), + STOPPOS("STOPPOS"), + STOPTIME("STOPTIME"), + STOPWORDS("STOPWORDS"), + STORAGE("STORAGE"), + STORE("STORE"), + STORED("STORED"), + STRICT("STRICT"), + SUBPARTITION("SUBPARTITION"), + SUBPARTITIONS("SUBPARTITIONS"), + SUBSTRING("SUBSTRING"), + SUCCESSFUL("SUCCESSFUL"), + SUSPEND("SUSPEND"), + SWITCHOVER("SWITCHOVER"), + SYNC("SYNC"), + SYSAUX("SYSAUX"), + SYSID("SYSID"), + SYSTEM("SYSTEM"), + T("T"), + TABLESPACE("TABLESPACE"), + TB("TB"), + TEMP("TEMP"), + TEMPFILE("TEMPFILE"), + TEMPLATE("TEMPLATE"), + TEMPORARY("TEMPORARY"), + TERMINATED("TERMINATED"), + THAN("THAN"), + TIMES("TIMES"), + TIMEZONE("TIMEZONE"), + TINYINT("TINYINT"), + TOAST("TOAST"), + TRACE("TRACE"), + TRACKING("TRACKING"), + TRAIL("TRAIL"), + TRAILING("TRAILING"), + TRANSACTION("TRANSACTION"), + TRANSACTIONAL("TRANSACTIONAL"), + TRANSFORMS("TRANSFORMS"), + TREAT("TREAT"), + TRIAL("TRIAL"), + TRIGGER("TRIGGER"), + TRIGGERS("TRIGGERS"), + TRIM("TRIM"), + TRUE("TRUE"), + TRUNCATE("TRUNCATE"), + TRUSTED("TRUSTED"), + TUPLE("TUPLE"), + TYPE("TYPE"), + UNBOUNDED("UNBOUNDED"), + UNCOMMITTED("UNCOMMITTED"), + UNDO("UNDO"), + UNENCRYPTED("UNENCRYPTED"), + UNKNOWN("UNKNOWN"), + UNLIMITED("UNLIMITED"), + UNLISTEN("UNLISTEN"), + UNLOCK("UNLOCK"), + UNMAINTENANCE("UNMAINTENANCE"), + UNPIVOT("UNPIVOT"), + UNSIGNED("UNSIGNED"), + UNTIL("UNTIL"), + UNUSABLE("UNUSABLE"), + UP("UP"), + UPDATE("UPDATE"), + UPDATELABEL("UPDATELABEL"), + UPDATEXML("UPDATEXML"), + USAGE("USAGE"), + USE("USE"), + USER("USER"), + UTF8("UTF8"), + UTF8MB4("UTF8MB4"), + VACUUM("VACUUM"), + VALID("VALID"), + VALIDATE("VALIDATE"), + VALIDATION("VALIDATION"), + VALIDATOR("VALIDATOR"), + VALUE("VALUE"), + VALUES("VALUES"), + VARBINARY("VARBINARY"), + VARBIT("VARBIT"), + VARCHAR("VARCHAR"), + VARCHAR2("VARCHAR2"), + VARYING("VARYING"), + VERBOSE("VERBOSE"), + VERSION("VERSION"), + VERSIONS("VERSIONS"), + VIEW("VIEW"), + VIRTUAL("VIRTUAL"), + VISIBLE("VISIBLE"), + VOLATILE("VOLATILE"), + VOTEDISK("VOTEDISK"), + WAIT("WAIT"), + WALLET("WALLET"), + WEIGHT("WEIGHT"), + WHEN("WHEN"), + WHENEVER("WHENEVER"), + WINDOW("WINDOW"), + WORK("WORK"), + XML("XML"), + XMLATTRIBUTES("XMLATTRIBUTES"), + XMLCONCAT("XMLCONCAT"), + XMLELEMENT("XMLELEMENT"), + XMLFOREST("XMLFOREST"), + XMLPARSE("XMLPARSE"), + XMLPI("XMLPI"), + XMLROOT("XMLROOT"), + XMLSERIALIZE("XMLSERIALIZE"), + XMLTABLE("XMLTABLE"), + YEAR("YEAR"), + YES("YES"), + ZONE("ZONE"); + /** + * The Name. + */ + public final String name; + OscarKeyword(String name) { + this.name = name; + } + } + + + @Override + public boolean checkIfKeyWords(String fieldOrTableName) { + if (keywordSet.contains(fieldOrTableName)) { + return true; + } + if (fieldOrTableName != null) { + fieldOrTableName = fieldOrTableName.toUpperCase(); + } + return keywordSet.contains(fieldOrTableName); + + } + + @Override + public boolean checkIfNeedEscape(String columnName, TableMeta tableMeta) { + if (StringUtils.isBlank(columnName)) { + return false; + } + columnName = columnName.trim(); + if (containsEscape(columnName)) { + return false; + } + boolean isKeyWord = checkIfKeyWords(columnName); + if (isKeyWord) { + return true; + } + // oscar + // we are recommend table name and column name must uppercase. + // if exists full uppercase, the table name or column name doesn't bundle escape symbol. + //create\read table TABLE "table" "TABLE" + if (null != tableMeta) { + ColumnMeta columnMeta = tableMeta.getColumnMeta(columnName); + if (null != columnMeta) { + return columnMeta.isCaseSensitive(); + } + } else if (isUppercase(columnName)) { + return false; + } + return true; + } + + private static boolean isUppercase(String fieldOrTableName) { + if (fieldOrTableName == null) { + return false; + } + char[] chars = fieldOrTableName.toCharArray(); + for (char ch : chars) { + if (ch >= 'a' && ch <= 'z') { + return false; + } + } + return true; + } +} diff --git a/rm-datasource/src/main/java/org/apache/seata/rm/datasource/sql/struct/cache/OscarTableMetaCache.java b/rm-datasource/src/main/java/org/apache/seata/rm/datasource/sql/struct/cache/OscarTableMetaCache.java new file mode 100644 index 00000000000..2bcb70a7032 --- /dev/null +++ b/rm-datasource/src/main/java/org/apache/seata/rm/datasource/sql/struct/cache/OscarTableMetaCache.java @@ -0,0 +1,198 @@ +/* + * Copyright 1999-2019 Seata.io Group. + * + * Licensed 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.seata.rm.datasource.sql.struct.cache; + +import org.apache.seata.common.exception.NotSupportYetException; +import org.apache.seata.common.exception.ShouldNeverHappenException; +import org.apache.seata.common.loader.LoadLevel; +import org.apache.seata.common.util.StringUtils; +import org.apache.seata.sqlparser.struct.ColumnMeta; +import org.apache.seata.sqlparser.struct.IndexMeta; +import org.apache.seata.sqlparser.struct.IndexType; +import org.apache.seata.sqlparser.struct.TableMeta; +import org.apache.seata.sqlparser.util.JdbcConstants; + +import java.sql.Connection; +import java.sql.DatabaseMetaData; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +/** + * The type Table meta cache. + * + * @author hsh + */ +@LoadLevel(name = JdbcConstants.OSCAR) +public class OscarTableMetaCache extends AbstractTableMetaCache { + + @Override + protected String getCacheKey(Connection connection, String tableName, String resourceId) { + StringBuilder cacheKey = new StringBuilder(resourceId); + cacheKey.append("."); + + //separate it to schemaName and tableName + String[] tableNameWithSchema = tableName.split("\\."); + String defaultTableName = tableNameWithSchema.length > 1 ? tableNameWithSchema[1] : tableNameWithSchema[0]; + + //oscar does not implement supportsMixedCaseIdentifiers in DatabaseMetadata + if (defaultTableName.contains("\"")) { + cacheKey.append(defaultTableName.replace("\"", "")); + } else { + // oscar default store in upper case + cacheKey.append(defaultTableName.toUpperCase()); + } + + return cacheKey.toString(); + } + + @Override + protected TableMeta fetchSchema(Connection connection, String tableName) throws SQLException { + try { + return resultSetMetaToSchema(connection.getMetaData(), tableName); + } catch (SQLException sqlEx) { + throw sqlEx; + } catch (Exception e) { + throw new SQLException(String.format("Failed to fetch schema of %s", tableName), e); + } + } + + private TableMeta resultSetMetaToSchema(DatabaseMetaData dbmd, String tableName) throws SQLException { + TableMeta tm = new TableMeta(); + tm.setTableName(tableName); + String[] schemaTable = tableName.split("\\."); + String schemaName = schemaTable.length > 1 ? schemaTable[0] : dbmd.getUserName(); + tableName = schemaTable.length > 1 ? schemaTable[1] : tableName; + if (schemaName.contains("\"")) { + schemaName = schemaName.replace("\"", ""); + } else { + schemaName = schemaName.toUpperCase(); + } + + if (tableName.contains("\"")) { + tableName = tableName.replace("\"", ""); + + } else { + tableName = tableName.toUpperCase(); + } + tm.setCaseSensitive(StringUtils.hasLowerCase(tableName)); + + try (ResultSet rsColumns = dbmd.getColumns("", schemaName, tableName, "%"); + ResultSet rsIndex = dbmd.getIndexInfo(null, schemaName, tableName, false, true); + ResultSet rsPrimary = dbmd.getPrimaryKeys(null, schemaName, tableName)) { + while (rsColumns.next()) { + ColumnMeta col = new ColumnMeta(); + col.setTableCat(rsColumns.getString("TABLE_CAT")); + col.setTableSchemaName(rsColumns.getString("TABLE_SCHEM")); + col.setTableName(rsColumns.getString("TABLE_NAME")); + col.setColumnName(rsColumns.getString("COLUMN_NAME")); + col.setDataType(rsColumns.getInt("DATA_TYPE")); + col.setDataTypeName(rsColumns.getString("TYPE_NAME")); + col.setColumnSize(rsColumns.getInt("COLUMN_SIZE")); + col.setDecimalDigits(rsColumns.getInt("DECIMAL_DIGITS")); + col.setNumPrecRadix(rsColumns.getInt("NUM_PREC_RADIX")); + col.setNullAble(rsColumns.getInt("NULLABLE")); + col.setRemarks(rsColumns.getString("REMARKS")); + col.setColumnDef(rsColumns.getString("COLUMN_DEF")); + col.setSqlDataType(rsColumns.getInt("SQL_DATA_TYPE")); + col.setSqlDatetimeSub(rsColumns.getInt("SQL_DATETIME_SUB")); + col.setCharOctetLength(rsColumns.getInt("CHAR_OCTET_LENGTH")); + col.setOrdinalPosition(rsColumns.getInt("ORDINAL_POSITION")); + col.setIsNullAble(rsColumns.getString("IS_NULLABLE")); + col.setCaseSensitive(StringUtils.hasLowerCase(col.getColumnName())); + + if (tm.getAllColumns().containsKey(col.getColumnName())) { + throw new NotSupportYetException("Not support the table has the same column name with different case yet"); + } + tm.getAllColumns().put(col.getColumnName(), col); + } + + while (rsIndex.next()) { + String indexName = rsIndex.getString("INDEX_NAME"); + if (StringUtils.isNullOrEmpty(indexName)) { + continue; + } + String colName = rsIndex.getString("COLUMN_NAME"); + ColumnMeta col = tm.getAllColumns().get(colName); + if (tm.getAllIndexes().containsKey(indexName)) { + IndexMeta index = tm.getAllIndexes().get(indexName); + index.getValues().add(col); + } else { + IndexMeta index = new IndexMeta(); + index.setIndexName(indexName); + index.setNonUnique(rsIndex.getBoolean("NON_UNIQUE")); + index.setIndexQualifier(rsIndex.getString("INDEX_QUALIFIER")); + index.setIndexName(rsIndex.getString("INDEX_NAME")); + index.setType(rsIndex.getShort("TYPE")); + index.setOrdinalPosition(rsIndex.getShort("ORDINAL_POSITION")); + index.setAscOrDesc(rsIndex.getString("ASC_OR_DESC")); + index.setCardinality(rsIndex.getLong("CARDINALITY")); + index.getValues().add(col); + if (!index.isNonUnique()) { + index.setIndextype(IndexType.UNIQUE); + } else { + index.setIndextype(IndexType.NORMAL); + } + tm.getAllIndexes().put(indexName, index); + + } + } + if (tm.getAllIndexes().isEmpty()) { + throw new ShouldNeverHappenException(String.format("Could not found any index in the table: %s", tableName)); + } + // when we create a primary key constraint oracle will uses and existing unique index. + // if we create a unique index before create a primary constraint in the same column will cause the problem + // that primary key constraint name was different from the unique name. + List pkcol = new ArrayList<>(); + while (rsPrimary.next()) { + String pkConstraintName = rsPrimary.getString("PK_NAME"); + if (tm.getAllIndexes().containsKey(pkConstraintName)) { + IndexMeta index = tm.getAllIndexes().get(pkConstraintName); + index.setIndextype(IndexType.PRIMARY); + } else { + //save the columns that constraint primary key name was different from unique index name + pkcol.add(rsPrimary.getString("COLUMN_NAME")); + } + } + //find the index that belong to the primary key constraint + if (!pkcol.isEmpty()) { + int matchCols = 0; + for (Map.Entry entry : tm.getAllIndexes().entrySet()) { + IndexMeta index = entry.getValue(); + // only the unique index and all the unique index's columes same as primary key columes, + // it belongs to primary key + if (index.getIndextype().value() == IndexType.UNIQUE.value()) { + for (ColumnMeta col : index.getValues()) { + if (pkcol.contains(col.getColumnName())) { + matchCols++; + } + } + if (matchCols == pkcol.size()) { + index.setIndextype(IndexType.PRIMARY); + // each table only has one primary key + break; + } else { + matchCols = 0; + } + } + } + } + } + return tm; + } +} diff --git a/rm-datasource/src/main/java/org/apache/seata/rm/datasource/undo/oscar/OscarUndoDeleteExecutor.java b/rm-datasource/src/main/java/org/apache/seata/rm/datasource/undo/oscar/OscarUndoDeleteExecutor.java new file mode 100644 index 00000000000..d41c32ea51d --- /dev/null +++ b/rm-datasource/src/main/java/org/apache/seata/rm/datasource/undo/oscar/OscarUndoDeleteExecutor.java @@ -0,0 +1,79 @@ +/* + * Copyright 1999-2019 Seata.io Group. + * + * Licensed 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.seata.rm.datasource.undo.oscar; + +import org.apache.seata.common.exception.ShouldNeverHappenException; +import org.apache.seata.common.util.CollectionUtils; +import org.apache.seata.rm.datasource.sql.struct.Field; +import org.apache.seata.rm.datasource.sql.struct.Row; +import org.apache.seata.rm.datasource.sql.struct.TableRecords; +import org.apache.seata.rm.datasource.undo.AbstractUndoExecutor; +import org.apache.seata.rm.datasource.undo.SQLUndoLog; +import org.apache.seata.sqlparser.util.ColumnUtils; +import org.apache.seata.sqlparser.util.JdbcConstants; + +import java.util.ArrayList; +import java.util.List; +import java.util.stream.Collectors; + +/** + * The type oscar undo delete executor. + * + * @author hsh + */ +public class OscarUndoDeleteExecutor extends AbstractUndoExecutor { + + /** + * INSERT INTO a (x, y, z, pk) VALUES (?, ?, ?, ?) + */ + private static final String INSERT_SQL_TEMPLATE = "INSERT INTO %s (%s) VALUES (%s)"; + + /** + * Instantiates a new oscar undo delete executor. + * + * @param sqlUndoLog the sql undo log + */ + public OscarUndoDeleteExecutor(SQLUndoLog sqlUndoLog) { + super(sqlUndoLog); + } + + @Override + protected String buildUndoSQL() { + TableRecords beforeImage = sqlUndoLog.getBeforeImage(); + List beforeImageRows = beforeImage.getRows(); + if (CollectionUtils.isEmpty(beforeImageRows)) { + throw new ShouldNeverHappenException("Invalid UNDO LOG"); + } + Row row = beforeImageRows.get(0); + List fields = new ArrayList<>(row.nonPrimaryKeys()); + fields.addAll(getOrderedPkList(beforeImage,row,JdbcConstants.ORACLE)); + + // delete sql undo log before image all field come from table meta, need add escape. + // see BaseTransactionalExecutor#buildTableRecords + String insertColumns = fields.stream() + .map(field -> ColumnUtils.addEscape(field.getName(), JdbcConstants.OSCAR)) + .collect(Collectors.joining(", ")); + String insertValues = fields.stream().map(field -> "?") + .collect(Collectors.joining(", ")); + + return String.format(INSERT_SQL_TEMPLATE, sqlUndoLog.getTableName(), insertColumns, insertValues); + } + + @Override + protected TableRecords getUndoRows() { + return sqlUndoLog.getBeforeImage(); + } +} diff --git a/rm-datasource/src/main/java/org/apache/seata/rm/datasource/undo/oscar/OscarUndoExecutorHolder.java b/rm-datasource/src/main/java/org/apache/seata/rm/datasource/undo/oscar/OscarUndoExecutorHolder.java new file mode 100644 index 00000000000..e0f83058e8a --- /dev/null +++ b/rm-datasource/src/main/java/org/apache/seata/rm/datasource/undo/oscar/OscarUndoExecutorHolder.java @@ -0,0 +1,46 @@ +/* + * Copyright 1999-2019 Seata.io Group. + * + * Licensed 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.seata.rm.datasource.undo.oscar; + +import org.apache.seata.common.loader.LoadLevel; +import org.apache.seata.rm.datasource.undo.AbstractUndoExecutor; +import org.apache.seata.rm.datasource.undo.SQLUndoLog; +import org.apache.seata.rm.datasource.undo.UndoExecutorHolder; +import org.apache.seata.sqlparser.util.JdbcConstants; + +/** + * The Type OscarUndoExecutorHolder + * + * @author Zhibei Hao + */ +@LoadLevel(name = JdbcConstants.OSCAR) +public class OscarUndoExecutorHolder implements UndoExecutorHolder { + + @Override + public AbstractUndoExecutor getInsertExecutor(SQLUndoLog sqlUndoLog) { + return new OscarUndoInsertExecutor(sqlUndoLog); + } + + @Override + public AbstractUndoExecutor getUpdateExecutor(SQLUndoLog sqlUndoLog) { + return new OscarUndoUpdateExecutor(sqlUndoLog); + } + + @Override + public AbstractUndoExecutor getDeleteExecutor(SQLUndoLog sqlUndoLog) { + return new OscarUndoDeleteExecutor(sqlUndoLog); + } +} diff --git a/rm-datasource/src/main/java/org/apache/seata/rm/datasource/undo/oscar/OscarUndoInsertExecutor.java b/rm-datasource/src/main/java/org/apache/seata/rm/datasource/undo/oscar/OscarUndoInsertExecutor.java new file mode 100644 index 00000000000..64261f80562 --- /dev/null +++ b/rm-datasource/src/main/java/org/apache/seata/rm/datasource/undo/oscar/OscarUndoInsertExecutor.java @@ -0,0 +1,86 @@ +/* + * Copyright 1999-2019 Seata.io Group. + * + * Licensed 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.seata.rm.datasource.undo.oscar; + +import org.apache.seata.common.exception.ShouldNeverHappenException; +import org.apache.seata.common.util.CollectionUtils; +import org.apache.seata.rm.datasource.SqlGenerateUtils; +import org.apache.seata.rm.datasource.sql.struct.Field; +import org.apache.seata.rm.datasource.sql.struct.Row; +import org.apache.seata.rm.datasource.sql.struct.TableRecords; +import org.apache.seata.rm.datasource.undo.AbstractUndoExecutor; +import org.apache.seata.rm.datasource.undo.SQLUndoLog; +import org.apache.seata.sqlparser.util.JdbcConstants; + +import java.sql.PreparedStatement; +import java.sql.SQLException; +import java.util.ArrayList; +import java.util.List; +import java.util.stream.Collectors; + +/** + * The type oscar undo insert executor. + * + * @author hsh + */ +public class OscarUndoInsertExecutor extends AbstractUndoExecutor { + + /** + * DELETE FROM a WHERE pk = ? + */ + private static final String DELETE_SQL_TEMPLATE = "DELETE FROM %s WHERE %s "; + + @Override + protected String buildUndoSQL() { + TableRecords afterImage = sqlUndoLog.getAfterImage(); + List afterImageRows = afterImage.getRows(); + if (CollectionUtils.isEmpty(afterImageRows)) { + throw new ShouldNeverHappenException("Invalid UNDO LOG"); + } + return generateDeleteSql(afterImageRows,afterImage); + } + + @Override + protected void undoPrepare(PreparedStatement undoPST, ArrayList undoValues, List pkValueList) + throws SQLException { + int undoIndex = 0; + for (Field pkField:pkValueList) { + undoIndex++; + undoPST.setObject(undoIndex, pkField.getValue(), pkField.getType()); + } + } + + private String generateDeleteSql(List rows, TableRecords afterImage) { + List pkNameList = getOrderedPkList(afterImage, rows.get(0), JdbcConstants.OSCAR).stream().map( + e -> e.getName()).collect(Collectors.toList()); + String whereSql = SqlGenerateUtils.buildWhereConditionByPKs(pkNameList, JdbcConstants.OSCAR); + return String.format(DELETE_SQL_TEMPLATE, sqlUndoLog.getTableName(), whereSql); + } + + /** + * Instantiates a new Oscar undo insert executor. + * + * @param sqlUndoLog the sql undo log + */ + public OscarUndoInsertExecutor(SQLUndoLog sqlUndoLog) { + super(sqlUndoLog); + } + + @Override + protected TableRecords getUndoRows() { + return sqlUndoLog.getAfterImage(); + } +} diff --git a/rm-datasource/src/main/java/org/apache/seata/rm/datasource/undo/oscar/OscarUndoLogManager.java b/rm-datasource/src/main/java/org/apache/seata/rm/datasource/undo/oscar/OscarUndoLogManager.java new file mode 100644 index 00000000000..35d4d30b44c --- /dev/null +++ b/rm-datasource/src/main/java/org/apache/seata/rm/datasource/undo/oscar/OscarUndoLogManager.java @@ -0,0 +1,105 @@ +/* + * Copyright 1999-2019 Seata.io Group. + * + * Licensed 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.seata.rm.datasource.undo.oscar; + +import org.apache.seata.common.loader.LoadLevel; +import org.apache.seata.common.util.DateUtil; +import org.apache.seata.core.compressor.CompressorType; +import org.apache.seata.core.constants.ClientTableColumnsName; +import org.apache.seata.rm.datasource.undo.AbstractUndoLogManager; +import org.apache.seata.rm.datasource.undo.UndoLogParser; +import org.apache.seata.sqlparser.util.JdbcConstants; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.sql.Connection; +import java.sql.PreparedStatement; +import java.sql.SQLException; +import java.util.Date; + +/** + * @author hsh + */ +@LoadLevel(name = JdbcConstants.OSCAR) +public class OscarUndoLogManager extends AbstractUndoLogManager { + + private static final Logger LOGGER = LoggerFactory.getLogger(OscarUndoLogManager.class); + + private static final String CHECK_UNDO_LOG_TABLE_EXIST_SQL = "SELECT 1 FROM " + UNDO_LOG_TABLE_NAME + " WHERE ROWNUM = 1"; + + private static final String INSERT_UNDO_LOG_SQL = "INSERT INTO " + UNDO_LOG_TABLE_NAME + + " (" + ClientTableColumnsName.UNDO_LOG_ID + "," + ClientTableColumnsName.UNDO_LOG_BRANCH_XID + ", " + + ClientTableColumnsName.UNDO_LOG_XID + ", " + ClientTableColumnsName.UNDO_LOG_CONTEXT + ", " + + ClientTableColumnsName.UNDO_LOG_ROLLBACK_INFO + ", " + ClientTableColumnsName.UNDO_LOG_LOG_STATUS + ", " + + ClientTableColumnsName.UNDO_LOG_LOG_CREATED + ", " + ClientTableColumnsName.UNDO_LOG_LOG_MODIFIED + ")" + + "VALUES (UNDO_LOG_SEQ.nextval, ?, ?, ?, ?, ?, sysdate, sysdate)"; + + private static final String DELETE_UNDO_LOG_BY_CREATE_SQL = "DELETE FROM " + UNDO_LOG_TABLE_NAME + " WHERE " + ClientTableColumnsName.UNDO_LOG_LOG_CREATED + " <= to_date(?,'yyyy-mm-dd hh24:mi:ss') and ROWNUM <= ?"; + + @Override + public int deleteUndoLogByLogCreated(Date logCreated, int limitRows, Connection conn) throws SQLException { + try (PreparedStatement deletePST = conn.prepareStatement(DELETE_UNDO_LOG_BY_CREATE_SQL)) { + String dateStr = DateUtil.formatDate(logCreated, "yyyy-MM-dd HH:mm:ss"); + deletePST.setString(1, dateStr); + deletePST.setInt(2, limitRows); + int deleteRows = deletePST.executeUpdate(); + if (LOGGER.isDebugEnabled()) { + LOGGER.debug("batch delete undo log size {}", deleteRows); + } + return deleteRows; + } catch (Exception e) { + if (!(e instanceof SQLException)) { + e = new SQLException(e); + } + throw (SQLException) e; + } + } + + @Override + protected void insertUndoLogWithNormal(String xid, long branchId, String rollbackCtx, byte[] undoLogContent, + Connection conn) throws SQLException { + insertUndoLog(xid, branchId,rollbackCtx, undoLogContent, State.Normal, conn); + } + + @Override + protected void insertUndoLogWithGlobalFinished(String xid, long branchId, UndoLogParser parser, Connection conn) throws SQLException { + insertUndoLog(xid, branchId, buildContext(parser.getName(), CompressorType.NONE), parser.getDefaultContent(), + State.GlobalFinished, conn); + } + + + private void insertUndoLog(String xid, long branchID, String rollbackCtx, byte[] undoLogContent, + State state, Connection conn) throws SQLException { + try (PreparedStatement pst = conn.prepareStatement(INSERT_UNDO_LOG_SQL)) { + pst.setLong(1, branchID); + pst.setString(2, xid); + pst.setString(3, rollbackCtx); + pst.setBytes(4, undoLogContent); + pst.setInt(5, state.getValue()); + pst.executeUpdate(); + } catch (Exception e) { + if (!(e instanceof SQLException)) { + e = new SQLException(e); + } + throw (SQLException) e; + } + } + + @Override + protected String getCheckUndoLogTableExistSql() { + return CHECK_UNDO_LOG_TABLE_EXIST_SQL; + } +} diff --git a/rm-datasource/src/main/java/org/apache/seata/rm/datasource/undo/oscar/OscarUndoUpdateExecutor.java b/rm-datasource/src/main/java/org/apache/seata/rm/datasource/undo/oscar/OscarUndoUpdateExecutor.java new file mode 100644 index 00000000000..bb9321e28ba --- /dev/null +++ b/rm-datasource/src/main/java/org/apache/seata/rm/datasource/undo/oscar/OscarUndoUpdateExecutor.java @@ -0,0 +1,80 @@ +/* + * Copyright 1999-2019 Seata.io Group. + * + * Licensed 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.seata.rm.datasource.undo.oscar; + +import org.apache.seata.common.exception.ShouldNeverHappenException; +import org.apache.seata.common.util.CollectionUtils; +import org.apache.seata.rm.datasource.SqlGenerateUtils; +import org.apache.seata.rm.datasource.sql.struct.Field; +import org.apache.seata.rm.datasource.sql.struct.Row; +import org.apache.seata.rm.datasource.sql.struct.TableRecords; +import org.apache.seata.rm.datasource.undo.AbstractUndoExecutor; +import org.apache.seata.rm.datasource.undo.SQLUndoLog; +import org.apache.seata.sqlparser.util.ColumnUtils; +import org.apache.seata.sqlparser.util.JdbcConstants; + +import java.util.List; +import java.util.stream.Collectors; + +/** + * The type oscar undo update executor. + * + * @author hsh + */ +public class OscarUndoUpdateExecutor extends AbstractUndoExecutor { + + /** + * UPDATE a SET x = ?, y = ?, z = ? WHERE pk1 = ? and pk2 = ? + */ + private static final String UPDATE_SQL_TEMPLATE = "UPDATE %s SET %s WHERE %s "; + + @Override + protected String buildUndoSQL() { + TableRecords beforeImage = sqlUndoLog.getBeforeImage(); + List beforeImageRows = beforeImage.getRows(); + if (CollectionUtils.isEmpty(beforeImageRows)) { + throw new ShouldNeverHappenException("Invalid UNDO LOG"); + } + Row row = beforeImageRows.get(0); + + List nonPkFields = row.nonPrimaryKeys(); + // update sql undo log before image all field come from table meta. need add escape. + // see BaseTransactionalExecutor#buildTableRecords + String updateColumns = nonPkFields.stream().map( + field -> ColumnUtils.addEscape(field.getName(), JdbcConstants.ORACLE) + " = ?").collect( + Collectors.joining(", ")); + + List pkNameList = getOrderedPkList(beforeImage, row, JdbcConstants.ORACLE).stream().map( + e -> e.getName()).collect(Collectors.toList()); + String whereSql = SqlGenerateUtils.buildWhereConditionByPKs(pkNameList, JdbcConstants.ORACLE); + + return String.format(UPDATE_SQL_TEMPLATE, sqlUndoLog.getTableName(), updateColumns, whereSql); + } + + /** + * Instantiates a new Oscar undo update executor. + * + * @param sqlUndoLog the sql undo log + */ + public OscarUndoUpdateExecutor(SQLUndoLog sqlUndoLog) { + super(sqlUndoLog); + } + + @Override + protected TableRecords getUndoRows() { + return sqlUndoLog.getBeforeImage(); + } +} diff --git a/rm-datasource/src/main/resources/META-INF/services/org.apache.seata.rm.datasource.exec.InsertExecutor b/rm-datasource/src/main/resources/META-INF/services/org.apache.seata.rm.datasource.exec.InsertExecutor index f928928e1dd..ba9cd4f2560 100644 --- a/rm-datasource/src/main/resources/META-INF/services/org.apache.seata.rm.datasource.exec.InsertExecutor +++ b/rm-datasource/src/main/resources/META-INF/services/org.apache.seata.rm.datasource.exec.InsertExecutor @@ -20,4 +20,5 @@ org.apache.seata.rm.datasource.exec.postgresql.PostgresqlInsertExecutor org.apache.seata.rm.datasource.exec.sqlserver.SqlServerInsertExecutor org.apache.seata.rm.datasource.exec.mariadb.MariadbInsertExecutor org.apache.seata.rm.datasource.exec.polardbx.PolarDBXInsertExecutor -org.apache.seata.rm.datasource.exec.dm.DmInsertExecutor \ No newline at end of file +org.apache.seata.rm.datasource.exec.dm.DmInsertExecutor +org.apache.seata.rm.datasource.exec.oscar.OscarInsertExecutor \ No newline at end of file diff --git a/rm-datasource/src/main/resources/META-INF/services/org.apache.seata.rm.datasource.undo.UndoExecutorHolder b/rm-datasource/src/main/resources/META-INF/services/org.apache.seata.rm.datasource.undo.UndoExecutorHolder index 4bad8e9af02..745542f09fc 100644 --- a/rm-datasource/src/main/resources/META-INF/services/org.apache.seata.rm.datasource.undo.UndoExecutorHolder +++ b/rm-datasource/src/main/resources/META-INF/services/org.apache.seata.rm.datasource.undo.UndoExecutorHolder @@ -20,4 +20,5 @@ org.apache.seata.rm.datasource.undo.postgresql.PostgresqlUndoExecutorHolder org.apache.seata.rm.datasource.undo.sqlserver.SqlServerUndoExecutorHolder org.apache.seata.rm.datasource.undo.mariadb.MariadbUndoExecutorHolder org.apache.seata.rm.datasource.undo.polardbx.PolarDBXUndoExecutorHolder -org.apache.seata.rm.datasource.undo.dm.DmUndoExecutorHolder \ No newline at end of file +org.apache.seata.rm.datasource.undo.dm.DmUndoExecutorHolder +org.apache.seata.rm.datasource.undo.oscar.OscarUndoExecutorHolder \ No newline at end of file diff --git a/rm-datasource/src/main/resources/META-INF/services/org.apache.seata.rm.datasource.undo.UndoLogManager b/rm-datasource/src/main/resources/META-INF/services/org.apache.seata.rm.datasource.undo.UndoLogManager index a18cb71ab84..8cec7126daf 100644 --- a/rm-datasource/src/main/resources/META-INF/services/org.apache.seata.rm.datasource.undo.UndoLogManager +++ b/rm-datasource/src/main/resources/META-INF/services/org.apache.seata.rm.datasource.undo.UndoLogManager @@ -20,4 +20,5 @@ org.apache.seata.rm.datasource.undo.postgresql.PostgresqlUndoLogManager org.apache.seata.rm.datasource.undo.sqlserver.SqlServerUndoLogManager org.apache.seata.rm.datasource.undo.mariadb.MariadbUndoLogManager org.apache.seata.rm.datasource.undo.polardbx.PolarDBXUndoLogManager -org.apache.seata.rm.datasource.undo.dm.DmUndoLogManager \ No newline at end of file +org.apache.seata.rm.datasource.undo.dm.DmUndoLogManager +org.apache.seata.rm.datasource.undo.oscar.OscarUndoLogManager \ No newline at end of file diff --git a/rm-datasource/src/main/resources/META-INF/services/org.apache.seata.sqlparser.EscapeHandler b/rm-datasource/src/main/resources/META-INF/services/org.apache.seata.sqlparser.EscapeHandler index c4f82c85498..c432d7c5ad1 100644 --- a/rm-datasource/src/main/resources/META-INF/services/org.apache.seata.sqlparser.EscapeHandler +++ b/rm-datasource/src/main/resources/META-INF/services/org.apache.seata.sqlparser.EscapeHandler @@ -20,4 +20,5 @@ org.apache.seata.rm.datasource.sql.handler.postgresql.PostgresqlEscapeHandler org.apache.seata.rm.datasource.sql.handler.mariadb.MariadbEscapeHandler org.apache.seata.rm.datasource.sql.handler.sqlserver.SqlServerEscapeHandler org.apache.seata.rm.datasource.sql.handler.polardbx.PolarDBXEscapeHandler -org.apache.seata.rm.datasource.sql.handler.dm.DmEscapeHandler \ No newline at end of file +org.apache.seata.rm.datasource.sql.handler.dm.DmEscapeHandler +org.apache.seata.rm.datasource.sql.handler.oscar.OscarEscapeHandler \ No newline at end of file diff --git a/rm-datasource/src/main/resources/META-INF/services/org.apache.seata.sqlparser.struct.TableMetaCache b/rm-datasource/src/main/resources/META-INF/services/org.apache.seata.sqlparser.struct.TableMetaCache index 1b09044c0f6..73762618efc 100644 --- a/rm-datasource/src/main/resources/META-INF/services/org.apache.seata.sqlparser.struct.TableMetaCache +++ b/rm-datasource/src/main/resources/META-INF/services/org.apache.seata.sqlparser.struct.TableMetaCache @@ -20,4 +20,5 @@ org.apache.seata.rm.datasource.sql.struct.cache.PostgresqlTableMetaCache org.apache.seata.rm.datasource.sql.struct.cache.SqlServerTableMetaCache org.apache.seata.rm.datasource.sql.struct.cache.MariadbTableMetaCache org.apache.seata.rm.datasource.sql.struct.cache.PolarDBXTableMetaCache -org.apache.seata.rm.datasource.sql.struct.cache.DmTableMetaCache \ No newline at end of file +org.apache.seata.rm.datasource.sql.struct.cache.DmTableMetaCache +org.apache.seata.rm.datasource.sql.struct.cache.OscarTableMetaCache \ No newline at end of file diff --git a/rm-datasource/src/test/java/org/apache/seata/rm/datasource/exec/OscarInsertExecutorTest.java b/rm-datasource/src/test/java/org/apache/seata/rm/datasource/exec/OscarInsertExecutorTest.java new file mode 100644 index 00000000000..40439c101b3 --- /dev/null +++ b/rm-datasource/src/test/java/org/apache/seata/rm/datasource/exec/OscarInsertExecutorTest.java @@ -0,0 +1,445 @@ +/* + * Copyright 1999-2019 Seata.io Group. + * + * Licensed 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.seata.rm.datasource.exec; + +import org.apache.seata.common.exception.NotSupportYetException; +import org.apache.seata.rm.datasource.ConnectionProxy; +import org.apache.seata.rm.datasource.PreparedStatementProxy; +import org.apache.seata.rm.datasource.StatementProxy; +import org.apache.seata.rm.datasource.exec.oscar.OscarInsertExecutor; +import org.apache.seata.sqlparser.SQLInsertRecognizer; +import org.apache.seata.sqlparser.struct.ColumnMeta; +import org.apache.seata.sqlparser.struct.Null; +import org.apache.seata.sqlparser.struct.SqlSequenceExpr; +import org.apache.seata.sqlparser.struct.TableMeta; +import org.apache.seata.sqlparser.util.JdbcConstants; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.mockito.Mockito; + +import java.sql.ResultSet; +import java.sql.SQLException; +import java.util.*; + +import static org.mockito.Mockito.*; + +/** + * @author hsh + */ +public class OscarInsertExecutorTest { + + private static final String ID_COLUMN = "id"; + private static final String USER_ID_COLUMN = "user_id"; + private static final String USER_NAME_COLUMN = "user_name"; + private static final String USER_STATUS_COLUMN = "user_status"; + private static final Integer PK_VALUE_ID = 100; + private static final Integer PK_VALUE_USER_ID = 200; + + private ConnectionProxy connectionProxy; + + private StatementProxy statementProxy; + + private SQLInsertRecognizer sqlInsertRecognizer; + + private StatementCallback statementCallback; + + private TableMeta tableMeta; + + private OscarInsertExecutor insertExecutor; + + private final int pkIndexId = 0; + + private final int pkIndexUserId = 1; + + private HashMap pkIndexMap; + + private HashMap multiPkIndexMap; + + @BeforeEach + public void init() { + connectionProxy = mock(ConnectionProxy.class); + when(connectionProxy.getDbType()).thenReturn(JdbcConstants.OSCAR); + + statementProxy = mock(PreparedStatementProxy.class); + when(statementProxy.getConnectionProxy()).thenReturn(connectionProxy); + + statementCallback = mock(StatementCallback.class); + sqlInsertRecognizer = mock(SQLInsertRecognizer.class); + tableMeta = mock(TableMeta.class); + insertExecutor = Mockito.spy(new OscarInsertExecutor(statementProxy, statementCallback, sqlInsertRecognizer)); + + pkIndexMap = new HashMap() {{ + put(ID_COLUMN, pkIndexId); + }}; + + multiPkIndexMap = new HashMap() {{ + put(ID_COLUMN, pkIndexId); + put(USER_ID_COLUMN, pkIndexUserId); + }}; + } + + @Test + public void testPkValue_sequence() throws Exception { + mockInsertColumns(); + SqlSequenceExpr expr = mockParametersPkWithSeq(); + doReturn(tableMeta).when(insertExecutor).getTableMeta(); + when(tableMeta.getPrimaryKeyOnlyName()).thenReturn(Arrays.asList(new String[]{ID_COLUMN})); + List pkValuesSeq = new ArrayList<>(); + pkValuesSeq.add(PK_VALUE_ID); + + doReturn(pkValuesSeq).when(insertExecutor).getPkValuesBySequence(expr, ID_COLUMN); + doReturn(pkIndexMap).when(insertExecutor).getPkIndex(); + + Map> pkValuesByColumn = insertExecutor.getPkValuesByColumn(); + verify(insertExecutor).getPkValuesBySequence(expr, ID_COLUMN); + Assertions.assertEquals(pkValuesByColumn.get(ID_COLUMN), pkValuesSeq); + } + + @Test + public void testMultiPkValue_sequence() throws Exception { + mockInsertColumns(); + SqlSequenceExpr expr = mockParametersMultiPkWithSeq(); + doReturn(tableMeta).when(insertExecutor).getTableMeta(); + when(tableMeta.getPrimaryKeyOnlyName()).thenReturn(Arrays.asList(new String[]{ID_COLUMN, USER_ID_COLUMN})); + List pkValuesSeqId = new ArrayList<>(); + pkValuesSeqId.add(PK_VALUE_ID); + List pkValuesSeqUserId = new ArrayList<>(); + pkValuesSeqUserId.add(PK_VALUE_USER_ID); + + doReturn(pkValuesSeqId).when(insertExecutor).getPkValuesBySequence(expr, ID_COLUMN); + doReturn(pkValuesSeqUserId).when(insertExecutor).getPkValuesBySequence(expr, USER_ID_COLUMN); + doReturn(multiPkIndexMap).when(insertExecutor).getPkIndex(); + + Map> pkValuesByColumn = insertExecutor.getPkValuesByColumn(); + verify(insertExecutor).getPkValuesBySequence(expr, ID_COLUMN); + verify(insertExecutor).getPkValuesBySequence(expr, USER_ID_COLUMN); + Assertions.assertEquals(pkValuesByColumn.get(ID_COLUMN), pkValuesSeqId); + Assertions.assertEquals(pkValuesByColumn.get(USER_ID_COLUMN), pkValuesSeqUserId); + } + + @Test + public void testPkValue_auto() throws Exception { + mockInsertColumns(); + mockParametersPkWithAuto(); + doReturn(tableMeta).when(insertExecutor).getTableMeta(); + doReturn(pkIndexMap).when(insertExecutor).getPkIndex(); + when(tableMeta.getPrimaryKeyOnlyName()).thenReturn(Arrays.asList(new String[]{ID_COLUMN})); + doReturn(Arrays.asList(new Object[]{PK_VALUE_ID})).when(insertExecutor).getGeneratedKeys(ID_COLUMN); + Map> pkValuesByAuto = insertExecutor.getPkValues(); + + verify(insertExecutor).getGeneratedKeys(ID_COLUMN); + Assertions.assertEquals(pkValuesByAuto.get(ID_COLUMN), Arrays.asList(new Object[]{PK_VALUE_ID})); + } + + @Test + public void testMultiPkValue_auto() throws Exception { + mockInsertColumns(); + mockParametersMultiPkWithAuto(); + doReturn(tableMeta).when(insertExecutor).getTableMeta(); + doReturn(multiPkIndexMap).when(insertExecutor).getPkIndex(); + when(tableMeta.getPrimaryKeyOnlyName()).thenReturn(Arrays.asList(new String[]{ID_COLUMN, USER_ID_COLUMN})); + Assertions.assertThrows(NotSupportYetException.class, () -> { + insertExecutor.getPkValues(); + }); + + + } + + @Test + public void testStatement_pkValueByAuto_NotSupportYetException() throws Exception { + mockInsertColumns(); + mockStatementInsertRows(); + + statementProxy = mock(StatementProxy.class); + when(statementProxy.getConnectionProxy()).thenReturn(connectionProxy); + when(connectionProxy.getDbType()).thenReturn(JdbcConstants.ORACLE); + + insertExecutor = Mockito.spy(new OscarInsertExecutor(statementProxy, statementCallback, sqlInsertRecognizer)); + + doReturn(tableMeta).when(insertExecutor).getTableMeta(); + + Map map = new HashMap<>(); + map.put(ID_COLUMN, mock(ColumnMeta.class)); + doReturn(map).when(tableMeta).getPrimaryKeyMap(); + + ResultSet rs = mock(ResultSet.class); + doReturn(rs).when(statementProxy).getGeneratedKeys(); + doReturn(false).when(rs).next(); + + Assertions.assertThrows(NotSupportYetException.class, () -> { + insertExecutor.getGeneratedKeys(ID_COLUMN); + }); + + doReturn(pkIndexMap).when(insertExecutor).getPkIndex(); + + Assertions.assertThrows(NotSupportYetException.class, () -> { + insertExecutor.getPkValuesByColumn(); + }); + + } + + @Test + public void testGetPkValues_SinglePk() throws SQLException { + doReturn(tableMeta).when(insertExecutor).getTableMeta(); + + List pkColumns = new ArrayList<>(); + pkColumns.add(ID_COLUMN); + doReturn(pkColumns).when(tableMeta).getPrimaryKeyOnlyName(); + + // mock pk values from insert rows + Map> mockPkValuesFromColumn = new HashMap<>(); + mockPkValuesFromColumn.put(ID_COLUMN, Collections.singletonList(PK_VALUE_ID + 1)); + doReturn(mockPkValuesFromColumn).when(insertExecutor).getPkValuesByColumn(); + + // mock pk values from auto increment + List mockPkValuesAutoGenerated = Collections.singletonList(PK_VALUE_ID); + doReturn(mockPkValuesAutoGenerated).when(insertExecutor).getGeneratedKeys(ID_COLUMN); + + // situation1: insert columns are empty + List columns = new ArrayList<>(); + when(sqlInsertRecognizer.getInsertColumns()).thenReturn(columns); + when(sqlInsertRecognizer.insertColumnsIsEmpty()).thenReturn(true); + Assertions.assertIterableEquals(mockPkValuesFromColumn.entrySet(), insertExecutor.getPkValues().entrySet()); + + // situation2: insert columns contain the pk column + columns = new ArrayList<>(); + columns.add(ID_COLUMN); + columns.add(USER_NAME_COLUMN); + when(sqlInsertRecognizer.getInsertColumns()).thenReturn(columns); + when(sqlInsertRecognizer.insertColumnsIsEmpty()).thenReturn(false); + Assertions.assertIterableEquals(mockPkValuesFromColumn.entrySet(), insertExecutor.getPkValues().entrySet()); + + // situation3: insert columns are not empty and do not contain the pk column + columns = new ArrayList<>(); + columns.add(USER_NAME_COLUMN); + when(sqlInsertRecognizer.getInsertColumns()).thenReturn(columns); + when(sqlInsertRecognizer.insertColumnsIsEmpty()).thenReturn(false); + Assertions.assertIterableEquals( + Collections.singletonMap(ID_COLUMN, mockPkValuesAutoGenerated).entrySet(), + insertExecutor.getPkValues().entrySet()); + } + + @Test + public void testGetPkValues_MultiPk() throws SQLException { + doReturn(tableMeta).when(insertExecutor).getTableMeta(); + + List pkColumns = new ArrayList<>(); + pkColumns.add(ID_COLUMN); + pkColumns.add(USER_ID_COLUMN); + doReturn(pkColumns).when(tableMeta).getPrimaryKeyOnlyName(); + + // mock all pk values from insert rows + Map> mockAllPkValuesFromColumn = new HashMap<>(); + mockAllPkValuesFromColumn.put(ID_COLUMN, Collections.singletonList(PK_VALUE_ID + 1)); + mockAllPkValuesFromColumn.put(USER_ID_COLUMN, Collections.singletonList(PK_VALUE_USER_ID + 1)); + doReturn(mockAllPkValuesFromColumn).when(insertExecutor).getPkValuesByColumn(); + + // mock pk values from auto increment + List mockPkValuesAutoGenerated_ID = Collections.singletonList(PK_VALUE_ID); + doReturn(mockPkValuesAutoGenerated_ID).when(insertExecutor).getGeneratedKeys(ID_COLUMN); + List mockPkValuesAutoGenerated_USER_ID = Collections.singletonList(PK_VALUE_USER_ID); + doReturn(mockPkValuesAutoGenerated_USER_ID).when(insertExecutor).getGeneratedKeys(USER_ID_COLUMN); + + // situation1: insert columns are empty + List insertColumns = new ArrayList<>(); + when(sqlInsertRecognizer.getInsertColumns()).thenReturn(insertColumns); + when(sqlInsertRecognizer.insertColumnsIsEmpty()).thenReturn(true); + Assertions.assertIterableEquals(mockAllPkValuesFromColumn.entrySet(), insertExecutor.getPkValues().entrySet()); + + // situation2: insert columns contain all pk columns + insertColumns = new ArrayList<>(); + insertColumns.add(ID_COLUMN); + insertColumns.add(USER_ID_COLUMN); + insertColumns.add(USER_NAME_COLUMN); + when(sqlInsertRecognizer.getInsertColumns()).thenReturn(insertColumns); + when(sqlInsertRecognizer.insertColumnsIsEmpty()).thenReturn(false); + Assertions.assertIterableEquals(mockAllPkValuesFromColumn.entrySet(), insertExecutor.getPkValues().entrySet()); + + // situation3: insert columns contain partial pk columns + insertColumns = new ArrayList<>(); + insertColumns.add(ID_COLUMN); + insertColumns.add(USER_NAME_COLUMN); + when(sqlInsertRecognizer.getInsertColumns()).thenReturn(insertColumns); + when(sqlInsertRecognizer.insertColumnsIsEmpty()).thenReturn(false); + + Map> mockPkValuesFromColumn_ID = new HashMap<>(); + mockPkValuesFromColumn_ID.put(ID_COLUMN, Collections.singletonList(PK_VALUE_ID + 1)); + doReturn(mockPkValuesFromColumn_ID).when(insertExecutor).getPkValuesByColumn(); + + Map> expectPkValues = new HashMap<>(mockPkValuesFromColumn_ID); + expectPkValues.put(USER_ID_COLUMN, mockPkValuesAutoGenerated_USER_ID); + Assertions.assertIterableEquals(expectPkValues.entrySet(), insertExecutor.getPkValues().entrySet()); + + // situation4: insert columns are not empty and do not contain the pk column + insertColumns = new ArrayList<>(); + insertColumns.add(USER_NAME_COLUMN); + when(sqlInsertRecognizer.getInsertColumns()).thenReturn(insertColumns); + when(sqlInsertRecognizer.insertColumnsIsEmpty()).thenReturn(false); + + doReturn(new HashMap<>()).when(insertExecutor).getPkValuesByColumn(); + + expectPkValues = new HashMap<>(); + expectPkValues.put(ID_COLUMN, mockPkValuesAutoGenerated_ID); + expectPkValues.put(USER_ID_COLUMN, mockPkValuesAutoGenerated_USER_ID); + Assertions.assertIterableEquals(expectPkValues.entrySet(), insertExecutor.getPkValues().entrySet()); + } + + @Test + public void testContainsAnyPK() { + doReturn(tableMeta).when(insertExecutor).getTableMeta(); + + Assertions.assertFalse(insertExecutor.containsAnyPk()); + + mockInsertColumns(); + doReturn(null).when(tableMeta).getPrimaryKeyOnlyName(); + Assertions.assertFalse(insertExecutor.containsAnyPk()); + + List pkColumns = new ArrayList<>(); + pkColumns.add(System.currentTimeMillis() + ""); + doReturn(pkColumns).when(tableMeta).getPrimaryKeyOnlyName(); + Assertions.assertFalse(insertExecutor.containsAnyPk()); + + pkColumns = new ArrayList<>(); + pkColumns.add(ID_COLUMN); + doReturn(pkColumns).when(tableMeta).getPrimaryKeyOnlyName(); + Assertions.assertTrue(insertExecutor.containsAnyPk()); + + pkColumns = new ArrayList<>(); + pkColumns.add(ID_COLUMN); + pkColumns.add(USER_ID_COLUMN); + doReturn(pkColumns).when(tableMeta).getPrimaryKeyOnlyName(); + Assertions.assertTrue(insertExecutor.containsAnyPk()); + + pkColumns = new ArrayList<>(); + pkColumns.add(ID_COLUMN); + pkColumns.add(System.currentTimeMillis() + ""); + doReturn(pkColumns).when(tableMeta).getPrimaryKeyOnlyName(); + Assertions.assertTrue(insertExecutor.containsAnyPk()); + } + + private List mockInsertColumns() { + List columns = new ArrayList<>(); + columns.add(ID_COLUMN); + columns.add(USER_ID_COLUMN); + columns.add(USER_NAME_COLUMN); + columns.add(USER_STATUS_COLUMN); + when(sqlInsertRecognizer.getInsertColumns()).thenReturn(columns); + return columns; + } + + private SqlSequenceExpr mockParametersPkWithSeq() { + SqlSequenceExpr expr = new SqlSequenceExpr("seq", "nextval"); + Map> paramters = new HashMap(4); + ArrayList arrayList0 = new ArrayList<>(); + arrayList0.add(expr); + ArrayList arrayList1 = new ArrayList<>(); + arrayList1.add("userId1"); + ArrayList arrayList2 = new ArrayList<>(); + arrayList2.add("userName1"); + ArrayList arrayList3 = new ArrayList<>(); + arrayList3.add("userStatus1"); + paramters.put(1, arrayList0); + paramters.put(2, arrayList1); + paramters.put(3, arrayList2); + paramters.put(4, arrayList3); + PreparedStatementProxy psp = (PreparedStatementProxy) this.statementProxy; + when(psp.getParameters()).thenReturn(paramters); + + List> rows = new ArrayList<>(); + rows.add(Arrays.asList("?", "?", "?")); + when(sqlInsertRecognizer.getInsertRows(pkIndexMap.values())).thenReturn(rows); + + return expr; + } + + private SqlSequenceExpr mockParametersMultiPkWithSeq() { + SqlSequenceExpr expr = new SqlSequenceExpr("seq", "nextval"); + Map> paramters = new HashMap(4); + ArrayList arrayList0 = new ArrayList<>(); + arrayList0.add(expr); + ArrayList arrayList1 = new ArrayList<>(); + arrayList1.add(expr); + ArrayList arrayList2 = new ArrayList<>(); + arrayList2.add("userName1"); + ArrayList arrayList3 = new ArrayList<>(); + arrayList3.add("userStatus1"); + paramters.put(1, arrayList0); + paramters.put(2, arrayList1); + paramters.put(3, arrayList2); + paramters.put(4, arrayList3); + PreparedStatementProxy psp = (PreparedStatementProxy) this.statementProxy; + when(psp.getParameters()).thenReturn(paramters); + + List> rows = new ArrayList<>(); + rows.add(Arrays.asList("?", "?")); + when(sqlInsertRecognizer.getInsertRows(multiPkIndexMap.values())).thenReturn(rows); + + return expr; + } + + private void mockParametersPkWithAuto() { + Map> paramters = new HashMap<>(4); + ArrayList arrayList0 = new ArrayList<>(); + arrayList0.add(Null.get()); + ArrayList arrayList1 = new ArrayList<>(); + arrayList1.add("userId1"); + ArrayList arrayList2 = new ArrayList<>(); + arrayList2.add("userName1"); + ArrayList arrayList3 = new ArrayList<>(); + arrayList3.add("userStatus1"); + paramters.put(1, arrayList0); + paramters.put(2, arrayList1); + paramters.put(3, arrayList2); + paramters.put(4, arrayList3); + PreparedStatementProxy psp = (PreparedStatementProxy) this.statementProxy; + when(psp.getParameters()).thenReturn(paramters); + + List> rows = new ArrayList<>(); + rows.add(Arrays.asList("?", "?", "?", "?")); + when(sqlInsertRecognizer.getInsertRows(pkIndexMap.values())).thenReturn(rows); + } + + private void mockParametersMultiPkWithAuto() { + Map> paramters = new HashMap<>(4); + ArrayList arrayList0 = new ArrayList<>(); + arrayList0.add(Null.get()); + ArrayList arrayList1 = new ArrayList<>(); + arrayList1.add(Null.get()); + ArrayList arrayList2 = new ArrayList<>(); + arrayList2.add("userName1"); + ArrayList arrayList3 = new ArrayList<>(); + arrayList3.add("userStatus1"); + paramters.put(1, arrayList0); + paramters.put(2, arrayList1); + paramters.put(3, arrayList2); + paramters.put(4, arrayList3); + PreparedStatementProxy psp = (PreparedStatementProxy) this.statementProxy; + when(psp.getParameters()).thenReturn(paramters); + + List> rows = new ArrayList<>(); + rows.add(Arrays.asList("?", "?", "?", "?")); + when(sqlInsertRecognizer.getInsertRows(multiPkIndexMap.values())).thenReturn(rows); + } + + private void mockStatementInsertRows() { + List> rows = new ArrayList<>(); + rows.add(Arrays.asList(Null.get(), "xx", "xx", "xx")); + when(sqlInsertRecognizer.getInsertRows(pkIndexMap.values())).thenReturn(rows); + } + + +} diff --git a/rm-datasource/src/test/java/org/apache/seata/rm/datasource/sql/druid/oscar/OscarDeleteRecognizerTest.java b/rm-datasource/src/test/java/org/apache/seata/rm/datasource/sql/druid/oscar/OscarDeleteRecognizerTest.java new file mode 100644 index 00000000000..389d09bbc9d --- /dev/null +++ b/rm-datasource/src/test/java/org/apache/seata/rm/datasource/sql/druid/oscar/OscarDeleteRecognizerTest.java @@ -0,0 +1,197 @@ +/* + * Copyright 1999-2019 Seata.io Group. + * + * Licensed 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.seata.rm.datasource.sql.druid.oscar; + +import com.alibaba.druid.sql.SQLUtils; +import com.alibaba.druid.sql.ast.SQLStatement; +import com.alibaba.druid.sql.ast.statement.SQLDeleteStatement; +import com.alibaba.druid.sql.dialect.oracle.ast.expr.OracleArgumentExpr; +import org.apache.seata.sqlparser.ParametersHolder; +import org.apache.seata.sqlparser.SQLType; +import org.apache.seata.sqlparser.druid.oscar.OscarDeleteRecognizer; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +/** + * @author hsh + */ +public class OscarDeleteRecognizerTest { + + private static final String DB_TYPE = "oscar"; + + @Test + public void testGetSqlType() { + String sql = "delete from t where id = ?"; + List asts = SQLUtils.parseStatements(sql, DB_TYPE); + + OscarDeleteRecognizer recognizer = new OscarDeleteRecognizer(sql, asts.get(0)); + Assertions.assertEquals(recognizer.getSQLType(), SQLType.DELETE); + } + + @Test + public void testGetTableAlias() { + String sql = "delete from t where id = ?"; + List asts = SQLUtils.parseStatements(sql, DB_TYPE); + + OscarDeleteRecognizer recognizer = new OscarDeleteRecognizer(sql, asts.get(0)); + Assertions.assertNull(recognizer.getTableAlias()); + } + + @Test + public void testGetTableName() { + String sql = "delete from t where id = ?"; + List asts = SQLUtils.parseStatements(sql, DB_TYPE); + + OscarDeleteRecognizer recognizer = new OscarDeleteRecognizer(sql, asts.get(0)); + Assertions.assertEquals(recognizer.getTableName(), "t"); + } + + @Test + public void testGetWhereCondition_0() { + String sql = "delete from t"; + List asts = SQLUtils.parseStatements(sql, DB_TYPE); + + OscarDeleteRecognizer recognizer = new OscarDeleteRecognizer(sql, asts.get(0)); + String whereCondition = recognizer.getWhereCondition(new ParametersHolder() { + @Override + public Map> getParameters() { + return null; + } + }, new ArrayList<>()); + + //test for no condition + Assertions.assertEquals("", whereCondition); + + sql = "delete from t where id = ?"; + asts = SQLUtils.parseStatements(sql, DB_TYPE); + + recognizer = new OscarDeleteRecognizer(sql, asts.get(0)); + whereCondition = recognizer.getWhereCondition(new ParametersHolder() { + @Override + public Map> getParameters() { + ArrayList idParam = new ArrayList<>(); + idParam.add(1); + Map result = new HashMap(); + result.put(1, idParam); + return result; + } + }, new ArrayList<>()); + + //test for normal sql + Assertions.assertEquals("id = ?", whereCondition); + + sql = "delete from t where id in (?)"; + asts = SQLUtils.parseStatements(sql, DB_TYPE); + recognizer = new OscarDeleteRecognizer(sql, asts.get(0)); + whereCondition = recognizer.getWhereCondition(new ParametersHolder() { + @Override + public Map> getParameters() { + ArrayList idParam = new ArrayList<>(); + idParam.add(1); + Map result = new HashMap(); + result.put(1, idParam); + return result; + } + }, new ArrayList<>()); + + //test for sql with in + Assertions.assertEquals("id IN (?)", whereCondition); + + sql = "delete from t where id between ? and ?"; + asts = SQLUtils.parseStatements(sql, DB_TYPE); + recognizer = new OscarDeleteRecognizer(sql, asts.get(0)); + whereCondition = recognizer.getWhereCondition(new ParametersHolder() { + @Override + public Map> getParameters() { + ArrayList idParam = new ArrayList<>(); + idParam.add(1); + ArrayList idParam2 = new ArrayList<>(); + idParam.add(2); + Map result = new HashMap(); + result.put(1, idParam); + result.put(2, idParam2); + return result; + } + }, new ArrayList<>()); + //test for sql with in + Assertions.assertEquals("id BETWEEN ? AND ?", whereCondition); + + //test for exception + Assertions.assertThrows(IllegalArgumentException.class, () -> { + String s = "delete from t where id in (?)"; + List sqlStatements = SQLUtils.parseStatements(s, DB_TYPE); + SQLDeleteStatement deleteAst = (SQLDeleteStatement) sqlStatements.get(0); + deleteAst.setWhere(new OracleArgumentExpr()); + new OscarDeleteRecognizer(s, deleteAst).getWhereCondition(new ParametersHolder() { + @Override + public Map> getParameters() { + return new HashMap<>(); + } + }, new ArrayList<>()); + }); + } + + @Test + public void testGetWhereCondition_1() { + + String sql = "delete from t"; + List asts = SQLUtils.parseStatements(sql, DB_TYPE); + + OscarDeleteRecognizer recognizer = new OscarDeleteRecognizer(sql, asts.get(0)); + String whereCondition = recognizer.getWhereCondition(); + + //test for no condition + Assertions.assertEquals("", whereCondition); + + sql = "delete from t where id = 1"; + asts = SQLUtils.parseStatements(sql, DB_TYPE); + + recognizer = new OscarDeleteRecognizer(sql, asts.get(0)); + whereCondition = recognizer.getWhereCondition(); + + //test for normal sql + Assertions.assertEquals("id = 1", whereCondition); + + sql = "delete from t where id in (1)"; + asts = SQLUtils.parseStatements(sql, DB_TYPE); + recognizer = new OscarDeleteRecognizer(sql, asts.get(0)); + whereCondition = recognizer.getWhereCondition(); + + //test for sql with in + Assertions.assertEquals("id IN (1)", whereCondition); + + sql = "delete from t where id between 1 and 2"; + asts = SQLUtils.parseStatements(sql, DB_TYPE); + recognizer = new OscarDeleteRecognizer(sql, asts.get(0)); + whereCondition = recognizer.getWhereCondition(); + //test for sql with in + Assertions.assertEquals("id BETWEEN 1 AND 2", whereCondition); + + //test for exception + Assertions.assertThrows(IllegalArgumentException.class, () -> { + String s = "delete from t where id in (1)"; + List sqlStatements = SQLUtils.parseStatements(s, DB_TYPE); + SQLDeleteStatement deleteAst = (SQLDeleteStatement) sqlStatements.get(0); + deleteAst.setWhere(new OracleArgumentExpr()); + new OscarDeleteRecognizer(s, deleteAst).getWhereCondition(); + }); + } +} diff --git a/rm-datasource/src/test/java/org/apache/seata/rm/datasource/sql/druid/oscar/OscarInsertRecognizerTest.java b/rm-datasource/src/test/java/org/apache/seata/rm/datasource/sql/druid/oscar/OscarInsertRecognizerTest.java new file mode 100644 index 00000000000..9f8dc375d1a --- /dev/null +++ b/rm-datasource/src/test/java/org/apache/seata/rm/datasource/sql/druid/oscar/OscarInsertRecognizerTest.java @@ -0,0 +1,129 @@ +/* + * Copyright 1999-2019 Seata.io Group. + * + * Licensed 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.seata.rm.datasource.sql.druid.oscar; + +import com.alibaba.druid.sql.SQLUtils; +import com.alibaba.druid.sql.ast.SQLStatement; +import com.alibaba.druid.sql.ast.statement.SQLInsertStatement; +import com.alibaba.druid.sql.dialect.oracle.ast.expr.OracleBinaryDoubleExpr; +import org.apache.seata.sqlparser.SQLParsingException; +import org.apache.seata.sqlparser.SQLType; +import org.apache.seata.sqlparser.druid.oscar.OscarInsertRecognizer; +import org.apache.seata.sqlparser.struct.NotPlaceholderExpr; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; + +import java.util.Collections; +import java.util.List; + +/** + * @author hsh + */ +public class OscarInsertRecognizerTest { + + private static final String DB_TYPE = "oscar"; + + @Test + public void testGetSqlType() { + String sql = "insert into t(id) values (?)"; + List asts = SQLUtils.parseStatements(sql, DB_TYPE); + + OscarInsertRecognizer recognizer = new OscarInsertRecognizer(sql, asts.get(0)); + Assertions.assertEquals(recognizer.getSQLType(), SQLType.INSERT); + } + + @Test + public void testGetTableAlias() { + String sql = "insert into t(id) values (?)"; + List asts = SQLUtils.parseStatements(sql, DB_TYPE); + + OscarInsertRecognizer recognizer = new OscarInsertRecognizer(sql, asts.get(0)); + Assertions.assertNull(recognizer.getTableAlias()); + } + + @Test + public void testGetTableName() { + String sql = "insert into t(id) values (?)"; + List asts = SQLUtils.parseStatements(sql, DB_TYPE); + + OscarInsertRecognizer recognizer = new OscarInsertRecognizer(sql, asts.get(0)); + Assertions.assertEquals(recognizer.getTableName(), "t"); + } + + @Test + public void testGetInsertColumns() { + + //test for no column + String sql = "insert into t values (?)"; + List asts = SQLUtils.parseStatements(sql, DB_TYPE); + + OscarInsertRecognizer recognizer = new OscarInsertRecognizer(sql, asts.get(0)); + List insertColumns = recognizer.getInsertColumns(); + Assertions.assertNull(insertColumns); + + //test for normal + sql = "insert into t(a) values (?)"; + asts = SQLUtils.parseStatements(sql, DB_TYPE); + + recognizer = new OscarInsertRecognizer(sql, asts.get(0)); + insertColumns = recognizer.getInsertColumns(); + Assertions.assertEquals(1, insertColumns.size()); + + //test for exception + Assertions.assertThrows(SQLParsingException.class, () -> { + String s = "insert into t(a) values (?)"; + List sqlStatements = SQLUtils.parseStatements(s, DB_TYPE); + SQLInsertStatement sqlInsertStatement = (SQLInsertStatement)sqlStatements.get(0); + sqlInsertStatement.getColumns().add(new OracleBinaryDoubleExpr()); + + OscarInsertRecognizer oscarInsertRecognizer = new OscarInsertRecognizer(s, sqlInsertStatement); + oscarInsertRecognizer.getInsertColumns(); + }); + } + + @Test + public void testGetInsertRows() { + final int pkIndex = 0; + //test for null value + String sql = "insert into t(id, no, name, age, time) values (id_seq.nextval, null, 'a', ?, now())"; + List asts = SQLUtils.parseStatements(sql, DB_TYPE); + + OscarInsertRecognizer recognizer = new OscarInsertRecognizer(sql, asts.get(0)); + List> insertRows = recognizer.getInsertRows(Collections.singletonList(pkIndex)); + Assertions.assertEquals(1, insertRows.size()); + + //test for exception + Assertions.assertThrows(SQLParsingException.class, () -> { + String s = "insert into t(a) values (?)"; + List sqlStatements = SQLUtils.parseStatements(s, DB_TYPE); + SQLInsertStatement sqlInsertStatement = (SQLInsertStatement)sqlStatements.get(0); + sqlInsertStatement.getValuesList().get(0).getValues().set(pkIndex, new OracleBinaryDoubleExpr()); + + OscarInsertRecognizer oscarInsertRecognizer = new OscarInsertRecognizer(s, sqlInsertStatement); + oscarInsertRecognizer.getInsertRows(Collections.singletonList(pkIndex)); + }); + } + + @Test + public void testNotPlaceholder_giveValidPkIndex() { + String sql = "insert into test(create_time) values(sysdate)"; + List sqlStatements = SQLUtils.parseStatements(sql, DB_TYPE); + + OscarInsertRecognizer oscar = new OscarInsertRecognizer(sql, sqlStatements.get(0)); + List> insertRows = oscar.getInsertRows(Collections.singletonList(-1)); + Assertions.assertTrue(insertRows.get(0).get(0) instanceof NotPlaceholderExpr); + } +} diff --git a/rm-datasource/src/test/java/org/apache/seata/rm/datasource/sql/druid/oscar/OscarSelectForUpdateRecognizerTest.java b/rm-datasource/src/test/java/org/apache/seata/rm/datasource/sql/druid/oscar/OscarSelectForUpdateRecognizerTest.java new file mode 100644 index 00000000000..969d7da3ca0 --- /dev/null +++ b/rm-datasource/src/test/java/org/apache/seata/rm/datasource/sql/druid/oscar/OscarSelectForUpdateRecognizerTest.java @@ -0,0 +1,110 @@ +/* + * Copyright 1999-2019 Seata.io Group. + * + * Licensed 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.seata.rm.datasource.sql.druid.oscar; + +import com.alibaba.druid.sql.SQLUtils; +import com.alibaba.druid.sql.ast.SQLStatement; +import com.alibaba.druid.sql.ast.statement.SQLSelectStatement; +import org.apache.seata.sqlparser.ParametersHolder; +import org.apache.seata.sqlparser.SQLParsingException; +import org.apache.seata.sqlparser.SQLType; +import org.apache.seata.sqlparser.druid.oscar.OscarSelectForUpdateRecognizer; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +/** + * @author hsh + */ +public class OscarSelectForUpdateRecognizerTest { + + private static final String DB_TYPE = "oscar"; + + @Test + public void testGetSqlType() { + String sql = "select * from t where id = ? for update"; + List asts = SQLUtils.parseStatements(sql, DB_TYPE); + + OscarSelectForUpdateRecognizer recognizer = new OscarSelectForUpdateRecognizer(sql, asts.get(0)); + Assertions.assertEquals(recognizer.getSQLType(), SQLType.SELECT_FOR_UPDATE); + } + + + @Test + public void testGetWhereCondition_0() { + String sql = "select * from t for update"; + List asts = SQLUtils.parseStatements(sql, DB_TYPE); + + OscarSelectForUpdateRecognizer recognizer = new OscarSelectForUpdateRecognizer(sql, asts.get(0)); + String whereCondition = recognizer.getWhereCondition(new ParametersHolder() { + @Override + public Map> getParameters() { + return null; + } + }, new ArrayList<>()); + Assertions.assertEquals("", whereCondition); + } + + @Test + public void testGetWhereCondition_1() { + String sql = "select * from t for update"; + List asts = SQLUtils.parseStatements(sql, DB_TYPE); + + OscarSelectForUpdateRecognizer recognizer = new OscarSelectForUpdateRecognizer(sql, asts.get(0)); + String whereCondition = recognizer.getWhereCondition(); + + Assertions.assertEquals("", whereCondition); + + //test for select was null + Assertions.assertThrows(SQLParsingException.class, () -> { + String s = "select * from t for update"; + List sqlStatements = SQLUtils.parseStatements(s, DB_TYPE); + SQLSelectStatement selectAst = (SQLSelectStatement) sqlStatements.get(0); + selectAst.setSelect(null); + new OscarSelectForUpdateRecognizer(s, selectAst).getWhereCondition(); + }); + + //test for query was null + Assertions.assertThrows(SQLParsingException.class, () -> { + String s = "select * from t"; + List sqlStatements = SQLUtils.parseStatements(s, DB_TYPE); + SQLSelectStatement selectAst = (SQLSelectStatement) sqlStatements.get(0); + selectAst.getSelect().setQuery(null); + new OscarSelectForUpdateRecognizer(s, selectAst).getWhereCondition(); + }); + } + + @Test + public void testGetTableAlias() { + String sql = "select * from t where id = ? for update"; + List asts = SQLUtils.parseStatements(sql, DB_TYPE); + + OscarSelectForUpdateRecognizer recognizer = new OscarSelectForUpdateRecognizer(sql, asts.get(0)); + Assertions.assertNull(recognizer.getTableAlias()); + } + + @Test + public void testGetTableName() { + String sql = "select * from t where id = ? for update"; + List asts = SQLUtils.parseStatements(sql, DB_TYPE); + + OscarSelectForUpdateRecognizer recognizer = new OscarSelectForUpdateRecognizer(sql, asts.get(0)); + Assertions.assertEquals(recognizer.getTableName(), "t"); + } +} diff --git a/rm-datasource/src/test/java/org/apache/seata/rm/datasource/sql/druid/oscar/OscarUpdateRecognizerTest.java b/rm-datasource/src/test/java/org/apache/seata/rm/datasource/sql/druid/oscar/OscarUpdateRecognizerTest.java new file mode 100644 index 00000000000..d0f5140659f --- /dev/null +++ b/rm-datasource/src/test/java/org/apache/seata/rm/datasource/sql/druid/oscar/OscarUpdateRecognizerTest.java @@ -0,0 +1,156 @@ +/* + * Copyright 1999-2019 Seata.io Group. + * + * Licensed 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.seata.rm.datasource.sql.druid.oscar; + +import com.alibaba.druid.sql.SQLUtils; +import com.alibaba.druid.sql.ast.SQLStatement; +import com.alibaba.druid.sql.ast.statement.SQLUpdateSetItem; +import com.alibaba.druid.sql.ast.statement.SQLUpdateStatement; +import com.alibaba.druid.sql.dialect.oracle.ast.expr.OracleCursorExpr; +import org.apache.seata.sqlparser.ParametersHolder; +import org.apache.seata.sqlparser.SQLParsingException; +import org.apache.seata.sqlparser.SQLType; +import org.apache.seata.sqlparser.druid.oscar.OscarUpdateRecognizer; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +/** + * @author hsh + */ +public class OscarUpdateRecognizerTest { + + private static final String DB_TYPE = "oscar"; + + @Test + public void testGetSqlType() { + String sql = "update t set n = ?"; + List asts = SQLUtils.parseStatements(sql, DB_TYPE); + + OscarUpdateRecognizer recognizer = new OscarUpdateRecognizer(sql, asts.get(0)); + Assertions.assertEquals(recognizer.getSQLType(), SQLType.UPDATE); + } + + @Test + public void testGetUpdateColumns() { + // test with normal + String sql = "update t set a = ?, b = ?, c = ?"; + List asts = SQLUtils.parseStatements(sql, DB_TYPE); + OscarUpdateRecognizer recognizer = new OscarUpdateRecognizer(sql, asts.get(0)); + List updateColumns = recognizer.getUpdateColumns(); + Assertions.assertEquals(updateColumns.size(), 3); + + // test with alias + sql = "update t set a.a = ?, a.b = ?, a.c = ?"; + asts = SQLUtils.parseStatements(sql, DB_TYPE); + recognizer = new OscarUpdateRecognizer(sql, asts.get(0)); + updateColumns = recognizer.getUpdateColumns(); + Assertions.assertEquals(updateColumns.size(), 3); + + //test with error + Assertions.assertThrows(SQLParsingException.class, () -> { + String s = "update t set a = a"; + List sqlStatements = SQLUtils.parseStatements(s, DB_TYPE); + SQLUpdateStatement sqlUpdateStatement = (SQLUpdateStatement) sqlStatements.get(0); + List updateSetItems = sqlUpdateStatement.getItems(); + for (SQLUpdateSetItem updateSetItem : updateSetItems) { + updateSetItem.setColumn(new OracleCursorExpr()); + } + OscarUpdateRecognizer oscarUpdateRecognizer = new OscarUpdateRecognizer(s, sqlUpdateStatement); + oscarUpdateRecognizer.getUpdateColumns(); + }); + } + + @Test + public void testGetUpdateValues() { + // test with normal + String sql = "update t set a = ?, b = ?, c = ?"; + List asts = SQLUtils.parseStatements(sql, DB_TYPE); + OscarUpdateRecognizer recognizer = new OscarUpdateRecognizer(sql, asts.get(0)); + List updateValues = recognizer.getUpdateValues(); + Assertions.assertEquals(updateValues.size(), 3); + + // test with values + sql = "update t set a = 1, b = 2, c = 3"; + asts = SQLUtils.parseStatements(sql, DB_TYPE); + recognizer = new OscarUpdateRecognizer(sql, asts.get(0)); + updateValues = recognizer.getUpdateValues(); + Assertions.assertEquals(updateValues.size(), 3); + + // test with error + Assertions.assertThrows(SQLParsingException.class, () -> { + String s = "update t set a = ?"; + List sqlStatements = SQLUtils.parseStatements(s, DB_TYPE); + SQLUpdateStatement sqlUpdateStatement = (SQLUpdateStatement)sqlStatements.get(0); + List updateSetItems = sqlUpdateStatement.getItems(); + for (SQLUpdateSetItem updateSetItem : updateSetItems) { + updateSetItem.setValue(new OracleCursorExpr()); + } + OscarUpdateRecognizer oscarUpdateRecognizer = new OscarUpdateRecognizer(s, sqlUpdateStatement); + oscarUpdateRecognizer.getUpdateValues(); + }); + } + + @Test + public void testGetWhereCondition_0() { + + String sql = "update t set a = 1"; + List asts = SQLUtils.parseStatements(sql, DB_TYPE); + + OscarUpdateRecognizer recognizer = new OscarUpdateRecognizer(sql, asts.get(0)); + String whereCondition = recognizer.getWhereCondition(new ParametersHolder() { + @Override + public Map> getParameters() { + return null; + } + }, new ArrayList<>()); + + Assertions.assertEquals("", whereCondition); + } + + @Test + public void testGetWhereCondition_1() { + + String sql = "update t set a = 1"; + List asts = SQLUtils.parseStatements(sql, DB_TYPE); + + OscarUpdateRecognizer recognizer = new OscarUpdateRecognizer(sql, asts.get(0)); + String whereCondition = recognizer.getWhereCondition(); + + Assertions.assertEquals("", whereCondition); + } + + @Test + public void testGetTableAlias() { + String sql = "update t set a = ?, b = ?, c = ?"; + List asts = SQLUtils.parseStatements(sql, DB_TYPE); + + OscarUpdateRecognizer recognizer = new OscarUpdateRecognizer(sql, asts.get(0)); + Assertions.assertNull(recognizer.getTableAlias()); + } + + @Test + public void testGetTableName() { + String sql = "update t set a = ?, b = ?, c = ?"; + List asts = SQLUtils.parseStatements(sql, DB_TYPE); + + OscarUpdateRecognizer recognizer = new OscarUpdateRecognizer(sql, asts.get(0)); + Assertions.assertEquals(recognizer.getTableName(), "t"); + } +} diff --git a/script/client/at/db/oscar.sql b/script/client/at/db/oscar.sql new file mode 100644 index 00000000000..e6d992afed5 --- /dev/null +++ b/script/client/at/db/oscar.sql @@ -0,0 +1,27 @@ +-- for AT mode you must to init this sql for you business database. the seata server not need it. +CREATE TABLE UNDO_LOG +( + ID numeric(19,0) NOT NULL, + BRANCH_ID numeric(19,0) NOT NULL, + XID character varying(128) NOT NULL, + "CONTEXT" character varying(128) NOT NULL, + ROLLBACK_INFO blob NOT NULL, + LOG_STATUS numeric(10,0) NOT NULL, + LOG_CREATED timestamp(0) without time zone NOT NULL, + LOG_MODIFIED timestamp(0) without time zone NOT NULL, + CONSTRAINT UNDO_LOG_PKEY PRIMARY KEY (ID), + CONSTRAINT UX_UNDO_LOG UNIQUE (XID, BRANCH_ID) +); + +CREATE INDEX ix_log_created ON UNDO_LOG(LOG_CREATED); +COMMENT ON TABLE UNDO_LOG IS 'AT transaction mode undo table'; +COMMENT ON COLUMN UNDO_LOG.BRANCH_ID is 'branch transaction id'; +COMMENT ON COLUMN UNDO_LOG.XID is 'global transaction id'; +COMMENT ON COLUMN UNDO_LOG.CONTEXT is 'undo_log context,such as serialization'; +COMMENT ON COLUMN UNDO_LOG.ROLLBACK_INFO is 'rollback info'; +COMMENT ON COLUMN UNDO_LOG.LOG_STATUS is '0:normal status,1:defense status'; +COMMENT ON COLUMN UNDO_LOG.LOG_CREATED is 'create datetime'; +COMMENT ON COLUMN UNDO_LOG.LOG_MODIFIED is 'modify datetime'; + +-- Generate ID using sequence and trigger +CREATE SEQUENCE UNDO_LOG_SEQ START WITH 1 INCREMENT BY 1; \ No newline at end of file diff --git a/script/server/db/oscar.sql b/script/server/db/oscar.sql new file mode 100644 index 00000000000..db07d96a8d4 --- /dev/null +++ b/script/server/db/oscar.sql @@ -0,0 +1,78 @@ +-- -------------------------------- The script used when storeMode is 'db' -------------------------------- +-- the table to store GlobalSession data +CREATE TABLE global_table +( + XID VARCHAR2(128) NOT NULL, + TRANSACTION_ID NUMBER(19), + STATUS NUMBER(3) NOT NULL, + APPLICATION_ID VARCHAR2(32), + TRANSACTION_SERVICE_GROUP VARCHAR2(32), + TRANSACTION_NAME VARCHAR2(128), + TIMEOUT NUMBER(10), + BEGIN_TIME NUMBER(19), + APPLICATION_DATA VARCHAR2(2000), + GMT_CREATE TIMESTAMP(0), + GMT_MODIFIED TIMESTAMP(0), + PRIMARY KEY (XID) +); + +CREATE INDEX idx_status_gmt_modified ON global_table (STATUS, GMT_MODIFIED); +CREATE INDEX idx_transaction_id ON global_table (TRANSACTION_ID); + +-- the table to store BranchSession data +CREATE TABLE branch_table +( + BRANCH_ID NUMBER(19) NOT NULL, + XID VARCHAR2(128) NOT NULL, + TRANSACTION_ID NUMBER(19), + RESOURCE_GROUP_ID VARCHAR2(32), + RESOURCE_ID VARCHAR2(256), + BRANCH_TYPE VARCHAR2(8), + STATUS NUMBER(3), + CLIENT_ID VARCHAR2(64), + APPLICATION_DATA VARCHAR2(2000), + GMT_CREATE TIMESTAMP(6), + GMT_MODIFIED TIMESTAMP(6), + PRIMARY KEY (BRANCH_ID) +); + +CREATE INDEX idx_xid ON branch_table (XID); + +-- the table to store lock data +CREATE TABLE lock_table +( + ROW_KEY VARCHAR2(128) NOT NULL, + XID VARCHAR2(128), + TRANSACTION_ID NUMBER(19), + BRANCH_ID NUMBER(19) NOT NULL, + RESOURCE_ID VARCHAR2(256), + TABLE_NAME VARCHAR2(32), + PK VARCHAR2(36), + STATUS NUMBER(3) DEFAULT 0 NOT NULL, + GMT_CREATE TIMESTAMP(0), + GMT_MODIFIED TIMESTAMP(0), + PRIMARY KEY (ROW_KEY) +); + +comment on column lock_table.STATUS is '0:locked ,1:rollbacking'; +CREATE INDEX idx_branch_id ON lock_table (BRANCH_ID); +CREATE INDEX idx_lock_table_xid ON lock_table (XID); +CREATE INDEX idx_status ON lock_table (STATUS); + +CREATE TABLE distributed_lock ( + LOCK_KEY VARCHAR2(20) NOT NULL, + LOCK_VALUE VARCHAR2(20) NOT NULL, + EXPIRE DECIMAL(18) NOT NULL, + PRIMARY KEY (LOCK_KEY) +); + +INSERT INTO distributed_lock (LOCK_KEY, LOCK_VALUE, EXPIRE) VALUES ('AsyncCommitting', ' ', 0); +INSERT INTO distributed_lock (LOCK_KEY, LOCK_VALUE, EXPIRE) VALUES ('RetryCommitting', ' ', 0); +INSERT INTO distributed_lock (LOCK_KEY, LOCK_VALUE, EXPIRE) VALUES ('RetryRollbacking', ' ', 0); +INSERT INTO distributed_lock (LOCK_KEY, LOCK_VALUE, EXPIRE) VALUES ('TxTimeoutCheck', ' ', 0); +CREATE TABLE VGROUP_TABLE +( + VGROUP VARCHAR2(255) PRIMARY KEY, + NAMESPACE VARCHAR2(255), + CLUSTER VARCHAR2(255) +); \ No newline at end of file diff --git a/sqlparser/seata-sqlparser-core/src/main/java/org/apache/seata/sqlparser/util/JdbcConstants.java b/sqlparser/seata-sqlparser-core/src/main/java/org/apache/seata/sqlparser/util/JdbcConstants.java index d923f8918f7..e5d50257318 100644 --- a/sqlparser/seata-sqlparser-core/src/main/java/org/apache/seata/sqlparser/util/JdbcConstants.java +++ b/sqlparser/seata-sqlparser-core/src/main/java/org/apache/seata/sqlparser/util/JdbcConstants.java @@ -84,4 +84,6 @@ public interface JdbcConstants { String POLARDB = "polardb"; String POLARDBX = "polardb-x"; + + String OSCAR = "oscar"; } diff --git a/sqlparser/seata-sqlparser-druid/src/main/java/org/apache/seata/sqlparser/druid/oscar/BaseOscarRecognizer.java b/sqlparser/seata-sqlparser-druid/src/main/java/org/apache/seata/sqlparser/druid/oscar/BaseOscarRecognizer.java new file mode 100644 index 00000000000..5a9891cf005 --- /dev/null +++ b/sqlparser/seata-sqlparser-druid/src/main/java/org/apache/seata/sqlparser/druid/oscar/BaseOscarRecognizer.java @@ -0,0 +1,195 @@ +/* + * Copyright 1999-2019 Seata.io Group. + * + * Licensed 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.seata.sqlparser.druid.oscar; + +import com.alibaba.druid.sql.ast.SQLExpr; +import com.alibaba.druid.sql.ast.SQLOrderBy; +import com.alibaba.druid.sql.ast.expr.SQLInSubQueryExpr; +import com.alibaba.druid.sql.ast.expr.SQLQueryExpr; +import com.alibaba.druid.sql.ast.expr.SQLVariantRefExpr; +import com.alibaba.druid.sql.ast.statement.SQLInsertStatement; +import com.alibaba.druid.sql.ast.statement.SQLMergeStatement; +import com.alibaba.druid.sql.ast.statement.SQLReplaceStatement; +import com.alibaba.druid.sql.ast.statement.SQLUpdateSetItem; +import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleSelectJoin; +import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleSelectSubqueryTableSource; +import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleUpdateStatement; +import com.alibaba.druid.sql.dialect.oracle.visitor.OracleASTVisitor; +import com.alibaba.druid.sql.dialect.oracle.visitor.OracleASTVisitorAdapter; +import com.alibaba.druid.sql.dialect.oracle.visitor.OracleOutputVisitor; +import org.apache.seata.common.exception.NotSupportYetException; +import org.apache.seata.common.util.StringUtils; +import org.apache.seata.sqlparser.ParametersHolder; +import org.apache.seata.sqlparser.druid.BaseRecognizer; +import org.apache.seata.sqlparser.struct.Null; +import org.apache.seata.sqlparser.util.JdbcConstants; + +import java.util.ArrayList; +import java.util.List; +import java.util.Objects; + +/** + * @author hsh + */ +public abstract class BaseOscarRecognizer extends BaseRecognizer { + + /** + * Instantiates a new oscar base recognizer + * + * @param originalSql the original sql + */ + public BaseOscarRecognizer(String originalSql) { + super(originalSql); + } + + public OracleOutputVisitor createOutputVisitor(final ParametersHolder parametersHolder, + final ArrayList> paramAppenderList, + final StringBuilder sb) { + + return new OracleOutputVisitor(sb) { + @Override + public boolean visit(SQLVariantRefExpr x) { + if ("?".equals(x.getName())) { + ArrayList oneParamValues = parametersHolder.getParameters().get(x.getIndex() + 1); + if (paramAppenderList.isEmpty()) { + oneParamValues.forEach(t -> paramAppenderList.add(new ArrayList<>())); + } + for (int i = 0; i < oneParamValues.size(); i++) { + Object o = oneParamValues.get(i); + paramAppenderList.get(i).add(o instanceof Null ? null : o); + } + } + return super.visit(x); + } + }; + } + + public String getWhereCondition(SQLExpr where, final ParametersHolder parametersHolder, final ArrayList> paramAppenderList) { + if (Objects.isNull(where)) { + return StringUtils.EMPTY; + } + + StringBuilder sb = new StringBuilder(); + executeVisit(where, createOutputVisitor(parametersHolder, paramAppenderList, sb)); + return sb.toString(); + } + + public String getWhereCondition(SQLExpr where) { + if (Objects.isNull(where)) { + return StringUtils.EMPTY; + } + + StringBuilder sb = new StringBuilder(); + executeVisit(where, new OracleOutputVisitor(sb)); + return sb.toString(); + } + + protected String getOrderByCondition(SQLOrderBy sqlOrderBy) { + if (Objects.isNull(sqlOrderBy)) { + return StringUtils.EMPTY; + } + + StringBuilder sb = new StringBuilder(); + executeOrderBy(sqlOrderBy, new OracleOutputVisitor(sb)); + + return sb.toString(); + } + + protected String getOrderByCondition(SQLOrderBy sqlOrderBy, final ParametersHolder parametersHolder, + final ArrayList> paramAppenderList) { + if (Objects.isNull(sqlOrderBy)) { + return StringUtils.EMPTY; + } + + StringBuilder sb = new StringBuilder(); + executeOrderBy(sqlOrderBy, createOutputVisitor(parametersHolder, paramAppenderList, sb)); + return sb.toString(); + } + + @Override + public boolean isSqlSyntaxSupports() { + OracleASTVisitor visitor = new OracleASTVisitorAdapter() { + @Override + public boolean visit(OracleSelectJoin x) { + //just like: UPDATE table a INNER JOIN table b ON a.id = b.pid ... + throw new NotSupportYetException("not support the sql syntax with join table:" + x + + "\nplease see the doc about SQL restrictions https://seata.io/zh-cn/docs/user/sqlreference/dml.html"); + } + + @Override + public boolean visit(OracleUpdateStatement x) { + if (x.getTableSource() instanceof OracleSelectSubqueryTableSource) { + //just like: "update (select a.id,a.name from a inner join b on a.id = b.id) t set t.name = 'xxx'" + throw new NotSupportYetException("not support the sql syntax with join table:" + x + + "\nplease see the doc about SQL restrictions https://seata.io/zh-cn/docs/user/sqlreference/dml.html"); + } + List updateSetItems = x.getItems(); + for (SQLUpdateSetItem updateSetItem : updateSetItems) { + if (updateSetItem.getValue() instanceof SQLQueryExpr) { + //just like: "update a set a.id = (select id from b where a.pid = b.pid)" + throw new NotSupportYetException("not support the sql syntax with join table:" + x + + "\nplease see the doc about SQL restrictions https://seata.io/zh-cn/docs/user/sqlreference/dml.html"); + } + } + return true; + } + + @Override + public boolean visit(SQLInSubQueryExpr x) { + //just like: ...where id in (select id from t) + throw new NotSupportYetException("not support the sql syntax with InSubQuery:" + x + + "\nplease see the doc about SQL restrictions https://seata.io/zh-cn/docs/user/sqlreference/dml.html"); + } + + @Override + public boolean visit(OracleSelectSubqueryTableSource x) { + //just like: select * from (select * from t) for update + throw new NotSupportYetException("not support the sql syntax with SubQuery:" + x + + "\nplease see the doc about SQL restrictions https://seata.io/zh-cn/docs/user/sqlreference/dml.html"); + } + + @Override + public boolean visit(SQLReplaceStatement x) { + //just like: replace into t (id,dr) values (1,'2'), (2,'3') + throw new NotSupportYetException("not support the sql syntax with ReplaceStatement:" + x + + "\nplease see the doc about SQL restrictions https://seata.io/zh-cn/docs/user/sqlreference/dml.html"); + } + + @Override + public boolean visit(SQLMergeStatement x) { + //just like: merge into ... WHEN MATCHED THEN ... + throw new NotSupportYetException("not support the sql syntax with MergeStatement:" + x + + "\nplease see the doc about SQL restrictions https://seata.io/zh-cn/docs/user/sqlreference/dml.html"); + } + + @Override + public boolean visit(SQLInsertStatement x) { + if (null != x.getQuery()) { + //just like: insert into t select * from t1 + throw new NotSupportYetException("not support the sql syntax insert with query:" + x + + "\nplease see the doc about SQL restrictions https://seata.io/zh-cn/docs/user/sqlreference/dml.html"); + } + return true; + } + }; + getAst().accept(visitor); + return true; + } + + public String getDbType() { + return JdbcConstants.OSCAR; + } +} diff --git a/sqlparser/seata-sqlparser-druid/src/main/java/org/apache/seata/sqlparser/druid/oscar/OscarDeleteRecognizer.java b/sqlparser/seata-sqlparser-druid/src/main/java/org/apache/seata/sqlparser/druid/oscar/OscarDeleteRecognizer.java new file mode 100644 index 00000000000..d38eb18ae55 --- /dev/null +++ b/sqlparser/seata-sqlparser-druid/src/main/java/org/apache/seata/sqlparser/druid/oscar/OscarDeleteRecognizer.java @@ -0,0 +1,137 @@ +/* + * Copyright 1999-2019 Seata.io Group. + * + * Licensed 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.seata.sqlparser.druid.oscar; + +import com.alibaba.druid.sql.ast.SQLExpr; +import com.alibaba.druid.sql.ast.SQLStatement; +import com.alibaba.druid.sql.ast.statement.SQLDeleteStatement; +import com.alibaba.druid.sql.ast.statement.SQLExprTableSource; +import com.alibaba.druid.sql.ast.statement.SQLJoinTableSource; +import com.alibaba.druid.sql.ast.statement.SQLTableSource; +import com.alibaba.druid.sql.dialect.oracle.visitor.OracleOutputVisitor; +import org.apache.seata.common.exception.NotSupportYetException; +import org.apache.seata.sqlparser.ParametersHolder; +import org.apache.seata.sqlparser.SQLDeleteRecognizer; +import org.apache.seata.sqlparser.SQLType; + +import java.util.ArrayList; +import java.util.List; + +/** + * The type oscar delete recognizer. + * + * @author ccg + */ +public class OscarDeleteRecognizer extends BaseOscarRecognizer implements SQLDeleteRecognizer { + + private final SQLDeleteStatement ast; + + /** + * Instantiates a new My sql delete recognizer. + * + * @param originalSQL the original sql + * @param ast the ast + */ + public OscarDeleteRecognizer(String originalSQL, SQLStatement ast) { + super(originalSQL); + this.ast = (SQLDeleteStatement)ast; + } + + @Override + public SQLType getSQLType() { + return SQLType.DELETE; + } + + @Override + public String getTableAlias() { + return ast.getTableSource().getAlias(); + } + + @Override + public String getTableName() { + StringBuilder sb = new StringBuilder(); + OracleOutputVisitor visitor = new OracleOutputVisitor(sb) { + + @Override + public boolean visit(SQLExprTableSource x) { + printTableSourceExpr(x.getExpr()); + return false; + } + + @Override + public boolean visit(SQLJoinTableSource x) { + throw new NotSupportYetException("not support the syntax of delete with join table"); + } + }; + SQLTableSource tableSource; + if (ast.getFrom() == null) { + tableSource = ast.getTableSource(); + } else { + tableSource = ast.getFrom(); + } + + if (tableSource instanceof SQLExprTableSource) { + visitor.visit((SQLExprTableSource) tableSource); + } else if (tableSource instanceof SQLJoinTableSource) { + visitor.visit((SQLJoinTableSource) tableSource); + } else { + throw new NotSupportYetException("not support the syntax of delete with unknow"); + } + return sb.toString(); + } + + @Override + public String getWhereCondition(final ParametersHolder parametersHolder, + final ArrayList> paramAppenderList) { + SQLExpr where = ast.getWhere(); + return super.getWhereCondition(where, parametersHolder, paramAppenderList); + } + + @Override + public String getWhereCondition() { + SQLExpr where = ast.getWhere(); + return super.getWhereCondition(where); + } + + @Override + public String getLimitCondition() { + //oscar does not support limit or rownum yet + return null; + } + + @Override + public String getLimitCondition(ParametersHolder parametersHolder, ArrayList> paramAppenderList) { + //oscar does not support limit or rownum yet + return null; + } + + @Override + public String getOrderByCondition() { + //oscar does not support order by yet + return null; + } + + @Override + public String getOrderByCondition(ParametersHolder parametersHolder, ArrayList> paramAppenderList) { + //oscar does not support order by yet + return null; + } + + @Override + protected SQLStatement getAst() { + return ast; + } +} diff --git a/sqlparser/seata-sqlparser-druid/src/main/java/org/apache/seata/sqlparser/druid/oscar/OscarInsertRecognizer.java b/sqlparser/seata-sqlparser-druid/src/main/java/org/apache/seata/sqlparser/druid/oscar/OscarInsertRecognizer.java new file mode 100644 index 00000000000..fbfb5f50c08 --- /dev/null +++ b/sqlparser/seata-sqlparser-druid/src/main/java/org/apache/seata/sqlparser/druid/oscar/OscarInsertRecognizer.java @@ -0,0 +1,159 @@ +/* + * Copyright 1999-2019 Seata.io Group. + * + * Licensed 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.seata.sqlparser.druid.oscar; + +import com.alibaba.druid.sql.ast.SQLExpr; +import com.alibaba.druid.sql.ast.SQLStatement; +import com.alibaba.druid.sql.ast.expr.*; +import com.alibaba.druid.sql.ast.statement.SQLExprTableSource; +import com.alibaba.druid.sql.ast.statement.SQLInsertStatement; +import com.alibaba.druid.sql.dialect.oracle.visitor.OracleOutputVisitor; +import org.apache.seata.common.util.CollectionUtils; +import org.apache.seata.sqlparser.SQLInsertRecognizer; +import org.apache.seata.sqlparser.SQLType; +import org.apache.seata.sqlparser.struct.NotPlaceholderExpr; +import org.apache.seata.sqlparser.struct.Null; +import org.apache.seata.sqlparser.struct.SqlMethodExpr; +import org.apache.seata.sqlparser.struct.SqlSequenceExpr; +import org.apache.seata.sqlparser.util.ColumnUtils; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; + +/** + * The type oscar insert recognizer. + * + * @author ccg + */ +public class OscarInsertRecognizer extends BaseOscarRecognizer implements SQLInsertRecognizer { + + private final SQLInsertStatement ast; + + /** + * Instantiates a new My sql insert recognizer. + * + * @param originalSQL the original sql + * @param ast the ast + */ + public OscarInsertRecognizer(String originalSQL, SQLStatement ast) { + super(originalSQL); + this.ast = (SQLInsertStatement)ast; + } + + @Override + public SQLType getSQLType() { + return SQLType.INSERT; + } + + @Override + public String getTableAlias() { + return ast.getTableSource().getAlias(); + } + + @Override + public String getTableName() { + StringBuilder sb = new StringBuilder(); + OracleOutputVisitor visitor = new OracleOutputVisitor(sb) { + + @Override + public boolean visit(SQLExprTableSource x) { + printTableSourceExpr(x.getExpr()); + return false; + } + }; + visitor.visit(ast.getTableSource()); + return sb.toString(); + } + + @Override + public boolean insertColumnsIsEmpty() { + return CollectionUtils.isEmpty(ast.getColumns()); + } + + @Override + public List getInsertColumns() { + List columnSQLExprs = ast.getColumns(); + if (columnSQLExprs.isEmpty()) { + // INSERT INTO ta VALUES (...), without fields clarified + return null; + } + List list = new ArrayList<>(columnSQLExprs.size()); + for (SQLExpr expr : columnSQLExprs) { + if (expr instanceof SQLIdentifierExpr) { + list.add(((SQLIdentifierExpr)expr).getName()); + } else { + wrapSQLParsingException(expr); + } + } + return list; + } + + @Override + public List> getInsertRows(Collection primaryKeyIndex) { + List valuesClauses = ast.getValuesList(); + List> rows = new ArrayList<>(valuesClauses.size()); + for (SQLInsertStatement.ValuesClause valuesClause : valuesClauses) { + List exprs = valuesClause.getValues(); + List row = new ArrayList<>(exprs.size()); + rows.add(row); + for (int i = 0, len = exprs.size(); i < len; i++) { + SQLExpr expr = exprs.get(i); + if (expr instanceof SQLNullExpr) { + row.add(Null.get()); + } else if (expr instanceof SQLValuableExpr) { + row.add(((SQLValuableExpr) expr).getValue()); + } else if (expr instanceof SQLVariantRefExpr) { + row.add(((SQLVariantRefExpr) expr).getName()); + } else if (expr instanceof SQLMethodInvokeExpr) { + row.add(SqlMethodExpr.get()); + } else if (expr instanceof SQLSequenceExpr) { + SQLSequenceExpr sequenceExpr = (SQLSequenceExpr) expr; + String sequence = sequenceExpr.getSequence().getSimpleName(); + String function = sequenceExpr.getFunction().name; + row.add(new SqlSequenceExpr(sequence, function)); + } else { + if (primaryKeyIndex.contains(i)) { + wrapSQLParsingException(expr); + } + row.add(NotPlaceholderExpr.get()); + } + } + } + return rows; + } + + @Override + public List getInsertParamsValue() { + return null; + } + + @Override + public List getDuplicateKeyUpdate() { + return null; + } + + @Override + public List getInsertColumnsUnEscape() { + List insertColumns = getInsertColumns(); + return ColumnUtils.delEscape(insertColumns, getDbType()); + } + + @Override + protected SQLStatement getAst() { + return ast; + } +} diff --git a/sqlparser/seata-sqlparser-druid/src/main/java/org/apache/seata/sqlparser/druid/oscar/OscarOperateRecognizerHolder.java b/sqlparser/seata-sqlparser-druid/src/main/java/org/apache/seata/sqlparser/druid/oscar/OscarOperateRecognizerHolder.java new file mode 100644 index 00000000000..af94962c221 --- /dev/null +++ b/sqlparser/seata-sqlparser-druid/src/main/java/org/apache/seata/sqlparser/druid/oscar/OscarOperateRecognizerHolder.java @@ -0,0 +1,55 @@ +/* + * Copyright 1999-2019 Seata.io Group. + * + * Licensed 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.seata.sqlparser.druid.oscar; + +import com.alibaba.druid.sql.ast.SQLStatement; +import com.alibaba.druid.sql.ast.statement.SQLSelectStatement; +import org.apache.seata.common.loader.LoadLevel; +import org.apache.seata.sqlparser.SQLRecognizer; +import org.apache.seata.sqlparser.druid.SQLOperateRecognizerHolder; +import org.apache.seata.sqlparser.util.JdbcConstants; + +/** + * The Type OscarOperateRecognizerHolder + * + * @author hsh + */ +@LoadLevel(name = JdbcConstants.OSCAR) +public class OscarOperateRecognizerHolder implements SQLOperateRecognizerHolder { + + @Override + public SQLRecognizer getDeleteRecognizer(String sql, SQLStatement ast) { + return new OscarDeleteRecognizer(sql, ast); + } + + @Override + public SQLRecognizer getInsertRecognizer(String sql, SQLStatement ast) { + return new OscarInsertRecognizer(sql, ast); + } + + @Override + public SQLRecognizer getUpdateRecognizer(String sql, SQLStatement ast) { + return new OscarUpdateRecognizer(sql, ast); + } + + @Override + public SQLRecognizer getSelectForUpdateRecognizer(String sql, SQLStatement ast) { + if (((SQLSelectStatement) ast).getSelect().getFirstQueryBlock().isForUpdate()) { + return new OscarSelectForUpdateRecognizer(sql, ast); + } + return null; + } +} diff --git a/sqlparser/seata-sqlparser-druid/src/main/java/org/apache/seata/sqlparser/druid/oscar/OscarSelectForUpdateRecognizer.java b/sqlparser/seata-sqlparser-druid/src/main/java/org/apache/seata/sqlparser/druid/oscar/OscarSelectForUpdateRecognizer.java new file mode 100644 index 00000000000..bcd0ebc0b71 --- /dev/null +++ b/sqlparser/seata-sqlparser-druid/src/main/java/org/apache/seata/sqlparser/druid/oscar/OscarSelectForUpdateRecognizer.java @@ -0,0 +1,135 @@ +/* + * Copyright 1999-2019 Seata.io Group. + * + * Licensed 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.seata.sqlparser.druid.oscar; + +import com.alibaba.druid.sql.ast.SQLExpr; +import com.alibaba.druid.sql.ast.SQLOrderBy; +import com.alibaba.druid.sql.ast.SQLStatement; +import com.alibaba.druid.sql.ast.statement.*; +import com.alibaba.druid.sql.dialect.oracle.visitor.OracleOutputVisitor; +import org.apache.seata.sqlparser.ParametersHolder; +import org.apache.seata.sqlparser.SQLParsingException; +import org.apache.seata.sqlparser.SQLSelectRecognizer; +import org.apache.seata.sqlparser.SQLType; + +import java.util.ArrayList; +import java.util.List; + +/** + * The type oscar select for update recognizer. + * + * @author ccg + */ +public class OscarSelectForUpdateRecognizer extends BaseOscarRecognizer implements SQLSelectRecognizer { + + private final SQLSelectStatement ast; + + /** + * Instantiates a new My sql select for update recognizer. + * + * @param originalSQL the original sql + * @param ast the ast + */ + public OscarSelectForUpdateRecognizer(String originalSQL, SQLStatement ast) { + super(originalSQL); + this.ast = (SQLSelectStatement)ast; + } + + @Override + public SQLType getSQLType() { + return SQLType.SELECT_FOR_UPDATE; + } + + @Override + public String getWhereCondition(final ParametersHolder parametersHolder, + final ArrayList> paramAppenderList) { + SQLSelectQueryBlock selectQueryBlock = getSelect(); + SQLExpr where = selectQueryBlock.getWhere(); + return super.getWhereCondition(where, parametersHolder, paramAppenderList); + } + + @Override + public String getWhereCondition() { + SQLSelectQueryBlock selectQueryBlock = getSelect(); + SQLExpr where = selectQueryBlock.getWhere(); + return super.getWhereCondition(where); + } + + @Override + public String getLimitCondition() { + //oscar does not support limit or rownum yet + return null; + } + + @Override + public String getLimitCondition(ParametersHolder parametersHolder, ArrayList> paramAppenderList) { + //oscar does not support limit or rownum yet + return null; + } + + @Override + public String getOrderByCondition() { + SQLOrderBy sqlOrderBy = getSelect().getOrderBy(); + return super.getOrderByCondition(sqlOrderBy); + } + + @Override + public String getOrderByCondition(ParametersHolder parametersHolder, ArrayList> paramAppenderList) { + SQLOrderBy sqlOrderBy = getSelect().getOrderBy(); + return super.getOrderByCondition(sqlOrderBy, parametersHolder, paramAppenderList); + } + + private SQLSelectQueryBlock getSelect() { + SQLSelect select = ast.getSelect(); + if (select == null) { + throw new SQLParsingException("should never happen!"); + } + SQLSelectQueryBlock selectQueryBlock = select.getQueryBlock(); + if (selectQueryBlock == null) { + throw new SQLParsingException("should never happen!"); + } + return selectQueryBlock; + } + + @Override + public String getTableAlias() { + SQLSelectQueryBlock selectQueryBlock = getSelect(); + SQLTableSource tableSource = selectQueryBlock.getFrom(); + return tableSource.getAlias(); + } + + @Override + public String getTableName() { + SQLSelectQueryBlock selectQueryBlock = getSelect(); + SQLTableSource tableSource = selectQueryBlock.getFrom(); + StringBuilder sb = new StringBuilder(); + OracleOutputVisitor visitor = new OracleOutputVisitor(sb) { + + @Override + public boolean visit(SQLExprTableSource x) { + printTableSourceExpr(x.getExpr()); + return false; + } + }; + visitor.visit((SQLExprTableSource)tableSource); + return sb.toString(); + } + + @Override + protected SQLStatement getAst() { + return ast; + } +} diff --git a/sqlparser/seata-sqlparser-druid/src/main/java/org/apache/seata/sqlparser/druid/oscar/OscarUpdateRecognizer.java b/sqlparser/seata-sqlparser-druid/src/main/java/org/apache/seata/sqlparser/druid/oscar/OscarUpdateRecognizer.java new file mode 100644 index 00000000000..b0460b26ad6 --- /dev/null +++ b/sqlparser/seata-sqlparser-druid/src/main/java/org/apache/seata/sqlparser/druid/oscar/OscarUpdateRecognizer.java @@ -0,0 +1,181 @@ +/* + * Copyright 1999-2019 Seata.io Group. + * + * Licensed 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.seata.sqlparser.druid.oscar; + +import com.alibaba.druid.sql.ast.SQLExpr; +import com.alibaba.druid.sql.ast.SQLStatement; +import com.alibaba.druid.sql.ast.expr.SQLIdentifierExpr; +import com.alibaba.druid.sql.ast.expr.SQLPropertyExpr; +import com.alibaba.druid.sql.ast.expr.SQLValuableExpr; +import com.alibaba.druid.sql.ast.expr.SQLVariantRefExpr; +import com.alibaba.druid.sql.ast.statement.*; +import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleUpdateStatement; +import com.alibaba.druid.sql.dialect.oracle.visitor.OracleOutputVisitor; +import org.apache.seata.common.exception.NotSupportYetException; +import org.apache.seata.sqlparser.ParametersHolder; +import org.apache.seata.sqlparser.SQLType; +import org.apache.seata.sqlparser.SQLUpdateRecognizer; +import org.apache.seata.sqlparser.util.ColumnUtils; + +import java.util.ArrayList; +import java.util.List; + +/** + * The type oscar update recognizer. + * + * @author hsh + */ +public class OscarUpdateRecognizer extends BaseOscarRecognizer implements SQLUpdateRecognizer { + + private SQLUpdateStatement ast; + + /** + * Instantiates a new My sql update recognizer. + * + * @param originalSQL the original sql + * @param ast the ast + */ + public OscarUpdateRecognizer(String originalSQL, SQLStatement ast) { + super(originalSQL); + this.ast = (OracleUpdateStatement)ast; + } + + @Override + public SQLType getSQLType() { + return SQLType.UPDATE; + } + + @Override + public List getUpdateColumns() { + List updateSetItems = ast.getItems(); + List list = new ArrayList<>(updateSetItems.size()); + for (SQLUpdateSetItem updateSetItem : updateSetItems) { + SQLExpr expr = updateSetItem.getColumn(); + if (expr instanceof SQLIdentifierExpr) { + list.add(((SQLIdentifierExpr)expr).getName()); + } else if (expr instanceof SQLPropertyExpr) { + // This is alias case, like UPDATE xxx_tbl a SET a.name = ? WHERE a.id = ? + SQLExpr owner = ((SQLPropertyExpr)expr).getOwner(); + if (owner instanceof SQLIdentifierExpr) { + list.add(((SQLIdentifierExpr)owner).getName() + "." + ((SQLPropertyExpr)expr).getName()); + //This is table Field Full path, like update xxx_database.xxx_tbl set xxx_database.xxx_tbl.xxx_field... + } else if (((SQLPropertyExpr) expr).getOwnerName().split("\\.").length > 1) { + list.add(((SQLPropertyExpr)expr).getOwnerName() + "." + ((SQLPropertyExpr)expr).getName()); + } + } else { + wrapSQLParsingException(expr); + } + } + return list; + } + + @Override + public List getUpdateValues() { + List updateSetItems = ast.getItems(); + List list = new ArrayList<>(updateSetItems.size()); + for (SQLUpdateSetItem updateSetItem : updateSetItems) { + SQLExpr expr = updateSetItem.getValue(); + if (expr instanceof SQLValuableExpr) { + list.add(((SQLValuableExpr)expr).getValue()); + } else if (expr instanceof SQLVariantRefExpr) { + list.add(new VMarker()); + } else { + wrapSQLParsingException(expr); + } + } + return list; + } + + @Override + public List getUpdateColumnsUnEscape() { + List updateColumns = getUpdateColumns(); + return ColumnUtils.delEscape(updateColumns, getDbType()); + } + + @Override + public String getWhereCondition(final ParametersHolder parametersHolder, + final ArrayList> paramAppenderList) { + SQLExpr where = ast.getWhere(); + return super.getWhereCondition(where, parametersHolder, paramAppenderList); + } + + @Override + public String getWhereCondition() { + SQLExpr where = ast.getWhere(); + return super.getWhereCondition(where); + } + + @Override + public String getLimitCondition() { + //oscar does not support limit or rownum yet + return null; + } + + @Override + public String getLimitCondition(ParametersHolder parametersHolder, ArrayList> paramAppenderList) { + //oscar does not support limit or rownum yet + return null; + } + + @Override + public String getOrderByCondition() { + //oscar does not support order by yet + return null; + } + + @Override + public String getOrderByCondition(ParametersHolder parametersHolder, ArrayList> paramAppenderList) { + //oscar does not support order by yet + return null; + } + + @Override + public String getTableAlias() { + return ast.getTableSource().getAlias(); + } + + @Override + public String getTableName() { + StringBuilder sb = new StringBuilder(); + OracleOutputVisitor visitor = new OracleOutputVisitor(sb) { + + @Override + public boolean visit(SQLExprTableSource x) { + printTableSourceExpr(x.getExpr()); + return false; + } + + @Override + public boolean visit(SQLJoinTableSource x) { + throw new NotSupportYetException("not support the syntax of update with join table"); + } + }; + SQLTableSource tableSource = ast.getTableSource(); + if (tableSource instanceof SQLExprTableSource) { + visitor.visit((SQLExprTableSource) tableSource); + } else if (tableSource instanceof SQLJoinTableSource) { + visitor.visit((SQLJoinTableSource) tableSource); + } else { + throw new NotSupportYetException("not support the syntax of update with unknow"); + } + return sb.toString(); + } + + @Override + protected SQLStatement getAst() { + return ast; + } +} diff --git a/sqlparser/seata-sqlparser-druid/src/main/resources/META-INF/services/org.apache.seata.sqlparser.druid.SQLOperateRecognizerHolder b/sqlparser/seata-sqlparser-druid/src/main/resources/META-INF/services/org.apache.seata.sqlparser.druid.SQLOperateRecognizerHolder index 78decdb2af3..2ba961fd641 100644 --- a/sqlparser/seata-sqlparser-druid/src/main/resources/META-INF/services/org.apache.seata.sqlparser.druid.SQLOperateRecognizerHolder +++ b/sqlparser/seata-sqlparser-druid/src/main/resources/META-INF/services/org.apache.seata.sqlparser.druid.SQLOperateRecognizerHolder @@ -20,4 +20,5 @@ org.apache.seata.sqlparser.druid.oracle.OracleOperateRecognizerHolder org.apache.seata.sqlparser.druid.postgresql.PostgresqlOperateRecognizerHolder org.apache.seata.sqlparser.druid.sqlserver.SqlServerOperateRecognizerHolder org.apache.seata.sqlparser.druid.polardbx.PolarDBXOperateRecognizerHolder -org.apache.seata.sqlparser.druid.dm.DmOperateRecognizerHolder \ No newline at end of file +org.apache.seata.sqlparser.druid.dm.DmOperateRecognizerHolder +org.apache.seata.sqlparser.druid.oscar.OscarOperateRecognizerHolder \ No newline at end of file From 227ea7e2a0dab0f0f64d444ba30eb8b1e59aa1cd Mon Sep 17 00:00:00 2001 From: hanshaohua Date: Thu, 19 Sep 2024 08:58:29 +0800 Subject: [PATCH 02/19] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E9=83=A8=E5=88=86?= =?UTF-8?q?=E9=94=99=E8=AF=AFDbType=E5=8F=82=E6=95=B0=E8=B0=83=E7=94=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../rm/datasource/undo/oscar/OscarUndoDeleteExecutor.java | 2 +- .../rm/datasource/undo/oscar/OscarUndoUpdateExecutor.java | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/rm-datasource/src/main/java/org/apache/seata/rm/datasource/undo/oscar/OscarUndoDeleteExecutor.java b/rm-datasource/src/main/java/org/apache/seata/rm/datasource/undo/oscar/OscarUndoDeleteExecutor.java index d41c32ea51d..9ac3caca7e2 100644 --- a/rm-datasource/src/main/java/org/apache/seata/rm/datasource/undo/oscar/OscarUndoDeleteExecutor.java +++ b/rm-datasource/src/main/java/org/apache/seata/rm/datasource/undo/oscar/OscarUndoDeleteExecutor.java @@ -59,7 +59,7 @@ protected String buildUndoSQL() { } Row row = beforeImageRows.get(0); List fields = new ArrayList<>(row.nonPrimaryKeys()); - fields.addAll(getOrderedPkList(beforeImage,row,JdbcConstants.ORACLE)); + fields.addAll(getOrderedPkList(beforeImage,row,JdbcConstants.OSCAR)); // delete sql undo log before image all field come from table meta, need add escape. // see BaseTransactionalExecutor#buildTableRecords diff --git a/rm-datasource/src/main/java/org/apache/seata/rm/datasource/undo/oscar/OscarUndoUpdateExecutor.java b/rm-datasource/src/main/java/org/apache/seata/rm/datasource/undo/oscar/OscarUndoUpdateExecutor.java index bb9321e28ba..99baea2444a 100644 --- a/rm-datasource/src/main/java/org/apache/seata/rm/datasource/undo/oscar/OscarUndoUpdateExecutor.java +++ b/rm-datasource/src/main/java/org/apache/seata/rm/datasource/undo/oscar/OscarUndoUpdateExecutor.java @@ -54,12 +54,12 @@ protected String buildUndoSQL() { // update sql undo log before image all field come from table meta. need add escape. // see BaseTransactionalExecutor#buildTableRecords String updateColumns = nonPkFields.stream().map( - field -> ColumnUtils.addEscape(field.getName(), JdbcConstants.ORACLE) + " = ?").collect( + field -> ColumnUtils.addEscape(field.getName(), JdbcConstants.OSCAR) + " = ?").collect( Collectors.joining(", ")); - List pkNameList = getOrderedPkList(beforeImage, row, JdbcConstants.ORACLE).stream().map( + List pkNameList = getOrderedPkList(beforeImage, row, JdbcConstants.OSCAR).stream().map( e -> e.getName()).collect(Collectors.toList()); - String whereSql = SqlGenerateUtils.buildWhereConditionByPKs(pkNameList, JdbcConstants.ORACLE); + String whereSql = SqlGenerateUtils.buildWhereConditionByPKs(pkNameList, JdbcConstants.OSCAR); return String.format(UPDATE_SQL_TEMPLATE, sqlUndoLog.getTableName(), updateColumns, whereSql); } From 0680ac967ff222034388dc3b2957b02f08bb5edb Mon Sep 17 00:00:00 2001 From: hanshaohua Date: Sun, 22 Sep 2024 16:02:41 +0800 Subject: [PATCH 03/19] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E5=BD=93=E5=87=BA?= =?UTF-8?q?=E7=8E=B0JdbcUrl=E4=B8=AD=E5=87=BA=E7=8E=B0=E5=BC=BA=E5=88=B6?= =?UTF-8?q?=E6=A8=A1=E5=BC=8F=E5=90=8D=E5=8F=82=E6=95=B0currentSchema?= =?UTF-8?q?=E4=B8=8E=E7=94=A8=E6=88=B7=E5=90=8D=E4=B8=8D=E7=BB=9F=E4=B8=80?= =?UTF-8?q?=E6=97=B6=E8=8E=B7=E5=8F=96=E4=B8=8D=E5=88=B0=E7=B4=A2=E5=BC=95?= =?UTF-8?q?=E7=BC=93=E5=AD=98=E7=9A=84=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../rm/datasource/sql/struct/cache/OscarTableMetaCache.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/rm-datasource/src/main/java/org/apache/seata/rm/datasource/sql/struct/cache/OscarTableMetaCache.java b/rm-datasource/src/main/java/org/apache/seata/rm/datasource/sql/struct/cache/OscarTableMetaCache.java index 2bcb70a7032..e1239bdff6e 100644 --- a/rm-datasource/src/main/java/org/apache/seata/rm/datasource/sql/struct/cache/OscarTableMetaCache.java +++ b/rm-datasource/src/main/java/org/apache/seata/rm/datasource/sql/struct/cache/OscarTableMetaCache.java @@ -76,7 +76,8 @@ private TableMeta resultSetMetaToSchema(DatabaseMetaData dbmd, String tableName) TableMeta tm = new TableMeta(); tm.setTableName(tableName); String[] schemaTable = tableName.split("\\."); - String schemaName = schemaTable.length > 1 ? schemaTable[0] : dbmd.getUserName(); + + String schemaName = schemaTable.length > 1 ? schemaTable[0] : dbmd.getConnection().getSchema(); tableName = schemaTable.length > 1 ? schemaTable[1] : tableName; if (schemaName.contains("\"")) { schemaName = schemaName.replace("\"", ""); From f20a4a453fe006a404fb36534a1db2e6e3bdce97 Mon Sep 17 00:00:00 2001 From: hanshaohua Date: Wed, 18 Sep 2024 14:47:19 +0800 Subject: [PATCH 04/19] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E7=A5=9E=E9=80=9A?= =?UTF-8?q?=E6=95=B0=E6=8D=AE=E5=BA=93=E6=94=AF=E6=8C=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../apache/seata/common/util/PageUtil.java | 4 + .../seata/common/util/PageUtilTest.java | 2 + .../apache/seata/core/constants/DBType.java | 7 +- .../lock/DistributedLockSqlFactory.java | 2 +- .../db/sql/lock/LockStoreSqlFactory.java | 2 +- .../store/db/sql/lock/OscarLockStoreSql.java | 28 + .../store/db/sql/log/OscarLogStoreSqls.java | 27 + ....seata.core.store.db.sql.lock.LockStoreSql | 3 +- ...e.seata.core.store.db.sql.log.LogStoreSqls | 3 +- .../db/sql/lock/LockStoreSqlFactoryTest.java | 49 ++ .../db/sql/log/LogStoreSqlsFactoryTest.java | 36 + .../seata/rm/datasource/DataSourceProxy.java | 14 + .../exec/oscar/OscarInsertExecutor.java | 139 ++++ .../sql/handler/oscar/OscarEscapeHandler.java | 744 ++++++++++++++++++ .../sql/struct/cache/OscarTableMetaCache.java | 198 +++++ .../undo/oscar/OscarUndoDeleteExecutor.java | 79 ++ .../undo/oscar/OscarUndoExecutorHolder.java | 46 ++ .../undo/oscar/OscarUndoInsertExecutor.java | 86 ++ .../undo/oscar/OscarUndoLogManager.java | 105 +++ .../undo/oscar/OscarUndoUpdateExecutor.java | 80 ++ ...he.seata.rm.datasource.exec.InsertExecutor | 3 +- ...eata.rm.datasource.undo.UndoExecutorHolder | 3 +- ...he.seata.rm.datasource.undo.UndoLogManager | 3 +- .../org.apache.seata.sqlparser.EscapeHandler | 3 +- ...ache.seata.sqlparser.struct.TableMetaCache | 3 +- .../exec/OscarInsertExecutorTest.java | 445 +++++++++++ .../oscar/OscarDeleteRecognizerTest.java | 197 +++++ .../oscar/OscarInsertRecognizerTest.java | 129 +++ .../OscarSelectForUpdateRecognizerTest.java | 110 +++ .../oscar/OscarUpdateRecognizerTest.java | 156 ++++ script/client/at/db/oscar.sql | 27 + script/server/db/oscar.sql | 78 ++ .../seata/sqlparser/util/JdbcConstants.java | 2 + .../druid/oscar/BaseOscarRecognizer.java | 195 +++++ .../druid/oscar/OscarDeleteRecognizer.java | 137 ++++ .../druid/oscar/OscarInsertRecognizer.java | 159 ++++ .../oscar/OscarOperateRecognizerHolder.java | 55 ++ .../oscar/OscarSelectForUpdateRecognizer.java | 135 ++++ .../druid/oscar/OscarUpdateRecognizer.java | 181 +++++ ...sqlparser.druid.SQLOperateRecognizerHolder | 3 +- 40 files changed, 3667 insertions(+), 11 deletions(-) create mode 100644 core/src/main/java/org/apache/seata/core/store/db/sql/lock/OscarLockStoreSql.java create mode 100644 core/src/main/java/org/apache/seata/core/store/db/sql/log/OscarLogStoreSqls.java create mode 100644 rm-datasource/src/main/java/org/apache/seata/rm/datasource/exec/oscar/OscarInsertExecutor.java create mode 100644 rm-datasource/src/main/java/org/apache/seata/rm/datasource/sql/handler/oscar/OscarEscapeHandler.java create mode 100644 rm-datasource/src/main/java/org/apache/seata/rm/datasource/sql/struct/cache/OscarTableMetaCache.java create mode 100644 rm-datasource/src/main/java/org/apache/seata/rm/datasource/undo/oscar/OscarUndoDeleteExecutor.java create mode 100644 rm-datasource/src/main/java/org/apache/seata/rm/datasource/undo/oscar/OscarUndoExecutorHolder.java create mode 100644 rm-datasource/src/main/java/org/apache/seata/rm/datasource/undo/oscar/OscarUndoInsertExecutor.java create mode 100644 rm-datasource/src/main/java/org/apache/seata/rm/datasource/undo/oscar/OscarUndoLogManager.java create mode 100644 rm-datasource/src/main/java/org/apache/seata/rm/datasource/undo/oscar/OscarUndoUpdateExecutor.java create mode 100644 rm-datasource/src/test/java/org/apache/seata/rm/datasource/exec/OscarInsertExecutorTest.java create mode 100644 rm-datasource/src/test/java/org/apache/seata/rm/datasource/sql/druid/oscar/OscarDeleteRecognizerTest.java create mode 100644 rm-datasource/src/test/java/org/apache/seata/rm/datasource/sql/druid/oscar/OscarInsertRecognizerTest.java create mode 100644 rm-datasource/src/test/java/org/apache/seata/rm/datasource/sql/druid/oscar/OscarSelectForUpdateRecognizerTest.java create mode 100644 rm-datasource/src/test/java/org/apache/seata/rm/datasource/sql/druid/oscar/OscarUpdateRecognizerTest.java create mode 100644 script/client/at/db/oscar.sql create mode 100644 script/server/db/oscar.sql create mode 100644 sqlparser/seata-sqlparser-druid/src/main/java/org/apache/seata/sqlparser/druid/oscar/BaseOscarRecognizer.java create mode 100644 sqlparser/seata-sqlparser-druid/src/main/java/org/apache/seata/sqlparser/druid/oscar/OscarDeleteRecognizer.java create mode 100644 sqlparser/seata-sqlparser-druid/src/main/java/org/apache/seata/sqlparser/druid/oscar/OscarInsertRecognizer.java create mode 100644 sqlparser/seata-sqlparser-druid/src/main/java/org/apache/seata/sqlparser/druid/oscar/OscarOperateRecognizerHolder.java create mode 100644 sqlparser/seata-sqlparser-druid/src/main/java/org/apache/seata/sqlparser/druid/oscar/OscarSelectForUpdateRecognizer.java create mode 100644 sqlparser/seata-sqlparser-druid/src/main/java/org/apache/seata/sqlparser/druid/oscar/OscarUpdateRecognizer.java diff --git a/common/src/main/java/org/apache/seata/common/util/PageUtil.java b/common/src/main/java/org/apache/seata/common/util/PageUtil.java index 90ca42974cd..55b2aec5c35 100644 --- a/common/src/main/java/org/apache/seata/common/util/PageUtil.java +++ b/common/src/main/java/org/apache/seata/common/util/PageUtil.java @@ -111,6 +111,7 @@ public static String pageSql(String sourceSql, String dbType, int pageNum, int p case "postgresql": case "oceanbase": case "dm": + case "oscar": return LIMIT_TEMPLATE.replace(SOURCE_SQL_PLACE_HOLD, sourceSql) .replace(LIMIT_PLACE_HOLD, String.valueOf(pageSize)) .replace(OFFSET_PLACE_HOLD, String.valueOf((pageNum - 1) * pageSize)); @@ -141,6 +142,7 @@ public static String countSql(String sourceSql, String dbType) { case "oceanbase": case "oracle": case "dm": + case "oscar": return sourceSql.replaceAll("(?i)(?<=select)(.*)(?=from)", " count(1) "); case "postgresql": case "sqlserver": @@ -183,6 +185,7 @@ public static String getTimeStartSql(String dbType, String timeColumnName) { case "postgresql": case "sqlserver": case "dm": + case "oscar": return " and FLOOR(" + timeColumnName + "/1000) >= ? "; default: throw new IllegalArgumentException("The DB type :" + dbType + " is not supported yet"); @@ -202,6 +205,7 @@ public static String getTimeEndSql(String dbType, String timeColumnName) { case "postgresql": case "sqlserver": case "dm": + case "oscar": return " and FLOOR(" + timeColumnName + "/1000) <= ? "; default: throw new IllegalArgumentException("The DB type :" + dbType + " is not supported yet"); diff --git a/common/src/test/java/org/apache/seata/common/util/PageUtilTest.java b/common/src/test/java/org/apache/seata/common/util/PageUtilTest.java index 5fcdcfd5116..640fa037015 100644 --- a/common/src/test/java/org/apache/seata/common/util/PageUtilTest.java +++ b/common/src/test/java/org/apache/seata/common/util/PageUtilTest.java @@ -44,6 +44,7 @@ public void testPageSql() { assertEquals(PageUtil.pageSql(sourceSql, "postgresql", 1, 5), mysqlTargetSql); assertEquals(PageUtil.pageSql(sourceSql, "oceanbase", 1, 5), mysqlTargetSql); assertEquals(PageUtil.pageSql(sourceSql, "dm", 1, 5), mysqlTargetSql); + assertEquals(PageUtil.pageSql(sourceSql, "oscar", 1, 5), mysqlTargetSql); assertEquals(PageUtil.pageSql(sourceSql, "oracle", 1, 5), oracleTargetSql); assertEquals(PageUtil.pageSql(sourceSql, "sqlserver", 1, 5), sqlserverTargetSql); @@ -61,6 +62,7 @@ void testCountSql() { assertEquals(PageUtil.countSql(sourceSql, "postgresql"), targetSql); assertEquals(PageUtil.countSql(sourceSql, "oceanbase"), targetSql); assertEquals(PageUtil.countSql(sourceSql, "dm"), targetSql); + assertEquals(PageUtil.countSql(sourceSql, "oscar"), targetSql); assertEquals(PageUtil.countSql(sourceSql, "oracle"), targetSql); assertEquals(PageUtil.countSql(sourceSql, "sqlserver"), targetSql); diff --git a/core/src/main/java/org/apache/seata/core/constants/DBType.java b/core/src/main/java/org/apache/seata/core/constants/DBType.java index af0e82d312a..3521e3e4545 100644 --- a/core/src/main/java/org/apache/seata/core/constants/DBType.java +++ b/core/src/main/java/org/apache/seata/core/constants/DBType.java @@ -192,7 +192,12 @@ public enum DBType { /** * PolarDB db type. */ - POLARDB; + POLARDB, + + /** + * oscar db type. + */ + OSCAR; /** * Valueof db type. diff --git a/core/src/main/java/org/apache/seata/core/store/db/sql/distributed/lock/DistributedLockSqlFactory.java b/core/src/main/java/org/apache/seata/core/store/db/sql/distributed/lock/DistributedLockSqlFactory.java index 2072d4631c5..8f589780caa 100644 --- a/core/src/main/java/org/apache/seata/core/store/db/sql/distributed/lock/DistributedLockSqlFactory.java +++ b/core/src/main/java/org/apache/seata/core/store/db/sql/distributed/lock/DistributedLockSqlFactory.java @@ -34,7 +34,7 @@ public class DistributedLockSqlFactory { /** * get the lock store sql * - * @param dbType the dbType, support mysql/oracle/h2/postgre/oceanbase/dm/sqlserver ... + * @param dbType the dbType, support mysql/oracle/h2/postgre/oceanbase/dm/sqlserver/oscar ... * @return lock store sql */ public static DistributedLockSql getDistributedLogStoreSql(String dbType) { diff --git a/core/src/main/java/org/apache/seata/core/store/db/sql/lock/LockStoreSqlFactory.java b/core/src/main/java/org/apache/seata/core/store/db/sql/lock/LockStoreSqlFactory.java index dcf5781edc5..6fb7a61e335 100644 --- a/core/src/main/java/org/apache/seata/core/store/db/sql/lock/LockStoreSqlFactory.java +++ b/core/src/main/java/org/apache/seata/core/store/db/sql/lock/LockStoreSqlFactory.java @@ -34,7 +34,7 @@ public class LockStoreSqlFactory { /** * get the lock store sql * - * @param dbType the dbType, support mysql/oracle/h2/postgre/oceanbase/dm + * @param dbType the dbType, support mysql/oracle/h2/postgre/oceanbase/dm/oscar * @return lock store sql */ public static LockStoreSql getLogStoreSql(String dbType) { diff --git a/core/src/main/java/org/apache/seata/core/store/db/sql/lock/OscarLockStoreSql.java b/core/src/main/java/org/apache/seata/core/store/db/sql/lock/OscarLockStoreSql.java new file mode 100644 index 00000000000..175fab3fbe4 --- /dev/null +++ b/core/src/main/java/org/apache/seata/core/store/db/sql/lock/OscarLockStoreSql.java @@ -0,0 +1,28 @@ +/* + * Copyright 1999-2019 Seata.io Group. + * + * Licensed 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.seata.core.store.db.sql.lock; + + +import org.apache.seata.common.loader.LoadLevel; + +/** + * the database lock store shentong sql + * + * @author hsh + */ +@LoadLevel(name = "oscar") +public class OscarLockStoreSql extends OracleLockStoreSql { +} diff --git a/core/src/main/java/org/apache/seata/core/store/db/sql/log/OscarLogStoreSqls.java b/core/src/main/java/org/apache/seata/core/store/db/sql/log/OscarLogStoreSqls.java new file mode 100644 index 00000000000..2e7f7322f93 --- /dev/null +++ b/core/src/main/java/org/apache/seata/core/store/db/sql/log/OscarLogStoreSqls.java @@ -0,0 +1,27 @@ +/* + * Copyright 1999-2019 Seata.io Group. + * + * Licensed 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.seata.core.store.db.sql.log; + + +import org.apache.seata.common.loader.LoadLevel; + +/** + * Database log store oscar sql + * @author hsh + */ +@LoadLevel(name = "oscar") +public class OscarLogStoreSqls extends OracleLogStoreSqls { +} diff --git a/core/src/main/resources/META-INF/services/org.apache.seata.core.store.db.sql.lock.LockStoreSql b/core/src/main/resources/META-INF/services/org.apache.seata.core.store.db.sql.lock.LockStoreSql index fea6412761c..feb48b65f26 100644 --- a/core/src/main/resources/META-INF/services/org.apache.seata.core.store.db.sql.lock.LockStoreSql +++ b/core/src/main/resources/META-INF/services/org.apache.seata.core.store.db.sql.lock.LockStoreSql @@ -22,4 +22,5 @@ org.apache.seata.core.store.db.sql.lock.H2LockStoreSql org.apache.seata.core.store.db.sql.lock.SqlServerLockStoreSql org.apache.seata.core.store.db.sql.lock.MariadbLockStoreSql org.apache.seata.core.store.db.sql.lock.PolarDBXLockStoreSql -org.apache.seata.core.store.db.sql.lock.DmLockStoreSql \ No newline at end of file +org.apache.seata.core.store.db.sql.lock.DmLockStoreSql +org.apache.seata.core.store.db.sql.lock.OscarLockStoreSql \ No newline at end of file diff --git a/core/src/main/resources/META-INF/services/org.apache.seata.core.store.db.sql.log.LogStoreSqls b/core/src/main/resources/META-INF/services/org.apache.seata.core.store.db.sql.log.LogStoreSqls index 2f87cbe5aae..cb9ea45dddf 100644 --- a/core/src/main/resources/META-INF/services/org.apache.seata.core.store.db.sql.log.LogStoreSqls +++ b/core/src/main/resources/META-INF/services/org.apache.seata.core.store.db.sql.log.LogStoreSqls @@ -22,4 +22,5 @@ org.apache.seata.core.store.db.sql.log.H2LogStoreSqls org.apache.seata.core.store.db.sql.log.SqlServerLogStoreSqls org.apache.seata.core.store.db.sql.log.MariadbLogStoreSqls org.apache.seata.core.store.db.sql.log.PolarDBXLogStoreSqls -org.apache.seata.core.store.db.sql.log.DmLogStoreSqls \ No newline at end of file +org.apache.seata.core.store.db.sql.log.DmLogStoreSqls +org.apache.seata.core.store.db.sql.log.OscarLogStoreSqls \ No newline at end of file diff --git a/core/src/test/java/org/apache/seata/core/store/db/sql/lock/LockStoreSqlFactoryTest.java b/core/src/test/java/org/apache/seata/core/store/db/sql/lock/LockStoreSqlFactoryTest.java index 4a598bbe52a..a38f75644cb 100644 --- a/core/src/test/java/org/apache/seata/core/store/db/sql/lock/LockStoreSqlFactoryTest.java +++ b/core/src/test/java/org/apache/seata/core/store/db/sql/lock/LockStoreSqlFactoryTest.java @@ -40,6 +40,8 @@ public class LockStoreSqlFactoryTest { private static LockStoreSql DM_LOCK_STORE = LockStoreSqlFactory.getLogStoreSql("dm"); + private static LockStoreSql OSCAR_LOCK_STORE = LockStoreSqlFactory.getLogStoreSql("oscar"); + private static String GLOBAL_TABLE = "global_table"; private static String BRANCH_TABLE = "branch_table"; @@ -379,4 +381,51 @@ public void dmLockTest() { sql = DM_LOCK_STORE.getCheckLockableSql(BRANCH_TABLE, 3); Assertions.assertEquals(EXPECT_CHECK_BRANCH_LOCKABLE_SQL,sql); } + + + @Test + public void oscarLockTest() { + String sql; + // Get insert lock sql string. + sql = OSCAR_LOCK_STORE.getInsertLockSQL(GLOBAL_TABLE); + Assertions.assertNotNull(sql); + sql = OSCAR_LOCK_STORE.getInsertLockSQL(BRANCH_TABLE); + Assertions.assertNotNull(sql); + + // Get delete lock sql string. + sql = OSCAR_LOCK_STORE.getDeleteLockSql(GLOBAL_TABLE); + Assertions.assertNotNull(sql); + sql = OSCAR_LOCK_STORE.getDeleteLockSql(BRANCH_TABLE); + Assertions.assertNotNull(sql); + + // Get batch delete lock sql string. + sql = OSCAR_LOCK_STORE.getBatchDeleteLockSql(GLOBAL_TABLE, 3); + Assertions.assertEquals(EXPECT_BATCH_GLOBAL_DELETE_LOCK_SQL,sql); + sql = OSCAR_LOCK_STORE.getBatchDeleteLockSql(BRANCH_TABLE, 3); + Assertions.assertEquals(EXPECT_BATCH_BRANCH_DELETE_LOCK_SQL,sql); + + // Get batch delete lock sql string. + sql = OSCAR_LOCK_STORE.getBatchDeleteLockSqlByBranchId(GLOBAL_TABLE); + Assertions.assertNotNull(sql); + sql = OSCAR_LOCK_STORE.getBatchDeleteLockSqlByBranchId(BRANCH_TABLE); + Assertions.assertNotNull(sql); + + // Get batch delete lock sql string. + sql = OSCAR_LOCK_STORE.getBatchDeleteLockSqlByXid(GLOBAL_TABLE); + Assertions.assertEquals(EXPECT_BATCH_GLOBAL_DELETE_LOCK_BY_BRANCHS_SQL,sql); + sql = OSCAR_LOCK_STORE.getBatchDeleteLockSqlByXid(BRANCH_TABLE); + Assertions.assertEquals(EXPECT_BATCH_BRANCH_DELETE_LOCK_BY_BRANCHS_SQL,sql); + + // Get query lock sql string. + sql = OSCAR_LOCK_STORE.getQueryLockSql(GLOBAL_TABLE); + Assertions.assertNotNull(sql); + sql = OSCAR_LOCK_STORE.getQueryLockSql(BRANCH_TABLE); + Assertions.assertNotNull(sql); + + // Get check lock sql string. + sql = OSCAR_LOCK_STORE.getCheckLockableSql(GLOBAL_TABLE, 3); + Assertions.assertEquals(EXPECT_CHECK_GLOBAL_LOCKABLE_SQL,sql); + sql = OSCAR_LOCK_STORE.getCheckLockableSql(BRANCH_TABLE, 3); + Assertions.assertEquals(EXPECT_CHECK_BRANCH_LOCKABLE_SQL,sql); + } } diff --git a/core/src/test/java/org/apache/seata/core/store/db/sql/log/LogStoreSqlsFactoryTest.java b/core/src/test/java/org/apache/seata/core/store/db/sql/log/LogStoreSqlsFactoryTest.java index f3b9421862e..45c1aa3d101 100644 --- a/core/src/test/java/org/apache/seata/core/store/db/sql/log/LogStoreSqlsFactoryTest.java +++ b/core/src/test/java/org/apache/seata/core/store/db/sql/log/LogStoreSqlsFactoryTest.java @@ -34,6 +34,8 @@ public class LogStoreSqlsFactoryTest { private static LogStoreSqls dmLog = LogStoreSqlsFactory.getLogStoreSqls("dm"); + private static LogStoreSqls oscarLog = LogStoreSqlsFactory.getLogStoreSqls("oscar"); + private static String globalTable = "global_table"; private static String branchTable = "branch_table"; @@ -246,4 +248,38 @@ public void dmLogTest() { sql = dmLog.getQueryBranchMax(branchTable); Assertions.assertNotNull(sql); } + + @Test + public void oscarLogTest() { + String sql = oscarLog.getInsertGlobalTransactionSQL(globalTable); + Assertions.assertNotNull(sql); + sql = oscarLog.getUpdateGlobalTransactionStatusSQL(globalTable); + Assertions.assertNotNull(sql); + sql = oscarLog.getDeleteGlobalTransactionSQL(globalTable); + Assertions.assertNotNull(sql); + sql = oscarLog.getQueryGlobalTransactionSQL(globalTable); + Assertions.assertNotNull(sql); + sql = oscarLog.getQueryGlobalTransactionSQLByTransactionId(globalTable); + Assertions.assertNotNull(sql); + sql = oscarLog.getQueryGlobalTransactionSQLByStatus(globalTable, "1"); + Assertions.assertNotNull(sql); + sql = oscarLog.getQueryGlobalTransactionForRecoverySQL(globalTable); + Assertions.assertNotNull(sql); + sql = oscarLog.getInsertBranchTransactionSQL(branchTable); + Assertions.assertNotNull(sql); + sql = oscarLog.getUpdateBranchTransactionStatusSQL(branchTable); + Assertions.assertNotNull(sql); + sql = oscarLog.getDeleteBranchTransactionByBranchIdSQL(branchTable); + Assertions.assertNotNull(sql); + sql = oscarLog.getDeleteBranchTransactionByXId(branchTable); + Assertions.assertNotNull(sql); + sql = oscarLog.getQueryBranchTransaction(branchTable); + Assertions.assertNotNull(sql); + sql = oscarLog.getQueryBranchTransaction(branchTable, "1"); + Assertions.assertNotNull(sql); + sql = oscarLog.getQueryGlobalMax(globalTable); + Assertions.assertNotNull(sql); + sql = oscarLog.getQueryBranchMax(branchTable); + Assertions.assertNotNull(sql); + } } diff --git a/rm-datasource/src/main/java/org/apache/seata/rm/datasource/DataSourceProxy.java b/rm-datasource/src/main/java/org/apache/seata/rm/datasource/DataSourceProxy.java index dfab706294e..8868a0c964b 100644 --- a/rm-datasource/src/main/java/org/apache/seata/rm/datasource/DataSourceProxy.java +++ b/rm-datasource/src/main/java/org/apache/seata/rm/datasource/DataSourceProxy.java @@ -243,6 +243,8 @@ private void initResourceId() { initSqlServerResourceId(); } else if (JdbcConstants.DM.equals(dbType)) { initDMResourceId(); + } else if (JdbcConstants.OSCAR.equals(dbType)) { + initOscarResourceId(); } else { initDefaultResourceId(); } @@ -321,6 +323,18 @@ private void initDMResourceId() { } } + /** + * init the oscar resource id + * jdbc:oscar://192.168.x.xx:2003/OSRDB + */ + private void initOscarResourceId() { + if (jdbcUrl.contains("?")) { + resourceId = jdbcUrl.substring(0, jdbcUrl.indexOf('?')) + "/" + userName; + } else { + resourceId = jdbcUrl + "/" + userName; + } + } + /** * prevent pg sql url like * jdbc:postgresql://127.0.0.1:5432/seata?currentSchema=public diff --git a/rm-datasource/src/main/java/org/apache/seata/rm/datasource/exec/oscar/OscarInsertExecutor.java b/rm-datasource/src/main/java/org/apache/seata/rm/datasource/exec/oscar/OscarInsertExecutor.java new file mode 100644 index 00000000000..0585e030601 --- /dev/null +++ b/rm-datasource/src/main/java/org/apache/seata/rm/datasource/exec/oscar/OscarInsertExecutor.java @@ -0,0 +1,139 @@ +/* + * Copyright 1999-2019 Seata.io Group. + * + * Licensed 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.seata.rm.datasource.exec.oscar; + +import org.apache.seata.common.loader.LoadLevel; +import org.apache.seata.common.loader.Scope; +import org.apache.seata.common.util.CollectionUtils; +import org.apache.seata.rm.datasource.StatementProxy; +import org.apache.seata.rm.datasource.exec.BaseInsertExecutor; +import org.apache.seata.rm.datasource.exec.StatementCallback; +import org.apache.seata.sqlparser.SQLInsertRecognizer; +import org.apache.seata.sqlparser.SQLRecognizer; +import org.apache.seata.sqlparser.struct.Null; +import org.apache.seata.sqlparser.struct.Sequenceable; +import org.apache.seata.sqlparser.struct.SqlMethodExpr; +import org.apache.seata.sqlparser.struct.SqlSequenceExpr; +import org.apache.seata.sqlparser.util.ColumnUtils; +import org.apache.seata.sqlparser.util.JdbcConstants; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.sql.SQLException; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Set; + +/** + * The type Oscar insert executor. + * + * @author hsh + */ +@LoadLevel(name = JdbcConstants.OSCAR, scope = Scope.PROTOTYPE) +public class OscarInsertExecutor extends BaseInsertExecutor implements Sequenceable { + + private static final Logger LOGGER = LoggerFactory.getLogger(OscarInsertExecutor.class); + + /** + * Instantiates a new Abstract dml base executor. + * + * @param statementProxy the statement proxy + * @param statementCallback the statement callback + * @param sqlRecognizer the sql recognizer + */ + public OscarInsertExecutor(StatementProxy statementProxy, StatementCallback statementCallback, + SQLRecognizer sqlRecognizer) { + super(statementProxy, statementCallback, sqlRecognizer); + } + + /** + * 1. If the insert columns are not empty and do not contain any pk columns, + * it means that there is no pk value in the insert rows, then all the pk values should come from auto-increment. + *

+ * 2. The pk value exists in insert rows. The possible situations are: + *

    + *
  • The insert columns are empty: all pk values can be obtained from insert rows
  • + *
  • The insert columns contain at least one pk column: first obtain the existing pk value from the insert rows, and other from auto-increment
  • + *
+ * + * @return {@link Map}<{@link String}, {@link List}<{@link Object}>> + * @throws SQLException the sql exception + */ + @Override + public Map> getPkValues() throws SQLException { + List pkColumnNameList = getTableMeta().getPrimaryKeyOnlyName(); + Map> pkValuesMap = new HashMap<>(pkColumnNameList.size()); + + // first obtain the existing pk value from the insert rows (if exists) + if (!containsColumns() || containsAnyPk()) { + pkValuesMap.putAll(getPkValuesByColumn()); + } + // other from auto-increment + for (String columnName : pkColumnNameList) { + if (!pkValuesMap.containsKey(columnName)) { + pkValuesMap.put(columnName, getGeneratedKeys(columnName)); + } + } + return pkValuesMap; + } + + /** + * Whether the insert columns contain any pk columns + * + * @return true: contain at least one pk column. false: do not contain any pk columns + */ + public boolean containsAnyPk() { + SQLInsertRecognizer recognizer = (SQLInsertRecognizer)sqlRecognizer; + List insertColumns = recognizer.getInsertColumns(); + if (CollectionUtils.isEmpty(insertColumns)) { + return false; + } + List pkColumnNameList = getTableMeta().getPrimaryKeyOnlyName(); + if (CollectionUtils.isEmpty(pkColumnNameList)) { + return false; + } + List newColumns = ColumnUtils.delEscape(insertColumns, getDbType()); + return pkColumnNameList.stream().anyMatch(pkColumn -> newColumns.contains(pkColumn) + || CollectionUtils.toUpperList(newColumns).contains(pkColumn.toUpperCase())); + } + + @Override + public Map> getPkValuesByColumn() throws SQLException { + Map> pkValuesMap = parsePkValuesFromStatement(); + Set keySet = pkValuesMap.keySet(); + for (String pkKey : keySet) { + List pkValues = pkValuesMap.get(pkKey); + for (int i = 0; i < pkValues.size(); i++) { + if (!pkKey.isEmpty() && pkValues.get(i) instanceof SqlSequenceExpr) { + pkValues.set(i, getPkValuesBySequence((SqlSequenceExpr) pkValues.get(i), pkKey).get(0)); + } else if (!pkKey.isEmpty() && pkValues.get(i) instanceof SqlMethodExpr) { + pkValues.set(i, getGeneratedKeys(pkKey).get(0)); + } else if (!pkKey.isEmpty() && pkValues.get(i) instanceof Null) { + pkValues.set(i, getGeneratedKeys(pkKey).get(0)); + } + } + pkValuesMap.put(pkKey, pkValues); + } + return pkValuesMap; + } + + @Override + public String getSequenceSql(SqlSequenceExpr expr) { + return "SELECT " + expr.getSequence() + ".currval FROM DUAL"; + } + +} diff --git a/rm-datasource/src/main/java/org/apache/seata/rm/datasource/sql/handler/oscar/OscarEscapeHandler.java b/rm-datasource/src/main/java/org/apache/seata/rm/datasource/sql/handler/oscar/OscarEscapeHandler.java new file mode 100644 index 00000000000..aa07be7f26d --- /dev/null +++ b/rm-datasource/src/main/java/org/apache/seata/rm/datasource/sql/handler/oscar/OscarEscapeHandler.java @@ -0,0 +1,744 @@ +/* + * Copyright 1999-2019 Seata.io Group. + * + * Licensed 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.seata.rm.datasource.sql.handler.oscar; + +import java.util.Arrays; +import java.util.Set; +import java.util.stream.Collectors; + +import org.apache.seata.common.loader.LoadLevel; +import org.apache.seata.common.util.StringUtils; +import org.apache.seata.sqlparser.EscapeHandler; +import org.apache.seata.sqlparser.struct.ColumnMeta; +import org.apache.seata.sqlparser.struct.TableMeta; +import org.apache.seata.sqlparser.util.JdbcConstants; + +/** + * The type OSCAR keyword checker. + * + * @author hsh + */ +@LoadLevel(name = JdbcConstants.OSCAR) +public class OscarEscapeHandler implements EscapeHandler { + + protected Set keywordSet = Arrays.stream(OscarKeyword.values()).map(OscarKeyword::name).collect(Collectors.toSet()); + + /** + * OSCAR keyword + */ + private enum OscarKeyword { + ABORT("ABORT"), + ABSOLUTE("ABSOLUTE"), + ACCESS("ACCESS"), + ACCESSED("ACCESSED"), + ACTION("ACTION"), + ADD("ADD"), + ADMIN("ADMIN"), + ADVISOR("ADVISOR"), + AFTER("AFTER"), + AGGREGATE("AGGREGATE"), + ALTER("ALTER"), + ALWAYS("ALWAYS"), + ANALYSE("ANALYSE"), + ANALYZE("ANALYZE"), + ANALYZER("ANALYZER"), + APP("APP"), + ARCHIVE("ARCHIVE"), + ARCHIVELOG("ARCHIVELOG"), + ARE("ARE"), + ARRAY("ARRAY"), + ASC("ASC"), + ASSERTION("ASSERTION"), + ASSIGNMENT("ASSIGNMENT"), + AST("AST"), + ASYNC("ASYNC"), + ATTRIBUTES("ATTRIBUTES"), + AUDIT("AUDIT"), + AUDITFILE("AUDITFILE"), + AUTHID("AUTHID"), + AUTHORIZATION("AUTHORIZATION"), + AUTO("AUTO"), + AUTO_INCREMENT("AUTO_INCREMENT"), + AUTOEXTEND("AUTOEXTEND"), + BACKUP("BACKUP"), + BACKWARD("BACKWARD"), + BASICANALYZER("BASICANALYZER"), + BATCHSIZE("BATCHSIZE"), + BEFORE("BEFORE"), + BEGIN("BEGIN"), + BETWEEN("BETWEEN"), + BIGINT("BIGINT"), + BINARY("BINARY"), + BINLOG("BINLOG"), + BIT("BIT"), + BITMAP("BITMAP"), + BLOCK("BLOCK"), + BODY("BODY"), + BOOLEAN("BOOLEAN"), + BOTH("BOTH"), + BPCHAR("BPCHAR"), + BUFFER("BUFFER"), + BUFFER_CACHE("BUFFER_CACHE"), + BUFFER_POOL("BUFFER_POOL"), + BUILD("BUILD"), + BULK("BULK"), + BY("BY"), + BYTE("BYTE"), + CACHE("CACHE"), + CALL("CALL"), + CALLED("CALLED"), + CANCEL("CANCEL"), + CASCADED("CASCADED"), + CDC("CDC"), + CHAIN("CHAIN"), + CHANGE("CHANGE"), + CHARACTERISTICS("CHARACTERISTICS"), + CHARACTERSET("CHARACTERSET"), + CHEAT("CHEAT"), + CHECKPOINT("CHECKPOINT"), + CHINESEANALYZER("CHINESEANALYZER"), + CHUNK("CHUNK"), + CJKANALYZER("CJKANALYZER"), + CLASS("CLASS"), + CLEAN("CLEAN"), + CLOSE("CLOSE"), + CLUSTER("CLUSTER"), + COLUMNS("COLUMNS"), + COMMENT("COMMENT"), + COMMENTS("COMMENTS"), + COMMIT("COMMIT"), + COMMITTED("COMMITTED"), + COMPILE("COMPILE"), + COMPLETE("COMPLETE"), + COMPRESS("COMPRESS"), + CONCAT("CONCAT"), + CONFIGURATION("CONFIGURATION"), + CONNECT("CONNECT"), + CONNECT_BY_ISCYCLE("CONNECT_BY_ISCYCLE"), + CONNECT_BY_ISLEAF("CONNECT_BY_ISLEAF"), + CONNECT_BY_ROOT("CONNECT_BY_ROOT"), + CONSTRAINTS("CONSTRAINTS"), + CONTENT("CONTENT"), + CONTEXT("CONTEXT"), + CONTINUE("CONTINUE"), + CONTROLFILE("CONTROLFILE"), + CONVERSION("CONVERSION"), + COPY("COPY"), + CROSS("CROSS"), + CSV("CSV"), + CUBE("CUBE"), + CURRENT("CURRENT"), + CURRENT_USER("CURRENT_USER"), + CURSOR("CURSOR"), + CYCLE("CYCLE"), + DATA("DATA"), + DATABASE("DATABASE"), + DATABASELINK("DATABASELINK"), + DATAFILE("DATAFILE"), + DATAFILETYPE("DATAFILETYPE"), + DATE("DATE"), + DATE_ADD("DATE_ADD"), + DATE_SUB("DATE_SUB"), + DATEFORMAT("DATEFORMAT"), + DATETIME("DATETIME"), + DAY("DAY"), + DBA("DBA"), + DEALLOCATE("DEALLOCATE"), + DEBUG("DEBUG"), + DEC("DEC"), + DECLARE("DECLARE"), + DECODE("DECODE"), + DECRYPT("DECRYPT"), + DEFERRABLE("DEFERRABLE"), + DEFERRED("DEFERRED"), + DEFINER("DEFINER"), + DELETE("DELETE"), + DELIMITED("DELIMITED"), + DELIMITER("DELIMITER"), + DELIMITERS("DELIMITERS"), + DEMAND("DEMAND"), + DENSE_RANK("DENSE_RANK"), + DESC("DESC"), + DESCRIPTION("DESCRIPTION"), + DETERMINISTIC("DETERMINISTIC"), + DIRECTORY("DIRECTORY"), + DISABLE("DISABLE"), + DOCUMENT("DOCUMENT"), + DOMAIN("DOMAIN"), + DOUBLE("DOUBLE"), + DUMP("DUMP"), + EACH("EACH"), + ELOG("ELOG"), + ELT("ELT"), + EMPTY("EMPTY"), + ENABLE("ENABLE"), + ENCODING("ENCODING"), + ENCRYPT("ENCRYPT"), + ENCRYPTED("ENCRYPTED"), + ENCRYPTION("ENCRYPTION"), + END("END"), + ERROR("ERROR"), + ERRORS("ERRORS"), + ESCALATION("ESCALATION"), + ESCAPE("ESCAPE"), + EVENTS("EVENTS"), + EXCHANGE("EXCHANGE"), + EXCLUDING("EXCLUDING"), + EXCLUSIVE("EXCLUSIVE"), + EXEC("EXEC"), + EXECUTE("EXECUTE"), + EXPLAIN("EXPLAIN"), + EXPORT("EXPORT"), + EXTEND("EXTEND"), + EXTERNALLY("EXTERNALLY"), + FAILOVER("FAILOVER"), + FALSE("FALSE"), + FAR("FAR"), + FAST("FAST"), + FAULT("FAULT"), + FETCH("FETCH"), + FIELD("FIELD"), + FIELDS("FIELDS"), + FIELDTERMINATOR("FIELDTERMINATOR"), + FILE("FILE"), + FILESIZE("FILESIZE"), + FILL("FILL"), + FILTER("FILTER"), + FIRE_TRIGGERS("FIRE_TRIGGERS"), + FIRST("FIRST"), + FIRSTROW("FIRSTROW"), + FLUSH("FLUSH"), + FOLLOWING("FOLLOWING"), + FORCE("FORCE"), + FOREIGNKEY_CONSTRAINTS("FOREIGNKEY_CONSTRAINTS"), + FOREVER("FOREVER"), + FORMATFILE("FORMATFILE"), + FORWARD("FORWARD"), + FREELISTS("FREELISTS"), + FREEPOOLS("FREEPOOLS"), + FULL("FULL"), + FULLTEXT("FULLTEXT"), + FUNCTION("FUNCTION"), + G("G"), + GB("GB"), + GBK("GBK"), + GCOV("GCOV"), + GENERATED("GENERATED"), + GEOGRAPHY("GEOGRAPHY"), + GEOMETRY("GEOMETRY"), + GET("GET"), + GETCLOBVAL("GETCLOBVAL"), + GETSTRINGVAL("GETSTRINGVAL"), + GLOBAL("GLOBAL"), + GLOBAL_NAME("GLOBAL_NAME"), + GLOBALLY("GLOBALLY"), + GREATEST("GREATEST"), + GROUPING("GROUPING"), + GROUPING_ID("GROUPING_ID"), + GUARANTEE("GUARANTEE"), + HANDLER("HANDLER"), + HASH("HASH"), + HEADER("HEADER"), + HEAP("HEAP"), + HOLD("HOLD"), + HOUR("HOUR"), + IDENTIFIED("IDENTIFIED"), + IDENTITY("IDENTITY"), + IF("IF"), + IGNORE("IGNORE"), + ILIKE("ILIKE"), + IMMEDIATE("IMMEDIATE"), + IMMUTABLE("IMMUTABLE"), + IMPLICIT("IMPLICIT"), + IMPORT("IMPORT"), + IMPORT_POLCOL("IMPORT_POLCOL"), + INCREMENT("INCREMENT"), + INDEX("INDEX"), + INDEXES("INDEXES"), + INHERITS("INHERITS"), + INIT("INIT"), + INITIAL("INITIAL"), + INITIALIZED("INITIALIZED"), + INITIALLY("INITIALLY"), + INITRANS("INITRANS"), + INNER("INNER"), + INOUT("INOUT"), + INPUT("INPUT"), + INSENSITIVE("INSENSITIVE"), + INSERT("INSERT"), + INSTEAD("INSTEAD"), + INTERVAL("INTERVAL"), + INVALIDATE("INVALIDATE"), + INVISIBLE("INVISIBLE"), + INVOKER("INVOKER"), + IP("IP"), + IS("IS"), + ISNULL("ISNULL"), + ISOLATION("ISOLATION"), + JOIN("JOIN"), + JSON("JSON"), + JSON_TABLE("JSON_TABLE"), + JSON_VALUE("JSON_VALUE"), + K("K"), + KB("KB"), + KEEP("KEEP"), + KEEPIDENTITY("KEEPIDENTITY"), + KEEPNULLS("KEEPNULLS"), + KEY("KEY"), + KEYSTORE("KEYSTORE"), + KILL("KILL"), + KILOBYTES_PER_BATCH("KILOBYTES_PER_BATCH"), + KSTORE("KSTORE"), + LABEL("LABEL"), + LANCOMPILER("LANCOMPILER"), + LANGUAGE("LANGUAGE"), + LAST("LAST"), + LASTROW("LASTROW"), + LC_COLLATE("LC_COLLATE"), + LC_CTYPE("LC_CTYPE"), + LDRTRIM("LDRTRIM"), + LEADING("LEADING"), + LEAK("LEAK"), + LEAST("LEAST"), + LEFT("LEFT"), + LESS("LESS"), + LIFETIME("LIFETIME"), + LIKE("LIKE"), + LIMIT("LIMIT"), + LIST("LIST"), + LISTEN("LISTEN"), + LOAD("LOAD"), + LOB("LOB"), + LOCAL("LOCAL"), + LOCATION("LOCATION"), + LOCK("LOCK"), + LOCKED("LOCKED"), + LOG("LOG"), + LOGFILE("LOGFILE"), + LOGGING("LOGGING"), + LOGICAL("LOGICAL"), + LONG("LONG"), + LOOP("LOOP"), + LRTRIM("LRTRIM"), + LSN("LSN"), + LTRIM("LTRIM"), + M("M"), + MAINTAIN_INDEX("MAINTAIN_INDEX"), + MAINTENANCE("MAINTENANCE"), + MANUAL("MANUAL"), + MASKING("MASKING"), + MATCH("MATCH"), + MATCHED("MATCHED"), + MATERIALIZED("MATERIALIZED"), + MAX("MAX"), + MAXERRORS("MAXERRORS"), + MAXEXTENDS("MAXEXTENDS"), + MAXEXTENTS("MAXEXTENTS"), + MAXSIZE("MAXSIZE"), + MAXTRANS("MAXTRANS"), + MAXVALUE("MAXVALUE"), + MB("MB"), + MEMBER("MEMBER"), + MEMORY("MEMORY"), + MERGE("MERGE"), + MIN("MIN"), + MINEXTENDS("MINEXTENDS"), + MINEXTENTS("MINEXTENTS"), + MINSIZE("MINSIZE"), + MINUS("MINUS"), + MINUTE("MINUTE"), + MINVALUE("MINVALUE"), + MISSING("MISSING"), + MOD("MOD"), + MODE("MODE"), + MODIFY("MODIFY"), + MONEY("MONEY"), + MONTH("MONTH"), + MOUNT("MOUNT"), + MOVE("MOVE"), + MOVEMENT("MOVEMENT"), + MULTICOLUMN("MULTICOLUMN"), + MULTIPLE("MULTIPLE"), + NAME("NAME"), + NAMES("NAMES"), + NATURAL("NATURAL"), + NCHAR("NCHAR"), + NEVER("NEVER"), + NEWLINE("NEWLINE"), + NEXT("NEXT"), + NEXTVAL("NEXTVAL"), + NO("NO"), + NOARCHIVELOG("NOARCHIVELOG"), + NOAUDIT("NOAUDIT"), + NOCACHE("NOCACHE"), + NOCOMPRESS("NOCOMPRESS"), + NOCOPY("NOCOPY"), + NOCYCLE("NOCYCLE"), + NODE("NODE"), + NOGUARANTEE("NOGUARANTEE"), + NOLOGGING("NOLOGGING"), + NOMAXVALUE("NOMAXVALUE"), + NOMINVALUE("NOMINVALUE"), + NOMOUNT("NOMOUNT"), + NORMAL("NORMAL"), + NOTHING("NOTHING"), + NOTIFY("NOTIFY"), + NOTNULL("NOTNULL"), + NOTRIM("NOTRIM"), + NOVALIDATE("NOVALIDATE"), + NOWAIT("NOWAIT"), + NVARCHAR2("NVARCHAR2"), + NVL("NVL"), + NVL2("NVL2"), + OBJECT("OBJECT"), + OF("OF"), + OFF("OFF"), + OFFLINE("OFFLINE"), + OFFSET("OFFSET"), + OIDS("OIDS"), + ONLINE("ONLINE"), + OPEN("OPEN"), + OPERATOR("OPERATOR"), + OPTIMIZE("OPTIMIZE"), + OPTIMIZE_KSCACHE("OPTIMIZE_KSCACHE"), + OPTION("OPTION"), + ORACLE("ORACLE"), + ORDINALITY("ORDINALITY"), + ORGANIZATION("ORGANIZATION"), + OSCAR("OSCAR"), + OUT("OUT"), + OUTER("OUTER"), + OUTLINE("OUTLINE"), + OVER("OVER"), + OVERFLOW("OVERFLOW"), + OVERLAPS("OVERLAPS"), + OVERLAY("OVERLAY"), + OWNER("OWNER"), + PACKAGE("PACKAGE"), + PAGESIZE("PAGESIZE"), + PARALLEL("PARALLEL"), + PARAMETER("PARAMETER"), + PARAMINFO("PARAMINFO"), + PARTIAL("PARTIAL"), + PARTITION("PARTITION"), + PARTITIONS("PARTITIONS"), + PASSING("PASSING"), + PASSWORD("PASSWORD"), + PATH("PATH"), + PCTFREE("PCTFREE"), + PCTINCREASE("PCTINCREASE"), + PCTTHRESHOLD("PCTTHRESHOLD"), + PCTUSED("PCTUSED"), + PCTVERSION("PCTVERSION"), + PENDANT("PENDANT"), + PETENTION("PETENTION"), + PFILE("PFILE"), + PIPELINED("PIPELINED"), + PIVOT("PIVOT"), + PLACING("PLACING"), + PLS_INTEGER("PLS_INTEGER"), + POLICY("POLICY"), + PORT("PORT"), + POSITION("POSITION"), + PRECEDING("PRECEDING"), + PRECISION("PRECISION"), + PREPARE("PREPARE"), + PRESERVE("PRESERVE"), + PREVAL("PREVAL"), + PRIMARY("PRIMARY"), + PRIOR("PRIOR"), + PRIORITY("PRIORITY"), + PRIVILEGES("PRIVILEGES"), + PROCEDURAL("PROCEDURAL"), + PROCEDURE("PROCEDURE"), + PUBLIC("PUBLIC"), + PURGE("PURGE"), + QU("QU"), + QUERY("QUERY"), + QUICK("QUICK"), + QUOTE("QUOTE"), + RAC("RAC"), + RANGE("RANGE"), + RATIO_TO_REPORT("RATIO_TO_REPORT"), + RAW("RAW"), + READ("READ"), + READABLE("READABLE"), + READS("READS"), + READSIZE("READSIZE"), + REBUILD("REBUILD"), + RECHECK("RECHECK"), + RECORDS("RECORDS"), + RECOVERY("RECOVERY"), + RECREATE("RECREATE"), + RECURSIVE("RECURSIVE"), + RECYCLE("RECYCLE"), + REFRESH("REFRESH"), + REGEXP("REGEXP"), + REGION("REGION"), + REJECT("REJECT"), + RELATIVE("RELATIVE"), + REMOVE("REMOVE"), + RENAME("RENAME"), + REPEATABLE("REPEATABLE"), + REPLACE("REPLACE"), + RESET("RESET"), + RESIZE("RESIZE"), + RESOURCE("RESOURCE"), + RESTART("RESTART"), + RESTORE("RESTORE"), + RESTRICT("RESTRICT"), + RESULT("RESULT"), + RESUME("RESUME"), + RETENTION("RETENTION"), + RETURN("RETURN"), + RETURN_GENERATED_KEYS("RETURN_GENERATED_KEYS"), + RETURNING("RETURNING"), + RETURNS("RETURNS"), + REUSE("REUSE"), + REVERSE("REVERSE"), + REVOKE("REVOKE"), + REWRITE("REWRITE"), + RIGHT("RIGHT"), + ROLE("ROLE"), + ROLLBACK("ROLLBACK"), + ROLLUP("ROLLUP"), + ROW("ROW"), + ROWDESCRIPTION("ROWDESCRIPTION"), + ROWID("ROWID"), + ROWS("ROWS"), + ROWS_PER_BATCH("ROWS_PER_BATCH"), + ROWTERMINATOR("ROWTERMINATOR"), + ROWTYPE("ROWTYPE"), + RTRIM("RTRIM"), + RULE("RULE"), + SAMPLE("SAMPLE"), + SAVEPOINT("SAVEPOINT"), + SCAN("SCAN"), + SCHEMA("SCHEMA"), + SCN("SCN"), + SCROLL("SCROLL"), + SECOND("SECOND"), + SECURITY("SECURITY"), + SEGMENT("SEGMENT"), + SEPARATOR("SEPARATOR"), + SEQUENCE("SEQUENCE"), + SERIALIZABLE("SERIALIZABLE"), + SESSION("SESSION"), + SETS("SETS"), + SHARE("SHARE"), + SHOW("SHOW"), + SHRINK("SHRINK"), + SHRINKLOG("SHRINKLOG"), + SHUTDOWN("SHUTDOWN"), + SIBLINGS("SIBLINGS"), + SIGNED("SIGNED"), + SILENTLY("SILENTLY"), + SIMILAR("SIMILAR"), + SIMPLE("SIMPLE"), + SINGLE("SINGLE"), + SINGLEROW("SINGLEROW"), + SIZE("SIZE"), + SKIP("SKIP"), + SMALLINT("SMALLINT"), + SPACE("SPACE"), + SPLIT("SPLIT"), + STABLE("STABLE"), + STANDALONE("STANDALONE"), + STANDARDANALYZER("STANDARDANALYZER"), + START("START"), + STARTFILE("STARTFILE"), + STARTPOS("STARTPOS"), + STARTTIME("STARTTIME"), + STARTUP("STARTUP"), + STATEMENT("STATEMENT"), + STATIC("STATIC"), + STATISTICS("STATISTICS"), + STDIN("STDIN"), + STDOUT("STDOUT"), + STOP("STOP"), + STOPFILE("STOPFILE"), + STOPPOS("STOPPOS"), + STOPTIME("STOPTIME"), + STOPWORDS("STOPWORDS"), + STORAGE("STORAGE"), + STORE("STORE"), + STORED("STORED"), + STRICT("STRICT"), + SUBPARTITION("SUBPARTITION"), + SUBPARTITIONS("SUBPARTITIONS"), + SUBSTRING("SUBSTRING"), + SUCCESSFUL("SUCCESSFUL"), + SUSPEND("SUSPEND"), + SWITCHOVER("SWITCHOVER"), + SYNC("SYNC"), + SYSAUX("SYSAUX"), + SYSID("SYSID"), + SYSTEM("SYSTEM"), + T("T"), + TABLESPACE("TABLESPACE"), + TB("TB"), + TEMP("TEMP"), + TEMPFILE("TEMPFILE"), + TEMPLATE("TEMPLATE"), + TEMPORARY("TEMPORARY"), + TERMINATED("TERMINATED"), + THAN("THAN"), + TIMES("TIMES"), + TIMEZONE("TIMEZONE"), + TINYINT("TINYINT"), + TOAST("TOAST"), + TRACE("TRACE"), + TRACKING("TRACKING"), + TRAIL("TRAIL"), + TRAILING("TRAILING"), + TRANSACTION("TRANSACTION"), + TRANSACTIONAL("TRANSACTIONAL"), + TRANSFORMS("TRANSFORMS"), + TREAT("TREAT"), + TRIAL("TRIAL"), + TRIGGER("TRIGGER"), + TRIGGERS("TRIGGERS"), + TRIM("TRIM"), + TRUE("TRUE"), + TRUNCATE("TRUNCATE"), + TRUSTED("TRUSTED"), + TUPLE("TUPLE"), + TYPE("TYPE"), + UNBOUNDED("UNBOUNDED"), + UNCOMMITTED("UNCOMMITTED"), + UNDO("UNDO"), + UNENCRYPTED("UNENCRYPTED"), + UNKNOWN("UNKNOWN"), + UNLIMITED("UNLIMITED"), + UNLISTEN("UNLISTEN"), + UNLOCK("UNLOCK"), + UNMAINTENANCE("UNMAINTENANCE"), + UNPIVOT("UNPIVOT"), + UNSIGNED("UNSIGNED"), + UNTIL("UNTIL"), + UNUSABLE("UNUSABLE"), + UP("UP"), + UPDATE("UPDATE"), + UPDATELABEL("UPDATELABEL"), + UPDATEXML("UPDATEXML"), + USAGE("USAGE"), + USE("USE"), + USER("USER"), + UTF8("UTF8"), + UTF8MB4("UTF8MB4"), + VACUUM("VACUUM"), + VALID("VALID"), + VALIDATE("VALIDATE"), + VALIDATION("VALIDATION"), + VALIDATOR("VALIDATOR"), + VALUE("VALUE"), + VALUES("VALUES"), + VARBINARY("VARBINARY"), + VARBIT("VARBIT"), + VARCHAR("VARCHAR"), + VARCHAR2("VARCHAR2"), + VARYING("VARYING"), + VERBOSE("VERBOSE"), + VERSION("VERSION"), + VERSIONS("VERSIONS"), + VIEW("VIEW"), + VIRTUAL("VIRTUAL"), + VISIBLE("VISIBLE"), + VOLATILE("VOLATILE"), + VOTEDISK("VOTEDISK"), + WAIT("WAIT"), + WALLET("WALLET"), + WEIGHT("WEIGHT"), + WHEN("WHEN"), + WHENEVER("WHENEVER"), + WINDOW("WINDOW"), + WORK("WORK"), + XML("XML"), + XMLATTRIBUTES("XMLATTRIBUTES"), + XMLCONCAT("XMLCONCAT"), + XMLELEMENT("XMLELEMENT"), + XMLFOREST("XMLFOREST"), + XMLPARSE("XMLPARSE"), + XMLPI("XMLPI"), + XMLROOT("XMLROOT"), + XMLSERIALIZE("XMLSERIALIZE"), + XMLTABLE("XMLTABLE"), + YEAR("YEAR"), + YES("YES"), + ZONE("ZONE"); + /** + * The Name. + */ + public final String name; + OscarKeyword(String name) { + this.name = name; + } + } + + + @Override + public boolean checkIfKeyWords(String fieldOrTableName) { + if (keywordSet.contains(fieldOrTableName)) { + return true; + } + if (fieldOrTableName != null) { + fieldOrTableName = fieldOrTableName.toUpperCase(); + } + return keywordSet.contains(fieldOrTableName); + + } + + @Override + public boolean checkIfNeedEscape(String columnName, TableMeta tableMeta) { + if (StringUtils.isBlank(columnName)) { + return false; + } + columnName = columnName.trim(); + if (containsEscape(columnName)) { + return false; + } + boolean isKeyWord = checkIfKeyWords(columnName); + if (isKeyWord) { + return true; + } + // oscar + // we are recommend table name and column name must uppercase. + // if exists full uppercase, the table name or column name doesn't bundle escape symbol. + //create\read table TABLE "table" "TABLE" + if (null != tableMeta) { + ColumnMeta columnMeta = tableMeta.getColumnMeta(columnName); + if (null != columnMeta) { + return columnMeta.isCaseSensitive(); + } + } else if (isUppercase(columnName)) { + return false; + } + return true; + } + + private static boolean isUppercase(String fieldOrTableName) { + if (fieldOrTableName == null) { + return false; + } + char[] chars = fieldOrTableName.toCharArray(); + for (char ch : chars) { + if (ch >= 'a' && ch <= 'z') { + return false; + } + } + return true; + } +} diff --git a/rm-datasource/src/main/java/org/apache/seata/rm/datasource/sql/struct/cache/OscarTableMetaCache.java b/rm-datasource/src/main/java/org/apache/seata/rm/datasource/sql/struct/cache/OscarTableMetaCache.java new file mode 100644 index 00000000000..2bcb70a7032 --- /dev/null +++ b/rm-datasource/src/main/java/org/apache/seata/rm/datasource/sql/struct/cache/OscarTableMetaCache.java @@ -0,0 +1,198 @@ +/* + * Copyright 1999-2019 Seata.io Group. + * + * Licensed 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.seata.rm.datasource.sql.struct.cache; + +import org.apache.seata.common.exception.NotSupportYetException; +import org.apache.seata.common.exception.ShouldNeverHappenException; +import org.apache.seata.common.loader.LoadLevel; +import org.apache.seata.common.util.StringUtils; +import org.apache.seata.sqlparser.struct.ColumnMeta; +import org.apache.seata.sqlparser.struct.IndexMeta; +import org.apache.seata.sqlparser.struct.IndexType; +import org.apache.seata.sqlparser.struct.TableMeta; +import org.apache.seata.sqlparser.util.JdbcConstants; + +import java.sql.Connection; +import java.sql.DatabaseMetaData; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +/** + * The type Table meta cache. + * + * @author hsh + */ +@LoadLevel(name = JdbcConstants.OSCAR) +public class OscarTableMetaCache extends AbstractTableMetaCache { + + @Override + protected String getCacheKey(Connection connection, String tableName, String resourceId) { + StringBuilder cacheKey = new StringBuilder(resourceId); + cacheKey.append("."); + + //separate it to schemaName and tableName + String[] tableNameWithSchema = tableName.split("\\."); + String defaultTableName = tableNameWithSchema.length > 1 ? tableNameWithSchema[1] : tableNameWithSchema[0]; + + //oscar does not implement supportsMixedCaseIdentifiers in DatabaseMetadata + if (defaultTableName.contains("\"")) { + cacheKey.append(defaultTableName.replace("\"", "")); + } else { + // oscar default store in upper case + cacheKey.append(defaultTableName.toUpperCase()); + } + + return cacheKey.toString(); + } + + @Override + protected TableMeta fetchSchema(Connection connection, String tableName) throws SQLException { + try { + return resultSetMetaToSchema(connection.getMetaData(), tableName); + } catch (SQLException sqlEx) { + throw sqlEx; + } catch (Exception e) { + throw new SQLException(String.format("Failed to fetch schema of %s", tableName), e); + } + } + + private TableMeta resultSetMetaToSchema(DatabaseMetaData dbmd, String tableName) throws SQLException { + TableMeta tm = new TableMeta(); + tm.setTableName(tableName); + String[] schemaTable = tableName.split("\\."); + String schemaName = schemaTable.length > 1 ? schemaTable[0] : dbmd.getUserName(); + tableName = schemaTable.length > 1 ? schemaTable[1] : tableName; + if (schemaName.contains("\"")) { + schemaName = schemaName.replace("\"", ""); + } else { + schemaName = schemaName.toUpperCase(); + } + + if (tableName.contains("\"")) { + tableName = tableName.replace("\"", ""); + + } else { + tableName = tableName.toUpperCase(); + } + tm.setCaseSensitive(StringUtils.hasLowerCase(tableName)); + + try (ResultSet rsColumns = dbmd.getColumns("", schemaName, tableName, "%"); + ResultSet rsIndex = dbmd.getIndexInfo(null, schemaName, tableName, false, true); + ResultSet rsPrimary = dbmd.getPrimaryKeys(null, schemaName, tableName)) { + while (rsColumns.next()) { + ColumnMeta col = new ColumnMeta(); + col.setTableCat(rsColumns.getString("TABLE_CAT")); + col.setTableSchemaName(rsColumns.getString("TABLE_SCHEM")); + col.setTableName(rsColumns.getString("TABLE_NAME")); + col.setColumnName(rsColumns.getString("COLUMN_NAME")); + col.setDataType(rsColumns.getInt("DATA_TYPE")); + col.setDataTypeName(rsColumns.getString("TYPE_NAME")); + col.setColumnSize(rsColumns.getInt("COLUMN_SIZE")); + col.setDecimalDigits(rsColumns.getInt("DECIMAL_DIGITS")); + col.setNumPrecRadix(rsColumns.getInt("NUM_PREC_RADIX")); + col.setNullAble(rsColumns.getInt("NULLABLE")); + col.setRemarks(rsColumns.getString("REMARKS")); + col.setColumnDef(rsColumns.getString("COLUMN_DEF")); + col.setSqlDataType(rsColumns.getInt("SQL_DATA_TYPE")); + col.setSqlDatetimeSub(rsColumns.getInt("SQL_DATETIME_SUB")); + col.setCharOctetLength(rsColumns.getInt("CHAR_OCTET_LENGTH")); + col.setOrdinalPosition(rsColumns.getInt("ORDINAL_POSITION")); + col.setIsNullAble(rsColumns.getString("IS_NULLABLE")); + col.setCaseSensitive(StringUtils.hasLowerCase(col.getColumnName())); + + if (tm.getAllColumns().containsKey(col.getColumnName())) { + throw new NotSupportYetException("Not support the table has the same column name with different case yet"); + } + tm.getAllColumns().put(col.getColumnName(), col); + } + + while (rsIndex.next()) { + String indexName = rsIndex.getString("INDEX_NAME"); + if (StringUtils.isNullOrEmpty(indexName)) { + continue; + } + String colName = rsIndex.getString("COLUMN_NAME"); + ColumnMeta col = tm.getAllColumns().get(colName); + if (tm.getAllIndexes().containsKey(indexName)) { + IndexMeta index = tm.getAllIndexes().get(indexName); + index.getValues().add(col); + } else { + IndexMeta index = new IndexMeta(); + index.setIndexName(indexName); + index.setNonUnique(rsIndex.getBoolean("NON_UNIQUE")); + index.setIndexQualifier(rsIndex.getString("INDEX_QUALIFIER")); + index.setIndexName(rsIndex.getString("INDEX_NAME")); + index.setType(rsIndex.getShort("TYPE")); + index.setOrdinalPosition(rsIndex.getShort("ORDINAL_POSITION")); + index.setAscOrDesc(rsIndex.getString("ASC_OR_DESC")); + index.setCardinality(rsIndex.getLong("CARDINALITY")); + index.getValues().add(col); + if (!index.isNonUnique()) { + index.setIndextype(IndexType.UNIQUE); + } else { + index.setIndextype(IndexType.NORMAL); + } + tm.getAllIndexes().put(indexName, index); + + } + } + if (tm.getAllIndexes().isEmpty()) { + throw new ShouldNeverHappenException(String.format("Could not found any index in the table: %s", tableName)); + } + // when we create a primary key constraint oracle will uses and existing unique index. + // if we create a unique index before create a primary constraint in the same column will cause the problem + // that primary key constraint name was different from the unique name. + List pkcol = new ArrayList<>(); + while (rsPrimary.next()) { + String pkConstraintName = rsPrimary.getString("PK_NAME"); + if (tm.getAllIndexes().containsKey(pkConstraintName)) { + IndexMeta index = tm.getAllIndexes().get(pkConstraintName); + index.setIndextype(IndexType.PRIMARY); + } else { + //save the columns that constraint primary key name was different from unique index name + pkcol.add(rsPrimary.getString("COLUMN_NAME")); + } + } + //find the index that belong to the primary key constraint + if (!pkcol.isEmpty()) { + int matchCols = 0; + for (Map.Entry entry : tm.getAllIndexes().entrySet()) { + IndexMeta index = entry.getValue(); + // only the unique index and all the unique index's columes same as primary key columes, + // it belongs to primary key + if (index.getIndextype().value() == IndexType.UNIQUE.value()) { + for (ColumnMeta col : index.getValues()) { + if (pkcol.contains(col.getColumnName())) { + matchCols++; + } + } + if (matchCols == pkcol.size()) { + index.setIndextype(IndexType.PRIMARY); + // each table only has one primary key + break; + } else { + matchCols = 0; + } + } + } + } + } + return tm; + } +} diff --git a/rm-datasource/src/main/java/org/apache/seata/rm/datasource/undo/oscar/OscarUndoDeleteExecutor.java b/rm-datasource/src/main/java/org/apache/seata/rm/datasource/undo/oscar/OscarUndoDeleteExecutor.java new file mode 100644 index 00000000000..d41c32ea51d --- /dev/null +++ b/rm-datasource/src/main/java/org/apache/seata/rm/datasource/undo/oscar/OscarUndoDeleteExecutor.java @@ -0,0 +1,79 @@ +/* + * Copyright 1999-2019 Seata.io Group. + * + * Licensed 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.seata.rm.datasource.undo.oscar; + +import org.apache.seata.common.exception.ShouldNeverHappenException; +import org.apache.seata.common.util.CollectionUtils; +import org.apache.seata.rm.datasource.sql.struct.Field; +import org.apache.seata.rm.datasource.sql.struct.Row; +import org.apache.seata.rm.datasource.sql.struct.TableRecords; +import org.apache.seata.rm.datasource.undo.AbstractUndoExecutor; +import org.apache.seata.rm.datasource.undo.SQLUndoLog; +import org.apache.seata.sqlparser.util.ColumnUtils; +import org.apache.seata.sqlparser.util.JdbcConstants; + +import java.util.ArrayList; +import java.util.List; +import java.util.stream.Collectors; + +/** + * The type oscar undo delete executor. + * + * @author hsh + */ +public class OscarUndoDeleteExecutor extends AbstractUndoExecutor { + + /** + * INSERT INTO a (x, y, z, pk) VALUES (?, ?, ?, ?) + */ + private static final String INSERT_SQL_TEMPLATE = "INSERT INTO %s (%s) VALUES (%s)"; + + /** + * Instantiates a new oscar undo delete executor. + * + * @param sqlUndoLog the sql undo log + */ + public OscarUndoDeleteExecutor(SQLUndoLog sqlUndoLog) { + super(sqlUndoLog); + } + + @Override + protected String buildUndoSQL() { + TableRecords beforeImage = sqlUndoLog.getBeforeImage(); + List beforeImageRows = beforeImage.getRows(); + if (CollectionUtils.isEmpty(beforeImageRows)) { + throw new ShouldNeverHappenException("Invalid UNDO LOG"); + } + Row row = beforeImageRows.get(0); + List fields = new ArrayList<>(row.nonPrimaryKeys()); + fields.addAll(getOrderedPkList(beforeImage,row,JdbcConstants.ORACLE)); + + // delete sql undo log before image all field come from table meta, need add escape. + // see BaseTransactionalExecutor#buildTableRecords + String insertColumns = fields.stream() + .map(field -> ColumnUtils.addEscape(field.getName(), JdbcConstants.OSCAR)) + .collect(Collectors.joining(", ")); + String insertValues = fields.stream().map(field -> "?") + .collect(Collectors.joining(", ")); + + return String.format(INSERT_SQL_TEMPLATE, sqlUndoLog.getTableName(), insertColumns, insertValues); + } + + @Override + protected TableRecords getUndoRows() { + return sqlUndoLog.getBeforeImage(); + } +} diff --git a/rm-datasource/src/main/java/org/apache/seata/rm/datasource/undo/oscar/OscarUndoExecutorHolder.java b/rm-datasource/src/main/java/org/apache/seata/rm/datasource/undo/oscar/OscarUndoExecutorHolder.java new file mode 100644 index 00000000000..e0f83058e8a --- /dev/null +++ b/rm-datasource/src/main/java/org/apache/seata/rm/datasource/undo/oscar/OscarUndoExecutorHolder.java @@ -0,0 +1,46 @@ +/* + * Copyright 1999-2019 Seata.io Group. + * + * Licensed 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.seata.rm.datasource.undo.oscar; + +import org.apache.seata.common.loader.LoadLevel; +import org.apache.seata.rm.datasource.undo.AbstractUndoExecutor; +import org.apache.seata.rm.datasource.undo.SQLUndoLog; +import org.apache.seata.rm.datasource.undo.UndoExecutorHolder; +import org.apache.seata.sqlparser.util.JdbcConstants; + +/** + * The Type OscarUndoExecutorHolder + * + * @author Zhibei Hao + */ +@LoadLevel(name = JdbcConstants.OSCAR) +public class OscarUndoExecutorHolder implements UndoExecutorHolder { + + @Override + public AbstractUndoExecutor getInsertExecutor(SQLUndoLog sqlUndoLog) { + return new OscarUndoInsertExecutor(sqlUndoLog); + } + + @Override + public AbstractUndoExecutor getUpdateExecutor(SQLUndoLog sqlUndoLog) { + return new OscarUndoUpdateExecutor(sqlUndoLog); + } + + @Override + public AbstractUndoExecutor getDeleteExecutor(SQLUndoLog sqlUndoLog) { + return new OscarUndoDeleteExecutor(sqlUndoLog); + } +} diff --git a/rm-datasource/src/main/java/org/apache/seata/rm/datasource/undo/oscar/OscarUndoInsertExecutor.java b/rm-datasource/src/main/java/org/apache/seata/rm/datasource/undo/oscar/OscarUndoInsertExecutor.java new file mode 100644 index 00000000000..64261f80562 --- /dev/null +++ b/rm-datasource/src/main/java/org/apache/seata/rm/datasource/undo/oscar/OscarUndoInsertExecutor.java @@ -0,0 +1,86 @@ +/* + * Copyright 1999-2019 Seata.io Group. + * + * Licensed 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.seata.rm.datasource.undo.oscar; + +import org.apache.seata.common.exception.ShouldNeverHappenException; +import org.apache.seata.common.util.CollectionUtils; +import org.apache.seata.rm.datasource.SqlGenerateUtils; +import org.apache.seata.rm.datasource.sql.struct.Field; +import org.apache.seata.rm.datasource.sql.struct.Row; +import org.apache.seata.rm.datasource.sql.struct.TableRecords; +import org.apache.seata.rm.datasource.undo.AbstractUndoExecutor; +import org.apache.seata.rm.datasource.undo.SQLUndoLog; +import org.apache.seata.sqlparser.util.JdbcConstants; + +import java.sql.PreparedStatement; +import java.sql.SQLException; +import java.util.ArrayList; +import java.util.List; +import java.util.stream.Collectors; + +/** + * The type oscar undo insert executor. + * + * @author hsh + */ +public class OscarUndoInsertExecutor extends AbstractUndoExecutor { + + /** + * DELETE FROM a WHERE pk = ? + */ + private static final String DELETE_SQL_TEMPLATE = "DELETE FROM %s WHERE %s "; + + @Override + protected String buildUndoSQL() { + TableRecords afterImage = sqlUndoLog.getAfterImage(); + List afterImageRows = afterImage.getRows(); + if (CollectionUtils.isEmpty(afterImageRows)) { + throw new ShouldNeverHappenException("Invalid UNDO LOG"); + } + return generateDeleteSql(afterImageRows,afterImage); + } + + @Override + protected void undoPrepare(PreparedStatement undoPST, ArrayList undoValues, List pkValueList) + throws SQLException { + int undoIndex = 0; + for (Field pkField:pkValueList) { + undoIndex++; + undoPST.setObject(undoIndex, pkField.getValue(), pkField.getType()); + } + } + + private String generateDeleteSql(List rows, TableRecords afterImage) { + List pkNameList = getOrderedPkList(afterImage, rows.get(0), JdbcConstants.OSCAR).stream().map( + e -> e.getName()).collect(Collectors.toList()); + String whereSql = SqlGenerateUtils.buildWhereConditionByPKs(pkNameList, JdbcConstants.OSCAR); + return String.format(DELETE_SQL_TEMPLATE, sqlUndoLog.getTableName(), whereSql); + } + + /** + * Instantiates a new Oscar undo insert executor. + * + * @param sqlUndoLog the sql undo log + */ + public OscarUndoInsertExecutor(SQLUndoLog sqlUndoLog) { + super(sqlUndoLog); + } + + @Override + protected TableRecords getUndoRows() { + return sqlUndoLog.getAfterImage(); + } +} diff --git a/rm-datasource/src/main/java/org/apache/seata/rm/datasource/undo/oscar/OscarUndoLogManager.java b/rm-datasource/src/main/java/org/apache/seata/rm/datasource/undo/oscar/OscarUndoLogManager.java new file mode 100644 index 00000000000..35d4d30b44c --- /dev/null +++ b/rm-datasource/src/main/java/org/apache/seata/rm/datasource/undo/oscar/OscarUndoLogManager.java @@ -0,0 +1,105 @@ +/* + * Copyright 1999-2019 Seata.io Group. + * + * Licensed 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.seata.rm.datasource.undo.oscar; + +import org.apache.seata.common.loader.LoadLevel; +import org.apache.seata.common.util.DateUtil; +import org.apache.seata.core.compressor.CompressorType; +import org.apache.seata.core.constants.ClientTableColumnsName; +import org.apache.seata.rm.datasource.undo.AbstractUndoLogManager; +import org.apache.seata.rm.datasource.undo.UndoLogParser; +import org.apache.seata.sqlparser.util.JdbcConstants; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.sql.Connection; +import java.sql.PreparedStatement; +import java.sql.SQLException; +import java.util.Date; + +/** + * @author hsh + */ +@LoadLevel(name = JdbcConstants.OSCAR) +public class OscarUndoLogManager extends AbstractUndoLogManager { + + private static final Logger LOGGER = LoggerFactory.getLogger(OscarUndoLogManager.class); + + private static final String CHECK_UNDO_LOG_TABLE_EXIST_SQL = "SELECT 1 FROM " + UNDO_LOG_TABLE_NAME + " WHERE ROWNUM = 1"; + + private static final String INSERT_UNDO_LOG_SQL = "INSERT INTO " + UNDO_LOG_TABLE_NAME + + " (" + ClientTableColumnsName.UNDO_LOG_ID + "," + ClientTableColumnsName.UNDO_LOG_BRANCH_XID + ", " + + ClientTableColumnsName.UNDO_LOG_XID + ", " + ClientTableColumnsName.UNDO_LOG_CONTEXT + ", " + + ClientTableColumnsName.UNDO_LOG_ROLLBACK_INFO + ", " + ClientTableColumnsName.UNDO_LOG_LOG_STATUS + ", " + + ClientTableColumnsName.UNDO_LOG_LOG_CREATED + ", " + ClientTableColumnsName.UNDO_LOG_LOG_MODIFIED + ")" + + "VALUES (UNDO_LOG_SEQ.nextval, ?, ?, ?, ?, ?, sysdate, sysdate)"; + + private static final String DELETE_UNDO_LOG_BY_CREATE_SQL = "DELETE FROM " + UNDO_LOG_TABLE_NAME + " WHERE " + ClientTableColumnsName.UNDO_LOG_LOG_CREATED + " <= to_date(?,'yyyy-mm-dd hh24:mi:ss') and ROWNUM <= ?"; + + @Override + public int deleteUndoLogByLogCreated(Date logCreated, int limitRows, Connection conn) throws SQLException { + try (PreparedStatement deletePST = conn.prepareStatement(DELETE_UNDO_LOG_BY_CREATE_SQL)) { + String dateStr = DateUtil.formatDate(logCreated, "yyyy-MM-dd HH:mm:ss"); + deletePST.setString(1, dateStr); + deletePST.setInt(2, limitRows); + int deleteRows = deletePST.executeUpdate(); + if (LOGGER.isDebugEnabled()) { + LOGGER.debug("batch delete undo log size {}", deleteRows); + } + return deleteRows; + } catch (Exception e) { + if (!(e instanceof SQLException)) { + e = new SQLException(e); + } + throw (SQLException) e; + } + } + + @Override + protected void insertUndoLogWithNormal(String xid, long branchId, String rollbackCtx, byte[] undoLogContent, + Connection conn) throws SQLException { + insertUndoLog(xid, branchId,rollbackCtx, undoLogContent, State.Normal, conn); + } + + @Override + protected void insertUndoLogWithGlobalFinished(String xid, long branchId, UndoLogParser parser, Connection conn) throws SQLException { + insertUndoLog(xid, branchId, buildContext(parser.getName(), CompressorType.NONE), parser.getDefaultContent(), + State.GlobalFinished, conn); + } + + + private void insertUndoLog(String xid, long branchID, String rollbackCtx, byte[] undoLogContent, + State state, Connection conn) throws SQLException { + try (PreparedStatement pst = conn.prepareStatement(INSERT_UNDO_LOG_SQL)) { + pst.setLong(1, branchID); + pst.setString(2, xid); + pst.setString(3, rollbackCtx); + pst.setBytes(4, undoLogContent); + pst.setInt(5, state.getValue()); + pst.executeUpdate(); + } catch (Exception e) { + if (!(e instanceof SQLException)) { + e = new SQLException(e); + } + throw (SQLException) e; + } + } + + @Override + protected String getCheckUndoLogTableExistSql() { + return CHECK_UNDO_LOG_TABLE_EXIST_SQL; + } +} diff --git a/rm-datasource/src/main/java/org/apache/seata/rm/datasource/undo/oscar/OscarUndoUpdateExecutor.java b/rm-datasource/src/main/java/org/apache/seata/rm/datasource/undo/oscar/OscarUndoUpdateExecutor.java new file mode 100644 index 00000000000..bb9321e28ba --- /dev/null +++ b/rm-datasource/src/main/java/org/apache/seata/rm/datasource/undo/oscar/OscarUndoUpdateExecutor.java @@ -0,0 +1,80 @@ +/* + * Copyright 1999-2019 Seata.io Group. + * + * Licensed 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.seata.rm.datasource.undo.oscar; + +import org.apache.seata.common.exception.ShouldNeverHappenException; +import org.apache.seata.common.util.CollectionUtils; +import org.apache.seata.rm.datasource.SqlGenerateUtils; +import org.apache.seata.rm.datasource.sql.struct.Field; +import org.apache.seata.rm.datasource.sql.struct.Row; +import org.apache.seata.rm.datasource.sql.struct.TableRecords; +import org.apache.seata.rm.datasource.undo.AbstractUndoExecutor; +import org.apache.seata.rm.datasource.undo.SQLUndoLog; +import org.apache.seata.sqlparser.util.ColumnUtils; +import org.apache.seata.sqlparser.util.JdbcConstants; + +import java.util.List; +import java.util.stream.Collectors; + +/** + * The type oscar undo update executor. + * + * @author hsh + */ +public class OscarUndoUpdateExecutor extends AbstractUndoExecutor { + + /** + * UPDATE a SET x = ?, y = ?, z = ? WHERE pk1 = ? and pk2 = ? + */ + private static final String UPDATE_SQL_TEMPLATE = "UPDATE %s SET %s WHERE %s "; + + @Override + protected String buildUndoSQL() { + TableRecords beforeImage = sqlUndoLog.getBeforeImage(); + List beforeImageRows = beforeImage.getRows(); + if (CollectionUtils.isEmpty(beforeImageRows)) { + throw new ShouldNeverHappenException("Invalid UNDO LOG"); + } + Row row = beforeImageRows.get(0); + + List nonPkFields = row.nonPrimaryKeys(); + // update sql undo log before image all field come from table meta. need add escape. + // see BaseTransactionalExecutor#buildTableRecords + String updateColumns = nonPkFields.stream().map( + field -> ColumnUtils.addEscape(field.getName(), JdbcConstants.ORACLE) + " = ?").collect( + Collectors.joining(", ")); + + List pkNameList = getOrderedPkList(beforeImage, row, JdbcConstants.ORACLE).stream().map( + e -> e.getName()).collect(Collectors.toList()); + String whereSql = SqlGenerateUtils.buildWhereConditionByPKs(pkNameList, JdbcConstants.ORACLE); + + return String.format(UPDATE_SQL_TEMPLATE, sqlUndoLog.getTableName(), updateColumns, whereSql); + } + + /** + * Instantiates a new Oscar undo update executor. + * + * @param sqlUndoLog the sql undo log + */ + public OscarUndoUpdateExecutor(SQLUndoLog sqlUndoLog) { + super(sqlUndoLog); + } + + @Override + protected TableRecords getUndoRows() { + return sqlUndoLog.getBeforeImage(); + } +} diff --git a/rm-datasource/src/main/resources/META-INF/services/org.apache.seata.rm.datasource.exec.InsertExecutor b/rm-datasource/src/main/resources/META-INF/services/org.apache.seata.rm.datasource.exec.InsertExecutor index f928928e1dd..ba9cd4f2560 100644 --- a/rm-datasource/src/main/resources/META-INF/services/org.apache.seata.rm.datasource.exec.InsertExecutor +++ b/rm-datasource/src/main/resources/META-INF/services/org.apache.seata.rm.datasource.exec.InsertExecutor @@ -20,4 +20,5 @@ org.apache.seata.rm.datasource.exec.postgresql.PostgresqlInsertExecutor org.apache.seata.rm.datasource.exec.sqlserver.SqlServerInsertExecutor org.apache.seata.rm.datasource.exec.mariadb.MariadbInsertExecutor org.apache.seata.rm.datasource.exec.polardbx.PolarDBXInsertExecutor -org.apache.seata.rm.datasource.exec.dm.DmInsertExecutor \ No newline at end of file +org.apache.seata.rm.datasource.exec.dm.DmInsertExecutor +org.apache.seata.rm.datasource.exec.oscar.OscarInsertExecutor \ No newline at end of file diff --git a/rm-datasource/src/main/resources/META-INF/services/org.apache.seata.rm.datasource.undo.UndoExecutorHolder b/rm-datasource/src/main/resources/META-INF/services/org.apache.seata.rm.datasource.undo.UndoExecutorHolder index 4bad8e9af02..745542f09fc 100644 --- a/rm-datasource/src/main/resources/META-INF/services/org.apache.seata.rm.datasource.undo.UndoExecutorHolder +++ b/rm-datasource/src/main/resources/META-INF/services/org.apache.seata.rm.datasource.undo.UndoExecutorHolder @@ -20,4 +20,5 @@ org.apache.seata.rm.datasource.undo.postgresql.PostgresqlUndoExecutorHolder org.apache.seata.rm.datasource.undo.sqlserver.SqlServerUndoExecutorHolder org.apache.seata.rm.datasource.undo.mariadb.MariadbUndoExecutorHolder org.apache.seata.rm.datasource.undo.polardbx.PolarDBXUndoExecutorHolder -org.apache.seata.rm.datasource.undo.dm.DmUndoExecutorHolder \ No newline at end of file +org.apache.seata.rm.datasource.undo.dm.DmUndoExecutorHolder +org.apache.seata.rm.datasource.undo.oscar.OscarUndoExecutorHolder \ No newline at end of file diff --git a/rm-datasource/src/main/resources/META-INF/services/org.apache.seata.rm.datasource.undo.UndoLogManager b/rm-datasource/src/main/resources/META-INF/services/org.apache.seata.rm.datasource.undo.UndoLogManager index a18cb71ab84..8cec7126daf 100644 --- a/rm-datasource/src/main/resources/META-INF/services/org.apache.seata.rm.datasource.undo.UndoLogManager +++ b/rm-datasource/src/main/resources/META-INF/services/org.apache.seata.rm.datasource.undo.UndoLogManager @@ -20,4 +20,5 @@ org.apache.seata.rm.datasource.undo.postgresql.PostgresqlUndoLogManager org.apache.seata.rm.datasource.undo.sqlserver.SqlServerUndoLogManager org.apache.seata.rm.datasource.undo.mariadb.MariadbUndoLogManager org.apache.seata.rm.datasource.undo.polardbx.PolarDBXUndoLogManager -org.apache.seata.rm.datasource.undo.dm.DmUndoLogManager \ No newline at end of file +org.apache.seata.rm.datasource.undo.dm.DmUndoLogManager +org.apache.seata.rm.datasource.undo.oscar.OscarUndoLogManager \ No newline at end of file diff --git a/rm-datasource/src/main/resources/META-INF/services/org.apache.seata.sqlparser.EscapeHandler b/rm-datasource/src/main/resources/META-INF/services/org.apache.seata.sqlparser.EscapeHandler index c4f82c85498..c432d7c5ad1 100644 --- a/rm-datasource/src/main/resources/META-INF/services/org.apache.seata.sqlparser.EscapeHandler +++ b/rm-datasource/src/main/resources/META-INF/services/org.apache.seata.sqlparser.EscapeHandler @@ -20,4 +20,5 @@ org.apache.seata.rm.datasource.sql.handler.postgresql.PostgresqlEscapeHandler org.apache.seata.rm.datasource.sql.handler.mariadb.MariadbEscapeHandler org.apache.seata.rm.datasource.sql.handler.sqlserver.SqlServerEscapeHandler org.apache.seata.rm.datasource.sql.handler.polardbx.PolarDBXEscapeHandler -org.apache.seata.rm.datasource.sql.handler.dm.DmEscapeHandler \ No newline at end of file +org.apache.seata.rm.datasource.sql.handler.dm.DmEscapeHandler +org.apache.seata.rm.datasource.sql.handler.oscar.OscarEscapeHandler \ No newline at end of file diff --git a/rm-datasource/src/main/resources/META-INF/services/org.apache.seata.sqlparser.struct.TableMetaCache b/rm-datasource/src/main/resources/META-INF/services/org.apache.seata.sqlparser.struct.TableMetaCache index 1b09044c0f6..73762618efc 100644 --- a/rm-datasource/src/main/resources/META-INF/services/org.apache.seata.sqlparser.struct.TableMetaCache +++ b/rm-datasource/src/main/resources/META-INF/services/org.apache.seata.sqlparser.struct.TableMetaCache @@ -20,4 +20,5 @@ org.apache.seata.rm.datasource.sql.struct.cache.PostgresqlTableMetaCache org.apache.seata.rm.datasource.sql.struct.cache.SqlServerTableMetaCache org.apache.seata.rm.datasource.sql.struct.cache.MariadbTableMetaCache org.apache.seata.rm.datasource.sql.struct.cache.PolarDBXTableMetaCache -org.apache.seata.rm.datasource.sql.struct.cache.DmTableMetaCache \ No newline at end of file +org.apache.seata.rm.datasource.sql.struct.cache.DmTableMetaCache +org.apache.seata.rm.datasource.sql.struct.cache.OscarTableMetaCache \ No newline at end of file diff --git a/rm-datasource/src/test/java/org/apache/seata/rm/datasource/exec/OscarInsertExecutorTest.java b/rm-datasource/src/test/java/org/apache/seata/rm/datasource/exec/OscarInsertExecutorTest.java new file mode 100644 index 00000000000..40439c101b3 --- /dev/null +++ b/rm-datasource/src/test/java/org/apache/seata/rm/datasource/exec/OscarInsertExecutorTest.java @@ -0,0 +1,445 @@ +/* + * Copyright 1999-2019 Seata.io Group. + * + * Licensed 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.seata.rm.datasource.exec; + +import org.apache.seata.common.exception.NotSupportYetException; +import org.apache.seata.rm.datasource.ConnectionProxy; +import org.apache.seata.rm.datasource.PreparedStatementProxy; +import org.apache.seata.rm.datasource.StatementProxy; +import org.apache.seata.rm.datasource.exec.oscar.OscarInsertExecutor; +import org.apache.seata.sqlparser.SQLInsertRecognizer; +import org.apache.seata.sqlparser.struct.ColumnMeta; +import org.apache.seata.sqlparser.struct.Null; +import org.apache.seata.sqlparser.struct.SqlSequenceExpr; +import org.apache.seata.sqlparser.struct.TableMeta; +import org.apache.seata.sqlparser.util.JdbcConstants; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.mockito.Mockito; + +import java.sql.ResultSet; +import java.sql.SQLException; +import java.util.*; + +import static org.mockito.Mockito.*; + +/** + * @author hsh + */ +public class OscarInsertExecutorTest { + + private static final String ID_COLUMN = "id"; + private static final String USER_ID_COLUMN = "user_id"; + private static final String USER_NAME_COLUMN = "user_name"; + private static final String USER_STATUS_COLUMN = "user_status"; + private static final Integer PK_VALUE_ID = 100; + private static final Integer PK_VALUE_USER_ID = 200; + + private ConnectionProxy connectionProxy; + + private StatementProxy statementProxy; + + private SQLInsertRecognizer sqlInsertRecognizer; + + private StatementCallback statementCallback; + + private TableMeta tableMeta; + + private OscarInsertExecutor insertExecutor; + + private final int pkIndexId = 0; + + private final int pkIndexUserId = 1; + + private HashMap pkIndexMap; + + private HashMap multiPkIndexMap; + + @BeforeEach + public void init() { + connectionProxy = mock(ConnectionProxy.class); + when(connectionProxy.getDbType()).thenReturn(JdbcConstants.OSCAR); + + statementProxy = mock(PreparedStatementProxy.class); + when(statementProxy.getConnectionProxy()).thenReturn(connectionProxy); + + statementCallback = mock(StatementCallback.class); + sqlInsertRecognizer = mock(SQLInsertRecognizer.class); + tableMeta = mock(TableMeta.class); + insertExecutor = Mockito.spy(new OscarInsertExecutor(statementProxy, statementCallback, sqlInsertRecognizer)); + + pkIndexMap = new HashMap() {{ + put(ID_COLUMN, pkIndexId); + }}; + + multiPkIndexMap = new HashMap() {{ + put(ID_COLUMN, pkIndexId); + put(USER_ID_COLUMN, pkIndexUserId); + }}; + } + + @Test + public void testPkValue_sequence() throws Exception { + mockInsertColumns(); + SqlSequenceExpr expr = mockParametersPkWithSeq(); + doReturn(tableMeta).when(insertExecutor).getTableMeta(); + when(tableMeta.getPrimaryKeyOnlyName()).thenReturn(Arrays.asList(new String[]{ID_COLUMN})); + List pkValuesSeq = new ArrayList<>(); + pkValuesSeq.add(PK_VALUE_ID); + + doReturn(pkValuesSeq).when(insertExecutor).getPkValuesBySequence(expr, ID_COLUMN); + doReturn(pkIndexMap).when(insertExecutor).getPkIndex(); + + Map> pkValuesByColumn = insertExecutor.getPkValuesByColumn(); + verify(insertExecutor).getPkValuesBySequence(expr, ID_COLUMN); + Assertions.assertEquals(pkValuesByColumn.get(ID_COLUMN), pkValuesSeq); + } + + @Test + public void testMultiPkValue_sequence() throws Exception { + mockInsertColumns(); + SqlSequenceExpr expr = mockParametersMultiPkWithSeq(); + doReturn(tableMeta).when(insertExecutor).getTableMeta(); + when(tableMeta.getPrimaryKeyOnlyName()).thenReturn(Arrays.asList(new String[]{ID_COLUMN, USER_ID_COLUMN})); + List pkValuesSeqId = new ArrayList<>(); + pkValuesSeqId.add(PK_VALUE_ID); + List pkValuesSeqUserId = new ArrayList<>(); + pkValuesSeqUserId.add(PK_VALUE_USER_ID); + + doReturn(pkValuesSeqId).when(insertExecutor).getPkValuesBySequence(expr, ID_COLUMN); + doReturn(pkValuesSeqUserId).when(insertExecutor).getPkValuesBySequence(expr, USER_ID_COLUMN); + doReturn(multiPkIndexMap).when(insertExecutor).getPkIndex(); + + Map> pkValuesByColumn = insertExecutor.getPkValuesByColumn(); + verify(insertExecutor).getPkValuesBySequence(expr, ID_COLUMN); + verify(insertExecutor).getPkValuesBySequence(expr, USER_ID_COLUMN); + Assertions.assertEquals(pkValuesByColumn.get(ID_COLUMN), pkValuesSeqId); + Assertions.assertEquals(pkValuesByColumn.get(USER_ID_COLUMN), pkValuesSeqUserId); + } + + @Test + public void testPkValue_auto() throws Exception { + mockInsertColumns(); + mockParametersPkWithAuto(); + doReturn(tableMeta).when(insertExecutor).getTableMeta(); + doReturn(pkIndexMap).when(insertExecutor).getPkIndex(); + when(tableMeta.getPrimaryKeyOnlyName()).thenReturn(Arrays.asList(new String[]{ID_COLUMN})); + doReturn(Arrays.asList(new Object[]{PK_VALUE_ID})).when(insertExecutor).getGeneratedKeys(ID_COLUMN); + Map> pkValuesByAuto = insertExecutor.getPkValues(); + + verify(insertExecutor).getGeneratedKeys(ID_COLUMN); + Assertions.assertEquals(pkValuesByAuto.get(ID_COLUMN), Arrays.asList(new Object[]{PK_VALUE_ID})); + } + + @Test + public void testMultiPkValue_auto() throws Exception { + mockInsertColumns(); + mockParametersMultiPkWithAuto(); + doReturn(tableMeta).when(insertExecutor).getTableMeta(); + doReturn(multiPkIndexMap).when(insertExecutor).getPkIndex(); + when(tableMeta.getPrimaryKeyOnlyName()).thenReturn(Arrays.asList(new String[]{ID_COLUMN, USER_ID_COLUMN})); + Assertions.assertThrows(NotSupportYetException.class, () -> { + insertExecutor.getPkValues(); + }); + + + } + + @Test + public void testStatement_pkValueByAuto_NotSupportYetException() throws Exception { + mockInsertColumns(); + mockStatementInsertRows(); + + statementProxy = mock(StatementProxy.class); + when(statementProxy.getConnectionProxy()).thenReturn(connectionProxy); + when(connectionProxy.getDbType()).thenReturn(JdbcConstants.ORACLE); + + insertExecutor = Mockito.spy(new OscarInsertExecutor(statementProxy, statementCallback, sqlInsertRecognizer)); + + doReturn(tableMeta).when(insertExecutor).getTableMeta(); + + Map map = new HashMap<>(); + map.put(ID_COLUMN, mock(ColumnMeta.class)); + doReturn(map).when(tableMeta).getPrimaryKeyMap(); + + ResultSet rs = mock(ResultSet.class); + doReturn(rs).when(statementProxy).getGeneratedKeys(); + doReturn(false).when(rs).next(); + + Assertions.assertThrows(NotSupportYetException.class, () -> { + insertExecutor.getGeneratedKeys(ID_COLUMN); + }); + + doReturn(pkIndexMap).when(insertExecutor).getPkIndex(); + + Assertions.assertThrows(NotSupportYetException.class, () -> { + insertExecutor.getPkValuesByColumn(); + }); + + } + + @Test + public void testGetPkValues_SinglePk() throws SQLException { + doReturn(tableMeta).when(insertExecutor).getTableMeta(); + + List pkColumns = new ArrayList<>(); + pkColumns.add(ID_COLUMN); + doReturn(pkColumns).when(tableMeta).getPrimaryKeyOnlyName(); + + // mock pk values from insert rows + Map> mockPkValuesFromColumn = new HashMap<>(); + mockPkValuesFromColumn.put(ID_COLUMN, Collections.singletonList(PK_VALUE_ID + 1)); + doReturn(mockPkValuesFromColumn).when(insertExecutor).getPkValuesByColumn(); + + // mock pk values from auto increment + List mockPkValuesAutoGenerated = Collections.singletonList(PK_VALUE_ID); + doReturn(mockPkValuesAutoGenerated).when(insertExecutor).getGeneratedKeys(ID_COLUMN); + + // situation1: insert columns are empty + List columns = new ArrayList<>(); + when(sqlInsertRecognizer.getInsertColumns()).thenReturn(columns); + when(sqlInsertRecognizer.insertColumnsIsEmpty()).thenReturn(true); + Assertions.assertIterableEquals(mockPkValuesFromColumn.entrySet(), insertExecutor.getPkValues().entrySet()); + + // situation2: insert columns contain the pk column + columns = new ArrayList<>(); + columns.add(ID_COLUMN); + columns.add(USER_NAME_COLUMN); + when(sqlInsertRecognizer.getInsertColumns()).thenReturn(columns); + when(sqlInsertRecognizer.insertColumnsIsEmpty()).thenReturn(false); + Assertions.assertIterableEquals(mockPkValuesFromColumn.entrySet(), insertExecutor.getPkValues().entrySet()); + + // situation3: insert columns are not empty and do not contain the pk column + columns = new ArrayList<>(); + columns.add(USER_NAME_COLUMN); + when(sqlInsertRecognizer.getInsertColumns()).thenReturn(columns); + when(sqlInsertRecognizer.insertColumnsIsEmpty()).thenReturn(false); + Assertions.assertIterableEquals( + Collections.singletonMap(ID_COLUMN, mockPkValuesAutoGenerated).entrySet(), + insertExecutor.getPkValues().entrySet()); + } + + @Test + public void testGetPkValues_MultiPk() throws SQLException { + doReturn(tableMeta).when(insertExecutor).getTableMeta(); + + List pkColumns = new ArrayList<>(); + pkColumns.add(ID_COLUMN); + pkColumns.add(USER_ID_COLUMN); + doReturn(pkColumns).when(tableMeta).getPrimaryKeyOnlyName(); + + // mock all pk values from insert rows + Map> mockAllPkValuesFromColumn = new HashMap<>(); + mockAllPkValuesFromColumn.put(ID_COLUMN, Collections.singletonList(PK_VALUE_ID + 1)); + mockAllPkValuesFromColumn.put(USER_ID_COLUMN, Collections.singletonList(PK_VALUE_USER_ID + 1)); + doReturn(mockAllPkValuesFromColumn).when(insertExecutor).getPkValuesByColumn(); + + // mock pk values from auto increment + List mockPkValuesAutoGenerated_ID = Collections.singletonList(PK_VALUE_ID); + doReturn(mockPkValuesAutoGenerated_ID).when(insertExecutor).getGeneratedKeys(ID_COLUMN); + List mockPkValuesAutoGenerated_USER_ID = Collections.singletonList(PK_VALUE_USER_ID); + doReturn(mockPkValuesAutoGenerated_USER_ID).when(insertExecutor).getGeneratedKeys(USER_ID_COLUMN); + + // situation1: insert columns are empty + List insertColumns = new ArrayList<>(); + when(sqlInsertRecognizer.getInsertColumns()).thenReturn(insertColumns); + when(sqlInsertRecognizer.insertColumnsIsEmpty()).thenReturn(true); + Assertions.assertIterableEquals(mockAllPkValuesFromColumn.entrySet(), insertExecutor.getPkValues().entrySet()); + + // situation2: insert columns contain all pk columns + insertColumns = new ArrayList<>(); + insertColumns.add(ID_COLUMN); + insertColumns.add(USER_ID_COLUMN); + insertColumns.add(USER_NAME_COLUMN); + when(sqlInsertRecognizer.getInsertColumns()).thenReturn(insertColumns); + when(sqlInsertRecognizer.insertColumnsIsEmpty()).thenReturn(false); + Assertions.assertIterableEquals(mockAllPkValuesFromColumn.entrySet(), insertExecutor.getPkValues().entrySet()); + + // situation3: insert columns contain partial pk columns + insertColumns = new ArrayList<>(); + insertColumns.add(ID_COLUMN); + insertColumns.add(USER_NAME_COLUMN); + when(sqlInsertRecognizer.getInsertColumns()).thenReturn(insertColumns); + when(sqlInsertRecognizer.insertColumnsIsEmpty()).thenReturn(false); + + Map> mockPkValuesFromColumn_ID = new HashMap<>(); + mockPkValuesFromColumn_ID.put(ID_COLUMN, Collections.singletonList(PK_VALUE_ID + 1)); + doReturn(mockPkValuesFromColumn_ID).when(insertExecutor).getPkValuesByColumn(); + + Map> expectPkValues = new HashMap<>(mockPkValuesFromColumn_ID); + expectPkValues.put(USER_ID_COLUMN, mockPkValuesAutoGenerated_USER_ID); + Assertions.assertIterableEquals(expectPkValues.entrySet(), insertExecutor.getPkValues().entrySet()); + + // situation4: insert columns are not empty and do not contain the pk column + insertColumns = new ArrayList<>(); + insertColumns.add(USER_NAME_COLUMN); + when(sqlInsertRecognizer.getInsertColumns()).thenReturn(insertColumns); + when(sqlInsertRecognizer.insertColumnsIsEmpty()).thenReturn(false); + + doReturn(new HashMap<>()).when(insertExecutor).getPkValuesByColumn(); + + expectPkValues = new HashMap<>(); + expectPkValues.put(ID_COLUMN, mockPkValuesAutoGenerated_ID); + expectPkValues.put(USER_ID_COLUMN, mockPkValuesAutoGenerated_USER_ID); + Assertions.assertIterableEquals(expectPkValues.entrySet(), insertExecutor.getPkValues().entrySet()); + } + + @Test + public void testContainsAnyPK() { + doReturn(tableMeta).when(insertExecutor).getTableMeta(); + + Assertions.assertFalse(insertExecutor.containsAnyPk()); + + mockInsertColumns(); + doReturn(null).when(tableMeta).getPrimaryKeyOnlyName(); + Assertions.assertFalse(insertExecutor.containsAnyPk()); + + List pkColumns = new ArrayList<>(); + pkColumns.add(System.currentTimeMillis() + ""); + doReturn(pkColumns).when(tableMeta).getPrimaryKeyOnlyName(); + Assertions.assertFalse(insertExecutor.containsAnyPk()); + + pkColumns = new ArrayList<>(); + pkColumns.add(ID_COLUMN); + doReturn(pkColumns).when(tableMeta).getPrimaryKeyOnlyName(); + Assertions.assertTrue(insertExecutor.containsAnyPk()); + + pkColumns = new ArrayList<>(); + pkColumns.add(ID_COLUMN); + pkColumns.add(USER_ID_COLUMN); + doReturn(pkColumns).when(tableMeta).getPrimaryKeyOnlyName(); + Assertions.assertTrue(insertExecutor.containsAnyPk()); + + pkColumns = new ArrayList<>(); + pkColumns.add(ID_COLUMN); + pkColumns.add(System.currentTimeMillis() + ""); + doReturn(pkColumns).when(tableMeta).getPrimaryKeyOnlyName(); + Assertions.assertTrue(insertExecutor.containsAnyPk()); + } + + private List mockInsertColumns() { + List columns = new ArrayList<>(); + columns.add(ID_COLUMN); + columns.add(USER_ID_COLUMN); + columns.add(USER_NAME_COLUMN); + columns.add(USER_STATUS_COLUMN); + when(sqlInsertRecognizer.getInsertColumns()).thenReturn(columns); + return columns; + } + + private SqlSequenceExpr mockParametersPkWithSeq() { + SqlSequenceExpr expr = new SqlSequenceExpr("seq", "nextval"); + Map> paramters = new HashMap(4); + ArrayList arrayList0 = new ArrayList<>(); + arrayList0.add(expr); + ArrayList arrayList1 = new ArrayList<>(); + arrayList1.add("userId1"); + ArrayList arrayList2 = new ArrayList<>(); + arrayList2.add("userName1"); + ArrayList arrayList3 = new ArrayList<>(); + arrayList3.add("userStatus1"); + paramters.put(1, arrayList0); + paramters.put(2, arrayList1); + paramters.put(3, arrayList2); + paramters.put(4, arrayList3); + PreparedStatementProxy psp = (PreparedStatementProxy) this.statementProxy; + when(psp.getParameters()).thenReturn(paramters); + + List> rows = new ArrayList<>(); + rows.add(Arrays.asList("?", "?", "?")); + when(sqlInsertRecognizer.getInsertRows(pkIndexMap.values())).thenReturn(rows); + + return expr; + } + + private SqlSequenceExpr mockParametersMultiPkWithSeq() { + SqlSequenceExpr expr = new SqlSequenceExpr("seq", "nextval"); + Map> paramters = new HashMap(4); + ArrayList arrayList0 = new ArrayList<>(); + arrayList0.add(expr); + ArrayList arrayList1 = new ArrayList<>(); + arrayList1.add(expr); + ArrayList arrayList2 = new ArrayList<>(); + arrayList2.add("userName1"); + ArrayList arrayList3 = new ArrayList<>(); + arrayList3.add("userStatus1"); + paramters.put(1, arrayList0); + paramters.put(2, arrayList1); + paramters.put(3, arrayList2); + paramters.put(4, arrayList3); + PreparedStatementProxy psp = (PreparedStatementProxy) this.statementProxy; + when(psp.getParameters()).thenReturn(paramters); + + List> rows = new ArrayList<>(); + rows.add(Arrays.asList("?", "?")); + when(sqlInsertRecognizer.getInsertRows(multiPkIndexMap.values())).thenReturn(rows); + + return expr; + } + + private void mockParametersPkWithAuto() { + Map> paramters = new HashMap<>(4); + ArrayList arrayList0 = new ArrayList<>(); + arrayList0.add(Null.get()); + ArrayList arrayList1 = new ArrayList<>(); + arrayList1.add("userId1"); + ArrayList arrayList2 = new ArrayList<>(); + arrayList2.add("userName1"); + ArrayList arrayList3 = new ArrayList<>(); + arrayList3.add("userStatus1"); + paramters.put(1, arrayList0); + paramters.put(2, arrayList1); + paramters.put(3, arrayList2); + paramters.put(4, arrayList3); + PreparedStatementProxy psp = (PreparedStatementProxy) this.statementProxy; + when(psp.getParameters()).thenReturn(paramters); + + List> rows = new ArrayList<>(); + rows.add(Arrays.asList("?", "?", "?", "?")); + when(sqlInsertRecognizer.getInsertRows(pkIndexMap.values())).thenReturn(rows); + } + + private void mockParametersMultiPkWithAuto() { + Map> paramters = new HashMap<>(4); + ArrayList arrayList0 = new ArrayList<>(); + arrayList0.add(Null.get()); + ArrayList arrayList1 = new ArrayList<>(); + arrayList1.add(Null.get()); + ArrayList arrayList2 = new ArrayList<>(); + arrayList2.add("userName1"); + ArrayList arrayList3 = new ArrayList<>(); + arrayList3.add("userStatus1"); + paramters.put(1, arrayList0); + paramters.put(2, arrayList1); + paramters.put(3, arrayList2); + paramters.put(4, arrayList3); + PreparedStatementProxy psp = (PreparedStatementProxy) this.statementProxy; + when(psp.getParameters()).thenReturn(paramters); + + List> rows = new ArrayList<>(); + rows.add(Arrays.asList("?", "?", "?", "?")); + when(sqlInsertRecognizer.getInsertRows(multiPkIndexMap.values())).thenReturn(rows); + } + + private void mockStatementInsertRows() { + List> rows = new ArrayList<>(); + rows.add(Arrays.asList(Null.get(), "xx", "xx", "xx")); + when(sqlInsertRecognizer.getInsertRows(pkIndexMap.values())).thenReturn(rows); + } + + +} diff --git a/rm-datasource/src/test/java/org/apache/seata/rm/datasource/sql/druid/oscar/OscarDeleteRecognizerTest.java b/rm-datasource/src/test/java/org/apache/seata/rm/datasource/sql/druid/oscar/OscarDeleteRecognizerTest.java new file mode 100644 index 00000000000..389d09bbc9d --- /dev/null +++ b/rm-datasource/src/test/java/org/apache/seata/rm/datasource/sql/druid/oscar/OscarDeleteRecognizerTest.java @@ -0,0 +1,197 @@ +/* + * Copyright 1999-2019 Seata.io Group. + * + * Licensed 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.seata.rm.datasource.sql.druid.oscar; + +import com.alibaba.druid.sql.SQLUtils; +import com.alibaba.druid.sql.ast.SQLStatement; +import com.alibaba.druid.sql.ast.statement.SQLDeleteStatement; +import com.alibaba.druid.sql.dialect.oracle.ast.expr.OracleArgumentExpr; +import org.apache.seata.sqlparser.ParametersHolder; +import org.apache.seata.sqlparser.SQLType; +import org.apache.seata.sqlparser.druid.oscar.OscarDeleteRecognizer; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +/** + * @author hsh + */ +public class OscarDeleteRecognizerTest { + + private static final String DB_TYPE = "oscar"; + + @Test + public void testGetSqlType() { + String sql = "delete from t where id = ?"; + List asts = SQLUtils.parseStatements(sql, DB_TYPE); + + OscarDeleteRecognizer recognizer = new OscarDeleteRecognizer(sql, asts.get(0)); + Assertions.assertEquals(recognizer.getSQLType(), SQLType.DELETE); + } + + @Test + public void testGetTableAlias() { + String sql = "delete from t where id = ?"; + List asts = SQLUtils.parseStatements(sql, DB_TYPE); + + OscarDeleteRecognizer recognizer = new OscarDeleteRecognizer(sql, asts.get(0)); + Assertions.assertNull(recognizer.getTableAlias()); + } + + @Test + public void testGetTableName() { + String sql = "delete from t where id = ?"; + List asts = SQLUtils.parseStatements(sql, DB_TYPE); + + OscarDeleteRecognizer recognizer = new OscarDeleteRecognizer(sql, asts.get(0)); + Assertions.assertEquals(recognizer.getTableName(), "t"); + } + + @Test + public void testGetWhereCondition_0() { + String sql = "delete from t"; + List asts = SQLUtils.parseStatements(sql, DB_TYPE); + + OscarDeleteRecognizer recognizer = new OscarDeleteRecognizer(sql, asts.get(0)); + String whereCondition = recognizer.getWhereCondition(new ParametersHolder() { + @Override + public Map> getParameters() { + return null; + } + }, new ArrayList<>()); + + //test for no condition + Assertions.assertEquals("", whereCondition); + + sql = "delete from t where id = ?"; + asts = SQLUtils.parseStatements(sql, DB_TYPE); + + recognizer = new OscarDeleteRecognizer(sql, asts.get(0)); + whereCondition = recognizer.getWhereCondition(new ParametersHolder() { + @Override + public Map> getParameters() { + ArrayList idParam = new ArrayList<>(); + idParam.add(1); + Map result = new HashMap(); + result.put(1, idParam); + return result; + } + }, new ArrayList<>()); + + //test for normal sql + Assertions.assertEquals("id = ?", whereCondition); + + sql = "delete from t where id in (?)"; + asts = SQLUtils.parseStatements(sql, DB_TYPE); + recognizer = new OscarDeleteRecognizer(sql, asts.get(0)); + whereCondition = recognizer.getWhereCondition(new ParametersHolder() { + @Override + public Map> getParameters() { + ArrayList idParam = new ArrayList<>(); + idParam.add(1); + Map result = new HashMap(); + result.put(1, idParam); + return result; + } + }, new ArrayList<>()); + + //test for sql with in + Assertions.assertEquals("id IN (?)", whereCondition); + + sql = "delete from t where id between ? and ?"; + asts = SQLUtils.parseStatements(sql, DB_TYPE); + recognizer = new OscarDeleteRecognizer(sql, asts.get(0)); + whereCondition = recognizer.getWhereCondition(new ParametersHolder() { + @Override + public Map> getParameters() { + ArrayList idParam = new ArrayList<>(); + idParam.add(1); + ArrayList idParam2 = new ArrayList<>(); + idParam.add(2); + Map result = new HashMap(); + result.put(1, idParam); + result.put(2, idParam2); + return result; + } + }, new ArrayList<>()); + //test for sql with in + Assertions.assertEquals("id BETWEEN ? AND ?", whereCondition); + + //test for exception + Assertions.assertThrows(IllegalArgumentException.class, () -> { + String s = "delete from t where id in (?)"; + List sqlStatements = SQLUtils.parseStatements(s, DB_TYPE); + SQLDeleteStatement deleteAst = (SQLDeleteStatement) sqlStatements.get(0); + deleteAst.setWhere(new OracleArgumentExpr()); + new OscarDeleteRecognizer(s, deleteAst).getWhereCondition(new ParametersHolder() { + @Override + public Map> getParameters() { + return new HashMap<>(); + } + }, new ArrayList<>()); + }); + } + + @Test + public void testGetWhereCondition_1() { + + String sql = "delete from t"; + List asts = SQLUtils.parseStatements(sql, DB_TYPE); + + OscarDeleteRecognizer recognizer = new OscarDeleteRecognizer(sql, asts.get(0)); + String whereCondition = recognizer.getWhereCondition(); + + //test for no condition + Assertions.assertEquals("", whereCondition); + + sql = "delete from t where id = 1"; + asts = SQLUtils.parseStatements(sql, DB_TYPE); + + recognizer = new OscarDeleteRecognizer(sql, asts.get(0)); + whereCondition = recognizer.getWhereCondition(); + + //test for normal sql + Assertions.assertEquals("id = 1", whereCondition); + + sql = "delete from t where id in (1)"; + asts = SQLUtils.parseStatements(sql, DB_TYPE); + recognizer = new OscarDeleteRecognizer(sql, asts.get(0)); + whereCondition = recognizer.getWhereCondition(); + + //test for sql with in + Assertions.assertEquals("id IN (1)", whereCondition); + + sql = "delete from t where id between 1 and 2"; + asts = SQLUtils.parseStatements(sql, DB_TYPE); + recognizer = new OscarDeleteRecognizer(sql, asts.get(0)); + whereCondition = recognizer.getWhereCondition(); + //test for sql with in + Assertions.assertEquals("id BETWEEN 1 AND 2", whereCondition); + + //test for exception + Assertions.assertThrows(IllegalArgumentException.class, () -> { + String s = "delete from t where id in (1)"; + List sqlStatements = SQLUtils.parseStatements(s, DB_TYPE); + SQLDeleteStatement deleteAst = (SQLDeleteStatement) sqlStatements.get(0); + deleteAst.setWhere(new OracleArgumentExpr()); + new OscarDeleteRecognizer(s, deleteAst).getWhereCondition(); + }); + } +} diff --git a/rm-datasource/src/test/java/org/apache/seata/rm/datasource/sql/druid/oscar/OscarInsertRecognizerTest.java b/rm-datasource/src/test/java/org/apache/seata/rm/datasource/sql/druid/oscar/OscarInsertRecognizerTest.java new file mode 100644 index 00000000000..9f8dc375d1a --- /dev/null +++ b/rm-datasource/src/test/java/org/apache/seata/rm/datasource/sql/druid/oscar/OscarInsertRecognizerTest.java @@ -0,0 +1,129 @@ +/* + * Copyright 1999-2019 Seata.io Group. + * + * Licensed 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.seata.rm.datasource.sql.druid.oscar; + +import com.alibaba.druid.sql.SQLUtils; +import com.alibaba.druid.sql.ast.SQLStatement; +import com.alibaba.druid.sql.ast.statement.SQLInsertStatement; +import com.alibaba.druid.sql.dialect.oracle.ast.expr.OracleBinaryDoubleExpr; +import org.apache.seata.sqlparser.SQLParsingException; +import org.apache.seata.sqlparser.SQLType; +import org.apache.seata.sqlparser.druid.oscar.OscarInsertRecognizer; +import org.apache.seata.sqlparser.struct.NotPlaceholderExpr; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; + +import java.util.Collections; +import java.util.List; + +/** + * @author hsh + */ +public class OscarInsertRecognizerTest { + + private static final String DB_TYPE = "oscar"; + + @Test + public void testGetSqlType() { + String sql = "insert into t(id) values (?)"; + List asts = SQLUtils.parseStatements(sql, DB_TYPE); + + OscarInsertRecognizer recognizer = new OscarInsertRecognizer(sql, asts.get(0)); + Assertions.assertEquals(recognizer.getSQLType(), SQLType.INSERT); + } + + @Test + public void testGetTableAlias() { + String sql = "insert into t(id) values (?)"; + List asts = SQLUtils.parseStatements(sql, DB_TYPE); + + OscarInsertRecognizer recognizer = new OscarInsertRecognizer(sql, asts.get(0)); + Assertions.assertNull(recognizer.getTableAlias()); + } + + @Test + public void testGetTableName() { + String sql = "insert into t(id) values (?)"; + List asts = SQLUtils.parseStatements(sql, DB_TYPE); + + OscarInsertRecognizer recognizer = new OscarInsertRecognizer(sql, asts.get(0)); + Assertions.assertEquals(recognizer.getTableName(), "t"); + } + + @Test + public void testGetInsertColumns() { + + //test for no column + String sql = "insert into t values (?)"; + List asts = SQLUtils.parseStatements(sql, DB_TYPE); + + OscarInsertRecognizer recognizer = new OscarInsertRecognizer(sql, asts.get(0)); + List insertColumns = recognizer.getInsertColumns(); + Assertions.assertNull(insertColumns); + + //test for normal + sql = "insert into t(a) values (?)"; + asts = SQLUtils.parseStatements(sql, DB_TYPE); + + recognizer = new OscarInsertRecognizer(sql, asts.get(0)); + insertColumns = recognizer.getInsertColumns(); + Assertions.assertEquals(1, insertColumns.size()); + + //test for exception + Assertions.assertThrows(SQLParsingException.class, () -> { + String s = "insert into t(a) values (?)"; + List sqlStatements = SQLUtils.parseStatements(s, DB_TYPE); + SQLInsertStatement sqlInsertStatement = (SQLInsertStatement)sqlStatements.get(0); + sqlInsertStatement.getColumns().add(new OracleBinaryDoubleExpr()); + + OscarInsertRecognizer oscarInsertRecognizer = new OscarInsertRecognizer(s, sqlInsertStatement); + oscarInsertRecognizer.getInsertColumns(); + }); + } + + @Test + public void testGetInsertRows() { + final int pkIndex = 0; + //test for null value + String sql = "insert into t(id, no, name, age, time) values (id_seq.nextval, null, 'a', ?, now())"; + List asts = SQLUtils.parseStatements(sql, DB_TYPE); + + OscarInsertRecognizer recognizer = new OscarInsertRecognizer(sql, asts.get(0)); + List> insertRows = recognizer.getInsertRows(Collections.singletonList(pkIndex)); + Assertions.assertEquals(1, insertRows.size()); + + //test for exception + Assertions.assertThrows(SQLParsingException.class, () -> { + String s = "insert into t(a) values (?)"; + List sqlStatements = SQLUtils.parseStatements(s, DB_TYPE); + SQLInsertStatement sqlInsertStatement = (SQLInsertStatement)sqlStatements.get(0); + sqlInsertStatement.getValuesList().get(0).getValues().set(pkIndex, new OracleBinaryDoubleExpr()); + + OscarInsertRecognizer oscarInsertRecognizer = new OscarInsertRecognizer(s, sqlInsertStatement); + oscarInsertRecognizer.getInsertRows(Collections.singletonList(pkIndex)); + }); + } + + @Test + public void testNotPlaceholder_giveValidPkIndex() { + String sql = "insert into test(create_time) values(sysdate)"; + List sqlStatements = SQLUtils.parseStatements(sql, DB_TYPE); + + OscarInsertRecognizer oscar = new OscarInsertRecognizer(sql, sqlStatements.get(0)); + List> insertRows = oscar.getInsertRows(Collections.singletonList(-1)); + Assertions.assertTrue(insertRows.get(0).get(0) instanceof NotPlaceholderExpr); + } +} diff --git a/rm-datasource/src/test/java/org/apache/seata/rm/datasource/sql/druid/oscar/OscarSelectForUpdateRecognizerTest.java b/rm-datasource/src/test/java/org/apache/seata/rm/datasource/sql/druid/oscar/OscarSelectForUpdateRecognizerTest.java new file mode 100644 index 00000000000..969d7da3ca0 --- /dev/null +++ b/rm-datasource/src/test/java/org/apache/seata/rm/datasource/sql/druid/oscar/OscarSelectForUpdateRecognizerTest.java @@ -0,0 +1,110 @@ +/* + * Copyright 1999-2019 Seata.io Group. + * + * Licensed 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.seata.rm.datasource.sql.druid.oscar; + +import com.alibaba.druid.sql.SQLUtils; +import com.alibaba.druid.sql.ast.SQLStatement; +import com.alibaba.druid.sql.ast.statement.SQLSelectStatement; +import org.apache.seata.sqlparser.ParametersHolder; +import org.apache.seata.sqlparser.SQLParsingException; +import org.apache.seata.sqlparser.SQLType; +import org.apache.seata.sqlparser.druid.oscar.OscarSelectForUpdateRecognizer; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +/** + * @author hsh + */ +public class OscarSelectForUpdateRecognizerTest { + + private static final String DB_TYPE = "oscar"; + + @Test + public void testGetSqlType() { + String sql = "select * from t where id = ? for update"; + List asts = SQLUtils.parseStatements(sql, DB_TYPE); + + OscarSelectForUpdateRecognizer recognizer = new OscarSelectForUpdateRecognizer(sql, asts.get(0)); + Assertions.assertEquals(recognizer.getSQLType(), SQLType.SELECT_FOR_UPDATE); + } + + + @Test + public void testGetWhereCondition_0() { + String sql = "select * from t for update"; + List asts = SQLUtils.parseStatements(sql, DB_TYPE); + + OscarSelectForUpdateRecognizer recognizer = new OscarSelectForUpdateRecognizer(sql, asts.get(0)); + String whereCondition = recognizer.getWhereCondition(new ParametersHolder() { + @Override + public Map> getParameters() { + return null; + } + }, new ArrayList<>()); + Assertions.assertEquals("", whereCondition); + } + + @Test + public void testGetWhereCondition_1() { + String sql = "select * from t for update"; + List asts = SQLUtils.parseStatements(sql, DB_TYPE); + + OscarSelectForUpdateRecognizer recognizer = new OscarSelectForUpdateRecognizer(sql, asts.get(0)); + String whereCondition = recognizer.getWhereCondition(); + + Assertions.assertEquals("", whereCondition); + + //test for select was null + Assertions.assertThrows(SQLParsingException.class, () -> { + String s = "select * from t for update"; + List sqlStatements = SQLUtils.parseStatements(s, DB_TYPE); + SQLSelectStatement selectAst = (SQLSelectStatement) sqlStatements.get(0); + selectAst.setSelect(null); + new OscarSelectForUpdateRecognizer(s, selectAst).getWhereCondition(); + }); + + //test for query was null + Assertions.assertThrows(SQLParsingException.class, () -> { + String s = "select * from t"; + List sqlStatements = SQLUtils.parseStatements(s, DB_TYPE); + SQLSelectStatement selectAst = (SQLSelectStatement) sqlStatements.get(0); + selectAst.getSelect().setQuery(null); + new OscarSelectForUpdateRecognizer(s, selectAst).getWhereCondition(); + }); + } + + @Test + public void testGetTableAlias() { + String sql = "select * from t where id = ? for update"; + List asts = SQLUtils.parseStatements(sql, DB_TYPE); + + OscarSelectForUpdateRecognizer recognizer = new OscarSelectForUpdateRecognizer(sql, asts.get(0)); + Assertions.assertNull(recognizer.getTableAlias()); + } + + @Test + public void testGetTableName() { + String sql = "select * from t where id = ? for update"; + List asts = SQLUtils.parseStatements(sql, DB_TYPE); + + OscarSelectForUpdateRecognizer recognizer = new OscarSelectForUpdateRecognizer(sql, asts.get(0)); + Assertions.assertEquals(recognizer.getTableName(), "t"); + } +} diff --git a/rm-datasource/src/test/java/org/apache/seata/rm/datasource/sql/druid/oscar/OscarUpdateRecognizerTest.java b/rm-datasource/src/test/java/org/apache/seata/rm/datasource/sql/druid/oscar/OscarUpdateRecognizerTest.java new file mode 100644 index 00000000000..d0f5140659f --- /dev/null +++ b/rm-datasource/src/test/java/org/apache/seata/rm/datasource/sql/druid/oscar/OscarUpdateRecognizerTest.java @@ -0,0 +1,156 @@ +/* + * Copyright 1999-2019 Seata.io Group. + * + * Licensed 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.seata.rm.datasource.sql.druid.oscar; + +import com.alibaba.druid.sql.SQLUtils; +import com.alibaba.druid.sql.ast.SQLStatement; +import com.alibaba.druid.sql.ast.statement.SQLUpdateSetItem; +import com.alibaba.druid.sql.ast.statement.SQLUpdateStatement; +import com.alibaba.druid.sql.dialect.oracle.ast.expr.OracleCursorExpr; +import org.apache.seata.sqlparser.ParametersHolder; +import org.apache.seata.sqlparser.SQLParsingException; +import org.apache.seata.sqlparser.SQLType; +import org.apache.seata.sqlparser.druid.oscar.OscarUpdateRecognizer; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +/** + * @author hsh + */ +public class OscarUpdateRecognizerTest { + + private static final String DB_TYPE = "oscar"; + + @Test + public void testGetSqlType() { + String sql = "update t set n = ?"; + List asts = SQLUtils.parseStatements(sql, DB_TYPE); + + OscarUpdateRecognizer recognizer = new OscarUpdateRecognizer(sql, asts.get(0)); + Assertions.assertEquals(recognizer.getSQLType(), SQLType.UPDATE); + } + + @Test + public void testGetUpdateColumns() { + // test with normal + String sql = "update t set a = ?, b = ?, c = ?"; + List asts = SQLUtils.parseStatements(sql, DB_TYPE); + OscarUpdateRecognizer recognizer = new OscarUpdateRecognizer(sql, asts.get(0)); + List updateColumns = recognizer.getUpdateColumns(); + Assertions.assertEquals(updateColumns.size(), 3); + + // test with alias + sql = "update t set a.a = ?, a.b = ?, a.c = ?"; + asts = SQLUtils.parseStatements(sql, DB_TYPE); + recognizer = new OscarUpdateRecognizer(sql, asts.get(0)); + updateColumns = recognizer.getUpdateColumns(); + Assertions.assertEquals(updateColumns.size(), 3); + + //test with error + Assertions.assertThrows(SQLParsingException.class, () -> { + String s = "update t set a = a"; + List sqlStatements = SQLUtils.parseStatements(s, DB_TYPE); + SQLUpdateStatement sqlUpdateStatement = (SQLUpdateStatement) sqlStatements.get(0); + List updateSetItems = sqlUpdateStatement.getItems(); + for (SQLUpdateSetItem updateSetItem : updateSetItems) { + updateSetItem.setColumn(new OracleCursorExpr()); + } + OscarUpdateRecognizer oscarUpdateRecognizer = new OscarUpdateRecognizer(s, sqlUpdateStatement); + oscarUpdateRecognizer.getUpdateColumns(); + }); + } + + @Test + public void testGetUpdateValues() { + // test with normal + String sql = "update t set a = ?, b = ?, c = ?"; + List asts = SQLUtils.parseStatements(sql, DB_TYPE); + OscarUpdateRecognizer recognizer = new OscarUpdateRecognizer(sql, asts.get(0)); + List updateValues = recognizer.getUpdateValues(); + Assertions.assertEquals(updateValues.size(), 3); + + // test with values + sql = "update t set a = 1, b = 2, c = 3"; + asts = SQLUtils.parseStatements(sql, DB_TYPE); + recognizer = new OscarUpdateRecognizer(sql, asts.get(0)); + updateValues = recognizer.getUpdateValues(); + Assertions.assertEquals(updateValues.size(), 3); + + // test with error + Assertions.assertThrows(SQLParsingException.class, () -> { + String s = "update t set a = ?"; + List sqlStatements = SQLUtils.parseStatements(s, DB_TYPE); + SQLUpdateStatement sqlUpdateStatement = (SQLUpdateStatement)sqlStatements.get(0); + List updateSetItems = sqlUpdateStatement.getItems(); + for (SQLUpdateSetItem updateSetItem : updateSetItems) { + updateSetItem.setValue(new OracleCursorExpr()); + } + OscarUpdateRecognizer oscarUpdateRecognizer = new OscarUpdateRecognizer(s, sqlUpdateStatement); + oscarUpdateRecognizer.getUpdateValues(); + }); + } + + @Test + public void testGetWhereCondition_0() { + + String sql = "update t set a = 1"; + List asts = SQLUtils.parseStatements(sql, DB_TYPE); + + OscarUpdateRecognizer recognizer = new OscarUpdateRecognizer(sql, asts.get(0)); + String whereCondition = recognizer.getWhereCondition(new ParametersHolder() { + @Override + public Map> getParameters() { + return null; + } + }, new ArrayList<>()); + + Assertions.assertEquals("", whereCondition); + } + + @Test + public void testGetWhereCondition_1() { + + String sql = "update t set a = 1"; + List asts = SQLUtils.parseStatements(sql, DB_TYPE); + + OscarUpdateRecognizer recognizer = new OscarUpdateRecognizer(sql, asts.get(0)); + String whereCondition = recognizer.getWhereCondition(); + + Assertions.assertEquals("", whereCondition); + } + + @Test + public void testGetTableAlias() { + String sql = "update t set a = ?, b = ?, c = ?"; + List asts = SQLUtils.parseStatements(sql, DB_TYPE); + + OscarUpdateRecognizer recognizer = new OscarUpdateRecognizer(sql, asts.get(0)); + Assertions.assertNull(recognizer.getTableAlias()); + } + + @Test + public void testGetTableName() { + String sql = "update t set a = ?, b = ?, c = ?"; + List asts = SQLUtils.parseStatements(sql, DB_TYPE); + + OscarUpdateRecognizer recognizer = new OscarUpdateRecognizer(sql, asts.get(0)); + Assertions.assertEquals(recognizer.getTableName(), "t"); + } +} diff --git a/script/client/at/db/oscar.sql b/script/client/at/db/oscar.sql new file mode 100644 index 00000000000..e6d992afed5 --- /dev/null +++ b/script/client/at/db/oscar.sql @@ -0,0 +1,27 @@ +-- for AT mode you must to init this sql for you business database. the seata server not need it. +CREATE TABLE UNDO_LOG +( + ID numeric(19,0) NOT NULL, + BRANCH_ID numeric(19,0) NOT NULL, + XID character varying(128) NOT NULL, + "CONTEXT" character varying(128) NOT NULL, + ROLLBACK_INFO blob NOT NULL, + LOG_STATUS numeric(10,0) NOT NULL, + LOG_CREATED timestamp(0) without time zone NOT NULL, + LOG_MODIFIED timestamp(0) without time zone NOT NULL, + CONSTRAINT UNDO_LOG_PKEY PRIMARY KEY (ID), + CONSTRAINT UX_UNDO_LOG UNIQUE (XID, BRANCH_ID) +); + +CREATE INDEX ix_log_created ON UNDO_LOG(LOG_CREATED); +COMMENT ON TABLE UNDO_LOG IS 'AT transaction mode undo table'; +COMMENT ON COLUMN UNDO_LOG.BRANCH_ID is 'branch transaction id'; +COMMENT ON COLUMN UNDO_LOG.XID is 'global transaction id'; +COMMENT ON COLUMN UNDO_LOG.CONTEXT is 'undo_log context,such as serialization'; +COMMENT ON COLUMN UNDO_LOG.ROLLBACK_INFO is 'rollback info'; +COMMENT ON COLUMN UNDO_LOG.LOG_STATUS is '0:normal status,1:defense status'; +COMMENT ON COLUMN UNDO_LOG.LOG_CREATED is 'create datetime'; +COMMENT ON COLUMN UNDO_LOG.LOG_MODIFIED is 'modify datetime'; + +-- Generate ID using sequence and trigger +CREATE SEQUENCE UNDO_LOG_SEQ START WITH 1 INCREMENT BY 1; \ No newline at end of file diff --git a/script/server/db/oscar.sql b/script/server/db/oscar.sql new file mode 100644 index 00000000000..db07d96a8d4 --- /dev/null +++ b/script/server/db/oscar.sql @@ -0,0 +1,78 @@ +-- -------------------------------- The script used when storeMode is 'db' -------------------------------- +-- the table to store GlobalSession data +CREATE TABLE global_table +( + XID VARCHAR2(128) NOT NULL, + TRANSACTION_ID NUMBER(19), + STATUS NUMBER(3) NOT NULL, + APPLICATION_ID VARCHAR2(32), + TRANSACTION_SERVICE_GROUP VARCHAR2(32), + TRANSACTION_NAME VARCHAR2(128), + TIMEOUT NUMBER(10), + BEGIN_TIME NUMBER(19), + APPLICATION_DATA VARCHAR2(2000), + GMT_CREATE TIMESTAMP(0), + GMT_MODIFIED TIMESTAMP(0), + PRIMARY KEY (XID) +); + +CREATE INDEX idx_status_gmt_modified ON global_table (STATUS, GMT_MODIFIED); +CREATE INDEX idx_transaction_id ON global_table (TRANSACTION_ID); + +-- the table to store BranchSession data +CREATE TABLE branch_table +( + BRANCH_ID NUMBER(19) NOT NULL, + XID VARCHAR2(128) NOT NULL, + TRANSACTION_ID NUMBER(19), + RESOURCE_GROUP_ID VARCHAR2(32), + RESOURCE_ID VARCHAR2(256), + BRANCH_TYPE VARCHAR2(8), + STATUS NUMBER(3), + CLIENT_ID VARCHAR2(64), + APPLICATION_DATA VARCHAR2(2000), + GMT_CREATE TIMESTAMP(6), + GMT_MODIFIED TIMESTAMP(6), + PRIMARY KEY (BRANCH_ID) +); + +CREATE INDEX idx_xid ON branch_table (XID); + +-- the table to store lock data +CREATE TABLE lock_table +( + ROW_KEY VARCHAR2(128) NOT NULL, + XID VARCHAR2(128), + TRANSACTION_ID NUMBER(19), + BRANCH_ID NUMBER(19) NOT NULL, + RESOURCE_ID VARCHAR2(256), + TABLE_NAME VARCHAR2(32), + PK VARCHAR2(36), + STATUS NUMBER(3) DEFAULT 0 NOT NULL, + GMT_CREATE TIMESTAMP(0), + GMT_MODIFIED TIMESTAMP(0), + PRIMARY KEY (ROW_KEY) +); + +comment on column lock_table.STATUS is '0:locked ,1:rollbacking'; +CREATE INDEX idx_branch_id ON lock_table (BRANCH_ID); +CREATE INDEX idx_lock_table_xid ON lock_table (XID); +CREATE INDEX idx_status ON lock_table (STATUS); + +CREATE TABLE distributed_lock ( + LOCK_KEY VARCHAR2(20) NOT NULL, + LOCK_VALUE VARCHAR2(20) NOT NULL, + EXPIRE DECIMAL(18) NOT NULL, + PRIMARY KEY (LOCK_KEY) +); + +INSERT INTO distributed_lock (LOCK_KEY, LOCK_VALUE, EXPIRE) VALUES ('AsyncCommitting', ' ', 0); +INSERT INTO distributed_lock (LOCK_KEY, LOCK_VALUE, EXPIRE) VALUES ('RetryCommitting', ' ', 0); +INSERT INTO distributed_lock (LOCK_KEY, LOCK_VALUE, EXPIRE) VALUES ('RetryRollbacking', ' ', 0); +INSERT INTO distributed_lock (LOCK_KEY, LOCK_VALUE, EXPIRE) VALUES ('TxTimeoutCheck', ' ', 0); +CREATE TABLE VGROUP_TABLE +( + VGROUP VARCHAR2(255) PRIMARY KEY, + NAMESPACE VARCHAR2(255), + CLUSTER VARCHAR2(255) +); \ No newline at end of file diff --git a/sqlparser/seata-sqlparser-core/src/main/java/org/apache/seata/sqlparser/util/JdbcConstants.java b/sqlparser/seata-sqlparser-core/src/main/java/org/apache/seata/sqlparser/util/JdbcConstants.java index d923f8918f7..e5d50257318 100644 --- a/sqlparser/seata-sqlparser-core/src/main/java/org/apache/seata/sqlparser/util/JdbcConstants.java +++ b/sqlparser/seata-sqlparser-core/src/main/java/org/apache/seata/sqlparser/util/JdbcConstants.java @@ -84,4 +84,6 @@ public interface JdbcConstants { String POLARDB = "polardb"; String POLARDBX = "polardb-x"; + + String OSCAR = "oscar"; } diff --git a/sqlparser/seata-sqlparser-druid/src/main/java/org/apache/seata/sqlparser/druid/oscar/BaseOscarRecognizer.java b/sqlparser/seata-sqlparser-druid/src/main/java/org/apache/seata/sqlparser/druid/oscar/BaseOscarRecognizer.java new file mode 100644 index 00000000000..5a9891cf005 --- /dev/null +++ b/sqlparser/seata-sqlparser-druid/src/main/java/org/apache/seata/sqlparser/druid/oscar/BaseOscarRecognizer.java @@ -0,0 +1,195 @@ +/* + * Copyright 1999-2019 Seata.io Group. + * + * Licensed 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.seata.sqlparser.druid.oscar; + +import com.alibaba.druid.sql.ast.SQLExpr; +import com.alibaba.druid.sql.ast.SQLOrderBy; +import com.alibaba.druid.sql.ast.expr.SQLInSubQueryExpr; +import com.alibaba.druid.sql.ast.expr.SQLQueryExpr; +import com.alibaba.druid.sql.ast.expr.SQLVariantRefExpr; +import com.alibaba.druid.sql.ast.statement.SQLInsertStatement; +import com.alibaba.druid.sql.ast.statement.SQLMergeStatement; +import com.alibaba.druid.sql.ast.statement.SQLReplaceStatement; +import com.alibaba.druid.sql.ast.statement.SQLUpdateSetItem; +import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleSelectJoin; +import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleSelectSubqueryTableSource; +import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleUpdateStatement; +import com.alibaba.druid.sql.dialect.oracle.visitor.OracleASTVisitor; +import com.alibaba.druid.sql.dialect.oracle.visitor.OracleASTVisitorAdapter; +import com.alibaba.druid.sql.dialect.oracle.visitor.OracleOutputVisitor; +import org.apache.seata.common.exception.NotSupportYetException; +import org.apache.seata.common.util.StringUtils; +import org.apache.seata.sqlparser.ParametersHolder; +import org.apache.seata.sqlparser.druid.BaseRecognizer; +import org.apache.seata.sqlparser.struct.Null; +import org.apache.seata.sqlparser.util.JdbcConstants; + +import java.util.ArrayList; +import java.util.List; +import java.util.Objects; + +/** + * @author hsh + */ +public abstract class BaseOscarRecognizer extends BaseRecognizer { + + /** + * Instantiates a new oscar base recognizer + * + * @param originalSql the original sql + */ + public BaseOscarRecognizer(String originalSql) { + super(originalSql); + } + + public OracleOutputVisitor createOutputVisitor(final ParametersHolder parametersHolder, + final ArrayList> paramAppenderList, + final StringBuilder sb) { + + return new OracleOutputVisitor(sb) { + @Override + public boolean visit(SQLVariantRefExpr x) { + if ("?".equals(x.getName())) { + ArrayList oneParamValues = parametersHolder.getParameters().get(x.getIndex() + 1); + if (paramAppenderList.isEmpty()) { + oneParamValues.forEach(t -> paramAppenderList.add(new ArrayList<>())); + } + for (int i = 0; i < oneParamValues.size(); i++) { + Object o = oneParamValues.get(i); + paramAppenderList.get(i).add(o instanceof Null ? null : o); + } + } + return super.visit(x); + } + }; + } + + public String getWhereCondition(SQLExpr where, final ParametersHolder parametersHolder, final ArrayList> paramAppenderList) { + if (Objects.isNull(where)) { + return StringUtils.EMPTY; + } + + StringBuilder sb = new StringBuilder(); + executeVisit(where, createOutputVisitor(parametersHolder, paramAppenderList, sb)); + return sb.toString(); + } + + public String getWhereCondition(SQLExpr where) { + if (Objects.isNull(where)) { + return StringUtils.EMPTY; + } + + StringBuilder sb = new StringBuilder(); + executeVisit(where, new OracleOutputVisitor(sb)); + return sb.toString(); + } + + protected String getOrderByCondition(SQLOrderBy sqlOrderBy) { + if (Objects.isNull(sqlOrderBy)) { + return StringUtils.EMPTY; + } + + StringBuilder sb = new StringBuilder(); + executeOrderBy(sqlOrderBy, new OracleOutputVisitor(sb)); + + return sb.toString(); + } + + protected String getOrderByCondition(SQLOrderBy sqlOrderBy, final ParametersHolder parametersHolder, + final ArrayList> paramAppenderList) { + if (Objects.isNull(sqlOrderBy)) { + return StringUtils.EMPTY; + } + + StringBuilder sb = new StringBuilder(); + executeOrderBy(sqlOrderBy, createOutputVisitor(parametersHolder, paramAppenderList, sb)); + return sb.toString(); + } + + @Override + public boolean isSqlSyntaxSupports() { + OracleASTVisitor visitor = new OracleASTVisitorAdapter() { + @Override + public boolean visit(OracleSelectJoin x) { + //just like: UPDATE table a INNER JOIN table b ON a.id = b.pid ... + throw new NotSupportYetException("not support the sql syntax with join table:" + x + + "\nplease see the doc about SQL restrictions https://seata.io/zh-cn/docs/user/sqlreference/dml.html"); + } + + @Override + public boolean visit(OracleUpdateStatement x) { + if (x.getTableSource() instanceof OracleSelectSubqueryTableSource) { + //just like: "update (select a.id,a.name from a inner join b on a.id = b.id) t set t.name = 'xxx'" + throw new NotSupportYetException("not support the sql syntax with join table:" + x + + "\nplease see the doc about SQL restrictions https://seata.io/zh-cn/docs/user/sqlreference/dml.html"); + } + List updateSetItems = x.getItems(); + for (SQLUpdateSetItem updateSetItem : updateSetItems) { + if (updateSetItem.getValue() instanceof SQLQueryExpr) { + //just like: "update a set a.id = (select id from b where a.pid = b.pid)" + throw new NotSupportYetException("not support the sql syntax with join table:" + x + + "\nplease see the doc about SQL restrictions https://seata.io/zh-cn/docs/user/sqlreference/dml.html"); + } + } + return true; + } + + @Override + public boolean visit(SQLInSubQueryExpr x) { + //just like: ...where id in (select id from t) + throw new NotSupportYetException("not support the sql syntax with InSubQuery:" + x + + "\nplease see the doc about SQL restrictions https://seata.io/zh-cn/docs/user/sqlreference/dml.html"); + } + + @Override + public boolean visit(OracleSelectSubqueryTableSource x) { + //just like: select * from (select * from t) for update + throw new NotSupportYetException("not support the sql syntax with SubQuery:" + x + + "\nplease see the doc about SQL restrictions https://seata.io/zh-cn/docs/user/sqlreference/dml.html"); + } + + @Override + public boolean visit(SQLReplaceStatement x) { + //just like: replace into t (id,dr) values (1,'2'), (2,'3') + throw new NotSupportYetException("not support the sql syntax with ReplaceStatement:" + x + + "\nplease see the doc about SQL restrictions https://seata.io/zh-cn/docs/user/sqlreference/dml.html"); + } + + @Override + public boolean visit(SQLMergeStatement x) { + //just like: merge into ... WHEN MATCHED THEN ... + throw new NotSupportYetException("not support the sql syntax with MergeStatement:" + x + + "\nplease see the doc about SQL restrictions https://seata.io/zh-cn/docs/user/sqlreference/dml.html"); + } + + @Override + public boolean visit(SQLInsertStatement x) { + if (null != x.getQuery()) { + //just like: insert into t select * from t1 + throw new NotSupportYetException("not support the sql syntax insert with query:" + x + + "\nplease see the doc about SQL restrictions https://seata.io/zh-cn/docs/user/sqlreference/dml.html"); + } + return true; + } + }; + getAst().accept(visitor); + return true; + } + + public String getDbType() { + return JdbcConstants.OSCAR; + } +} diff --git a/sqlparser/seata-sqlparser-druid/src/main/java/org/apache/seata/sqlparser/druid/oscar/OscarDeleteRecognizer.java b/sqlparser/seata-sqlparser-druid/src/main/java/org/apache/seata/sqlparser/druid/oscar/OscarDeleteRecognizer.java new file mode 100644 index 00000000000..d38eb18ae55 --- /dev/null +++ b/sqlparser/seata-sqlparser-druid/src/main/java/org/apache/seata/sqlparser/druid/oscar/OscarDeleteRecognizer.java @@ -0,0 +1,137 @@ +/* + * Copyright 1999-2019 Seata.io Group. + * + * Licensed 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.seata.sqlparser.druid.oscar; + +import com.alibaba.druid.sql.ast.SQLExpr; +import com.alibaba.druid.sql.ast.SQLStatement; +import com.alibaba.druid.sql.ast.statement.SQLDeleteStatement; +import com.alibaba.druid.sql.ast.statement.SQLExprTableSource; +import com.alibaba.druid.sql.ast.statement.SQLJoinTableSource; +import com.alibaba.druid.sql.ast.statement.SQLTableSource; +import com.alibaba.druid.sql.dialect.oracle.visitor.OracleOutputVisitor; +import org.apache.seata.common.exception.NotSupportYetException; +import org.apache.seata.sqlparser.ParametersHolder; +import org.apache.seata.sqlparser.SQLDeleteRecognizer; +import org.apache.seata.sqlparser.SQLType; + +import java.util.ArrayList; +import java.util.List; + +/** + * The type oscar delete recognizer. + * + * @author ccg + */ +public class OscarDeleteRecognizer extends BaseOscarRecognizer implements SQLDeleteRecognizer { + + private final SQLDeleteStatement ast; + + /** + * Instantiates a new My sql delete recognizer. + * + * @param originalSQL the original sql + * @param ast the ast + */ + public OscarDeleteRecognizer(String originalSQL, SQLStatement ast) { + super(originalSQL); + this.ast = (SQLDeleteStatement)ast; + } + + @Override + public SQLType getSQLType() { + return SQLType.DELETE; + } + + @Override + public String getTableAlias() { + return ast.getTableSource().getAlias(); + } + + @Override + public String getTableName() { + StringBuilder sb = new StringBuilder(); + OracleOutputVisitor visitor = new OracleOutputVisitor(sb) { + + @Override + public boolean visit(SQLExprTableSource x) { + printTableSourceExpr(x.getExpr()); + return false; + } + + @Override + public boolean visit(SQLJoinTableSource x) { + throw new NotSupportYetException("not support the syntax of delete with join table"); + } + }; + SQLTableSource tableSource; + if (ast.getFrom() == null) { + tableSource = ast.getTableSource(); + } else { + tableSource = ast.getFrom(); + } + + if (tableSource instanceof SQLExprTableSource) { + visitor.visit((SQLExprTableSource) tableSource); + } else if (tableSource instanceof SQLJoinTableSource) { + visitor.visit((SQLJoinTableSource) tableSource); + } else { + throw new NotSupportYetException("not support the syntax of delete with unknow"); + } + return sb.toString(); + } + + @Override + public String getWhereCondition(final ParametersHolder parametersHolder, + final ArrayList> paramAppenderList) { + SQLExpr where = ast.getWhere(); + return super.getWhereCondition(where, parametersHolder, paramAppenderList); + } + + @Override + public String getWhereCondition() { + SQLExpr where = ast.getWhere(); + return super.getWhereCondition(where); + } + + @Override + public String getLimitCondition() { + //oscar does not support limit or rownum yet + return null; + } + + @Override + public String getLimitCondition(ParametersHolder parametersHolder, ArrayList> paramAppenderList) { + //oscar does not support limit or rownum yet + return null; + } + + @Override + public String getOrderByCondition() { + //oscar does not support order by yet + return null; + } + + @Override + public String getOrderByCondition(ParametersHolder parametersHolder, ArrayList> paramAppenderList) { + //oscar does not support order by yet + return null; + } + + @Override + protected SQLStatement getAst() { + return ast; + } +} diff --git a/sqlparser/seata-sqlparser-druid/src/main/java/org/apache/seata/sqlparser/druid/oscar/OscarInsertRecognizer.java b/sqlparser/seata-sqlparser-druid/src/main/java/org/apache/seata/sqlparser/druid/oscar/OscarInsertRecognizer.java new file mode 100644 index 00000000000..fbfb5f50c08 --- /dev/null +++ b/sqlparser/seata-sqlparser-druid/src/main/java/org/apache/seata/sqlparser/druid/oscar/OscarInsertRecognizer.java @@ -0,0 +1,159 @@ +/* + * Copyright 1999-2019 Seata.io Group. + * + * Licensed 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.seata.sqlparser.druid.oscar; + +import com.alibaba.druid.sql.ast.SQLExpr; +import com.alibaba.druid.sql.ast.SQLStatement; +import com.alibaba.druid.sql.ast.expr.*; +import com.alibaba.druid.sql.ast.statement.SQLExprTableSource; +import com.alibaba.druid.sql.ast.statement.SQLInsertStatement; +import com.alibaba.druid.sql.dialect.oracle.visitor.OracleOutputVisitor; +import org.apache.seata.common.util.CollectionUtils; +import org.apache.seata.sqlparser.SQLInsertRecognizer; +import org.apache.seata.sqlparser.SQLType; +import org.apache.seata.sqlparser.struct.NotPlaceholderExpr; +import org.apache.seata.sqlparser.struct.Null; +import org.apache.seata.sqlparser.struct.SqlMethodExpr; +import org.apache.seata.sqlparser.struct.SqlSequenceExpr; +import org.apache.seata.sqlparser.util.ColumnUtils; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; + +/** + * The type oscar insert recognizer. + * + * @author ccg + */ +public class OscarInsertRecognizer extends BaseOscarRecognizer implements SQLInsertRecognizer { + + private final SQLInsertStatement ast; + + /** + * Instantiates a new My sql insert recognizer. + * + * @param originalSQL the original sql + * @param ast the ast + */ + public OscarInsertRecognizer(String originalSQL, SQLStatement ast) { + super(originalSQL); + this.ast = (SQLInsertStatement)ast; + } + + @Override + public SQLType getSQLType() { + return SQLType.INSERT; + } + + @Override + public String getTableAlias() { + return ast.getTableSource().getAlias(); + } + + @Override + public String getTableName() { + StringBuilder sb = new StringBuilder(); + OracleOutputVisitor visitor = new OracleOutputVisitor(sb) { + + @Override + public boolean visit(SQLExprTableSource x) { + printTableSourceExpr(x.getExpr()); + return false; + } + }; + visitor.visit(ast.getTableSource()); + return sb.toString(); + } + + @Override + public boolean insertColumnsIsEmpty() { + return CollectionUtils.isEmpty(ast.getColumns()); + } + + @Override + public List getInsertColumns() { + List columnSQLExprs = ast.getColumns(); + if (columnSQLExprs.isEmpty()) { + // INSERT INTO ta VALUES (...), without fields clarified + return null; + } + List list = new ArrayList<>(columnSQLExprs.size()); + for (SQLExpr expr : columnSQLExprs) { + if (expr instanceof SQLIdentifierExpr) { + list.add(((SQLIdentifierExpr)expr).getName()); + } else { + wrapSQLParsingException(expr); + } + } + return list; + } + + @Override + public List> getInsertRows(Collection primaryKeyIndex) { + List valuesClauses = ast.getValuesList(); + List> rows = new ArrayList<>(valuesClauses.size()); + for (SQLInsertStatement.ValuesClause valuesClause : valuesClauses) { + List exprs = valuesClause.getValues(); + List row = new ArrayList<>(exprs.size()); + rows.add(row); + for (int i = 0, len = exprs.size(); i < len; i++) { + SQLExpr expr = exprs.get(i); + if (expr instanceof SQLNullExpr) { + row.add(Null.get()); + } else if (expr instanceof SQLValuableExpr) { + row.add(((SQLValuableExpr) expr).getValue()); + } else if (expr instanceof SQLVariantRefExpr) { + row.add(((SQLVariantRefExpr) expr).getName()); + } else if (expr instanceof SQLMethodInvokeExpr) { + row.add(SqlMethodExpr.get()); + } else if (expr instanceof SQLSequenceExpr) { + SQLSequenceExpr sequenceExpr = (SQLSequenceExpr) expr; + String sequence = sequenceExpr.getSequence().getSimpleName(); + String function = sequenceExpr.getFunction().name; + row.add(new SqlSequenceExpr(sequence, function)); + } else { + if (primaryKeyIndex.contains(i)) { + wrapSQLParsingException(expr); + } + row.add(NotPlaceholderExpr.get()); + } + } + } + return rows; + } + + @Override + public List getInsertParamsValue() { + return null; + } + + @Override + public List getDuplicateKeyUpdate() { + return null; + } + + @Override + public List getInsertColumnsUnEscape() { + List insertColumns = getInsertColumns(); + return ColumnUtils.delEscape(insertColumns, getDbType()); + } + + @Override + protected SQLStatement getAst() { + return ast; + } +} diff --git a/sqlparser/seata-sqlparser-druid/src/main/java/org/apache/seata/sqlparser/druid/oscar/OscarOperateRecognizerHolder.java b/sqlparser/seata-sqlparser-druid/src/main/java/org/apache/seata/sqlparser/druid/oscar/OscarOperateRecognizerHolder.java new file mode 100644 index 00000000000..af94962c221 --- /dev/null +++ b/sqlparser/seata-sqlparser-druid/src/main/java/org/apache/seata/sqlparser/druid/oscar/OscarOperateRecognizerHolder.java @@ -0,0 +1,55 @@ +/* + * Copyright 1999-2019 Seata.io Group. + * + * Licensed 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.seata.sqlparser.druid.oscar; + +import com.alibaba.druid.sql.ast.SQLStatement; +import com.alibaba.druid.sql.ast.statement.SQLSelectStatement; +import org.apache.seata.common.loader.LoadLevel; +import org.apache.seata.sqlparser.SQLRecognizer; +import org.apache.seata.sqlparser.druid.SQLOperateRecognizerHolder; +import org.apache.seata.sqlparser.util.JdbcConstants; + +/** + * The Type OscarOperateRecognizerHolder + * + * @author hsh + */ +@LoadLevel(name = JdbcConstants.OSCAR) +public class OscarOperateRecognizerHolder implements SQLOperateRecognizerHolder { + + @Override + public SQLRecognizer getDeleteRecognizer(String sql, SQLStatement ast) { + return new OscarDeleteRecognizer(sql, ast); + } + + @Override + public SQLRecognizer getInsertRecognizer(String sql, SQLStatement ast) { + return new OscarInsertRecognizer(sql, ast); + } + + @Override + public SQLRecognizer getUpdateRecognizer(String sql, SQLStatement ast) { + return new OscarUpdateRecognizer(sql, ast); + } + + @Override + public SQLRecognizer getSelectForUpdateRecognizer(String sql, SQLStatement ast) { + if (((SQLSelectStatement) ast).getSelect().getFirstQueryBlock().isForUpdate()) { + return new OscarSelectForUpdateRecognizer(sql, ast); + } + return null; + } +} diff --git a/sqlparser/seata-sqlparser-druid/src/main/java/org/apache/seata/sqlparser/druid/oscar/OscarSelectForUpdateRecognizer.java b/sqlparser/seata-sqlparser-druid/src/main/java/org/apache/seata/sqlparser/druid/oscar/OscarSelectForUpdateRecognizer.java new file mode 100644 index 00000000000..bcd0ebc0b71 --- /dev/null +++ b/sqlparser/seata-sqlparser-druid/src/main/java/org/apache/seata/sqlparser/druid/oscar/OscarSelectForUpdateRecognizer.java @@ -0,0 +1,135 @@ +/* + * Copyright 1999-2019 Seata.io Group. + * + * Licensed 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.seata.sqlparser.druid.oscar; + +import com.alibaba.druid.sql.ast.SQLExpr; +import com.alibaba.druid.sql.ast.SQLOrderBy; +import com.alibaba.druid.sql.ast.SQLStatement; +import com.alibaba.druid.sql.ast.statement.*; +import com.alibaba.druid.sql.dialect.oracle.visitor.OracleOutputVisitor; +import org.apache.seata.sqlparser.ParametersHolder; +import org.apache.seata.sqlparser.SQLParsingException; +import org.apache.seata.sqlparser.SQLSelectRecognizer; +import org.apache.seata.sqlparser.SQLType; + +import java.util.ArrayList; +import java.util.List; + +/** + * The type oscar select for update recognizer. + * + * @author ccg + */ +public class OscarSelectForUpdateRecognizer extends BaseOscarRecognizer implements SQLSelectRecognizer { + + private final SQLSelectStatement ast; + + /** + * Instantiates a new My sql select for update recognizer. + * + * @param originalSQL the original sql + * @param ast the ast + */ + public OscarSelectForUpdateRecognizer(String originalSQL, SQLStatement ast) { + super(originalSQL); + this.ast = (SQLSelectStatement)ast; + } + + @Override + public SQLType getSQLType() { + return SQLType.SELECT_FOR_UPDATE; + } + + @Override + public String getWhereCondition(final ParametersHolder parametersHolder, + final ArrayList> paramAppenderList) { + SQLSelectQueryBlock selectQueryBlock = getSelect(); + SQLExpr where = selectQueryBlock.getWhere(); + return super.getWhereCondition(where, parametersHolder, paramAppenderList); + } + + @Override + public String getWhereCondition() { + SQLSelectQueryBlock selectQueryBlock = getSelect(); + SQLExpr where = selectQueryBlock.getWhere(); + return super.getWhereCondition(where); + } + + @Override + public String getLimitCondition() { + //oscar does not support limit or rownum yet + return null; + } + + @Override + public String getLimitCondition(ParametersHolder parametersHolder, ArrayList> paramAppenderList) { + //oscar does not support limit or rownum yet + return null; + } + + @Override + public String getOrderByCondition() { + SQLOrderBy sqlOrderBy = getSelect().getOrderBy(); + return super.getOrderByCondition(sqlOrderBy); + } + + @Override + public String getOrderByCondition(ParametersHolder parametersHolder, ArrayList> paramAppenderList) { + SQLOrderBy sqlOrderBy = getSelect().getOrderBy(); + return super.getOrderByCondition(sqlOrderBy, parametersHolder, paramAppenderList); + } + + private SQLSelectQueryBlock getSelect() { + SQLSelect select = ast.getSelect(); + if (select == null) { + throw new SQLParsingException("should never happen!"); + } + SQLSelectQueryBlock selectQueryBlock = select.getQueryBlock(); + if (selectQueryBlock == null) { + throw new SQLParsingException("should never happen!"); + } + return selectQueryBlock; + } + + @Override + public String getTableAlias() { + SQLSelectQueryBlock selectQueryBlock = getSelect(); + SQLTableSource tableSource = selectQueryBlock.getFrom(); + return tableSource.getAlias(); + } + + @Override + public String getTableName() { + SQLSelectQueryBlock selectQueryBlock = getSelect(); + SQLTableSource tableSource = selectQueryBlock.getFrom(); + StringBuilder sb = new StringBuilder(); + OracleOutputVisitor visitor = new OracleOutputVisitor(sb) { + + @Override + public boolean visit(SQLExprTableSource x) { + printTableSourceExpr(x.getExpr()); + return false; + } + }; + visitor.visit((SQLExprTableSource)tableSource); + return sb.toString(); + } + + @Override + protected SQLStatement getAst() { + return ast; + } +} diff --git a/sqlparser/seata-sqlparser-druid/src/main/java/org/apache/seata/sqlparser/druid/oscar/OscarUpdateRecognizer.java b/sqlparser/seata-sqlparser-druid/src/main/java/org/apache/seata/sqlparser/druid/oscar/OscarUpdateRecognizer.java new file mode 100644 index 00000000000..b0460b26ad6 --- /dev/null +++ b/sqlparser/seata-sqlparser-druid/src/main/java/org/apache/seata/sqlparser/druid/oscar/OscarUpdateRecognizer.java @@ -0,0 +1,181 @@ +/* + * Copyright 1999-2019 Seata.io Group. + * + * Licensed 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.seata.sqlparser.druid.oscar; + +import com.alibaba.druid.sql.ast.SQLExpr; +import com.alibaba.druid.sql.ast.SQLStatement; +import com.alibaba.druid.sql.ast.expr.SQLIdentifierExpr; +import com.alibaba.druid.sql.ast.expr.SQLPropertyExpr; +import com.alibaba.druid.sql.ast.expr.SQLValuableExpr; +import com.alibaba.druid.sql.ast.expr.SQLVariantRefExpr; +import com.alibaba.druid.sql.ast.statement.*; +import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleUpdateStatement; +import com.alibaba.druid.sql.dialect.oracle.visitor.OracleOutputVisitor; +import org.apache.seata.common.exception.NotSupportYetException; +import org.apache.seata.sqlparser.ParametersHolder; +import org.apache.seata.sqlparser.SQLType; +import org.apache.seata.sqlparser.SQLUpdateRecognizer; +import org.apache.seata.sqlparser.util.ColumnUtils; + +import java.util.ArrayList; +import java.util.List; + +/** + * The type oscar update recognizer. + * + * @author hsh + */ +public class OscarUpdateRecognizer extends BaseOscarRecognizer implements SQLUpdateRecognizer { + + private SQLUpdateStatement ast; + + /** + * Instantiates a new My sql update recognizer. + * + * @param originalSQL the original sql + * @param ast the ast + */ + public OscarUpdateRecognizer(String originalSQL, SQLStatement ast) { + super(originalSQL); + this.ast = (OracleUpdateStatement)ast; + } + + @Override + public SQLType getSQLType() { + return SQLType.UPDATE; + } + + @Override + public List getUpdateColumns() { + List updateSetItems = ast.getItems(); + List list = new ArrayList<>(updateSetItems.size()); + for (SQLUpdateSetItem updateSetItem : updateSetItems) { + SQLExpr expr = updateSetItem.getColumn(); + if (expr instanceof SQLIdentifierExpr) { + list.add(((SQLIdentifierExpr)expr).getName()); + } else if (expr instanceof SQLPropertyExpr) { + // This is alias case, like UPDATE xxx_tbl a SET a.name = ? WHERE a.id = ? + SQLExpr owner = ((SQLPropertyExpr)expr).getOwner(); + if (owner instanceof SQLIdentifierExpr) { + list.add(((SQLIdentifierExpr)owner).getName() + "." + ((SQLPropertyExpr)expr).getName()); + //This is table Field Full path, like update xxx_database.xxx_tbl set xxx_database.xxx_tbl.xxx_field... + } else if (((SQLPropertyExpr) expr).getOwnerName().split("\\.").length > 1) { + list.add(((SQLPropertyExpr)expr).getOwnerName() + "." + ((SQLPropertyExpr)expr).getName()); + } + } else { + wrapSQLParsingException(expr); + } + } + return list; + } + + @Override + public List getUpdateValues() { + List updateSetItems = ast.getItems(); + List list = new ArrayList<>(updateSetItems.size()); + for (SQLUpdateSetItem updateSetItem : updateSetItems) { + SQLExpr expr = updateSetItem.getValue(); + if (expr instanceof SQLValuableExpr) { + list.add(((SQLValuableExpr)expr).getValue()); + } else if (expr instanceof SQLVariantRefExpr) { + list.add(new VMarker()); + } else { + wrapSQLParsingException(expr); + } + } + return list; + } + + @Override + public List getUpdateColumnsUnEscape() { + List updateColumns = getUpdateColumns(); + return ColumnUtils.delEscape(updateColumns, getDbType()); + } + + @Override + public String getWhereCondition(final ParametersHolder parametersHolder, + final ArrayList> paramAppenderList) { + SQLExpr where = ast.getWhere(); + return super.getWhereCondition(where, parametersHolder, paramAppenderList); + } + + @Override + public String getWhereCondition() { + SQLExpr where = ast.getWhere(); + return super.getWhereCondition(where); + } + + @Override + public String getLimitCondition() { + //oscar does not support limit or rownum yet + return null; + } + + @Override + public String getLimitCondition(ParametersHolder parametersHolder, ArrayList> paramAppenderList) { + //oscar does not support limit or rownum yet + return null; + } + + @Override + public String getOrderByCondition() { + //oscar does not support order by yet + return null; + } + + @Override + public String getOrderByCondition(ParametersHolder parametersHolder, ArrayList> paramAppenderList) { + //oscar does not support order by yet + return null; + } + + @Override + public String getTableAlias() { + return ast.getTableSource().getAlias(); + } + + @Override + public String getTableName() { + StringBuilder sb = new StringBuilder(); + OracleOutputVisitor visitor = new OracleOutputVisitor(sb) { + + @Override + public boolean visit(SQLExprTableSource x) { + printTableSourceExpr(x.getExpr()); + return false; + } + + @Override + public boolean visit(SQLJoinTableSource x) { + throw new NotSupportYetException("not support the syntax of update with join table"); + } + }; + SQLTableSource tableSource = ast.getTableSource(); + if (tableSource instanceof SQLExprTableSource) { + visitor.visit((SQLExprTableSource) tableSource); + } else if (tableSource instanceof SQLJoinTableSource) { + visitor.visit((SQLJoinTableSource) tableSource); + } else { + throw new NotSupportYetException("not support the syntax of update with unknow"); + } + return sb.toString(); + } + + @Override + protected SQLStatement getAst() { + return ast; + } +} diff --git a/sqlparser/seata-sqlparser-druid/src/main/resources/META-INF/services/org.apache.seata.sqlparser.druid.SQLOperateRecognizerHolder b/sqlparser/seata-sqlparser-druid/src/main/resources/META-INF/services/org.apache.seata.sqlparser.druid.SQLOperateRecognizerHolder index 78decdb2af3..2ba961fd641 100644 --- a/sqlparser/seata-sqlparser-druid/src/main/resources/META-INF/services/org.apache.seata.sqlparser.druid.SQLOperateRecognizerHolder +++ b/sqlparser/seata-sqlparser-druid/src/main/resources/META-INF/services/org.apache.seata.sqlparser.druid.SQLOperateRecognizerHolder @@ -20,4 +20,5 @@ org.apache.seata.sqlparser.druid.oracle.OracleOperateRecognizerHolder org.apache.seata.sqlparser.druid.postgresql.PostgresqlOperateRecognizerHolder org.apache.seata.sqlparser.druid.sqlserver.SqlServerOperateRecognizerHolder org.apache.seata.sqlparser.druid.polardbx.PolarDBXOperateRecognizerHolder -org.apache.seata.sqlparser.druid.dm.DmOperateRecognizerHolder \ No newline at end of file +org.apache.seata.sqlparser.druid.dm.DmOperateRecognizerHolder +org.apache.seata.sqlparser.druid.oscar.OscarOperateRecognizerHolder \ No newline at end of file From 41b8b2e3f750952c8bc16e4fc973f81f2c5d06eb Mon Sep 17 00:00:00 2001 From: hanshaohua Date: Thu, 19 Sep 2024 08:58:29 +0800 Subject: [PATCH 05/19] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E9=83=A8=E5=88=86?= =?UTF-8?q?=E9=94=99=E8=AF=AFDbType=E5=8F=82=E6=95=B0=E8=B0=83=E7=94=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../rm/datasource/undo/oscar/OscarUndoDeleteExecutor.java | 2 +- .../rm/datasource/undo/oscar/OscarUndoUpdateExecutor.java | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/rm-datasource/src/main/java/org/apache/seata/rm/datasource/undo/oscar/OscarUndoDeleteExecutor.java b/rm-datasource/src/main/java/org/apache/seata/rm/datasource/undo/oscar/OscarUndoDeleteExecutor.java index d41c32ea51d..9ac3caca7e2 100644 --- a/rm-datasource/src/main/java/org/apache/seata/rm/datasource/undo/oscar/OscarUndoDeleteExecutor.java +++ b/rm-datasource/src/main/java/org/apache/seata/rm/datasource/undo/oscar/OscarUndoDeleteExecutor.java @@ -59,7 +59,7 @@ protected String buildUndoSQL() { } Row row = beforeImageRows.get(0); List fields = new ArrayList<>(row.nonPrimaryKeys()); - fields.addAll(getOrderedPkList(beforeImage,row,JdbcConstants.ORACLE)); + fields.addAll(getOrderedPkList(beforeImage,row,JdbcConstants.OSCAR)); // delete sql undo log before image all field come from table meta, need add escape. // see BaseTransactionalExecutor#buildTableRecords diff --git a/rm-datasource/src/main/java/org/apache/seata/rm/datasource/undo/oscar/OscarUndoUpdateExecutor.java b/rm-datasource/src/main/java/org/apache/seata/rm/datasource/undo/oscar/OscarUndoUpdateExecutor.java index bb9321e28ba..99baea2444a 100644 --- a/rm-datasource/src/main/java/org/apache/seata/rm/datasource/undo/oscar/OscarUndoUpdateExecutor.java +++ b/rm-datasource/src/main/java/org/apache/seata/rm/datasource/undo/oscar/OscarUndoUpdateExecutor.java @@ -54,12 +54,12 @@ protected String buildUndoSQL() { // update sql undo log before image all field come from table meta. need add escape. // see BaseTransactionalExecutor#buildTableRecords String updateColumns = nonPkFields.stream().map( - field -> ColumnUtils.addEscape(field.getName(), JdbcConstants.ORACLE) + " = ?").collect( + field -> ColumnUtils.addEscape(field.getName(), JdbcConstants.OSCAR) + " = ?").collect( Collectors.joining(", ")); - List pkNameList = getOrderedPkList(beforeImage, row, JdbcConstants.ORACLE).stream().map( + List pkNameList = getOrderedPkList(beforeImage, row, JdbcConstants.OSCAR).stream().map( e -> e.getName()).collect(Collectors.toList()); - String whereSql = SqlGenerateUtils.buildWhereConditionByPKs(pkNameList, JdbcConstants.ORACLE); + String whereSql = SqlGenerateUtils.buildWhereConditionByPKs(pkNameList, JdbcConstants.OSCAR); return String.format(UPDATE_SQL_TEMPLATE, sqlUndoLog.getTableName(), updateColumns, whereSql); } From d31610b538ef38ff5bb4ce888f21ba8a9095760c Mon Sep 17 00:00:00 2001 From: hanshaohua Date: Sun, 22 Sep 2024 16:02:41 +0800 Subject: [PATCH 06/19] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E5=BD=93=E5=87=BA?= =?UTF-8?q?=E7=8E=B0JdbcUrl=E4=B8=AD=E5=87=BA=E7=8E=B0=E5=BC=BA=E5=88=B6?= =?UTF-8?q?=E6=A8=A1=E5=BC=8F=E5=90=8D=E5=8F=82=E6=95=B0currentSchema?= =?UTF-8?q?=E4=B8=8E=E7=94=A8=E6=88=B7=E5=90=8D=E4=B8=8D=E7=BB=9F=E4=B8=80?= =?UTF-8?q?=E6=97=B6=E8=8E=B7=E5=8F=96=E4=B8=8D=E5=88=B0=E7=B4=A2=E5=BC=95?= =?UTF-8?q?=E7=BC=93=E5=AD=98=E7=9A=84=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../rm/datasource/sql/struct/cache/OscarTableMetaCache.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/rm-datasource/src/main/java/org/apache/seata/rm/datasource/sql/struct/cache/OscarTableMetaCache.java b/rm-datasource/src/main/java/org/apache/seata/rm/datasource/sql/struct/cache/OscarTableMetaCache.java index 2bcb70a7032..e1239bdff6e 100644 --- a/rm-datasource/src/main/java/org/apache/seata/rm/datasource/sql/struct/cache/OscarTableMetaCache.java +++ b/rm-datasource/src/main/java/org/apache/seata/rm/datasource/sql/struct/cache/OscarTableMetaCache.java @@ -76,7 +76,8 @@ private TableMeta resultSetMetaToSchema(DatabaseMetaData dbmd, String tableName) TableMeta tm = new TableMeta(); tm.setTableName(tableName); String[] schemaTable = tableName.split("\\."); - String schemaName = schemaTable.length > 1 ? schemaTable[0] : dbmd.getUserName(); + + String schemaName = schemaTable.length > 1 ? schemaTable[0] : dbmd.getConnection().getSchema(); tableName = schemaTable.length > 1 ? schemaTable[1] : tableName; if (schemaName.contains("\"")) { schemaName = schemaName.replace("\"", ""); From 1271811b22bdfa4644fc198020285fe145f3aeea Mon Sep 17 00:00:00 2001 From: hanshaohua Date: Thu, 26 Sep 2024 15:07:03 +0800 Subject: [PATCH 07/19] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E5=8D=8F=E8=AE=AE?= =?UTF-8?q?=E5=A3=B0=E6=98=8E=EF=BC=8C=E4=BF=AE=E6=94=B9=E4=BB=A3=E7=A0=81?= =?UTF-8?q?=E9=A3=8E=E6=A0=BC=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../store/db/sql/lock/OscarLockStoreSql.java | 23 +++++++------- .../store/db/sql/log/OscarLogStoreSqls.java | 23 +++++++------- .../exec/oscar/OscarInsertExecutor.java | 23 +++++++------- .../sql/handler/oscar/OscarEscapeHandler.java | 23 +++++++------- .../sql/struct/cache/OscarTableMetaCache.java | 23 +++++++------- .../undo/oscar/OscarUndoDeleteExecutor.java | 23 +++++++------- .../undo/oscar/OscarUndoExecutorHolder.java | 23 +++++++------- .../undo/oscar/OscarUndoInsertExecutor.java | 23 +++++++------- .../undo/oscar/OscarUndoLogManager.java | 23 +++++++------- .../undo/oscar/OscarUndoUpdateExecutor.java | 23 +++++++------- .../exec/OscarInsertExecutorTest.java | 23 +++++++------- .../oscar/OscarDeleteRecognizerTest.java | 23 +++++++------- .../oscar/OscarInsertRecognizerTest.java | 23 +++++++------- .../OscarSelectForUpdateRecognizerTest.java | 23 +++++++------- .../oscar/OscarUpdateRecognizerTest.java | 23 +++++++------- script/client/at/db/oscar.sql | 16 ++++++++++ script/server/db/oscar.sql | 16 ++++++++++ .../druid/oscar/BaseOscarRecognizer.java | 23 +++++++------- .../druid/oscar/OscarDeleteRecognizer.java | 23 +++++++------- .../druid/oscar/OscarInsertRecognizer.java | 30 +++++++++++-------- .../oscar/OscarOperateRecognizerHolder.java | 23 +++++++------- .../oscar/OscarSelectForUpdateRecognizer.java | 29 ++++++++++-------- .../druid/oscar/OscarUpdateRecognizer.java | 29 ++++++++++-------- 23 files changed, 300 insertions(+), 234 deletions(-) diff --git a/core/src/main/java/org/apache/seata/core/store/db/sql/lock/OscarLockStoreSql.java b/core/src/main/java/org/apache/seata/core/store/db/sql/lock/OscarLockStoreSql.java index 175fab3fbe4..07f30517e59 100644 --- a/core/src/main/java/org/apache/seata/core/store/db/sql/lock/OscarLockStoreSql.java +++ b/core/src/main/java/org/apache/seata/core/store/db/sql/lock/OscarLockStoreSql.java @@ -1,17 +1,18 @@ /* - * Copyright 1999-2019 Seata.io Group. + * 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 * - * Licensed 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 * - * 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. + * 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.seata.core.store.db.sql.lock; diff --git a/core/src/main/java/org/apache/seata/core/store/db/sql/log/OscarLogStoreSqls.java b/core/src/main/java/org/apache/seata/core/store/db/sql/log/OscarLogStoreSqls.java index 2e7f7322f93..08a83cbcea8 100644 --- a/core/src/main/java/org/apache/seata/core/store/db/sql/log/OscarLogStoreSqls.java +++ b/core/src/main/java/org/apache/seata/core/store/db/sql/log/OscarLogStoreSqls.java @@ -1,17 +1,18 @@ /* - * Copyright 1999-2019 Seata.io Group. + * 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 * - * Licensed 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 * - * 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. + * 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.seata.core.store.db.sql.log; diff --git a/rm-datasource/src/main/java/org/apache/seata/rm/datasource/exec/oscar/OscarInsertExecutor.java b/rm-datasource/src/main/java/org/apache/seata/rm/datasource/exec/oscar/OscarInsertExecutor.java index 0585e030601..c26b32d3151 100644 --- a/rm-datasource/src/main/java/org/apache/seata/rm/datasource/exec/oscar/OscarInsertExecutor.java +++ b/rm-datasource/src/main/java/org/apache/seata/rm/datasource/exec/oscar/OscarInsertExecutor.java @@ -1,17 +1,18 @@ /* - * Copyright 1999-2019 Seata.io Group. + * 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 * - * Licensed 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 * - * 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. + * 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.seata.rm.datasource.exec.oscar; diff --git a/rm-datasource/src/main/java/org/apache/seata/rm/datasource/sql/handler/oscar/OscarEscapeHandler.java b/rm-datasource/src/main/java/org/apache/seata/rm/datasource/sql/handler/oscar/OscarEscapeHandler.java index aa07be7f26d..d93c757c9d6 100644 --- a/rm-datasource/src/main/java/org/apache/seata/rm/datasource/sql/handler/oscar/OscarEscapeHandler.java +++ b/rm-datasource/src/main/java/org/apache/seata/rm/datasource/sql/handler/oscar/OscarEscapeHandler.java @@ -1,17 +1,18 @@ /* - * Copyright 1999-2019 Seata.io Group. + * 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 * - * Licensed 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 * - * 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. + * 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.seata.rm.datasource.sql.handler.oscar; diff --git a/rm-datasource/src/main/java/org/apache/seata/rm/datasource/sql/struct/cache/OscarTableMetaCache.java b/rm-datasource/src/main/java/org/apache/seata/rm/datasource/sql/struct/cache/OscarTableMetaCache.java index e1239bdff6e..35610d4e310 100644 --- a/rm-datasource/src/main/java/org/apache/seata/rm/datasource/sql/struct/cache/OscarTableMetaCache.java +++ b/rm-datasource/src/main/java/org/apache/seata/rm/datasource/sql/struct/cache/OscarTableMetaCache.java @@ -1,17 +1,18 @@ /* - * Copyright 1999-2019 Seata.io Group. + * 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 * - * Licensed 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 * - * 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. + * 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.seata.rm.datasource.sql.struct.cache; diff --git a/rm-datasource/src/main/java/org/apache/seata/rm/datasource/undo/oscar/OscarUndoDeleteExecutor.java b/rm-datasource/src/main/java/org/apache/seata/rm/datasource/undo/oscar/OscarUndoDeleteExecutor.java index 9ac3caca7e2..4874cfc80eb 100644 --- a/rm-datasource/src/main/java/org/apache/seata/rm/datasource/undo/oscar/OscarUndoDeleteExecutor.java +++ b/rm-datasource/src/main/java/org/apache/seata/rm/datasource/undo/oscar/OscarUndoDeleteExecutor.java @@ -1,17 +1,18 @@ /* - * Copyright 1999-2019 Seata.io Group. + * 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 * - * Licensed 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 * - * 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. + * 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.seata.rm.datasource.undo.oscar; diff --git a/rm-datasource/src/main/java/org/apache/seata/rm/datasource/undo/oscar/OscarUndoExecutorHolder.java b/rm-datasource/src/main/java/org/apache/seata/rm/datasource/undo/oscar/OscarUndoExecutorHolder.java index e0f83058e8a..c6b70ccfd28 100644 --- a/rm-datasource/src/main/java/org/apache/seata/rm/datasource/undo/oscar/OscarUndoExecutorHolder.java +++ b/rm-datasource/src/main/java/org/apache/seata/rm/datasource/undo/oscar/OscarUndoExecutorHolder.java @@ -1,17 +1,18 @@ /* - * Copyright 1999-2019 Seata.io Group. + * 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 * - * Licensed 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 * - * 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. + * 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.seata.rm.datasource.undo.oscar; diff --git a/rm-datasource/src/main/java/org/apache/seata/rm/datasource/undo/oscar/OscarUndoInsertExecutor.java b/rm-datasource/src/main/java/org/apache/seata/rm/datasource/undo/oscar/OscarUndoInsertExecutor.java index 64261f80562..cd696f62001 100644 --- a/rm-datasource/src/main/java/org/apache/seata/rm/datasource/undo/oscar/OscarUndoInsertExecutor.java +++ b/rm-datasource/src/main/java/org/apache/seata/rm/datasource/undo/oscar/OscarUndoInsertExecutor.java @@ -1,17 +1,18 @@ /* - * Copyright 1999-2019 Seata.io Group. + * 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 * - * Licensed 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 * - * 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. + * 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.seata.rm.datasource.undo.oscar; diff --git a/rm-datasource/src/main/java/org/apache/seata/rm/datasource/undo/oscar/OscarUndoLogManager.java b/rm-datasource/src/main/java/org/apache/seata/rm/datasource/undo/oscar/OscarUndoLogManager.java index 35d4d30b44c..445581b48ff 100644 --- a/rm-datasource/src/main/java/org/apache/seata/rm/datasource/undo/oscar/OscarUndoLogManager.java +++ b/rm-datasource/src/main/java/org/apache/seata/rm/datasource/undo/oscar/OscarUndoLogManager.java @@ -1,17 +1,18 @@ /* - * Copyright 1999-2019 Seata.io Group. + * 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 * - * Licensed 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 * - * 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. + * 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.seata.rm.datasource.undo.oscar; diff --git a/rm-datasource/src/main/java/org/apache/seata/rm/datasource/undo/oscar/OscarUndoUpdateExecutor.java b/rm-datasource/src/main/java/org/apache/seata/rm/datasource/undo/oscar/OscarUndoUpdateExecutor.java index 99baea2444a..e8eabd4a63e 100644 --- a/rm-datasource/src/main/java/org/apache/seata/rm/datasource/undo/oscar/OscarUndoUpdateExecutor.java +++ b/rm-datasource/src/main/java/org/apache/seata/rm/datasource/undo/oscar/OscarUndoUpdateExecutor.java @@ -1,17 +1,18 @@ /* - * Copyright 1999-2019 Seata.io Group. + * 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 * - * Licensed 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 * - * 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. + * 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.seata.rm.datasource.undo.oscar; diff --git a/rm-datasource/src/test/java/org/apache/seata/rm/datasource/exec/OscarInsertExecutorTest.java b/rm-datasource/src/test/java/org/apache/seata/rm/datasource/exec/OscarInsertExecutorTest.java index 40439c101b3..5ce10955ec5 100644 --- a/rm-datasource/src/test/java/org/apache/seata/rm/datasource/exec/OscarInsertExecutorTest.java +++ b/rm-datasource/src/test/java/org/apache/seata/rm/datasource/exec/OscarInsertExecutorTest.java @@ -1,17 +1,18 @@ /* - * Copyright 1999-2019 Seata.io Group. + * 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 * - * Licensed 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 * - * 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. + * 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.seata.rm.datasource.exec; diff --git a/rm-datasource/src/test/java/org/apache/seata/rm/datasource/sql/druid/oscar/OscarDeleteRecognizerTest.java b/rm-datasource/src/test/java/org/apache/seata/rm/datasource/sql/druid/oscar/OscarDeleteRecognizerTest.java index 389d09bbc9d..81e432a065e 100644 --- a/rm-datasource/src/test/java/org/apache/seata/rm/datasource/sql/druid/oscar/OscarDeleteRecognizerTest.java +++ b/rm-datasource/src/test/java/org/apache/seata/rm/datasource/sql/druid/oscar/OscarDeleteRecognizerTest.java @@ -1,17 +1,18 @@ /* - * Copyright 1999-2019 Seata.io Group. + * 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 * - * Licensed 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 * - * 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. + * 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.seata.rm.datasource.sql.druid.oscar; diff --git a/rm-datasource/src/test/java/org/apache/seata/rm/datasource/sql/druid/oscar/OscarInsertRecognizerTest.java b/rm-datasource/src/test/java/org/apache/seata/rm/datasource/sql/druid/oscar/OscarInsertRecognizerTest.java index 9f8dc375d1a..a344ae2c549 100644 --- a/rm-datasource/src/test/java/org/apache/seata/rm/datasource/sql/druid/oscar/OscarInsertRecognizerTest.java +++ b/rm-datasource/src/test/java/org/apache/seata/rm/datasource/sql/druid/oscar/OscarInsertRecognizerTest.java @@ -1,17 +1,18 @@ /* - * Copyright 1999-2019 Seata.io Group. + * 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 * - * Licensed 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 * - * 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. + * 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.seata.rm.datasource.sql.druid.oscar; diff --git a/rm-datasource/src/test/java/org/apache/seata/rm/datasource/sql/druid/oscar/OscarSelectForUpdateRecognizerTest.java b/rm-datasource/src/test/java/org/apache/seata/rm/datasource/sql/druid/oscar/OscarSelectForUpdateRecognizerTest.java index 969d7da3ca0..b028835291d 100644 --- a/rm-datasource/src/test/java/org/apache/seata/rm/datasource/sql/druid/oscar/OscarSelectForUpdateRecognizerTest.java +++ b/rm-datasource/src/test/java/org/apache/seata/rm/datasource/sql/druid/oscar/OscarSelectForUpdateRecognizerTest.java @@ -1,17 +1,18 @@ /* - * Copyright 1999-2019 Seata.io Group. + * 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 * - * Licensed 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 * - * 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. + * 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.seata.rm.datasource.sql.druid.oscar; diff --git a/rm-datasource/src/test/java/org/apache/seata/rm/datasource/sql/druid/oscar/OscarUpdateRecognizerTest.java b/rm-datasource/src/test/java/org/apache/seata/rm/datasource/sql/druid/oscar/OscarUpdateRecognizerTest.java index d0f5140659f..209c892781e 100644 --- a/rm-datasource/src/test/java/org/apache/seata/rm/datasource/sql/druid/oscar/OscarUpdateRecognizerTest.java +++ b/rm-datasource/src/test/java/org/apache/seata/rm/datasource/sql/druid/oscar/OscarUpdateRecognizerTest.java @@ -1,17 +1,18 @@ /* - * Copyright 1999-2019 Seata.io Group. + * 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 * - * Licensed 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 * - * 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. + * 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.seata.rm.datasource.sql.druid.oscar; diff --git a/script/client/at/db/oscar.sql b/script/client/at/db/oscar.sql index e6d992afed5..ff62de40f76 100644 --- a/script/client/at/db/oscar.sql +++ b/script/client/at/db/oscar.sql @@ -1,3 +1,19 @@ +-- +-- 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. +-- -- for AT mode you must to init this sql for you business database. the seata server not need it. CREATE TABLE UNDO_LOG ( diff --git a/script/server/db/oscar.sql b/script/server/db/oscar.sql index db07d96a8d4..a65b5e8b0d5 100644 --- a/script/server/db/oscar.sql +++ b/script/server/db/oscar.sql @@ -1,3 +1,19 @@ +-- +-- 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. +-- -- -------------------------------- The script used when storeMode is 'db' -------------------------------- -- the table to store GlobalSession data CREATE TABLE global_table diff --git a/sqlparser/seata-sqlparser-druid/src/main/java/org/apache/seata/sqlparser/druid/oscar/BaseOscarRecognizer.java b/sqlparser/seata-sqlparser-druid/src/main/java/org/apache/seata/sqlparser/druid/oscar/BaseOscarRecognizer.java index 5a9891cf005..0a3e925bfe9 100644 --- a/sqlparser/seata-sqlparser-druid/src/main/java/org/apache/seata/sqlparser/druid/oscar/BaseOscarRecognizer.java +++ b/sqlparser/seata-sqlparser-druid/src/main/java/org/apache/seata/sqlparser/druid/oscar/BaseOscarRecognizer.java @@ -1,17 +1,18 @@ /* - * Copyright 1999-2019 Seata.io Group. + * 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 * - * Licensed 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 * - * 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. + * 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.seata.sqlparser.druid.oscar; diff --git a/sqlparser/seata-sqlparser-druid/src/main/java/org/apache/seata/sqlparser/druid/oscar/OscarDeleteRecognizer.java b/sqlparser/seata-sqlparser-druid/src/main/java/org/apache/seata/sqlparser/druid/oscar/OscarDeleteRecognizer.java index d38eb18ae55..f8f691bb9d5 100644 --- a/sqlparser/seata-sqlparser-druid/src/main/java/org/apache/seata/sqlparser/druid/oscar/OscarDeleteRecognizer.java +++ b/sqlparser/seata-sqlparser-druid/src/main/java/org/apache/seata/sqlparser/druid/oscar/OscarDeleteRecognizer.java @@ -1,17 +1,18 @@ /* - * Copyright 1999-2019 Seata.io Group. + * 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 * - * Licensed 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 * - * 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. + * 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.seata.sqlparser.druid.oscar; diff --git a/sqlparser/seata-sqlparser-druid/src/main/java/org/apache/seata/sqlparser/druid/oscar/OscarInsertRecognizer.java b/sqlparser/seata-sqlparser-druid/src/main/java/org/apache/seata/sqlparser/druid/oscar/OscarInsertRecognizer.java index fbfb5f50c08..fcb1ede4e88 100644 --- a/sqlparser/seata-sqlparser-druid/src/main/java/org/apache/seata/sqlparser/druid/oscar/OscarInsertRecognizer.java +++ b/sqlparser/seata-sqlparser-druid/src/main/java/org/apache/seata/sqlparser/druid/oscar/OscarInsertRecognizer.java @@ -1,23 +1,29 @@ /* - * Copyright 1999-2019 Seata.io Group. + * 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 * - * Licensed 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 * - * 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. + * 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.seata.sqlparser.druid.oscar; import com.alibaba.druid.sql.ast.SQLExpr; import com.alibaba.druid.sql.ast.SQLStatement; -import com.alibaba.druid.sql.ast.expr.*; +import com.alibaba.druid.sql.ast.expr.SQLIdentifierExpr; +import com.alibaba.druid.sql.ast.expr.SQLMethodInvokeExpr; +import com.alibaba.druid.sql.ast.expr.SQLNullExpr; +import com.alibaba.druid.sql.ast.expr.SQLSequenceExpr; +import com.alibaba.druid.sql.ast.expr.SQLValuableExpr; +import com.alibaba.druid.sql.ast.expr.SQLVariantRefExpr; import com.alibaba.druid.sql.ast.statement.SQLExprTableSource; import com.alibaba.druid.sql.ast.statement.SQLInsertStatement; import com.alibaba.druid.sql.dialect.oracle.visitor.OracleOutputVisitor; diff --git a/sqlparser/seata-sqlparser-druid/src/main/java/org/apache/seata/sqlparser/druid/oscar/OscarOperateRecognizerHolder.java b/sqlparser/seata-sqlparser-druid/src/main/java/org/apache/seata/sqlparser/druid/oscar/OscarOperateRecognizerHolder.java index af94962c221..b0704508582 100644 --- a/sqlparser/seata-sqlparser-druid/src/main/java/org/apache/seata/sqlparser/druid/oscar/OscarOperateRecognizerHolder.java +++ b/sqlparser/seata-sqlparser-druid/src/main/java/org/apache/seata/sqlparser/druid/oscar/OscarOperateRecognizerHolder.java @@ -1,17 +1,18 @@ /* - * Copyright 1999-2019 Seata.io Group. + * 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 * - * Licensed 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 * - * 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. + * 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.seata.sqlparser.druid.oscar; diff --git a/sqlparser/seata-sqlparser-druid/src/main/java/org/apache/seata/sqlparser/druid/oscar/OscarSelectForUpdateRecognizer.java b/sqlparser/seata-sqlparser-druid/src/main/java/org/apache/seata/sqlparser/druid/oscar/OscarSelectForUpdateRecognizer.java index bcd0ebc0b71..beb6229297b 100644 --- a/sqlparser/seata-sqlparser-druid/src/main/java/org/apache/seata/sqlparser/druid/oscar/OscarSelectForUpdateRecognizer.java +++ b/sqlparser/seata-sqlparser-druid/src/main/java/org/apache/seata/sqlparser/druid/oscar/OscarSelectForUpdateRecognizer.java @@ -1,24 +1,29 @@ /* - * Copyright 1999-2019 Seata.io Group. + * 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 * - * Licensed 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 * - * 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. + * 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.seata.sqlparser.druid.oscar; import com.alibaba.druid.sql.ast.SQLExpr; import com.alibaba.druid.sql.ast.SQLOrderBy; import com.alibaba.druid.sql.ast.SQLStatement; -import com.alibaba.druid.sql.ast.statement.*; +import com.alibaba.druid.sql.ast.statement.SQLExprTableSource; +import com.alibaba.druid.sql.ast.statement.SQLSelect; +import com.alibaba.druid.sql.ast.statement.SQLSelectQueryBlock; +import com.alibaba.druid.sql.ast.statement.SQLSelectStatement; +import com.alibaba.druid.sql.ast.statement.SQLTableSource; import com.alibaba.druid.sql.dialect.oracle.visitor.OracleOutputVisitor; import org.apache.seata.sqlparser.ParametersHolder; import org.apache.seata.sqlparser.SQLParsingException; diff --git a/sqlparser/seata-sqlparser-druid/src/main/java/org/apache/seata/sqlparser/druid/oscar/OscarUpdateRecognizer.java b/sqlparser/seata-sqlparser-druid/src/main/java/org/apache/seata/sqlparser/druid/oscar/OscarUpdateRecognizer.java index b0460b26ad6..18f361fc6b2 100644 --- a/sqlparser/seata-sqlparser-druid/src/main/java/org/apache/seata/sqlparser/druid/oscar/OscarUpdateRecognizer.java +++ b/sqlparser/seata-sqlparser-druid/src/main/java/org/apache/seata/sqlparser/druid/oscar/OscarUpdateRecognizer.java @@ -1,17 +1,18 @@ /* - * Copyright 1999-2019 Seata.io Group. + * 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 * - * Licensed 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 * - * 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. + * 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.seata.sqlparser.druid.oscar; @@ -21,7 +22,11 @@ import com.alibaba.druid.sql.ast.expr.SQLPropertyExpr; import com.alibaba.druid.sql.ast.expr.SQLValuableExpr; import com.alibaba.druid.sql.ast.expr.SQLVariantRefExpr; -import com.alibaba.druid.sql.ast.statement.*; +import com.alibaba.druid.sql.ast.statement.SQLExprTableSource; +import com.alibaba.druid.sql.ast.statement.SQLJoinTableSource; +import com.alibaba.druid.sql.ast.statement.SQLTableSource; +import com.alibaba.druid.sql.ast.statement.SQLUpdateSetItem; +import com.alibaba.druid.sql.ast.statement.SQLUpdateStatement; import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleUpdateStatement; import com.alibaba.druid.sql.dialect.oracle.visitor.OracleOutputVisitor; import org.apache.seata.common.exception.NotSupportYetException; From a4b6f819733b1de3a14903b1c6e53ae17882ec0f Mon Sep 17 00:00:00 2001 From: hanshaohua Date: Sun, 29 Sep 2024 16:49:25 +0800 Subject: [PATCH 08/19] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E6=B5=8B=E8=AF=95?= =?UTF-8?q?=E7=94=A8=E4=BE=8B=E4=B8=8D=E9=80=9A=E8=BF=87=E7=9A=84=E9=97=AE?= =?UTF-8?q?=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../seata/sqlparser/druid/oscar/OscarUpdateRecognizer.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/sqlparser/seata-sqlparser-druid/src/main/java/org/apache/seata/sqlparser/druid/oscar/OscarUpdateRecognizer.java b/sqlparser/seata-sqlparser-druid/src/main/java/org/apache/seata/sqlparser/druid/oscar/OscarUpdateRecognizer.java index 18f361fc6b2..259ff6b4d55 100644 --- a/sqlparser/seata-sqlparser-druid/src/main/java/org/apache/seata/sqlparser/druid/oscar/OscarUpdateRecognizer.java +++ b/sqlparser/seata-sqlparser-druid/src/main/java/org/apache/seata/sqlparser/druid/oscar/OscarUpdateRecognizer.java @@ -27,7 +27,6 @@ import com.alibaba.druid.sql.ast.statement.SQLTableSource; import com.alibaba.druid.sql.ast.statement.SQLUpdateSetItem; import com.alibaba.druid.sql.ast.statement.SQLUpdateStatement; -import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleUpdateStatement; import com.alibaba.druid.sql.dialect.oracle.visitor.OracleOutputVisitor; import org.apache.seata.common.exception.NotSupportYetException; import org.apache.seata.sqlparser.ParametersHolder; @@ -55,7 +54,7 @@ public class OscarUpdateRecognizer extends BaseOscarRecognizer implements SQLUpd */ public OscarUpdateRecognizer(String originalSQL, SQLStatement ast) { super(originalSQL); - this.ast = (OracleUpdateStatement)ast; + this.ast = (SQLUpdateStatement) ast; } @Override From 06413777d1808ad5d6032c7599f175eb82af4e6e Mon Sep 17 00:00:00 2001 From: hanshaohua Date: Mon, 30 Sep 2024 09:26:08 +0800 Subject: [PATCH 09/19] =?UTF-8?q?=E8=A7=A3=E5=86=B3PMD=E6=A3=80=E6=9F=A5?= =?UTF-8?q?=E4=B8=8D=E9=80=9A=E8=BF=87=E7=9A=84=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../rm/datasource/sql/handler/oscar/OscarEscapeHandler.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/rm-datasource/src/main/java/org/apache/seata/rm/datasource/sql/handler/oscar/OscarEscapeHandler.java b/rm-datasource/src/main/java/org/apache/seata/rm/datasource/sql/handler/oscar/OscarEscapeHandler.java index d93c757c9d6..efd0fb73b33 100644 --- a/rm-datasource/src/main/java/org/apache/seata/rm/datasource/sql/handler/oscar/OscarEscapeHandler.java +++ b/rm-datasource/src/main/java/org/apache/seata/rm/datasource/sql/handler/oscar/OscarEscapeHandler.java @@ -41,6 +41,9 @@ public class OscarEscapeHandler implements EscapeHandler { * OSCAR keyword */ private enum OscarKeyword { + /** + * ABORT is oscar keyword + */ ABORT("ABORT"), ABSOLUTE("ABSOLUTE"), ACCESS("ACCESS"), From efc8c31d22826235f2b73472085784bd25a35feb Mon Sep 17 00:00:00 2001 From: hanshaohua Date: Sat, 5 Oct 2024 19:36:12 +0800 Subject: [PATCH 10/19] =?UTF-8?q?=E5=88=A0=E9=99=A4author=E6=A0=87?= =?UTF-8?q?=E8=AF=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../store/db/sql/lock/OscarLockStoreSql.java | 1 - .../store/db/sql/log/OscarLogStoreSqls.java | 1 - .../exec/oscar/OscarInsertExecutor.java | 1 - .../sql/handler/oscar/OscarEscapeHandler.java | 1915 ++++++++++++++++- .../sql/struct/cache/OscarTableMetaCache.java | 1 - .../undo/oscar/OscarUndoDeleteExecutor.java | 1 - .../undo/oscar/OscarUndoInsertExecutor.java | 1 - .../undo/oscar/OscarUndoLogManager.java | 2 +- .../undo/oscar/OscarUndoUpdateExecutor.java | 1 - .../exec/OscarInsertExecutorTest.java | 2 +- .../oscar/OscarDeleteRecognizerTest.java | 2 +- .../oscar/OscarInsertRecognizerTest.java | 2 +- .../OscarSelectForUpdateRecognizerTest.java | 2 +- .../oscar/OscarUpdateRecognizerTest.java | 2 +- .../druid/oscar/BaseOscarRecognizer.java | 2 +- .../oscar/OscarOperateRecognizerHolder.java | 1 - .../druid/oscar/OscarUpdateRecognizer.java | 1 - 17 files changed, 1921 insertions(+), 17 deletions(-) diff --git a/core/src/main/java/org/apache/seata/core/store/db/sql/lock/OscarLockStoreSql.java b/core/src/main/java/org/apache/seata/core/store/db/sql/lock/OscarLockStoreSql.java index 07f30517e59..bd72749ea1f 100644 --- a/core/src/main/java/org/apache/seata/core/store/db/sql/lock/OscarLockStoreSql.java +++ b/core/src/main/java/org/apache/seata/core/store/db/sql/lock/OscarLockStoreSql.java @@ -22,7 +22,6 @@ /** * the database lock store shentong sql * - * @author hsh */ @LoadLevel(name = "oscar") public class OscarLockStoreSql extends OracleLockStoreSql { diff --git a/core/src/main/java/org/apache/seata/core/store/db/sql/log/OscarLogStoreSqls.java b/core/src/main/java/org/apache/seata/core/store/db/sql/log/OscarLogStoreSqls.java index 08a83cbcea8..f310e03ff2e 100644 --- a/core/src/main/java/org/apache/seata/core/store/db/sql/log/OscarLogStoreSqls.java +++ b/core/src/main/java/org/apache/seata/core/store/db/sql/log/OscarLogStoreSqls.java @@ -21,7 +21,6 @@ /** * Database log store oscar sql - * @author hsh */ @LoadLevel(name = "oscar") public class OscarLogStoreSqls extends OracleLogStoreSqls { diff --git a/rm-datasource/src/main/java/org/apache/seata/rm/datasource/exec/oscar/OscarInsertExecutor.java b/rm-datasource/src/main/java/org/apache/seata/rm/datasource/exec/oscar/OscarInsertExecutor.java index c26b32d3151..1a68e7f30d2 100644 --- a/rm-datasource/src/main/java/org/apache/seata/rm/datasource/exec/oscar/OscarInsertExecutor.java +++ b/rm-datasource/src/main/java/org/apache/seata/rm/datasource/exec/oscar/OscarInsertExecutor.java @@ -42,7 +42,6 @@ /** * The type Oscar insert executor. * - * @author hsh */ @LoadLevel(name = JdbcConstants.OSCAR, scope = Scope.PROTOTYPE) public class OscarInsertExecutor extends BaseInsertExecutor implements Sequenceable { diff --git a/rm-datasource/src/main/java/org/apache/seata/rm/datasource/sql/handler/oscar/OscarEscapeHandler.java b/rm-datasource/src/main/java/org/apache/seata/rm/datasource/sql/handler/oscar/OscarEscapeHandler.java index efd0fb73b33..22c67143ef1 100644 --- a/rm-datasource/src/main/java/org/apache/seata/rm/datasource/sql/handler/oscar/OscarEscapeHandler.java +++ b/rm-datasource/src/main/java/org/apache/seata/rm/datasource/sql/handler/oscar/OscarEscapeHandler.java @@ -30,7 +30,6 @@ /** * The type OSCAR keyword checker. * - * @author hsh */ @LoadLevel(name = JdbcConstants.OSCAR) public class OscarEscapeHandler implements EscapeHandler { @@ -45,643 +44,2557 @@ private enum OscarKeyword { * ABORT is oscar keyword */ ABORT("ABORT"), + /** + * ABSOLUTE is oscar keyword + */ ABSOLUTE("ABSOLUTE"), + /** + * ACCESS is oscar keyword + */ ACCESS("ACCESS"), + /** + * ACCESSED is oscar keyword + */ ACCESSED("ACCESSED"), + /** + * ACTION is oscar keyword + */ ACTION("ACTION"), + /** + * ADD is oscar keyword + */ ADD("ADD"), + /** + * ADMIN is oscar keyword + */ ADMIN("ADMIN"), + /** + * ADVISOR is oscar keyword + */ ADVISOR("ADVISOR"), + /** + * AFTER is oscar keyword + */ AFTER("AFTER"), + /** + * AGGREGATE is oscar keyword + */ AGGREGATE("AGGREGATE"), + /** + * ALTER is oscar keyword + */ ALTER("ALTER"), + /** + * ALWAYS is oscar keyword + */ ALWAYS("ALWAYS"), + /** + * ANALYSE is oscar keyword + */ ANALYSE("ANALYSE"), + /** + * ANALYZE is oscar keyword + */ ANALYZE("ANALYZE"), + /** + * ANALYZER is oscar keyword + */ ANALYZER("ANALYZER"), + /** + * APP is oscar keyword + */ APP("APP"), + /** + * ARCHIVE is oscar keyword + */ ARCHIVE("ARCHIVE"), + /** + * ARCHIVELOG is oscar keyword + */ ARCHIVELOG("ARCHIVELOG"), + /** + * ARE is oscar keyword + */ ARE("ARE"), + /** + * ARRAY is oscar keyword + */ ARRAY("ARRAY"), + /** + * ASC is oscar keyword + */ ASC("ASC"), + /** + * ASSERTION is oscar keyword + */ ASSERTION("ASSERTION"), + /** + * ASSIGNMENT is oscar keyword + */ ASSIGNMENT("ASSIGNMENT"), + /** + * AST is oscar keyword + */ AST("AST"), + /** + * ASYNC is oscar keyword + */ ASYNC("ASYNC"), + /** + * ATTRIBUTES is oscar keyword + */ ATTRIBUTES("ATTRIBUTES"), + /** + * AUDIT is oscar keyword + */ AUDIT("AUDIT"), + /** + * AUDITFILE is oscar keyword + */ AUDITFILE("AUDITFILE"), + /** + * AUTHID is oscar keyword + */ AUTHID("AUTHID"), + /** + * AUTHORIZATION is oscar keyword + */ AUTHORIZATION("AUTHORIZATION"), + /** + * AUTO is oscar keyword + */ AUTO("AUTO"), + /** + * AUTO_INCREMENT is oscar keyword + */ AUTO_INCREMENT("AUTO_INCREMENT"), + /** + * AUTOEXTEND is oscar keyword + */ AUTOEXTEND("AUTOEXTEND"), + /** + * BACKUP is oscar keyword + */ BACKUP("BACKUP"), + /** + * BACKWARD is oscar keyword + */ BACKWARD("BACKWARD"), + /** + * BASICANALYZER is oscar keyword + */ BASICANALYZER("BASICANALYZER"), + /** + * BATCHSIZE is oscar keyword + */ BATCHSIZE("BATCHSIZE"), + /** + * BEFORE is oscar keyword + */ BEFORE("BEFORE"), + /** + * BEGIN is oscar keyword + */ BEGIN("BEGIN"), + /** + * BETWEEN is oscar keyword + */ BETWEEN("BETWEEN"), + /** + * BIGINT is oscar keyword + */ BIGINT("BIGINT"), + /** + * BINARY is oscar keyword + */ BINARY("BINARY"), + /** + * BINLOG is oscar keyword + */ BINLOG("BINLOG"), + /** + * BIT is oscar keyword + */ BIT("BIT"), + /** + * BITMAP is oscar keyword + */ BITMAP("BITMAP"), + /** + * BLOCK is oscar keyword + */ BLOCK("BLOCK"), + /** + * BODY is oscar keyword + */ BODY("BODY"), + /** + * BOOLEAN is oscar keyword + */ BOOLEAN("BOOLEAN"), + /** + * BOTH is oscar keyword + */ BOTH("BOTH"), + /** + * BPCHAR is oscar keyword + */ BPCHAR("BPCHAR"), + /** + * BUFFER is oscar keyword + */ BUFFER("BUFFER"), + /** + * BUFFER_CACHE is oscar keyword + */ BUFFER_CACHE("BUFFER_CACHE"), + /** + * BUFFER_POOL is oscar keyword + */ BUFFER_POOL("BUFFER_POOL"), + /** + * BUILD is oscar keyword + */ BUILD("BUILD"), + /** + * BULK is oscar keyword + */ BULK("BULK"), + /** + * BY is oscar keyword + */ BY("BY"), + /** + * BYTE is oscar keyword + */ BYTE("BYTE"), + /** + * CACHE is oscar keyword + */ CACHE("CACHE"), + /** + * CALL is oscar keyword + */ CALL("CALL"), + /** + * CALLED is oscar keyword + */ CALLED("CALLED"), + /** + * CANCEL is oscar keyword + */ CANCEL("CANCEL"), + /** + * CASCADED is oscar keyword + */ CASCADED("CASCADED"), + /** + * CDC is oscar keyword + */ CDC("CDC"), + /** + * CHAIN is oscar keyword + */ CHAIN("CHAIN"), + /** + * CHANGE is oscar keyword + */ CHANGE("CHANGE"), + /** + * CHARACTERISTICS is oscar keyword + */ CHARACTERISTICS("CHARACTERISTICS"), + /** + * CHARACTERSET is oscar keyword + */ CHARACTERSET("CHARACTERSET"), + /** + * CHEAT is oscar keyword + */ CHEAT("CHEAT"), + /** + * CHECKPOINT is oscar keyword + */ CHECKPOINT("CHECKPOINT"), + /** + * CHINESEANALYZER is oscar keyword + */ CHINESEANALYZER("CHINESEANALYZER"), + /** + * CHUNK is oscar keyword + */ CHUNK("CHUNK"), + /** + * CJKANALYZER is oscar keyword + */ CJKANALYZER("CJKANALYZER"), + /** + * CLASS is oscar keyword + */ CLASS("CLASS"), + /** + * CLEAN is oscar keyword + */ CLEAN("CLEAN"), + /** + * CLOSE is oscar keyword + */ CLOSE("CLOSE"), + /** + * CLUSTER is oscar keyword + */ CLUSTER("CLUSTER"), + /** + * COLUMNS is oscar keyword + */ COLUMNS("COLUMNS"), + /** + * COMMENT is oscar keyword + */ COMMENT("COMMENT"), + /** + * COMMENTS is oscar keyword + */ COMMENTS("COMMENTS"), + /** + * COMMIT is oscar keyword + */ COMMIT("COMMIT"), + /** + * COMMITTED is oscar keyword + */ COMMITTED("COMMITTED"), + /** + * COMPILE is oscar keyword + */ COMPILE("COMPILE"), + /** + * COMPLETE is oscar keyword + */ COMPLETE("COMPLETE"), + /** + * COMPRESS is oscar keyword + */ COMPRESS("COMPRESS"), + /** + * CONCAT is oscar keyword + */ CONCAT("CONCAT"), + /** + * CONFIGURATION is oscar keyword + */ CONFIGURATION("CONFIGURATION"), + /** + * CONNECT is oscar keyword + */ CONNECT("CONNECT"), + /** + * CONNECT_BY_ISCYCLE is oscar keyword + */ CONNECT_BY_ISCYCLE("CONNECT_BY_ISCYCLE"), + /** + * CONNECT_BY_ISLEAF is oscar keyword + */ CONNECT_BY_ISLEAF("CONNECT_BY_ISLEAF"), + /** + * CONNECT_BY_ROOT is oscar keyword + */ CONNECT_BY_ROOT("CONNECT_BY_ROOT"), + /** + * CONSTRAINTS is oscar keyword + */ CONSTRAINTS("CONSTRAINTS"), + /** + * CONTENT is oscar keyword + */ CONTENT("CONTENT"), + /** + * CONTEXT is oscar keyword + */ CONTEXT("CONTEXT"), + /** + * CONTINUE is oscar keyword + */ CONTINUE("CONTINUE"), + /** + * CONTROLFILE is oscar keyword + */ CONTROLFILE("CONTROLFILE"), + /** + * CONVERSION is oscar keyword + */ CONVERSION("CONVERSION"), + /** + * COPY is oscar keyword + */ COPY("COPY"), + /** + * CROSS is oscar keyword + */ CROSS("CROSS"), + /** + * CSV is oscar keyword + */ CSV("CSV"), + /** + * CUBE is oscar keyword + */ CUBE("CUBE"), + /** + * CURRENT is oscar keyword + */ CURRENT("CURRENT"), + /** + * CURRENT_USER is oscar keyword + */ CURRENT_USER("CURRENT_USER"), + /** + * CURSOR is oscar keyword + */ CURSOR("CURSOR"), + /** + * CYCLE is oscar keyword + */ CYCLE("CYCLE"), + /** + * DATA is oscar keyword + */ DATA("DATA"), + /** + * DATABASE is oscar keyword + */ DATABASE("DATABASE"), + /** + * DATABASELINK is oscar keyword + */ DATABASELINK("DATABASELINK"), + /** + * DATAFILE is oscar keyword + */ DATAFILE("DATAFILE"), + /** + * DATAFILETYPE is oscar keyword + */ DATAFILETYPE("DATAFILETYPE"), + /** + * DATE is oscar keyword + */ DATE("DATE"), + /** + * DATE_ADD is oscar keyword + */ DATE_ADD("DATE_ADD"), + /** + * DATE_SUB is oscar keyword + */ DATE_SUB("DATE_SUB"), + /** + * DATEFORMAT is oscar keyword + */ DATEFORMAT("DATEFORMAT"), + /** + * DATETIME is oscar keyword + */ DATETIME("DATETIME"), + /** + * DAY is oscar keyword + */ DAY("DAY"), + /** + * DBA is oscar keyword + */ DBA("DBA"), + /** + * DEALLOCATE is oscar keyword + */ DEALLOCATE("DEALLOCATE"), + /** + * DEBUG is oscar keyword + */ DEBUG("DEBUG"), + /** + * DEC is oscar keyword + */ DEC("DEC"), + /** + * DECLARE is oscar keyword + */ DECLARE("DECLARE"), + /** + * DECODE is oscar keyword + */ DECODE("DECODE"), + /** + * DECRYPT is oscar keyword + */ DECRYPT("DECRYPT"), + /** + * DEFERRABLE is oscar keyword + */ DEFERRABLE("DEFERRABLE"), + /** + * DEFERRED is oscar keyword + */ DEFERRED("DEFERRED"), + /** + * DEFINER is oscar keyword + */ DEFINER("DEFINER"), + /** + * DELETE is oscar keyword + */ DELETE("DELETE"), + /** + * DELIMITED is oscar keyword + */ DELIMITED("DELIMITED"), + /** + * DELIMITER is oscar keyword + */ DELIMITER("DELIMITER"), + /** + * DELIMITERS is oscar keyword + */ DELIMITERS("DELIMITERS"), + /** + * DEMAND is oscar keyword + */ DEMAND("DEMAND"), + /** + * DENSE_RANK is oscar keyword + */ DENSE_RANK("DENSE_RANK"), + /** + * DESC is oscar keyword + */ DESC("DESC"), + /** + * DESCRIPTION is oscar keyword + */ DESCRIPTION("DESCRIPTION"), + /** + * DETERMINISTIC is oscar keyword + */ DETERMINISTIC("DETERMINISTIC"), + /** + * DIRECTORY is oscar keyword + */ DIRECTORY("DIRECTORY"), + /** + * DISABLE is oscar keyword + */ DISABLE("DISABLE"), + /** + * DOCUMENT is oscar keyword + */ DOCUMENT("DOCUMENT"), + /** + * DOMAIN is oscar keyword + */ DOMAIN("DOMAIN"), + /** + * DOUBLE is oscar keyword + */ DOUBLE("DOUBLE"), + /** + * DUMP is oscar keyword + */ DUMP("DUMP"), + /** + * EACH is oscar keyword + */ EACH("EACH"), + /** + * ELOG is oscar keyword + */ ELOG("ELOG"), + /** + * ELT is oscar keyword + */ ELT("ELT"), + /** + * EMPTY is oscar keyword + */ EMPTY("EMPTY"), + /** + * ENABLE is oscar keyword + */ ENABLE("ENABLE"), + /** + * ENCODING is oscar keyword + */ ENCODING("ENCODING"), + /** + * ENCRYPT is oscar keyword + */ ENCRYPT("ENCRYPT"), + /** + * ENCRYPTED is oscar keyword + */ ENCRYPTED("ENCRYPTED"), + /** + * ENCRYPTION is oscar keyword + */ ENCRYPTION("ENCRYPTION"), + /** + * END is oscar keyword + */ END("END"), + /** + * ERROR is oscar keyword + */ ERROR("ERROR"), + /** + * ERRORS is oscar keyword + */ ERRORS("ERRORS"), + /** + * ESCALATION is oscar keyword + */ ESCALATION("ESCALATION"), + /** + * ESCAPE is oscar keyword + */ ESCAPE("ESCAPE"), + /** + * EVENTS is oscar keyword + */ EVENTS("EVENTS"), + /** + * EXCHANGE is oscar keyword + */ EXCHANGE("EXCHANGE"), + /** + * EXCLUDING is oscar keyword + */ EXCLUDING("EXCLUDING"), + /** + * EXCLUSIVE is oscar keyword + */ EXCLUSIVE("EXCLUSIVE"), + /** + * EXEC is oscar keyword + */ EXEC("EXEC"), + /** + * EXECUTE is oscar keyword + */ EXECUTE("EXECUTE"), + /** + * EXPLAIN is oscar keyword + */ EXPLAIN("EXPLAIN"), + /** + * EXPORT is oscar keyword + */ EXPORT("EXPORT"), + /** + * EXTEND is oscar keyword + */ EXTEND("EXTEND"), + /** + * EXTERNALLY is oscar keyword + */ EXTERNALLY("EXTERNALLY"), + /** + * FAILOVER is oscar keyword + */ FAILOVER("FAILOVER"), + /** + * FALSE is oscar keyword + */ FALSE("FALSE"), + /** + * FAR is oscar keyword + */ FAR("FAR"), + /** + * FAST is oscar keyword + */ FAST("FAST"), + /** + * FAULT is oscar keyword + */ FAULT("FAULT"), + /** + * FETCH is oscar keyword + */ FETCH("FETCH"), + /** + * FIELD is oscar keyword + */ FIELD("FIELD"), + /** + * FIELDS is oscar keyword + */ FIELDS("FIELDS"), + /** + * FIELDTERMINATOR is oscar keyword + */ FIELDTERMINATOR("FIELDTERMINATOR"), + /** + * FILE is oscar keyword + */ FILE("FILE"), + /** + * FILESIZE is oscar keyword + */ FILESIZE("FILESIZE"), + /** + * FILL is oscar keyword + */ FILL("FILL"), + /** + * FILTER is oscar keyword + */ FILTER("FILTER"), + /** + * FIRE_TRIGGERS is oscar keyword + */ FIRE_TRIGGERS("FIRE_TRIGGERS"), + /** + * FIRST is oscar keyword + */ FIRST("FIRST"), + /** + * FIRSTROW is oscar keyword + */ FIRSTROW("FIRSTROW"), + /** + * FLUSH is oscar keyword + */ FLUSH("FLUSH"), + /** + * FOLLOWING is oscar keyword + */ FOLLOWING("FOLLOWING"), + /** + * FORCE is oscar keyword + */ FORCE("FORCE"), + /** + * FOREIGNKEY_CONSTRAINTS is oscar keyword + */ FOREIGNKEY_CONSTRAINTS("FOREIGNKEY_CONSTRAINTS"), + /** + * FOREVER is oscar keyword + */ FOREVER("FOREVER"), + /** + * FORMATFILE is oscar keyword + */ FORMATFILE("FORMATFILE"), + /** + * FORWARD is oscar keyword + */ FORWARD("FORWARD"), + /** + * FREELISTS is oscar keyword + */ FREELISTS("FREELISTS"), + /** + * FREEPOOLS is oscar keyword + */ FREEPOOLS("FREEPOOLS"), + /** + * FULL is oscar keyword + */ FULL("FULL"), + /** + * FULLTEXT is oscar keyword + */ FULLTEXT("FULLTEXT"), + /** + * FUNCTION is oscar keyword + */ FUNCTION("FUNCTION"), + /** + * G is oscar keyword + */ G("G"), + /** + * GB is oscar keyword + */ GB("GB"), + /** + * GBK is oscar keyword + */ GBK("GBK"), + /** + * GCOV is oscar keyword + */ GCOV("GCOV"), + /** + * GENERATED is oscar keyword + */ GENERATED("GENERATED"), + /** + * GEOGRAPHY is oscar keyword + */ GEOGRAPHY("GEOGRAPHY"), + /** + * GEOMETRY is oscar keyword + */ GEOMETRY("GEOMETRY"), + /** + * GET is oscar keyword + */ GET("GET"), + /** + * GETCLOBVAL is oscar keyword + */ GETCLOBVAL("GETCLOBVAL"), + /** + * GETSTRINGVAL is oscar keyword + */ GETSTRINGVAL("GETSTRINGVAL"), + /** + * GLOBAL is oscar keyword + */ GLOBAL("GLOBAL"), + /** + * GLOBAL_NAME is oscar keyword + */ GLOBAL_NAME("GLOBAL_NAME"), + /** + * GLOBALLY is oscar keyword + */ GLOBALLY("GLOBALLY"), + /** + * GREATEST is oscar keyword + */ GREATEST("GREATEST"), + /** + * GROUPING is oscar keyword + */ GROUPING("GROUPING"), + /** + * GROUPING_ID is oscar keyword + */ GROUPING_ID("GROUPING_ID"), + /** + * GUARANTEE is oscar keyword + */ GUARANTEE("GUARANTEE"), + /** + * HANDLER is oscar keyword + */ HANDLER("HANDLER"), + /** + * HASH is oscar keyword + */ HASH("HASH"), + /** + * HEADER is oscar keyword + */ HEADER("HEADER"), + /** + * HEAP is oscar keyword + */ HEAP("HEAP"), + /** + * HOLD is oscar keyword + */ HOLD("HOLD"), + /** + * HOUR is oscar keyword + */ HOUR("HOUR"), + /** + * IDENTIFIED is oscar keyword + */ IDENTIFIED("IDENTIFIED"), + /** + * IDENTITY is oscar keyword + */ IDENTITY("IDENTITY"), + /** + * IF is oscar keyword + */ IF("IF"), + /** + * IGNORE is oscar keyword + */ IGNORE("IGNORE"), + /** + * ILIKE is oscar keyword + */ ILIKE("ILIKE"), + /** + * IMMEDIATE is oscar keyword + */ IMMEDIATE("IMMEDIATE"), + /** + * IMMUTABLE is oscar keyword + */ IMMUTABLE("IMMUTABLE"), + /** + * IMPLICIT is oscar keyword + */ IMPLICIT("IMPLICIT"), + /** + * IMPORT is oscar keyword + */ IMPORT("IMPORT"), + /** + * IMPORT_POLCOL is oscar keyword + */ IMPORT_POLCOL("IMPORT_POLCOL"), + /** + * INCREMENT is oscar keyword + */ INCREMENT("INCREMENT"), + /** + * INDEX is oscar keyword + */ INDEX("INDEX"), + /** + * INDEXES is oscar keyword + */ INDEXES("INDEXES"), + /** + * INHERITS is oscar keyword + */ INHERITS("INHERITS"), + /** + * INIT is oscar keyword + */ INIT("INIT"), + /** + * INITIAL is oscar keyword + */ INITIAL("INITIAL"), + /** + * INITIALIZED is oscar keyword + */ INITIALIZED("INITIALIZED"), + /** + * INITIALLY is oscar keyword + */ INITIALLY("INITIALLY"), + /** + * INITRANS is oscar keyword + */ INITRANS("INITRANS"), + /** + * INNER is oscar keyword + */ INNER("INNER"), + /** + * INOUT is oscar keyword + */ INOUT("INOUT"), + /** + * INPUT is oscar keyword + */ INPUT("INPUT"), + /** + * INSENSITIVE is oscar keyword + */ INSENSITIVE("INSENSITIVE"), + /** + * INSERT is oscar keyword + */ INSERT("INSERT"), + /** + * INSTEAD is oscar keyword + */ INSTEAD("INSTEAD"), + /** + * INTERVAL is oscar keyword + */ INTERVAL("INTERVAL"), + /** + * INVALIDATE is oscar keyword + */ INVALIDATE("INVALIDATE"), + /** + * INVISIBLE is oscar keyword + */ INVISIBLE("INVISIBLE"), + /** + * INVOKER is oscar keyword + */ INVOKER("INVOKER"), + /** + * IP is oscar keyword + */ IP("IP"), + /** + * IS is oscar keyword + */ IS("IS"), + /** + * ISNULL is oscar keyword + */ ISNULL("ISNULL"), + /** + * ISOLATION is oscar keyword + */ ISOLATION("ISOLATION"), + /** + * JOIN is oscar keyword + */ JOIN("JOIN"), + /** + * JSON is oscar keyword + */ JSON("JSON"), + /** + * JSON_TABLE is oscar keyword + */ JSON_TABLE("JSON_TABLE"), + /** + * JSON_VALUE is oscar keyword + */ JSON_VALUE("JSON_VALUE"), + /** + * K is oscar keyword + */ K("K"), + /** + * KB is oscar keyword + */ KB("KB"), + /** + * KEEP is oscar keyword + */ KEEP("KEEP"), + /** + * KEEPIDENTITY is oscar keyword + */ KEEPIDENTITY("KEEPIDENTITY"), + /** + * KEEPNULLS is oscar keyword + */ KEEPNULLS("KEEPNULLS"), + /** + * KEY is oscar keyword + */ KEY("KEY"), + /** + * KEYSTORE is oscar keyword + */ KEYSTORE("KEYSTORE"), + /** + * KILL is oscar keyword + */ KILL("KILL"), + /** + * KILOBYTES_PER_BATCH is oscar keyword + */ KILOBYTES_PER_BATCH("KILOBYTES_PER_BATCH"), + /** + * KSTORE is oscar keyword + */ KSTORE("KSTORE"), + /** + * LABEL is oscar keyword + */ LABEL("LABEL"), + /** + * LANCOMPILER is oscar keyword + */ LANCOMPILER("LANCOMPILER"), + /** + * LANGUAGE is oscar keyword + */ LANGUAGE("LANGUAGE"), + /** + * LAST is oscar keyword + */ LAST("LAST"), + /** + * LASTROW is oscar keyword + */ LASTROW("LASTROW"), + /** + * LC_COLLATE is oscar keyword + */ LC_COLLATE("LC_COLLATE"), + /** + * LC_CTYPE is oscar keyword + */ LC_CTYPE("LC_CTYPE"), + /** + * LDRTRIM is oscar keyword + */ LDRTRIM("LDRTRIM"), + /** + * LEADING is oscar keyword + */ LEADING("LEADING"), + /** + * LEAK is oscar keyword + */ LEAK("LEAK"), + /** + * LEAST is oscar keyword + */ LEAST("LEAST"), + /** + * LEFT is oscar keyword + */ LEFT("LEFT"), + /** + * LESS is oscar keyword + */ LESS("LESS"), + /** + * LIFETIME is oscar keyword + */ LIFETIME("LIFETIME"), + /** + * LIKE is oscar keyword + */ LIKE("LIKE"), + /** + * LIMIT is oscar keyword + */ LIMIT("LIMIT"), + /** + * LIST is oscar keyword + */ LIST("LIST"), + /** + * LISTEN is oscar keyword + */ LISTEN("LISTEN"), + /** + * LOAD is oscar keyword + */ LOAD("LOAD"), + /** + * LOB is oscar keyword + */ LOB("LOB"), + /** + * LOCAL is oscar keyword + */ LOCAL("LOCAL"), + /** + * LOCATION is oscar keyword + */ LOCATION("LOCATION"), + /** + * LOCK is oscar keyword + */ LOCK("LOCK"), + /** + * LOCKED is oscar keyword + */ LOCKED("LOCKED"), + /** + * LOG is oscar keyword + */ LOG("LOG"), + /** + * LOGFILE is oscar keyword + */ LOGFILE("LOGFILE"), + /** + * LOGGING is oscar keyword + */ LOGGING("LOGGING"), + /** + * LOGICAL is oscar keyword + */ LOGICAL("LOGICAL"), + /** + * LONG is oscar keyword + */ LONG("LONG"), + /** + * LOOP is oscar keyword + */ LOOP("LOOP"), + /** + * LRTRIM is oscar keyword + */ LRTRIM("LRTRIM"), + /** + * LSN is oscar keyword + */ LSN("LSN"), + /** + * LTRIM is oscar keyword + */ LTRIM("LTRIM"), + /** + * M is oscar keyword + */ M("M"), + /** + * MAINTAIN_INDEX is oscar keyword + */ MAINTAIN_INDEX("MAINTAIN_INDEX"), + /** + * MAINTENANCE is oscar keyword + */ MAINTENANCE("MAINTENANCE"), + /** + * MANUAL is oscar keyword + */ MANUAL("MANUAL"), + /** + * MASKING is oscar keyword + */ MASKING("MASKING"), + /** + * MATCH is oscar keyword + */ MATCH("MATCH"), + /** + * MATCHED is oscar keyword + */ MATCHED("MATCHED"), + /** + * MATERIALIZED is oscar keyword + */ MATERIALIZED("MATERIALIZED"), + /** + * MAX is oscar keyword + */ MAX("MAX"), + /** + * MAXERRORS is oscar keyword + */ MAXERRORS("MAXERRORS"), + /** + * MAXEXTENDS is oscar keyword + */ MAXEXTENDS("MAXEXTENDS"), + /** + * MAXEXTENTS is oscar keyword + */ MAXEXTENTS("MAXEXTENTS"), + /** + * MAXSIZE is oscar keyword + */ MAXSIZE("MAXSIZE"), + /** + * MAXTRANS is oscar keyword + */ MAXTRANS("MAXTRANS"), + /** + * MAXVALUE is oscar keyword + */ MAXVALUE("MAXVALUE"), + /** + * MB is oscar keyword + */ MB("MB"), + /** + * MEMBER is oscar keyword + */ MEMBER("MEMBER"), + /** + * MEMORY is oscar keyword + */ MEMORY("MEMORY"), + /** + * MERGE is oscar keyword + */ MERGE("MERGE"), + /** + * MIN is oscar keyword + */ MIN("MIN"), + /** + * MINEXTENDS is oscar keyword + */ MINEXTENDS("MINEXTENDS"), + /** + * MINEXTENTS is oscar keyword + */ MINEXTENTS("MINEXTENTS"), + /** + * MINSIZE is oscar keyword + */ MINSIZE("MINSIZE"), + /** + * MINUS is oscar keyword + */ MINUS("MINUS"), + /** + * MINUTE is oscar keyword + */ MINUTE("MINUTE"), + /** + * MINVALUE is oscar keyword + */ MINVALUE("MINVALUE"), + /** + * MISSING is oscar keyword + */ MISSING("MISSING"), + /** + * MOD is oscar keyword + */ MOD("MOD"), + /** + * MODE is oscar keyword + */ MODE("MODE"), + /** + * MODIFY is oscar keyword + */ MODIFY("MODIFY"), + /** + * MONEY is oscar keyword + */ MONEY("MONEY"), + /** + * MONTH is oscar keyword + */ MONTH("MONTH"), + /** + * MOUNT is oscar keyword + */ MOUNT("MOUNT"), + /** + * MOVE is oscar keyword + */ MOVE("MOVE"), + /** + * MOVEMENT is oscar keyword + */ MOVEMENT("MOVEMENT"), + /** + * MULTICOLUMN is oscar keyword + */ MULTICOLUMN("MULTICOLUMN"), + /** + * MULTIPLE is oscar keyword + */ MULTIPLE("MULTIPLE"), + /** + * NAME is oscar keyword + */ NAME("NAME"), + /** + * NAMES is oscar keyword + */ NAMES("NAMES"), + /** + * NATURAL is oscar keyword + */ NATURAL("NATURAL"), + /** + * NCHAR is oscar keyword + */ NCHAR("NCHAR"), + /** + * NEVER is oscar keyword + */ NEVER("NEVER"), + /** + * NEWLINE is oscar keyword + */ NEWLINE("NEWLINE"), + /** + * NEXT is oscar keyword + */ NEXT("NEXT"), + /** + * NEXTVAL is oscar keyword + */ NEXTVAL("NEXTVAL"), + /** + * NO is oscar keyword + */ NO("NO"), + /** + * NOARCHIVELOG is oscar keyword + */ NOARCHIVELOG("NOARCHIVELOG"), + /** + * NOAUDIT is oscar keyword + */ NOAUDIT("NOAUDIT"), + /** + * NOCACHE is oscar keyword + */ NOCACHE("NOCACHE"), + /** + * NOCOMPRESS is oscar keyword + */ NOCOMPRESS("NOCOMPRESS"), + /** + * NOCOPY is oscar keyword + */ NOCOPY("NOCOPY"), + /** + * NOCYCLE is oscar keyword + */ NOCYCLE("NOCYCLE"), + /** + * NODE is oscar keyword + */ NODE("NODE"), + /** + * NOGUARANTEE is oscar keyword + */ NOGUARANTEE("NOGUARANTEE"), + /** + * NOLOGGING is oscar keyword + */ NOLOGGING("NOLOGGING"), + /** + * NOMAXVALUE is oscar keyword + */ NOMAXVALUE("NOMAXVALUE"), + /** + * NOMINVALUE is oscar keyword + */ NOMINVALUE("NOMINVALUE"), + /** + * NOMOUNT is oscar keyword + */ NOMOUNT("NOMOUNT"), + /** + * NORMAL is oscar keyword + */ NORMAL("NORMAL"), + /** + * NOTHING is oscar keyword + */ NOTHING("NOTHING"), + /** + * NOTIFY is oscar keyword + */ NOTIFY("NOTIFY"), + /** + * NOTNULL is oscar keyword + */ NOTNULL("NOTNULL"), + /** + * NOTRIM is oscar keyword + */ NOTRIM("NOTRIM"), + /** + * NOVALIDATE is oscar keyword + */ NOVALIDATE("NOVALIDATE"), + /** + * NOWAIT is oscar keyword + */ NOWAIT("NOWAIT"), + /** + * NVARCHAR2 is oscar keyword + */ NVARCHAR2("NVARCHAR2"), + /** + * NVL is oscar keyword + */ NVL("NVL"), + /** + * NVL2 is oscar keyword + */ NVL2("NVL2"), + /** + * OBJECT is oscar keyword + */ OBJECT("OBJECT"), + /** + * OF is oscar keyword + */ OF("OF"), + /** + * OFF is oscar keyword + */ OFF("OFF"), + /** + * OFFLINE is oscar keyword + */ OFFLINE("OFFLINE"), + /** + * OFFSET is oscar keyword + */ OFFSET("OFFSET"), + /** + * OIDS is oscar keyword + */ OIDS("OIDS"), + /** + * ONLINE is oscar keyword + */ ONLINE("ONLINE"), + /** + * OPEN is oscar keyword + */ OPEN("OPEN"), + /** + * OPERATOR is oscar keyword + */ OPERATOR("OPERATOR"), + /** + * OPTIMIZE is oscar keyword + */ OPTIMIZE("OPTIMIZE"), + /** + * OPTIMIZE_KSCACHE is oscar keyword + */ OPTIMIZE_KSCACHE("OPTIMIZE_KSCACHE"), + /** + * OPTION is oscar keyword + */ OPTION("OPTION"), + /** + * ORACLE is oscar keyword + */ ORACLE("ORACLE"), + /** + * ORDINALITY is oscar keyword + */ ORDINALITY("ORDINALITY"), + /** + * ORGANIZATION is oscar keyword + */ ORGANIZATION("ORGANIZATION"), + /** + * OSCAR is oscar keyword + */ OSCAR("OSCAR"), + /** + * OUT is oscar keyword + */ OUT("OUT"), + /** + * OUTER is oscar keyword + */ OUTER("OUTER"), + /** + * OUTLINE is oscar keyword + */ OUTLINE("OUTLINE"), + /** + * OVER is oscar keyword + */ OVER("OVER"), + /** + * OVERFLOW is oscar keyword + */ OVERFLOW("OVERFLOW"), + /** + * OVERLAPS is oscar keyword + */ OVERLAPS("OVERLAPS"), + /** + * OVERLAY is oscar keyword + */ OVERLAY("OVERLAY"), + /** + * OWNER is oscar keyword + */ OWNER("OWNER"), + /** + * PACKAGE is oscar keyword + */ PACKAGE("PACKAGE"), + /** + * PAGESIZE is oscar keyword + */ PAGESIZE("PAGESIZE"), + /** + * PARALLEL is oscar keyword + */ PARALLEL("PARALLEL"), + /** + * PARAMETER is oscar keyword + */ PARAMETER("PARAMETER"), + /** + * PARAMINFO is oscar keyword + */ PARAMINFO("PARAMINFO"), + /** + * PARTIAL is oscar keyword + */ PARTIAL("PARTIAL"), + /** + * PARTITION is oscar keyword + */ PARTITION("PARTITION"), + /** + * PARTITIONS is oscar keyword + */ PARTITIONS("PARTITIONS"), + /** + * PASSING is oscar keyword + */ PASSING("PASSING"), + /** + * PASSWORD is oscar keyword + */ PASSWORD("PASSWORD"), + /** + * PATH is oscar keyword + */ PATH("PATH"), + /** + * PCTFREE is oscar keyword + */ PCTFREE("PCTFREE"), + /** + * PCTINCREASE is oscar keyword + */ PCTINCREASE("PCTINCREASE"), + /** + * PCTTHRESHOLD is oscar keyword + */ PCTTHRESHOLD("PCTTHRESHOLD"), + /** + * PCTUSED is oscar keyword + */ PCTUSED("PCTUSED"), + /** + * PCTVERSION is oscar keyword + */ PCTVERSION("PCTVERSION"), + /** + * PENDANT is oscar keyword + */ PENDANT("PENDANT"), + /** + * PETENTION is oscar keyword + */ PETENTION("PETENTION"), + /** + * PFILE is oscar keyword + */ PFILE("PFILE"), + /** + * PIPELINED is oscar keyword + */ PIPELINED("PIPELINED"), + /** + * PIVOT is oscar keyword + */ PIVOT("PIVOT"), + /** + * PLACING is oscar keyword + */ PLACING("PLACING"), + /** + * PLS_INTEGER is oscar keyword + */ PLS_INTEGER("PLS_INTEGER"), + /** + * POLICY is oscar keyword + */ POLICY("POLICY"), + /** + * PORT is oscar keyword + */ PORT("PORT"), + /** + * POSITION is oscar keyword + */ POSITION("POSITION"), + /** + * PRECEDING is oscar keyword + */ PRECEDING("PRECEDING"), + /** + * PRECISION is oscar keyword + */ PRECISION("PRECISION"), + /** + * PREPARE is oscar keyword + */ PREPARE("PREPARE"), + /** + * PRESERVE is oscar keyword + */ PRESERVE("PRESERVE"), + /** + * PREVAL is oscar keyword + */ PREVAL("PREVAL"), + /** + * PRIMARY is oscar keyword + */ PRIMARY("PRIMARY"), + /** + * PRIOR is oscar keyword + */ PRIOR("PRIOR"), + /** + * PRIORITY is oscar keyword + */ PRIORITY("PRIORITY"), + /** + * PRIVILEGES is oscar keyword + */ PRIVILEGES("PRIVILEGES"), + /** + * PROCEDURAL is oscar keyword + */ PROCEDURAL("PROCEDURAL"), + /** + * PROCEDURE is oscar keyword + */ PROCEDURE("PROCEDURE"), + /** + * PUBLIC is oscar keyword + */ PUBLIC("PUBLIC"), + /** + * PURGE is oscar keyword + */ PURGE("PURGE"), + /** + * QU is oscar keyword + */ QU("QU"), + /** + * QUERY is oscar keyword + */ QUERY("QUERY"), + /** + * QUICK is oscar keyword + */ QUICK("QUICK"), + /** + * QUOTE is oscar keyword + */ QUOTE("QUOTE"), + /** + * RAC is oscar keyword + */ RAC("RAC"), + /** + * RANGE is oscar keyword + */ RANGE("RANGE"), + /** + * RATIO_TO_REPORT is oscar keyword + */ RATIO_TO_REPORT("RATIO_TO_REPORT"), + /** + * RAW is oscar keyword + */ RAW("RAW"), + /** + * READ is oscar keyword + */ READ("READ"), + /** + * READABLE is oscar keyword + */ READABLE("READABLE"), + /** + * READS is oscar keyword + */ READS("READS"), + /** + * READSIZE is oscar keyword + */ READSIZE("READSIZE"), + /** + * REBUILD is oscar keyword + */ REBUILD("REBUILD"), + /** + * RECHECK is oscar keyword + */ RECHECK("RECHECK"), + /** + * RECORDS is oscar keyword + */ RECORDS("RECORDS"), + /** + * RECOVERY is oscar keyword + */ RECOVERY("RECOVERY"), + /** + * RECREATE is oscar keyword + */ RECREATE("RECREATE"), + /** + * RECURSIVE is oscar keyword + */ RECURSIVE("RECURSIVE"), + /** + * RECYCLE is oscar keyword + */ RECYCLE("RECYCLE"), + /** + * REFRESH is oscar keyword + */ REFRESH("REFRESH"), + /** + * REGEXP is oscar keyword + */ REGEXP("REGEXP"), + /** + * REGION is oscar keyword + */ REGION("REGION"), + /** + * REJECT is oscar keyword + */ REJECT("REJECT"), + /** + * RELATIVE is oscar keyword + */ RELATIVE("RELATIVE"), + /** + * REMOVE is oscar keyword + */ REMOVE("REMOVE"), + /** + * RENAME is oscar keyword + */ RENAME("RENAME"), + /** + * REPEATABLE is oscar keyword + */ REPEATABLE("REPEATABLE"), + /** + * REPLACE is oscar keyword + */ REPLACE("REPLACE"), + /** + * RESET is oscar keyword + */ RESET("RESET"), + /** + * RESIZE is oscar keyword + */ RESIZE("RESIZE"), + /** + * RESOURCE is oscar keyword + */ RESOURCE("RESOURCE"), + /** + * RESTART is oscar keyword + */ RESTART("RESTART"), + /** + * RESTORE is oscar keyword + */ RESTORE("RESTORE"), + /** + * RESTRICT is oscar keyword + */ RESTRICT("RESTRICT"), + /** + * RESULT is oscar keyword + */ RESULT("RESULT"), + /** + * RESUME is oscar keyword + */ RESUME("RESUME"), + /** + * RETENTION is oscar keyword + */ RETENTION("RETENTION"), + /** + * RETURN is oscar keyword + */ RETURN("RETURN"), + /** + * RETURN_GENERATED_KEYS is oscar keyword + */ RETURN_GENERATED_KEYS("RETURN_GENERATED_KEYS"), + /** + * RETURNING is oscar keyword + */ RETURNING("RETURNING"), + /** + * RETURNS is oscar keyword + */ RETURNS("RETURNS"), + /** + * REUSE is oscar keyword + */ REUSE("REUSE"), + /** + * REVERSE is oscar keyword + */ REVERSE("REVERSE"), + /** + * REVOKE is oscar keyword + */ REVOKE("REVOKE"), + /** + * REWRITE is oscar keyword + */ REWRITE("REWRITE"), + /** + * RIGHT is oscar keyword + */ RIGHT("RIGHT"), + /** + * ROLE is oscar keyword + */ ROLE("ROLE"), + /** + * ROLLBACK is oscar keyword + */ ROLLBACK("ROLLBACK"), + /** + * ROLLUP is oscar keyword + */ ROLLUP("ROLLUP"), + /** + * ROW is oscar keyword + */ ROW("ROW"), + /** + * ROWDESCRIPTION is oscar keyword + */ ROWDESCRIPTION("ROWDESCRIPTION"), + /** + * ROWID is oscar keyword + */ ROWID("ROWID"), + /** + * ROWS is oscar keyword + */ ROWS("ROWS"), + /** + * ROWS_PER_BATCH is oscar keyword + */ ROWS_PER_BATCH("ROWS_PER_BATCH"), + /** + * ROWTERMINATOR is oscar keyword + */ ROWTERMINATOR("ROWTERMINATOR"), + /** + * ROWTYPE is oscar keyword + */ ROWTYPE("ROWTYPE"), + /** + * RTRIM is oscar keyword + */ RTRIM("RTRIM"), + /** + * RULE is oscar keyword + */ RULE("RULE"), + /** + * SAMPLE is oscar keyword + */ SAMPLE("SAMPLE"), + /** + * SAVEPOINT is oscar keyword + */ SAVEPOINT("SAVEPOINT"), + /** + * SCAN is oscar keyword + */ SCAN("SCAN"), + /** + * SCHEMA is oscar keyword + */ SCHEMA("SCHEMA"), + /** + * SCN is oscar keyword + */ SCN("SCN"), + /** + * SCROLL is oscar keyword + */ SCROLL("SCROLL"), + /** + * SECOND is oscar keyword + */ SECOND("SECOND"), + /** + * SECURITY is oscar keyword + */ SECURITY("SECURITY"), + /** + * SEGMENT is oscar keyword + */ SEGMENT("SEGMENT"), + /** + * SEPARATOR is oscar keyword + */ SEPARATOR("SEPARATOR"), + /** + * SEQUENCE is oscar keyword + */ SEQUENCE("SEQUENCE"), + /** + * SERIALIZABLE is oscar keyword + */ SERIALIZABLE("SERIALIZABLE"), + /** + * SESSION is oscar keyword + */ SESSION("SESSION"), + /** + * SETS is oscar keyword + */ SETS("SETS"), + /** + * SHARE is oscar keyword + */ SHARE("SHARE"), + /** + * SHOW is oscar keyword + */ SHOW("SHOW"), + /** + * SHRINK is oscar keyword + */ SHRINK("SHRINK"), + /** + * SHRINKLOG is oscar keyword + */ SHRINKLOG("SHRINKLOG"), + /** + * SHUTDOWN is oscar keyword + */ SHUTDOWN("SHUTDOWN"), + /** + * SIBLINGS is oscar keyword + */ SIBLINGS("SIBLINGS"), + /** + * SIGNED is oscar keyword + */ SIGNED("SIGNED"), + /** + * SILENTLY is oscar keyword + */ SILENTLY("SILENTLY"), + /** + * SIMILAR is oscar keyword + */ SIMILAR("SIMILAR"), + /** + * SIMPLE is oscar keyword + */ SIMPLE("SIMPLE"), + /** + * SINGLE is oscar keyword + */ SINGLE("SINGLE"), + /** + * SINGLEROW is oscar keyword + */ SINGLEROW("SINGLEROW"), + /** + * SIZE is oscar keyword + */ SIZE("SIZE"), + /** + * SKIP is oscar keyword + */ SKIP("SKIP"), + /** + * SMALLINT is oscar keyword + */ SMALLINT("SMALLINT"), + /** + * SPACE is oscar keyword + */ SPACE("SPACE"), + /** + * SPLIT is oscar keyword + */ SPLIT("SPLIT"), + /** + * STABLE is oscar keyword + */ STABLE("STABLE"), + /** + * STANDALONE is oscar keyword + */ STANDALONE("STANDALONE"), + /** + * STANDARDANALYZER is oscar keyword + */ STANDARDANALYZER("STANDARDANALYZER"), + /** + * START is oscar keyword + */ START("START"), + /** + * STARTFILE is oscar keyword + */ STARTFILE("STARTFILE"), + /** + * STARTPOS is oscar keyword + */ STARTPOS("STARTPOS"), + /** + * STARTTIME is oscar keyword + */ STARTTIME("STARTTIME"), + /** + * STARTUP is oscar keyword + */ STARTUP("STARTUP"), + /** + * STATEMENT is oscar keyword + */ STATEMENT("STATEMENT"), + /** + * STATIC is oscar keyword + */ STATIC("STATIC"), + /** + * STATISTICS is oscar keyword + */ STATISTICS("STATISTICS"), + /** + * STDIN is oscar keyword + */ STDIN("STDIN"), + /** + * STDOUT is oscar keyword + */ STDOUT("STDOUT"), + /** + * STOP is oscar keyword + */ STOP("STOP"), + /** + * STOPFILE is oscar keyword + */ STOPFILE("STOPFILE"), + /** + * STOPPOS is oscar keyword + */ STOPPOS("STOPPOS"), + /** + * STOPTIME is oscar keyword + */ STOPTIME("STOPTIME"), + /** + * STOPWORDS is oscar keyword + */ STOPWORDS("STOPWORDS"), + /** + * STORAGE is oscar keyword + */ STORAGE("STORAGE"), + /** + * STORE is oscar keyword + */ STORE("STORE"), + /** + * STORED is oscar keyword + */ STORED("STORED"), + /** + * STRICT is oscar keyword + */ STRICT("STRICT"), + /** + * SUBPARTITION is oscar keyword + */ SUBPARTITION("SUBPARTITION"), + /** + * SUBPARTITIONS is oscar keyword + */ SUBPARTITIONS("SUBPARTITIONS"), + /** + * SUBSTRING is oscar keyword + */ SUBSTRING("SUBSTRING"), + /** + * SUCCESSFUL is oscar keyword + */ SUCCESSFUL("SUCCESSFUL"), + /** + * SUSPEND is oscar keyword + */ SUSPEND("SUSPEND"), + /** + * SWITCHOVER is oscar keyword + */ SWITCHOVER("SWITCHOVER"), + /** + * SYNC is oscar keyword + */ SYNC("SYNC"), + /** + * SYSAUX is oscar keyword + */ SYSAUX("SYSAUX"), + /** + * SYSID is oscar keyword + */ SYSID("SYSID"), + /** + * SYSTEM is oscar keyword + */ SYSTEM("SYSTEM"), + /** + * T is oscar keyword + */ T("T"), + /** + * TABLESPACE is oscar keyword + */ TABLESPACE("TABLESPACE"), + /** + * TB is oscar keyword + */ TB("TB"), + /** + * TEMP is oscar keyword + */ TEMP("TEMP"), + /** + * TEMPFILE is oscar keyword + */ TEMPFILE("TEMPFILE"), + /** + * TEMPLATE is oscar keyword + */ TEMPLATE("TEMPLATE"), + /** + * TEMPORARY is oscar keyword + */ TEMPORARY("TEMPORARY"), + /** + * TERMINATED is oscar keyword + */ TERMINATED("TERMINATED"), + /** + * THAN is oscar keyword + */ THAN("THAN"), + /** + * TIMES is oscar keyword + */ TIMES("TIMES"), + /** + * TIMEZONE is oscar keyword + */ TIMEZONE("TIMEZONE"), + /** + * TINYINT is oscar keyword + */ TINYINT("TINYINT"), + /** + * TOAST is oscar keyword + */ TOAST("TOAST"), + /** + * TRACE is oscar keyword + */ TRACE("TRACE"), + /** + * TRACKING is oscar keyword + */ TRACKING("TRACKING"), + /** + * TRAIL is oscar keyword + */ TRAIL("TRAIL"), + /** + * TRAILING is oscar keyword + */ TRAILING("TRAILING"), + /** + * TRANSACTION is oscar keyword + */ TRANSACTION("TRANSACTION"), + /** + * TRANSACTIONAL is oscar keyword + */ TRANSACTIONAL("TRANSACTIONAL"), + /** + * TRANSFORMS is oscar keyword + */ TRANSFORMS("TRANSFORMS"), + /** + * TREAT is oscar keyword + */ TREAT("TREAT"), + /** + * TRIAL is oscar keyword + */ TRIAL("TRIAL"), + /** + * TRIGGER is oscar keyword + */ TRIGGER("TRIGGER"), + /** + * TRIGGERS is oscar keyword + */ TRIGGERS("TRIGGERS"), + /** + * TRIM is oscar keyword + */ TRIM("TRIM"), + /** + * TRUE is oscar keyword + */ TRUE("TRUE"), + /** + * TRUNCATE is oscar keyword + */ TRUNCATE("TRUNCATE"), + /** + * TRUSTED is oscar keyword + */ TRUSTED("TRUSTED"), + /** + * TUPLE is oscar keyword + */ TUPLE("TUPLE"), + /** + * TYPE is oscar keyword + */ TYPE("TYPE"), + /** + * UNBOUNDED is oscar keyword + */ UNBOUNDED("UNBOUNDED"), + /** + * UNCOMMITTED is oscar keyword + */ UNCOMMITTED("UNCOMMITTED"), + /** + * UNDO is oscar keyword + */ UNDO("UNDO"), + /** + * UNENCRYPTED is oscar keyword + */ UNENCRYPTED("UNENCRYPTED"), + /** + * UNKNOWN is oscar keyword + */ UNKNOWN("UNKNOWN"), + /** + * UNLIMITED is oscar keyword + */ UNLIMITED("UNLIMITED"), + /** + * UNLISTEN is oscar keyword + */ UNLISTEN("UNLISTEN"), + /** + * UNLOCK is oscar keyword + */ UNLOCK("UNLOCK"), + /** + * UNMAINTENANCE is oscar keyword + */ UNMAINTENANCE("UNMAINTENANCE"), + /** + * UNPIVOT is oscar keyword + */ UNPIVOT("UNPIVOT"), + /** + * UNSIGNED is oscar keyword + */ UNSIGNED("UNSIGNED"), + /** + * UNTIL is oscar keyword + */ UNTIL("UNTIL"), + /** + * UNUSABLE is oscar keyword + */ UNUSABLE("UNUSABLE"), + /** + * UP is oscar keyword + */ UP("UP"), + /** + * UPDATE is oscar keyword + */ UPDATE("UPDATE"), + /** + * UPDATELABEL is oscar keyword + */ UPDATELABEL("UPDATELABEL"), + /** + * UPDATEXML is oscar keyword + */ UPDATEXML("UPDATEXML"), + /** + * USAGE is oscar keyword + */ USAGE("USAGE"), + /** + * USE is oscar keyword + */ USE("USE"), + /** + * USER is oscar keyword + */ USER("USER"), + /** + * UTF8 is oscar keyword + */ UTF8("UTF8"), + /** + * UTF8MB4 is oscar keyword + */ UTF8MB4("UTF8MB4"), + /** + * VACUUM is oscar keyword + */ VACUUM("VACUUM"), + /** + * VALID is oscar keyword + */ VALID("VALID"), + /** + * VALIDATE is oscar keyword + */ VALIDATE("VALIDATE"), + /** + * VALIDATION is oscar keyword + */ VALIDATION("VALIDATION"), + /** + * VALIDATOR is oscar keyword + */ VALIDATOR("VALIDATOR"), + /** + * VALUE is oscar keyword + */ VALUE("VALUE"), + /** + * VALUES is oscar keyword + */ VALUES("VALUES"), + /** + * VARBINARY is oscar keyword + */ VARBINARY("VARBINARY"), + /** + * VARBIT is oscar keyword + */ VARBIT("VARBIT"), + /** + * VARCHAR is oscar keyword + */ VARCHAR("VARCHAR"), + /** + * VARCHAR2 is oscar keyword + */ VARCHAR2("VARCHAR2"), + /** + * VARYING is oscar keyword + */ VARYING("VARYING"), + /** + * VERBOSE is oscar keyword + */ VERBOSE("VERBOSE"), + /** + * VERSION is oscar keyword + */ VERSION("VERSION"), + /** + * VERSIONS is oscar keyword + */ VERSIONS("VERSIONS"), + /** + * VIEW is oscar keyword + */ VIEW("VIEW"), + /** + * VIRTUAL is oscar keyword + */ VIRTUAL("VIRTUAL"), + /** + * VISIBLE is oscar keyword + */ VISIBLE("VISIBLE"), + /** + * VOLATILE is oscar keyword + */ VOLATILE("VOLATILE"), + /** + * VOTEDISK is oscar keyword + */ VOTEDISK("VOTEDISK"), + /** + * WAIT is oscar keyword + */ WAIT("WAIT"), + /** + * WALLET is oscar keyword + */ WALLET("WALLET"), + /** + * WEIGHT is oscar keyword + */ WEIGHT("WEIGHT"), + /** + * WHEN is oscar keyword + */ WHEN("WHEN"), + /** + * WHENEVER is oscar keyword + */ WHENEVER("WHENEVER"), + /** + * WINDOW is oscar keyword + */ WINDOW("WINDOW"), + /** + * WORK is oscar keyword + */ WORK("WORK"), + /** + * XML is oscar keyword + */ XML("XML"), + /** + * XMLATTRIBUTES is oscar keyword + */ XMLATTRIBUTES("XMLATTRIBUTES"), + /** + * XMLCONCAT is oscar keyword + */ XMLCONCAT("XMLCONCAT"), + /** + * XMLELEMENT is oscar keyword + */ XMLELEMENT("XMLELEMENT"), + /** + * XMLFOREST is oscar keyword + */ XMLFOREST("XMLFOREST"), + /** + * XMLPARSE is oscar keyword + */ XMLPARSE("XMLPARSE"), + /** + * XMLPI is oscar keyword + */ XMLPI("XMLPI"), + /** + * XMLROOT is oscar keyword + */ XMLROOT("XMLROOT"), + /** + * XMLSERIALIZE is oscar keyword + */ XMLSERIALIZE("XMLSERIALIZE"), + /** + * XMLTABLE is oscar keyword + */ XMLTABLE("XMLTABLE"), + /** + * YEAR is oscar keyword + */ YEAR("YEAR"), + /** + * YES is oscar keyword + */ YES("YES"), + /** + * ZONE is oscar keyword + */ ZONE("ZONE"); /** * The Name. diff --git a/rm-datasource/src/main/java/org/apache/seata/rm/datasource/sql/struct/cache/OscarTableMetaCache.java b/rm-datasource/src/main/java/org/apache/seata/rm/datasource/sql/struct/cache/OscarTableMetaCache.java index 35610d4e310..bed10c785f1 100644 --- a/rm-datasource/src/main/java/org/apache/seata/rm/datasource/sql/struct/cache/OscarTableMetaCache.java +++ b/rm-datasource/src/main/java/org/apache/seata/rm/datasource/sql/struct/cache/OscarTableMetaCache.java @@ -37,7 +37,6 @@ /** * The type Table meta cache. * - * @author hsh */ @LoadLevel(name = JdbcConstants.OSCAR) public class OscarTableMetaCache extends AbstractTableMetaCache { diff --git a/rm-datasource/src/main/java/org/apache/seata/rm/datasource/undo/oscar/OscarUndoDeleteExecutor.java b/rm-datasource/src/main/java/org/apache/seata/rm/datasource/undo/oscar/OscarUndoDeleteExecutor.java index 4874cfc80eb..04105a4b152 100644 --- a/rm-datasource/src/main/java/org/apache/seata/rm/datasource/undo/oscar/OscarUndoDeleteExecutor.java +++ b/rm-datasource/src/main/java/org/apache/seata/rm/datasource/undo/oscar/OscarUndoDeleteExecutor.java @@ -33,7 +33,6 @@ /** * The type oscar undo delete executor. * - * @author hsh */ public class OscarUndoDeleteExecutor extends AbstractUndoExecutor { diff --git a/rm-datasource/src/main/java/org/apache/seata/rm/datasource/undo/oscar/OscarUndoInsertExecutor.java b/rm-datasource/src/main/java/org/apache/seata/rm/datasource/undo/oscar/OscarUndoInsertExecutor.java index cd696f62001..3e56b37059f 100644 --- a/rm-datasource/src/main/java/org/apache/seata/rm/datasource/undo/oscar/OscarUndoInsertExecutor.java +++ b/rm-datasource/src/main/java/org/apache/seata/rm/datasource/undo/oscar/OscarUndoInsertExecutor.java @@ -35,7 +35,6 @@ /** * The type oscar undo insert executor. * - * @author hsh */ public class OscarUndoInsertExecutor extends AbstractUndoExecutor { diff --git a/rm-datasource/src/main/java/org/apache/seata/rm/datasource/undo/oscar/OscarUndoLogManager.java b/rm-datasource/src/main/java/org/apache/seata/rm/datasource/undo/oscar/OscarUndoLogManager.java index 445581b48ff..68b405b6237 100644 --- a/rm-datasource/src/main/java/org/apache/seata/rm/datasource/undo/oscar/OscarUndoLogManager.java +++ b/rm-datasource/src/main/java/org/apache/seata/rm/datasource/undo/oscar/OscarUndoLogManager.java @@ -32,7 +32,7 @@ import java.util.Date; /** - * @author hsh + * The type Oscar undo log manager. */ @LoadLevel(name = JdbcConstants.OSCAR) public class OscarUndoLogManager extends AbstractUndoLogManager { diff --git a/rm-datasource/src/main/java/org/apache/seata/rm/datasource/undo/oscar/OscarUndoUpdateExecutor.java b/rm-datasource/src/main/java/org/apache/seata/rm/datasource/undo/oscar/OscarUndoUpdateExecutor.java index e8eabd4a63e..d2364d7f482 100644 --- a/rm-datasource/src/main/java/org/apache/seata/rm/datasource/undo/oscar/OscarUndoUpdateExecutor.java +++ b/rm-datasource/src/main/java/org/apache/seata/rm/datasource/undo/oscar/OscarUndoUpdateExecutor.java @@ -33,7 +33,6 @@ /** * The type oscar undo update executor. * - * @author hsh */ public class OscarUndoUpdateExecutor extends AbstractUndoExecutor { diff --git a/rm-datasource/src/test/java/org/apache/seata/rm/datasource/exec/OscarInsertExecutorTest.java b/rm-datasource/src/test/java/org/apache/seata/rm/datasource/exec/OscarInsertExecutorTest.java index 5ce10955ec5..0e27823212c 100644 --- a/rm-datasource/src/test/java/org/apache/seata/rm/datasource/exec/OscarInsertExecutorTest.java +++ b/rm-datasource/src/test/java/org/apache/seata/rm/datasource/exec/OscarInsertExecutorTest.java @@ -39,7 +39,7 @@ import static org.mockito.Mockito.*; /** - * @author hsh + * The type Oscar insert executor test. */ public class OscarInsertExecutorTest { diff --git a/rm-datasource/src/test/java/org/apache/seata/rm/datasource/sql/druid/oscar/OscarDeleteRecognizerTest.java b/rm-datasource/src/test/java/org/apache/seata/rm/datasource/sql/druid/oscar/OscarDeleteRecognizerTest.java index 81e432a065e..405198f5b55 100644 --- a/rm-datasource/src/test/java/org/apache/seata/rm/datasource/sql/druid/oscar/OscarDeleteRecognizerTest.java +++ b/rm-datasource/src/test/java/org/apache/seata/rm/datasource/sql/druid/oscar/OscarDeleteRecognizerTest.java @@ -32,7 +32,7 @@ import java.util.Map; /** - * @author hsh + * The type Oscar delete recognizer test. */ public class OscarDeleteRecognizerTest { diff --git a/rm-datasource/src/test/java/org/apache/seata/rm/datasource/sql/druid/oscar/OscarInsertRecognizerTest.java b/rm-datasource/src/test/java/org/apache/seata/rm/datasource/sql/druid/oscar/OscarInsertRecognizerTest.java index a344ae2c549..2a025866816 100644 --- a/rm-datasource/src/test/java/org/apache/seata/rm/datasource/sql/druid/oscar/OscarInsertRecognizerTest.java +++ b/rm-datasource/src/test/java/org/apache/seata/rm/datasource/sql/druid/oscar/OscarInsertRecognizerTest.java @@ -31,7 +31,7 @@ import java.util.List; /** - * @author hsh + * The type Oscar insert recognizer test. */ public class OscarInsertRecognizerTest { diff --git a/rm-datasource/src/test/java/org/apache/seata/rm/datasource/sql/druid/oscar/OscarSelectForUpdateRecognizerTest.java b/rm-datasource/src/test/java/org/apache/seata/rm/datasource/sql/druid/oscar/OscarSelectForUpdateRecognizerTest.java index b028835291d..604dcd99132 100644 --- a/rm-datasource/src/test/java/org/apache/seata/rm/datasource/sql/druid/oscar/OscarSelectForUpdateRecognizerTest.java +++ b/rm-datasource/src/test/java/org/apache/seata/rm/datasource/sql/druid/oscar/OscarSelectForUpdateRecognizerTest.java @@ -31,7 +31,7 @@ import java.util.Map; /** - * @author hsh + * The type Oscar select for update recognizer test. */ public class OscarSelectForUpdateRecognizerTest { diff --git a/rm-datasource/src/test/java/org/apache/seata/rm/datasource/sql/druid/oscar/OscarUpdateRecognizerTest.java b/rm-datasource/src/test/java/org/apache/seata/rm/datasource/sql/druid/oscar/OscarUpdateRecognizerTest.java index 209c892781e..120086affc5 100644 --- a/rm-datasource/src/test/java/org/apache/seata/rm/datasource/sql/druid/oscar/OscarUpdateRecognizerTest.java +++ b/rm-datasource/src/test/java/org/apache/seata/rm/datasource/sql/druid/oscar/OscarUpdateRecognizerTest.java @@ -33,7 +33,7 @@ import java.util.Map; /** - * @author hsh + * The Oscar Update Recognizer Test. */ public class OscarUpdateRecognizerTest { diff --git a/sqlparser/seata-sqlparser-druid/src/main/java/org/apache/seata/sqlparser/druid/oscar/BaseOscarRecognizer.java b/sqlparser/seata-sqlparser-druid/src/main/java/org/apache/seata/sqlparser/druid/oscar/BaseOscarRecognizer.java index 0a3e925bfe9..a0a3b505354 100644 --- a/sqlparser/seata-sqlparser-druid/src/main/java/org/apache/seata/sqlparser/druid/oscar/BaseOscarRecognizer.java +++ b/sqlparser/seata-sqlparser-druid/src/main/java/org/apache/seata/sqlparser/druid/oscar/BaseOscarRecognizer.java @@ -43,7 +43,7 @@ import java.util.Objects; /** - * @author hsh + * The type Base oscar recognizer. */ public abstract class BaseOscarRecognizer extends BaseRecognizer { diff --git a/sqlparser/seata-sqlparser-druid/src/main/java/org/apache/seata/sqlparser/druid/oscar/OscarOperateRecognizerHolder.java b/sqlparser/seata-sqlparser-druid/src/main/java/org/apache/seata/sqlparser/druid/oscar/OscarOperateRecognizerHolder.java index b0704508582..4cffed03774 100644 --- a/sqlparser/seata-sqlparser-druid/src/main/java/org/apache/seata/sqlparser/druid/oscar/OscarOperateRecognizerHolder.java +++ b/sqlparser/seata-sqlparser-druid/src/main/java/org/apache/seata/sqlparser/druid/oscar/OscarOperateRecognizerHolder.java @@ -26,7 +26,6 @@ /** * The Type OscarOperateRecognizerHolder * - * @author hsh */ @LoadLevel(name = JdbcConstants.OSCAR) public class OscarOperateRecognizerHolder implements SQLOperateRecognizerHolder { diff --git a/sqlparser/seata-sqlparser-druid/src/main/java/org/apache/seata/sqlparser/druid/oscar/OscarUpdateRecognizer.java b/sqlparser/seata-sqlparser-druid/src/main/java/org/apache/seata/sqlparser/druid/oscar/OscarUpdateRecognizer.java index 259ff6b4d55..c1cca98ff7b 100644 --- a/sqlparser/seata-sqlparser-druid/src/main/java/org/apache/seata/sqlparser/druid/oscar/OscarUpdateRecognizer.java +++ b/sqlparser/seata-sqlparser-druid/src/main/java/org/apache/seata/sqlparser/druid/oscar/OscarUpdateRecognizer.java @@ -40,7 +40,6 @@ /** * The type oscar update recognizer. * - * @author hsh */ public class OscarUpdateRecognizer extends BaseOscarRecognizer implements SQLUpdateRecognizer { From c53552b2ce70fca75c328791a9f4eda2e37a7803 Mon Sep 17 00:00:00 2001 From: hanshaohua Date: Wed, 9 Oct 2024 09:37:29 +0800 Subject: [PATCH 11/19] Update sqlparser/seata-sqlparser-druid/src/main/java/org/apache/seata/sqlparser/druid/oscar/OscarInsertRecognizer.java Co-authored-by: funkye <364176773@qq.com> --- .../seata/sqlparser/druid/oscar/OscarInsertRecognizer.java | 1 - 1 file changed, 1 deletion(-) diff --git a/sqlparser/seata-sqlparser-druid/src/main/java/org/apache/seata/sqlparser/druid/oscar/OscarInsertRecognizer.java b/sqlparser/seata-sqlparser-druid/src/main/java/org/apache/seata/sqlparser/druid/oscar/OscarInsertRecognizer.java index fcb1ede4e88..fe484f9b758 100644 --- a/sqlparser/seata-sqlparser-druid/src/main/java/org/apache/seata/sqlparser/druid/oscar/OscarInsertRecognizer.java +++ b/sqlparser/seata-sqlparser-druid/src/main/java/org/apache/seata/sqlparser/druid/oscar/OscarInsertRecognizer.java @@ -43,7 +43,6 @@ /** * The type oscar insert recognizer. * - * @author ccg */ public class OscarInsertRecognizer extends BaseOscarRecognizer implements SQLInsertRecognizer { From 8f942906019a8a3b947304e95a80610b93ad1eb9 Mon Sep 17 00:00:00 2001 From: hanshaohua Date: Wed, 9 Oct 2024 09:37:40 +0800 Subject: [PATCH 12/19] Update sqlparser/seata-sqlparser-druid/src/main/java/org/apache/seata/sqlparser/druid/oscar/OscarSelectForUpdateRecognizer.java Co-authored-by: funkye <364176773@qq.com> --- .../sqlparser/druid/oscar/OscarSelectForUpdateRecognizer.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sqlparser/seata-sqlparser-druid/src/main/java/org/apache/seata/sqlparser/druid/oscar/OscarSelectForUpdateRecognizer.java b/sqlparser/seata-sqlparser-druid/src/main/java/org/apache/seata/sqlparser/druid/oscar/OscarSelectForUpdateRecognizer.java index beb6229297b..2e2a35f0b25 100644 --- a/sqlparser/seata-sqlparser-druid/src/main/java/org/apache/seata/sqlparser/druid/oscar/OscarSelectForUpdateRecognizer.java +++ b/sqlparser/seata-sqlparser-druid/src/main/java/org/apache/seata/sqlparser/druid/oscar/OscarSelectForUpdateRecognizer.java @@ -43,7 +43,7 @@ public class OscarSelectForUpdateRecognizer extends BaseOscarRecognizer implemen private final SQLSelectStatement ast; /** - * Instantiates a new My sql select for update recognizer. + * Instantiates a new Oscar sql select for update recognizer. * * @param originalSQL the original sql * @param ast the ast From 435b5d940285bd7fdb131a6667c3808d8e472c42 Mon Sep 17 00:00:00 2001 From: hanshaohua Date: Wed, 9 Oct 2024 09:37:47 +0800 Subject: [PATCH 13/19] Update sqlparser/seata-sqlparser-druid/src/main/java/org/apache/seata/sqlparser/druid/oscar/OscarSelectForUpdateRecognizer.java Co-authored-by: funkye <364176773@qq.com> --- .../sqlparser/druid/oscar/OscarSelectForUpdateRecognizer.java | 1 - 1 file changed, 1 deletion(-) diff --git a/sqlparser/seata-sqlparser-druid/src/main/java/org/apache/seata/sqlparser/druid/oscar/OscarSelectForUpdateRecognizer.java b/sqlparser/seata-sqlparser-druid/src/main/java/org/apache/seata/sqlparser/druid/oscar/OscarSelectForUpdateRecognizer.java index 2e2a35f0b25..6e30f25f9b4 100644 --- a/sqlparser/seata-sqlparser-druid/src/main/java/org/apache/seata/sqlparser/druid/oscar/OscarSelectForUpdateRecognizer.java +++ b/sqlparser/seata-sqlparser-druid/src/main/java/org/apache/seata/sqlparser/druid/oscar/OscarSelectForUpdateRecognizer.java @@ -36,7 +36,6 @@ /** * The type oscar select for update recognizer. * - * @author ccg */ public class OscarSelectForUpdateRecognizer extends BaseOscarRecognizer implements SQLSelectRecognizer { From 47f4a3881d30e7f053ec4ab3561b322368a8f64f Mon Sep 17 00:00:00 2001 From: hanshaohua Date: Wed, 9 Oct 2024 09:39:31 +0800 Subject: [PATCH 14/19] Update rm-datasource/src/main/java/org/apache/seata/rm/datasource/undo/oscar/OscarUndoExecutorHolder.java Co-authored-by: funkye <364176773@qq.com> --- .../seata/rm/datasource/undo/oscar/OscarUndoExecutorHolder.java | 1 - 1 file changed, 1 deletion(-) diff --git a/rm-datasource/src/main/java/org/apache/seata/rm/datasource/undo/oscar/OscarUndoExecutorHolder.java b/rm-datasource/src/main/java/org/apache/seata/rm/datasource/undo/oscar/OscarUndoExecutorHolder.java index c6b70ccfd28..aa6c560136e 100644 --- a/rm-datasource/src/main/java/org/apache/seata/rm/datasource/undo/oscar/OscarUndoExecutorHolder.java +++ b/rm-datasource/src/main/java/org/apache/seata/rm/datasource/undo/oscar/OscarUndoExecutorHolder.java @@ -25,7 +25,6 @@ /** * The Type OscarUndoExecutorHolder * - * @author Zhibei Hao */ @LoadLevel(name = JdbcConstants.OSCAR) public class OscarUndoExecutorHolder implements UndoExecutorHolder { From 65b6414ac58670dc0b97525ee4272dfe25fab118 Mon Sep 17 00:00:00 2001 From: hanshaohua Date: Wed, 9 Oct 2024 09:39:41 +0800 Subject: [PATCH 15/19] Update sqlparser/seata-sqlparser-druid/src/main/java/org/apache/seata/sqlparser/druid/oscar/OscarDeleteRecognizer.java Co-authored-by: funkye <364176773@qq.com> --- .../seata/sqlparser/druid/oscar/OscarDeleteRecognizer.java | 1 - 1 file changed, 1 deletion(-) diff --git a/sqlparser/seata-sqlparser-druid/src/main/java/org/apache/seata/sqlparser/druid/oscar/OscarDeleteRecognizer.java b/sqlparser/seata-sqlparser-druid/src/main/java/org/apache/seata/sqlparser/druid/oscar/OscarDeleteRecognizer.java index f8f691bb9d5..13f6d9f3d76 100644 --- a/sqlparser/seata-sqlparser-druid/src/main/java/org/apache/seata/sqlparser/druid/oscar/OscarDeleteRecognizer.java +++ b/sqlparser/seata-sqlparser-druid/src/main/java/org/apache/seata/sqlparser/druid/oscar/OscarDeleteRecognizer.java @@ -34,7 +34,6 @@ /** * The type oscar delete recognizer. * - * @author ccg */ public class OscarDeleteRecognizer extends BaseOscarRecognizer implements SQLDeleteRecognizer { From 612fc8fb51b1ef8d6b851f3870222f68e90b6843 Mon Sep 17 00:00:00 2001 From: hanshaohua Date: Wed, 9 Oct 2024 09:39:50 +0800 Subject: [PATCH 16/19] Update sqlparser/seata-sqlparser-druid/src/main/java/org/apache/seata/sqlparser/druid/oscar/OscarUpdateRecognizer.java Co-authored-by: funkye <364176773@qq.com> --- .../seata/sqlparser/druid/oscar/OscarUpdateRecognizer.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sqlparser/seata-sqlparser-druid/src/main/java/org/apache/seata/sqlparser/druid/oscar/OscarUpdateRecognizer.java b/sqlparser/seata-sqlparser-druid/src/main/java/org/apache/seata/sqlparser/druid/oscar/OscarUpdateRecognizer.java index c1cca98ff7b..2f22469238f 100644 --- a/sqlparser/seata-sqlparser-druid/src/main/java/org/apache/seata/sqlparser/druid/oscar/OscarUpdateRecognizer.java +++ b/sqlparser/seata-sqlparser-druid/src/main/java/org/apache/seata/sqlparser/druid/oscar/OscarUpdateRecognizer.java @@ -46,7 +46,7 @@ public class OscarUpdateRecognizer extends BaseOscarRecognizer implements SQLUpd private SQLUpdateStatement ast; /** - * Instantiates a new My sql update recognizer. + * Instantiates a new Oscar sql update recognizer. * * @param originalSQL the original sql * @param ast the ast From 0fd24edc630f9784edcb3bdf64c5931a6fdcc84f Mon Sep 17 00:00:00 2001 From: hanshaohua Date: Wed, 9 Oct 2024 09:40:01 +0800 Subject: [PATCH 17/19] Update sqlparser/seata-sqlparser-druid/src/main/java/org/apache/seata/sqlparser/druid/oscar/OscarInsertRecognizer.java Co-authored-by: funkye <364176773@qq.com> --- .../seata/sqlparser/druid/oscar/OscarInsertRecognizer.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sqlparser/seata-sqlparser-druid/src/main/java/org/apache/seata/sqlparser/druid/oscar/OscarInsertRecognizer.java b/sqlparser/seata-sqlparser-druid/src/main/java/org/apache/seata/sqlparser/druid/oscar/OscarInsertRecognizer.java index fe484f9b758..9e731d95529 100644 --- a/sqlparser/seata-sqlparser-druid/src/main/java/org/apache/seata/sqlparser/druid/oscar/OscarInsertRecognizer.java +++ b/sqlparser/seata-sqlparser-druid/src/main/java/org/apache/seata/sqlparser/druid/oscar/OscarInsertRecognizer.java @@ -49,7 +49,7 @@ public class OscarInsertRecognizer extends BaseOscarRecognizer implements SQLIns private final SQLInsertStatement ast; /** - * Instantiates a new My sql insert recognizer. + * Instantiates a new Oscar sql insert recognizer. * * @param originalSQL the original sql * @param ast the ast From f192a00d7318ddff1da11a18fbff5554ebbbbc3a Mon Sep 17 00:00:00 2001 From: hanshaohua Date: Wed, 9 Oct 2024 09:40:12 +0800 Subject: [PATCH 18/19] Update sqlparser/seata-sqlparser-druid/src/main/java/org/apache/seata/sqlparser/druid/oscar/OscarDeleteRecognizer.java Co-authored-by: funkye <364176773@qq.com> --- .../seata/sqlparser/druid/oscar/OscarDeleteRecognizer.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sqlparser/seata-sqlparser-druid/src/main/java/org/apache/seata/sqlparser/druid/oscar/OscarDeleteRecognizer.java b/sqlparser/seata-sqlparser-druid/src/main/java/org/apache/seata/sqlparser/druid/oscar/OscarDeleteRecognizer.java index 13f6d9f3d76..fd9213a5349 100644 --- a/sqlparser/seata-sqlparser-druid/src/main/java/org/apache/seata/sqlparser/druid/oscar/OscarDeleteRecognizer.java +++ b/sqlparser/seata-sqlparser-druid/src/main/java/org/apache/seata/sqlparser/druid/oscar/OscarDeleteRecognizer.java @@ -40,7 +40,7 @@ public class OscarDeleteRecognizer extends BaseOscarRecognizer implements SQLDel private final SQLDeleteStatement ast; /** - * Instantiates a new My sql delete recognizer. + * Instantiates a new Oscar sql delete recognizer. * * @param originalSQL the original sql * @param ast the ast From 21c61a73eb22e0c453a50b2b18d8c2951751f711 Mon Sep 17 00:00:00 2001 From: hanshaohua Date: Fri, 11 Oct 2024 14:52:14 +0800 Subject: [PATCH 19/19] =?UTF-8?q?pr=E6=A0=87=E8=AF=86=E5=92=8C=E4=BD=9C?= =?UTF-8?q?=E8=80=85=E4=BF=A1=E6=81=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- changes/en-us/2.x.md | 2 ++ changes/zh-cn/2.x.md | 7 +++++-- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/changes/en-us/2.x.md b/changes/en-us/2.x.md index e93e075b700..a4a567fa78d 100644 --- a/changes/en-us/2.x.md +++ b/changes/en-us/2.x.md @@ -6,6 +6,7 @@ Add changes here for all PR submitted to the 2.x branch. - [[#6876](https://github.com/apache/incubator-seata/pull/6876)]support kingbase - [[#6881](https://github.com/apache/incubator-seata/pull/6881)]support grpc +- [[#6864](https://github.com/apache/incubator-seata/pull/6864)]support shentong database ### bugfix: - [[#6899](https://github.com/apache/incubator-seata/pull/6899)] fix file.conf read failed after package @@ -44,6 +45,7 @@ Thanks to these contributors for their code commits. Please report an unintended - [arrrnold17](https://github.com/arrrnold17) - [xjlgod](https://github.com/xjlgod) - [PleaseGiveMeTheCoke](https://github.com/PleaseGiveMeTheCoke) +- [dsomehan](https://github.com/dsomehan) diff --git a/changes/zh-cn/2.x.md b/changes/zh-cn/2.x.md index 771a64ad0d7..efb5f32ae50 100644 --- a/changes/zh-cn/2.x.md +++ b/changes/zh-cn/2.x.md @@ -3,8 +3,10 @@ ### feature: -[[#6876](https://github.com/apache/incubator-seata/pull/6876)]支持人大金仓数据库(kingbase) -[[#6881](https://github.com/apache/incubator-seata/pull/6881)]全链路支持grpc +- [[#6876](https://github.com/apache/incubator-seata/pull/6876)]支持人大金仓数据库(kingbase) +- [[#6881](https://github.com/apache/incubator-seata/pull/6881)]全链路支持grpc +- [[#6864](https://github.com/apache/incubator-seata/pull/6864)]支持神通数据库(oscar) + ### bugfix: - [[#6899](https://github.com/apache/incubator-seata/pull/6899)] 修复file.conf打包后的读取 @@ -46,6 +48,7 @@ - [arrrnold17](https://github.com/arrrnold17) - [xjlgod](https://github.com/xjlgod) - [PleaseGiveMeTheCoke](https://github.com/PleaseGiveMeTheCoke) +- [dsomehan](https://github.com/dsomehan) 同时,我们收到了社区反馈的很多有价值的issue和建议,非常感谢大家。