diff --git a/bigquery/integration_test.go b/bigquery/integration_test.go index 9c3e80f41d9e..34ffa80bc5ff 100644 --- a/bigquery/integration_test.go +++ b/bigquery/integration_test.go @@ -1175,6 +1175,7 @@ type TestStruct struct { RangeDate *RangeValue `bigquery:"rangedate"` //TODO: remove tags when field normalization works RangeDateTime *RangeValue `bigquery:"rangedatetime"` RangeTimestamp *RangeValue `bigquery:"rangetimestamp"` + RangeArray []*RangeValue StringArray []string IntegerArray []int64 FloatArray []float64 @@ -1208,6 +1209,7 @@ func TestIntegration_InsertAndReadStructs(t *testing.T) { 11: DateFieldType, 12: DateTimeFieldType, 13: TimestampFieldType, + 14: DateFieldType, } { if schema[idx].Type != RangeFieldType { t.Fatalf("mismatch in expected RANGE element in schema field %d", idx) @@ -1258,6 +1260,7 @@ func TestIntegration_InsertAndReadStructs(t *testing.T) { rangedate, rangedatetime, rangetimestamp, + []*RangeValue{rangedate}, []string{"a", "b"}, []int64{1, 2}, []float64{1, 1.41}, @@ -1296,6 +1299,7 @@ func TestIntegration_InsertAndReadStructs(t *testing.T) { RangeDate: rangedate, RangeDateTime: rangedatetime, RangeTimestamp: rangetimestamp, + RangeArray: []*RangeValue{rangedate}, }, } var savers []*StructSaver @@ -2317,6 +2321,31 @@ func initQueryParameterTestCases() { []Value{rangeTimestamp2}, rangeTimestamp2, }, + { + "RangeArray", + "SELECT @val", + []QueryParameter{ + { + Name: "val", + Value: &QueryParameterValue{ + Type: StandardSQLDataType{ + ArrayElementType: &StandardSQLDataType{ + TypeKind: "RANGE", + RangeElementType: &StandardSQLDataType{ + TypeKind: "TIMESTAMP", + }, + }, + }, + ArrayValue: []QueryParameterValue{ + {Value: rangeTimestamp1}, + {Value: rangeTimestamp2}, + }, + }, + }, + }, + []Value{[]Value{rangeTimestamp1, rangeTimestamp2}}, + []interface{}{rangeTimestamp1, rangeTimestamp2}, + }, { "NestedStructParam", "SELECT @val", diff --git a/bigquery/value.go b/bigquery/value.go index 5c0165f7373c..e5b9ccc7e66c 100644 --- a/bigquery/value.go +++ b/bigquery/value.go @@ -900,7 +900,7 @@ func convertRow(r *bq.TableRow, schema Schema) ([]Value, error) { if fs.RangeElementType == nil { return nil, errors.New("bigquery: incomplete range schema for conversion") } - v, err = convertRangeValue(cell.V.(string), fs.RangeElementType.Type) + v, err = convertRangeTableCell(cell, fs) } else { v, err = convertValue(cell.V, fs.Type, fs.Schema) } @@ -1058,3 +1058,21 @@ func convertRangeValue(val string, elementType FieldType) (Value, error) { } return rv, nil } + +// convertRangeTableCell handles parsing of the API representation of the RANGE type, +// which can come as a single value or array. +func convertRangeTableCell(cell *bq.TableCell, fs *FieldSchema) (Value, error) { + if fs.Repeated { + rangeValues := []Value{} + for _, val := range cell.V.([]interface{}) { + rawRangeValue := val.(map[string]interface{})["v"] + rangeVal, err := convertRangeValue(rawRangeValue.(string), fs.RangeElementType.Type) + if err != nil { + return nil, err + } + rangeValues = append(rangeValues, rangeVal) + } + return rangeValues, nil + } + return convertRangeValue(cell.V.(string), fs.RangeElementType.Type) +}