google-cloud-bigquery 1.26.0 → 1.29.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -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.
@@ -726,7 +735,7 @@ module Google
726
735
  end
727
736
 
728
737
  ##
729
- # Checks if the table's type is "TABLE".
738
+ # Checks if the table's type is `TABLE`.
730
739
  #
731
740
  # @return [Boolean, nil] `true` when the type is `TABLE`, `false`
732
741
  # otherwise, if the object is a resource (see {#resource?}); `nil` if
@@ -740,8 +749,10 @@ module Google
740
749
  end
741
750
 
742
751
  ##
743
- # Checks if the table's type is "VIEW", indicating that the table
744
- # represents a BigQuery view. See {Dataset#create_view}.
752
+ # Checks if the table's type is `VIEW`, indicating that the table
753
+ # represents a BigQuery logical view. See {Dataset#create_view}.
754
+ #
755
+ # @see https://cloud.google.com/bigquery/docs/views Creating views
745
756
  #
746
757
  # @return [Boolean, nil] `true` when the type is `VIEW`, `false`
747
758
  # otherwise, if the object is a resource (see {#resource?}); `nil` if
@@ -755,7 +766,25 @@ module Google
755
766
  end
756
767
 
757
768
  ##
758
- # Checks if the table's type is "EXTERNAL", indicating that the table
769
+ # Checks if the table's type is `MATERIALIZED_VIEW`, indicating that
770
+ # the table represents a BigQuery materialized view.
771
+ # See {Dataset#create_materialized_view}.
772
+ #
773
+ # @see https://cloud.google.com/bigquery/docs/materialized-views-intro Introduction to materialized views
774
+ #
775
+ # @return [Boolean, nil] `true` when the type is `MATERIALIZED_VIEW`,
776
+ # `false` otherwise, if the object is a resource (see {#resource?});
777
+ # `nil` if the object is a reference (see {#reference?}).
778
+ #
779
+ # @!group Attributes
780
+ #
781
+ def materialized_view?
782
+ return nil if reference?
783
+ @gapi.type == "MATERIALIZED_VIEW"
784
+ end
785
+
786
+ ##
787
+ # Checks if the table's type is `EXTERNAL`, indicating that the table
759
788
  # represents an External Data Source. See {#external?} and
760
789
  # {External::DataSource}.
761
790
  #
@@ -1138,21 +1167,24 @@ module Google
1138
1167
  end
1139
1168
 
1140
1169
  ##
1141
- # The query that executes each time the view is loaded.
1170
+ # The query that defines the view or materialized view. See {#view?} and
1171
+ # {#materialized_view?}.
1142
1172
  #
1143
- # @return [String] The query that defines the view.
1173
+ # @return [String, nil] The query that defines the view or materialized_view;
1174
+ # or `nil` if not a view or materialized view.
1144
1175
  #
1145
1176
  # @!group Attributes
1146
1177
  #
1147
1178
  def query
1148
- @gapi.view&.query
1179
+ view? ? @gapi.view&.query : @gapi.materialized_view&.query
1149
1180
  end
1150
1181
 
1151
1182
  ##
1152
- # Updates the query that executes each time the view is loaded.
1183
+ # Updates the query that defines the view. (See {#view?}.) Not supported
1184
+ # for materialized views.
1153
1185
  #
1154
- # This sets the query using standard SQL. To specify legacy SQL or to
1155
- # use user-defined function resources use (#set_query) instead.
1186
+ # This method sets the query using standard SQL. To specify legacy SQL or
1187
+ # to use user-defined function resources for a view, use (#set_query) instead.
1156
1188
  #
1157
1189
  # @see https://cloud.google.com/bigquery/query-reference BigQuery Query
1158
1190
  # Reference
@@ -1167,7 +1199,7 @@ module Google
1167
1199
  # view = dataset.table "my_view"
1168
1200
  #
1169
1201
  # view.query = "SELECT first_name FROM " \
1170
- # "`my_project.my_dataset.my_table`"
1202
+ # "`my_project.my_dataset.my_table`"
1171
1203
  #
1172
1204
  # @!group Lifecycle
1173
1205
  #
@@ -1176,12 +1208,12 @@ module Google
1176
1208
  end
1177
1209
 
1178
1210
  ##
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.
1211
+ # Updates the query that defines the view. (See {#view?}.) Not supported for
1212
+ # materialized views.
1182
1213
  #
