sdbcli 1.1.4 → 1.2.0
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.
- data/README +24 -1
- data/bin/sdbcli +9 -6
- data/lib/sdbcli/sdb-parser.tab.rb +34 -13
- data/lib/sdbcli/sdb-parser.y +22 -1
- data/lib/sdbcli/sdb-runner.rb +68 -9
- metadata +1 -1
data/README
CHANGED
@@ -70,7 +70,7 @@ https://bitbucket.org/winebarrel/sdbcli
|
|
70
70
|
DELETE [attr1, ...] FROM domain_name WHERE [WHERE expression] [sort_instructions] [LIMIT limit]
|
71
71
|
deletes the attribute of an item or an item
|
72
72
|
|
73
|
-
SELECT output_list FROM domain_name [WHERE expression] [sort_instructions] [LIMIT limit]
|
73
|
+
SELECT output_list FROM domain_name [WHERE expression] [sort_instructions] [LIMIT limit] [ | ruby script ]
|
74
74
|
queries using the SELECT statement
|
75
75
|
see http://docs.aws.amazon.com/AmazonSimpleDB/latest/DeveloperGuide/UsingSelect.html
|
76
76
|
|
@@ -134,3 +134,26 @@ see http://docs.amazonwebservices.com/AmazonSimpleDB/latest/DeveloperGuide/Quoti
|
|
134
134
|
// 7500 rows was inputted...
|
135
135
|
|
136
136
|
If '-' is specified as a file name, the input/output of data will become a standard input/output.
|
137
|
+
|
138
|
+
== Pipe to ruby
|
139
|
+
|
140
|
+
ap-northeast-1> select * from employees limit 3;
|
141
|
+
---
|
142
|
+
- ["100000", {first_name: Hiroyasu, hire_date: "1991-07-02", birth_date: "1956-01-11", last_name: Emden}]
|
143
|
+
- ["100001", {first_name: Jasminko, hire_date: "1994-12-25", birth_date: "1953-02-07", last_name: Antonakopoulos}]
|
144
|
+
- ["100002", {first_name: Claudi, hire_date: "1988-02-20", birth_date: "1957-03-04", last_name: Kolinko}]
|
145
|
+
# 3 rows in set
|
146
|
+
|
147
|
+
ap-northeast-1> select * from employees limit 3 | hire_date.max;
|
148
|
+
--- "1994-12-25"
|
149
|
+
|
150
|
+
ap-northeast-1> select * from employees limit 3 | hire_date.to_i;
|
151
|
+
---
|
152
|
+
- 1991
|
153
|
+
- 1994
|
154
|
+
- 1988
|
155
|
+
# 3 rows in set
|
156
|
+
ap-northeast-1> select * from employees limit 3 | hire_date.to_f.avg;
|
157
|
+
--- 1991.0
|
158
|
+
|
159
|
+
'sum' method and 'avg' method are added to the Array class.
|
data/bin/sdbcli
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 = '1.
|
4
|
+
Version = '1.2.0'
|
5
5
|
HISTORY_FILE = File.join((ENV['HOME'] || ENV['USERPROFILE'] || '.'), '.sdbcli_history')
|
6
6
|
HISTSIZE = 500
|
7
7
|
SELECT_LIMIT = 2500
|
@@ -16,6 +16,7 @@ require 'strscan'
|
|
16
16
|
require 'syck' if /\A1\.9/ =~ RUBY_VERSION
|
17
17
|
require 'yaml'
|
18
18
|
require 'json'
|
19
|
+
require 'time'
|
19
20
|
|
20
21
|
access_key_id = ENV['AWS_ACCESS_KEY_ID']
|
21
22
|
secret_access_key = ENV['AWS_SECRET_ACCESS_KEY']
|
@@ -72,7 +73,7 @@ def execute(src, show_rows = false)
|
|
72
73
|
buf = ''
|
73
74
|
|
74
75
|
until ss.eos?
|
75
|
-
if (tok = ss.scan %r{[^-`'";\\/#]+})
|
76
|
+
if (tok = ss.scan %r{[^-`'";\\/#]+}) #'
|
76
77
|
buf << tok
|
77
78
|
elsif (tok = ss.scan /`(?:[^`]|``)*`/)
|
78
79
|
buf << tok
|
@@ -108,14 +109,15 @@ def execute(src, show_rows = false)
|
|
108
109
|
out = $runner.execute(query, inline, $consistent)
|
109
110
|
end
|
110
111
|
|
111
|
-
if out.kind_of?(
|
112
|
+
if out.kind_of?(SimpleDB::Runner::Rownum)
|
113
|
+
rownum = out.to_i
|
112
114
|
puts case $format
|
113
115
|
when :yaml
|
114
|
-
"# #{
|
116
|
+
"# #{rownum} #{rownum > 1 ? 'rows' : 'row'} changed"
|
115
117
|
when :json
|
116
|
-
"// #{
|
118
|
+
"// #{rownum} #{rownum > 1 ? 'rows' : 'row'} changed"
|
117
119
|
else
|
118
|
-
"# #{
|
120
|
+
"# #{rownum} #{rownum > 1 ? 'rows' : 'row'} changed"
|
119
121
|
end
|
120
122
|
elsif out
|
121
123
|
str = nil
|
@@ -374,6 +376,7 @@ DELETE [attr1, ...] FROM domain_name WHERE [WHERE expression] [sort_instructions
|
|
374
376
|
deletes the attribute of an item or an item
|
375
377
|
|
376
378
|
SELECT output_list FROM domain_name [WHERE expression] [sort_instructions] [LIMIT limit]
|
379
|
+
SELECT output_list FROM domain_name [WHERE expression] [sort_instructions] [LIMIT limit] [ | ruby script ]
|
377
380
|
queries using the SELECT statement
|
378
381
|
see http://docs.aws.amazon.com/AmazonSimpleDB/latest/DeveloperGuide/UsingSelect.html
|
379
382
|
|
@@ -13,7 +13,7 @@ module SimpleDB
|
|
13
13
|
|
14
14
|
class Parser < Racc::Parser
|
15
15
|
|
16
|
-
module_eval(<<'...end sdb-parser.y/module_eval...', 'sdb-parser.y',
|
16
|
+
module_eval(<<'...end sdb-parser.y/module_eval...', 'sdb-parser.y', 249)
|
17
17
|
|
18
18
|
KEYWORDS = %w(
|
19
19
|
ADD
|
@@ -609,82 +609,103 @@ module_eval(<<'.,.,', 'sdb-parser.y', 162)
|
|
609
609
|
|
610
610
|
module_eval(<<'.,.,', 'sdb-parser.y', 168)
|
611
611
|
def _reduce_41(val, _values)
|
612
|
-
|
612
|
+
query = ''
|
613
|
+
ruby = nil
|
614
|
+
|
615
|
+
ss = StringScanner.new(val[0])
|
616
|
+
|
617
|
+
until ss.eos?
|
618
|
+
if (tok = ss.scan %r{[^-`'";\\/#|]+}) #'
|
619
|
+
query << tok
|
620
|
+
elsif (tok = ss.scan /`(?:[^`]|``)*`/)
|
621
|
+
query << tok
|
622
|
+
elsif (tok = ss.scan /'(?:[^']|'')*'/) #'
|
623
|
+
query << tok
|
624
|
+
elsif (tok = ss.scan /"(?:[^"]|"")*"/) #"
|
625
|
+
query << tok
|
626
|
+
elsif (tok = ss.scan /\|/)
|
627
|
+
ruby = ss.scan_until(/\Z/)
|
628
|
+
elsif (tok = ss.scan /./)
|
629
|
+
query << tok
|
630
|
+
end
|
631
|
+
end
|
632
|
+
|
633
|
+
struct(:SELECT, :query => query, :ruby => ruby)
|
613
634
|
|
614
635
|
end
|
615
636
|
.,.,
|
616
637
|
|
617
|
-
module_eval(<<'.,.,', 'sdb-parser.y',
|
638
|
+
module_eval(<<'.,.,', 'sdb-parser.y', 194)
|
618
639
|
def _reduce_42(val, _values)
|
619
640
|
struct(:CREATE, :domain => val[2])
|
620
641
|
|
621
642
|
end
|
622
643
|
.,.,
|
623
644
|
|
624
|
-
module_eval(<<'.,.,', 'sdb-parser.y',
|
645
|
+
module_eval(<<'.,.,', 'sdb-parser.y', 199)
|
625
646
|
def _reduce_43(val, _values)
|
626
647
|
struct(:DROP, :domain => val[2])
|
627
648
|
|
628
649
|
end
|
629
650
|
.,.,
|
630
651
|
|
631
|
-
module_eval(<<'.,.,', 'sdb-parser.y',
|
652
|
+
module_eval(<<'.,.,', 'sdb-parser.y', 204)
|
632
653
|
def _reduce_44(val, _values)
|
633
654
|
struct(:SHOW, :operand => :domains)
|
634
655
|
|
635
656
|
end
|
636
657
|
.,.,
|
637
658
|
|
638
|
-
module_eval(<<'.,.,', 'sdb-parser.y',
|
659
|
+
module_eval(<<'.,.,', 'sdb-parser.y', 208)
|
639
660
|
def _reduce_45(val, _values)
|
640
661
|
struct(:SHOW, :operand => :regions)
|
641
662
|
|
642
663
|
end
|
643
664
|
.,.,
|
644
665
|
|
645
|
-
module_eval(<<'.,.,', 'sdb-parser.y',
|
666
|
+
module_eval(<<'.,.,', 'sdb-parser.y', 212)
|
646
667
|
def _reduce_46(val, _values)
|
647
668
|
struct(:USE, :endpoint => val[1])
|
648
669
|
|
649
670
|
end
|
650
671
|
.,.,
|
651
672
|
|
652
|
-
module_eval(<<'.,.,', 'sdb-parser.y',
|
673
|
+
module_eval(<<'.,.,', 'sdb-parser.y', 216)
|
653
674
|
def _reduce_47(val, _values)
|
654
675
|
struct(:DESCRIBE, :domain => val[1])
|
655
676
|
|
656
677
|
end
|
657
678
|
.,.,
|
658
679
|
|
659
|
-
module_eval(<<'.,.,', 'sdb-parser.y',
|
680
|
+
module_eval(<<'.,.,', 'sdb-parser.y', 220)
|
660
681
|
def _reduce_48(val, _values)
|
661
682
|
struct(:DESCRIBE, :domain => val[1])
|
662
683
|
|
663
684
|
end
|
664
685
|
.,.,
|
665
686
|
|
666
|
-
module_eval(<<'.,.,', 'sdb-parser.y',
|
687
|
+
module_eval(<<'.,.,', 'sdb-parser.y', 225)
|
667
688
|
def _reduce_49(val, _values)
|
668
689
|
[val[0]]
|
669
690
|
|
670
691
|
end
|
671
692
|
.,.,
|
672
693
|
|
673
|
-
module_eval(<<'.,.,', 'sdb-parser.y',
|
694
|
+
module_eval(<<'.,.,', 'sdb-parser.y', 229)
|
674
695
|
def _reduce_50(val, _values)
|
675
696
|
val[0] + [val[2]]
|
676
697
|
|
677
698
|
end
|
678
699
|
.,.,
|
679
700
|
|
680
|
-
module_eval(<<'.,.,', 'sdb-parser.y',
|
701
|
+
module_eval(<<'.,.,', 'sdb-parser.y', 234)
|
681
702
|
def _reduce_51(val, _values)
|
682
703
|
[val[0]]
|
683
704
|
|
684
705
|
end
|
685
706
|
.,.,
|
686
707
|
|
687
|
-
module_eval(<<'.,.,', 'sdb-parser.y',
|
708
|
+
module_eval(<<'.,.,', 'sdb-parser.y', 238)
|
688
709
|
def _reduce_52(val, _values)
|
689
710
|
[val[0], val[2]].flatten
|
690
711
|
|
data/lib/sdbcli/sdb-parser.y
CHANGED
@@ -166,7 +166,28 @@ rule
|
|
166
166
|
|
167
167
|
select_stmt : SELECT
|
168
168
|
{
|
169
|
-
|
169
|
+
query = ''
|
170
|
+
ruby = nil
|
171
|
+
|
172
|
+
ss = StringScanner.new(val[0])
|
173
|
+
|
174
|
+
until ss.eos?
|
175
|
+
if (tok = ss.scan %r{[^-`'";\\/#|]+}) #'
|
176
|
+
query << tok
|
177
|
+
elsif (tok = ss.scan /`(?:[^`]|``)*`/)
|
178
|
+
query << tok
|
179
|
+
elsif (tok = ss.scan /'(?:[^']|'')*'/) #'
|
180
|
+
query << tok
|
181
|
+
elsif (tok = ss.scan /"(?:[^"]|"")*"/) #"
|
182
|
+
query << tok
|
183
|
+
elsif (tok = ss.scan /\|/)
|
184
|
+
ruby = ss.scan_until(/\Z/)
|
185
|
+
elsif (tok = ss.scan /./)
|
186
|
+
query << tok
|
187
|
+
end
|
188
|
+
end
|
189
|
+
|
190
|
+
struct(:SELECT, :query => query, :ruby => ruby)
|
170
191
|
}
|
171
192
|
|
172
193
|
create_stmt : CREATE DOMAIN IDENTIFIER
|
data/lib/sdbcli/sdb-runner.rb
CHANGED
@@ -1,6 +1,29 @@
|
|
1
1
|
require 'sdbcli/sdb-driver'
|
2
2
|
require 'sdbcli/sdb-parser.tab'
|
3
3
|
|
4
|
+
# XXX:
|
5
|
+
class Array
|
6
|
+
def to_s
|
7
|
+
self.map {|i| i.to_s }
|
8
|
+
end
|
9
|
+
|
10
|
+
def to_i
|
11
|
+
self.map {|i| i.to_i }
|
12
|
+
end
|
13
|
+
|
14
|
+
def to_f
|
15
|
+
self.map {|i| i.to_f }
|
16
|
+
end
|
17
|
+
|
18
|
+
def sum
|
19
|
+
self.inject {|r, i| r + i }
|
20
|
+
end
|
21
|
+
|
22
|
+
def avg
|
23
|
+
self.sum / self.length
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
4
27
|
module SimpleDB
|
5
28
|
class Error < StandardError; end
|
6
29
|
|
@@ -16,6 +39,16 @@ module SimpleDB
|
|
16
39
|
}
|
17
40
|
|
18
41
|
class Runner
|
42
|
+
class Rownum
|
43
|
+
def initialize(rownum)
|
44
|
+
@rownum = rownum
|
45
|
+
end
|
46
|
+
|
47
|
+
def to_i
|
48
|
+
@rownum
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
19
52
|
attr_reader :driver
|
20
53
|
|
21
54
|
def initialize(accessKeyId, secretAccessKey, endpoint = 'sdb.amazonaws.com')
|
@@ -60,43 +93,69 @@ module SimpleDB
|
|
60
93
|
when :INSERT
|
61
94
|
rownum = parsed.items.length
|
62
95
|
@driver.insert(parsed.domain, parsed.items)
|
63
|
-
rownum
|
96
|
+
Rownum.new(rownum)
|
64
97
|
when :UPDATE
|
65
98
|
rownum = parsed.items.length
|
66
99
|
@driver.update(parsed.domain, parsed.items)
|
67
|
-
rownum
|
100
|
+
Rownum.new(rownum)
|
68
101
|
when :UPDATE_WITH_EXPR
|
69
102
|
query = "SELECT itemName FROM #{parsed.domain} #{parsed.expr}"
|
70
103
|
items = @driver.select(query, consistent).map {|i| [i[0], parsed.attrs] }
|
71
104
|
rownum = items.length
|
72
105
|
@driver.update(parsed.domain, items)
|
73
|
-
rownum
|
106
|
+
Rownum.new(rownum)
|
74
107
|
when :MERGE
|
75
108
|
rownum = parsed.items.length
|
76
109
|
@driver.insert(parsed.domain, parsed.items)
|
77
|
-
rownum
|
110
|
+
Rownum.new(rownum)
|
78
111
|
when :MERGE_WITH_EXPR
|
79
112
|
query = "SELECT itemName FROM #{parsed.domain} #{parsed.expr}"
|
80
113
|
items = @driver.select(query, consistent).map {|i| [i[0], parsed.attrs] }
|
81
114
|
rownum = items.length
|
82
115
|
@driver.insert(parsed.domain, items)
|
83
|
-
rownum
|
116
|
+
Rownum.new(rownum)
|
84
117
|
when :DELETE
|
85
118
|
rownum = parsed.items.length
|
86
119
|
@driver.delete(parsed.domain, parsed.items)
|
87
|
-
rownum
|
120
|
+
Rownum.new(rownum)
|
88
121
|
when :DELETE_WITH_EXPR
|
89
122
|
query = "SELECT itemName FROM #{parsed.domain} #{parsed.expr}"
|
90
123
|
items = @driver.select(query, consistent).map {|i| [i[0], parsed.attrs] }
|
91
124
|
rownum = items.length
|
92
125
|
@driver.delete(parsed.domain, items)
|
93
|
-
rownum
|
126
|
+
Rownum.new(rownum)
|
94
127
|
when :SELECT
|
95
128
|
items = @driver.select(parsed.query, consistent)
|
96
129
|
|
97
|
-
|
130
|
+
def items.method_missing(method_name)
|
131
|
+
case method_name.to_s
|
132
|
+
when /itemName/i
|
133
|
+
self.map {|i| i[0] }
|
134
|
+
else
|
135
|
+
self.map {|i| i[1][method_name.to_s] }
|
136
|
+
end
|
137
|
+
end
|
138
|
+
|
139
|
+
items.each do |item|
|
140
|
+
def item.method_missing(method_name)
|
141
|
+
case method_name.to_s
|
142
|
+
when /itemName/i
|
143
|
+
self[0]
|
144
|
+
else
|
145
|
+
self[1][method_name.to_s]
|
146
|
+
end
|
147
|
+
end
|
148
|
+
end
|
149
|
+
|
150
|
+
if parsed.ruby
|
151
|
+
items = items.instance_eval(parsed.ruby.strip)
|
152
|
+
end
|
153
|
+
|
154
|
+
if inline and items.kind_of?(Array)
|
98
155
|
items.each do |item|
|
99
|
-
|
156
|
+
if item.kind_of?(Array)
|
157
|
+
def item.to_yaml_style; :inline; end
|
158
|
+
end
|
100
159
|
end
|
101
160
|
end
|
102
161
|
|