google-cloud-bigquery 0.29.0 → 0.30.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 +5 -5
- data/README.md +2 -2
- data/lib/google-cloud-bigquery.rb +12 -10
- data/lib/google/cloud/bigquery.rb +57 -17
- data/lib/google/cloud/bigquery/credentials.rb +31 -5
- data/lib/google/cloud/bigquery/data.rb +12 -12
- data/lib/google/cloud/bigquery/dataset.rb +281 -38
- data/lib/google/cloud/bigquery/dataset/access.rb +6 -6
- data/lib/google/cloud/bigquery/job.rb +1 -1
- data/lib/google/cloud/bigquery/project.rb +22 -7
- data/lib/google/cloud/bigquery/query_job.rb +6 -4
- data/lib/google/cloud/bigquery/service.rb +7 -5
- data/lib/google/cloud/bigquery/table.rb +487 -62
- data/lib/google/cloud/bigquery/table/async_inserter.rb +180 -5
- data/lib/google/cloud/bigquery/version.rb +1 -1
- metadata +21 -8
- data/lib/google/cloud/bigquery/view.rb +0 -739
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 8c5eccec9f2f10fd5b5637a91516d68bee4f8b7f2e7e8e58a6b213afe89e56fe
|
4
|
+
data.tar.gz: 55d8b9b98cd3e52bb7c6111feaa9811487c61a4b2868126c54af7f9dec5fde1b
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 6377e7a4cef9081723669ae08913786a1cdb37d65b0ae922dfc0a930e664eec451f95802e3f95f96eefcf24a5bf2eff23b00102bdd1f449a076018b7fc4d61cc
|
7
|
+
data.tar.gz: 9a4e917438c795ba7baa5692c5c6b70de0593b047e575f6113f112221d5c9925348e17ed6564d9361a872d6ca9918ac12df421a217e1d6e1096e98649829e447
|
data/README.md
CHANGED
@@ -24,8 +24,8 @@ Instructions and configuration options are covered in the [Authentication Guide]
|
|
24
24
|
require "google/cloud/bigquery"
|
25
25
|
|
26
26
|
bigquery = Google::Cloud::Bigquery.new(
|
27
|
-
|
28
|
-
|
27
|
+
project_id: "my-todo-project",
|
28
|
+
credentials: "/path/to/keyfile.json"
|
29
29
|
)
|
30
30
|
|
31
31
|
# Create a new table to archive todos
|
@@ -13,9 +13,9 @@
|
|
13
13
|
# limitations under the License.
|
14
14
|
|
15
15
|
##
|
16
|
-
# This file is here to be autorequired by bundler, so that the
|
17
|
-
# #bigquery methods can be available,
|
18
|
-
# be loaded until required and used.
|
16
|
+
# This file is here to be autorequired by bundler, so that the
|
17
|
+
# Google::Cloud.bigquery and Google::Cloud#bigquery methods can be available,
|
18
|
+
# but the library and all dependencies won't be loaded until required and used.
|
19
19
|
|
20
20
|
|
21
21
|
gem "google-cloud-core"
|
@@ -75,10 +75,11 @@ module Google
|
|
75
75
|
# For more information on connecting to Google Cloud see the [Authentication
|
76
76
|
# Guide](https://googlecloudplatform.github.io/google-cloud-ruby/#/docs/guides/authentication).
|
77
77
|
#
|
78
|
-
# @param [String]
|
79
|
-
# the default project for the credentials is used.
|
80
|
-
# @param [String, Hash]
|
81
|
-
#
|
78
|
+
# @param [String] project_id Identifier for a BigQuery project. If not
|
79
|
+
# present, the default project for the credentials is used.
|
80
|
+
# @param [String, Hash, Google::Auth::Credentials] credentials The path to
|
81
|
+
# the keyfile as a String, the contents of the keyfile as a Hash, or a
|
82
|
+
# Google::Auth::Credentials object. (See {Bigquery::Credentials})
|
82
83
|
# @param [String, Array<String>] scope The OAuth 2.0 scopes controlling the
|
83
84
|
# set of resources and operations that the connection can access. See
|
84
85
|
# [Using OAuth 2.0 to Access Google
|
@@ -100,10 +101,11 @@ module Google
|
|
100
101
|
# dataset = bigquery.dataset "my_dataset"
|
101
102
|
# table = dataset.table "my_table"
|
102
103
|
#
|
103
|
-
def self.bigquery
|
104
|
-
timeout: nil
|
104
|
+
def self.bigquery project_id = nil, credentials = nil, scope: nil,
|
105
|
+
retries: nil, timeout: nil
|
105
106
|
require "google/cloud/bigquery"
|
106
|
-
Google::Cloud::Bigquery.new
|
107
|
+
Google::Cloud::Bigquery.new project_id: project_id,
|
108
|
+
credentials: credentials,
|
107
109
|
scope: scope, retries: retries,
|
108
110
|
timeout: timeout
|
109
111
|
end
|
@@ -347,6 +347,45 @@ module Google
|
|
347
347
|
# table.insert rows
|
348
348
|
# ```
|
349
349
|
#
|
350
|
+
# To avoid making RPCs (network requests) to retrieve the dataset and table
|
351
|
+
# resources when streaming records, pass the `skip_lookup` option. This
|
352
|
+
# creates local objects without verifying that the resources exist on the
|
353
|
+
# BigQuery service.
|
354
|
+
#
|
355
|
+
# ```ruby
|
356
|
+
# require "google/cloud/bigquery"
|
357
|
+
#
|
358
|
+
# bigquery = Google::Cloud::Bigquery.new
|
359
|
+
# dataset = bigquery.dataset "my_dataset", skip_lookup: true
|
360
|
+
# table = dataset.table "people", skip_lookup: true
|
361
|
+
#
|
362
|
+
# rows = [
|
363
|
+
# {
|
364
|
+
# "first_name" => "Anna",
|
365
|
+
# "cities_lived" => [
|
366
|
+
# {
|
367
|
+
# "place" => "Stockholm",
|
368
|
+
# "number_of_years" => 2
|
369
|
+
# }
|
370
|
+
# ]
|
371
|
+
# },
|
372
|
+
# {
|
373
|
+
# "first_name" => "Bob",
|
374
|
+
# "cities_lived" => [
|
375
|
+
# {
|
376
|
+
# "place" => "Seattle",
|
377
|
+
# "number_of_years" => 5
|
378
|
+
# },
|
379
|
+
# {
|
380
|
+
# "place" => "Austin",
|
381
|
+
# "number_of_years" => 6
|
382
|
+
# }
|
383
|
+
# ]
|
384
|
+
# }
|
385
|
+
# ]
|
386
|
+
# table.insert rows
|
387
|
+
# ```
|
388
|
+
#
|
350
389
|
# There are some trade-offs involved with streaming, so be sure to read the
|
351
390
|
# discussion of data consistency in [Streaming Data Into
|
352
391
|
# BigQuery](https://cloud.google.com/bigquery/streaming-data-into-bigquery).
|
@@ -455,10 +494,11 @@ module Google
|
|
455
494
|
# [Authentication
|
456
495
|
# Guide](https://googlecloudplatform.github.io/google-cloud-ruby/#/docs/guides/authentication).
|
457
496
|
#
|
458
|
-
# @param [String]
|
497
|
+
# @param [String] project_id Identifier for a BigQuery project. If not
|
459
498
|
# present, the default project for the credentials is used.
|
460
|
-
# @param [String, Hash]
|
461
|
-
#
|
499
|
+
# @param [String, Hash, Google::Auth::Credentials] credentials The path to
|
500
|
+
# the keyfile as a String, the contents of the keyfile as a Hash, or a
|
501
|
+
# Google::Auth::Credentials object. (See {Bigquery::Credentials})
|
462
502
|
# @param [String, Array<String>] scope The OAuth 2.0 scopes controlling
|
463
503
|
# the set of resources and operations that the connection can access.
|
464
504
|
# See # [Using OAuth 2.0 to Access Google #
|
@@ -470,6 +510,9 @@ module Google
|
|
470
510
|
# @param [Integer] retries Number of times to retry requests on server
|
471
511
|
# error. The default value is `5`. Optional.
|
472
512
|
# @param [Integer] timeout Default timeout to use in requests. Optional.
|
513
|
+
# @param [String] project Alias for the `project_id` argument. Deprecated.
|
514
|
+
# @param [String] keyfile Alias for the `credentials` argument.
|
515
|
+
# Deprecated.
|
473
516
|
#
|
474
517
|
# @return [Google::Cloud::Bigquery::Project]
|
475
518
|
#
|
@@ -480,23 +523,20 @@ module Google
|
|
480
523
|
# dataset = bigquery.dataset "my_dataset"
|
481
524
|
# table = dataset.table "my_table"
|
482
525
|
#
|
483
|
-
def self.new
|
484
|
-
timeout: nil
|
485
|
-
|
486
|
-
|
487
|
-
fail ArgumentError, "
|
526
|
+
def self.new project_id: nil, credentials: nil, scope: nil, retries: nil,
|
527
|
+
timeout: nil, project: nil, keyfile: nil
|
528
|
+
project_id ||= (project || Bigquery::Project.default_project_id)
|
529
|
+
project_id = project_id.to_s # Always cast to a string
|
530
|
+
fail ArgumentError, "project_id is missing" if project_id.empty?
|
488
531
|
|
489
|
-
|
490
|
-
|
491
|
-
|
492
|
-
else
|
493
|
-
credentials = Google::Cloud::Bigquery::Credentials.new(
|
494
|
-
keyfile, scope: scope)
|
532
|
+
credentials ||= (keyfile || Bigquery::Credentials.default(scope: scope))
|
533
|
+
unless credentials.is_a? Google::Auth::Credentials
|
534
|
+
credentials = Bigquery::Credentials.new credentials, scope: scope
|
495
535
|
end
|
496
536
|
|
497
|
-
|
498
|
-
|
499
|
-
|
537
|
+
Bigquery::Project.new(
|
538
|
+
Bigquery::Service.new(
|
539
|
+
project_id, credentials, retries: retries, timeout: timeout))
|
500
540
|
end
|
501
541
|
end
|
502
542
|
end
|
@@ -13,18 +13,44 @@
|
|
13
13
|
# limitations under the License.
|
14
14
|
|
15
15
|
|
16
|
-
require "
|
16
|
+
require "googleauth"
|
17
17
|
|
18
18
|
module Google
|
19
19
|
module Cloud
|
20
20
|
module Bigquery
|
21
21
|
##
|
22
|
-
#
|
23
|
-
|
22
|
+
# # Credentials
|
23
|
+
#
|
24
|
+
# Represents the authentication and authorization used to connect to the
|
25
|
+
# BigQuery API.
|
26
|
+
#
|
27
|
+
# @example
|
28
|
+
# require "google/cloud/bigquery"
|
29
|
+
#
|
30
|
+
# keyfile = "/path/to/keyfile.json"
|
31
|
+
# creds = Google::Cloud::Bigquery::Credentials.new keyfile
|
32
|
+
#
|
33
|
+
# bigquery = Google::Cloud::Bigquery.new(
|
34
|
+
# project_id: "my-project",
|
35
|
+
# credentials: creds
|
36
|
+
# )
|
37
|
+
#
|
38
|
+
# bigquery.project_id #=> "my-project"
|
39
|
+
#
|
40
|
+
class Credentials < Google::Auth::Credentials
|
24
41
|
SCOPE = ["https://www.googleapis.com/auth/bigquery"]
|
25
|
-
PATH_ENV_VARS = %w(
|
26
|
-
|
42
|
+
PATH_ENV_VARS = %w(BIGQUERY_CREDENTIALS
|
43
|
+
GOOGLE_CLOUD_CREDENTIALS
|
44
|
+
BIGQUERY_KEYFILE
|
45
|
+
GOOGLE_CLOUD_KEYFILE
|
46
|
+
GCLOUD_KEYFILE)
|
47
|
+
JSON_ENV_VARS = %w(BIGQUERY_CREDENTIALS_JSON
|
48
|
+
GOOGLE_CLOUD_CREDENTIALS_JSON
|
49
|
+
BIGQUERY_KEYFILE_JSON
|
50
|
+
GOOGLE_CLOUD_KEYFILE_JSON
|
27
51
|
GCLOUD_KEYFILE_JSON)
|
52
|
+
DEFAULT_PATHS = \
|
53
|
+
["~/.config/gcloud/application_default_credentials.json"]
|
28
54
|
end
|
29
55
|
end
|
30
56
|
end
|
@@ -49,14 +49,14 @@ module Google
|
|
49
49
|
attr_accessor :table_gapi
|
50
50
|
|
51
51
|
##
|
52
|
-
# @private The Google API Client object.
|
53
|
-
attr_accessor :
|
52
|
+
# @private The Google API Client object in JSON Hash.
|
53
|
+
attr_accessor :gapi_json
|
54
54
|
|
55
55
|
# @private
|
56
56
|
def initialize arr = []
|
57
57
|
@service = nil
|
58
58
|
@table_gapi = nil
|
59
|
-
@
|
59
|
+
@gapi_json = nil
|
60
60
|
super arr
|
61
61
|
end
|
62
62
|
|
@@ -66,7 +66,7 @@ module Google
|
|
66
66
|
# @return [String] The resource type.
|
67
67
|
#
|
68
68
|
def kind
|
69
|
-
@
|
69
|
+
@gapi_json[:kind]
|
70
70
|
end
|
71
71
|
|
72
72
|
##
|
@@ -75,7 +75,7 @@ module Google
|
|
75
75
|
# @return [String] The ETag hash.
|
76
76
|
#
|
77
77
|
def etag
|
78
|
-
@
|
78
|
+
@gapi_json[:etag]
|
79
79
|
end
|
80
80
|
|
81
81
|
##
|
@@ -85,7 +85,7 @@ module Google
|
|
85
85
|
# @return [String] The pagination token.
|
86
86
|
#
|
87
87
|
def token
|
88
|
-
@
|
88
|
+
@gapi_json[:pageToken]
|
89
89
|
end
|
90
90
|
|
91
91
|
##
|
@@ -107,7 +107,7 @@ module Google
|
|
107
107
|
# end
|
108
108
|
#
|
109
109
|
def total
|
110
|
-
Integer @
|
110
|
+
Integer @gapi_json[:totalRows]
|
111
111
|
rescue
|
112
112
|
nil
|
113
113
|
end
|
@@ -224,11 +224,11 @@ module Google
|
|
224
224
|
def next
|
225
225
|
return nil unless next?
|
226
226
|
ensure_service!
|
227
|
-
|
227
|
+
data_json = service.list_tabledata \
|
228
228
|
@table_gapi.table_reference.dataset_id,
|
229
229
|
@table_gapi.table_reference.table_id,
|
230
230
|
token: token
|
231
|
-
self.class.
|
231
|
+
self.class.from_gapi_json data_json, @table_gapi, @service
|
232
232
|
end
|
233
233
|
|
234
234
|
##
|
@@ -302,13 +302,13 @@ module Google
|
|
302
302
|
|
303
303
|
##
|
304
304
|
# @private New Data from a response object.
|
305
|
-
def self.
|
306
|
-
formatted_rows = Convert.format_rows(
|
305
|
+
def self.from_gapi_json gapi_json, table_gapi, service
|
306
|
+
formatted_rows = Convert.format_rows(gapi_json[:rows],
|
307
307
|
table_gapi.schema.fields)
|
308
308
|
|
309
309
|
data = new formatted_rows
|
310
310
|
data.table_gapi = table_gapi
|
311
|
-
data.
|
311
|
+
data.gapi_json = gapi_json
|
312
312
|
data.service = service
|
313
313
|
data
|
314
314
|
end
|
@@ -51,11 +51,16 @@ module Google
|
|
51
51
|
# @private The Google API Client object.
|
52
52
|
attr_accessor :gapi
|
53
53
|
|
54
|
+
##
|
55
|
+
# @private A Google API Client Dataset Reference object.
|
56
|
+
attr_reader :reference
|
57
|
+
|
54
58
|
##
|
55
59
|
# @private Create an empty Dataset object.
|
56
60
|
def initialize
|
57
61
|
@service = nil
|
58
|
-
@gapi =
|
62
|
+
@gapi = nil
|
63
|
+
@reference = nil
|
59
64
|
end
|
60
65
|
|
61
66
|
##
|
@@ -67,6 +72,7 @@ module Google
|
|
67
72
|
# @!group Attributes
|
68
73
|
#
|
69
74
|
def dataset_id
|
75
|
+
return reference.dataset_id if reference?
|
70
76
|
@gapi.dataset_reference.dataset_id
|
71
77
|
end
|
72
78
|
|
@@ -78,6 +84,7 @@ module Google
|
|
78
84
|
# @!group Attributes
|
79
85
|
#
|
80
86
|
def project_id
|
87
|
+
return reference.project_id if reference?
|
81
88
|
@gapi.dataset_reference.project_id
|
82
89
|
end
|
83
90
|
|
@@ -86,7 +93,7 @@ module Google
|
|
86
93
|
# The gapi fragment containing the Project ID and Dataset ID as a
|
87
94
|
# camel-cased hash.
|
88
95
|
def dataset_ref
|
89
|
-
dataset_ref = @gapi.dataset_reference
|
96
|
+
dataset_ref = reference? ? reference : @gapi.dataset_reference
|
90
97
|
dataset_ref = dataset_ref.to_h if dataset_ref.respond_to? :to_h
|
91
98
|
dataset_ref
|
92
99
|
end
|
@@ -94,22 +101,30 @@ module Google
|
|
94
101
|
##
|
95
102
|
# A descriptive name for the dataset.
|
96
103
|
#
|
97
|
-
# @return [String] The friendly name
|
104
|
+
# @return [String, nil] The friendly name, or `nil` if the object is
|
105
|
+
# a reference (see {#reference?}).
|
98
106
|
#
|
99
107
|
# @!group Attributes
|
100
108
|
#
|
101
109
|
def name
|
110
|
+
return nil if reference?
|
102
111
|
@gapi.friendly_name
|
103
112
|
end
|
104
113
|
|
105
114
|
##
|
106
115
|
# Updates the descriptive name for the dataset.
|
107
116
|
#
|
108
|
-
#
|
117
|
+
# If the dataset is not a full resource representation (see
|
118
|
+
# {#resource_full?}), the full representation will be retrieved before
|
119
|
+
# the update to comply with ETag-based optimistic concurrency control.
|
120
|
+
#
|
121
|
+
# @param [String] new_name The new friendly name, or `nil` if the object
|
122
|
+
# is a reference (see {#reference?}).
|
109
123
|
#
|
110
124
|
# @!group Attributes
|
111
125
|
#
|
112
126
|
def name= new_name
|
127
|
+
reload! unless resource_full?
|
113
128
|
@gapi.update! friendly_name: new_name
|
114
129
|
patch_gapi! :friendly_name
|
115
130
|
end
|
@@ -117,11 +132,13 @@ module Google
|
|
117
132
|
##
|
118
133
|
# The ETag hash of the dataset.
|
119
134
|
#
|
120
|
-
# @return [String] The ETag hash
|
135
|
+
# @return [String, nil] The ETag hash, or `nil` if the object is a
|
136
|
+
# reference (see {#reference?}).
|
121
137
|
#
|
122
138
|
# @!group Attributes
|
123
139
|
#
|
124
140
|
def etag
|
141
|
+
return nil if reference?
|
125
142
|
ensure_full_data!
|
126
143
|
@gapi.etag
|
127
144
|
end
|
@@ -129,11 +146,13 @@ module Google
|
|
129
146
|
##
|
130
147
|
# A URL that can be used to access the dataset using the REST API.
|
131
148
|
#
|
132
|
-
# @return [String] A REST URL for the resource
|
149
|
+
# @return [String, nil] A REST URL for the resource, or `nil` if the
|
150
|
+
# object is a reference (see {#reference?}).
|
133
151
|
#
|
134
152
|
# @!group Attributes
|
135
153
|
#
|
136
154
|
def api_url
|
155
|
+
return nil if reference?
|
137
156
|
ensure_full_data!
|
138
157
|
@gapi.self_link
|
139
158
|
end
|
@@ -141,11 +160,13 @@ module Google
|
|
141
160
|
##
|
142
161
|
# A user-friendly description of the dataset.
|
143
162
|
#
|
144
|
-
# @return [String] The description
|
163
|
+
# @return [String, nil] The description, or `nil` if the object is a
|
164
|
+
# reference (see {#reference?}).
|
145
165
|
#
|
146
166
|
# @!group Attributes
|
147
167
|
#
|
148
168
|
def description
|
169
|
+
return nil if reference?
|
149
170
|
ensure_full_data!
|
150
171
|
@gapi.description
|
151
172
|
end
|
@@ -153,11 +174,16 @@ module Google
|
|
153
174
|
##
|
154
175
|
# Updates the user-friendly description of the dataset.
|
155
176
|
#
|
177
|
+
# If the dataset is not a full resource representation (see
|
178
|
+
# {#resource_full?}), the full representation will be retrieved before
|
179
|
+
# the update to comply with ETag-based optimistic concurrency control.
|
180
|
+
#
|
156
181
|
# @param [String] new_description The new description for the dataset.
|
157
182
|
#
|
158
183
|
# @!group Attributes
|
159
184
|
#
|
160
185
|
def description= new_description
|
186
|
+
reload! unless resource_full?
|
161
187
|
@gapi.update! description: new_description
|
162
188
|
patch_gapi! :description
|
163
189
|
end
|
@@ -165,11 +191,14 @@ module Google
|
|
165
191
|
##
|
166
192
|
# The default lifetime of all tables in the dataset, in milliseconds.
|
167
193
|
#
|
168
|
-
# @return [Integer] The default table expiration in milliseconds
|
194
|
+
# @return [Integer, nil] The default table expiration in milliseconds,
|
195
|
+
# or `nil` if not present or the object is a reference (see
|
196
|
+
# {#reference?}).
|
169
197
|
#
|
170
198
|
# @!group Attributes
|
171
199
|
#
|
172
200
|
def default_expiration
|
201
|
+
return nil if reference?
|
173
202
|
ensure_full_data!
|
174
203
|
begin
|
175
204
|
Integer @gapi.default_table_expiration_ms
|
@@ -182,12 +211,17 @@ module Google
|
|
182
211
|
# Updates the default lifetime of all tables in the dataset, in
|
183
212
|
# milliseconds.
|
184
213
|
#
|
214
|
+
# If the dataset is not a full resource representation (see
|
215
|
+
# {#resource_full?}), the full representation will be retrieved before
|
216
|
+
# the update to comply with ETag-based optimistic concurrency control.
|
217
|
+
#
|
185
218
|
# @param [Integer] new_default_expiration The new default table
|
186
219
|
# expiration in milliseconds.
|
187
220
|
#
|
188
221
|
# @!group Attributes
|
189
222
|
#
|
190
223
|
def default_expiration= new_default_expiration
|
224
|
+
reload! unless resource_full?
|
191
225
|
@gapi.update! default_table_expiration_ms: new_default_expiration
|
192
226
|
patch_gapi! :default_table_expiration_ms
|
193
227
|
end
|
@@ -195,11 +229,13 @@ module Google
|
|
195
229
|
##
|
196
230
|
# The time when this dataset was created.
|
197
231
|
#
|
198
|
-
# @return [Time, nil] The creation time
|
232
|
+
# @return [Time, nil] The creation time, or `nil` if not present or the
|
233
|
+
# object is a reference (see {#reference?}).
|
199
234
|
#
|
200
235
|
# @!group Attributes
|
201
236
|
#
|
202
237
|
def created_at
|
238
|
+
return nil if reference?
|
203
239
|
ensure_full_data!
|
204
240
|
begin
|
205
241
|
::Time.at(Integer(@gapi.creation_time) / 1000.0)
|
@@ -211,11 +247,13 @@ module Google
|
|
211
247
|
##
|
212
248
|
# The date when this dataset or any of its tables was last modified.
|
213
249
|
#
|
214
|
-
# @return [Time, nil] The last modified time
|
250
|
+
# @return [Time, nil] The last modified time, or `nil` if not present or
|
251
|
+
# the object is a reference (see {#reference?}).
|
215
252
|
#
|
216
253
|
# @!group Attributes
|
217
254
|
#
|
218
255
|
def modified_at
|
256
|
+
return nil if reference?
|
219
257
|
ensure_full_data!
|
220
258
|
begin
|
221
259
|
::Time.at(Integer(@gapi.last_modified_time) / 1000.0)
|
@@ -228,11 +266,13 @@ module Google
|
|
228
266
|
# The geographic location where the dataset should reside. Possible
|
229
267
|
# values include `EU` and `US`. The default value is `US`.
|
230
268
|
#
|
231
|
-
# @return [String] The location code
|
269
|
+
# @return [String, nil] The location code, or `nil` if the object is a
|
270
|
+
# reference (see {#reference?}).
|
232
271
|
#
|
233
272
|
# @!group Attributes
|
234
273
|
#
|
235
274
|
def location
|
275
|
+
return nil if reference?
|
236
276
|
ensure_full_data!
|
237
277
|
@gapi.location
|
238
278
|
end
|
@@ -245,7 +285,8 @@ module Google
|
|
245
285
|
# The returned hash is frozen and changes are not allowed. Use
|
246
286
|
# {#labels=} to replace the entire hash.
|
247
287
|
#
|
248
|
-
# @return [Hash<String, String
|
288
|
+
# @return [Hash<String, String>, nil] A hash containing key/value pairs,
|
289
|
+
# or `nil` if the object is a reference (see {#reference?}).
|
249
290
|
#
|
250
291
|
# @example
|
251
292
|
# require "google/cloud/bigquery"
|
@@ -259,6 +300,7 @@ module Google
|
|
259
300
|
# @!group Attributes
|
260
301
|
#
|
261
302
|
def labels
|
303
|
+
return nil if reference?
|
262
304
|
m = @gapi.labels
|
263
305
|
m = m.to_h if m.respond_to? :to_h
|
264
306
|
m.dup.freeze
|
@@ -269,6 +311,10 @@ module Google
|
|
269
311
|
# Labels are used to organize and group datasets. See [Using
|
270
312
|
# Labels](https://cloud.google.com/bigquery/docs/labels).
|
271
313
|
#
|
314
|
+
# If the dataset is not a full resource representation (see
|
315
|
+
# {#resource_full?}), the full representation will be retrieved before
|
316
|
+
# the update to comply with ETag-based optimistic concurrency control.
|
317
|
+
#
|
272
318
|
# @param [Hash<String, String>] labels A hash containing key/value
|
273
319
|
# pairs.
|
274
320
|
#
|
@@ -290,6 +336,7 @@ module Google
|
|
290
336
|
# @!group Attributes
|
291
337
|
#
|
292
338
|
def labels= labels
|
339
|
+
reload! unless resource_full?
|
293
340
|
@gapi.labels = labels
|
294
341
|
patch_gapi! :labels
|
295
342
|
end
|
@@ -299,6 +346,10 @@ module Google
|
|
299
346
|
# when passing a block, see {Dataset::Access} for all the methods
|
300
347
|
# available.
|
301
348
|
#
|
349
|
+
# If the dataset is not a full resource representation (see
|
350
|
+
# {#resource_full?}), the full representation will be retrieved before
|
351
|
+
# the update to comply with ETag-based optimistic concurrency control.
|
352
|
+
#
|
302
353
|
# @see https://cloud.google.com/bigquery/access-control BigQuery Access
|
303
354
|
# Control
|
304
355
|
#
|
@@ -332,6 +383,7 @@ module Google
|
|
332
383
|
#
|
333
384
|
def access
|
334
385
|
ensure_full_data!
|
386
|
+
reload! unless resource_full?
|
335
387
|
access_builder = Access.from_gapi @gapi
|
336
388
|
if block_given?
|
337
389
|
yield access_builder
|
@@ -455,7 +507,14 @@ module Google
|
|
455
507
|
end
|
456
508
|
|
457
509
|
##
|
458
|
-
# Creates a new view
|
510
|
+
# Creates a new [view](https://cloud.google.com/bigquery/docs/views)
|
511
|
+
# table, which is a virtual table defined by the given SQL query.
|
512
|
+
#
|
513
|
+
# BigQuery's views are logical views, not materialized views, which
|
514
|
+
# means that the query that defines the view is re-executed every time
|
515
|
+
# the view is queried. Queries are billed according to the total amount
|
516
|
+
# of data in all table fields referenced directly or indirectly by the
|
517
|
+
# top-level query. (See {Table#view?} and {Table#query}.)
|
459
518
|
#
|
460
519
|
# @param [String] table_id The ID of the view table. The ID must contain
|
461
520
|
# only letters (a-z, A-Z), numbers (0-9), or underscores (_). The
|
@@ -480,7 +539,7 @@ module Google
|
|
480
539
|
# containing the same code. See [User-Defined
|
481
540
|
# Functions](https://cloud.google.com/bigquery/docs/reference/standard-sql/user-defined-functions).
|
482
541
|
#
|
483
|
-
# @return [Google::Cloud::Bigquery::
|
542
|
+
# @return [Google::Cloud::Bigquery::Table] A new table object.
|
484
543
|
#
|
485
544
|
# @example
|
486
545
|
# require "google/cloud/bigquery"
|
@@ -528,10 +587,13 @@ module Google
|
|
528
587
|
# Retrieves an existing table by ID.
|
529
588
|
#
|
530
589
|
# @param [String] table_id The ID of a table.
|
590
|
+
# @param [Boolean] skip_lookup Optionally create just a local reference
|
591
|
+
# object without verifying that the resource exists on the BigQuery
|
592
|
+
# service. Calls made on this object will raise errors if the resource
|
593
|
+
# does not exist. Default is `false`. Optional.
|
531
594
|
#
|
532
|
-
# @return [Google::Cloud::Bigquery::Table,
|
533
|
-
#
|
534
|
-
# not exist
|
595
|
+
# @return [Google::Cloud::Bigquery::Table, nil] Returns `nil` if the
|
596
|
+
# table does not exist.
|
535
597
|
#
|
536
598
|
# @example
|
537
599
|
# require "google/cloud/bigquery"
|
@@ -542,10 +604,22 @@ module Google
|
|
542
604
|
# table = dataset.table "my_table"
|
543
605
|
# puts table.name
|
544
606
|
#
|
607
|
+
# @example Avoid retrieving the table resource with `skip_lookup`:
|
608
|
+
# require "google/cloud/bigquery"
|
609
|
+
#
|
610
|
+
# bigquery = Google::Cloud::Bigquery.new
|
611
|
+
#
|
612
|
+
# dataset = bigquery.dataset "my_dataset"
|
613
|
+
#
|
614
|
+
# table = dataset.table "my_table", skip_lookup: true
|
615
|
+
#
|
545
616
|
# @!group Table
|
546
617
|
#
|
547
|
-
def table table_id
|
618
|
+
def table table_id, skip_lookup: nil
|
548
619
|
ensure_service!
|
620
|
+
if skip_lookup
|
621
|
+
return Table.new_reference project_id, dataset_id, table_id, service
|
622
|
+
end
|
549
623
|
gapi = service.get_table dataset_id, table_id
|
550
624
|
Table.from_gapi gapi, service
|
551
625
|
rescue Google::Cloud::NotFoundError
|
@@ -559,9 +633,8 @@ module Google
|
|
559
633
|
# part of the larger set of results to view.
|
560
634
|
# @param [Integer] max Maximum number of tables to return.
|
561
635
|
#
|
562
|
-
# @return [Array<Google::Cloud::Bigquery::Table
|
563
|
-
#
|
564
|
-
# views(See {Google::Cloud::Bigquery::Table::List})
|
636
|
+
# @return [Array<Google::Cloud::Bigquery::Table>] An array of tables
|
637
|
+
# (See {Google::Cloud::Bigquery::Table::List})
|
565
638
|
#
|
566
639
|
# @example
|
567
640
|
# require "google/cloud/bigquery"
|
@@ -1507,6 +1580,146 @@ module Google
|
|
1507
1580
|
true
|
1508
1581
|
end
|
1509
1582
|
|
1583
|
+
##
|
1584
|
+
# Reloads the dataset with current data from the BigQuery service.
|
1585
|
+
#
|
1586
|
+
# @return [Google::Cloud::Bigquery::Dataset] Returns the reloaded
|
1587
|
+
# dataset.
|
1588
|
+
#
|
1589
|
+
# @example Skip retrieving the dataset from the service, then load it:
|
1590
|
+
# require "google/cloud/bigquery"
|
1591
|
+
#
|
1592
|
+
# bigquery = Google::Cloud::Bigquery.new
|
1593
|
+
#
|
1594
|
+
# dataset = bigquery.dataset "my_dataset", skip_lookup: true
|
1595
|
+
# dataset.reload!
|
1596
|
+
#
|
1597
|
+
def reload!
|
1598
|
+
ensure_service!
|
1599
|
+
reloaded_gapi = service.get_dataset dataset_id
|
1600
|
+
@reference = nil
|
1601
|
+
@gapi = reloaded_gapi
|
1602
|
+
self
|
1603
|
+
end
|
1604
|
+
alias_method :refresh!, :reload!
|
1605
|
+
|
1606
|
+
##
|
1607
|
+
# Determines whether the dataset exists in the BigQuery service. The
|
1608
|
+
# result is cached locally.
|
1609
|
+
#
|
1610
|
+
# @return [Boolean] `true` when the dataset exists in the BigQuery
|
1611
|
+
# service, `false` otherwise.
|
1612
|
+
#
|
1613
|
+
# @example
|
1614
|
+
# require "google/cloud/bigquery"
|
1615
|
+
#
|
1616
|
+
# bigquery = Google::Cloud::Bigquery.new
|
1617
|
+
#
|
1618
|
+
# dataset = bigquery.dataset "my_dataset", skip_lookup: true
|
1619
|
+
# dataset.exists? # true
|
1620
|
+
#
|
1621
|
+
def exists?
|
1622
|
+
# Always true if we have a gapi object
|
1623
|
+
return true unless reference?
|
1624
|
+
# If we have a value, return it
|
1625
|
+
return @exists unless @exists.nil?
|
1626
|
+
ensure_gapi!
|
1627
|
+
@exists = true
|
1628
|
+
rescue Google::Cloud::NotFoundError
|
1629
|
+
@exists = false
|
1630
|
+
end
|
1631
|
+
|
1632
|
+
##
|
1633
|
+
# Whether the dataset was created without retrieving the resource
|
1634
|
+
# representation from the BigQuery service.
|
1635
|
+
#
|
1636
|
+
# @return [Boolean] `true` when the dataset is just a local reference
|
1637
|
+
# object, `false` otherwise.
|
1638
|
+
#
|
1639
|
+
# @example
|
1640
|
+
# require "google/cloud/bigquery"
|
1641
|
+
#
|
1642
|
+
# bigquery = Google::Cloud::Bigquery.new
|
1643
|
+
#
|
1644
|
+
# dataset = bigquery.dataset "my_dataset", skip_lookup: true
|
1645
|
+
#
|
1646
|
+
# dataset.reference? # true
|
1647
|
+
# dataset.reload!
|
1648
|
+
# dataset.reference? # false
|
1649
|
+
#
|
1650
|
+
def reference?
|
1651
|
+
@gapi.nil?
|
1652
|
+
end
|
1653
|
+
|
1654
|
+
##
|
1655
|
+
# Whether the dataset was created with a resource representation from
|
1656
|
+
# the BigQuery service.
|
1657
|
+
#
|
1658
|
+
# @return [Boolean] `true` when the dataset was created with a resource
|
1659
|
+
# representation, `false` otherwise.
|
1660
|
+
#
|
1661
|
+
# @example
|
1662
|
+
# require "google/cloud/bigquery"
|
1663
|
+
#
|
1664
|
+
# bigquery = Google::Cloud::Bigquery.new
|
1665
|
+
#
|
1666
|
+
# dataset = bigquery.dataset "my_dataset", skip_lookup: true
|
1667
|
+
#
|
1668
|
+
# dataset.resource? # false
|
1669
|
+
# dataset.reload!
|
1670
|
+
# dataset.resource? # true
|
1671
|
+
#
|
1672
|
+
def resource?
|
1673
|
+
!@gapi.nil?
|
1674
|
+
end
|
1675
|
+
|
1676
|
+
##
|
1677
|
+
# Whether the dataset was created with a partial resource representation
|
1678
|
+
# from the BigQuery service by retrieval through {Project#datasets}.
|
1679
|
+
# See [Datasets: list
|
1680
|
+
# response](https://cloud.google.com/bigquery/docs/reference/rest/v2/datasets/list#response)
|
1681
|
+
# for the contents of the partial representation. Accessing any
|
1682
|
+
# attribute outside of the partial representation will result in loading
|
1683
|
+
# the full representation.
|
1684
|
+
#
|
1685
|
+
# @return [Boolean] `true` when the dataset was created with a partial
|
1686
|
+
# resource representation, `false` otherwise.
|
1687
|
+
#
|
1688
|
+
# @example
|
1689
|
+
# require "google/cloud/bigquery"
|
1690
|
+
#
|
1691
|
+
# bigquery = Google::Cloud::Bigquery.new
|
1692
|
+
#
|
1693
|
+
# dataset = bigquery.datasets.first
|
1694
|
+
#
|
1695
|
+
# dataset.resource_partial? # true
|
1696
|
+
# dataset.description # Loads the full resource.
|
1697
|
+
# dataset.resource_partial? # false
|
1698
|
+
#
|
1699
|
+
def resource_partial?
|
1700
|
+
@gapi.is_a? Google::Apis::BigqueryV2::DatasetList::Dataset
|
1701
|
+
end
|
1702
|
+
|
1703
|
+
##
|
1704
|
+
# Whether the dataset was created with a full resource representation
|
1705
|
+
# from the BigQuery service.
|
1706
|
+
#
|
1707
|
+
# @return [Boolean] `true` when the dataset was created with a full
|
1708
|
+
# resource representation, `false` otherwise.
|
1709
|
+
#
|
1710
|
+
# @example
|
1711
|
+
# require "google/cloud/bigquery"
|
1712
|
+
#
|
1713
|
+
# bigquery = Google::Cloud::Bigquery.new
|
1714
|
+
#
|
1715
|
+
# dataset = bigquery.dataset "my_dataset"
|
1716
|
+
#
|
1717
|
+
# dataset.resource_full? # true
|
1718
|
+
#
|
1719
|
+
def resource_full?
|
1720
|
+
@gapi.is_a? Google::Apis::BigqueryV2::Dataset
|
1721
|
+
end
|
1722
|
+
|
1510
1723
|
##
|
1511
1724
|
# @private New Dataset from a Google API Client object.
|
1512
1725
|
def self.from_gapi gapi, conn
|
@@ -1516,6 +1729,20 @@ module Google
|
|
1516
1729
|
end
|
1517
1730
|
end
|
1518
1731
|
|
1732
|
+
##
|
1733
|
+
# @private New lazy Dataset object without making an HTTP request.
|
1734
|
+
def self.new_reference project_id, dataset_id, service
|
1735
|
+
# TODO: raise if dataset_id is nil?
|
1736
|
+
new.tap do |b|
|
1737
|
+
reference_gapi = Google::Apis::BigqueryV2::DatasetReference.new(
|
1738
|
+
project_id: project_id,
|
1739
|
+
dataset_id: dataset_id
|
1740
|
+
)
|
1741
|
+
b.service = service
|
1742
|
+
b.instance_variable_set :@reference, reference_gapi
|
1743
|
+
end
|
1744
|
+
end
|
1745
|
+
|
1519
1746
|
##
|
1520
1747
|
# Inserts data into the given table for near-immediate querying, without
|
1521
1748
|
# the need to complete a load operation before the data can appear in
|
@@ -1552,6 +1779,19 @@ module Google
|
|
1552
1779
|
# ]
|
1553
1780
|
# dataset.insert "my_table", rows
|
1554
1781
|
#
|
1782
|
+
# @example Avoid retrieving the dataset with `skip_lookup`:
|
1783
|
+
# require "google/cloud/bigquery"
|
1784
|
+
#
|
1785
|
+
# bigquery = Google::Cloud::Bigquery.new
|
1786
|
+
#
|
1787
|
+
# dataset = bigquery.dataset "my_dataset", skip_lookup: true
|
1788
|
+
#
|
1789
|
+
# rows = [
|
1790
|
+
# { "first_name" => "Alice", "age" => 21 },
|
1791
|
+
# { "first_name" => "Bob", "age" => 22 }
|
1792
|
+
# ]
|
1793
|
+
# dataset.insert "my_table", rows
|
1794
|
+
#
|
1555
1795
|
# @example Using `autocreate` to create a new table if none exists.
|
1556
1796
|
# require "google/cloud/bigquery"
|
1557
1797
|
#
|
@@ -1598,7 +1838,7 @@ module Google
|
|
1598
1838
|
end
|
1599
1839
|
|
1600
1840
|
##
|
1601
|
-
# Create an
|
1841
|
+
# Create an asynchronous inserter object used to insert rows in batches.
|
1602
1842
|
#
|
1603
1843
|
# @param [String] table_id The ID of the table to insert rows into.
|
1604
1844
|
# @param [Boolean] skip_invalid Insert all valid rows of a request, even
|
@@ -1617,8 +1857,8 @@ module Google
|
|
1617
1857
|
# @attr_reader [Numeric] threads The number of threads used to insert
|
1618
1858
|
# batches of rows. Default is 4.
|
1619
1859
|
# @yield [response] the callback for when a batch of rows is inserted
|
1620
|
-
# @yieldparam [
|
1621
|
-
# insert
|
1860
|
+
# @yieldparam [Table::AsyncInserter::Result] result the result of the
|
1861
|
+
# asynchronous insert
|
1622
1862
|
#
|
1623
1863
|
# @return [Table::AsyncInserter] Returns an inserter object.
|
1624
1864
|
#
|
@@ -1628,9 +1868,13 @@ module Google
|
|
1628
1868
|
# bigquery = Google::Cloud::Bigquery.new
|
1629
1869
|
# dataset = bigquery.dataset "my_dataset"
|
1630
1870
|
# table = dataset.table "my_table"
|
1631
|
-
# inserter = table.insert_async do |
|
1632
|
-
#
|
1633
|
-
#
|
1871
|
+
# inserter = table.insert_async do |result|
|
1872
|
+
# if result.error?
|
1873
|
+
# log_error result.error
|
1874
|
+
# else
|
1875
|
+
# log_insert "inserted #{result.insert_count} rows " \
|
1876
|
+
# "with #{result.error_count} errors"
|
1877
|
+
# end
|
1634
1878
|
# end
|
1635
1879
|
#
|
1636
1880
|
# rows = [
|
@@ -1674,6 +1918,15 @@ module Google
|
|
1674
1918
|
fail "Must have active connection" unless service
|
1675
1919
|
end
|
1676
1920
|
|
1921
|
+
##
|
1922
|
+
# Ensures the Google::Apis::BigqueryV2::Dataset object has been loaded
|
1923
|
+
# from the service.
|
1924
|
+
def ensure_gapi!
|
1925
|
+
ensure_service!
|
1926
|
+
return unless reference?
|
1927
|
+
reload!
|
1928
|
+
end
|
1929
|
+
|
1677
1930
|
def patch_gapi! *attributes
|
1678
1931
|
return if attributes.empty?
|
1679
1932
|
ensure_service!
|
@@ -1689,17 +1942,7 @@ module Google
|
|
1689
1942
|
# Load the complete representation of the dataset if it has been
|
1690
1943
|
# only partially loaded by a request to the API list method.
|
1691
1944
|
def ensure_full_data!
|
1692
|
-
|
1693
|
-
end
|
1694
|
-
|
1695
|
-
def reload_gapi!
|
1696
|
-
ensure_service!
|
1697
|
-
gapi = service.get_dataset dataset_id
|
1698
|
-
@gapi = gapi
|
1699
|
-
end
|
1700
|
-
|
1701
|
-
def data_complete?
|
1702
|
-
@gapi.is_a? Google::Apis::BigqueryV2::Dataset
|
1945
|
+
reload! if resource_partial?
|
1703
1946
|
end
|
1704
1947
|
|
1705
1948
|
def load_storage table_id, url, options = {}
|