1
2
3
4
5
6
7
8
9
10
11
12
13
14
15 package bigquery
16
17 import (
18 "bytes"
19 "encoding/json"
20 "fmt"
21 "math"
22 "reflect"
23 "strconv"
24 "time"
25
26 "cloud.google.com/go/civil"
27 )
28
29 var (
30 jsonNull = []byte("null")
31 posInf = []byte(`"+Inf"`)
32 inf = []byte(`"Inf"`)
33 minusInf = []byte(`"-Inf"`)
34 infinity = []byte(`"Infinity"`)
35 minusInfinity = []byte(`"-Infinity"`)
36 nan = []byte(`"NaN"`)
37 )
38
39
40 type NullInt64 struct {
41 Int64 int64
42 Valid bool
43 }
44
45 func (n NullInt64) String() string { return nullstr(n.Valid, n.Int64) }
46
47
48 type NullString struct {
49 StringVal string
50 Valid bool
51 }
52
53 func (n NullString) String() string { return nullstr(n.Valid, n.StringVal) }
54
55
56 type NullGeography struct {
57 GeographyVal string
58 Valid bool
59 }
60
61 func (n NullGeography) String() string { return nullstr(n.Valid, n.GeographyVal) }
62
63
64 type NullJSON struct {
65 JSONVal string
66 Valid bool
67 }
68
69 func (n NullJSON) String() string { return nullstr(n.Valid, n.JSONVal) }
70
71
72 type NullFloat64 struct {
73 Float64 float64
74 Valid bool
75 }
76
77 func (n NullFloat64) String() string { return nullstr(n.Valid, n.Float64) }
78
79
80 type NullBool struct {
81 Bool bool
82 Valid bool
83 }
84
85 func (n NullBool) String() string { return nullstr(n.Valid, n.Bool) }
86
87
88 type NullTimestamp struct {
89 Timestamp time.Time
90 Valid bool
91 }
92
93 func (n NullTimestamp) String() string { return nullstr(n.Valid, n.Timestamp) }
94
95
96 type NullDate struct {
97 Date civil.Date
98 Valid bool
99 }
100
101 func (n NullDate) String() string { return nullstr(n.Valid, n.Date) }
102
103
104 type NullTime struct {
105 Time civil.Time
106 Valid bool
107 }
108
109 func (n NullTime) String() string {
110 if !n.Valid {
111 return "<null>"
112 }
113 return CivilTimeString(n.Time)
114 }
115
116
117 type NullDateTime struct {
118 DateTime civil.DateTime
119 Valid bool
120 }
121
122 func (n NullDateTime) String() string {
123 if !n.Valid {
124 return "<null>"
125 }
126 return CivilDateTimeString(n.DateTime)
127 }
128
129
130 func (n NullInt64) MarshalJSON() ([]byte, error) { return nulljson(n.Valid, n.Int64) }
131
132
133 func (n NullFloat64) MarshalJSON() (b []byte, err error) {
134 if n.Valid {
135 switch {
136 case math.IsInf(n.Float64, 1):
137 return infinity, nil
138 case math.IsInf(n.Float64, -1):
139 return minusInfinity, nil
140 case math.IsNaN(n.Float64):
141 return nan, nil
142 default:
143 return json.Marshal(n.Float64)
144 }
145 }
146 return jsonNull, nil
147 }
148
149
150 func (n NullBool) MarshalJSON() ([]byte, error) { return nulljson(n.Valid, n.Bool) }
151
152
153 func (n NullString) MarshalJSON() ([]byte, error) { return nulljson(n.Valid, n.StringVal) }
154
155
156 func (n NullGeography) MarshalJSON() ([]byte, error) { return nulljson(n.Valid, n.GeographyVal) }
157
158
159 func (n NullJSON) MarshalJSON() ([]byte, error) { return nulljson(n.Valid, n.JSONVal) }
160
161
162 func (n NullTimestamp) MarshalJSON() ([]byte, error) { return nulljson(n.Valid, n.Timestamp) }
163
164
165 func (n NullDate) MarshalJSON() ([]byte, error) { return nulljson(n.Valid, n.Date) }
166
167
168 func (n NullTime) MarshalJSON() ([]byte, error) {
169 if !n.Valid {
170 return jsonNull, nil
171 }
172 return []byte(`"` + CivilTimeString(n.Time) + `"`), nil
173 }
174
175
176 func (n NullDateTime) MarshalJSON() ([]byte, error) {
177 if !n.Valid {
178 return jsonNull, nil
179 }
180 return []byte(`"` + CivilDateTimeString(n.DateTime) + `"`), nil
181 }
182
183 func nullstr(valid bool, v interface{}) string {
184 if !valid {
185 return "NULL"
186 }
187 return fmt.Sprint(v)
188 }
189
190 func nulljson(valid bool, v interface{}) ([]byte, error) {
191 if !valid {
192 return jsonNull, nil
193 }
194 return json.Marshal(v)
195 }
196
197
198 func (n *NullInt64) UnmarshalJSON(b []byte) error {
199 n.Valid = false
200 n.Int64 = 0
201 if bytes.Equal(b, jsonNull) {
202 return nil
203 }
204
205 if err := json.Unmarshal(b, &n.Int64); err != nil {
206 return err
207 }
208 n.Valid = true
209 return nil
210 }
211
212
213 func (n *NullFloat64) UnmarshalJSON(b []byte) error {
214 n.Valid = false
215 n.Float64 = 0
216 if bytes.Equal(b, jsonNull) {
217 return nil
218 } else if bytes.Equal(b, posInf) || bytes.Equal(b, inf) || bytes.Equal(b, infinity) {
219 n.Float64 = math.Inf(1)
220 n.Valid = true
221 return nil
222 } else if bytes.Equal(b, minusInf) || bytes.Equal(b, minusInfinity) {
223 n.Float64 = math.Inf(-1)
224 n.Valid = true
225 return nil
226 } else if bytes.Equal(b, nan) {
227 n.Float64 = math.NaN()
228 n.Valid = true
229 return nil
230 }
231 if err := json.Unmarshal(b, &n.Float64); err != nil {
232 return err
233 }
234 n.Valid = true
235 return nil
236 }
237
238
239 func (n *NullBool) UnmarshalJSON(b []byte) error {
240 n.Valid = false
241 n.Bool = false
242 if bytes.Equal(b, jsonNull) {
243 return nil
244 }
245
246 if err := json.Unmarshal(b, &n.Bool); err != nil {
247 return err
248 }
249 n.Valid = true
250 return nil
251 }
252
253
254 func (n *NullString) UnmarshalJSON(b []byte) error {
255 n.Valid = false
256 n.StringVal = ""
257 if bytes.Equal(b, jsonNull) {
258 return nil
259 }
260
261 if err := json.Unmarshal(b, &n.StringVal); err != nil {
262 return err
263 }
264 n.Valid = true
265 return nil
266 }
267
268
269 func (n *NullGeography) UnmarshalJSON(b []byte) error {
270 n.Valid = false
271 n.GeographyVal = ""
272 if bytes.Equal(b, jsonNull) {
273 return nil
274 }
275 if err := json.Unmarshal(b, &n.GeographyVal); err != nil {
276 return err
277 }
278 n.Valid = true
279 return nil
280 }
281
282
283 func (n *NullJSON) UnmarshalJSON(b []byte) error {
284 n.Valid = false
285 n.JSONVal = ""
286 if bytes.Equal(b, jsonNull) {
287 return nil
288 }
289 if err := json.Unmarshal(b, &n.JSONVal); err != nil {
290 return err
291 }
292 n.Valid = true
293 return nil
294 }
295
296
297 func (n *NullTimestamp) UnmarshalJSON(b []byte) error {
298 n.Valid = false
299 n.Timestamp = time.Time{}
300 if bytes.Equal(b, jsonNull) {
301 return nil
302 }
303
304 if err := json.Unmarshal(b, &n.Timestamp); err != nil {
305 return err
306 }
307 n.Valid = true
308 return nil
309 }
310
311
312 func (n *NullDate) UnmarshalJSON(b []byte) error {
313 n.Valid = false
314 n.Date = civil.Date{}
315 if bytes.Equal(b, jsonNull) {
316 return nil
317 }
318
319 if err := json.Unmarshal(b, &n.Date); err != nil {
320 return err
321 }
322 n.Valid = true
323 return nil
324 }
325
326
327 func (n *NullTime) UnmarshalJSON(b []byte) error {
328 n.Valid = false
329 n.Time = civil.Time{}
330 if bytes.Equal(b, jsonNull) {
331 return nil
332 }
333
334 s, err := strconv.Unquote(string(b))
335 if err != nil {
336 return err
337 }
338
339 t, err := civil.ParseTime(s)
340 if err != nil {
341 return err
342 }
343 n.Time = t
344
345 n.Valid = true
346 return nil
347 }
348
349
350 func (n *NullDateTime) UnmarshalJSON(b []byte) error {
351 n.Valid = false
352 n.DateTime = civil.DateTime{}
353 if bytes.Equal(b, jsonNull) {
354 return nil
355 }
356
357 s, err := strconv.Unquote(string(b))
358 if err != nil {
359 return err
360 }
361
362 dt, err := parseCivilDateTime(s)
363 if err != nil {
364 return err
365 }
366 n.DateTime = dt
367
368 n.Valid = true
369 return nil
370 }
371
372 var (
373 typeOfNullInt64 = reflect.TypeOf(NullInt64{})
374 typeOfNullFloat64 = reflect.TypeOf(NullFloat64{})
375 typeOfNullBool = reflect.TypeOf(NullBool{})
376 typeOfNullString = reflect.TypeOf(NullString{})
377 typeOfNullGeography = reflect.TypeOf(NullGeography{})
378 typeOfNullJSON = reflect.TypeOf(NullJSON{})
379 typeOfNullTimestamp = reflect.TypeOf(NullTimestamp{})
380 typeOfNullDate = reflect.TypeOf(NullDate{})
381 typeOfNullTime = reflect.TypeOf(NullTime{})
382 typeOfNullDateTime = reflect.TypeOf(NullDateTime{})
383 )
384
385 func nullableFieldType(t reflect.Type) FieldType {
386 switch t {
387 case typeOfNullInt64:
388 return IntegerFieldType
389 case typeOfNullFloat64:
390 return FloatFieldType
391 case typeOfNullBool:
392 return BooleanFieldType
393 case typeOfNullString:
394 return StringFieldType
395 case typeOfNullGeography:
396 return GeographyFieldType
397 case typeOfNullJSON:
398 return JSONFieldType
399 case typeOfNullTimestamp:
400 return TimestampFieldType
401 case typeOfNullDate:
402 return DateFieldType
403 case typeOfNullTime:
404 return TimeFieldType
405 case typeOfNullDateTime:
406 return DateTimeFieldType
407 default:
408 return ""
409 }
410 }
411
View as plain text