Skip to content

Commit

Permalink
Merge pull request #570 from folio-org/MODFQMMGR-622-showing-jason-bo…
Browse files Browse the repository at this point in the history
…urne-a-ray
  • Loading branch information
mweaver-ebsco authored Dec 30, 2024
2 parents ef8fbfa + ada25ff commit b6802ce
Show file tree
Hide file tree
Showing 4 changed files with 78 additions and 14 deletions.
41 changes: 31 additions & 10 deletions src/main/java/org/folio/fqm/repository/ResultSetRepository.java
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,9 @@
import java.util.Map;
import java.util.Set;
import java.util.UUID;
import java.util.stream.Collectors;

import com.fasterxml.jackson.databind.ObjectMapper;
import org.folio.fql.model.Fql;
import org.folio.fqm.exception.FieldNotFoundException;
import org.folio.fqm.service.EntityTypeFlatteningService;
Expand All @@ -22,16 +24,13 @@

import org.apache.commons.collections4.CollectionUtils;
import org.folio.querytool.domain.dto.EntityTypeColumn;
import org.jooq.Record;
import org.folio.querytool.domain.dto.JsonbArrayType;
import org.jooq.*;
import org.folio.spring.FolioExecutionContext;
import org.jooq.Condition;
import org.jooq.DSLContext;
import org.jooq.Field;
import org.jooq.Result;
import org.jooq.SelectConditionStep;
import org.jooq.SelectLimitPercentStep;
import org.jooq.Record;
import org.jooq.impl.DSL;
import org.postgresql.jdbc.PgArray;
import org.postgresql.util.PGobject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Repository;
Expand All @@ -48,6 +47,7 @@ public class ResultSetRepository {
private final DSLContext jooqContext;
private final EntityTypeFlatteningService entityTypeFlatteningService;
private final FolioExecutionContext executionContext;
private final ObjectMapper objectMapper;


public List<Map<String, Object>> getResultSet(UUID entityTypeId,
Expand Down Expand Up @@ -97,7 +97,7 @@ public List<Map<String, Object>> getResultSet(UUID entityTypeId,
result = query.groupBy(groupByFields).fetch();
}

return recordToMap(result);
return recordToMap(baseEntityType, result);
}

// TODO: update for GROUP BY functionality
Expand Down Expand Up @@ -169,7 +169,7 @@ public List<Map<String, Object>> getResultSetSync(UUID entityTypeId,
throw new IllegalArgumentException("Synchronous queries are not currently supported for entity types with GROUP BY clauses.");
}

return recordToMap(result);
return recordToMap(baseEntityType, result);
}

