gcloud 0.2.0 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (41) hide show
  1. checksums.yaml +8 -8
  2. data/AUTHENTICATION.md +3 -3
  3. data/CHANGELOG.md +12 -0
  4. data/OVERVIEW.md +30 -0
  5. data/lib/gcloud.rb +126 -9
  6. data/lib/gcloud/bigquery.rb +399 -0
  7. data/lib/gcloud/bigquery/connection.rb +592 -0
  8. data/lib/gcloud/bigquery/copy_job.rb +98 -0
  9. data/lib/gcloud/bigquery/credentials.rb +29 -0
  10. data/lib/gcloud/bigquery/data.rb +134 -0
  11. data/lib/gcloud/bigquery/dataset.rb +662 -0
  12. data/lib/gcloud/bigquery/dataset/list.rb +51 -0
  13. data/lib/gcloud/bigquery/errors.rb +62 -0
  14. data/lib/gcloud/bigquery/extract_job.rb +117 -0
  15. data/lib/gcloud/bigquery/insert_response.rb +80 -0
  16. data/lib/gcloud/bigquery/job.rb +283 -0
  17. data/lib/gcloud/bigquery/job/list.rb +55 -0
  18. data/lib/gcloud/bigquery/load_job.rb +199 -0
  19. data/lib/gcloud/bigquery/project.rb +512 -0
  20. data/lib/gcloud/bigquery/query_data.rb +135 -0
  21. data/lib/gcloud/bigquery/query_job.rb +151 -0
  22. data/lib/gcloud/bigquery/table.rb +827 -0
  23. data/lib/gcloud/bigquery/table/list.rb +55 -0
  24. data/lib/gcloud/bigquery/view.rb +419 -0
  25. data/lib/gcloud/credentials.rb +3 -3
  26. data/lib/gcloud/datastore.rb +15 -3
  27. data/lib/gcloud/datastore/credentials.rb +3 -2
  28. data/lib/gcloud/datastore/dataset.rb +5 -1
  29. data/lib/gcloud/datastore/transaction.rb +1 -1
  30. data/lib/gcloud/pubsub.rb +14 -3
  31. data/lib/gcloud/pubsub/credentials.rb +4 -4
  32. data/lib/gcloud/pubsub/project.rb +5 -1
  33. data/lib/gcloud/pubsub/topic.rb +5 -0
  34. data/lib/gcloud/storage.rb +14 -24
  35. data/lib/gcloud/storage/bucket.rb +10 -4
  36. data/lib/gcloud/storage/credentials.rb +3 -2
  37. data/lib/gcloud/storage/file.rb +8 -1
  38. data/lib/gcloud/storage/project.rb +5 -1
  39. data/lib/gcloud/upload.rb +54 -0
  40. data/lib/gcloud/version.rb +1 -1
  41. metadata +78 -2
