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 5c06df2125..7275067708 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 @@ -23,6 +23,7 @@ import com.alibaba.druid.sql.ast.SQLObject; import com.alibaba.druid.sql.ast.SQLSetQuantifier; import com.alibaba.druid.sql.ast.SQLStatement; import com.alibaba.druid.sql.ast.expr.SQLAllColumnExpr; +import com.alibaba.druid.sql.ast.expr.SQLCharExpr; import com.alibaba.druid.sql.ast.expr.SQLIdentifierExpr; import com.alibaba.druid.sql.ast.expr.SQLLiteralExpr; import com.alibaba.druid.sql.ast.expr.SQLMethodInvokeExpr; @@ -3417,4 +3418,14 @@ public class OracleOutputVisitor extends SQLASTOutputVisitor implements OracleAS return super.visit(x); } + + public boolean visit(SQLCharExpr x) { + if (x.getText() != null && x.getText().length() == 0) { + print("NULL"); + } else { + super.visit(x); + } + + return false; + } } 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 05cee8f275..5f6b831a2f 100644 --- a/src/main/java/com/alibaba/druid/sql/visitor/SQLASTOutputVisitor.java +++ b/src/main/java/com/alibaba/druid/sql/visitor/SQLASTOutputVisitor.java @@ -452,7 +452,7 @@ public class SQLASTOutputVisitor extends SQLASTVisitorAdapter implements Printab } public boolean visit(SQLCharExpr x) { - if ((x.getText() == null) || (x.getText().length() == 0)) { + if (x.getText() == null) { print("NULL"); } else { print("'"); @@ -541,7 +541,7 @@ public class SQLASTOutputVisitor extends SQLASTVisitorAdapter implements Printab visitAggreateRest(x); print(")"); - + if (x.getWithinGroup() != null) { print(" WITHIN GROUP ("); x.getWithinGroup().accept(this); @@ -577,7 +577,31 @@ public class SQLASTOutputVisitor extends SQLASTVisitorAdapter implements Printab public boolean visit(SQLNotExpr x) { print("NOT "); - x.getExpr().accept(this); + SQLExpr expr = x.getExpr(); + + boolean needQuote = false; + + if (expr instanceof SQLBinaryOpExpr) { + SQLBinaryOpExpr binaryOpExpr = (SQLBinaryOpExpr) expr; + switch (binaryOpExpr.getOperator()) { + case BooleanAnd: + case BooleanOr: + case BooleanXor: + needQuote = true; + break; + default: + break; + } + } + + if (needQuote) { + print('('); + } + expr.accept(this); + + if (needQuote) { + print(')'); + } return false; } @@ -699,7 +723,7 @@ public class SQLASTOutputVisitor extends SQLASTVisitorAdapter implements Printab } public boolean visit(SQLSelectItem x) { - if(x.isConnectByRoot()) { + if (x.isConnectByRoot()) { print("CONNECT_BY_ROOT "); } x.getExpr().accept(this); @@ -1150,12 +1174,12 @@ public class SQLASTOutputVisitor extends SQLASTVisitorAdapter implements Printab public boolean visit(SQLSetStatement x) { print("SET "); printAndAccept(x.getItems(), ", "); - + if (x.getHints() != null && x.getHints().size() > 0) { print(" "); printAndAccept(x.getHints(), " "); } - + return false; } @@ -1433,24 +1457,24 @@ public class SQLASTOutputVisitor extends SQLASTVisitorAdapter implements Printab x.getName().accept(this); return false; } - + @Override public boolean visit(SQLCreateViewStatement x) { print("CREATE "); - if(x.isOrReplace()) { + if (x.isOrReplace()) { print("OR REPLACE "); } print("VIEW "); x.getName().accept(this); - + if (x.getColumns().size() > 0) { print(" ("); printAndAccept(x.getColumns(), ", "); print(")"); } - + print(" AS "); - + x.getSubQuery().accept(this); return false; } @@ -1852,28 +1876,28 @@ public class SQLASTOutputVisitor extends SQLASTVisitorAdapter implements Printab return false; } - + @Override public boolean visit(SQLRevokeStatement x) { print("ROVOKE "); printAndAccept(x.getPrivileges(), ", "); - + if (x.getOn() != null) { print(" ON "); - + if (x.getObjectType() != null) { print(x.getObjectType().name()); print(' '); } - + x.getOn().accept(this); } - + if (x.getFrom() != null) { print(" FROM "); x.getFrom().accept(this); } - + return false; } @@ -2006,7 +2030,7 @@ public class SQLASTOutputVisitor extends SQLASTVisitorAdapter implements Printab x.getBody().accept(this); return false; } - + public boolean visit(SQLBooleanExpr x) { print(x.getValue() ? "true" : "false"); @@ -2036,11 +2060,11 @@ public class SQLASTOutputVisitor extends SQLASTVisitorAdapter implements Printab @Override public boolean visit(SQLTimestampExpr x) { print("TIMESTAMP "); - + if (x.isWithTimeZone()) { print(" WITH TIME ZONE "); } - + print('\''); print(x.getLiteral()); print('\''); diff --git a/src/test/java/com/alibaba/druid/bvt/sql/sqlserver/SQLServerSelectTest17.java b/src/test/java/com/alibaba/druid/bvt/sql/sqlserver/SQLServerSelectTest17.java new file mode 100644 index 0000000000..5165e2c1b2 --- /dev/null +++ b/src/test/java/com/alibaba/druid/bvt/sql/sqlserver/SQLServerSelectTest17.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.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 SQLServerSelectTest17 extends TestCase { + + public void test_simple() throws Exception { + String sql = "SELECT CIM_ASSET_TYPE.ID" + + "\nFROM CIM_ASSET_TYPE" + + "\nWHERE CIM_ASSET_TYPE.DEL_STATUS = '0'" + + "\nAND NOT (" + + "\nCIM_ASSET_TYPE.MODEL_TABLE IS NULL" + + "\nOR CIM_ASSET_TYPE.MODEL_TABLE = ''" + + ")"; // + + String expect = "SELECT CIM_ASSET_TYPE.ID" + + "\nFROM CIM_ASSET_TYPE" + + "\nWHERE CIM_ASSET_TYPE.DEL_STATUS = '0'" + + "\n\tAND NOT (CIM_ASSET_TYPE.MODEL_TABLE IS NULL" + + "\n\tOR CIM_ASSET_TYPE.MODEL_TABLE = '')"; + + SQLServerStatementParser parser = new SQLServerStatementParser(sql); + SQLStatement stmt = parser.parseStatementList().get(0); + + String text = TestUtils.outputSqlServer(stmt); + + Assert.assertEquals(expect, text); + + System.out.println(text); + } +}