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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +31 -0
- data/CONTRIBUTING.md +1 -1
- data/LOGGING.md +1 -1
- data/lib/google/cloud/bigquery/convert.rb +0 -4
- data/lib/google/cloud/bigquery/copy_job.rb +1 -0
- data/lib/google/cloud/bigquery/data.rb +2 -2
- data/lib/google/cloud/bigquery/dataset.rb +106 -21
- data/lib/google/cloud/bigquery/dataset/access.rb +3 -3
- data/lib/google/cloud/bigquery/dataset/list.rb +2 -2
- data/lib/google/cloud/bigquery/extract_job.rb +4 -2
- data/lib/google/cloud/bigquery/job.rb +43 -3
- data/lib/google/cloud/bigquery/job/list.rb +4 -4
- data/lib/google/cloud/bigquery/load_job.rb +1 -0
- data/lib/google/cloud/bigquery/model/list.rb +2 -2
- data/lib/google/cloud/bigquery/policy.rb +2 -1
- data/lib/google/cloud/bigquery/project.rb +3 -3
- data/lib/google/cloud/bigquery/project/list.rb +2 -2
- data/lib/google/cloud/bigquery/query_job.rb +24 -12
- data/lib/google/cloud/bigquery/routine.rb +128 -9
- data/lib/google/cloud/bigquery/routine/list.rb +2 -2
- data/lib/google/cloud/bigquery/service.rb +11 -13
- data/lib/google/cloud/bigquery/standard_sql.rb +4 -3
- data/lib/google/cloud/bigquery/table.rb +159 -45
- data/lib/google/cloud/bigquery/table/async_inserter.rb +24 -15
- data/lib/google/cloud/bigquery/table/list.rb +2 -2
- data/lib/google/cloud/bigquery/version.rb +1 -1
- metadata +12 -12
@@ -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
|
42
|
-
# materialized views,
|
43
|
-
#
|
44
|
-
#
|
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
|
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
|
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
|
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
|
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
|
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
|
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
|
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
|
-
#
|
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
|
1180
|
-
#
|
1181
|
-
# resources.
|
1211
|
+
# Updates the query that defines the view. (See {#view?}.) Not supported for
|
1212
|
+
# materialized views.
|
1182
1213
|
#
|
1183
|
-
#
|
1184
|
-
#
|
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.
|
1197
|
-
#
|
1198
|
-
#
|
1199
|
-
#
|
1200
|
-
#
|
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
|
-
#
|
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
|
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
|
-
|
2268
|
-
|
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
|
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
|
-
|
2694
|
-
|
2695
|
-
|
2696
|
-
|
2697
|
-
|
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
|
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
|
-
|
269
|
-
|
270
|
-
|
271
|
-
|
272
|
-
|
273
|
-
|
274
|
-
|
275
|
-
|
276
|
-
|
277
|
-
|
278
|
-
|
279
|
-
|
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
|
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
|
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
|
138
|
+
results.each(&block)
|
139
139
|
if request_limit
|
140
140
|
request_limit -= 1
|
141
141
|
break if request_limit.negative?
|