google-cloud-bigquery 1.25.0 → 1.30.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -124,12 +124,12 @@ module Google
124
124
  # puts routine.routine_id
125
125
  # end
126
126
  #
127
- def all request_limit: nil
127
+ def all request_limit: nil, &block
128
128
  request_limit = request_limit.to_i if request_limit
129
129
  return enum_for :all, request_limit: request_limit unless block_given?
130
130
  results = self
131
131
  loop do
132
- results.each { |r| yield r }
132
+ results.each(&block)
133
133
  if request_limit
134
134
  request_limit -= 1
135
135
  break if request_limit.negative?
@@ -332,9 +332,18 @@ module Google
332
332
  end
333
333
 
334
334
  ##
335
- # Adds a numeric number field to the schema. Numeric is a
336
- # fixed-precision numeric type with 38 decimal digits, 9 that follow the
337
- # decimal point.
335
+ # Adds a numeric number field to the schema. `NUMERIC` is a decimal
336
+ # type with fixed precision and scale. Precision is the number of
337
+ # digits that the number contains. Scale is how many of these
338
+ # digits appear after the decimal point. It supports:
339
+ #
340
+ # Precision: 38
341
+ # Scale: 9
342
+ # Min: -9.9999999999999999999999999999999999999E+28
343
+ # Max: 9.9999999999999999999999999999999999999E+28
344
+ #
345
+ # This type can represent decimal fractions exactly, and is suitable
346
+ # for financial calculations.
338
347
  #
339
348
  # @param [String] name The field name. The name must contain only
340
349
  # letters (a-z, A-Z), numbers (0-9), or underscores (_), and must
@@ -349,6 +358,33 @@ module Google
349
358
  add_field name, :numeric, description: description, mode: mode
350
359
  end
351
360
 
361
+ ##
362
+ # Adds a bignumeric number field to the schema. `BIGNUMERIC` is a
363
+ # decimal type with fixed precision and scale. Precision is the
364
+ # number of digits that the number contains. Scale is how many of
365
+ # these digits appear after the decimal point. It supports:
366
+ #
367
+ # Precision: 76.76 (the 77th digit is partial)
368
+ # Scale: 38
369
+ # Min: -5.7896044618658097711785492504343953926634992332820282019728792003956564819968E+38
370
+ # Max: 5.7896044618658097711785492504343953926634992332820282019728792003956564819967E+38
371
+ #
372
+ # This type can represent decimal fractions exactly, and is suitable
373
+ # for financial calculations.
374
+ #
375
+ # @param [String] name The field name. The name must contain only
376
+ # letters (a-z, A-Z), numbers (0-9), or underscores (_), and must
377
+ # start with a letter or underscore. The maximum length is 128
378
+ # characters.
379
+ # @param [String] description A description of the field.
380
+ # @param [Symbol] mode The field's mode. The possible values are
381
+ # `:nullable`, `:required`, and `:repeated`. The default value is
382
+ # `:nullable`.
383
+ #
384
+ def bignumeric name, description: nil, mode: :nullable
385
+ add_field name, :bignumeric, description: description, mode: mode
386
+ end
387
+
352
388
  ##
353
389
  # Adds a boolean field to the schema.
354
390
  #
@@ -40,8 +40,8 @@ module Google
40
40
  MODES = ["NULLABLE", "REQUIRED", "REPEATED"].freeze
41
41
 
42
42
  # @private
43
- TYPES = ["STRING", "INTEGER", "INT64", "FLOAT", "FLOAT64", "NUMERIC", "BOOLEAN", "BOOL", "BYTES", "TIMESTAMP",
44
- "TIME", "DATETIME", "DATE", "RECORD", "STRUCT"].freeze
43
+ TYPES = ["STRING", "INTEGER", "INT64", "FLOAT", "FLOAT64", "NUMERIC", "BIGNUMERIC", "BOOLEAN", "BOOL",
44
+ "BYTES", "TIMESTAMP", "TIME", "DATETIME", "DATE", "RECORD", "STRUCT"].freeze
45
45
 
46
46
  ##
47
47
  # The name of the field.
@@ -72,10 +72,10 @@ module Google
72
72
  #
73
73
  # @return [String] The field data type. Possible values include
74
74
  # `STRING`, `BYTES`, `INTEGER`, `INT64` (same as `INTEGER`),
