gcloud 0.11.0 → 0.12.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (121) hide show
  1. checksums.yaml +8 -8
  2. data/AUTHENTICATION.md +3 -3
  3. data/CHANGELOG.md +92 -0
  4. data/OVERVIEW.md +3 -3
  5. data/lib/gcloud.rb +75 -25
  6. data/lib/gcloud/backoff.rb +5 -1
  7. data/lib/gcloud/bigquery.rb +25 -43
  8. data/lib/gcloud/bigquery/copy_job.rb +13 -13
  9. data/lib/gcloud/bigquery/data.rb +20 -16
  10. data/lib/gcloud/bigquery/dataset.rb +202 -177
  11. data/lib/gcloud/bigquery/dataset/access.rb +118 -104
  12. data/lib/gcloud/bigquery/dataset/list.rb +14 -18
  13. data/lib/gcloud/bigquery/extract_job.rb +12 -12
  14. data/lib/gcloud/bigquery/insert_response.rb +12 -14
  15. data/lib/gcloud/bigquery/job.rb +45 -57
  16. data/lib/gcloud/bigquery/job/list.rb +18 -24
  17. data/lib/gcloud/bigquery/load_job.rb +35 -27
  18. data/lib/gcloud/bigquery/project.rb +53 -73
  19. data/lib/gcloud/bigquery/query_data.rb +28 -35
  20. data/lib/gcloud/bigquery/query_job.rb +18 -18
  21. data/lib/gcloud/bigquery/schema.rb +359 -0
  22. data/lib/gcloud/bigquery/service.rb +506 -0
  23. data/lib/gcloud/bigquery/table.rb +185 -266
  24. data/lib/gcloud/bigquery/table/list.rb +15 -19
  25. data/lib/gcloud/bigquery/view.rb +126 -81
  26. data/lib/gcloud/datastore.rb +39 -27
  27. data/lib/gcloud/datastore/commit.rb +2 -2
  28. data/lib/gcloud/datastore/dataset.rb +8 -19
  29. data/lib/gcloud/datastore/dataset/lookup_results.rb +2 -4
  30. data/lib/gcloud/datastore/dataset/query_results.rb +0 -2
  31. data/lib/gcloud/datastore/entity.rb +7 -1
  32. data/lib/gcloud/datastore/errors.rb +5 -27
  33. data/lib/gcloud/datastore/grpc_utils.rb +4 -3
  34. data/lib/gcloud/datastore/key.rb +6 -0
  35. data/lib/gcloud/datastore/service.rb +18 -12
  36. data/lib/gcloud/datastore/transaction.rb +0 -10
  37. data/lib/gcloud/dns.rb +29 -19
  38. data/lib/gcloud/dns/change.rb +10 -15
  39. data/lib/gcloud/dns/change/list.rb +4 -4
  40. data/lib/gcloud/dns/importer.rb +1 -1
  41. data/lib/gcloud/dns/project.rb +32 -49
  42. data/lib/gcloud/dns/record.rb +8 -2
  43. data/lib/gcloud/dns/record/list.rb +4 -4
  44. data/lib/gcloud/dns/service.rb +167 -0
  45. data/lib/gcloud/dns/zone.rb +33 -52
  46. data/lib/gcloud/dns/zone/list.rb +12 -16
  47. data/lib/gcloud/errors.rb +31 -19
  48. data/lib/gcloud/logging.rb +50 -39
  49. data/lib/gcloud/logging/entry.rb +197 -24
  50. data/lib/gcloud/logging/entry/list.rb +0 -2
  51. data/lib/gcloud/logging/logger.rb +1 -1
  52. data/lib/gcloud/logging/metric.rb +3 -9
  53. data/lib/gcloud/logging/metric/list.rb +0 -2
  54. data/lib/gcloud/logging/project.rb +58 -54
  55. data/lib/gcloud/logging/resource_descriptor.rb +2 -2
  56. data/lib/gcloud/logging/resource_descriptor/list.rb +0 -2
  57. data/lib/gcloud/logging/service.rb +32 -23
  58. data/lib/gcloud/logging/sink.rb +8 -14
  59. data/lib/gcloud/logging/sink/list.rb +0 -2
  60. data/lib/gcloud/pubsub.rb +21 -16
  61. data/lib/gcloud/pubsub/policy.rb +204 -0
  62. data/lib/gcloud/pubsub/project.rb +26 -38
  63. data/lib/gcloud/pubsub/service.rb +39 -31
  64. data/lib/gcloud/pubsub/subscription.rb +56 -59
  65. data/lib/gcloud/pubsub/subscription/list.rb +4 -4
  66. data/lib/gcloud/pubsub/topic.rb +69 -66
  67. data/lib/gcloud/pubsub/topic/list.rb +0 -2
  68. data/lib/gcloud/pubsub/topic/{batch.rb → publisher.rb} +15 -2
  69. data/lib/gcloud/resource_manager.rb +27 -26
  70. data/lib/gcloud/resource_manager/manager.rb +19 -39
  71. data/lib/gcloud/resource_manager/policy.rb +211 -0
  72. data/lib/gcloud/resource_manager/project.rb +97 -121
  73. data/lib/gcloud/resource_manager/project/list.rb +7 -7
  74. data/lib/gcloud/resource_manager/project/updater.rb +4 -9
  75. data/lib/gcloud/resource_manager/service.rb +127 -0
  76. data/lib/gcloud/storage.rb +24 -42
  77. data/lib/gcloud/storage/bucket.rb +104 -192
  78. data/lib/gcloud/storage/bucket/acl.rb +47 -143
  79. data/lib/gcloud/storage/bucket/cors.rb +55 -11
  80. data/lib/gcloud/storage/bucket/list.rb +14 -14
  81. data/lib/gcloud/storage/errors.rb +3 -43
  82. data/lib/gcloud/storage/file.rb +114 -111
  83. data/lib/gcloud/storage/file/acl.rb +27 -113
  84. data/lib/gcloud/storage/file/list.rb +21 -21
  85. data/lib/gcloud/storage/project.rb +49 -59
  86. data/lib/gcloud/storage/service.rb +347 -0
  87. data/lib/gcloud/translate.rb +24 -14
  88. data/lib/gcloud/translate/api.rb +12 -21
  89. data/lib/gcloud/translate/detection.rb +5 -5
  90. data/lib/gcloud/translate/language.rb +1 -1
  91. data/lib/gcloud/translate/service.rb +80 -0
  92. data/lib/gcloud/translate/translation.rb +6 -6
  93. data/lib/gcloud/version.rb +1 -1
  94. data/lib/gcloud/vision.rb +24 -15
  95. data/lib/gcloud/vision/annotate.rb +24 -21
  96. data/lib/gcloud/vision/annotation.rb +9 -9
  97. data/lib/gcloud/vision/annotation/entity.rb +11 -11
  98. data/lib/gcloud/vision/annotation/face.rb +25 -25
  99. data/lib/gcloud/vision/annotation/properties.rb +8 -8
  100. data/lib/gcloud/vision/annotation/safe_search.rb +4 -4
  101. data/lib/gcloud/vision/annotation/text.rb +7 -7
  102. data/lib/gcloud/vision/annotation/vertex.rb +1 -1
  103. data/lib/gcloud/vision/image.rb +11 -11
  104. data/lib/gcloud/vision/location.rb +5 -2
  105. data/lib/gcloud/vision/project.rb +14 -16
  106. data/lib/gcloud/vision/service.rb +66 -0
  107. data/lib/google/api_client.rb +0 -0
  108. metadata +27 -24
  109. data/lib/gcloud/bigquery/connection.rb +0 -624
  110. data/lib/gcloud/bigquery/errors.rb +0 -68
  111. data/lib/gcloud/bigquery/table/schema.rb +0 -234
  112. data/lib/gcloud/dns/connection.rb +0 -173
  113. data/lib/gcloud/dns/errors.rb +0 -68
  114. data/lib/gcloud/resource_manager/connection.rb +0 -134
  115. data/lib/gcloud/resource_manager/errors.rb +0 -68
  116. data/lib/gcloud/storage/connection.rb +0 -444
  117. data/lib/gcloud/translate/connection.rb +0 -85
  118. data/lib/gcloud/translate/errors.rb +0 -68
  119. data/lib/gcloud/upload.rb +0 -95
  120. data/lib/gcloud/vision/connection.rb +0 -63
  121. data/lib/gcloud/vision/errors.rb +0 -69
