gcloud 0.2.0 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
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,55 @@
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
+ class Table
19
+ ##
20
+ # Table::List is a special case Array with additional values.
21
+ class List < DelegateClass(::Array)
22
+ ##
23
+ # If not empty, indicates that there are more records that match
24
+ # the request and this value should be passed to continue.
25
+ attr_accessor :token
26
+
27
+ # A hash of this page of results.
28
+ attr_accessor :etag
29
+
30
+ # Total number of jobs in this collection.
31
+ attr_accessor :total
32
+
33
+ ##
34
+ # Create a new Table::List with an array of jobs.
35
+ def initialize arr = []
36
+ super arr
37
+ end
38
+
39
+ ##
40
+ # New Table::List from a response object.
41
+ def self.from_resp resp, conn #:nodoc:
42
+ tables = List.new(Array(resp.data["tables"]).map do |gapi_object|
43
+ Table.from_gapi gapi_object, conn
44
+ end)
45
+ tables.instance_eval do
46
+ @token = resp.data["nextPageToken"]
47
+ @etag = resp.data["etag"]
48
+ @total = resp.data["totalItems"]
49
+ end
50
+ tables
51
+ end
52
+ end
53
+ end
54
+ end
55
+ end
@@ -0,0 +1,419 @@
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/bigquery/data"
17
+ require "gcloud/bigquery/table/list"
18
+ require "gcloud/bigquery/errors"
19
+
20
+ module Gcloud
21
+ module Bigquery
22
+ ##
23
+ # = View
24
+ #
25
+ # A view is a virtual table defined by a SQL query. You can query views in
26
+ # the browser tool, or by using a query job.
27
+ #
28
+ # BigQuery's views are logical views, not materialized views, which means
29
+ # that the query that defines the view is re-executed every time the view is
30
+ # queried. Queries are billed according to the total amount of data in all
31
+ # table fields referenced directly or indirectly by the top-level query.
32
+ #
33
+ # require "gcloud"
34
+ #
35
+ # gcloud = Gcloud.new
36
+ # bigquery = gcloud.bigquery
37
+ # dataset = bigquery.dataset "my_dataset"
38
+ # view = dataset.create_view "my_view",
39
+ # "SELECT name, age FROM [proj:dataset.users]"
40
+ #
41
+ class View
42
+ ##
43
+ # The Connection object.
44
+ attr_accessor :connection #:nodoc:
45
+
46
+ ##
47
+ # The Google API Client object.
48
+ attr_accessor :gapi #:nodoc:
49
+
50
+ ##
51
+ # Create an empty Table object.
52
+ def initialize #:nodoc:
53
+ @connection = nil
54
+ @gapi = {}
55
+ end
56
+
57
+ ##
58
+ # A unique ID for this table.
59
+ # The ID must contain only letters (a-z, A-Z), numbers (0-9),
60
+ # or underscores (_). The maximum length is 1,024 characters.
61
+ #
62
+ # :category: Attributes
63
+ #
64
+ def table_id
65
+ @gapi["tableReference"]["tableId"]
66
+ end
67
+
68
+ ##
69
+ # The ID of the +Dataset+ containing this table.
70
+ #
71
+ # :category: Attributes
72
+ #
73
+ def dataset_id
74
+ @gapi["tableReference"]["datasetId"]
75
+ end
76
+
77
+ ##
78
+ # The ID of the +Project+ containing this table.
79
+ #
80
+ # :category: Attributes
81
+ #
82
+ def project_id
83
+ @gapi["tableReference"]["projectId"]
84
+ end
85
+
86
+ ##
87
+ # The name of the table.
88
+ #
89
+ # :category: Attributes
90
+ #
91
+ def name
92
+ @gapi["friendlyName"]
93
+ end
94
+
95
+ ##
96
+ # Updates the name of the table.
97
+ #
98
+ # :category: Lifecycle
99
+ #
100
+ def name= new_name
101
+ patch_gapi! name: new_name
102
+ end
103
+
104
+ ##
105
+ # A string hash of the dataset.
106
+ #
107
+ # :category: Attributes
108
+ #
109
+ def etag
110
+ ensure_full_data!
111
+ @gapi["etag"]
112
+ end
113
+
114
+ ##
115
+ # A URL that can be used to access the dataset using the REST API.
116
+ #
117
+ # :category: Attributes
118
+ #
119
+ def url
120
+ ensure_full_data!
121
+ @gapi["selfLink"]
122
+ end
123
+
124
+ ##
125
+ # The description of the table.
126
+ #
127
+ # :category: Attributes
128
+ #
129
+ def description
130
+ ensure_full_data!
131
+ @gapi["description"]
132
+ end
133
+
134
+ ##
135
+ # Updates the description of the table.
136
+ #
137
+ # :category: Lifecycle
138
+ #
139
+ def description= new_description
140
+ patch_gapi! description: new_description
141
+ end
142
+
143
+ ##
144
+ # The time when this table was created.
145
+ #
146
+ # :category: Attributes
147
+ #
148
+ def created_at
149
+ ensure_full_data!
150
+ Time.at(@gapi["creationTime"] / 1000.0)
151
+ end
152
+
153
+ ##
154
+ # The time when this table expires.
155
+ # If not present, the table will persist indefinitely.
156
+ # Expired tables will be deleted and their storage reclaimed.
157
+ #
158
+ # :category: Attributes
159
+ #
160
+ def expires_at
161
+ ensure_full_data!
162
+ return nil if @gapi["expirationTime"].nil?
163
+ Time.at(@gapi["expirationTime"] / 1000.0)
164
+ end
165
+
166
+ ##
167
+ # The date when this table was last modified.
168
+ #
169
+ # :category: Attributes
170
+ #
171
+ def modified_at
172
+ ensure_full_data!
173
+ Time.at(@gapi["lastModifiedTime"] / 1000.0)
174
+ end
175
+
176
+ ##
177
+ # Checks if the table's type is "TABLE".
178
+ #
179
+ # :category: Attributes
180
+ #
181
+ def table?
182
+ @gapi["type"] == "TABLE"
183
+ end
184
+
185
+ ##
186
+ # Checks if the table's type is "VIEW".
187
+ #
188
+ # :category: Attributes
189
+ #
190
+ def view?
191
+ @gapi["type"] == "VIEW"
192
+ end
193
+
194
+ ##
195
+ # The geographic location where the table should reside. Possible
196
+ # values include EU and US. The default value is US.
197
+ #
198
+ # :category: Attributes
199
+ #
200
+ def location
201
+ ensure_full_data!
202
+ @gapi["location"]
203
+ end
204
+
205
+ ##
206
+ # The schema of the table.
207
+ #
208
+ # :category: Attributes
209
+ #
210
+ def schema
211
+ ensure_full_data!
212
+ s = @gapi["schema"]
213
+ s = s.to_hash if s.respond_to? :to_hash
214
+ s = {} if s.nil?
215
+ s
216
+ end
217
+
218
+ ##
219
+ # The fields of the table.
220
+ #
221
+ # :category: Attributes
222
+ #
223
+ def fields
224
+ f = schema["fields"]
225
+ f = f.to_hash if f.respond_to? :to_hash
226
+ f = [] if f.nil?
227
+ f
228
+ end
229
+
230
+ ##
231
+ # The names of the columns in the table.
232
+ #
233
+ # :category: Attributes
234
+ #
235
+ def headers
236
+ fields.map { |f| f["name"] }
237
+ end
238
+
239
+ ##
240
+ # The query that executes each time the view is loaded.
241
+ #
242
+ # :category: Attributes
243
+ #
244
+ def query
245
+ @gapi["view"]["query"] if @gapi["view"]
246
+ end
247
+
248
+ ##
249
+ # Updates the query that executes each time the view is loaded.
250
+ # See the BigQuery {Query Reference
251
+ # }[https://cloud.google.com/bigquery/query-reference].
252
+ #
253
+ # === Parameters
254
+ #
255
+ # +new_query+::
256
+ # The query that defines the view. (+String+)
257
+ #
258
+ # === Example
259
+ #
260
+ # require "gcloud"
261
+ #
262
+ # gcloud = Gcloud.new
263
+ # bigquery = gcloud.bigquery
264
+ # dataset = bigquery.dataset "my_dataset"
265
+ # view = dataset.table "my_view"
266
+ #
267
+ # view.query = "SELECT first_name FROM [my_project:my_dataset.my_table]"
268
+ #
269
+ # :category: Lifecycle
270
+ #
271
+ def query= new_query
272
+ patch_gapi! query: new_query
273
+ end
274
+
275
+ ##
276
+ # Runs a query to retrieve all data from the view.
277
+ #
278
+ # === Parameters
279
+ #
280
+ # +options+::
281
+ # An optional Hash for controlling additional behavior. (+Hash+)
282
+ # <code>options[:max]</code>::
283
+ # The maximum number of rows of data to return per page of results.
284
+ # Setting this flag to a small value such as 1000 and then paging
285
+ # through results might improve reliability when the query result set is
286
+ # large. In addition to this limit, responses are also limited to 10 MB.
287
+ # By default, there is no maximum row count, and only the byte limit
288
+ # applies. (+Integer+)
289
+ # <code>options[:timeout]</code>::
290
+ # How long to wait for the query to complete, in milliseconds, before
291
+ # the request times out and returns. Note that this is only a timeout
292
+ # for the request, not the query. If the query takes longer to run than
293
+ # the timeout value, the call returns without any results and with
294
+ # QueryData#complete? set to false. The default value is 10000
295
+ # milliseconds (10 seconds). (+Integer+)
296
+ # <code>options[:dryrun]</code>::
297
+ # If set to +true+, BigQuery doesn't run the job. Instead, if the query
298
+ # is valid, BigQuery returns statistics about the job such as how many
299
+ # bytes would be processed. If the query is invalid, an error returns.
300
+ # The default value is +false+. (+Boolean+)
301
+ # <code>options[:cache]</code>::
302
+ # Whether to look for the result in the query cache. The query cache is
303
+ # a best-effort cache that will be flushed whenever tables in the query
304
+ # are modified. The default value is true. For more information, see
305
+ # {query caching}[https://developers.google.com/bigquery/querying-data].
306
+ # (+Boolean+)
307
+ #
308
+ # === Returns
309
+ #
310
+ # Gcloud::Bigquery::QueryData
311
+ #
312
+ # === Example
313
+ #
314
+ # require "gcloud"
315
+ #
316
+ # gcloud = Gcloud.new
317
+ # bigquery = gcloud.bigquery
318
+ # dataset = bigquery.dataset "my_dataset"
319
+ # view = dataset.table "my_view"
320
+ #
321
+ # data = view.data
322
+ # data.each do |row|
323
+ # puts row["first_name"]
324
+ # end
325
+ # more_data = data.next if data.next?
326
+ #
327
+ # :category: Data
328
+ #
329
+ def data options = {}
330
+ sql = "SELECT * FROM #{@gapi['id']}"
331
+ ensure_connection!
332
+ resp = connection.query sql, options
333
+ if resp.success?
334
+ QueryData.from_gapi resp.data, connection
335
+ else
336
+ fail ApiError.from_response(resp)
337
+ end
338
+ end
339
+
340
+ ##
341
+ # Permanently deletes the table.
342
+ #
343
+ # === Returns
344
+ #
345
+ # +true+ if the table was deleted.
346
+ #
347
+ # === Example
348
+ #
349
+ # require "gcloud"
350
+ #
351
+ # gcloud = Gcloud.new
352
+ # bigquery = gcloud.bigquery
353
+ # dataset = bigquery.dataset "my_dataset"
354
+ # table = dataset.table "my_table"
355
+ #
356
+ # table.delete
357
+ #
358
+ # :category: Lifecycle
359
+ #
360
+ def delete
361
+ ensure_connection!
362
+ resp = connection.delete_table dataset_id, table_id
363
+ if resp.success?
364
+ true
365
+ else
366
+ fail ApiError.from_response(resp)
367
+ end
368
+ end
369
+
370
+ ##
371
+ # New Table from a Google API Client object.
372
+ def self.from_gapi gapi, conn #:nodoc:
373
+ new.tap do |f|
374
+ f.gapi = gapi
375
+ f.connection = conn
376
+ end
377
+ end
378
+
379
+ protected
380
+
381
+ ##
382
+ # Raise an error unless an active connection is available.
383
+ def ensure_connection!
384
+ fail "Must have active connection" unless connection
385
+ end
386
+
387
+ def patch_gapi! options = {}
388
+ ensure_connection!
389
+ resp = connection.patch_table dataset_id, table_id, options
390
+ if resp.success?
391
+ @gapi = resp.data
392
+ else
393
+ fail ApiError.from_response(resp)
394
+ end
395
+ end
396
+
397
+ ##
398
+ # Load the complete representation of the table if it has been
399
+ # only partially loaded by a request to the API list method.
400
+ def ensure_full_data!
401
+ reload_gapi! unless data_complete?
402
+ end
403
+
404
+ def reload_gapi!
405
+ ensure_connection!
406
+ resp = connection.get_table dataset_id, table_id
407
+ if resp.success?
408
+ @gapi = resp.data
409
+ else
410
+ fail ApiError.from_response(resp)
411
+ end
412
+ end
413
+
414
+ def data_complete?
415
+ !@gapi["creationTime"].nil?
416
+ end
417
+ end
418
+ end
419
+ end