Skip to content

Commit

Permalink
fix(bigquery): handle null RANGE (#11058)
Browse files Browse the repository at this point in the history
Fixes #11047
  • Loading branch information
alvarowolfx authored Oct 29, 2024
1 parent 83352c4 commit 9979e72
Show file tree
Hide file tree
Showing 2 changed files with 43 additions and 3 deletions.
10 changes: 7 additions & 3 deletions bigquery/value.go
Original file line number Diff line number Diff line change
Expand Up @@ -1021,7 +1021,11 @@ var unboundedRangeSentinel = "UNBOUNDED"

// convertRangeValue aids in parsing the compound RANGE api data representation.
// The format for a range value is: "[startval, endval)"
func convertRangeValue(val string, elementType FieldType) (Value, error) {
func convertRangeValue(cellVal interface{}, elementType FieldType) (Value, error) {
if cellVal == nil {
return nil, nil
}
val := cellVal.(string)
supported := false
for _, t := range []FieldType{DateFieldType, DateTimeFieldType, TimestampFieldType} {
if elementType == t {
Expand Down Expand Up @@ -1066,13 +1070,13 @@ func convertRangeTableCell(cell *bq.TableCell, fs *FieldSchema) (Value, error) {
rangeValues := []Value{}
for _, val := range cell.V.([]interface{}) {
rawRangeValue := val.(map[string]interface{})["v"]
rangeVal, err := convertRangeValue(rawRangeValue.(string), fs.RangeElementType.Type)
rangeVal, err := convertRangeValue(rawRangeValue, fs.RangeElementType.Type)
if err != nil {
return nil, err
}
rangeValues = append(rangeValues, rangeVal)
}
return rangeValues, nil
}
return convertRangeValue(cell.V.(string), fs.RangeElementType.Type)
return convertRangeValue(cell.V, fs.RangeElementType.Type)
}
36 changes: 36 additions & 0 deletions bigquery/value_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,42 @@ func TestConvertTime(t *testing.T) {
}
}

func TestConvertRange(t *testing.T) {
schema := Schema{
{Type: RangeFieldType, RangeElementType: &RangeElementType{Type: TimestampFieldType}},
{Type: RangeFieldType, RangeElementType: &RangeElementType{Type: DateTimeFieldType}},
{Type: RangeFieldType, RangeElementType: &RangeElementType{Type: DateFieldType}},
// Test null value
{Type: RangeFieldType, RangeElementType: &RangeElementType{Type: TimestampFieldType}},
}

ts := testTimestamp.Round(time.Millisecond)
row := &bq.TableRow{
F: []*bq.TableCell{
{V: fmt.Sprintf("[%d, UNBOUNDED)", ts.UnixMicro())},
{V: fmt.Sprintf("[UNBOUNDED, %s)", testDateTime.String())},
{V: fmt.Sprintf("[%s, %s)", testDate.String(), testDate.String())},
{V: nil}, // NULL RANGE
},
}
got, err := convertRow(row, schema)
if err != nil {
t.Fatalf("error converting: %v", err)
}
want := []Value{
&RangeValue{Start: ts},
&RangeValue{End: testDateTime},
&RangeValue{Start: testDate, End: testDate},
nil,
}
for i, g := range got {
w := want[i]
if !testutil.Equal(g, w) {
t.Errorf("#%d: got:\n%v\nwant:\n%v", i, g, w)
}
}
}

func TestConvertSmallTimes(t *testing.T) {
for _, year := range []int{1600, 1066, 1} {
want := time.Date(year, time.January, 1, 0, 0, 0, 0, time.UTC)
Expand Down

0 comments on commit 9979e72

Please sign in to comment.