google-cloud-bigquery 1.12.0 → 1.38.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (50) hide show
  1. checksums.yaml +4 -4
  2. data/AUTHENTICATION.md +9 -28
  3. data/CHANGELOG.md +372 -1
  4. data/CONTRIBUTING.md +328 -116
  5. data/LOGGING.md +2 -2
  6. data/OVERVIEW.md +21 -20
  7. data/TROUBLESHOOTING.md +2 -8
  8. data/lib/google/cloud/bigquery/argument.rb +197 -0
  9. data/lib/google/cloud/bigquery/convert.rb +154 -170
  10. data/lib/google/cloud/bigquery/copy_job.rb +40 -23
  11. data/lib/google/cloud/bigquery/credentials.rb +5 -12
  12. data/lib/google/cloud/bigquery/data.rb +109 -18
  13. data/lib/google/cloud/bigquery/dataset/access.rb +322 -51
  14. data/lib/google/cloud/bigquery/dataset/list.rb +7 -13
  15. data/lib/google/cloud/bigquery/dataset.rb +960 -279
  16. data/lib/google/cloud/bigquery/external/avro_source.rb +107 -0
  17. data/lib/google/cloud/bigquery/external/bigtable_source/column.rb +404 -0
  18. data/lib/google/cloud/bigquery/external/bigtable_source/column_family.rb +945 -0
  19. data/lib/google/cloud/bigquery/external/bigtable_source.rb +230 -0
  20. data/lib/google/cloud/bigquery/external/csv_source.rb +481 -0
  21. data/lib/google/cloud/bigquery/external/data_source.rb +771 -0
  22. data/lib/google/cloud/bigquery/external/json_source.rb +170 -0
  23. data/lib/google/cloud/bigquery/external/parquet_source.rb +148 -0
  24. data/lib/google/cloud/bigquery/external/sheets_source.rb +166 -0
  25. data/lib/google/cloud/bigquery/external.rb +50 -2256
  26. data/lib/google/cloud/bigquery/extract_job.rb +217 -58
  27. data/lib/google/cloud/bigquery/insert_response.rb +1 -3
  28. data/lib/google/cloud/bigquery/job/list.rb +13 -20
  29. data/lib/google/cloud/bigquery/job.rb +286 -11
  30. data/lib/google/cloud/bigquery/load_job.rb +801 -133
  31. data/lib/google/cloud/bigquery/model/list.rb +5 -9
  32. data/lib/google/cloud/bigquery/model.rb +247 -16
  33. data/lib/google/cloud/bigquery/policy.rb +432 -0
  34. data/lib/google/cloud/bigquery/project/list.rb +6 -11
  35. data/lib/google/cloud/bigquery/project.rb +526 -243
  36. data/lib/google/cloud/bigquery/query_job.rb +584 -125
  37. data/lib/google/cloud/bigquery/routine/list.rb +165 -0
  38. data/lib/google/cloud/bigquery/routine.rb +1227 -0
  39. data/lib/google/cloud/bigquery/schema/field.rb +413 -63
  40. data/lib/google/cloud/bigquery/schema.rb +221 -48
  41. data/lib/google/cloud/bigquery/service.rb +186 -109
  42. data/lib/google/cloud/bigquery/standard_sql.rb +269 -53
  43. data/lib/google/cloud/bigquery/table/async_inserter.rb +86 -42
  44. data/lib/google/cloud/bigquery/table/list.rb +6 -11
  45. data/lib/google/cloud/bigquery/table.rb +1188 -326
  46. data/lib/google/cloud/bigquery/time.rb +6 -0
  47. data/lib/google/cloud/bigquery/version.rb +1 -1
  48. data/lib/google/cloud/bigquery.rb +18 -8
  49. data/lib/google-cloud-bigquery.rb +15 -13
  50. metadata +67 -40
@@ -23,6 +23,7 @@ require "google/cloud/bigquery/external"
23
23
  require "google/cloud/bigquery/insert_response"
24
24
  require "google/cloud/bigquery/table/async_inserter"
25
25
  require "google/cloud/bigquery/convert"
26
+ require "google/cloud/bigquery/policy"
26
27
  require "google/apis/bigquery_v2"
27
28
 
28
29
  module Google
@@ -36,16 +37,16 @@ module Google
36
37
  # repeated fields.
37
38
  #
38
39
  # The Table class can also represent a
39
- # [view](https://cloud.google.com/bigquery/docs/views), which is a virtual
40
- # table defined by a SQL query. BigQuery's views are logical views, not
41
- # materialized views, which means that the query that defines the view is
42
- # re-executed every time the view is queried. Queries are billed according
43
- # to the total amount of data in all table fields referenced directly or
44
- # indirectly by the top-level query. (See {#view?}, {#query}, {#query=},
45
- # and {Dataset#create_view}.)
40
+ # [logical view](https://cloud.google.com/bigquery/docs/views), which is a virtual
41
+ # table defined by a SQL query (see {#view?} and {Dataset#create_view}); or a
42
+ # [materialized view](https://cloud.google.com/bigquery/docs/materialized-views-intro),
43
+ # which is a precomputed view that periodically caches results of a query for increased
44
+ # performance and efficiency (see {#materialized_view?} and {Dataset#create_materialized_view}).
46
45
  #
47
46
  # @see https://cloud.google.com/bigquery/docs/loading-data#loading_denormalized_nested_and_repeated_data
48
47
  # Loading denormalized, nested, and repeated data
48
+ # @see https://cloud.google.com/bigquery/docs/views Creating views
49
+ # @see https://cloud.google.com/bigquery/docs/materialized-views-intro Introduction to materialized views
49
50
  #
50
51
  # @example
51
52
  # require "google/cloud/bigquery"
@@ -76,7 +77,7 @@ module Google
76
77
  # }
77
78
  # table.insert row
78
79
  #
79
- # @example Creating a BigQuery view:
80
+ # @example Creating a logical view:
80
81
  # require "google/cloud/bigquery"
81
82
  #
82
83
  # bigquery = Google::Cloud::Bigquery.new
@@ -85,6 +86,15 @@ module Google
85
86
  # "SELECT name, age FROM `my_project.my_dataset.my_table`"
86
87
  # view.view? # true
87
88
  #
89
+ # @example Creating a materialized view:
90
+ # require "google/cloud/bigquery"
91
+ #
92
+ # bigquery = Google::Cloud::Bigquery.new
93
+ # dataset = bigquery.dataset "my_dataset"
94
+ # view = dataset.create_materialized_view "my_materialized_view",
95
+ # "SELECT name, age FROM `my_project.my_dataset.my_table`"
96
+ # view.materialized_view? # true
97
+ #
88
98
  class Table
89
99
  ##
90
100
  # @private The Service object.
@@ -109,8 +119,8 @@ module Google
109
119
  ##
110
120
  # A unique ID for this table.
111
121
  #
112
- # @return [String] The ID must contain only letters (a-z, A-Z), numbers
113
- # (0-9), or underscores (_). The maximum length is 1,024 characters.
122
+ # @return [String] The ID must contain only letters (`[A-Za-z]`), numbers
123
+ # (`[0-9]`), or underscores (`_`). The maximum length is 1,024 characters.
114
124
  #
115
125
  # @!group Attributes
116
126
  #
@@ -122,8 +132,8 @@ module Google
122
132
  ##
123
133
  # The ID of the `Dataset` containing this table.
124
134
  #
125
- # @return [String] The ID must contain only letters (a-z, A-Z), numbers
126
- # (0-9), or underscores (_). The maximum length is 1,024 characters.
135
+ # @return [String] The ID must contain only letters (`[A-Za-z]`), numbers
136
+ # (`[0-9]`), or underscores (`_`). The maximum length is 1,024 characters.
127
137
  #
128
138
  # @!group Attributes
129
139
  #
@@ -155,10 +165,87 @@ module Google
155
165
  end
156
166
 
157
167
  ###
158
- # Checks if the table is time-partitioned. See [Partitioned
168
+ # Checks if the table is range partitioned. See [Creating and using integer range partitioned
169
+ # tables](https://cloud.google.com/bigquery/docs/creating-integer-range-partitions).
170
+ #
171
+ # @return [Boolean, nil] `true` when the table is range partitioned, or
172
+ # `false` otherwise, if the object is a resource (see {#resource?});
173
+ # `nil` if the object is a reference (see {#reference?}).
174
+ #
175
+ # @!group Attributes
176
+ #
177
+ def range_partitioning?
178
+ return nil if reference?
179
+ !@gapi.range_partitioning.nil?
180
+ end
181
+
182
+ ###
183
+ # The field on which the table is range partitioned, if any. The field must be a top-level `NULLABLE/REQUIRED`
184
+ # field. The only supported type is `INTEGER/INT64`. See [Creating and using integer range partitioned
185
+ # tables](https://cloud.google.com/bigquery/docs/creating-integer-range-partitions).
186
+ #
187
+ # @return [Integer, nil] The range partition field, or `nil` if not range partitioned or the object is a
188
+ # reference (see {#reference?}).
189
+ #
190
+ # @!group Attributes
191
+ #
192
+ def range_partitioning_field
193
+ return nil if reference?
194
+ ensure_full_data!
195
+ @gapi.range_partitioning.field if range_partitioning?
196
+ end
197
+
198
+ ###
199
+ # The start of range partitioning, inclusive. See [Creating and using integer range partitioned
200
+ # tables](https://cloud.google.com/bigquery/docs/creating-integer-range-partitions).
201
+ #
202
+ # @return [Integer, nil] The start of range partitioning, inclusive, or `nil` if not range partitioned or the
203
+ # object is a reference (see {#reference?}).
204
+ #
205
+ # @!group Attributes
206
+ #
207
+ def range_partitioning_start
208
+ return nil if reference?
209
+ ensure_full_data!
210
+ @gapi.range_partitioning.range.start if range_partitioning?
211
+ end
212
+
213
+ ###
214
+ # The width of each interval. See [Creating and using integer range partitioned
215
+ # tables](https://cloud.google.com/bigquery/docs/creating-integer-range-partitions).
216
+ #
217
+ # @return [Integer, nil] The width of each interval, for data in range partitions, or `nil` if not range
218
+ # partitioned or the object is a reference (see {#reference?}).
219
+ #
220
+ # @!group Attributes
221
+ #
222
+ def range_partitioning_interval
223
+ return nil if reference?
224
+ ensure_full_data!
225
+ return nil unless range_partitioning?
226
+ @gapi.range_partitioning.range.interval
227
+ end
228
+
229
+ ###
230
+ # The end of range partitioning, exclusive. See [Creating and using integer range partitioned
231
+ # tables](https://cloud.google.com/bigquery/docs/creating-integer-range-partitions).
232
+ #
233
+ # @return [Integer, nil] The end of range partitioning, exclusive, or `nil` if not range partitioned or the
234
+ # object is a reference (see {#reference?}).
235
+ #
236
+ # @!group Attributes
237
+ #
238
+ def range_partitioning_end
239
+ return nil if reference?
240
+ ensure_full_data!
241
+ @gapi.range_partitioning.range.end if range_partitioning?
242
+ end
243
+
244
+ ###
245
+ # Checks if the table is time partitioned. See [Partitioned
159
246
  # Tables](https://cloud.google.com/bigquery/docs/partitioned-tables).
160
247
  #
161
- # @return [Boolean, nil] `true` when the table is time-partitioned, or
248
+ # @return [Boolean, nil] `true` when the table is time partitioned, or
162
249
  # `false` otherwise, if the object is a resource (see {#resource?});
163
250
  # `nil` if the object is a reference (see {#reference?}).
164
251
  #
@@ -170,12 +257,13 @@ module Google
170
257
  end
171
258
 
172
259
  ###
173
- # The period for which the table is partitioned, if any. See
260
+ # The period for which the table is time partitioned, if any. See
174
261
  # [Partitioned Tables](https://cloud.google.com/bigquery/docs/partitioned-tables).
175
262
  #
176
- # @return [String, nil] The partition type. Currently the only supported
177
- # value is "DAY", or `nil` if the object is a reference (see
178
- # {#reference?}).
263
+ # @return [String, nil] The time partition type. The supported types are `DAY`,
264
+ # `HOUR`, `MONTH`, and `YEAR`, which will generate one partition per day,
265
+ # hour, month, and year, respectively; or `nil` if not set or the object is a
266
+ # reference (see {#reference?}).
179
267
  #
180
268
  # @!group Attributes
181
269
  #
@@ -186,43 +274,49 @@ module Google
186
274
  end
187
275
 
188
276
  ##
189
- # Sets the partitioning for the table. See [Partitioned
277
+ # Sets the time partitioning type for the table. See [Partitioned
190
278
  # Tables](https://cloud.google.com/bigquery/docs/partitioned-tables).
279
+ # The supported types are `DAY`, `HOUR`, `MONTH`, and `YEAR`, which will
280
+ # generate one partition per day, hour, month, and year, respectively.
191
281
  #
192
- # You can only set partitioning when creating a table as in
193
- # the example below. BigQuery does not allow you to change partitioning
282
+ # You can only set time partitioning when creating a table as in
283
+ # the example below. BigQuery does not allow you to change time partitioning
194
284
  # on an existing table.
195
285
  #
196
- # @param [String] type The partition type. Currently the only
197
- # supported value is "DAY".
286
+ # @param [String] type The time partition type. The supported types are `DAY`,
287
+ # `HOUR`, `MONTH`, and `YEAR`, which will generate one partition per day,
288
+ # hour, month, and year, respectively.
198
289
  #
199
290
  # @example
200
291
  # require "google/cloud/bigquery"
201
292
  #
202
293
  # bigquery = Google::Cloud::Bigquery.new
203
294
  # dataset = bigquery.dataset "my_dataset"
204
- # table = dataset.create_table "my_table" do |table|
205
- # table.time_partitioning_type = "DAY"
295
+ # table = dataset.create_table "my_table" do |t|
296
+ # t.schema do |schema|
297
+ # schema.timestamp "dob", mode: :required
298
+ # end
299
+ # t.time_partitioning_type = "DAY"
300
+ # t.time_partitioning_field = "dob"
206
301
  # end
207
302
  #
208
303
  # @!group Attributes
209
304
  #
210
305
  def time_partitioning_type= type
211
306
  reload! unless resource_full?
212
- @gapi.time_partitioning ||= \
213
- Google::Apis::BigqueryV2::TimePartitioning.new
307
+ @gapi.time_partitioning ||= Google::Apis::BigqueryV2::TimePartitioning.new
214
308
  @gapi.time_partitioning.type = type
215
309
  patch_gapi! :time_partitioning
216
310
  end
217
311
 
218
312
  ###
219
- # The field on which the table is partitioned, if any. If not
220
- # set, the destination table is partitioned by pseudo column
221
- # `_PARTITIONTIME`; if set, the table is partitioned by this field. See
313
+ # The field on which the table is time partitioned, if any. If not
314
+ # set, the destination table is time partitioned by pseudo column
315
+ # `_PARTITIONTIME`; if set, the table is time partitioned by this field. See
222
316
  # [Partitioned Tables](https://cloud.google.com/bigquery/docs/partitioned-tables).
