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 +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
@@ -185,8 +185,8 @@ module Google
|
|
185
185
|
##
|
186
186
|
# Add reader access to a view.
|
187
187
|
#
|
188
|
-
# @param [Google::Cloud::Bigquery::
|
189
|
-
# a string identifier as specified by the [Query
|
188
|
+
# @param [Google::Cloud::Bigquery::Table, String] view A table object
|
189
|
+
# or a string identifier as specified by the [Query
|
190
190
|
# Reference](https://cloud.google.com/bigquery/query-reference#from):
|
191
191
|
# `project_name:datasetId.tableId`.
|
192
192
|
#
|
@@ -444,8 +444,8 @@ module Google
|
|
444
444
|
##
|
445
445
|
# Remove reader access from a view.
|
446
446
|
#
|
447
|
-
# @param [Google::Cloud::Bigquery::
|
448
|
-
# a string identifier as specified by the [Query
|
447
|
+
# @param [Google::Cloud::Bigquery::Table, String] view A table object
|
448
|
+
# or a string identifier as specified by the [Query
|
449
449
|
# Reference](https://cloud.google.com/bigquery/query-reference#from):
|
450
450
|
# `project_name:datasetId.tableId`.
|
451
451
|
#
|
@@ -699,8 +699,8 @@ module Google
|
|
699
699
|
##
|
700
700
|
# Checks reader access for a view.
|
701
701
|
#
|
702
|
-
# @param [Google::Cloud::Bigquery::
|
703
|
-
# a string identifier as specified by the [Query
|
702
|
+
# @param [Google::Cloud::Bigquery::Table, String] view A table object
|
703
|
+
# or a string identifier as specified by the [Query
|
704
704
|
# Reference](https://cloud.google.com/bigquery/query-reference#from):
|
705
705
|
# `project_name:datasetId.tableId`.
|
706
706
|
#
|
@@ -31,7 +31,7 @@ module Google
|
|
31
31
|
#
|
32
32
|
# A job instance is created when you call {Project#query_job},
|
33
33
|
# {Dataset#query_job}, {Table#copy_job}, {Table#extract_job},
|
34
|
-
# {Table#load_job}
|
34
|
+
# {Table#load_job}.
|
35
35
|
#
|
36
36
|
# @see https://cloud.google.com/bigquery/docs/managing-jobs Running and
|
37
37
|
# Managing Jobs
|
@@ -74,19 +74,20 @@ module Google
|
|
74
74
|
# require "google/cloud/bigquery"
|
75
75
|
#
|
76
76
|
# bigquery = Google::Cloud::Bigquery.new(
|
77
|
-
#
|
78
|
-
#
|
77
|
+
# project_id: "my-project",
|
78
|
+
# credentials: "/path/to/keyfile.json"
|
79
79
|
# )
|
80
80
|
#
|
81
|
-
# bigquery.
|
81
|
+
# bigquery.project_id #=> "my-project"
|
82
82
|
#
|
83
|
-
def
|
83
|
+
def project_id
|
84
84
|
service.project
|
85
85
|
end
|
86
|
+
alias_method :project, :project_id
|
86
87
|
|
87
88
|
##
|
88
|
-
# @private Default
|
89
|
-
def self.
|
89
|
+
# @private Default project_id.
|
90
|
+
def self.default_project_id
|
90
91
|
ENV["BIGQUERY_PROJECT"] ||
|
91
92
|
ENV["GOOGLE_CLOUD_PROJECT"] ||
|
92
93
|
ENV["GCLOUD_PROJECT"] ||
|
@@ -580,6 +581,10 @@ module Google
|
|
580
581
|
# Retrieves an existing dataset by ID.
|
581
582
|
#
|
582
583
|
# @param [String] dataset_id The ID of a dataset.
|
584
|
+
# @param [Boolean] skip_lookup Optionally create just a local reference
|
585
|
+
# object without verifying that the resource exists on the BigQuery
|
586
|
+
# service. Calls made on this object will raise errors if the resource
|
587
|
+
# does not exist. Default is `false`. Optional.
|
583
588
|
#
|
584
589
|
# @return [Google::Cloud::Bigquery::Dataset, nil] Returns `nil` if the
|
585
590
|
# dataset does not exist.
|
@@ -592,8 +597,18 @@ module Google
|
|
592
597
|
# dataset = bigquery.dataset "my_dataset"
|
593
598
|
# puts dataset.name
|
594
599
|
#
|
595
|
-
|
600
|
+
# @example Avoid retrieving the dataset resource with `skip_lookup`:
|
601
|
+
# require "google/cloud/bigquery"
|
602
|
+
#
|
603
|
+
# bigquery = Google::Cloud::Bigquery.new
|
604
|
+
#
|
605
|
+
# dataset = bigquery.dataset "my_dataset", skip_lookup: true
|
606
|
+
#
|
607
|
+
def dataset dataset_id, skip_lookup: nil
|
596
608
|
ensure_service!
|
609
|
+
if skip_lookup
|
610
|
+
return Dataset.new_reference project, dataset_id, service
|
611
|
+
end
|
597
612
|
gapi = service.get_dataset dataset_id
|
598
613
|
Dataset.from_gapi gapi, service
|
599
614
|
rescue Google::Cloud::NotFoundError
|
@@ -24,7 +24,7 @@ module Google
|
|
24
24
|
#
|
25
25
|
# A {Job} subclass representing a query operation that may be performed
|
26
26
|
# on a {Table}. A QueryJob instance is created when you call
|
27
|
-
# {Project#query_job}, {Dataset#query_job}
|
27
|
+
# {Project#query_job}, {Dataset#query_job}.
|
28
28
|
#
|
29
29
|
# @see https://cloud.google.com/bigquery/querying-data Querying Data
|
30
30
|
# @see https://cloud.google.com/bigquery/docs/reference/v2/jobs Jobs API
|
@@ -305,9 +305,11 @@ module Google
|
|
305
305
|
ensure_schema!
|
306
306
|
|
307
307
|
options = { token: token, max: max, start: start }
|
308
|
-
|
309
|
-
|
310
|
-
|
308
|
+
data_hash = service.list_tabledata \
|
309
|
+
destination_table_dataset_id,
|
310
|
+
destination_table_table_id,
|
311
|
+
options
|
312
|
+
Data.from_gapi_json data_hash, destination_table_gapi, service
|
311
313
|
end
|
312
314
|
alias_method :query_results, :data
|
313
315
|
|
@@ -46,7 +46,6 @@ module Google
|
|
46
46
|
def initialize project, credentials, retries: nil, timeout: nil
|
47
47
|
@project = project
|
48
48
|
@credentials = credentials
|
49
|
-
@credentials = credentials
|
50
49
|
@retries = retries
|
51
50
|
@timeout = timeout
|
52
51
|
end
|
@@ -191,10 +190,13 @@ module Google
|
|
191
190
|
def list_tabledata dataset_id, table_id, options = {}
|
192
191
|
# The list operation is considered idempotent
|
193
192
|
execute backoff: true do
|
194
|
-
service.list_table_data
|
195
|
-
|
196
|
-
|
197
|
-
|
193
|
+
json_txt = service.list_table_data \
|
194
|
+
@project, dataset_id, table_id,
|
195
|
+
max_results: options.delete(:max),
|
196
|
+
page_token: options.delete(:token),
|
197
|
+
start_index: options.delete(:start),
|
198
|
+
options: { skip_deserialization: true }
|
199
|
+
JSON.parse json_txt, symbolize_names: true
|
198
200
|
end
|
199
201
|
end
|
200
202
|
|
@@ -15,7 +15,6 @@
|
|
15
15
|
|
16
16
|
require "google/cloud/errors"
|
17
17
|
require "google/cloud/bigquery/service"
|
18
|
-
require "google/cloud/bigquery/view"
|
19
18
|
require "google/cloud/bigquery/data"
|
20
19
|
require "google/cloud/bigquery/table/list"
|
21
20
|
require "google/cloud/bigquery/schema"
|
@@ -34,6 +33,15 @@ module Google
|
|
34
33
|
# records. Every table is defined by a schema that may contain nested and
|
35
34
|
# repeated fields.
|
36
35
|
#
|
36
|
+
# The Table class can also represent a
|
37
|
+
# [view](https://cloud.google.com/bigquery/docs/views), which is a virtual
|
38
|
+
# table defined by a SQL query. BigQuery's views are logical views, not
|
39
|
+
# materialized views, which means that the query that defines the view is
|
40
|
+
# re-executed every time the view is queried. Queries are billed according
|
41
|
+
# to the total amount of data in all table fields referenced directly or
|
42
|
+
# indirectly by the top-level query. (See {#view?}, {#query}, {#query=},
|
43
|
+
# and {Dataset#create_view}.)
|
44
|
+
#
|
37
45
|
# @see https://cloud.google.com/bigquery/preparing-data-for-bigquery
|
38
46
|
# Preparing Data for BigQuery
|
39
47
|
#
|
@@ -66,6 +74,15 @@ module Google
|
|
66
74
|
# }
|
67
75
|
# table.insert row
|
68
76
|
#
|
77
|
+
# @example Creating a BigQuery view:
|
78
|
+
# require "google/cloud/bigquery"
|
79
|
+
#
|
80
|
+
# bigquery = Google::Cloud::Bigquery.new
|
81
|
+
# dataset = bigquery.dataset "my_dataset"
|
82
|
+
# view = dataset.create_view "my_view",
|
83
|
+
# "SELECT name, age FROM `my_project.my_dataset.my_table`"
|
84
|
+
# view.view? # true
|
85
|
+
#
|
69
86
|
class Table
|
70
87
|
##
|
71
88
|
# @private The Service object.
|
@@ -75,11 +92,16 @@ module Google
|
|
75
92
|
# @private The Google API Client object.
|
76
93
|
attr_accessor :gapi
|
77
94
|
|
95
|
+
##
|
96
|
+
# @private A Google API Client Table Reference object.
|
97
|
+
attr_reader :reference
|
98
|
+
|
78
99
|
##
|
79
100
|
# @private Create an empty Table object.
|
80
101
|
def initialize
|
81
102
|
@service = nil
|
82
|
-
@gapi =
|
103
|
+
@gapi = nil
|
104
|
+
@reference = nil
|
83
105
|
end
|
84
106
|
|
85
107
|
##
|
@@ -91,6 +113,7 @@ module Google
|
|
91
113
|
# @!group Attributes
|
92
114
|
#
|
93
115
|
def table_id
|
116
|
+
return reference.table_id if reference?
|
94
117
|
@gapi.table_reference.table_id
|
95
118
|
end
|
96
119
|
|
@@ -103,6 +126,7 @@ module Google
|
|
103
126
|
# @!group Attributes
|
104
127
|
#
|
105
128
|
def dataset_id
|
129
|
+
return reference.dataset_id if reference?
|
106
130
|
@gapi.table_reference.dataset_id
|
107
131
|
end
|
108
132
|
|
@@ -114,28 +138,32 @@ module Google
|
|
114
138
|
# @!group Attributes
|
115
139
|
#
|
116
140
|
def project_id
|
141
|
+
return reference.project_id if reference?
|
117
142
|
@gapi.table_reference.project_id
|
118
143
|
end
|
119
144
|
|
120
145
|
##
|
121
146
|
# @private The gapi fragment containing the Project ID, Dataset ID, and
|
122
|
-
# Table ID
|
147
|
+
# Table ID.
|
148
|
+
#
|
149
|
+
# @return [Google::Apis::BigqueryV2::TableReference]
|
150
|
+
#
|
123
151
|
def table_ref
|
124
|
-
|
125
|
-
table_ref = table_ref.to_hash if table_ref.respond_to? :to_hash
|
126
|
-
table_ref
|
152
|
+
reference? ? reference : @gapi.table_reference
|
127
153
|
end
|
128
154
|
|
129
155
|
###
|
130
156
|
# Checks if the table is time-partitioned. See [Partitioned
|
131
157
|
# Tables](https://cloud.google.com/bigquery/docs/partitioned-tables).
|
132
158
|
#
|
133
|
-
# @return [Boolean] `true` when the table is time-partitioned,
|
134
|
-
# otherwise
|
159
|
+
# @return [Boolean, nil] `true` when the table is time-partitioned, or
|
160
|
+
# `false` otherwise, if the object is a resource (see {#resource?});
|
161
|
+
# `nil` if the object is a reference (see {#reference?}).
|
135
162
|
#
|
136
163
|
# @!group Attributes
|
137
164
|
#
|
138
165
|
def time_partitioning?
|
166
|
+
return nil if reference?
|
139
167
|
!@gapi.time_partitioning.nil?
|
140
168
|
end
|
141
169
|
|
@@ -144,11 +172,13 @@ module Google
|
|
144
172
|
# [Partitioned Tables](https://cloud.google.com/bigquery/docs/partitioned-tables).
|
145
173
|
#
|
146
174
|
# @return [String, nil] The partition type. Currently the only supported
|
147
|
-
# value is "DAY"
|
175
|
+
# value is "DAY", or `nil` if the object is a reference (see
|
176
|
+
# {#reference?}).
|
148
177
|
#
|
149
178
|
# @!group Attributes
|
150
179
|
#
|
151
180
|
def time_partitioning_type
|
181
|
+
return nil if reference?
|
152
182
|
ensure_full_data!
|
153
183
|
@gapi.time_partitioning.type if time_partitioning?
|
154
184
|
end
|
@@ -161,6 +191,10 @@ module Google
|
|
161
191
|
# the example below. BigQuery does not allow you to change partitioning
|
162
192
|
# on an existing table.
|
163
193
|
#
|
194
|
+
# If the table is not a full resource representation (see
|
195
|
+
# {#resource_full?}), the full representation will be retrieved before
|
196
|
+
# the update to comply with ETag-based optimistic concurrency control.
|
197
|
+
#
|
164
198
|
# @param [String] type The partition type. Currently the only
|
165
199
|
# supported value is "DAY".
|
166
200
|
#
|
@@ -176,6 +210,7 @@ module Google
|
|
176
210
|
# @!group Attributes
|
177
211
|
#
|
178
212
|
def time_partitioning_type= type
|
213
|
+
reload! unless resource_full?
|
179
214
|
@gapi.time_partitioning ||=
|
180
215
|
Google::Apis::BigqueryV2::TimePartitioning.new
|
181
216
|
@gapi.time_partitioning.type = type
|
@@ -188,11 +223,13 @@ module Google
|
|
188
223
|
# [Partitioned Tables](https://cloud.google.com/bigquery/docs/partitioned-tables).
|
189
224
|
#
|
190
225
|
# @return [Integer, nil] The expiration time, in seconds, for data in
|
191
|
-
# partitions
|
226
|
+
# partitions, or `nil` if not present or the object is a reference
|
227
|
+
# (see {#reference?}).
|
192
228
|
#
|
193
229
|
# @!group Attributes
|
194
230
|
#
|
195
231
|
def time_partitioning_expiration
|
232
|
+
return nil if reference?
|
196
233
|
ensure_full_data!
|
197
234
|
@gapi.time_partitioning.expiration_ms / 1_000 if
|
198
235
|
time_partitioning? &&
|
@@ -206,6 +243,10 @@ module Google
|
|
206
243
|
#
|
207
244
|
# See {Table#time_partitioning_type=}.
|
208
245
|
#
|
246
|
+
# If the table is not a full resource representation (see
|
247
|
+
# {#resource_full?}), the full representation will be retrieved before
|
248
|
+
# the update to comply with ETag-based optimistic concurrency control.
|
249
|
+
#
|
209
250
|
# @param [Integer] expiration An expiration time, in seconds,
|
210
251
|
# for data in partitions.
|
211
252
|
#
|
@@ -222,6 +263,7 @@ module Google
|
|
222
263
|
# @!group Attributes
|
223
264
|
#
|
224
265
|
def time_partitioning_expiration= expiration
|
266
|
+
reload! unless resource_full?
|
225
267
|
@gapi.time_partitioning ||=
|
226
268
|
Google::Apis::BigqueryV2::TimePartitioning.new
|
227
269
|
@gapi.time_partitioning.expiration_ms = expiration * 1000
|
@@ -235,11 +277,13 @@ module Google
|
|
235
277
|
# `project_name:datasetId.tableId`. To use this value in queries see
|
236
278
|
# {#query_id}.
|
237
279
|
#
|
238
|
-
# @return [String] The combined ID
|
280
|
+
# @return [String, nil] The combined ID, or `nil` if the object is a
|
281
|
+
# reference (see {#reference?}).
|
239
282
|
#
|
240
283
|
# @!group Attributes
|
241
284
|
#
|
242
285
|
def id
|
286
|
+
return nil if reference?
|
243
287
|
@gapi.id
|
244
288
|
end
|
245
289
|
|
@@ -274,7 +318,7 @@ module Google
|
|
274
318
|
#
|
275
319
|
def query_id standard_sql: nil, legacy_sql: nil
|
276
320
|
if Convert.resolve_legacy_sql standard_sql, legacy_sql
|
277
|
-
"[#{
|
321
|
+
"[#{project_id}:#{dataset_id}.#{table_id}]"
|
278
322
|
else
|
279
323
|
"`#{project_id}.#{dataset_id}.#{table_id}`"
|
280
324
|
end
|
@@ -283,22 +327,29 @@ module Google
|
|
283
327
|
##
|
284
328
|
# The name of the table.
|
285
329
|
#
|
286
|
-
# @return [String] The friendly name
|
330
|
+
# @return [String, nil] The friendly name, or `nil` if the object is a
|
331
|
+
# reference (see {#reference?}).
|
287
332
|
#
|
288
333
|
# @!group Attributes
|
289
334
|
#
|
290
335
|
def name
|
336
|
+
return nil if reference?
|
291
337
|
@gapi.friendly_name
|
292
338
|
end
|
293
339
|
|
294
340
|
##
|
295
341
|
# Updates the name of the table.
|
296
342
|
#
|
343
|
+
# If the table is not a full resource representation (see
|
344
|
+
# {#resource_full?}), the full representation will be retrieved before
|
345
|
+
# the update to comply with ETag-based optimistic concurrency control.
|
346
|
+
#
|
297
347
|
# @param [String] new_name The new friendly name.
|
298
348
|
#
|
299
349
|
# @!group Attributes
|
300
350
|
#
|
301
351
|
def name= new_name
|
352
|
+
reload! unless resource_full?
|
302
353
|
@gapi.update! friendly_name: new_name
|
303
354
|
patch_gapi! :friendly_name
|
304
355
|
end
|
@@ -306,11 +357,13 @@ module Google
|
|
306
357
|
##
|
307
358
|
# The ETag hash of the table.
|
308
359
|
#
|
309
|
-
# @return [String] The ETag hash
|
360
|
+
# @return [String, nil] The ETag hash, or `nil` if the object is a
|
361
|
+
# reference (see {#reference?}).
|
310
362
|
#
|
311
363
|
# @!group Attributes
|
312
364
|
#
|
313
365
|
def etag
|
366
|
+
return nil if reference?
|
314
367
|
ensure_full_data!
|
315
368
|
@gapi.etag
|
316
369
|
end
|
@@ -318,11 +371,13 @@ module Google
|
|
318
371
|
##
|
319
372
|
# A URL that can be used to access the table using the REST API.
|
320
373
|
#
|
321
|
-
# @return [String] A REST URL for the resource
|
374
|
+
# @return [String, nil] A REST URL for the resource, or `nil` if the
|
375
|
+
# object is a reference (see {#reference?}).
|
322
376
|
#
|
323
377
|
# @!group Attributes
|
324
378
|
#
|
325
379
|
def api_url
|
380
|
+
return nil if reference?
|
326
381
|
ensure_full_data!
|
327
382
|
@gapi.self_link
|
328
383
|
end
|
@@ -330,11 +385,13 @@ module Google
|
|
330
385
|
##
|
331
386
|
# A user-friendly description of the table.
|
332
387
|
#
|
333
|
-
# @return [String] The description
|
388
|
+
# @return [String, nil] The description, or `nil` if the object is a
|
389
|
+
# reference (see {#reference?}).
|
334
390
|
#
|
335
391
|
# @!group Attributes
|
336
392
|
#
|
337
393
|
def description
|
394
|
+
return nil if reference?
|
338
395
|
ensure_full_data!
|
339
396
|
@gapi.description
|
340
397
|
end
|
@@ -342,11 +399,16 @@ module Google
|
|
342
399
|
##
|
343
400
|
# Updates the user-friendly description of the table.
|
344
401
|
#
|
402
|
+
# If the table is not a full resource representation (see
|
403
|
+
# {#resource_full?}), the full representation will be retrieved before
|
404
|
+
# the update to comply with ETag-based optimistic concurrency control.
|
405
|
+
#
|
345
406
|
# @param [String] new_description The new user-friendly description.
|
346
407
|
#
|
347
408
|
# @!group Attributes
|
348
409
|
#
|
349
410
|
def description= new_description
|
411
|
+
reload! unless resource_full?
|
350
412
|
@gapi.update! description: new_description
|
351
413
|
patch_gapi! :description
|
352
414
|
end
|
@@ -354,11 +416,13 @@ module Google
|
|
354
416
|
##
|
355
417
|
# The number of bytes in the table.
|
356
418
|
#
|
357
|
-
# @return [Integer] The count of bytes in the table
|
419
|
+
# @return [Integer, nil] The count of bytes in the table, or `nil` if
|
420
|
+
# the object is a reference (see {#reference?}).
|
358
421
|
#
|
359
422
|
# @!group Data
|
360
423
|
#
|
361
424
|
def bytes_count
|
425
|
+
return nil if reference?
|
362
426
|
ensure_full_data!
|
363
427
|
begin
|
364
428
|
Integer @gapi.num_bytes
|
@@ -370,11 +434,13 @@ module Google
|
|
370
434
|
##
|
371
435
|
# The number of rows in the table.
|
372
436
|
#
|
373
|
-
# @return [Integer] The count of rows in the table
|
437
|
+
# @return [Integer, nil] The count of rows in the table, or `nil` if the
|
438
|
+
# object is a reference (see {#reference?}).
|
374
439
|
#
|
375
440
|
# @!group Data
|
376
441
|
#
|
377
442
|
def rows_count
|
443
|
+
return nil if reference?
|
378
444
|
ensure_full_data!
|
379
445
|
begin
|
380
446
|
Integer @gapi.num_rows
|
@@ -386,11 +452,13 @@ module Google
|
|
386
452
|
##
|
387
453
|
# The time when this table was created.
|
388
454
|
#
|
389
|
-
# @return [Time, nil] The creation time
|
455
|
+
# @return [Time, nil] The creation time, or `nil` if the object is a
|
456
|
+
# reference (see {#reference?}).
|
390
457
|
#
|
391
458
|
# @!group Attributes
|
392
459
|
#
|
393
460
|
def created_at
|
461
|
+
return nil if reference?
|
394
462
|
ensure_full_data!
|
395
463
|
begin
|
396
464
|
::Time.at(Integer(@gapi.creation_time) / 1000.0)
|
@@ -404,11 +472,13 @@ module Google
|
|
404
472
|
# If not present, the table will persist indefinitely.
|
405
473
|
# Expired tables will be deleted and their storage reclaimed.
|
406
474
|
#
|
407
|
-
# @return [Time, nil] The expiration time
|
475
|
+
# @return [Time, nil] The expiration time, or `nil` if not present or
|
476
|
+
# the object is a reference (see {#reference?}).
|
408
477
|
#
|
409
478
|
# @!group Attributes
|
410
479
|
#
|
411
480
|
def expires_at
|
481
|
+
return nil if reference?
|
412
482
|
ensure_full_data!
|
413
483
|
begin
|
414
484
|
::Time.at(Integer(@gapi.expiration_time) / 1000.0)
|
@@ -420,11 +490,13 @@ module Google
|
|
420
490
|
##
|
421
491
|
# The date when this table was last modified.
|
422
492
|
#
|
423
|
-
# @return [Time, nil] The last modified time
|
493
|
+
# @return [Time, nil] The last modified time, or `nil` if not present or
|
494
|
+
# the object is a reference (see {#reference?}).
|
424
495
|
#
|
425
496
|
# @!group Attributes
|
426
497
|
#
|
427
498
|
def modified_at
|
499
|
+
return nil if reference?
|
428
500
|
ensure_full_data!
|
429
501
|
begin
|
430
502
|
::Time.at(Integer(@gapi.last_modified_time) / 1000.0)
|
@@ -436,34 +508,45 @@ module Google
|
|
436
508
|
##
|
437
509
|
# Checks if the table's type is "TABLE".
|
438
510
|
#
|
439
|
-
# @return [Boolean] `true` when the type is `TABLE`, `false`
|
511
|
+
# @return [Boolean, nil] `true` when the type is `TABLE`, `false`
|
512
|
+
# otherwise, if the object is a resource (see {#resource?}); `nil` if
|
513
|
+
# the object is a reference (see {#reference?}).
|
440
514
|
#
|
441
515
|
# @!group Attributes
|
442
516
|
#
|
443
517
|
def table?
|
518
|
+
return nil if reference?
|
444
519
|
@gapi.type == "TABLE"
|
445
520
|
end
|
446
521
|
|
447
522
|
##
|
448
|
-
# Checks if the table's type is "VIEW"
|
523
|
+
# Checks if the table's type is "VIEW", indicating that the table
|
524
|
+
# represents a BigQuery view. See {Dataset#create_view}.
|
449
525
|
#
|
450
|
-
# @return [Boolean] `true` when the type is `VIEW`, `false`
|
526
|
+
# @return [Boolean, nil] `true` when the type is `VIEW`, `false`
|
527
|
+
# otherwise, if the object is a resource (see {#resource?}); `nil` if
|
528
|
+
# the object is a reference (see {#reference?}).
|
451
529
|
#
|
452
530
|
# @!group Attributes
|
453
531
|
#
|
454
532
|
def view?
|
533
|
+
return nil if reference?
|
455
534
|
@gapi.type == "VIEW"
|
456
535
|
end
|
457
536
|
|
458
537
|
##
|
459
|
-
# Checks if the table's type is "EXTERNAL"
|
538
|
+
# Checks if the table's type is "EXTERNAL", indicating that the table
|
539
|
+
# represents an External Data Source. See {#external?} and
|
540
|
+
# {External::DataSource}.
|
460
541
|
#
|
461
|
-
# @return [Boolean] `true` when the type is `EXTERNAL`, `false`
|
462
|
-
# otherwise
|
542
|
+
# @return [Boolean, nil] `true` when the type is `EXTERNAL`, `false`
|
543
|
+
# otherwise, if the object is a resource (see {#resource?}); `nil` if
|
544
|
+
# the object is a reference (see {#reference?}).
|
463
545
|
#
|
464
546
|
# @!group Attributes
|
465
547
|
#
|
466
548
|
def external?
|
549
|
+
return nil if reference?
|
467
550
|
@gapi.type == "EXTERNAL"
|
468
551
|
end
|
469
552
|
|
@@ -471,11 +554,12 @@ module Google
|
|
471
554
|
# The geographic location where the table should reside. Possible
|
472
555
|
# values include `EU` and `US`. The default value is `US`.
|
473
556
|
#
|
474
|
-
# @return [String] The location code.
|
557
|
+
# @return [String, nil] The location code.
|
475
558
|
#
|
476
559
|
# @!group Attributes
|
477
560
|
#
|
478
561
|
def location
|
562
|
+
return nil if reference?
|
479
563
|
ensure_full_data!
|
480
564
|
@gapi.location
|
481
565
|
end
|
@@ -488,7 +572,7 @@ module Google
|
|
488
572
|
# The returned hash is frozen and changes are not allowed. Use
|
489
573
|
# {#labels=} to replace the entire hash.
|
490
574
|
#
|
491
|
-
# @return [Hash<String, String
|
575
|
+
# @return [Hash<String, String>, nil] A hash containing key/value pairs.
|
492
576
|
#
|
493
577
|
# @example
|
494
578
|
# require "google/cloud/bigquery"
|
@@ -503,6 +587,7 @@ module Google
|
|
503
587
|
# @!group Attributes
|
504
588
|
#
|
505
589
|
def labels
|
590
|
+
return nil if reference?
|
506
591
|
m = @gapi.labels
|
507
592
|
m = m.to_h if m.respond_to? :to_h
|
508
593
|
m.dup.freeze
|
@@ -513,6 +598,10 @@ module Google
|
|
513
598
|
# Labels are used to organize and group tables. See [Using
|
514
599
|
# Labels](https://cloud.google.com/bigquery/docs/labels).
|
515
600
|
#
|
601
|
+
# If the table is not a full resource representation (see
|
602
|
+
# {#resource_full?}), the full representation will be retrieved before
|
603
|
+
# the update to comply with ETag-based optimistic concurrency control.
|
604
|
+
#
|
516
605
|
# @param [Hash<String, String>] labels A hash containing key/value
|
517
606
|
# pairs.
|
518
607
|
#
|
@@ -535,14 +624,18 @@ module Google
|
|
535
624
|
# @!group Attributes
|
536
625
|
#
|
537
626
|
def labels= labels
|
627
|
+
reload! unless resource_full?
|
538
628
|
@gapi.labels = labels
|
539
629
|
patch_gapi! :labels
|
540
630
|
end
|
541
631
|
|
542
632
|
##
|
543
|
-
# Returns the table's schema.
|
544
|
-
# replace, or add to the schema by
|
545
|
-
# available methods.
|
633
|
+
# Returns the table's schema. If the table is not a view (See {#view?}),
|
634
|
+
# this method can also be used to set, replace, or add to the schema by
|
635
|
+
# passing a block. See {Schema} for available methods.
|
636
|
+
#
|
637
|
+
# If the table is not a full resource representation (see
|
638
|
+
# {#resource_full?}), the full representation will be retrieved.
|
546
639
|
#
|
547
640
|
# @param [Boolean] replace Whether to replace the existing schema with
|
548
641
|
# the new schema. If `true`, the fields will replace the existing
|
@@ -552,7 +645,7 @@ module Google
|
|
552
645
|
# @yield [schema] a block for setting the schema
|
553
646
|
# @yieldparam [Schema] schema the object accepting the schema
|
554
647
|
#
|
555
|
-
# @return [Google::Cloud::Bigquery::Schema] A frozen schema object.
|
648
|
+
# @return [Google::Cloud::Bigquery::Schema, nil] A frozen schema object.
|
556
649
|
#
|
557
650
|
# @example
|
558
651
|
# require "google/cloud/bigquery"
|
@@ -572,7 +665,8 @@ module Google
|
|
572
665
|
# @!group Attributes
|
573
666
|
#
|
574
667
|
def schema replace: false
|
575
|
-
|
668
|
+
return nil if reference? && !block_given?
|
669
|
+
reload! unless resource_full?
|
576
670
|
schema_builder = Schema.from_gapi @gapi.schema
|
577
671
|
if block_given?
|
578
672
|
schema_builder = Schema.from_gapi if replace
|
@@ -588,7 +682,7 @@ module Google
|
|
588
682
|
##
|
589
683
|
# The fields of the table, obtained from its schema.
|
590
684
|
#
|
591
|
-
# @return [Array<Schema::Field
|
685
|
+
# @return [Array<Schema::Field>, nil] An array of field objects.
|
592
686
|
#
|
593
687
|
# @example
|
594
688
|
# require "google/cloud/bigquery"
|
@@ -604,13 +698,14 @@ module Google
|
|
604
698
|
# @!group Attributes
|
605
699
|
#
|
606
700
|
def fields
|
701
|
+
return nil if reference?
|
607
702
|
schema.fields
|
608
703
|
end
|
609
704
|
|
610
705
|
##
|
611
706
|
# The names of the columns in the table, obtained from its schema.
|
612
707
|
#
|
613
|
-
# @return [Array<Symbol
|
708
|
+
# @return [Array<Symbol>, nil] An array of column names.
|
614
709
|
#
|
615
710
|
# @example
|
616
711
|
# require "google/cloud/bigquery"
|
@@ -626,6 +721,7 @@ module Google
|
|
626
721
|
# @!group Attributes
|
627
722
|
#
|
628
723
|
def headers
|
724
|
+
return nil if reference?
|
629
725
|
schema.headers
|
630
726
|
end
|
631
727
|
|
@@ -642,11 +738,13 @@ module Google
|
|
642
738
|
# @see https://cloud.google.com/bigquery/external-data-sources
|
643
739
|
# Querying External Data Sources
|
644
740
|
#
|
645
|
-
# @return [External::DataSource] The external data source.
|
741
|
+
# @return [External::DataSource, nil] The external data source.
|
646
742
|
#
|
647
743
|
# @!group Attributes
|
648
744
|
#
|
649
745
|
def external
|
746
|
+
return nil if reference?
|
747
|
+
ensure_full_data!
|
650
748
|
return nil if @gapi.external_data_configuration.nil?
|
651
749
|
External.from_gapi(@gapi.external_data_configuration).freeze
|
652
750
|
end
|
@@ -661,6 +759,10 @@ module Google
|
|
661
759
|
# Use only if the table represents an External Data Source. See
|
662
760
|
# {#external?} and {External::DataSource}.
|
663
761
|
#
|
762
|
+
# If the table is not a full resource representation (see
|
763
|
+
# {#resource_full?}), the full representation will be retrieved before
|
764
|
+
# the update to comply with ETag-based optimistic concurrency control.
|
765
|
+
#
|
664
766
|
# @see https://cloud.google.com/bigquery/external-data-sources
|
665
767
|
# Querying External Data Sources
|
666
768
|
#
|
@@ -669,6 +771,7 @@ module Google
|
|
669
771
|
# @!group Attributes
|
670
772
|
#
|
671
773
|
def external= external
|
774
|
+
reload! unless resource_full?
|
672
775
|
@gapi.external_data_configuration = external.to_gapi
|
673
776
|
patch_gapi! :external_data_configuration
|
674
777
|
end
|
@@ -679,11 +782,14 @@ module Google
|
|
679
782
|
# if the table is not being streamed to or if there is no data in the
|
680
783
|
# streaming buffer.
|
681
784
|
#
|
682
|
-
# @return [Integer] The estimated number of bytes in the buffer
|
785
|
+
# @return [Integer, nil] The estimated number of bytes in the buffer, or
|
786
|
+
# `nil` if not present or the object is a reference (see
|
787
|
+
# {#reference?}).
|
683
788
|
#
|
684
789
|
# @!group Attributes
|
685
790
|
#
|
686
791
|
def buffer_bytes
|
792
|
+
return nil if reference?
|
687
793
|
ensure_full_data!
|
688
794
|
@gapi.streaming_buffer.estimated_bytes if @gapi.streaming_buffer
|
689
795
|
end
|
@@ -694,11 +800,14 @@ module Google
|
|
694
800
|
# if the table is not being streamed to or if there is no data in the
|
695
801
|
# streaming buffer.
|
696
802
|
#
|
697
|
-
# @return [Integer] The estimated number of rows in the buffer
|
803
|
+
# @return [Integer, nil] The estimated number of rows in the buffer, or
|
804
|
+
# `nil` if not present or the object is a reference (see
|
805
|
+
# {#reference?}).
|
698
806
|
#
|
699
807
|
# @!group Attributes
|
700
808
|
#
|
701
809
|
def buffer_rows
|
810
|
+
return nil if reference?
|
702
811
|
ensure_full_data!
|
703
812
|
@gapi.streaming_buffer.estimated_rows if @gapi.streaming_buffer
|
704
813
|
end
|
@@ -708,11 +817,13 @@ module Google
|
|
708
817
|
# buffer, if one is present. This field will be absent if the table is
|
709
818
|
# not being streamed to or if there is no data in the streaming buffer.
|
710
819
|
#
|
711
|
-
# @return [Time, nil] The oldest entry time
|
820
|
+
# @return [Time, nil] The oldest entry time, or `nil` if not present or
|
821
|
+
# the object is a reference (see {#reference?}).
|
712
822
|
#
|
713
823
|
# @!group Attributes
|
714
824
|
#
|
715
825
|
def buffer_oldest_at
|
826
|
+
return nil if reference?
|
716
827
|
ensure_full_data!
|
717
828
|
return nil unless @gapi.streaming_buffer
|
718
829
|
oldest_entry_time = @gapi.streaming_buffer.oldest_entry_time
|
@@ -723,9 +834,142 @@ module Google
|
|
723
834
|
end
|
724
835
|
end
|
725
836
|
|
837
|
+
##
|
838
|
+
# The query that executes each time the view is loaded.
|
839
|
+
#
|
840
|
+
# @return [String] The query that defines the view.
|
841
|
+
#
|
842
|
+
# @!group Attributes
|
843
|
+
#
|
844
|
+
def query
|
845
|
+
@gapi.view.query if @gapi.view
|
846
|
+
end
|
847
|
+
|
848
|
+
##
|
849
|
+
# Updates the query that executes each time the view is loaded.
|
850
|
+
#
|
851
|
+
# This sets the query using standard SQL. To specify legacy SQL or to
|
852
|
+
# use user-defined function resources use (#set_query) instead.
|
853
|
+
#
|
854
|
+
# @see https://cloud.google.com/bigquery/query-reference BigQuery Query
|
855
|
+
# Reference
|
856
|
+
#
|
857
|
+
# @param [String] new_query The query that defines the view.
|
858
|
+
#
|
859
|
+
# @example
|
860
|
+
# require "google/cloud/bigquery"
|
861
|
+
#
|
862
|
+
# bigquery = Google::Cloud::Bigquery.new
|
863
|
+
# dataset = bigquery.dataset "my_dataset"
|
864
|
+
# view = dataset.table "my_view"
|
865
|
+
#
|
866
|
+
# view.query = "SELECT first_name FROM " \
|
867
|
+
# "`my_project.my_dataset.my_table`"
|
868
|
+
#
|
869
|
+
# @!group Lifecycle
|
870
|
+
#
|
871
|
+
def query= new_query
|
872
|
+
set_query new_query
|
873
|
+
end
|
874
|
+
|
875
|
+
##
|
876
|
+
# Updates the query that executes each time the view is loaded. Allows
|
877
|
+
# setting of standard vs. legacy SQL and user-defined function
|
878
|
+
# resources.
|
879
|
+
#
|
880
|
+
# @see https://cloud.google.com/bigquery/query-reference BigQuery Query
|
881
|
+
# Reference
|
882
|
+
#
|
883
|
+
# @param [String] query The query that defines the view.
|
884
|
+
# @param [Boolean] standard_sql Specifies whether to use BigQuery's
|
885
|
+
# [standard
|
886
|
+
# SQL](https://cloud.google.com/bigquery/docs/reference/standard-sql/)
|
887
|
+
# dialect. Optional. The default value is true.
|
888
|
+
# @param [Boolean] legacy_sql Specifies whether to use BigQuery's
|
889
|
+
# [legacy
|
890
|
+
# SQL](https://cloud.google.com/bigquery/docs/reference/legacy-sql)
|
891
|
+
# dialect. Optional. The default value is false.
|
892
|
+
# @param [Array<String>, String] udfs User-defined function resources
|
893
|
+
# used in the query. May be either a code resource to load from a
|
894
|
+
# Google Cloud Storage URI (`gs://bucket/path`), or an inline resource
|
895
|
+
# that contains code for a user-defined function (UDF). Providing an
|
896
|
+
# inline code resource is equivalent to providing a URI for a file
|
897
|
+
# containing the same code. See [User-Defined
|
898
|
+
# Functions](https://cloud.google.com/bigquery/docs/reference/standard-sql/user-defined-functions).
|
899
|
+
#
|
900
|
+
# @example
|
901
|
+
# require "google/cloud/bigquery"
|
902
|
+
#
|
903
|
+
# bigquery = Google::Cloud::Bigquery.new
|
904
|
+
# dataset = bigquery.dataset "my_dataset"
|
905
|
+
# view = dataset.table "my_view"
|
906
|
+
#
|
907
|
+
# view.set_query "SELECT first_name FROM " \
|
908
|
+
# "`my_project.my_dataset.my_table`",
|
909
|
+
# standard_sql: true
|
910
|
+
#
|
911
|
+
# @!group Lifecycle
|
912
|
+
#
|
913
|
+
def set_query query, standard_sql: nil, legacy_sql: nil, udfs: nil
|
914
|
+
@gapi.view = Google::Apis::BigqueryV2::ViewDefinition.new \
|
915
|
+
query: query,
|
916
|
+
use_legacy_sql: Convert.resolve_legacy_sql(standard_sql,
|
917
|
+
legacy_sql),
|
918
|
+
user_defined_function_resources: udfs_gapi(udfs)
|
919
|
+
patch_gapi! :view
|
920
|
+
end
|
921
|
+
|
922
|
+
##
|
923
|
+
# Checks if the view's query is using legacy sql.
|
924
|
+
#
|
925
|
+
# @return [Boolean] `true` when legacy sql is used, `false` otherwise.
|
926
|
+
#
|
927
|
+
# @!group Attributes
|
928
|
+
#
|
929
|
+
def query_legacy_sql?
|
930
|
+
val = @gapi.view.use_legacy_sql
|
931
|
+
return true if val.nil?
|
932
|
+
val
|
933
|
+
end
|
934
|
+
|
935
|
+
##
|
936
|
+
# Checks if the view's query is using standard sql.
|
937
|
+
#
|
938
|
+
# @return [Boolean] `true` when standard sql is used, `false` otherwise.
|
939
|
+
#
|
940
|
+
# @!group Attributes
|
941
|
+
#
|
942
|
+
def query_standard_sql?
|
943
|
+
!query_legacy_sql?
|
944
|
+
end
|
945
|
+
|
946
|
+
##
|
947
|
+
# The user-defined function resources used in the view's query. May be
|
948
|
+
# either a code resource to load from a Google Cloud Storage URI
|
949
|
+
# (`gs://bucket/path`), or an inline resource that contains code for a
|
950
|
+
# user-defined function (UDF). Providing an inline code resource is
|
951
|
+
# equivalent to providing a URI for a file containing the same code. See
|
952
|
+
# [User-Defined
|
953
|
+
# Functions](https://cloud.google.com/bigquery/docs/reference/standard-sql/user-defined-functions).
|
954
|
+
#
|
955
|
+
# @return [Array<String>] An array containing Google Cloud Storage URIs
|
956
|
+
# and/or inline source code.
|
957
|
+
#
|
958
|
+
# @!group Attributes
|
959
|
+
#
|
960
|
+
def query_udfs
|
961
|
+
udfs_gapi = @gapi.view.user_defined_function_resources
|
962
|
+
return [] if udfs_gapi.nil?
|
963
|
+
Array(udfs_gapi).map { |udf| udf.inline_code || udf.resource_uri }
|
964
|
+
end
|
965
|
+
|
726
966
|
##
|
727
967
|
# Retrieves data from the table.
|
728
968
|
#
|
969
|
+
# If the table is not a full resource representation (see
|
970
|
+
# {#resource_full?}), the full representation will be retrieved before
|
971
|
+
# the data retrieval.
|
972
|
+
#
|
729
973
|
# @param [String] token Page token, returned by a previous call,
|
730
974
|
# identifying the result set.
|
731
975
|
#
|
@@ -765,9 +1009,11 @@ module Google
|
|
765
1009
|
#
|
766
1010
|
def data token: nil, max: nil, start: nil
|
767
1011
|
ensure_service!
|
1012
|
+
reload! unless resource_full?
|
768
1013
|
options = { token: token, max: max, start: start }
|
769
|
-
|
770
|
-
|
1014
|
+
data_json = service.list_tabledata \
|
1015
|
+
dataset_id, table_id, options
|
1016
|
+
Data.from_gapi_json data_json, gapi, service
|
771
1017
|
end
|
772
1018
|
|
773
1019
|
##
|
@@ -1438,6 +1684,19 @@ module Google
|
|
1438
1684
|
# ]
|
1439
1685
|
# table.insert rows
|
1440
1686
|
#
|
1687
|
+
# @example Avoid retrieving the dataset and table with `skip_lookup`:
|
1688
|
+
# require "google/cloud/bigquery"
|
1689
|
+
#
|
1690
|
+
# bigquery = Google::Cloud::Bigquery.new
|
1691
|
+
# dataset = bigquery.dataset "my_dataset", skip_lookup: true
|
1692
|
+
# table = dataset.table "my_table", skip_lookup: true
|
1693
|
+
#
|
1694
|
+
# rows = [
|
1695
|
+
# { "first_name" => "Alice", "age" => 21 },
|
1696
|
+
# { "first_name" => "Bob", "age" => 22 }
|
1697
|
+
# ]
|
1698
|
+
# table.insert rows
|
1699
|
+
#
|
1441
1700
|
# @!group Data
|
1442
1701
|
#
|
1443
1702
|
def insert rows, skip_invalid: nil, ignore_unknown: nil
|
@@ -1451,7 +1710,7 @@ module Google
|
|
1451
1710
|
end
|
1452
1711
|
|
1453
1712
|
##
|
1454
|
-
# Create an
|
1713
|
+
# Create an asynchronous inserter object used to insert rows in batches.
|
1455
1714
|
#
|
1456
1715
|
# @param [Boolean] skip_invalid Insert all valid rows of a request, even
|
1457
1716
|
# if invalid rows exist. The default value is `false`, which causes
|
@@ -1469,8 +1728,8 @@ module Google
|
|
1469
1728
|
# @attr_reader [Numeric] threads The number of threads used to insert
|
1470
1729
|
# batches of rows. Default is 4.
|
1471
1730
|
# @yield [response] the callback for when a batch of rows is inserted
|
1472
|
-
# @yieldparam [
|
1473
|
-
# insert
|
1731
|
+
# @yieldparam [Table::AsyncInserter::Result] result the result of the
|
1732
|
+
# asynchronous insert
|
1474
1733
|
#
|
1475
1734
|
# @return [Table::AsyncInserter] Returns inserter object.
|
1476
1735
|
#
|
@@ -1480,9 +1739,13 @@ module Google
|
|
1480
1739
|
# bigquery = Google::Cloud::Bigquery.new
|
1481
1740
|
# dataset = bigquery.dataset "my_dataset"
|
1482
1741
|
# table = dataset.table "my_table"
|
1483
|
-
# inserter = table.insert_async do |
|
1484
|
-
#
|
1485
|
-
#
|
1742
|
+
# inserter = table.insert_async do |result|
|
1743
|
+
# if result.error?
|
1744
|
+
# log_error result.error
|
1745
|
+
# else
|
1746
|
+
# log_insert "inserted #{result.insert_count} rows " \
|
1747
|
+
# "with #{result.error_count} errors"
|
1748
|
+
# end
|
1486
1749
|
# end
|
1487
1750
|
#
|
1488
1751
|
# rows = [
|
@@ -1529,6 +1792,19 @@ module Google
|
|
1529
1792
|
##
|
1530
1793
|
# Reloads the table with current data from the BigQuery service.
|
1531
1794
|
#
|
1795
|
+
# @return [Google::Cloud::Bigquery::Table] Returns the reloaded
|
1796
|
+
# table.
|
1797
|
+
#
|
1798
|
+
# @example Skip retrieving the table from the service, then load it:
|
1799
|
+
# require "google/cloud/bigquery"
|
1800
|
+
#
|
1801
|
+
# bigquery = Google::Cloud::Bigquery.new
|
1802
|
+
#
|
1803
|
+
# dataset = bigquery.dataset "my_dataset"
|
1804
|
+
# table = dataset.table "my_table", skip_lookup: true
|
1805
|
+
#
|
1806
|
+
# table.reload!
|
1807
|
+
#
|
1532
1808
|
# @!group Lifecycle
|
1533
1809
|
#
|
1534
1810
|
def reload!
|
@@ -1538,16 +1814,152 @@ module Google
|
|
1538
1814
|
end
|
1539
1815
|
alias_method :refresh!, :reload!
|
1540
1816
|
|
1817
|
+
##
|
1818
|
+
# Determines whether the table exists in the BigQuery service. The
|
1819
|
+
# result is cached locally.
|
1820
|
+
#
|
1821
|
+
# @return [Boolean] `true` when the table exists in the BigQuery
|
1822
|
+
# service, `false` otherwise.
|
1823
|
+
#
|
1824
|
+
# @example
|
1825
|
+
# require "google/cloud/bigquery"
|
1826
|
+
#
|
1827
|
+
# bigquery = Google::Cloud::Bigquery.new
|
1828
|
+
#
|
1829
|
+
# dataset = bigquery.dataset "my_dataset"
|
1830
|
+
# table = dataset.table "my_table", skip_lookup: true
|
1831
|
+
# table.exists? # true
|
1832
|
+
#
|
1833
|
+
def exists?
|
1834
|
+
# Always true if we have a gapi object
|
1835
|
+
return true unless reference?
|
1836
|
+
# If we have a value, return it
|
1837
|
+
return @exists unless @exists.nil?
|
1838
|
+
ensure_gapi!
|
1839
|
+
@exists = true
|
1840
|
+
rescue Google::Cloud::NotFoundError
|
1841
|
+
@exists = false
|
1842
|
+
end
|
1843
|
+
|
1844
|
+
##
|
1845
|
+
# Whether the table was created without retrieving the resource
|
1846
|
+
# representation from the BigQuery service.
|
1847
|
+
#
|
1848
|
+
# @return [Boolean] `true` when the table is just a local reference
|
1849
|
+
# object, `false` otherwise.
|
1850
|
+
#
|
1851
|
+
# @example
|
1852
|
+
# require "google/cloud/bigquery"
|
1853
|
+
#
|
1854
|
+
# bigquery = Google::Cloud::Bigquery.new
|
1855
|
+
#
|
1856
|
+
# dataset = bigquery.dataset "my_dataset"
|
1857
|
+
# table = dataset.table "my_table", skip_lookup: true
|
1858
|
+
#
|
1859
|
+
# table.reference? # true
|
1860
|
+
# table.reload!
|
1861
|
+
# table.reference? # false
|
1862
|
+
#
|
1863
|
+
def reference?
|
1864
|
+
@gapi.nil?
|
1865
|
+
end
|
1866
|
+
|
1867
|
+
##
|
1868
|
+
# Whether the table was created with a resource representation from
|
1869
|
+
# the BigQuery service.
|
1870
|
+
#
|
1871
|
+
# @return [Boolean] `true` when the table was created with a resource
|
1872
|
+
# representation, `false` otherwise.
|
1873
|
+
#
|
1874
|
+
# @example
|
1875
|
+
# require "google/cloud/bigquery"
|
1876
|
+
#
|
1877
|
+
# bigquery = Google::Cloud::Bigquery.new
|
1878
|
+
#
|
1879
|
+
# dataset = bigquery.dataset "my_dataset"
|
1880
|
+
# table = dataset.table "my_table", skip_lookup: true
|
1881
|
+
#
|
1882
|
+
# table.resource? # false
|
1883
|
+
# table.reload!
|
1884
|
+
# table.resource? # true
|
1885
|
+
#
|
1886
|
+
def resource?
|
1887
|
+
!@gapi.nil?
|
1888
|
+
end
|
1889
|
+
|
1890
|
+
##
|
1891
|
+
# Whether the table was created with a partial resource representation
|
1892
|
+
# from the BigQuery service by retrieval through {Dataset#tables}.
|
1893
|
+
# See [Tables: list
|
1894
|
+
# response](https://cloud.google.com/bigquery/docs/reference/rest/v2/tables/list#response)
|
1895
|
+
# for the contents of the partial representation. Accessing any
|
1896
|
+
# attribute outside of the partial representation will result in loading
|
1897
|
+
# the full representation.
|
1898
|
+
#
|
1899
|
+
# @return [Boolean] `true` when the table was created with a partial
|
1900
|
+
# resource representation, `false` otherwise.
|
1901
|
+
#
|
1902
|
+
# @example
|
1903
|
+
# require "google/cloud/bigquery"
|
1904
|
+
#
|
1905
|
+
# bigquery = Google::Cloud::Bigquery.new
|
1906
|
+
#
|
1907
|
+
# dataset = bigquery.dataset "my_dataset"
|
1908
|
+
# table = dataset.tables.first
|
1909
|
+
#
|
1910
|
+
# table.resource_partial? # true
|
1911
|
+
# table.description # Loads the full resource.
|
1912
|
+
# table.resource_partial? # false
|
1913
|
+
#
|
1914
|
+
def resource_partial?
|
1915
|
+
@gapi.is_a? Google::Apis::BigqueryV2::TableList::Table
|
1916
|
+
end
|
1917
|
+
|
1918
|
+
##
|
1919
|
+
# Whether the table was created with a full resource representation
|
1920
|
+
# from the BigQuery service.
|
1921
|
+
#
|
1922
|
+
# @return [Boolean] `true` when the table was created with a full
|
1923
|
+
# resource representation, `false` otherwise.
|
1924
|
+
#
|
1925
|
+
# @example
|
1926
|
+
# require "google/cloud/bigquery"
|
1927
|
+
#
|
1928
|
+
# bigquery = Google::Cloud::Bigquery.new
|
1929
|
+
#
|
1930
|
+
# dataset = bigquery.dataset "my_dataset"
|
1931
|
+
# table = dataset.table "my_table"
|
1932
|
+
#
|
1933
|
+
# table.resource_full? # true
|
1934
|
+
#
|
1935
|
+
def resource_full?
|
1936
|
+
@gapi.is_a? Google::Apis::BigqueryV2::Table
|
1937
|
+
end
|
1938
|
+
|
1541
1939
|
##
|
1542
1940
|
# @private New Table from a Google API Client object.
|
1543
1941
|
def self.from_gapi gapi, conn
|
1544
|
-
|
1545
|
-
klass.new.tap do |f|
|
1942
|
+
new.tap do |f|
|
1546
1943
|
f.gapi = gapi
|
1547
1944
|
f.service = conn
|
1548
1945
|
end
|
1549
1946
|
end
|
1550
1947
|
|
1948
|
+
##
|
1949
|
+
# @private New lazy Table object without making an HTTP request.
|
1950
|
+
def self.new_reference project_id, dataset_id, table_id, service
|
1951
|
+
# TODO: raise if dataset_id or table_id is nil?
|
1952
|
+
new.tap do |b|
|
1953
|
+
reference_gapi = Google::Apis::BigqueryV2::TableReference.new(
|
1954
|
+
project_id: project_id,
|
1955
|
+
dataset_id: dataset_id,
|
1956
|
+
table_id: table_id
|
1957
|
+
)
|
1958
|
+
b.service = service
|
1959
|
+
b.instance_variable_set :@reference, reference_gapi
|
1960
|
+
end
|
1961
|
+
end
|
1962
|
+
|
1551
1963
|
protected
|
1552
1964
|
|
1553
1965
|
##
|
@@ -1556,6 +1968,15 @@ module Google
|
|
1556
1968
|
fail "Must have active connection" unless service
|
1557
1969
|
end
|
1558
1970
|
|
1971
|
+
##
|
1972
|
+
# Ensures the Google::Apis::BigqueryV2::Table object has been loaded
|
1973
|
+
# from the service.
|
1974
|
+
def ensure_gapi!
|
1975
|
+
ensure_service!
|
1976
|
+
return unless reference?
|
1977
|
+
reload!
|
1978
|
+
end
|
1979
|
+
|
1559
1980
|
def patch_gapi! *attributes
|
1560
1981
|
return if attributes.empty?
|
1561
1982
|
ensure_service!
|
@@ -1571,11 +1992,6 @@ module Google
|
|
1571
1992
|
reload!
|
1572
1993
|
end
|
1573
1994
|
|
1574
|
-
def self.class_for gapi
|
1575
|
-
return View if gapi.type == "VIEW"
|
1576
|
-
self
|
1577
|
-
end
|
1578
|
-
|
1579
1995
|
def load_storage url, options = {}
|
1580
1996
|
# Convert to storage URL
|
1581
1997
|
url = url.to_gs_url if url.respond_to? :to_gs_url
|
@@ -1608,19 +2024,28 @@ module Google
|
|
1608
2024
|
# Load the complete representation of the table if it has been
|
1609
2025
|
# only partially loaded by a request to the API list method.
|
1610
2026
|
def ensure_full_data!
|
1611
|
-
|
1612
|
-
end
|
1613
|
-
|
1614
|
-
def reload_gapi!
|
1615
|
-
ensure_service!
|
1616
|
-
gapi = service.get_table dataset_id, table_id
|
1617
|
-
@gapi = gapi
|
2027
|
+
reload! unless data_complete?
|
1618
2028
|
end
|
1619
2029
|
|
1620
2030
|
def data_complete?
|
1621
2031
|
@gapi.is_a? Google::Apis::BigqueryV2::Table
|
1622
2032
|
end
|
1623
2033
|
|
2034
|
+
##
|
2035
|
+
# Supports views.
|
2036
|
+
def udfs_gapi array_or_str
|
2037
|
+
return [] if array_or_str.nil?
|
2038
|
+
Array(array_or_str).map do |uri_or_code|
|
2039
|
+
resource = Google::Apis::BigqueryV2::UserDefinedFunctionResource.new
|
2040
|
+
if uri_or_code.start_with?("gs://")
|
2041
|
+
resource.resource_uri = uri_or_code
|
2042
|
+
else
|
2043
|
+
resource.inline_code = uri_or_code
|
2044
|
+
end
|
2045
|
+
resource
|
2046
|
+
end
|
2047
|
+
end
|
2048
|
+
|
1624
2049
|
private
|
1625
2050
|
|
1626
2051
|
def get_table_ref table
|