@@ -31,21 +31,21 @@ module Gcloud
31
31
  # The table from which data is copied. This is the table on
32
32
  # which {Table#copy} was called. Returns a {Table} instance.
33
33
  def source
34
- table = config["copy"]["sourceTable"]
34
+ table = @gapi.configuration.copy.source_table
35
35
  return nil unless table
36
- retrieve_table table["projectId"],
37
- table["datasetId"],
38
- table["tableId"]
36
+ retrieve_table table.project_id,
37
+ table.dataset_id,
38
+ table.table_id
39
39
  end
40
40
 
41
41
  ##
42
42
  # The table to which data is copied. Returns a {Table} instance.
43
43
  def destination
44
- table = config["copy"]["destinationTable"]
44
+ table = @gapi.configuration.copy.destination_table
45
45
  return nil unless table
46
- retrieve_table table["projectId"],
47
- table["datasetId"],
48
- table["tableId"]
46
+ retrieve_table table.project_id,
47
+ table.dataset_id,
48
+ table.table_id
49
49
  end
50
50
 
51
51
  ##
@@ -53,7 +53,7 @@ module Gcloud
53
53
  # which provides the following behavior: If the table does not exist,
54
54
  # the copy operation creates the table. This is the default.
55
55
  def create_if_needed?
56
- disp = config["copy"]["createDisposition"]
56
+ disp = @gapi.configuration.copy.create_disposition
57
57
  disp == "CREATE_IF_NEEDED"
