nulls.go 7.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320
  1. // Copyright 2015 Google LLC
  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. "bytes"
  17. "encoding/json"
  18. "fmt"
  19. "reflect"
  20. "strconv"
  21. "time"
  22. "cloud.google.com/go/civil"
  23. )
  24. // NullInt64 represents a BigQuery INT64 that may be NULL.
  25. type NullInt64 struct {
  26. Int64 int64
  27. Valid bool // Valid is true if Int64 is not NULL.
  28. }
  29. func (n NullInt64) String() string { return nullstr(n.Valid, n.Int64) }
  30. // NullString represents a BigQuery STRING that may be NULL.
  31. type NullString struct {
  32. StringVal string
  33. Valid bool // Valid is true if StringVal is not NULL.
  34. }
  35. func (n NullString) String() string { return nullstr(n.Valid, n.StringVal) }
  36. // NullFloat64 represents a BigQuery FLOAT64 that may be NULL.
  37. type NullFloat64 struct {
  38. Float64 float64
  39. Valid bool // Valid is true if Float64 is not NULL.
  40. }
  41. func (n NullFloat64) String() string { return nullstr(n.Valid, n.Float64) }
  42. // NullBool represents a BigQuery BOOL that may be NULL.
  43. type NullBool struct {
  44. Bool bool
  45. Valid bool // Valid is true if Bool is not NULL.
  46. }
  47. func (n NullBool) String() string { return nullstr(n.Valid, n.Bool) }
  48. // NullTimestamp represents a BigQuery TIMESTAMP that may be null.
  49. type NullTimestamp struct {
  50. Timestamp time.Time
  51. Valid bool // Valid is true if Time is not NULL.
  52. }
  53. func (n NullTimestamp) String() string { return nullstr(n.Valid, n.Timestamp) }
  54. // NullDate represents a BigQuery DATE that may be null.
  55. type NullDate struct {
  56. Date civil.Date
  57. Valid bool // Valid is true if Date is not NULL.
  58. }
  59. func (n NullDate) String() string { return nullstr(n.Valid, n.Date) }
  60. // NullTime represents a BigQuery TIME that may be null.
  61. type NullTime struct {
  62. Time civil.Time
  63. Valid bool // Valid is true if Time is not NULL.
  64. }
  65. func (n NullTime) String() string {
  66. if !n.Valid {
  67. return "<null>"
  68. }
  69. return CivilTimeString(n.Time)
  70. }
  71. // NullDateTime represents a BigQuery DATETIME that may be null.
  72. type NullDateTime struct {
  73. DateTime civil.DateTime
  74. Valid bool // Valid is true if DateTime is not NULL.
  75. }
  76. func (n NullDateTime) String() string {
  77. if !n.Valid {
  78. return "<null>"
  79. }
  80. return CivilDateTimeString(n.DateTime)
  81. }
  82. // MarshalJSON converts the NullInt64 to JSON.
  83. func (n NullInt64) MarshalJSON() ([]byte, error) { return nulljson(n.Valid, n.Int64) }
  84. // MarshalJSON converts the NullFloat64 to JSON.
  85. func (n NullFloat64) MarshalJSON() ([]byte, error) { return nulljson(n.Valid, n.Float64) }
  86. // MarshalJSON converts the NullBool to JSON.
  87. func (n NullBool) MarshalJSON() ([]byte, error) { return nulljson(n.Valid, n.Bool) }
  88. // MarshalJSON converts the NullString to JSON.
  89. func (n NullString) MarshalJSON() ([]byte, error) { return nulljson(n.Valid, n.StringVal) }
  90. // MarshalJSON converts the NullTimestamp to JSON.
  91. func (n NullTimestamp) MarshalJSON() ([]byte, error) { return nulljson(n.Valid, n.Timestamp) }
  92. // MarshalJSON converts the NullDate to JSON.
  93. func (n NullDate) MarshalJSON() ([]byte, error) { return nulljson(n.Valid, n.Date) }
  94. // MarshalJSON converts the NullTime to JSON.
  95. func (n NullTime) MarshalJSON() ([]byte, error) {
  96. if !n.Valid {
  97. return jsonNull, nil
  98. }
  99. return []byte(`"` + CivilTimeString(n.Time) + `"`), nil
  100. }
  101. // MarshalJSON converts the NullDateTime to JSON.
  102. func (n NullDateTime) MarshalJSON() ([]byte, error) {
  103. if !n.Valid {
  104. return jsonNull, nil
  105. }
  106. return []byte(`"` + CivilDateTimeString(n.DateTime) + `"`), nil
  107. }
  108. func nullstr(valid bool, v interface{}) string {
  109. if !valid {
  110. return "NULL"
  111. }
  112. return fmt.Sprint(v)
  113. }
  114. var jsonNull = []byte("null")
  115. func nulljson(valid bool, v interface{}) ([]byte, error) {
  116. if !valid {
  117. return jsonNull, nil
  118. }
  119. return json.Marshal(v)
  120. }
  121. // UnmarshalJSON converts JSON into a NullInt64.
  122. func (n *NullInt64) UnmarshalJSON(b []byte) error {
  123. n.Valid = false
  124. n.Int64 = 0
  125. if bytes.Equal(b, jsonNull) {
  126. return nil
  127. }
  128. if err := json.Unmarshal(b, &n.Int64); err != nil {
  129. return err
  130. }
  131. n.Valid = true
  132. return nil
  133. }
  134. // UnmarshalJSON converts JSON into a NullFloat64.
  135. func (n *NullFloat64) UnmarshalJSON(b []byte) error {
  136. n.Valid = false
  137. n.Float64 = 0
  138. if bytes.Equal(b, jsonNull) {
  139. return nil
  140. }
  141. if err := json.Unmarshal(b, &n.Float64); err != nil {
  142. return err
  143. }
  144. n.Valid = true
  145. return nil
  146. }
  147. // UnmarshalJSON converts JSON into a NullBool.
  148. func (n *NullBool) UnmarshalJSON(b []byte) error {
  149. n.Valid = false
  150. n.Bool = false
  151. if bytes.Equal(b, jsonNull) {
  152. return nil
  153. }
  154. if err := json.Unmarshal(b, &n.Bool); err != nil {
  155. return err
  156. }
  157. n.Valid = true
  158. return nil
  159. }
  160. // UnmarshalJSON converts JSON into a NullString.
  161. func (n *NullString) UnmarshalJSON(b []byte) error {
  162. n.Valid = false
  163. n.StringVal = ""
  164. if bytes.Equal(b, jsonNull) {
  165. return nil
  166. }
  167. if err := json.Unmarshal(b, &n.StringVal); err != nil {
  168. return err
  169. }
  170. n.Valid = true
  171. return nil
  172. }
  173. // UnmarshalJSON converts JSON into a NullTimestamp.
  174. func (n *NullTimestamp) UnmarshalJSON(b []byte) error {
  175. n.Valid = false
  176. n.Timestamp = time.Time{}
  177. if bytes.Equal(b, jsonNull) {
  178. return nil
  179. }
  180. if err := json.Unmarshal(b, &n.Timestamp); err != nil {
  181. return err
  182. }
  183. n.Valid = true
  184. return nil
  185. }
  186. // UnmarshalJSON converts JSON into a NullDate.
  187. func (n *NullDate) UnmarshalJSON(b []byte) error {
  188. n.Valid = false
  189. n.Date = civil.Date{}
  190. if bytes.Equal(b, jsonNull) {
  191. return nil
  192. }
  193. if err := json.Unmarshal(b, &n.Date); err != nil {
  194. return err
  195. }
  196. n.Valid = true
  197. return nil
  198. }
  199. // UnmarshalJSON converts JSON into a NullTime.
  200. func (n *NullTime) UnmarshalJSON(b []byte) error {
  201. n.Valid = false
  202. n.Time = civil.Time{}
  203. if bytes.Equal(b, jsonNull) {
  204. return nil
  205. }
  206. s, err := strconv.Unquote(string(b))
  207. if err != nil {
  208. return err
  209. }
  210. t, err := civil.ParseTime(s)
  211. if err != nil {
  212. return err
  213. }
  214. n.Time = t
  215. n.Valid = true
  216. return nil
  217. }
  218. // UnmarshalJSON converts JSON into a NullDateTime.
  219. func (n *NullDateTime) UnmarshalJSON(b []byte) error {
  220. n.Valid = false
  221. n.DateTime = civil.DateTime{}
  222. if bytes.Equal(b, jsonNull) {
  223. return nil
  224. }
  225. s, err := strconv.Unquote(string(b))
  226. if err != nil {
  227. return err
  228. }
  229. dt, err := parseCivilDateTime(s)
  230. if err != nil {
  231. return err
  232. }
  233. n.DateTime = dt
  234. n.Valid = true
  235. return nil
  236. }
  237. var (
  238. typeOfNullInt64 = reflect.TypeOf(NullInt64{})
  239. typeOfNullFloat64 = reflect.TypeOf(NullFloat64{})
  240. typeOfNullBool = reflect.TypeOf(NullBool{})
  241. typeOfNullString = reflect.TypeOf(NullString{})
  242. typeOfNullTimestamp = reflect.TypeOf(NullTimestamp{})
  243. typeOfNullDate = reflect.TypeOf(NullDate{})
  244. typeOfNullTime = reflect.TypeOf(NullTime{})
  245. typeOfNullDateTime = reflect.TypeOf(NullDateTime{})
  246. )
  247. func nullableFieldType(t reflect.Type) FieldType {
  248. switch t {
  249. case typeOfNullInt64:
  250. return IntegerFieldType
  251. case typeOfNullFloat64:
  252. return FloatFieldType
  253. case typeOfNullBool:
  254. return BooleanFieldType
  255. case typeOfNullString:
  256. return StringFieldType
  257. case typeOfNullTimestamp:
  258. return TimestampFieldType
  259. case typeOfNullDate:
  260. return DateFieldType
  261. case typeOfNullTime:
  262. return TimeFieldType
  263. case typeOfNullDateTime:
  264. return DateTimeFieldType
  265. default:
  266. return ""
  267. }
  268. }