td-client 0.8.82 → 0.8.83

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: bf42a2c04e997054b7071bd6dc6038738a8857a6
4
- data.tar.gz: 360933ff5ee21f22dbb9fce7b5acab14a23006f4
3
+ metadata.gz: d3662e5e2dfaa4e0eef6afb81bee1ba5eda81b2f
4
+ data.tar.gz: 4863761d3f0b4851a94348f776a09d923cec2e85
5
5
  SHA512:
6
- metadata.gz: ab861c2082d0eb19039a928c59e18414f64d31b15303ab4e11144f3290eeb9b29bacbd26ec721d2eb85f25b8935c571c3b0a27ae660885454756fddfae37fbdc
7
- data.tar.gz: d562b950d3c9c09d2bf25cef45d2397212a5ea654fc7ca6bf002c403dd9cc76022a0a8db6203f9218ccf40457bfd4fe8c7134592d71875993a5c40181db1e6b4
6
+ metadata.gz: 4c40f28abe243f4ad108595155324da7c93f56e57ac81564ffcc7dfba6f310a3a22abae62ae8447eb5a9753e0abdad3cfc0611410606d8ba485e9e173f44d2eb
7
+ data.tar.gz: d5a1d2e957400ab340b0a5ba91634575f08d27029eb363bc8c9d57ba41a55cbf64b2b87e3846a6f200ea846d99371c8b9a9f80dff513a854c584eac050e455fa
@@ -574,9 +574,9 @@ class Client
574
574
  @api.bulk_load_show(name)
575
575
  end
576
576
 
577
- # name: String, job: BulkLoad -> BulkLoad
578
- def bulk_load_update(name, job)
579
- @api.bulk_load_update(name, job)
577
+ # name: String, settings: Hash -> BulkLoad
578
+ def bulk_load_update(name, settings)
579
+ @api.bulk_load_update(name, settings)
580
580
  end
581
581
 
582
582
  # name: String -> BulkLoad
@@ -174,7 +174,26 @@ class API
174
174
 
175
175
  # @param [String] name
176
176
  def self.validate_column_name(name)
177
- validate_name("column", 1, 255, name)
177
+ target = 'column'
178
+ min_len = 1
179
+ max_len = 128
180
+ name = name.to_s
181
+ if name.empty?
182
+ raise ParameterValidationError,
183
+ "Empty #{target} name is not allowed"
184
+ end
185
+ if name.length < min_len || name.length > max_len
186
+ raise ParameterValidationError,
187
+ "#{target.capitalize} name must be between #{min_len} and #{max_len} characters long. Got #{name.length} " +
188
+ (name.length == 1 ? "character" : "characters") + "."
189
+ end
190
+
191
+ name
192
+ end
193
+
194
+ # @param [String] name
195
+ def self.validate_sql_alias_name(name)
196
+ validate_name("sql_alias", 1, 128, name)
178
197
  end
179
198
 
180
199
  # @param [String] name
@@ -199,25 +218,6 @@ class API
199
218
  normalize_database_name(name)
200
219
  end
201
220
 
202
- # TODO support array types
203
- # @param [String] name
204
- def self.normalize_type_name(name)
205
- case name
206
- when /int/i, /integer/i
207
- "int"
208
- when /long/i, /bigint/i
209
- "long"
210
- when /string/i
211
- "string"
212
- when /float/i
213
- "float"
214
- when /double/i
215
- "double"
216
- else
217
- raise "Type name must either of int, long, string float or double"
218
- end
219
- end
220
-
221
221
  # for fluent-plugin-td / td command to check table existence with import onlt user
222
222
  # @return [String]
223
223
  def self.create_empty_gz_data
@@ -116,10 +116,10 @@ module BulkLoad
116
116
  JSON.load(res.body)
117
117
  end
118
118
 
119
- # name: String, job: Hash -> Hash
120
- def bulk_load_update(name, job)
119
+ # name: String, settings: Hash -> Hash
120
+ def bulk_load_update(name, settings)
121
121
  path = session_path(name)
122
- res = api { put(path, job.to_json) }
122
+ res = api { put(path, settings.to_json) }
123
123
  unless res.ok?
124
124
  raise_error("BulkLoadSession: #{name} update failed", res)
125
125
  end
@@ -269,36 +269,62 @@ class Table < Model
269
269
  def update_database!
270
270
  @database = @client.database(@db_name)
271
271
  end
