Skip to content

Commit

Permalink
Enhance 'sort' field parser to handle shorthand maps
Browse files Browse the repository at this point in the history
  • Loading branch information
pivovarit committed May 17, 2024
1 parent 0fd5a5a commit 2658e44
Show file tree
Hide file tree
Showing 2 changed files with 49 additions and 24 deletions.
64 changes: 41 additions & 23 deletions quesma/queryparser/query_parser.go
Original file line number Diff line number Diff line change
Expand Up @@ -1200,38 +1200,56 @@ func (cw *ClickhouseQueryTranslator) extractInterval(queryMap QueryMap) string {

// parseSortFields parses sort fields from the query
// We're skipping ELK internal fields, like "_doc", "_id", etc. (we only accept field starting with "_" if it exists in our table)
func (cw *ClickhouseQueryTranslator) parseSortFields(sortMaps []any) []string {
sortFields := make([]string, 0)
for _, sortMapAsAny := range sortMaps {
sortMap, ok := sortMapAsAny.(QueryMap)
if !ok {
logger.WarnWithCtx(cw.Ctx).Msgf("parseSortFields: unexpected type of value: %T, value: %v", sortMapAsAny, sortMapAsAny)
continue
}

// sortMap has only 1 key, so we can just iterate over it
for k, v := range sortMap {
if strings.HasPrefix(k, "_") && cw.Table.GetFieldInfo(cw.Ctx, k) == clickhouse.NotExists {
// we're skipping ELK internal fields, like "_doc", "_id", etc.
func (cw *ClickhouseQueryTranslator) parseSortFields(sortMaps any) []string {
switch sortMaps := sortMaps.(type) {
case []any:
sortFields := make([]string, 0)
for _, sortMapAsAny := range sortMaps {
sortMap, ok := sortMapAsAny.(QueryMap)
if !ok {
logger.WarnWithCtx(cw.Ctx).Msgf("parseSortFields: unexpected type of value: %T, value: %v", sortMapAsAny, sortMapAsAny)
continue
}
fieldName := cw.Table.ResolveField(cw.Ctx, k)
if vAsMap, ok := v.(QueryMap); ok {
if order, ok := vAsMap["order"]; ok {
if orderAsString, ok := order.(string); ok {
sortFields = append(sortFields, strconv.Quote(fieldName)+" "+orderAsString)

// sortMap has only 1 key, so we can just iterate over it
for k, v := range sortMap {
if strings.HasPrefix(k, "_") && cw.Table.GetFieldInfo(cw.Ctx, k) == clickhouse.NotExists {
// we're skipping ELK internal fields, like "_doc", "_id", etc.
continue
}
fieldName := cw.Table.ResolveField(cw.Ctx, k)
if vAsMap, ok := v.(QueryMap); ok {
if order, ok := vAsMap["order"]; ok {
if orderAsString, ok := order.(string); ok {
sortFields = append(sortFields, strconv.Quote(fieldName)+" "+orderAsString)
} else {
logger.WarnWithCtx(cw.Ctx).Msgf("unexpected order type: %T, value: %v. Skipping", order, order)
}
} else {
logger.WarnWithCtx(cw.Ctx).Msgf("unexpected order type: %T, value: %v. Skipping", order, order)
sortFields = append(sortFields, strconv.Quote(fieldName))
}
} else {
sortFields = append(sortFields, strconv.Quote(fieldName))
logger.WarnWithCtx(cw.Ctx).Msgf("unexpected value's type: %T (key, value): (%s, %v). Skipping", v, k, v)
}
} else {
logger.WarnWithCtx(cw.Ctx).Msgf("unexpected value's type: %T (key, value): (%s, %v). Skipping", v, k, v)
}
}
return sortFields
case map[string]string:
sortFields := make([]string, 0)

for fieldName, fieldValue := range sortMaps {
if strings.HasPrefix(fieldName, "_") && cw.Table.GetFieldInfo(cw.Ctx, fieldName) == clickhouse.NotExists {
// TODO Elastic internal fields will need to be supported in the future
continue
}
sortFields = append(sortFields, fmt.Sprintf("%s %s", strconv.Quote(fieldName), fieldValue))
}

return sortFields
default:
logger.ErrorWithCtx(cw.Ctx).Msgf("unexpected type of sortMaps: %T, value: %v", sortMaps, sortMaps)
return []string{}
}
return sortFields
}

func (cw *ClickhouseQueryTranslator) parseSize(queryMap QueryMap) (size int, ok bool) {
Expand Down
9 changes: 8 additions & 1 deletion quesma/queryparser/query_parser_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -490,7 +490,7 @@ func TestQueryParseDateMathExpression(t *testing.T) {

func Test_parseSortFields(t *testing.T) {
tests := []struct {
sortMap []any
sortMap any
sortFields []string
}{
{
Expand All @@ -507,6 +507,13 @@ func Test_parseSortFields(t *testing.T) {
[]any{},
[]string{},
},
{
sortMap: map[string]string{
"timestamp": "desc",
"_doc": "desc",
},
sortFields: []string{`"timestamp" desc`},
},
}
table, _ := clickhouse.NewTable(`CREATE TABLE `+tableName+`
( "@timestamp" DateTime64(3, 'UTC'), "service.name" String, "no_order_field" String, "_table_field_with_underscore" Int64 )
Expand Down

0 comments on commit 2658e44

Please sign in to comment.