Skip to content

Commit

Permalink
fix parsing mysql 8 create table sql with check not enforce that can'…
Browse files Browse the repository at this point in the history
…t recognize the "NOT" token alibaba#4089
  • Loading branch information
WillsonYip committed Dec 25, 2020
1 parent 44ce8ea commit cb16757
Show file tree
Hide file tree
Showing 2 changed files with 117 additions and 17 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -1546,13 +1546,19 @@ protected SQLTableConstraint parseConstraint() {
lexer.nextToken();
SQLCheck check = new SQLCheck();
check.setName(name);
SQLExpr expr = this.exprParser.expr();
SQLExpr expr = this.exprParser.primary();
check.setExpr(expr);
constraint = check;

boolean enforce = true;
//should find Token.NOT to recognize "NOT ENFORCED"
//but somehow Token.NOT eaten by "this.exprParser.expr()" in above code
if (Token.NOT.equals(lexer.token())) {
enforce = false;
lexer.nextToken();
}
if (lexer.stringVal().equalsIgnoreCase("ENFORCED")) {
check.setEnforced(enforce);
lexer.nextToken();
}
if (lexer.token() == Token.HINT) {
String hintText = lexer.stringVal();
if (hintText != null) {
Expand All @@ -1567,9 +1573,6 @@ protected SQLTableConstraint parseConstraint() {
}
lexer.nextToken();
}
} else if (lexer.stringVal().equalsIgnoreCase("ENFORCED")) {
check.setEnforced(enforce);
lexer.nextToken();
}
}

Expand Down
119 changes: 108 additions & 11 deletions src/test/java/com/alibaba/druid/bvt/sql/mysql/MysqlCheckTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