75
- # `FLOAT`, `FLOAT64` (same as `FLOAT`), `NUMERIC`, `BOOLEAN`, `BOOL`
76
- # (same as `BOOLEAN`), `TIMESTAMP`, `DATE`, `TIME`, `DATETIME`,
77
- # `RECORD` (where `RECORD` indicates that the field contains a
78
- # nested schema) or `STRUCT` (same as `RECORD`).
75
+ # `FLOAT`, `FLOAT64` (same as `FLOAT`), `NUMERIC`, `BIGNUMERIC`,
76
+ # `BOOLEAN`, `BOOL` (same as `BOOLEAN`), `TIMESTAMP`, `DATE`,
77
+ # `TIME`, `DATETIME`, `RECORD` (where `RECORD` indicates that the
78
+ # field contains a nested schema) or `STRUCT` (same as `RECORD`).
79
79
  #
80
80
  def type
81
81
  @gapi.type
@@ -86,10 +86,10 @@ module Google
86
86
  #
87
87
  # @param [String] new_type The data type. Possible values include
88
88
  # `STRING`, `BYTES`, `INTEGER`, `INT64` (same as `INTEGER`),
89
- # `FLOAT`, `FLOAT64` (same as `FLOAT`), `NUMERIC`, `BOOLEAN`, `BOOL`
90
- # (same as `BOOLEAN`), `TIMESTAMP`, `DATE`, `TIME`, `DATETIME`,
91
- # `RECORD` (where `RECORD` indicates that the field contains a
92
- # nested schema) or `STRUCT` (same as `RECORD`).
89
+ # `FLOAT`, `FLOAT64` (same as `FLOAT`), `NUMERIC`, `BIGNUMERIC`,
90
+ # `BOOLEAN`, `BOOL` (same as `BOOLEAN`), `TIMESTAMP`, `DATE`,
91
+ # `TIME`, `DATETIME`, `RECORD` (where `RECORD` indicates that the
92
+ # field contains a nested schema) or `STRUCT` (same as `RECORD`).
93
93
  #
94
94
  def type= new_type
95
95
  @gapi.update! type: verify_type(new_type)
@@ -199,6 +199,15 @@ module Google
199
199
  type == "NUMERIC"
200
200
  end
201
201
 
202
+ ##
203
+ # Checks if the type of the field is `BIGNUMERIC`.
204
+ #
205
+ # @return [Boolean] `true` when `BIGNUMERIC`, `false` otherwise.
206
+ #
207
+ def bignumeric?
208
+ type == "BIGNUMERIC"
209
+ end
210
+
202
211
  ##
203
212
  # Checks if the type of the field is `BOOLEAN`.
204
213
  #
@@ -299,6 +308,7 @@ module Google
299
308
  # * `:INT64`
300
309
  # * `:FLOAT64`
301
310
  # * `:NUMERIC`
311
+ # * `:BIGNUMERIC`
302
312
  # * `:STRING`
303
313
  # * `:DATETIME`
304
314
  # * `:DATE`
@@ -394,9 +404,18 @@ module Google
394
404
  end
395
405
 
396
406
  ##
397
- # Adds a numeric number field to the schema. Numeric is a
398
- # fixed-precision numeric type with 38 decimal digits, 9 that follow
399
- # the decimal point.
407
+ # Adds a numeric number field to the schema. `NUMERIC` is a decimal
408
+ # type with fixed precision and scale. Precision is the number of
409
+ # digits that the number contains. Scale is how many of these
410
+ # digits appear after the decimal point. It supports:
411
+ #
412
+ # Precision: 38
413
+ # Scale: 9
414
+ # Min: -9.9999999999999999999999999999999999999E+28
415
+ # Max: 9.9999999999999999999999999999999999999E+28
416
+ #
417
+ # This type can represent decimal fractions exactly, and is suitable
418
+ # for financial calculations.
400
419
  #
401
420
  # This can only be called on fields that are of type `RECORD`.
402
421
  #
@@ -415,6 +434,37 @@ module Google
415
434
  add_field name, :numeric, description: description, mode: mode
416
435
  end
417
436
 
437
+ ##
438
+ # Adds a bignumeric number field to the schema. `BIGNUMERIC` is a
439
+ # decimal type with fixed precision and scale. Precision is the
440
+ # number of digits that the number contains. Scale is how many of
441
+ # these digits appear after the decimal point. It supports:
442
+ #
443
+ # Precision: 76.76 (the 77th digit is partial)
444
+ # Scale: 38
445
+ # Min: -5.7896044618658097711785492504343953926634992332820282019728792003956564819968E+38
446
+ # Max: 5.7896044618658097711785492504343953926634992332820282019728792003956564819967E+38
447
+ #
448
+ # This type can represent decimal fractions exactly, and is suitable
449
+ # for financial calculations.
450
+ #
451
+ # This can only be called on fields that are of type `RECORD`.
452
+ #
453
+ # @param [String] name The field name. The name must contain only
454
+ # letters (a-z, A-Z), numbers (0-9), or underscores (_), and must
455
+ # start with a letter or underscore. The maximum length is 128
456
+ # characters.
457
+ # @param [String] description A description of the field.
458
+ # @param [Symbol] mode The field's mode. The possible values are
459
+ # `:nullable`, `:required`, and `:repeated`. The default value is
460
+ # `:nullable`.
461
+ #
462
+ def bignumeric name, description: nil, mode: :nullable
463
+ record_check!
464
+
465
+ add_field name, :bignumeric, description: description, mode: mode
466
+ end
467
+
418
468
  ##