58
58
  end
59
59
 
@@ -62,7 +62,7 @@ module Gcloud
62
62
  # provides the following behavior: The table must already exist; if it
63
63
  # does not, an error is returned in the job result.
64
64
  def create_never?
65
- disp = config["copy"]["createDisposition"]
65
+ disp = @gapi.configuration.copy.create_disposition
66
66
  disp == "CREATE_NEVER"
67
67
  end
68
68
 
@@ -71,7 +71,7 @@ module Gcloud
71
71
  # provides the following behavior: If the table already exists, the copy
72
72
  # operation overwrites the table data.
73
73
  def write_truncate?
74
- disp = config["copy"]["writeDisposition"]
74
+ disp = @gapi.configuration.copy.write_disposition
75
75
  disp == "WRITE_TRUNCATE"
76
76
  end
77
77
 
@@ -80,7 +80,7 @@ module Gcloud
80
80
  # provides the following behavior: If the table already exists, the copy
81
81
  # operation appends the data to the table.
82
82
  def write_append?
83
- disp = config["copy"]["writeDisposition"]
83
+ disp = @gapi.configuration.copy.write_disposition
84
84
  disp == "WRITE_APPEND"
85
85
  end
86
86
 
@@ -89,7 +89,7 @@ module Gcloud
89
89
  # provides the following behavior: If the table already exists and
90
90
  # contains data, the job will have an error. This is the default.
91
91
  def write_empty?
92
- disp = config["copy"]["writeDisposition"]
92
+ disp = @gapi.configuration.copy.write_disposition
93
93
  disp == "WRITE_EMPTY"
94
94
  end
95
95
  end
@@ -14,6 +14,7 @@
14
14
 
15
15
 
16
16
  require "delegate"
17
+ require "gcloud/bigquery/service"
17
18
 
18
19
  module Gcloud
19
20
  module Bigquery
@@ -41,23 +42,26 @@ module Gcloud
41
42
  ##
42
43
  # The resource type of the API response.
43
44
  def kind
44
- @gapi["kind"]
45
+ @gapi.kind
45
46
  end
46
47
 
47
48
  ##
48
- # A token used for paging results.
49
- def token
50
- @gapi["pageToken"]
49
+ # The etag.
50
+ def etag
51
+ @gapi.etag
51
52
  end
52
53
 
53
- # A hash of this page of results.
54
- def etag
55
- @gapi["etag"]
54
+ ##
55
+ # A token used for paging results.
56
+ def token
57
+ @gapi.page_token
56
58
  end
57
59
 
58
60
  # The total number of rows in the complete table.
59
61
  def total
60
- @gapi["totalRows"]
62
+ Integer @gapi.total_rows
63
+ rescue
64
+ nil
61
65
  end
62
66
 
63
67
  ##
@@ -174,17 +178,17 @@ module Gcloud
174
178
  # Represents Table Data as a list of positional values (array of arrays).
175
179
  # No type conversion is made, e.g. numbers are formatted as strings.
176
180
  def raw
177
- Array(gapi["rows"]).map { |row| row["f"].map { |f| f["v"] } }
181
+ Array(gapi.rows).map { |row| row.f.map(&:v) }
178
182
  end
179
183
 
180
184
  ##
181
185
  # @private New Data from a response object.
182
- def self.from_response resp, table
183
- formatted_rows = format_rows resp.data["rows"], table.fields
186
+ def self.from_gapi gapi, table
187
+ formatted_rows = format_rows gapi.rows, table.fields
184
188
 
185
189
  data = new formatted_rows
186
190
  data.table = table
187
- data.gapi = resp.data
191
+ data.gapi = gapi
188
192
  data
189
193
  end
190
194
 
