Browse Source

Thread OR operation through DefaultEntityQueryRepository query building

- Read keyFiltersOperationOrDefault in countEntitiesByQuery and findEntityDataByQuery
- Under OR: relocate entity field filter predicates from inner WHERE to outer WHERE
- Under OR: pass forceLeftJoin=true to buildLatestJoins for all aliases
- Under OR: combine all filter mappings with OR joiner via buildQuery(ComplexOperation.OR)
- Under OR: ensure entity field filter columns are in inner SELECT for outer WHERE reference
- AND path remains completely unchanged (same execution path as before)
pull/15394/head
Viacheslav Klimov 3 months ago
parent
commit
51bb37aa96
Failed to extract signature
  1. 87
      dao/src/main/java/org/thingsboard/server/dao/sql/query/DefaultEntityQueryRepository.java

87
dao/src/main/java/org/thingsboard/server/dao/sql/query/DefaultEntityQueryRepository.java

@ -30,6 +30,7 @@ import org.thingsboard.server.common.data.page.PageData;
import org.thingsboard.server.common.data.permission.QueryContext;
import org.thingsboard.server.common.data.query.ApiUsageStateFilter;
import org.thingsboard.server.common.data.query.AssetSearchQueryFilter;
import org.thingsboard.server.common.data.query.ComplexOperation;
import org.thingsboard.server.common.data.query.AssetTypeFilter;
import org.thingsboard.server.common.data.query.DeviceSearchQueryFilter;
import org.thingsboard.server.common.data.query.DeviceTypeFilter;
@ -54,6 +55,7 @@ import org.thingsboard.server.common.data.query.SingleEntityFilter;
import org.thingsboard.server.common.data.relation.EntitySearchDirection;
import org.thingsboard.server.common.data.relation.RelationEntityTypeFilter;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
@ -351,25 +353,48 @@ public class DefaultEntityQueryRepository implements EntityQueryRepository {
}
});
} else {
List<EntityKeyMapping> mappings = EntityKeyMapping.prepareEntityCountKeyMapping(query);
ComplexOperation operation = query.getKeyFiltersOperationOrDefault();
boolean isOr = operation == ComplexOperation.OR;
List<EntityKeyMapping> selectionMapping = mappings.stream().filter(EntityKeyMapping::isSelection)
.collect(Collectors.toList());
List<EntityKeyMapping> entityFieldsSelectionMapping = selectionMapping.stream().filter(mapping -> !mapping.isLatest())
.collect(Collectors.toList());
List<EntityKeyMapping> mappings = EntityKeyMapping.prepareEntityCountKeyMapping(query);
List<EntityKeyMapping> selectionMapping = new ArrayList<>(mappings.stream().filter(EntityKeyMapping::isSelection)
.collect(Collectors.toList()));
List<EntityKeyMapping> filterMapping = mappings.stream().filter(EntityKeyMapping::hasFilter)
.collect(Collectors.toList());
List<EntityKeyMapping> entityFieldsFiltersMapping = filterMapping.stream().filter(mapping -> !mapping.isLatest() && mapping.getEntityKeyColumn() != null)
.collect(Collectors.toList());
// Under OR: entity field filter columns must be in inner SELECT for outer WHERE reference
if (isOr) {
for (EntityKeyMapping m : entityFieldsFiltersMapping) {
if (!selectionMapping.contains(m)) {
selectionMapping.add(m);
}
}
}
List<EntityKeyMapping> entityFieldsSelectionMapping = selectionMapping.stream().filter(mapping -> !mapping.isLatest())
.collect(Collectors.toList());
List<EntityKeyMapping> allLatestMappings = mappings.stream().filter(EntityKeyMapping::isLatest)
.collect(Collectors.toList());
// Under OR: entity field filters move to outer WHERE (not inner WHERE)
List<EntityKeyMapping> innerEntityFieldsFilters = isOr ? Collections.emptyList() : entityFieldsFiltersMapping;
String entityWhereClause = DefaultEntityQueryRepository.this.buildEntityWhere(ctx, query.getEntityFilter(), innerEntityFieldsFilters);
String latestJoinsCnt = EntityKeyMapping.buildLatestJoins(ctx, query.getEntityFilter(), entityType, allLatestMappings, true, isOr);
// Under OR: combine ALL filter mappings (entity fields + aliases) in outer WHERE with OR joiner
String aliasWhereQuery;
if (isOr) {
String combinedFilterQuery = EntityKeyMapping.buildQuery(ctx, filterMapping, query.getEntityFilter().getType(), ComplexOperation.OR);
aliasWhereQuery = combinedFilterQuery.isEmpty() ? "" : " where (" + combinedFilterQuery + ")";
} else {
aliasWhereQuery = DefaultEntityQueryRepository.this.buildAliasWhereQuery(ctx, query.getEntityFilter(), selectionMapping, "");
}
String entityWhereClause = DefaultEntityQueryRepository.this.buildEntityWhere(ctx, query.getEntityFilter(), entityFieldsFiltersMapping);
String aliasWhereQuery = DefaultEntityQueryRepository.this.buildAliasWhereQuery(ctx, query.getEntityFilter(), selectionMapping, "");
String latestJoinsCnt = EntityKeyMapping.buildLatestJoins(ctx, query.getEntityFilter(), entityType, allLatestMappings, true);
String entityFieldsSelection = EntityKeyMapping.buildSelections(entityFieldsSelectionMapping, query.getEntityFilter().getType(), entityType);
String entityTypeStr;
if (query.getEntityFilter().getType().equals(EntityFilterType.RELATIONS_QUERY)) {
@ -419,13 +444,13 @@ public class DefaultEntityQueryRepository implements EntityQueryRepository {
EntityType entityType = resolveEntityType(query.getEntityFilter());
SqlQueryContext ctx = new SqlQueryContext(new QueryContext(tenantId, customerId, entityType, ignorePermissionCheck));
EntityDataPageLink pageLink = query.getPageLink();
ComplexOperation operation = query.getKeyFiltersOperationOrDefault();
boolean isOr = operation == ComplexOperation.OR;
List<EntityKeyMapping> mappings = EntityKeyMapping.prepareKeyMapping(entityType, query);
List<EntityKeyMapping> selectionMapping = mappings.stream().filter(EntityKeyMapping::isSelection)
.collect(Collectors.toList());
List<EntityKeyMapping> entityFieldsSelectionMapping = selectionMapping.stream().filter(mapping -> !mapping.isLatest())
.collect(Collectors.toList());
List<EntityKeyMapping> selectionMapping = new ArrayList<>(mappings.stream().filter(EntityKeyMapping::isSelection)
.collect(Collectors.toList()));
List<EntityKeyMapping> latestSelectionMapping = selectionMapping.stream().filter(EntityKeyMapping::isLatest)
.collect(Collectors.toList());
@ -434,14 +459,44 @@ public class DefaultEntityQueryRepository implements EntityQueryRepository {
List<EntityKeyMapping> entityFieldsFiltersMapping = filterMapping.stream().filter(mapping -> !mapping.isLatest() && mapping.getEntityKeyColumn() != null)
.collect(Collectors.toList());
// Under OR: entity field filter columns must be in inner SELECT for outer WHERE reference
if (isOr) {
for (EntityKeyMapping m : entityFieldsFiltersMapping) {
if (!selectionMapping.contains(m)) {
selectionMapping.add(m);
}
}
}
List<EntityKeyMapping> entityFieldsSelectionMapping = selectionMapping.stream().filter(mapping -> !mapping.isLatest())
.collect(Collectors.toList());
List<EntityKeyMapping> allLatestMappings = mappings.stream().filter(EntityKeyMapping::isLatest)
.collect(Collectors.toList());
// Under OR: entity field filters move to outer WHERE (not inner WHERE)
List<EntityKeyMapping> innerEntityFieldsFilters = isOr ? Collections.emptyList() : entityFieldsFiltersMapping;
String entityWhereClause = DefaultEntityQueryRepository.this.buildEntityWhere(ctx, query.getEntityFilter(), innerEntityFieldsFilters);
String latestJoinsCnt = EntityKeyMapping.buildLatestJoins(ctx, query.getEntityFilter(), entityType, allLatestMappings, true, isOr);
String latestJoinsData = EntityKeyMapping.buildLatestJoins(ctx, query.getEntityFilter(), entityType, allLatestMappings, false, isOr);
// Under OR: combine ALL filter mappings (entity fields + aliases) in outer WHERE with OR joiner
String aliasWhereQuery;
if (isOr) {
String combinedFilterQuery = EntityKeyMapping.buildQuery(ctx, filterMapping, query.getEntityFilter().getType(), ComplexOperation.OR);
String searchTextQuery = buildTextSearchQuery(ctx, selectionMapping, pageLink.getTextSearch());
aliasWhereQuery = "";
if (!combinedFilterQuery.isEmpty()) {
aliasWhereQuery = " where (" + combinedFilterQuery + ")";
}
if (!searchTextQuery.isEmpty()) {
aliasWhereQuery += (aliasWhereQuery.isEmpty() ? " where " : " and ") + "(" + searchTextQuery + ") ";
}
} else {
aliasWhereQuery = DefaultEntityQueryRepository.this.buildAliasWhereQuery(ctx, query.getEntityFilter(), selectionMapping, pageLink.getTextSearch());
}
String entityWhereClause = DefaultEntityQueryRepository.this.buildEntityWhere(ctx, query.getEntityFilter(), entityFieldsFiltersMapping);
String latestJoinsCnt = EntityKeyMapping.buildLatestJoins(ctx, query.getEntityFilter(), entityType, allLatestMappings, true);
String latestJoinsData = EntityKeyMapping.buildLatestJoins(ctx, query.getEntityFilter(), entityType, allLatestMappings, false);
String aliasWhereQuery = DefaultEntityQueryRepository.this.buildAliasWhereQuery(ctx, query.getEntityFilter(), selectionMapping, pageLink.getTextSearch());
String entityFieldsSelection = EntityKeyMapping.buildSelections(entityFieldsSelectionMapping, query.getEntityFilter().getType(), entityType);
String entityTypeStr;
if (query.getEntityFilter().getType().equals(EntityFilterType.RELATIONS_QUERY)) {

Loading…
Cancel
Save