diff --git a/src/main/java/com/alibaba/druid/sql/dialect/oracle/ast/clause/OracleErrorLoggingClause.java b/src/main/java/com/alibaba/druid/sql/ast/statement/SQLErrorLoggingClause.java similarity index 79% rename from src/main/java/com/alibaba/druid/sql/dialect/oracle/ast/clause/OracleErrorLoggingClause.java rename to src/main/java/com/alibaba/druid/sql/ast/statement/SQLErrorLoggingClause.java index 70a35df379..2af5fa804a 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/oracle/ast/clause/OracleErrorLoggingClause.java +++ b/src/main/java/com/alibaba/druid/sql/ast/statement/SQLErrorLoggingClause.java @@ -13,21 +13,21 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package com.alibaba.druid.sql.dialect.oracle.ast.clause; +package com.alibaba.druid.sql.ast.statement; import com.alibaba.druid.sql.ast.SQLExpr; import com.alibaba.druid.sql.ast.SQLName; -import com.alibaba.druid.sql.dialect.oracle.ast.OracleSQLObjectImpl; -import com.alibaba.druid.sql.dialect.oracle.visitor.OracleASTVisitor; +import com.alibaba.druid.sql.ast.SQLObjectImpl; +import com.alibaba.druid.sql.visitor.SQLASTVisitor; -public class OracleErrorLoggingClause extends OracleSQLObjectImpl { +public class SQLErrorLoggingClause extends SQLObjectImpl { private SQLName into; private SQLExpr simpleExpression; private SQLExpr limit; @Override - public void accept0(OracleASTVisitor visitor) { + public void accept0(SQLASTVisitor visitor) { if (visitor.visit(this)) { acceptChild(visitor, into); acceptChild(visitor, simpleExpression); diff --git a/src/main/java/com/alibaba/druid/sql/dialect/oracle/ast/stmt/OracleMergeStatement.java b/src/main/java/com/alibaba/druid/sql/ast/statement/SQLMergeStatement.java similarity index 79% rename from src/main/java/com/alibaba/druid/sql/dialect/oracle/ast/stmt/OracleMergeStatement.java rename to src/main/java/com/alibaba/druid/sql/ast/statement/SQLMergeStatement.java index c77b505e7c..757719fbf4 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/oracle/ast/stmt/OracleMergeStatement.java +++ b/src/main/java/com/alibaba/druid/sql/ast/statement/SQLMergeStatement.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package com.alibaba.druid.sql.dialect.oracle.ast.stmt; +package com.alibaba.druid.sql.ast.statement; import java.util.ArrayList; import java.util.List; @@ -21,14 +21,11 @@ import java.util.List; import com.alibaba.druid.sql.ast.SQLExpr; import com.alibaba.druid.sql.ast.SQLHint; import com.alibaba.druid.sql.ast.SQLName; -import com.alibaba.druid.sql.ast.statement.SQLExprTableSource; -import com.alibaba.druid.sql.ast.statement.SQLTableSource; -import com.alibaba.druid.sql.ast.statement.SQLUpdateSetItem; -import com.alibaba.druid.sql.dialect.oracle.ast.OracleSQLObjectImpl; -import com.alibaba.druid.sql.dialect.oracle.ast.clause.OracleErrorLoggingClause; -import com.alibaba.druid.sql.dialect.oracle.visitor.OracleASTVisitor; +import com.alibaba.druid.sql.ast.SQLObjectImpl; +import com.alibaba.druid.sql.ast.SQLStatementImpl; +import com.alibaba.druid.sql.visitor.SQLASTVisitor; -public class OracleMergeStatement extends OracleStatementImpl { +public class SQLMergeStatement extends SQLStatementImpl { private final List hints = new ArrayList(); @@ -38,9 +35,9 @@ public class OracleMergeStatement extends OracleStatementImpl { private SQLExpr on; private MergeUpdateClause updateClause; private MergeInsertClause insertClause; - private OracleErrorLoggingClause errorLoggingClause; + private SQLErrorLoggingClause errorLoggingClause; - public void accept0(OracleASTVisitor visitor) { + public void accept0(SQLASTVisitor visitor) { if (visitor.visit(this)) { acceptChild(visitor, into); acceptChild(visitor, using); @@ -107,11 +104,11 @@ public class OracleMergeStatement extends OracleStatementImpl { this.insertClause = insertClause; } - public OracleErrorLoggingClause getErrorLoggingClause() { + public SQLErrorLoggingClause getErrorLoggingClause() { return errorLoggingClause; } - public void setErrorLoggingClause(OracleErrorLoggingClause errorLoggingClause) { + public void setErrorLoggingClause(SQLErrorLoggingClause errorLoggingClause) { this.errorLoggingClause = errorLoggingClause; } @@ -119,7 +116,7 @@ public class OracleMergeStatement extends OracleStatementImpl { return hints; } - public static class MergeUpdateClause extends OracleSQLObjectImpl { + public static class MergeUpdateClause extends SQLObjectImpl { private List items = new ArrayList(); private SQLExpr where; @@ -153,7 +150,7 @@ public class OracleMergeStatement extends OracleStatementImpl { } @Override - public void accept0(OracleASTVisitor visitor) { + public void accept0(SQLASTVisitor visitor) { if (visitor.visit(this)) { acceptChild(visitor, items); acceptChild(visitor, where); @@ -164,14 +161,14 @@ public class OracleMergeStatement extends OracleStatementImpl { } - public static class MergeInsertClause extends OracleSQLObjectImpl { + public static class MergeInsertClause extends SQLObjectImpl { private List columns = new ArrayList(); private List values = new ArrayList(); private SQLExpr where; @Override - public void accept0(OracleASTVisitor visitor) { + public void accept0(SQLASTVisitor visitor) { if (visitor.visit(this)) { acceptChild(visitor, columns); acceptChild(visitor, columns); diff --git a/src/main/java/com/alibaba/druid/sql/dialect/db2/parser/DB2Lexer.java b/src/main/java/com/alibaba/druid/sql/dialect/db2/parser/DB2Lexer.java index 05ba0a0fff..52505e92c9 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/db2/parser/DB2Lexer.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/db2/parser/DB2Lexer.java @@ -40,6 +40,9 @@ public class DB2Lexer extends Lexer { map.put("CONCAT", Token.CONCAT); map.put("CONTINUE", Token.CONTINUE); map.put("IDENTITY", Token.IDENTITY); + map.put("MERGE", Token.MERGE); + map.put("USING", Token.USING); + map.put("MATCHED", Token.MATCHED); DEFAULT_DB2_KEYWORDS = new Keywords(map); } diff --git a/src/main/java/com/alibaba/druid/sql/dialect/oracle/ast/stmt/OracleInsertStatement.java b/src/main/java/com/alibaba/druid/sql/dialect/oracle/ast/stmt/OracleInsertStatement.java index 0535442414..c641d9b930 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/oracle/ast/stmt/OracleInsertStatement.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/oracle/ast/stmt/OracleInsertStatement.java @@ -19,8 +19,8 @@ import java.util.ArrayList; import java.util.List; import com.alibaba.druid.sql.ast.SQLHint; +import com.alibaba.druid.sql.ast.statement.SQLErrorLoggingClause; import com.alibaba.druid.sql.ast.statement.SQLInsertStatement; -import com.alibaba.druid.sql.dialect.oracle.ast.clause.OracleErrorLoggingClause; import com.alibaba.druid.sql.dialect.oracle.ast.clause.OracleReturningClause; import com.alibaba.druid.sql.dialect.oracle.visitor.OracleASTVisitor; import com.alibaba.druid.sql.dialect.oracle.visitor.OracleOutputVisitor; @@ -29,7 +29,7 @@ import com.alibaba.druid.sql.visitor.SQLASTVisitor; public class OracleInsertStatement extends SQLInsertStatement implements OracleStatement { private OracleReturningClause returning; - private OracleErrorLoggingClause errorLogging; + private SQLErrorLoggingClause errorLogging; private List hints = new ArrayList(); public List getHints() { @@ -48,11 +48,11 @@ public class OracleInsertStatement extends SQLInsertStatement implements OracleS this.returning = returning; } - public OracleErrorLoggingClause getErrorLogging() { + public SQLErrorLoggingClause getErrorLogging() { return errorLogging; } - public void setErrorLogging(OracleErrorLoggingClause errorLogging) { + public void setErrorLogging(SQLErrorLoggingClause errorLogging) { this.errorLogging = errorLogging; } diff --git a/src/main/java/com/alibaba/druid/sql/dialect/oracle/ast/stmt/OracleMultiInsertStatement.java b/src/main/java/com/alibaba/druid/sql/dialect/oracle/ast/stmt/OracleMultiInsertStatement.java index c9c5b963f5..b085c16f6d 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/oracle/ast/stmt/OracleMultiInsertStatement.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/oracle/ast/stmt/OracleMultiInsertStatement.java @@ -20,11 +20,11 @@ import java.util.List; import com.alibaba.druid.sql.ast.SQLExpr; import com.alibaba.druid.sql.ast.SQLHint; +import com.alibaba.druid.sql.ast.statement.SQLErrorLoggingClause; import com.alibaba.druid.sql.ast.statement.SQLInsertInto; import com.alibaba.druid.sql.ast.statement.SQLSelect; import com.alibaba.druid.sql.dialect.oracle.ast.OracleSQLObject; import com.alibaba.druid.sql.dialect.oracle.ast.OracleSQLObjectImpl; -import com.alibaba.druid.sql.dialect.oracle.ast.clause.OracleErrorLoggingClause; import com.alibaba.druid.sql.dialect.oracle.ast.clause.OracleReturningClause; import com.alibaba.druid.sql.dialect.oracle.visitor.OracleASTVisitor; import com.alibaba.druid.sql.visitor.SQLASTVisitor; @@ -158,7 +158,7 @@ public class OracleMultiInsertStatement extends OracleStatementImpl { public static class InsertIntoClause extends SQLInsertInto implements OracleSQLObject, Entry { private OracleReturningClause returning; - private OracleErrorLoggingClause errorLogging; + private SQLErrorLoggingClause errorLogging; public InsertIntoClause(){ @@ -172,11 +172,11 @@ public class OracleMultiInsertStatement extends OracleStatementImpl { this.returning = returning; } - public OracleErrorLoggingClause getErrorLogging() { + public SQLErrorLoggingClause getErrorLogging() { return errorLogging; } - public void setErrorLogging(OracleErrorLoggingClause errorLogging) { + public void setErrorLogging(SQLErrorLoggingClause errorLogging) { this.errorLogging = errorLogging; } diff --git a/src/main/java/com/alibaba/druid/sql/dialect/oracle/parser/OracleStatementParser.java b/src/main/java/com/alibaba/druid/sql/dialect/oracle/parser/OracleStatementParser.java index 9af35491dd..5acedb7634 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/oracle/parser/OracleStatementParser.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/oracle/parser/OracleStatementParser.java @@ -51,11 +51,7 @@ import com.alibaba.druid.sql.ast.statement.SQLSelect; import com.alibaba.druid.sql.ast.statement.SQLSelectOrderByItem; import com.alibaba.druid.sql.ast.statement.SQLSelectStatement; import com.alibaba.druid.sql.ast.statement.SQLSetStatement; -import com.alibaba.druid.sql.ast.statement.SQLSubqueryTableSource; -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.clause.OracleErrorLoggingClause; import com.alibaba.druid.sql.dialect.oracle.ast.clause.OracleReturningClause; import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleAlterIndexStatement; import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleAlterProcedureStatement; @@ -91,11 +87,9 @@ import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleInsertStatement; import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleLabelStatement; import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleLockTableStatement; import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleLockTableStatement.LockMode; -import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleMergeStatement; import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleMultiInsertStatement; import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OraclePLSQLCommitStatement; import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleSavePointStatement; -import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleSelect; import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleSetTransactionStatement; import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleStatement; import com.alibaba.druid.sql.parser.Lexer; @@ -119,10 +113,6 @@ public class OracleStatementParser extends SQLStatementParser { return (OracleExprParser) exprParser; } - public void parseHints(List hints) { - this.getExprParser().parseHints(hints); - } - public OracleCreateTableParser getSQLCreateTableParser() { return new OracleCreateTableParser(lexer); } @@ -1100,119 +1090,6 @@ public class OracleStatementParser extends SQLStatementParser { return new OracleSelectParser(this.exprParser); } - public OracleMergeStatement parseMerge() { - accept(Token.MERGE); - - OracleMergeStatement stmt = new OracleMergeStatement(); - - parseHints(stmt.getHints()); - - accept(Token.INTO); - - if (lexer.token() == Token.LPAREN) { - lexer.nextToken(); - OracleSelect select = this.createSQLSelectParser().select(); - SQLSubqueryTableSource tableSource = new SQLSubqueryTableSource(select); - stmt.setInto(tableSource); - accept(Token.RPAREN); - } else { - stmt.setInto(exprParser.name()); - } - - stmt.setAlias(as()); - - accept(Token.USING); - - SQLTableSource using = this.createSQLSelectParser().parseTableSource(); - stmt.setUsing(using); - - accept(Token.ON); - stmt.setOn(exprParser.expr()); - - boolean insertFlag = false; - if (lexer.token() == Token.WHEN) { - lexer.nextToken(); - if (lexer.token() == Token.MATCHED) { - OracleMergeStatement.MergeUpdateClause updateClause = new OracleMergeStatement.MergeUpdateClause(); - lexer.nextToken(); - accept(Token.THEN); - accept(Token.UPDATE); - accept(Token.SET); - - for (;;) { - SQLUpdateSetItem item = this.exprParser.parseUpdateSetItem(); - - updateClause.addItem(item); - item.setParent(updateClause); - - if (lexer.token() == (Token.COMMA)) { - lexer.nextToken(); - continue; - } - - break; - } - - if (lexer.token() == Token.WHERE) { - lexer.nextToken(); - updateClause.setWhere(exprParser.expr()); - } - - if (lexer.token() == Token.DELETE) { - lexer.nextToken(); - accept(Token.WHERE); - updateClause.setWhere(exprParser.expr()); - } - - stmt.setUpdateClause(updateClause); - } else if (lexer.token() == Token.NOT) { - lexer.nextToken(); - insertFlag = true; - } - } - - if (!insertFlag) { - if (lexer.token() == Token.WHEN) { - lexer.nextToken(); - } - - if (lexer.token() == Token.NOT) { - lexer.nextToken(); - insertFlag = true; - } - } - - if (insertFlag) { - OracleMergeStatement.MergeInsertClause insertClause = new OracleMergeStatement.MergeInsertClause(); - - accept(Token.MATCHED); - accept(Token.THEN); - accept(Token.INSERT); - - if (lexer.token() == Token.LPAREN) { - accept(Token.LPAREN); - exprParser.exprList(insertClause.getColumns(), insertClause); - accept(Token.RPAREN); - } - accept(Token.VALUES); - accept(Token.LPAREN); - exprParser.exprList(insertClause.getValues(), insertClause); - accept(Token.RPAREN); - - if (lexer.token() == Token.WHERE) { - lexer.nextToken(); - insertClause.setWhere(exprParser.expr()); - } - - stmt.setInsertClause(insertClause); - } - - OracleErrorLoggingClause errorClause = parseErrorLoggingClause(); - stmt.setErrorLoggingClause(errorClause); - - return stmt; - } - public OracleStatement parseInsert() { if (lexer.token() == Token.LPAREN) { OracleInsertStatement stmt = new OracleInsertStatement(); @@ -1322,34 +1199,6 @@ public class OracleStatementParser extends SQLStatementParser { return stmt; } - private OracleErrorLoggingClause parseErrorLoggingClause() { - if (identifierEquals("LOG")) { - OracleErrorLoggingClause errorClause = new OracleErrorLoggingClause(); - - lexer.nextToken(); - accept(Token.ERRORS); - if (lexer.token() == Token.INTO) { - lexer.nextToken(); - errorClause.setInto(exprParser.name()); - } - - if (lexer.token() == Token.LPAREN) { - lexer.nextToken(); - errorClause.setSimpleExpression(exprParser.expr()); - accept(Token.RPAREN); - } - - if (lexer.token() == Token.REJECT) { - lexer.nextToken(); - accept(Token.LIMIT); - errorClause.setLimit(exprParser.expr()); - } - - return errorClause; - } - return null; - } - public OracleReturningClause parseReturningClause() { OracleReturningClause clause = null; diff --git a/src/main/java/com/alibaba/druid/sql/dialect/oracle/visitor/OracleASTVisitor.java b/src/main/java/com/alibaba/druid/sql/dialect/oracle/visitor/OracleASTVisitor.java index 2db65b9bc7..444c86fb52 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/oracle/visitor/OracleASTVisitor.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/oracle/visitor/OracleASTVisitor.java @@ -23,7 +23,6 @@ import com.alibaba.druid.sql.dialect.oracle.ast.clause.FlashbackQueryClause.AsOf import com.alibaba.druid.sql.dialect.oracle.ast.clause.FlashbackQueryClause.AsOfSnapshotClause; import com.alibaba.druid.sql.dialect.oracle.ast.clause.FlashbackQueryClause.VersionsFlashbackQueryClause; import com.alibaba.druid.sql.dialect.oracle.ast.clause.ModelClause; -import com.alibaba.druid.sql.dialect.oracle.ast.clause.OracleErrorLoggingClause; import com.alibaba.druid.sql.dialect.oracle.ast.clause.OracleLobStorageClause; import com.alibaba.druid.sql.dialect.oracle.ast.clause.OracleReturningClause; import com.alibaba.druid.sql.dialect.oracle.ast.clause.OracleStorageClause; @@ -79,7 +78,6 @@ import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleGotoStatement; import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleInsertStatement; import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleLabelStatement; import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleLockTableStatement; -import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleMergeStatement; import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleMultiInsertStatement; import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleMultiInsertStatement.ConditionalInsertClause; import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleMultiInsertStatement.ConditionalInsertClauseItem; @@ -269,22 +267,6 @@ public interface OracleASTVisitor extends SQLASTVisitor { void endVisit(ModelClause x); - boolean visit(OracleMergeStatement x); - - void endVisit(OracleMergeStatement x); - - boolean visit(OracleMergeStatement.MergeUpdateClause x); - - void endVisit(OracleMergeStatement.MergeUpdateClause x); - - boolean visit(OracleMergeStatement.MergeInsertClause x); - - void endVisit(OracleMergeStatement.MergeInsertClause x); - - boolean visit(OracleErrorLoggingClause x); - - void endVisit(OracleErrorLoggingClause x); - boolean visit(OracleReturningClause x); void endVisit(OracleReturningClause x); diff --git a/src/main/java/com/alibaba/druid/sql/dialect/oracle/visitor/OracleASTVisitorAdapter.java b/src/main/java/com/alibaba/druid/sql/dialect/oracle/visitor/OracleASTVisitorAdapter.java index 2844ced0db..a53dca3342 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/oracle/visitor/OracleASTVisitorAdapter.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/oracle/visitor/OracleASTVisitorAdapter.java @@ -15,6 +15,8 @@ */ package com.alibaba.druid.sql.dialect.oracle.visitor; +import com.alibaba.druid.sql.ast.statement.SQLMergeStatement.MergeInsertClause; +import com.alibaba.druid.sql.ast.statement.SQLMergeStatement.MergeUpdateClause; import com.alibaba.druid.sql.dialect.oracle.ast.OracleDataTypeIntervalDay; import com.alibaba.druid.sql.dialect.oracle.ast.OracleDataTypeIntervalYear; import com.alibaba.druid.sql.dialect.oracle.ast.OracleDataTypeTimestamp; @@ -31,7 +33,6 @@ import com.alibaba.druid.sql.dialect.oracle.ast.clause.ModelClause.ModelColumnCl import com.alibaba.druid.sql.dialect.oracle.ast.clause.ModelClause.ModelRulesClause; import com.alibaba.druid.sql.dialect.oracle.ast.clause.ModelClause.QueryPartitionClause; import com.alibaba.druid.sql.dialect.oracle.ast.clause.ModelClause.ReturnRowsClause; -import com.alibaba.druid.sql.dialect.oracle.ast.clause.OracleErrorLoggingClause; import com.alibaba.druid.sql.dialect.oracle.ast.clause.OracleLobStorageClause; import com.alibaba.druid.sql.dialect.oracle.ast.clause.OracleReturningClause; import com.alibaba.druid.sql.dialect.oracle.ast.clause.OracleStorageClause; @@ -87,9 +88,6 @@ import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleGotoStatement; import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleInsertStatement; import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleLabelStatement; import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleLockTableStatement; -import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleMergeStatement; -import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleMergeStatement.MergeInsertClause; -import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleMergeStatement.MergeUpdateClause; import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleMultiInsertStatement; import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleMultiInsertStatement.ConditionalInsertClause; import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleMultiInsertStatement.ConditionalInsertClauseItem; @@ -553,15 +551,6 @@ public class OracleASTVisitorAdapter extends SQLASTVisitorAdapter implements Ora } - @Override - public boolean visit(OracleMergeStatement x) { - return true; - } - - @Override - public void endVisit(OracleMergeStatement x) { - } - @Override public boolean visit(MergeUpdateClause x) { return true; @@ -582,16 +571,6 @@ public class OracleASTVisitorAdapter extends SQLASTVisitorAdapter implements Ora } - @Override - public boolean visit(OracleErrorLoggingClause x) { - return true; - } - - @Override - public void endVisit(OracleErrorLoggingClause x) { - - } - @Override public boolean visit(OracleReturningClause x) { return true; diff --git a/src/main/java/com/alibaba/druid/sql/dialect/oracle/visitor/OracleOutputVisitor.java b/src/main/java/com/alibaba/druid/sql/dialect/oracle/visitor/OracleOutputVisitor.java index 0e757e460f..ab60bdbc89 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/oracle/visitor/OracleOutputVisitor.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/oracle/visitor/OracleOutputVisitor.java @@ -65,7 +65,6 @@ import com.alibaba.druid.sql.dialect.oracle.ast.clause.ModelClause.ModelRulesCla import com.alibaba.druid.sql.dialect.oracle.ast.clause.ModelClause.QueryPartitionClause; import com.alibaba.druid.sql.dialect.oracle.ast.clause.ModelClause.ReferenceModelClause; import com.alibaba.druid.sql.dialect.oracle.ast.clause.ModelClause.ReturnRowsClause; -import com.alibaba.druid.sql.dialect.oracle.ast.clause.OracleErrorLoggingClause; import com.alibaba.druid.sql.dialect.oracle.ast.clause.OracleLobStorageClause; import com.alibaba.druid.sql.dialect.oracle.ast.clause.OracleReturningClause; import com.alibaba.druid.sql.dialect.oracle.ast.clause.OracleStorageClause; @@ -126,9 +125,6 @@ import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleGotoStatement; import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleInsertStatement; import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleLabelStatement; import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleLockTableStatement; -import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleMergeStatement; -import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleMergeStatement.MergeInsertClause; -import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleMergeStatement.MergeUpdateClause; import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleMultiInsertStatement; import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleMultiInsertStatement.ConditionalInsertClause; import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleMultiInsertStatement.ConditionalInsertClauseItem; @@ -1285,138 +1281,6 @@ public class OracleOutputVisitor extends SQLASTOutputVisitor implements OracleAS } - @Override - public boolean visit(OracleMergeStatement x) { - print0(ucase ? "MERGE " : "merge "); - if (x.getHints().size() > 0) { - printAndAccept(x.getHints(), ", "); - print(' '); - } - - print0(ucase ? "INTO " : "into "); - x.getInto().accept(this); - - if (x.getAlias() != null) { - print(' '); - print0(x.getAlias()); - } - - println(); - print0(ucase ? "USING " : "using "); - x.getUsing().accept(this); - - print0(ucase ? " ON (" : " on ("); - x.getOn().accept(this); - print0(") "); - - if (x.getUpdateClause() != null) { - println(); - x.getUpdateClause().accept(this); - } - - if (x.getInsertClause() != null) { - println(); - x.getInsertClause().accept(this); - } - - if (x.getErrorLoggingClause() != null) { - println(); - x.getErrorLoggingClause().accept(this); - } - - return false; - } - - @Override - public void endVisit(OracleMergeStatement x) { - - } - - @Override - public boolean visit(MergeUpdateClause x) { - print0(ucase ? "WHEN MATCHED THEN UPDATE SET " : "when matched then update set "); - printAndAccept(x.getItems(), ", "); - if (x.getWhere() != null) { - incrementIndent(); - println(); - print0(ucase ? "WHERE " : "where "); - x.getWhere().setParent(x); - x.getWhere().accept(this); - decrementIndent(); - } - - if (x.getDeleteWhere() != null) { - incrementIndent(); - println(); - print0(ucase ? "DELETE WHERE " : "delete where "); - x.getDeleteWhere().setParent(x); - x.getDeleteWhere().accept(this); - decrementIndent(); - } - - return false; - } - - @Override - public void endVisit(MergeUpdateClause x) { - - } - - @Override - public boolean visit(MergeInsertClause x) { - print0(ucase ? "WHEN NOT MATCHED THEN INSERT" : "when not matched then insert"); - if (x.getColumns().size() > 0) { - print(' '); - printAndAccept(x.getColumns(), ", "); - } - print0(ucase ? " VALUES (" : " values ("); - printAndAccept(x.getValues(), ", "); - print(')'); - if (x.getWhere() != null) { - incrementIndent(); - println(); - print0(ucase ? "WHERE " : "where "); - x.getWhere().setParent(x); - x.getWhere().accept(this); - decrementIndent(); - } - - return false; - } - - @Override - public void endVisit(MergeInsertClause x) { - - } - - @Override - public boolean visit(OracleErrorLoggingClause x) { - print0(ucase ? "LOG ERRORS " : "log errors "); - if (x.getInto() != null) { - print0(ucase ? "INTO " : "into "); - x.getInto().accept(this); - print(' '); - } - - if (x.getSimpleExpression() != null) { - print('('); - x.getSimpleExpression().accept(this); - print(')'); - } - - if (x.getLimit() != null) { - print0(ucase ? " REJECT LIMIT " : " reject limit "); - x.getLimit().accept(this); - } - - return false; - } - - @Override - public void endVisit(OracleErrorLoggingClause x) { - - } - @Override public boolean visit(OracleReturningClause x) { print0(ucase ? "RETURNING " : "returning "); diff --git a/src/main/java/com/alibaba/druid/sql/dialect/oracle/visitor/OracleSchemaStatVisitor.java b/src/main/java/com/alibaba/druid/sql/dialect/oracle/visitor/OracleSchemaStatVisitor.java index 14ea4cc7e8..bebddcad19 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/oracle/visitor/OracleSchemaStatVisitor.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/oracle/visitor/OracleSchemaStatVisitor.java @@ -34,6 +34,8 @@ import com.alibaba.druid.sql.ast.statement.SQLDeleteStatement; import com.alibaba.druid.sql.ast.statement.SQLExprTableSource; import com.alibaba.druid.sql.ast.statement.SQLForeignKeyImpl; import com.alibaba.druid.sql.ast.statement.SQLInsertStatement; +import com.alibaba.druid.sql.ast.statement.SQLMergeStatement.MergeInsertClause; +import com.alibaba.druid.sql.ast.statement.SQLMergeStatement.MergeUpdateClause; import com.alibaba.druid.sql.ast.statement.SQLSelect; import com.alibaba.druid.sql.ast.statement.SQLSelectQueryBlock; import com.alibaba.druid.sql.ast.statement.SQLTableSource; @@ -54,7 +56,6 @@ import com.alibaba.druid.sql.dialect.oracle.ast.clause.ModelClause.ModelColumnCl import com.alibaba.druid.sql.dialect.oracle.ast.clause.ModelClause.ModelRulesClause; import com.alibaba.druid.sql.dialect.oracle.ast.clause.ModelClause.QueryPartitionClause; import com.alibaba.druid.sql.dialect.oracle.ast.clause.ModelClause.ReturnRowsClause; -import com.alibaba.druid.sql.dialect.oracle.ast.clause.OracleErrorLoggingClause; import com.alibaba.druid.sql.dialect.oracle.ast.clause.OracleLobStorageClause; import com.alibaba.druid.sql.dialect.oracle.ast.clause.OracleReturningClause; import com.alibaba.druid.sql.dialect.oracle.ast.clause.OracleStorageClause; @@ -110,9 +111,6 @@ import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleGotoStatement; import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleInsertStatement; import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleLabelStatement; import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleLockTableStatement; -import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleMergeStatement; -import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleMergeStatement.MergeInsertClause; -import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleMergeStatement.MergeUpdateClause; import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleMultiInsertStatement; import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleMultiInsertStatement.ConditionalInsertClause; import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleMultiInsertStatement.ConditionalInsertClauseItem; @@ -826,49 +824,6 @@ public class OracleSchemaStatVisitor extends SchemaStatVisitor implements Oracle } - @Override - public boolean visit(OracleMergeStatement x) { - setAliasMap(); - - String originalTable = getCurrentTable(); - - setMode(x.getUsing(), Mode.Select); - x.getUsing().accept(this); - - setMode(x, Mode.Merge); - - String ident = x.getInto().toString(); - setCurrentTable(x, ident); - x.putAttribute("_old_local_", originalTable); - - TableStat stat = getTableStat(ident); - stat.incrementMergeCount(); - - Map aliasMap = getAliasMap(); - if (aliasMap != null) { - if (x.getAlias() != null) { - putAliasMap(aliasMap, x.getAlias(), ident); - } - putAliasMap(aliasMap, ident, ident); - } - - x.getOn().accept(this); - - if (x.getUpdateClause() != null) { - x.getUpdateClause().accept(this); - } - - if (x.getInsertClause() != null) { - x.getInsertClause().accept(this); - } - - return false; - } - - @Override - public void endVisit(OracleMergeStatement x) { - } - @Override public boolean visit(MergeUpdateClause x) { return true; @@ -889,16 +844,6 @@ public class OracleSchemaStatVisitor extends SchemaStatVisitor implements Oracle } - @Override - public boolean visit(OracleErrorLoggingClause x) { - return true; - } - - @Override - public void endVisit(OracleErrorLoggingClause x) { - - } - @Override public boolean visit(OracleReturningClause x) { return true; diff --git a/src/main/java/com/alibaba/druid/sql/parser/SQLStatementParser.java b/src/main/java/com/alibaba/druid/sql/parser/SQLStatementParser.java index 7f053227af..d1888bf7ac 100644 --- a/src/main/java/com/alibaba/druid/sql/parser/SQLStatementParser.java +++ b/src/main/java/com/alibaba/druid/sql/parser/SQLStatementParser.java @@ -19,6 +19,7 @@ import java.util.ArrayList; import java.util.List; import com.alibaba.druid.sql.ast.SQLExpr; +import com.alibaba.druid.sql.ast.SQLHint; import com.alibaba.druid.sql.ast.SQLName; import com.alibaba.druid.sql.ast.SQLObject; import com.alibaba.druid.sql.ast.SQLStatement; @@ -74,12 +75,14 @@ import com.alibaba.druid.sql.ast.statement.SQLDropTableStatement; import com.alibaba.druid.sql.ast.statement.SQLDropTriggerStatement; import com.alibaba.druid.sql.ast.statement.SQLDropUserStatement; import com.alibaba.druid.sql.ast.statement.SQLDropViewStatement; +import com.alibaba.druid.sql.ast.statement.SQLErrorLoggingClause; import com.alibaba.druid.sql.ast.statement.SQLExplainStatement; import com.alibaba.druid.sql.ast.statement.SQLExprTableSource; import com.alibaba.druid.sql.ast.statement.SQLFetchStatement; import com.alibaba.druid.sql.ast.statement.SQLGrantStatement; import com.alibaba.druid.sql.ast.statement.SQLInsertInto; import com.alibaba.druid.sql.ast.statement.SQLInsertStatement; +import com.alibaba.druid.sql.ast.statement.SQLMergeStatement; import com.alibaba.druid.sql.ast.statement.SQLObjectType; import com.alibaba.druid.sql.ast.statement.SQLOpenStatement; import com.alibaba.druid.sql.ast.statement.SQLPrimaryKey; @@ -91,12 +94,12 @@ import com.alibaba.druid.sql.ast.statement.SQLSelect; import com.alibaba.druid.sql.ast.statement.SQLSelectOrderByItem; import com.alibaba.druid.sql.ast.statement.SQLSelectStatement; import com.alibaba.druid.sql.ast.statement.SQLSetStatement; +import com.alibaba.druid.sql.ast.statement.SQLSubqueryTableSource; import com.alibaba.druid.sql.ast.statement.SQLTableSource; import com.alibaba.druid.sql.ast.statement.SQLTruncateStatement; import com.alibaba.druid.sql.ast.statement.SQLUpdateSetItem; import com.alibaba.druid.sql.ast.statement.SQLUpdateStatement; import com.alibaba.druid.sql.ast.statement.SQLUseStatement; -import com.alibaba.druid.sql.dialect.odps.parser.OdpsSelectParser; public class SQLStatementParser extends SQLParser { @@ -400,6 +403,11 @@ public class SQLStatementParser extends SQLParser { continue; } } + + if (lexer.token() == Token.MERGE) { + statementList.add(this.parseMerge()); + continue; + } if (parseStatementListDialect(statementList)) { continue; @@ -1834,7 +1842,7 @@ public class SQLStatementParser extends SQLParser { } public SQLSelectParser createSQLSelectParser() { - return new OdpsSelectParser(this.exprParser); + return new SQLSelectParser(this.exprParser); } public SQLUpdateStatement parseUpdateStatement() { @@ -2136,4 +2144,149 @@ public class SQLStatementParser extends SQLParser { public void setParseValuesSize(int parseValuesSize) { this.parseValuesSize = parseValuesSize; } + + public SQLMergeStatement parseMerge() { + accept(Token.MERGE); + + SQLMergeStatement stmt = new SQLMergeStatement(); + + parseHints(stmt.getHints()); + + accept(Token.INTO); + + if (lexer.token() == Token.LPAREN) { + lexer.nextToken(); + SQLSelect select = this.createSQLSelectParser().select(); + SQLSubqueryTableSource tableSource = new SQLSubqueryTableSource(select); + stmt.setInto(tableSource); + accept(Token.RPAREN); + } else { + stmt.setInto(exprParser.name()); + } + + stmt.setAlias(as()); + + accept(Token.USING); + + SQLTableSource using = this.createSQLSelectParser().parseTableSource(); + stmt.setUsing(using); + + accept(Token.ON); + stmt.setOn(exprParser.expr()); + + boolean insertFlag = false; + if (lexer.token() == Token.WHEN) { + lexer.nextToken(); + if (lexer.token() == Token.MATCHED) { + SQLMergeStatement.MergeUpdateClause updateClause = new SQLMergeStatement.MergeUpdateClause(); + lexer.nextToken(); + accept(Token.THEN); + accept(Token.UPDATE); + accept(Token.SET); + + for (;;) { + SQLUpdateSetItem item = this.exprParser.parseUpdateSetItem(); + + updateClause.addItem(item); + item.setParent(updateClause); + + if (lexer.token() == (Token.COMMA)) { + lexer.nextToken(); + continue; + } + + break; + } + + if (lexer.token() == Token.WHERE) { + lexer.nextToken(); + updateClause.setWhere(exprParser.expr()); + } + + if (lexer.token() == Token.DELETE) { + lexer.nextToken(); + accept(Token.WHERE); + updateClause.setWhere(exprParser.expr()); + } + + stmt.setUpdateClause(updateClause); + } else if (lexer.token() == Token.NOT) { + lexer.nextToken(); + insertFlag = true; + } + } + + if (!insertFlag) { + if (lexer.token() == Token.WHEN) { + lexer.nextToken(); + } + + if (lexer.token() == Token.NOT) { + lexer.nextToken(); + insertFlag = true; + } + } + + if (insertFlag) { + SQLMergeStatement.MergeInsertClause insertClause = new SQLMergeStatement.MergeInsertClause(); + + accept(Token.MATCHED); + accept(Token.THEN); + accept(Token.INSERT); + + if (lexer.token() == Token.LPAREN) { + accept(Token.LPAREN); + exprParser.exprList(insertClause.getColumns(), insertClause); + accept(Token.RPAREN); + } + accept(Token.VALUES); + accept(Token.LPAREN); + exprParser.exprList(insertClause.getValues(), insertClause); + accept(Token.RPAREN); + + if (lexer.token() == Token.WHERE) { + lexer.nextToken(); + insertClause.setWhere(exprParser.expr()); + } + + stmt.setInsertClause(insertClause); + } + + SQLErrorLoggingClause errorClause = parseErrorLoggingClause(); + stmt.setErrorLoggingClause(errorClause); + + return stmt; + } + + protected SQLErrorLoggingClause parseErrorLoggingClause() { + if (identifierEquals("LOG")) { + SQLErrorLoggingClause errorClause = new SQLErrorLoggingClause(); + + lexer.nextToken(); + accept(Token.ERRORS); + if (lexer.token() == Token.INTO) { + lexer.nextToken(); + errorClause.setInto(exprParser.name()); + } + + if (lexer.token() == Token.LPAREN) { + lexer.nextToken(); + errorClause.setSimpleExpression(exprParser.expr()); + accept(Token.RPAREN); + } + + if (lexer.token() == Token.REJECT) { + lexer.nextToken(); + accept(Token.LIMIT); + errorClause.setLimit(exprParser.expr()); + } + + return errorClause; + } + return null; + } + + public void parseHints(List hints) { + this.getExprParser().parseHints(hints); + } } diff --git a/src/main/java/com/alibaba/druid/sql/visitor/SQLASTOutputVisitor.java b/src/main/java/com/alibaba/druid/sql/visitor/SQLASTOutputVisitor.java index 32b7ed4ded..4c0781932e 100644 --- a/src/main/java/com/alibaba/druid/sql/visitor/SQLASTOutputVisitor.java +++ b/src/main/java/com/alibaba/druid/sql/visitor/SQLASTOutputVisitor.java @@ -88,6 +88,8 @@ import com.alibaba.druid.sql.ast.statement.SQLCreateTriggerStatement.TriggerEven import com.alibaba.druid.sql.ast.statement.SQLCreateTriggerStatement.TriggerType; import com.alibaba.druid.sql.ast.statement.SQLInsertStatement.ValuesClause; import com.alibaba.druid.sql.ast.statement.SQLJoinTableSource.JoinType; +import com.alibaba.druid.sql.ast.statement.SQLMergeStatement.MergeInsertClause; +import com.alibaba.druid.sql.ast.statement.SQLMergeStatement.MergeUpdateClause; import com.alibaba.druid.util.JdbcConstants; public class SQLASTOutputVisitor extends SQLASTVisitorAdapter implements PrintableVisitor { @@ -3107,4 +3109,116 @@ public class SQLASTOutputVisitor extends SQLASTVisitorAdapter implements Printab print0(ucase ? x.getFunction().name : x.getFunction().name_lcase); return false; } + + @Override + public boolean visit(SQLMergeStatement x) { + print0(ucase ? "MERGE " : "merge "); + if (x.getHints().size() > 0) { + printAndAccept(x.getHints(), ", "); + print(' '); + } + + print0(ucase ? "INTO " : "into "); + x.getInto().accept(this); + + if (x.getAlias() != null) { + print(' '); + print0(x.getAlias()); + } + + println(); + print0(ucase ? "USING " : "using "); + x.getUsing().accept(this); + + print0(ucase ? " ON (" : " on ("); + x.getOn().accept(this); + print0(") "); + + if (x.getUpdateClause() != null) { + println(); + x.getUpdateClause().accept(this); + } + + if (x.getInsertClause() != null) { + println(); + x.getInsertClause().accept(this); + } + + if (x.getErrorLoggingClause() != null) { + println(); + x.getErrorLoggingClause().accept(this); + } + + return false; + } + + @Override + public boolean visit(MergeUpdateClause x) { + print0(ucase ? "WHEN MATCHED THEN UPDATE SET " : "when matched then update set "); + printAndAccept(x.getItems(), ", "); + if (x.getWhere() != null) { + incrementIndent(); + println(); + print0(ucase ? "WHERE " : "where "); + x.getWhere().setParent(x); + x.getWhere().accept(this); + decrementIndent(); + } + + if (x.getDeleteWhere() != null) { + incrementIndent(); + println(); + print0(ucase ? "DELETE WHERE " : "delete where "); + x.getDeleteWhere().setParent(x); + x.getDeleteWhere().accept(this); + decrementIndent(); + } + + return false; + } + + @Override + public boolean visit(MergeInsertClause x) { + print0(ucase ? "WHEN NOT MATCHED THEN INSERT" : "when not matched then insert"); + if (x.getColumns().size() > 0) { + print(' '); + printAndAccept(x.getColumns(), ", "); + } + print0(ucase ? " VALUES (" : " values ("); + printAndAccept(x.getValues(), ", "); + print(')'); + if (x.getWhere() != null) { + incrementIndent(); + println(); + print0(ucase ? "WHERE " : "where "); + x.getWhere().setParent(x); + x.getWhere().accept(this); + decrementIndent(); + } + + return false; + } + + @Override + public boolean visit(SQLErrorLoggingClause x) { + print0(ucase ? "LOG ERRORS " : "log errors "); + if (x.getInto() != null) { + print0(ucase ? "INTO " : "into "); + x.getInto().accept(this); + print(' '); + } + + if (x.getSimpleExpression() != null) { + print('('); + x.getSimpleExpression().accept(this); + print(')'); + } + + if (x.getLimit() != null) { + print0(ucase ? " REJECT LIMIT " : " reject limit "); + x.getLimit().accept(this); + } + + return false; + } } diff --git a/src/main/java/com/alibaba/druid/sql/visitor/SQLASTVisitor.java b/src/main/java/com/alibaba/druid/sql/visitor/SQLASTVisitor.java index d0dfc85bff..0f641957e7 100644 --- a/src/main/java/com/alibaba/druid/sql/visitor/SQLASTVisitor.java +++ b/src/main/java/com/alibaba/druid/sql/visitor/SQLASTVisitor.java @@ -700,5 +700,20 @@ public interface SQLASTVisitor { boolean visit(SQLSequenceExpr x); void endVisit(SQLSequenceExpr x); + + boolean visit(SQLMergeStatement x); + + void endVisit(SQLMergeStatement x); + + boolean visit(SQLMergeStatement.MergeUpdateClause x); + + void endVisit(SQLMergeStatement.MergeUpdateClause x); + + boolean visit(SQLMergeStatement.MergeInsertClause x); + + void endVisit(SQLMergeStatement.MergeInsertClause x); + boolean visit(SQLErrorLoggingClause x); + + void endVisit(SQLErrorLoggingClause x); } diff --git a/src/main/java/com/alibaba/druid/sql/visitor/SQLASTVisitorAdapter.java b/src/main/java/com/alibaba/druid/sql/visitor/SQLASTVisitorAdapter.java index a4d18eabd6..fb20641240 100644 --- a/src/main/java/com/alibaba/druid/sql/visitor/SQLASTVisitorAdapter.java +++ b/src/main/java/com/alibaba/druid/sql/visitor/SQLASTVisitorAdapter.java @@ -68,6 +68,8 @@ import com.alibaba.druid.sql.ast.expr.SQLUnaryExpr; import com.alibaba.druid.sql.ast.expr.SQLVariantRefExpr; import com.alibaba.druid.sql.ast.statement.*; import com.alibaba.druid.sql.ast.statement.SQLInsertStatement.ValuesClause; +import com.alibaba.druid.sql.ast.statement.SQLMergeStatement.MergeInsertClause; +import com.alibaba.druid.sql.ast.statement.SQLMergeStatement.MergeUpdateClause; public class SQLASTVisitorAdapter implements SQLASTVisitor { @@ -1523,5 +1525,44 @@ public class SQLASTVisitorAdapter implements SQLASTVisitor { public void endVisit(SQLSequenceExpr x) { } - + + @Override + public boolean visit(SQLMergeStatement x) { + return true; + } + + @Override + public void endVisit(SQLMergeStatement x) { + + } + + @Override + public boolean visit(MergeUpdateClause x) { + return true; + } + + @Override + public void endVisit(MergeUpdateClause x) { + + } + + @Override + public boolean visit(MergeInsertClause x) { + return true; + } + + @Override + public void endVisit(MergeInsertClause x) { + + } + + @Override + public boolean visit(SQLErrorLoggingClause x) { + return true; + } + + @Override + public void endVisit(SQLErrorLoggingClause x) { + + } } diff --git a/src/main/java/com/alibaba/druid/sql/visitor/SchemaStatVisitor.java b/src/main/java/com/alibaba/druid/sql/visitor/SchemaStatVisitor.java index ae96478e1a..9945a74664 100644 --- a/src/main/java/com/alibaba/druid/sql/visitor/SchemaStatVisitor.java +++ b/src/main/java/com/alibaba/druid/sql/visitor/SchemaStatVisitor.java @@ -101,6 +101,7 @@ import com.alibaba.druid.sql.ast.statement.SQLForeignKeyImpl; import com.alibaba.druid.sql.ast.statement.SQLGrantStatement; import com.alibaba.druid.sql.ast.statement.SQLInsertStatement; import com.alibaba.druid.sql.ast.statement.SQLJoinTableSource; +import com.alibaba.druid.sql.ast.statement.SQLMergeStatement; import com.alibaba.druid.sql.ast.statement.SQLObjectType; import com.alibaba.druid.sql.ast.statement.SQLOpenStatement; import com.alibaba.druid.sql.ast.statement.SQLRevokeStatement; @@ -1689,4 +1690,43 @@ public class SchemaStatVisitor extends SQLASTVisitorAdapter { public boolean visit(SQLSequenceExpr x) { return false; } + + @Override + public boolean visit(SQLMergeStatement x) { + setAliasMap(); + + String originalTable = getCurrentTable(); + + setMode(x.getUsing(), Mode.Select); + x.getUsing().accept(this); + + setMode(x, Mode.Merge); + + String ident = x.getInto().toString(); + setCurrentTable(x, ident); + x.putAttribute("_old_local_", originalTable); + + TableStat stat = getTableStat(ident); + stat.incrementMergeCount(); + + Map aliasMap = getAliasMap(); + if (aliasMap != null) { + if (x.getAlias() != null) { + putAliasMap(aliasMap, x.getAlias(), ident); + } + putAliasMap(aliasMap, ident, ident); + } + + x.getOn().accept(this); + + if (x.getUpdateClause() != null) { + x.getUpdateClause().accept(this); + } + + if (x.getInsertClause() != null) { + x.getInsertClause().accept(this); + } + + return false; + } } diff --git a/src/main/java/com/alibaba/druid/wall/spi/WallVisitorUtils.java b/src/main/java/com/alibaba/druid/wall/spi/WallVisitorUtils.java index b27b1342c5..03efba5d2a 100644 --- a/src/main/java/com/alibaba/druid/wall/spi/WallVisitorUtils.java +++ b/src/main/java/com/alibaba/druid/wall/spi/WallVisitorUtils.java @@ -78,6 +78,7 @@ import com.alibaba.druid.sql.ast.statement.SQLInsertInto; import com.alibaba.druid.sql.ast.statement.SQLInsertStatement; import com.alibaba.druid.sql.ast.statement.SQLInsertStatement.ValuesClause; import com.alibaba.druid.sql.ast.statement.SQLJoinTableSource; +import com.alibaba.druid.sql.ast.statement.SQLMergeStatement; import com.alibaba.druid.sql.ast.statement.SQLRollbackStatement; import com.alibaba.druid.sql.ast.statement.SQLSelect; import com.alibaba.druid.sql.ast.statement.SQLSelectGroupByClause; @@ -113,7 +114,6 @@ import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlStartTransactionSt import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlUpdateStatement; import com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser; import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleCreateSequenceStatement; -import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleMergeStatement; import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleMultiInsertStatement; import com.alibaba.druid.sql.dialect.postgresql.ast.stmt.PGShowStatement; import com.alibaba.druid.sql.dialect.sqlserver.ast.stmt.SQLServerCommitStatement; @@ -2404,7 +2404,7 @@ public class WallVisitorUtils { allow = true; denyMessage = "multi-insert not allow"; errorCode = ErrorCode.INSERT_NOT_ALLOW; - } else if (x instanceof OracleMergeStatement) { + } else if (x instanceof SQLMergeStatement) { allow = config.isMergeAllow(); denyMessage = "merge not allow"; errorCode = ErrorCode.MERGE_NOT_ALLOW; diff --git a/src/test/java/com/alibaba/druid/bvt/sql/db2/DB2MergeTest.java b/src/test/java/com/alibaba/druid/bvt/sql/db2/DB2MergeTest.java new file mode 100644 index 0000000000..32e34c8931 --- /dev/null +++ b/src/test/java/com/alibaba/druid/bvt/sql/db2/DB2MergeTest.java @@ -0,0 +1,76 @@ +/* + * Copyright 1999-2101 Alibaba Group Holding Ltd. + * + * 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 com.alibaba.druid.bvt.sql.db2; + +import java.util.List; + +import org.junit.Assert; + +import com.alibaba.druid.sql.DB2Test; +import com.alibaba.druid.sql.SQLUtils; +import com.alibaba.druid.sql.ast.SQLStatement; +import com.alibaba.druid.sql.dialect.db2.parser.DB2StatementParser; +import com.alibaba.druid.sql.dialect.db2.visitor.DB2SchemaStatVisitor; +import com.alibaba.druid.stat.TableStat; +import com.alibaba.druid.stat.TableStat.Column; +import com.alibaba.druid.util.JdbcConstants; + +public class DB2MergeTest extends DB2Test { + + public void test_0() throws Exception { + String sql = "MERGE INTO product AS T " + + " USING sales AS S" + + " ON S.id = T.id" + + " WHEN MATCHED THEN UPDATE SET inventory = T.inventory - S.sold;" + ; + + DB2StatementParser parser = new DB2StatementParser(sql); + List statementList = parser.parseStatementList(); + SQLStatement stmt = statementList.get(0); + print(statementList); + + Assert.assertEquals(1, statementList.size()); + + DB2SchemaStatVisitor visitor = new DB2SchemaStatVisitor(); + stmt.accept(visitor); + +// System.out.println("Tables : " + visitor.getTables()); +// System.out.println("fields : " + visitor.getColumns()); +// System.out.println("coditions : " + visitor.getConditions()); +// System.out.println("orderBy : " + visitor.getOrderByColumns()); + + Assert.assertEquals(2, visitor.getTables().size()); + Assert.assertEquals(4, visitor.getColumns().size()); + Assert.assertEquals(2, visitor.getConditions().size()); + + Assert.assertTrue(visitor.getTables().containsKey(new TableStat.Name("sales"))); + Assert.assertTrue(visitor.getTables().containsKey(new TableStat.Name("product"))); + +// Assert.assertTrue(visitor.getColumns().contains(new Column("DSN8B10.EMP", "WORKDEPT"))); + // Assert.assertTrue(visitor.getColumns().contains(new Column("mytable", "first_name"))); + // Assert.assertTrue(visitor.getColumns().contains(new Column("mytable", "full_name"))); + + Assert.assertEquals("MERGE INTO product T" + + "\nUSING sales S ON (S.id = T.id) " + + "\nWHEN MATCHED THEN UPDATE SET inventory = T.inventory - S.sold", // + SQLUtils.toSQLString(stmt, JdbcConstants.DB2)); + + Assert.assertEquals("merge into product T" + + "\nusing sales S on (S.id = T.id) " + + "\nwhen matched then update set inventory = T.inventory - S.sold", // + SQLUtils.toSQLString(stmt, JdbcConstants.DB2, SQLUtils.DEFAULT_LCASE_FORMAT_OPTION)); + } +} diff --git a/src/test/java/com/alibaba/druid/bvt/sql/oracle/OracleMergeTest7.java b/src/test/java/com/alibaba/druid/bvt/sql/oracle/OracleMergeTest7.java index 2c99745737..bcf1cf71f1 100644 --- a/src/test/java/com/alibaba/druid/bvt/sql/oracle/OracleMergeTest7.java +++ b/src/test/java/com/alibaba/druid/bvt/sql/oracle/OracleMergeTest7.java @@ -22,7 +22,7 @@ import org.junit.Assert; import com.alibaba.druid.sql.OracleTest; import com.alibaba.druid.sql.SQLUtils; import com.alibaba.druid.sql.ast.SQLStatement; -import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleMergeStatement; +import com.alibaba.druid.sql.ast.statement.SQLMergeStatement; import com.alibaba.druid.sql.dialect.oracle.parser.OracleStatementParser; import com.alibaba.druid.sql.parser.SQLStatementParser; @@ -44,7 +44,7 @@ public class OracleMergeTest7 extends OracleTest { SQLStatementParser parser = new OracleStatementParser(sql); List stmtList = parser.parseStatementList(); - OracleMergeStatement mergeStatement = (OracleMergeStatement) stmtList.get(0); + SQLMergeStatement mergeStatement = (SQLMergeStatement) stmtList.get(0); String result = SQLUtils.toOracleString(mergeStatement); Assert.assertEquals("MERGE INTO copy_emp c" // + "\nUSING employees e ON (c.employee_id = e.employee_id) " // diff --git a/src/test/java/com/alibaba/druid/bvt/sql/oracle/OracleMergeTest8.java b/src/test/java/com/alibaba/druid/bvt/sql/oracle/OracleMergeTest8.java index ac6a6603c2..38b01c6934 100644 --- a/src/test/java/com/alibaba/druid/bvt/sql/oracle/OracleMergeTest8.java +++ b/src/test/java/com/alibaba/druid/bvt/sql/oracle/OracleMergeTest8.java @@ -22,7 +22,7 @@ import org.junit.Assert; import com.alibaba.druid.sql.OracleTest; import com.alibaba.druid.sql.SQLUtils; import com.alibaba.druid.sql.ast.SQLStatement; -import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleMergeStatement; +import com.alibaba.druid.sql.ast.statement.SQLMergeStatement; import com.alibaba.druid.sql.dialect.oracle.parser.OracleStatementParser; import com.alibaba.druid.sql.parser.SQLStatementParser; @@ -40,7 +40,7 @@ public class OracleMergeTest8 extends OracleTest { SQLStatementParser parser = new OracleStatementParser(sql); List stmtList = parser.parseStatementList(); - OracleMergeStatement mergeStatement = (OracleMergeStatement) stmtList.get(0); + SQLMergeStatement mergeStatement = (SQLMergeStatement) stmtList.get(0); String result = SQLUtils.toOracleString(mergeStatement); Assert.assertEquals("MERGE INTO (SELECT *" + "\n\tFROM T09_RULE_CAL_COUNT" diff --git a/src/test/java/com/alibaba/druid/bvt/sql/oracle/visitor/OracleASTVisitorAdapterTest.java b/src/test/java/com/alibaba/druid/bvt/sql/oracle/visitor/OracleASTVisitorAdapterTest.java index b2d21fb46e..3638d7c90d 100644 --- a/src/test/java/com/alibaba/druid/bvt/sql/oracle/visitor/OracleASTVisitorAdapterTest.java +++ b/src/test/java/com/alibaba/druid/bvt/sql/oracle/visitor/OracleASTVisitorAdapterTest.java @@ -7,8 +7,12 @@ import com.alibaba.druid.sql.ast.statement.SQLAlterTableRename; import com.alibaba.druid.sql.ast.statement.SQLBlockStatement; import com.alibaba.druid.sql.ast.statement.SQLCreateProcedureStatement; import com.alibaba.druid.sql.ast.statement.SQLDropSequenceStatement; +import com.alibaba.druid.sql.ast.statement.SQLErrorLoggingClause; import com.alibaba.druid.sql.ast.statement.SQLFetchStatement; import com.alibaba.druid.sql.ast.statement.SQLLoopStatement; +import com.alibaba.druid.sql.ast.statement.SQLMergeStatement; +import com.alibaba.druid.sql.ast.statement.SQLMergeStatement.MergeInsertClause; +import com.alibaba.druid.sql.ast.statement.SQLMergeStatement.MergeUpdateClause; import com.alibaba.druid.sql.dialect.oracle.ast.OracleDataTypeIntervalDay; import com.alibaba.druid.sql.dialect.oracle.ast.OracleDataTypeIntervalYear; import com.alibaba.druid.sql.dialect.oracle.ast.OracleDataTypeTimestamp; @@ -25,7 +29,6 @@ import com.alibaba.druid.sql.dialect.oracle.ast.clause.ModelClause.ModelColumnCl import com.alibaba.druid.sql.dialect.oracle.ast.clause.ModelClause.ModelRulesClause; import com.alibaba.druid.sql.dialect.oracle.ast.clause.ModelClause.QueryPartitionClause; import com.alibaba.druid.sql.dialect.oracle.ast.clause.ModelClause.ReturnRowsClause; -import com.alibaba.druid.sql.dialect.oracle.ast.clause.OracleErrorLoggingClause; import com.alibaba.druid.sql.dialect.oracle.ast.clause.OracleReturningClause; import com.alibaba.druid.sql.dialect.oracle.ast.clause.OracleStorageClause; import com.alibaba.druid.sql.dialect.oracle.ast.clause.OracleWithSubqueryEntry; @@ -76,9 +79,6 @@ import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleGotoStatement; import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleInsertStatement; import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleLabelStatement; import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleLockTableStatement; -import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleMergeStatement; -import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleMergeStatement.MergeInsertClause; -import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleMergeStatement.MergeUpdateClause; import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleMultiInsertStatement; import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleMultiInsertStatement.ConditionalInsertClause; import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleMultiInsertStatement.ConditionalInsertClauseItem; @@ -150,10 +150,10 @@ public class OracleASTVisitorAdapterTest extends TestCase { new ModelRulesClause().accept(adapter); new CellAssignmentItem().accept(adapter); new CellAssignment().accept(adapter); - new OracleMergeStatement().accept(adapter); + new SQLMergeStatement().accept(adapter); new MergeUpdateClause().accept(adapter); new MergeInsertClause().accept(adapter); - new OracleErrorLoggingClause().accept(adapter); + new SQLErrorLoggingClause().accept(adapter); new OracleReturningClause().accept(adapter); new OracleInsertStatement().accept(adapter); new InsertIntoClause().accept(adapter);