google-cloud-bigquery 1.26.0 → 1.29.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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