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.
- 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?
|