value.go 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145
  1. // Copyright 2015 Google Inc. All Rights Reserved.
  2. //
  3. // Licensed under the Apache License, Version 2.0 (the "License");
  4. // you may not use this file except in compliance with the License.
  5. // You may obtain a copy of the License at
  6. //
  7. // http://www.apache.org/licenses/LICENSE-2.0
  8. //
  9. // Unless required by applicable law or agreed to in writing, software
  10. // distributed under the License is distributed on an "AS IS" BASIS,
  11. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. // See the License for the specific language governing permissions and
  13. // limitations under the License.
  14. package bigquery
  15. import (
  16. "errors"
  17. "fmt"
  18. "strconv"
  19. "time"
  20. bq "google.golang.org/api/bigquery/v2"
  21. )
  22. // Value stores the contents of a single cell from a BigQuery result.
  23. type Value interface{}
  24. // ValueLoader stores a slice of Values representing a result row from a Read operation.
  25. // See Iterator.Get for more information.
  26. type ValueLoader interface {
  27. Load(v []Value) error
  28. }
  29. // ValueList converts a []Value to implement ValueLoader.
  30. type ValueList []Value
  31. // Load stores a sequence of values in a ValueList.
  32. func (vs *ValueList) Load(v []Value) error {
  33. *vs = append(*vs, v...)
  34. return nil
  35. }
  36. // convertRows converts a series of TableRows into a series of Value slices.
  37. // schema is used to interpret the data from rows; its length must match the
  38. // length of each row.
  39. func convertRows(rows []*bq.TableRow, schema Schema) ([][]Value, error) {
  40. var rs [][]Value
  41. for _, r := range rows {
  42. row, err := convertRow(r, schema)
  43. if err != nil {
  44. return nil, err
  45. }
  46. rs = append(rs, row)
  47. }
  48. return rs, nil
  49. }
  50. func convertRow(r *bq.TableRow, schema Schema) ([]Value, error) {
  51. if len(schema) != len(r.F) {
  52. return nil, errors.New("schema length does not match row length")
  53. }
  54. var values []Value
  55. for i, cell := range r.F {
  56. fs := schema[i]
  57. v, err := convertValue(cell.V, fs.Type, fs.Schema)
  58. if err != nil {
  59. return nil, err
  60. }
  61. values = append(values, v)
  62. }
  63. return values, nil
  64. }
  65. func convertValue(val interface{}, typ FieldType, schema Schema) (Value, error) {
  66. switch val := val.(type) {
  67. case nil:
  68. return nil, nil
  69. case []interface{}:
  70. return convertRepeatedRecord(val, typ, schema)
  71. case map[string]interface{}:
  72. return convertNestedRecord(val, schema)
  73. case string:
  74. return convertBasicType(val, typ)
  75. default:
  76. return nil, fmt.Errorf("got value %v; expected a value of type %s", val, typ)
  77. }
  78. }
  79. func convertRepeatedRecord(vals []interface{}, typ FieldType, schema Schema) (Value, error) {
  80. var values []Value
  81. for _, cell := range vals {
  82. // each cell contains a single entry, keyed by "v"
  83. val := cell.(map[string]interface{})["v"]
  84. v, err := convertValue(val, typ, schema)
  85. if err != nil {
  86. return nil, err
  87. }
  88. values = append(values, v)
  89. }
  90. return values, nil
  91. }
  92. func convertNestedRecord(val map[string]interface{}, schema Schema) (Value, error) {
  93. // convertNestedRecord is similar to convertRow, as a record has the same structure as a row.
  94. // Nested records are wrapped in a map with a single key, "f".
  95. record := val["f"].([]interface{})
  96. if len(record) != len(schema) {
  97. return nil, errors.New("schema length does not match record length")
  98. }
  99. var values []Value
  100. for i, cell := range record {
  101. // each cell contains a single entry, keyed by "v"
  102. val := cell.(map[string]interface{})["v"]
  103. fs := schema[i]
  104. v, err := convertValue(val, fs.Type, fs.Schema)
  105. if err != nil {
  106. return nil, err
  107. }
  108. values = append(values, v)
  109. }
  110. return values, nil
  111. }
  112. // convertBasicType returns val as an interface with a concrete type specified by typ.
  113. func convertBasicType(val string, typ FieldType) (Value, error) {
  114. switch typ {
  115. case StringFieldType:
  116. return val, nil
  117. case IntegerFieldType:
  118. return strconv.Atoi(val)
  119. case FloatFieldType:
  120. return strconv.ParseFloat(val, 64)
  121. case BooleanFieldType:
  122. return strconv.ParseBool(val)
  123. case TimestampFieldType:
  124. f, err := strconv.ParseFloat(val, 64)
  125. return Value(time.Unix(0, int64(f*1e9))), err
  126. default:
  127. return nil, errors.New("unrecognized type")
  128. }
  129. }