Compare commits

...

3 Commits

Author SHA1 Message Date
Tushar Vats
419d31790a fix: use WithTimestampGroupByValidation instead 2026-04-21 15:34:09 +05:30
Tushar Vats
459e7cfd5c fix: added a unit test 2026-04-20 19:22:23 +05:30
Tushar Vats
4908220d01 fix: disallow group by timestamp for timeseries request 2026-04-20 19:11:58 +05:30
2 changed files with 75 additions and 7 deletions

View File

@@ -47,12 +47,13 @@ const (
type ValidationOption func(*validationConfig)
type validationConfig struct {
skipLimitOffsetValidation bool
skipAggregationValidation bool
skipHavingValidation bool
skipAggregationOrderBy bool
skipSelectFieldValidation bool
skipGroupByValidation bool
skipLimitOffsetValidation bool
skipAggregationValidation bool
skipHavingValidation bool
skipAggregationOrderBy bool
skipSelectFieldValidation bool
skipGroupByValidation bool
WithTimestampGroupByValidation bool
}
func applyValidationOptions(opts []ValidationOption) validationConfig {
@@ -111,6 +112,13 @@ func WithSkipGroupByValidation() ValidationOption {
}
}
// WithRequestType sets the request type for validation.
func WithTimestampGroupByValidation() ValidationOption {
return func(cfg *validationConfig) {
cfg.WithTimestampGroupByValidation = true
}
}
// Validate performs preliminary validation on QueryBuilderQuery.
func (q *QueryBuilderQuery[T]) Validate(opts ...ValidationOption) error {
cfg := applyValidationOptions(opts)
@@ -177,6 +185,11 @@ func (q *QueryBuilderQuery[T]) validateGroupBy(cfg validationConfig) error {
errors.CodeInvalidInput, "invalid empty key name for group by at index %d", idx,
)
}
if cfg.WithTimestampGroupByValidation && item.Name == "timestamp" {
return errors.NewInvalidInputf(
errors.CodeInvalidInput, "group by on timestamp is not allowed",
).WithAdditional("Timeseries request already accounts for timestamp in the response")
}
}
return nil
}
@@ -665,7 +678,9 @@ func validateQueryEnvelope(envelope QueryEnvelope, opts ...ValidationOption) err
func GetValidationOptions(requestType RequestType) []ValidationOption {
switch requestType {
case RequestTypeTimeSeries, RequestTypeScalar:
case RequestTypeTimeSeries:
return []ValidationOption{WithSkipSelectFieldValidation(), WithTimestampGroupByValidation()}
case RequestTypeScalar:
return []ValidationOption{WithSkipSelectFieldValidation()}
case RequestTypeRaw, RequestTypeRawStream, RequestTypeTrace:
return []ValidationOption{WithSkipAggregationValidation(), WithSkipHavingValidation(), WithSkipAggregationOrderBy(), WithSkipGroupByValidation()}

View File

@@ -695,6 +695,59 @@ func TestQueryRangeRequest_ValidateCompositeQuery(t *testing.T) {
wantErr: true,
errMsg: "raw request type is not supported for metric queries",
},
{
name: "timeseries request with group by timestamp should return error",
request: QueryRangeRequest{
Start: 1640995200000,
End: 1640998800000,
RequestType: RequestTypeTimeSeries,
CompositeQuery: CompositeQuery{
Queries: []QueryEnvelope{
{
Type: QueryTypeBuilder,
Spec: QueryBuilderQuery[LogAggregation]{
Name: "A",
Signal: telemetrytypes.SignalLogs,
Aggregations: []LogAggregation{
{Expression: "count()"},
},
GroupBy: []GroupByKey{
{TelemetryFieldKey: telemetrytypes.TelemetryFieldKey{Name: "timestamp"}},
},
},
},
},
},
},
wantErr: true,
errMsg: "group by on timestamp is not allowed",
},
{
name: "scalar request with group by timestamp should pass",
request: QueryRangeRequest{
Start: 1640995200000,
End: 1640998800000,
RequestType: RequestTypeScalar,
CompositeQuery: CompositeQuery{
Queries: []QueryEnvelope{
{
Type: QueryTypeBuilder,
Spec: QueryBuilderQuery[LogAggregation]{
Name: "A",
Signal: telemetrytypes.SignalLogs,
Aggregations: []LogAggregation{
{Expression: "count()"},
},
GroupBy: []GroupByKey{
{TelemetryFieldKey: telemetrytypes.TelemetryFieldKey{Name: "timestamp"}},
},
},
},
},
},
},
wantErr: false,
},
{
name: "raw request with log query without aggregations should pass",
request: QueryRangeRequest{