ddbcli 0.1.4 → 0.1.5
Sign up to get free protection for your applications and to get access to all the features.
- data/README +4 -0
- data/bin/ddbcli +8 -2
- data/lib/ddbcli/cli/help.rb +3 -0
- data/lib/ddbcli/cli/options.rb +6 -0
- data/lib/ddbcli/ddb-driver.rb +90 -19
- data/lib/ddbcli/ddb-parser.tab.rb +522 -503
- data/lib/ddbcli/ddb-parser.y +9 -0
- metadata +1 -1
data/README
CHANGED
@@ -26,6 +26,7 @@ https://bitbucket.org/winebarrel/ddbcli
|
|
26
26
|
-r, --region=REGION_OR_ENDPOINT
|
27
27
|
-e, --eval=COMMAND
|
28
28
|
-t, --timeout=SECOND
|
29
|
+
--import=TABLE,JSON_FILE
|
29
30
|
--consistent-read
|
30
31
|
--retry=NUM
|
31
32
|
--retry-interval=SECOND
|
@@ -56,6 +57,9 @@ https://bitbucket.org/winebarrel/ddbcli
|
|
56
57
|
) READ = num, WRITE = num
|
57
58
|
creates a table
|
58
59
|
|
60
|
+
CREATE TABLES table_name LIKE another_table_name [READ = num, WRITE = num]
|
61
|
+
creates a table like another table
|
62
|
+
|
59
63
|
DROP TABLE table_name
|
60
64
|
deletes a table
|
61
65
|
|
data/bin/ddbcli
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
2
|
$LOAD_PATH << File.join(File.dirname(__FILE__), '..', 'lib')
|
3
3
|
|
4
|
-
Version = '0.1.
|
4
|
+
Version = '0.1.5'
|
5
5
|
|
6
6
|
HISTORY_FILE = File.join((ENV['HOME'] || ENV['USERPROFILE'] || '.'), '.ddbcli_history')
|
7
7
|
HISTSIZE = 500
|
@@ -24,7 +24,13 @@ driver.retry_num = options.retry_num
|
|
24
24
|
driver.retry_intvl = options.retry_intvl
|
25
25
|
driver.debug = options.debug
|
26
26
|
|
27
|
-
if
|
27
|
+
if options.import
|
28
|
+
# import mode
|
29
|
+
table, file = options.import.values_at(:table, :file)
|
30
|
+
items = open(file) {|f| JSON.load(f) }
|
31
|
+
n = driver.import(table, items)
|
32
|
+
print_rownum(n)
|
33
|
+
elsif not $stdin.tty? or options.command
|
28
34
|
|
29
35
|
# run mode
|
30
36
|
src = options.command || $stdin.read.strip
|
data/lib/ddbcli/cli/help.rb
CHANGED
data/lib/ddbcli/cli/options.rb
CHANGED
@@ -22,6 +22,12 @@ def parse_options
|
|
22
22
|
opt.on('-r', '--region=REGION_OR_ENDPOINT') {|v| options.ddb_endpoint_or_region = v }
|
23
23
|
opt.on('-e', '--eval=COMMAND') {|v| options.command = v }
|
24
24
|
opt.on('-t', '--timeout=SECOND', Integer) {|v| options.timeout = v.to_i }
|
25
|
+
|
26
|
+
opt.on('', '--import=TABLE,JSON_FILE') {|v|
|
27
|
+
v = v.split(/\s*,\s*/, 2)
|
28
|
+
options.import = {:table => v[0], :file => v[1]}
|
29
|
+
}
|
30
|
+
|
25
31
|
opt.on('', '--consistent-read') { options.consistent = true }
|
26
32
|
opt.on('', '--iteratable') { options.iteratable = true }
|
27
33
|
opt.on('', '--retry=NUM', Integer) {|v| options.retry_num = v.to_i }
|
data/lib/ddbcli/ddb-driver.rb
CHANGED
@@ -62,6 +62,8 @@ module DynamoDB
|
|
62
62
|
do_use(parsed)
|
63
63
|
when :CREATE
|
64
64
|
do_create(parsed)
|
65
|
+
when :CREATE_LIKE
|
66
|
+
do_create_like(parsed)
|
65
67
|
when :DROP
|
66
68
|
do_drop(parsed)
|
67
69
|
when :DESCRIBE
|
@@ -94,25 +96,58 @@ module DynamoDB
|
|
94
96
|
raise 'must not happen'
|
95
97
|
end
|
96
98
|
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
99
|
+
begin
|
100
|
+
case script_type
|
101
|
+
when :ruby
|
102
|
+
retval = retval.data if retval.kind_of?(DynamoDB::Iteratorable)
|
103
|
+
retval.instance_eval(script)
|
104
|
+
when :shell
|
105
|
+
retval = retval.data if retval.kind_of?(DynamoDB::Iteratorable)
|
106
|
+
IO.popen(script, "r+") do |f|
|
107
|
+
f.puts(retval.kind_of?(Array) ? retval.map {|i| i.to_s }.join("\n") : retval.to_s)
|
108
|
+
f.close_write
|
109
|
+
f.read
|
110
|
+
end
|
111
|
+
else
|
112
|
+
retval
|
113
|
+
end
|
114
|
+
rescue Exception => e
|
115
|
+
raise DynamoDB::Error, e.message, e.backtrace
|
116
|
+
end
|
117
|
+
end
|
118
|
+
|
119
|
+
def import(table, items)
|
120
|
+
n = 0
|
121
|
+
|
122
|
+
until (chunk = items.slice!(0, MAX_NUMBER_BATCH_PROCESS_ITEMS)).empty?
|
123
|
+
operations = []
|
124
|
+
|
125
|
+
req_hash = {
|
126
|
+
'RequestItems' => {
|
127
|
+
table => operations,
|
128
|
+
},
|
129
|
+
}
|
130
|
+
|
131
|
+
chunk.each do |item|
|
132
|
+
h = {}
|
133
|
+
|
134
|
+
operations << {
|
135
|
+
'PutRequest' => {
|
136
|
+
'Item' => h,
|
137
|
+
},
|
138
|
+
}
|
139
|
+
|
140
|
+
item.each do |name, val|
|
141
|
+
h[name] = convert_to_attribute_value(val)
|
142
|
+
end
|
143
|
+
end
|
144
|
+
|
145
|
+
batch_write_item(req_hash)
|
146
|
+
n += chunk.length
|
147
|
+
end
|
148
|
+
|
149
|
+
return n
|
150
|
+
end
|
116
151
|
|
117
152
|
private
|
118
153
|
|
@@ -303,6 +338,42 @@ module DynamoDB
|
|
303
338
|
nil
|
304
339
|
end
|
305
340
|
|
341
|
+
def do_create_like(parsed)
|
342
|
+
table_info = @client.query('DescribeTable', 'TableName' => parsed.like)['Table']
|
343
|
+
|
344
|
+
req_hash = {
|
345
|
+
'TableName' => parsed.table,
|
346
|
+
'AttributeDefinitions' => table_info['AttributeDefinitions'],
|
347
|
+
'KeySchema' => table_info['KeySchema'],
|
348
|
+
}
|
349
|
+
|
350
|
+
local_secondary_indexes = (table_info['LocalSecondaryIndexes'] || [])
|
351
|
+
|
352
|
+
unless local_secondary_indexes.empty?
|
353
|
+
req_hash['LocalSecondaryIndexes'] = local_secondary_indexes.map do |lsi|
|
354
|
+
h = {}
|
355
|
+
|
356
|
+
%w(IndexName KeySchema Projection).each do |i|
|
357
|
+
h[i] = lsi[i]
|
358
|
+
end
|
359
|
+
|
360
|
+
h
|
361
|
+
end
|
362
|
+
end
|
363
|
+
|
364
|
+
if parsed.capacity
|
365
|
+
req_hash['ProvisionedThroughput'] = {
|
366
|
+
'ReadCapacityUnits' => parsed.capacity[:read],
|
367
|
+
'WriteCapacityUnits' => parsed.capacity[:write],
|
368
|
+
}
|
369
|
+
else
|
370
|
+
req_hash['ProvisionedThroughput'] = table_info['ProvisionedThroughput']
|
371
|
+
end
|
372
|
+
|
373
|
+
@client.query('CreateTable', req_hash)
|
374
|
+
nil
|
375
|
+
end
|
376
|
+
|
306
377
|
def do_drop(parsed)
|
307
378
|
@client.query('DeleteTable', 'TableName' => parsed.table)
|
308
379
|
nil
|