1183
- # @see https://cloud.google.com/bigquery/query-reference BigQuery Query
1184
- # Reference
1214
+ # Allows setting of standard vs. legacy SQL and user-defined function resources.
1215
+ #
1216
+ # @see https://cloud.google.com/bigquery/query-reference BigQuery Query Reference
1185
1217
  #
1186
1218
  # @param [String] query The query that defines the view.
1187
1219
  # @param [Boolean] standard_sql Specifies whether to use BigQuery's
@@ -1193,11 +1225,12 @@ module Google
1193
1225
  # SQL](https://cloud.google.com/bigquery/docs/reference/legacy-sql)
1194
1226
  # dialect. Optional. The default value is false.
1195
1227
  # @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.
1228
+ # used in a legacy SQL query. Optional.
1229
+ #
1230
+ # May be either a code resource to load from a Google Cloud Storage URI
1231
+ # (`gs://bucket/path`), or an inline resource that contains code for a
1232
+ # user-defined function (UDF). Providing an inline code resource is equivalent
1233
+ # to providing a URI for a file containing the same code.
1201
1234
  #
1202
1235
  # This parameter is used for defining User Defined Function (UDF)
1203
1236
  # resources only when using legacy SQL. Users of standard SQL should
@@ -1208,7 +1241,7 @@ module Google
1208
1241
  # standard SQL - Differences in user-defined JavaScript
1209
1242
  # functions](https://cloud.google.com/bigquery/docs/reference/standard-sql/migrating-from-legacy-sql#differences_in_user-defined_javascript_functions)
1210
1243
  #
1211
- # @example
1244
+ # @example Update a view:
1212
1245
  # require "google/cloud/bigquery"
1213
1246
  #
1214
1247
  # bigquery = Google::Cloud::Bigquery.new
@@ -1216,12 +1249,13 @@ module Google
1216
1249
  # view = dataset.table "my_view"
1217
1250
  #
1218
1251
  # view.set_query "SELECT first_name FROM " \
1219
- # "`my_project.my_dataset.my_table`",
1252
+ # "`my_project.my_dataset.my_table`",
1220
1253
  # standard_sql: true
1221
1254
  #
1222
1255
  # @!group Lifecycle
1223
1256
  #
1224
1257
  def set_query query, standard_sql: nil, legacy_sql: nil, udfs: nil
1258
+ raise "Updating the query is not supported for Table type: #{@gapi.type}" unless view?
1225
1259
  use_legacy_sql = Convert.resolve_legacy_sql standard_sql, legacy_sql
