google-cloud-bigquery 0.20.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/lib/google-cloud-bigquery.rb +122 -0
- data/lib/google/cloud/bigquery.rb +353 -0
- data/lib/google/cloud/bigquery/copy_job.rb +99 -0
- data/lib/google/cloud/bigquery/credentials.rb +31 -0
- data/lib/google/cloud/bigquery/data.rb +244 -0
- data/lib/google/cloud/bigquery/dataset.rb +758 -0
- data/lib/google/cloud/bigquery/dataset/access.rb +509 -0
- data/lib/google/cloud/bigquery/dataset/list.rb +171 -0
- data/lib/google/cloud/bigquery/extract_job.rb +120 -0
- data/lib/google/cloud/bigquery/insert_response.rb +83 -0
- data/lib/google/cloud/bigquery/job.rb +301 -0
- data/lib/google/cloud/bigquery/job/list.rb +174 -0
- data/lib/google/cloud/bigquery/load_job.rb +203 -0
- data/lib/google/cloud/bigquery/project.rb +481 -0
- data/lib/google/cloud/bigquery/query_data.rb +238 -0
- data/lib/google/cloud/bigquery/query_job.rb +139 -0
- data/lib/google/cloud/bigquery/schema.rb +361 -0
- data/lib/google/cloud/bigquery/service.rb +502 -0
- data/lib/google/cloud/bigquery/table.rb +1141 -0
- data/lib/google/cloud/bigquery/table/list.rb +182 -0
- data/lib/google/cloud/bigquery/version.rb +22 -0
- data/lib/google/cloud/bigquery/view.rb +478 -0
- metadata +208 -0
@@ -0,0 +1,99 @@
|
|
1
|
+
# Copyright 2015 Google Inc. All rights reserved.
|
2
|
+
#
|
3
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
4
|
+
# you may not use this file except in compliance with the License.
|
5
|
+
# You may obtain a copy of the License at
|
6
|
+
#
|
7
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
8
|
+
#
|
9
|
+
# Unless required by applicable law or agreed to in writing, software
|
10
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
11
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
12
|
+
# See the License for the specific language governing permissions and
|
13
|
+
# limitations under the License.
|
14
|
+
|
15
|
+
|
16
|
+
module Google
|
17
|
+
module Cloud
|
18
|
+
module Bigquery
|
19
|
+
##
|
20
|
+
# # CopyJob
|
21
|
+
#
|
22
|
+
# A {Job} subclass representing a copy operation that may be performed on
|
23
|
+
# a {Table}. A CopyJob instance is created when you call {Table#copy}.
|
24
|
+
#
|
25
|
+
# @see https://cloud.google.com/bigquery/docs/tables#copyingtable Copying
|
26
|
+
# an Existing Table
|
27
|
+
# @see https://cloud.google.com/bigquery/docs/reference/v2/jobs Jobs API
|
28
|
+
# reference
|
29
|
+
#
|
30
|
+
class CopyJob < Job
|
31
|
+
##
|
32
|
+
# The table from which data is copied. This is the table on
|
33
|
+
# which {Table#copy} was called. Returns a {Table} instance.
|
34
|
+
def source
|
35
|
+
table = @gapi.configuration.copy.source_table
|
36
|
+
return nil unless table
|
37
|
+
retrieve_table table.project_id,
|
38
|
+
table.dataset_id,
|
39
|
+
table.table_id
|
40
|
+
end
|
41
|
+
|
42
|
+
##
|
43
|
+
# The table to which data is copied. Returns a {Table} instance.
|
44
|
+
def destination
|
45
|
+
table = @gapi.configuration.copy.destination_table
|
46
|
+
return nil unless table
|
47
|
+
retrieve_table table.project_id,
|
48
|
+
table.dataset_id,
|
49
|
+
table.table_id
|
50
|
+
end
|
51
|
+
|
52
|
+
##
|
53
|
+
# Checks if the create disposition for the job is `CREATE_IF_NEEDED`,
|
54
|
+
# which provides the following behavior: If the table does not exist,
|
55
|
+
# the copy operation creates the table. This is the default.
|
56
|
+
def create_if_needed?
|
57
|
+
disp = @gapi.configuration.copy.create_disposition
|
58
|
+
disp == "CREATE_IF_NEEDED"
|
59
|
+
end
|
60
|
+
|
61
|
+
##
|
62
|
+
# Checks if the create disposition for the job is `CREATE_NEVER`, which
|
63
|
+
# provides the following behavior: The table must already exist; if it
|
64
|
+
# does not, an error is returned in the job result.
|
65
|
+
def create_never?
|
66
|
+
disp = @gapi.configuration.copy.create_disposition
|
67
|
+
disp == "CREATE_NEVER"
|
68
|
+
end
|
69
|
+
|
70
|
+
##
|
71
|
+
# Checks if the write disposition for the job is `WRITE_TRUNCATE`, which
|
72
|
+
# provides the following behavior: If the table already exists, the copy
|
73
|
+
# operation overwrites the table data.
|
74
|
+
def write_truncate?
|
75
|
+
disp = @gapi.configuration.copy.write_disposition
|
76
|
+
disp == "WRITE_TRUNCATE"
|
77
|
+
end
|
78
|
+
|
79
|
+
##
|
80
|
+
# Checks if the write disposition for the job is `WRITE_APPEND`, which
|
81
|
+
# provides the following behavior: If the table already exists, the copy
|
82
|
+
# operation appends the data to the table.
|
83
|
+
def write_append?
|
84
|
+
disp = @gapi.configuration.copy.write_disposition
|
85
|
+
disp == "WRITE_APPEND"
|
86
|
+
end
|
87
|
+
|
88
|
+
##
|
89
|
+
# Checks if the write disposition for the job is `WRITE_EMPTY`, which
|
90
|
+
# provides the following behavior: If the table already exists and
|
91
|
+
# contains data, the job will have an error. This is the default.
|
92
|
+
def write_empty?
|
93
|
+
disp = @gapi.configuration.copy.write_disposition
|
94
|
+
disp == "WRITE_EMPTY"
|
95
|
+
end
|
96
|
+
end
|
97
|
+
end
|
98
|
+
end
|
99
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
# Copyright 2015 Google Inc. All rights reserved.
|
2
|
+
#
|
3
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
4
|
+
# you may not use this file except in compliance with the License.
|
5
|
+
# You may obtain a copy of the License at
|
6
|
+
#
|
7
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
8
|
+
#
|
9
|
+
# Unless required by applicable law or agreed to in writing, software
|
10
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
11
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
12
|
+
# See the License for the specific language governing permissions and
|
13
|
+
# limitations under the License.
|
14
|
+
|
15
|
+
|
16
|
+
require "google/cloud/credentials"
|
17
|
+
|
18
|
+
module Google
|
19
|
+
module Cloud
|
20
|
+
module Bigquery
|
21
|
+
##
|
22
|
+
# @private Represents the Oauth2 signing logic for Bigquery.
|
23
|
+
class Credentials < Google::Cloud::Credentials
|
24
|
+
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
|
27
|
+
GCLOUD_KEYFILE_JSON)
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,244 @@
|
|
1
|
+
# Copyright 2015 Google Inc. All rights reserved.
|
2
|
+
#
|
3
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
4
|
+
# you may not use this file except in compliance with the License.
|
5
|
+
# You may obtain a copy of the License at
|
6
|
+
#
|
7
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
8
|
+
#
|
9
|
+
# Unless required by applicable law or agreed to in writing, software
|
10
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
11
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
12
|
+
# See the License for the specific language governing permissions and
|
13
|
+
# limitations under the License.
|
14
|
+
|
15
|
+
|
16
|
+
require "delegate"
|
17
|
+
require "google/cloud/bigquery/service"
|
18
|
+
|
19
|
+
module Google
|
20
|
+
module Cloud
|
21
|
+
module Bigquery
|
22
|
+
##
|
23
|
+
# # Data
|
24
|
+
#
|
25
|
+
# Represents {Table} Data as a list of name/value pairs.
|
26
|
+
# Also contains metadata such as `etag` and `total`.
|
27
|
+
class Data < DelegateClass(::Array)
|
28
|
+
##
|
29
|
+
# @private The {Table} object the data belongs to.
|
30
|
+
attr_accessor :table
|
31
|
+
|
32
|
+
##
|
33
|
+
# @private The Google API Client object.
|
34
|
+
attr_accessor :gapi
|
35
|
+
|
36
|
+
# @private
|
37
|
+
def initialize arr = []
|
38
|
+
@table = nil
|
39
|
+
@gapi = {}
|
40
|
+
super arr
|
41
|
+
end
|
42
|
+
|
43
|
+
##
|
44
|
+
# The resource type of the API response.
|
45
|
+
def kind
|
46
|
+
@gapi.kind
|
47
|
+
end
|
48
|
+
|
49
|
+
##
|
50
|
+
# The etag.
|
51
|
+
def etag
|
52
|
+
@gapi.etag
|
53
|
+
end
|
54
|
+
|
55
|
+
##
|
56
|
+
# A token used for paging results.
|
57
|
+
def token
|
58
|
+
@gapi.page_token
|
59
|
+
end
|
60
|
+
|
61
|
+
# The total number of rows in the complete table.
|
62
|
+
def total
|
63
|
+
Integer @gapi.total_rows
|
64
|
+
rescue
|
65
|
+
nil
|
66
|
+
end
|
67
|
+
|
68
|
+
##
|
69
|
+
# Whether there is a next page of data.
|
70
|
+
#
|
71
|
+
# @return [Boolean]
|
72
|
+
#
|
73
|
+
# @example
|
74
|
+
# require "google/cloud"
|
75
|
+
#
|
76
|
+
# gcloud = Google::Cloud.new
|
77
|
+
# bigquery = gcloud.bigquery
|
78
|
+
# table = dataset.table "my_table"
|
79
|
+
#
|
80
|
+
# data = table.data
|
81
|
+
# if data.next?
|
82
|
+
# next_data = data.next
|
83
|
+
# end
|
84
|
+
#
|
85
|
+
def next?
|
86
|
+
!token.nil?
|
87
|
+
end
|
88
|
+
|
89
|
+
##
|
90
|
+
# Retrieve the next page of data.
|
91
|
+
#
|
92
|
+
# @return [Data]
|
93
|
+
#
|
94
|
+
# @example
|
95
|
+
# require "google/cloud"
|
96
|
+
#
|
97
|
+
# gcloud = Google::Cloud.new
|
98
|
+
# bigquery = gcloud.bigquery
|
99
|
+
# table = dataset.table "my_table"
|
100
|
+
#
|
101
|
+
# data = table.data
|
102
|
+
# if data.next?
|
103
|
+
# next_data = data.next
|
104
|
+
# end
|
105
|
+
#
|
106
|
+
def next
|
107
|
+
return nil unless next?
|
108
|
+
ensure_table!
|
109
|
+
table.data token: token
|
110
|
+
end
|
111
|
+
|
112
|
+
##
|
113
|
+
# Retrieves all rows by repeatedly loading {#next} until {#next?}
|
114
|
+
# returns `false`. Calls the given block once for each row, which is
|
115
|
+
# passed as the parameter.
|
116
|
+
#
|
117
|
+
# An Enumerator is returned if no block is given.
|
118
|
+
#
|
119
|
+
# This method may make several API calls until all rows are retrieved.
|
120
|
+
# Be sure to use as narrow a search criteria as possible. Please use
|
121
|
+
# with caution.
|
122
|
+
#
|
123
|
+
# @param [Integer] request_limit The upper limit of API requests to make
|
124
|
+
# to load all data. Default is no limit.
|
125
|
+
# @yield [row] The block for accessing each row of data.
|
126
|
+
# @yieldparam [Hash] row The row object.
|
127
|
+
#
|
128
|
+
# @return [Enumerator]
|
129
|
+
#
|
130
|
+
# @example Iterating each rows by passing a block:
|
131
|
+
# require "google/cloud"
|
132
|
+
#
|
133
|
+
# gcloud = Google::Cloud.new
|
134
|
+
# bigquery = gcloud.bigquery
|
135
|
+
# table = dataset.table "my_table"
|
136
|
+
#
|
137
|
+
# table.data.all do |row|
|
138
|
+
# puts row["word"]
|
139
|
+
# end
|
140
|
+
#
|
141
|
+
# @example Using the enumerator by not passing a block:
|
142
|
+
# require "google/cloud"
|
143
|
+
#
|
144
|
+
# gcloud = Google::Cloud.new
|
145
|
+
# bigquery = gcloud.bigquery
|
146
|
+
# table = dataset.table "my_table"
|
147
|
+
#
|
148
|
+
# words = table.data.all.map do |row|
|
149
|
+
# row["word"]
|
150
|
+
# end
|
151
|
+
#
|
152
|
+
# @example Limit the number of API calls made:
|
153
|
+
# require "google/cloud"
|
154
|
+
#
|
155
|
+
# gcloud = Google::Cloud.new
|
156
|
+
# bigquery = gcloud.bigquery
|
157
|
+
# table = dataset.table "my_table"
|
158
|
+
#
|
159
|
+
# table.data.all(request_limit: 10) do |row|
|
160
|
+
# puts row["word"]
|
161
|
+
# end
|
162
|
+
#
|
163
|
+
def all request_limit: nil
|
164
|
+
request_limit = request_limit.to_i if request_limit
|
165
|
+
unless block_given?
|
166
|
+
return enum_for(:all, request_limit: request_limit)
|
167
|
+
end
|
168
|
+
results = self
|
169
|
+
loop do
|
170
|
+
results.each { |r| yield r }
|
171
|
+
if request_limit
|
172
|
+
request_limit -= 1
|
173
|
+
break if request_limit < 0
|
174
|
+
end
|
175
|
+
break unless results.next?
|
176
|
+
results = results.next
|
177
|
+
end
|
178
|
+
end
|
179
|
+
|
180
|
+
##
|
181
|
+
# Represents Table Data as a list of positional values (array of
|
182
|
+
# arrays). No type conversion is made, e.g. numbers are formatted as
|
183
|
+
# strings.
|
184
|
+
def raw
|
185
|
+
Array(gapi.rows).map { |row| row.f.map(&:v) }
|
186
|
+
end
|
187
|
+
|
188
|
+
##
|
189
|
+
# @private New Data from a response object.
|
190
|
+
def self.from_gapi gapi, table
|
191
|
+
formatted_rows = format_rows gapi.rows, table.fields
|
192
|
+
|
193
|
+
data = new formatted_rows
|
194
|
+
data.table = table
|
195
|
+
data.gapi = gapi
|
196
|
+
data
|
197
|
+
end
|
198
|
+
|
199
|
+
# rubocop:disable all
|
200
|
+
# Disabled rubocop because this implementation will not last.
|
201
|
+
|
202
|
+
def self.format_rows rows, fields
|
203
|
+
headers = Array(fields).map { |f| f.name }
|
204
|
+
field_types = Array(fields).map { |f| f.type }
|
205
|
+
|
206
|
+
Array(rows).map do |row|
|
207
|
+
values = row.f.map { |f| f.v }
|
208
|
+
formatted_values = format_values field_types, values
|
209
|
+
Hash[headers.zip formatted_values]
|
210
|
+
end
|
211
|
+
end
|
212
|
+
|
213
|
+
def self.format_values field_types, values
|
214
|
+
field_types.zip(values).map do |type, value|
|
215
|
+
begin
|
216
|
+
if value.nil?
|
217
|
+
nil
|
218
|
+
elsif type == "INTEGER"
|
219
|
+
Integer value
|
220
|
+
elsif type == "FLOAT"
|
221
|
+
Float value
|
222
|
+
elsif type == "BOOLEAN"
|
223
|
+
(value == "true" ? true : (value == "false" ? false : nil))
|
224
|
+
else
|
225
|
+
value
|
226
|
+
end
|
227
|
+
rescue
|
228
|
+
value
|
229
|
+
end
|
230
|
+
end
|
231
|
+
end
|
232
|
+
# rubocop:enable all
|
233
|
+
|
234
|
+
protected
|
235
|
+
|
236
|
+
##
|
237
|
+
# Raise an error unless an active service is available.
|
238
|
+
def ensure_table!
|
239
|
+
fail "Must have active connection" unless table
|
240
|
+
end
|
241
|
+
end
|
242
|
+
end
|
243
|
+
end
|
244
|
+
end
|
@@ -0,0 +1,758 @@
|
|
1
|
+
# Copyright 2015 Google Inc. All rights reserved.
|
2
|
+
#
|
3
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
4
|
+
# you may not use this file except in compliance with the License.
|
5
|
+
# You may obtain a copy of the License at
|
6
|
+
#
|
7
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
8
|
+
#
|
9
|
+
# Unless required by applicable law or agreed to in writing, software
|
10
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
11
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
12
|
+
# See the License for the specific language governing permissions and
|
13
|
+
# limitations under the License.
|
14
|
+
|
15
|
+
|
16
|
+
require "json"
|
17
|
+
require "google/cloud/errors"
|
18
|
+
require "google/cloud/bigquery/service"
|
19
|
+
require "google/cloud/bigquery/table"
|
20
|
+
require "google/cloud/bigquery/dataset/list"
|
21
|
+
require "google/cloud/bigquery/dataset/access"
|
22
|
+
require "google/apis/bigquery_v2"
|
23
|
+
|
24
|
+
module Google
|
25
|
+
module Cloud
|
26
|
+
module Bigquery
|
27
|
+
##
|
28
|
+
# # Dataset
|
29
|
+
#
|
30
|
+
# Represents a Dataset. A dataset is a grouping mechanism that holds zero
|
31
|
+
# or more tables. Datasets are the lowest level unit of access control;
|
32
|
+
# you cannot control access at the table level. A dataset is contained
|
33
|
+
# within a specific project.
|
34
|
+
#
|
35
|
+
# @example
|
36
|
+
# require "google/cloud"
|
37
|
+
#
|
38
|
+
# gcloud = Google::Cloud.new
|
39
|
+
# bigquery = gcloud.bigquery
|
40
|
+
#
|
41
|
+
# dataset = bigquery.create_dataset "my_dataset",
|
42
|
+
# name: "My Dataset",
|
43
|
+
# description: "This is my Dataset"
|
44
|
+
#
|
45
|
+
class Dataset
|
46
|
+
##
|
47
|
+
# @private The Connection object.
|
48
|
+
attr_accessor :service
|
49
|
+
|
50
|
+
##
|
51
|
+
# @private The Google API Client object.
|
52
|
+
attr_accessor :gapi
|
53
|
+
|
54
|
+
##
|
55
|
+
# @private Create an empty Dataset object.
|
56
|
+
def initialize
|
57
|
+
@service = nil
|
58
|
+
@gapi = {}
|
59
|
+
end
|
60
|
+
|
61
|
+
##
|
62
|
+
# A unique ID for this dataset, without the project name.
|
63
|
+
# The ID must contain only letters (a-z, A-Z), numbers (0-9),
|
64
|
+
# or underscores (_). The maximum length is 1,024 characters.
|
65
|
+
#
|
66
|
+
# @!group Attributes
|
67
|
+
#
|
68
|
+
def dataset_id
|
69
|
+
@gapi.dataset_reference.dataset_id
|
70
|
+
end
|
71
|
+
|
72
|
+
##
|
73
|
+
# The ID of the project containing this dataset.
|
74
|
+
#
|
75
|
+
# @!group Attributes
|
76
|
+
#
|
77
|
+
def project_id
|
78
|
+
@gapi.dataset_reference.project_id
|
79
|
+
end
|
80
|
+
|
81
|
+
##
|
82
|
+
# @private
|
83
|
+
# The gapi fragment containing the Project ID and Dataset ID as a
|
84
|
+
# camel-cased hash.
|
85
|
+
def dataset_ref
|
86
|
+
dataset_ref = @gapi.dataset_reference
|
87
|
+
dataset_ref = dataset_ref.to_h if dataset_ref.respond_to? :to_h
|
88
|
+
dataset_ref
|
89
|
+
end
|
90
|
+
|
91
|
+
##
|
92
|
+
# A descriptive name for the dataset.
|
93
|
+
#
|
94
|
+
# @!group Attributes
|
95
|
+
#
|
96
|
+
def name
|
97
|
+
@gapi.friendly_name
|
98
|
+
end
|
99
|
+
|
100
|
+
##
|
101
|
+
# Updates the descriptive name for the dataset.
|
102
|
+
#
|
103
|
+
# @!group Attributes
|
104
|
+
#
|
105
|
+
def name= new_name
|
106
|
+
@gapi.update! friendly_name: new_name
|
107
|
+
patch_gapi! :friendly_name
|
108
|
+
end
|
109
|
+
|
110
|
+
##
|
111
|
+
# A string hash of the dataset.
|
112
|
+
#
|
113
|
+
# @!group Attributes
|
114
|
+
#
|
115
|
+
def etag
|
116
|
+
ensure_full_data!
|
117
|
+
@gapi.etag
|
118
|
+
end
|
119
|
+
|
120
|
+
##
|
121
|
+
# A URL that can be used to access the dataset using the REST API.
|
122
|
+
#
|
123
|
+
# @!group Attributes
|
124
|
+
#
|
125
|
+
def api_url
|
126
|
+
ensure_full_data!
|
127
|
+
@gapi.self_link
|
128
|
+
end
|
129
|
+
|
130
|
+
##
|
131
|
+
# A user-friendly description of the dataset.
|
132
|
+
#
|
133
|
+
# @!group Attributes
|
134
|
+
#
|
135
|
+
def description
|
136
|
+
ensure_full_data!
|
137
|
+
@gapi.description
|
138
|
+
end
|
139
|
+
|
140
|
+
##
|
141
|
+
# Updates the user-friendly description of the dataset.
|
142
|
+
#
|
143
|
+
# @!group Attributes
|
144
|
+
#
|
145
|
+
def description= new_description
|
146
|
+
@gapi.update! description: new_description
|
147
|
+
patch_gapi! :description
|
148
|
+
end
|
149
|
+
|
150
|
+
##
|
151
|
+
# The default lifetime of all tables in the dataset, in milliseconds.
|
152
|
+
#
|
153
|
+
# @!group Attributes
|
154
|
+
#
|
155
|
+
def default_expiration
|
156
|
+
ensure_full_data!
|
157
|
+
begin
|
158
|
+
Integer @gapi.default_table_expiration_ms
|
159
|
+
rescue
|
160
|
+
nil
|
161
|
+
end
|
162
|
+
end
|
163
|
+
|
164
|
+
##
|
165
|
+
# Updates the default lifetime of all tables in the dataset, in
|
166
|
+
# milliseconds.
|
167
|
+
#
|
168
|
+
# @!group Attributes
|
169
|
+
#
|
170
|
+
def default_expiration= new_default_expiration
|
171
|
+
@gapi.update! default_table_expiration_ms: new_default_expiration
|
172
|
+
patch_gapi! :default_table_expiration_ms
|
173
|
+
end
|
174
|
+
|
175
|
+
##
|
176
|
+
# The time when this dataset was created.
|
177
|
+
#
|
178
|
+
# @!group Attributes
|
179
|
+
#
|
180
|
+
def created_at
|
181
|
+
ensure_full_data!
|
182
|
+
begin
|
183
|
+
Time.at(Integer(@gapi.creation_time) / 1000.0)
|
184
|
+
rescue
|
185
|
+
nil
|
186
|
+
end
|
187
|
+
end
|
188
|
+
|
189
|
+
##
|
190
|
+
# The date when this dataset or any of its tables was last modified.
|
191
|
+
#
|
192
|
+
# @!group Attributes
|
193
|
+
#
|
194
|
+
def modified_at
|
195
|
+
ensure_full_data!
|
196
|
+
begin
|
197
|
+
Time.at(Integer(@gapi.last_modified_time) / 1000.0)
|
198
|
+
rescue
|
199
|
+
nil
|
200
|
+
end
|
201
|
+
end
|
202
|
+
|
203
|
+
##
|
204
|
+
# The geographic location where the dataset should reside. Possible
|
205
|
+
# values include EU and US. The default value is US.
|
206
|
+
#
|
207
|
+
# @!group Attributes
|
208
|
+
#
|
209
|
+
def location
|
210
|
+
ensure_full_data!
|
211
|
+
@gapi.location
|
212
|
+
end
|
213
|
+
|
214
|
+
##
|
215
|
+
# Retrieves the access rules for a Dataset. The rules can be updated
|
216
|
+
# when passing a block, see {Dataset::Access} for all the methods
|
217
|
+
# available.
|
218
|
+
#
|
219
|
+
# @see https://cloud.google.com/bigquery/access-control BigQuery Access
|
220
|
+
# Control
|
221
|
+
#
|
222
|
+
# @yield [access] a block for setting rules
|
223
|
+
# @yieldparam [Dataset::Access] access the object accepting rules
|
224
|
+
#
|
225
|
+
# @return [Google::Cloud::Bigquery::Dataset::Access]
|
226
|
+
#
|
227
|
+
# @example
|
228
|
+
# require "google/cloud"
|
229
|
+
#
|
230
|
+
# gcloud = Google::Cloud.new
|
231
|
+
# bigquery = gcloud.bigquery
|
232
|
+
# dataset = bigquery.dataset "my_dataset"
|
233
|
+
#
|
234
|
+
# dataset.access #=> [{"role"=>"OWNER",
|
235
|
+
# # "specialGroup"=>"projectOwners"},
|
236
|
+
# # {"role"=>"WRITER",
|
237
|
+
# # "specialGroup"=>"projectWriters"},
|
238
|
+
# # {"role"=>"READER",
|
239
|
+
# # "specialGroup"=>"projectReaders"},
|
240
|
+
# # {"role"=>"OWNER",
|
241
|
+
# # "userByEmail"=>"123456789-...com"}]
|
242
|
+
#
|
243
|
+
# @example Manage the access rules by passing a block:
|
244
|
+
# require "google/cloud"
|
245
|
+
#
|
246
|
+
# gcloud = Google::Cloud.new
|
247
|
+
# bigquery = gcloud.bigquery
|
248
|
+
# dataset = bigquery.dataset "my_dataset"
|
249
|
+
#
|
250
|
+
# dataset.access do |access|
|
251
|
+
# access.add_owner_group "owners@example.com"
|
252
|
+
# access.add_writer_user "writer@example.com"
|
253
|
+
# access.remove_writer_user "readers@example.com"
|
254
|
+
# access.add_reader_special :all
|
255
|
+
# access.add_reader_view other_dataset_view_object
|
256
|
+
# end
|
257
|
+
#
|
258
|
+
def access
|
259
|
+
ensure_full_data!
|
260
|
+
access_builder = Access.from_gapi @gapi
|
261
|
+
if block_given?
|
262
|
+
yield access_builder
|
263
|
+
if access_builder.changed?
|
264
|
+
@gapi.update! access: access_builder.to_gapi
|
265
|
+
patch_gapi! :access
|
266
|
+
end
|
267
|
+
end
|
268
|
+
access_builder.freeze
|
269
|
+
end
|
270
|
+
|
271
|
+
##
|
272
|
+
# Permanently deletes the dataset. The dataset must be empty before it
|
273
|
+
# can be deleted unless the `force` option is set to `true`.
|
274
|
+
#
|
275
|
+
# @param [Boolean] force If `true`, delete all the tables in the
|
276
|
+
# dataset. If `false` and the dataset contains tables, the request
|
277
|
+
# will fail. Default is `false`.
|
278
|
+
#
|
279
|
+
# @return [Boolean] Returns `true` if the dataset was deleted.
|
280
|
+
#
|
281
|
+
# @example
|
282
|
+
# require "google/cloud"
|
283
|
+
#
|
284
|
+
# gcloud = Google::Cloud.new
|
285
|
+
# bigquery = gcloud.bigquery
|
286
|
+
#
|
287
|
+
# dataset = bigquery.dataset "my_dataset"
|
288
|
+
# dataset.delete
|
289
|
+
#
|
290
|
+
# @!group Lifecycle
|
291
|
+
#
|
292
|
+
def delete force: nil
|
293
|
+
ensure_service!
|
294
|
+
service.delete_dataset dataset_id, force
|
295
|
+
true
|
296
|
+
end
|
297
|
+
|
298
|
+
##
|
299
|
+
# Creates a new table. If you are adapting existing code that was
|
300
|
+
# written for the [Rest API
|
301
|
+
# ](https://cloud.google.com/bigquery/docs/reference/v2/tables#resource),
|
302
|
+
# you can pass the table's schema as a hash (see example.)
|
303
|
+
#
|
304
|
+
# @param [String] table_id The ID of the table. The ID must contain only
|
305
|
+
# letters (a-z, A-Z), numbers (0-9), or underscores (_). The maximum
|
306
|
+
# length is 1,024 characters.
|
307
|
+
# @param [String] name A descriptive name for the table.
|
308
|
+
# @param [String] description A user-friendly description of the table.
|
309
|
+
# @param [Array<Schema::Field>] fields An array of Schema::Field objects
|
310
|
+
# specifying the schema's data types for the table. The schema may
|
311
|
+
# also be configured when passing a block.
|
312
|
+
# @yield [table] a block for setting the table
|
313
|
+
# @yieldparam [Table] table the table object to be updated
|
314
|
+
#
|
315
|
+
# @return [Google::Cloud::Bigquery::Table]
|
316
|
+
#
|
317
|
+
# @example
|
318
|
+
# require "google/cloud"
|
319
|
+
#
|
320
|
+
# gcloud = Google::Cloud.new
|
321
|
+
# bigquery = gcloud.bigquery
|
322
|
+
# dataset = bigquery.dataset "my_dataset"
|
323
|
+
# table = dataset.create_table "my_table"
|
324
|
+
#
|
325
|
+
# @example You can also pass name and description options.
|
326
|
+
# require "google/cloud"
|
327
|
+
#
|
328
|
+
# gcloud = Google::Cloud.new
|
329
|
+
# bigquery = gcloud.bigquery
|
330
|
+
# dataset = bigquery.dataset "my_dataset"
|
331
|
+
# table = dataset.create_table "my_table"
|
332
|
+
# name: "My Table",
|
333
|
+
# description: "A description of table."
|
334
|
+
#
|
335
|
+
# @example The table's schema fields can be passed as an argument.
|
336
|
+
# require "google/cloud"
|
337
|
+
#
|
338
|
+
# gcloud = Google::Cloud.new
|
339
|
+
# bigquery = gcloud.bigquery
|
340
|
+
# dataset = bigquery.dataset "my_dataset"
|
341
|
+
#
|
342
|
+
# schema_fields = [
|
343
|
+
# Google::Cloud::Bigquery::Schema::Field.new(
|
344
|
+
# "first_name", :string, mode: :required),
|
345
|
+
# Google::Cloud::Bigquery::Schema::Field.new(
|
346
|
+
# "cities_lived", :record, mode: :repeated
|
347
|
+
# fields: [
|
348
|
+
# Google::Cloud::Bigquery::Schema::Field.new(
|
349
|
+
# "place", :string, mode: :required),
|
350
|
+
# Google::Cloud::Bigquery::Schema::Field.new(
|
351
|
+
# "number_of_years", :integer, mode: :required),
|
352
|
+
# ])
|
353
|
+
# ]
|
354
|
+
# table = dataset.create_table "my_table", fields: schema_fields
|
355
|
+
#
|
356
|
+
# @example Or the table's schema can be configured with the block.
|
357
|
+
# require "google/cloud"
|
358
|
+
#
|
359
|
+
# gcloud = Google::Cloud.new
|
360
|
+
# bigquery = gcloud.bigquery
|
361
|
+
# dataset = bigquery.dataset "my_dataset"
|
362
|
+
#
|
363
|
+
# table = dataset.create_table "my_table" do |t|
|
364
|
+
# t.schema.string "first_name", mode: :required
|
365
|
+
# t.schema.record "cities_lived", mode: :required do |s|
|
366
|
+
# s.string "place", mode: :required
|
367
|
+
# s.integer "number_of_years", mode: :required
|
368
|
+
# end
|
369
|
+
# end
|
370
|
+
#
|
371
|
+
# @example You can define the schema using a nested block.
|
372
|
+
# require "google/cloud"
|
373
|
+
#
|
374
|
+
# gcloud = Google::Cloud.new
|
375
|
+
# bigquery = gcloud.bigquery
|
376
|
+
# dataset = bigquery.dataset "my_dataset"
|
377
|
+
# table = dataset.create_table "my_table" do |t|
|
378
|
+
# t.name = "My Table",
|
379
|
+
# t.description = "A description of my table."
|
380
|
+
# t.schema do |s|
|
381
|
+
# s.string "first_name", mode: :required
|
382
|
+
# s.record "cities_lived", mode: :repeated do |r|
|
383
|
+
# r.string "place", mode: :required
|
384
|
+
# r.integer "number_of_years", mode: :required
|
385
|
+
# end
|
386
|
+
# end
|
387
|
+
# end
|
388
|
+
#
|
389
|
+
# @!group Table
|
390
|
+
#
|
391
|
+
def create_table table_id, name: nil, description: nil, fields: nil
|
392
|
+
ensure_service!
|
393
|
+
new_tb = Google::Apis::BigqueryV2::Table.new(
|
394
|
+
table_reference: Google::Apis::BigqueryV2::TableReference.new(
|
395
|
+
project_id: project_id, dataset_id: dataset_id,
|
396
|
+
table_id: table_id))
|
397
|
+
updater = Table::Updater.new(new_tb).tap do |tb|
|
398
|
+
tb.name = name unless name.nil?
|
399
|
+
tb.description = description unless description.nil?
|
400
|
+
tb.schema.fields = fields unless fields.nil?
|
401
|
+
end
|
402
|
+
|
403
|
+
yield updater if block_given?
|
404
|
+
|
405
|
+
gapi = service.insert_table dataset_id, updater.to_gapi
|
406
|
+
Table.from_gapi gapi, service
|
407
|
+
end
|
408
|
+
|
409
|
+
##
|
410
|
+
# Creates a new view table from the given query.
|
411
|
+
#
|
412
|
+
# @param [String] table_id The ID of the view table. The ID must contain
|
413
|
+
# only letters (a-z, A-Z), numbers (0-9), or underscores (_). The
|
414
|
+
# maximum length is 1,024 characters.
|
415
|
+
# @param [String] query The query that BigQuery executes when the view
|
416
|
+
# is referenced.
|
417
|
+
# @param [String] name A descriptive name for the table.
|
418
|
+
# @param [String] description A user-friendly description of the table.
|
419
|
+
#
|
420
|
+
# @return [Google::Cloud::Bigquery::View]
|
421
|
+
#
|
422
|
+
# @example
|
423
|
+
# require "google/cloud"
|
424
|
+
#
|
425
|
+
# gcloud = Google::Cloud.new
|
426
|
+
# bigquery = gcloud.bigquery
|
427
|
+
# dataset = bigquery.dataset "my_dataset"
|
428
|
+
# view = dataset.create_view "my_view",
|
429
|
+
# "SELECT name, age FROM [proj:dataset.users]"
|
430
|
+
#
|
431
|
+
# @example A name and description can be provided:
|
432
|
+
# require "google/cloud"
|
433
|
+
#
|
434
|
+
# gcloud = Google::Cloud.new
|
435
|
+
# bigquery = gcloud.bigquery
|
436
|
+
# dataset = bigquery.dataset "my_dataset"
|
437
|
+
# view = dataset.create_view "my_view",
|
438
|
+
# "SELECT name, age FROM [proj:dataset.users]",
|
439
|
+
# name: "My View", description: "This is my view"
|
440
|
+
#
|
441
|
+
# @!group Table
|
442
|
+
#
|
443
|
+
def create_view table_id, query, name: nil, description: nil
|
444
|
+
new_view_opts = {
|
445
|
+
table_reference: Google::Apis::BigqueryV2::TableReference.new(
|
446
|
+
project_id: project_id, dataset_id: dataset_id, table_id: table_id
|
447
|
+
),
|
448
|
+
friendly_name: name,
|
449
|
+
description: description,
|
450
|
+
view: Google::Apis::BigqueryV2::ViewDefinition.new(
|
451
|
+
query: query
|
452
|
+
)
|
453
|
+
}.delete_if { |_, v| v.nil? }
|
454
|
+
new_view = Google::Apis::BigqueryV2::Table.new new_view_opts
|
455
|
+
|
456
|
+
gapi = service.insert_table dataset_id, new_view
|
457
|
+
Table.from_gapi gapi, service
|
458
|
+
end
|
459
|
+
|
460
|
+
##
|
461
|
+
# Retrieves an existing table by ID.
|
462
|
+
#
|
463
|
+
# @param [String] table_id The ID of a table.
|
464
|
+
#
|
465
|
+
# @return [Google::Cloud::Bigquery::Table,
|
466
|
+
# Google::Cloud::Bigquery::View, nil] Returns `nil` if the table does
|
467
|
+
# not exist
|
468
|
+
#
|
469
|
+
# @example
|
470
|
+
# require "google/cloud"
|
471
|
+
#
|
472
|
+
# gcloud = Google::Cloud.new
|
473
|
+
# bigquery = gcloud.bigquery
|
474
|
+
# dataset = bigquery.dataset "my_dataset"
|
475
|
+
# table = dataset.table "my_table"
|
476
|
+
# puts table.name
|
477
|
+
#
|
478
|
+
# @!group Table
|
479
|
+
#
|
480
|
+
def table table_id
|
481
|
+
ensure_service!
|
482
|
+
gapi = service.get_table dataset_id, table_id
|
483
|
+
Table.from_gapi gapi, service
|
484
|
+
rescue Google::Cloud::NotFoundError
|
485
|
+
nil
|
486
|
+
end
|
487
|
+
|
488
|
+
##
|
489
|
+
# Retrieves the list of tables belonging to the dataset.
|
490
|
+
#
|
491
|
+
# @param [String] token A previously-returned page token representing
|
492
|
+
# part of the larger set of results to view.
|
493
|
+
# @param [Integer] max Maximum number of tables to return.
|
494
|
+
#
|
495
|
+
# @return [Array<Google::Cloud::Bigquery::Table>,
|
496
|
+
# Array<Google::Cloud::Bigquery::View>] (See
|
497
|
+
# {Google::Cloud::Bigquery::Table::List})
|
498
|
+
#
|
499
|
+
# @example
|
500
|
+
# require "google/cloud"
|
501
|
+
#
|
502
|
+
# gcloud = Google::Cloud.new
|
503
|
+
# bigquery = gcloud.bigquery
|
504
|
+
# dataset = bigquery.dataset "my_dataset"
|
505
|
+
# tables = dataset.tables
|
506
|
+
# tables.each do |table|
|
507
|
+
# puts table.name
|
508
|
+
# end
|
509
|
+
#
|
510
|
+
# @example Retrieve all tables: (See {Table::List#all})
|
511
|
+
# require "google/cloud"
|
512
|
+
#
|
513
|
+
# gcloud = Google::Cloud.new
|
514
|
+
# bigquery = gcloud.bigquery
|
515
|
+
# dataset = bigquery.dataset "my_dataset"
|
516
|
+
# tables = dataset.tables
|
517
|
+
# tables.all do |table|
|
518
|
+
# puts table.name
|
519
|
+
# end
|
520
|
+
#
|
521
|
+
# @!group Table
|
522
|
+
#
|
523
|
+
def tables token: nil, max: nil
|
524
|
+
ensure_service!
|
525
|
+
options = { token: token, max: max }
|
526
|
+
gapi = service.list_tables dataset_id, options
|
527
|
+
Table::List.from_gapi gapi, service, dataset_id, max
|
528
|
+
end
|
529
|
+
|
530
|
+
##
|
531
|
+
# Queries data using the [asynchronous
|
532
|
+
# method](https://cloud.google.com/bigquery/querying-data).
|
533
|
+
#
|
534
|
+
# Sets the current dataset as the default dataset in the query. Useful
|
535
|
+
# for using unqualified table names.
|
536
|
+
#
|
537
|
+
# @param [String] query A query string, following the BigQuery [query
|
538
|
+
# syntax](https://cloud.google.com/bigquery/query-reference), of the
|
539
|
+
# query to execute. Example: "SELECT count(f1) FROM
|
540
|
+
# [myProjectId:myDatasetId.myTableId]".
|
541
|
+
# @param [String] priority Specifies a priority for the query. Possible
|
542
|
+
# values include `INTERACTIVE` and `BATCH`. The default value is
|
543
|
+
# `INTERACTIVE`.
|
544
|
+
# @param [Boolean] cache Whether to look for the result in the query
|
545
|
+
# cache. The query cache is a best-effort cache that will be flushed
|
546
|
+
# whenever tables in the query are modified. The default value is
|
547
|
+
# true. For more information, see [query
|
548
|
+
# caching](https://developers.google.com/bigquery/querying-data).
|
549
|
+
# @param [Table] table The destination table where the query results
|
550
|
+
# should be stored. If not present, a new table will be created to
|
551
|
+
# store the results.
|
552
|
+
# @param [String] create Specifies whether the job is allowed to create
|
553
|
+
# new tables.
|
554
|
+
#
|
555
|
+
# The following values are supported:
|
556
|
+
#
|
557
|
+
# * `needed` - Create the table if it does not exist.
|
558
|
+
# * `never` - The table must already exist. A 'notFound' error is
|
559
|
+
# raised if the table does not exist.
|
560
|
+
# @param [String] write Specifies the action that occurs if the
|
561
|
+
# destination table already exists.
|
562
|
+
#
|
563
|
+
# The following values are supported:
|
564
|
+
#
|
565
|
+
# * `truncate` - BigQuery overwrites the table data.
|
566
|
+
# * `append` - BigQuery appends the data to the table.
|
567
|
+
# * `empty` - A 'duplicate' error is returned in the job result if the
|
568
|
+
# table exists and contains data.
|
569
|
+
# @param [Boolean] large_results If `true`, allows the query to produce
|
570
|
+
# arbitrarily large result tables at a slight cost in performance.
|
571
|
+
# Requires `table` parameter to be set.
|
572
|
+
# @param [Boolean] flatten Flattens all nested and repeated fields in
|
573
|
+
# the query results. The default value is `true`. `large_results`
|
574
|
+
# parameter must be `true` if this is set to `false`.
|
575
|
+
#
|
576
|
+
# @return [Google::Cloud::Bigquery::QueryJob]
|
577
|
+
#
|
578
|
+
# @example
|
579
|
+
# require "google/cloud"
|
580
|
+
#
|
581
|
+
# gcloud = Google::Cloud.new
|
582
|
+
# bigquery = gcloud.bigquery
|
583
|
+
#
|
584
|
+
# job = bigquery.query_job "SELECT name FROM my_table"
|
585
|
+
#
|
586
|
+
# job.wait_until_done!
|
587
|
+
# if !job.failed?
|
588
|
+
# job.query_results.each do |row|
|
589
|
+
# puts row["name"]
|
590
|
+
# end
|
591
|
+
# end
|
592
|
+
#
|
593
|
+
# @!group Data
|
594
|
+
#
|
595
|
+
def query_job query, priority: "INTERACTIVE", cache: true, table: nil,
|
596
|
+
create: nil, write: nil, large_results: nil, flatten: nil
|
597
|
+
options = { priority: priority, cache: cache, table: table,
|
598
|
+
create: create, write: write,
|
599
|
+
large_results: large_results, flatten: flatten }
|
600
|
+
options[:dataset] ||= self
|
601
|
+
ensure_service!
|
602
|
+
gapi = service.query_job query, options
|
603
|
+
Job.from_gapi gapi, service
|
604
|
+
end
|
605
|
+
|
606
|
+
##
|
607
|
+
# Queries data using the [synchronous
|
608
|
+
# method](https://cloud.google.com/bigquery/querying-data).
|
609
|
+
#
|
610
|
+
# Sets the current dataset as the default dataset in the query. Useful
|
611
|
+
# for using unqualified table names.
|
612
|
+
#
|
613
|
+
# @param [String] query A query string, following the BigQuery [query
|
614
|
+
# syntax](https://cloud.google.com/bigquery/query-reference), of the
|
615
|
+
# query to execute. Example: "SELECT count(f1) FROM
|
616
|
+
# [myProjectId:myDatasetId.myTableId]".
|
617
|
+
# @param [Integer] max The maximum number of rows of data to return per
|
618
|
+
# page of results. Setting this flag to a small value such as 1000 and
|
619
|
+
# then paging through results might improve reliability when the query
|
620
|
+
# result set is large. In addition to this limit, responses are also
|
621
|
+
# limited to 10 MB. By default, there is no maximum row count, and
|
622
|
+
# only the byte limit applies.
|
623
|
+
# @param [Integer] timeout How long to wait for the query to complete,
|
624
|
+
# in milliseconds, before the request times out and returns. Note that
|
625
|
+
# this is only a timeout for the request, not the query. If the query
|
626
|
+
# takes longer to run than the timeout value, the call returns without
|
627
|
+
# any results and with QueryData#complete? set to false. The default
|
628
|
+
# value is 10000 milliseconds (10 seconds).
|
629
|
+
# @param [Boolean] dryrun If set to `true`, BigQuery doesn't run the
|
630
|
+
# job. Instead, if the query is valid, BigQuery returns statistics
|
631
|
+
# about the job such as how many bytes would be processed. If the
|
632
|
+
# query is invalid, an error returns. The default value is `false`.
|
633
|
+
# @param [Boolean] cache Whether to look for the result in the query
|
634
|
+
# cache. The query cache is a best-effort cache that will be flushed
|
635
|
+
# whenever tables in the query are modified. The default value is
|
636
|
+
# true. For more information, see [query
|
637
|
+
# caching](https://developers.google.com/bigquery/querying-data).
|
638
|
+
#
|
639
|
+
# @return [Google::Cloud::Bigquery::QueryData]
|
640
|
+
#
|
641
|
+
# @example
|
642
|
+
# require "google/cloud"
|
643
|
+
#
|
644
|
+
# gcloud = Google::Cloud.new
|
645
|
+
# bigquery = gcloud.bigquery
|
646
|
+
#
|
647
|
+
# data = bigquery.query "SELECT name FROM my_table"
|
648
|
+
# data.each do |row|
|
649
|
+
# puts row["name"]
|
650
|
+
# end
|
651
|
+
#
|
652
|
+
# @!group Data
|
653
|
+
#
|
654
|
+
def query query, max: nil, timeout: 10000, dryrun: nil, cache: true
|
655
|
+
options = { max: max, timeout: timeout, dryrun: dryrun, cache: cache }
|
656
|
+
options[:dataset] ||= dataset_id
|
657
|
+
options[:project] ||= project_id
|
658
|
+
ensure_service!
|
659
|
+
gapi = service.query query, options
|
660
|
+
QueryData.from_gapi gapi, service
|
661
|
+
end
|
662
|
+
|
663
|
+
##
|
664
|
+
# @private New Dataset from a Google API Client object.
|
665
|
+
def self.from_gapi gapi, conn
|
666
|
+
new.tap do |f|
|
667
|
+
f.gapi = gapi
|
668
|
+
f.service = conn
|
669
|
+
end
|
670
|
+
end
|
671
|
+
|
672
|
+
protected
|
673
|
+
|
674
|
+
##
|
675
|
+
# Raise an error unless an active service is available.
|
676
|
+
def ensure_service!
|
677
|
+
fail "Must have active connection" unless service
|
678
|
+
end
|
679
|
+
|
680
|
+
def patch_gapi! *attributes
|
681
|
+
return if attributes.empty?
|
682
|
+
ensure_service!
|
683
|
+
patch_args = Hash[attributes.map do |attr|
|
684
|
+
[attr, @gapi.send(attr)]
|
685
|
+
end]
|
686
|
+
patch_gapi = Google::Apis::BigqueryV2::Dataset.new patch_args
|
687
|
+
@gapi = service.patch_dataset dataset_id, patch_gapi
|
688
|
+
end
|
689
|
+
|
690
|
+
##
|
691
|
+
# Load the complete representation of the dataset if it has been
|
692
|
+
# only partially loaded by a request to the API list method.
|
693
|
+
def ensure_full_data!
|
694
|
+
reload_gapi! unless data_complete?
|
695
|
+
end
|
696
|
+
|
697
|
+
def reload_gapi!
|
698
|
+
ensure_service!
|
699
|
+
gapi = service.get_dataset dataset_id
|
700
|
+
@gapi = gapi
|
701
|
+
end
|
702
|
+
|
703
|
+
def data_complete?
|
704
|
+
@gapi.is_a? Google::Apis::BigqueryV2::Dataset
|
705
|
+
end
|
706
|
+
|
707
|
+
##
|
708
|
+
# Yielded to a block to accumulate changes for a patch request.
|
709
|
+
class Updater < Dataset
|
710
|
+
##
|
711
|
+
# A list of attributes that were updated.
|
712
|
+
attr_reader :updates
|
713
|
+
|
714
|
+
##
|
715
|
+
# Create an Updater object.
|
716
|
+
def initialize gapi
|
717
|
+
@updates = []
|
718
|
+
@gapi = gapi
|
719
|
+
end
|
720
|
+
|
721
|
+
def access
|
722
|
+
# TODO: make sure to call ensure_full_data! on Dataset#update
|
723
|
+
@access ||= Access.from_gapi @gapi
|
724
|
+
if block_given?
|
725
|
+
yield @access
|
726
|
+
check_for_mutated_access!
|
727
|
+
end
|
728
|
+
# Same as Dataset#access, but not frozen
|
729
|
+
@access
|
730
|
+
end
|
731
|
+
|
732
|
+
##
|
733
|
+
# Make sure any access changes are saved
|
734
|
+
def check_for_mutated_access!
|
735
|
+
return if @access.nil?
|
736
|
+
return unless @access.changed?
|
737
|
+
@gapi.update! access: @access.to_gapi
|
738
|
+
patch_gapi! :access
|
739
|
+
end
|
740
|
+
|
741
|
+
def to_gapi
|
742
|
+
check_for_mutated_access!
|
743
|
+
@gapi
|
744
|
+
end
|
745
|
+
|
746
|
+
protected
|
747
|
+
|
748
|
+
##
|
749
|
+
# Queue up all the updates instead of making them.
|
750
|
+
def patch_gapi! attribute
|
751
|
+
@updates << attribute
|
752
|
+
@updates.uniq!
|
753
|
+
end
|
754
|
+
end
|
755
|
+
end
|
756
|
+
end
|
757
|
+
end
|
758
|
+
end
|