From e13c5c9ca0d9e73b6b848fcbe7db1f56e2fcdd06 Mon Sep 17 00:00:00 2001 From: jsbxyyx Date: Fri, 5 Jun 2020 11:14:00 +0800 Subject: [PATCH] optimize: insert check pkvalue support. (#2607) --- .../datasource/exec/BaseInsertExecutor.java | 64 ++++-- .../exec/MySQLInsertExecutorTest.java | 182 ++++++++++++++---- 2 files changed, 198 insertions(+), 48 deletions(-) diff --git a/rm-datasource/src/main/java/io/seata/rm/datasource/exec/BaseInsertExecutor.java b/rm-datasource/src/main/java/io/seata/rm/datasource/exec/BaseInsertExecutor.java index 1978f8f1a78..d2a080af55d 100644 --- a/rm-datasource/src/main/java/io/seata/rm/datasource/exec/BaseInsertExecutor.java +++ b/rm-datasource/src/main/java/io/seata/rm/datasource/exec/BaseInsertExecutor.java @@ -33,6 +33,7 @@ import io.seata.sqlparser.SQLRecognizer; import io.seata.sqlparser.struct.Null; import io.seata.sqlparser.struct.Sequenceable; +import io.seata.sqlparser.struct.SqlDefaultExpr; import io.seata.sqlparser.struct.SqlMethodExpr; import io.seata.sqlparser.struct.SqlSequenceExpr; import org.slf4j.Logger; @@ -132,6 +133,7 @@ protected List parsePkValuesFromStatement() { if (pkIndex == -1) { throw new ShouldNeverHappenException(String.format("pkIndex is %d", pkIndex)); } + boolean ps = true; List pkValues = null; if (statementProxy instanceof PreparedStatementProxy) { PreparedStatementProxy preparedStatementProxy = (PreparedStatementProxy) statementProxy; @@ -173,6 +175,7 @@ protected List parsePkValuesFromStatement() { } } } else { + ps = false; List> insertRows = recognizer.getInsertRows(); pkValues = new ArrayList<>(insertRows.size()); for (List row : insertRows) { @@ -182,7 +185,7 @@ protected List parsePkValuesFromStatement() { if (pkValues == null) { throw new ShouldNeverHappenException(); } - boolean b = this.checkPkValues(pkValues); + boolean b = this.checkPkValues(pkValues, ps); if (!b) { throw new NotSupportYetException(String.format("not support sql [%s]", sqlRecognizer.getOriginalSQL())); } @@ -244,25 +247,32 @@ protected List getPkValuesBySequence(SqlSequenceExpr expr) throws SQLExc /** * check pk values * @param pkValues + * @param ps true: is prepared statement. false: normal statement. * @return true: support. false: not support. */ - protected boolean checkPkValues(List pkValues) { + protected boolean checkPkValues(List pkValues, boolean ps) { + /* + ps = true ----------------------------------------------- one more null O O value O O + method O O + sequence O O + default O O + ----------------------------------------------- + ps = false + ----------------------------------------------- + one more + null O X + value O O method X X sequence O X - ----------------------------------------------- - null value method sequence - null O X X X - value X O X X - method X X X X - sequence X X X X + default O X ----------------------------------------------- */ - int n = 0, v = 0, m = 0, s = 0; + int n = 0, v = 0, m = 0, s = 0, d = 0; for (Object pkValue : pkValues) { if (pkValue instanceof Null) { n++; @@ -276,19 +286,45 @@ protected boolean checkPkValues(List pkValues) { s++; continue; } + if (pkValue instanceof SqlDefaultExpr) { + d++; + continue; + } v++; } - // not support sql primary key is function. - if (m > 0) { + + if (!ps) { + if (m > 0) { + return false; + } + if (n == 1 && v == 0 && m == 0 && s == 0 && d == 0) { + return true; + } + if (n == 0 && v > 0 && m == 0 && s == 0 && d == 0) { + return true; + } + if (n == 0 && v == 0 && m == 0 && s == 1 && d == 0) { + return true; + } + if (n == 0 && v == 0 && m == 0 && s == 0 && d == 1) { + return true; + } return false; } - if (n > 0 && v == 0 && s == 0) { + + if (n > 0 && v == 0 && m == 0 && s == 0 && d == 0) { + return true; + } + if (n == 0 && v > 0 && m == 0 && s == 0 && d == 0) { + return true; + } + if (n == 0 && v == 0 && m > 0 && s == 0 && d == 0) { return true; } - if (n == 0 && v > 0 && s == 0) { + if (n == 0 && v == 0 && m == 0 && s > 0 && d == 0) { return true; } - if (n == 0 && v == 0 && s == 1) { + if (n == 0 && v == 0 && m == 0 && s == 0 && d > 0) { return true; } return false; diff --git a/rm-datasource/src/test/java/io/seata/rm/datasource/exec/MySQLInsertExecutorTest.java b/rm-datasource/src/test/java/io/seata/rm/datasource/exec/MySQLInsertExecutorTest.java index 81727ab2e4c..01be4cfa363 100644 --- a/rm-datasource/src/test/java/io/seata/rm/datasource/exec/MySQLInsertExecutorTest.java +++ b/rm-datasource/src/test/java/io/seata/rm/datasource/exec/MySQLInsertExecutorTest.java @@ -35,6 +35,7 @@ import io.seata.rm.datasource.sql.struct.TableRecords; import io.seata.sqlparser.SQLInsertRecognizer; import io.seata.sqlparser.struct.Null; +import io.seata.sqlparser.struct.SqlDefaultExpr; import io.seata.sqlparser.struct.SqlMethodExpr; import io.seata.sqlparser.struct.SqlSequenceExpr; import io.seata.sqlparser.util.JdbcConstants; @@ -50,7 +51,7 @@ import static org.mockito.Mockito.when; /** - * @author guoyao + * @author guoyao, jsbxyyx */ public class MySQLInsertExecutorTest { @@ -308,87 +309,200 @@ public void test_getPkIndex() { @Test public void test_checkPkValues() { - // one parameters. - // pk is null support + + // ps = true List pkValues = new ArrayList<>(); pkValues.add(Null.get()); - Assertions.assertTrue(insertExecutor.checkPkValues(pkValues)); + Assertions.assertTrue(insertExecutor.checkPkValues(pkValues, true)); - // pk is sequence support. pkValues = new ArrayList<>(); - pkValues.add(new SqlSequenceExpr()); - Assertions.assertTrue(insertExecutor.checkPkValues(pkValues)); + pkValues.add(Null.get()); + pkValues.add(Null.get()); + Assertions.assertTrue(insertExecutor.checkPkValues(pkValues, true)); + + pkValues = new ArrayList<>(); + pkValues.add(1); + Assertions.assertTrue(insertExecutor.checkPkValues(pkValues, true)); - // pk is specify value support. pkValues = new ArrayList<>(); pkValues.add(1); - Assertions.assertTrue(insertExecutor.checkPkValues(pkValues)); + pkValues.add(2); + Assertions.assertTrue(insertExecutor.checkPkValues(pkValues, true)); - // pk is sql function not support. pkValues = new ArrayList<>(); pkValues.add(new SqlMethodExpr()); - Assertions.assertFalse(insertExecutor.checkPkValues(pkValues)); + Assertions.assertTrue(insertExecutor.checkPkValues(pkValues, true)); - // more parameters. - // pk is specify value support. pkValues = new ArrayList<>(); - pkValues.add(1); - pkValues.add(2); - Assertions.assertTrue(insertExecutor.checkPkValues(pkValues)); + pkValues.add(new SqlMethodExpr()); + pkValues.add(new SqlMethodExpr()); + Assertions.assertTrue(insertExecutor.checkPkValues(pkValues, true)); + + pkValues = new ArrayList<>(); + pkValues.add(new SqlSequenceExpr()); + Assertions.assertTrue(insertExecutor.checkPkValues(pkValues, true)); + + pkValues = new ArrayList<>(); + pkValues.add(new SqlSequenceExpr()); + pkValues.add(new SqlSequenceExpr()); + Assertions.assertTrue(insertExecutor.checkPkValues(pkValues, true)); + + pkValues = new ArrayList<>(); + pkValues.add(SqlDefaultExpr.get()); + Assertions.assertTrue(insertExecutor.checkPkValues(pkValues, true)); + + pkValues = new ArrayList<>(); + pkValues.add(SqlDefaultExpr.get()); + pkValues.add(SqlDefaultExpr.get()); + Assertions.assertTrue(insertExecutor.checkPkValues(pkValues, true)); + + // ps = false + pkValues = new ArrayList<>(); + pkValues.add(Null.get()); + Assertions.assertTrue(insertExecutor.checkPkValues(pkValues, false)); - // pk is null support. pkValues = new ArrayList<>(); pkValues.add(Null.get()); pkValues.add(Null.get()); - Assertions.assertTrue(insertExecutor.checkPkValues(pkValues)); + Assertions.assertFalse(insertExecutor.checkPkValues(pkValues, false)); + + pkValues = new ArrayList<>(); + pkValues.add(1); + Assertions.assertTrue(insertExecutor.checkPkValues(pkValues, false)); + + pkValues = new ArrayList<>(); + pkValues.add(1); + pkValues.add(2); + Assertions.assertTrue(insertExecutor.checkPkValues(pkValues, false)); - // pk is sql function not support. pkValues = new ArrayList<>(); pkValues.add(new SqlMethodExpr()); + Assertions.assertFalse(insertExecutor.checkPkValues(pkValues, false)); + + pkValues = new ArrayList<>(); pkValues.add(new SqlMethodExpr()); - Assertions.assertFalse(insertExecutor.checkPkValues(pkValues)); + pkValues.add(new SqlMethodExpr()); + Assertions.assertFalse(insertExecutor.checkPkValues(pkValues, false)); + + pkValues = new ArrayList<>(); + pkValues.add(new SqlSequenceExpr()); + Assertions.assertTrue(insertExecutor.checkPkValues(pkValues, false)); - // pk is sql sequence not support. pkValues = new ArrayList<>(); pkValues.add(new SqlSequenceExpr()); pkValues.add(new SqlSequenceExpr()); - Assertions.assertFalse(insertExecutor.checkPkValues(pkValues)); + Assertions.assertFalse(insertExecutor.checkPkValues(pkValues, false)); + + pkValues = new ArrayList<>(); + pkValues.add(SqlDefaultExpr.get()); + Assertions.assertTrue(insertExecutor.checkPkValues(pkValues, false)); + + pkValues = new ArrayList<>(); + pkValues.add(SqlDefaultExpr.get()); + pkValues.add(SqlDefaultExpr.get()); + Assertions.assertFalse(insertExecutor.checkPkValues(pkValues, false)); + + // not support. + pkValues = new ArrayList<>(); + pkValues.add(1); + pkValues.add(Null.get()); + Assertions.assertFalse(insertExecutor.checkPkValues(pkValues, true)); - // pk is specify value and null not support. pkValues = new ArrayList<>(); pkValues.add(1); pkValues.add(Null.get()); - Assertions.assertFalse(insertExecutor.checkPkValues(pkValues)); + Assertions.assertFalse(insertExecutor.checkPkValues(pkValues, false)); + + pkValues = new ArrayList<>(); + pkValues.add(1); + pkValues.add(new SqlMethodExpr()); + Assertions.assertFalse(insertExecutor.checkPkValues(pkValues, true)); - // pk is specify value and sql function not support. pkValues = new ArrayList<>(); pkValues.add(1); pkValues.add(new SqlMethodExpr()); - Assertions.assertFalse(insertExecutor.checkPkValues(pkValues)); + Assertions.assertFalse(insertExecutor.checkPkValues(pkValues, false)); + + pkValues = new ArrayList<>(); + pkValues.add(1); + pkValues.add(new SqlSequenceExpr()); + Assertions.assertFalse(insertExecutor.checkPkValues(pkValues, true)); - // pk is specify value and sequence not support. pkValues = new ArrayList<>(); pkValues.add(1); pkValues.add(new SqlSequenceExpr()); - Assertions.assertFalse(insertExecutor.checkPkValues(pkValues)); + Assertions.assertFalse(insertExecutor.checkPkValues(pkValues, false)); + + pkValues = new ArrayList<>(); + pkValues.add(1); + pkValues.add(SqlDefaultExpr.get()); + Assertions.assertFalse(insertExecutor.checkPkValues(pkValues, true)); + + pkValues = new ArrayList<>(); + pkValues.add(1); + pkValues.add(SqlDefaultExpr.get()); + Assertions.assertFalse(insertExecutor.checkPkValues(pkValues, false)); - // pk is null and sql function not support. pkValues = new ArrayList<>(); pkValues.add(Null.get()); pkValues.add(new SqlMethodExpr()); - Assertions.assertFalse(insertExecutor.checkPkValues(pkValues)); + Assertions.assertFalse(insertExecutor.checkPkValues(pkValues, true)); + + pkValues = new ArrayList<>(); + pkValues.add(Null.get()); + pkValues.add(new SqlMethodExpr()); + Assertions.assertFalse(insertExecutor.checkPkValues(pkValues, false)); + + + pkValues = new ArrayList<>(); + pkValues.add(Null.get()); + pkValues.add(new SqlSequenceExpr()); + Assertions.assertFalse(insertExecutor.checkPkValues(pkValues, true)); + + pkValues = new ArrayList<>(); + pkValues.add(Null.get()); + pkValues.add(new SqlSequenceExpr()); + Assertions.assertFalse(insertExecutor.checkPkValues(pkValues, false)); + + pkValues = new ArrayList<>(); + pkValues.add(Null.get()); + pkValues.add(SqlDefaultExpr.get()); + Assertions.assertFalse(insertExecutor.checkPkValues(pkValues, true)); - // pk is null and sequence not support. pkValues = new ArrayList<>(); pkValues.add(Null.get()); + pkValues.add(SqlDefaultExpr.get()); + Assertions.assertFalse(insertExecutor.checkPkValues(pkValues, false)); + + pkValues = new ArrayList<>(); + pkValues.add(new SqlMethodExpr()); pkValues.add(new SqlSequenceExpr()); - Assertions.assertFalse(insertExecutor.checkPkValues(pkValues)); + Assertions.assertFalse(insertExecutor.checkPkValues(pkValues, true)); - // pk is sql function and sequence not support. pkValues = new ArrayList<>(); pkValues.add(new SqlMethodExpr()); pkValues.add(new SqlSequenceExpr()); - Assertions.assertFalse(insertExecutor.checkPkValues(pkValues)); + Assertions.assertFalse(insertExecutor.checkPkValues(pkValues, false)); + + pkValues = new ArrayList<>(); + pkValues.add(new SqlMethodExpr()); + pkValues.add(SqlDefaultExpr.get()); + Assertions.assertFalse(insertExecutor.checkPkValues(pkValues, true)); + + pkValues = new ArrayList<>(); + pkValues.add(new SqlMethodExpr()); + pkValues.add(SqlDefaultExpr.get()); + Assertions.assertFalse(insertExecutor.checkPkValues(pkValues, false)); + + pkValues = new ArrayList<>(); + pkValues.add(new SqlSequenceExpr()); + pkValues.add(SqlDefaultExpr.get()); + Assertions.assertFalse(insertExecutor.checkPkValues(pkValues, true)); + + pkValues = new ArrayList<>(); + pkValues.add(new SqlSequenceExpr()); + pkValues.add(SqlDefaultExpr.get()); + Assertions.assertFalse(insertExecutor.checkPkValues(pkValues, false)); } private List mockInsertColumns() {