1226
1260
  @gapi.view = Google::Apis::BigqueryV2::ViewDefinition.new(
1227
1261
  query: query,
@@ -1232,26 +1266,28 @@ module Google
1232
1266
  end
1233
1267
 
1234
1268
  ##
1235
- # Checks if the view's query is using legacy sql.
1269
+ # Checks if the view's query is using legacy sql. See {#view?}.
1236
1270
  #
1237
- # @return [Boolean] `true` when legacy sql is used, `false` otherwise.
1271
+ # @return [Boolean] `true` when legacy sql is used, `false` otherwise; or `nil` if not a logical view.
1238
1272
  #
1239
1273
  # @!group Attributes
1240
1274
  #
1241
1275
  def query_legacy_sql?
1276
+ return nil unless @gapi.view
1242
1277
  val = @gapi.view.use_legacy_sql
1243
1278
  return true if val.nil?
1244
1279
  val
1245
1280
  end
1246
1281
 
1247
1282
  ##
1248
- # Checks if the view's query is using standard sql.
1283
+ # Checks if the view's query is using standard sql. See {#view?}.
1249
1284
  #
1250
1285
  # @return [Boolean] `true` when standard sql is used, `false` otherwise.
1251
1286
  #
1252
1287
  # @!group Attributes
1253
1288
  #
1254
1289
  def query_standard_sql?
1290
+ return nil unless @gapi.view
1255
1291
  !query_legacy_sql?
1256
1292
  end
1257
1293
 
@@ -1263,18 +1299,92 @@ module Google
1263
1299
  # equivalent to providing a URI for a file containing the same code. See
1264
1300
  # [User-Defined
1265
1301
  # Functions](https://cloud.google.com/bigquery/docs/reference/standard-sql/user-defined-functions).
1302
+ # See {#view?}.
1266
1303
  #
1267
- # @return [Array<String>] An array containing Google Cloud Storage URIs
1268
- # and/or inline source code.
1304
+ # @return [Array<String>, nil] An array containing Google Cloud Storage URIs
1305
+ # and/or inline source code, or `nil` if not a logical view.
1269
1306
  #
1270
1307
  # @!group Attributes
1271
1308
  #
1272
1309
  def query_udfs
1310
+ return nil unless @gapi.view
1273
1311
  udfs_gapi = @gapi.view.user_defined_function_resources
1274
1312
  return [] if udfs_gapi.nil?
1275
1313
  Array(udfs_gapi).map { |udf| udf.inline_code || udf.resource_uri }
1276
1314
  end
1277
1315
 
1316
+ ##
1317
+ # Whether automatic refresh of the materialized view is enabled. When true,
1318
+ # the materialized view is updated when the base table is updated. The default
1319
+ # value is true. See {#materialized_view?}.
1320
+ #
1321
+ # @return [Boolean, nil] `true` when automatic refresh is enabled, `false` otherwise;
1322
+ # or `nil` if not a materialized view.
1323
+ #
1324
+ # @!group Attributes
1325
+ #
1326
+ def enable_refresh?
1327
+ return nil unless @gapi.materialized_view
1328
+ val = @gapi.materialized_view.enable_refresh
1329
+ return true if val.nil?
1330
+ val
1331
+ end
1332
+
1333
+ ##
1334
+ # Sets whether automatic refresh of the materialized view is enabled. When true,
1335
+ # the materialized view is updated when the base table is updated. See {#materialized_view?}.
1336
+ #
1337
+ # @param [Boolean] new_enable_refresh `true` when automatic refresh is enabled, `false` otherwise.
1338
+ #
1339
+ # @!group Attributes
1340
+ #
1341
+ def enable_refresh= new_enable_refresh
1342
+ @gapi.materialized_view = Google::Apis::BigqueryV2::MaterializedViewDefinition.new(
1343
+ enable_refresh: new_enable_refresh
1344
+ )
1345
+ patch_gapi! :materialized_view
1346
+ end
1347
+
1348
+ ##
1349
+ # The time when the materialized view was last modified.
1350
+ # See {#materialized_view?}.
1351
+ #
1352
+ # @return [Time, nil] The time, or `nil` if not present or not a materialized view.
1353
+ #
1354
+ # @!group Attributes
1355
+ #
1356
+ def last_refresh_time
1357
+ Convert.millis_to_time @gapi.materialized_view&.last_refresh_time
1358
+ end
1359
+
1360
+ ##
1361
+ # The maximum frequency in milliseconds at which the materialized view will be refreshed.
1362
+ # See {#materialized_view?}.
1363
+ #
1364
+ # @return [Integer, nil] The maximum frequency in milliseconds;
1365
+ # or `nil` if not a materialized view.
1366
+ #
1367
+ # @!group Attributes
1368
+ #
1369
+ def refresh_interval_ms
1370
+ @gapi.materialized_view&.refresh_interval_ms
1371
+ end
1372
+
1373
+ ##
1374
+ # Sets the maximum frequency at which the materialized view will be refreshed.
1375
+ # See {#materialized_view?}.
1376
+ #
1377
+ # @param [Integer] new_refresh_interval_ms The maximum frequency in milliseconds.
1378
+ #
1379
+ # @!group Attributes
1380
+ #
1381
+ def refresh_interval_ms= new_refresh_interval_ms
1382
+ @gapi.materialized_view = Google::Apis::BigqueryV2::MaterializedViewDefinition.new(
1383
+ refresh_interval_ms: new_refresh_interval_ms
1384
+ )
1385
+ patch_gapi! :materialized_view
1386
+ end
1387
+
1278
1388
  ##
1279
1389
  # Gets the Cloud IAM access control policy for the table. The latest policy will be read from the service. See
1280
1390
  # also {#update_policy}.
@@ -2264,8 +2374,12 @@ module Google
2264
2374
  end
2265
2375
 
2266
2376
  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
2377
+ gapi = service.insert_tabledata dataset_id,
2378
+ table_id,
2379
+ rows,
2380
+ skip_invalid: skip_invalid,
2381
+ ignore_unknown: ignore_unknown,
2382
+ insert_ids: insert_ids
2269
2383
  InsertResponse.from_gapi rows, gapi
2270
2384
  end
2271
2385
 
@@ -2564,7 +2678,7 @@ module Google
2564
2678
  return if attributes.empty?
2565
2679
  ensure_service!
2566
2680
  patch_args = Hash[attributes.map { |attr| [attr, @gapi.send(attr)] }]
2567
- patch_gapi = Google::Apis::BigqueryV2::Table.new patch_args
2681
+ patch_gapi = Google::Apis::BigqueryV2::Table.new(**patch_args)
2568
2682
  patch_gapi.etag = etag if etag
2569
2683
  @gapi = service.patch_table dataset_id, table_id, patch_gapi
2570
2684
 
@@ -2690,12 +2804,11 @@ module Google
2690
2804
 
2691
2805
  def load_local_or_uri file, updater
2692
2806
  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
2807
+ if local_file? file
2808
+ load_local file, job_gapi
2809
+ else
2810
+ load_storage file, job_gapi
2811
+ end
2699
2812
  end
2700
2813
 
2701
2814
  def storage_url? files
@@ -2748,6 +2861,7 @@ module Google
2748
2861
  ##
2749
2862
  # @private Create an Updater object.
2750
2863
  def initialize gapi
2864
+ super()
2751
2865
  @updates = []
2752
2866
  @gapi = gapi
2753
2867
  @schema = nil
@@ -64,7 +64,10 @@ module Google
64
64
  class AsyncInserter
65
65
  include MonitorMixin
66
66
 
67
- attr_reader :max_bytes, :max_rows, :interval, :threads
67
+ attr_reader :max_bytes
68
+ attr_reader :max_rows
69
+ attr_reader :interval
70
+ attr_reader :threads
68
71
  ##
69
72
  # @private Implementation accessors
70
73
  attr_reader :table, :batch
@@ -265,18 +268,19 @@ module Google
265
268
  json_rows = @batch.json_rows
266
269
  insert_ids = @batch.insert_ids
267
270
  Concurrent::Future.new executor: @thread_pool do
268
- begin
269
- raise ArgumentError, "No rows provided" if json_rows.empty?
270
- options = { skip_invalid: @skip_invalid, ignore_unknown: @ignore_unknown, insert_ids: insert_ids }
271
- insert_resp = @table.service.insert_tabledata_json_rows(
272
- @table.dataset_id, @table.table_id, json_rows, options
273
- )
274
- result = Result.new InsertResponse.from_gapi(orig_rows, insert_resp)
275
- rescue StandardError => e
276
- result = Result.new nil, e
277
- ensure
278
- @callback&.call result
279
- end
271
+ raise ArgumentError, "No rows provided" if json_rows.empty?
272
+ insert_resp = @table.service.insert_tabledata_json_rows @table.dataset_id,
273
+ @table.table_id,
274
+ json_rows,
275
+ skip_invalid: @skip_invalid,
276
+ ignore_unknown: @ignore_unknown,
277
+ insert_ids: insert_ids
278
+
279
+ result = Result.new InsertResponse.from_gapi(orig_rows, insert_resp)
280
+ rescue StandardError => e
281
+ result = Result.new nil, e
282
+ ensure
283
+ @callback&.call result
280
284
  end.execute
281
285
 
282
286
  @batch = nil
@@ -286,7 +290,11 @@ module Google
286
290
  ##
287
291
  # @private
288
292
  class Batch
289
- attr_reader :max_bytes, :max_rows, :rows, :json_rows, :insert_ids
293
+ attr_reader :max_bytes
294
+ attr_reader :max_rows
295
+ attr_reader :rows
296
+ attr_reader :json_rows
297
+ attr_reader :insert_ids
290
298
 
291
299
  def initialize max_bytes: 10_000_000, max_rows: 500
292
300
  @max_bytes = max_bytes
@@ -395,7 +403,8 @@ module Google
395
403
  @error = error
396
404
  end
397
405
 
398
- attr_reader :insert_response, :error
406
+ attr_reader :insert_response
407
+ attr_reader :error
399
408
 
400
409
  ##
401
410
  # Checks if an error is present, meaning that the insert operation
@@ -130,12 +130,12 @@ module Google
130
130
  # puts table.name
131
131
  # end
132
132
  #
133
- def all request_limit: nil
133
+ def all request_limit: nil, &block
134
134
  request_limit = request_limit.to_i if request_limit
135
135
  return enum_for :all, request_limit: request_limit unless block_given?
136
136
  results = self
137
137
  loop do
138
- results.each { |r| yield r }
138
+ results.each(&block)
139
139
  if request_limit
140
140
  request_limit -= 1
141
141
  break if request_limit.negative?
@@ -16,7 +16,7 @@
16
16
  module Google
17
17
  module Cloud
18
18
  module Bigquery
19
- VERSION = "1.26.0".freeze
19
+ VERSION = "1.29.0".freeze
20
20
  end
21
21
  end
22
22
  end