diff --git a/query-service-impl/src/test/java/org/hypertrace/core/query/service/pinot/QueryRequestToPinotSQLConverterTest.java b/query-service-impl/src/test/java/org/hypertrace/core/query/service/pinot/QueryRequestToPinotSQLConverterTest.java index 57f3783d..97da1bcd 100644 --- a/query-service-impl/src/test/java/org/hypertrace/core/query/service/pinot/QueryRequestToPinotSQLConverterTest.java +++ b/query-service-impl/src/test/java/org/hypertrace/core/query/service/pinot/QueryRequestToPinotSQLConverterTest.java @@ -11,6 +11,7 @@ import static org.hypertrace.core.query.service.QueryRequestBuilderUtils.createInFilter; import static org.hypertrace.core.query.service.QueryRequestBuilderUtils.createLongLiteralValueExpression; import static org.hypertrace.core.query.service.QueryRequestBuilderUtils.createNotEqualsFilter; +import static org.hypertrace.core.query.service.QueryRequestBuilderUtils.createNotInFilter; import static org.hypertrace.core.query.service.QueryRequestBuilderUtils.createNullNumberLiteralValueExpression; import static org.hypertrace.core.query.service.QueryRequestBuilderUtils.createNullStringFilter; import static org.hypertrace.core.query.service.QueryRequestBuilderUtils.createNullStringLiteralValueExpression; @@ -35,13 +36,16 @@ import org.apache.pinot.client.Request; import org.hypertrace.core.query.service.ExecutionContext; import org.hypertrace.core.query.service.QueryFunctionConstants; +import org.hypertrace.core.query.service.api.ColumnIdentifier; import org.hypertrace.core.query.service.api.Expression; import org.hypertrace.core.query.service.api.Filter; import org.hypertrace.core.query.service.api.Function; +import org.hypertrace.core.query.service.api.LiteralConstant; import org.hypertrace.core.query.service.api.Operator; import org.hypertrace.core.query.service.api.QueryRequest; import org.hypertrace.core.query.service.api.QueryRequest.Builder; import org.hypertrace.core.query.service.api.SortOrder; +import org.hypertrace.core.query.service.api.Value; import org.hypertrace.core.query.service.pinot.PinotClientFactory.PinotClient; import org.hypertrace.core.query.service.pinot.converters.PinotFunctionConverter; import org.junit.jupiter.api.Assertions; @@ -539,6 +543,58 @@ public void testSQLiWithBooleanArrayFilter() { executionContext); } + @Test + void testQueryWithArrayColumnInFilter() { + Builder builder = QueryRequest.newBuilder(); + builder.addSelection(createColumnExpression("Span.id").build()); + + Filter filter = createInFilter("Span.ip_types", List.of("Public Proxy", "Bot")); + builder.setFilter(filter); + builder.setLimit(5); + + QueryRequest request = builder.build(); + ViewDefinition viewDefinition = getDefaultViewDefinition(); + defaultMockingForExecutionContext(); + + assertPQLQuery( + request, + "select span_id from spaneventview " + + "WHERE " + + viewDefinition.getTenantIdColumn() + + " = '" + + TENANT_ID + + "' " + + "and ip_types in ('public proxy', 'bot') limit 5", + viewDefinition, + executionContext); + } + + @Test + void testQueryWithArrayColumnNotInFilter() { + Builder builder = QueryRequest.newBuilder(); + builder.addSelection(createColumnExpression("Span.id").build()); + + Filter filter = createNotInFilter("Span.ip_types", List.of("Public Proxy", "Bot")); + builder.setFilter(filter); + builder.setLimit(5); + + QueryRequest request = builder.build(); + ViewDefinition viewDefinition = getDefaultViewDefinition(); + defaultMockingForExecutionContext(); + + assertPQLQuery( + request, + "select span_id from spaneventview " + + "WHERE " + + viewDefinition.getTenantIdColumn() + + " = '" + + TENANT_ID + + "' " + + "and ip_types not in ('public proxy', 'bot') limit 5", + viewDefinition, + executionContext); + } + @Test public void testQueryWithLikeOperator() { Builder builder = QueryRequest.newBuilder(); @@ -1060,6 +1116,79 @@ public void testQueryWithLikeOperatorForResponseBodyHavingTextIndex() { executionContext); } + @Test + public void testQueryWithTimeSeries() { + Builder builder = QueryRequest.newBuilder(); + + Filter startTimeFilter = + createTimeFilter("Span.start_time_millis", Operator.GT, 1570658506605L); + Filter endTimeFilter = createTimeFilter("Span.start_time_millis", Operator.LT, 1570744906673L); + + ColumnIdentifier spanCalls = ColumnIdentifier.newBuilder().setColumnName("Spans.calls").build(); + Function spanCallsFunctionCount = + Function.newBuilder() + .addArguments(Expression.newBuilder().setColumnIdentifier(spanCalls).build()) + .setFunctionName("COUNT") + .setAlias("COUNT_SPANS.calls_[]") + .build(); + builder.addSelection(Expression.newBuilder().setFunction(spanCallsFunctionCount)); + + Function dateTimeConvert = + Function.newBuilder() + .setFunctionName("dateTimeConvert") + .addArguments( + Expression.newBuilder() + .setColumnIdentifier( + ColumnIdentifier.newBuilder() + .setColumnName("Span.start_time_millis") + .build()) + .build()) + .addArguments( + Expression.newBuilder() + .setLiteral( + LiteralConstant.newBuilder() + .setValue(Value.newBuilder().setString("1:MILLISECONDS:EPOCH")) + .build()) + .build()) + .addArguments( + Expression.newBuilder() + .setLiteral( + LiteralConstant.newBuilder() + .setValue(Value.newBuilder().setString("1:MILLISECONDS:EPOCH")) + .build()) + .build()) + .addArguments( + Expression.newBuilder() + .setLiteral( + LiteralConstant.newBuilder() + .setValue(Value.newBuilder().setString("30:SECONDS")) + .build()) + .build()) + .build(); + builder.addGroupBy(Expression.newBuilder().setFunction(dateTimeConvert).build()); + builder + .setFilter(createCompositeFilter(Operator.AND, startTimeFilter, endTimeFilter)) + .setLimit(15); + + ViewDefinition viewDefinition = getDefaultViewDefinition(); + defaultMockingForExecutionContext(); + + assertPQLQuery( + builder.build(), + "select datetimeconvert(start_time_millis,'1:milliseconds:epoch','1:milliseconds:epoch','30:seconds'), count(*) from spaneventview " + + "where " + + viewDefinition.getTenantIdColumn() + + " = '" + + TENANT_ID + + "'" + + " and " + + "( start_time_millis > 1570658506605 and start_time_millis < 1570744906673 ) " + + "group by datetimeconvert(start_time_millis,'1:milliseconds:epoch','1:milliseconds:epoch','30:seconds') " + + "limit 15", + viewDefinition, + executionContext); + } + private QueryRequest buildSimpleQueryWithFilter(Filter filter) { Builder builder = QueryRequest.newBuilder(); builder.addSelection(createColumnExpression("Span.id").build()); diff --git a/query-service-impl/src/test/resources/request_handler.conf b/query-service-impl/src/test/resources/request_handler.conf index 6e5eecc0..0a2018a8 100644 --- a/query-service-impl/src/test/resources/request_handler.conf +++ b/query-service-impl/src/test/resources/request_handler.conf @@ -9,6 +9,7 @@ mapFields = ["tags", "request_headers"] bytesFields = ["parent_span_id", "span_id"] textIndexes = ["span_name"] + arrayFields = ["ip_types"] fieldMap = { "Span.tags": "tags", "Span.id": "span_id", @@ -24,7 +25,9 @@ "Span.attributes.response_body": "response_body", "Span.metrics.duration_millis": "duration_millis", "Span.serviceName": "service_name", - "Span.attributes.parent_span_id": "parent_span_id" + "Span.attributes.parent_span_id": "parent_span_id", + "Span.ip_types": "ip_types", + "Span.calls": "calls" } } }