fxi(功能用例): 高级搜索部分条件查询有误
--task=1016128 --user=陈建星 高级搜索-视图增删改查-后端 https://www.tapd.cn/55049933/s/1573254
This commit is contained in:
parent
8a9808f541
commit
c0400c483d
|
@ -1,10 +1,12 @@
|
|||
package io.metersphere.sdk.dto;
|
||||
|
||||
import io.metersphere.sdk.constants.CustomFieldType;
|
||||
import io.metersphere.sdk.valid.EnumValue;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
import lombok.Data;
|
||||
import org.apache.commons.collections.CollectionUtils;
|
||||
import org.apache.commons.lang3.BooleanUtils;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
||||
import java.util.List;
|
||||
|
@ -35,6 +37,19 @@ public class CombineCondition {
|
|||
@EnumValue(enumClass = CombineConditionOperator.class)
|
||||
private String operator;
|
||||
|
||||
/**
|
||||
* 是否是多选自定义字段
|
||||
* BaseMapper.xml 中调用
|
||||
* @return
|
||||
*/
|
||||
public Boolean isMultipleCustomField() {
|
||||
if (BooleanUtils.isTrue(customField)) {
|
||||
return StringUtils.equalsAny(customFieldType, CustomFieldType.MULTIPLE_SELECT.name(),
|
||||
CustomFieldType.MULTIPLE_INPUT.name(), CustomFieldType.MULTIPLE_MEMBER.name(), CustomFieldType.CHECKBOX.name());
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean valid() {
|
||||
if (StringUtils.isBlank(name) || StringUtils.isBlank(operator)) {
|
||||
return false;
|
||||
|
|
|
@ -373,13 +373,13 @@
|
|||
</include>
|
||||
</if>
|
||||
<if test="condition.name == 'follower'">
|
||||
api_definition.id in (
|
||||
select api_definition_id from api_definition_follower where
|
||||
<include refid="io.metersphere.system.mapper.BaseMapper.condition">
|
||||
<include refid="io.metersphere.system.mapper.BaseMapper.associationCondition">
|
||||
<property name="mainIdColumn" value="api_definition.id"/>
|
||||
<property name="associationTable" value="api_definition_follower"/>
|
||||
<property name="associationIdColumn" value="api_definition_id"/>
|
||||
<property name="searchColumn" value="user_id"/>
|
||||
<property name="condition" value="condition"/>
|
||||
<property name="column" value="user_id"/>
|
||||
</include>
|
||||
)
|
||||
</if>
|
||||
<include refid="io.metersphere.system.mapper.BaseMapper.queryType">
|
||||
<property name="searchMode" value="${combineSearch}.searchMode"/>
|
||||
|
@ -418,15 +418,12 @@
|
|||
<property name="searchMode" value="${combineSearch}.searchMode"/>
|
||||
</include>
|
||||
</foreach>
|
||||
<if test="${combineSearch}.customFiledConditions.size() > 0">
|
||||
api_definition.id in (
|
||||
select api_id from api_definition_custom_field where
|
||||
<include refid="io.metersphere.system.mapper.BaseMapper.customFiledConditions">
|
||||
<property name="conditions" value="${combineSearch}.customFiledConditions"/>
|
||||
<property name="searchMode" value="${combineSearch}.searchMode"/>
|
||||
<property name="mainIdColumn" value="api_definition.id"/>
|
||||
<property name="associationTable" value="api_definition_custom_field"/>
|
||||
<property name="associationIdColumn" value="api_id"/>
|
||||
<property name="combineSearch" value="${combineSearch}"/>
|
||||
</include>
|
||||
)
|
||||
</if>
|
||||
</if>
|
||||
</trim>
|
||||
</sql>
|
||||
|
|
|
@ -144,16 +144,14 @@
|
|||
<property name="column" value="functional_case.create_user"/>
|
||||
</include>
|
||||
</if>
|
||||
<if test="condition.name == 'reviewUser'">
|
||||
crfc.case_id in (
|
||||
select case_id from case_review_functional_case_user
|
||||
where review_id = #{request.reviewId}
|
||||
and
|
||||
<include refid="io.metersphere.system.mapper.BaseMapper.condition">
|
||||
<if test="condition.name == 'reviewers'">
|
||||
<include refid="io.metersphere.system.mapper.BaseMapper.associationCondition">
|
||||
<property name="mainIdColumn" value="crfc.case_id"/>
|
||||
<property name="associationTable" value="case_review_functional_case_user"/>
|
||||
<property name="associationIdColumn" value="case_id"/>
|
||||
<property name="searchColumn" value="user_id"/>
|
||||
<property name="condition" value="condition"/>
|
||||
<property name="column" value="user_id"/>
|
||||
</include>
|
||||
)
|
||||
</if>
|
||||
<include refid="io.metersphere.system.mapper.BaseMapper.queryType">
|
||||
<property name="searchMode" value="${combineSearch}.searchMode"/>
|
||||
|
@ -170,37 +168,40 @@
|
|||
<property name="column" value="crfc.status"/>
|
||||
</include>
|
||||
</if>
|
||||
<if test="condition.name == 'demand'">
|
||||
functional_case.id in (
|
||||
select case_id from functional_case_demand where
|
||||
<if test="condition.name == 'lastExecuteResult'">
|
||||
<include refid="io.metersphere.system.mapper.BaseMapper.condition">
|
||||
<property name="condition" value="condition"/>
|
||||
<property name="column" value="demand_name"/>
|
||||
<property name="column" value="functional_case.last_execute_result"/>
|
||||
</include>
|
||||
</if>
|
||||
<if test="condition.name == 'demand'">
|
||||
<include refid="io.metersphere.system.mapper.BaseMapper.associationCondition">
|
||||
<property name="mainIdColumn" value="functional_case.id"/>
|
||||
<property name="associationTable" value="functional_case_demand"/>
|
||||
<property name="associationIdColumn" value="case_id"/>
|
||||
<property name="searchColumn" value="demand_name"/>
|
||||
<property name="condition" value="condition"/>
|
||||
</include>
|
||||
)
|
||||
</if>
|
||||
<if test="condition.name == 'attachment'">
|
||||
functional_case.id in (
|
||||
select case_id from functional_case_attachment where
|
||||
<include refid="io.metersphere.system.mapper.BaseMapper.condition">
|
||||
<include refid="io.metersphere.system.mapper.BaseMapper.associationCondition">
|
||||
<property name="mainIdColumn" value="functional_case.id"/>
|
||||
<property name="associationTable" value="functional_case_attachment"/>
|
||||
<property name="associationIdColumn" value="case_id"/>
|
||||
<property name="searchColumn" value="file_name"/>
|
||||
<property name="condition" value="condition"/>
|
||||
<property name="column" value="file_name"/>
|
||||
</include>
|
||||
)
|
||||
</if>
|
||||
<include refid="io.metersphere.system.mapper.BaseMapper.queryType">
|
||||
<property name="searchMode" value="${combineSearch}.searchMode"/>
|
||||
</include>
|
||||
</foreach>
|
||||
<if test="${combineSearch}.customFiledConditions.size() > 0">
|
||||
functional_case.id in (
|
||||
select case_id from functional_case_custom_field where
|
||||
<include refid="io.metersphere.system.mapper.BaseMapper.customFiledConditions">
|
||||
<property name="conditions" value="${combineSearch}.customFiledConditions"/>
|
||||
<property name="searchMode" value="${combineSearch}.searchMode"/>
|
||||
<property name="mainIdColumn" value="functional_case.id"/>
|
||||
<property name="associationTable" value="functional_case_custom_field"/>
|
||||
<property name="associationIdColumn" value="case_id"/>
|
||||
<property name="combineSearch" value="${combineSearch}"/>
|
||||
</include>
|
||||
)
|
||||
</if>
|
||||
</if>
|
||||
</trim>
|
||||
</sql>
|
||||
|
|
|
@ -292,13 +292,13 @@
|
|||
</include>
|
||||
</if>
|
||||
<if test="condition.name == 'follower'">
|
||||
functional_case.id in (
|
||||
select case_id from functional_case_follower where
|
||||
<include refid="io.metersphere.system.mapper.BaseMapper.condition">
|
||||
<include refid="io.metersphere.system.mapper.BaseMapper.associationCondition">
|
||||
<property name="mainIdColumn" value="functional_case.id"/>
|
||||
<property name="associationTable" value="functional_case_follower"/>
|
||||
<property name="associationIdColumn" value="case_id"/>
|
||||
<property name="searchColumn" value="user_id"/>
|
||||
<property name="condition" value="condition"/>
|
||||
<property name="column" value="user_id"/>
|
||||
</include>
|
||||
)
|
||||
</if>
|
||||
<include refid="io.metersphere.system.mapper.BaseMapper.queryType">
|
||||
<property name="searchMode" value="${combineSearch}.searchMode"/>
|
||||
|
@ -322,36 +322,33 @@
|
|||
</include>
|
||||
</if>
|
||||
<if test="condition.name == 'demand'">
|
||||
functional_case.id in (
|
||||
select case_id from functional_case_demand where
|
||||
<include refid="io.metersphere.system.mapper.BaseMapper.condition">
|
||||
<include refid="io.metersphere.system.mapper.BaseMapper.associationCondition">
|
||||
<property name="mainIdColumn" value="functional_case.id"/>
|
||||
<property name="associationTable" value="functional_case_demand"/>
|
||||
<property name="associationIdColumn" value="case_id"/>
|
||||
<property name="searchColumn" value="demand_name"/>
|
||||
<property name="condition" value="condition"/>
|
||||
<property name="column" value="demand_name"/>
|
||||
</include>
|
||||
)
|
||||
</if>
|
||||
<if test="condition.name == 'attachment'">
|
||||
functional_case.id in (
|
||||
select case_id from functional_case_attachment where
|
||||
<include refid="io.metersphere.system.mapper.BaseMapper.condition">
|
||||
<include refid="io.metersphere.system.mapper.BaseMapper.associationCondition">
|
||||
<property name="mainIdColumn" value="functional_case.id"/>
|
||||
<property name="associationTable" value="functional_case_attachment"/>
|
||||
<property name="associationIdColumn" value="case_id"/>
|
||||
<property name="searchColumn" value="file_name"/>
|
||||
<property name="condition" value="condition"/>
|
||||
<property name="column" value="file_name"/>
|
||||
</include>
|
||||
)
|
||||
</if>
|
||||
<include refid="io.metersphere.system.mapper.BaseMapper.queryType">
|
||||
<property name="searchMode" value="${combineSearch}.searchMode"/>
|
||||
</include>
|
||||
</foreach>
|
||||
<if test="${combineSearch}.customFiledConditions.size() > 0">
|
||||
functional_case.id in (
|
||||
select case_id from functional_case_custom_field where
|
||||
<include refid="io.metersphere.system.mapper.BaseMapper.customFiledConditions">
|
||||
<property name="conditions" value="${combineSearch}.customFiledConditions"/>
|
||||
<property name="searchMode" value="${combineSearch}.searchMode"/>
|
||||
<property name="mainIdColumn" value="functional_case.id"/>
|
||||
<property name="associationTable" value="functional_case_custom_field"/>
|
||||
<property name="associationIdColumn" value="case_id"/>
|
||||
<property name="combineSearch" value="${combineSearch}"/>
|
||||
</include>
|
||||
)
|
||||
</if>
|
||||
</if>
|
||||
</trim>
|
||||
</sql>
|
||||
|
@ -394,7 +391,6 @@
|
|||
group by ref_id
|
||||
</select>
|
||||
|
||||
|
||||
<update id="batchDelete">
|
||||
update functional_case
|
||||
set deleted = 1,
|
||||
|
|
|
@ -39,7 +39,7 @@ public enum InternalUserView {
|
|||
MY_REVIEW(() -> {
|
||||
UserViewDTO userViewDTO = getUserViewDTO("my_review");
|
||||
CombineCondition condition = new CombineCondition();
|
||||
condition.setName("reviewUser");
|
||||
condition.setName("reviewers");
|
||||
condition.setValue(getCurrentUserArrayValue());
|
||||
condition.setOperator(CombineCondition.CombineConditionOperator.IN.name());
|
||||
userViewDTO.setConditions(List.of(condition));
|
||||
|
|
|
@ -23,7 +23,15 @@ public class DBCombineSearch extends CombineSearch {
|
|||
*/
|
||||
private List<CombineCondition> systemFieldConditions;
|
||||
/**
|
||||
* 自定义字段筛选条件
|
||||
* 自定义字段为空的筛选条件
|
||||
*/
|
||||
private List<CombineCondition> customFiledEmptyConditions;
|
||||
/**
|
||||
* 自定义字段中 NOT_IN NOT_EQUALS NOT_CONTAINS COUNT_LT 的条件
|
||||
*/
|
||||
private List<CombineCondition> customFiledNoneConditions;
|
||||
/**
|
||||
* 其他的自定义字段筛选条件
|
||||
*/
|
||||
private List<CombineCondition> customFiledConditions;
|
||||
}
|
||||
|
|
|
@ -18,7 +18,10 @@ import org.aspectj.lang.annotation.Pointcut;
|
|||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* @Author: jianxing
|
||||
|
@ -63,13 +66,40 @@ public class BaseConditionFilterAspect {
|
|||
}
|
||||
List<CombineCondition> validConditions = getValidConditions(combineSearch.getConditions());
|
||||
replaceCurrentUser(validConditions);
|
||||
List<CombineCondition> systemFieldConditions = validConditions.stream().filter(item -> !BooleanUtils.isTrue(item.getCustomField())).toList();
|
||||
List<CombineCondition> customFieldConditions = validConditions.stream().filter(item -> BooleanUtils.isTrue(item.getCustomField())).toList();
|
||||
List<CombineCondition> systemFieldConditions = validConditions.stream()
|
||||
.filter(item -> !BooleanUtils.isTrue(item.getCustomField()))
|
||||
.toList();
|
||||
List<CombineCondition> customFieldConditions = validConditions.stream()
|
||||
.filter(item -> BooleanUtils.isTrue(item.getCustomField()))
|
||||
.collect(Collectors.toList());
|
||||
|
||||
// 拆分系统字段和自定义字段
|
||||
DBCombineSearch dbCombineSearch = BeanUtils.copyBean(new DBCombineSearch(), combineSearch);
|
||||
dbCombineSearch.setSystemFieldConditions(systemFieldConditions);
|
||||
|
||||
// 拆分自定义字段操作符为空的条件
|
||||
List<CombineCondition> customFiledEmptyConditions = new ArrayList<>(0);
|
||||
// 拆分自定义字段操作符为 NOT_IN NOT_EQUALS NOT_CONTAINS 的条件
|
||||
List<CombineCondition> customFiledNoneConditions = new ArrayList<>(0);
|
||||
Iterator<CombineCondition> iterator = customFieldConditions.iterator();
|
||||
while (iterator.hasNext()) {
|
||||
CombineCondition customFieldCondition = iterator.next();
|
||||
if (StringUtils.equalsAny(customFieldCondition.getOperator(), CombineCondition.CombineConditionOperator.EMPTY.name())) {
|
||||
customFiledEmptyConditions.add(customFieldCondition);
|
||||
iterator.remove();
|
||||
} else if (StringUtils.equalsAny(customFieldCondition.getOperator(),
|
||||
CombineCondition.CombineConditionOperator.COUNT_LT.name(),
|
||||
CombineCondition.CombineConditionOperator.NOT_IN.name(),
|
||||
CombineCondition.CombineConditionOperator.NOT_EQUALS.name(),
|
||||
CombineCondition.CombineConditionOperator.NOT_CONTAINS.name())) {
|
||||
customFiledNoneConditions.add(customFieldCondition);
|
||||
iterator.remove();
|
||||
}
|
||||
}
|
||||
dbCombineSearch.setCustomFiledEmptyConditions(customFiledEmptyConditions);
|
||||
dbCombineSearch.setCustomFiledNoneConditions(customFiledNoneConditions);
|
||||
dbCombineSearch.setCustomFiledConditions(customFieldConditions);
|
||||
|
||||
baseCondition.setCombineSearch(dbCombineSearch);
|
||||
|
||||
// 处理视图查询条件
|
||||
|
|
|
@ -54,13 +54,65 @@
|
|||
</sql>
|
||||
|
||||
<sql id="customFiledConditions">
|
||||
<trim suffixOverrides="AND|OR">
|
||||
<foreach collection="${conditions}" item="condition">
|
||||
<trim prefix="(" suffix=")">
|
||||
field_id = #{condition.name}
|
||||
and
|
||||
<if test="${combineSearch}.customFiledEmptyConditions.size() > 0">
|
||||
<foreach collection="${combineSearch}.customFiledEmptyConditions" item="condition">
|
||||
${mainIdColumn} not in (
|
||||
select ${associationIdColumn} from ${associationTable} where
|
||||
field_id = #{condition.name} and
|
||||
`value` is not null and `value` != ''
|
||||
<if test="condition.customFieldType != null and condition.isMultipleCustomField()">
|
||||
and `value` != '[]'
|
||||
</if>
|
||||
)
|
||||
<include refid="io.metersphere.system.mapper.BaseMapper.queryType">
|
||||
<property name="searchMode" value="${combineSearch}.searchMode"/>
|
||||
</include>
|
||||
</foreach>
|
||||
</if>
|
||||
|
||||
<if test="${combineSearch}.customFiledNoneConditions.size() > 0">
|
||||
<foreach collection="${combineSearch}.customFiledNoneConditions" item="condition">
|
||||
${mainIdColumn} not in (
|
||||
select ${associationIdColumn} from ${associationTable} where
|
||||
field_id = #{condition.name} and
|
||||
`value` is not null and `value` != ''
|
||||
<if test="condition.customFieldType != null and condition.isMultipleCustomField()">
|
||||
and `value` != '[]'
|
||||
</if>
|
||||
) or
|
||||
${mainIdColumn} in (
|
||||
select ${associationIdColumn} from ${associationTable} where
|
||||
field_id = #{condition.name} and
|
||||
<choose>
|
||||
<when test="condition.customFieldType != null and (condition.customFieldType == 'MULTIPLE_SELECT' or condition.customFieldType == 'MULTIPLE_SELECT' or condition.customFieldType == 'MULTIPLE_INPUT')">
|
||||
<when test="condition.customFieldType != null and condition.isMultipleCustomField()">
|
||||
<include refid="io.metersphere.system.mapper.BaseMapper.arrayValueCondition">
|
||||
<property name="condition" value="condition"/>
|
||||
<property name="column" value="value"/>
|
||||
</include>
|
||||
</when>
|
||||
<otherwise>
|
||||
<include refid="io.metersphere.system.mapper.BaseMapper.condition">
|
||||
<property name="condition" value="condition"/>
|
||||
<property name="column" value="value"/>
|
||||
</include>
|
||||
</otherwise>
|
||||
</choose>
|
||||
)
|
||||
<include refid="io.metersphere.system.mapper.BaseMapper.queryType">
|
||||
<property name="searchMode" value="${combineSearch}.searchMode"/>
|
||||
</include>
|
||||
</foreach>
|
||||
</if>
|
||||
|
||||
<if test="${combineSearch}.customFiledConditions.size() > 0">
|
||||
${mainIdColumn} in (
|
||||
select ${associationIdColumn} from ${associationTable} where
|
||||
<trim suffixOverrides="AND|OR">
|
||||
<foreach collection="${combineSearch}.customFiledConditions" item="condition">
|
||||
<trim prefix="(" suffix=")">
|
||||
field_id = #{condition.name} and
|
||||
<choose>
|
||||
<when test="condition.customFieldType != null and condition.isMultipleCustomField()">
|
||||
<include refid="io.metersphere.system.mapper.BaseMapper.arrayValueCondition">
|
||||
<property name="condition" value="condition"/>
|
||||
<property name="column" value="value"/>
|
||||
|
@ -75,10 +127,12 @@
|
|||
</choose>
|
||||
</trim>
|
||||
<include refid="io.metersphere.system.mapper.BaseMapper.queryType">
|
||||
<property name="searchMode" value="${searchMode}"/>
|
||||
<property name="searchMode" value="${combineSearch}.searchMode"/>
|
||||
</include>
|
||||
</foreach>
|
||||
</trim>
|
||||
)
|
||||
</if>
|
||||
</sql>
|
||||
|
||||
<sql id="arrayValueCondition">
|
||||
|
@ -117,12 +171,40 @@
|
|||
${column} is null or ${column} = '[]'
|
||||
</when>
|
||||
<when test="${condition}.operator == 'NOT_EMPTY'">
|
||||
${column} is not null and ${column} = '[]'
|
||||
${column} is not null and ${column} != '[]'
|
||||
</when>
|
||||
</choose>
|
||||
</trim>
|
||||
</sql>
|
||||
|
||||
<sql id="associationCondition">
|
||||
<choose>
|
||||
<when test="${condition}.operator == 'EMPTY'">
|
||||
${mainIdColumn} not in (
|
||||
select ${associationIdColumn} from ${associationTable} where
|
||||
${searchColumn} is not null and ${searchColumn} != ''
|
||||
)
|
||||
</when>
|
||||
<otherwise>
|
||||
(
|
||||
<if test="${condition}.operator == 'NOT_IN' or ${condition}.operator == 'NOT_EQUALS' or ${condition}.operator == 'NOT_CONTAINS'">
|
||||
${mainIdColumn} not in (
|
||||
select ${associationIdColumn} from ${associationTable} where
|
||||
${searchColumn} is not null and ${searchColumn} != ''
|
||||
) or
|
||||
</if>
|
||||
${mainIdColumn} in (
|
||||
select ${associationIdColumn} from ${associationTable} where
|
||||
<include refid="io.metersphere.system.mapper.BaseMapper.condition">
|
||||
<property name="condition" value="${condition}"/>
|
||||
<property name="column" value="${searchColumn}"/>
|
||||
</include>
|
||||
)
|
||||
)
|
||||
</otherwise>
|
||||
</choose>
|
||||
</sql>
|
||||
|
||||
<sql id="condition">
|
||||
<trim prefix="(" suffix=")">
|
||||
<choose>
|
||||
|
|
Loading…
Reference in New Issue