Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion entity-service-impl/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ plugins {
dependencies {
api(project(":entity-service-api"))
api("org.hypertrace.core.serviceframework:service-framework-spi:0.1.19")
implementation("org.hypertrace.core.documentstore:document-store:0.5.1")
implementation("org.hypertrace.core.documentstore:document-store:0.5.2")
implementation("org.hypertrace.core.grpcutils:grpc-context-utils:0.3.1")
implementation(project(":entity-type-service-rx-client"))

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -128,8 +128,12 @@ private static Filter transform(AttributeFilter filter) {
if (filter.hasAttributeValue()) {
if (ATTRIBUTES_LABELS_FIELD_NAME.equals(filter.getName()) && filter.getOperator() == Operator.EQ) {
return transformToEqFilterWithValueListRhs(filter);
} else if (ATTRIBUTES_LABELS_FIELD_NAME.equals(filter.getName()) && filter.getOperator() == Operator.NEQ) {
return transformToNeqFilterWithValueListRhs(filter);
} else if (ATTRIBUTES_LABELS_FIELD_NAME.equals(filter.getName()) && filter.getOperator() == Operator.IN) {
return transformToOrFilterChainForStrArray(filter);
} else if (ATTRIBUTES_LABELS_FIELD_NAME.equals(filter.getName()) && filter.getOperator() == Operator.NOT_IN) {
return transformToAndFilterChainForStrArray(filter);
} else {
return transformNonListRhsFilterTypes(filter);
}
Expand Down Expand Up @@ -183,33 +187,72 @@ private static Filter transformToOrFilterChainForStrArray(AttributeFilter attrib
return f;
}

private static Filter transformToAndFilterChainForStrArray(AttributeFilter attributeFilter) {
String fieldName = attributeFilter.getName() + VALUE_LIST_VALUES_CONST;

Filter f = new Filter();
f.setFieldName("");
f.setOp(Op.AND);

List<Filter> filters = attributeFilter.getAttributeValue().getValueList().getValuesList().stream()
.map(rhsAttributeValue -> createNeqFilterForAttributeValue(fieldName, rhsAttributeValue))
.collect(Collectors.toList());

f.setChildFilters(filters.toArray(new Filter[]{}));

return f;
}

private static Filter transformToEqFilterWithValueListRhs(AttributeFilter attributeFilter) {
String fieldName = attributeFilter.getName() + VALUE_LIST_VALUES_CONST;
return createEqFilterForAttributeValue(fieldName, attributeFilter.getAttributeValue());
}

private static Filter transformToNeqFilterWithValueListRhs(AttributeFilter attributeFilter) {
String fieldName = attributeFilter.getName() + VALUE_LIST_VALUES_CONST;
Filter f = new Filter();
f.setFieldName(fieldName);
f.setOp(Op.NEQ);
f.setValue(prepareRhsValueForSpecialValueListCase(attributeFilter.getAttributeValue()));
// Set child filters to empty array
f.setChildFilters(new Filter[]{});
return f;
}

private static Filter createEqFilterForAttributeValue(String fieldName, AttributeValue attributeValue) {
Filter f = new Filter();
f.setFieldName(fieldName);
f.setOp(Op.EQ);
f.setValue(prepareRhsValueForSpecialValueListCase(attributeValue));
// Set child filters to empty array
f.setChildFilters(new Filter[]{});
return f;
}

private static Filter createNeqFilterForAttributeValue(String fieldName, AttributeValue attributeValue) {
Filter f = new Filter();
f.setFieldName(fieldName);
f.setOp(Op.NEQ);
f.setValue(prepareRhsValueForSpecialValueListCase(attributeValue));
// Set child filters to empty array
f.setChildFilters(new Filter[]{});
return f;
}

private static Object prepareRhsValueForSpecialValueListCase(AttributeValue attributeValue) {
org.hypertrace.entity.data.service.v1.AttributeValue.TypeCase typeCase = attributeValue.getTypeCase();
if (typeCase == TypeCase.VALUE) {
try {
JsonNode mapNode = OBJECT_MAPPER.readTree(JSONFORMAT_PRINTER.print(attributeValue));
Map map = OBJECT_MAPPER.convertValue(mapNode, Map.class);
f.setValue(map);
return map;
} catch (JsonProcessingException | InvalidProtocolBufferException e) {
throw new RuntimeException(e);
}
} else { // For now, just expecting VALUE type on the RHS
throw new UnsupportedOperationException(
String.format("The RHS of filter for string array types can only be VALUE: %s", attributeValue));
}

// Set child filters to empty array
f.setChildFilters(new Filter[]{});
return f;
}

private static void transform(AttributeValue attributeValue, Filter filter,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -479,6 +479,57 @@ public void testStringArrayValueTypeColumnEqAndChain() throws JsonProcessingExce
transformedFilter.getChildFilters()[2].getChildFilters()[1].getValue());
}

@Test
public void testStringArrayValueTypeColumnNeqAndChain() throws JsonProcessingException {
Query query = Query.newBuilder()
.addEntityId("some id")
.setFilter(
AttributeFilter.newBuilder().setOperator(Operator.AND)
.addChildFilter(
AttributeFilter.newBuilder()
.setName(ATTRIBUTES_LABELS_FIELD_NAME)
.setOperator(Operator.NEQ)
.setAttributeValue(AttributeValue.newBuilder()
.setValue(Value.newBuilder().setString("l1"))
)
)
.addChildFilter(
AttributeFilter.newBuilder()
.setName(ATTRIBUTES_LABELS_FIELD_NAME)
.setOperator(Operator.NEQ)
.setAttributeValue(AttributeValue.newBuilder()
.setValue(Value.newBuilder().setString("l2"))
)
)
)
.build();
org.hypertrace.core.documentstore.Query transformedQuery =
DocStoreConverter.transform(TENANT_ID, query, Collections.emptyList());

Filter transformedFilter = transformedQuery.getFilter();
Assertions.assertEquals(Filter.Op.AND, transformedFilter.getOp());

Assertions.assertEquals(3, transformedFilter.getChildFilters().length);
Assertions.assertEquals(EntityServiceConstants.ENTITY_ID,
transformedFilter.getChildFilters()[1].getFieldName());
Assertions.assertEquals(Collections.singletonList("some id"),
transformedFilter.getChildFilters()[1].getValue());

Assertions.assertEquals(Op.AND, transformedFilter.getChildFilters()[2].getOp());

Assertions.assertEquals(ATTRIBUTES_LABELS_FIELD_NAME + ".valueList.values",
transformedFilter.getChildFilters()[2].getChildFilters()[0].getFieldName());
Assertions.assertEquals(Op.NEQ, transformedFilter.getChildFilters()[2].getChildFilters()[0].getOp());
Assertions.assertEquals(OBJECT_MAPPER.convertValue(OBJECT_MAPPER.readTree("{\"value\": {\"string\":\"l1\"}}"), Map.class),
transformedFilter.getChildFilters()[2].getChildFilters()[0].getValue());

Assertions.assertEquals(ATTRIBUTES_LABELS_FIELD_NAME + ".valueList.values",
transformedFilter.getChildFilters()[2].getChildFilters()[1].getFieldName());
Assertions.assertEquals(Op.NEQ, transformedFilter.getChildFilters()[2].getChildFilters()[1].getOp());
Assertions.assertEquals(OBJECT_MAPPER.convertValue(OBJECT_MAPPER.readTree("{\"value\": {\"string\":\"l2\"}}"), Map.class),
transformedFilter.getChildFilters()[2].getChildFilters()[1].getValue());
}

@Test
public void testStringArrayValueTypeColumnOrChain() throws JsonProcessingException {
Query query = Query.newBuilder()
Expand Down Expand Up @@ -554,6 +605,81 @@ public void testStringArrayValueTypeColumnOrChain() throws JsonProcessingExcepti
transformedFilter.getChildFilters()[2].getChildFilters()[1].getChildFilters()[2].getValue());
}

@Test
public void testStringArrayValueTypeColumnAndChain() throws JsonProcessingException {
Query query = Query.newBuilder()
.addEntityId("some id")
.setFilter(
AttributeFilter.newBuilder().setOperator(Operator.AND)
.addChildFilter(
AttributeFilter.newBuilder()
.setName("attributes.some_col")
.setOperator(Operator.EQ)
.setAttributeValue(AttributeValue.newBuilder()
.setValue(Value.newBuilder().setString("some_val"))
)
)
.addChildFilter(
AttributeFilter.newBuilder()
.setName(ATTRIBUTES_LABELS_FIELD_NAME)
.setOperator(Operator.NOT_IN)
.setAttributeValue(AttributeValue.newBuilder()
.setValueList(
AttributeValueList.newBuilder()
.addValues(
AttributeValue.newBuilder().setValue(Value.newBuilder().setString("l1"))
)
.addValues(
AttributeValue.newBuilder().setValue(Value.newBuilder().setString("l2"))
)
.addValues(
AttributeValue.newBuilder().setValue(Value.newBuilder().setString("l3"))
)
)
)
)
)
.build();
org.hypertrace.core.documentstore.Query transformedQuery =
DocStoreConverter.transform(TENANT_ID, query, Collections.emptyList());

Filter transformedFilter = transformedQuery.getFilter();
Assertions.assertEquals(Filter.Op.AND, transformedFilter.getOp());

Assertions.assertEquals(3, transformedFilter.getChildFilters().length);
Assertions.assertEquals(EntityServiceConstants.ENTITY_ID,
transformedFilter.getChildFilters()[1].getFieldName());
Assertions.assertEquals(Collections.singletonList("some id"),
transformedFilter.getChildFilters()[1].getValue());

Assertions.assertEquals(Op.AND, transformedFilter.getChildFilters()[2].getOp());

Assertions.assertEquals("attributes.some_col.value.string",
transformedFilter.getChildFilters()[2].getChildFilters()[0].getFieldName());
Assertions.assertEquals(Op.EQ, transformedFilter.getChildFilters()[2].getChildFilters()[0].getOp());
Assertions.assertEquals("some_val", transformedFilter.getChildFilters()[2].getChildFilters()[0].getValue());

Assertions.assertEquals(Op.AND, transformedFilter.getChildFilters()[2].getChildFilters()[1].getOp());

Assertions.assertEquals(ATTRIBUTES_LABELS_FIELD_NAME + ".valueList.values",
transformedFilter.getChildFilters()[2].getChildFilters()[1].getChildFilters()[0].getFieldName());
Assertions.assertEquals(Op.NEQ, transformedFilter.getChildFilters()[2].getChildFilters()[1].getChildFilters()[0].getOp());
Assertions.assertEquals(OBJECT_MAPPER.convertValue(OBJECT_MAPPER.readTree("{\"value\": {\"string\":\"l1\"}}"), Map.class),
transformedFilter.getChildFilters()[2].getChildFilters()[1].getChildFilters()[0].getValue());

Assertions.assertEquals(ATTRIBUTES_LABELS_FIELD_NAME + ".valueList.values",
transformedFilter.getChildFilters()[2].getChildFilters()[1].getChildFilters()[1].getFieldName());
Assertions.assertEquals(Op.NEQ, transformedFilter.getChildFilters()[2].getChildFilters()[1].getChildFilters()[1].getOp());
Assertions.assertEquals(OBJECT_MAPPER.convertValue(OBJECT_MAPPER.readTree("{\"value\": {\"string\":\"l2\"}}"), Map.class),
transformedFilter.getChildFilters()[2].getChildFilters()[1].getChildFilters()[1].getValue());

Assertions.assertEquals(ATTRIBUTES_LABELS_FIELD_NAME + ".valueList.values",
transformedFilter.getChildFilters()[2].getChildFilters()[1].getChildFilters()[2].getFieldName());
Assertions.assertEquals(Op.NEQ, transformedFilter.getChildFilters()[2].getChildFilters()[1].getChildFilters()[2].getOp());
Assertions.assertEquals(OBJECT_MAPPER.convertValue(OBJECT_MAPPER.readTree("{\"value\": {\"string\":\"l3\"}}"), Map.class),
transformedFilter.getChildFilters()[2].getChildFilters()[1].getChildFilters()[2].getValue());
}

@Test
public void testNeqFilterConversionForValueListThrowsException() {
Assertions.assertThrows(UnsupportedOperationException.class, () -> {
Expand Down
2 changes: 1 addition & 1 deletion entity-service/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ dependencies {
implementation("org.hypertrace.core.grpcutils:grpc-server-utils:0.3.1")
implementation("org.hypertrace.core.grpcutils:grpc-client-utils:0.3.1")
implementation("org.hypertrace.core.serviceframework:platform-service-framework:0.1.19")
implementation("org.hypertrace.core.documentstore:document-store:0.5.1")
implementation("org.hypertrace.core.documentstore:document-store:0.5.2")

runtimeOnly("io.grpc:grpc-netty:1.33.1")
runtimeOnly("io.netty:netty-codec-http2:4.1.59.Final")
Expand Down
Loading