223
317
  #
224
- # @return [String, nil] The partition field, if a field was configured.
225
- # `nil` if not partitioned, not set (partitioned by pseudo column
318
+ # @return [String, nil] The time partition field, if a field was configured.
319
+ # `nil` if not time partitioned, not set (time partitioned by pseudo column
226
320
  # '_PARTITIONTIME') or the object is a reference (see {#reference?}).
227
321
  #
228
322
  # @!group Attributes
@@ -234,19 +328,19 @@ module Google
234
328
  end
235
329
 
236
330
  ##
237
- # Sets the field on which to partition the table. If not
238
- # set, the destination table is partitioned by pseudo column
239
- # `_PARTITIONTIME`; if set, the table is partitioned by this field. See
331
+ # Sets the field on which to time partition the table. If not
332
+ # set, the destination table is time partitioned by pseudo column
333
+ # `_PARTITIONTIME`; if set, the table is time partitioned by this field. See
240
334
  # [Partitioned Tables](https://cloud.google.com/bigquery/docs/partitioned-tables).
241
- # The table must also be partitioned.
335
+ # The table must also be time partitioned.
242
336
  #
243
337
  # See {Table#time_partitioning_type=}.
244
338
  #
245
- # You can only set the partitioning field while creating a table as in
246
- # the example below. BigQuery does not allow you to change partitioning
339
+ # You can only set the time partitioning field while creating a table as in
340
+ # the example below. BigQuery does not allow you to change time partitioning
247
341
  # on an existing table.
248
342
  #
249
- # @param [String] field The partition field. The field must be a
343
+ # @param [String] field The time partition field. The field must be a
250
344
  # top-level TIMESTAMP or DATE field. Its mode must be NULLABLE or
251
345
  # REQUIRED.
252
346
  #
@@ -255,30 +349,29 @@ module Google
255
349
  #
256
350
  # bigquery = Google::Cloud::Bigquery.new
257
351
  # dataset = bigquery.dataset "my_dataset"
258
- # table = dataset.create_table "my_table" do |table|
259
- # table.time_partitioning_type = "DAY"
260
- # table.time_partitioning_field = "dob"
261
- # table.schema do |schema|
352
+ # table = dataset.create_table "my_table" do |t|
353
+ # t.schema do |schema|
262
354
  # schema.timestamp "dob", mode: :required
263
355
  # end
356
+ # t.time_partitioning_type = "DAY"
357
+ # t.time_partitioning_field = "dob"
264
358
  # end
265
359
  #
266
360
  # @!group Attributes
267
361
  #
268
362
  def time_partitioning_field= field
269
363
  reload! unless resource_full?
270
- @gapi.time_partitioning ||= \
271
- Google::Apis::BigqueryV2::TimePartitioning.new
364
+ @gapi.time_partitioning ||= Google::Apis::BigqueryV2::TimePartitioning.new
272
365
  @gapi.time_partitioning.field = field
273
366
  patch_gapi! :time_partitioning
274
367
  end
275
368
 
276
369
  ###
277
- # The expiration for the table partitions, if any, in seconds. See
370
+ # The expiration for the time partitions, if any, in seconds. See
278
371
  # [Partitioned Tables](https://cloud.google.com/bigquery/docs/partitioned-tables).
279
372
  #
280
373
  # @return [Integer, nil] The expiration time, in seconds, for data in
281
- # partitions, or `nil` if not present or the object is a reference
374
+ # time partitions, or `nil` if not present or the object is a reference
282
375
  # (see {#reference?}).
283
376
  #
284
377
  # @!group Attributes
@@ -286,15 +379,15 @@ module Google
286
379
  def time_partitioning_expiration
287
380
  return nil if reference?
288
381
  ensure_full_data!
289
- @gapi.time_partitioning.expiration_ms / 1_000 if
290
- time_partitioning? &&
291
- !@gapi.time_partitioning.expiration_ms.nil?
382
+ return nil unless time_partitioning?
383
+ return nil if @gapi.time_partitioning.expiration_ms.nil?
384
+ @gapi.time_partitioning.expiration_ms / 1_000
292
385
  end
293
386
 
294
387
  ##
295
- # Sets the partition expiration for the table. See [Partitioned
388
+ # Sets the time partition expiration for the table. See [Partitioned
296
389
  # Tables](https://cloud.google.com/bigquery/docs/partitioned-tables).
297
- # The table must also be partitioned.
390
+ # The table must also be time partitioned.
298
391
  #
299
392
  # See {Table#time_partitioning_type=}.
300
393
  #
@@ -302,34 +395,89 @@ module Google
302
395
  # {#resource_full?}), the full representation will be retrieved before
303
396
  # the update to comply with ETag-based optimistic concurrency control.
304
397
  #
305
- # @param [Integer] expiration An expiration time, in seconds,
306
- # for data in partitions.
398
+ # @param [Integer, nil] expiration An expiration time, in seconds,
399
+ # for data in time partitions, , or `nil` to indicate no expiration time.
307
400
  #
308
401
  # @example
309
402
  # require "google/cloud/bigquery"
310
403
  #
311
404
  # bigquery = Google::Cloud::Bigquery.new
312
405
  # dataset = bigquery.dataset "my_dataset"
313
- # table = dataset.create_table "my_table" do |table|
314
- # table.time_partitioning_type = "DAY"
315
- # table.time_partitioning_expiration = 86_400
406
+ # table = dataset.create_table "my_table" do |t|
407
+ # t.schema do |schema|
408
+ # schema.timestamp "dob", mode: :required
409
+ # end
410
+ # t.time_partitioning_type = "DAY"
411
+ # t.time_partitioning_field = "dob"
412
+ # t.time_partitioning_expiration = 86_400
316
413
  # end
317
414
  #
318
415
  # @!group Attributes
319
416
  #
320
417
  def time_partitioning_expiration= expiration
321
418
  reload! unless resource_full?
322
- @gapi.time_partitioning ||= \
323
- Google::Apis::BigqueryV2::TimePartitioning.new
324
- @gapi.time_partitioning.expiration_ms = expiration * 1000
419
+ expiration_ms = expiration * 1000 if expiration
420
+ @gapi.time_partitioning ||= Google::Apis::BigqueryV2::TimePartitioning.new
421
+ @gapi.time_partitioning.expiration_ms = expiration_ms
325
422
  patch_gapi! :time_partitioning
326
423
  end
327
424
 
425
+ ###
426
+ # Whether queries over this table require a partition filter that can be
427
+ # used for partition elimination to be specified. See [Partitioned
428
+ # Tables](https://cloud.google.com/bigquery/docs/partitioned-tables).
429
+ #
430
+ # @return [Boolean, nil] `true` when a partition filter will be
431
+ # required, `false` otherwise, or `nil` if the object is a reference
432
+ # (see {#reference?}).
433
+ #
434
+ # @!group Attributes
435
+ #
436
+ def require_partition_filter
437
+ return nil if reference?
438
+ ensure_full_data!
439
+ @gapi.require_partition_filter
440
+ end
441
+
442
+ ##
443
+ # Sets whether queries over this table require a partition filter. See
444
+ # [Partitioned
445
+ # Tables](https://cloud.google.com/bigquery/docs/partitioned-tables).
446
+ #
447
+ # If the table is not a full resource representation (see
448
+ # {#resource_full?}), the full representation will be retrieved before
449
+ # the update to comply with ETag-based optimistic concurrency control.
450
+ #
451
+ # @param [Boolean] new_require Whether queries over this table require a
452
+ # partition filter.
453
+ #
454
+ # @example
455
+ # require "google/cloud/bigquery"
456
+ #
457
+ # bigquery = Google::Cloud::Bigquery.new
458
+ # dataset = bigquery.dataset "my_dataset"
459
+ # table = dataset.create_table "my_table" do |t|
460
+ # t.require_partition_filter = true
461
+ # end
462
+ #
463
+ # @!group Attributes
464
+ #
465
+ def require_partition_filter= new_require
466
+ reload! unless resource_full?
467
+ @gapi.require_partition_filter = new_require
468
+ patch_gapi! :require_partition_filter
469
+ end
470
+
328
471
  ###
329
472
  # Checks if the table is clustered.
330
473
  #
474
+ # See {Table::Updater#clustering_fields=}, {Table#clustering_fields} and
475
+ # {Table#clustering_fields=}.
476
+ #
331
477
  # @see https://cloud.google.com/bigquery/docs/clustered-tables
332
- # Introduction to Clustered Tables
478
+ # Introduction to clustered tables
479
+ # @see https://cloud.google.com/bigquery/docs/creating-clustered-tables
480
+ # Creating and using clustered tables
333
481
  #
334
482
  # @return [Boolean, nil] `true` when the table is clustered, or
335
483
  # `false` otherwise, if the object is a resource (see {#resource?});
@@ -344,18 +492,20 @@ module Google
344
492
 
345
493
  ###
346
494
  # One or more fields on which data should be clustered. Must be
347
- # specified with time-based partitioning, data in the table will be
495
+ # specified with time partitioning, data in the table will be
348
496
  # first partitioned and subsequently clustered. The order of the
349
497
  # returned fields determines the sort order of the data.
350
498
  #
351
- # See {Table::Updater#clustering_fields=}.
499
+ # BigQuery supports clustering for both partitioned and non-partitioned
500
+ # tables.
501
+ #
502
+ # See {Table::Updater#clustering_fields=}, {Table#clustering_fields=} and
503
+ # {Table#clustering?}.
352
504
  #
353
- # @see https://cloud.google.com/bigquery/docs/partitioned-tables
354
- # Partitioned Tables
355
505
  # @see https://cloud.google.com/bigquery/docs/clustered-tables
356
- # Introduction to Clustered Tables
506
+ # Introduction to clustered tables
357
507
  # @see https://cloud.google.com/bigquery/docs/creating-clustered-tables
358
- # Creating and Using Clustered Tables
508
+ # Creating and using clustered tables
359
509
  #
360
510
  # @return [Array<String>, nil] The clustering fields, or `nil` if the
361
511
  # table is not clustered or if the table is a reference (see
@@ -369,6 +519,53 @@ module Google
369
519
  @gapi.clustering.fields if clustering?
370
520
  end
371
521
 
522
+ ##
523
+ # Updates the list of fields on which data should be clustered.
524
+ #
525
+ # Only top-level, non-repeated, simple-type fields are supported. When
526
+ # you cluster a table using multiple columns, the order of columns you
527
+ # specify is important. The order of the specified columns determines
528
+ # the sort order of the data.
529
+ #
530
+ # BigQuery supports clustering for both partitioned and non-partitioned
531
+ # tables.
532
+ #
533
+ # See {Table::Updater#clustering_fields=}, {Table#clustering_fields} and
534
+ # {Table#clustering?}.
535
+ #
536
+ # @see https://cloud.google.com/bigquery/docs/clustered-tables
537
+ # Introduction to clustered tables
538
+ # @see https://cloud.google.com/bigquery/docs/creating-clustered-tables
539
+ # Creating and using clustered tables
540
+ # @see https://cloud.google.com/bigquery/docs/creating-clustered-tables#modifying-cluster-spec
541
+ # Modifying clustering specification
542
+ #
543
+ # @param [Array<String>, nil] fields The clustering fields, or `nil` to
544
+ # remove the clustering configuration. Only top-level, non-repeated,
545
+ # simple-type fields are supported.
546
+ #
547
+ # @example
548
+ # require "google/cloud/bigquery"
549
+ #
550
+ # bigquery = Google::Cloud::Bigquery.new
551
+ # dataset = bigquery.dataset "my_dataset"
552
+ # table = dataset.table "my_table"
553
+ #
554
+ # table.clustering_fields = ["last_name", "first_name"]
555
+ #
556
+ # @!group Attributes
557
+ #
558
+ def clustering_fields= fields
559
+ reload! unless resource_full?
560
+ if fields
561
+ @gapi.clustering ||= Google::Apis::BigqueryV2::Clustering.new
562
+ @gapi.clustering.fields = fields
563
+ else
564
+ @gapi.clustering = nil
565
+ end
566
+ patch_gapi! :clustering
567
+ end
568
+
372
569
  ##
373
570
  # The combined Project ID, Dataset ID, and Table ID for this table, in
374
571
  # the format specified by the [Legacy SQL Query
@@ -593,7 +790,7 @@ module Google
593
790
  end
594
791
 
595
792
  ##
596
- # Checks if the table's type is "TABLE".
793
+ # Checks if the table's type is `TABLE`.
597
794
  #
598
795
  # @return [Boolean, nil] `true` when the type is `TABLE`, `false`
599
796
  # otherwise, if the object is a resource (see {#resource?}); `nil` if
@@ -607,8 +804,10 @@ module Google
607
804
  end
608
805
 
609
806
  ##
610
- # Checks if the table's type is "VIEW", indicating that the table
611
- # represents a BigQuery view. See {Dataset#create_view}.
807
+ # Checks if the table's type is `VIEW`, indicating that the table
808
+ # represents a BigQuery logical view. See {Dataset#create_view}.
809
+ #
810
+ # @see https://cloud.google.com/bigquery/docs/views Creating views
612
811
  #
613
812
  # @return [Boolean, nil] `true` when the type is `VIEW`, `false`
614
813
  # otherwise, if the object is a resource (see {#resource?}); `nil` if
@@ -622,7 +821,25 @@ module Google
622
821
  end
623
822
 
624
823
  ##
625
- # Checks if the table's type is "EXTERNAL", indicating that the table
824
+ # Checks if the table's type is `MATERIALIZED_VIEW`, indicating that
825
+ # the table represents a BigQuery materialized view.
826
+ # See {Dataset#create_materialized_view}.
827
+ #
828
+ # @see https://cloud.google.com/bigquery/docs/materialized-views-intro Introduction to materialized views
829
+ #
830
+ # @return [Boolean, nil] `true` when the type is `MATERIALIZED_VIEW`,
831
+ # `false` otherwise, if the object is a resource (see {#resource?});
832
+ # `nil` if the object is a reference (see {#reference?}).
833
+ #
834
+ # @!group Attributes
835
+ #
836
+ def materialized_view?
837
+ return nil if reference?
838
+ @gapi.type == "MATERIALIZED_VIEW"
839
+ end
840
+
841
+ ##
842
+ # Checks if the table's type is `EXTERNAL`, indicating that the table
626
843
  # represents an External Data Source. See {#external?} and
627
844
  # {External::DataSource}.
628
845
  #
@@ -692,12 +909,19 @@ module Google
692
909
  # @param [Hash<String, String>] labels A hash containing key/value
693
910
  # pairs.
694
911
  #
