diff --git a/src/main/java/com/alibaba/druid/sql/ast/SQLDataTypeImpl.java b/src/main/java/com/alibaba/druid/sql/ast/SQLDataTypeImpl.java index a9232ee75f..21c7fb62d9 100644 --- a/src/main/java/com/alibaba/druid/sql/ast/SQLDataTypeImpl.java +++ b/src/main/java/com/alibaba/druid/sql/ast/SQLDataTypeImpl.java @@ -18,7 +18,6 @@ package com.alibaba.druid.sql.ast; import java.util.ArrayList; import java.util.List; -import com.alibaba.druid.sql.dialect.oracle.visitor.OracleASTVisitor; import com.alibaba.druid.sql.visitor.SQLASTVisitor; public class SQLDataTypeImpl extends SQLObjectImpl implements SQLDataType { diff --git a/src/main/java/com/alibaba/druid/sql/dialect/mysql/ast/statement/MySqlUnionQuery.java b/src/main/java/com/alibaba/druid/sql/dialect/mysql/ast/statement/MySqlUnionQuery.java index 94185435dd..e2eded664c 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/mysql/ast/statement/MySqlUnionQuery.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/mysql/ast/statement/MySqlUnionQuery.java @@ -16,11 +16,12 @@ package com.alibaba.druid.sql.dialect.mysql.ast.statement; import com.alibaba.druid.sql.ast.statement.SQLUnionQuery; +import com.alibaba.druid.sql.dialect.mysql.ast.MySqlObject; import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlSelectQueryBlock.Limit; import com.alibaba.druid.sql.dialect.mysql.visitor.MySqlASTVisitor; import com.alibaba.druid.sql.visitor.SQLASTVisitor; -public class MySqlUnionQuery extends SQLUnionQuery implements MySqlStatement { +public class MySqlUnionQuery extends SQLUnionQuery implements MySqlObject { private static final long serialVersionUID = 1L; diff --git a/src/main/java/com/alibaba/druid/sql/dialect/mysql/parser/MySqlStatementParser.java b/src/main/java/com/alibaba/druid/sql/dialect/mysql/parser/MySqlStatementParser.java index 46ee5bb6d6..cc547f2e84 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/mysql/parser/MySqlStatementParser.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/mysql/parser/MySqlStatementParser.java @@ -23,6 +23,7 @@ import com.alibaba.druid.sql.ast.SQLName; import com.alibaba.druid.sql.ast.SQLOrderBy; import com.alibaba.druid.sql.ast.SQLStatement; import com.alibaba.druid.sql.ast.expr.SQLCharExpr; +import com.alibaba.druid.sql.ast.expr.SQLListExpr; import com.alibaba.druid.sql.ast.expr.SQLLiteralExpr; import com.alibaba.druid.sql.ast.expr.SQLQueryExpr; import com.alibaba.druid.sql.ast.expr.SQLVariantRefExpr; @@ -199,27 +200,7 @@ public class MySqlStatementParser extends SQLStatementParser { stmt.setTableSource(tableSource); } - accept(Token.SET); - - for (;;) { - SQLUpdateSetItem item = new SQLUpdateSetItem(); - item.setColumn(this.exprParser.name()); - if (lexer.token() == Token.EQ) { - lexer.nextToken(); - } else { - accept(Token.COLONEQ); - } - item.setValue(this.exprParser.expr()); - - stmt.getItems().add(item); - - if (lexer.token() == (Token.COMMA)) { - lexer.nextToken(); - continue; - } - - break; - } + parseUpdateSet(stmt); if (lexer.token() == (Token.WHERE)) { lexer.nextToken(); @@ -2361,4 +2342,35 @@ public class MySqlStatementParser extends SQLStatementParser { return stmt; } + + protected void parseUpdateSet(SQLUpdateStatement update) { + accept(Token.SET); + + for (;;) { + SQLUpdateSetItem item = new SQLUpdateSetItem(); + + if (lexer.token() == (Token.LPAREN)) { + lexer.nextToken(); + SQLListExpr list = new SQLListExpr(); + this.exprParser.exprList(list.getItems()); + accept(Token.RPAREN); + item.setColumn(list); + } else { + item.setColumn(this.exprParser.primary()); + } + if (lexer.token() == Token.COLONEQ) { + lexer.nextToken(); + } else { + accept(Token.EQ); + } + item.setValue(this.exprParser.expr()); + update.getItems().add(item); + + if (lexer.token() != Token.COMMA) { + break; + } + + lexer.nextToken(); + } + } } diff --git a/src/main/java/com/alibaba/druid/sql/dialect/oracle/ast/OracleDataTypeIntervalDay.java b/src/main/java/com/alibaba/druid/sql/dialect/oracle/ast/OracleDataTypeIntervalDay.java new file mode 100644 index 0000000000..024353909c --- /dev/null +++ b/src/main/java/com/alibaba/druid/sql/dialect/oracle/ast/OracleDataTypeIntervalDay.java @@ -0,0 +1,63 @@ +/* + * Copyright 1999-2011 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.sql.dialect.oracle.ast; + +import java.util.ArrayList; +import java.util.List; + +import com.alibaba.druid.sql.ast.SQLDataTypeImpl; +import com.alibaba.druid.sql.ast.SQLExpr; +import com.alibaba.druid.sql.dialect.oracle.visitor.OracleASTVisitor; +import com.alibaba.druid.sql.visitor.SQLASTVisitor; + +public class OracleDataTypeIntervalDay extends SQLDataTypeImpl implements OracleSQLObject { + + private static final long serialVersionUID = 1L; + + private boolean toSecond = false; + + protected final List fractionalSeconds = new ArrayList(); + + public OracleDataTypeIntervalDay(){ + this.setName("INTERVAL DAY"); + } + + @Override + protected void accept0(SQLASTVisitor visitor) { + this.accept0((OracleASTVisitor) visitor); + } + + @Override + public void accept0(OracleASTVisitor visitor) { + if (visitor.visit(this)) { + acceptChild(visitor, getArguments()); + } + visitor.endVisit(this); + } + + public boolean isToSecond() { + return toSecond; + } + + public void setToSecond(boolean toSecond) { + this.toSecond = toSecond; + } + + public List getFractionalSeconds() { + return fractionalSeconds; + } + +} diff --git a/src/main/java/com/alibaba/druid/sql/dialect/oracle/ast/OracleDataTypeIntervalYear.java b/src/main/java/com/alibaba/druid/sql/dialect/oracle/ast/OracleDataTypeIntervalYear.java new file mode 100644 index 0000000000..6aac7f6c80 --- /dev/null +++ b/src/main/java/com/alibaba/druid/sql/dialect/oracle/ast/OracleDataTypeIntervalYear.java @@ -0,0 +1,43 @@ +/* + * Copyright 1999-2011 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.sql.dialect.oracle.ast; + +import com.alibaba.druid.sql.ast.SQLDataTypeImpl; +import com.alibaba.druid.sql.dialect.oracle.visitor.OracleASTVisitor; +import com.alibaba.druid.sql.visitor.SQLASTVisitor; + +public class OracleDataTypeIntervalYear extends SQLDataTypeImpl implements OracleSQLObject { + + private static final long serialVersionUID = 1L; + + public OracleDataTypeIntervalYear(){ + this.setName("INTERVAL YEAR"); + } + + @Override + protected void accept0(SQLASTVisitor visitor) { + this.accept0((OracleASTVisitor) visitor); + } + + @Override + public void accept0(OracleASTVisitor visitor) { + if (visitor.visit(this)) { + acceptChild(visitor, getArguments()); + } + visitor.endVisit(this); + } + +} diff --git a/src/main/java/com/alibaba/druid/sql/dialect/oracle/ast/OracleDataTypeTimestamp.java b/src/main/java/com/alibaba/druid/sql/dialect/oracle/ast/OracleDataTypeTimestamp.java new file mode 100644 index 0000000000..924633eadf --- /dev/null +++ b/src/main/java/com/alibaba/druid/sql/dialect/oracle/ast/OracleDataTypeTimestamp.java @@ -0,0 +1,62 @@ +/* + * Copyright 1999-2011 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.sql.dialect.oracle.ast; + +import com.alibaba.druid.sql.ast.SQLDataTypeImpl; +import com.alibaba.druid.sql.dialect.oracle.visitor.OracleASTVisitor; +import com.alibaba.druid.sql.visitor.SQLASTVisitor; + +public class OracleDataTypeTimestamp extends SQLDataTypeImpl implements OracleSQLObject { + + private static final long serialVersionUID = 1L; + + private boolean withTimeZone = false; + private boolean withLocalTimeZone = false; + + public OracleDataTypeTimestamp() { + this.setName("TIMESTAMP"); + } + + @Override + protected void accept0(SQLASTVisitor visitor) { + this.accept0((OracleASTVisitor) visitor); + } + + @Override + public void accept0(OracleASTVisitor visitor) { + if (visitor.visit(this)) { + acceptChild(visitor, getArguments()); + } + visitor.endVisit(this); + } + + public boolean isWithTimeZone() { + return withTimeZone; + } + + public void setWithTimeZone(boolean withTimeZone) { + this.withTimeZone = withTimeZone; + } + + public boolean isWithLocalTimeZone() { + return withLocalTimeZone; + } + + public void setWithLocalTimeZone(boolean withLocalTimeZone) { + this.withLocalTimeZone = withLocalTimeZone; + } + +} diff --git a/src/main/java/com/alibaba/druid/sql/dialect/oracle/ast/stmt/OracleDropSequenceStatement.java b/src/main/java/com/alibaba/druid/sql/dialect/oracle/ast/stmt/OracleDropSequenceStatement.java new file mode 100644 index 0000000000..057302768e --- /dev/null +++ b/src/main/java/com/alibaba/druid/sql/dialect/oracle/ast/stmt/OracleDropSequenceStatement.java @@ -0,0 +1,43 @@ +/* + * Copyright 1999-2011 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.sql.dialect.oracle.ast.stmt; + +import com.alibaba.druid.sql.ast.SQLName; +import com.alibaba.druid.sql.dialect.oracle.visitor.OracleASTVisitor; + +public class OracleDropSequenceStatement extends OracleStatementImpl implements OracleDDLStatement { + + private static final long serialVersionUID = 1L; + + private SQLName name; + + @Override + public void accept0(OracleASTVisitor visitor) { + if (visitor.visit(this)) { + acceptChild(visitor, name); + } + visitor.endVisit(this); + } + + public SQLName getName() { + return name; + } + + public void setName(SQLName name) { + this.name = name; + } + +} diff --git a/src/main/java/com/alibaba/druid/sql/dialect/oracle/parser/OracleExprParser.java b/src/main/java/com/alibaba/druid/sql/dialect/oracle/parser/OracleExprParser.java index 635c91c47c..68ac72fbc4 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/oracle/parser/OracleExprParser.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/oracle/parser/OracleExprParser.java @@ -37,6 +37,9 @@ import com.alibaba.druid.sql.ast.expr.SQLUnaryOperator; import com.alibaba.druid.sql.ast.expr.SQLVariantRefExpr; import com.alibaba.druid.sql.ast.statement.SQLCharactorDataType; import com.alibaba.druid.sql.ast.statement.SQLColumnDefinition; +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; import com.alibaba.druid.sql.dialect.oracle.ast.OracleOrderBy; import com.alibaba.druid.sql.dialect.oracle.ast.expr.OracleAggregateExpr; import com.alibaba.druid.sql.dialect.oracle.ast.expr.OracleAnalytic; @@ -75,6 +78,7 @@ public class OracleExprParser extends SQLExprParser { + public boolean allowStringAdditive = false; /** @@ -117,9 +121,73 @@ public class OracleExprParser extends SQLExprParser { return null; } + if (lexer.token() == Token.INTERVAL) { + lexer.nextToken(); + if (identifierEquals("YEAR")) { + lexer.nextToken(); + OracleDataTypeIntervalYear interval = new OracleDataTypeIntervalYear(); + + if (lexer.token() == Token.LPAREN) { + lexer.nextToken(); + interval.getArguments().add(this.expr()); + accept(Token.RPAREN); + } + + accept(Token.TO); + acceptIdentifier("MONTH"); + + return interval; + } else { + acceptIdentifier("DAY"); + OracleDataTypeIntervalDay interval = new OracleDataTypeIntervalDay(); + if (lexer.token() == Token.LPAREN) { + lexer.nextToken(); + interval.getArguments().add(this.expr()); + accept(Token.RPAREN); + } + + accept(Token.TO); + acceptIdentifier("SECOND"); + + if (lexer.token() == Token.LPAREN) { + lexer.nextToken(); + interval.getFractionalSeconds().add(this.expr()); + accept(Token.RPAREN); + } + + return interval; + } + } + SQLName typeExpr = name(); String typeName = typeExpr.toString(); + if ("TIMESTAMP".equalsIgnoreCase(typeName)) { + OracleDataTypeTimestamp timestamp = new OracleDataTypeTimestamp(); + + if (lexer.token() == Token.LPAREN) { + lexer.nextToken(); + timestamp.getArguments().add(this.expr()); + accept(Token.RPAREN); + } + + if (lexer.token() == Token.WITH) { + lexer.nextToken(); + + if (identifierEquals("LOCAL")) { + lexer.nextToken(); + timestamp.setWithLocalTimeZone(true); + } else { + timestamp.setWithTimeZone(true); + } + + acceptIdentifier("TIME"); + acceptIdentifier("ZONE"); + } + + return timestamp; + } + if (isCharType(typeName)) { SQLCharactorDataType charType = new SQLCharactorDataType(typeName); 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 b1fa2ac68b..84d52d4b47 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 @@ -72,6 +72,7 @@ import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleCreateProcedureStatem import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleCreateSequenceStatement; import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleDeleteStatement; import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleDropDatabaseLinkStatement; +import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleDropSequenceStatement; import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleExceptionStatement; import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleExitStatement; import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleExplainStatement; @@ -444,6 +445,18 @@ public class OracleStatementParser extends SQLStatementParser { continue; } } + + if (identifierEquals("SEQUENCE")) { + lexer.nextToken(); + + SQLName name = this.exprParser.name(); + + OracleDropSequenceStatement stmt = new OracleDropSequenceStatement(); + stmt.setName(name); + + statementList.add(stmt); + continue; + } throw new ParserException("TODO : " + lexer.token() + " " + lexer.stringVal()); } diff --git a/src/main/java/com/alibaba/druid/sql/dialect/oracle/parser/OracleUpdateParser.java b/src/main/java/com/alibaba/druid/sql/dialect/oracle/parser/OracleUpdateParser.java index 2859c2801e..dcb6548b65 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/oracle/parser/OracleUpdateParser.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/oracle/parser/OracleUpdateParser.java @@ -55,7 +55,7 @@ public class OracleUpdateParser extends SQLStatementParser { } } - parseSet(update); + parseUpdateSet(update); parseWhere(update); @@ -117,30 +117,4 @@ public class OracleUpdateParser extends SQLStatementParser { } } - private void parseSet(OracleUpdateStatement update) { - accept(Token.SET); - - for (;;) { - SQLUpdateSetItem item = new SQLUpdateSetItem(); - - if (lexer.token() == (Token.LPAREN)) { - lexer.nextToken(); - SQLListExpr list = new SQLListExpr(); - this.exprParser.exprList(list.getItems()); - accept(Token.RPAREN); - item.setColumn(list); - } else { - item.setColumn(this.exprParser.primary()); - } - accept(Token.EQ); - item.setValue(this.exprParser.expr()); - update.getItems().add(item); - - if (lexer.token() != Token.COMMA) { - break; - } - - lexer.nextToken(); - } - } } 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 baa78a0f71..ddcecf2a1a 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 @@ -16,6 +16,9 @@ package com.alibaba.druid.sql.dialect.oracle.visitor; import com.alibaba.druid.sql.ast.expr.SQLObjectCreateExpr; +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; import com.alibaba.druid.sql.dialect.oracle.ast.OracleOrderBy; import com.alibaba.druid.sql.dialect.oracle.ast.clause.CycleClause; import com.alibaba.druid.sql.dialect.oracle.ast.clause.FlashbackQueryClause.AsOfFlashbackQueryClause; @@ -77,6 +80,7 @@ import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleCreateSequenceStateme import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleCreateTableStatement; import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleDeleteStatement; import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleDropDatabaseLinkStatement; +import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleDropSequenceStatement; import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleExceptionStatement; import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleExitStatement; import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleExplainStatement; @@ -611,4 +615,20 @@ public interface OracleASTVisitor extends SQLASTVisitor { boolean visit(OracleDropDatabaseLinkStatement x); void endVisit(OracleDropDatabaseLinkStatement x); + + boolean visit(OracleDataTypeTimestamp x); + + void endVisit(OracleDataTypeTimestamp x); + + boolean visit(OracleDataTypeIntervalYear x); + + void endVisit(OracleDataTypeIntervalYear x); + + boolean visit(OracleDataTypeIntervalDay x); + + void endVisit(OracleDataTypeIntervalDay x); + + boolean visit(OracleDropSequenceStatement x); + + void endVisit(OracleDropSequenceStatement 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 7122c89aa6..32152d5101 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 @@ -16,6 +16,9 @@ package com.alibaba.druid.sql.dialect.oracle.visitor; import com.alibaba.druid.sql.ast.expr.SQLObjectCreateExpr; +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; import com.alibaba.druid.sql.dialect.oracle.ast.OracleOrderBy; import com.alibaba.druid.sql.dialect.oracle.ast.clause.CycleClause; import com.alibaba.druid.sql.dialect.oracle.ast.clause.FlashbackQueryClause.AsOfFlashbackQueryClause; @@ -85,6 +88,7 @@ import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleCreateSequenceStateme import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleCreateTableStatement; import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleDeleteStatement; import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleDropDatabaseLinkStatement; +import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleDropSequenceStatement; import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleExceptionStatement; import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleExitStatement; import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleExplainStatement; @@ -1393,4 +1397,44 @@ public class OracleASTVisitorAdapter extends SQLASTVisitorAdapter implements Ora } + @Override + public boolean visit(OracleDataTypeTimestamp x) { + return true; + } + + @Override + public void endVisit(OracleDataTypeTimestamp x) { + + } + + @Override + public boolean visit(OracleDataTypeIntervalYear x) { + return true; + } + + @Override + public void endVisit(OracleDataTypeIntervalYear x) { + + } + + @Override + public boolean visit(OracleDataTypeIntervalDay x) { + return true; + } + + @Override + public void endVisit(OracleDataTypeIntervalDay x) { + + } + + @Override + public boolean visit(OracleDropSequenceStatement x) { + return true; + } + + @Override + public void endVisit(OracleDropSequenceStatement x) { + + } + } 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 07a611c768..e004e07df2 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 @@ -38,6 +38,9 @@ import com.alibaba.druid.sql.ast.statement.SQLJoinTableSource.JoinType; import com.alibaba.druid.sql.ast.statement.SQLRollbackStatement; import com.alibaba.druid.sql.ast.statement.SQLSelect; import com.alibaba.druid.sql.ast.statement.SQLSelectQueryBlock; +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; import com.alibaba.druid.sql.dialect.oracle.ast.OracleOrderBy; import com.alibaba.druid.sql.dialect.oracle.ast.clause.CycleClause; import com.alibaba.druid.sql.dialect.oracle.ast.clause.FlashbackQueryClause.AsOfFlashbackQueryClause; @@ -114,6 +117,7 @@ import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleCreateSequenceStateme import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleCreateTableStatement; import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleDeleteStatement; import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleDropDatabaseLinkStatement; +import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleDropSequenceStatement; import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleExceptionStatement; import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleExitStatement; import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleExplainStatement; @@ -3107,4 +3111,83 @@ public class OracleOutputVisitor extends SQLASTOutputVisitor implements OracleAS } return false; } + + @Override + public boolean visit(OracleDataTypeTimestamp x) { + print(x.getName()); + if (x.getArguments().size() > 0) { + print("("); + x.getArguments().get(0).accept(this); + print(")"); + } + + if (x.isWithTimeZone()) { + print(" WITH TIME ZONE"); + } else if (x.isWithLocalTimeZone()) { + print(" WITH LOCAL TIME ZONE"); + } + + return false; + } + + @Override + public void endVisit(OracleDataTypeTimestamp x) { + + } + + @Override + public boolean visit(OracleDataTypeIntervalYear x) { + print(x.getName()); + if (x.getArguments().size() > 0) { + print("("); + x.getArguments().get(0).accept(this); + print(")"); + } + + print(" TO MONTH"); + + return false; + } + + @Override + public void endVisit(OracleDataTypeIntervalYear x) { + + } + + @Override + public boolean visit(OracleDataTypeIntervalDay x) { + print(x.getName()); + if (x.getArguments().size() > 0) { + print("("); + x.getArguments().get(0).accept(this); + print(")"); + } + + print(" TO SECOND"); + + if (x.getFractionalSeconds().size() > 0) { + print("("); + x.getFractionalSeconds().get(0).accept(this); + print(")"); + } + + return false; + } + + @Override + public void endVisit(OracleDataTypeIntervalDay x) { + + } + + @Override + public boolean visit(OracleDropSequenceStatement x) { + print("DROP SEQUENCE "); + x.getName().accept(this); + return false; + } + + @Override + public void endVisit(OracleDropSequenceStatement x) { + + } } 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 cd06b63dc3..da30c98718 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 @@ -37,6 +37,9 @@ import com.alibaba.druid.sql.ast.statement.SQLSelect; import com.alibaba.druid.sql.ast.statement.SQLSelectQueryBlock; import com.alibaba.druid.sql.ast.statement.SQLTableSource; import com.alibaba.druid.sql.ast.statement.SQLTruncateStatement; +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; import com.alibaba.druid.sql.dialect.oracle.ast.OracleOrderBy; import com.alibaba.druid.sql.dialect.oracle.ast.clause.CycleClause; import com.alibaba.druid.sql.dialect.oracle.ast.clause.FlashbackQueryClause.AsOfFlashbackQueryClause; @@ -106,6 +109,7 @@ import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleCreateSequenceStateme import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleCreateTableStatement; import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleDeleteStatement; import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleDropDatabaseLinkStatement; +import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleDropSequenceStatement; import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleExceptionStatement; import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleExitStatement; import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleExplainStatement; @@ -1822,4 +1826,44 @@ public class OracleSchemaStatVisitor extends SchemaStatVisitor implements Oracle public void endVisit(OracleDropDatabaseLinkStatement x) { } + + @Override + public boolean visit(OracleDataTypeTimestamp x) { + return false; + } + + @Override + public void endVisit(OracleDataTypeTimestamp x) { + + } + + @Override + public boolean visit(OracleDataTypeIntervalYear x) { + return false; + } + + @Override + public void endVisit(OracleDataTypeIntervalYear x) { + + } + + @Override + public boolean visit(OracleDataTypeIntervalDay x) { + return false; + } + + @Override + public void endVisit(OracleDataTypeIntervalDay x) { + + } + + @Override + public boolean visit(OracleDropSequenceStatement x) { + return false; + } + + @Override + public void endVisit(OracleDropSequenceStatement x) { + + } } diff --git a/src/main/java/com/alibaba/druid/sql/dialect/postgresql/parser/PGSQLStatementParser.java b/src/main/java/com/alibaba/druid/sql/dialect/postgresql/parser/PGSQLStatementParser.java index c0c3cd4c47..7d1a4c033b 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/postgresql/parser/PGSQLStatementParser.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/postgresql/parser/PGSQLStatementParser.java @@ -60,23 +60,7 @@ public class PGSQLStatementParser extends SQLStatementParser { SQLTableSource tableSource = this.exprParser.createSelectParser().parseTableSource(); udpateStatement.setTableSource(tableSource); - accept(Token.SET); - - for (;;) { - SQLUpdateSetItem item = new SQLUpdateSetItem(); - item.setColumn(this.exprParser.name()); - accept(Token.EQ); - item.setValue(this.exprParser.expr()); - - udpateStatement.getItems().add(item); - - if (lexer.token() == (Token.COMMA)) { - lexer.nextToken(); - continue; - } - - break; - } + parseUpdateSet(udpateStatement); if (lexer.token() == (Token.WHERE)) { lexer.nextToken(); diff --git a/src/main/java/com/alibaba/druid/sql/dialect/sqlserver/ast/SQLServerStatement.java b/src/main/java/com/alibaba/druid/sql/dialect/sqlserver/ast/SQLServerStatement.java index ede91d3fb0..12e1962b6c 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/sqlserver/ast/SQLServerStatement.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/sqlserver/ast/SQLServerStatement.java @@ -17,6 +17,6 @@ package com.alibaba.druid.sql.dialect.sqlserver.ast; import com.alibaba.druid.sql.ast.SQLStatement; -public interface SQLServerStatement extends SQLStatement { +public interface SQLServerStatement extends SQLStatement, SQLServerObject { } diff --git a/src/main/java/com/alibaba/druid/sql/dialect/sqlserver/ast/stmt/SQLServerUpdateStatement.java b/src/main/java/com/alibaba/druid/sql/dialect/sqlserver/ast/stmt/SQLServerUpdateStatement.java new file mode 100644 index 0000000000..7fa22aea22 --- /dev/null +++ b/src/main/java/com/alibaba/druid/sql/dialect/sqlserver/ast/stmt/SQLServerUpdateStatement.java @@ -0,0 +1,55 @@ +/* + * Copyright 1999-2011 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.sql.dialect.sqlserver.ast.stmt; + +import com.alibaba.druid.sql.ast.statement.SQLTableSource; +import com.alibaba.druid.sql.ast.statement.SQLUpdateStatement; +import com.alibaba.druid.sql.dialect.sqlserver.ast.SQLServerStatement; +import com.alibaba.druid.sql.dialect.sqlserver.visitor.SQLServerASTVisitor; +import com.alibaba.druid.sql.visitor.SQLASTVisitor; + +public class SQLServerUpdateStatement extends SQLUpdateStatement implements SQLServerStatement { + private static final long serialVersionUID = 1L; + + private SQLTableSource from; + + + public SQLTableSource getFrom() { + return from; + } + + + public void setFrom(SQLTableSource from) { + this.from = from; + } + + @Override + protected void accept0(SQLASTVisitor visitor) { + this.accept0((SQLServerASTVisitor) visitor); + } + + @Override + public void accept0(SQLServerASTVisitor visitor) { + if (visitor.visit(this)) { + acceptChild(visitor, tableSource); + acceptChild(visitor, items); + acceptChild(visitor, from); + acceptChild(visitor, where); + } + visitor.endVisit(this); + } + +} diff --git a/src/main/java/com/alibaba/druid/sql/dialect/sqlserver/parser/SQLServerLexer.java b/src/main/java/com/alibaba/druid/sql/dialect/sqlserver/parser/SQLServerLexer.java index 1d03d19c36..4cc3ad1a8a 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/sqlserver/parser/SQLServerLexer.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/sqlserver/parser/SQLServerLexer.java @@ -15,11 +15,14 @@ */ package com.alibaba.druid.sql.dialect.sqlserver.parser; +import static com.alibaba.druid.sql.parser.LayoutCharacters.EOI; + import java.util.HashMap; import java.util.Map; import com.alibaba.druid.sql.parser.Keywords; import com.alibaba.druid.sql.parser.Lexer; +import com.alibaba.druid.sql.parser.NotAllowCommentException; import com.alibaba.druid.sql.parser.Token; public class SQLServerLexer extends Lexer { @@ -48,4 +51,95 @@ public class SQLServerLexer extends Lexer { super(input); super.keywods = DEFAULT_SQL_SERVER_KEYWORDS; } + + public void scanComment() { + if (ch != '/' && ch != '-') { + throw new IllegalStateException(); + } + + mark = pos; + bufPos = 0; + scanChar(); + + // /*+ */ + if (ch == '*') { + scanChar(); + bufPos++; + + while (ch == ' ') { + scanChar(); + bufPos++; + } + + boolean isHint = false; + int startHintSp = bufPos + 1; + if (ch == '!') { + isHint = true; + scanChar(); + bufPos++; + } + + for (;;) { + if (ch == '*' && charAt(pos + 1) == '/') { + bufPos += 2; + scanChar(); + scanChar(); + break; + } + + scanChar(); + bufPos++; + } + + if (isHint) { + stringVal = subString(mark + startHintSp, (bufPos - startHintSp) - 1); + token = Token.HINT; + } else { + stringVal = subString(mark, bufPos); + token = Token.MULTI_LINE_COMMENT; + } + + if (token != Token.HINT && !isAllowComment()) { + throw new NotAllowCommentException(); + } + + return; + } + + if (!isAllowComment()) { + throw new NotAllowCommentException(); + } + + if (ch == '/' || ch == '-') { + scanChar(); + bufPos++; + + for (;;) { + if (ch == '\r') { + if (charAt(pos + 1) == '\n') { + bufPos += 2; + scanChar(); + break; + } + bufPos++; + break; + } else if (ch == EOI) { + break; + } + + if (ch == '\n') { + scanChar(); + bufPos++; + break; + } + + scanChar(); + bufPos++; + } + + stringVal = subString(mark + 1, bufPos); + token = Token.LINE_COMMENT; + return; + } + } } diff --git a/src/main/java/com/alibaba/druid/sql/dialect/sqlserver/parser/SQLServerSelectParser.java b/src/main/java/com/alibaba/druid/sql/dialect/sqlserver/parser/SQLServerSelectParser.java index 6fae0bb0ad..19908b74e4 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/sqlserver/parser/SQLServerSelectParser.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/sqlserver/parser/SQLServerSelectParser.java @@ -37,6 +37,8 @@ public class SQLServerSelectParser extends SQLSelectParser { public SQLSelect select() { SQLServerSelect select = new SQLServerSelect(); + + withSubquery(select); select.setQuery(query()); select.setOrderBy(parseOrderBy()); diff --git a/src/main/java/com/alibaba/druid/sql/dialect/sqlserver/parser/SQLServerStatementParser.java b/src/main/java/com/alibaba/druid/sql/dialect/sqlserver/parser/SQLServerStatementParser.java index b29aa7d642..95671d475b 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/sqlserver/parser/SQLServerStatementParser.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/sqlserver/parser/SQLServerStatementParser.java @@ -15,12 +15,18 @@ */ package com.alibaba.druid.sql.dialect.sqlserver.parser; +import java.util.List; + import com.alibaba.druid.sql.ast.SQLName; import com.alibaba.druid.sql.ast.SQLStatement; import com.alibaba.druid.sql.ast.expr.SQLQueryExpr; import com.alibaba.druid.sql.ast.statement.SQLInsertInto; import com.alibaba.druid.sql.ast.statement.SQLInsertStatement; +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.sqlserver.ast.stmt.SQLServerInsertStatement; +import com.alibaba.druid.sql.dialect.sqlserver.ast.stmt.SQLServerUpdateStatement; import com.alibaba.druid.sql.parser.Lexer; import com.alibaba.druid.sql.parser.SQLSelectParser; import com.alibaba.druid.sql.parser.SQLStatementParser; @@ -40,6 +46,16 @@ public class SQLServerStatementParser extends SQLStatementParser { super(new SQLServerExprParser(lexer)); } + public boolean parseStatementListDialect(List statementList) { + if (lexer.token() == Token.WITH) { + SQLStatement stmt = parseSelect(); + statementList.add(stmt); + return true; + } + + return false; + } + public SQLStatement parseInsert() { SQLServerInsertStatement insertStatement = new SQLServerInsertStatement(); @@ -100,4 +116,34 @@ public class SQLServerStatementParser extends SQLStatementParser { insertStatement.setQuery(queryExpr.getSubQuery()); } } + + protected SQLServerUpdateStatement createUpdateStatement() { + return new SQLServerUpdateStatement(); + } + + public SQLUpdateStatement parseUpdateStatement() { + SQLServerUpdateStatement udpateStatement = createUpdateStatement(); + + if (lexer.token() == Token.UPDATE) { + lexer.nextToken(); + + SQLTableSource tableSource = this.exprParser.createSelectParser().parseTableSource(); + udpateStatement.setTableSource(tableSource); + } + + parseUpdateSet(udpateStatement); + + if (lexer.token() == Token.FROM) { + lexer.nextToken(); + SQLTableSource from = this.exprParser.createSelectParser().parseTableSource(); + udpateStatement.setFrom(from); + } + + if (lexer.token() == (Token.WHERE)) { + lexer.nextToken(); + udpateStatement.setWhere(this.exprParser.expr()); + } + + return udpateStatement; + } } diff --git a/src/main/java/com/alibaba/druid/sql/dialect/sqlserver/visitor/SQLServerASTVisitor.java b/src/main/java/com/alibaba/druid/sql/dialect/sqlserver/visitor/SQLServerASTVisitor.java index 1f07cb136f..d61534be7c 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/sqlserver/visitor/SQLServerASTVisitor.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/sqlserver/visitor/SQLServerASTVisitor.java @@ -19,6 +19,7 @@ import com.alibaba.druid.sql.dialect.sqlserver.ast.SQLServerSelectQueryBlock; import com.alibaba.druid.sql.dialect.sqlserver.ast.Top; import com.alibaba.druid.sql.dialect.sqlserver.ast.expr.SQLServerObjectReferenceExpr; import com.alibaba.druid.sql.dialect.sqlserver.ast.stmt.SQLServerInsertStatement; +import com.alibaba.druid.sql.dialect.sqlserver.ast.stmt.SQLServerUpdateStatement; import com.alibaba.druid.sql.visitor.SQLASTVisitor; public interface SQLServerASTVisitor extends SQLASTVisitor { @@ -38,4 +39,8 @@ public interface SQLServerASTVisitor extends SQLASTVisitor { boolean visit(SQLServerInsertStatement x); void endVisit(SQLServerInsertStatement x); + + boolean visit(SQLServerUpdateStatement x); + + void endVisit(SQLServerUpdateStatement x); } diff --git a/src/main/java/com/alibaba/druid/sql/dialect/sqlserver/visitor/SQLServerASTVisitorAdapter.java b/src/main/java/com/alibaba/druid/sql/dialect/sqlserver/visitor/SQLServerASTVisitorAdapter.java index 699a8abbb6..f26fe7b0be 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/sqlserver/visitor/SQLServerASTVisitorAdapter.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/sqlserver/visitor/SQLServerASTVisitorAdapter.java @@ -19,6 +19,7 @@ import com.alibaba.druid.sql.dialect.sqlserver.ast.SQLServerSelectQueryBlock; import com.alibaba.druid.sql.dialect.sqlserver.ast.Top; import com.alibaba.druid.sql.dialect.sqlserver.ast.expr.SQLServerObjectReferenceExpr; import com.alibaba.druid.sql.dialect.sqlserver.ast.stmt.SQLServerInsertStatement; +import com.alibaba.druid.sql.dialect.sqlserver.ast.stmt.SQLServerUpdateStatement; import com.alibaba.druid.sql.visitor.SQLASTVisitorAdapter; public class SQLServerASTVisitorAdapter extends SQLASTVisitorAdapter implements SQLServerASTVisitor { @@ -63,4 +64,14 @@ public class SQLServerASTVisitorAdapter extends SQLASTVisitorAdapter implements } + @Override + public boolean visit(SQLServerUpdateStatement x) { + return true; + } + + @Override + public void endVisit(SQLServerUpdateStatement x) { + + } + } diff --git a/src/main/java/com/alibaba/druid/sql/dialect/sqlserver/visitor/SQLServerOutputVisitor.java b/src/main/java/com/alibaba/druid/sql/dialect/sqlserver/visitor/SQLServerOutputVisitor.java index 5f6bf013ad..a0169e8320 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/sqlserver/visitor/SQLServerOutputVisitor.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/sqlserver/visitor/SQLServerOutputVisitor.java @@ -20,6 +20,7 @@ import com.alibaba.druid.sql.dialect.sqlserver.ast.SQLServerSelectQueryBlock; import com.alibaba.druid.sql.dialect.sqlserver.ast.Top; import com.alibaba.druid.sql.dialect.sqlserver.ast.expr.SQLServerObjectReferenceExpr; import com.alibaba.druid.sql.dialect.sqlserver.ast.stmt.SQLServerInsertStatement; +import com.alibaba.druid.sql.dialect.sqlserver.ast.stmt.SQLServerUpdateStatement; import com.alibaba.druid.sql.visitor.SQLASTOutputVisitor; public class SQLServerOutputVisitor extends SQLASTOutputVisitor implements SQLServerASTVisitor { @@ -144,4 +145,40 @@ public class SQLServerOutputVisitor extends SQLASTOutputVisitor implements SQLSe } + @Override + public boolean visit(SQLServerUpdateStatement x) { + print("UPDATE "); + + x.getTableSource().accept(this); + + println(); + print("SET "); + for (int i = 0, size = x.getItems().size(); i < size; ++i) { + if (i != 0) { + print(", "); + } + x.getItems().get(i).accept(this); + } + + if (x.getFrom() != null) { + println(); + print("FROM "); + x.getFrom().setParent(x); + x.getFrom().accept(this); + } + + if (x.getWhere() != null) { + println(); + print("WHERE "); + x.getWhere().setParent(x); + x.getWhere().accept(this); + } + + return false; + } + + @Override + public void endVisit(SQLServerUpdateStatement x) { + + } } diff --git a/src/main/java/com/alibaba/druid/sql/dialect/sqlserver/visitor/SQLServerSchemaStatVisitor.java b/src/main/java/com/alibaba/druid/sql/dialect/sqlserver/visitor/SQLServerSchemaStatVisitor.java index a56c5c5ecb..93069d1f32 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/sqlserver/visitor/SQLServerSchemaStatVisitor.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/sqlserver/visitor/SQLServerSchemaStatVisitor.java @@ -15,13 +15,17 @@ */ package com.alibaba.druid.sql.dialect.sqlserver.visitor; +import java.util.Map; + import com.alibaba.druid.sql.ast.statement.SQLInsertStatement; import com.alibaba.druid.sql.ast.statement.SQLSelectQueryBlock; import com.alibaba.druid.sql.dialect.sqlserver.ast.SQLServerSelectQueryBlock; import com.alibaba.druid.sql.dialect.sqlserver.ast.Top; import com.alibaba.druid.sql.dialect.sqlserver.ast.expr.SQLServerObjectReferenceExpr; import com.alibaba.druid.sql.dialect.sqlserver.ast.stmt.SQLServerInsertStatement; +import com.alibaba.druid.sql.dialect.sqlserver.ast.stmt.SQLServerUpdateStatement; import com.alibaba.druid.sql.visitor.SchemaStatVisitor; +import com.alibaba.druid.stat.TableStat; import com.alibaba.druid.util.JdbcUtils; @@ -73,5 +77,30 @@ public class SQLServerSchemaStatVisitor extends SchemaStatVisitor implements SQL this.endVisit((SQLInsertStatement) x); } + @Override + public boolean visit(SQLServerUpdateStatement x) { + setAliasMap(); + + String ident = x.getTableName().toString(); + setCurrentTable(ident); + + TableStat stat = getTableStat(ident); + stat.incrementUpdateCount(); + + Map aliasMap = getAliasMap(); + aliasMap.put(ident, ident); + + accept(x.getItems()); + accept(x.getFrom()); + accept(x.getWhere()); + + return false; + } + + @Override + public void endVisit(SQLServerUpdateStatement x) { + + } + } 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 4837ed096d..779e9888ff 100644 --- a/src/main/java/com/alibaba/druid/sql/parser/SQLStatementParser.java +++ b/src/main/java/com/alibaba/druid/sql/parser/SQLStatementParser.java @@ -21,6 +21,7 @@ import java.util.List; import com.alibaba.druid.sql.ast.SQLExpr; import com.alibaba.druid.sql.ast.SQLName; import com.alibaba.druid.sql.ast.SQLStatement; +import com.alibaba.druid.sql.ast.expr.SQLListExpr; import com.alibaba.druid.sql.ast.expr.SQLQueryExpr; import com.alibaba.druid.sql.ast.statement.SQLAssignItem; import com.alibaba.druid.sql.ast.statement.SQLCallStatement; @@ -38,6 +39,7 @@ import com.alibaba.druid.sql.ast.statement.SQLInsertStatement; import com.alibaba.druid.sql.ast.statement.SQLReleaseSavePointStatement; import com.alibaba.druid.sql.ast.statement.SQLRollbackStatement; import com.alibaba.druid.sql.ast.statement.SQLSavePointStatement; +import com.alibaba.druid.sql.ast.statement.SQLSelect; import com.alibaba.druid.sql.ast.statement.SQLSelectStatement; import com.alibaba.druid.sql.ast.statement.SQLSetStatement; import com.alibaba.druid.sql.ast.statement.SQLTableSource; @@ -80,7 +82,7 @@ public class SQLStatementParser extends SQLParser { continue; } - if (lexer.token() == (Token.SELECT)) { + if (lexer.token() == Token.SELECT) { statementList.add(parseSelect()); continue; } @@ -545,7 +547,9 @@ public class SQLStatementParser extends SQLParser { } public SQLSelectStatement parseSelect() { - return new SQLSelectStatement(createSQLSelectParser().select()); + SQLSelectParser selectParser = createSQLSelectParser(); + SQLSelect select = selectParser.select(); + return new SQLSelectStatement(select); } public SQLSelectParser createSQLSelectParser() { @@ -562,23 +566,7 @@ public class SQLStatementParser extends SQLParser { udpateStatement.setTableSource(tableSource); } - accept(Token.SET); - - for (;;) { - SQLUpdateSetItem item = new SQLUpdateSetItem(); - item.setColumn(this.exprParser.name()); - accept(Token.EQ); - item.setValue(this.exprParser.expr()); - - udpateStatement.getItems().add(item); - - if (lexer.token() == (Token.COMMA)) { - lexer.nextToken(); - continue; - } - - break; - } + parseUpdateSet(udpateStatement); if (lexer.token() == (Token.WHERE)) { lexer.nextToken(); @@ -587,6 +575,33 @@ public class SQLStatementParser extends SQLParser { return udpateStatement; } + + protected void parseUpdateSet(SQLUpdateStatement update) { + accept(Token.SET); + + for (;;) { + SQLUpdateSetItem item = new SQLUpdateSetItem(); + + if (lexer.token() == (Token.LPAREN)) { + lexer.nextToken(); + SQLListExpr list = new SQLListExpr(); + this.exprParser.exprList(list.getItems()); + accept(Token.RPAREN); + item.setColumn(list); + } else { + item.setColumn(this.exprParser.primary()); + } + accept(Token.EQ); + item.setValue(this.exprParser.expr()); + update.getItems().add(item); + + if (lexer.token() != Token.COMMA) { + break; + } + + lexer.nextToken(); + } + } protected SQLUpdateStatement createUpdateStatement() { return new SQLUpdateStatement(); diff --git a/src/main/java/com/alibaba/druid/wall/spi/MySqlWallVisitor.java b/src/main/java/com/alibaba/druid/wall/spi/MySqlWallVisitor.java index 2df999daac..8a50af9d04 100644 --- a/src/main/java/com/alibaba/druid/wall/spi/MySqlWallVisitor.java +++ b/src/main/java/com/alibaba/druid/wall/spi/MySqlWallVisitor.java @@ -46,6 +46,7 @@ import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlInsertStatement; import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlSelectGroupBy; import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlSelectQueryBlock; import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlSelectQueryBlock.Limit; +import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlUnionQuery; import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlUpdateStatement; import com.alibaba.druid.sql.dialect.mysql.visitor.MySqlASTVisitor; import com.alibaba.druid.sql.dialect.mysql.visitor.MySqlASTVisitorAdapter; @@ -222,6 +223,13 @@ public class MySqlWallVisitor extends MySqlASTVisitorAdapter implements WallVisi return true; } + + @Override + public boolean visit(MySqlUnionQuery x) { + WallVisitorUtils.checkUnion(this, x); + + return true; + } @Override public String toSQL(SQLObject obj) { diff --git a/src/test/java/com/alibaba/druid/bvt/filter/wall/MySqlWallTest1.java b/src/test/java/com/alibaba/druid/bvt/filter/wall/MySqlWallTest1.java new file mode 100644 index 0000000000..7854aeedf6 --- /dev/null +++ b/src/test/java/com/alibaba/druid/bvt/filter/wall/MySqlWallTest1.java @@ -0,0 +1,52 @@ +/* + * Copyright 1999-2011 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.filter.wall; + +import junit.framework.TestCase; + +import org.junit.Assert; + +import com.alibaba.druid.wall.WallUtils; + +/** + * SQLServerWallTest + * + * @author RaymondXiu + * @version 1.0, 2012-3-18 + * @see + */ +public class MySqlWallTest1 extends TestCase { + + /** + * @param name + */ + public MySqlWallTest1(String name){ + super(name); + } + + protected void setUp() throws Exception { + super.setUp(); + } + + protected void tearDown() throws Exception { + super.tearDown(); + } + + public void test_stuff() throws Exception { + Assert.assertTrue(WallUtils.isValidateMySql(// + "select count(*) from (select DATE_FORMAT(staydate,'%m月') as month,sum(a) as addnum,sum(q) as quitnum from (select staydate,1 as a,0 as q from add_person union all select quitdate,0 as a,1 as q from quit_person) t where (DATE_FORMAT(staydate,'%Y')= ? ) group by DATE_FORMAT(staydate,'%Y-%m'))")); + } +} diff --git a/src/test/java/com/alibaba/druid/bvt/sql/oracle/OracleCreateTableTest15.java b/src/test/java/com/alibaba/druid/bvt/sql/oracle/OracleCreateTableTest15.java new file mode 100644 index 0000000000..65b21b964d --- /dev/null +++ b/src/test/java/com/alibaba/druid/bvt/sql/oracle/OracleCreateTableTest15.java @@ -0,0 +1,79 @@ +/* + * Copyright 1999-2011 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.oracle; + +import java.util.List; + +import junit.framework.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.parser.OracleStatementParser; +import com.alibaba.druid.sql.dialect.oracle.visitor.OracleSchemaStatVisitor; +import com.alibaba.druid.stat.TableStat; +import com.alibaba.druid.util.JdbcConstants; + +public class OracleCreateTableTest15 extends OracleTest { + + public void test_types() throws Exception { + String sql = // + "create table T (" + // + "F1 TIMESTAMP," + // + "F2 TIMESTAMP(9), " + // + "F3 TIMESTAMP WITH TIME ZONE," + // + "F4 TIMESTAMP(9) WITH TIME ZONE, " + // + "F5 TIMESTAMP WITH TIME ZONE," + // + "F6 TIMESTAMP(9) WITH TIME ZONE" + // + ") "; + + OracleStatementParser parser = new OracleStatementParser(sql); + List statementList = parser.parseStatementList(); + SQLStatement statement = statementList.get(0); + print(statementList); + + Assert.assertEquals(1, statementList.size()); + + Assert.assertEquals("CREATE TABLE T (" + // + "\n\tF1 TIMESTAMP," + // + "\n\tF2 TIMESTAMP(9)," + // + "\n\tF3 TIMESTAMP WITH TIME ZONE," + // + "\n\tF4 TIMESTAMP(9) WITH TIME ZONE," + // + "\n\tF5 TIMESTAMP WITH TIME ZONE," + // + "\n\tF6 TIMESTAMP(9) WITH TIME ZONE" + // + "\n)", SQLUtils.toSQLString(statement, JdbcConstants.ORACLE)); + + OracleSchemaStatVisitor visitor = new OracleSchemaStatVisitor(); + statement.accept(visitor); + + System.out.println("Tables : " + visitor.getTables()); + System.out.println("fields : " + visitor.getColumns()); + System.out.println("coditions : " + visitor.getConditions()); + System.out.println("relationships : " + visitor.getRelationships()); + System.out.println("orderBy : " + visitor.getOrderByColumns()); + + Assert.assertEquals(1, visitor.getTables().size()); + + Assert.assertEquals(6, visitor.getColumns().size()); + + Assert.assertTrue(visitor.getColumns().contains(new TableStat.Column("T", "F1"))); + Assert.assertTrue(visitor.getColumns().contains(new TableStat.Column("T", "F2"))); + Assert.assertTrue(visitor.getColumns().contains(new TableStat.Column("T", "F3"))); + Assert.assertTrue(visitor.getColumns().contains(new TableStat.Column("T", "F4"))); + Assert.assertTrue(visitor.getColumns().contains(new TableStat.Column("T", "F5"))); + Assert.assertTrue(visitor.getColumns().contains(new TableStat.Column("T", "F6"))); + } +} diff --git a/src/test/java/com/alibaba/druid/bvt/sql/oracle/OracleCreateTableTest16.java b/src/test/java/com/alibaba/druid/bvt/sql/oracle/OracleCreateTableTest16.java new file mode 100644 index 0000000000..2ffd095467 --- /dev/null +++ b/src/test/java/com/alibaba/druid/bvt/sql/oracle/OracleCreateTableTest16.java @@ -0,0 +1,79 @@ +/* + * Copyright 1999-2011 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.oracle; + +import java.util.List; + +import junit.framework.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.parser.OracleStatementParser; +import com.alibaba.druid.sql.dialect.oracle.visitor.OracleSchemaStatVisitor; +import com.alibaba.druid.stat.TableStat; +import com.alibaba.druid.util.JdbcConstants; + +public class OracleCreateTableTest16 extends OracleTest { + + public void test_types() throws Exception { + String sql = // + "create table T (" + // + "F1 INTERVAL YEAR TO MONTH," + // + "F2 INTERVAL YEAR (3) TO MONTH," + // + "F3 INTERVAL DAY TO SECOND," + // + "F4 INTERVAL DAY (3) TO SECOND," + // + "F5 INTERVAL DAY TO SECOND (9)," + // + "F6 INTERVAL DAY (3) TO SECOND (9)" + // + ") "; + + OracleStatementParser parser = new OracleStatementParser(sql); + List statementList = parser.parseStatementList(); + SQLStatement statement = statementList.get(0); + print(statementList); + + Assert.assertEquals(1, statementList.size()); + + Assert.assertEquals("CREATE TABLE T (" + // + "\n\tF1 INTERVAL YEAR TO MONTH," + // + "\n\tF2 INTERVAL YEAR(3) TO MONTH," + // + "\n\tF3 INTERVAL DAY TO SECOND," + // + "\n\tF4 INTERVAL DAY(3) TO SECOND," + // + "\n\tF5 INTERVAL DAY TO SECOND(9)," + // + "\n\tF6 INTERVAL DAY(3) TO SECOND(9)" + // + "\n)", SQLUtils.toSQLString(statement, JdbcConstants.ORACLE)); + + OracleSchemaStatVisitor visitor = new OracleSchemaStatVisitor(); + statement.accept(visitor); + + System.out.println("Tables : " + visitor.getTables()); + System.out.println("fields : " + visitor.getColumns()); + System.out.println("coditions : " + visitor.getConditions()); + System.out.println("relationships : " + visitor.getRelationships()); + System.out.println("orderBy : " + visitor.getOrderByColumns()); + + Assert.assertEquals(1, visitor.getTables().size()); + + Assert.assertEquals(6, visitor.getColumns().size()); + + Assert.assertTrue(visitor.getColumns().contains(new TableStat.Column("T", "F1"))); + Assert.assertTrue(visitor.getColumns().contains(new TableStat.Column("T", "F2"))); + Assert.assertTrue(visitor.getColumns().contains(new TableStat.Column("T", "F3"))); + Assert.assertTrue(visitor.getColumns().contains(new TableStat.Column("T", "F4"))); + Assert.assertTrue(visitor.getColumns().contains(new TableStat.Column("T", "F5"))); + Assert.assertTrue(visitor.getColumns().contains(new TableStat.Column("T", "F6"))); + } +} diff --git a/src/test/java/com/alibaba/druid/bvt/sql/oracle/OracleDropSequenceTest.java b/src/test/java/com/alibaba/druid/bvt/sql/oracle/OracleDropSequenceTest.java new file mode 100644 index 0000000000..31f581c4ed --- /dev/null +++ b/src/test/java/com/alibaba/druid/bvt/sql/oracle/OracleDropSequenceTest.java @@ -0,0 +1,58 @@ +/* + * Copyright 1999-2011 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.oracle; + +import java.util.List; + +import junit.framework.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.parser.OracleStatementParser; +import com.alibaba.druid.sql.dialect.oracle.visitor.OracleSchemaStatVisitor; +import com.alibaba.druid.stat.TableStat; +import com.alibaba.druid.util.JdbcConstants; + +public class OracleDropSequenceTest extends OracleTest { + + public void test_types() throws Exception { + String sql = // + "DROP SEQUENCE oe.customers_seq"; + + OracleStatementParser parser = new OracleStatementParser(sql); + List statementList = parser.parseStatementList(); + SQLStatement statement = statementList.get(0); + print(statementList); + + Assert.assertEquals(1, statementList.size()); + + Assert.assertEquals("DROP SEQUENCE oe.customers_seq", SQLUtils.toSQLString(statement, JdbcConstants.ORACLE)); + + OracleSchemaStatVisitor visitor = new OracleSchemaStatVisitor(); + statement.accept(visitor); + + System.out.println("Tables : " + visitor.getTables()); + System.out.println("fields : " + visitor.getColumns()); + System.out.println("coditions : " + visitor.getConditions()); + System.out.println("relationships : " + visitor.getRelationships()); + System.out.println("orderBy : " + visitor.getOrderByColumns()); + + Assert.assertEquals(0, visitor.getTables().size()); + + Assert.assertEquals(0, visitor.getColumns().size()); + } +} diff --git a/src/test/java/com/alibaba/druid/bvt/sql/sqlserver/SQLServerSelectTest6.java b/src/test/java/com/alibaba/druid/bvt/sql/sqlserver/SQLServerSelectTest6.java new file mode 100644 index 0000000000..270091be86 --- /dev/null +++ b/src/test/java/com/alibaba/druid/bvt/sql/sqlserver/SQLServerSelectTest6.java @@ -0,0 +1,62 @@ +/* + * Copyright 1999-2011 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.sqlserver; + +import junit.framework.TestCase; + +import org.junit.Assert; + +import com.alibaba.druid.sql.ast.SQLStatement; +import com.alibaba.druid.sql.dialect.sqlserver.parser.SQLServerStatementParser; +import com.alibaba.druid.sql.test.TestUtils; + +public class SQLServerSelectTest6 extends TestCase { + + public void test_isEmpty() throws Exception { + String sql = "WITH DirReps(ManagerID, DirectReports) AS " + // + "(" + // + " SELECT ManagerID, COUNT(*) " + // + " FROM HumanResources.Employee AS e" + // + " WHERE ManagerID IS NOT NULL" + // + " GROUP BY ManagerID" + // + ")" + // + "SELECT ManagerID, DirectReports " + // + "FROM DirReps " + // + "ORDER BY ManagerID;"; + + String expect = "WITH" + + "\n\tDirReps (ManagerID, DirectReports)" + + "\n\tAS" + + "\n\t(" + + "\n\t\tSELECT ManagerID, COUNT(*)" + + "\n\t\tFROM HumanResources.Employee e" + + "\n\t\tWHERE ManagerID IS NOT NULL" + + "\n\t\tGROUP BY ManagerID" + + "\n\t)" + + "\nSELECT ManagerID, DirectReports" + + "\nFROM DirReps" + + "\nORDER BY ManagerID"; + + SQLServerStatementParser parser = new SQLServerStatementParser(sql); + SQLStatement stmt = parser.parseStatementList().get(0); + + String text = TestUtils.outputSqlServer(stmt); + + Assert.assertEquals(expect, text); + + System.out.println(text); + } +} diff --git a/src/test/java/com/alibaba/druid/bvt/sql/sqlserver/SQLServerSelectTest7.java b/src/test/java/com/alibaba/druid/bvt/sql/sqlserver/SQLServerSelectTest7.java new file mode 100644 index 0000000000..bd30f98742 --- /dev/null +++ b/src/test/java/com/alibaba/druid/bvt/sql/sqlserver/SQLServerSelectTest7.java @@ -0,0 +1,109 @@ +/* + * Copyright 1999-2011 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.sqlserver; + +import junit.framework.TestCase; + +import org.junit.Assert; + +import com.alibaba.druid.sql.ast.SQLStatement; +import com.alibaba.druid.sql.dialect.sqlserver.parser.SQLServerStatementParser; +import com.alibaba.druid.sql.test.TestUtils; + +public class SQLServerSelectTest7 extends TestCase { + + public void test_isEmpty() throws Exception { + String sql = "with menu_view as(" + + "\n select t.*,1 level from sec_portal_menu t where t.parent_id = ?" + + "\n union all" + + "\n select t.*,level + 1 from sec_portal_menu t , menu_view x where t.parent_id = x.menu_id" + + "\n )" + + "\n select t.menu_id \"id\"," + + "\n t.menu_name \"name\"," + + "\n t.parent_id \"pId\"," + + "\n case t.level when 1 then 'true' else 'false' end \"open\"," + + "\n t.link_type \"linkType\"" + + "\n from menu_view t" + + "\n where 1=1" + + "\n and t.deleted = 0" + + "\n --菜单权限控制" + + "\n AND t.link_type in ('simple','link')" + + "\n AND (" + + "\n EXISTS (" + + "\n select p.entity_code from sec_role_auth p where p.entity_code = t.menu_id" + + "\n and p.entity_type = 'menu'" + + "\n and p.role_id in (" + + "\n select r.role_code from sec_role_member rm ,sec_role r where rm.entity_type = 'user'" + + "\n and entity_code = ? --用户ID" + + "\n and r.role_id = rm.role_id" + + "\n and r.enabled = 1" + + "\n and r.deleted = 0" + + "\n )" + + "\n )" + + "\n or '1'= ? --超级管理员账户id" + + "\n or t.need_control = 0" + + "\n )" + + "\n AND (" + + "\n t.enabled = 1 or '1'= ? --超级管理员账户id" + + "\n or t.need_control = 0" + + "\n )" + + "\n order by t.sort_order"; + + String expect = "WITH" + + "\n\tmenu_view" + + "\n\tAS" + + "\n\t(" + + "\n\t\tSELECT t.*, 1 AS level" + + "\n\t\tFROM sec_portal_menu t" + + "\n\t\tWHERE t.parent_id = ?" + + "\n\t\tUNION ALL" + + "\n\t\tSELECT t.*, level + 1" + + "\n\t\tFROM sec_portal_menu t, menu_view x" + + "\n\t\tWHERE t.parent_id = x.menu_id" + + "\n\t)" + + "\nSELECT t.menu_id AS \"id\", t.menu_name AS \"name\", t.parent_id AS \"pId\", CASE t.level WHEN 1 THEN 'true' ELSE 'false' END AS \"open\", t.link_type AS \"linkType\"" + + "\nFROM menu_view t" + + "\nWHERE 1 = 1" + + "\n\tAND t.deleted = 0" + + "\n\tAND t.link_type IN ('simple', 'link')" + + "\n\tAND (EXISTS (SELECT p.entity_code" + + "\n\t\t\tFROM sec_role_auth p" + + "\n\t\t\tWHERE p.entity_code = t.menu_id" + + "\n\t\t\t\tAND p.entity_type = 'menu'" + + "\n\t\t\t\tAND p.role_id IN (SELECT r.role_code" + + "\n\t\t\t\t\tFROM sec_role_member rm, sec_role r" + + "\n\t\t\t\t\tWHERE rm.entity_type = 'user'" + + "\n\t\t\t\t\t\tAND entity_code = ?" + + "\n\t\t\t\t\t\tAND r.role_id = rm.role_id" + + "\n\t\t\t\t\t\tAND r.enabled = 1" + + "\n\t\t\t\t\t\tAND r.deleted = 0))" + + "\n\t\tOR '1' = ?" + + "\n\t\tOR t.need_control = 0)" + + "\n\tAND (t.enabled = 1" + + "\n\t\tOR '1' = ?" + + "\n\t\tOR t.need_control = 0)" + + "\nORDER BY t.sort_order"; + + SQLServerStatementParser parser = new SQLServerStatementParser(sql); + SQLStatement stmt = parser.parseStatementList().get(0); + + String text = TestUtils.outputSqlServer(stmt); + + Assert.assertEquals(expect, text); + + System.out.println(text); + } +} diff --git a/src/test/java/com/alibaba/druid/bvt/sql/sqlserver/SQLServerUpdateTest.java b/src/test/java/com/alibaba/druid/bvt/sql/sqlserver/SQLServerUpdateTest.java new file mode 100644 index 0000000000..2d72014b41 --- /dev/null +++ b/src/test/java/com/alibaba/druid/bvt/sql/sqlserver/SQLServerUpdateTest.java @@ -0,0 +1,62 @@ +/* + * Copyright 1999-2011 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.sqlserver; + +import junit.framework.TestCase; + +import org.junit.Assert; + +import com.alibaba.druid.sql.ast.SQLStatement; +import com.alibaba.druid.sql.dialect.sqlserver.parser.SQLServerStatementParser; +import com.alibaba.druid.sql.test.TestUtils; + +public class SQLServerUpdateTest extends TestCase { + + public void test_isEmpty() throws Exception { + String sql = "update reg_student_charge_item " + // + "set FAmountReceived = b.amount " + // + "from reg_student_charge_item a" + // + " ,(" + // + " select a.FId, " + // + " case when sum(b.FChargeAmount) is null then 0 " + // + " else sum(b.FChargeAmount)" + // + " end as amount " + // + " from reg_student_charge_item a " + // + " left join reg_student_charge_daybook b on a.FId = b.FChargeItemId" + // + " where a.FId=? group by a.FId" + // + " ) b " + // + "where a.FId = b.FId and a.FId = ?"; + + String expect = "UPDATE reg_student_charge_item" + + "\nSET FAmountReceived = b.amount" + + "\nFROM reg_student_charge_item a, (SELECT a.FId, CASE WHEN SUM(b.FChargeAmount) IS NULL THEN 0 ELSE SUM(b.FChargeAmount) END AS amount" + + "\n\t\tFROM reg_student_charge_item a" + + "\n\t\t\tLEFT JOIN reg_student_charge_daybook b ON a.FId = b.FChargeItemId" + + "\n\t\tWHERE a.FId = ? GROUP BY a.FId" + + "\n\t\t) b" + + "\nWHERE a.FId = b.FId" + + "\nAND a.FId = ?"; + + SQLServerStatementParser parser = new SQLServerStatementParser(sql); + SQLStatement stmt = parser.parseStatementList().get(0); + + String text = TestUtils.outputSqlServer(stmt); + + Assert.assertEquals(expect, text); + + System.out.println(text); + } +}