Skip to content

Commit

Permalink
Fix timestamp undesired cast to float64
Browse files Browse the repository at this point in the history
  • Loading branch information
ddelemeny committed Apr 22, 2024
1 parent e463295 commit e68dd1f
Show file tree
Hide file tree
Showing 2 changed files with 45 additions and 10 deletions.
47 changes: 37 additions & 10 deletions pkg/quickwit/response_parser.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package quickwit

import (
"bytes"
"encoding/json"
"errors"
"fmt"
Expand Down Expand Up @@ -49,14 +50,20 @@ func parseResponse(rawResponses []*json.RawMessage, targets []*Query, configured
}

for i, rawRes := range rawResponses {
target := targets[i]

byteReader := bytes.NewReader(*rawRes)
dec := json.NewDecoder(byteReader)
if isLogsQuery(target) {
dec.UseNumber()
}
var res *es.SearchResponse
err := json.Unmarshal([]byte(*rawRes), &res)
err := dec.Decode(&res)
if nil != err {
qwlog.Debug("Failed to unmarshal response", "err", err.Error(), "byteRes", *rawRes)
qwlog.Debug("Failed to decode response", "err", err.Error(), "byteRes", *rawRes)
continue
}

target := targets[i]
if res.Error != nil {
errResult := getErrorFromElasticResponse(res)
result.Responses[target.RefID] = backend.DataResponse{
Expand Down Expand Up @@ -269,14 +276,28 @@ func processDocsToDataFrameFields(docs []map[string]interface{}, propNames []str
switch propNameValue.(type) {
// We are checking for default data types values (float64, int, bool, string)
// and default to json.RawMessage if we cannot find any of them
case json.Number:
rawPropSlice := getDocPropSlice[json.Number](docs, propName, size)
propSlice := make([]*float64, size)
for i, val := range rawPropSlice {
val_f64, err := val.Float64()
if err == nil {
propSlice[i] = &val_f64
}
}
allFields[propNameIdx] = createFieldOfType[float64](propSlice, propName, size, isFilterable)
case float64:
allFields[propNameIdx] = createFieldOfType[float64](docs, propName, size, isFilterable)
propSlice := getDocPropSlice[float64](docs, propName, size)
allFields[propNameIdx] = createFieldOfType[float64](propSlice, propName, size, isFilterable)
case int:
allFields[propNameIdx] = createFieldOfType[int](docs, propName, size, isFilterable)
propSlice := getDocPropSlice[int](docs, propName, size)
allFields[propNameIdx] = createFieldOfType[int](propSlice, propName, size, isFilterable)
case string:
allFields[propNameIdx] = createFieldOfType[string](docs, propName, size, isFilterable)
propSlice := getDocPropSlice[string](docs, propName, size)
allFields[propNameIdx] = createFieldOfType[string](propSlice, propName, size, isFilterable)
case bool:
allFields[propNameIdx] = createFieldOfType[bool](docs, propName, size, isFilterable)
propSlice := getDocPropSlice[bool](docs, propName, size)
allFields[propNameIdx] = createFieldOfType[bool](propSlice, propName, size, isFilterable)
default:
fieldVector := make([]*json.RawMessage, size)
for i, doc := range docs {
Expand Down Expand Up @@ -1076,15 +1097,21 @@ func findTheFirstNonNilDocValueForPropName(docs []map[string]interface{}, propNa
return docs[0][propName]
}

func createFieldOfType[T int | float64 | bool | string](docs []map[string]interface{}, propName string, size int, isFilterable bool) *data.Field {
fieldVector := make([]*T, size)
func getDocPropSlice[T json.Number | int | float64 | bool | string](docs []map[string]any, propName string, size int) []*T {
values := make([]*T, size)

for i, doc := range docs {
value, ok := doc[propName].(T)
if !ok {
continue
}
fieldVector[i] = &value
values[i] = &value
}

return values
}

func createFieldOfType[T int | float64 | bool | string](fieldVector []*T, propName string, size int, isFilterable bool) *data.Field {
field := data.NewField(propName, nil, fieldVector)
field.Config = &data.FieldConfig{Filterable: &isFilterable}
return field
Expand Down
8 changes: 8 additions & 0 deletions pkg/utils/parse_time.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package utils

import (
"encoding/json"
"errors"
"fmt"
"reflect"
Expand Down Expand Up @@ -55,6 +56,13 @@ func ParseTime(value any, timeOutputFormat string) (time.Time, error) {
case TimestampSecs, TimestampMillis, TimestampMicros, TimestampNanos:
var value_i64 int64
switch value.(type) {
case json.Number:
var err error
valueNumber := value.(json.Number)
value_i64, err = valueNumber.Int64()
if nil != err {
return time.Time{}, errors.New("couldn't convert timestamp from json.Number to Int64")
}
case int, int8, int16, int32, int64:
value_i64 = reflect.ValueOf(value).Int()
case float32, float64:
Expand Down

0 comments on commit e68dd1f

Please sign in to comment.