272
+
273
+ # @return [String]
274
+ def inspect
275
+ %[#<%s:%#0#{1.size*2}x @db_name="%s" @table_name="%s">] %
276
+ [self.class.name, self.__id__*2, @db_name, @table_name]
277
+ end
272
278
  end
273
279
 
274
280
  class Schema
275
281
  class Field
276
282
  # @param [String] name
277
283
  # @param [String] type
278
- def initialize(name, type)
284
+ # @param [String] sql_alias
285
+ def initialize(name, type, sql_alias=nil)
286
+ if name == 'v' || name == 'time'
287
+ raise ParameterValidationError, "Column name '#{name}' is reserved."
288
+ end
289
+ API.validate_column_name(name)
290
+ API.validate_sql_alias_name(sql_alias) if sql_alias
279
291
  @name = name
280
292
  @type = type
293
+ @sql_alias = sql_alias
281
294
  end
282
295
 
283
296
  # @!attribute [r] name
284
297
  # @!attribute [r] type
285
298
  attr_reader :name
286
299
  attr_reader :type
300
+ attr_reader :sql_alias
287
301
  end
288
302
 
289
- # @param [String] cols
303
+ # @param [String] columns
290
304
  # @return [Schema]
291
- def self.parse(cols)
292
- fields = cols.split(',').map {|col|
293
- name, type, *_ = col.split(':')
294
- Field.new(name, type)
305
+ def self.parse(columns)
306
+ schema = Schema.new
307
+ columns.each {|column|
308
+ unless /\A(?<name>.*)(?::(?<type>[^:]+))(?:@(?<sql_alias>[^:@]+))?\z/ =~ column
309
+ raise ParameterValidationError, "type must be specified"
310
+ end
311
+ schema.add_field(name, type, sql_alias)
295
312
  }
296
- Schema.new(fields)
313
+ schema
297
314
  end
298
315
 
299
316
  # @param [Array] fields
300
317
  def initialize(fields=[])
301
318
  @fields = fields
319
+ @names = {}
320
+ @fields.each do |f|
321
+ raise ArgumentError, "Column name '#{f.name}' is duplicated." if @names.key?(f.name)
322
+ @names[f.name] = true
323
+ if f.sql_alias
324
+ raise ArgumentError, "SQL Column alias '#{f.sql_alias}' is duplicated." if @names.key?(f.sql_alias)
325
+ @names[f.sql_alias] = true
326
+ end
327
+ end
302
328
  end
303
329
 
304
330
  # @!attribute [r] fields
@@ -307,8 +333,16 @@ class Schema
307
333
  # @param [String] name
308
334
  # @param [String] type
309
335
  # @return [Array]
310
- def add_field(name, type)
311
- @fields << Field.new(name, type)
336
+ def add_field(name, type, sql_alias=nil)
337
+ if @names.key?(name)
338
+ raise ParameterValidationError, "Column name '#{name}' is duplicated."
339
+ end
340
+ @names[name] = true
341
+ if sql_alias && @names.key?(sql_alias)
342
+ raise ParameterValidationError, "SQL Column alias '#{sql_alias}' is duplicated."
343
+ end
344
+ @names[sql_alias] = true
345
+ @fields << Field.new(name, type, sql_alias)
312
346
  end
313
347
 
314
348
  # @param [Schema] schema
@@ -327,14 +361,14 @@ class Schema
327
361
 
328
362
  # @return [Array<Field>]
329
363
  def to_json(*args)
330
- @fields.map {|f| [f.name, f.type] }.to_json(*args)
364
+ @fields.map {|f| f.sql_alias ? [f.name, f.type, f.sql_alias] : [f.name, f.type] }.to_json(*args)
331
365
  end
332
366
 
333
367
  # @param [Object] obj
334
368
  # @return [self]
335
369
  def from_json(obj)
336
370
  @fields = obj.map {|f|
337
- Field.new(f[0], f[1])
371
+ Field.new(*f)
338
372
  }
339
373
  self
340
374
  end
@@ -416,7 +450,7 @@ class Job < Model
416
450
  d = t - t1
417
451
  t1 = t
418
452
  timeout -= d if d > 0
419
- raise ::TimeoutError, "timeout=#{orig_timeout} wait_interval=#{wait_interval}" if timeout <= 0
453
+ raise Timeout::Error, "timeout=#{orig_timeout} wait_interval=#{wait_interval}" if timeout <= 0
420
454
  end
421
455
  sleep wait_interval
422
456
  yield self if block_given?
@@ -1,5 +1,5 @@
1
1
  module TreasureData
2
2
  class Client
3
- VERSION = '0.8.82'
3
+ VERSION = '0.8.83'
4
4
  end
5
5
  end
@@ -126,7 +126,7 @@ describe API do
126
126
 
127
127
  describe "'validate_column_name'" do
128
128
  it 'should raise a ParameterValidationError exception' do
129
- ['/', '', 'D'].each { |ng|
129
+ ['', 'a'*129].each { |ng|
130
130
  expect {
131
131
  API.validate_column_name(ng)
132
132
  }.to raise_error(ParameterValidationError)
@@ -137,14 +137,40 @@ describe API do
137
137
  VALID_NAMES.each {|ok|
138
138
  expect(API.validate_column_name(ok)).to eq(ok)
139
139
  }
140
- # columns can be as short as 2 characters
141
- expect(API.validate_column_name('ab')).to eq('ab')
140
+ ['a', 'a'*128].each {|ok|
141
+ expect(API.validate_column_name(ok)).to eq(ok)
142
+ }
142
143
  end
143
144
  end
144
145
 
146
+ describe "'validate_sql_alias_name'" do
147
+ it 'should raise a ParameterValidationError exception' do
148
+ ['', 'a'*129].each { |ng|
149
+ expect{API.validate_sql_alias_name(ng)}.to raise_error(ParameterValidationError)
150
+ }
151
+ valid = ("a".."z").to_a.join<<("0".."9").to_a.join<<"_"
152
+ ("\x00".."\x7F").each { |ng|
153
+ next if valid.include?(ng)
154
+ expect{API.validate_sql_alias_name(ng)}.to raise_error(ParameterValidationError)
155
+ }
156
+ end
157
+
158
+ it 'should return valid data' do
159
+ VALID_NAMES.each {|ok|
160
+ expect(API.validate_sql_alias_name(ok)).to eq(ok)
161
+ }
162
+ ['a', '_a', 'a_', 'a'*128].each {|ok|
163
+ expect(API.validate_sql_alias_name(ok)).to eq(ok)
164
+ }
165
+ end
166
+ end
145
167
 
146
168
  describe "'generic validate_name'" do
147
169
  it 'should raise a ParameterValidationError exception' do
170
+ # wrong target
171
+ expect {
172
+ API.validate_name("", 3, 256, '')
173
+ }.to raise_error(ParameterValidationError)
148
174
  INVALID_NAMES.each_pair {|ng,ok|
149
175
  expect {
150
176
  API.validate_name("generic", 3, 256, ng)
@@ -336,6 +336,31 @@ describe 'BulkImport API' do
336
336
  bulk_load_session
337
337
  )).to eq(bulk_load_session)
338
338
  end
339
+
340
+ it 'returns updated bulk_load_session' do
341
+ updated_bulk_load_session = bulk_load_session.merge({'timezone' => 'America/Los Angeles'})
342
+ stub_api_request(:put, '/v3/bulk_loads/nahi_test_1').
343
+ with(:body => updated_bulk_load_session.to_json).
344
+ to_return(:body => updated_bulk_load_session.to_json)
345
+ expect(api.bulk_load_update(
346
+ 'nahi_test_1',
347
+ updated_bulk_load_session
348
+ )).to eq updated_bulk_load_session
349
+ end
350
+
351
+ it 'can remove the cron schedule ' do
352
+ updated_bulk_load_session = bulk_load_session.merge({'cron' => ''})
353
+ # NOTE: currently the API just ignores an empty 'cron' specification update
354
+ # I am assuming that once fixed, the API will return a nil for cron if unscheduled.
355
+ expected_bulk_load_session = (bulk_load_session['cron'] = nil)
356
+ stub_api_request(:put, '/v3/bulk_loads/nahi_test_1').
357
+ with(:body => updated_bulk_load_session.to_json).
358
+ to_return(:body => expected_bulk_load_session.to_json)
359
+ expect(api.bulk_load_update(
360
+ 'nahi_test_1',
361
+ updated_bulk_load_session
362
+ )).to eq expected_bulk_load_session
363
+ end
339
364
  end
340
365
 
341
366
  describe 'delete' do
@@ -97,7 +97,7 @@ describe 'Job Model' do
97
97
  }
98
98
  sleep 0.3
99
99
  change_job_status(Job::STATUS_SUCCESS)
100
- thread.join(0.5)
100
+ thread.join(1)
101
101
  expect(thread).to be_stop
102
102
  ensure
103
103
  thread.kill # just in case
@@ -108,10 +108,10 @@ describe 'Job Model' do
108
108
 
109
109
  context 'with timeout' do
110
110
  context 'the job running time is too long' do
111
- it 'raise ::TimeoutError' do
111
+ it 'raise Timeout::Error' do
112
112
  expect {
113
113
  job.wait(0.1)
114
- }.to raise_error(::TimeoutError)
114
+ }.to raise_error(Timeout::Error)
115
115
  end
116
116
  end
117
117
 
@@ -121,7 +121,7 @@ describe 'Job Model' do
121
121
  thread = Thread.start {
122
122
  job.wait(0.3, 0.1, &b)
123
123
  }
124
- expect{ thread.value }.to raise_error(::TimeoutError)
124
+ expect{ thread.value }.to raise_error(Timeout::Error)
125
125
  expect(thread).to be_stop
126
126
  ensure
127
127
  thread.kill # just in case
@@ -82,10 +82,10 @@ describe 'Table API' do
82
82
  describe "'tables' Client API" do
83
83
  it 'should return an array of Table objects' do
84
84
  tables = [
85
- ["table_1", "item", "[[\"time\",\"long\"],[\"value\",\"string\"]]", 111, "2013-01-21 01:51:41 UTC", "2014-01-21 01:51:41 UTC"],
86
- ["table_2", "log", "[[\"time\",\"long\"],[\"value\",\"long\"]]", 222, "2013-02-22 02:52:42 UTC", "2014-02-22 02:52:42 UTC"],
87
- ["table_3", "item", "[[\"time\",\"long\"],[\"value\",\"string\"]]", 333, "2013-03-23 03:53:43 UTC", "2014-03-23 03:53:43 UTC"],
88
- ["table_4", "log", "[[\"time\",\"long\"],[\"value\",\"long\"]]", 444, "2013-04-24 04:54:44 UTC", "2014-04-24 04:54:44 UTC"]
85
+ ["table_1", "item", "[[\"value\",\"string\"]]", 111, "2013-01-21 01:51:41 UTC", "2014-01-21 01:51:41 UTC"],
86
+ ["table_2", "log", "[[\"value\",\"long\"]]", 222, "2013-02-22 02:52:42 UTC", "2014-02-22 02:52:42 UTC"],
87
+ ["table_3", "item", "[[\"value\",\"string\"]]", 333, "2013-03-23 03:53:43 UTC", "2014-03-23 03:53:43 UTC"],
88
+ ["table_4", "log", "[[\"value\",\"long\"]]", 444, "2013-04-24 04:54:44 UTC", "2014-04-24 04:54:44 UTC"]
89
89
  ]
90
90
  stub_api_request(:get, "/v3/table/list/#{e db_name}").
91
91
  to_return(:body => {'tables' => [
@@ -138,10 +138,10 @@ describe 'Table API' do
138
138
  describe "'table' Client API" do
139
139
  it 'should return the Table object corresponding to the name' do
140
140
  tables = [
141
- ["table_1", "item", "[[\"time\",\"long\"],[\"value\",\"string\"]]", 111, "2013-01-21 01:51:41 UTC", "2014-01-21 01:51:41 UTC"],
142
- ["table_2", "log", "[[\"time\",\"long\"],[\"value\",\"long\"]]", 222, "2013-02-22 02:52:42 UTC", "2014-02-22 02:52:42 UTC"],
143
- ["table_3", "item", "[[\"time\",\"long\"],[\"value\",\"string\"]]", 333, "2013-03-23 03:53:43 UTC", "2014-03-23 03:53:43 UTC"],
144
- ["table_4", "log", "[[\"time\",\"long\"],[\"value\",\"long\"]]", 444, "2013-04-24 04:54:44 UTC", "2014-04-24 04:54:44 UTC"]
141
+ ["table_1", "item", "[[\"value\",\"string\"]]", 111, "2013-01-21 01:51:41 UTC", "2014-01-21 01:51:41 UTC"],
142
+ ["table_2", "log", "[[\"value\",\"long\"]]", 222, "2013-02-22 02:52:42 UTC", "2014-02-22 02:52:42 UTC"],
143
+ ["table_3", "item", "[[\"value\",\"string\"]]", 333, "2013-03-23 03:53:43 UTC", "2014-03-23 03:53:43 UTC"],
144
+ ["table_4", "log", "[[\"value\",\"long\"]]", 444, "2013-04-24 04:54:44 UTC", "2014-04-24 04:54:44 UTC"]
145
145
  ]
146
146
  stub_api_request(:get, "/v3/table/list/#{e db_name}").
147
147
  to_return(:body => {'tables' => [
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: td-client
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.8.82
4
+ version: 0.8.83
5
5
  platform: ruby
6
6
  authors:
7
7
  - Treasure Data, Inc.
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2016-07-11 00:00:00.000000000 Z
11
+ date: 2016-09-23 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: msgpack
@@ -257,7 +257,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
257
257
  requirements:
258
258
  - - ">="
259
259
  - !ruby/object:Gem::Version
260
- version: 1.8.7
260
+ version: 2.0.0
261
261
  required_rubygems_version: !ruby/object:Gem::Requirement
262
262
  requirements:
263
263
  - - ">="
@@ -291,4 +291,3 @@ test_files:
291
291
  - spec/td/client/user_api_spec.rb
292
292
  - spec/td/client_sched_spec.rb
293
293
  - spec/td/client_spec.rb
294
- has_rdoc: false