Skip to content

Commit

Permalink
optimize: insert check pkvalue support. (apache#2607)
Browse files Browse the repository at this point in the history
  • Loading branch information
jsbxyyx committed Jun 5, 2020
1 parent 7a6583a commit e13c5c9
Show file tree
Hide file tree
Showing 2 changed files with 198 additions and 48 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -132,6 +133,7 @@ protected List<Object> parsePkValuesFromStatement() {
if (pkIndex == -1) {
throw new ShouldNeverHappenException(String.format("pkIndex is %d", pkIndex));
}
boolean ps = true;
List<Object> pkValues = null;
if (statementProxy instanceof PreparedStatementProxy) {
PreparedStatementProxy preparedStatementProxy = (PreparedStatementProxy) statementProxy;
Expand Down Expand Up @@ -173,6 +175,7 @@ protected List<Object> parsePkValuesFromStatement() {
}
}
} else {
ps = false;
List<List<Object>> insertRows = recognizer.getInsertRows();
pkValues = new ArrayList<>(insertRows.size());
for (List<Object> row : insertRows) {
Expand All @@ -182,7 +185,7 @@ protected List<Object> 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()));
}
Expand Down Expand Up @@ -244,25 +247,32 @@ protected List<Object> 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<Object> pkValues) {
protected boolean checkPkValues(List<Object> 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++;
Expand All @@ -276,19 +286,45 @@ protected boolean checkPkValues(List<Object> 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;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -50,7 +51,7 @@
import static org.mockito.Mockito.when;

/**
* @author guoyao
* @author guoyao, jsbxyyx
*/
public class MySQLInsertExecutorTest {

Expand Down Expand Up @@ -308,87 +309,200 @@ public void test_getPkIndex() {

@Test
public void test_checkPkValues() {
// one parameters.
// pk is null support

// ps = true
List<Object> 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<String> mockInsertColumns() {
Expand Down

0 comments on commit e13c5c9

Please sign in to comment.