@@ -192,11 +196,11 @@ module Gcloud
192
196
  # Disabled rubocop because this implementation will not last.
193
197
 
194
198
  def self.format_rows rows, fields
195
- headers = Array(fields).map { |f| f["name"] }
196
- field_types = Array(fields).map { |f| f["type"] }
199
+ headers = Array(fields).map { |f| f.name }
200
+ field_types = Array(fields).map { |f| f.type }
197
201
 
198
202
  Array(rows).map do |row|
199
- values = row["f"].map { |f| f["v"] }
203
+ values = row.f.map { |f| f.v }
200
204
  formatted_values = format_values field_types, values
201
205
  Hash[headers.zip formatted_values]
202
206
  end
@@ -226,7 +230,7 @@ module Gcloud
226
230
  protected
227
231
 
228
232
  ##
229
- # Raise an error unless an active connection is available.
233
+ # Raise an error unless an active service is available.
230
234
  def ensure_table!
231
235
  fail "Must have active connection" unless table
232
236
  end
@@ -14,11 +14,12 @@
14
14
 
15
15
 
16
16
  require "json"
17
- require "gcloud/bigquery/errors"
17
+ require "gcloud/errors"
18
+ require "gcloud/bigquery/service"
18
19
  require "gcloud/bigquery/table"
19
- require "gcloud/bigquery/table/schema"
20
20
  require "gcloud/bigquery/dataset/list"
21
21
  require "gcloud/bigquery/dataset/access"
22
+ require "google/apis/bigquery_v2"
22
23
 
23
24
  module Gcloud
24
25
  module Bigquery
@@ -43,7 +44,7 @@ module Gcloud
43
44
  class Dataset
44
45
  ##
45
46
  # @private The Connection object.
46
- attr_accessor :connection
47
+ attr_accessor :service
47
48
 
48
49
  ##
49
50
  # @private The Google API Client object.
@@ -52,7 +53,7 @@ module Gcloud
52
53
  ##
53
54
  # @private Create an empty Dataset object.
54
55
  def initialize
55
- @connection = nil
56
+ @service = nil
56
57
  @gapi = {}
57
58
  end
58
59
 
@@ -64,7 +65,7 @@ module Gcloud
64
65
  # @!group Attributes
65
66
  #
66
67
  def dataset_id
67
- @gapi["datasetReference"]["datasetId"]
68
+ @gapi.dataset_reference.dataset_id
68
69
  end
69
70
 
70
71
  ##
@@ -73,7 +74,7 @@ module Gcloud
73
74
  # @!group Attributes
74
75
  #
75
76
  def project_id
76
- @gapi["datasetReference"]["projectId"]
77
+ @gapi.dataset_reference.project_id
77
78
  end
78
79
 
79
80
  ##
@@ -81,8 +82,8 @@ module Gcloud
81
82
  # The gapi fragment containing the Project ID and Dataset ID as a
82
83
  # camel-cased hash.
83
84
  def dataset_ref
84
- dataset_ref = @gapi["datasetReference"]
85
- dataset_ref = dataset_ref.to_hash if dataset_ref.respond_to? :to_hash
85
+ dataset_ref = @gapi.dataset_reference
86
+ dataset_ref = dataset_ref.to_h if dataset_ref.respond_to? :to_h
86
87
  dataset_ref
87
88
  end
88
89
 
@@ -92,7 +93,7 @@ module Gcloud
92
93
  # @!group Attributes
93
94
  #
94
95
  def name
95
- @gapi["friendlyName"]
96
+ @gapi.friendly_name
96
97
  end
97
98
 
98
99
  ##
@@ -101,7 +102,8 @@ module Gcloud
101
102
  # @!group Attributes
102
103
  #
103
104
  def name= new_name
104
- patch_gapi! name: new_name
105
+ @gapi.update! friendly_name: new_name
106
+ patch_gapi! :friendly_name
105
107
  end
106
108
 
107
109
  ##
@@ -111,7 +113,7 @@ module Gcloud
111
113
  #
112
114
  def etag
113
115
  ensure_full_data!
114
- @gapi["etag"]
116
+ @gapi.etag
115
117
  end
116
118
 
117
119
  ##
@@ -121,7 +123,7 @@ module Gcloud
121
123
  #
122
124
  def api_url
123
125
  ensure_full_data!
124
- @gapi["selfLink"]
126
+ @gapi.self_link
125
127
  end
126
128
 
127
129
  ##
@@ -131,7 +133,7 @@ module Gcloud
131
133
  #
132
134
  def description
133
135
  ensure_full_data!
134
- @gapi["description"]
136
+ @gapi.description
135
137
  end
