td-client 0.8.82 → 0.8.83
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/td/client.rb +3 -3
- data/lib/td/client/api.rb +20 -20
- data/lib/td/client/api/bulk_load.rb +3 -3
- data/lib/td/client/model.rb +46 -12
- data/lib/td/client/version.rb +1 -1
- data/spec/td/client/api_spec.rb +29 -3
- data/spec/td/client/bulk_load_spec.rb +25 -0
- data/spec/td/client/model_job_spec.rb +4 -4
- data/spec/td/client/table_api_spec.rb +8 -8
- metadata +3 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: d3662e5e2dfaa4e0eef6afb81bee1ba5eda81b2f
|
4
|
+
data.tar.gz: 4863761d3f0b4851a94348f776a09d923cec2e85
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 4c40f28abe243f4ad108595155324da7c93f56e57ac81564ffcc7dfba6f310a3a22abae62ae8447eb5a9753e0abdad3cfc0611410606d8ba485e9e173f44d2eb
|
7
|
+
data.tar.gz: d5a1d2e957400ab340b0a5ba91634575f08d27029eb363bc8c9d57ba41a55cbf64b2b87e3846a6f200ea846d99371c8b9a9f80dff513a854c584eac050e455fa
|
data/lib/td/client.rb
CHANGED
@@ -574,9 +574,9 @@ class Client
|
|
574
574
|
@api.bulk_load_show(name)
|
575
575
|
end
|
576
576
|
|
577
|
-
# name: String,
|
578
|
-
def bulk_load_update(name,
|
579
|
-
@api.bulk_load_update(name,
|
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
|
data/lib/td/client/api.rb
CHANGED
@@ -174,7 +174,26 @@ class API
|
|
174
174
|
|
175
175
|
# @param [String] name
|
176
176
|
def self.validate_column_name(name)
|
177
|
-
|
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,
|
120
|
-
def bulk_load_update(name,
|
119
|
+
# name: String, settings: Hash -> Hash
|
120
|
+
def bulk_load_update(name, settings)
|
121
121
|
path = session_path(name)
|
122
|
-
res = api { put(path,
|
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
|
data/lib/td/client/model.rb
CHANGED
@@ -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
|
-
|
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]
|
303
|
+
# @param [String] columns
|
290
304
|
# @return [Schema]
|
291
|
-
def self.parse(
|
292
|
-
|
293
|
-
|
294
|
-
|
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
|
-
|
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
|
-
@
|
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
|
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 ::
|
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?
|
data/lib/td/client/version.rb
CHANGED
data/spec/td/client/api_spec.rb
CHANGED
@@ -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
|
-
['
|
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
|
-
|
141
|
-
|
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(
|
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 ::
|
111
|
+
it 'raise Timeout::Error' do
|
112
112
|
expect {
|
113
113
|
job.wait(0.1)
|
114
|
-
}.to raise_error(::
|
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(::
|
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", "[[\"
|
86
|
-
["table_2", "log", "[[\"
|
87
|
-
["table_3", "item", "[[\"
|
88
|
-
["table_4", "log", "[[\"
|
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", "[[\"
|
142
|
-
["table_2", "log", "[[\"
|
143
|
-
["table_3", "item", "[[\"
|
144
|
-
["table_4", "log", "[[\"
|
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.
|
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-
|
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:
|
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
|