kura 0.1.1 → 0.1.2

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: a3b3f01fed1dd8a0b55be71b85f918308f6a9362
4
- data.tar.gz: 72e91b8d8eca47315fb73a3cd98b48d04bf80a8b
3
+ metadata.gz: d152cd817d2c2b1d5ca66756310e5af0a4a1d338
4
+ data.tar.gz: a18b967e4fec4f97b1d22937590ef5e9866f4f96
5
5
  SHA512:
6
- metadata.gz: 1d863fa3c9d9c6463d292863285ee5843a372ef0587e4ed2c77d7be59138d310fe9ea66a32334a5b386d22d3805b8b9bec11ff3d012fb9dd4ed171855068c942
7
- data.tar.gz: 4c84a956904d442888657c43c196bfa6221a31dc0a415d1c77543a6f1755abe614c9de5ad926f0e3d988afa0dc714657e326d55e380afe134f7422cdebbcc19f
6
+ metadata.gz: a834c80e7c6eec7e1aea2c32a37616e4adbbdfc44509df5f49c3e5859eedce046d69b256d3919d1fb38267de61734e59f496a52a35a3910a7eebcfb582b8f180
7
+ data.tar.gz: dd055673db99ecd8c38bf2810c7d44c53ee449292e08bd0a53206bc3a9072b372bc1bdf3accc2e5ed15b48b266e350df38af60891b0758487004891b45be815d
@@ -1,3 +1,43 @@
1
+ # 0.1.2
2
+
3
+ ## Incompatible Changes
4
+
5
+ * Kura::Client#load: 3rd argument `source_uris` is now optional (default value is nil)
6
+ because is is not required on multipart upload. `source_uris` and keyworkd argument `file` is exclusive.
7
+ * Kura::Client#load: 4th argument `schema` become keyword argument. It is marked as [Optional] in
8
+ [API Reference](https://cloud.google.com/bigquery/docs/reference/v2/jobs#configuration.load.schema)
9
+ * Kura::Client#query: 1st and 2nd argument `dataset_id`, `table_id` become keyord argument.
10
+ destinationTable is an [Optional] parameter.
11
+
12
+ ## Enhancements
13
+
14
+ * Kura::Client#load support keyword argument `file` for multipart upload.
15
+ * Add optional keyword arguments of Kura::Client#load.
16
+ * `field_delimiter`
17
+ * `allow_jagged_rows`
18
+ * `max_bad_records`
19
+ * `ignore_unknown_values`
20
+ * `allow_quoted_newlines`
21
+ * `quote`
22
+ * `skip_leading_rows`
23
+ * `source_format`
24
+ * Kura::Client#load keyword argument `delimiter` is deprecated. It is alias of `field_delimiter` now.
25
+ * Add optional keyword arguments of Kura::Client#query.
26
+ * `flatten_results`
27
+ * `priority`
28
+ * `use_query_cache`
29
+ * Kura::Client#query keyword argument `allow_large_result` is deprecated. It is alias of `allow_large_results` now.
30
+ * Add optional keyword arguments of Kura::Client#extract.
31
+ * `compression`
32
+ * `destination_format`
33
+ * `field_delimiter`
34
+ * `print_header`
35
+ * Fix error handling. Kura::ApiError#reason was missing.
36
+ * Add Kura::Client#list_tabledata API.
37
+
1
38
  # 0.1.1
39
+
40
+ ## Enhancements
41
+
2
42
  * Add Kura::Client#tables API.
3
43
  * Kura::Client#wait_job yield block every second if block was passed.
@@ -24,7 +24,8 @@ module Kura
24
24
  def datasets(project_id: @project_id, all: false, limit: 1000)
25
25
  r = @api.execute(api_method: @bigquery_api.datasets.list, parameters: { projectId: project_id, all: all, maxResult: limit })
26
26
  unless r.success?
27
- raise Kura::ApiError.new(r.data["error"]["reason"], r.data["error"]["message"])
27
+ error = r.data["error"]["errors"][0]
28
+ raise Kura::ApiError.new(error["reason"], error["message"])
28
29
  end
29
30
  r.data.datasets
30
31
  end
@@ -35,7 +36,8 @@ module Kura
35
36
  if r.data.error["code"] == 404
36
37
  return nil
37
38
  else
38
- raise Kura::ApiError.new(r.data.error["reason"], r.data.error["message"])
39
+ error = r.data["error"]["errors"][0]
40
+ raise Kura::ApiError.new(error["reason"], error["message"])
39
41
  end
40
42
  end
41
43
  r.data
@@ -44,7 +46,8 @@ module Kura
44
46
  def insert_dataset(dataset_id)
45
47
  r = @api.execute(api_method: @bigquery_api.datasets.insert, parameters: { projectId: @project_id }, body_object: { datasetReference: { datasetId: dataset_id } })
46
48
  unless r.success?
47
- raise Kura::ApiError.new(r.data["error"]["reason"], r.data["error"]["message"])
49
+ error = r.data["error"]["errors"][0]
50
+ raise Kura::ApiError.new(error["reason"], error["message"])
48
51
  end
49
52
  r.data
50
53
  end
@@ -52,7 +55,8 @@ module Kura
52
55
  def delete_dataset(dataset_id, delete_contents: false)
53
56
  r = @api.execute(api_method: @bigquery_api.datasets.delete, parameters: { projectId: @project_id, datasetId: dataset_id, deleteContents: delete_contents })
54
57
  unless r.success?
55
- raise Kura::ApiError.new(r.data["error"]["reason"], r.data["error"]["message"])
58
+ error = r.data["error"]["errors"][0]
59
+ raise Kura::ApiError.new(error["reason"], error["message"])
56
60
  end
57
61
  r.data
58
62
  end
@@ -65,7 +69,8 @@ module Kura
65
69
  body["friendlyName"] = friendly_name if friendly_name
66
70
  r = @api.execute(api_method: @bigquery_api.datasets.patch, parameters: { projectId: project_id, datasetId: dataset_id }, body_object: body)
67
71
  unless r.success?
68
- raise Kura::ApiError.new(r.data["error"]["reason"], r.data["error"]["message"])
72
+ error = r.data["error"]["errors"][0]
73
+ raise Kura::ApiError.new(error["reason"], error["message"])
69
74
  end
70
75
  r.data
71
76
  end
@@ -74,7 +79,8 @@ module Kura
74
79
  params = { projectId: project_id, datasetId: dataset_id, maxResult: limit }
75
80
  r = @api.execute(api_method: @bigquery_api.tables.list, parameters: params)
76
81
  unless r.success?
77
- raise Kura::ApiError.new(r.data["error"]["reason"], r.data["error"]["message"])
82
+ error = r.data["error"]["errors"][0]
83
+ raise Kura::ApiError.new(error["reason"], error["message"])
78
84
  end
79
85
  r.data.tables
80
86
  end
@@ -86,7 +92,8 @@ module Kura
86
92
  if r.data["error"]["code"] == 404
87
93
  return nil
88
94
  else
89
- raise Kura::ApiError.new(r.data["error"]["reason"], r.data["error"]["message"])
95
+ error = r.data["error"]["errors"][0]
96
+ raise Kura::ApiError.new(error["reason"], error["message"])
90
97
  end
91
98
  end
92
99
  r.data
@@ -99,12 +106,36 @@ module Kura
99
106
  if r.data["error"]["code"] == 404
100
107
  return nil
101
108
  else
102
- raise Kura::ApiError.new(r.data["error"]["reason"], r.data["error"]["message"])
109
+ error = r.data["error"]["errors"][0]
110
+ raise Kura::ApiError.new(error["reason"], error["message"])
103
111
  end
104
112
  end
105
113
  r.data
106
114
  end
107
115
 
116
+ def list_tabledata(dataset_id, table_id, project_id: @project_id, start_index: 0, max_result: 100, page_token: nil, schema: nil)
117
+ schema ||= table(dataset_id, table_id, project_id: project_id).schema.fields
118
+ field_names = schema.map{|f| f["name"] }
119
+ params = { projectId: project_id, datasetId: dataset_id, tableId: table_id, maxResults: max_result }
120
+ if page_token
121
+ params[:pageToken] = page_token
122
+ else
123
+ params[:startIndex] = start_index
124
+ end
125
+ r = @api.execute(api_method: @bigquery_api.tabledata.list, parameters: params)
126
+ unless r.success?
127
+ error = r.data["error"]["errors"][0]
128
+ raise Kura::ApiError.new(error["reason"], error["message"])
129
+ end
130
+ {
131
+ total_rows: r.data.totalRows,
132
+ next_token: r.data["pageToken"],
133
+ rows: r.data.rows.map do |row|
134
+ row.f.zip(field_names).each_with_object({}) do |(v, fn), tbl| tbl[fn] = v.v end
135
+ end
136
+ }
137
+ end
138
+
108
139
  def mode_to_write_disposition(mode)
109
140
  unless %i{ append truncate empty }.include?(mode)
110
141
  raise "mode option should be one of :append, :truncate, :empty but #{mode}"
@@ -113,12 +144,16 @@ module Kura
113
144
  end
114
145
  private :mode_to_write_disposition
115
146
 
116
- def insert_job(configuration, wait: nil)
147
+ def insert_job(configuration, media: nil, wait: nil)
117
148
  params = { projectId: @project_id }
149
+ if media
150
+ params["uploadType"] = "multipart"
151
+ end
118
152
  body = { configuration: configuration }
119
- r = @api.execute(api_method: @bigquery_api.jobs.insert, parameters: params, body_object: body)
153
+ r = @api.execute(api_method: @bigquery_api.jobs.insert, parameters: params, body_object: body, media: media)
120
154
  unless r.success?
121
- raise Kura::ApiError.new(r.data["error"]["reason"], r.data["error"]["message"])
155
+ error = r.data["error"]["errors"][0]
156
+ raise Kura::ApiError.new(error["reason"], error["message"])
122
157
  end
123
158
  if wait
124
159
  wait_job(r.data.jobReference.jobId, wait)
@@ -127,42 +162,83 @@ module Kura
127
162
  end
128
163
  end
129
164
 
130
- def query(dataset_id, table_id, sql, mode: :truncate, allow_large_result: true, wait: nil)
165
+ def query(sql, mode: :truncate,
166
+ dataset_id: nil, table_id: nil,
167
+ allow_large_result: true, # for backward compatibility
168
+ allow_large_results: allow_large_result,
169
+ flatten_results: true,
170
+ priority: "INTERACTIVE",
171
+ use_query_cache: true,
172
+ wait: nil)
131
173
  write_disposition = mode_to_write_disposition(mode)
132
174
  configuration = {
133
175
  query: {
134
176
  query: sql,
135
- destinationTable: { projectId: @project_id, datasetId: dataset_id, tableId: table_id },
136
177
  writeDisposition: write_disposition,
137
- allowLargeResults: allow_large_result,
178
+ allowLargeResults: allow_large_results,
179
+ flattenResults: flatten_results,
180
+ priority: priority,
181
+ useQueryCache: use_query_cache,
138
182
  }
139
183
  }
184
+ if dataset_id and table_id
185
+ configuration[:query][:destinationTable] = { projectId: @project_id, datasetId: dataset_id, tableId: table_id }
186
+ end
140
187
  insert_job(configuration, wait: wait)
141
188
  end
142
189
 
143
- def load(dataset_id, table_id, source_uris, schema, delimiter: ",", mode: :append, wait: nil)
190
+ def load(dataset_id, table_id, source_uris=nil,
191
+ schema: nil, delimiter: ",", field_delimiter: delimiter, mode: :append,
192
+ allow_jagged_rows: false, max_bad_records: 0,
193
+ ignore_unknown_values: false,
194
+ allow_quoted_newlines: false,
195
+ quote: '"', skip_leading_rows: 0,
196
+ source_format: "CSV",
197
+ file: nil, wait: nil)
144
198
  write_disposition = mode_to_write_disposition(mode)
145
199
  source_uris = [source_uris] if source_uris.is_a?(String)
146
200
  configuration = {
147
201
  load: {
148
- sourceUris: source_uris,
149
202
  destinationTable: {
150
203
  projectId: @project_id,
151
204
  datasetId: dataset_id,
152
205
  tableId: table_id,
153
206
  },
154
- fieldDelimiter: delimiter,
155
207
  writeDisposition: write_disposition,
156
- schema: { fields: schema },
208
+ allowJaggedRows: allow_jagged_rows,
209
+ maxBadRecords: max_bad_records,
210
+ ignoreUnknownValues: ignore_unknown_values,
211
+ sourceFormat: source_format,
157
212
  }
158
213
  }
159
- insert_job(configuration, wait: wait)
214
+ if schema
215
+ configuration[:load][:schema] = { fields: schema }
216
+ end
217
+ if source_format == "CSV"
218
+ configuration[:load][:fieldDelimiter] = field_delimiter
219
+ configuration[:load][:allowQuotedNewlines] = allow_quoted_newlines
220
+ configuration[:load][:quote] = quote
221
+ configuration[:load][:skipLeadingRows] = skip_leading_rows
222
+ end
223
+ if file
224
+ file = Google::APIClient::UploadIO.new(file, "application/octet-stream")
225
+ else
226
+ configuration[:load][:sourceUris] = source_uris
227
+ end
228
+ insert_job(configuration, media: file, wait: wait)
160
229
  end
161
230
 
162
- def extract(dataset_id, table_id, dest_uris, wait: nil)
231
+ def extract(dataset_id, table_id, dest_uris,
232
+ compression: "NONE",
233
+ destination_format: "CSV",
234
+ field_delimiter: ",",
235
+ print_header: true,
236
+ wait: nil)
163
237
  dest_uris = [ dest_uris ] if dest_uris.is_a?(String)
164
238
  configuration = {
165
239
  extract: {
240
+ compression: compression,
241
+ destinationFormat: destination_format,
166
242
  sourceTable: {
167
243
  projectId: @project_id,
168
244
  datasetId: dataset_id,
@@ -171,6 +247,10 @@ module Kura
171
247
  destinationUris: dest_uris,
172
248
  }
173
249
  }
250
+ if destination_format == "CSV"
251
+ configuration[:extract][:fieldDelimiter] = field_delimiter
252
+ configuration[:extract][:printHeader] = print_header
253
+ end
174
254
  insert_job(configuration, wait: wait)
175
255
  end
176
256
 
@@ -198,13 +278,13 @@ module Kura
198
278
  params = { projectId: @project_id, jobId: job_id }
199
279
  r = @api.execute(api_method: @bigquery_api.jobs.get, parameters: params)
200
280
  unless r.success?
201
- raise Kura::ApiError.new(r.data["error"]["reason"], r.data["error"]["message"])
281
+ error = r.data["error"]["errors"][0]
282
+ raise Kura::ApiError.new(error["reason"], error["message"])
202
283
  end
203
284
  r.data
204
285
  end
205
286
 
206
- def job_finished?(job_id)
207
- r = job(job_id)
287
+ def job_finished?(r)
208
288
  if r.status.state == "DONE"
209
289
  if r.status["errorResult"]
210
290
  raise Kura::ApiError.new(r.status.errorResult.reason, r.status.errorResult.message)
@@ -217,11 +297,12 @@ module Kura
217
297
  def wait_job(job_id, timeout=60*10)
218
298
  expire = Time.now + timeout
219
299
  while expire > Time.now
220
- if job_finished?(job_id)
221
- return true
300
+ j = job(job_id)
301
+ if job_finished?(j)
302
+ return j
222
303
  end
223
304
  if block_given?
224
- yield
305
+ yield j
225
306
  end
226
307
  sleep 1
227
308
  end
@@ -1,3 +1,3 @@
1
1
  module Kura
2
- VERSION = "0.1.1"
2
+ VERSION = "0.1.2"
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: kura
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.1
4
+ version: 0.1.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Chikanaga Tomoyuki
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2015-07-14 00:00:00.000000000 Z
11
+ date: 2015-07-22 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: google-api-client