Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
com.github.mengxianun.core.SQLBuilder Maven / Gradle / Ivy
package com.github.mengxianun.core;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
import com.github.mengxianun.core.exception.DataException;
import com.github.mengxianun.core.item.ColumnItem;
import com.github.mengxianun.core.item.FilterItem;
import com.github.mengxianun.core.item.GroupItem;
import com.github.mengxianun.core.item.JoinColumnItem;
import com.github.mengxianun.core.item.JoinItem;
import com.github.mengxianun.core.item.JoinItem.SingleColumnJoinItem;
import com.github.mengxianun.core.item.LimitItem;
import com.github.mengxianun.core.item.OrderItem;
import com.github.mengxianun.core.item.SQLValue;
import com.github.mengxianun.core.item.TableItem;
import com.github.mengxianun.core.item.ValueItem;
import com.github.mengxianun.core.item.extension.StatementFilterItem;
import com.github.mengxianun.core.item.extension.StatementValueFilterItem;
import com.github.mengxianun.core.request.Connector;
import com.github.mengxianun.core.request.JoinType;
import com.github.mengxianun.core.request.Operator;
import com.github.mengxianun.core.request.Order;
import com.github.mengxianun.core.schema.Column;
import com.github.mengxianun.core.schema.Schema;
import com.github.mengxianun.core.schema.Table;
import com.google.common.base.Strings;
public class SQLBuilder {
public static final String PREFIX_SELECT = "SELECT ";
public static final String PREFIX_SELECT_DISTINCT = "SELECT DISTINCT ";
public static final String PREFIX_FROM = " FROM ";
public static final String PREFIX_WHERE = " WHERE ";
public static final String PREFIX_GROUP_BY = " GROUP BY ";
public static final String PREFIX_HAVING = " HAVING ";
public static final String PREFIX_ORDER_BY = " ORDER BY ";
public static final String LIMIT = " LIMIT ";
public static final String OFFSET = " OFFSET ";
public static final String ORDER_ASC = " ASC";
public static final String ORDER_DESC = " DESC";
public static final String INNER_JOIN = " INNER JOIN ";
public static final String LEFT_OUTER_JOIN = " LEFT JOIN ";
public static final String RIGHT_OUTER_JOIN = " RIGHT JOIN ";
public static final String FULL_OUTER_JOIN = " FULL JOIN ";
public static final String JOIN_ON = " ON ";
public static final String DELIM_COMMA = ", ";
public static final String DELIM_AND = " AND ";
public static final String DELIM_OR = " OR ";
public static final String COUNT = " COUNT(*) ";
public static final String COLUMN_ALL = "*";
public static final String DISTINCT = " DISTINCT ";
// 字段别名关联字符串
public static final String ALIAS_KEY = " AS ";
public static final String PREFIX_INSERT_INTO = "INSERT INTO ";
public static final String PREFIX_UPDATE = "UPDATE ";
public static final String UPDATE_SET = " SET ";
public static final String PREFIX_DELETE_FROM = "DELETE FROM ";
public static final Pattern FUNCTION_PATTERN = Pattern.compile("\\$(?[^$()]*)\\((?[^$()]*)\\)");
// matcher's pattern name
public static final String FUNCTION_MATCHER_GROUP_FUNC = "func";
public static final String FUNCTION_MATCHER_GROUP_ARGS = "args";
public static final Pattern SOURCE_TABLE_COLUMN = Pattern
.compile("((?[\\w-]*)(\\.)+)*(?[\\w-]+)\\.(?([\\w-]+|\\*))");
public static final String MATCHER_GROUP_SOURCE = "source";
public static final String MATCHER_GROUP_TABLE = "table";
public static final String MATCHER_GROUP_COLUMN = "column";
protected Action action;
protected DataContext dataContext;
protected Dialect dialect;
protected String sql;
protected List params = new ArrayList<>();
protected List whereParams = new ArrayList<>();
// 关联分页查询的情况, SQL 语句构建做特殊处理
protected boolean joinLimit;
protected List joinLimitFilterItems = new ArrayList<>();
// 拼接后的字符串
protected String columnString = "";
protected String tableString = "";
protected String joinString = "";
protected String whereString = "";
protected String groupString = "";
protected String orderString = "";
protected String limitString = "";
protected String valueString = "";
public SQLBuilder(Action action) {
this.action = action;
this.dataContext = action.getDataContext();
this.dialect = dataContext.getDialect();
}
public void toSql() {
if (action.isQuery()) {
toSelect();
} else if (action.isInsert()) {
toInsert();
} else if (action.isUpdate()) {
toUpdate();
} else if (action.isDelete()) {
toDelete();
}
}
public void toSelect() {
StringBuilder sqlBuilder = new StringBuilder();
sqlBuilder.append(toColumns());
sqlBuilder.append(toSelectTables());
sqlBuilder.append(toJoins());
sqlBuilder.append(toWhere());
sqlBuilder.append(toGroups());
sqlBuilder.append(toOrders());
sqlBuilder.append(toLimit());
sql = sqlBuilder.toString();
}
public void toInsert() {
StringBuilder sqlBuilder = new StringBuilder();
sqlBuilder.append(toInsertTable());
sqlBuilder.append(toInsertValues());
sql = sqlBuilder.toString();
}
public void toUpdate() {
StringBuilder sqlBuilder = new StringBuilder();
sqlBuilder.append(toUpdateTable());
sqlBuilder.append(toUpdateValues());
sqlBuilder.append(toWhere());
sql = sqlBuilder.toString();
}
public void toDelete() {
StringBuilder sqlBuilder = new StringBuilder();
sqlBuilder.append(toDeleteTable());
sqlBuilder.append(toWhere());
sql = sqlBuilder.toString();
}
public String toColumns() {
StringBuilder columnsBuilder = new StringBuilder(action.isDistinct() ? PREFIX_SELECT_DISTINCT : PREFIX_SELECT);
columnsBuilder.append(toColumns(action.getColumnItems()));
return columnString = columnsBuilder.toString();
}
public String toColumns(List columnItems) {
if (columnItems.isEmpty()) {
return "*";
}
StringBuilder columnsBuilder = new StringBuilder();
boolean comma = false;
for (ColumnItem columnItem : columnItems) {
if (comma) {
columnsBuilder.append(", ");
}
columnsBuilder.append(spliceColumn(columnItem));
String alias = columnItem.getAlias();
if (!Strings.isNullOrEmpty(alias) && dialect.columnAliasEnabled()) {
columnsBuilder.append(ALIAS_KEY).append(dialect.getIdentifierQuoteString()).append(alias)
.append(dialect.getIdentifierQuoteString());
}
comma = true;
}
return columnsBuilder.toString();
}
public String toSelectTables() {
StringBuilder tablesBuilder = new StringBuilder(PREFIX_FROM);
List tableItems = action.getTableItems();
boolean comma = false;
for (TableItem tableItem : tableItems) {
if (comma) {
tablesBuilder.append(", ");
}
tablesBuilder.append(spliceTable(tableItem));
////////////////////////////////////////////
// To optimize
////////////////////////////////////////////
// join 和 limit 同时存在时, 并且存在一对多或多对多的情况下, 分页会出问题.
// 这里将主表作为基础表(子查询), 进行Inner Join.
if (action.isJoin() && action.isLimit() && !action.isGroup() && action.isHandleJoinLimit()) {
tablesBuilder.append(toJoinLimit(tableItem));
}
comma = true;
}
return tableString = tablesBuilder.toString();
}
public String toJoinLimit(TableItem tableItem) {
List originalColumnItems = action.getColumnItems();
boolean distinct = action.isDistinct();
boolean handleJoinLimit = action.isHandleJoinLimit();
Table table = tableItem.getTable();
String originalTableAlias = tableItem.getAlias();
// 临时状态
String tempAliasPrefix = "inner_";
tableItem.setAlias(tempAliasPrefix + tableItem.getAlias());
for (JoinItem joinItem : action.getJoinItems()) {
TableItem joinTableItem = joinItem.getJoinItems().get(0).getRightColumn().getTableItem();
joinTableItem.setAlias(tempAliasPrefix + joinTableItem.getAlias());
}
List innerColumnItems = ActionUtil.createColumnItems(tableItem, false);
// 过滤 Json 字段类型, Json 类型无法与 distinct 一起使用
innerColumnItems = innerColumnItems.stream().filter(e -> !e.getColumn().getType().isJson())
.collect(Collectors.toList());
action.setColumnItems(innerColumnItems);
action.setDistinct(true);
action.setHandleJoinLimit(false);
// 构建子查询 SQL
action.build();
String innerSQL = action.getSql();
// 返回原始状态
tableItem.setAlias(tableItem.getAlias().replaceFirst(tempAliasPrefix, ""));
for (JoinItem joinItem : action.getJoinItems()) {
TableItem joinTableItem = joinItem.getJoinItems().get(0).getRightColumn().getTableItem();
joinTableItem.setAlias(joinTableItem.getAlias().replaceFirst(tempAliasPrefix, ""));
}
action.setColumnItems(originalColumnItems);
action.setDistinct(distinct);
action.setHandleJoinLimit(handleJoinLimit);
joinLimitFilterItems = Collections.emptyList();
joinLimit = true;
// splice join string
String joinTable = "(" + innerSQL + ")";
String joinTableAlias = ActionUtil.createTableAlias(tableItem.getTable());
String leftTableString = originalTableAlias;
String rightTableString = joinTableAlias;
Column joinColumn = (!table.getPrimaryKeys().isEmpty() ? table.getPrimaryKeys() : table.getColumns()).get(0);
String joinColumnString = process(joinColumn.getName());
return spliceJoin(joinTable, joinTableAlias, leftTableString, joinColumnString,
rightTableString, joinColumnString, JoinType.INNER);
}
public String toJoins() {
List joinItems = action.getJoinItems();
if (joinItems.isEmpty()) {
return "";
}
StringBuilder joinsBuilder = new StringBuilder();
for (JoinItem joinItem : joinItems) {
JoinType joinType = joinItem.getJoinType();
List innerJoinItemss = joinItem.getJoinItems();
boolean first = true;
for (SingleColumnJoinItem singleColumnJoinItem : innerJoinItemss) {
// join left table
ColumnItem leftColumnItem = singleColumnJoinItem.getLeftColumn();
TableItem leftTableItem = leftColumnItem.getTableItem();
Table leftTable = leftTableItem.getTable();
String leftTableAlias = leftTableItem.getAlias();
// join right table
ColumnItem rightColumnItem = singleColumnJoinItem.getRightColumn();
TableItem rightTableItem = rightColumnItem.getTableItem();
Table rightTable = rightTableItem.getTable();
String rightTableAlias = rightTableItem.getAlias();
// join elements
String joinTable = spliceTable(rightTable);
String joinTableAlias = !Strings.isNullOrEmpty(rightTableAlias) ? rightTableAlias : null;
String leftTableString = !Strings.isNullOrEmpty(leftTableAlias) ? leftTableAlias
: process(leftTable.getName());
String leftColumnString = process(leftColumnItem.getColumn().getName());
String rightTableString = !Strings.isNullOrEmpty(rightTableAlias) ? rightTableAlias
: process(rightTable.getName());
String rightColumnString = process(rightColumnItem.getColumn().getName());
String joinSpliceString = first
? spliceJoin(joinTable, joinTableAlias, leftTableString, leftColumnString, rightTableString,
rightColumnString, joinType)
: spliceJoin(leftTableString, leftColumnString, rightTableString, rightColumnString, DELIM_AND);
joinsBuilder.append(joinSpliceString);
first = false;
}
}
return joinString = joinsBuilder.toString();
}
private String spliceJoin(String joinTable, String joinTableAlias, String leftTableString, String leftColumnString,
String rightTableString,
String rightColumnString, JoinType joinType) {
StringBuilder joinsBuilder = new StringBuilder();
switch (joinType) {
case LEFT:
joinsBuilder.append(LEFT_OUTER_JOIN);
break;
case RIGHT:
joinsBuilder.append(RIGHT_OUTER_JOIN);
break;
case INNER:
joinsBuilder.append(INNER_JOIN);
break;
case FULL:
joinsBuilder.append(FULL_OUTER_JOIN);
break;
default:
throw new DataException(String.format("Wrong join type [%s]", joinType));
}
joinsBuilder.append(joinTable);
if (!Strings.isNullOrEmpty(joinTableAlias)) {
joinsBuilder.append(ALIAS_KEY).append(joinTableAlias);
}
String joinExpression = spliceJoin(leftTableString, leftColumnString, rightTableString, rightColumnString,
JOIN_ON);
joinsBuilder.append(joinExpression);
return joinsBuilder.toString();
}
private String spliceJoin(String leftTableString, String leftColumnString, String rightTableString,
String rightColumnString, String prefix) {
StringBuilder joinsBuilder = new StringBuilder();
joinsBuilder.append(prefix);
joinsBuilder.append(leftTableString);
joinsBuilder.append(".").append(leftColumnString);
joinsBuilder.append(" = ");
joinsBuilder.append(rightTableString);
joinsBuilder.append(".").append(rightColumnString);
return joinsBuilder.toString();
}
public String toWhere() {
// return whereString = joinLimit ? toWhere(joinLimitFilterItems) : toWhere(action.getFilterItems());
// Inner join causes query records to increase
return whereString = toWhere(action.getFilterItems());
}
public String toWhere(List filterItems) {
return toWhere(filterItems, true);
}
public String toWhere(List filterItems, boolean assignTableAlias) {
if (filterItems.isEmpty()) {
return "";
}
StringBuilder whereBuilder = new StringBuilder(PREFIX_WHERE);
boolean first = true;
for (FilterItem filterItem : filterItems) {
String filterSql = null;
if (filterItem instanceof StatementValueFilterItem) {
filterSql = toStatementValueFilter((StatementValueFilterItem) filterItem, assignTableAlias);
} else if (filterItem instanceof StatementFilterItem) {
filterSql = toStatementFilter((StatementFilterItem) filterItem);
} else {
filterSql = toFilter(filterItem, assignTableAlias);
}
if (first) {
// 去掉开头的连接符
filterSql = deleteFirstConnector(filterSql, filterItem.getConnector());
}
whereBuilder.append(filterSql);
first = false;
}
return whereBuilder.toString();
}
public String toFilter(FilterItem filterItem, boolean assignTableAlias) {
StringBuilder filterBuilder = new StringBuilder();
filterBuilder.append(" ").append(filterItem.getConnector()).append(" ");
// 嵌套子条件
List subFilterItems = filterItem.getSubFilterItems();
if (!subFilterItems.isEmpty()) {
StringBuilder subFilterBuilder = new StringBuilder();
subFilterItems.forEach(f -> subFilterBuilder.append(toFilter(f, assignTableAlias)));
// 去掉开头的连接符
String subFilterSql = deleteFirstConnector(subFilterBuilder.toString(),
subFilterItems.get(0).getConnector());
filterBuilder.append("(").append(subFilterSql).append(")");
return filterBuilder.toString();
}
ColumnItem columnItem = filterItem.getColumnItem();
filterBuilder.append(spliceColumn(columnItem, assignTableAlias));
filterBuilder.append(" ");
/////////////////
// optimize
/////////////////
if (filterItem.getValue() instanceof SQLValue) {
filterBuilder.append(filterItem.getOperator().sql()).append(" ")
.append(((SQLValue) filterItem.getValue()).sql());
return filterBuilder.toString();
}
Object value = filterItem.getRealValue();
Operator operator = filterItem.getOperator();
switch (operator) {
case EQUAL:
case NOT_EQUAL:
case LT:
case LTE:
case GT:
case GTE:
case LIKE:
case NOT_LIKE:
filterBuilder.append(operator.sql()).append(" ?");
params.add(value);
whereParams.add(value);
break;
case IN:
case NOT_IN:
Object[] inValue = (Object[]) value;
filterBuilder.append(operator.sql()).append(" (?").append(Strings.repeat(",?", inValue.length - 1))
.append(")");
List inValueList = Arrays.asList(inValue);
params.addAll(inValueList);
whereParams.addAll(inValueList);
break;
case IN_SQL:
case NOT_IN_SQL:
filterBuilder.append(operator.sql()).append(" (").append(value.toString()).append(")");
break;
case BETWEEN:
filterBuilder.append("between ? and ?");
List betweenValueList = Arrays.asList((Object[]) value);
params.addAll(betweenValueList);
whereParams.addAll(betweenValueList);
break;
case NULL:
case NOT_NULL:
filterBuilder.append(operator.sql());
break;
default:
break;
}
return filterBuilder.toString();
}
public String toStatementValueFilter(StatementValueFilterItem filterItem, boolean assignTableAlias) {
StringBuilder filterBuilder = new StringBuilder();
filterBuilder.append(" ").append(filterItem.getConnector()).append(" ");
ColumnItem columnItem = filterItem.getColumnItem();
filterBuilder.append(spliceColumn(columnItem, assignTableAlias));
filterBuilder.append(" ");
Object value = filterItem.getValue();
Operator operator = filterItem.getOperator();
switch (operator) {
case EQUAL:
case STRONG_EQUAL:
case NOT_EQUAL:
case LT:
case LTE:
case GT:
case GTE:
case LIKE:
case NOT_LIKE:
filterBuilder.append(operator.sql()).append(" ").append(value.toString());
params.add(value);
whereParams.add(value);
break;
case IN:
case NOT_IN:
filterBuilder.append(operator.sql()).append(" (").append(value.toString()).append(")");
break;
default:
break;
}
return filterBuilder.toString();
}
public String toStatementFilter(StatementFilterItem filterItem) {
StringBuilder filterBuilder = new StringBuilder();
filterBuilder.append(" ").append(filterItem.getConnector()).append(" ");
filterBuilder.append(filterItem.getValue().toString());
return filterBuilder.toString();
}
public String toGroups() {
List groupItems = action.getGroupItems();
if (groupItems.isEmpty()) {
return "";
}
StringBuilder groupsBuilder = new StringBuilder(PREFIX_GROUP_BY);
boolean comma = false;
for (GroupItem groupItem : groupItems) {
if (comma) {
groupsBuilder.append(", ");
}
ColumnItem columnItem = groupItem.getColumnItem();
if (!Strings.isNullOrEmpty(columnItem.getAlias()) && columnItem.isCustomAlias()) {
groupsBuilder.append(dialect.getIdentifierQuoteString()).append(columnItem.getAlias())
.append(dialect.getIdentifierQuoteString());
} else {
groupsBuilder.append(spliceColumn(columnItem));
}
comma = true;
}
return groupString = groupsBuilder.toString();
}
public String toOrders() {
return orderString = toOrders(action.getOrderItems());
}
public String toOrders(List orderItems) {
return toOrders(orderItems, true);
}
public String toOrders(List orderItems, boolean assignTableAlias) {
if (orderItems.isEmpty()) {
return "";
}
StringBuilder ordersBuilder = new StringBuilder(PREFIX_ORDER_BY);
boolean comma = false;
for (OrderItem orderItem : orderItems) {
if (comma) {
ordersBuilder.append(", ");
}
ColumnItem columnItem = orderItem.getColumnItem();
if (!Strings.isNullOrEmpty(columnItem.getAlias()) && columnItem.isCustomAlias()) {
ordersBuilder.append(dialect.getIdentifierQuoteString()).append(columnItem.getAlias())
.append(dialect.getIdentifierQuoteString());
} else {
ordersBuilder.append(spliceColumn(columnItem, assignTableAlias));
}
if (orderItem.getOrder() == Order.DESC) {
ordersBuilder.append(ORDER_DESC);
} else {
ordersBuilder.append(ORDER_ASC);
}
comma = true;
}
return orderString = ordersBuilder.toString();
}
public String toLimit() {
if (joinLimit) {
return "";
}
LimitItem limitItem = action.getLimitItem();
if (limitItem == null) {
return "";
}
params.add(limitItem.getLimit());
params.add(limitItem.getStart());
limitString = new StringBuilder().append(LIMIT).append("?").append(OFFSET).append("?").toString();
return limitString;
}
public String toInsertTable() {
StringBuilder tableBuilder = new StringBuilder(PREFIX_INSERT_INTO);
tableBuilder.append(spliceTable(action.getPrimaryTable()));
return tableString = tableBuilder.toString();
}
public String toInsertValues() {
List> insertValueItems = action.getInsertValueItems();
List valueItems = insertValueItems.get(0);
StringBuilder valuesBuilder = new StringBuilder();
StringBuilder tempColumnsBuilder = new StringBuilder("(");
StringBuilder tempValuesBuilder = new StringBuilder(" VALUES(");
boolean comma = false;
for (ValueItem valueItem : valueItems) {
if (comma) {
tempColumnsBuilder.append(", ");
tempValuesBuilder.append(", ");
}
Column column = valueItem.getColumn();
Object value = valueItem.getRealValue();
tempColumnsBuilder.append(process(column.getName()));
if (column.getType().isJson()) {
tempValuesBuilder.append(dialect.getJsonPlaceholder());
} else {
tempValuesBuilder.append("?");
}
params.add(processColumnValue(column, value));
comma = true;
}
tempColumnsBuilder.append(")");
tempValuesBuilder.append(")");
valuesBuilder.append(tempColumnsBuilder).append(tempValuesBuilder);
return valueString = valuesBuilder.toString();
}
public String toUpdateTable() {
StringBuilder tableBuilder = new StringBuilder(PREFIX_UPDATE);
tableBuilder.append(spliceTable(action.getPrimaryTable()));
return tableString = tableBuilder.toString();
}
public String toUpdateValues() {
List valueItems = action.getUpdateValueItem();
StringBuilder valuesBuilder = new StringBuilder(UPDATE_SET);
boolean comma = false;
for (ValueItem valueItem : valueItems) {
if (comma) {
valuesBuilder.append(", ");
}
Column column = valueItem.getColumn();
Object value = valueItem.getRealValue();
valuesBuilder.append(process(column.getName())).append(" = ");
if (column.getType().isJson()) {
valuesBuilder.append(dialect.getJsonPlaceholder());
} else {
valuesBuilder.append("?");
}
params.add(processColumnValue(column, value));
comma = true;
}
return valueString = valuesBuilder.toString();
}
public Object processColumnValue(Column column, Object value) {
return value;
}
public String toDeleteTable() {
StringBuilder tableBuilder = new StringBuilder(PREFIX_DELETE_FROM);
tableBuilder.append(spliceTable(action.getPrimaryTable()));
return tableString = tableBuilder.toString();
}
public String deleteFirstConnector(String sql, Connector connector) {
switch (connector) {
case AND:
return sql.replaceFirst(DELIM_AND, "");
case OR:
return sql.replaceFirst(DELIM_OR, "");
default:
return sql;
}
}
public String spliceTable(TableItem tableItem) {
StringBuilder tableBuilder = new StringBuilder();
Table table = tableItem.getTable();
tableBuilder.append(table != null ? spliceTable(table) : spliceTable(tableItem.getExpression()));
String alias = tableItem.getAlias();
if (!Strings.isNullOrEmpty(alias) && dialect.tableAliasEnabled()) {
tableBuilder.append(ALIAS_KEY).append(alias);
}
return tableBuilder.toString();
}
public String spliceTable(Table table) {
StringBuilder tableBuilder = new StringBuilder();
if (dialect.schemaPrefix()) {
Schema schema = table.getSchema();
tableBuilder.append(process(schema.getName())).append(".");
}
tableBuilder.append(process(table.getName()));
return tableBuilder.toString();
}
public String spliceTable(String expression) {
return expression;
}
public String spliceColumn(ColumnItem columnItem) {
return spliceColumn(columnItem, true);
}
/**
* 拼接列 在启动了表别名的情况下, 如果所属表指定了别名, 以表别名作为前缀, 否则以表名作为前缀. 如果没有启动表别名, 不添加前缀
*
* @param columnItem
* @param assignTableAlias
* @return 拼接列后的字符串
*/
public String spliceColumn(ColumnItem columnItem, boolean assignTableAlias) {
StringBuilder columnBuilder = new StringBuilder();
Column column = columnItem.getColumn();
if (column == null) {
columnBuilder.append(processExpression(columnItem.getExpression()));
} else {
if (dialect.tableAliasEnabled() && assignTableAlias) {
TableItem tableItem = columnItem.getTableItem();
String tableAlias = tableItem.getAlias();
if (!Strings.isNullOrEmpty(tableAlias)) {
columnBuilder.append(tableAlias);
} else {
Table table = tableItem.getTable();
if (table != null) {
columnBuilder.append(table.getName());
}
}
columnBuilder.append(".");
}
columnBuilder.append(process(column.getName()));
}
return columnBuilder.toString();
}
/**
* 拼接 GROUP/WHERE/ORDER 列
* 在启动了表别名的而情况下, 如果所属表指定了别名, 以表别名作为前缀, 否则以表名作为前缀. 如果没有启动表别名, 不添加前缀
*
* @param columnItem
* @return 拼接条件列后的字符串
*/
public String spliceCondColumn(ColumnItem columnItem) {
StringBuilder columnBuilder = new StringBuilder();
Column column = columnItem.getColumn();
if (column == null) {
columnBuilder.append(columnItem.getExpression());
} else {
if (dialect.tableAliasEnabled()) {
TableItem tableItem = columnItem.getTableItem();
String tableAlias = tableItem.getAlias();
if (!Strings.isNullOrEmpty(tableAlias)) {
columnBuilder.append(tableAlias);
} else {
Table table = tableItem.getTable();
if (table != null) {
columnBuilder.append(table.getName());
}
}
columnBuilder.append(".");
}
if (dialect.columnAliasEnabled() && !Strings.isNullOrEmpty(columnItem.getAlias())) {
columnBuilder.append(columnItem.getAlias());
} else {
columnBuilder.append(process(column.getName()));
}
}
return columnBuilder.toString();
}
public String process(String element) {
return dialect.processKeyword(element);
}
private String processExpression(String element) {
if (Strings.isNullOrEmpty(element)) {
return element;
}
// check function expression
element = matchFunction(element);
return element;
}
private String matchFunction(String element) {
Matcher matcher = FUNCTION_PATTERN.matcher(element);
if (matcher.find()) {
matcher.reset();
StringBuffer buffer = new StringBuffer();
while (matcher.find()) {
// If a function exists, it is treated as a function; otherwise, the $prefix is removed to match the data source function
String processFunction;
String func = matcher.group(FUNCTION_MATCHER_GROUP_FUNC);
String args = matcher.group(FUNCTION_MATCHER_GROUP_ARGS);
// Replace table alias
args = replaceTableWithAlias(args);
if (dialect.hasFunction(func)) {
processFunction = dialect.getFunction(func).convert(func, args);
} else {
// processFunction = matcher.group().substring(1);
processFunction = func + "(" + args + ")";
}
matcher.appendReplacement(buffer, processFunction);
}
matcher.appendTail(buffer);
return matchFunction(buffer.toString());
} else {
return element;
}
}
private String replaceTableWithAlias(String expression) {
if (Strings.isNullOrEmpty(expression)) {
return expression;
}
Matcher matcher = SOURCE_TABLE_COLUMN.matcher(expression);
if (matcher.find()) {
matcher.reset();
StringBuffer buffer = new StringBuffer();
while (matcher.find()) {
String processExpression = matcher.group();
String tableName = matcher.group(MATCHER_GROUP_TABLE);
Table table = dataContext.getTable(tableName);
if (table != null) {
String tableAlias = getTableAlias(tableName);
if (!Strings.isNullOrEmpty(tableAlias)) {
processExpression = processExpression.replace(tableName, tableAlias);
}
}
matcher.appendReplacement(buffer, processExpression);
}
matcher.appendTail(buffer);
return matchFunction(buffer.toString());
} else {
return expression;
}
}
/**
* Find table alias, priority primary table
* To do optimize
*
* @param tableName
* @return
*/
private String getTableAlias(String tableName) {
for (TableItem tableItem : action.getTableItems()) {
if (tableItem.getTable() != null && tableItem.getTable().getName().equalsIgnoreCase(tableName)) {
return tableItem.getAlias();
}
}
for (JoinItem joinItem : action.getJoinItems()) {
TableItem joinTableItem = joinItem.getJoinItems().get(0).getRightColumn().getTableItem();
if (joinTableItem.getTable() != null && joinTableItem.getTable().getName().equalsIgnoreCase(tableName)) {
return joinTableItem.getAlias();
}
}
return null;
}
public String countSql() {
List columnItems = action.isGroup()
// Only query the group field
? action.getGroupItems().stream().map(GroupItem::getColumnItem).collect(Collectors.toList())
// Only query the primary table fields
// Do not query json fields because json fields cannot be used with distinct
: action.getColumnItems().stream().filter(e -> e.getColumn() != null
&& !e.getColumn().getType().isJson() && !(e instanceof JoinColumnItem))
.collect(Collectors.toList());
String columnsString = toColumns(columnItems);
StringBuilder originalBuilder = new StringBuilder();
// Original SQL
// Remove the LIMIT condition
String originalSql = originalBuilder.append(PREFIX_SELECT_DISTINCT).append(columnsString)
.append(" ").append(tableString).append(joinString).append(whereString).append(groupString).toString();
originalSql = originalSql.replace(Strings.nullToEmpty(limitString), "");
StringBuilder countBuilder = new StringBuilder();
StringBuilder countSql = countBuilder.append(PREFIX_SELECT).append(COUNT).append(ALIAS_KEY).append("count")
.append(PREFIX_FROM).append("(").append(originalSql).append(")").append(ALIAS_KEY)
.append("original_table");
return countSql.toString();
}
public List countParams() {
return whereParams;
}
public void clear() {
sql = null;
params.clear();;
whereParams.clear();
joinLimit = false;
joinLimitFilterItems.clear();;
columnString = "";
tableString = "";
joinString = "";
whereString = "";
groupString = "";
orderString = "";
limitString = "";
valueString = "";
}
public String getSql() {
return sql;
}
public void setSql(String sql) {
this.sql = sql;
}
public List getParams() {
return params;
}
public void setParams(List params) {
this.params = params;
}
}