import com.alibaba.druid.sql.MysqlTest;
import com.alibaba.druid.sql.ast.SQLStatement;
import com.alibaba.druid.sql.ast.expr.SQLBinaryOpExpr;
import com.alibaba.druid.sql.ast.expr.SQLBinaryOperator;
import com.alibaba.druid.sql.ast.statement.*;
import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlCreateTableStatement;
import com.alibaba.druid.sql.dialect.mysql.ast.statement.MysqlAlterTableAlterCheck;
Expand All @@ -21,7 +23,7 @@ public void test_create1() {
" CONSTRAINT `c21_nonzero` CHECK ((`c1` <> 0)),\n" +
" CONSTRAINT `t12_chk_1` CHECK ((`c1` <> `c2`)),\n" +
" CONSTRAINT `t12_chk_2` CHECK ((`c1` > 10)),\n" +
" CONSTRAINT `t12_chk_3` CHECK ((`c3` < 100)),\n" +
" CONSTRAINT `t12_chk_3` CHECK (((`c3` < 100) and (`c3` > 0))),\n" +
" CONSTRAINT `t12_chk_4` CHECK ((`c1` > `c3`))\n" +
") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci";

Expand All @@ -35,10 +37,57 @@ public void test_create1() {

MySqlCreateTableStatement statement = (MySqlCreateTableStatement) statementList.get(0);
Assert.assertEquals(9, statement.getTableElementList().size());
SQLTableElement element = statement.getTableElementList().get(3);
Assert.assertTrue(element instanceof SQLCheck);
SQLCheck sqlCheck = (SQLCheck) element;
Assert.assertEquals(false, sqlCheck.getEnforced());
{
SQLTableElement element = statement.getTableElementList().get(3);
Assert.assertTrue(element instanceof SQLCheck);
SQLCheck sqlCheck = (SQLCheck) element;
Assert.assertEquals(false, sqlCheck.getEnforced());
Assert.assertEquals("`c12_positive`", sqlCheck.getName().getSimpleName());
Assert.assertEquals("`c2` > 0", sqlCheck.getExpr().toString());
}
{
SQLTableElement element = statement.getTableElementList().get(4);
Assert.assertTrue(element instanceof SQLCheck);
SQLCheck sqlCheck = (SQLCheck) element;
Assert.assertNull(sqlCheck.getEnforced());
Assert.assertEquals("`c21_nonzero`", sqlCheck.getName().getSimpleName());
Assert.assertEquals("`c1` <> 0", sqlCheck.getExpr().toString());
}
{
SQLTableElement element = statement.getTableElementList().get(5);
Assert.assertTrue(element instanceof SQLCheck);
SQLCheck sqlCheck = (SQLCheck) element;
Assert.assertNull(sqlCheck.getEnforced());
Assert.assertEquals("`t12_chk_1`", sqlCheck.getName().getSimpleName());
Assert.assertEquals("`c1` <> `c2`", sqlCheck.getExpr().toString());
}
{
SQLTableElement element = statement.getTableElementList().get(6);
Assert.assertTrue(element instanceof SQLCheck);
SQLCheck sqlCheck = (SQLCheck) element;
Assert.assertNull(sqlCheck.getEnforced());
Assert.assertEquals("`t12_chk_2`", sqlCheck.getName().getSimpleName());
Assert.assertEquals("`c1` > 10", sqlCheck.getExpr().toString());
}
{
SQLTableElement element = statement.getTableElementList().get(7);
Assert.assertTrue(element instanceof SQLCheck);
SQLCheck sqlCheck = (SQLCheck) element;
Assert.assertNull(sqlCheck.getEnforced());
Assert.assertEquals("`t12_chk_3`", sqlCheck.getName().getSimpleName());
Assert.assertTrue(sqlCheck.getExpr() instanceof SQLBinaryOpExpr);
Assert.assertEquals(SQLBinaryOperator.BooleanAnd, ((SQLBinaryOpExpr) sqlCheck.getExpr()).getOperator());
Assert.assertEquals("`c3` < 100", ((SQLBinaryOpExpr) sqlCheck.getExpr()).getLeft().toString());
Assert.assertEquals("`c3` > 0", ((SQLBinaryOpExpr) sqlCheck.getExpr()).getRight().toString());
}
{
SQLTableElement element = statement.getTableElementList().get(8);
Assert.assertTrue(element instanceof SQLCheck);
SQLCheck sqlCheck = (SQLCheck) element;
Assert.assertNull(sqlCheck.getEnforced());
Assert.assertEquals("`t12_chk_4`", sqlCheck.getName().getSimpleName());
Assert.assertEquals("`c1` > `c3`", sqlCheck.getExpr().toString());
}
}

public void test_create2() {
Expand All @@ -50,7 +99,8 @@ public void test_create2() {
"\tCONSTRAINT `c21_nonzero` CHECK (`c1` <> 0),\n" +
"\tCONSTRAINT `t12_chk_1` CHECK (`c1` <> `c2`),\n" +
"\tCONSTRAINT `t12_chk_2` CHECK (`c1` > 10),\n" +
"\tCONSTRAINT `t12_chk_3` CHECK (`c3` < 100),\n" +
"\tCONSTRAINT `t12_chk_3` CHECK (`c3` < 100\n" +
"\t\tAND `c3` > 0),\n" +
"\tCONSTRAINT `t12_chk_4` CHECK (`c1` > `c3`)\n" +
") ENGINE = InnoDB CHARSET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci;\n";

Expand All @@ -64,10 +114,57 @@ public void test_create2() {

MySqlCreateTableStatement statement = (MySqlCreateTableStatement) statementList.get(0);
Assert.assertEquals(9, statement.getTableElementList().size());
SQLTableElement element = statement.getTableElementList().get(3);
Assert.assertTrue(element instanceof SQLCheck);
SQLCheck sqlCheck = (SQLCheck) element;
Assert.assertEquals(false, sqlCheck.getEnforced());
{
SQLTableElement element = statement.getTableElementList().get(3);
Assert.assertTrue(element instanceof SQLCheck);
SQLCheck sqlCheck = (SQLCheck) element;
Assert.assertEquals(false, sqlCheck.getEnforced());
Assert.assertEquals("`c12_positive`", sqlCheck.getName().getSimpleName());
Assert.assertEquals("`c2` > 0", sqlCheck.getExpr().toString());
}
{
SQLTableElement element = statement.getTableElementList().get(4);
Assert.assertTrue(element instanceof SQLCheck);
SQLCheck sqlCheck = (SQLCheck) element;
Assert.assertNull(sqlCheck.getEnforced());
Assert.assertEquals("`c21_nonzero`", sqlCheck.getName().getSimpleName());
Assert.assertEquals("`c1` <> 0", sqlCheck.getExpr().toString());
}
{
SQLTableElement element = statement.getTableElementList().get(5);
Assert.assertTrue(element instanceof SQLCheck);
SQLCheck sqlCheck = (SQLCheck) element;
Assert.assertNull(sqlCheck.getEnforced());
Assert.assertEquals("`t12_chk_1`", sqlCheck.getName().getSimpleName());
Assert.assertEquals("`c1` <> `c2`", sqlCheck.getExpr().toString());
}
{
SQLTableElement element = statement.getTableElementList().get(6);
Assert.assertTrue(element instanceof SQLCheck);
SQLCheck sqlCheck = (SQLCheck) element;
Assert.assertNull(sqlCheck.getEnforced());
Assert.assertEquals("`t12_chk_2`", sqlCheck.getName().getSimpleName());
Assert.assertEquals("`c1` > 10", sqlCheck.getExpr().toString());
}
{
SQLTableElement element = statement.getTableElementList().get(7);
Assert.assertTrue(element instanceof SQLCheck);
SQLCheck sqlCheck = (SQLCheck) element;
Assert.assertNull(sqlCheck.getEnforced());
Assert.assertEquals("`t12_chk_3`", sqlCheck.getName().getSimpleName());
Assert.assertTrue(sqlCheck.getExpr() instanceof SQLBinaryOpExpr);
Assert.assertEquals(SQLBinaryOperator.BooleanAnd, ((SQLBinaryOpExpr) sqlCheck.getExpr()).getOperator());
Assert.assertEquals("`c3` < 100", ((SQLBinaryOpExpr) sqlCheck.getExpr()).getLeft().toString());
Assert.assertEquals("`c3` > 0", ((SQLBinaryOpExpr) sqlCheck.getExpr()).getRight().toString());
}
{
SQLTableElement element = statement.getTableElementList().get(8);
Assert.assertTrue(element instanceof SQLCheck);
SQLCheck sqlCheck = (SQLCheck) element;
Assert.assertNull(sqlCheck.getEnforced());
Assert.assertEquals("`t12_chk_4`", sqlCheck.getName().getSimpleName());
Assert.assertEquals("`c1` > `c3`", sqlCheck.getExpr().toString());
}
}

public void test_alter_add1() {
Expand Down Expand Up @@ -120,7 +217,7 @@ public void test_alter_add2() {
Assert.assertEquals("a > 1", sqlCheck.getExpr().toString());
}

public void test_alter_drop() throws Exception {
public void test_alter_drop() {
String sql = "ALTER TABLE t1 DROP CONSTRAINT t1_check ;";

MySqlStatementParser parser = new MySqlStatementParser(sql);
Expand Down

0 comments on commit cb16757

Please sign in to comment.