695
- # * Label keys and values can be no longer than 63 characters.
696
- # * Label keys and values can contain only lowercase letters, numbers,
697
- # underscores, hyphens, and international characters.
698
- # * Label keys and values cannot exceed 128 bytes in size.
699
- # * Label keys must begin with a letter.
700
- # * Label keys must be unique within a table.
912
+ # The labels applied to a resource must meet the following requirements:
913
+ #
914
+ # * Each resource can have multiple labels, up to a maximum of 64.
915
+ # * Each label must be a key-value pair.
916
+ # * Keys have a minimum length of 1 character and a maximum length of
917
+ # 63 characters, and cannot be empty. Values can be empty, and have
918
+ # a maximum length of 63 characters.
919
+ # * Keys and values can contain only lowercase letters, numeric characters,
920
+ # underscores, and dashes. All characters must use UTF-8 encoding, and
921
+ # international characters are allowed.
922
+ # * The key portion of a label must be unique. However, you can use the
923
+ # same key with multiple resources.
924
+ # * Keys must start with a lowercase letter or international character.
701
925
  #
702
926
  # @example
703
927
  # require "google/cloud/bigquery"
@@ -827,10 +1051,30 @@ module Google
827
1051
  schema.headers
828
1052
  end
829
1053
 
1054
+ ##
1055
+ # The types of the fields in the table, obtained from its schema.
1056
+ # Types use the same format as the optional query parameter types.
1057
+ #
1058
+ # @return [Hash] A hash with field names as keys, and types as values.
1059
+ #
1060
+ # @example
1061
+ # require "google/cloud/bigquery"
1062
+ #
1063
+ # bigquery = Google::Cloud::Bigquery.new
1064
+ # dataset = bigquery.dataset "my_dataset"
1065
+ # table = dataset.table "my_table"
1066
+ #
1067
+ # table.param_types
1068
+ #
1069
+ def param_types
1070
+ return nil if reference?
1071
+ schema.param_types
1072
+ end
1073
+
830
1074
  ##
831
1075
  # The {EncryptionConfiguration} object that represents the custom
832
- # encryption method used to protect the table. If not set, default
833
- # encryption is used.
1076
+ # encryption method used to protect the table. If not set,
1077
+ # {Dataset#default_encryption} is used.
834
1078
  #
835
1079
  # Present only if the table is using custom encryption.
836
1080
  #
@@ -845,14 +1089,13 @@ module Google
845
1089
  return nil if reference?
846
1090
  ensure_full_data!
847
1091
  return nil if @gapi.encryption_configuration.nil?
848
- EncryptionConfiguration.from_gapi(@gapi.encryption_configuration)
849
- .freeze
1092
+ EncryptionConfiguration.from_gapi(@gapi.encryption_configuration).freeze
850
1093
  end
851
1094
 
852
1095
  ##
853
1096
  # Set the {EncryptionConfiguration} object that represents the custom
854
- # encryption method used to protect the table. If not set, default
855
- # encryption is used.
1097
+ # encryption method used to protect the table. If not set,
1098
+ # {Dataset#default_encryption} is used.
856
1099
  #
857
1100
  # Present only if the table is using custom encryption.
858
1101
  #
@@ -860,7 +1103,6 @@ module Google
860
1103
  # {#resource_full?}), the full representation will be retrieved before
861
1104
  # the update to comply with ETag-based optimistic concurrency control.
862
1105
  #
863
- #
864
1106
  # @see https://cloud.google.com/bigquery/docs/customer-managed-encryption
865
1107
  # Protecting Data with Cloud KMS Keys
866
1108
  #
@@ -940,7 +1182,7 @@ module Google
940
1182
  def buffer_bytes
941
1183
  return nil if reference?
942
1184
  ensure_full_data!
943
- @gapi.streaming_buffer.estimated_bytes if @gapi.streaming_buffer
1185
+ @gapi.streaming_buffer&.estimated_bytes
944
1186
  end
945
1187
 
946
1188
  ##
@@ -958,7 +1200,7 @@ module Google
958
1200
  def buffer_rows
959
1201
  return nil if reference?
960
1202
  ensure_full_data!
961
- @gapi.streaming_buffer.estimated_rows if @gapi.streaming_buffer
1203
+ @gapi.streaming_buffer&.estimated_rows
962
1204
  end
963
1205
 
964
1206
  ##
@@ -980,21 +1222,24 @@ module Google
980
1222
  end
981
1223
 
982
1224
  ##
983
- # The query that executes each time the view is loaded.
1225
+ # The query that defines the view or materialized view. See {#view?} and
1226
+ # {#materialized_view?}.
984
1227
  #
985
- # @return [String] The query that defines the view.
1228
+ # @return [String, nil] The query that defines the view or materialized_view;
1229
+ # or `nil` if not a view or materialized view.
986
1230
  #
987
1231
  # @!group Attributes
988
1232
  #
989
1233
  def query
990
- @gapi.view.query if @gapi.view
1234
+ view? ? @gapi.view&.query : @gapi.materialized_view&.query
991
1235
  end
992
1236
 
993
1237
  ##
994
- # Updates the query that executes each time the view is loaded.
1238
+ # Updates the query that defines the view. (See {#view?}.) Not supported
1239
+ # for materialized views.
995
1240
  #
996
- # This sets the query using standard SQL. To specify legacy SQL or to
997
- # use user-defined function resources use (#set_query) instead.
1241
+ # This method sets the query using standard SQL. To specify legacy SQL or
1242
+ # to use user-defined function resources for a view, use (#set_query) instead.
998
1243
  #
999
1244
  # @see https://cloud.google.com/bigquery/query-reference BigQuery Query
1000
1245
  # Reference
@@ -1009,7 +1254,7 @@ module Google
1009
1254
  # view = dataset.table "my_view"
1010
1255
  #
1011
1256
  # view.query = "SELECT first_name FROM " \
1012
- # "`my_project.my_dataset.my_table`"
1257
+ # "`my_project.my_dataset.my_table`"
1013
1258
  #
1014
1259
  # @!group Lifecycle
1015
1260
  #
@@ -1018,12 +1263,12 @@ module Google
1018
1263
  end
1019
1264
 
1020
1265
  ##
1021
- # Updates the query that executes each time the view is loaded. Allows
1022
- # setting of standard vs. legacy SQL and user-defined function
1023
- # resources.
1266
+ # Updates the query that defines the view. (See {#view?}.) Not supported for
1267
+ # materialized views.
1024
1268
  #
1025
- # @see https://cloud.google.com/bigquery/query-reference BigQuery Query
1026
- # Reference
1269
+ # Allows setting of standard vs. legacy SQL and user-defined function resources.
1270
+ #
1271
+ # @see https://cloud.google.com/bigquery/query-reference BigQuery Query Reference
1027
1272
  #
1028
1273
  # @param [String] query The query that defines the view.
1029
1274
  # @param [Boolean] standard_sql Specifies whether to use BigQuery's
@@ -1035,14 +1280,23 @@ module Google
1035
1280
  # SQL](https://cloud.google.com/bigquery/docs/reference/legacy-sql)
1036
1281
  # dialect. Optional. The default value is false.
1037
1282
  # @param [Array<String>, String] udfs User-defined function resources
1038
- # used in the query. May be either a code resource to load from a
1039
- # Google Cloud Storage URI (`gs://bucket/path`), or an inline resource
1040
- # that contains code for a user-defined function (UDF). Providing an
1041
- # inline code resource is equivalent to providing a URI for a file
1042
- # containing the same code. See [User-Defined
1043
- # Functions](https://cloud.google.com/bigquery/docs/reference/standard-sql/user-defined-functions).
1283
+ # used in a legacy SQL query. Optional.
1044
1284
  #
1045
- # @example
1285
+ # May be either a code resource to load from a Google Cloud Storage URI
1286
+ # (`gs://bucket/path`), or an inline resource that contains code for a
1287
+ # user-defined function (UDF). Providing an inline code resource is equivalent
1288
+ # to providing a URI for a file containing the same code.
1289
+ #
1290
+ # This parameter is used for defining User Defined Function (UDF)
1291
+ # resources only when using legacy SQL. Users of standard SQL should
1292
+ # leverage either DDL (e.g. `CREATE [TEMPORARY] FUNCTION ...`) or the
1293
+ # Routines API to define UDF resources.
1294
+ #
1295
+ # For additional information on migrating, see: [Migrating to
1296
+ # standard SQL - Differences in user-defined JavaScript
1297
+ # functions](https://cloud.google.com/bigquery/docs/reference/standard-sql/migrating-from-legacy-sql#differences_in_user-defined_javascript_functions)
1298
+ #
1299
+ # @example Update a view:
1046
1300
  # require "google/cloud/bigquery"
1047
1301
  #
1048
1302
  # bigquery = Google::Cloud::Bigquery.new
@@ -1050,41 +1304,45 @@ module Google
1050
1304
  # view = dataset.table "my_view"
1051
1305
  #
1052
1306
  # view.set_query "SELECT first_name FROM " \
1053
- # "`my_project.my_dataset.my_table`",
1307
+ # "`my_project.my_dataset.my_table`",
1054
1308
  # standard_sql: true
1055
1309
  #
1056
1310
  # @!group Lifecycle
1057
1311
  #
1058
1312
  def set_query query, standard_sql: nil, legacy_sql: nil, udfs: nil
1313
+ raise "Updating the query is not supported for Table type: #{@gapi.type}" unless view?
1059
1314
  use_legacy_sql = Convert.resolve_legacy_sql standard_sql, legacy_sql
1060
- @gapi.view = Google::Apis::BigqueryV2::ViewDefinition.new \
1315
+ @gapi.view = Google::Apis::BigqueryV2::ViewDefinition.new(
1061
1316
  query: query,
1062
1317
  use_legacy_sql: use_legacy_sql,
1063
1318
  user_defined_function_resources: udfs_gapi(udfs)
1319
+ )
1064
1320
  patch_gapi! :view
1065
1321
  end
1066
1322
 
1067
1323
  ##
1068
- # Checks if the view's query is using legacy sql.
1324
+ # Checks if the view's query is using legacy sql. See {#view?}.
1069
1325
  #
1070
- # @return [Boolean] `true` when legacy sql is used, `false` otherwise.
1326
+ # @return [Boolean] `true` when legacy sql is used, `false` otherwise; or `nil` if not a logical view.
1071
1327
  #
1072
1328
  # @!group Attributes
1073
1329
  #
1074
1330
  def query_legacy_sql?
1331
+ return nil unless @gapi.view
1075
1332
  val = @gapi.view.use_legacy_sql
1076
1333
  return true if val.nil?
1077
1334
  val
1078
1335
  end
1079
1336
 
1080
1337
  ##
1081
- # Checks if the view's query is using standard sql.
1338
+ # Checks if the view's query is using standard sql. See {#view?}.
1082
1339
  #
1083
1340
  # @return [Boolean] `true` when standard sql is used, `false` otherwise.
1084
1341
  #
1085
1342
  # @!group Attributes
1086
1343
  #
1087
1344
  def query_standard_sql?
1345
+ return nil unless @gapi.view
1088
1346
  !query_legacy_sql?
1089
1347
  end
1090
1348
 
@@ -1096,18 +1354,193 @@ module Google
1096
1354
  # equivalent to providing a URI for a file containing the same code. See
1097
1355
  # [User-Defined
1098
1356
  # Functions](https://cloud.google.com/bigquery/docs/reference/standard-sql/user-defined-functions).
1357
+ # See {#view?}.
1099
1358
  #
1100
- # @return [Array<String>] An array containing Google Cloud Storage URIs
1101
- # and/or inline source code.
1359
+ # @return [Array<String>, nil] An array containing Google Cloud Storage URIs
1360
+ # and/or inline source code, or `nil` if not a logical view.
1102
1361
  #
1103
1362
  # @!group Attributes
1104
1363
  #
1105
1364
  def query_udfs
1365
+ return nil unless @gapi.view
1106
1366
  udfs_gapi = @gapi.view.user_defined_function_resources
1107
1367
  return [] if udfs_gapi.nil?
1108
1368
  Array(udfs_gapi).map { |udf| udf.inline_code || udf.resource_uri }
1109
1369
  end
1110
1370
 
