google-cloud-bigquery 1.21.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.yardopts +16 -0
- data/AUTHENTICATION.md +158 -0
- data/CHANGELOG.md +397 -0
- data/CODE_OF_CONDUCT.md +40 -0
- data/CONTRIBUTING.md +188 -0
- data/LICENSE +201 -0
- data/LOGGING.md +27 -0
- data/OVERVIEW.md +463 -0
- data/TROUBLESHOOTING.md +31 -0
- data/lib/google-cloud-bigquery.rb +139 -0
- data/lib/google/cloud/bigquery.rb +145 -0
- data/lib/google/cloud/bigquery/argument.rb +197 -0
- data/lib/google/cloud/bigquery/convert.rb +383 -0
- data/lib/google/cloud/bigquery/copy_job.rb +316 -0
- data/lib/google/cloud/bigquery/credentials.rb +50 -0
- data/lib/google/cloud/bigquery/data.rb +526 -0
- data/lib/google/cloud/bigquery/dataset.rb +2845 -0
- data/lib/google/cloud/bigquery/dataset/access.rb +1021 -0
- data/lib/google/cloud/bigquery/dataset/list.rb +162 -0
- data/lib/google/cloud/bigquery/encryption_configuration.rb +123 -0
- data/lib/google/cloud/bigquery/external.rb +2432 -0
- data/lib/google/cloud/bigquery/extract_job.rb +368 -0
- data/lib/google/cloud/bigquery/insert_response.rb +180 -0
- data/lib/google/cloud/bigquery/job.rb +657 -0
- data/lib/google/cloud/bigquery/job/list.rb +162 -0
- data/lib/google/cloud/bigquery/load_job.rb +1704 -0
- data/lib/google/cloud/bigquery/model.rb +740 -0
- data/lib/google/cloud/bigquery/model/list.rb +164 -0
- data/lib/google/cloud/bigquery/project.rb +1655 -0
- data/lib/google/cloud/bigquery/project/list.rb +161 -0
- data/lib/google/cloud/bigquery/query_job.rb +1695 -0
- data/lib/google/cloud/bigquery/routine.rb +1108 -0
- data/lib/google/cloud/bigquery/routine/list.rb +165 -0
- data/lib/google/cloud/bigquery/schema.rb +564 -0
- data/lib/google/cloud/bigquery/schema/field.rb +668 -0
- data/lib/google/cloud/bigquery/service.rb +589 -0
- data/lib/google/cloud/bigquery/standard_sql.rb +495 -0
- data/lib/google/cloud/bigquery/table.rb +3340 -0
- data/lib/google/cloud/bigquery/table/async_inserter.rb +520 -0
- data/lib/google/cloud/bigquery/table/list.rb +172 -0
- data/lib/google/cloud/bigquery/time.rb +65 -0
- data/lib/google/cloud/bigquery/version.rb +22 -0
- metadata +297 -0
@@ -0,0 +1,668 @@
|
|
1
|
+
# Copyright 2017 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
|
+
# https://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
|
+
|
15
|
+
|
16
|
+
module Google
|
17
|
+
module Cloud
|
18
|
+
module Bigquery
|
19
|
+
class Schema
|
20
|
+
##
|
21
|
+
# # Schema Field
|
22
|
+
#
|
23
|
+
# The fields of a table schema.
|
24
|
+
#
|
25
|
+
# @see https://cloud.google.com/bigquery/docs/loading-data#loading_denormalized_nested_and_repeated_data
|
26
|
+
# Loading denormalized, nested, and repeated data
|
27
|
+
#
|
28
|
+
# @example
|
29
|
+
# require "google/cloud/bigquery"
|
30
|
+
#
|
31
|
+
# bigquery = Google::Cloud::Bigquery.new
|
32
|
+
# dataset = bigquery.dataset "my_dataset"
|
33
|
+
# table = dataset.table "my_table"
|
34
|
+
#
|
35
|
+
# field = table.schema.field "name"
|
36
|
+
# field.required? #=> true
|
37
|
+
#
|
38
|
+
class Field
|
39
|
+
# @private
|
40
|
+
MODES = ["NULLABLE", "REQUIRED", "REPEATED"].freeze
|
41
|
+
|
42
|
+
# @private
|
43
|
+
TYPES = ["STRING", "INTEGER", "INT64", "FLOAT", "FLOAT64", "NUMERIC", "BOOLEAN", "BOOL", "BYTES", "TIMESTAMP",
|
44
|
+
"TIME", "DATETIME", "DATE", "RECORD", "STRUCT"].freeze
|
45
|
+
|
46
|
+
##
|
47
|
+
# The name of the field.
|
48
|
+
#
|
49
|
+
# @return [String] The field name. The name must contain only
|
50
|
+
# letters (a-z, A-Z), numbers (0-9), or underscores (_), and must
|
51
|
+
# start with a letter or underscore. The maximum length is 128
|
52
|
+
# characters.
|
53
|
+
#
|
54
|
+
def name
|
55
|
+
@gapi.name
|
56
|
+
end
|
57
|
+
|
58
|
+
##
|
59
|
+
# Updates the name of the field.
|
60
|
+
#
|
61
|
+
# @param [String] new_name The field name. The name must contain only
|
62
|
+
# letters (a-z, A-Z), numbers (0-9), or underscores (_), and must
|
63
|
+
# start with a letter or underscore. The maximum length is 128
|
64
|
+
# characters.
|
65
|
+
#
|
66
|
+
def name= new_name
|
67
|
+
@gapi.update! name: String(new_name)
|
68
|
+
end
|
69
|
+
|
70
|
+
##
|
71
|
+
# The data type of the field.
|
72
|
+
#
|
73
|
+
# @return [String] The field data type. Possible values include
|
74
|
+
# `STRING`, `BYTES`, `INTEGER`, `INT64` (same as `INTEGER`),
|
75
|
+
# `FLOAT`, `FLOAT64` (same as `FLOAT`), `NUMERIC`, `BOOLEAN`, `BOOL`
|
76
|
+
# (same as `BOOLEAN`), `TIMESTAMP`, `DATE`, `TIME`, `DATETIME`,
|
77
|
+
# `RECORD` (where `RECORD` indicates that the field contains a
|
78
|
+
# nested schema) or `STRUCT` (same as `RECORD`).
|
79
|
+
#
|
80
|
+
def type
|
81
|
+
@gapi.type
|
82
|
+
end
|
83
|
+
|
84
|
+
##
|
85
|
+
# Updates the data type of the field.
|
86
|
+
#
|
87
|
+
# @param [String] new_type The data type. Possible values include
|
88
|
+
# `STRING`, `BYTES`, `INTEGER`, `INT64` (same as `INTEGER`),
|
89
|
+
# `FLOAT`, `FLOAT64` (same as `FLOAT`), `NUMERIC`, `BOOLEAN`, `BOOL`
|
90
|
+
# (same as `BOOLEAN`), `TIMESTAMP`, `DATE`, `TIME`, `DATETIME`,
|
91
|
+
# `RECORD` (where `RECORD` indicates that the field contains a
|
92
|
+
# nested schema) or `STRUCT` (same as `RECORD`).
|
93
|
+
#
|
94
|
+
def type= new_type
|
95
|
+
@gapi.update! type: verify_type(new_type)
|
96
|
+
end
|
97
|
+
|
98
|
+
##
|
99
|
+
# Checks if the type of the field is `NULLABLE`.
|
100
|
+
#
|
101
|
+
# @return [Boolean] `true` when `NULLABLE`, `false` otherwise.
|
102
|
+
#
|
103
|
+
def nullable?
|
104
|
+
mode == "NULLABLE"
|
105
|
+
end
|
106
|
+
|
107
|
+
##
|
108
|
+
# Checks if the type of the field is `REQUIRED`.
|
109
|
+
#
|
110
|
+
# @return [Boolean] `true` when `REQUIRED`, `false` otherwise.
|
111
|
+
#
|
112
|
+
def required?
|
113
|
+
mode == "REQUIRED"
|
114
|
+
end
|
115
|
+
|
116
|
+
##
|
117
|
+
# Checks if the type of the field is `REPEATED`.
|
118
|
+
#
|
119
|
+
# @return [Boolean] `true` when `REPEATED`, `false` otherwise.
|
120
|
+
#
|
121
|
+
def repeated?
|
122
|
+
mode == "REPEATED"
|
123
|
+
end
|
124
|
+
|
125
|
+
##
|
126
|
+
# The description of the field.
|
127
|
+
#
|
128
|
+
# @return [String] The field description. The maximum length is 1,024
|
129
|
+
# characters.
|
130
|
+
#
|
131
|
+
def description
|
132
|
+
@gapi.description
|
133
|
+
end
|
134
|
+
|
135
|
+
##
|
136
|
+
# Updates the description of the field.
|
137
|
+
#
|
138
|
+
# @param [String] new_description The field description. The maximum
|
139
|
+
# length is 1,024 characters.
|
140
|
+
#
|
141
|
+
def description= new_description
|
142
|
+
@gapi.update! description: new_description
|
143
|
+
end
|
144
|
+
|
145
|
+
##
|
146
|
+
# The mode of the field.
|
147
|
+
#
|
148
|
+
# @return [String] The field mode. Possible values include `NULLABLE`,
|
149
|
+
# `REQUIRED` and `REPEATED`. The default value is `NULLABLE`.
|
150
|
+
#
|
151
|
+
def mode
|
152
|
+
@gapi.mode
|
153
|
+
end
|
154
|
+
|
155
|
+
##
|
156
|
+
# Updates the mode of the field.
|
157
|
+
#
|
158
|
+
# @param [String] new_mode The field mode. Possible values include
|
159
|
+
# `NULLABLE`, `REQUIRED` and `REPEATED`. The default value is
|
160
|
+
# `NULLABLE`.
|
161
|
+
#
|
162
|
+
def mode= new_mode
|
163
|
+
@gapi.update! mode: verify_mode(new_mode)
|
164
|
+
end
|
165
|
+
|
166
|
+
##
|
167
|
+
# Checks if the type of the field is `STRING`.
|
168
|
+
#
|
169
|
+
# @return [Boolean] `true` when `STRING`, `false` otherwise.
|
170
|
+
#
|
171
|
+
def string?
|
172
|
+
type == "STRING"
|
173
|
+
end
|
174
|
+
|
175
|
+
##
|
176
|
+
# Checks if the type of the field is `INTEGER`.
|
177
|
+
#
|
178
|
+
# @return [Boolean] `true` when `INTEGER`, `false` otherwise.
|
179
|
+
#
|
180
|
+
def integer?
|
181
|
+
type == "INTEGER" || type == "INT64"
|
182
|
+
end
|
183
|
+
|
184
|
+
##
|
185
|
+
# Checks if the type of the field is `FLOAT`.
|
186
|
+
#
|
187
|
+
# @return [Boolean] `true` when `FLOAT`, `false` otherwise.
|
188
|
+
#
|
189
|
+
def float?
|
190
|
+
type == "FLOAT" || type == "FLOAT64"
|
191
|
+
end
|
192
|
+
|
193
|
+
##
|
194
|
+
# Checks if the type of the field is `NUMERIC`.
|
195
|
+
#
|
196
|
+
# @return [Boolean] `true` when `NUMERIC`, `false` otherwise.
|
197
|
+
#
|
198
|
+
def numeric?
|
199
|
+
type == "NUMERIC"
|
200
|
+
end
|
201
|
+
|
202
|
+
##
|
203
|
+
# Checks if the type of the field is `BOOLEAN`.
|
204
|
+
#
|
205
|
+
# @return [Boolean] `true` when `BOOLEAN`, `false` otherwise.
|
206
|
+
#
|
207
|
+
def boolean?
|
208
|
+
type == "BOOLEAN" || type == "BOOL"
|
209
|
+
end
|
210
|
+
|
211
|
+
##
|
212
|
+
# Checks if the type of the field is `BYTES`.
|
213
|
+
#
|
214
|
+
# @return [Boolean] `true` when `BYTES`, `false` otherwise.
|
215
|
+
#
|
216
|
+
def bytes?
|
217
|
+
type == "BYTES"
|
218
|
+
end
|
219
|
+
|
220
|
+
##
|
221
|
+
# Checks if the type of the field is `TIMESTAMP`.
|
222
|
+
#
|
223
|
+
# @return [Boolean] `true` when `TIMESTAMP`, `false` otherwise.
|
224
|
+
#
|
225
|
+
def timestamp?
|
226
|
+
type == "TIMESTAMP"
|
227
|
+
end
|
228
|
+
|
229
|
+
##
|
230
|
+
# Checks if the type of the field is `TIME`.
|
231
|
+
#
|
232
|
+
# @return [Boolean] `true` when `TIME`, `false` otherwise.
|
233
|
+
#
|
234
|
+
def time?
|
235
|
+
type == "TIME"
|
236
|
+
end
|
237
|
+
|
238
|
+
##
|
239
|
+
# Checks if the type of the field is `DATETIME`.
|
240
|
+
#
|
241
|
+
# @return [Boolean] `true` when `DATETIME`, `false` otherwise.
|
242
|
+
#
|
243
|
+
def datetime?
|
244
|
+
type == "DATETIME"
|
245
|
+
end
|
246
|
+
|
247
|
+
##
|
248
|
+
# Checks if the type of the field is `DATE`.
|
249
|
+
#
|
250
|
+
# @return [Boolean] `true` when `DATE`, `false` otherwise.
|
251
|
+
#
|
252
|
+
def date?
|
253
|
+
type == "DATE"
|
254
|
+
end
|
255
|
+
|
256
|
+
##
|
257
|
+
# Checks if the type of the field is `RECORD`.
|
258
|
+
#
|
259
|
+
# @return [Boolean] `true` when `RECORD`, `false` otherwise.
|
260
|
+
#
|
261
|
+
def record?
|
262
|
+
type == "RECORD" || type == "STRUCT"
|
263
|
+
end
|
264
|
+
alias struct? record?
|
265
|
+
|
266
|
+
##
|
267
|
+
# The nested fields if the type property is set to `RECORD`. Will be
|
268
|
+
# empty otherwise.
|
269
|
+
#
|
270
|
+
# @return [Array<Field>, nil] The nested schema fields if the type
|
271
|
+
# is set to `RECORD`.
|
272
|
+
#
|
273
|
+
def fields
|
274
|
+
if frozen?
|
275
|
+
Array(@gapi.fields).map { |f| Field.from_gapi(f).freeze }.freeze
|
276
|
+
else
|
277
|
+
Array(@gapi.fields).map { |f| Field.from_gapi f }
|
278
|
+
end
|
279
|
+
end
|
280
|
+
|
281
|
+
##
|
282
|
+
# The names of the nested fields as symbols if the type property is
|
283
|
+
# set to `RECORD`. Will be empty otherwise.
|
284
|
+
#
|
285
|
+
# @return [Array<Symbol>, nil] The names of the nested schema fields
|
286
|
+
# if the type is set to `RECORD`.
|
287
|
+
#
|
288
|
+
def headers
|
289
|
+
fields.map(&:name).map(&:to_sym)
|
290
|
+
end
|
291
|
+
|
292
|
+
##
|
293
|
+
# The types of the field, using the same format as the optional query
|
294
|
+
# parameter types.
|
295
|
+
#
|
296
|
+
# The parameter types are one of the following BigQuery type codes:
|
297
|
+
#
|
298
|
+
# * `:BOOL`
|
299
|
+
# * `:INT64`
|
300
|
+
# * `:FLOAT64`
|
301
|
+
# * `:NUMERIC`
|
302
|
+
# * `:STRING`
|
303
|
+
# * `:DATETIME`
|
304
|
+
# * `:DATE`
|
305
|
+
# * `:TIMESTAMP`
|
306
|
+
# * `:TIME`
|
307
|
+
# * `:BYTES`
|
308
|
+
# * `Array` - Lists are specified by providing the type code in an array. For example, an array of integers
|
309
|
+
# are specified as `[:INT64]`.
|
310
|
+
# * `Hash` - Types for STRUCT values (`Hash` objects) are specified using a `Hash` object, where the keys
|
311
|
+
# are the nested field names, and the values are the the nested field types.
|
312
|
+
#
|
313
|
+
# @return [Symbol, Array, Hash] The type.
|
314
|
+
#
|
315
|
+
def param_type
|
316
|
+
param_type = type.to_sym
|
317
|
+
param_type = Hash[fields.map { |field| [field.name.to_sym, field.param_type] }] if record?
|
318
|
+
param_type = [param_type] if repeated?
|
319
|
+
param_type
|
320
|
+
end
|
321
|
+
|
322
|
+
##
|
323
|
+
# Retrieve a nested field by name, if the type property is
|
324
|
+
# set to `RECORD`. Will return `nil` otherwise.
|
325
|
+
#
|
326
|
+
# @return [Field, nil] The nested schema field object, or `nil`.
|
327
|
+
#
|
328
|
+
def field name
|
329
|
+
f = fields.find { |fld| fld.name == name.to_s }
|
330
|
+
return nil if f.nil?
|
331
|
+
yield f if block_given?
|
332
|
+
f
|
333
|
+
end
|
334
|
+
|
335
|
+
##
|
336
|
+
# Adds a string field to the nested schema of a record field.
|
337
|
+
#
|
338
|
+
# This can only be called on fields that are of type `RECORD`.
|
339
|
+
#
|
340
|
+
# @param [String] name The field name. The name must contain only
|
341
|
+
# letters (a-z, A-Z), numbers (0-9), or underscores (_), and must
|
342
|
+
# start with a letter or underscore. The maximum length is 128
|
343
|
+
# characters.
|
344
|
+
# @param [String] description A description of the field.
|
345
|
+
# @param [Symbol] mode The field's mode. The possible values are
|
346
|
+
# `:nullable`, `:required`, and `:repeated`. The default value is
|
347
|
+
# `:nullable`.
|
348
|
+
#
|
349
|
+
def string name, description: nil, mode: :nullable
|
350
|
+
record_check!
|
351
|
+
|
352
|
+
add_field name, :string, description: description, mode: mode
|
353
|
+
end
|
354
|
+
|
355
|
+
##
|
356
|
+
# Adds an integer field to the nested schema of a record field.
|
357
|
+
#
|
358
|
+
# This can only be called on fields that are of type `RECORD`.
|
359
|
+
#
|
360
|
+
# @param [String] name The field name. The name must contain only
|
361
|
+
# letters (a-z, A-Z), numbers (0-9), or underscores (_), and must
|
362
|
+
# start with a letter or underscore. The maximum length is 128
|
363
|
+
# characters.
|
364
|
+
# @param [String] description A description of the field.
|
365
|
+
# @param [Symbol] mode The field's mode. The possible values are
|
366
|
+
# `:nullable`, `:required`, and `:repeated`. The default value is
|
367
|
+
# `:nullable`.
|
368
|
+
#
|
369
|
+
def integer name, description: nil, mode: :nullable
|
370
|
+
record_check!
|
371
|
+
|
372
|
+
add_field name, :integer, description: description, mode: mode
|
373
|
+
end
|
374
|
+
|
375
|
+
##
|
376
|
+
# Adds a floating-point number field to the nested schema of a record
|
377
|
+
# field.
|
378
|
+
#
|
379
|
+
# This can only be called on fields that are of type `RECORD`.
|
380
|
+
#
|
381
|
+
# @param [String] name The field name. The name must contain only
|
382
|
+
# letters (a-z, A-Z), numbers (0-9), or underscores (_), and must
|
383
|
+
# start with a letter or underscore. The maximum length is 128
|
384
|
+
# characters.
|
385
|
+
# @param [String] description A description of the field.
|
386
|
+
# @param [Symbol] mode The field's mode. The possible values are
|
387
|
+
# `:nullable`, `:required`, and `:repeated`. The default value is
|
388
|
+
# `:nullable`.
|
389
|
+
#
|
390
|
+
def float name, description: nil, mode: :nullable
|
391
|
+
record_check!
|
392
|
+
|
393
|
+
add_field name, :float, description: description, mode: mode
|
394
|
+
end
|
395
|
+
|
396
|
+
##
|
397
|
+
# Adds a numeric number field to the schema. Numeric is a
|
398
|
+
# fixed-precision numeric type with 38 decimal digits, 9 that follow
|
399
|
+
# the decimal point.
|
400
|
+
#
|
401
|
+
# This can only be called on fields that are of type `RECORD`.
|
402
|
+
#
|
403
|
+
# @param [String] name The field name. The name must contain only
|
404
|
+
# letters (a-z, A-Z), numbers (0-9), or underscores (_), and must
|
405
|
+
# start with a letter or underscore. The maximum length is 128
|
406
|
+
# characters.
|
407
|
+
# @param [String] description A description of the field.
|
408
|
+
# @param [Symbol] mode The field's mode. The possible values are
|
409
|
+
# `:nullable`, `:required`, and `:repeated`. The default value is
|
410
|
+
# `:nullable`.
|
411
|
+
#
|
412
|
+
def numeric name, description: nil, mode: :nullable
|
413
|
+
record_check!
|
414
|
+
|
415
|
+
add_field name, :numeric, description: description, mode: mode
|
416
|
+
end
|
417
|
+
|
418
|
+
##
|
419
|
+
# Adds a boolean field to the nested schema of a record field.
|
420
|
+
#
|
421
|
+
# This can only be called on fields that are of type `RECORD`.
|
422
|
+
#
|
423
|
+
# @param [String] name The field name. The name must contain only
|
424
|
+
# letters (a-z, A-Z), numbers (0-9), or underscores (_), and must
|
425
|
+
# start with a letter or underscore. The maximum length is 128
|
426
|
+
# characters.
|
427
|
+
# @param [String] description A description of the field.
|
428
|
+
# @param [Symbol] mode The field's mode. The possible values are
|
429
|
+
# `:nullable`, `:required`, and `:repeated`. The default value is
|
430
|
+
# `:nullable`.
|
431
|
+
#
|
432
|
+
def boolean name, description: nil, mode: :nullable
|
433
|
+
record_check!
|
434
|
+
|
435
|
+
add_field name, :boolean, description: description, mode: mode
|
436
|
+
end
|
437
|
+
|
438
|
+
##
|
439
|
+
# Adds a bytes field to the nested schema of a record field.
|
440
|
+
#
|
441
|
+
# This can only be called on fields that are of type `RECORD`.
|
442
|
+
#
|
443
|
+
# @param [String] name The field name. The name must contain only
|
444
|
+
# letters (a-z, A-Z), numbers (0-9), or underscores (_), and must
|
445
|
+
# start with a letter or underscore. The maximum length is 128
|
446
|
+
# characters.
|
447
|
+
# @param [String] description A description of the field.
|
448
|
+
# @param [Symbol] mode The field's mode. The possible values are
|
449
|
+
# `:nullable`, `:required`, and `:repeated`. The default value is
|
450
|
+
# `:nullable`.
|
451
|
+
#
|
452
|
+
def bytes name, description: nil, mode: :nullable
|
453
|
+
record_check!
|
454
|
+
|
455
|
+
add_field name, :bytes, description: description, mode: mode
|
456
|
+
end
|
457
|
+
|
458
|
+
##
|
459
|
+
# Adds a timestamp field to the nested schema of a record field.
|
460
|
+
#
|
461
|
+
# This can only be called on fields that are of type `RECORD`.
|
462
|
+
#
|
463
|
+
# @param [String] name The field name. The name must contain only
|
464
|
+
# letters (a-z, A-Z), numbers (0-9), or underscores (_), and must
|
465
|
+
# start with a letter or underscore. The maximum length is 128
|
466
|
+
# characters.
|
467
|
+
# @param [String] description A description of the field.
|
468
|
+
# @param [Symbol] mode The field's mode. The possible values are
|
469
|
+
# `:nullable`, `:required`, and `:repeated`. The default value is
|
470
|
+
# `:nullable`.
|
471
|
+
#
|
472
|
+
def timestamp name, description: nil, mode: :nullable
|
473
|
+
record_check!
|
474
|
+
|
475
|
+
add_field name, :timestamp, description: description, mode: mode
|
476
|
+
end
|
477
|
+
|
478
|
+
##
|
479
|
+
# Adds a time field to the nested schema of a record field.
|
480
|
+
#
|
481
|
+
# This can only be called on fields that are of type `RECORD`.
|
482
|
+
#
|
483
|
+
# @param [String] name The field name. The name must contain only
|
484
|
+
# letters (a-z, A-Z), numbers (0-9), or underscores (_), and must
|
485
|
+
# start with a letter or underscore. The maximum length is 128
|
486
|
+
# characters.
|
487
|
+
# @param [String] description A description of the field.
|
488
|
+
# @param [Symbol] mode The field's mode. The possible values are
|
489
|
+
# `:nullable`, `:required`, and `:repeated`. The default value is
|
490
|
+
# `:nullable`.
|
491
|
+
#
|
492
|
+
def time name, description: nil, mode: :nullable
|
493
|
+
record_check!
|
494
|
+
|
495
|
+
add_field name, :time, description: description, mode: mode
|
496
|
+
end
|
497
|
+
|
498
|
+
##
|
499
|
+
# Adds a datetime field to the nested schema of a record field.
|
500
|
+
#
|
501
|
+
# This can only be called on fields that are of type `RECORD`.
|
502
|
+
#
|
503
|
+
# @param [String] name The field name. The name must contain only
|
504
|
+
# letters (a-z, A-Z), numbers (0-9), or underscores (_), and must
|
505
|
+
# start with a letter or underscore. The maximum length is 128
|
506
|
+
# characters.
|
507
|
+
# @param [String] description A description of the field.
|
508
|
+
# @param [Symbol] mode The field's mode. The possible values are
|
509
|
+
# `:nullable`, `:required`, and `:repeated`. The default value is
|
510
|
+
# `:nullable`.
|
511
|
+
#
|
512
|
+
def datetime name, description: nil, mode: :nullable
|
513
|
+
record_check!
|
514
|
+
|
515
|
+
add_field name, :datetime, description: description, mode: mode
|
516
|
+
end
|
517
|
+
|
518
|
+
##
|
519
|
+
# Adds a date field to the nested schema of a record field.
|
520
|
+
#
|
521
|
+
# This can only be called on fields that are of type `RECORD`.
|
522
|
+
#
|
523
|
+
# @param [String] name The field name. The name must contain only
|
524
|
+
# letters (a-z, A-Z), numbers (0-9), or underscores (_), and must
|
525
|
+
# start with a letter or underscore. The maximum length is 128
|
526
|
+
# characters.
|
527
|
+
# @param [String] description A description of the field.
|
528
|
+
# @param [Symbol] mode The field's mode. The possible values are
|
529
|
+
# `:nullable`, `:required`, and `:repeated`. The default value is
|
530
|
+
# `:nullable`.
|
531
|
+
#
|
532
|
+
def date name, description: nil, mode: :nullable
|
533
|
+
record_check!
|
534
|
+
|
535
|
+
add_field name, :date, description: description, mode: mode
|
536
|
+
end
|
537
|
+
|
538
|
+
##
|
539
|
+
# Adds a record field to the nested schema of a record field. A block
|
540
|
+
# must be passed describing the nested fields of the record. For more
|
541
|
+
# information about nested and repeated records, see [Preparing Data
|
542
|
+
# for BigQuery](https://cloud.google.com/bigquery/docs/loading-data#loading_denormalized_nested_and_repeated_data).
|
543
|
+
#
|
544
|
+
# This can only be called on fields that are of type `RECORD`.
|
545
|
+
#
|
546
|
+
# @param [String] name The field name. The name must contain only
|
547
|
+
# letters (a-z, A-Z), numbers (0-9), or underscores (_), and must
|
548
|
+
# start with a letter or underscore. The maximum length is 128
|
549
|
+
# characters.
|
550
|
+
# @param [String] description A description of the field.
|
551
|
+
# @param [Symbol] mode The field's mode. The possible values are
|
552
|
+
# `:nullable`, `:required`, and `:repeated`. The default value is
|
553
|
+
# `:nullable`.
|
554
|
+
# @yield [nested_schema] a block for setting the nested schema
|
555
|
+
# @yieldparam [Schema] nested_schema the object accepting the
|
556
|
+
# nested schema
|
557
|
+
#
|
558
|
+
# @example
|
559
|
+
# require "google/cloud/bigquery"
|
560
|
+
#
|
561
|
+
# bigquery = Google::Cloud::Bigquery.new
|
562
|
+
# dataset = bigquery.dataset "my_dataset"
|
563
|
+
# table = dataset.create_table "my_table"
|
564
|
+
#
|
565
|
+
# table.schema do |schema|
|
566
|
+
# schema.string "first_name", mode: :required
|
567
|
+
# schema.record "cities_lived", mode: :repeated do |cities_lived|
|
568
|
+
# cities_lived.record "city", mode: :required do |city|
|
569
|
+
# city.string "name", mode: :required
|
570
|
+
# city.string "country", mode: :required
|
571
|
+
# end
|
572
|
+
# cities_lived.integer "number_of_years", mode: :required
|
573
|
+
# end
|
574
|
+
# end
|
575
|
+
#
|
576
|
+
def record name, description: nil, mode: nil
|
577
|
+
record_check!
|
578
|
+
|
579
|
+
# TODO: do we need to raise if no block was given?
|
580
|
+
raise ArgumentError, "a block is required" unless block_given?
|
581
|
+
|
582
|
+
nested_field = add_field name, :record, description: description, mode: mode
|
583
|
+
yield nested_field
|
584
|
+
nested_field
|
585
|
+
end
|
586
|
+
|
587
|
+
# @private
|
588
|
+
def self.from_gapi gapi
|
589
|
+
new.tap do |f|
|
590
|
+
f.instance_variable_set :@gapi, gapi
|
591
|
+
f.instance_variable_set :@original_json, gapi.to_json
|
592
|
+
end
|
593
|
+
end
|
594
|
+
|
595
|
+
# @private
|
596
|
+
def to_gapi
|
597
|
+
@gapi
|
598
|
+
end
|
599
|
+
|
600
|
+
# @private
|
601
|
+
def == other
|
602
|
+
return false unless other.is_a? Field
|
603
|
+
to_gapi.to_h == other.to_gapi.to_h
|
604
|
+
end
|
605
|
+
|
606
|
+
# @private
|
607
|
+
def to_hash
|
608
|
+
h = {
|
609
|
+
name: name,
|
610
|
+
type: type,
|
611
|
+
mode: mode
|
612
|
+
}
|
613
|
+
h[:description] = description if description
|
614
|
+
h[:fields] = fields.map(&:to_hash) if record?
|
615
|
+
h
|
616
|
+
end
|
617
|
+
|
618
|
+
protected
|
619
|
+
|
620
|
+
def frozen_check!
|
621
|
+
return unless frozen?
|
622
|
+
raise ArgumentError, "Cannot modify a frozen field"
|
623
|
+
end
|
624
|
+
|
625
|
+
def record_check!
|
626
|
+
return unless type != "RECORD"
|
627
|
+
raise ArgumentError,
|
628
|
+
"Cannot add fields to a non-RECORD field (#{type})"
|
629
|
+
end
|
630
|
+
|
631
|
+
def add_field name, type, description: nil, mode: :nullable
|
632
|
+
frozen_check!
|
633
|
+
|
634
|
+
new_gapi = Google::Apis::BigqueryV2::TableFieldSchema.new(
|
635
|
+
name: String(name),
|
636
|
+
type: verify_type(type),
|
637
|
+
description: description,
|
638
|
+
mode: verify_mode(mode),
|
639
|
+
fields: []
|
640
|
+
)
|
641
|
+
|
642
|
+
# Remove any existing field of this name
|
643
|
+
@gapi.fields ||= []
|
644
|
+
@gapi.fields.reject! { |f| f.name == new_gapi.name }
|
645
|
+
# Add to the nested fields
|
646
|
+
@gapi.fields << new_gapi
|
647
|
+
|
648
|
+
# return the public API object
|
649
|
+
Field.from_gapi new_gapi
|
650
|
+
end
|
651
|
+
|
652
|
+
def verify_type type
|
653
|
+
type = type.to_s.upcase
|
654
|
+
raise ArgumentError, "Type '#{type}' not found" unless TYPES.include? type
|
655
|
+
type
|
656
|
+
end
|
657
|
+
|
658
|
+
def verify_mode mode
|
659
|
+
mode = :nullable if mode.nil?
|
660
|
+
mode = mode.to_s.upcase
|
661
|
+
raise ArgumentError "Unable to determine mode for '#{mode}'" unless MODES.include? mode
|
662
|
+
mode
|
663
|
+
end
|
664
|
+
end
|
665
|
+
end
|
666
|
+
end
|
667
|
+
end
|
668
|
+
end
|