136
138
 
137
139
  ##
@@ -140,7 +142,8 @@ module Gcloud
140
142
  # @!group Attributes
141
143
  #
142
144
  def description= new_description
143
- patch_gapi! description: new_description
145
+ @gapi.update! description: new_description
146
+ patch_gapi! :description
144
147
  end
145
148
 
146
149
  ##
@@ -150,7 +153,11 @@ module Gcloud
150
153
  #
151
154
  def default_expiration
152
155
  ensure_full_data!
153
- @gapi["defaultTableExpirationMs"]
156
+ begin
157
+ Integer @gapi.default_table_expiration_ms
158
+ rescue
159
+ nil
160
+ end
154
161
  end
155
162
 
156
163
  ##
@@ -160,7 +167,8 @@ module Gcloud
160
167
  # @!group Attributes
161
168
  #
162
169
  def default_expiration= new_default_expiration
163
- patch_gapi! default_expiration: new_default_expiration
170
+ @gapi.update! default_table_expiration_ms: new_default_expiration
171
+ patch_gapi! :default_table_expiration_ms
164
172
  end
165
173
 
166
174
  ##
@@ -170,7 +178,11 @@ module Gcloud
170
178
  #
171
179
  def created_at
172
180
  ensure_full_data!
173
- Time.at(@gapi["creationTime"] / 1000.0)
181
+ begin
182
+ Time.at(Integer(@gapi.creation_time) / 1000.0)
183
+ rescue
184
+ nil
185
+ end
174
186
  end
175
187
 
176
188
  ##
@@ -180,7 +192,11 @@ module Gcloud
180
192
  #
181
193
  def modified_at
182
194
  ensure_full_data!
183
- Time.at(@gapi["lastModifiedTime"] / 1000.0)
195
+ begin
196
+ Time.at(Integer(@gapi.last_modified_time) / 1000.0)
197
+ rescue
198
+ nil
199
+ end
184
200
  end
185
201
 
186
202
  ##
@@ -191,12 +207,11 @@ module Gcloud
191
207
  #
192
208
  def location
193
209
  ensure_full_data!
194
- @gapi["location"]
210
+ @gapi.location
195
211
  end
196
212
 
197
213
  ##
198
- # Retrieves the access rules for a Dataset using the Google Cloud
199
- # Datastore API data structure of an array of hashes. The rules can be
214
+ # Retrieves the access rules for a Dataset. The rules can be
200
215
  # updated when passing a block, see {Dataset::Access} for all the methods
201
216
  # available.
202
217
  #
@@ -206,6 +221,8 @@ module Gcloud
206
221
  # @yield [access] a block for setting rules
207
222
  # @yieldparam [Dataset::Access] access the object accepting rules
208
223
  #
224
+ # @return [Gcloud::Bigquery::Dataset::Access]
225
+ #
209
226
  # @example
210
227
  # require "gcloud"
211
228
  #
@@ -239,43 +256,15 @@ module Gcloud
239
256
  #
240
257
  def access
241
258
  ensure_full_data!
242
- g = @gapi
243
- g = g.to_hash if g.respond_to? :to_hash
244
- a = g["access"] ||= []
245
- return a unless block_given?
246
- a2 = Access.new a, dataset_ref
247
- yield a2
248
- self.access = a2.access if a2.changed?
249
- end
250
-
251
- ##
252
- # Sets the access rules for a Dataset using the Google Cloud Datastore API
253
- # data structure of an array of hashes. See [BigQuery Access
254
- # Control](https://cloud.google.com/bigquery/access-control) for more
255
- # information.
256
- #
257
- # This method is provided for advanced usage of managing the access rules.
258
- # Calling {#access} with a block is the preferred way to manage access
259
- # rules.
260
- #
261
- # @example
262
- # require "gcloud"
263
- #
264
- # gcloud = Gcloud.new
265
- # bigquery = gcloud.bigquery
266
- # dataset = bigquery.dataset "my_dataset"
267
- #
268
- # dataset.access = [{"role"=>"OWNER",
269
- # "specialGroup"=>"projectOwners"},
270
- # {"role"=>"WRITER",
271
- # "specialGroup"=>"projectWriters"},
272
- # {"role"=>"READER",
273
- # "specialGroup"=>"projectReaders"},
274
- # {"role"=>"OWNER",
275
- # "userByEmail"=>"123456789-...com"}]
276
- #
277
- def access= new_access
278
- patch_gapi! access: new_access
259
+ access_builder = Access.from_gapi @gapi
260
+ if block_given?
261
+ yield access_builder
262
+ if access_builder.changed?
263
+ @gapi.update! access: access_builder.to_gapi
264
+ patch_gapi! :access
265
+ end
266
+ end
267
+ access_builder.freeze
279
268
  end