419
469
  # Adds a boolean field to the nested schema of a record field.
420
470
  #
@@ -483,7 +483,7 @@ module Google
483
483
  table_id: m["tbl"]
484
484
  }.delete_if { |_, v| v.nil? }
485
485
  str_table_ref_hash = default_ref.to_h.merge str_table_ref_hash
486
- ref = Google::Apis::BigqueryV2::TableReference.new str_table_ref_hash
486
+ ref = Google::Apis::BigqueryV2::TableReference.new(**str_table_ref_hash)
487
487
  validate_table_ref ref
488
488
  ref
489
489
  end
@@ -554,9 +554,9 @@ module Google
554
554
  nil
555
555
  end
556
556
 
557
- def execute backoff: nil
557
+ def execute backoff: nil, &block
558
558
  if backoff
559
- Backoff.new(retries: retries).execute { yield }
559
+ Backoff.new(retries: retries).execute(&block)
560
560
  else
561
561
  yield
562
562
  end
@@ -590,22 +590,20 @@ module Google
590
590
  def execute
591
591
  current_retries = 0
592
592
  loop do
593
- begin
594
- return yield
595
- rescue Google::Apis::Error => e
596
- raise e unless retry? e.body, current_retries
597
-
598
- @backoff.call current_retries
599
- current_retries += 1
600
- end
593
+ return yield
594
+ rescue Google::Apis::Error => e
595
+ raise e unless retry? e.body, current_retries
596
+
597
+ @backoff.call current_retries
598
+ current_retries += 1
601
599
  end
602
600
  end
603
601
 
604
602
  protected
605
603
 
606
604
  def retry? result, current_retries #:nodoc:
607
- if current_retries < @retries
608
- return true if retry_error_reason? result
605
+ if current_retries < @retries && retry_error_reason?(result)
606
+ return true
609
607
  end
610
608
  false
611
609
  end
@@ -273,6 +273,17 @@ module Google
273
273
  type_kind == "NUMERIC".freeze
274
274
  end
275
275
 
276
+ ##
277
+ # Checks if the {#type_kind} of the field is `BIGNUMERIC`.
278
+ #
279
+ # @return [Boolean] `true` when `BIGNUMERIC`, `false` otherwise.
280
+ #
281
+ # @!group Helpers
282
+ #
283
+ def bignumeric?
284
+ type_kind == "BIGNUMERIC".freeze
285
+ end
286
+
276
287
  ##
277
288
  # Checks if the {#type_kind} of the field is `BOOL`.
278
289
  #
@@ -401,11 +412,12 @@ module Google
401
412
  # @private New Google::Apis::BigqueryV2::StandardSqlDataType from a String or StandardSql::DataType object.
402
413
  def self.gapi_from_string_or_data_type data_type
403
414
  return if data_type.nil?
404
- if data_type.is_a? StandardSql::DataType
415
+ case data_type
416
+ when StandardSql::DataType
405
417
  data_type.to_gapi
406
- elsif data_type.is_a? Hash
418
+ when Hash
407
419
  data_type
408
- elsif data_type.is_a?(String) || data_type.is_a?(Symbol)
420
+ when String, Symbol
409
421
  Google::Apis::BigqueryV2::StandardSqlDataType.new type_kind: data_type.to_s.upcase
410
422
  else
411
423
  raise ArgumentError, "Unable to convert #{data_type} to Google::Apis::BigqueryV2::StandardSqlDataType"
@@ -37,16 +37,16 @@ module Google
37
37
  # repeated fields.
38
38
  #
39
39
  # The Table class can also represent a
40
- # [view](https://cloud.google.com/bigquery/docs/views), which is a virtual
41
- # table defined by a SQL query. BigQuery's views are logical views, not
42
- # materialized views, which means that the query that defines the view is
43
- # re-executed every time the view is queried. Queries are billed according
44
- # to the total amount of data in all table fields referenced directly or
45
- # indirectly by the top-level query. (See {#view?}, {#query}, {#query=},
46
- # 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}).
47
45
  #
48
46
  # @see https://cloud.google.com/bigquery/docs/loading-data#loading_denormalized_nested_and_repeated_data
49
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
50
50
  #
51
51
  # @example
52
52
  # require "google/cloud/bigquery"