private List<Field<Object>> getSqlFields(EntityType entityType, List<String> fields) {
Expand All @@ -186,11 +186,22 @@ private EntityType getEntityType(String tenantId, UUID entityTypeId) {
return entityTypeFlatteningService.getFlattenedEntityType(entityTypeId, tenantId);
}

private List<Map<String, Object>> recordToMap(Result<Record> result) {
private List<Map<String, Object>> recordToMap(EntityType entityType, Result<Record> result) {
List<Map<String, Object>> resultList = new ArrayList<>();
Set<String> jsonbArrayColumnsInEntityType = entityType.getColumns()
.stream()
.filter(col -> col.getDataType() instanceof JsonbArrayType)
.map(org.folio.querytool.domain.dto.Field::getName)
.collect(Collectors.toSet());
Set<String> jsonbArrayColumnsInResults = result.get(0).intoMap()
.keySet()
.stream()
.filter(jsonbArrayColumnsInEntityType::contains)
.collect(Collectors.toSet());
result.forEach(row -> {
Map<String, Object> recordMap = row.intoMap();
for (Map.Entry<String, Object> entry : recordMap.entrySet()) {
// Turn SQL arrays into Java arrays
if (entry.getValue() instanceof PgArray pgArray) {
try {
recordMap.put(entry.getKey(), pgArray.getArray());
Expand All @@ -199,6 +210,16 @@ private List<Map<String, Object>> recordToMap(Result<Record> result) {
recordMap.remove(entry.getKey());
}
}
if (jsonbArrayColumnsInResults.contains(entry.getKey()) && entry.getValue() instanceof PGobject pgobject && "jsonb".equals(pgobject.getType())) {
try {
JSONB jsonb = JSONB.valueOf(pgobject.getValue());
recordMap.put(entry.getKey(), objectMapper.readValue(jsonb.toString(), String[].class));
} catch (Exception e) {
log.error("Failed to parse jsonb value: {}", e.getMessage(), e);
recordMap.remove(entry.getKey());
}
}

}
resultList.add(recordMap);
});
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package org.folio.fqm.repository;

import com.fasterxml.jackson.databind.ObjectMapper;
import org.folio.fqm.service.EntityTypeFlatteningService;
import org.folio.spring.FolioExecutionContext;
import org.jooq.DSLContext;
Expand Down Expand Up @@ -32,7 +33,7 @@ void setup() {
DSLContext context = DSL.using(new MockConnection(
new ResultSetRepositoryArrayTestDataProvider()), SQLDialect.POSTGRES);
entityTypeFlatteningService = mock(EntityTypeFlatteningService.class);
this.repo = new ResultSetRepository(context, entityTypeFlatteningService, mock(FolioExecutionContext.class));
this.repo = new ResultSetRepository(context, entityTypeFlatteningService, mock(FolioExecutionContext.class), new ObjectMapper());
}

@Test
Expand All @@ -58,4 +59,28 @@ void getResultSetShouldHandleArray() {
assertEquals(expectedList.get(0).get("id"), actualList.get(0).get("id"));
assertEquals(expectedList.get(0).get("arrayField"), actualList.get(0).get("arrayField"));
}

@Test
void getResultSetShouldHandleJsonbArray() {
UUID entityTypeId = UUID.randomUUID();
List<List<String>> listIds = List.of(
List.of(UUID.randomUUID().toString())
);
List<String> fields = List.of("id", "testJsonbArrayField");
List<Map<String, Object>> expectedFullList = ResultSetRepositoryArrayTestDataProvider.TEST_ENTITY_WITH_ARRAY_CONTENTS;
List<Map<String, Object>> expectedList = List.of(
Map.of("id", expectedFullList.get(0).get("id"), "testField", List.of("value1"))
);
when(entityTypeFlatteningService.getFlattenedEntityType(entityTypeId, null))
.thenReturn(ResultSetRepositoryArrayTestDataProvider.ARRAY_ENTITY_TYPE);
when(entityTypeFlatteningService.getJoinClause(ResultSetRepositoryArrayTestDataProvider.ARRAY_ENTITY_TYPE, null))
.thenReturn("TEST_ENTITY_TYPE");
when(entityTypeFlatteningService.getFlattenedEntityType(entityTypeId, "tenant_01"))
.thenReturn(ResultSetRepositoryArrayTestDataProvider.ARRAY_ENTITY_TYPE);
when(entityTypeFlatteningService.getJoinClause(ResultSetRepositoryArrayTestDataProvider.ARRAY_ENTITY_TYPE, "tenant_01"))
.thenReturn("TEST_ENTITY_TYPE");
List<Map<String, Object>> actualList = repo.getResultSet(entityTypeId, fields, listIds, List.of("tenant_01"));
assertEquals(expectedList.get(0).get("id"), actualList.get(0).get("id"));
assertEquals(expectedList.get(0).get("jsonbArrayField"), actualList.get(0).get("jsonbArrayField"));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
import org.jooq.tools.jdbc.MockResult;
import org.mockito.Mockito;
import org.postgresql.jdbc.PgArray;
import org.postgresql.util.PGobject;

import java.util.List;
import java.util.Map;
Expand All @@ -36,7 +37,7 @@ public class ResultSetRepositoryArrayTestDataProvider implements MockDataProvide
);

public static final List<Map<String, Object>> TEST_ENTITY_WITH_ARRAY_CONTENTS = List.of(
Map.of(ID_FIELD_NAME, UUID.randomUUID(), "testField", getPgArray()));
Map.of(ID_FIELD_NAME, UUID.randomUUID(), "testField", getPgArray(), "testJsonbArrayField", getJsonbArray()));

public static final EntityType ARRAY_ENTITY_TYPE = new EntityType()
.columns(List.of(
Expand All @@ -50,7 +51,12 @@ public class ResultSetRepositoryArrayTestDataProvider implements MockDataProvide
.name("testField")
.dataType(new EntityDataType().dataType("arrayType"))
.sourceAlias("source1")
.valueGetter(":sourceAlias.testField")
.valueGetter(":sourceAlias.testField"),
new EntityTypeColumn()
.name("testJsonbArrayField")
.dataType(new EntityDataType().dataType("jsonbArrayType"))
.sourceAlias("source1")
.valueGetter(":sourceAlias.testJsonbArrayField")
))
.name("TEST_ARRAY_ENTITY_TYPE")
.fromClause("TEST_ARRAY_ENTITY_TYPE")
Expand Down Expand Up @@ -113,6 +119,17 @@ private static PgArray getPgArray() {
}
}

private static PGobject getJsonbArray() {
try {
PGobject mockPgArray = Mockito.mock(PGobject.class);
when(mockPgArray.getType()).thenReturn("jsonb");
when(mockPgArray.getValue()).thenReturn("[\"value1\"]");
return mockPgArray;
} catch(Exception e) {
return null;
}
}

@SneakyThrows
private String writeValueAsString(Object value) {
return OBJECT_MAPPER.writeValueAsString(value);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package org.folio.fqm.repository;

import com.fasterxml.jackson.databind.ObjectMapper;
import org.folio.fql.model.EqualsCondition;
import org.folio.fql.model.Fql;
import org.folio.fql.model.field.FqlField;
Expand Down Expand Up @@ -41,7 +42,7 @@ void setup() {
new ResultSetRepositoryTestDataProvider()), SQLDialect.POSTGRES);

entityTypeFlatteningService = mock(EntityTypeFlatteningService.class);
this.repo = new ResultSetRepository(context, entityTypeFlatteningService, mock(FolioExecutionContext.class));
this.repo = new ResultSetRepository(context, entityTypeFlatteningService, mock(FolioExecutionContext.class), new ObjectMapper());
}

@Test
Expand Down

0 comments on commit b6802ce

Please sign in to comment.