diff --git a/core/src/main/java/com/alibaba/druid/sql/ast/expr/SQLListExpr.java b/core/src/main/java/com/alibaba/druid/sql/ast/expr/SQLListExpr.java index 5f9e76a4d7..8a75bc4a70 100644 --- a/core/src/main/java/com/alibaba/druid/sql/ast/expr/SQLListExpr.java +++ b/core/src/main/java/com/alibaba/druid/sql/ast/expr/SQLListExpr.java @@ -98,6 +98,9 @@ public boolean equals(Object obj) { public SQLListExpr clone() { SQLListExpr x = new SQLListExpr(); + if (isParenthesized()) { + x.setParenthesized(true); + } for (SQLExpr item : items) { SQLExpr item2 = item.clone(); item2.setParent(x); diff --git a/core/src/main/java/com/alibaba/druid/sql/dialect/hive/parser/HiveCreateTableParser.java b/core/src/main/java/com/alibaba/druid/sql/dialect/hive/parser/HiveCreateTableParser.java index fce4e804b0..29e99a0dc5 100644 --- a/core/src/main/java/com/alibaba/druid/sql/dialect/hive/parser/HiveCreateTableParser.java +++ b/core/src/main/java/com/alibaba/druid/sql/dialect/hive/parser/HiveCreateTableParser.java @@ -229,6 +229,7 @@ protected void parseCreateTableRest(SQLCreateTableStatement createTable) { for (; ; ) { if (lexer.token() == Token.LPAREN) { SQLListExpr list = new SQLListExpr(); + list.setParenthesized(true); lexer.nextToken(); this.exprParser.exprList(list.getItems(), list); accept(Token.RPAREN); diff --git a/core/src/main/java/com/alibaba/druid/sql/dialect/mysql/parser/MySqlCreateTableParser.java b/core/src/main/java/com/alibaba/druid/sql/dialect/mysql/parser/MySqlCreateTableParser.java index 83f4892a08..5d915c8a40 100644 --- a/core/src/main/java/com/alibaba/druid/sql/dialect/mysql/parser/MySqlCreateTableParser.java +++ b/core/src/main/java/com/alibaba/druid/sql/dialect/mysql/parser/MySqlCreateTableParser.java @@ -726,6 +726,7 @@ protected void parseOptions(MySqlCreateTableStatement stmt) { accept(Token.LPAREN); SQLListExpr list = new SQLListExpr(); + list.setParenthesized(true); this.exprParser.exprList(list.getItems(), list); stmt.addOption("UNION", list); accept(Token.RPAREN); diff --git a/core/src/main/java/com/alibaba/druid/sql/dialect/mysql/parser/MySqlExprParser.java b/core/src/main/java/com/alibaba/druid/sql/dialect/mysql/parser/MySqlExprParser.java index 68c4cced48..f52051cf08 100644 --- a/core/src/main/java/com/alibaba/druid/sql/dialect/mysql/parser/MySqlExprParser.java +++ b/core/src/main/java/com/alibaba/druid/sql/dialect/mysql/parser/MySqlExprParser.java @@ -1260,7 +1260,9 @@ public SQLExpr primary() { if (lexer.token() != Token.LPAREN) { SQLExpr expr = primary(); SQLValuesQuery values = new SQLValuesQuery(); - values.addValue(new SQLListExpr(expr)); + SQLListExpr sqlListExpr = new SQLListExpr(expr); + sqlListExpr.setParenthesized(true); + values.addValue(sqlListExpr); return new SQLQueryExpr(new SQLSelect(values)); } return this.methodRest(new SQLIdentifierExpr("VALUES"), true); @@ -2542,6 +2544,7 @@ public boolean parseTableOptions(List assignItems, SQLDDLStatemen accept(Token.LPAREN); SQLListExpr list = new SQLListExpr(); + list.setParenthesized(true); exprList(list.getItems(), list); accept(Token.RPAREN); assignItem = new SQLAssignItem(new SQLIdentifierExpr("UNION"), list); diff --git a/core/src/main/java/com/alibaba/druid/sql/dialect/odps/parser/OdpsExprParser.java b/core/src/main/java/com/alibaba/druid/sql/dialect/odps/parser/OdpsExprParser.java index 606e3b5463..8ba3091c85 100644 --- a/core/src/main/java/com/alibaba/druid/sql/dialect/odps/parser/OdpsExprParser.java +++ b/core/src/main/java/com/alibaba/druid/sql/dialect/odps/parser/OdpsExprParser.java @@ -239,6 +239,7 @@ protected void parseAssignItemNcToBeExecuted() { protected boolean parseAssignItemTblProperties(SQLAssignItem item) { if (lexer.token() == Token.LPAREN) { SQLListExpr list = new SQLListExpr(); + list.setParenthesized(true); this.exprList(list.getItems(), list); item.setTarget(new SQLIdentifierExpr("tblproperties")); item.setValue(list); diff --git a/core/src/main/java/com/alibaba/druid/sql/dialect/postgresql/parser/PGExprParser.java b/core/src/main/java/com/alibaba/druid/sql/dialect/postgresql/parser/PGExprParser.java index 529b8583a8..beed6eaa84 100644 --- a/core/src/main/java/com/alibaba/druid/sql/dialect/postgresql/parser/PGExprParser.java +++ b/core/src/main/java/com/alibaba/druid/sql/dialect/postgresql/parser/PGExprParser.java @@ -282,6 +282,7 @@ public SQLExpr primary() { for (; ; ) { accept(Token.LPAREN); SQLListExpr listExpr = new SQLListExpr(); + listExpr.setParenthesized(true); exprList(listExpr.getItems(), listExpr); accept(Token.RPAREN); diff --git a/core/src/main/java/com/alibaba/druid/sql/dialect/postgresql/parser/PGSQLStatementParser.java b/core/src/main/java/com/alibaba/druid/sql/dialect/postgresql/parser/PGSQLStatementParser.java index e88cda94f1..5ff9b71f28 100644 --- a/core/src/main/java/com/alibaba/druid/sql/dialect/postgresql/parser/PGSQLStatementParser.java +++ b/core/src/main/java/com/alibaba/druid/sql/dialect/postgresql/parser/PGSQLStatementParser.java @@ -218,6 +218,7 @@ public PGInsertStatement parseInsert() { if (lexer.token() == Token.COMMA) { lexer.nextToken(); SQLListExpr list = new SQLListExpr(); + list.setParenthesized(true); list.addItem(returning); this.exprParser.exprList(list.getItems(), list); diff --git a/core/src/main/java/com/alibaba/druid/sql/parser/SQLExprParser.java b/core/src/main/java/com/alibaba/druid/sql/parser/SQLExprParser.java index 71836576bb..56b6fb2406 100644 --- a/core/src/main/java/com/alibaba/druid/sql/parser/SQLExprParser.java +++ b/core/src/main/java/com/alibaba/druid/sql/parser/SQLExprParser.java @@ -1602,6 +1602,7 @@ public SQLExpr primaryRest(SQLExpr expr) { } SQLListExpr listExpr = new SQLListExpr(); + listExpr.setParenthesized(true); this.exprList(listExpr.getItems(), listExpr); item = listExpr; @@ -3054,6 +3055,7 @@ public SQLUpdateSetItem parseUpdateSetItem() { if (lexer.token == (Token.LPAREN)) { lexer.nextToken(); SQLListExpr list = new SQLListExpr(); + list.setParenthesized(true); this.exprList(list.getItems(), list); accept(Token.RPAREN); item.setColumn(list); diff --git a/core/src/main/java/com/alibaba/druid/sql/parser/SQLSelectParser.java b/core/src/main/java/com/alibaba/druid/sql/parser/SQLSelectParser.java index a426de86f8..bfe2f936fd 100644 --- a/core/src/main/java/com/alibaba/druid/sql/parser/SQLSelectParser.java +++ b/core/src/main/java/com/alibaba/druid/sql/parser/SQLSelectParser.java @@ -554,6 +554,7 @@ protected SQLSelectQuery valuesQuery(boolean acceptUnion) { if (lexer.token == Token.LPAREN) { lexer.nextToken(); SQLListExpr listExpr = new SQLListExpr(); + listExpr.setParenthesized(true); this.exprParser.exprList(listExpr.getItems(), listExpr); accept(Token.RPAREN); valuesQuery.addValue(listExpr); @@ -1054,7 +1055,9 @@ protected SQLExpr parseGroupByItem() { if (lexer.token == Token.RPAREN) { lexer.nextToken(); - return new SQLListExpr(); + SQLListExpr listExpr = new SQLListExpr(); + listExpr.setParenthesized(true); + return listExpr; } lexer.reset(mark); @@ -1077,6 +1080,7 @@ protected SQLExpr parseGroupByItem() { if (lexer.token == Token.LPAREN) { accept(Token.LPAREN); SQLListExpr list = new SQLListExpr(); + list.setParenthesized(true); if (lexer.token == Token.COMMA) { lexer.nextToken(); } @@ -1284,6 +1288,7 @@ public SQLTableSource parseTableSource(boolean forFrom) { for (; ; ) { accept(Token.LPAREN); SQLListExpr listExpr = new SQLListExpr(); + listExpr.setParenthesized(true); this.exprParser.exprList(listExpr.getItems(), listExpr); accept(Token.RPAREN); @@ -2298,13 +2303,14 @@ public SQLValuesTableSource parseValues() { if (lexer.token == Token.ROW) { lexer.nextToken(); } + + SQLListExpr listExpr = new SQLListExpr(); + listExpr.setParenthesized(true); if (lexer.token() == Token.LPAREN) { accept(Token.LPAREN); isSingleValue = false; } - SQLListExpr listExpr = new SQLListExpr(); - if (isSingleValue) { SQLExpr expr = expr(); expr.setParent(listExpr); diff --git a/core/src/main/java/com/alibaba/druid/sql/visitor/SQLASTOutputVisitor.java b/core/src/main/java/com/alibaba/druid/sql/visitor/SQLASTOutputVisitor.java index 992793b84a..79e14eaf1f 100644 --- a/core/src/main/java/com/alibaba/druid/sql/visitor/SQLASTOutputVisitor.java +++ b/core/src/main/java/com/alibaba/druid/sql/visitor/SQLASTOutputVisitor.java @@ -5053,9 +5053,13 @@ public boolean visit(SQLInSubQueryExpr x) { @Override public boolean visit(SQLListExpr x) { - print('('); + if (x.isParenthesized()) { + print('('); + } printAndAccept(x.getItems(), ", "); - print(')'); + if (x.isParenthesized()) { + print(')'); + } return false; } diff --git a/core/src/test/java/com/alibaba/druid/bvt/sql/oracle/select/OracleSelectTest110.java b/core/src/test/java/com/alibaba/druid/bvt/sql/oracle/select/OracleSelectTest110.java index f2b9993f21..44dd9ac294 100644 --- a/core/src/test/java/com/alibaba/druid/bvt/sql/oracle/select/OracleSelectTest110.java +++ b/core/src/test/java/com/alibaba/druid/bvt/sql/oracle/select/OracleSelectTest110.java @@ -72,7 +72,7 @@ public void test_0() throws Exception { + "\t, in_ProductNo, in_Order_Payment, in_OrderCnt, in_Commision, in_RebateFee\n" + "\t, in_ProdDiscount, in_CreditCardFee, in_ServiceFee, in_ActivityNo, in_ProductShelfNo\n" + "\t, IN_PayOrganID, IN_CorrelationID\n" - + "INTO (:b0, :b1, :b2:b3, :b4:b5, :b6:b7, :b8:b9, :b10:b11, :b12:b13, :b14:b15, :b16:b17, :b18:b19, :b20:b21, :b22:b23, :b24:b25, :b26:b27, :b28:b29, :b30:b31, :b32:b33, :b34:b35, :b36:b37, :b38:b39, :b40:b41, :b42:b43, :b44:b45, :b46:b47, :b48:b49, :b50:b51, :b52:b53, :b54:b55, :b56:b57, :b58:b59, :b60:b61, :b62:b63, :b64:b65, :b66:b67, :b68:b69, :b70:b71, :b72:b73, :b74:b75, :b76:b77, :b78:b79, :b80:b81, :b82:b83, :b84:b85, :b86:b87, :b88:b89, :b90:b91, :b92:b93, :b94:b95, :b96:b97, :b98:b99, :b100:b101, :b102:b103, :b104:b105)\n" + + "INTO :b0, :b1, :b2:b3, :b4:b5, :b6:b7, :b8:b9, :b10:b11, :b12:b13, :b14:b15, :b16:b17, :b18:b19, :b20:b21, :b22:b23, :b24:b25, :b26:b27, :b28:b29, :b30:b31, :b32:b33, :b34:b35, :b36:b37, :b38:b39, :b40:b41, :b42:b43, :b44:b45, :b46:b47, :b48:b49, :b50:b51, :b52:b53, :b54:b55, :b56:b57, :b58:b59, :b60:b61, :b62:b63, :b64:b65, :b66:b67, :b68:b69, :b70:b71, :b72:b73, :b74:b75, :b76:b77, :b78:b79, :b80:b81, :b82:b83, :b84:b85, :b86:b87, :b88:b89, :b90:b91, :b92:b93, :b94:b95, :b96:b97, :b98:b99, :b100:b101, :b102:b103, :b104:b105\n" + "FROM b2b_payment_ReconDetail\n" + "WHERE (Recon_seq_id = :b106\n" + "\tAND transaction_id = :b107)", text); } @@ -162,7 +162,7 @@ public void test_2() throws Exception { + "\t, ACCOUNT_ID, SUBTOTAL_DETAILBILL_ID, NVL(ACCT_HOME_COUNTY, -1)\n" + "\t, TO_CHAR(NVL(BILLCYCLE_INURE_DATE, TO_DATE(TO_CHAR(GEN_TIME, 'yyyymm'), 'yyyymm')), 'yyyymmdd')\n" + "\t, NVL(BILLCYCLE_MONTH, -1)\n" + "\t, NVL(Detailbill_Flag, 0)\n" - + "INTO (:b0, :b1, :b2, :b3, :b4, :b5, :b6, :b7, :b8, :b9, :b10, :b11, :b12, :b13, :b14, :b15, :b16, :b17, :b18, :b19, :b20:b21, :b22:b23, :b24:b25, :b26:b27, :b28:b29, :b30, :b31, :b32, :b33)\n" + + "INTO :b0, :b1, :b2, :b3, :b4, :b5, :b6, :b7, :b8, :b9, :b10, :b11, :b12, :b13, :b14, :b15, :b16, :b17, :b18, :b19, :b20:b21, :b22:b23, :b24:b25, :b26:b27, :b28:b29, :b30, :b31, :b32, :b33\n" + "FROM DebtBill_Item\n" + "WHERE ROWID = :b34", text); }