280
269
 
281
270
  ##
@@ -300,13 +289,9 @@ module Gcloud
300
289
  # @!group Lifecycle
301
290
  #
302
291
  def delete force: nil
303
- ensure_connection!
304
- resp = connection.delete_dataset dataset_id, force
305
- if resp.success?
306
- true
307
- else
308
- fail ApiError.from_response(resp)
309
- end
292
+ ensure_service!
293
+ service.delete_dataset dataset_id, force
294
+ true
310
295
  end
311
296
 
312
297
  ##
@@ -320,13 +305,11 @@ module Gcloud
320
305
  # length is 1,024 characters.
321
306
  # @param [String] name A descriptive name for the table.
322
307
  # @param [String] description A user-friendly description of the table.
323
- # @param [Hash] schema A hash specifying fields and data types for the
324
- # table. A block may be passed instead (see examples.) For the format of
325
- # this hash, see the [Tables resource
326
- # ](https://cloud.google.com/bigquery/docs/reference/v2/tables#resource)
327
- # .
328
- # @yield [schema] a block for setting the schema
329
- # @yieldparam [Table::Schema] schema the object accepting the schema
308
+ # @param [Array<Schema::Field>] fields An array of Schema::Field objects
309
+ # specifying the schema's data types for the table. The schema may also
310
+ # be configured when passing a block.
311
+ # @yield [table] a block for setting the table
312
+ # @yieldparam [Table] table the table object to be updated
330
313
  #
331
314
  # @return [Gcloud::Bigquery::Table]
332
315
  #
@@ -348,69 +331,77 @@ module Gcloud
348
331
  # name: "My Table",
349
332
  # description: "A description of my table."
350
333
  #
351
- # @example You can define the table's schema using a block.
334
+ # @example The table's schema fields can be passed as an argument.
352
335
  # require "gcloud"
353
336
  #
354
337
  # gcloud = Gcloud.new
355
338
  # bigquery = gcloud.bigquery
356
339
  # dataset = bigquery.dataset "my_dataset"
357
- # table = dataset.create_table "my_table" do |schema|
358
- # schema.string "first_name", mode: :required
359
- # schema.record "cities_lived", mode: :repeated do |nested_schema|
360
- # nested_schema.string "place", mode: :required
361
- # nested_schema.integer "number_of_years", mode: :required
340
+ #
341
+ # schema_fields = [
342
+ # Gcloud::Bigquery::Schema::Field.new(
343
+ # "first_name", :string, mode: :required),
344
+ # Gcloud::Bigquery::Schema::Field.new(
345
+ # "cities_lived", :record, mode: :repeated
346
+ # fields: [
347
+ # Gcloud::Bigquery::Schema::Field.new(
348
+ # "place", :string, mode: :required),
349
+ # Gcloud::Bigquery::Schema::Field.new(
350
+ # "number_of_years", :integer, mode: :required),
351
+ # ])
352
+ # ]
353
+ # table = dataset.create_table "my_table", fields: schema_fields
354
+ #
355
+ # @example Or the table's schema can be configured with the block.
356
+ # require "gcloud"
357
+ #
358
+ # gcloud = Gcloud.new
359
+ # bigquery = gcloud.bigquery
360
+ # dataset = bigquery.dataset "my_dataset"
361
+ #
362
+ # table = dataset.create_table "my_table" do |t|
363
+ # t.schema.string "first_name", mode: :required
364
+ # t.schema.record "cities_lived", mode: :required do |s|
365
+ # s.string "place", mode: :required
366
+ # s.integer "number_of_years", mode: :required
362
367
  # end
363
368
  # end
364
369
  #
365
- # @example You can pass the table's schema as a hash.
370
+ # @example You can define the schema using a nested block.
366
371
  # require "gcloud"
367
372
  #
368
373
  # gcloud = Gcloud.new
369
374
  # bigquery = gcloud.bigquery
370
375
  # dataset = bigquery.dataset "my_dataset"
