diff --git a/pom.xml b/pom.xml
index f7fb32ded1..42227a9377 100644
--- a/pom.xml
+++ b/pom.xml
@@ -407,7 +407,7 @@
org.mybatis
mybatis-spring
- 1.1.1
+ 1.2.2
provided
true
@@ -446,7 +446,7 @@
mysql
mysql-connector-java
- 5.1.24
+ 5.1.35
provided
@@ -568,7 +568,7 @@
org.nutz
nutz
- 1.b.47
+ 1.b.52
test
diff --git a/src/main/java/com/alibaba/druid/sql/SQLUtils.java b/src/main/java/com/alibaba/druid/sql/SQLUtils.java
index d8ac7edfaa..68acc9f166 100644
--- a/src/main/java/com/alibaba/druid/sql/SQLUtils.java
+++ b/src/main/java/com/alibaba/druid/sql/SQLUtils.java
@@ -26,9 +26,11 @@ import com.alibaba.druid.sql.ast.expr.SQLBinaryOpExpr;
import com.alibaba.druid.sql.ast.expr.SQLBinaryOperator;
import com.alibaba.druid.sql.ast.statement.SQLDeleteStatement;
import com.alibaba.druid.sql.ast.statement.SQLSelectItem;
+import com.alibaba.druid.sql.ast.statement.SQLSelectOrderByItem;
import com.alibaba.druid.sql.ast.statement.SQLSelectQuery;
import com.alibaba.druid.sql.ast.statement.SQLSelectQueryBlock;
import com.alibaba.druid.sql.ast.statement.SQLSelectStatement;
+import com.alibaba.druid.sql.ast.statement.SQLUpdateSetItem;
import com.alibaba.druid.sql.ast.statement.SQLUpdateStatement;
import com.alibaba.druid.sql.dialect.db2.visitor.DB2OutputVisitor;
import com.alibaba.druid.sql.dialect.db2.visitor.DB2SchemaStatVisitor;
@@ -175,6 +177,39 @@ public class SQLUtils {
return expr;
}
+
+ public static SQLSelectOrderByItem toOrderByItem(String sql, String dbType) {
+ SQLExprParser parser = SQLParserUtils.createExprParser(sql, dbType);
+ SQLSelectOrderByItem orderByItem = parser.parseSelectOrderByItem();
+
+ if (parser.getLexer().token() != Token.EOF) {
+ throw new ParserException("illegal sql expr : " + sql);
+ }
+
+ return orderByItem;
+ }
+
+ public static SQLUpdateSetItem toUpdateSetItem(String sql, String dbType) {
+ SQLExprParser parser = SQLParserUtils.createExprParser(sql, dbType);
+ SQLUpdateSetItem updateSetItem = parser.parseUpdateSetItem();
+
+ if (parser.getLexer().token() != Token.EOF) {
+ throw new ParserException("illegal sql expr : " + sql);
+ }
+
+ return updateSetItem;
+ }
+
+ public static SQLSelectItem toSelectItem(String sql, String dbType) {
+ SQLExprParser parser = SQLParserUtils.createExprParser(sql, dbType);
+ SQLSelectItem selectItem = parser.parseSelectItem();
+
+ if (parser.getLexer().token() != Token.EOF) {
+ throw new ParserException("illegal sql expr : " + sql);
+ }
+
+ return selectItem;
+ }
public static List toStatementList(String sql, String dbType) {
SQLStatementParser parser = SQLParserUtils.createSQLStatementParser(sql, dbType);
@@ -406,7 +441,7 @@ public class SQLUtils {
SQLSelectQuery query = ((SQLSelectStatement) stmt).getSelect().getQuery();
if (query instanceof SQLSelectQueryBlock) {
SQLSelectQueryBlock queryBlock = (SQLSelectQueryBlock) query;
- SQLExpr newCondition = buildNewCondition(op, condition, left, queryBlock.getWhere());
+ SQLExpr newCondition = buildCondition(op, condition, left, queryBlock.getWhere());
queryBlock.setWhere(newCondition);
} else {
throw new IllegalArgumentException("add condition not support " + stmt.getClass().getName());
@@ -418,7 +453,7 @@ public class SQLUtils {
if (stmt instanceof SQLDeleteStatement) {
SQLDeleteStatement delete = (SQLDeleteStatement) stmt;
- SQLExpr newCondition = buildNewCondition(op, condition, left, delete.getWhere());
+ SQLExpr newCondition = buildCondition(op, condition, left, delete.getWhere());
delete.setWhere(newCondition);
return;
@@ -427,7 +462,7 @@ public class SQLUtils {
if (stmt instanceof SQLUpdateStatement) {
SQLUpdateStatement update = (SQLUpdateStatement) stmt;
- SQLExpr newCondition = buildNewCondition(op, condition, left, update.getWhere());
+ SQLExpr newCondition = buildCondition(op, condition, left, update.getWhere());
update.setWhere(newCondition);
return;
@@ -436,7 +471,7 @@ public class SQLUtils {
throw new IllegalArgumentException("add condition not support " + stmt.getClass().getName());
}
- protected static SQLExpr buildNewCondition(SQLBinaryOperator op, SQLExpr condition, boolean left, SQLExpr where) {
+ public static SQLExpr buildCondition(SQLBinaryOperator op, SQLExpr condition, boolean left, SQLExpr where) {
if (where == null) {
return condition;
}
diff --git a/src/main/java/com/alibaba/druid/sql/ast/SQLOrderBy.java b/src/main/java/com/alibaba/druid/sql/ast/SQLOrderBy.java
index d0720a961c..8200a7b842 100644
--- a/src/main/java/com/alibaba/druid/sql/ast/SQLOrderBy.java
+++ b/src/main/java/com/alibaba/druid/sql/ast/SQLOrderBy.java
@@ -31,8 +31,7 @@ public class SQLOrderBy extends SQLObjectImpl {
public SQLOrderBy(SQLExpr expr){
SQLSelectOrderByItem item = new SQLSelectOrderByItem(expr);
- item.setParent(this);
- this.items.add(item);
+ addItem(item);
}
public void addItem(SQLSelectOrderByItem item) {
@@ -71,5 +70,14 @@ public class SQLOrderBy extends SQLObjectImpl {
return items.equals(other.items);
}
+ public void addItem(SQLExpr expr, SQLOrderingSpecification type) {
+ SQLSelectOrderByItem item = createItem();
+ item.setExpr(expr);
+ item.setType(type);
+ addItem(item);
+ }
+ protected SQLSelectOrderByItem createItem() {
+ return new SQLSelectOrderByItem();
+ }
}
diff --git a/src/main/java/com/alibaba/druid/sql/ast/statement/SQLExprTableSource.java b/src/main/java/com/alibaba/druid/sql/ast/statement/SQLExprTableSource.java
index eb0cbb76ad..37fc8776f2 100644
--- a/src/main/java/com/alibaba/druid/sql/ast/statement/SQLExprTableSource.java
+++ b/src/main/java/com/alibaba/druid/sql/ast/statement/SQLExprTableSource.java
@@ -27,7 +27,12 @@ public class SQLExprTableSource extends SQLTableSourceImpl {
}
public SQLExprTableSource(SQLExpr expr){
+ this(expr, null);
+ }
+
+ public SQLExprTableSource(SQLExpr expr, String alias){
this.setExpr(expr);
+ this.setAlias(alias);
}
public SQLExpr getExpr() {
diff --git a/src/main/java/com/alibaba/druid/sql/ast/statement/SQLSelectQueryBlock.java b/src/main/java/com/alibaba/druid/sql/ast/statement/SQLSelectQueryBlock.java
index 79331a3e0e..7c2831b068 100644
--- a/src/main/java/com/alibaba/druid/sql/ast/statement/SQLSelectQueryBlock.java
+++ b/src/main/java/com/alibaba/druid/sql/ast/statement/SQLSelectQueryBlock.java
@@ -82,6 +82,11 @@ public class SQLSelectQueryBlock extends SQLObjectImpl implements SQLSelectQuery
public List getSelectList() {
return this.selectList;
}
+
+ public void addSelectItem(SQLSelectItem item) {
+ this.selectList.add(item);
+ item.setParent(this);
+ }
public SQLTableSource getFrom() {
return this.from;
diff --git a/src/main/java/com/alibaba/druid/sql/ast/statement/SQLUpdateStatement.java b/src/main/java/com/alibaba/druid/sql/ast/statement/SQLUpdateStatement.java
index 8abdcfc828..ff930a2893 100644
--- a/src/main/java/com/alibaba/druid/sql/ast/statement/SQLUpdateStatement.java
+++ b/src/main/java/com/alibaba/druid/sql/ast/statement/SQLUpdateStatement.java
@@ -75,6 +75,11 @@ public class SQLUpdateStatement extends SQLStatementImpl {
public List getItems() {
return items;
}
+
+ public void addItem(SQLUpdateSetItem item) {
+ this.items.add(item);
+ item.setParent(this);
+ }
@Override
public void output(StringBuffer buf) {
diff --git a/src/main/java/com/alibaba/druid/sql/builder/SQLBuilder.java b/src/main/java/com/alibaba/druid/sql/builder/SQLBuilder.java
new file mode 100644
index 0000000000..0f7cd19215
--- /dev/null
+++ b/src/main/java/com/alibaba/druid/sql/builder/SQLBuilder.java
@@ -0,0 +1,6 @@
+package com.alibaba.druid.sql.builder;
+
+
+public interface SQLBuilder {
+
+}
diff --git a/src/main/java/com/alibaba/druid/sql/builder/SQLBuilderFactory.java b/src/main/java/com/alibaba/druid/sql/builder/SQLBuilderFactory.java
new file mode 100644
index 0000000000..b49451d3e1
--- /dev/null
+++ b/src/main/java/com/alibaba/druid/sql/builder/SQLBuilderFactory.java
@@ -0,0 +1,39 @@
+package com.alibaba.druid.sql.builder;
+
+import com.alibaba.druid.sql.builder.impl.SQLDeleteBuilderImpl;
+import com.alibaba.druid.sql.builder.impl.SQLSelectBuilderImpl;
+import com.alibaba.druid.sql.builder.impl.SQLUpdateBuilderImpl;
+import com.alibaba.druid.sql.builder.impl.dialect.MySqlSelectBuilderImpl;
+import com.alibaba.druid.sql.builder.impl.dialect.PGSelectBuilderImpl;
+import com.alibaba.druid.util.JdbcConstants;
+
+
+public class SQLBuilderFactory {
+ public static SQLSelectBuilder createSelectSQLBuilder(String dbType) {
+ if (JdbcConstants.MYSQL.equals(dbType)) {
+ return new MySqlSelectBuilderImpl();
+ }
+
+ if (JdbcConstants.POSTGRESQL.equals(dbType)) {
+ return new PGSelectBuilderImpl();
+ }
+
+ if (JdbcConstants.SQL_SERVER.equals(dbType)) {
+ return new PGSelectBuilderImpl();
+ }
+
+ if (JdbcConstants.ORACLE.equals(dbType)) {
+ return new PGSelectBuilderImpl();
+ }
+
+ return new SQLSelectBuilderImpl(dbType);
+ }
+
+ public static SQLDeleteBuilder createDeleteBuilder(String dbType) {
+ return new SQLDeleteBuilderImpl(dbType);
+ }
+
+ public static SQLUpdateBuilder createUpdateBuilder(String dbType) {
+ return new SQLUpdateBuilderImpl(dbType);
+ }
+}
diff --git a/src/main/java/com/alibaba/druid/sql/builder/SQLDeleteBuilder.java b/src/main/java/com/alibaba/druid/sql/builder/SQLDeleteBuilder.java
new file mode 100644
index 0000000000..01fc38e6ea
--- /dev/null
+++ b/src/main/java/com/alibaba/druid/sql/builder/SQLDeleteBuilder.java
@@ -0,0 +1,18 @@
+package com.alibaba.druid.sql.builder;
+
+
+public interface SQLDeleteBuilder {
+ SQLDeleteBuilder from(String table);
+
+ SQLDeleteBuilder from(String table, String alias);
+
+ SQLDeleteBuilder limit(int rowCount);
+
+ SQLDeleteBuilder limit(int rowCount, int offset);
+
+ SQLDeleteBuilder where(String sql);
+
+ SQLDeleteBuilder whereAnd(String sql);
+
+ SQLDeleteBuilder whereOr(String sql);
+}
diff --git a/src/main/java/com/alibaba/druid/sql/builder/SQLSelectBuilder.java b/src/main/java/com/alibaba/druid/sql/builder/SQLSelectBuilder.java
new file mode 100644
index 0000000000..3c12527cda
--- /dev/null
+++ b/src/main/java/com/alibaba/druid/sql/builder/SQLSelectBuilder.java
@@ -0,0 +1,36 @@
+package com.alibaba.druid.sql.builder;
+
+import com.alibaba.druid.sql.ast.statement.SQLSelectStatement;
+
+public interface SQLSelectBuilder {
+
+ SQLSelectStatement getSQLSelectStatement();
+
+ SQLSelectBuilder select(String... column);
+
+ SQLSelectBuilder selectWithAlias(String column, String alias);
+
+ SQLSelectBuilder from(String table);
+
+ SQLSelectBuilder from(String table, String alias);
+
+ SQLSelectBuilder orderBy(String... columns);
+
+ SQLSelectBuilder groupBy(String expr);
+
+ SQLSelectBuilder having(String expr);
+
+ SQLSelectBuilder into(String expr);
+
+ SQLSelectBuilder limit(int rowCount);
+
+ SQLSelectBuilder limit(int rowCount, int offset);
+
+ SQLSelectBuilder where(String sql);
+
+ SQLSelectBuilder whereAnd(String sql);
+
+ SQLSelectBuilder whereOr(String sql);
+
+ String toString();
+}
diff --git a/src/main/java/com/alibaba/druid/sql/builder/SQLUpdateBuilder.java b/src/main/java/com/alibaba/druid/sql/builder/SQLUpdateBuilder.java
new file mode 100644
index 0000000000..6a2ad480a0
--- /dev/null
+++ b/src/main/java/com/alibaba/druid/sql/builder/SQLUpdateBuilder.java
@@ -0,0 +1,20 @@
+package com.alibaba.druid.sql.builder;
+
+
+public interface SQLUpdateBuilder {
+ SQLUpdateBuilder from(String table);
+
+ SQLUpdateBuilder from(String table, String alias);
+
+ SQLUpdateBuilder limit(int rowCount);
+
+ SQLUpdateBuilder limit(int rowCount, int offset);
+
+ SQLUpdateBuilder where(String sql);
+
+ SQLUpdateBuilder whereAnd(String sql);
+
+ SQLUpdateBuilder whereOr(String sql);
+
+ SQLUpdateBuilder set(String... items);
+}
diff --git a/src/main/java/com/alibaba/druid/sql/builder/UpdateBuilder.java b/src/main/java/com/alibaba/druid/sql/builder/UpdateBuilder.java
new file mode 100644
index 0000000000..9f73886360
--- /dev/null
+++ b/src/main/java/com/alibaba/druid/sql/builder/UpdateBuilder.java
@@ -0,0 +1,18 @@
+package com.alibaba.druid.sql.builder;
+
+
+public interface UpdateBuilder {
+ UpdateBuilder from(String table);
+
+ UpdateBuilder from(String table, String alias);
+
+ UpdateBuilder limit(int rowCount);
+
+ UpdateBuilder limit(int rowCount, int offset);
+
+ UpdateBuilder where(String sql);
+
+ UpdateBuilder whereAnd(String sql);
+
+ UpdateBuilder whereOr(String sql);
+}
diff --git a/src/main/java/com/alibaba/druid/sql/builder/impl/SQLBuilderImpl.java b/src/main/java/com/alibaba/druid/sql/builder/impl/SQLBuilderImpl.java
new file mode 100644
index 0000000000..4e98289d7d
--- /dev/null
+++ b/src/main/java/com/alibaba/druid/sql/builder/impl/SQLBuilderImpl.java
@@ -0,0 +1,8 @@
+package com.alibaba.druid.sql.builder.impl;
+
+import com.alibaba.druid.sql.builder.SQLBuilder;
+
+
+public class SQLBuilderImpl implements SQLBuilder {
+
+}
diff --git a/src/main/java/com/alibaba/druid/sql/builder/impl/SQLDeleteBuilderImpl.java b/src/main/java/com/alibaba/druid/sql/builder/impl/SQLDeleteBuilderImpl.java
new file mode 100644
index 0000000000..d15bceafc7
--- /dev/null
+++ b/src/main/java/com/alibaba/druid/sql/builder/impl/SQLDeleteBuilderImpl.java
@@ -0,0 +1,94 @@
+package com.alibaba.druid.sql.builder.impl;
+
+import com.alibaba.druid.sql.SQLUtils;
+import com.alibaba.druid.sql.ast.SQLExpr;
+import com.alibaba.druid.sql.ast.expr.SQLBinaryOperator;
+import com.alibaba.druid.sql.ast.expr.SQLIdentifierExpr;
+import com.alibaba.druid.sql.ast.statement.SQLDeleteStatement;
+import com.alibaba.druid.sql.ast.statement.SQLExprTableSource;
+import com.alibaba.druid.sql.builder.SQLDeleteBuilder;
+
+public class SQLDeleteBuilderImpl implements SQLDeleteBuilder {
+
+ private SQLDeleteStatement stmt;
+ private String dbType;
+
+ public SQLDeleteBuilderImpl(String dbType){
+ this.dbType = dbType;
+ }
+
+ public SQLDeleteBuilderImpl(SQLDeleteStatement stmt, String dbType){
+ this.stmt = stmt;
+ this.dbType = dbType;
+ }
+
+ @Override
+ public SQLDeleteBuilderImpl limit(int rowCount) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public SQLDeleteBuilderImpl limit(int rowCount, int offset) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public SQLDeleteBuilder from(String table) {
+ return from(table, null);
+ }
+
+ @Override
+ public SQLDeleteBuilder from(String table, String alias) {
+ SQLDeleteStatement delete = getSQLDeleteStatement();
+ SQLExprTableSource from = new SQLExprTableSource(new SQLIdentifierExpr(table), alias);
+ delete.setTableSource(from);
+ return this;
+ }
+
+ @Override
+ public SQLDeleteBuilder where(String expr) {
+ SQLDeleteStatement delete = getSQLDeleteStatement();
+
+ SQLExpr exprObj = SQLUtils.toSQLExpr(expr, dbType);
+ delete.setWhere(exprObj);
+
+ return this;
+ }
+
+ @Override
+ public SQLDeleteBuilder whereAnd(String expr) {
+ SQLDeleteStatement delete = getSQLDeleteStatement();
+
+ SQLExpr exprObj = SQLUtils.toSQLExpr(expr, dbType);
+ SQLExpr newCondition = SQLUtils.buildCondition(SQLBinaryOperator.BooleanAnd, exprObj, false, delete.getWhere());
+ delete.setWhere(newCondition);
+
+ return this;
+ }
+
+ @Override
+ public SQLDeleteBuilder whereOr(String expr) {
+ SQLDeleteStatement delete = getSQLDeleteStatement();
+
+ SQLExpr exprObj = SQLUtils.toSQLExpr(expr, dbType);
+ SQLExpr newCondition = SQLUtils.buildCondition(SQLBinaryOperator.BooleanOr, exprObj, false, delete.getWhere());
+ delete.setWhere(newCondition);
+
+ return this;
+ }
+
+ public SQLDeleteStatement getSQLDeleteStatement() {
+ if (stmt == null) {
+ stmt = createSQLDeleteStatement();
+ }
+ return stmt;
+ }
+
+ public SQLDeleteStatement createSQLDeleteStatement() {
+ return new SQLDeleteStatement();
+ }
+
+ public String toString() {
+ return SQLUtils.toSQLString(stmt, dbType);
+ }
+}
diff --git a/src/main/java/com/alibaba/druid/sql/builder/impl/SQLSelectBuilderImpl.java b/src/main/java/com/alibaba/druid/sql/builder/impl/SQLSelectBuilderImpl.java
new file mode 100644
index 0000000000..597d79ceb3
--- /dev/null
+++ b/src/main/java/com/alibaba/druid/sql/builder/impl/SQLSelectBuilderImpl.java
@@ -0,0 +1,217 @@
+package com.alibaba.druid.sql.builder.impl;
+
+import com.alibaba.druid.sql.SQLUtils;
+import com.alibaba.druid.sql.ast.SQLExpr;
+import com.alibaba.druid.sql.ast.SQLOrderBy;
+import com.alibaba.druid.sql.ast.expr.SQLBinaryOperator;
+import com.alibaba.druid.sql.ast.expr.SQLIdentifierExpr;
+import com.alibaba.druid.sql.ast.statement.SQLExprTableSource;
+import com.alibaba.druid.sql.ast.statement.SQLSelect;
+import com.alibaba.druid.sql.ast.statement.SQLSelectGroupByClause;
+import com.alibaba.druid.sql.ast.statement.SQLSelectItem;
+import com.alibaba.druid.sql.ast.statement.SQLSelectOrderByItem;
+import com.alibaba.druid.sql.ast.statement.SQLSelectQuery;
+import com.alibaba.druid.sql.ast.statement.SQLSelectQueryBlock;
+import com.alibaba.druid.sql.ast.statement.SQLSelectStatement;
+import com.alibaba.druid.sql.builder.SQLSelectBuilder;
+
+public class SQLSelectBuilderImpl implements SQLSelectBuilder {
+
+ private SQLSelectStatement stmt;
+ private String dbType;
+
+ public SQLSelectBuilderImpl(String dbType){
+ this(new SQLSelectStatement(), dbType);
+ }
+
+ public SQLSelectBuilderImpl(SQLSelectStatement stmt, String dbType){
+ this.stmt = stmt;
+ this.dbType = dbType;
+ }
+
+ public SQLSelect getSQLSelect() {
+ if (stmt.getSelect() == null) {
+ stmt.setSelect(createSelect());
+ }
+ return stmt.getSelect();
+ }
+
+ @Override
+ public SQLSelectStatement getSQLSelectStatement() {
+ return stmt;
+ }
+
+ public SQLSelectBuilderImpl select(String... columns) {
+ SQLSelectQueryBlock queryBlock = getQueryBlock();
+
+ for (String column : columns) {
+ SQLSelectItem selectItem = SQLUtils.toSelectItem(column, dbType);
+ queryBlock.addSelectItem(selectItem);
+ }
+
+ return this;
+ }
+
+ @Override
+ public SQLSelectBuilderImpl selectWithAlias(String column, String alias) {
+ SQLSelectQueryBlock queryBlock = getQueryBlock();
+
+ SQLExpr columnExpr = SQLUtils.toSQLExpr(column, dbType);
+ SQLSelectItem selectItem = new SQLSelectItem(columnExpr, alias);
+ queryBlock.addSelectItem(selectItem);
+
+ return this;
+ }
+
+ @Override
+ public SQLSelectBuilderImpl from(String table) {
+ return from(table, null);
+ }
+
+ @Override
+ public SQLSelectBuilderImpl from(String table, String alias) {
+ SQLSelectQueryBlock queryBlock = getQueryBlock();
+ SQLExprTableSource from = new SQLExprTableSource(new SQLIdentifierExpr(table), alias);
+ queryBlock.setFrom(from);
+
+ return this;
+ }
+
+ @Override
+ public SQLSelectBuilderImpl orderBy(String... columns) {
+ SQLSelect select = this.getSQLSelect();
+
+ SQLOrderBy orderBy = select.getOrderBy();
+ if (orderBy == null) {
+ orderBy = createOrderBy();
+ select.setOrderBy(orderBy);
+ }
+
+ for (String column : columns) {
+ SQLSelectOrderByItem orderByItem = SQLUtils.toOrderByItem(column, dbType);
+ orderBy.addItem(orderByItem);
+ }
+
+ return this;
+ }
+
+ @Override
+ public SQLSelectBuilderImpl groupBy(String expr) {
+ SQLSelectQueryBlock queryBlock = getQueryBlock();
+
+ SQLSelectGroupByClause groupBy = queryBlock.getGroupBy();
+ if (groupBy == null) {
+ groupBy = createGroupBy();
+ queryBlock.setGroupBy(groupBy);
+ }
+
+ SQLExpr exprObj = SQLUtils.toSQLExpr(expr, dbType);
+ groupBy.addItem(exprObj);
+
+ return this;
+ }
+
+ @Override
+ public SQLSelectBuilderImpl having(String expr) {
+ SQLSelectQueryBlock queryBlock = getQueryBlock();
+
+ SQLSelectGroupByClause groupBy = queryBlock.getGroupBy();
+ if (groupBy == null) {
+ groupBy = createGroupBy();
+ queryBlock.setGroupBy(groupBy);
+ }
+
+ SQLExpr exprObj = SQLUtils.toSQLExpr(expr, dbType);
+ groupBy.setHaving(exprObj);
+
+ return this;
+ }
+
+ @Override
+ public SQLSelectBuilderImpl into(String expr) {
+ SQLSelectQueryBlock queryBlock = getQueryBlock();
+
+ SQLExpr exprObj = SQLUtils.toSQLExpr(expr, dbType);
+ queryBlock.setInto(exprObj);
+
+ return this;
+ }
+
+ @Override
+ public SQLSelectBuilderImpl where(String expr) {
+ SQLSelectQueryBlock queryBlock = getQueryBlock();
+
+ SQLExpr exprObj = SQLUtils.toSQLExpr(expr, dbType);
+ queryBlock.setWhere(exprObj);
+
+ return this;
+ }
+
+ @Override
+ public SQLSelectBuilderImpl whereAnd(String expr) {
+ SQLSelectQueryBlock queryBlock = getQueryBlock();
+
+ SQLExpr exprObj = SQLUtils.toSQLExpr(expr, dbType);
+ SQLExpr newCondition = SQLUtils.buildCondition(SQLBinaryOperator.BooleanAnd, exprObj, false, queryBlock.getWhere());
+ queryBlock.setWhere(newCondition);
+
+ return this;
+ }
+
+ @Override
+ public SQLSelectBuilderImpl whereOr(String expr) {
+ SQLSelectQueryBlock queryBlock = getQueryBlock();
+
+ SQLExpr exprObj = SQLUtils.toSQLExpr(expr, dbType);
+ SQLExpr newCondition = SQLUtils.buildCondition(SQLBinaryOperator.BooleanOr, exprObj, false, queryBlock.getWhere());
+ queryBlock.setWhere(newCondition);
+
+ return this;
+ }
+
+ @Override
+ public SQLSelectBuilderImpl limit(int rowCount) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public SQLSelectBuilderImpl limit(int rowCount, int offset) {
+ throw new UnsupportedOperationException();
+ }
+
+ protected SQLSelectQueryBlock getQueryBlock() {
+ SQLSelect select = getSQLSelect();
+ SQLSelectQuery query = select.getQuery();
+ if (query == null) {
+ query = createSelectQueryBlock();
+ select.setQuery(query);
+ }
+
+ if (!(query instanceof SQLSelectQueryBlock)) {
+ throw new IllegalStateException("not support from, class : " + query.getClass().getName());
+ }
+
+ SQLSelectQueryBlock queryBlock = (SQLSelectQueryBlock) query;
+ return queryBlock;
+ }
+
+ protected SQLSelect createSelect() {
+ return new SQLSelect();
+ }
+
+ protected SQLSelectQuery createSelectQueryBlock() {
+ return new SQLSelectQueryBlock();
+ }
+
+ protected SQLOrderBy createOrderBy() {
+ return new SQLOrderBy();
+ }
+
+ protected SQLSelectGroupByClause createGroupBy() {
+ return new SQLSelectGroupByClause();
+ }
+
+ public String toString() {
+ return SQLUtils.toSQLString(stmt, dbType);
+ }
+}
diff --git a/src/main/java/com/alibaba/druid/sql/builder/impl/SQLUpdateBuilderImpl.java b/src/main/java/com/alibaba/druid/sql/builder/impl/SQLUpdateBuilderImpl.java
new file mode 100644
index 0000000000..51785b0a24
--- /dev/null
+++ b/src/main/java/com/alibaba/druid/sql/builder/impl/SQLUpdateBuilderImpl.java
@@ -0,0 +1,105 @@
+package com.alibaba.druid.sql.builder.impl;
+
+import com.alibaba.druid.sql.SQLUtils;
+import com.alibaba.druid.sql.ast.SQLExpr;
+import com.alibaba.druid.sql.ast.expr.SQLBinaryOperator;
+import com.alibaba.druid.sql.ast.expr.SQLIdentifierExpr;
+import com.alibaba.druid.sql.ast.statement.SQLExprTableSource;
+import com.alibaba.druid.sql.ast.statement.SQLUpdateSetItem;
+import com.alibaba.druid.sql.ast.statement.SQLUpdateStatement;
+import com.alibaba.druid.sql.builder.SQLUpdateBuilder;
+
+public class SQLUpdateBuilderImpl implements SQLUpdateBuilder {
+
+ private SQLUpdateStatement stmt;
+ private String dbType;
+
+ public SQLUpdateBuilderImpl(String dbType){
+ this.dbType = dbType;
+ }
+
+ public SQLUpdateBuilderImpl(SQLUpdateStatement stmt, String dbType){
+ this.stmt = stmt;
+ this.dbType = dbType;
+ }
+
+ @Override
+ public SQLUpdateBuilderImpl limit(int rowCount) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public SQLUpdateBuilderImpl limit(int rowCount, int offset) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public SQLUpdateBuilderImpl from(String table) {
+ return from(table, null);
+ }
+
+ @Override
+ public SQLUpdateBuilderImpl from(String table, String alias) {
+ SQLUpdateStatement update = getSQLUpdateStatement();
+ SQLExprTableSource from = new SQLExprTableSource(new SQLIdentifierExpr(table), alias);
+ update.setTableSource(from);
+ return this;
+ }
+
+ @Override
+ public SQLUpdateBuilderImpl where(String expr) {
+ SQLUpdateStatement update = getSQLUpdateStatement();
+
+ SQLExpr exprObj = SQLUtils.toSQLExpr(expr, dbType);
+ update.setWhere(exprObj);
+
+ return this;
+ }
+
+ @Override
+ public SQLUpdateBuilderImpl whereAnd(String expr) {
+ SQLUpdateStatement update = getSQLUpdateStatement();
+
+ SQLExpr exprObj = SQLUtils.toSQLExpr(expr, dbType);
+ SQLExpr newCondition = SQLUtils.buildCondition(SQLBinaryOperator.BooleanAnd, exprObj, false, update.getWhere());
+ update.setWhere(newCondition);
+
+ return this;
+ }
+
+ @Override
+ public SQLUpdateBuilderImpl whereOr(String expr) {
+ SQLUpdateStatement update = getSQLUpdateStatement();
+
+ SQLExpr exprObj = SQLUtils.toSQLExpr(expr, dbType);
+ SQLExpr newCondition = SQLUtils.buildCondition(SQLBinaryOperator.BooleanOr, exprObj, false, update.getWhere());
+ update.setWhere(newCondition);
+
+ return this;
+ }
+
+ public SQLUpdateBuilderImpl set(String... items) {
+ SQLUpdateStatement update = getSQLUpdateStatement();
+ for (String item : items) {
+ SQLUpdateSetItem updateSetItem = SQLUtils.toUpdateSetItem(item, dbType);
+ update.addItem(updateSetItem);
+ }
+
+ return this;
+ }
+
+ public SQLUpdateStatement getSQLUpdateStatement() {
+ if (stmt == null) {
+ stmt = createSQLUpdateStatement();
+ }
+ return stmt;
+ }
+
+ public SQLUpdateStatement createSQLUpdateStatement() {
+ return new SQLUpdateStatement();
+ }
+
+ public String toString() {
+ return SQLUtils.toSQLString(stmt, dbType);
+ }
+}
diff --git a/src/main/java/com/alibaba/druid/sql/builder/impl/dialect/MySqlSelectBuilderImpl.java b/src/main/java/com/alibaba/druid/sql/builder/impl/dialect/MySqlSelectBuilderImpl.java
new file mode 100644
index 0000000000..cb1424bb7e
--- /dev/null
+++ b/src/main/java/com/alibaba/druid/sql/builder/impl/dialect/MySqlSelectBuilderImpl.java
@@ -0,0 +1,23 @@
+package com.alibaba.druid.sql.builder.impl.dialect;
+
+import com.alibaba.druid.sql.ast.statement.SQLSelectGroupByClause;
+import com.alibaba.druid.sql.ast.statement.SQLSelectQuery;
+import com.alibaba.druid.sql.builder.impl.SQLSelectBuilderImpl;
+import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlSelectGroupBy;
+import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlSelectQueryBlock;
+import com.alibaba.druid.util.JdbcConstants;
+
+public class MySqlSelectBuilderImpl extends SQLSelectBuilderImpl {
+
+ public MySqlSelectBuilderImpl(){
+ super(JdbcConstants.MYSQL);
+ }
+
+ protected SQLSelectQuery createSelectQueryBlock() {
+ return new MySqlSelectQueryBlock();
+ }
+
+ protected SQLSelectGroupByClause createGroupBy() {
+ return new MySqlSelectGroupBy();
+ }
+}
diff --git a/src/main/java/com/alibaba/druid/sql/builder/impl/dialect/OracleSelectBuilderImpl.java b/src/main/java/com/alibaba/druid/sql/builder/impl/dialect/OracleSelectBuilderImpl.java
new file mode 100644
index 0000000000..58f0f3209f
--- /dev/null
+++ b/src/main/java/com/alibaba/druid/sql/builder/impl/dialect/OracleSelectBuilderImpl.java
@@ -0,0 +1,26 @@
+package com.alibaba.druid.sql.builder.impl.dialect;
+
+import com.alibaba.druid.sql.builder.impl.SQLSelectBuilderImpl;
+import com.alibaba.druid.sql.dialect.oracle.ast.OracleOrderBy;
+import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleSelect;
+import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleSelectQueryBlock;
+import com.alibaba.druid.util.JdbcConstants;
+
+public class OracleSelectBuilderImpl extends SQLSelectBuilderImpl {
+
+ public OracleSelectBuilderImpl(){
+ super(JdbcConstants.ORACLE);
+ }
+
+ protected OracleSelectQueryBlock createSelectQueryBlock() {
+ return new OracleSelectQueryBlock();
+ }
+
+ protected OracleSelect createSelect() {
+ return new OracleSelect();
+ }
+
+ protected OracleOrderBy createOrderBy() {
+ return new OracleOrderBy();
+ }
+}
diff --git a/src/main/java/com/alibaba/druid/sql/builder/impl/dialect/PGSelectBuilderImpl.java b/src/main/java/com/alibaba/druid/sql/builder/impl/dialect/PGSelectBuilderImpl.java
new file mode 100644
index 0000000000..a438626399
--- /dev/null
+++ b/src/main/java/com/alibaba/druid/sql/builder/impl/dialect/PGSelectBuilderImpl.java
@@ -0,0 +1,22 @@
+package com.alibaba.druid.sql.builder.impl.dialect;
+
+import com.alibaba.druid.sql.builder.impl.SQLSelectBuilderImpl;
+import com.alibaba.druid.sql.dialect.postgresql.ast.PGOrderBy;
+import com.alibaba.druid.sql.dialect.postgresql.ast.stmt.PGSelectQueryBlock;
+import com.alibaba.druid.sql.dialect.postgresql.ast.stmt.PGSelectStatement;
+import com.alibaba.druid.util.JdbcConstants;
+
+public class PGSelectBuilderImpl extends SQLSelectBuilderImpl {
+
+ public PGSelectBuilderImpl(){
+ super(new PGSelectStatement(), JdbcConstants.POSTGRESQL);
+ }
+
+ protected PGSelectQueryBlock createSelectQueryBlock() {
+ return new PGSelectQueryBlock();
+ }
+
+ protected PGOrderBy createOrderBy() {
+ return new PGOrderBy();
+ }
+}
diff --git a/src/main/java/com/alibaba/druid/sql/builder/impl/dialect/SQLServerSelectBuilderImpl.java b/src/main/java/com/alibaba/druid/sql/builder/impl/dialect/SQLServerSelectBuilderImpl.java
new file mode 100644
index 0000000000..f4690df0b4
--- /dev/null
+++ b/src/main/java/com/alibaba/druid/sql/builder/impl/dialect/SQLServerSelectBuilderImpl.java
@@ -0,0 +1,21 @@
+package com.alibaba.druid.sql.builder.impl.dialect;
+
+import com.alibaba.druid.sql.builder.impl.SQLSelectBuilderImpl;
+import com.alibaba.druid.sql.dialect.sqlserver.ast.SQLServerSelect;
+import com.alibaba.druid.sql.dialect.sqlserver.ast.SQLServerSelectQueryBlock;
+import com.alibaba.druid.util.JdbcConstants;
+
+public class SQLServerSelectBuilderImpl extends SQLSelectBuilderImpl {
+
+ public SQLServerSelectBuilderImpl(){
+ super(JdbcConstants.SQL_SERVER);
+ }
+
+ protected SQLServerSelectQueryBlock createSelectQueryBlock() {
+ return new SQLServerSelectQueryBlock();
+ }
+
+ protected SQLServerSelect createSelect() {
+ return new SQLServerSelect();
+ }
+}
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 56ef1e5534..96c07827e2 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
@@ -25,7 +25,6 @@ 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.SQLIntegerExpr;
-import com.alibaba.druid.sql.ast.expr.SQLListExpr;
import com.alibaba.druid.sql.ast.expr.SQLLiteralExpr;
import com.alibaba.druid.sql.ast.expr.SQLNCharExpr;
import com.alibaba.druid.sql.ast.expr.SQLQueryExpr;
@@ -2666,24 +2665,8 @@ public class MySqlStatementParser extends SQLStatementParser {
accept(Token.SET);
for (;;) {
- SQLUpdateSetItem item = new SQLUpdateSetItem();
-
- if (lexer.token() == (Token.LPAREN)) {
- lexer.nextToken();
- SQLListExpr list = new SQLListExpr();
- this.exprParser.exprList(list.getItems(), list);
- 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);
+ SQLUpdateSetItem item = this.exprParser.parseUpdateSetItem();
+ update.addItem(item);
if (lexer.token() != Token.COMMA) {
break;
diff --git a/src/main/java/com/alibaba/druid/sql/dialect/odps/parser/OdpsExprParser.java b/src/main/java/com/alibaba/druid/sql/dialect/odps/parser/OdpsExprParser.java
index b7d9257f53..d6bc801569 100644
--- a/src/main/java/com/alibaba/druid/sql/dialect/odps/parser/OdpsExprParser.java
+++ b/src/main/java/com/alibaba/druid/sql/dialect/odps/parser/OdpsExprParser.java
@@ -17,8 +17,12 @@ package com.alibaba.druid.sql.dialect.odps.parser;
import com.alibaba.druid.sql.ast.SQLExpr;
import com.alibaba.druid.sql.ast.expr.SQLCharExpr;
+import com.alibaba.druid.sql.ast.expr.SQLIdentifierExpr;
+import com.alibaba.druid.sql.ast.statement.SQLSelectItem;
+import com.alibaba.druid.sql.dialect.odps.ast.OdpsUDTFSQLSelectItem;
import com.alibaba.druid.sql.parser.Lexer;
import com.alibaba.druid.sql.parser.SQLExprParser;
+import com.alibaba.druid.sql.parser.Token;
public class OdpsExprParser extends SQLExprParser {
@@ -47,4 +51,53 @@ public class OdpsExprParser extends SQLExprParser {
protected SQLExpr parseAliasExpr(String alias) {
return new SQLCharExpr(alias);
}
+
+ @Override
+ public SQLSelectItem parseSelectItem() {
+ SQLExpr expr;
+ if (lexer.token() == Token.IDENTIFIER) {
+ expr = new SQLIdentifierExpr(lexer.stringVal());
+ lexer.nextTokenComma();
+
+ if (lexer.token() != Token.COMMA) {
+ expr = this.primaryRest(expr);
+ expr = this.exprRest(expr);
+ }
+ } else {
+ expr = expr();
+ }
+
+ if (lexer.token() == Token.AS) {
+ lexer.nextToken();
+
+ if (lexer.token() == Token.LPAREN) {
+ lexer.nextToken();
+
+ OdpsUDTFSQLSelectItem selectItem = new OdpsUDTFSQLSelectItem();
+
+ selectItem.setExpr(expr);
+
+ for (;;) {
+ String alias = lexer.stringVal();
+ lexer.nextToken();
+
+ selectItem.getAliasList().add(alias);
+
+ if (lexer.token() == Token.COMMA) {
+ lexer.nextToken();
+ continue;
+ }
+ break;
+ }
+
+ accept(Token.RPAREN);
+
+ return selectItem;
+ }
+ }
+
+ final String alias = as();
+
+ return new SQLSelectItem(expr, alias);
+ }
}
diff --git a/src/main/java/com/alibaba/druid/sql/dialect/odps/parser/OdpsSelectParser.java b/src/main/java/com/alibaba/druid/sql/dialect/odps/parser/OdpsSelectParser.java
index f4299db585..26ecd1a7a3 100644
--- a/src/main/java/com/alibaba/druid/sql/dialect/odps/parser/OdpsSelectParser.java
+++ b/src/main/java/com/alibaba/druid/sql/dialect/odps/parser/OdpsSelectParser.java
@@ -15,13 +15,9 @@
*/
package com.alibaba.druid.sql.dialect.odps.parser;
-import com.alibaba.druid.sql.ast.SQLExpr;
import com.alibaba.druid.sql.ast.SQLSetQuantifier;
-import com.alibaba.druid.sql.ast.expr.SQLIdentifierExpr;
-import com.alibaba.druid.sql.ast.statement.SQLSelectItem;
import com.alibaba.druid.sql.ast.statement.SQLSelectQuery;
import com.alibaba.druid.sql.dialect.odps.ast.OdpsSelectQueryBlock;
-import com.alibaba.druid.sql.dialect.odps.ast.OdpsUDTFSQLSelectItem;
import com.alibaba.druid.sql.parser.SQLExprParser;
import com.alibaba.druid.sql.parser.SQLSelectParser;
import com.alibaba.druid.sql.parser.Token;
@@ -81,52 +77,4 @@ public class OdpsSelectParser extends SQLSelectParser {
return queryRest(queryBlock);
}
- @Override
- protected SQLSelectItem parseSelectItem() {
- SQLExpr expr;
- if (lexer.token() == Token.IDENTIFIER) {
- expr = new SQLIdentifierExpr(lexer.stringVal());
- lexer.nextTokenComma();
-
- if (lexer.token() != Token.COMMA) {
- expr = this.exprParser.primaryRest(expr);
- expr = this.exprParser.exprRest(expr);
- }
- } else {
- expr = expr();
- }
-
- if (lexer.token() == Token.AS) {
- lexer.nextToken();
-
- if (lexer.token() == Token.LPAREN) {
- lexer.nextToken();
-
- OdpsUDTFSQLSelectItem selectItem = new OdpsUDTFSQLSelectItem();
-
- selectItem.setExpr(expr);
-
- for (;;) {
- String alias = lexer.stringVal();
- lexer.nextToken();
-
- selectItem.getAliasList().add(alias);
-
- if (lexer.token() == Token.COMMA) {
- lexer.nextToken();
- continue;
- }
- break;
- }
-
- accept(Token.RPAREN);
-
- return selectItem;
- }
- }
-
- final String alias = as();
-
- return new SQLSelectItem(expr, alias);
- }
}
diff --git a/src/main/java/com/alibaba/druid/sql/dialect/oracle/ast/OracleOrderBy.java b/src/main/java/com/alibaba/druid/sql/dialect/oracle/ast/OracleOrderBy.java
index d297606575..a3eee22fd2 100644
--- a/src/main/java/com/alibaba/druid/sql/dialect/oracle/ast/OracleOrderBy.java
+++ b/src/main/java/com/alibaba/druid/sql/dialect/oracle/ast/OracleOrderBy.java
@@ -16,6 +16,7 @@
package com.alibaba.druid.sql.dialect.oracle.ast;
import com.alibaba.druid.sql.ast.SQLOrderBy;
+import com.alibaba.druid.sql.ast.statement.SQLSelectOrderByItem;
import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleOrderByItem;
import com.alibaba.druid.sql.dialect.oracle.visitor.OracleASTVisitor;
import com.alibaba.druid.sql.visitor.SQLASTVisitor;
@@ -67,4 +68,8 @@ public class OracleOrderBy extends SQLOrderBy {
((OracleOrderByItem) this.items.get(i)).output(buf);
}
}
+
+ protected SQLSelectOrderByItem createItem() {
+ return new OracleOrderByItem();
+ }
}
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 ecd2bd5fef..2c64fde35a 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
@@ -1137,12 +1137,10 @@ public class OracleStatementParser extends SQLStatementParser {
accept(Token.SET);
for (;;) {
- SQLUpdateSetItem item = new SQLUpdateSetItem();
- item.setColumn(this.exprParser.name());
- accept(Token.EQ);
- item.setValue(this.exprParser.expr());
+ SQLUpdateSetItem item = this.exprParser.parseUpdateSetItem();
updateClause.getItems().add(item);
+ item.setParent(updateClause);
if (lexer.token() == (Token.COMMA)) {
lexer.nextToken();
diff --git a/src/main/java/com/alibaba/druid/sql/dialect/sqlserver/parser/SQLServerExprParser.java b/src/main/java/com/alibaba/druid/sql/dialect/sqlserver/parser/SQLServerExprParser.java
index 69e2a97f7a..e2837e09de 100644
--- a/src/main/java/com/alibaba/druid/sql/dialect/sqlserver/parser/SQLServerExprParser.java
+++ b/src/main/java/com/alibaba/druid/sql/dialect/sqlserver/parser/SQLServerExprParser.java
@@ -174,7 +174,7 @@ public class SQLServerExprParser extends SQLExprParser {
return null;
}
- protected SQLSelectItem parseSelectItem() {
+ public SQLSelectItem parseSelectItem() {
SQLExpr expr;
if (lexer.token() == Token.IDENTIFIER) {
expr = new SQLIdentifierExpr(lexer.stringVal());
diff --git a/src/main/java/com/alibaba/druid/sql/parser/SQLExprParser.java b/src/main/java/com/alibaba/druid/sql/parser/SQLExprParser.java
index 52085129f2..7ae7d02a8f 100644
--- a/src/main/java/com/alibaba/druid/sql/parser/SQLExprParser.java
+++ b/src/main/java/com/alibaba/druid/sql/parser/SQLExprParser.java
@@ -76,8 +76,10 @@ import com.alibaba.druid.sql.ast.statement.SQLForeignKeyImpl;
import com.alibaba.druid.sql.ast.statement.SQLPrimaryKey;
import com.alibaba.druid.sql.ast.statement.SQLPrimaryKeyImpl;
import com.alibaba.druid.sql.ast.statement.SQLSelect;
+import com.alibaba.druid.sql.ast.statement.SQLSelectItem;
import com.alibaba.druid.sql.ast.statement.SQLSelectOrderByItem;
import com.alibaba.druid.sql.ast.statement.SQLUnique;
+import com.alibaba.druid.sql.ast.statement.SQLUpdateSetItem;
public class SQLExprParser extends SQLParser {
@@ -1001,6 +1003,28 @@ public class SQLExprParser extends SQLParser {
return item;
}
+
+ public SQLUpdateSetItem parseUpdateSetItem() {
+ SQLUpdateSetItem item = new SQLUpdateSetItem();
+
+ if (lexer.token() == (Token.LPAREN)) {
+ lexer.nextToken();
+ SQLListExpr list = new SQLListExpr();
+ this.exprList(list.getItems(), list);
+ accept(Token.RPAREN);
+ item.setColumn(list);
+ } else {
+ item.setColumn(this.primary());
+ }
+ if (lexer.token() == Token.COLONEQ) {
+ lexer.nextToken();
+ } else {
+ accept(Token.EQ);
+ }
+
+ item.setValue(this.expr());
+ return item;
+ }
public final SQLExpr bitAnd() {
SQLExpr expr = shift();
@@ -1743,4 +1767,27 @@ public class SQLExprParser extends SQLParser {
protected SQLForeignKeyConstraint createForeignKey() {
return new SQLForeignKeyImpl();
}
+
+ public SQLSelectItem parseSelectItem() {
+ SQLExpr expr;
+ boolean connectByRoot = false;
+ if (lexer.token() == Token.IDENTIFIER) {
+ if (identifierEquals("CONNECT_BY_ROOT")) {
+ connectByRoot = true;
+ lexer.nextToken();
+ }
+ expr = new SQLIdentifierExpr(lexer.stringVal());
+ lexer.nextTokenComma();
+
+ if (lexer.token() != Token.COMMA) {
+ expr = this.primaryRest(expr);
+ expr = this.exprRest(expr);
+ }
+ } else {
+ expr = expr();
+ }
+ final String alias = as();
+
+ return new SQLSelectItem(expr, alias, connectByRoot);
+ }
}
diff --git a/src/main/java/com/alibaba/druid/sql/parser/SQLSelectParser.java b/src/main/java/com/alibaba/druid/sql/parser/SQLSelectParser.java
index 475900cf40..898f54aa74 100644
--- a/src/main/java/com/alibaba/druid/sql/parser/SQLSelectParser.java
+++ b/src/main/java/com/alibaba/druid/sql/parser/SQLSelectParser.java
@@ -64,7 +64,7 @@ public class SQLSelectParser extends SQLParser {
select.setOrderBy(parseOrderBy());
}
- while(lexer.token() == Token.HINT) {
+ while (lexer.token() == Token.HINT) {
this.exprParser.parseHints(select.getHints());
}
@@ -269,11 +269,12 @@ public class SQLSelectParser extends SQLParser {
}
}
- protected final void parseSelectList(SQLSelectQueryBlock queryBlock) {
+ protected void parseSelectList(SQLSelectQueryBlock queryBlock) {
final List selectList = queryBlock.getSelectList();
for (;;) {
- final SQLSelectItem selectItem = parseSelectItem();
+ final SQLSelectItem selectItem = this.exprParser.parseSelectItem();
selectList.add(selectItem);
+ selectItem.setParent(queryBlock);
if (lexer.token() != Token.COMMA) {
break;
@@ -283,29 +284,6 @@ public class SQLSelectParser extends SQLParser {
}
}
- protected SQLSelectItem parseSelectItem() {
- SQLExpr expr;
- boolean connectByRoot = false;
- if (lexer.token() == Token.IDENTIFIER) {
- if (identifierEquals("CONNECT_BY_ROOT")) {
- connectByRoot = true;
- lexer.nextToken();
- }
- expr = new SQLIdentifierExpr(lexer.stringVal());
- lexer.nextTokenComma();
-
- if (lexer.token() != Token.COMMA) {
- expr = this.exprParser.primaryRest(expr);
- expr = this.exprParser.exprRest(expr);
- }
- } else {
- expr = expr();
- }
- final String alias = as();
-
- return new SQLSelectItem(expr, alias, connectByRoot);
- }
-
public void parseFrom(SQLSelectQueryBlock queryBlock) {
if (lexer.token() != Token.FROM) {
return;
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 1895cc0f53..6035f8eb33 100644
--- a/src/main/java/com/alibaba/druid/sql/parser/SQLStatementParser.java
+++ b/src/main/java/com/alibaba/druid/sql/parser/SQLStatementParser.java
@@ -1539,20 +1539,8 @@ public class SQLStatementParser extends SQLParser {
accept(Token.SET);
for (;;) {
- SQLUpdateSetItem item = new SQLUpdateSetItem();
-
- if (lexer.token() == (Token.LPAREN)) {
- lexer.nextToken();
- SQLListExpr list = new SQLListExpr();
- this.exprParser.exprList(list.getItems(), list);
- accept(Token.RPAREN);
- item.setColumn(list);
- } else {
- item.setColumn(this.exprParser.primary());
- }
- accept(Token.EQ);
- item.setValue(this.exprParser.expr());
- update.getItems().add(item);
+ SQLUpdateSetItem item = this.exprParser.parseUpdateSetItem();
+ update.addItem(item);
if (lexer.token() != Token.COMMA) {
break;
diff --git a/src/test/java/com/alibaba/druid/bvt/sql/builder/BuilderDeleteTest.java b/src/test/java/com/alibaba/druid/bvt/sql/builder/BuilderDeleteTest.java
new file mode 100644
index 0000000000..52df54d466
--- /dev/null
+++ b/src/test/java/com/alibaba/druid/bvt/sql/builder/BuilderDeleteTest.java
@@ -0,0 +1,26 @@
+package com.alibaba.druid.bvt.sql.builder;
+
+import junit.framework.TestCase;
+
+import org.junit.Assert;
+
+import com.alibaba.druid.sql.builder.SQLBuilderFactory;
+import com.alibaba.druid.sql.builder.SQLDeleteBuilder;
+import com.alibaba.druid.util.JdbcConstants;
+
+public class BuilderDeleteTest extends TestCase {
+
+ public void test_0() throws Exception {
+ SQLDeleteBuilder builder = SQLBuilderFactory.createDeleteBuilder(JdbcConstants.MYSQL);
+
+ builder //
+ .from("mytable") //
+ .whereAnd("f1 > 0") //
+ ;
+
+ String sql = builder.toString();
+ System.out.println(sql);
+ Assert.assertEquals("DELETE FROM mytable" //
+ + "\nWHERE f1 > 0", sql);
+ }
+}
diff --git a/src/test/java/com/alibaba/druid/bvt/sql/builder/BuilderSelectTest.java b/src/test/java/com/alibaba/druid/bvt/sql/builder/BuilderSelectTest.java
new file mode 100644
index 0000000000..c63c221ad8
--- /dev/null
+++ b/src/test/java/com/alibaba/druid/bvt/sql/builder/BuilderSelectTest.java
@@ -0,0 +1,32 @@
+package com.alibaba.druid.bvt.sql.builder;
+
+import junit.framework.TestCase;
+
+import org.junit.Assert;
+
+import com.alibaba.druid.sql.builder.SQLBuilderFactory;
+import com.alibaba.druid.sql.builder.SQLSelectBuilder;
+import com.alibaba.druid.util.JdbcConstants;
+
+public class BuilderSelectTest extends TestCase {
+
+ public void test_0() throws Exception {
+ SQLSelectBuilder builder = SQLBuilderFactory.createSelectSQLBuilder(JdbcConstants.MYSQL);
+
+ builder.from("mytable");
+ builder.select("f1", "f2", "f3 F3", "count(*) cnt");
+ builder.groupBy("f1");
+ builder.having("count(*) > 1");
+ builder.orderBy("f1", "f2 desc");
+ builder.whereAnd("f1 > 0");
+
+ String sql = builder.toString();
+ System.out.println(sql);
+ Assert.assertEquals("SELECT f1, f2, f3 AS F3, COUNT(*) AS cnt" //
+ + "\nFROM mytable"//
+ + "\nWHERE f1 > 0"//
+ + "\nGROUP BY f1"//
+ + "\nHAVING COUNT(*) > 1"//
+ + "\nORDER BY f1, f2 DESC", sql);
+ }
+}
diff --git a/src/test/java/com/alibaba/druid/bvt/sql/builder/BuilderUpdateTest.java b/src/test/java/com/alibaba/druid/bvt/sql/builder/BuilderUpdateTest.java
new file mode 100644
index 0000000000..61f8951995
--- /dev/null
+++ b/src/test/java/com/alibaba/druid/bvt/sql/builder/BuilderUpdateTest.java
@@ -0,0 +1,27 @@
+package com.alibaba.druid.bvt.sql.builder;
+
+import junit.framework.TestCase;
+
+import org.junit.Assert;
+
+import com.alibaba.druid.sql.builder.SQLBuilderFactory;
+import com.alibaba.druid.sql.builder.SQLUpdateBuilder;
+import com.alibaba.druid.util.JdbcConstants;
+
+public class BuilderUpdateTest extends TestCase {
+
+ public void test_0() throws Exception {
+ SQLUpdateBuilder builder = SQLBuilderFactory.createUpdateBuilder(JdbcConstants.MYSQL);
+
+ builder //
+ .from("mytable") //
+ .whereAnd("f1 > 0") //
+ .set("f1 = f1 + 1", "f2 = ?");
+
+ String sql = builder.toString();
+ System.out.println(sql);
+ Assert.assertEquals("UPDATE mytable" //
+ + "\nSET f1 = f1 + 1, f2 = ?" //
+ + "\nWHERE f1 > 0", sql);
+ }
+}