@@ -77,7 +77,7 @@ module Google
77
77
  # }
78
78
  # table.insert row
79
79
  #
80
- # @example Creating a BigQuery view:
80
+ # @example Creating a logical view:
81
81
  # require "google/cloud/bigquery"
82
82
  #
83
83
  # bigquery = Google::Cloud::Bigquery.new
@@ -86,6 +86,15 @@ module Google
86
86
  # "SELECT name, age FROM `my_project.my_dataset.my_table`"
87
87
  # view.view? # true
88
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
+ #
89
98
  class Table
90
99
  ##
91
100
  # @private The Service object.
@@ -386,8 +395,8 @@ module Google
386
395
  # {#resource_full?}), the full representation will be retrieved before
387
396
  # the update to comply with ETag-based optimistic concurrency control.
388
397
  #
389
- # @param [Integer] expiration An expiration time, in seconds,
390
- # for data in time partitions.
398
+ # @param [Integer, nil] expiration An expiration time, in seconds,
399
+ # for data in time partitions, , or `nil` to indicate no expiration time.
391
400
  #
392
401
  # @example
393
402
  # require "google/cloud/bigquery"
@@ -407,8 +416,9 @@ module Google
407
416
  #
408
417
  def time_partitioning_expiration= expiration
409
418
  reload! unless resource_full?
419
+ expiration_ms = expiration * 1000 if expiration
410
420
  @gapi.time_partitioning ||= Google::Apis::BigqueryV2::TimePartitioning.new
411
- @gapi.time_partitioning.expiration_ms = expiration * 1000
421
+ @gapi.time_partitioning.expiration_ms = expiration_ms
412
422
  patch_gapi! :time_partitioning
413
423
  end
414
424
 
@@ -726,7 +736,7 @@ module Google
726
736
  end
727
737
 
728
738
  ##
729
- # Checks if the table's type is "TABLE".
739
+ # Checks if the table's type is `TABLE`.
730
740
  #
731
741
  # @return [Boolean, nil] `true` when the type is `TABLE`, `false`
732
742
  # otherwise, if the object is a resource (see {#resource?}); `nil` if
@@ -740,8 +750,10 @@ module Google
740
750
  end
741
751
 
742
752
  ##
743
- # Checks if the table's type is "VIEW", indicating that the table
744
- # represents a BigQuery view. See {Dataset#create_view}.
753
+ # Checks if the table's type is `VIEW`, indicating that the table
754
+ # represents a BigQuery logical view. See {Dataset#create_view}.
755
+ #
756
+ # @see https://cloud.google.com/bigquery/docs/views Creating views
745
757
  #
746
758
  # @return [Boolean, nil] `true` when the type is `VIEW`, `false`
747
759
  # otherwise, if the object is a resource (see {#resource?}); `nil` if
@@ -755,7 +767,25 @@ module Google
755
767
  end
756
768
 
757
769
  ##
758
- # Checks if the table's type is "EXTERNAL", indicating that the table
770
+ # Checks if the table's type is `MATERIALIZED_VIEW`, indicating that
771
+ # the table represents a BigQuery materialized view.
772
+ # See {Dataset#create_materialized_view}.
773
+ #
774
+ # @see https://cloud.google.com/bigquery/docs/materialized-views-intro Introduction to materialized views
775
+ #
776
+ # @return [Boolean, nil] `true` when the type is `MATERIALIZED_VIEW`,
777
+ # `false` otherwise, if the object is a resource (see {#resource?});
778
+ # `nil` if the object is a reference (see {#reference?}).
779
+ #
780
+ # @!group Attributes
781
+ #
782
+ def materialized_view?
783
+ return nil if reference?
784
+ @gapi.type == "MATERIALIZED_VIEW"
785
+ end
786
+
787
+ ##
788
+ # Checks if the table's type is `EXTERNAL`, indicating that the table
759
789
  # represents an External Data Source. See {#external?} and
760
790
  # {External::DataSource}.
761
791
  #
@@ -1138,21 +1168,24 @@ module Google
1138
1168
  end
1139
1169
 
1140
1170
  ##
1141
- # The query that executes each time the view is loaded.
1171
+ # The query that defines the view or materialized view. See {#view?} and
1172
+ # {#materialized_view?}.
1142
1173
  #
1143
- # @return [String] The query that defines the view.
1174
+ # @return [String, nil] The query that defines the view or materialized_view;
1175
+ # or `nil` if not a view or materialized view.
1144
1176
  #
1145
1177
  # @!group Attributes
1146
1178
  #
1147
1179
  def query
1148
- @gapi.view&.query
1180
+ view? ? @gapi.view&.query : @gapi.materialized_view&.query
1149
1181
  end
1150
1182
 