1371
+ ##
1372
+ # Whether automatic refresh of the materialized view is enabled. When true,
1373
+ # the materialized view is updated when the base table is updated. The default
1374
+ # value is true. See {#materialized_view?}.
1375
+ #
1376
+ # @return [Boolean, nil] `true` when automatic refresh is enabled, `false` otherwise;
1377
+ # or `nil` if not a materialized view.
1378
+ #
1379
+ # @!group Attributes
1380
+ #
1381
+ def enable_refresh?
1382
+ return nil unless @gapi.materialized_view
1383
+ val = @gapi.materialized_view.enable_refresh
1384
+ return true if val.nil?
1385
+ val
1386
+ end
1387
+
1388
+ ##
1389
+ # Sets whether automatic refresh of the materialized view is enabled. When true,
1390
+ # the materialized view is updated when the base table is updated. See {#materialized_view?}.
1391
+ #
1392
+ # @param [Boolean] new_enable_refresh `true` when automatic refresh is enabled, `false` otherwise.
1393
+ #
1394
+ # @!group Attributes
1395
+ #
1396
+ def enable_refresh= new_enable_refresh
1397
+ @gapi.materialized_view = Google::Apis::BigqueryV2::MaterializedViewDefinition.new(
1398
+ enable_refresh: new_enable_refresh
1399
+ )
1400
+ patch_gapi! :materialized_view
1401
+ end
1402
+
1403
+ ##
1404
+ # The time when the materialized view was last modified.
1405
+ # See {#materialized_view?}.
1406
+ #
1407
+ # @return [Time, nil] The time, or `nil` if not present or not a materialized view.
1408
+ #
1409
+ # @!group Attributes
1410
+ #
1411
+ def last_refresh_time
1412
+ Convert.millis_to_time @gapi.materialized_view&.last_refresh_time
1413
+ end
1414
+
1415
+ ##
1416
+ # The maximum frequency in milliseconds at which the materialized view will be refreshed.
1417
+ # See {#materialized_view?}.
1418
+ #
1419
+ # @return [Integer, nil] The maximum frequency in milliseconds;
1420
+ # or `nil` if not a materialized view.
1421
+ #
1422
+ # @!group Attributes
1423
+ #
1424
+ def refresh_interval_ms
1425
+ @gapi.materialized_view&.refresh_interval_ms
1426
+ end
1427
+
1428
+ ##
1429
+ # Sets the maximum frequency at which the materialized view will be refreshed.
1430
+ # See {#materialized_view?}.
1431
+ #
1432
+ # @param [Integer] new_refresh_interval_ms The maximum frequency in milliseconds.
1433
+ #
1434
+ # @!group Attributes
1435
+ #
1436
+ def refresh_interval_ms= new_refresh_interval_ms
1437
+ @gapi.materialized_view = Google::Apis::BigqueryV2::MaterializedViewDefinition.new(
1438
+ refresh_interval_ms: new_refresh_interval_ms
1439
+ )
1440
+ patch_gapi! :materialized_view
1441
+ end
1442
+
1443
+ ##
1444
+ # Gets the Cloud IAM access control policy for the table. The latest policy will be read from the service. See
1445
+ # also {#update_policy}.
1446
+ #
1447
+ # @see https://cloud.google.com/iam/docs/managing-policies Managing Policies
1448
+ # @see https://cloud.google.com/bigquery/docs/table-access-controls-intro Controlling access to tables
1449
+ #
1450
+ # @return [Policy] The frozen policy for the table.
1451
+ #
1452
+ # @example
1453
+ # require "google/cloud/bigquery"
1454
+ #
1455
+ # bigquery = Google::Cloud::Bigquery.new
1456
+ # dataset = bigquery.dataset "my_dataset"
1457
+ # table = dataset.table "my_table"
1458
+ #
1459
+ # policy = table.policy
1460
+ #
1461
+ # policy.frozen? #=> true
1462
+ # binding_owner = policy.bindings.find { |b| b.role == "roles/owner" }
1463
+ # binding_owner.role #=> "roles/owner"
1464
+ # binding_owner.members #=> ["user:owner@example.com"]
1465
+ # binding_owner.frozen? #=> true
1466
+ # binding_owner.members.frozen? #=> true
1467
+ #
1468
+ def policy
1469
+ raise ArgumentError, "Block argument not supported: Use #update_policy instead." if block_given?
1470
+ ensure_service!
1471
+ gapi = service.get_table_policy dataset_id, table_id
1472
+ Policy.from_gapi(gapi).freeze
1473
+ end
1474
+
1475
+ ##
1476
+ # Updates the Cloud IAM access control policy for the table. The latest policy will be read from the service.
1477
+ # See also {#policy}.
1478
+ #
1479
+ # @see https://cloud.google.com/iam/docs/managing-policies Managing Policies
1480
+ # @see https://cloud.google.com/bigquery/docs/table-access-controls-intro Controlling access to tables
1481
+ #
1482
+ # @yield [policy] A block for updating the policy. The latest policy will be read from the service and passed to
1483
+ # the block. After the block completes, the modified policy will be written to the service.
1484
+ # @yieldparam [Policy] policy The mutable Policy for the table.
1485
+ #
1486
+ # @return [Policy] The updated and frozen policy for the table.
1487
+ #
1488
+ # @example Update the policy by passing a block.
1489
+ # require "google/cloud/bigquery"
1490
+ #
1491
+ # bigquery = Google::Cloud::Bigquery.new
1492
+ # dataset = bigquery.dataset "my_dataset"
1493
+ # table = dataset.table "my_table"
1494
+ #
1495
+ # table.update_policy do |p|
1496
+ # p.grant role: "roles/viewer", members: "user:viewer@example.com"
1497
+ # p.revoke role: "roles/editor", members: "user:editor@example.com"
1498
+ # p.revoke role: "roles/owner"
1499
+ # end # 2 API calls
1500
+ #
1501
+ def update_policy
1502
+ raise ArgumentError, "A block updating the policy must be provided" unless block_given?
1503
+ ensure_service!
1504
+ gapi = service.get_table_policy dataset_id, table_id
1505
+ policy = Policy.from_gapi gapi
1506
+ yield policy
1507
+ # TODO: Check for changes before calling RPC
1508
+ gapi = service.set_table_policy dataset_id, table_id, policy.to_gapi
1509
+ Policy.from_gapi(gapi).freeze
1510
+ end
1511
+
1512
+ ##
1513
+ # Tests the specified permissions against the [Cloud
1514
+ # IAM](https://cloud.google.com/iam/) access control policy.
1515
+ #
1516
+ # @see https://cloud.google.com/iam/docs/managing-policies Managing Policies
1517
+ #
1518
+ # @param [String, Array<String>] permissions The set of permissions
1519
+ # against which to check access. Permissions must be of the format
1520
+ # `bigquery.resource.capability`.
1521
+ # See https://cloud.google.com/bigquery/docs/access-control#bigquery.
1522
+ #
1523
+ # @return [Array<String>] The frozen array of permissions held by the caller.
1524
+ #
1525
+ # @example
1526
+ # require "google/cloud/bigquery"
1527
+ #
1528
+ # bigquery = Google::Cloud::Bigquery.new
1529
+ # dataset = bigquery.dataset "my_dataset"
1530
+ # table = dataset.table "my_table"
1531
+ #
1532
+ # permissions = table.test_iam_permissions "bigquery.tables.get",
1533
+ # "bigquery.tables.delete"
1534
+ # permissions.include? "bigquery.tables.get" #=> true
1535
+ # permissions.include? "bigquery.tables.delete" #=> false
1536
+ #
1537
+ def test_iam_permissions *permissions
1538
+ permissions = Array(permissions).flatten
1539
+ ensure_service!
1540
+ gapi = service.test_table_permissions dataset_id, table_id, permissions
1541
+ gapi.permissions.freeze
1542
+ end
1543
+
1111
1544
  ##
1112
1545
  # Retrieves data from the table.
1113
1546
  #
@@ -1131,12 +1564,13 @@ module Google
1131
1564
  # table = dataset.table "my_table"
1132
1565
  #
1133
1566
  # data = table.data
1567
+ #
1568
+ # # Iterate over the first page of results
1134
1569
  # data.each do |row|
1135
- # puts row[:first_name]
1136
- # end
1137
- # if data.next?
1138
- # more_data = data.next if data.next?
1570
+ # puts row[:name]
1139
1571
  # end
1572
+ # # Retrieve the next page of results
1573
+ # data = data.next if data.next?
1140
1574
  #
1141
1575
  # @example Retrieve all rows of data: (See {Data#all})
1142
1576
  # require "google/cloud/bigquery"
@@ -1146,8 +1580,9 @@ module Google
1146
1580
  # table = dataset.table "my_table"
1147
1581
  #
1148
1582
  # data = table.data
1583
+ #
1149
1584
  # data.all do |row|
1150
- # puts row[:first_name]
1585
+ # puts row[:name]
1151
1586
  # end
1152
1587
  #
1153
1588
  # @!group Data
@@ -1155,9 +1590,7 @@ module Google
1155
1590
  def data token: nil, max: nil, start: nil
1156
1591
  ensure_service!
1157
1592
  reload! unless resource_full?
1158
- options = { token: token, max: max, start: start }
1159
- data_json = service.list_tabledata \
1160
- dataset_id, table_id, options
1593
+ data_json = service.list_tabledata dataset_id, table_id, token: token, max: max, start: start
1161
1594
  Data.from_gapi_json data_json, gapi, nil, service
1162
1595
  end
1163
1596
 
@@ -1200,8 +1633,8 @@ module Google
1200
1633
  # * `empty` - An error will be returned if the destination table
1201
1634
  # already contains data.
1202
1635
  # @param [String] job_id A user-defined ID for the copy job. The ID
1203
- # must contain only letters (a-z, A-Z), numbers (0-9), underscores
1204
- # (_), or dashes (-). The maximum length is 1,024 characters. If
1636
+ # must contain only letters (`[A-Za-z]`), numbers (`[0-9]`), underscores
1637
+ # (`_`), or dashes (`-`). The maximum length is 1,024 characters. If
1205
1638
  # `job_id` is provided, then `prefix` will not be used.
1206
1639
  #
1207
1640
  # See [Generating a job
@@ -1210,18 +1643,26 @@ module Google
1210
1643
  # prepended to a generated value to produce a unique job ID. For
1211
1644
  # example, the prefix `daily_import_job_` can be given to generate a
1212
1645
  # job ID such as `daily_import_job_12vEDtMQ0mbp1Mo5Z7mzAFQJZazh`. The
1213
- # prefix must contain only letters (a-z, A-Z), numbers (0-9),
1214
- # underscores (_), or dashes (-). The maximum length of the entire ID
1646
+ # prefix must contain only letters (`[A-Za-z]`), numbers (`[0-9]`),
1647
+ # underscores (`_`), or dashes (`-`). The maximum length of the entire ID
1215
1648
  # is 1,024 characters. If `job_id` is provided, then `prefix` will not
1216
1649
  # be used.
1217
1650
  # @param [Hash] labels A hash of user-provided labels associated with
1218
- # the job. You can use these to organize and group your jobs. Label
1219
- # keys and values can be no longer than 63 characters, can only
1220
- # contain lowercase letters, numeric characters, underscores and
1221
- # dashes. International characters are allowed. Label values are
1222
- # optional. Label keys must start with a letter and each label in the
1223
- # list must have a different key. See [Requirements for
1224
- # labels](https://cloud.google.com/bigquery/docs/creating-managing-labels#requirements).
1651
+ # the job. You can use these to organize and group your jobs.
1652
+ #
1653
+ # The labels applied to a resource must meet the following requirements:
1654
+ #
1655
+ # * Each resource can have multiple labels, up to a maximum of 64.
1656
+ # * Each label must be a key-value pair.
1657
+ # * Keys have a minimum length of 1 character and a maximum length of
1658
+ # 63 characters, and cannot be empty. Values can be empty, and have
1659
+ # a maximum length of 63 characters.
1660
+ # * Keys and values can contain only lowercase letters, numeric characters,
1661
+ # underscores, and dashes. All characters must use UTF-8 encoding, and
1662
+ # international characters are allowed.
1663
+ # * The key portion of a label must be unique. However, you can use the
1664
+ # same key with multiple resources.
1665
+ # * Keys must start with a lowercase letter or international character.
1225
1666
  # @param [Boolean] dryrun If set, don't actually run this job. Behavior
1226
1667
  # is undefined however for non-query jobs and may result in an error.
1227
1668
  # Deprecated.
@@ -1256,11 +1697,9 @@ module Google
1256
1697
  #
1257
1698
  # @!group Data
1258
1699
  #
1259
- def copy_job destination_table, create: nil, write: nil, job_id: nil,
1260
- prefix: nil, labels: nil, dryrun: nil
1700
+ def copy_job destination_table, create: nil, write: nil, job_id: nil, prefix: nil, labels: nil, dryrun: nil
1261
1701
  ensure_service!
