diff --git a/src/main/java/com/epam/ta/reportportal/commons/querygen/FilterTarget.java b/src/main/java/com/epam/ta/reportportal/commons/querygen/FilterTarget.java index 476ac32d7..ea6b61eb1 100644 --- a/src/main/java/com/epam/ta/reportportal/commons/querygen/FilterTarget.java +++ b/src/main/java/com/epam/ta/reportportal/commons/querygen/FilterTarget.java @@ -139,6 +139,7 @@ import static com.epam.ta.reportportal.jooq.Tables.WIDGET; import static com.epam.ta.reportportal.jooq.tables.JOwnedEntity.OWNED_ENTITY; import static org.jooq.impl.DSL.choose; +import static org.jooq.impl.DSL.coalesce; import static org.jooq.impl.DSL.field; import com.epam.ta.reportportal.commons.querygen.constant.TestItemCriteriaConstant; @@ -550,15 +551,13 @@ private List> getSelectSimpleFields() { } private List> getSelectAggregatedFields() { - return Lists.newArrayList(DSL.arrayAgg( - DSL.field("concat({0}, {1}, {2}, {3}, {4})", - ITEM_ATTRIBUTE.KEY, - KEY_VALUE_SEPARATOR, - ITEM_ATTRIBUTE.VALUE, - KEY_VALUE_SEPARATOR, - ITEM_ATTRIBUTE.SYSTEM - )).as(ATTRIBUTE_ALIAS) - ); + return Lists.newArrayList( + DSL.arrayAgg(DSL.jsonArray( + coalesce(ITEM_ATTRIBUTE.KEY, ""), + coalesce(ITEM_ATTRIBUTE.VALUE, ""), + ITEM_ATTRIBUTE.SYSTEM + )) + .as(ATTRIBUTE_ALIAS)); } }, @@ -989,15 +988,13 @@ private List> getSelectSimpleFields() { } private List> getSelectAggregatedFields() { - return Lists.newArrayList(DSL.arrayAgg( - DSL.field("concat({0}, {1}, {2}, {3}, {4})", - ITEM_ATTRIBUTE.KEY, - KEY_VALUE_SEPARATOR, - ITEM_ATTRIBUTE.VALUE, - KEY_VALUE_SEPARATOR, - ITEM_ATTRIBUTE.SYSTEM - )).as(ATTRIBUTE_ALIAS) - ); + return Lists.newArrayList( + DSL.arrayAgg(DSL.jsonArray( + coalesce(ITEM_ATTRIBUTE.KEY, ""), + coalesce(ITEM_ATTRIBUTE.VALUE, ""), + ITEM_ATTRIBUTE.SYSTEM + )) + .as(ATTRIBUTE_ALIAS)); } }, diff --git a/src/main/java/com/epam/ta/reportportal/dao/LaunchRepositoryCustomImpl.java b/src/main/java/com/epam/ta/reportportal/dao/LaunchRepositoryCustomImpl.java index 7bd1be7c6..9a2e1dd4f 100644 --- a/src/main/java/com/epam/ta/reportportal/dao/LaunchRepositoryCustomImpl.java +++ b/src/main/java/com/epam/ta/reportportal/dao/LaunchRepositoryCustomImpl.java @@ -67,6 +67,7 @@ import java.util.stream.Collectors; import org.jooq.DSLContext; import org.jooq.Field; +import org.jooq.JSON; import org.jooq.SortField; import org.jooq.impl.DSL; import org.springframework.beans.factory.annotation.Autowired; @@ -186,7 +187,7 @@ public Page findAllLatestByFilter(Queryable filter, Pageable pageable) { List> simpleSelectedFields = getLaunchSimpleSelectedFields(); List> selectFields = new ArrayList<>(simpleSelectedFields); - selectFields.add(getAttributeConcatedFields()); + selectFields.addAll(getAttributeConcatenatedFields()); List> groupFields = new ArrayList<>(simpleSelectedFields); for (SortField sortField : sortFieldList) { @@ -223,11 +224,14 @@ public Page findAllLatestByFilter(Queryable filter, Pageable pageable) { ); } - private Field getAttributeConcatedFields() { - return DSL.arrayAgg(DSL.concat( - ITEM_ATTRIBUTE.KEY, DSL.val(":"), - ITEM_ATTRIBUTE.VALUE, DSL.val(":"), - ITEM_ATTRIBUTE.SYSTEM)).as(ATTRIBUTE_ALIAS); + private ArrayList> getAttributeConcatenatedFields() { + return Lists.newArrayList( + DSL.arrayAgg(DSL.jsonArray( + coalesce(ITEM_ATTRIBUTE.KEY, ""), + coalesce(ITEM_ATTRIBUTE.VALUE, ""), + ITEM_ATTRIBUTE.SYSTEM + )) + .as(ATTRIBUTE_ALIAS)); } private ArrayList> getLaunchSimpleSelectedFields() { @@ -263,7 +267,7 @@ public Optional findLastRun(Long projectId, String mode) { List> simpleSelectedFields = getLaunchSimpleSelectedFields(); List> selectFields = new ArrayList<>(simpleSelectedFields); - selectFields.add(getAttributeConcatedFields()); + selectFields.addAll(getAttributeConcatenatedFields()); return LAUNCH_FETCHER.apply(dsl.fetch(dsl.with(FILTERED_QUERY) .as(dsl.select(LAUNCH.ID) diff --git a/src/main/java/com/epam/ta/reportportal/dao/util/RecordMappers.java b/src/main/java/com/epam/ta/reportportal/dao/util/RecordMappers.java index 8a96b1988..ca752aa41 100644 --- a/src/main/java/com/epam/ta/reportportal/dao/util/RecordMappers.java +++ b/src/main/java/com/epam/ta/reportportal/dao/util/RecordMappers.java @@ -103,7 +103,10 @@ import com.google.common.collect.Lists; import com.google.common.collect.Maps; import com.google.common.collect.Sets; +import com.google.gson.Gson; +import com.google.gson.reflect.TypeToken; import java.io.IOException; +import java.lang.reflect.Type; import java.time.Instant; import java.time.LocalDateTime; import java.util.ArrayList; @@ -118,6 +121,7 @@ import java.util.function.Function; import org.apache.logging.log4j.util.Strings; import org.jooq.Field; +import org.jooq.JSON; import org.jooq.Record; import org.jooq.RecordMapper; import org.jooq.Result; @@ -507,17 +511,19 @@ public class RecordMappers { List attributeList = new ArrayList<>(); if (r.get(ATTRIBUTE_ALIAS) != null) { - String[] attributesArray = r.get(ATTRIBUTE_ALIAS, String[].class); + List attributesArray = r.get(ATTRIBUTE_ALIAS, List.class); + Gson gson = new Gson(); + Type listType = new TypeToken>() {}.getType(); - for (String attributeString : attributesArray) { - if (Strings.isEmpty(attributeString)) { + for (JSON attributeEntry : attributesArray) { + if (attributeEntry == null) { continue; } + String[] attributes = gson.>fromJson(attributeEntry.data(), listType) + .toArray(new String[0]); - // explode attributes from string "key:value:system" - String[] attributes = attributeString.split(":", -1); - if (attributes.length > 1 && (Strings.isNotEmpty(attributes[0]) || Strings.isNotEmpty( - attributes[1]))) { + if (attributes.length > 1 && (Strings.isNotEmpty(attributes[0]) + || Strings.isNotEmpty(attributes[1]))) { Boolean systemAttribute; //Case when system attribute is retrieved as 't' or 'f' if ("t".equals(attributes[2]) || "f".equals(attributes[2])) { @@ -532,7 +538,7 @@ public class RecordMappers { } } - if (attributeList.size() > 0) { + if (!attributeList.isEmpty()) { return Optional.of(attributeList); } else { return Optional.empty(); diff --git a/src/test/java/com/epam/ta/reportportal/dao/LaunchCompositeAttributeFilteringTest.java b/src/test/java/com/epam/ta/reportportal/dao/LaunchCompositeAttributeFilteringTest.java index 883488e99..42fa8405d 100644 --- a/src/test/java/com/epam/ta/reportportal/dao/LaunchCompositeAttributeFilteringTest.java +++ b/src/test/java/com/epam/ta/reportportal/dao/LaunchCompositeAttributeFilteringTest.java @@ -41,6 +41,24 @@ void compositeAttributeHas() { assertEquals(1, launches.size()); assertEquals(1L, launches.get(0).getId()); + + launches = launchRepository.findByFilter( + buildFilterWithConditions(buildCompositeAttributeCondition(Condition.HAS, + "key:semi:value:colon", + false + ))); + + assertEquals(1, launches.size()); + assertEquals(1L, launches.get(0).getId()); + + launches = launchRepository.findByFilter( + buildFilterWithConditions(buildCompositeAttributeCondition(Condition.HAS, + "key:semi:value:colon,key1:value1,key2:value2,key3:value3", + false + ))); + + assertEquals(1, launches.size()); + assertEquals(1L, launches.get(0).getId()); } @Test diff --git a/src/test/resources/db/fill/launch/launch-filtering-data.sql b/src/test/resources/db/fill/launch/launch-filtering-data.sql index 14acbff58..75ea03015 100644 --- a/src/test/resources/db/fill/launch/launch-filtering-data.sql +++ b/src/test/resources/db/fill/launch/launch-filtering-data.sql @@ -10,6 +10,8 @@ INSERT INTO item_attribute(key, value, launch_id) VALUES ('key2', 'value2', 1); INSERT INTO item_attribute(key, value, launch_id) VALUES ('key3', 'value3', 1); +INSERT INTO item_attribute(key, value, launch_id) +VALUES ('key:semi', 'value:colon', 1); INSERT INTO launch(id, uuid, project_id, user_id, name, start_time, end_time, last_modified, mode, status)