ddbcli 0.3.0 → 0.3.1

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,15 +1,7 @@
1
1
  ---
2
- !binary "U0hBMQ==":
3
- metadata.gz: !binary |-
4
- MzMzZGJiNzFlZDY4ZGUwM2VkOTA3MzA4NjgxMzUzZjgxMjAyNmE0MQ==
5
- data.tar.gz: !binary |-
6
- OGE3NGE3ZTVmMzhiMGRiNTllMWU3MGVmMjJkODczZTA1YmUzNDI2Ng==
2
+ SHA1:
3
+ metadata.gz: 920be6266d63a91338388bb5c64ee492192bf4ea
4
+ data.tar.gz: 294e678d52312af238381e8166e4fbe5dbdea1a3
7
5
  SHA512:
8
- metadata.gz: !binary |-
9
- NmU1Nzc3MzM3ZjJhNWRhYjNjYWZlYmE0MTA1OTMxYjkwMTAxZDU3NzFhZjQz
10
- ZjIzZDhmNmRmYjkyNzEwZDllNGVhZGY3Zjk0ZTZkNTE0OGJhZTMxZGViZmJi
11
- ZjczYWI3MjQxMWZiY2FiNThiZDA4ZWRhN2E1ZGI3MWRlYjBkMTk=
12
- data.tar.gz: !binary |-
13
- ZDk5ODQ1NjBkMTIxNmZmM2E2ZTA4MjBiOGQ4Njc2ZDBjYmFmYWY3YjA4Zjgz
14
- YmU1MTYyMDhiNWM2N2VhOTcwYWE1NTEwZmZkNmQzMDcxMDk0OTZlN2JhODdh
15
- NDk0N2JlY2Y1MjRmY2MwYmQ5ZjUxMTk2MTlkYmY2MTMxY2E4ODI=
6
+ metadata.gz: 6a5a3d587336ca8ade3dd5dd41b5edd103bbb3d04784b113f003ef2a4fcf244fcbed1e3c29893cb6975fd42a697a70895ef88617394d4fd42829f1bbdfbd7ab0
7
+ data.tar.gz: 9eb0c49ec7d16c1f7ed09564dae0b229cffad4984d0f2bee0575595b52d438967fe7a4b6d1ad309fcbe8d40510b7d3f6d202e196e332af441eae2e7d3f24b5b3
data/.gitignore ADDED
@@ -0,0 +1,17 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --require spec_helper
2
+ --colour
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in ddbcli.gemspec
4
+ gemspec
data/LICENSE.txt ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2013 Genki Sugawara
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,197 @@
1
+ # ddbcli
2
+
3
+ ddbcli is an interactive command-line client of Amazon DynamoDB.
4
+
5
+ [![Build Status](https://drone.io/bitbucket.org/winebarrel/ddbcli/status.png)](https://drone.io/bitbucket.org/winebarrel/ddbcli/latest)
6
+
7
+ ## Installation
8
+
9
+ Add this line to your application's Gemfile:
10
+
11
+ gem 'ddbcli'
12
+
13
+ And then execute:
14
+
15
+ $ bundle
16
+
17
+ Or install it yourself as:
18
+
19
+ $ gem install ddbcli
20
+
21
+ ## Usage
22
+
23
+ ```sh
24
+ export AWS_ACCESS_KEY_ID='...'
25
+ export AWS_SECRET_ACCESS_KEY='...'
26
+ export AWS_REGION=ap-northeast-1
27
+
28
+ ddbcli -e 'show tables'
29
+ # [
30
+ # "employees"
31
+ # ]
32
+
33
+ ddbcli # show prompt
34
+ ```
35
+
36
+ ### Use DynamoDB Local
37
+
38
+ $ ddbcli --url localhost:8000
39
+
40
+ ## Demo
41
+
42
+ ![ddbcli demo](https://bitbucket.org/winebarrel/ddbcli/downloads/ddbcli-demo.gif)
43
+
44
+ ## Use GSI
45
+
46
+ * [https://gist.github.com/winebarrel/7938971](https://gist.github.com/winebarrel/7938971)
47
+
48
+ ## Help
49
+
50
+ ```
51
+ ##### Query #####
52
+
53
+ SHOW TABLES [LIMIT num] [LIKE '...']
54
+ displays a table list
55
+
56
+ SHOW TABLE STATUS [LIKE '...']
57
+ displays table statues
58
+
59
+ SHOW REGIONS
60
+ displays a region list
61
+
62
+ SHOW CREATE TABLE table_name
63
+ displays a CREATE TABLE statement
64
+
65
+ CREATE TABLES table_name (
66
+ key_name {STRING|NUMBER|BINARY} HASH
67
+ [, key_name {STRING|NUMBER|BINARY} RANGE]
68
+ [, INDEX index1_name (attr1 {STRING|NUMBER|BINARY}) {ALL|KEYS_ONLY|INCLUDE (attr, ...)}
69
+ , INDEX index2_name (attr2 {STRING|NUMBER|BINARY}) {ALL|KEYS_ONLY|INCLUDE (attr, ...)}
70
+ , ...]
71
+ [, GLOBAL INDEX index1_name (hash_attr1 {STRING|NUMBER|BINARY} [, range_attr1 {STRING|NUMBER|BINARY}]) {ALL|KEYS_ONLY|INCLUDE (attr, ...)} [READ = num WRITE = num]
72
+ , GLOBAL INDEX index2_name (hash_attr2 {STRING|NUMBER|BINARY} [, range_attr2 {STRING|NUMBER|BINARY}]) {ALL|KEYS_ONLY|INCLUDE (attr, ...)} [READ = num WRITE = num]
73
+ , ...]
74
+ ) READ = num WRITE = num
75
+ creates a table
76
+
77
+ CREATE TABLES table_name LIKE another_table_name [READ = num, WRITE = num]
78
+ creates a table like another table
79
+
80
+ DROP TABLE table_name
81
+ deletes a table
82
+
83
+ ALTER TABLE table_name READ = num WRITE = num
84
+ updates the provisioned throughput
85
+
86
+ GET {*|attr1,attr2,...} FROM table_name WHERE key1 = '...' AND ...
87
+ gets items
88
+
89
+ INSERT INTO table_name (attr1, attr2, ...) VALUES ('val1', 'val2', ...), ('val3', 'val4', ...), ...
90
+ INSERT INTO table_name SELECT ...
91
+ INSERT INTO table_name SELECT ALL ...
92
+ creates items
93
+
94
+ UPDATE table_name {SET|ADD} attr1 = 'val1', ... WHERE key1 = '...' AND ...
95
+ UPDATE ALL table_name {SET|ADD} attr1 = 'val1', ... [WHERE attr1 = '...' AND ...] [LIMIT limit]
96
+ updates items
97
+ ("UPDATE" can update only one record. Please use "UPDATE ALL", when you update more than one.)
98
+
99
+ DELETE FROM table_name WHERE key1 = '...' AND ..
100
+ DELETE ALL FROM table_name WHERE [WHERE attr1 = '...' AND ...] [ORDER {ASC|DESC}] [LIMIT limit]
101
+ deletes items
102
+ ("DELETE" can delete only one record. Please use "DELETE ALL", when you update more than one.)
103
+
104
+ SELECT {*|attr1,attr2,...|COUNT(*)} FROM table_name [USE INDEX (index_name)] [WHERE key1 = '...' AND ...] [ORDER {ASC|DESC}] [LIMIT limit]
105
+ SELECT ALL {*|attr1,attr2,...|COUNT(*)} FROM table_name [WHERE attr1 = '...' AND ...] [LIMIT limit]
106
+ SELECT segment/total_segments {*|attr1,attr2,...|COUNT(*)} FROM table_name [WHERE attr1 = '...' AND ...] [LIMIT limit]
107
+ queries using the Query/Scan action
108
+ see http://docs.aws.amazon.com/amazondynamodb/latest/developerguide/QueryAndScan.html
109
+
110
+ DESC[RIBE] table_name
111
+ displays information about the table
112
+
113
+ USE region_or_endpoint
114
+ changes an endpoint
115
+
116
+ NEXT
117
+ displays a continuation of a result
118
+ (NEXT statement is published after SELECT statement)
119
+
120
+
121
+ ##### Type #####
122
+
123
+ String
124
+ 'London Bridge is...', "is broken down..." ...
125
+
126
+ Number
127
+ 10, 100, 0.3 ...
128
+
129
+ Binary
130
+ x'123456789abcd...', x"123456789abcd..." ...
131
+
132
+ Identifier
133
+ `ABCD...` or Non-keywords
134
+
135
+ Array
136
+ ('String', 'String', ...), (1, 2, 3, ...)
137
+
138
+
139
+ ##### Operator #####
140
+
141
+ Query (SELECT)
142
+ = | <= | < | >= | > | BEGINS_WITH | BETWEEN
143
+ see http://docs.aws.amazon.com/amazondynamodb/latest/APIReference/API_Query.html#DDB-Query-request-KeyConditions
144
+
145
+ Scan (SELECT ALL)
146
+ = | <> | != | <= | < | >= | > | IS NOT NULL | IS NULL | CONTAINS | NOT CONTAINS | BEGINS_WITH | IN | BETWEEN
147
+ see http://docs.aws.amazon.com/amazondynamodb/latest/APIReference/API_Scan.html#DDB-Scan-request-ScanFilter
148
+
149
+
150
+ ##### Pass to Ruby/Shell #####
151
+
152
+ Ryby
153
+ query | ruby_script
154
+
155
+ ex) SELECT ALL * FROM employees WHERE gender = 'M' | birth_date.map {|i| Time.parse(i) };
156
+ [
157
+ "1957-09-16 00:00:00 +0900",
158
+ "1954-12-16 00:00:00 +0900",
159
+ "1964-05-23 00:00:00 +0900",
160
+ ...
161
+
162
+ Shell
163
+ query ! shell_command
164
+
165
+ ex) SELECT ALL * FROM employees LIMIT 10 ! sort;
166
+ {"birth_date"=>"1957-09-16", "emp_no"=>452020,...
167
+ {"birth_date"=>"1963-07-14", "emp_no"=>16998, ...
168
+ {"birth_date"=>"1964-04-30", "emp_no"=>225407,...
169
+ ...
170
+
171
+
172
+ ##### Output to a file #####
173
+
174
+ Overwrite
175
+ SELECT ALL * FROM employees > 'foo.json';
176
+
177
+ Append
178
+ SELECT ALL * FROM employees >> 'foo.json';
179
+
180
+
181
+ ##### Command #####
182
+
183
+ .help displays this message
184
+ .quit | .exit exits ddbcli
185
+ .consistent (true|false)? displays ConsistentRead parameter or changes it
186
+ .iteratable (true|false)? displays iteratable option or changes it
187
+ all results are displayed if true
188
+ .debug (true|false)? displays a debug status or changes it
189
+ .retry NUM? displays number of times of a retry or changes it
190
+ .retry_interval SECOND? displays a retry interval second or changes it
191
+ .timeout SECOND? displays a timeout second or changes it
192
+ .version displays a version
193
+ ```
194
+
195
+ ## Link
196
+
197
+ * [RubyGems.org site](http://rubygems.org/gems/ddbcli)
data/Rakefile ADDED
@@ -0,0 +1,5 @@
1
+ require 'bundler/gem_tasks'
2
+ require 'rspec/core/rake_task'
3
+
4
+ RSpec::Core::RakeTask.new('spec')
5
+ task :default => :spec
data/bin/ddbcli CHANGED
@@ -1,8 +1,6 @@
1
1
  #!/usr/bin/env ruby
2
2
  $LOAD_PATH << File.join(File.dirname(__FILE__), '..', 'lib')
3
3
 
4
- Version = '0.3.0'
5
-
6
4
  HISTORY_FILE = File.join((ENV['HOME'] || ENV['USERPROFILE'] || '.'), '.ddbcli_history')
7
5
  HISTSIZE = 500
8
6
 
data/ddbcli.gemspec ADDED
@@ -0,0 +1,25 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'ddbcli/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = 'ddbcli'
8
+ spec.version = DynamoDB::VERSION
9
+ spec.authors = 'Genki Sugawara'
10
+ spec.email = 'sgwr_dts@yahoo.co.jp'
11
+ spec.description = 'ddbcli is an interactive command-line client of Amazon DynamoDB.'
12
+ spec.summary = spec.description
13
+ spec.homepage = 'https://bitbucket.org/winebarrel/ddbcli'
14
+ spec.license = 'MIT'
15
+
16
+ spec.files = `git ls-files`.split($/)
17
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
18
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
+ spec.require_paths = ['lib']
20
+
21
+ spec.add_dependency 'json'
22
+ spec.add_development_dependency 'bundler', '~> 1.3'
23
+ spec.add_development_dependency 'rake'
24
+ spec.add_development_dependency 'rspec', '>= 2.14.1'
25
+ end
@@ -34,7 +34,7 @@ CREATE TABLES table_name LIKE another_table_name [READ = num, WRITE = num]
34
34
  DROP TABLE table_name
35
35
  deletes a table
36
36
 
37
- ALTER TABLE table_name READ = num, WRITE = num
37
+ ALTER TABLE table_name READ = num WRITE = num
38
38
  updates the provisioned throughput
39
39
 
40
40
  GET {*|attr1,attr2,...} FROM table_name WHERE key1 = '...' AND ...
@@ -48,10 +48,12 @@ INSERT INTO table_name SELECT ALL ...
48
48
  UPDATE table_name {SET|ADD} attr1 = 'val1', ... WHERE key1 = '...' AND ...
49
49
  UPDATE ALL table_name {SET|ADD} attr1 = 'val1', ... [WHERE attr1 = '...' AND ...] [LIMIT limit]
50
50
  updates items
51
+ ("UPDATE" can update only one record. Please use "UPDATE ALL", when you update more than one.)
51
52
 
52
53
  DELETE FROM table_name WHERE key1 = '...' AND ..
53
54
  DELETE ALL FROM table_name WHERE [WHERE attr1 = '...' AND ...] [ORDER {ASC|DESC}] [LIMIT limit]
54
55
  deletes items
56
+ ("DELETE" can delete only one record. Please use "DELETE ALL", when you update more than one.)
55
57
 
56
58
  SELECT {*|attr1,attr2,...|COUNT(*)} FROM table_name [USE INDEX (index_name)] [WHERE key1 = '...' AND ...] [ORDER {ASC|DESC}] [LIMIT limit]
57
59
  SELECT ALL {*|attr1,attr2,...|COUNT(*)} FROM table_name [WHERE attr1 = '...' AND ...] [LIMIT limit]
@@ -7,7 +7,7 @@ def parse_options
7
7
  options.access_key_id = ENV['AWS_ACCESS_KEY_ID']
8
8
  options.secret_access_key = ENV['AWS_SECRET_ACCESS_KEY']
9
9
  options.ddb_endpoint_or_region =
10
- ENV['DDB_ENDPOINT'] || ENV['DDB_REGION'] || 'dynamodb.us-east-1.amazonaws.com'
10
+ ENV['AWS_REGION'] || ENV['DDB_ENDPOINT'] || ENV['DDB_REGION'] || 'dynamodb.us-east-1.amazonaws.com'
11
11
 
12
12
  # default value
13
13
  options.timeout = 60
@@ -22,13 +22,16 @@ def parse_options
22
22
  opt.on('-s', '--secret-key=SECRET_KEY') {|v| options.secret_access_key = v }
23
23
  opt.on('-r', '--region=REGION_OR_ENDPOINT') {|v| options.ddb_endpoint_or_region = v }
24
24
 
25
- opt.on('', '--uri=URI') {|v|
25
+ url_opt = proc do |v|
26
26
  uri = v
27
27
  uri = "http://#{uri}" unless uri =~ %r|\A\w+://|
28
28
  uri = URI.parse(uri)
29
29
  raise URI::InvalidURIError, "invalid shceme: #{v}" unless /\Ahttps?\Z/ =~ uri.scheme
30
30
  options.ddb_endpoint_or_region = uri
31
- }
31
+ end
32
+
33
+ opt.on('', '--url=URL', &url_opt)
34
+ opt.on('', '--uri=URL (DEPRECATION)', &url_opt)
32
35
 
33
36
  opt.on('-e', '--eval=COMMAND') {|v| options.command = v }
34
37
  opt.on('-t', '--timeout=SECOND', Integer) {|v| options.timeout = v.to_i }
@@ -388,21 +388,32 @@ module DynamoDB
388
388
  local_indices = (parsed.indices || []).select {|i| not i[:global] }
389
389
  global_indices = (parsed.indices || []).select {|i| i[:global] }
390
390
 
391
+ define_attribute = lambda do |attr_name, attr_type|
392
+ attr_defs = req_hash['AttributeDefinitions']
393
+ same_attr = attr_defs.find {|i| i['AttributeName'] == attr_name }
394
+
395
+ if same_attr
396
+ if same_attr['AttributeType'] != attr_type
397
+ raise DynamoDB::Error, "different types have been defined: #{attr_name}"
398
+ end
399
+ else
400
+ attr_defs << {
401
+ 'AttributeName' => attr_name,
402
+ 'AttributeType' => attr_type,
403
+ }
404
+ end
405
+ end
406
+
391
407
  define_index = lambda do |idx_def, def_idx_opts|
392
408
  global_idx = def_idx_opts[:global]
393
409
 
410
+
394
411
  if global_idx
395
412
  idx_def[:keys].each do |key_type, name_type|
396
- req_hash['AttributeDefinitions'] << {
397
- 'AttributeName' => name_type[:key],
398
- 'AttributeType' => name_type[:type],
399
- }
413
+ define_attribute.call(name_type[:key], name_type[:type])
400
414
  end
401
415
  else
402
- req_hash['AttributeDefinitions'] << {
403
- 'AttributeName' => idx_def[:key],
404
- 'AttributeType' => idx_def[:type],
405
- }
416
+ define_attribute.call(idx_def[:key], idx_def[:type])
406
417
  end
407
418
 
408
419
  secondary_index = {
@@ -0,0 +1,5 @@
1
+ module DynamoDB
2
+ VERSION = "0.3.1"
3
+ end
4
+
5
+ Version = DynamoDB::VERSION
data/lib/ddbcli.rb CHANGED
@@ -1,3 +1,5 @@
1
+ require 'ddbcli/version'
2
+
1
3
  require 'ddbcli/ddb-binary'
2
4
  require 'ddbcli/ddb-client'
3
5
  require 'ddbcli/ddb-driver'
@@ -0,0 +1,196 @@
1
+ describe 'ddbcli' do
2
+ it 'version' do
3
+ out = ddbcli(nil, ['-v'])
4
+ expect(out).to match /ddbcli \d+\.\d+\.\d+/
5
+ end
6
+
7
+ it 'show tables' do
8
+ ddbcli(<<-'EOS')
9
+ CREATE TABLE `foo` (
10
+ `id` STRING HASH,
11
+ `val` STRING RANGE
12
+ ) read=2 write=2
13
+ EOS
14
+
15
+ out = ddbcli('show tables')
16
+ out = JSON.parse(out)
17
+ expect(out).to eq(['foo'])
18
+ end
19
+
20
+ it 'create table (hash only)' do
21
+ ddbcli(<<-'EOS')
22
+ CREATE TABLE `foo` (
23
+ `id` NUMBER HASH
24
+ ) read=2 write=2
25
+ EOS
26
+
27
+ out = ddbcli('desc foo')
28
+ out = JSON.parse(out)
29
+ out.delete('CreationDateTime')
30
+
31
+ expect(out).to eq(
32
+ {"AttributeDefinitions"=>[{"AttributeName"=>"id", "AttributeType"=>"N"}],
33
+ "TableName"=>"foo",
34
+ "KeySchema"=>[{"AttributeName"=>"id", "KeyType"=>"HASH"}],
35
+ "TableStatus"=>"ACTIVE",
36
+ "ProvisionedThroughput"=>
37
+ {"NumberOfDecreasesToday"=>0,
38
+ "ReadCapacityUnits"=>2,
39
+ "WriteCapacityUnits"=>2},
40
+ "TableSizeBytes"=>0,
41
+ "ItemCount"=>0}
42
+ )
43
+ end
44
+
45
+ it 'create table (hash and range)' do
46
+ ddbcli(<<-'EOS')
47
+ CREATE TABLE `foo` (
48
+ `id` NUMBER HASH,
49
+ `val` STRING RANGE
50
+ ) read=2 write=2
51
+ EOS
52
+
53
+ out = ddbcli('desc foo')
54
+ out = JSON.parse(out)
55
+ out.delete('CreationDateTime')
56
+
57
+ expect(out).to eq(
58
+ {"AttributeDefinitions"=>
59
+ [{"AttributeName"=>"id", "AttributeType"=>"N"},
60
+ {"AttributeName"=>"val", "AttributeType"=>"S"}],
61
+ "TableName"=>"foo",
62
+ "KeySchema"=>
63
+ [{"AttributeName"=>"id", "KeyType"=>"HASH"},
64
+ {"AttributeName"=>"val", "KeyType"=>"RANGE"}],
65
+ "TableStatus"=>"ACTIVE",
66
+ "ProvisionedThroughput"=>
67
+ {"NumberOfDecreasesToday"=>0,
68
+ "ReadCapacityUnits"=>2,
69
+ "WriteCapacityUnits"=>2},
70
+ "TableSizeBytes"=>0,
71
+ "ItemCount"=>0}
72
+ )
73
+ end
74
+
75
+ it 'create table with LSI' do
76
+ ddbcli(<<-'EOS')
77
+ CREATE TABLE `foo` (
78
+ `id` NUMBER HASH,
79
+ `val` STRING RANGE,
80
+ INDEX `idx_bar` (`val2` STRING) ALL
81
+ ) read=2 write=2
82
+ EOS
83
+
84
+ out = ddbcli('desc foo')
85
+ out = JSON.parse(out)
86
+ out.delete('CreationDateTime')
87
+
88
+ expect(out).to eq(
89
+ {"AttributeDefinitions"=>
90
+ [{"AttributeName"=>"id", "AttributeType"=>"N"},
91
+ {"AttributeName"=>"val", "AttributeType"=>"S"},
92
+ {"AttributeName"=>"val2", "AttributeType"=>"S"}],
93
+ "TableName"=>"foo",
94
+ "KeySchema"=>
95
+ [{"AttributeName"=>"id", "KeyType"=>"HASH"},
96
+ {"AttributeName"=>"val", "KeyType"=>"RANGE"}],
97
+ "TableStatus"=>"ACTIVE",
98
+ "ProvisionedThroughput"=>
99
+ {"NumberOfDecreasesToday"=>0,
100
+ "ReadCapacityUnits"=>2,
101
+ "WriteCapacityUnits"=>2},
102
+ "TableSizeBytes"=>0,
103
+ "ItemCount"=>0,
104
+ "LocalSecondaryIndexes"=>
105
+ [{"IndexName"=>"idx_bar",
106
+ "KeySchema"=>
107
+ [{"AttributeName"=>"id", "KeyType"=>"HASH"},
108
+ {"AttributeName"=>"val2", "KeyType"=>"RANGE"}],
109
+ "Projection"=>{"ProjectionType"=>"ALL"},
110
+ "IndexSizeBytes"=>0,
111
+ "ItemCount"=>0}]}
112
+ )
113
+ end
114
+
115
+ it 'create table with GSI' do
116
+ ddbcli(<<-'EOS')
117
+ CREATE TABLE `foo` (
118
+ `id` NUMBER HASH,
119
+ `val` STRING RANGE,
120
+ GLOBAL INDEX `idx_bar` (`val2` STRING) ALL read=1 write=1
121
+ ) read=2 write=2
122
+ EOS
123
+
124
+ out = ddbcli('desc foo')
125
+ out = JSON.parse(out)
126
+ out.delete('CreationDateTime')
127
+
128
+ expect(out).to eq(
129
+ {"AttributeDefinitions"=>
130
+ [{"AttributeName"=>"id", "AttributeType"=>"N"},
131
+ {"AttributeName"=>"val", "AttributeType"=>"S"},
132
+ {"AttributeName"=>"val2", "AttributeType"=>"S"}],
133
+ "TableName"=>"foo",
134
+ "KeySchema"=>
135
+ [{"AttributeName"=>"id", "KeyType"=>"HASH"},
136
+ {"AttributeName"=>"val", "KeyType"=>"RANGE"}],
137
+ "TableStatus"=>"ACTIVE",
138
+ "ProvisionedThroughput"=>
139
+ {"NumberOfDecreasesToday"=>0,
140
+ "ReadCapacityUnits"=>2,
141
+ "WriteCapacityUnits"=>2},
142
+ "TableSizeBytes"=>0,
143
+ "ItemCount"=>0,
144
+ "GlobalSecondaryIndexes"=>
145
+ [{"IndexName"=>"idx_bar",
146
+ "KeySchema"=>[{"AttributeName"=>"val2", "KeyType"=>"HASH"}],
147
+ "Projection"=>{"ProjectionType"=>"ALL"},
148
+ "IndexStatus"=>"ACTIVE",
149
+ "ProvisionedThroughput"=>{"ReadCapacityUnits"=>1, "WriteCapacityUnits"=>1},
150
+ "IndexSizeBytes"=>0,
151
+ "ItemCount"=>0}]}
152
+ )
153
+ end
154
+
155
+ it 'create table with GSI' do
156
+ ddbcli(<<-'EOS')
157
+ CREATE TABLE `foo` (
158
+ `id` NUMBER HASH,
159
+ `val` STRING RANGE,
160
+ GLOBAL INDEX `idx_bar` (`val2` STRING) ALL read=1 write=1
161
+ ) read=2 write=2
162
+ EOS
163
+
164
+ out = ddbcli('alter table foo read=4 write=4')
165
+
166
+ out = ddbcli('desc foo')
167
+ out = JSON.parse(out)
168
+ out.delete('CreationDateTime')
169
+
170
+ expect(out).to eq(
171
+ {"AttributeDefinitions"=>
172
+ [{"AttributeName"=>"id", "AttributeType"=>"N"},
173
+ {"AttributeName"=>"val", "AttributeType"=>"S"},
174
+ {"AttributeName"=>"val2", "AttributeType"=>"S"}],
175
+ "TableName"=>"foo",
176
+ "KeySchema"=>
177
+ [{"AttributeName"=>"id", "KeyType"=>"HASH"},
178
+ {"AttributeName"=>"val", "KeyType"=>"RANGE"}],
179
+ "TableStatus"=>"ACTIVE",
180
+ "ProvisionedThroughput"=>
181
+ {"NumberOfDecreasesToday"=>0,
182
+ "ReadCapacityUnits"=>4,
183
+ "WriteCapacityUnits"=>4},
184
+ "TableSizeBytes"=>0,
185
+ "ItemCount"=>0,
186
+ "GlobalSecondaryIndexes"=>
187
+ [{"IndexName"=>"idx_bar",
188
+ "KeySchema"=>[{"AttributeName"=>"val2", "KeyType"=>"HASH"}],
189
+ "Projection"=>{"ProjectionType"=>"ALL"},
190
+ "IndexStatus"=>"ACTIVE",
191
+ "ProvisionedThroughput"=>{"ReadCapacityUnits"=>1, "WriteCapacityUnits"=>1},
192
+ "IndexSizeBytes"=>0,
193
+ "ItemCount"=>0}]}
194
+ )
195
+ end
196
+ end