diff --git a/query-service-api/src/main/proto/request.proto b/query-service-api/src/main/proto/request.proto index ed44ec03..5e4962f7 100644 --- a/query-service-api/src/main/proto/request.proto +++ b/query-service-api/src/main/proto/request.proto @@ -56,6 +56,7 @@ enum Operator { CONTAINS_KEY = 13; CONTAINS_KEYVALUE = 14; NOT_CONTAINS_KEY = 15; + CONTAINS_KEY_LIKE = 16; } diff --git a/query-service-impl/src/main/java/org/hypertrace/core/query/service/pinot/QueryRequestToPinotSQLConverter.java b/query-service-impl/src/main/java/org/hypertrace/core/query/service/pinot/QueryRequestToPinotSQLConverter.java index 8b219716..2f3f5a92 100644 --- a/query-service-impl/src/main/java/org/hypertrace/core/query/service/pinot/QueryRequestToPinotSQLConverter.java +++ b/query-service-impl/src/main/java/org/hypertrace/core/query/service/pinot/QueryRequestToPinotSQLConverter.java @@ -186,6 +186,15 @@ private String convertFilterToString( builder.append(") = "); builder.append(convertLiteralToString(kvp.get(MAP_VALUE_INDEX), paramsBuilder)); break; + case CONTAINS_KEY_LIKE: + kvp = convertExpressionToMapLiterals(filter.getRhs()); + builder.append(operator); + builder.append("("); + builder.append(convertExpressionToMapKeyColumn(filter.getLhs())); + builder.append(","); + builder.append(convertLiteralToString(kvp.get(MAP_KEY_INDEX), paramsBuilder)); + builder.append(")"); + break; default: rhs = handleValueConversionForLiteralExpression(filter.getLhs(), filter.getRhs()); builder.append( @@ -255,6 +264,7 @@ private String convertOperatorToString(Operator operator) { case LE: return "<="; case LIKE: + case CONTAINS_KEY_LIKE: return REGEX_OPERATOR; case CONTAINS_KEYVALUE: return MAP_VALUE; @@ -347,7 +357,7 @@ private List convertExpressionToMapLiterals(Expression expressi literals.set(0, value.getValue().getString()); } else { throw new IllegalArgumentException( - "Unsupported arguments for CONTAINS_KEY / CONTAINS_KEYVALUE operator"); + "Unsupported arguments for CONTAINS_KEY / CONTAINS_KEYVALUE / CONTAINS_KEY_LIKE operator"); } } 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 12173323..c5ac8b46 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 @@ -597,6 +597,37 @@ public void testQueryWithContainsKeyValueOperator() { executionContext); } + @Test + void testQueryWithContainsKeyLikeOperator() { + Builder builder = QueryRequest.newBuilder(); + Expression spanTag = createColumnExpression("Span.tags").build(); + builder.addSelection(spanTag); + + Expression tag = createStringLiteralValueExpression("my_tag_name.*"); + Filter likeFilter = + Filter.newBuilder() + .setOperator(Operator.CONTAINS_KEY_LIKE) + .setLhs(spanTag) + .setRhs(tag) + .build(); + builder.setFilter(likeFilter); + + ViewDefinition viewDefinition = getDefaultViewDefinition(); + defaultMockingForExecutionContext(); + + assertPQLQuery( + builder.build(), + "SELECT tags__keys, tags__values FROM SpanEventView " + + "WHERE " + + viewDefinition.getTenantIdColumn() + + " = '" + + TENANT_ID + + "' " + + "AND REGEXP_LIKE(tags__keys,'my_tag_name.*')", + viewDefinition, + executionContext); + } + @Test public void testQueryWithBytesColumnWithValidId() { Builder builder = QueryRequest.newBuilder();