2023-07-08 08:43:30 -06:00
|
|
|
package models
|
|
|
|
|
2023-08-14 16:50:09 -06:00
|
|
|
import (
|
|
|
|
"fmt"
|
|
|
|
"strings"
|
|
|
|
)
|
2023-08-11 14:24:11 -06:00
|
|
|
|
2023-07-08 08:43:30 -06:00
|
|
|
// maps to frontend/src/app/models/widget/dashboard-widget-query.ts
|
|
|
|
type QueryResource struct {
|
|
|
|
Use string `json:"use"`
|
|
|
|
Select []string `json:"select"`
|
|
|
|
From string `json:"from"`
|
|
|
|
Where map[string]interface{} `json:"where"`
|
2023-10-01 18:05:55 -06:00
|
|
|
Limit *int `json:"limit,omitempty"`
|
|
|
|
Offset *int `json:"offset,omitempty"`
|
2023-08-11 14:24:11 -06:00
|
|
|
|
|
|
|
//aggregation fields
|
2023-08-14 00:35:02 -06:00
|
|
|
Aggregations *QueryResourceAggregations `json:"aggregations"`
|
|
|
|
}
|
|
|
|
|
|
|
|
type QueryResourceAggregations struct {
|
2023-10-02 14:42:41 -06:00
|
|
|
CountBy *QueryResourceAggregation `json:"count_by,omitempty"` //alias for both groupby and orderby, cannot be used together
|
2023-08-14 00:35:02 -06:00
|
|
|
|
2023-10-02 14:42:41 -06:00
|
|
|
GroupBy *QueryResourceAggregation `json:"group_by,omitempty"`
|
|
|
|
OrderBy *QueryResourceAggregation `json:"order_by,omitempty"`
|
|
|
|
}
|
|
|
|
|
|
|
|
type QueryResourceAggregation struct {
|
|
|
|
Field string `json:"field"`
|
|
|
|
Function string `json:"fn"`
|
2023-08-14 00:35:02 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
func (q *QueryResource) Validate() error {
|
|
|
|
if len(q.Use) > 0 {
|
|
|
|
return fmt.Errorf("'use' is not supported yet")
|
|
|
|
}
|
|
|
|
|
|
|
|
if len(q.From) == 0 {
|
|
|
|
return fmt.Errorf("'from' is required")
|
|
|
|
}
|
|
|
|
|
|
|
|
if q.Aggregations != nil {
|
|
|
|
if len(q.Select) > 0 {
|
|
|
|
return fmt.Errorf("cannot use 'select' and 'aggregations' together")
|
|
|
|
}
|
2023-10-02 14:42:41 -06:00
|
|
|
|
|
|
|
if q.Aggregations.CountBy != nil {
|
|
|
|
if len(q.Aggregations.CountBy.Field) == 0 {
|
|
|
|
return fmt.Errorf("if 'count_by' is present, field must be populated")
|
2023-08-14 00:35:02 -06:00
|
|
|
}
|
2023-10-02 14:42:41 -06:00
|
|
|
if strings.Contains(q.Aggregations.CountBy.Field, " ") {
|
|
|
|
return fmt.Errorf("count_by cannot have spaces (or aliases)")
|
2023-08-14 00:35:02 -06:00
|
|
|
}
|
|
|
|
}
|
2023-10-02 14:42:41 -06:00
|
|
|
if q.Aggregations.GroupBy != nil {
|
|
|
|
if len(q.Aggregations.GroupBy.Field) == 0 {
|
|
|
|
return fmt.Errorf("if 'group_by' is present, field must be populated")
|
|
|
|
}
|
|
|
|
if strings.Contains(q.Aggregations.GroupBy.Field, " ") {
|
|
|
|
return fmt.Errorf("group_by cannot have spaces (or aliases)")
|
|
|
|
}
|
2023-08-14 00:35:02 -06:00
|
|
|
}
|
2023-10-02 14:42:41 -06:00
|
|
|
if q.Aggregations.OrderBy != nil {
|
|
|
|
if len(q.Aggregations.OrderBy.Field) == 0 {
|
|
|
|
return fmt.Errorf("if 'order_by' is present, field must be populated")
|
|
|
|
}
|
|
|
|
if strings.Contains(q.Aggregations.OrderBy.Field, " ") {
|
|
|
|
return fmt.Errorf("order_by cannot have spaces (or aliases)")
|
|
|
|
}
|
2023-08-14 16:50:09 -06:00
|
|
|
}
|
2023-10-02 14:42:41 -06:00
|
|
|
|
|
|
|
if q.Aggregations.CountBy != nil {
|
|
|
|
if q.Aggregations.GroupBy != nil {
|
|
|
|
return fmt.Errorf("cannot use 'count_by' and 'group_by' together")
|
|
|
|
}
|
|
|
|
if q.Aggregations.OrderBy != nil {
|
|
|
|
return fmt.Errorf("cannot use 'count_by' and 'order_by' together")
|
|
|
|
}
|
2023-08-14 16:50:09 -06:00
|
|
|
}
|
2023-10-02 14:42:41 -06:00
|
|
|
if q.Aggregations.CountBy == nil && q.Aggregations.OrderBy == nil && q.Aggregations.GroupBy == nil {
|
|
|
|
return fmt.Errorf("aggregations must have at least one of 'count_by', 'group_by', or 'order_by'")
|
2023-08-14 16:50:09 -06:00
|
|
|
}
|
2023-10-02 14:42:41 -06:00
|
|
|
|
2023-10-01 18:05:55 -06:00
|
|
|
}
|
2023-08-14 00:35:02 -06:00
|
|
|
|
2023-10-01 18:05:55 -06:00
|
|
|
if q.Limit != nil && *q.Limit < 0 {
|
|
|
|
return fmt.Errorf("'limit' must be greater than or equal to zero")
|
|
|
|
}
|
|
|
|
if q.Offset != nil && *q.Offset < 0 {
|
|
|
|
return fmt.Errorf("'offset' must be greater than or equal to zero")
|
2023-08-14 00:35:02 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
return nil
|
2023-07-08 08:43:30 -06:00
|
|
|
}
|