1262
- options = { create: create, write: write, dryrun: dryrun,
1263
- labels: labels, job_id: job_id, prefix: prefix }
1702
+ options = { create: create, write: write, dryrun: dryrun, labels: labels, job_id: job_id, prefix: prefix }
1264
1703
  updater = CopyJob::Updater.from_options(
1265
1704
  service,
1266
1705
  table_ref,
@@ -1358,11 +1797,11 @@ module Google
1358
1797
  # The geographic location for the job ("US", "EU", etc.) can be set via
1359
1798
  # {ExtractJob::Updater#location=} in a block passed to this method. If
1360
1799
  # the table is a full resource representation (see {#resource_full?}),
1361
- # the location of the job will be automatically set to the location of
1800
+ # the location of the job will automatically be set to the location of
1362
1801
  # the table.
1363
1802
  #
1364
- # @see https://cloud.google.com/bigquery/exporting-data-from-bigquery
1365
- # Exporting Data From BigQuery
1803
+ # @see https://cloud.google.com/bigquery/docs/exporting-data
1804
+ # Exporting table data
1366
1805
  #
1367
1806
  # @param [Google::Cloud::Storage::File, String, Array<String>]
1368
1807
  # extract_url The Google Storage file or file URI pattern(s) to which
@@ -1383,8 +1822,8 @@ module Google
1383
1822
  # @param [Boolean] header Whether to print out a header row in the
1384
1823
  # results. Default is `true`.
1385
1824
  # @param [String] job_id A user-defined ID for the extract job. The ID
1386
- # must contain only letters (a-z, A-Z), numbers (0-9), underscores
1387
- # (_), or dashes (-). The maximum length is 1,024 characters. If
1825
+ # must contain only letters (`[A-Za-z]`), numbers (`[0-9]`), underscores
1826
+ # (`_`), or dashes (`-`). The maximum length is 1,024 characters. If
1388
1827
  # `job_id` is provided, then `prefix` will not be used.
1389
1828
  #
1390
1829
  # See [Generating a job
@@ -1393,18 +1832,26 @@ module Google
1393
1832
  # prepended to a generated value to produce a unique job ID. For
1394
1833
  # example, the prefix `daily_import_job_` can be given to generate a
1395
1834
  # job ID such as `daily_import_job_12vEDtMQ0mbp1Mo5Z7mzAFQJZazh`. The
1396
- # prefix must contain only letters (a-z, A-Z), numbers (0-9),
1397
- # underscores (_), or dashes (-). The maximum length of the entire ID
1835
+ # prefix must contain only letters (`[A-Za-z]`), numbers (`[0-9]`),
1836
+ # underscores (`_`), or dashes (`-`). The maximum length of the entire ID
1398
1837
  # is 1,024 characters. If `job_id` is provided, then `prefix` will not
1399
1838
  # be used.
1400
1839
  # @param [Hash] labels A hash of user-provided labels associated with
1401
- # the job. You can use these to organize and group your jobs. Label
1402
- # keys and values can be no longer than 63 characters, can only
1403
- # contain lowercase letters, numeric characters, underscores and
1404
- # dashes. International characters are allowed. Label values are
1405
- # optional. Label keys must start with a letter and each label in the
1406
- # list must have a different key. See [Requirements for
1407
- # labels](https://cloud.google.com/bigquery/docs/creating-managing-labels#requirements).
1840
+ # the job. You can use these to organize and group your jobs.
1841
+ #
1842
+ # The labels applied to a resource must meet the following requirements:
1843
+ #
1844
+ # * Each resource can have multiple labels, up to a maximum of 64.
1845
+ # * Each label must be a key-value pair.
1846
+ # * Keys have a minimum length of 1 character and a maximum length of
1847
+ # 63 characters, and cannot be empty. Values can be empty, and have
1848
+ # a maximum length of 63 characters.
1849
+ # * Keys and values can contain only lowercase letters, numeric characters,
1850
+ # underscores, and dashes. All characters must use UTF-8 encoding, and
1851
+ # international characters are allowed.
1852
+ # * The key portion of a label must be unique. However, you can use the
1853
+ # same key with multiple resources.
1854
+ # * Keys must start with a lowercase letter or international character.
1408
1855
  # @param [Boolean] dryrun If set, don't actually run this job. Behavior
1409
1856
  # is undefined however for non-query jobs and may result in an error.
1410
1857
  # Deprecated.
@@ -1429,15 +1876,12 @@ module Google
1429
1876
  #
1430
1877
  # @!group Data
1431
1878
  #
1432
- def extract_job extract_url, format: nil, compression: nil,
1433
- delimiter: nil, header: nil, job_id: nil, prefix: nil,
1434
- labels: nil, dryrun: nil
1879
+ def extract_job extract_url, format: nil, compression: nil, delimiter: nil, header: nil, job_id: nil,
1880
+ prefix: nil, labels: nil, dryrun: nil
1435
1881
  ensure_service!
1436
- options = { format: format, compression: compression,
1437
- delimiter: delimiter, header: header, dryrun: dryrun,
1882
+ options = { format: format, compression: compression, delimiter: delimiter, header: header, dryrun: dryrun,
1438
1883
  job_id: job_id, prefix: prefix, labels: labels }
1439
- updater = ExtractJob::Updater.from_options service, table_ref,
1440
- extract_url, options
1884
+ updater = ExtractJob::Updater.from_options service, table_ref, extract_url, options
1441
1885
  updater.location = location if location # may be table reference
1442
1886
 
1443
1887
  yield updater if block_given?
@@ -1459,8 +1903,8 @@ module Google
1459
1903
  # the location of the job will be automatically set to the location of
1460
1904
  # the table.
1461
1905
  #
1462
- # @see https://cloud.google.com/bigquery/exporting-data-from-bigquery
1463
- # Exporting Data From BigQuery
1906
+ # @see https://cloud.google.com/bigquery/docs/exporting-data
1907
+ # Exporting table data
1464
1908
  #
1465
1909
  # @param [Google::Cloud::Storage::File, String, Array<String>]
1466
1910
  # extract_url The Google Storage file or file URI pattern(s) to which
@@ -1508,8 +1952,7 @@ module Google
1508
1952
  #
1509
1953
  # @!group Data
1510
1954
  #
1511
- def extract extract_url, format: nil, compression: nil, delimiter: nil,
1512
- header: nil, &block
1955
+ def extract extract_url, format: nil, compression: nil, delimiter: nil, header: nil, &block
1513
1956
  job = extract_job extract_url,
1514
1957
  format: format,
1515
1958
  compression: compression,
@@ -1627,8 +2070,8 @@ module Google
1627
2070
  # value is `0`. This property is useful if you have header rows in the
1628
2071
  # file that should be skipped.
1629
2072
  # @param [String] job_id A user-defined ID for the load job. The ID
1630
- # must contain only letters (a-z, A-Z), numbers (0-9), underscores
1631
- # (_), or dashes (-). The maximum length is 1,024 characters. If
2073
+ # must contain only letters (`[A-Za-z]`), numbers (`[0-9]`), underscores
2074
+ # (`_`), or dashes (`-`). The maximum length is 1,024 characters. If
1632
2075
  # `job_id` is provided, then `prefix` will not be used.
1633
2076
  #
1634
2077
  # See [Generating a job
@@ -1637,18 +2080,26 @@ module Google
1637
2080
  # prepended to a generated value to produce a unique job ID. For
1638
2081
  # example, the prefix `daily_import_job_` can be given to generate a
1639
2082
  # job ID such as `daily_import_job_12vEDtMQ0mbp1Mo5Z7mzAFQJZazh`. The
1640
- # prefix must contain only letters (a-z, A-Z), numbers (0-9),
1641
- # underscores (_), or dashes (-). The maximum length of the entire ID
2083
+ # prefix must contain only letters (`[A-Za-z]`), numbers (`[0-9]`),
2084
+ # underscores (`_`), or dashes (`-`). The maximum length of the entire ID
1642
2085
  # is 1,024 characters. If `job_id` is provided, then `prefix` will not
1643
2086
  # be used.
1644
2087
  # @param [Hash] labels A hash of user-provided labels associated with
1645
- # the job. You can use these to organize and group your jobs. Label
1646
- # keys and values can be no longer than 63 characters, can only
1647
- # contain lowercase letters, numeric characters, underscores and
1648
- # dashes. International characters are allowed. Label values are
1649
- # optional. Label keys must start with a letter and each label in the
1650
- # list must have a different key. See [Requirements for
1651
- # labels](https://cloud.google.com/bigquery/docs/creating-managing-labels#requirements).
2088
+ # the job. You can use these to organize and group your jobs.
2089
+ #
2090
+ # The labels applied to a resource must meet the following requirements:
2091
+ #
2092
+ # * Each resource can have multiple labels, up to a maximum of 64.
2093
+ # * Each label must be a key-value pair.
2094
+ # * Keys have a minimum length of 1 character and a maximum length of
2095
+ # 63 characters, and cannot be empty. Values can be empty, and have
2096
+ # a maximum length of 63 characters.
2097
+ # * Keys and values can contain only lowercase letters, numeric characters,
2098
+ # underscores, and dashes. All characters must use UTF-8 encoding, and
2099
+ # international characters are allowed.
2100
+ # * The key portion of a label must be unique. However, you can use the
2101
+ # same key with multiple resources.
2102
+ # * Keys must start with a lowercase letter or international character.
1652
2103
  # @param [Boolean] dryrun If set, don't actually run this job. Behavior
1653
2104
  # is undefined however for non-query jobs and may result in an error.
1654
2105
  # Deprecated.
@@ -1705,28 +2156,18 @@ module Google
1705
2156
  #
1706
2157
  # @!group Data
1707
2158
  #
1708
- def load_job files, format: nil, create: nil, write: nil,
1709
- projection_fields: nil, jagged_rows: nil,
1710
- quoted_newlines: nil, encoding: nil, delimiter: nil,
1711
- ignore_unknown: nil, max_bad_records: nil, quote: nil,
1712
- skip_leading: nil, job_id: nil, prefix: nil, labels: nil,
1713
- autodetect: nil, null_marker: nil, dryrun: nil
2159
+ def load_job files, format: nil, create: nil, write: nil, projection_fields: nil, jagged_rows: nil,
2160
+ quoted_newlines: nil, encoding: nil, delimiter: nil, ignore_unknown: nil, max_bad_records: nil,
2161
+ quote: nil, skip_leading: nil, job_id: nil, prefix: nil, labels: nil, autodetect: nil,
2162
+ null_marker: nil, dryrun: nil
1714
2163
  ensure_service!
1715
2164
 
1716
- updater = load_job_updater format: format, create: create,
1717
- write: write,
1718
- projection_fields: projection_fields,
1719
- jagged_rows: jagged_rows,
1720
- quoted_newlines: quoted_newlines,
1721
- encoding: encoding,
1722
- delimiter: delimiter,
1723
- ignore_unknown: ignore_unknown,
1724
- max_bad_records: max_bad_records,
1725
- quote: quote, skip_leading: skip_leading,
1726
- dryrun: dryrun, job_id: job_id,
1727
- prefix: prefix, schema: schema,
1728
- labels: labels, autodetect: autodetect,
1729
- null_marker: null_marker
2165
+ updater = load_job_updater format: format, create: create, write: write, projection_fields: projection_fields,
2166
+ jagged_rows: jagged_rows, quoted_newlines: quoted_newlines, encoding: encoding,
2167
+ delimiter: delimiter, ignore_unknown: ignore_unknown,
2168
+ max_bad_records: max_bad_records, quote: quote, skip_leading: skip_leading,
2169
+ dryrun: dryrun, job_id: job_id, prefix: prefix, schema: schema, labels: labels,
2170
+ autodetect: autodetect, null_marker: null_marker
1730
2171
 
1731
2172
  yield updater if block_given?
1732
2173
 
@@ -1900,20 +2341,13 @@ module Google
1900
2341
  #
1901
2342
  # @!group Data
1902
2343
  #
1903
- def load files, format: nil, create: nil, write: nil,
1904
- projection_fields: nil, jagged_rows: nil, quoted_newlines: nil,
1905
- encoding: nil, delimiter: nil, ignore_unknown: nil,
1906
- max_bad_records: nil, quote: nil, skip_leading: nil,
1907
- autodetect: nil, null_marker: nil, &block
1908
- job = load_job files, format: format, create: create, write: write,
1909
- projection_fields: projection_fields,
1910
- jagged_rows: jagged_rows,
1911
- quoted_newlines: quoted_newlines,
1912
- encoding: encoding, delimiter: delimiter,
1913
- ignore_unknown: ignore_unknown,
1914
- max_bad_records: max_bad_records,
1915
- quote: quote, skip_leading: skip_leading,
1916
- autodetect: autodetect,
2344
+ def load files, format: nil, create: nil, write: nil, projection_fields: nil, jagged_rows: nil,
2345
+ quoted_newlines: nil, encoding: nil, delimiter: nil, ignore_unknown: nil, max_bad_records: nil,
2346
+ quote: nil, skip_leading: nil, autodetect: nil, null_marker: nil, &block
2347
+ job = load_job files, format: format, create: create, write: write, projection_fields: projection_fields,
2348
+ jagged_rows: jagged_rows, quoted_newlines: quoted_newlines, encoding: encoding,
2349
+ delimiter: delimiter, ignore_unknown: ignore_unknown, max_bad_records: max_bad_records,
2350
+ quote: quote, skip_leading: skip_leading, autodetect: autodetect,
1917
2351
  null_marker: null_marker, &block
1918
2352
 
1919
2353
  job.wait_until_done!
@@ -1926,17 +2360,48 @@ module Google
1926
2360
  # need to complete a load operation before the data can appear in query
1927
2361
  # results.
1928
2362
  #
2363
+ # Simple Ruby types are generally accepted per JSON rules, along with the following support for BigQuery's more
2364
+ # complex types:
2365
+ #
2366
+ # | BigQuery | Ruby | Notes |
2367
+ # |--------------|--------------------------------------|----------------------------------------------------|
2368
+ # | `NUMERIC` | `BigDecimal` | `BigDecimal` values will be rounded to scale 9. |
2369
+ # | `BIGNUMERIC` | `String` | Pass as `String` to avoid rounding to scale 9. |
2370
+ # | `DATETIME` | `DateTime` | `DATETIME` does not support time zone. |
2371
+ # | `DATE` | `Date` | |
2372
+ # | `GEOGRAPHY` | `String` | Well-known text (WKT) or GeoJSON. |
2373
+ # | `TIMESTAMP` | `Time` | |
2374
+ # | `TIME` | `Google::Cloud::BigQuery::Time` | |
2375
+ # | `BYTES` | `File`, `IO`, `StringIO`, or similar | |
2376
+ # | `ARRAY` | `Array` | Nested arrays, `nil` values are not supported. |
2377
+ # | `STRUCT` | `Hash` | Hash keys may be strings or symbols. |
2378
+ #
2379
+ # For `GEOGRAPHY` data, see [Working with BigQuery GIS data](https://cloud.google.com/bigquery/docs/gis-data).
2380
+ #
2381
+ # Because BigQuery's streaming API is designed for high insertion rates,
2382
+ # modifications to the underlying table metadata are eventually
2383
+ # consistent when interacting with the streaming system. In most cases
2384
+ # metadata changes are propagated within minutes, but during this period
2385
+ # API responses may reflect the inconsistent state of the table.
2386
+ #
1929
2387
  # @see https://cloud.google.com/bigquery/streaming-data-into-bigquery
1930
2388
  # Streaming Data Into BigQuery
1931
2389
  #
2390
+ # @see https://cloud.google.com/bigquery/troubleshooting-errors#metadata-errors-for-streaming-inserts
2391
+ # BigQuery Troubleshooting: Metadata errors for streaming inserts
2392
+ #
1932
2393
  # @param [Hash, Array<Hash>] rows A hash object or array of hash objects
1933
- # containing the data. Required.
1934
- # @param [Array<String>] insert_ids A unique ID for each row. BigQuery
1935
- # uses this property to detect duplicate insertion requests on a
1936
- # best-effort basis. For more information, see [data
1937
- # consistency](https://cloud.google.com/bigquery/streaming-data-into-bigquery#dataconsistency).
1938
- # Optional. If not provided, the client library will assign a UUID to
1939
- # each row before the request is sent.
2394
+ # containing the data. Required. `BigDecimal` values will be rounded to
2395
+ # scale 9 to conform with the BigQuery `NUMERIC` data type. To avoid
2396
+ # rounding `BIGNUMERIC` type values with scale greater than 9, use `String`
2397
+ # instead of `BigDecimal`.
2398
+ # @param [Array<String|Symbol>, Symbol] insert_ids A unique ID for each row. BigQuery uses this property to
2399
+ # detect duplicate insertion requests on a best-effort basis. For more information, see [data
2400
+ # consistency](https://cloud.google.com/bigquery/streaming-data-into-bigquery#dataconsistency). Optional. If
2401
+ # not provided, the client library will assign a UUID to each row before the request is sent.
2402
+ #
2403
+ # The value `:skip` can be provided to skip the generation of IDs for all rows, or to skip the generation of an
2404
+ # ID for a specific row in the array.
1940
2405
  # @param [Boolean] skip_invalid Insert all valid rows of a request, even
1941
2406
  # if invalid rows exist. The default value is `false`, which causes
1942
2407
  # the entire request to fail if any invalid rows exist.
@@ -1972,21 +2437,38 @@ module Google
1972
2437
  # ]
1973
2438
  # table.insert rows
1974
2439
  #
2440
+ # @example Pass `BIGNUMERIC` value as a string to avoid rounding to scale 9 in the conversion from `BigDecimal`:
2441
+ # require "google/cloud/bigquery"
2442
+ #
2443
+ # bigquery = Google::Cloud::Bigquery.new
2444
+ # dataset = bigquery.dataset "my_dataset"
2445
+ # table = dataset.table "my_table"
2446
+ #
2447
+ # row = {
2448
+ # "my_numeric" => BigDecimal("123456798.987654321"),
2449
+ # "my_bignumeric" => "123456798.98765432100001" # BigDecimal would be rounded, use String instead!
2450
+ # }
2451
+ # table.insert row
2452
+ #
1975
2453
  # @!group Data
1976
2454
  #
1977
2455
  def insert rows, insert_ids: nil, skip_invalid: nil, ignore_unknown: nil
1978
2456
  rows = [rows] if rows.is_a? Hash
2457
+ raise ArgumentError, "No rows provided" if rows.empty?
2458
+
2459
+ insert_ids = Array.new(rows.count) { :skip } if insert_ids == :skip
1979
2460
  insert_ids = Array insert_ids
1980
- if insert_ids.count > 0 && insert_ids.count != rows.count
2461
+ if insert_ids.count.positive? && insert_ids.count != rows.count
1981
2462
  raise ArgumentError, "insert_ids must be the same size as rows"
1982
2463
  end
1983
- rows = [rows] if rows.is_a? Hash
1984
- raise ArgumentError, "No rows provided" if rows.empty?
2464
+
1985
2465
  ensure_service!
1986
- options = { skip_invalid: skip_invalid,
1987
- ignore_unknown: ignore_unknown,
1988
- insert_ids: insert_ids }
1989
- gapi = service.insert_tabledata dataset_id, table_id, rows, options
2466
+ gapi = service.insert_tabledata dataset_id,
2467
+ table_id,
2468
+ rows,
2469
+ skip_invalid: skip_invalid,
2470
+ ignore_unknown: ignore_unknown,
2471
+ insert_ids: insert_ids
1990
2472
  InsertResponse.from_gapi rows, gapi
1991
2473
  end
1992
2474
 
@@ -2037,15 +2519,12 @@ module Google
2037
2519
  #
2038
2520
  # inserter.stop.wait!
2039
2521
  #
2040
- def insert_async skip_invalid: nil, ignore_unknown: nil,
2041
- max_bytes: 10000000, max_rows: 500, interval: 10,
2522
+ def insert_async skip_invalid: nil, ignore_unknown: nil, max_bytes: 10_000_000, max_rows: 500, interval: 10,
2042
2523
  threads: 4, &block
2043
2524
  ensure_service!
2044
2525
 
2045
- AsyncInserter.new self, skip_invalid: skip_invalid,
2046
- ignore_unknown: ignore_unknown,
2047
- max_bytes: max_bytes, max_rows: max_rows,
2048
- interval: interval, threads: threads, &block
2526
+ AsyncInserter.new self, skip_invalid: skip_invalid, ignore_unknown: ignore_unknown, max_bytes: max_bytes,
2527
+ max_rows: max_rows, interval: interval, threads: threads, &block
2049
2528
  end
2050
2529
 
2051
2530
  ##
@@ -2120,7 +2599,7 @@ module Google
2120
2599
  # table = dataset.table "my_table", skip_lookup: true
2121
2600
  # table.exists? # true
2122
2601
  #
2123
- def exists? force: nil
2602
+ def exists? force: false
2124
2603
  return gapi_exists? if force
2125
2604
  # If we have a value, return it
2126
2605
  return @exists unless @exists.nil?
@@ -2234,7 +2713,7 @@ module Google
2234
2713
  end
2235
2714
 
2236
2715
  ##
2237
- # @private New lazy Table object without making an HTTP request.
2716
+ # @private New lazy Table object without making an HTTP request, for use with the skip_lookup option.
2238
2717
  def self.new_reference project_id, dataset_id, table_id, service
2239
2718
  raise ArgumentError, "dataset_id is required" unless dataset_id
2240
2719
  raise ArgumentError, "table_id is required" unless table_id
@@ -2287,10 +2766,8 @@ module Google
2287
2766
  def patch_gapi! *attributes
2288
2767
  return if attributes.empty?
2289
2768
  ensure_service!
2290
- patch_args = Hash[attributes.map do |attr|
2291
- [attr, @gapi.send(attr)]
2292
- end]
2293
- patch_gapi = Google::Apis::BigqueryV2::Table.new patch_args
2769
+ patch_args = Hash[attributes.map { |attr| [attr, @gapi.send(attr)] }]
2770
+ patch_gapi = Google::Apis::BigqueryV2::Table.new(**patch_args)
2294
2771
  patch_gapi.etag = etag if etag
2295
2772
  @gapi = service.patch_table dataset_id, table_id, patch_gapi
2296
2773
 
@@ -2327,11 +2804,8 @@ module Google
2327
2804
  )
2328
2805
  end
2329
2806
 
2330
- def load_job_csv_options! job, jagged_rows: nil,
2331
- quoted_newlines: nil,
2332
- delimiter: nil,
2333
- quote: nil, skip_leading: nil,
2334
- null_marker: nil
2807
+ def load_job_csv_options! job, jagged_rows: nil, quoted_newlines: nil, delimiter: nil, quote: nil,
2808
+ skip_leading: nil, null_marker: nil
2335
2809
  job.jagged_rows = jagged_rows unless jagged_rows.nil?
2336
2810
  job.quoted_newlines = quoted_newlines unless quoted_newlines.nil?
2337
2811
  job.delimiter = delimiter unless delimiter.nil?
@@ -2340,17 +2814,11 @@ module Google
2340
2814
  job.skip_leading = skip_leading unless skip_leading.nil?
2341
2815
  end
2342
2816
 
2343
- def load_job_file_options! job, format: nil,
2344
- projection_fields: nil,
2345
- jagged_rows: nil, quoted_newlines: nil,
2346
- encoding: nil, delimiter: nil,
2347
- ignore_unknown: nil, max_bad_records: nil,
2348
- quote: nil, skip_leading: nil,
2349
- null_marker: nil
2817
+ def load_job_file_options! job, format: nil, projection_fields: nil, jagged_rows: nil, quoted_newlines: nil,
2818
+ encoding: nil, delimiter: nil, ignore_unknown: nil, max_bad_records: nil, quote: nil,
2819
+ skip_leading: nil, null_marker: nil
2350
2820
  job.format = format unless format.nil?
2351
- unless projection_fields.nil?
2352
- job.projection_fields = projection_fields
2353
- end
2821
+ job.projection_fields = projection_fields unless projection_fields.nil?
2354
2822
  job.encoding = encoding unless encoding.nil?
2355
2823
  job.ignore_unknown = ignore_unknown unless ignore_unknown.nil?
2356
2824
  job.max_bad_records = max_bad_records unless max_bad_records.nil?
@@ -2362,16 +2830,11 @@ module Google
2362
2830
  null_marker: null_marker
2363
2831
  end
2364
2832
 
2365
- def load_job_updater format: nil, create: nil,
2366
- write: nil, projection_fields: nil,
2367
- jagged_rows: nil, quoted_newlines: nil,
2368
- encoding: nil, delimiter: nil,
2369
- ignore_unknown: nil, max_bad_records: nil,
2370
- quote: nil, skip_leading: nil, dryrun: nil,
2371
- schema: nil, job_id: nil, prefix: nil, labels: nil,
2372
- autodetect: nil, null_marker: nil
2373
- new_job = load_job_gapi table_id, dryrun, job_id: job_id,
2374
- prefix: prefix
2833
+ def load_job_updater format: nil, create: nil, write: nil, projection_fields: nil, jagged_rows: nil,
2834
+ quoted_newlines: nil, encoding: nil, delimiter: nil, ignore_unknown: nil,
2835
+ max_bad_records: nil, quote: nil, skip_leading: nil, dryrun: nil, schema: nil, job_id: nil,
2836
+ prefix: nil, labels: nil, autodetect: nil, null_marker: nil
2837
+ new_job = load_job_gapi table_id, dryrun, job_id: job_id, prefix: prefix
2375
2838
  LoadJob::Updater.new(new_job).tap do |job|
2376
2839
  job.location = location if location # may be table reference
2377
2840
  job.create = create unless create.nil?
@@ -2409,9 +2872,7 @@ module Google
2409
2872
  job_gapi.configuration.load.update! source_uris: urls
2410
2873
  if job_gapi.configuration.load.source_format.nil?
2411
2874
  source_format = Convert.derive_source_format_from_list urls
2412
- unless source_format.nil?
2413
- job_gapi.configuration.load.source_format = source_format
2414
- end
2875
+ job_gapi.configuration.load.source_format = source_format unless source_format.nil?
2415
2876
  end
2416
2877
  end
2417
2878
 
@@ -2423,9 +2884,7 @@ module Google
2423
2884
  path = Pathname(file).to_path
2424
2885
  if job_gapi.configuration.load.source_format.nil?
2425
2886
  source_format = Convert.derive_source_format path
2426
- unless source_format.nil?
2427
- job_gapi.configuration.load.source_format = source_format
2428
- end
2887
+ job_gapi.configuration.load.source_format = source_format unless source_format.nil?
2429
2888
  end
2430
2889
 
2431
2890
  gapi = service.load_table_file file, job_gapi
@@ -2434,21 +2893,18 @@ module Google
2434
2893
 
2435
2894
  def load_local_or_uri file, updater
2436
2895
  job_gapi = updater.to_gapi
2437
- job = if local_file? file
2438
- load_local file, job_gapi
2439
- else
2440
- load_storage file, job_gapi
2441
- end
2442
- job
2896
+ if local_file? file
2897
+ load_local file, job_gapi
2898
+ else
2899
+ load_storage file, job_gapi
2900
+ end
2443
2901
  end
2444
2902
 
2445
2903
  def storage_url? files
2446
2904
  [files].flatten.all? do |file|
2447
2905
  file.respond_to?(:to_gs_url) ||
2448
- (file.respond_to?(:to_str) &&
2449
- file.to_str.downcase.start_with?("gs://")) ||
2450
- (file.is_a?(URI) &&
2451
- file.to_s.downcase.start_with?("gs://"))
2906
+ (file.respond_to?(:to_str) && file.to_str.downcase.start_with?("gs://")) ||
2907
+ (file.is_a?(URI) && file.to_s.downcase.start_with?("gs://"))
2452
2908
  end
2453
2909
  end
2454
2910
 
@@ -2485,42 +2941,200 @@ module Google
2485
2941
  end
2486
2942
 
2487
2943
  ##
2488
- # Yielded to a block to accumulate changes for a patch request.
2944
+ # Yielded to a block to accumulate changes for a create request. See {Dataset#create_table}.
2489
2945
  class Updater < Table
2490
2946
  ##
2491
- # A list of attributes that were updated.
2947
+ # @private A list of attributes that were updated.
2492
2948
  attr_reader :updates
2493
2949
 
2494
2950
  ##
2495
- # Create an Updater object.
2951
+ # @private Create an Updater object.
2496
2952
  def initialize gapi
2953
+ super()
2497
2954
  @updates = []
2498
2955
  @gapi = gapi
2499
2956
  @schema = nil
2500
2957
  end
2501
2958
 
2502
2959
  ##
2503
- # Sets one or more fields on which data should be clustered. Must be
2504
- # specified with time-based partitioning, data in the table will be
2505
- # first partitioned and subsequently clustered.
2960
+ # Sets the field on which to range partition the table. See [Creating and using integer range partitioned
2961
+ # tables](https://cloud.google.com/bigquery/docs/creating-integer-range-partitions).
2962
+ #
2963
+ # See {Table::Updater#range_partitioning_start=}, {Table::Updater#range_partitioning_interval=} and
2964
+ # {Table::Updater#range_partitioning_end=}.
2965
+ #
2966
+ # You can only set range partitioning when creating a table as in the example below. BigQuery does not allow
2967
+ # you to change partitioning on an existing table.
2968
+ #
2969
+ # @param [String] field The range partition field. The table is partitioned by this
2970
+ # field. The field must be a top-level `NULLABLE/REQUIRED` field. The only supported
2971
+ # type is `INTEGER/INT64`.
2972
+ #
2973
+ # @example
2974
+ # require "google/cloud/bigquery"
2975
+ #
2976
+ # bigquery = Google::Cloud::Bigquery.new
2977
+ # dataset = bigquery.dataset "my_dataset"
2978
+ #
2979
+ # table = dataset.create_table "my_table" do |t|
2980
+ # t.schema do |schema|
2981
+ # schema.integer "my_table_id", mode: :required
2982
+ # schema.string "my_table_data", mode: :required
2983
+ # end
2984
+ # t.range_partitioning_field = "my_table_id"
2985
+ # t.range_partitioning_start = 0
2986
+ # t.range_partitioning_interval = 10
2987
+ # t.range_partitioning_end = 100
2988
+ # end
2989
+ #
2990
+ # @!group Attributes
2991
+ #
2992
+ def range_partitioning_field= field
2993
+ reload! unless resource_full?
2994
+ @gapi.range_partitioning ||= Google::Apis::BigqueryV2::RangePartitioning.new(
2995
+ range: Google::Apis::BigqueryV2::RangePartitioning::Range.new
2996
+ )
2997
+ @gapi.range_partitioning.field = field
2998
+ patch_gapi! :range_partitioning
2999
+ end
3000
+
3001
+ ##
3002
+ # Sets the start of range partitioning, inclusive, for the table. See [Creating and using integer range
3003
+ # partitioned tables](https://cloud.google.com/bigquery/docs/creating-integer-range-partitions).
3004
+ #
3005
+ # You can only set range partitioning when creating a table as in the example below. BigQuery does not allow
3006
+ # you to change partitioning on an existing table.
3007
+ #
3008
+ # See {Table::Updater#range_partitioning_field=}, {Table::Updater#range_partitioning_interval=} and
3009
+ # {Table::Updater#range_partitioning_end=}.
3010
+ #
3011
+ # @param [Integer] range_start The start of range partitioning, inclusive.
3012
+ #
3013
+ # @example
3014
+ # require "google/cloud/bigquery"
3015
+ #
3016
+ # bigquery = Google::Cloud::Bigquery.new
3017
+ # dataset = bigquery.dataset "my_dataset"
3018
+ #
3019
+ # table = dataset.create_table "my_table" do |t|
3020
+ # t.schema do |schema|
3021
+ # schema.integer "my_table_id", mode: :required
3022
+ # schema.string "my_table_data", mode: :required
3023
+ # end
3024
+ # t.range_partitioning_field = "my_table_id"
3025
+ # t.range_partitioning_start = 0
3026
+ # t.range_partitioning_interval = 10
3027
+ # t.range_partitioning_end = 100
3028
+ # end
3029
+ #
3030
+ # @!group Attributes
3031
+ #
3032
+ def range_partitioning_start= range_start
3033
+ reload! unless resource_full?
3034
+ @gapi.range_partitioning ||= Google::Apis::BigqueryV2::RangePartitioning.new(
3035
+ range: Google::Apis::BigqueryV2::RangePartitioning::Range.new
3036
+ )
3037
+ @gapi.range_partitioning.range.start = range_start
3038
+ patch_gapi! :range_partitioning
3039
+ end
3040
+
3041
+ ##
3042
+ # Sets width of each interval for data in range partitions. See [Creating and using integer range partitioned
3043
+ # tables](https://cloud.google.com/bigquery/docs/creating-integer-range-partitions).
3044
+ #
3045
+ # You can only set range partitioning when creating a table as in the example below. BigQuery does not allow
3046
+ # you to change partitioning on an existing table.
3047
+ #
3048
+ # See {Table::Updater#range_partitioning_field=}, {Table::Updater#range_partitioning_start=} and
3049
+ # {Table::Updater#range_partitioning_end=}.
3050
+ #
3051
+ # @param [Integer] range_interval The width of each interval, for data in partitions.
3052
+ #
3053
+ # @example
3054
+ # require "google/cloud/bigquery"
3055
+ #
3056
+ # bigquery = Google::Cloud::Bigquery.new
3057
+ # dataset = bigquery.dataset "my_dataset"
3058
+ #
3059
+ # table = dataset.create_table "my_table" do |t|
3060
+ # t.schema do |schema|
3061
+ # schema.integer "my_table_id", mode: :required
3062
+ # schema.string "my_table_data", mode: :required
3063
+ # end
3064
+ # t.range_partitioning_field = "my_table_id"
3065
+ # t.range_partitioning_start = 0
3066
+ # t.range_partitioning_interval = 10
3067
+ # t.range_partitioning_end = 100
3068
+ # end
3069
+ #
3070
+ # @!group Attributes
3071
+ #
3072
+ def range_partitioning_interval= range_interval
3073
+ reload! unless resource_full?
3074
+ @gapi.range_partitioning ||= Google::Apis::BigqueryV2::RangePartitioning.new(
3075
+ range: Google::Apis::BigqueryV2::RangePartitioning::Range.new
3076
+ )
3077
+ @gapi.range_partitioning.range.interval = range_interval
3078
+ patch_gapi! :range_partitioning
3079
+ end
3080
+
3081
+ ##
3082
+ # Sets the end of range partitioning, exclusive, for the table. See [Creating and using integer range
3083
+ # partitioned tables](https://cloud.google.com/bigquery/docs/creating-integer-range-partitions).
3084
+ #
3085
+ # You can only set range partitioning when creating a table as in the example below. BigQuery does not allow
3086
+ # you to change partitioning on an existing table.
3087
+ #
3088
+ # See {Table::Updater#range_partitioning_start=}, {Table::Updater#range_partitioning_interval=} and
3089
+ # {Table::Updater#range_partitioning_field=}.
3090
+ #
3091
+ # @param [Integer] range_end The end of range partitioning, exclusive.
3092
+ #
3093
+ # @example
3094
+ # require "google/cloud/bigquery"
3095
+ #
3096
+ # bigquery = Google::Cloud::Bigquery.new
3097
+ # dataset = bigquery.dataset "my_dataset"
3098
+ #
3099
+ # table = dataset.create_table "my_table" do |t|
3100
+ # t.schema do |schema|
3101
+ # schema.integer "my_table_id", mode: :required
3102
+ # schema.string "my_table_data", mode: :required
3103
+ # end
3104
+ # t.range_partitioning_field = "my_table_id"
3105
+ # t.range_partitioning_start = 0
3106
+ # t.range_partitioning_interval = 10
3107
+ # t.range_partitioning_end = 100
3108
+ # end
3109
+ #
3110
+ # @!group Attributes
3111
+ #
3112
+ def range_partitioning_end= range_end
3113
+ reload! unless resource_full?
3114
+ @gapi.range_partitioning ||= Google::Apis::BigqueryV2::RangePartitioning.new(
3115
+ range: Google::Apis::BigqueryV2::RangePartitioning::Range.new
3116
+ )
3117
+ @gapi.range_partitioning.range.end = range_end
3118
+ patch_gapi! :range_partitioning
3119
+ end
3120
+
3121
+ ##
3122
+ # Sets the list of fields on which data should be clustered.
2506
3123
  #
2507
3124
  # Only top-level, non-repeated, simple-type fields are supported. When
2508
3125
  # you cluster a table using multiple columns, the order of columns you
2509
3126
  # specify is important. The order of the specified columns determines
2510
3127
  # the sort order of the data.
2511
3128
  #
2512
- # You can only set the clustering fields while creating a table as in
2513
- # the example below. BigQuery does not allow you to change clustering
2514
- # on an existing table.
3129
+ # BigQuery supports clustering for both partitioned and non-partitioned
3130
+ # tables.
2515
3131
  #
2516
- # See {Table#clustering_fields}.
3132
+ # See {Table#clustering_fields} and {Table#clustering_fields=}.
2517
3133
  #
2518
- # @see https://cloud.google.com/bigquery/docs/partitioned-tables
2519
- # Partitioned Tables
2520
3134
  # @see https://cloud.google.com/bigquery/docs/clustered-tables
2521
- # Introduction to Clustered Tables
3135
+ # Introduction to clustered tables
2522
3136
  # @see https://cloud.google.com/bigquery/docs/creating-clustered-tables
2523
- # Creating and Using Clustered Tables
3137
+ # Creating and using clustered tables
2524
3138
  #
2525
3139
  # @param [Array<String>] fields The clustering fields. Only top-level,
2526
3140
  # non-repeated, simple-type fields are supported.
@@ -2530,15 +3144,15 @@ module Google
2530
3144
  #
2531
3145
  # bigquery = Google::Cloud::Bigquery.new
2532
3146
  # dataset = bigquery.dataset "my_dataset"
2533
- # table = dataset.create_table "my_table" do |table|
2534
- # table.time_partitioning_type = "DAY"
2535
- # table.time_partitioning_field = "dob"
2536
- # table.schema do |schema|
3147
+ # table = dataset.create_table "my_table" do |t|
3148
+ # t.schema do |schema|
2537
3149
  # schema.timestamp "dob", mode: :required
2538
3150
  # schema.string "first_name", mode: :required
2539
3151
  # schema.string "last_name", mode: :required
2540
3152
  # end
2541
- # table.clustering_fields = ["last_name", "first_name"]
3153
+ # t.time_partitioning_type = "DAY"
3154
+ # t.time_partitioning_field = "dob"
3155
+ # t.clustering_fields = ["last_name", "first_name"]
2542
3156
  # end
2543
3157
  #
2544
3158
  # @!group Attributes
@@ -2620,13 +3234,19 @@ module Google
2620
3234
  # See {Schema#string}.
2621
3235
  #
2622
3236
  # @param [String] name The field name. The name must contain only
2623
- # letters (a-z, A-Z), numbers (0-9), or underscores (_), and must
3237
+ # letters (`[A-Za-z]`), numbers (`[0-9]`), or underscores (`_`), and must
2624
3238
  # start with a letter or underscore. The maximum length is 128
2625
3239
  # characters.
2626
3240
  # @param [String] description A description of the field.
2627
3241
  # @param [Symbol] mode The field's mode. The possible values are
2628
3242
  # `:nullable`, `:required`, and `:repeated`. The default value is
2629
3243
  # `:nullable`.
3244
+ # @param [Array<String>, String] policy_tags The policy tag list or
3245
+ # single policy tag for the field. Policy tag identifiers are of
3246
+ # the form `projects/*/locations/*/taxonomies/*/policyTags/*`.
3247
+ # At most 1 policy tag is currently allowed.
3248
+ # @param [Integer] max_length The maximum UTF-8 length of strings
3249
+ # allowed in the field.
2630
3250
  #
2631
3251
  # @example
2632
3252
  # require "google/cloud/bigquery"
@@ -2638,8 +3258,8 @@ module Google
2638
3258
  # end
2639
3259
  #
2640
3260
  # @!group Schema
2641
- def string name, description: nil, mode: :nullable
2642
- schema.string name, description: description, mode: mode
3261
+ def string name, description: nil, mode: :nullable, policy_tags: nil, max_length: nil
3262
+ schema.string name, description: description, mode: mode, policy_tags: policy_tags, max_length: max_length
2643
3263
  end
2644
3264
 
2645
3265
  ##
@@ -2648,13 +3268,17 @@ module Google
2648
3268
  # See {Schema#integer}.
2649
3269
  #
2650
3270
  # @param [String] name The field name. The name must contain only
2651
- # letters (a-z, A-Z), numbers (0-9), or underscores (_), and must
3271
+ # letters (`[A-Za-z]`), numbers (`[0-9]`), or underscores (`_`), and must
2652
3272
  # start with a letter or underscore. The maximum length is 128
2653
3273
  # characters.
2654
3274
  # @param [String] description A description of the field.
2655
3275
  # @param [Symbol] mode The field's mode. The possible values are
2656
3276
  # `:nullable`, `:required`, and `:repeated`. The default value is
2657
3277
  # `:nullable`.
3278
+ # @param [Array<String>, String] policy_tags The policy tag list or
3279
+ # single policy tag for the field. Policy tag identifiers are of
3280
+ # the form `projects/*/locations/*/taxonomies/*/policyTags/*`.
3281
+ # At most 1 policy tag is currently allowed.
2658
3282
  #
2659
3283
  # @example
2660
3284
  # require "google/cloud/bigquery"
@@ -2666,8 +3290,8 @@ module Google
2666
3290
  # end
2667
3291
  #
2668
3292
  # @!group Schema
2669
- def integer name, description: nil, mode: :nullable
2670
- schema.integer name, description: description, mode: mode
3293
+ def integer name, description: nil, mode: :nullable, policy_tags: nil
3294
+ schema.integer name, description: description, mode: mode, policy_tags: policy_tags
2671
3295
  end
2672
3296
 
2673
3297
  ##
@@ -2676,13 +3300,17 @@ module Google
2676
3300
  # See {Schema#float}.
2677
3301
  #
2678
3302
  # @param [String] name The field name. The name must contain only
2679
- # letters (a-z, A-Z), numbers (0-9), or underscores (_), and must
3303
+ # letters (`[A-Za-z]`), numbers (`[0-9]`), or underscores (`_`), and must
2680
3304
  # start with a letter or underscore. The maximum length is 128
2681
3305
  # characters.
2682
3306
  # @param [String] description A description of the field.
2683
3307
  # @param [Symbol] mode The field's mode. The possible values are
2684
3308
  # `:nullable`, `:required`, and `:repeated`. The default value is
2685
3309
  # `:nullable`.
3310
+ # @param [Array<String>, String] policy_tags The policy tag list or
3311
+ # single policy tag for the field. Policy tag identifiers are of
3312
+ # the form `projects/*/locations/*/taxonomies/*/policyTags/*`.
3313
+ # At most 1 policy tag is currently allowed.
2686
3314
  #
2687
3315
  # @example
2688
3316
  # require "google/cloud/bigquery"
@@ -2694,25 +3322,48 @@ module Google
2694
3322
  # end
2695
3323
  #
2696
3324
  # @!group Schema
2697
- def float name, description: nil, mode: :nullable
2698
- schema.float name, description: description, mode: mode
3325
+ def float name, description: nil, mode: :nullable, policy_tags: nil
3326
+ schema.float name, description: description, mode: mode, policy_tags: policy_tags
2699
3327
  end
2700
3328
 
2701
3329
  ##
2702
- # Adds a numeric number field to the schema. Numeric is a
2703
- # fixed-precision numeric type with 38 decimal digits, 9 that follow
2704
- # the decimal point.
3330
+ # Adds a numeric number field to the schema. `NUMERIC` is a decimal
3331
+ # type with fixed precision and scale. Precision is the number of
3332
+ # digits that the number contains. Scale is how many of these
3333
+ # digits appear after the decimal point. It supports:
3334
+ #
3335
+ # Precision: 38
3336
+ # Scale: 9
3337
+ # Min: -9.9999999999999999999999999999999999999E+28
3338
+ # Max: 9.9999999999999999999999999999999999999E+28
3339
+ #
3340
+ # This type can represent decimal fractions exactly, and is suitable
3341
+ # for financial calculations.
2705
3342
  #
2706
3343
  # See {Schema#numeric}
2707
3344
  #
2708
3345
  # @param [String] name The field name. The name must contain only
2709
- # letters (a-z, A-Z), numbers (0-9), or underscores (_), and must
3346
+ # letters (`[A-Za-z]`), numbers (`[0-9]`), or underscores (`_`), and must
2710
3347
  # start with a letter or underscore. The maximum length is 128
2711
3348
  # characters.
2712
3349
  # @param [String] description A description of the field.
2713
3350
  # @param [Symbol] mode The field's mode. The possible values are
2714
3351
  # `:nullable`, `:required`, and `:repeated`. The default value is
2715
3352
  # `:nullable`.
3353
+ # @param [Array<String>, String] policy_tags The policy tag list or
3354
+ # single policy tag for the field. Policy tag identifiers are of
3355
+ # the form `projects/*/locations/*/taxonomies/*/policyTags/*`.
3356
+ # At most 1 policy tag is currently allowed.
3357
+ # @param [Integer] precision The precision (maximum number of total
3358
+ # digits) for the field. Acceptable values for precision must be:
3359
+ # `1 ≤ (precision - scale) ≤ 29`. Values for scale must be:
3360
+ # `0 ≤ scale ≤ 9`. If the scale value is set, the precision value
3361
+ # must be set as well.
3362
+ # @param [Integer] scale The scale (maximum number of digits in the
3363
+ # fractional part) for the field. Acceptable values for precision
3364
+ # must be: `1 ≤ (precision - scale) ≤ 29`. Values for scale must
3365
+ # be: `0 ≤ scale ≤ 9`. If the scale value is set, the precision
3366
+ # value must be set as well.
2716
3367
  #
2717
3368
  # @example
2718
3369
  # require "google/cloud/bigquery"
@@ -2724,8 +3375,71 @@ module Google
2724
3375
  # end
2725
3376
  #
2726
3377
  # @!group Schema
2727
- def numeric name, description: nil, mode: :nullable
2728
- schema.numeric name, description: description, mode: mode
3378
+ def numeric name, description: nil, mode: :nullable, policy_tags: nil, precision: nil, scale: nil
3379
+ schema.numeric name,
3380
+ description: description,
3381
+ mode: mode,
3382
+ policy_tags: policy_tags,
3383
+ precision: precision,
3384
+ scale: scale
3385
+ end
3386
+
3387
+ ##
3388
+ # Adds a bignumeric number field to the schema. `BIGNUMERIC` is a
3389
+ # decimal type with fixed precision and scale. Precision is the
3390
+ # number of digits that the number contains. Scale is how many of
3391
+ # these digits appear after the decimal point. It supports:
3392
+ #
3393
+ # Precision: 76.76 (the 77th digit is partial)
3394
+ # Scale: 38
3395
+ # Min: -5.7896044618658097711785492504343953926634992332820282019728792003956564819968E+38
3396
+ # Max: 5.7896044618658097711785492504343953926634992332820282019728792003956564819967E+38
3397
+ #
3398
+ # This type can represent decimal fractions exactly, and is suitable
3399
+ # for financial calculations.
3400
+ #
3401
+ # See {Schema#bignumeric}
3402
+ #
3403
+ # @param [String] name The field name. The name must contain only
3404
+ # letters (`[A-Za-z]`), numbers (`[0-9]`), or underscores (`_`), and must
3405
+ # start with a letter or underscore. The maximum length is 128
3406
+ # characters.
3407
+ # @param [String] description A description of the field.
3408
+ # @param [Symbol] mode The field's mode. The possible values are
3409
+ # `:nullable`, `:required`, and `:repeated`. The default value is
3410
+ # `:nullable`.
3411
+ # @param [Array<String>, String] policy_tags The policy tag list or
3412
+ # single policy tag for the field. Policy tag identifiers are of
3413
+ # the form `projects/*/locations/*/taxonomies/*/policyTags/*`.
3414
+ # At most 1 policy tag is currently allowed.
3415
+ # @param [Integer] precision The precision (maximum number of total
3416
+ # digits) for the field. Acceptable values for precision must be:
3417
+ # `1 ≤ (precision - scale) ≤ 38`. Values for scale must be:
3418
+ # `0 ≤ scale ≤ 38`. If the scale value is set, the precision value
3419
+ # must be set as well.
3420
+ # @param [Integer] scale The scale (maximum number of digits in the
3421
+ # fractional part) for the field. Acceptable values for precision
3422
+ # must be: `1 ≤ (precision - scale) ≤ 38`. Values for scale must
3423
+ # be: `0 ≤ scale ≤ 38`. If the scale value is set, the precision
3424
+ # value must be set as well.
3425
+ #
3426
+ # @example
3427
+ # require "google/cloud/bigquery"
3428
+ #
3429
+ # bigquery = Google::Cloud::Bigquery.new
3430
+ # dataset = bigquery.dataset "my_dataset"
3431
+ # table = dataset.create_table "my_table" do |schema|
3432
+ # schema.bignumeric "total_cost", mode: :required
3433
+ # end
3434
+ #
3435
+ # @!group Schema
3436
+ def bignumeric name, description: nil, mode: :nullable, policy_tags: nil, precision: nil, scale: nil
3437
+ schema.bignumeric name,
3438
+ description: description,
3439
+ mode: mode,
3440
+ policy_tags: policy_tags,
3441
+ precision: precision,
3442
+ scale: scale
2729
3443
  end
2730
3444
 
2731
3445
  ##
@@ -2734,13 +3448,17 @@ module Google
2734
3448
  # See {Schema#boolean}.
2735
3449
  #
2736
3450
  # @param [String] name The field name. The name must contain only
2737
- # letters (a-z, A-Z), numbers (0-9), or underscores (_), and must
3451
+ # letters (`[A-Za-z]`), numbers (`[0-9]`), or underscores (`_`), and must
2738
3452
  # start with a letter or underscore. The maximum length is 128
2739
3453
  # characters.
2740
3454
  # @param [String] description A description of the field.
2741
3455
  # @param [Symbol] mode The field's mode. The possible values are
2742
3456
  # `:nullable`, `:required`, and `:repeated`. The default value is
2743
3457
  # `:nullable`.
3458
+ # @param [Array<String>, String] policy_tags The policy tag list or
3459
+ # single policy tag for the field. Policy tag identifiers are of
3460
+ # the form `projects/*/locations/*/taxonomies/*/policyTags/*`.
3461
+ # At most 1 policy tag is currently allowed.
2744
3462
  #
2745
3463
  # @example
2746
3464
  # require "google/cloud/bigquery"
@@ -2752,8 +3470,8 @@ module Google
2752
3470
  # end
2753
3471
  #
2754
3472
  # @!group Schema
2755
- def boolean name, description: nil, mode: :nullable
2756
- schema.boolean name, description: description, mode: mode
3473
+ def boolean name, description: nil, mode: :nullable, policy_tags: nil
3474
+ schema.boolean name, description: description, mode: mode, policy_tags: policy_tags
2757
3475
  end
2758
3476
 
2759
3477
  ##
@@ -2762,13 +3480,19 @@ module Google
2762
3480
  # See {Schema#bytes}.
2763
3481
  #
2764
3482
  # @param [String] name The field name. The name must contain only
2765
- # letters (a-z, A-Z), numbers (0-9), or underscores (_), and must
3483
+ # letters (`[A-Za-z]`), numbers (`[0-9]`), or underscores (`_`), and must
2766
3484
  # start with a letter or underscore. The maximum length is 128
2767
3485
  # characters.
2768
3486
  # @param [String] description A description of the field.
2769
3487
  # @param [Symbol] mode The field's mode. The possible values are
2770
3488
  # `:nullable`, `:required`, and `:repeated`. The default value is
2771
3489
  # `:nullable`.
3490
+ # @param [Array<String>, String] policy_tags The policy tag list or
3491
+ # single policy tag for the field. Policy tag identifiers are of
3492
+ # the form `projects/*/locations/*/taxonomies/*/policyTags/*`.
3493
+ # At most 1 policy tag is currently allowed.
3494
+ # @param [Integer] max_length The maximum the maximum number of
3495
+ # bytes in the field.
2772
3496
  #
2773
3497
  # @example
2774
3498
  # require "google/cloud/bigquery"
@@ -2780,8 +3504,8 @@ module Google
2780
3504
  # end
2781
3505
  #
2782
3506
  # @!group Schema
2783
- def bytes name, description: nil, mode: :nullable
2784
- schema.bytes name, description: description, mode: mode
3507
+ def bytes name, description: nil, mode: :nullable, policy_tags: nil, max_length: nil
3508
+ schema.bytes name, description: description, mode: mode, policy_tags: policy_tags, max_length: max_length
2785
3509
  end
2786
3510
 
2787
3511
  ##
@@ -2790,13 +3514,17 @@ module Google
2790
3514
  # See {Schema#timestamp}.
2791
3515
  #
2792
3516
  # @param [String] name The field name. The name must contain only
2793
- # letters (a-z, A-Z), numbers (0-9), or underscores (_), and must
3517
+ # letters (`[A-Za-z]`), numbers (`[0-9]`), or underscores (`_`), and must
2794
3518
  # start with a letter or underscore. The maximum length is 128
2795
3519
  # characters.
2796
3520
  # @param [String] description A description of the field.
2797
3521
  # @param [Symbol] mode The field's mode. The possible values are
2798
3522
  # `:nullable`, `:required`, and `:repeated`. The default value is
2799
3523
  # `:nullable`.
3524
+ # @param [Array<String>, String] policy_tags The policy tag list or
3525
+ # single policy tag for the field. Policy tag identifiers are of
3526
+ # the form `projects/*/locations/*/taxonomies/*/policyTags/*`.
3527
+ # At most 1 policy tag is currently allowed.
2800
3528
  #
2801
3529
  # @example
2802
3530
  # require "google/cloud/bigquery"
@@ -2808,8 +3536,8 @@ module Google
2808
3536
  # end
2809
3537
  #
2810
3538
  # @!group Schema
2811
- def timestamp name, description: nil, mode: :nullable
2812
- schema.timestamp name, description: description, mode: mode
3539
+ def timestamp name, description: nil, mode: :nullable, policy_tags: nil
3540
+ schema.timestamp name, description: description, mode: mode, policy_tags: policy_tags
2813
3541
  end
2814
3542
 
2815
3543
  ##
@@ -2818,13 +3546,17 @@ module Google
2818
3546
  # See {Schema#time}.
2819
3547
  #
2820
3548
  # @param [String] name The field name. The name must contain only
2821
- # letters (a-z, A-Z), numbers (0-9), or underscores (_), and must
3549
+ # letters (`[A-Za-z]`), numbers (`[0-9]`), or underscores (`_`), and must
2822
3550
  # start with a letter or underscore. The maximum length is 128
2823
3551
  # characters.
2824
3552
  # @param [String] description A description of the field.
2825
3553
  # @param [Symbol] mode The field's mode. The possible values are
2826
3554
  # `:nullable`, `:required`, and `:repeated`. The default value is
2827
3555
  # `:nullable`.
3556
+ # @param [Array<String>, String] policy_tags The policy tag list or
3557
+ # single policy tag for the field. Policy tag identifiers are of
3558
+ # the form `projects/*/locations/*/taxonomies/*/policyTags/*`.
3559
+ # At most 1 policy tag is currently allowed.
2828
3560
  #
2829
3561
  # @example
2830
3562
  # require "google/cloud/bigquery"
@@ -2836,8 +3568,8 @@ module Google
2836
3568
  # end
2837
3569
  #
2838
3570
  # @!group Schema
2839
- def time name, description: nil, mode: :nullable
2840
- schema.time name, description: description, mode: mode
3571
+ def time name, description: nil, mode: :nullable, policy_tags: nil
3572
+ schema.time name, description: description, mode: mode, policy_tags: policy_tags
2841
3573
  end
2842
3574
 
2843
3575
  ##
@@ -2846,13 +3578,17 @@ module Google
2846
3578
  # See {Schema#datetime}.
2847
3579
  #
2848
3580
  # @param [String] name The field name. The name must contain only
2849
- # letters (a-z, A-Z), numbers (0-9), or underscores (_), and must
3581
+ # letters (`[A-Za-z]`), numbers (`[0-9]`), or underscores (`_`), and must
2850
3582
  # start with a letter or underscore. The maximum length is 128
2851
3583
  # characters.
2852
3584
  # @param [String] description A description of the field.
2853
3585
  # @param [Symbol] mode The field's mode. The possible values are
2854
3586
  # `:nullable`, `:required`, and `:repeated`. The default value is
2855
3587
  # `:nullable`.
3588
+ # @param [Array<String>, String] policy_tags The policy tag list or
3589
+ # single policy tag for the field. Policy tag identifiers are of
3590
+ # the form `projects/*/locations/*/taxonomies/*/policyTags/*`.
3591
+ # At most 1 policy tag is currently allowed.
2856
3592
  #
2857
3593
  # @example
2858
3594
  # require "google/cloud/bigquery"
@@ -2864,8 +3600,8 @@ module Google
2864
3600
  # end
2865
3601
  #
2866
3602
  # @!group Schema
2867
- def datetime name, description: nil, mode: :nullable
2868
- schema.datetime name, description: description, mode: mode
3603
+ def datetime name, description: nil, mode: :nullable, policy_tags: nil
3604
+ schema.datetime name, description: description, mode: mode, policy_tags: policy_tags
2869
3605
  end
2870
3606
 
2871
3607
  ##
@@ -2874,13 +3610,17 @@ module Google
2874
3610
  # See {Schema#date}.
2875
3611
  #
2876
3612
  # @param [String] name The field name. The name must contain only
2877
- # letters (a-z, A-Z), numbers (0-9), or underscores (_), and must
3613
+ # letters (`[A-Za-z]`), numbers (`[0-9]`), or underscores (`_`), and must
2878
3614
  # start with a letter or underscore. The maximum length is 128
2879
3615
  # characters.
2880
3616
  # @param [String] description A description of the field.
2881
3617
  # @param [Symbol] mode The field's mode. The possible values are
2882
3618
  # `:nullable`, `:required`, and `:repeated`. The default value is
2883
3619
  # `:nullable`.
3620
+ # @param [Array<String>, String] policy_tags The policy tag list or
3621
+ # single policy tag for the field. Policy tag identifiers are of
3622
+ # the form `projects/*/locations/*/taxonomies/*/policyTags/*`.
3623
+ # At most 1 policy tag is currently allowed.
2884
3624
  #
2885
3625
  # @example
2886
3626
  # require "google/cloud/bigquery"
@@ -2892,8 +3632,39 @@ module Google
2892
3632
  # end
2893
3633
  #
2894
3634
  # @!group Schema
2895
- def date name, description: nil, mode: :nullable
2896
- schema.date name, description: description, mode: mode
3635
+ def date name, description: nil, mode: :nullable, policy_tags: nil
3636
+ schema.date name, description: description, mode: mode, policy_tags: policy_tags
3637
+ end
3638
+
3639
+ ##
3640
+ # Adds a geography field to the schema.
3641
+ #
3642
+ # @see https://cloud.google.com/bigquery/docs/gis-data Working with BigQuery GIS data
3643
+ #
3644
+ # @param [String] name The field name. The name must contain only
3645
+ # letters (`[A-Za-z]`), numbers (`[0-9]`), or underscores (`_`), and must
3646
+ # start with a letter or underscore. The maximum length is 128
3647
+ # characters.
3648
+ # @param [String] description A description of the field.
3649
+ # @param [Symbol] mode The field's mode. The possible values are
3650
+ # `:nullable`, `:required`, and `:repeated`. The default value is
3651
+ # `:nullable`.
3652
+ # @param [Array<String>, String] policy_tags The policy tag list or
3653
+ # single policy tag for the field. Policy tag identifiers are of
3654
+ # the form `projects/*/locations/*/taxonomies/*/policyTags/*`.
3655
+ # At most 1 policy tag is currently allowed.
3656
+ #
3657
+ # @example
3658
+ # require "google/cloud/bigquery"
3659
+ #
3660
+ # bigquery = Google::Cloud::Bigquery.new
3661
+ # dataset = bigquery.dataset "my_dataset"
3662
+ # table = dataset.create_table "my_table" do |schema|
3663
+ # schema.geography "home", mode: :required
3664
+ # end
3665
+ #
3666
+ def geography name, description: nil, mode: :nullable, policy_tags: nil
3667
+ schema.geography name, description: description, mode: mode, policy_tags: policy_tags
2897
3668
  end
2898
3669
 
2899
3670
  ##
@@ -2906,7 +3677,7 @@ module Google
2906
3677
  # See {Schema#record}.
2907
3678
  #
2908
3679
  # @param [String] name The field name. The name must contain only
2909
- # letters (a-z, A-Z), numbers (0-9), or underscores (_), and must
3680
+ # letters (`[A-Za-z]`), numbers (`[0-9]`), or underscores (`_`), and must
2910
3681
  # start with a letter or underscore. The maximum length is 128
2911
3682
  # characters.
2912
3683
  # @param [String] description A description of the field.
@@ -2935,8 +3706,97 @@ module Google
2935
3706
  schema.record name, description: description, mode: mode, &block
2936
3707
  end
2937
3708
 
3709
+ # rubocop:disable Style/MethodDefParentheses
3710
+
3711
+ ##
3712
+ # @raise [RuntimeError] not implemented
3713
+ def data(*)
3714
+ raise "not implemented in #{self.class}"
3715
+ end
3716
+
3717
+ ##
3718
+ # @raise [RuntimeError] not implemented
3719
+ def copy_job(*)
3720
+ raise "not implemented in #{self.class}"
3721
+ end
3722
+
3723
+ ##
3724
+ # @raise [RuntimeError] not implemented
3725
+ def copy(*)
3726
+ raise "not implemented in #{self.class}"
3727
+ end
3728
+
3729
+ ##
3730
+ # @raise [RuntimeError] not implemented
3731
+ def extract_job(*)
3732
+ raise "not implemented in #{self.class}"
3733
+ end
3734
+
3735
+ ##
3736
+ # @raise [RuntimeError] not implemented
3737
+ def extract(*)
3738
+ raise "not implemented in #{self.class}"
3739
+ end
3740
+
3741
+ ##
3742
+ # @raise [RuntimeError] not implemented
3743
+ def load_job(*)
3744
+ raise "not implemented in #{self.class}"
3745
+ end
3746
+
3747
+ ##
3748
+ # @raise [RuntimeError] not implemented
3749
+ def load(*)
3750
+ raise "not implemented in #{self.class}"
3751
+ end
3752
+
3753
+ ##
3754
+ # @raise [RuntimeError] not implemented
3755
+ def insert(*)
3756
+ raise "not implemented in #{self.class}"
3757
+ end
3758
+
2938
3759
  ##
2939
- # Make sure any access changes are saved
3760
+ # @raise [RuntimeError] not implemented
3761
+ def insert_async(*)
3762
+ raise "not implemented in #{self.class}"
3763
+ end
3764
+
3765
+ ##
3766
+ # @raise [RuntimeError] not implemented
3767
+ def delete
3768
+ raise "not implemented in #{self.class}"
3769
+ end
3770
+
3771
+ ##
3772
+ # @raise [RuntimeError] not implemented
3773
+ def query_job(*)
3774
+ raise "not implemented in #{self.class}"
3775
+ end
3776
+
3777
+ ##
3778
+ # @raise [RuntimeError] not implemented
3779
+ def query(*)
3780
+ raise "not implemented in #{self.class}"
3781
+ end
3782
+
3783
+ ##
3784
+ # @raise [RuntimeError] not implemented
3785
+ def external(*)
3786
+ raise "not implemented in #{self.class}"
3787
+ end
3788
+
3789
+ ##
3790
+ # @raise [RuntimeError] not implemented
3791
+ def reload!
3792
+ raise "not implemented in #{self.class}"
3793
+ end
3794
+ alias refresh! reload!
3795
+
3796
+ # rubocop:enable Style/MethodDefParentheses
3797
+
3798
+ ##
3799
+ # @private Make sure any access changes are saved
2940
3800
  def check_for_mutated_schema!
2941
3801
  return if @schema.nil?
2942
3802
  return unless @schema.changed?
@@ -2944,6 +3804,8 @@ module Google
2944
3804
  patch_gapi! :schema
2945
3805
  end
2946
3806
 
3807
+ ##
3808
+ # @private
2947
3809
  def to_gapi
2948
3810
  check_for_mutated_schema!
2949
3811
  @gapi