371
- #
372
- # schema = {
373
- # "fields" => [
374
- # {
375
- # "name" => "first_name",
376
- # "type" => "STRING",
377
- # "mode" => "REQUIRED"
378
- # },
379
- # {
380
- # "name" => "cities_lived",
381
- # "type" => "RECORD",
382
- # "mode" => "REPEATED",
383
- # "fields" => [
384
- # {
385
- # "name" => "place",
386
- # "type" => "STRING",
387
- # "mode" => "REQUIRED"
388
- # },
389
- # {
390
- # "name" => "number_of_years",
391
- # "type" => "INTEGER",
392
- # "mode" => "REQUIRED"
393
- # }
394
- # ]
395
- # }
396
- # ]
397
- # }
398
- # table = dataset.create_table "my_table", schema: schema
376
+ # table = dataset.create_table "my_table" do |t|
377
+ # t.name = "My Table",
378
+ # t.description = "A description of my table."
379
+ # t.schema do |s|
380
+ # s.string "first_name", mode: :required
381
+ # s.record "cities_lived", mode: :repeated do |r|
382
+ # r.string "place", mode: :required
383
+ # r.integer "number_of_years", mode: :required
384
+ # end
385
+ # end
386
+ # end
399
387
  #
400
388
  # @!group Table
401
389
  #
402
- def create_table table_id, name: nil, description: nil, schema: nil
403
- ensure_connection!
404
- if block_given?
405
- if schema
406
- fail ArgumentError, "only schema block or schema option is allowed"
407
- end
408
- schema_builder = Table::Schema.new nil
409
- yield schema_builder
410
- schema = schema_builder.schema if schema_builder.changed?
390
+ def create_table table_id, name: nil, description: nil, fields: nil
391
+ ensure_service!
392
+ new_tb = Google::Apis::BigqueryV2::Table.new(
393
+ table_reference: Google::Apis::BigqueryV2::TableReference.new(
394
+ project_id: project_id, dataset_id: dataset_id, table_id: table_id))
395
+ updater = Table::Updater.new(new_tb).tap do |tb|
396
+ tb.name = name unless name.nil?
397
+ tb.description = description unless description.nil?
398
+ tb.schema.fields = fields unless fields.nil?
411
399
  end
412
- options = { name: name, description: description, schema: schema }
413
- insert_table table_id, options
400
+
401
+ yield updater if block_given?
402
+
403
+ gapi = service.insert_table dataset_id, updater.to_gapi
404
+ Table.from_gapi gapi, service
414
405
  end
415
406
 
416
407
  ##
@@ -448,8 +439,20 @@ module Gcloud
448
439
  # @!group Table
449
440
  #
450
441
  def create_view table_id, query, name: nil, description: nil
451
- options = { query: query, name: name, description: description }
452
- insert_table table_id, options
442
+ new_view_opts = {
443
+ table_reference: Google::Apis::BigqueryV2::TableReference.new(
444
+ project_id: project_id, dataset_id: dataset_id, table_id: table_id
445
+ ),
446
+ friendly_name: name,
447
+ description: description,
448
+ view: Google::Apis::BigqueryV2::ViewDefinition.new(
449
+ query: query
450
+ )
451
+ }.delete_if { |_, v| v.nil? }
452
+ new_view = Google::Apis::BigqueryV2::Table.new new_view_opts
453
+
454
+ gapi = service.insert_table dataset_id, new_view
455
+ Table.from_gapi gapi, service
453
456
  end
454
457
 
455
458
  ##
@@ -472,13 +475,11 @@ module Gcloud
472
475
  # @!group Table
473
476
  #
474
477
  def table table_id
475
- ensure_connection!
476
- resp = connection.get_table dataset_id, table_id
477
- if resp.success?
478
- Table.from_gapi resp.data, connection
479
- else
480
- nil
481
- end
478
+ ensure_service!
479
+ gapi = service.get_table dataset_id, table_id
480
+ Table.from_gapi gapi, service
481
+ rescue Gcloud::NotFoundError
482
+ nil
482
483
  end
483
484
 
484
485
  ##
@@ -516,14 +517,10 @@ module Gcloud
516
517
  # @!group Table
517
518
  #
518
519
  def tables token: nil, max: nil
519
- ensure_connection!
520
+ ensure_service!
520
521
  options = { token: token, max: max }
521
- resp = connection.list_tables dataset_id, options
522
- if resp.success?
523
- Table::List.from_response resp, connection, dataset_id, max
524
- else
525
- fail ApiError.from_response(resp)
526
- end
522
+ gapi = service.list_tables dataset_id, options
523
+ Table::List.from_gapi gapi, service, dataset_id, max
527
524
  end
528
525
 
529
526
  ##
@@ -597,13 +594,9 @@ module Gcloud
597
594
  create: create, write: write, large_results: large_results,
598
595
  flatten: flatten }
599
596
  options[:dataset] ||= self