1151
1183
  ##
1152
- # Updates the query that executes each time the view is loaded.
1184
+ # Updates the query that defines the view. (See {#view?}.) Not supported
1185
+ # for materialized views.
1153
1186
  #
1154
- # This sets the query using standard SQL. To specify legacy SQL or to
1155
- # use user-defined function resources use (#set_query) instead.
1187
+ # This method sets the query using standard SQL. To specify legacy SQL or
1188
+ # to use user-defined function resources for a view, use (#set_query) instead.
1156
1189
  #
1157
1190
  # @see https://cloud.google.com/bigquery/query-reference BigQuery Query
1158
1191
  # Reference
@@ -1167,7 +1200,7 @@ module Google
1167
1200
  # view = dataset.table "my_view"
1168
1201
  #
1169
1202
  # view.query = "SELECT first_name FROM " \
1170
- # "`my_project.my_dataset.my_table`"
1203
+ # "`my_project.my_dataset.my_table`"
1171
1204
  #
1172
1205
  # @!group Lifecycle
1173
1206
  #
@@ -1176,12 +1209,12 @@ module Google
1176
1209
  end
1177
1210
 
1178
1211
  ##
1179
- # Updates the query that executes each time the view is loaded. Allows
1180
- # setting of standard vs. legacy SQL and user-defined function
1181
- # resources.
1212
+ # Updates the query that defines the view. (See {#view?}.) Not supported for
1213
+ # materialized views.
1182
1214
  #
1183
- # @see https://cloud.google.com/bigquery/query-reference BigQuery Query
1184
- # Reference
1215
+ # Allows setting of standard vs. legacy SQL and user-defined function resources.
1216
+ #
1217
+ # @see https://cloud.google.com/bigquery/query-reference BigQuery Query Reference
1185
1218
  #
1186
1219
  # @param [String] query The query that defines the view.
1187
1220
  # @param [Boolean] standard_sql Specifies whether to use BigQuery's
@@ -1193,11 +1226,12 @@ module Google
1193
1226
  # SQL](https://cloud.google.com/bigquery/docs/reference/legacy-sql)
1194
1227
  # dialect. Optional. The default value is false.
1195
1228
  # @param [Array<String>, String] udfs User-defined function resources
1196
- # used in a legacy SQL query. May be either a code resource to load from
1197
- # a Google Cloud Storage URI (`gs://bucket/path`), or an inline resource
1198
- # that contains code for a user-defined function (UDF). Providing an
1199
- # inline code resource is equivalent to providing a URI for a file
1200
- # containing the same code.
1229
+ # used in a legacy SQL query. Optional.
1230
+ #
1231
+ # May be either a code resource to load from a Google Cloud Storage URI
1232
+ # (`gs://bucket/path`), or an inline resource that contains code for a
1233
+ # user-defined function (UDF). Providing an inline code resource is equivalent
1234
+ # to providing a URI for a file containing the same code.
1201
1235
  #
1202
1236
  # This parameter is used for defining User Defined Function (UDF)
1203
1237
  # resources only when using legacy SQL. Users of standard SQL should
@@ -1208,7 +1242,7 @@ module Google
1208
1242
  # standard SQL - Differences in user-defined JavaScript
1209
1243
  # functions](https://cloud.google.com/bigquery/docs/reference/standard-sql/migrating-from-legacy-sql#differences_in_user-defined_javascript_functions)
1210
1244
  #
1211
- # @example
1245
+ # @example Update a view:
1212
1246
  # require "google/cloud/bigquery"
1213
1247
  #
1214
1248
  # bigquery = Google::Cloud::Bigquery.new
@@ -1216,12 +1250,13 @@ module Google
1216
1250
  # view = dataset.table "my_view"
1217
1251
  #
1218
1252
  # view.set_query "SELECT first_name FROM " \
1219
- # "`my_project.my_dataset.my_table`",
1253
+ # "`my_project.my_dataset.my_table`",
1220
1254
  # standard_sql: true
1221
1255
  #
1222
1256
  # @!group Lifecycle
1223
1257
  #
1224
1258
  def set_query query, standard_sql: nil, legacy_sql: nil, udfs: nil
1259
+ raise "Updating the query is not supported for Table type: #{@gapi.type}" unless view?
1225
1260
  use_legacy_sql = Convert.resolve_legacy_sql standard_sql, legacy_sql
