Merge pull request #2201 from JohnCailj/dev

improved update statement parser for mysql
This commit is contained in:
温绍
2017-12-18 17:56:44 +08:00
committed by GitHub
8 changed files with 89 additions and 7 deletions
@@ -36,13 +36,15 @@ public class SQLUpdateStatement extends SQLStatementImpl implements SQLReplaceab
protected SQLTableSource tableSource;
protected List<SQLExpr> returning;
protected List<SQLHint> hints;
// for mysql
protected SQLOrderBy orderBy;
public SQLUpdateStatement(){
}
public SQLUpdateStatement(String dbType){
super (dbType);
}
@@ -90,7 +92,7 @@ public class SQLUpdateStatement extends SQLStatementImpl implements SQLReplaceab
public List<SQLUpdateSetItem> getItems() {
return items;
}
public void addItem(SQLUpdateSetItem item) {
this.items.add(item);
item.setParent(this);
@@ -115,6 +117,25 @@ public class SQLUpdateStatement extends SQLStatementImpl implements SQLReplaceab
this.from = from;
}
public int getHintsSize() {
if (hints == null) {
return 0;
}
return hints.size();
}
public List<SQLHint> getHints() {
if (hints == null) {
hints = new ArrayList<SQLHint>(2);
}
return hints;
}
public void setHints(List<SQLHint> hints) {
this.hints = hints;
}
@Override
public void output(StringBuffer buf) {
SQLASTOutputVisitor visitor = SQLUtils.createOutputVisitor(buf, dbType);
@@ -129,6 +150,7 @@ public class SQLUpdateStatement extends SQLStatementImpl implements SQLReplaceab
acceptChild(visitor, items);
acceptChild(visitor, where);
acceptChild(visitor, orderBy);
acceptChild(visitor, hints);
}
visitor.endVisit(this);
}
@@ -260,4 +282,34 @@ public class SQLUpdateStatement extends SQLStatementImpl implements SQLReplaceab
return false;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
SQLUpdateStatement that = (SQLUpdateStatement) o;
if (with != null ? !with.equals(that.with) : that.with != null) return false;
if (items != null ? !items.equals(that.items) : that.items != null) return false;
if (where != null ? !where.equals(that.where) : that.where != null) return false;
if (from != null ? !from.equals(that.from) : that.from != null) return false;
if (hints != null ? !hints.equals(that.hints) : that.hints != null) return false;
if (tableSource != null ? !tableSource.equals(that.tableSource) : that.tableSource != null) return false;
if (returning != null ? !returning.equals(that.returning) : that.returning != null) return false;
return orderBy != null ? orderBy.equals(that.orderBy) : that.orderBy == null;
}
@Override
public int hashCode() {
int result = with != null ? with.hashCode() : 0;
result = 31 * result + (items != null ? items.hashCode() : 0);
result = 31 * result + (where != null ? where.hashCode() : 0);
result = 31 * result + (from != null ? from.hashCode() : 0);
result = 31 * result + (tableSource != null ? tableSource.hashCode() : 0);
result = 31 * result + (returning != null ? returning.hashCode() : 0);
result = 31 * result + (orderBy != null ? orderBy.hashCode() : 0);
result = 31 * result + (hints != null ? hints.hashCode() : 0);
return result;
}
}
@@ -323,6 +323,10 @@ public class MySqlSelectParser extends SQLSelectParser {
}
}
while (lexer.token() == Token.HINT) {
this.exprParser.parseHints(update.getHints());
}
SQLSelectParser selectParser = this.exprParser.createSelectParser();
SQLTableSource updateTableSource = selectParser.parseTableSource();
update.setTableSource(updateTableSource);
@@ -1594,6 +1594,12 @@ public class MySqlOutputVisitor extends SQLASTOutputVisitor implements MySqlASTV
print0(ucase ? "IGNORE " : "ignore ");
}
if (x.getHints() != null && x.getHints().size() > 0) {
printAndAccept(x.getHints(), " ");
print0(" ");
}
if (x.isCommitOnSuccess()) {
print0(ucase ? "COMMIT_ON_SUCCESS " : "commit_on_success ");
}
@@ -2818,7 +2818,13 @@ public class SQLExprParser extends SQLParser {
@SuppressWarnings({ "unchecked", "rawtypes" })
public void parseHints(List hints) {
if (lexer.token == Token.HINT) {
hints.add(new SQLCommentHint(lexer.stringVal()));
SQLCommentHint hint = new SQLCommentHint(lexer.stringVal());
if (lexer.commentCount > 0) {
hint.addBeforeComment(lexer.comments);
}
hints.add(hint);
lexer.nextToken();
}
}
@@ -3257,6 +3257,11 @@ public class SQLASTOutputVisitor extends SQLASTVisitorAdapter implements Paramet
}
public boolean visit(SQLCommentHint x) {
if (x.hasBeforeComment()) {
printlnComment(x.getBeforeCommentsDirect());
print0(" ");
}
print0("/*");
print0(x.getText());
print0("*/");
@@ -48,4 +48,13 @@ public class MySqlHintStatementTest extends TestCase {
+ "\n"
+ "\n/*!40101 SET character_set_client = @saved_cs_client */;", rs);
}
public void test_1() throws Exception {
String sql = "update "
+ "/*MS-MRCHISHUB-MH-MESSAGE-UPDATE*/ "
+ "/*+ INDEX(mh_message primary) */ "
+ "mh_message set gmt_modified = now(),status= '099' where id = 1244918;";
String rs = SQLUtils.formatMySql(sql);
assertEquals("UPDATE /*MS-MRCHISHUB-MH-MESSAGE-UPDATE*/ /*+ INDEX(mh_message primary) */ mh_message\n"
+ "SET gmt_modified = now(), status = '099'\n" + "WHERE id = 1244918;", rs);
}
}
@@ -52,7 +52,7 @@ public class MySqlSelectTest_49_for_update_no_wait extends MysqlTest {
{
String output = SQLUtils.toMySqlString(stmt);
assertEquals("SELECT /*+INDEX(AR_II_M_004 PRIMARY) */ tnt_inst_id, ar_no, ar_nm, ar_tp_code, ar_entity_type\n" +
assertEquals("SELECT /*MS-ARCORE-AR-II-M-QUERY-IN-LOCK-BY-AR-NOS*/ /*+INDEX(AR_II_M_004 PRIMARY) */ tnt_inst_id, ar_no, ar_nm, ar_tp_code, ar_entity_type\n" +
"FROM tb_001\n" +
"WHERE tnt_inst_id = ?\n" +
"\tAND ar_no IN (?)\n" +
@@ -61,7 +61,7 @@ public class MySqlSelectTest_49_for_update_no_wait extends MysqlTest {
}
{
String output = SQLUtils.toMySqlString(stmt, SQLUtils.DEFAULT_LCASE_FORMAT_OPTION);
assertEquals("select /*+INDEX(AR_II_M_004 PRIMARY) */ tnt_inst_id, ar_no, ar_nm, ar_tp_code, ar_entity_type\n" +
assertEquals("select /*MS-ARCORE-AR-II-M-QUERY-IN-LOCK-BY-AR-NOS*/ /*+INDEX(AR_II_M_004 PRIMARY) */ tnt_inst_id, ar_no, ar_nm, ar_tp_code, ar_entity_type\n" +
"from tb_001\n" +
"where tnt_inst_id = ?\n" +
"\tand ar_no in (?)\n" +
@@ -71,7 +71,7 @@ public class MySqlSelectTest_49_for_update_no_wait extends MysqlTest {
{
String output = SQLUtils.toMySqlString(stmt, new SQLUtils.FormatOption(true, true, true));
assertEquals("SELECT /*+INDEX(AR_II_M_004 PRIMARY) */ tnt_inst_id, ar_no, ar_nm, ar_tp_code, ar_entity_type\n" +
assertEquals("SELECT /*MS-ARCORE-AR-II-M-QUERY-IN-LOCK-BY-AR-NOS*/ /*+INDEX(AR_II_M_004 PRIMARY) */ tnt_inst_id, ar_no, ar_nm, ar_tp_code, ar_entity_type\n" +
"FROM tb\n" +
"WHERE tnt_inst_id = ?\n" +
"\tAND ar_no IN (?)\n" +
@@ -66,7 +66,7 @@ public class OracleSelectTest104 extends OracleTest {
{
String text = SQLUtils.toOracleString(stmt);
assertEquals("SELECT /*+ cursor_sharing_exact dynamic_sampling(0) no_sql_tune no_monitoring optimizer_features_enable(default) */ SUM(C1)\n" +
assertEquals("SELECT /* DS_SVC */ /*+ cursor_sharing_exact dynamic_sampling(0) no_sql_tune no_monitoring optimizer_features_enable(default) */ SUM(C1)\n" +
"FROM (\n" +
"\tSELECT /*+ qb_name(\"innerQuery\") */ 1 AS C1\n" +
"\tFROM SYS.\"X$KZSPR\" \"X$KZSPR\"\n" +