mirror of
https://gitee.com/mybatis-flex/mybatis-flex.git
synced 2025-12-07 09:08:24 +08:00
feat: QueryWrapper 添加 "delete" 与 "update" 的 left join 支持
This commit is contained in:
parent
79d7b2c934
commit
bf23e81e20
@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
@ -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) {
|
||||
|
||||
@ -71,7 +71,7 @@ public class OperatorSelectCondition extends QueryCondition {
|
||||
|
||||
@Override
|
||||
public Object getValue() {
|
||||
return queryWrapper.getValueArray();
|
||||
return queryWrapper.getAllValueArray();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@ -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
|
||||
|
||||
@ -58,7 +58,7 @@ public class SelectQueryColumn extends QueryColumn implements HasParamsColumn {
|
||||
|
||||
@Override
|
||||
public Object[] getParamValues() {
|
||||
return queryWrapper.getValueArray();
|
||||
return queryWrapper.getAllValueArray();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -42,7 +42,7 @@ public class SelectQueryTable extends QueryTable {
|
||||
|
||||
@Override
|
||||
Object[] getValueArray() {
|
||||
return queryWrapper.getValueArray();
|
||||
return queryWrapper.getAllValueArray();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@ -44,7 +44,7 @@ public class WithSelectDetail implements WithDetail {
|
||||
|
||||
@Override
|
||||
public Object[] getParamValues() {
|
||||
return queryWrapper.getValueArray();
|
||||
return queryWrapper.getAllValueArray();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@ -57,7 +57,7 @@ public class WithValuesDetail implements WithDetail {
|
||||
|
||||
@Override
|
||||
public Object[] getParamValues() {
|
||||
return queryWrapper.getValueArray();
|
||||
return queryWrapper.getAllValueArray();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@ -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());
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user