feat: QueryWrapper 添加 "delete" 与 "update" 的 left join 支持

This commit is contained in:
开源海哥 2023-08-09 12:01:36 +08:00
parent 79d7b2c934
commit bf23e81e20
10 changed files with 148 additions and 36 deletions

View File

@ -242,7 +242,7 @@ public class CommonsDialectImpl implements IDialect {
@Override
public String forUpdateByQuery(QueryWrapper queryWrapper, Row row) {
StringBuilder sql = new StringBuilder();
StringBuilder sqlBuilder = new StringBuilder();
Set<String> modifyAttrs = RowCPI.getModifyAttrs(row);
Map<String, RawValue> rawValueMap = RowCPI.getRawValueMap(row);
@ -254,30 +254,39 @@ public class CommonsDialectImpl implements IDialect {
//fix: support schema
QueryTable queryTable = queryTables.get(0);
sql.append(UPDATE).append(queryTable.toSql(this)).append(SET);
sqlBuilder.append(UPDATE).append(queryTable.toSql(this)).append(SET);
int index = 0;
for (String modifyAttr : modifyAttrs) {
if (index > 0) {
sql.append(DELIMITER);
sqlBuilder.append(DELIMITER);
}
sql.append(wrap(modifyAttr));
sqlBuilder.append(wrap(modifyAttr));
if (rawValueMap.containsKey(modifyAttr)) {
sql.append(EQUALS).append(rawValueMap.get(modifyAttr).toSql(this));
sqlBuilder.append(EQUALS).append(rawValueMap.get(modifyAttr).toSql(this));
} else {
sql.append(EQUALS_PLACEHOLDER);
sqlBuilder.append(EQUALS_PLACEHOLDER);
}
index++;
}
String whereConditionSql = buildWhereConditionSql(queryWrapper);
if (StringUtil.isNotBlank(whereConditionSql)) {
sql.append(WHERE).append(whereConditionSql);
buildJoinSql(sqlBuilder, queryWrapper, queryTables);
buildWhereSql(sqlBuilder, queryWrapper, queryTables, false);
buildGroupBySql(sqlBuilder, queryWrapper, queryTables);
buildHavingSql(sqlBuilder, queryWrapper, queryTables);
//ignore orderBy and limit
buildOrderBySql(sqlBuilder, queryWrapper, queryTables);
Long limitRows = CPI.getLimitRows(queryWrapper);
Long limitOffset = CPI.getLimitOffset(queryWrapper);
if (limitRows != null || limitOffset != null) {
sqlBuilder = buildLimitOffsetSql(sqlBuilder, queryWrapper, limitRows, limitOffset);
}
return sql.toString();
return sqlBuilder.toString();
}
@Override
@ -473,8 +482,13 @@ public class CommonsDialectImpl implements IDialect {
buildHavingSql(sqlBuilder, queryWrapper, allTables);
//ignore orderBy and limit
//buildOrderBySql(sqlBuilder, queryWrapper)
//buildLimitSql(sqlBuilder, queryWrapper)
buildOrderBySql(sqlBuilder, queryWrapper, allTables);
Long limitRows = CPI.getLimitRows(queryWrapper);
Long limitOffset = CPI.getLimitOffset(queryWrapper);
if (limitRows != null || limitOffset != null) {
sqlBuilder = buildLimitOffsetSql(sqlBuilder, queryWrapper, limitRows, limitOffset);
}
List<String> endFragments = CPI.getEndFragments(queryWrapper);
if (CollectionUtil.isNotEmpty(endFragments)) {
@ -777,13 +791,19 @@ public class CommonsDialectImpl implements IDialect {
@Override
public String forUpdateEntityByQuery(TableInfo tableInfo, Object entity, boolean ignoreNulls, QueryWrapper queryWrapper) {
StringBuilder sql = new StringBuilder();
StringBuilder sqlBuilder = new StringBuilder();
Set<String> updateColumns = tableInfo.obtainUpdateColumns(entity, ignoreNulls, true);
Map<String, RawValue> rawValueMap = tableInfo.obtainUpdateRawValueMap(entity);
sql.append(UPDATE).append(forHint(CPI.getHint(queryWrapper)));
sql.append(tableInfo.getWrapSchemaAndTableName(this)).append(SET);
sqlBuilder.append(UPDATE).append(forHint(CPI.getHint(queryWrapper)));
sqlBuilder.append(tableInfo.getWrapSchemaAndTableName(this));
List<QueryTable> queryTables = CPI.getQueryTables(queryWrapper);
buildJoinSql(sqlBuilder, queryWrapper, queryTables);
sqlBuilder.append(SET);
StringJoiner stringJoiner = new StringJoiner(DELIMITER);
@ -807,26 +827,40 @@ public class CommonsDialectImpl implements IDialect {
stringJoiner.add(wrap(versionColumn) + EQUALS + wrap(versionColumn) + " + 1 ");
}
sql.append(stringJoiner);
sqlBuilder.append(stringJoiner);
String whereConditionSql = buildWhereConditionSql(queryWrapper);
buildWhereSql(sqlBuilder, queryWrapper, queryTables, false);
buildGroupBySql(sqlBuilder, queryWrapper, queryTables);
buildHavingSql(sqlBuilder, queryWrapper, queryTables);
//不允许全量更新
if (StringUtil.isBlank(whereConditionSql)) {
throw FlexExceptions.wrap(LocalizedFormats.UPDATE_OR_DELETE_NOT_ALLOW);
//ignore orderBy and limit
buildOrderBySql(sqlBuilder, queryWrapper, queryTables);
Long limitRows = CPI.getLimitRows(queryWrapper);
Long limitOffset = CPI.getLimitOffset(queryWrapper);
if (limitRows != null || limitOffset != null) {
sqlBuilder = buildLimitOffsetSql(sqlBuilder, queryWrapper, limitRows, limitOffset);
}
sql.append(WHERE).append(whereConditionSql);
// String whereConditionSql = buildWhereConditionSql(queryWrapper);
//
// //不允许全量更新
// if (StringUtil.isBlank(whereConditionSql)) {
// throw FlexExceptions.wrap(LocalizedFormats.UPDATE_OR_DELETE_NOT_ALLOW);
// }
//
// sql.append(WHERE).append(whereConditionSql);
List<String> endFragments = CPI.getEndFragments(queryWrapper);
if (CollectionUtil.isNotEmpty(endFragments)) {
for (String endFragment : endFragments) {
sql.append(BLANK).append(endFragment);
sqlBuilder.append(BLANK).append(endFragment);
}
}
return sql.toString();
return sqlBuilder.toString();
}
@ -973,16 +1007,19 @@ public class CommonsDialectImpl implements IDialect {
}
protected void buildJoinSql(StringBuilder sqlBuilder, QueryWrapper queryWrapper, List<QueryTable> queryTables) {
protected boolean buildJoinSql(StringBuilder sqlBuilder, QueryWrapper queryWrapper, List<QueryTable> queryTables) {
List<Join> joins = CPI.getJoins(queryWrapper);
boolean joinSuccess = false;
if (joins != null && !joins.isEmpty()) {
for (Join join : joins) {
if (!join.checkEffective()) {
continue;
}
sqlBuilder.append(join.toSql(queryTables, this));
joinSuccess = true;
}
}
return joinSuccess;
}

View File

@ -261,7 +261,9 @@ public class EntitySqlProvider {
FlexAssert.notNull(entity, "entity can not be null");
boolean ignoreNulls = ProviderUtil.isIgnoreNulls(params);
QueryWrapper queryWrapper = ProviderUtil.getQueryWrapper(params);
appendTableConditions(context,queryWrapper,false);
TableInfo tableInfo = ProviderUtil.getTableInfo(context);
@ -274,9 +276,13 @@ public class EntitySqlProvider {
//优先构建 sql再构建参数
String sql = DialectFactory.getDialect().forUpdateEntityByQuery(tableInfo, entity, ignoreNulls, queryWrapper);
Object[] joinValueArray = CPI.getJoinValueArray(queryWrapper);
Object[] values = tableInfo.buildUpdateSqlArgs(entity, ignoreNulls, true);
Object[] queryParams = CPI.getValueArray(queryWrapper);
ProviderUtil.setSqlArgs(params, ArrayUtil.concat(values, queryParams));
Object[] queryParams = CPI.getConditionValueArray(queryWrapper);
Object[] paramValues = ArrayUtil.concat(joinValueArray,ArrayUtil.concat(values,queryParams));
ProviderUtil.setSqlArgs(params, paramValues);
return sql;
}

View File

@ -34,7 +34,15 @@ public class CPI {
}
public static Object[] getValueArray(QueryWrapper queryWrapper) {
return queryWrapper.getValueArray();
return queryWrapper.getAllValueArray();
}
public static Object[] getJoinValueArray(QueryWrapper queryWrapper) {
return queryWrapper.getJoinValueArray();
}
public static Object[] getConditionValueArray(QueryWrapper queryWrapper) {
return queryWrapper.getConditionValueArray();
}
public static List<QueryWrapper> getChildSelect(QueryWrapper queryWrapper) {

View File

@ -71,7 +71,7 @@ public class OperatorSelectCondition extends QueryCondition {
@Override
public Object getValue() {
return queryWrapper.getValueArray();
return queryWrapper.getAllValueArray();
}
@Override

View File

@ -692,7 +692,7 @@ public class QueryWrapper extends BaseQueryWrapper<QueryWrapper> {
* 获取 queryWrapper 的参数
* 在构建 sql 的时候需要保证 where having 的前面
*/
Object[] getValueArray() {
Object[] getAllValueArray() {
List<Object> withValues = null;
if (with != null) {
@ -770,7 +770,7 @@ public class QueryWrapper extends BaseQueryWrapper<QueryWrapper> {
if (CollectionUtil.isNotEmpty(unions)) {
for (UnionWrapper union : unions) {
QueryWrapper queryWrapper = union.getQueryWrapper();
paramValues = ArrayUtil.concat(paramValues, queryWrapper.getValueArray());
paramValues = ArrayUtil.concat(paramValues, queryWrapper.getAllValueArray());
}
}
@ -783,6 +783,67 @@ public class QueryWrapper extends BaseQueryWrapper<QueryWrapper> {
return returnValues;
}
/**
* 获取 queryWrapper 的参数
* 在构建 sql 的时候需要保证 where having 的前面
*/
Object[] getJoinValueArray() {
//join 子查询的参数left join (select ...)
List<Object> joinValues = null;
List<Join> joins = getJoins();
if (CollectionUtil.isNotEmpty(joins)) {
for (Join join : joins) {
QueryTable joinTable = join.getQueryTable();
Object[] valueArray = joinTable.getValueArray();
if (valueArray.length > 0) {
if (joinValues == null) {
joinValues = new ArrayList<>(valueArray.length);
}
joinValues.addAll(Arrays.asList(valueArray));
}
QueryCondition onCondition = join.getOnCondition();
Object[] values = WrapperUtil.getValues(onCondition);
if (values.length > 0) {
if (joinValues == null) {
joinValues = new ArrayList<>(values.length);
}
joinValues.addAll(Arrays.asList(values));
}
}
}
return joinValues == null ? FlexConsts.EMPTY_ARRAY : joinValues.toArray();
}
/**
* 获取 queryWrapper 的参数
* 在构建 sql 的时候需要保证 where having 的前面
*/
Object[] getConditionValueArray() {
//where 参数
Object[] whereValues = WrapperUtil.getValues(whereQueryCondition);
//having 参数
Object[] havingValues = WrapperUtil.getValues(havingQueryCondition);
Object[] paramValues = ArrayUtil.concat(whereValues, havingValues);
//unions 参数
if (CollectionUtil.isNotEmpty(unions)) {
for (UnionWrapper union : unions) {
QueryWrapper queryWrapper = union.getQueryWrapper();
paramValues = ArrayUtil.concat(paramValues, queryWrapper.getAllValueArray());
}
}
return paramValues;
}
List<QueryWrapper> getChildSelect() {
List<QueryWrapper> tableChildQuery = null;
@ -815,7 +876,7 @@ public class QueryWrapper extends BaseQueryWrapper<QueryWrapper> {
public String toSQL() {
String sql = DialectFactory.getDialect().forSelectByQuery(this);
return SqlUtil.replaceSqlParams(sql, getValueArray());
return SqlUtil.replaceSqlParams(sql, getAllValueArray());
}
@Override

View File

@ -58,7 +58,7 @@ public class SelectQueryColumn extends QueryColumn implements HasParamsColumn {
@Override
public Object[] getParamValues() {
return queryWrapper.getValueArray();
return queryWrapper.getAllValueArray();
}
}

View File

@ -42,7 +42,7 @@ public class SelectQueryTable extends QueryTable {
@Override
Object[] getValueArray() {
return queryWrapper.getValueArray();
return queryWrapper.getAllValueArray();
}
@Override

View File

@ -44,7 +44,7 @@ public class WithSelectDetail implements WithDetail {
@Override
public Object[] getParamValues() {
return queryWrapper.getValueArray();
return queryWrapper.getAllValueArray();
}
@Override

View File

@ -57,7 +57,7 @@ public class WithValuesDetail implements WithDetail {
@Override
public Object[] getParamValues() {
return queryWrapper.getValueArray();
return queryWrapper.getAllValueArray();
}
@Override

View File

@ -115,7 +115,7 @@ class WrapperUtil {
addParam(paras, Array.get(value, i));
}
} else if (value instanceof QueryWrapper) {
Object[] valueArray = ((QueryWrapper) value).getValueArray();
Object[] valueArray = ((QueryWrapper) value).getAllValueArray();
paras.addAll(Arrays.asList(valueArray));
} else if (value.getClass().isEnum()) {
EnumWrapper enumWrapper = EnumWrapper.of(value.getClass());