package com.litesuits.orm.db.assit;
import com.litesuits.orm.db.TableManager;
import com.litesuits.orm.db.impl.SQLStatement;
import java.util.regex.Pattern;
/**
* 查询构建
*
* @author mty
* @date 2013-6-14下午3:47:16
*/
public class QueryBuilder {
private static final Pattern limitPattern = Pattern.compile("\\s*\\d+\\s*(,\\s*\\d+\\s*)?");
public static final String ASC = " ASC";
public static final String DESC = " DESC";
public static final String AND = " AND ";
public static final String OR = " OR ";
public static final String GROUP_BY = " GROUP BY ";
public static final String HAVING = " HAVING ";
public static final String ORDER_BY = " ORDER BY ";
public static final String LIMIT = " LIMIT ";
public static final String SELECT_COUNT = "SELECT COUNT(*) FROM ";
public static final String SELECT = "SELECT ";
public static final String DISTINCT = " DISTINCT ";
public static final String ASTERISK = "*";
public static final String FROM = " FROM ";
public static final String EQUAL_HOLDER = "=?";
public static final String COMMA_HOLDER = ",?";
public static final String COMMA = ",";
private Class clazz;
private Class clazzMapping;
private boolean distinct;
private String[] columns;
//private String where;
//private Object[] whereArgs;
private String group;
private String having;
private String order;
private String limit;
private WhereBuilder whereBuilder = new WhereBuilder();
public QueryBuilder() {
}
public Class getQueryClass() {
return clazz;
}
public QueryBuilder(Class claxx) {
queryWho(claxx);
}
public static QueryBuilder create(Class claxx) {
return new QueryBuilder(claxx);
}
public static QueryBuilder get(Class claxx) {
return create(claxx);
}
public QueryBuilder queryWho(Class claxx) {
this.clazz = claxx;
return this;
}
public QueryBuilder where(WhereBuilder builder) {
this.whereBuilder = builder;
return this;
}
public WhereBuilder getwhereBuilder() {
return whereBuilder;
}
/**
* @param where "id = ?";
* "id in(?,?,?)";
* "id LIKE %?"
* @param whereArgs new String[]{"",""};
* new Integer[]{1,2}
* @return
*/
public QueryBuilder where(String where, Object[] whereArgs) {
whereBuilder.where(where, whereArgs);
return this;
}
/**
* build as " AND " + where
*
* @param where "id = ?";
* "id in(?,?,?)";
* "id LIKE %?"
* @param whereArgs new String[]{"",""};
* new Integer[]{1,2}
* @return
*/
public QueryBuilder whereAnd(String where, Object[] whereArgs) {
whereBuilder.and(where, whereArgs);
return this;
}
/**
* build as " OR " + where
*
* @param where "id = ?";
* "id in(?,?,?)";
* "id LIKE %?"
* @param whereArgs new String[]{"",""};
* new Integer[]{1,2}
* @return
*/
public QueryBuilder whereOr(String where, Object[] whereArgs) {
whereBuilder.or(where, whereArgs);
return this;
}
/**
* build as where+" OR "
*/
public QueryBuilder whereAppendOr() {
whereBuilder.or();
return this;
}
/**
* build as where+" NOT "
*/
public QueryBuilder whereAppendNot() {
whereBuilder.not();
return this;
}
/**
* build as where+" column != ? "
*/
public QueryBuilder whereNoEquals(String column, Object value) {
whereBuilder.noEquals(column, value);
return this;
}
/**
* build as where+" column > ? "
*/
public QueryBuilder whereGreaterThan(String column, Object value) {
whereBuilder.greaterThan(column, value);
return this;
}
/**
* build as where+" column < ? "
*/
public QueryBuilder whereLessThan(String column, Object value) {
whereBuilder.lessThan(column, value);
return this;
}
/**
* build as where+" column = ? "
*/
public QueryBuilder whereEquals(String column, Object value) {
whereBuilder.equals(column, value);
return this;
}
/**
* build as where+" column IN(?, ?, ?...)"
*/
public QueryBuilder whereIn(String column, Object[] values) {
whereBuilder.in(column, values);
return this;
}
/**
* 需要返回的列,不填写默认全部,即select * 。
*
* @param columns 列名,注意不是对象的属性名。
* @return
*/
public QueryBuilder columns(String[] columns) {
this.columns = columns;
return this;
}
/**
* 累积需要返回的列,不填写默认全部,即select * 。
*
* @param columns 列名,注意不是对象的属性名。
* @return
*/
public QueryBuilder appendColumns(String[] columns) {
if (this.columns != null) {
String[] newCols = new String[this.columns.length + columns.length];
System.arraycopy(this.columns, 0, newCols, 0, this.columns.length);
System.arraycopy(columns, 0, newCols, this.columns.length, columns.length);
this.columns = newCols;
} else {
this.columns = columns;
}
return this;
}
/**
* 唯一性保证
*
* @return
*/
public QueryBuilder distinct(boolean distinct) {
this.distinct = distinct;
return this;
}
/**
* GROUP BY 语句用于结合合计函数,根据一个或多个列对结果集进行分组。
*
* @param group
* @return
*/
public QueryBuilder groupBy(String group) {
this.group = group;
return this;
}
/**
* 在 SQL 中增加 HAVING 子句原因是,WHERE 关键字无法与合计函数一起使用。
*
* @param having
* @return
*/
public QueryBuilder having(String having) {
this.having = having;
return this;
}
public QueryBuilder orderBy(String order) {
this.order = order;
return this;
}
public QueryBuilder appendOrderAscBy(String column) {
if (order == null) {
order = column + ASC;
} else {
order += ", " + column + ASC;
}
return this;
}
public QueryBuilder appendOrderDescBy(String column) {
if (order == null) {
order = column + DESC;
} else {
order += ", " + column + DESC;
}
return this;
}
public QueryBuilder limit(String limit) {
this.limit = limit;
return this;
}
public QueryBuilder limit(int start, int length) {
this.limit = start + COMMA + length;
return this;
}
public QueryBuilder queryMappingInfo(Class clazzMapping) {
this.clazzMapping = clazzMapping;
return this;
}
/**
* 构建查询语句
*
* @return
*/
public SQLStatement createStatement() {
if (clazz == null) {
throw new IllegalArgumentException("U Must Set A Query Entity Class By queryWho(Class) or " +
"QueryBuilder(Class)");
}
if (Checker.isEmpty(group) && !Checker.isEmpty(having)) {
throw new IllegalArgumentException(
"HAVING仅允许在有GroupBy的时候使用(HAVING clauses are only permitted when using a groupBy clause)");
}
if (!Checker.isEmpty(limit) && !limitPattern.matcher(limit).matches()) {
throw new IllegalArgumentException(
"invalid LIMIT clauses:" + limit);
}
StringBuilder query = new StringBuilder(120);
query.append(SELECT);
if (distinct) {
query.append(DISTINCT);
}
if (!Checker.isEmpty(columns)) {
appendColumns(query, columns);
} else {
query.append(ASTERISK);
}
query.append(FROM).append(getTableName());
query.append(whereBuilder.createWhereString(clazz));
appendClause(query, GROUP_BY, group);
appendClause(query, HAVING, having);
appendClause(query, ORDER_BY, order);
appendClause(query, LIMIT, limit);
SQLStatement stmt = new SQLStatement();
stmt.sql = query.toString();
stmt.bindArgs = whereBuilder.transToStringArray();
return stmt;
}
/**
* Build a statement that returns a 1 by 1 table with a numeric value.
* SELECT COUNT(*) FROM table;
*
* @return
*/
public SQLStatement createStatementForCount() {
StringBuilder query = new StringBuilder(120);
query.append(SELECT_COUNT).append(getTableName());
SQLStatement stmt = new SQLStatement();
if (whereBuilder != null) {
query.append(whereBuilder.createWhereString(clazz));
stmt.bindArgs = whereBuilder.transToStringArray();
}
stmt.sql = query.toString();
return stmt;
}
private String getTableName() {
if (clazzMapping == null) {
return TableManager.getTableName(clazz);
} else {
return TableManager.getMapTableName(clazz, clazzMapping);
}
}
/**
* 添加条件
*
* @param s
* @param name
* @param clause
*/
private static void appendClause(StringBuilder s, String name, String clause) {
if (!Checker.isEmpty(clause)) {
s.append(name);
s.append(clause);
}
}
/**
* 添加列,逗号分隔
*
* @param s
* @param columns
*/
private static void appendColumns(StringBuilder s, String[] columns) {
int n = columns.length;
for (int i = 0; i < n; i++) {
String column = columns[i];
if (column != null) {
if (i > 0) {
s.append(",");
}
s.append(column);
}
}
s.append(" ");
}
private String buildWhereIn(String column, int num) {
StringBuilder sb = new StringBuilder(column).append(" IN (?");
for (int i = 1; i < num; i++) {
sb.append(COMMA_HOLDER);
}
return sb.append(")").toString();
}
}