@@ -0,0 +1,98 @@
1
+ #--
2
+ # Copyright 2015 Google Inc. All rights reserved.
3
+ #
4
+ # Licensed under the Apache License, Version 2.0 (the "License");
5
+ # you may not use this file except in compliance with the License.
6
+ # You may obtain a copy of the License at
7
+ #
8
+ # http://www.apache.org/licenses/LICENSE-2.0
9
+ #
10
+ # Unless required by applicable law or agreed to in writing, software
11
+ # distributed under the License is distributed on an "AS IS" BASIS,
12
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ # See the License for the specific language governing permissions and
14
+ # limitations under the License.
15
+
16
+ module Gcloud
17
+ module Bigquery
18
+ ##
19
+ # = CopyJob
20
+ #
21
+ # A Job subclass representing a copy operation that may be performed on a
22
+ # Table. A CopyJob instance is created when you call Table#copy.
23
+ #
24
+ # See {Copying an Existing
25
+ # Table}[https://cloud.google.com/bigquery/docs/tables#copyingtable]
26
+ # and the {Jobs API
27
+ # reference}[https://cloud.google.com/bigquery/docs/reference/v2/jobs]
28
+ # for details.
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 = config["copy"]["sourceTable"]
36
+ return nil unless table
37
+ retrieve_table table["projectId"],
38
+ table["datasetId"],
39
+ table["tableId"]
40
+ end
41
+
42
+ ##
43
+ # The table to which data is copied. Returns a Table instance.
44
+ def destination
45
+ table = config["copy"]["destinationTable"]
46
+ return nil unless table
47
+ retrieve_table table["projectId"],
48
+ table["datasetId"],
49
+ table["tableId"]
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 = config["copy"]["createDisposition"]
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 = config["copy"]["createDisposition"]
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 = config["copy"]["writeDisposition"]
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 = config["copy"]["writeDisposition"]
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 = config["copy"]["writeDisposition"]
94
+ disp == "WRITE_EMPTY"
95
+ end
96
+ end
97
+ end
98
+ end
@@ -0,0 +1,29 @@
1
+ #--
2
+ # Copyright 2015 Google Inc. All rights reserved.
3
+ #
4
+ # Licensed under the Apache License, Version 2.0 (the "License");
5
+ # you may not use this file except in compliance with the License.
6
+ # You may obtain a copy of the License at
7
+ #
8
+ # http://www.apache.org/licenses/LICENSE-2.0
9
+ #
10
+ # Unless required by applicable law or agreed to in writing, software
11
+ # distributed under the License is distributed on an "AS IS" BASIS,
12
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ # See the License for the specific language governing permissions and
14
+ # limitations under the License.
15
+
16
+ require "gcloud/credentials"
17
+
18
+ module Gcloud
19
+ module Bigquery
20
+ ##
21
+ # Represents the Oauth2 signing logic for Bigquery.
22
+ class Credentials < Gcloud::Credentials #:nodoc:
23
+ SCOPE = ["https://www.googleapis.com/auth/bigquery"]
24
+ PATH_ENV_VARS = %w(BIGQUERY_KEYFILE GCLOUD_KEYFILE GOOGLE_CLOUD_KEYFILE)
25
+ JSON_ENV_VARS = %w(BIGQUERY_KEYFILE_JSON GCLOUD_KEYFILE_JSON
26
+ GOOGLE_CLOUD_KEYFILE_JSON)
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,134 @@
1
+ #--
2
+ # Copyright 2015 Google Inc. All rights reserved.
3
+ #
4
+ # Licensed under the Apache License, Version 2.0 (the "License");
5
+ # you may not use this file except in compliance with the License.
6
+ # You may obtain a copy of the License at
7
+ #
8
+ # http://www.apache.org/licenses/LICENSE-2.0
9
+ #
10
+ # Unless required by applicable law or agreed to in writing, software
11
+ # distributed under the License is distributed on an "AS IS" BASIS,
12
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ # See the License for the specific language governing permissions and
14
+ # limitations under the License.
15
+
16
+ module Gcloud
17
+ module Bigquery
18
+ ##
19
+ # = Data
20
+ #
21
+ # Represents Table Data as a list of name/value pairs.
22
+ # Also contains metadata such as +etag+ and +total+.
23
+ class Data < DelegateClass(::Array)
24
+ ##
25
+ # The Table object the data belongs to.
26
+ attr_accessor :table #:nodoc:
27
+
28
+ ##
29
+ # The Google API Client object.
30
+ attr_accessor :gapi #:nodoc:
31
+
32
+ def initialize arr = [] #:nodoc:
33
+ @table = nil
34
+ @gapi = {}
35
+ super arr
36
+ end
37
+
38
+ ##
39
+ # The resource type of the API response.
40
+ def kind
41
+ @gapi["kind"]
42
+ end
43
+
44
+ ##
45
+ # A token used for paging results.
46
+ def token
47
+ @gapi["pageToken"]
48
+ end
49
+
50
+ # A hash of this page of results.
51
+ def etag
52
+ @gapi["etag"]
53
+ end
54
+
55
+ # The total number of rows in the complete table.
56
+ def total
57
+ @gapi["totalRows"]
58
+ end
59
+
60
+ ##
61
+ # Is there a next page of data?
62
+ def next?
63
+ !token.nil?
64
+ end
65
+
66
+ def next
67
+ return nil unless next?
68
+ ensure_table!
69
+ table.data token: token
70
+ end
71
+
72
+ ##
73
+ # Represents Table Data as a list of positional values (array of arrays).
74
+ # No type conversion is made, e.g. numbers are formatted as strings.
75
+ def raw
76
+ Array(gapi["rows"]).map { |row| row["f"].map { |f| f["v"] } }
77
+ end
78
+
79
+ ##
80
+ # New Data from a response object.
81
+ def self.from_response resp, table #:nodoc:
82
+ formatted_rows = format_rows resp.data["rows"], table.fields
83
+
84
+ data = new formatted_rows
85
+ data.table = table
86
+ data.gapi = resp.data
87
+ data
88
+ end
89
+
90
+ # rubocop:disable all
91
+ # Disabled rubocop because this implementation will not last.
92
+
93
+ def self.format_rows rows, fields
94
+ headers = fields.map { |f| f["name"] }
95
+ field_types = fields.map { |f| f["type"] }
96
+
97
+ Array(rows).map do |row|
98
+ values = row["f"].map { |f| f["v"] }
99
+ formatted_values = format_values field_types, values
100
+ Hash[headers.zip formatted_values]
101
+ end
102
+ end
103
+
104
+ def self.format_values field_types, values
105
+ field_types.zip(values).map do |type, value|
106
+ begin
107
+ if value.nil?
108
+ nil
109
+ elsif type == "INTEGER"
110
+ Integer value
111
+ elsif type == "FLOAT"
112
+ Float value
113
+ elsif type == "BOOLEAN"
114
+ (value == "true" ? true : (value == "false" ? false : nil))
115
+ else
116
+ value
117
+ end
118
+ rescue
119
+ value
120
+ end
121
+ end
122
+ end
123
+ # rubocop:enable all
124
+
125
+ protected
126
+
127
+ ##
128
+ # Raise an error unless an active connection is available.
129
+ def ensure_table!
130
+ fail "Must have active connection" unless table
131
+ end
132
+ end
133
+ end
134
+ end
@@ -0,0 +1,662 @@
1
+ #--
2
+ # Copyright 2015 Google Inc. All rights reserved.
3
+ #
4
+ # Licensed under the Apache License, Version 2.0 (the "License");
5
+ # you may not use this file except in compliance with the License.
6
+ # You may obtain a copy of the License at
7
+ #
8
+ # http://www.apache.org/licenses/LICENSE-2.0
9
+ #
10
+ # Unless required by applicable law or agreed to in writing, software
11
+ # distributed under the License is distributed on an "AS IS" BASIS,
12
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ # See the License for the specific language governing permissions and
14
+ # limitations under the License.
15
+
16
+ require "json"
17
+ require "gcloud/bigquery/errors"
18
+ require "gcloud/bigquery/table"
19
+ require "gcloud/bigquery/dataset/list"
20
+
21
+ module Gcloud
22
+ module Bigquery
23
+ ##
24
+ # = Dataset
25
+ #
26
+ # Represents a Dataset. A dataset is a grouping mechanism that holds zero or
27
+ # more tables. Datasets are the lowest level unit of access control; you
28
+ # cannot control access at the table level. A dataset is contained within a
29
+ # specific project.
30
+ #
31
+ # require "gcloud"
32
+ #
33
+ # gcloud = Gcloud.new
34
+ # bigquery = gcloud.bigquery
35
+ #
36
+ # dataset = bigquery.create_dataset "my_dataset",
37
+ # name: "My Dataset"
38
+ # description: "This is my Dataset"
39
+ #
40
+ class Dataset
41
+ ##
42
+ # The Connection object.
43
+ attr_accessor :connection #:nodoc:
44
+
45
+ ##
46
+ # The Google API Client object.
47
+ attr_accessor :gapi #:nodoc:
48
+
49
+ ##
50
+ # Create an empty Dataset object.
51
+ def initialize #:nodoc:
52
+ @connection = nil
53
+ @gapi = {}
54
+ end
55
+
56
+ ##
57
+ # A unique ID for this dataset, without the project name.
58
+ # The ID must contain only letters (a-z, A-Z), numbers (0-9),
59
+ # or underscores (_). The maximum length is 1,024 characters.
60
+ #
61
+ # :category: Attributes
62
+ #
63
+ def dataset_id
64
+ @gapi["datasetReference"]["datasetId"]
65
+ end
66
+
67
+ ##
68
+ # The ID of the project containing this dataset.
69
+ #
70
+ # :category: Attributes
71
+ #
72
+ def project_id
73
+ @gapi["datasetReference"]["projectId"]
74
+ end
75
+
76
+ ##
77
+ # A descriptive name for the dataset.
78
+ #
79
+ # :category: Attributes
80
+ #
81
+ def name
82
+ @gapi["friendlyName"]
83
+ end
84
+
85
+ ##
86
+ # Updates the descriptive name for the dataset.
87
+ #
88
+ # :category: Attributes
89
+ #
90
+ def name= new_name
91
+ patch_gapi! name: new_name
92
+ end
93
+
94
+ ##
95
+ # A string hash of the dataset.
96
+ #
97
+ # :category: Attributes
98
+ #
99
+ def etag
100
+ ensure_full_data!
101
+ @gapi["etag"]
102
+ end
103
+
104
+ ##
105
+ # A URL that can be used to access the dataset using the REST API.
106
+ #
107
+ # :category: Attributes
108
+ #
109
+ def url
110
+ ensure_full_data!
111
+ @gapi["selfLink"]
112
+ end
113
+
114
+ ##
115
+ # A user-friendly description of the dataset.
116
+ #
117
+ # :category: Attributes
118
+ #
119
+ def description
120
+ ensure_full_data!
121
+ @gapi["description"]
122
+ end
123
+
124
+ ##
125
+ # Updates the user-friendly description of the dataset.
126
+ #
127
+ # :category: Attributes
128
+ #
129
+ def description= new_description
130
+ patch_gapi! description: new_description
131
+ end
132
+
133
+ ##
134
+ # The default lifetime of all tables in the dataset, in milliseconds.
135
+ #
136
+ # :category: Attributes
137
+ #
138
+ def default_expiration
139
+ ensure_full_data!
140
+ @gapi["defaultTableExpirationMs"]
141
+ end
142
+
143
+ ##
144
+ # Updates the default lifetime of all tables in the dataset, in
145
+ # milliseconds.
146
+ #
147
+ # :category: Attributes
148
+ #
149
+ def default_expiration= new_default_expiration
150
+ patch_gapi! default_expiration: new_default_expiration
151
+ end
152
+
153
+ ##
154
+ # The time when this dataset was created.
155
+ #
156
+ # :category: Attributes
157
+ #
158
+ def created_at
159
+ ensure_full_data!
160
+ Time.at(@gapi["creationTime"] / 1000.0)
161
+ end
162
+
163
+ ##
164
+ # The date when this dataset or any of its tables was last modified.
165
+ #
166
+ # :category: Attributes
167
+ #
168
+ def modified_at
169
+ ensure_full_data!
170
+ Time.at(@gapi["lastModifiedTime"] / 1000.0)
171
+ end
172
+
173
+ ##
174
+ # The geographic location where the dataset should reside. Possible
175
+ # values include EU and US. The default value is US.
176
+ #
177
+ # :category: Attributes
178
+ #
179
+ def location
180
+ ensure_full_data!
181
+ @gapi["location"]
182
+ end
183
+
184
+ ##
185
+ # Permanently deletes the dataset. The dataset must be empty before it can
186
+ # be deleted unless the +force+ option is set to +true+.
187
+ #
188
+ # === Parameters
189
+ #
190
+ # +options+::
191
+ # An optional Hash for controlling additional behavior. (+Hash+)
192
+ # <code>options[:force]</code>::
193
+ # If +true+, delete all the tables in the dataset. If +false+ and the
194
+ # dataset contains tables, the request will fail. Default is +false+.
195
+ # (+Boolean+)
196
+ #
197
+ # === Returns
198
+ #
199
+ # +true+ if the dataset was deleted.
200
+ #
201
+ # === Example
202
+ #
203
+ # require "gcloud"
204
+ #
205
+ # gcloud = Gcloud.new
206
+ # bigquery = gcloud.bigquery
207
+ #
208
+ # dataset = bigquery.dataset "my_dataset"
209
+ # dataset.delete
210
+ #
211
+ # :category: Lifecycle
212
+ #
213
+ def delete options = {}
214
+ ensure_connection!
215
+ resp = connection.delete_dataset dataset_id, options
216
+ if resp.success?
217
+ true
218
+ else
219
+ fail ApiError.from_response(resp)
220
+ end
221
+ end
222
+
223
+ ##
224
+ # Creates a new table.
225
+ #
226
+ # === Parameters
227
+ #
228
+ # +table_id+::
229
+ # The ID of the table. The ID must contain only letters (a-z, A-Z),
230
+ # numbers (0-9), or underscores (_). The maximum length is 1,024
231
+ # characters. (+String+)
232
+ # +options+::
233
+ # An optional Hash for controlling additional behavior. (+Hash+)
234
+ # <code>options[:name]</code>::
235
+ # A descriptive name for the table. (+String+)
236
+ # <code>options[:description]</code>::
237
+ # A user-friendly description of the table. (+String+)
238
+ # <code>options[:schema]</code>::
239
+ # A schema specifying fields and data types for the table. See the
240
+ # {Tables resource
241
+ # }[https://cloud.google.com/bigquery/docs/reference/v2/tables#resource]
242
+ # for more information. (+Hash+)
243
+ #
244
+ # === Returns
245
+ #
246
+ # Gcloud::Bigquery::Table
247
+ #
248
+ # === Examples
249
+ #
250
+ # require "gcloud"
251
+ #
252
+ # gcloud = Gcloud.new
253
+ # bigquery = gcloud.bigquery
254
+ # dataset = bigquery.dataset "my_dataset"
255
+ # table = dataset.create_table "my_table"
256
+ #
257
+ # A name and description can be provided:
258
+ #
259
+ # require "gcloud"
260
+ #
261
+ # gcloud = Gcloud.new
262
+ # bigquery = gcloud.bigquery
263
+ # dataset = bigquery.dataset "my_dataset"
264
+ #
265
+ # schema = {
266
+ # "fields" => [
267
+ # {
268
+ # "name" => "first_name",
269
+ # "type" => "STRING",
270
+ # "mode" => "REQUIRED"
271
+ # },
272
+ # {
273
+ # "name" => "cities_lived",
274
+ # "type" => "RECORD",
275
+ # "mode" => "REPEATED",
276
+ # "fields" => [
277
+ # {
278
+ # "name" => "place",
279
+ # "type" => "STRING",
280
+ # "mode" => "REQUIRED"
281
+ # },
282
+ # {
283
+ # "name" => "number_of_years",
284
+ # "type" => "INTEGER",
285
+ # "mode" => "REQUIRED"
286
+ # }
287
+ # ]
288
+ # }
289
+ # ]
290
+ # }
291
+ # table = dataset.create_table "my_table",
292
+ # name: "My Table",
293
+ # schema: schema
294
+ #
295
+ # :category: Table
296
+ #
297
+ def create_table table_id, options = {}
298
+ ensure_connection!
299
+ resp = connection.insert_table dataset_id, table_id, options
300
+ if resp.success?
301
+ Table.from_gapi resp.data, connection
302
+ else
303
+ fail ApiError.from_response(resp)
304
+ end
305
+ end
306
+
307
+ ##
308
+ # Creates a new view table from the given query.
309
+ #
310
+ # === Parameters
311
+ #
312
+ # +table_id+::
313
+ # The ID of the view table. The ID must contain only letters (a-z, A-Z),
314
+ # numbers (0-9), or underscores (_). The maximum length is 1,024
315
+ # characters. (+String+)
316
+ # +query+::
317
+ # The query that BigQuery executes when the view is referenced.
318
+ # (+String+)
319
+ # +options+::
320
+ # An optional Hash for controlling additional behavior. (+Hash+)
321
+ # <code>options[:name]</code>::
322
+ # A descriptive name for the table. (+String+)
323
+ # <code>options[:description]</code>::
324
+ # A user-friendly description of the table. (+String+)
325
+ #
326
+ # === Returns
327
+ #
328
+ # Gcloud::Bigquery::View
329
+ #
330
+ # === Examples
331
+ #
332
+ # require "gcloud"
333
+ #
334
+ # gcloud = Gcloud.new
335
+ # bigquery = gcloud.bigquery
336
+ # dataset = bigquery.dataset "my_dataset"
337
+ # view = dataset.create_view "my_view",
338
+ # "SELECT name, age FROM [proj:dataset.users]"
339
+ #
340
+ # A name and description can be provided:
341
+ #
342
+ # require "gcloud"
343
+ #
344
+ # gcloud = Gcloud.new
345
+ # bigquery = gcloud.bigquery
346
+ # dataset = bigquery.dataset "my_dataset"
347
+ # view = dataset.create_view "my_view",
348
+ # "SELECT name, age FROM [proj:dataset.users]",
349
+ # name: "My View", description: "This is my view"
350
+ #
351
+ # :category: Table
352
+ #
353
+ def create_view table_id, query, options = {}
354
+ options[:query] = query
355
+ create_table table_id, options
356
+ end
357
+
358
+ ##
359
+ # Retrieves an existing table by ID.
360
+ #
361
+ # === Parameters
362
+ #
363
+ # +table_id+::
364
+ # The ID of a table. (+String+)
365
+ #
366
+ # === Returns
367
+ #
368
+ # Gcloud::Bigquery::Table or Gcloud::Bigquery::View or nil if the table
369
+ # does not exist
370
+ #
371
+ # === Example
372
+ #
373
+ # require "gcloud"
374
+ #
375
+ # gcloud = Gcloud.new
376
+ # bigquery = gcloud.bigquery
377
+ # dataset = bigquery.dataset "my_dataset"
378
+ # table = dataset.table "my_table"
379
+ # puts table.name
380
+ #
381
+ # :category: Table
382
+ #
383
+ def table table_id
384
+ ensure_connection!
385
+ resp = connection.get_table dataset_id, table_id
386
+ if resp.success?
387
+ Table.from_gapi resp.data, connection
388
+ else
389
+ nil
390
+ end
391
+ end
392
+
393
+ ##
394
+ # Retrieves the list of tables belonging to the dataset.
395
+ #
396
+ # === Parameters
397
+ #
398
+ # +options+::
399
+ # An optional Hash for controlling additional behavior. (+Hash+)
400
+ # <code>options[:token]</code>::
401
+ # A previously-returned page token representing part of the larger set
402
+ # of results to view. (+String+)
403
+ # <code>options[:max]</code>::
404
+ # Maximum number of tables to return. (+Integer+)
405
+ #
406
+ # === Returns
407
+ #
408
+ # Array of Gcloud::Bigquery::Table or Gcloud::Bigquery::View
409
+ # (Gcloud::Bigquery::Table::List)
410
+ #
411
+ # === Examples
412
+ #
413
+ # require "gcloud"
414
+ #
415
+ # gcloud = Gcloud.new
416
+ # bigquery = gcloud.bigquery
417
+ # dataset = bigquery.dataset "my_dataset"
418
+ # tables = dataset.tables
419
+ # tables.each do |table|
420
+ # puts table.name
421
+ # end
422
+ #
423
+ # If you have a significant number of tables, you may need to paginate
424
+ # through them: (See Dataset::List#token)
425
+ #
426
+ # require "gcloud"
427
+ #
428
+ # gcloud = Gcloud.new
429
+ # bigquery = gcloud.bigquery
430
+ # dataset = bigquery.dataset "my_dataset"
431
+ #
432
+ # all_tables = []
433
+ # tmp_tables = dataset.tables
434
+ # while tmp_tables.any? do
435
+ # tmp_tables.each do |table|
436
+ # all_tables << table
437
+ # end
438
+ # # break loop if no more tables available
439
+ # break if tmp_tables.token.nil?
440
+ # # get the next group of tables
441
+ # tmp_tables = dataset.tables token: tmp_tables.token
442
+ # end
443
+ #
444
+ # :category: Table
445
+ #
446
+ def tables options = {}
447
+ ensure_connection!
448
+ resp = connection.list_tables dataset_id, options
449
+ if resp.success?
450
+ Table::List.from_resp resp, connection
451
+ else
452
+ fail ApiError.from_response(resp)
453
+ end
454
+ end
455
+
456
+ ##
457
+ # Queries data using the {asynchronous
458
+ # method}[https://cloud.google.com/bigquery/querying-data].
459
+ #
460
+ # Sets the current dataset as the default dataset in the query. Useful for
461
+ # using unqualified table names.
462
+ #
463
+ # === Parameters
464
+ #
465
+ # +query+::
466
+ # A query string, following the BigQuery {query
467
+ # syntax}[https://cloud.google.com/bigquery/query-reference], of the
468
+ # query to execute. Example: "SELECT count(f1) FROM
469
+ # [myProjectId:myDatasetId.myTableId]". (+String+)
470
+ # <code>options[:priority]</code>::
471
+ # Specifies a priority for the query. Possible values include
472
+ # +INTERACTIVE+ and +BATCH+. The default value is +INTERACTIVE+.
473
+ # (+String+)
474
+ # <code>options[:cache]</code>::
475
+ # Whether to look for the result in the query cache. The query cache is
476
+ # a best-effort cache that will be flushed whenever tables in the query
477
+ # are modified. The default value is +true+. (+Boolean+)
478
+ # <code>options[:table]</code>::
479
+ # The destination table where the query results should be stored. If not
480
+ # present, a new table will be created to store the results. (+Table+)
481
+ # <code>options[:create]</code>::
482
+ # Specifies whether the job is allowed to create new tables. (+String+)
483
+ #
484
+ # The following values are supported:
485
+ # * +needed+ - Create the table if it does not exist.
486
+ # * +never+ - The table must already exist. A 'notFound' error is
487
+ # raised if the table does not exist.
488
+ # <code>options[:write]</code>::
489
+ # Specifies the action that occurs if the destination table already
490
+ # exists. (+String+)
491
+ #
492
+ # The following values are supported:
493
+ # * +truncate+ - BigQuery overwrites the table data.
494
+ # * +append+ - BigQuery appends the data to the table.
495
+ # * +empty+ - A 'duplicate' error is returned in the job result if the
496
+ # table exists and contains data.
497
+ # <code>options[:large_results]</code>::
498
+ # If +true+, allows the query to produce arbitrarily large result tables
499
+ # at a slight cost in performance. Requires <code>options[:table]</code>
500
+ # to be set. (+Boolean+)
501
+ # <code>options[:flatten]</code>::
502
+ # Flattens all nested and repeated fields in the query results. The
503
+ # default value is +true+. <code>options[:large_results]</code> must be
504
+ # +true+ if this is set to +false+. (+Boolean+)
505
+ #
506
+ # === Returns
507
+ #
508
+ # Gcloud::Bigquery::QueryJob
509
+ #
510
+ # === Example
511
+ #
512
+ # require "gcloud"
513
+ #
514
+ # gcloud = Gcloud.new
515
+ # bigquery = gcloud.bigquery
516
+ #
517
+ # job = bigquery.query_job "SELECT name FROM my_table"
518
+ #
519
+ # loop do
520
+ # break if job.done?
521
+ # sleep 1
522
+ # job.refresh!
523
+ # end
524
+ # if !job.failed?
525
+ # job.query_results.each do |row|
526
+ # puts row["name"]
527
+ # end
528
+ # end
529
+ #
530
+ # :category: Data
531
+ #
532
+ def query_job query, options = {}
533
+ options[:dataset] ||= self
534
+ ensure_connection!
535
+ resp = connection.query_job query, options
536
+ if resp.success?
537
+ Job.from_gapi resp.data, connection
538
+ else
539
+ fail ApiError.from_response(resp)
540
+ end
541
+ end
542
+
543
+ ##
544
+ # Queries data using the {synchronous
545
+ # method}[https://cloud.google.com/bigquery/querying-data].
546
+ #
547
+ # Sets the current dataset as the default dataset in the query. Useful for
548
+ # using unqualified table names.
549
+ #
550
+ # === Parameters
551
+ #
552
+ # +query+::
553
+ # A query string, following the BigQuery {query
554
+ # syntax}[https://cloud.google.com/bigquery/query-reference], of the
555
+ # query to execute. Example: "SELECT count(f1) FROM
556
+ # [myProjectId:myDatasetId.myTableId]". (+String+)
557
+ # <code>options[:max]</code>::
558
+ # The maximum number of rows of data to return per page of results.
559
+ # Setting this flag to a small value such as 1000 and then paging
560
+ # through results might improve reliability when the query result set is
561
+ # large. In addition to this limit, responses are also limited to 10 MB.
562
+ # By default, there is no maximum row count, and only the byte limit
563
+ # applies. (+Integer+)
564
+ # <code>options[:timeout]</code>::
565
+ # How long to wait for the query to complete, in milliseconds, before
566
+ # the request times out and returns. Note that this is only a timeout
567
+ # for the request, not the query. If the query takes longer to run than
568
+ # the timeout value, the call returns without any results and with
569
+ # QueryData#complete? set to false. The default value is 10000
570
+ # milliseconds (10 seconds). (+Integer+)
571
+ # <code>options[:dryrun]</code>::
572
+ # If set to +true+, BigQuery doesn't run the job. Instead, if the query
573
+ # is valid, BigQuery returns statistics about the job such as how many
574
+ # bytes would be processed. If the query is invalid, an error returns.
575
+ # The default value is +false+. (+Boolean+)
576
+ # <code>options[:cache]</code>::
577
+ # Whether to look for the result in the query cache. The query cache is
578
+ # a best-effort cache that will be flushed whenever tables in the query
579
+ # are modified. The default value is true. For more information, see
580
+ # {query caching}[https://developers.google.com/bigquery/querying-data].
581
+ # (+Boolean+)
582
+ #
583
+ # === Returns
584
+ #
585
+ # Gcloud::Bigquery::QueryData
586
+ #
587
+ # === Example
588
+ #
589
+ # require "gcloud"
590
+ #
591
+ # gcloud = Gcloud.new
592
+ # bigquery = gcloud.bigquery
593
+ #
594
+ # data = bigquery.query "SELECT name FROM my_table"
595
+ # data.each do |row|
596
+ # puts row["name"]
597
+ # end
598
+ #
599
+ # :category: Data
600
+ #
601
+ def query query, options = {}
602
+ options[:dataset] ||= dataset_id
603
+ options[:project] ||= project_id
604
+ ensure_connection!
605
+ resp = connection.query query, options
606
+ if resp.success?
607
+ QueryData.from_gapi resp.data, connection
608
+ else
609
+ fail ApiError.from_response(resp)
610
+ end
611
+ end
612
+
613
+ ##
614
+ # New Dataset from a Google API Client object.
615
+ def self.from_gapi gapi, conn #:nodoc:
616
+ new.tap do |f|
617
+ f.gapi = gapi
618
+ f.connection = conn
619
+ end
620
+ end
621
+
622
+ protected
623
+
624
+ ##
625
+ # Raise an error unless an active connection is available.
626
+ def ensure_connection!
627
+ fail "Must have active connection" unless connection
628
+ end
629
+
630
+ def patch_gapi! options = {}
631
+ ensure_connection!
632
+ resp = connection.patch_dataset dataset_id, options
633
+ if resp.success?
634
+ @gapi = resp.data
635
+ else
636
+ fail ApiError.from_response(resp)
637
+ end
638
+ end
639
+
640
+ ##
641
+ # Load the complete representation of the dataset if it has been
642
+ # only partially loaded by a request to the API list method.
643
+ def ensure_full_data!
644
+ reload_gapi! unless data_complete?
645
+ end
646
+
647
+ def reload_gapi!
648
+ ensure_connection!
649
+ resp = connection.get_dataset dataset_id
650
+ if resp.success?
651
+ @gapi = resp.data
652
+ else
653
+ fail ApiError.from_response(resp)
654
+ end
655
+ end
656
+
657
+ def data_complete?
658
+ !@gapi["creationTime"].nil?
659
+ end
660
+ end
661
+ end
662
+ end