600
- ensure_connection!
601
- resp = connection.query_job query, options
602
- if resp.success?
603
- Job.from_gapi resp.data, connection
604
- else
605
- fail ApiError.from_response(resp)
606
- end
597
+ ensure_service!
598
+ gapi = service.query_job query, options
599
+ Job.from_gapi gapi, service
607
600
  end
608
601
 
609
602
  ##
@@ -658,13 +651,9 @@ module Gcloud
658
651
  options = { max: max, timeout: timeout, dryrun: dryrun, cache: cache }
659
652
  options[:dataset] ||= dataset_id
660
653
  options[:project] ||= project_id
661
- ensure_connection!
662
- resp = connection.query query, options
663
- if resp.success?
664
- QueryData.from_gapi resp.data, connection
665
- else
666
- fail ApiError.from_response(resp)
667
- end
654
+ ensure_service!
655
+ gapi = service.query query, options
656
+ QueryData.from_gapi gapi, service
668
657
  end
669
658
 
670
659
  ##
@@ -672,35 +661,26 @@ module Gcloud
672
661
  def self.from_gapi gapi, conn
673
662
  new.tap do |f|
674
663
  f.gapi = gapi
675
- f.connection = conn
664
+ f.service = conn
676
665
  end
677
666
  end
678
667
 
679
668
  protected
680
669
 
681
- def insert_table table_id, options
682
- resp = connection.insert_table dataset_id, table_id, options
683
- if resp.success?
684
- Table.from_gapi resp.data, connection
685
- else
686
- fail ApiError.from_response(resp)
687
- end
688
- end
689
-
690
670
  ##
691
- # Raise an error unless an active connection is available.
692
- def ensure_connection!
693
- fail "Must have active connection" unless connection
671
+ # Raise an error unless an active service is available.
672
+ def ensure_service!
673
+ fail "Must have active connection" unless service
694
674
  end
695
675
 
696
- def patch_gapi! options = {}
697
- ensure_connection!
698
- resp = connection.patch_dataset dataset_id, options
699
- if resp.success?
700
- @gapi = resp.data
701
- else
702
- fail ApiError.from_response(resp)
703
- end
676
+ def patch_gapi! *attributes
677
+ return if attributes.empty?
678
+ ensure_service!
679
+ patch_args = Hash[attributes.map do |attr|
680
+ [attr, @gapi.send(attr)]
681
+ end]
682
+ patch_gapi = Google::Apis::BigqueryV2::Dataset.new patch_args
683
+ @gapi = service.patch_dataset dataset_id, patch_gapi
704
684
  end
705
685
 
706
686
  ##
@@ -711,17 +691,62 @@ module Gcloud
711
691
  end
712
692
 
713
693
  def reload_gapi!
714
- ensure_connection!
715
- resp = connection.get_dataset dataset_id
716
- if resp.success?
717
- @gapi = resp.data
718
- else
719
- fail ApiError.from_response(resp)
720
- end
694
+ ensure_service!
695
+ gapi = service.get_dataset dataset_id
696
+ @gapi = gapi
721
697
  end
722
698
 
723
699
  def data_complete?
724
- !@gapi["creationTime"].nil?
700
+ @gapi.is_a? Google::Apis::BigqueryV2::Dataset
701
+ end
702
+
703
+ ##
704
+ # Yielded to a block to accumulate changes for a patch request.
705
+ class Updater < Dataset
706
+ ##
707
+ # A list of attributes that were updated.
708
+ attr_reader :updates
709
+
710
+ ##
711
+ # Create an Updater object.
712
+ def initialize gapi
713
+ @updates = []
714
+ @gapi = gapi
715
+ end
716
+
717
+ def access
718
+ # TODO: make sure to call ensure_full_data! on Dataset#update
719
+ @access ||= Access.from_gapi @gapi
720
+ if block_given?
721
+ yield @access
722
+ check_for_mutated_access!
723
+ end
724
+ # Same as Dataset#access, but not frozen
725
+ @access
726
+ end
727
+
728
+ ##
729
+ # Make sure any access changes are saved
730
+ def check_for_mutated_access!
731
+ return if @access.nil?
732
+ return unless @access.changed?
733
+ @gapi.update! access: @access.to_gapi
734
+ patch_gapi! :access
735
+ end
736
+
737
+ def to_gapi
738
+ check_for_mutated_access!
739
+ @gapi
740
+ end
741
+
742
+ protected
743
+
744
+ ##
745
+ # Queue up all the updates instead of making them.
746
+ def patch_gapi! attribute
747
+ @updates << attribute
748
+ @updates.uniq!
749
+ end
725
750
  end
726
751
  end
727
752
  end