Skip to content

Commit e68dd1f

Browse files
committed
Fix timestamp undesired cast to float64
1 parent e463295 commit e68dd1f

File tree

2 files changed

+45
-10
lines changed

2 files changed

+45
-10
lines changed

pkg/quickwit/response_parser.go

Lines changed: 37 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package quickwit
22

33
import (
4+
"bytes"
45
"encoding/json"
56
"errors"
67
"fmt"
@@ -49,14 +50,20 @@ func parseResponse(rawResponses []*json.RawMessage, targets []*Query, configured
4950
}
5051

5152
for i, rawRes := range rawResponses {
53+
target := targets[i]
54+
55+
byteReader := bytes.NewReader(*rawRes)
56+
dec := json.NewDecoder(byteReader)
57+
if isLogsQuery(target) {
58+
dec.UseNumber()
59+
}
5260
var res *es.SearchResponse
53-
err := json.Unmarshal([]byte(*rawRes), &res)
61+
err := dec.Decode(&res)
5462
if nil != err {
55-
qwlog.Debug("Failed to unmarshal response", "err", err.Error(), "byteRes", *rawRes)
63+
qwlog.Debug("Failed to decode response", "err", err.Error(), "byteRes", *rawRes)
5664
continue
5765
}
5866

59-
target := targets[i]
6067
if res.Error != nil {
6168
errResult := getErrorFromElasticResponse(res)
6269
result.Responses[target.RefID] = backend.DataResponse{
@@ -269,14 +276,28 @@ func processDocsToDataFrameFields(docs []map[string]interface{}, propNames []str
269276
switch propNameValue.(type) {
270277
// We are checking for default data types values (float64, int, bool, string)
271278
// and default to json.RawMessage if we cannot find any of them
279+
case json.Number:
280+
rawPropSlice := getDocPropSlice[json.Number](docs, propName, size)
281+
propSlice := make([]*float64, size)
282+
for i, val := range rawPropSlice {
283+
val_f64, err := val.Float64()
284+
if err == nil {
285+
propSlice[i] = &val_f64
286+
}
287+
}
288+
allFields[propNameIdx] = createFieldOfType[float64](propSlice, propName, size, isFilterable)
272289
case float64:
273-
allFields[propNameIdx] = createFieldOfType[float64](docs, propName, size, isFilterable)
290+
propSlice := getDocPropSlice[float64](docs, propName, size)
291+
allFields[propNameIdx] = createFieldOfType[float64](propSlice, propName, size, isFilterable)
274292
case int:
275-
allFields[propNameIdx] = createFieldOfType[int](docs, propName, size, isFilterable)
293+
propSlice := getDocPropSlice[int](docs, propName, size)
294+
allFields[propNameIdx] = createFieldOfType[int](propSlice, propName, size, isFilterable)
276295
case string:
277-
allFields[propNameIdx] = createFieldOfType[string](docs, propName, size, isFilterable)
296+
propSlice := getDocPropSlice[string](docs, propName, size)
297+
allFields[propNameIdx] = createFieldOfType[string](propSlice, propName, size, isFilterable)
278298
case bool:
279-
allFields[propNameIdx] = createFieldOfType[bool](docs, propName, size, isFilterable)
299+
propSlice := getDocPropSlice[bool](docs, propName, size)
300+
allFields[propNameIdx] = createFieldOfType[bool](propSlice, propName, size, isFilterable)
280301
default:
281302
fieldVector := make([]*json.RawMessage, size)
282303
for i, doc := range docs {
@@ -1076,15 +1097,21 @@ func findTheFirstNonNilDocValueForPropName(docs []map[string]interface{}, propNa
10761097
return docs[0][propName]
10771098
}
10781099

1079-
func createFieldOfType[T int | float64 | bool | string](docs []map[string]interface{}, propName string, size int, isFilterable bool) *data.Field {
1080-
fieldVector := make([]*T, size)
1100+
func getDocPropSlice[T json.Number | int | float64 | bool | string](docs []map[string]any, propName string, size int) []*T {
1101+
values := make([]*T, size)
1102+
10811103
for i, doc := range docs {
10821104
value, ok := doc[propName].(T)
10831105
if !ok {
10841106
continue
10851107
}
1086-
fieldVector[i] = &value
1108+
values[i] = &value
10871109
}
1110+
1111+
return values
1112+
}
1113+
1114+
func createFieldOfType[T int | float64 | bool | string](fieldVector []*T, propName string, size int, isFilterable bool) *data.Field {
10881115
field := data.NewField(propName, nil, fieldVector)
10891116
field.Config = &data.FieldConfig{Filterable: &isFilterable}
10901117
return field

pkg/utils/parse_time.go

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package utils
22

33
import (
4+
"encoding/json"
45
"errors"
56
"fmt"
67
"reflect"
@@ -55,6 +56,13 @@ func ParseTime(value any, timeOutputFormat string) (time.Time, error) {
5556
case TimestampSecs, TimestampMillis, TimestampMicros, TimestampNanos:
5657
var value_i64 int64
5758
switch value.(type) {
59+
case json.Number:
60+
var err error
61+
valueNumber := value.(json.Number)
62+
value_i64, err = valueNumber.Int64()
63+
if nil != err {
64+
return time.Time{}, errors.New("couldn't convert timestamp from json.Number to Int64")
65+
}
5866
case int, int8, int16, int32, int64:
5967
value_i64 = reflect.ValueOf(value).Int()
6068
case float32, float64:

0 commit comments

Comments
 (0)