google-cloud-bigquery 0.29.0 → 0.30.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: 58e73b43f4053457d2df061703e3314483552dbb
4
- data.tar.gz: 927a49cb45ff1a1c2aac5fa319e19dc0b422af23
2
+ SHA256:
3
+ metadata.gz: 8c5eccec9f2f10fd5b5637a91516d68bee4f8b7f2e7e8e58a6b213afe89e56fe
4
+ data.tar.gz: 55d8b9b98cd3e52bb7c6111feaa9811487c61a4b2868126c54af7f9dec5fde1b
5
5
  SHA512:
6
- metadata.gz: 8d86f37859a1a6cf2b682afd8b4e3f77b178fb8333e47606673e02e0a5e6ba76e61c6ee3c9bfbd5bd8d4763eff03f9c54bc067c10f39883772a6c730c0d8b443
7
- data.tar.gz: d9d5afd3aac9c23e523909d78b7ae5fc886ce783e5b3cad0068aff21a815841a564e9baf6f35b2235adf0ed743df55d41c33b570f9b99a5d5a96ea50768882d0
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
- project: "my-todo-project",
28
- keyfile: "/path/to/keyfile.json"
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 .bigquery and
17
- # #bigquery methods can be available, but the library and all dependencies won't
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] project Identifier for a BigQuery project. If not present,
79
- # the default project for the credentials is used.
80
- # @param [String, Hash] keyfile Keyfile downloaded from Google Cloud. If
81
- # file path the file must be readable.
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 project = nil, keyfile = nil, scope: nil, retries: nil,
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 project: project, keyfile: keyfile,
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] project Identifier for a BigQuery project. If not
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] keyfile Keyfile downloaded from Google Cloud. If
461
- # file path the file must be readable.
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 project: nil, keyfile: nil, scope: nil, retries: nil,
484
- timeout: nil
485
- project ||= Google::Cloud::Bigquery::Project.default_project
486
- project = project.to_s # Always cast to a string
487
- fail ArgumentError, "project is missing" if project.empty?
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
- if keyfile.nil?
490
- credentials = Google::Cloud::Bigquery::Credentials.default(
491
- scope: scope)
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
- Google::Cloud::Bigquery::Project.new(
498
- Google::Cloud::Bigquery::Service.new(
499
- project, credentials, retries: retries, timeout: timeout))
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 "google/cloud/credentials"
16
+ require "googleauth"
17
17
 
18
18
  module Google
19
19
  module Cloud
20
20
  module Bigquery
21
21
  ##
22
- # @private Represents the Oauth2 signing logic for Bigquery.
23
- class Credentials < Google::Cloud::Credentials
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(BIGQUERY_KEYFILE GOOGLE_CLOUD_KEYFILE GCLOUD_KEYFILE)
26
- JSON_ENV_VARS = %w(BIGQUERY_KEYFILE_JSON GOOGLE_CLOUD_KEYFILE_JSON
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 :gapi
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
- @gapi = nil
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
- @gapi.kind
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
- @gapi.etag
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
- @gapi.page_token
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 @gapi.total_rows
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
- data_gapi = service.list_tabledata \
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.from_gapi data_gapi, @table_gapi, @service
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.from_gapi gapi, table_gapi, service
306
- formatted_rows = Convert.format_rows(gapi.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.gapi = gapi
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
- # @param [String] new_name The new friendly name.
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>] A hash containing key/value pairs.
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 table from the given query.
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::View] A new view object.
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
- # Google::Cloud::Bigquery::View, nil] Returns `nil` if the table does
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
- # Array<Google::Cloud::Bigquery::View>] An array of tables and/or
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 asynchonous inserter object used to insert rows in batches.
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 [InsertResponse] response the result of the asynchonous
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 |response|
1632
- # log_insert "inserted #{response.insert_count} rows " \
1633
- # "with #{response.error_count} errors"
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
- reload_gapi! unless data_complete?
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 = {}