1226
1261
  @gapi.view = Google::Apis::BigqueryV2::ViewDefinition.new(
1227
1262
  query: query,
@@ -1232,26 +1267,28 @@ module Google
1232
1267
  end
1233
1268
 
1234
1269
  ##
1235
- # Checks if the view's query is using legacy sql.
1270
+ # Checks if the view's query is using legacy sql. See {#view?}.
1236
1271
  #
1237
- # @return [Boolean] `true` when legacy sql is used, `false` otherwise.
1272
+ # @return [Boolean] `true` when legacy sql is used, `false` otherwise; or `nil` if not a logical view.
1238
1273
  #
1239
1274
  # @!group Attributes
1240
1275
  #
1241
1276
  def query_legacy_sql?
1277
+ return nil unless @gapi.view
1242
1278
  val = @gapi.view.use_legacy_sql
1243
1279
  return true if val.nil?
1244
1280
  val
1245
1281
  end
1246
1282
 
1247
1283
  ##
1248
- # Checks if the view's query is using standard sql.
1284
+ # Checks if the view's query is using standard sql. See {#view?}.
1249
1285
  #
1250
1286
  # @return [Boolean] `true` when standard sql is used, `false` otherwise.
1251
1287
  #
1252
1288
  # @!group Attributes
1253
1289
  #
1254
1290
  def query_standard_sql?
1291
+ return nil unless @gapi.view
1255
1292
  !query_legacy_sql?
1256
1293
  end
1257
1294
 
@@ -1263,18 +1300,92 @@ module Google
1263
1300
  # equivalent to providing a URI for a file containing the same code. See
1264
1301
  # [User-Defined
1265
1302
  # Functions](https://cloud.google.com/bigquery/docs/reference/standard-sql/user-defined-functions).
1303
+ # See {#view?}.
1266
1304
  #
1267
- # @return [Array<String>] An array containing Google Cloud Storage URIs
1268
- # and/or inline source code.
1305
+ # @return [Array<String>, nil] An array containing Google Cloud Storage URIs
1306
+ # and/or inline source code, or `nil` if not a logical view.
1269
1307
  #
1270
1308
  # @!group Attributes
1271
1309
  #
1272
1310
  def query_udfs
1311
+ return nil unless @gapi.view
1273
1312
  udfs_gapi = @gapi.view.user_defined_function_resources
1274
1313
  return [] if udfs_gapi.nil?
1275
1314
  Array(udfs_gapi).map { |udf| udf.inline_code || udf.resource_uri }
1276
1315
  end
1277
1316
 
1317
+ ##
1318
+ # Whether automatic refresh of the materialized view is enabled. When true,
1319
+ # the materialized view is updated when the base table is updated. The default
1320
+ # value is true. See {#materialized_view?}.
1321
+ #
1322
+ # @return [Boolean, nil] `true` when automatic refresh is enabled, `false` otherwise;
1323
+ # or `nil` if not a materialized view.
1324
+ #
1325
+ # @!group Attributes
1326
+ #
1327
+ def enable_refresh?
1328
+ return nil unless @gapi.materialized_view
1329
+ val = @gapi.materialized_view.enable_refresh
1330
+ return true if val.nil?
1331
+ val
1332
+ end
1333
+
1334
+ ##
1335
+ # Sets whether automatic refresh of the materialized view is enabled. When true,
1336
+ # the materialized view is updated when the base table is updated. See {#materialized_view?}.
1337
+ #
1338
+ # @param [Boolean] new_enable_refresh `true` when automatic refresh is enabled, `false` otherwise.
1339
+ #
1340
+ # @!group Attributes
1341
+ #
1342
+ def enable_refresh= new_enable_refresh
1343
+ @gapi.materialized_view = Google::Apis::BigqueryV2::MaterializedViewDefinition.new(
1344
+ enable_refresh: new_enable_refresh
1345
+ )
1346
+ patch_gapi! :materialized_view
1347
+ end
1348
+
1349
+ ##
1350
+ # The time when the materialized view was last modified.
1351
+ # See {#materialized_view?}.
1352
+ #
1353
+ # @return [Time, nil] The time, or `nil` if not present or not a materialized view.
1354
+ #
1355
+ # @!group Attributes
1356
+ #
1357
+ def last_refresh_time
1358
+ Convert.millis_to_time @gapi.materialized_view&.last_refresh_time
1359
+ end
1360
+
1361
+ ##
1362
+ # The maximum frequency in milliseconds at which the materialized view will be refreshed.
1363
+ # See {#materialized_view?}.
1364
+ #
1365
+ # @return [Integer, nil] The maximum frequency in milliseconds;
1366
+ # or `nil` if not a materialized view.
1367
+ #
1368
+ # @!group Attributes
1369
+ #
1370
+ def refresh_interval_ms
1371
+ @gapi.materialized_view&.refresh_interval_ms
1372
+ end
1373
+
1374
+ ##
1375
+ # Sets the maximum frequency at which the materialized view will be refreshed.
1376
+ # See {#materialized_view?}.
1377
+ #
1378
+ # @param [Integer] new_refresh_interval_ms The maximum frequency in milliseconds.
1379
+ #
1380
+ # @!group Attributes
1381
+ #
1382
+ def refresh_interval_ms= new_refresh_interval_ms
1383
+ @gapi.materialized_view = Google::Apis::BigqueryV2::MaterializedViewDefinition.new(
1384
+ refresh_interval_ms: new_refresh_interval_ms
1385
+ )
1386
+ patch_gapi! :materialized_view
1387
+ end
1388
+
1278
1389
  ##
1279
1390
  # Gets the Cloud IAM access control policy for the table. The latest policy will be read from the service. See
1280
1391
  # also {#update_policy}.
@@ -2195,6 +2306,21 @@ module Google
2195
2306
  # need to complete a load operation before the data can appear in query
2196
2307
  # results.
2197
2308
  #
2309
+ # Simple Ruby types are generally accepted per JSON rules, along with the following support for BigQuery's more
2310
+ # complex types:
2311
+ #
2312
+ # | BigQuery | Ruby | Notes |
2313
+ # |--------------|--------------------------------------|----------------------------------------------------|
2314
+ # | `NUMERIC` | `BigDecimal` | `BigDecimal` values will be rounded to scale 9. |
2315
+ # | `BIGNUMERIC` | `String` | Pass as `String` to avoid rounding to scale 9. |
2316
+ # | `DATETIME` | `DateTime` | `DATETIME` does not support time zone. |
2317
+ # | `DATE` | `Date` | |
2318
+ # | `TIMESTAMP` | `Time` | |
2319
+ # | `TIME` | `Google::Cloud::BigQuery::Time` | |
2320
+ # | `BYTES` | `File`, `IO`, `StringIO`, or similar | |
2321
+ # | `ARRAY` | `Array` | Nested arrays, `nil` values are not supported. |
2322
+ # | `STRUCT` | `Hash` | Hash keys may be strings or symbols. |
2323
+ #
2198
2324
  # Because BigQuery's streaming API is designed for high insertion rates,
2199
2325
  # modifications to the underlying table metadata are eventually
2200
2326
  # consistent when interacting with the streaming system. In most cases
@@ -2208,7 +2334,10 @@ module Google
2208
2334
  # BigQuery Troubleshooting: Metadata errors for streaming inserts
2209
2335
  #
2210
2336
  # @param [Hash, Array<Hash>] rows A hash object or array of hash objects
2211
- # containing the data. Required.
2337
+ # containing the data. Required. `BigDecimal` values will be rounded to
2338
+ # scale 9 to conform with the BigQuery `NUMERIC` data type. To avoid
2339
+ # rounding `BIGNUMERIC` type values with scale greater than 9, use `String`
2340
+ # instead of `BigDecimal`.
2212
2341
  # @param [Array<String|Symbol>, Symbol] insert_ids A unique ID for each row. BigQuery uses this property to
2213
2342
  # detect duplicate insertion requests on a best-effort basis. For more information, see [data
2214
2343
  # consistency](https://cloud.google.com/bigquery/streaming-data-into-bigquery#dataconsistency). Optional. If
@@ -2251,6 +2380,19 @@ module Google
2251
2380
  # ]
2252
2381
  # table.insert rows
2253
2382
  #
2383
+ # @example Pass `BIGNUMERIC` value as a string to avoid rounding to scale 9 in the conversion from `BigDecimal`:
2384
+ # require "google/cloud/bigquery"
2385
+ #
2386
+ # bigquery = Google::Cloud::Bigquery.new
2387
+ # dataset = bigquery.dataset "my_dataset"
2388
+ # table = dataset.table "my_table"
2389
+ #
2390
+ # row = {
2391
+ # "my_numeric" => BigDecimal("123456798.987654321"),
2392
+ # "my_bignumeric" => "123456798.98765432100001" # BigDecimal would be rounded, use String instead!
2393
+ # }
2394
+ # table.insert row
2395
+ #
2254
2396
  # @!group Data
2255
2397
  #
2256
2398
  def insert rows, insert_ids: nil, skip_invalid: nil, ignore_unknown: nil
@@ -2264,8 +2406,12 @@ module Google
2264
2406
  end
2265
2407
 
2266
2408
  ensure_service!
2267
- options = { skip_invalid: skip_invalid, ignore_unknown: ignore_unknown, insert_ids: insert_ids }
2268
- gapi = service.insert_tabledata dataset_id, table_id, rows, options
2409
+ gapi = service.insert_tabledata dataset_id,
2410
+ table_id,
2411
+ rows,
2412
+ skip_invalid: skip_invalid,
2413
+ ignore_unknown: ignore_unknown,
2414
+ insert_ids: insert_ids
2269
2415
  InsertResponse.from_gapi rows, gapi
2270
2416
  end
2271
2417
 
@@ -2564,7 +2710,7 @@ module Google
2564
2710
  return if attributes.empty?
2565
2711
  ensure_service!
2566
2712
  patch_args = Hash[attributes.map { |attr| [attr, @gapi.send(attr)] }]
2567
- patch_gapi = Google::Apis::BigqueryV2::Table.new patch_args
2713
+ patch_gapi = Google::Apis::BigqueryV2::Table.new(**patch_args)
2568
2714
  patch_gapi.etag = etag if etag
2569
2715
  @gapi = service.patch_table dataset_id, table_id, patch_gapi
2570
2716
 
@@ -2690,12 +2836,11 @@ module Google
2690
2836
 
2691
2837
  def load_local_or_uri file, updater
2692
2838
  job_gapi = updater.to_gapi
2693
- job = if local_file? file
2694
- load_local file, job_gapi
2695
- else
2696
- load_storage file, job_gapi
2697
- end
2698
- job
2839
+ if local_file? file
2840
+ load_local file, job_gapi
2841
+ else
2842
+ load_storage file, job_gapi
2843
+ end
2699
2844
  end
2700
2845
 
2701
2846
  def storage_url? files
@@ -2748,6 +2893,7 @@ module Google
2748
2893
  ##
2749
2894
  # @private Create an Updater object.
2750
2895
  def initialize gapi
2896
+ super()
2751
2897
  @updates = []
2752
2898
  @gapi = gapi
2753
2899
  @schema = nil
@@ -3115,9 +3261,18 @@ module Google
3115
3261
  end
3116
3262
 
3117
3263
  ##
3118
- # Adds a numeric number field to the schema. Numeric is a
3119
- # fixed-precision numeric type with 38 decimal digits, 9 that follow
3120
- # the decimal point.
3264
+ # Adds a numeric number field to the schema. `NUMERIC` is a decimal
3265
+ # type with fixed precision and scale. Precision is the number of
3266
+ # digits that the number contains. Scale is how many of these
3267
+ # digits appear after the decimal point. It supports:
3268
+ #
3269
+ # Precision: 38
3270
+ # Scale: 9
3271
+ # Min: -9.9999999999999999999999999999999999999E+28
3272
+ # Max: 9.9999999999999999999999999999999999999E+28
3273
+ #
3274
+ # This type can represent decimal fractions exactly, and is suitable
3275
+ # for financial calculations.
3121
3276
  #
3122
3277
  # See {Schema#numeric}
3123
3278
  #
@@ -3144,6 +3299,45 @@ module Google
3144
3299
  schema.numeric name, description: description, mode: mode
3145
3300
  end
3146
3301
 
3302
+ ##
3303
+ # Adds a bignumeric number field to the schema. `BIGNUMERIC` is a
3304
+ # decimal type with fixed precision and scale. Precision is the
3305
+ # number of digits that the number contains. Scale is how many of
3306
+ # these digits appear after the decimal point. It supports:
3307
+ #
3308
+ # Precision: 76.76 (the 77th digit is partial)
3309
+ # Scale: 38
3310
+ # Min: -5.7896044618658097711785492504343953926634992332820282019728792003956564819968E+38
3311
+ # Max: 5.7896044618658097711785492504343953926634992332820282019728792003956564819967E+38
3312
+ #
3313
+ # This type can represent decimal fractions exactly, and is suitable
3314
+ # for financial calculations.
3315
+ #
3316
+ # See {Schema#bignumeric}
3317
+ #
3318
+ # @param [String] name The field name. The name must contain only
3319
+ # letters (a-z, A-Z), numbers (0-9), or underscores (_), and must
3320
+ # start with a letter or underscore. The maximum length is 128
3321
+ # characters.
3322
+ # @param [String] description A description of the field.
3323
+ # @param [Symbol] mode The field's mode. The possible values are
3324
+ # `:nullable`, `:required`, and `:repeated`. The default value is
3325
+ # `:nullable`.
3326
+ #
3327
+ # @example
3328
+ # require "google/cloud/bigquery"
3329
+ #
3330
+ # bigquery = Google::Cloud::Bigquery.new
3331
+ # dataset = bigquery.dataset "my_dataset"
3332
+ # table = dataset.create_table "my_table" do |schema|
3333
+ # schema.bignumeric "total_cost", mode: :required
3334
+ # end
3335
+ #
3336
+ # @!group Schema
3337
+ def bignumeric name, description: nil, mode: :nullable
3338
+ schema.bignumeric name, description: description, mode: mode
3339
+ end
3340
+
3147
3341
  ##
3148
3342
  # Adds a boolean field to the schema.
3149
3343
  #