sdbcli 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/README +48 -0
- data/bin/sdbcli +72 -0
- data/lib/sdbcli/sdb-client.rb +128 -0
- data/lib/sdbcli/sdb-driver.rb +165 -0
- data/lib/sdbcli/sdb-parser.tab.rb +466 -0
- data/lib/sdbcli/sdb-parser.y +222 -0
- data/lib/sdbcli/sdb-runner.rb +51 -0
- data/lib/sdbcli.rb +3 -0
- metadata +85 -0
data/README
ADDED
@@ -0,0 +1,48 @@
|
|
1
|
+
= sdbcli
|
2
|
+
|
3
|
+
== Description
|
4
|
+
|
5
|
+
sdbcli is command line client of Amazon SimpleDB.
|
6
|
+
|
7
|
+
== Source Code
|
8
|
+
|
9
|
+
https://bitbucket.org/winebarrel/sdbcli
|
10
|
+
|
11
|
+
== Install
|
12
|
+
|
13
|
+
shell> gem install sdbcli
|
14
|
+
shell> export AWS_ACCESS_KEY_ID='...'
|
15
|
+
shell> export AWS_SECRET_ACCESS_KEY='...'
|
16
|
+
shell> export SDB_ENDPOINT='sdb.ap-northeast-1.amazonaws.com'
|
17
|
+
shell> sdbcli
|
18
|
+
|
19
|
+
== Example
|
20
|
+
|
21
|
+
ap-northeast-1> help
|
22
|
+
commands:
|
23
|
+
show domains
|
24
|
+
create domain domain_name
|
25
|
+
drop domain domain_name
|
26
|
+
get [output_list] from domain_name where itemname = '...'
|
27
|
+
insert into domain_name (itemname, attr1, attr2, ...) values ('name', 'val1', 'val2', ...)
|
28
|
+
update domain_name set attr1 = 'val1', attr2 = 'val2', ... where itemname = '...'
|
29
|
+
delete [attr1, attr2, ...] from domain_name itemname = '...'
|
30
|
+
select output_list from domain_name [where expression] [sort_instructions] [limit limit]
|
31
|
+
ap-northeast-1> select * from test
|
32
|
+
---
|
33
|
+
- - itemname1
|
34
|
+
- attr1: val1
|
35
|
+
attr2: val2
|
36
|
+
- - itemname2
|
37
|
+
- attr1: val1
|
38
|
+
attr2: val2
|
39
|
+
|
40
|
+
shell> echo 'select * from test' | sdbcli
|
41
|
+
---
|
42
|
+
- - itemname1
|
43
|
+
- attr1: val1
|
44
|
+
attr2: val2
|
45
|
+
- - itemname2
|
46
|
+
- attr1: val1
|
47
|
+
attr2: val2
|
48
|
+
|
data/bin/sdbcli
ADDED
@@ -0,0 +1,72 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
$LOAD_PATH << File.join(File.expand_path(File.dirname(__FILE__)), '..', 'lib')
|
3
|
+
|
4
|
+
require 'rubygems'
|
5
|
+
require 'sdbcli'
|
6
|
+
|
7
|
+
require 'optparse'
|
8
|
+
require 'readline'
|
9
|
+
require 'yaml'
|
10
|
+
|
11
|
+
access_key_id = ENV['AWS_ACCESS_KEY_ID']
|
12
|
+
secret_access_key = ENV['AWS_SECRET_ACCESS_KEY']
|
13
|
+
sdb_endpoint = ENV['SDB_ENDPOINT'] || 'sdb.amazonaws.com'
|
14
|
+
|
15
|
+
ARGV.options do |opt|
|
16
|
+
opt.on('-k', '--access-key-id=AWS_ACCESS_KEY_ID') {|v| access_key_id = v }
|
17
|
+
opt.on('-s', '--secret-access-key=AWS_SECRET_ACCESS_KEY') {|v| secret_access_key = v }
|
18
|
+
opt.on('-e', '--endpoint=SDB_ENDPOINT') {|v| sdb_endpoint = v }
|
19
|
+
opt.parse!
|
20
|
+
|
21
|
+
unless access_key_id and secret_access_key and sdb_endpoint
|
22
|
+
puts opt.help
|
23
|
+
exit 1
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
$runner = SimpleDB::Runner.new(access_key_id, secret_access_key, sdb_endpoint)
|
28
|
+
|
29
|
+
def execute(query)
|
30
|
+
out = $runner.execute(query)
|
31
|
+
puts YAML.dump(out) if out
|
32
|
+
end
|
33
|
+
|
34
|
+
unless $stdin.tty?
|
35
|
+
execute($stdin.read)
|
36
|
+
exit 0
|
37
|
+
end
|
38
|
+
|
39
|
+
if sdb_endpoint =~ /sdb\.([^.]+)\.amazonaws\.com/
|
40
|
+
region = $1
|
41
|
+
else
|
42
|
+
region = 'us-east-1'
|
43
|
+
end
|
44
|
+
|
45
|
+
def help
|
46
|
+
<<-EOS
|
47
|
+
commands:
|
48
|
+
show domains
|
49
|
+
create domain domain_name
|
50
|
+
drop domain domain_name
|
51
|
+
get [output_list] from domain_name where itemname = '...'
|
52
|
+
insert into domain_name (itemname, attr1, attr2, ...) values ('name', 'val1', 'val2', ...)
|
53
|
+
update domain_name set attr1 = 'val1', attr2 = 'val2', ... where itemname = '...'
|
54
|
+
delete [attr1, attr2, ...] from domain_name itemname = '...'
|
55
|
+
select output_list from domain_name [where expression] [sort_instructions] [limit limit]
|
56
|
+
EOS
|
57
|
+
end
|
58
|
+
|
59
|
+
while buf = Readline.readline("#{region}> ", true)
|
60
|
+
begin
|
61
|
+
case buf.downcase
|
62
|
+
when 'help'
|
63
|
+
puts help
|
64
|
+
when 'exit', 'quit'
|
65
|
+
exit
|
66
|
+
else
|
67
|
+
execute(buf.sub(/;\Z/, ''))
|
68
|
+
end
|
69
|
+
rescue => e
|
70
|
+
puts e.message
|
71
|
+
end
|
72
|
+
end
|
@@ -0,0 +1,128 @@
|
|
1
|
+
require 'cgi'
|
2
|
+
require 'base64'
|
3
|
+
require 'net/https'
|
4
|
+
require 'openssl'
|
5
|
+
require 'nokogiri'
|
6
|
+
|
7
|
+
module SimpleDB
|
8
|
+
class Error < StandardError; end
|
9
|
+
|
10
|
+
class Client
|
11
|
+
API_VERSION = '2009-04-15'
|
12
|
+
SIGNATURE_VERSION = 2
|
13
|
+
SIGNATURE_ALGORITHM = :SHA256
|
14
|
+
|
15
|
+
attr_accessor :endpoint
|
16
|
+
|
17
|
+
def initialize(accessKeyId, secretAccessKey, endpoint = 'sdb.amazonaws.com')
|
18
|
+
@accessKeyId = accessKeyId
|
19
|
+
@secretAccessKey = secretAccessKey
|
20
|
+
@endpoint = endpoint
|
21
|
+
end
|
22
|
+
|
23
|
+
# domain action
|
24
|
+
|
25
|
+
def create_domain(domain_name, params = {})
|
26
|
+
params = params.merge(:DomainName => domain_name)
|
27
|
+
query('CreateDomain', params)
|
28
|
+
end
|
29
|
+
|
30
|
+
def list_domains(params = {})
|
31
|
+
query('ListDomains', params)
|
32
|
+
end
|
33
|
+
|
34
|
+
def delete_domain(domain_name, params = {})
|
35
|
+
params = params.merge(:DomainName => domain_name)
|
36
|
+
query('DeleteDomain', params)
|
37
|
+
end
|
38
|
+
|
39
|
+
# attr action
|
40
|
+
|
41
|
+
def put_attributes(domain_name, item_name, params = {})
|
42
|
+
params = params.merge(:DomainName => domain_name, :ItemName => item_name)
|
43
|
+
query('PutAttributes', params)
|
44
|
+
end
|
45
|
+
|
46
|
+
def get_attributes(domain_name, item_name, params = {})
|
47
|
+
params = params.merge(:DomainName => domain_name, :ItemName => item_name)
|
48
|
+
query('GetAttributes', params)
|
49
|
+
end
|
50
|
+
|
51
|
+
def select(params = {})
|
52
|
+
query('Select', params)
|
53
|
+
end
|
54
|
+
|
55
|
+
def delete_attributes(domain_name, item_name, params = {})
|
56
|
+
params = params.merge(:DomainName => domain_name, :ItemName => item_name)
|
57
|
+
query('DeleteAttributes', params)
|
58
|
+
end
|
59
|
+
|
60
|
+
# batch attr action
|
61
|
+
|
62
|
+
def batch_put_attributes(domain_name, params = {})
|
63
|
+
params = params.merge(:DomainName => domain_name)
|
64
|
+
query('BatchPutAttributes', params)
|
65
|
+
end
|
66
|
+
|
67
|
+
def batch_delete_attributes(domain_name, params = {})
|
68
|
+
params = params.merge(:DomainName => domain_name)
|
69
|
+
query('BatchDeleteAttributes', params)
|
70
|
+
end
|
71
|
+
|
72
|
+
private
|
73
|
+
|
74
|
+
def query(action, params = {})
|
75
|
+
params = {
|
76
|
+
:Action => action,
|
77
|
+
:Version => API_VERSION,
|
78
|
+
:Timestamp => Time.now.getutc.strftime('%Y-%m-%dT%H:%M:%SZ'),
|
79
|
+
:SignatureVersion => SIGNATURE_VERSION,
|
80
|
+
:SignatureMethod => "Hmac#{SIGNATURE_ALGORITHM}",
|
81
|
+
:AWSAccessKeyId => @accessKeyId,
|
82
|
+
}.merge(params)
|
83
|
+
|
84
|
+
signature = aws_sign(params)
|
85
|
+
params[:Signature] = signature
|
86
|
+
|
87
|
+
Net::HTTP.version_1_2
|
88
|
+
https = Net::HTTP.new(@endpoint, 443)
|
89
|
+
https.use_ssl = true
|
90
|
+
https.verify_mode = OpenSSL::SSL::VERIFY_NONE
|
91
|
+
|
92
|
+
doc = https.start do |w|
|
93
|
+
req = Net::HTTP::Post.new('/',
|
94
|
+
'Host' => @endpoint,
|
95
|
+
'Content-Type' => 'application/x-www-form-urlencoded'
|
96
|
+
)
|
97
|
+
|
98
|
+
req.set_form_data(params)
|
99
|
+
res = w.request(req)
|
100
|
+
|
101
|
+
Nokogiri::XML(res.body)
|
102
|
+
end
|
103
|
+
|
104
|
+
validate(doc)
|
105
|
+
return doc
|
106
|
+
end
|
107
|
+
|
108
|
+
private
|
109
|
+
def aws_sign(params)
|
110
|
+
params = params.sort_by {|a, b| a.to_s }.map {|k, v| "#{escape(k)}=#{escape(v)}" }.join('&')
|
111
|
+
string_to_sign = "POST\n#{@endpoint}\n/\n#{params}"
|
112
|
+
digest = OpenSSL::HMAC.digest(OpenSSL::Digest.const_get(SIGNATURE_ALGORITHM).new, @secretAccessKey, string_to_sign)
|
113
|
+
Base64.encode64(digest).gsub("\n", '')
|
114
|
+
end
|
115
|
+
|
116
|
+
def validate(doc)
|
117
|
+
if (error = doc.at_css('Errors Error'))
|
118
|
+
code = error.at_css('Code').content
|
119
|
+
message = error.at_css('Message').content
|
120
|
+
raise Error, "#{code}: #{message}"
|
121
|
+
end
|
122
|
+
end
|
123
|
+
|
124
|
+
def escape(str)
|
125
|
+
CGI.escape(str.to_s).gsub('+', '%20')
|
126
|
+
end
|
127
|
+
end # Client
|
128
|
+
end # SimpleDB
|
@@ -0,0 +1,165 @@
|
|
1
|
+
require 'sdbcli/sdb-client'
|
2
|
+
|
3
|
+
module SimpleDB
|
4
|
+
class Error < StandardError; end
|
5
|
+
|
6
|
+
class Driver
|
7
|
+
def initialize(accessKeyId, secretAccessKey, endpoint = 'sdb.amazonaws.com')
|
8
|
+
@client = Client.new(accessKeyId, secretAccessKey, endpoint)
|
9
|
+
end
|
10
|
+
|
11
|
+
def endpoint
|
12
|
+
@client.endpoint
|
13
|
+
end
|
14
|
+
|
15
|
+
def endpoint=(v)
|
16
|
+
@client.endpoint = v
|
17
|
+
end
|
18
|
+
|
19
|
+
# domain action
|
20
|
+
|
21
|
+
def create_domain(domain_name)
|
22
|
+
@client.create_domain(domain_name)
|
23
|
+
end
|
24
|
+
|
25
|
+
def show_domains
|
26
|
+
domains = []
|
27
|
+
|
28
|
+
iterate(:list_domains) do |doc|
|
29
|
+
doc.css('DomainName').each do |i|
|
30
|
+
domains << i.content
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
return domains
|
35
|
+
end
|
36
|
+
|
37
|
+
def drop_domain(domain_name)
|
38
|
+
@client.delete_domain(domain_name)
|
39
|
+
end
|
40
|
+
|
41
|
+
# attr action
|
42
|
+
|
43
|
+
def insert(domain_name, item_name, attrs = {}, consistent = false)
|
44
|
+
params = {:ConsistentRead => consistent}
|
45
|
+
i = 0
|
46
|
+
|
47
|
+
attrs.each do |name, values|
|
48
|
+
[values].flatten.each do |v|
|
49
|
+
i += 1
|
50
|
+
params["Attribute.#{i}.Name"] = name
|
51
|
+
params["Attribute.#{i}.Value"] = v
|
52
|
+
params["Attribute.#{i}.Replace"] = false
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
@client.put_attributes(domain_name, item_name, params)
|
57
|
+
end
|
58
|
+
|
59
|
+
def update(domain_name, items = {}, consistent = false)
|
60
|
+
params = {:ConsistentRead => consistent}
|
61
|
+
i = j = 0
|
62
|
+
|
63
|
+
items.each do |item_name, attrs|
|
64
|
+
i += 1
|
65
|
+
params["Item.#{i}.ItemName"] = item_name
|
66
|
+
|
67
|
+
(attrs || {}).each do |attr_name, values|
|
68
|
+
[values].flatten.each do |v|
|
69
|
+
j += 1
|
70
|
+
params["Item.#{i}.Attribute.#{j}.Name"] = attr_name
|
71
|
+
params["Item.#{i}.Attribute.#{j}.Value"] = v
|
72
|
+
params["Item.#{i}.Attribute.#{j}.Replace"] = true
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
@client.batch_put_attributes(domain_name, params)
|
78
|
+
end
|
79
|
+
|
80
|
+
def get(domain_name, item_name, attr_names = [], consistent = false)
|
81
|
+
params = {:ConsistentRead => consistent}
|
82
|
+
attr_names.each_with_index {|name, i| params["AttributeName.#{i}"] = name }
|
83
|
+
doc = @client.get_attributes(domain_name, item_name, params)
|
84
|
+
attrs_to_hash(doc)
|
85
|
+
end
|
86
|
+
|
87
|
+
def select(expr, consistent = false)
|
88
|
+
params = {:SelectExpression => expr, :ConsistentRead => consistent}
|
89
|
+
items = []
|
90
|
+
|
91
|
+
iterate(:select, params) do |doc|
|
92
|
+
doc.css('Item').map do |i|
|
93
|
+
items << [i.at_css('Name').content, attrs_to_hash(i)]
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
return items
|
98
|
+
end
|
99
|
+
|
100
|
+
def delete(domain_name, items = {}, consistent = false)
|
101
|
+
params = {:ConsistentRead => consistent}
|
102
|
+
i = j = 0
|
103
|
+
|
104
|
+
items.each do |item_name, attrs|
|
105
|
+
i += 1
|
106
|
+
params["Item.#{i}.ItemName"] = item_name
|
107
|
+
|
108
|
+
(attrs || []).each do |attr_name, values|
|
109
|
+
[values].flatten.each do |v|
|
110
|
+
j += 1
|
111
|
+
params["Item.#{i}.Attribute.#{j}.Name"] = attr_name
|
112
|
+
params["Item.#{i}.Attribute.#{j}.Value"] = v if v
|
113
|
+
end
|
114
|
+
end
|
115
|
+
end
|
116
|
+
|
117
|
+
@client.batch_delete_attributes(domain_name, params)
|
118
|
+
end
|
119
|
+
|
120
|
+
private
|
121
|
+
|
122
|
+
def attrs_to_hash(node)
|
123
|
+
h = {}
|
124
|
+
|
125
|
+
node.css('Attribute').map do |i|
|
126
|
+
name = i.at_css('Name').content
|
127
|
+
value = i.at_css('Value').content
|
128
|
+
|
129
|
+
if h[name].kind_of?(Array)
|
130
|
+
h[name] << value
|
131
|
+
elsif h.has_key?(name)
|
132
|
+
h[name] = [h[name], value]
|
133
|
+
else
|
134
|
+
h[name] = value
|
135
|
+
end
|
136
|
+
end
|
137
|
+
|
138
|
+
return h
|
139
|
+
end
|
140
|
+
|
141
|
+
def iterate(method, params = {})
|
142
|
+
Iterator.new(@client, method, params).each do |doc|
|
143
|
+
yield(doc)
|
144
|
+
end
|
145
|
+
end
|
146
|
+
|
147
|
+
class Iterator
|
148
|
+
def initialize(client, method, params = {})
|
149
|
+
@client = client
|
150
|
+
@method = method
|
151
|
+
@params = params.dup
|
152
|
+
@token = :first
|
153
|
+
end
|
154
|
+
|
155
|
+
def each
|
156
|
+
while @token
|
157
|
+
@params.update(:NextToken => @token.content) if @token != :first
|
158
|
+
doc = @client.send(@method, @params)
|
159
|
+
yield(doc)
|
160
|
+
@token = doc.at_css('NextToken')
|
161
|
+
end
|
162
|
+
end
|
163
|
+
end # Iterator
|
164
|
+
end # Driver
|
165
|
+
end # SimpleDB
|
@@ -0,0 +1,466 @@
|
|
1
|
+
#
|
2
|
+
# DO NOT MODIFY!!!!
|
3
|
+
# This file is automatically generated by racc 1.4.5
|
4
|
+
# from racc grammer file "sdb-parser.y".
|
5
|
+
#
|
6
|
+
|
7
|
+
require 'racc/parser'
|
8
|
+
|
9
|
+
|
10
|
+
|
11
|
+
require 'strscan'
|
12
|
+
|
13
|
+
module SimpleDB
|
14
|
+
|
15
|
+
|
16
|
+
class Parser < Racc::Parser
|
17
|
+
|
18
|
+
module_eval <<'..end sdb-parser.y modeval..idc908e49d79', 'sdb-parser.y', 119
|
19
|
+
|
20
|
+
KEYWORDS = %w(
|
21
|
+
AND
|
22
|
+
ASC
|
23
|
+
BETWEEN
|
24
|
+
BY
|
25
|
+
CREATE
|
26
|
+
DELETE
|
27
|
+
DESC
|
28
|
+
DOMAINS
|
29
|
+
DOMAIN
|
30
|
+
DROP
|
31
|
+
EVERY
|
32
|
+
FROM
|
33
|
+
GET
|
34
|
+
INSERT
|
35
|
+
INTERSECTION
|
36
|
+
INTO
|
37
|
+
IN
|
38
|
+
IS
|
39
|
+
ITEMNAME
|
40
|
+
LIKE
|
41
|
+
LIMIT
|
42
|
+
NOT
|
43
|
+
ORDER
|
44
|
+
OR
|
45
|
+
SET
|
46
|
+
SHOW
|
47
|
+
UPDATE
|
48
|
+
VALUES
|
49
|
+
WHERE
|
50
|
+
)
|
51
|
+
|
52
|
+
KEYWORD_REGEXP = Regexp.compile("#{KEYWORDS.join '|'}\\b", Regexp::IGNORECASE)
|
53
|
+
|
54
|
+
def initialize(obj)
|
55
|
+
src = obj.is_a?(IO) ? obj.read : obj.to_s
|
56
|
+
@ss = StringScanner.new(src)
|
57
|
+
end
|
58
|
+
|
59
|
+
@@structs = {}
|
60
|
+
|
61
|
+
def struct(name, attrs = {})
|
62
|
+
unless (clazz = @@structs[name])
|
63
|
+
clazz = attrs.empty? ? Struct.new(name.to_s) : Struct.new(name.to_s, *attrs.keys)
|
64
|
+
@@structs[name] = clazz
|
65
|
+
end
|
66
|
+
|
67
|
+
obj = clazz.new
|
68
|
+
|
69
|
+
attrs.each do |key, val|
|
70
|
+
obj.send("#{key}=", val)
|
71
|
+
end
|
72
|
+
|
73
|
+
return obj
|
74
|
+
end
|
75
|
+
private :struct
|
76
|
+
|
77
|
+
def scan
|
78
|
+
tok = nil
|
79
|
+
|
80
|
+
until @ss.eos?
|
81
|
+
if (tok = @ss.scan /\s+/)
|
82
|
+
# nothing to do
|
83
|
+
elsif (tok = @ss.scan /(?:!=|>=|<=|>|<|=)/)
|
84
|
+
yield tok, tok
|
85
|
+
elsif (tok = @ss.scan KEYWORD_REGEXP)
|
86
|
+
yield tok.upcase.to_sym, tok
|
87
|
+
elsif (tok = @ss.scan /SELECT\b/i)
|
88
|
+
yield :SELECT, tok + @ss.scan(/.*/)
|
89
|
+
elsif (tok = @ss.scan /NULL\b/i)
|
90
|
+
yield :NULL, nil
|
91
|
+
elsif (tok = @ss.scan /`([^`]|``)*`/)
|
92
|
+
yield :IDENTIFIER, tok.slice(1...-1).gsub(/``/, '`')
|
93
|
+
elsif (tok = @ss.scan /'([^']|'')*'/) #'
|
94
|
+
yield :VALUE, tok.slice(1...-1).gsub(/''/, "'")
|
95
|
+
elsif (tok = @ss.scan /"([^"]|"")*"/) #"
|
96
|
+
yield :VALUE, tok.slice(1...-1).gsub(/""/, '"')
|
97
|
+
elsif (tok = @ss.scan /(0|[1-9]\d*)/)
|
98
|
+
yield :NATURAL_NUMBER, tok.to_i
|
99
|
+
elsif (tok = @ss.scan /[,\(\)\*]/)
|
100
|
+
yield tok, tok
|
101
|
+
elsif (tok = @ss.scan /[a-z_$][0-9a-z_$]*\b/i)
|
102
|
+
yield :IDENTIFIER, tok
|
103
|
+
else
|
104
|
+
raise Racc::ParseError, ('parse error on value "%s"' % @ss.rest.inspect)
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
108
|
+
yield false, '$'
|
109
|
+
end
|
110
|
+
private :scan
|
111
|
+
|
112
|
+
def parse
|
113
|
+
yyparse self, :scan
|
114
|
+
end
|
115
|
+
|
116
|
+
def self.parse(obj)
|
117
|
+
self.new(obj).parse
|
118
|
+
end
|
119
|
+
|
120
|
+
..end sdb-parser.y modeval..idc908e49d79
|
121
|
+
|
122
|
+
##### racc 1.4.5 generates ###
|
123
|
+
|
124
|
+
racc_reduce_table = [
|
125
|
+
0, 0, :racc_error,
|
126
|
+
1, 27, :_reduce_none,
|
127
|
+
1, 27, :_reduce_none,
|
128
|
+
1, 27, :_reduce_none,
|
129
|
+
1, 27, :_reduce_none,
|
130
|
+
1, 27, :_reduce_none,
|
131
|
+
1, 27, :_reduce_none,
|
132
|
+
1, 27, :_reduce_none,
|
133
|
+
1, 27, :_reduce_none,
|
134
|
+
1, 27, :_reduce_none,
|
135
|
+
8, 28, :_reduce_10,
|
136
|
+
0, 36, :_reduce_11,
|
137
|
+
1, 36, :_reduce_12,
|
138
|
+
1, 36, :_reduce_none,
|
139
|
+
10, 29, :_reduce_14,
|
140
|
+
3, 38, :_reduce_15,
|
141
|
+
8, 30, :_reduce_16,
|
142
|
+
1, 40, :_reduce_17,
|
143
|
+
3, 40, :_reduce_18,
|
144
|
+
3, 41, :_reduce_19,
|
145
|
+
8, 31, :_reduce_20,
|
146
|
+
0, 42, :_reduce_21,
|
147
|
+
1, 42, :_reduce_none,
|
148
|
+
1, 32, :_reduce_23,
|
149
|
+
3, 33, :_reduce_24,
|
150
|
+
3, 34, :_reduce_25,
|
151
|
+
2, 35, :_reduce_26,
|
152
|
+
1, 37, :_reduce_27,
|
153
|
+
3, 37, :_reduce_28,
|
154
|
+
1, 39, :_reduce_29,
|
155
|
+
3, 39, :_reduce_30 ]
|
156
|
+
|
157
|
+
racc_reduce_n = 31
|
158
|
+
|
159
|
+
racc_shift_n = 74
|
160
|
+
|
161
|
+
racc_action_table = [
|
162
|
+
6, 8, 51, 24, 71, 48, 72, 26, 25, 1,
|
163
|
+
27, 24, 50, 30, 31, 10, 32, 13, 15, 17,
|
164
|
+
33, 3, 5, 34, 35, 36, 34, 37, 38, 39,
|
165
|
+
40, 41, 42, 45, 47, 21, 49, 20, 52, 53,
|
166
|
+
54, 55, 56, 42, 58, 59, 60, 24, 62, 63,
|
167
|
+
64, 65, 34, 66, 67, 68, 70, 19, 73 ]
|
168
|
+
|
169
|
+
racc_action_check = [
|
170
|
+
0, 0, 43, 8, 69, 40, 69, 9, 8, 0,
|
171
|
+
10, 13, 43, 17, 19, 0, 20, 0, 0, 0,
|
172
|
+
22, 0, 0, 23, 26, 27, 28, 29, 30, 31,
|
173
|
+
33, 34, 36, 37, 39, 5, 42, 3, 45, 46,
|
174
|
+
47, 48, 49, 50, 51, 52, 53, 54, 55, 58,
|
175
|
+
59, 60, 61, 62, 63, 64, 65, 1, 72 ]
|
176
|
+
|
177
|
+
racc_action_pointer = [
|
178
|
+
-2, 45, nil, 15, nil, 10, nil, nil, -2, 7,
|
179
|
+
5, nil, nil, 6, nil, nil, nil, -9, nil, 9,
|
180
|
+
11, nil, 16, 7, nil, nil, 24, 7, 10, 23,
|
181
|
+
23, 16, nil, 25, 26, nil, 27, 28, nil, 27,
|
182
|
+
-1, nil, 28, -4, nil, 32, 25, 24, 34, 33,
|
183
|
+
38, 37, 38, 31, 42, 40, nil, nil, 41, 42,
|
184
|
+
38, 36, 44, 45, 46, 47, nil, nil, nil, -10,
|
185
|
+
nil, nil, 49, nil ]
|
186
|
+
|
187
|
+
racc_action_default = [
|
188
|
+
-31, -31, -6, -31, -7, -31, -9, -8, -11, -31,
|
189
|
+
-31, -1, -2, -21, -3, -23, -4, -31, -5, -31,
|
190
|
+
-31, -26, -31, -13, -27, -12, -31, -31, -22, -31,
|
191
|
+
-31, -31, -25, -31, -31, 74, -31, -31, -24, -31,
|
192
|
+
-31, -28, -31, -31, -17, -31, -31, -31, -31, -31,
|
193
|
+
-31, -31, -31, -31, -31, -31, -19, -18, -31, -31,
|
194
|
+
-31, -15, -31, -31, -31, -31, -10, -16, -20, -31,
|
195
|
+
-29, -14, -31, -30 ]
|
196
|
+
|
197
|
+
racc_goto_table = [
|
198
|
+
23, 44, 7, 14, 16, 28, 18, 2, 4, 12,
|
199
|
+
22, 9, 46, 69, 43, 57, 11, 29, nil, nil,
|
200
|
+
nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
|
201
|
+
nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
|
202
|
+
nil, nil, nil, nil, nil, nil, 61 ]
|
203
|
+
|
204
|
+
racc_goto_check = [
|
205
|
+
11, 15, 9, 4, 5, 11, 6, 7, 8, 3,
|
206
|
+
10, 1, 12, 13, 14, 15, 2, 16, nil, nil,
|
207
|
+
nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
|
208
|
+
nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
|
209
|
+
nil, nil, nil, nil, nil, nil, 11 ]
|
210
|
+
|
211
|
+
racc_goto_pointer = [
|
212
|
+
nil, 11, 16, 9, 3, 4, 6, 7, 8, 2,
|
213
|
+
2, -8, -27, -52, -22, -35, 4 ]
|
214
|
+
|
215
|
+
racc_goto_default = [
|
216
|
+
nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
|
217
|
+
nil, nil, nil, nil, nil, nil, nil ]
|
218
|
+
|
219
|
+
racc_token_table = {
|
220
|
+
false => 0,
|
221
|
+
Object.new => 1,
|
222
|
+
:use_stmt => 2,
|
223
|
+
:GET => 3,
|
224
|
+
:FROM => 4,
|
225
|
+
:IDENTIFIER => 5,
|
226
|
+
:WHERE => 6,
|
227
|
+
:ITEMNAME => 7,
|
228
|
+
"=" => 8,
|
229
|
+
:VALUE => 9,
|
230
|
+
"*" => 10,
|
231
|
+
:INSERT => 11,
|
232
|
+
:INTO => 12,
|
233
|
+
"(" => 13,
|
234
|
+
")" => 14,
|
235
|
+
:VALUES => 15,
|
236
|
+
"," => 16,
|
237
|
+
:UPDATE => 17,
|
238
|
+
:SET => 18,
|
239
|
+
:DELETE => 19,
|
240
|
+
:SELECT => 20,
|
241
|
+
:CREATE => 21,
|
242
|
+
:DOMAIN => 22,
|
243
|
+
:DROP => 23,
|
244
|
+
:SHOW => 24,
|
245
|
+
:DOMAINS => 25 }
|
246
|
+
|
247
|
+
racc_use_result_var = false
|
248
|
+
|
249
|
+
racc_nt_base = 26
|
250
|
+
|
251
|
+
Racc_arg = [
|
252
|
+
racc_action_table,
|
253
|
+
racc_action_check,
|
254
|
+
racc_action_default,
|
255
|
+
racc_action_pointer,
|
256
|
+
racc_goto_table,
|
257
|
+
racc_goto_check,
|
258
|
+
racc_goto_default,
|
259
|
+
racc_goto_pointer,
|
260
|
+
racc_nt_base,
|
261
|
+
racc_reduce_table,
|
262
|
+
racc_token_table,
|
263
|
+
racc_shift_n,
|
264
|
+
racc_reduce_n,
|
265
|
+
racc_use_result_var ]
|
266
|
+
|
267
|
+
Racc_token_to_s_table = [
|
268
|
+
'$end',
|
269
|
+
'error',
|
270
|
+
'use_stmt',
|
271
|
+
'GET',
|
272
|
+
'FROM',
|
273
|
+
'IDENTIFIER',
|
274
|
+
'WHERE',
|
275
|
+
'ITEMNAME',
|
276
|
+
'"="',
|
277
|
+
'VALUE',
|
278
|
+
'"*"',
|
279
|
+
'INSERT',
|
280
|
+
'INTO',
|
281
|
+
'"("',
|
282
|
+
'")"',
|
283
|
+
'VALUES',
|
284
|
+
'","',
|
285
|
+
'UPDATE',
|
286
|
+
'SET',
|
287
|
+
'DELETE',
|
288
|
+
'SELECT',
|
289
|
+
'CREATE',
|
290
|
+
'DOMAIN',
|
291
|
+
'DROP',
|
292
|
+
'SHOW',
|
293
|
+
'DOMAINS',
|
294
|
+
'$start',
|
295
|
+
'stmt',
|
296
|
+
'get_stmt',
|
297
|
+
'insert_stmt',
|
298
|
+
'update_stmt',
|
299
|
+
'delete_stmt',
|
300
|
+
'select_stmt',
|
301
|
+
'create_stmt',
|
302
|
+
'drop_stmt',
|
303
|
+
'show_stmt',
|
304
|
+
'get_output_list',
|
305
|
+
'identifier_list',
|
306
|
+
'insert_attr_list',
|
307
|
+
'value_list',
|
308
|
+
'set_clause_list',
|
309
|
+
'set_clause',
|
310
|
+
'delete_attr_list']
|
311
|
+
|
312
|
+
Racc_debug_parser = false
|
313
|
+
|
314
|
+
##### racc system variables end #####
|
315
|
+
|
316
|
+
# reduce 0 omitted
|
317
|
+
|
318
|
+
# reduce 1 omitted
|
319
|
+
|
320
|
+
# reduce 2 omitted
|
321
|
+
|
322
|
+
# reduce 3 omitted
|
323
|
+
|
324
|
+
# reduce 4 omitted
|
325
|
+
|
326
|
+
# reduce 5 omitted
|
327
|
+
|
328
|
+
# reduce 6 omitted
|
329
|
+
|
330
|
+
# reduce 7 omitted
|
331
|
+
|
332
|
+
# reduce 8 omitted
|
333
|
+
|
334
|
+
# reduce 9 omitted
|
335
|
+
|
336
|
+
module_eval <<'.,.,', 'sdb-parser.y', 17
|
337
|
+
def _reduce_10( val, _values)
|
338
|
+
struct(:GET, :domain => val[3], :item_name => val[7], :attr_names => val[1])
|
339
|
+
end
|
340
|
+
.,.,
|
341
|
+
|
342
|
+
module_eval <<'.,.,', 'sdb-parser.y', 22
|
343
|
+
def _reduce_11( val, _values)
|
344
|
+
[]
|
345
|
+
end
|
346
|
+
.,.,
|
347
|
+
|
348
|
+
module_eval <<'.,.,', 'sdb-parser.y', 26
|
349
|
+
def _reduce_12( val, _values)
|
350
|
+
[]
|
351
|
+
end
|
352
|
+
.,.,
|
353
|
+
|
354
|
+
# reduce 13 omitted
|
355
|
+
|
356
|
+
module_eval <<'.,.,', 'sdb-parser.y', 35
|
357
|
+
def _reduce_14( val, _values)
|
358
|
+
attrs = {}
|
359
|
+
val[4].zip(val[8]).each {|k, v| attrs[k] = v }
|
360
|
+
item_name = attrs.delete(:item_name)
|
361
|
+
struct(:INSERT, :domain => val[2], :item_name => item_name, :attrs => attrs)
|
362
|
+
end
|
363
|
+
.,.,
|
364
|
+
|
365
|
+
module_eval <<'.,.,', 'sdb-parser.y', 40
|
366
|
+
def _reduce_15( val, _values)
|
367
|
+
[:item_name, val[2]].flatten
|
368
|
+
end
|
369
|
+
.,.,
|
370
|
+
|
371
|
+
module_eval <<'.,.,', 'sdb-parser.y', 47
|
372
|
+
def _reduce_16( val, _values)
|
373
|
+
attrs = {}
|
374
|
+
val[3].each {|k, v| attrs[k] = v }
|
375
|
+
struct(:UPDATE, :domain => val[1], :items => [[val[7], attrs]])
|
376
|
+
end
|
377
|
+
.,.,
|
378
|
+
|
379
|
+
module_eval <<'.,.,', 'sdb-parser.y', 52
|
380
|
+
def _reduce_17( val, _values)
|
381
|
+
[val[0]]
|
382
|
+
end
|
383
|
+
.,.,
|
384
|
+
|
385
|
+
module_eval <<'.,.,', 'sdb-parser.y', 56
|
386
|
+
def _reduce_18( val, _values)
|
387
|
+
val[0] + [val[2]]
|
388
|
+
end
|
389
|
+
.,.,
|
390
|
+
|
391
|
+
module_eval <<'.,.,', 'sdb-parser.y', 61
|
392
|
+
def _reduce_19( val, _values)
|
393
|
+
[val[0], val[2]]
|
394
|
+
end
|
395
|
+
.,.,
|
396
|
+
|
397
|
+
module_eval <<'.,.,', 'sdb-parser.y', 66
|
398
|
+
def _reduce_20( val, _values)
|
399
|
+
struct(:DELETE, :domain => val[3], :items => [[val[7], val[1]]])
|
400
|
+
end
|
401
|
+
.,.,
|
402
|
+
|
403
|
+
module_eval <<'.,.,', 'sdb-parser.y', 71
|
404
|
+
def _reduce_21( val, _values)
|
405
|
+
[]
|
406
|
+
end
|
407
|
+
.,.,
|
408
|
+
|
409
|
+
# reduce 22 omitted
|
410
|
+
|
411
|
+
module_eval <<'.,.,', 'sdb-parser.y', 77
|
412
|
+
def _reduce_23( val, _values)
|
413
|
+
struct(:SELECT, :query => val[0])
|
414
|
+
end
|
415
|
+
.,.,
|
416
|
+
|
417
|
+
module_eval <<'.,.,', 'sdb-parser.y', 82
|
418
|
+
def _reduce_24( val, _values)
|
419
|
+
struct(:CREATE, :domain => val[2])
|
420
|
+
end
|
421
|
+
.,.,
|
422
|
+
|
423
|
+
module_eval <<'.,.,', 'sdb-parser.y', 87
|
424
|
+
def _reduce_25( val, _values)
|
425
|
+
struct(:DROP, :domain => val[2])
|
426
|
+
end
|
427
|
+
.,.,
|
428
|
+
|
429
|
+
module_eval <<'.,.,', 'sdb-parser.y', 92
|
430
|
+
def _reduce_26( val, _values)
|
431
|
+
struct(:SHOW, :operand => :domains)
|
432
|
+
end
|
433
|
+
.,.,
|
434
|
+
|
435
|
+
module_eval <<'.,.,', 'sdb-parser.y', 97
|
436
|
+
def _reduce_27( val, _values)
|
437
|
+
[val[0]]
|
438
|
+
end
|
439
|
+
.,.,
|
440
|
+
|
441
|
+
module_eval <<'.,.,', 'sdb-parser.y', 101
|
442
|
+
def _reduce_28( val, _values)
|
443
|
+
val[0] + [val[2]]
|
444
|
+
end
|
445
|
+
.,.,
|
446
|
+
|
447
|
+
module_eval <<'.,.,', 'sdb-parser.y', 106
|
448
|
+
def _reduce_29( val, _values)
|
449
|
+
[val[0]]
|
450
|
+
end
|
451
|
+
.,.,
|
452
|
+
|
453
|
+
module_eval <<'.,.,', 'sdb-parser.y', 110
|
454
|
+
def _reduce_30( val, _values)
|
455
|
+
[val[0], val[2]].flatten
|
456
|
+
end
|
457
|
+
.,.,
|
458
|
+
|
459
|
+
def _reduce_none( val, _values)
|
460
|
+
val[0]
|
461
|
+
end
|
462
|
+
|
463
|
+
end # class Parser
|
464
|
+
|
465
|
+
|
466
|
+
end # module SimpleDB
|
@@ -0,0 +1,222 @@
|
|
1
|
+
class Parser
|
2
|
+
options no_result_var
|
3
|
+
rule
|
4
|
+
stmt : get_stmt
|
5
|
+
| insert_stmt
|
6
|
+
| update_stmt
|
7
|
+
| delete_stmt
|
8
|
+
| select_stmt
|
9
|
+
| create_stmt
|
10
|
+
| drop_stmt
|
11
|
+
| show_stmt
|
12
|
+
| use_stmt
|
13
|
+
|
14
|
+
get_stmt : GET get_output_list FROM IDENTIFIER WHERE ITEMNAME '=' VALUE
|
15
|
+
{
|
16
|
+
struct(:GET, :domain => val[3], :item_name => val[7], :attr_names => val[1])
|
17
|
+
}
|
18
|
+
|
19
|
+
get_output_list :
|
20
|
+
{
|
21
|
+
[]
|
22
|
+
}
|
23
|
+
| '*'
|
24
|
+
{
|
25
|
+
[]
|
26
|
+
}
|
27
|
+
| identifier_list
|
28
|
+
|
29
|
+
insert_stmt : INSERT INTO IDENTIFIER '(' insert_attr_list ')' VALUES '(' value_list ')'
|
30
|
+
{
|
31
|
+
attrs = {}
|
32
|
+
val[4].zip(val[8]).each {|k, v| attrs[k] = v }
|
33
|
+
item_name = attrs.delete(:item_name)
|
34
|
+
struct(:INSERT, :domain => val[2], :item_name => item_name, :attrs => attrs)
|
35
|
+
}
|
36
|
+
|
37
|
+
insert_attr_list : ITEMNAME ',' identifier_list
|
38
|
+
{
|
39
|
+
[:item_name, val[2]].flatten
|
40
|
+
}
|
41
|
+
|
42
|
+
update_stmt : UPDATE IDENTIFIER SET set_clause_list WHERE ITEMNAME '=' VALUE
|
43
|
+
{
|
44
|
+
attrs = {}
|
45
|
+
val[3].each {|k, v| attrs[k] = v }
|
46
|
+
struct(:UPDATE, :domain => val[1], :items => [[val[7], attrs]])
|
47
|
+
}
|
48
|
+
|
49
|
+
set_clause_list : set_clause
|
50
|
+
{
|
51
|
+
[val[0]]
|
52
|
+
}
|
53
|
+
| set_clause_list ',' set_clause
|
54
|
+
{
|
55
|
+
val[0] + [val[2]]
|
56
|
+
}
|
57
|
+
|
58
|
+
set_clause : IDENTIFIER '=' VALUE
|
59
|
+
{
|
60
|
+
[val[0], val[2]]
|
61
|
+
}
|
62
|
+
|
63
|
+
delete_stmt : DELETE delete_attr_list FROM IDENTIFIER WHERE ITEMNAME '=' VALUE
|
64
|
+
{
|
65
|
+
struct(:DELETE, :domain => val[3], :items => [[val[7], val[1]]])
|
66
|
+
}
|
67
|
+
|
68
|
+
delete_attr_list :
|
69
|
+
{
|
70
|
+
[]
|
71
|
+
}
|
72
|
+
| identifier_list
|
73
|
+
|
74
|
+
select_stmt : SELECT
|
75
|
+
{
|
76
|
+
struct(:SELECT, :query => val[0])
|
77
|
+
}
|
78
|
+
|
79
|
+
create_stmt : CREATE DOMAIN IDENTIFIER
|
80
|
+
{
|
81
|
+
struct(:CREATE, :domain => val[2])
|
82
|
+
}
|
83
|
+
|
84
|
+
drop_stmt : DROP DOMAIN IDENTIFIER
|
85
|
+
{
|
86
|
+
struct(:DROP, :domain => val[2])
|
87
|
+
}
|
88
|
+
|
89
|
+
show_stmt : SHOW DOMAINS
|
90
|
+
{
|
91
|
+
struct(:SHOW, :operand => :domains)
|
92
|
+
}
|
93
|
+
|
94
|
+
identifier_list: IDENTIFIER
|
95
|
+
{
|
96
|
+
[val[0]]
|
97
|
+
}
|
98
|
+
| identifier_list ',' IDENTIFIER
|
99
|
+
{
|
100
|
+
val[0] + [val[2]]
|
101
|
+
}
|
102
|
+
|
103
|
+
value_list : VALUE
|
104
|
+
{
|
105
|
+
[val[0]]
|
106
|
+
}
|
107
|
+
| value_list ',' VALUE
|
108
|
+
{
|
109
|
+
[val[0], val[2]].flatten
|
110
|
+
}
|
111
|
+
|
112
|
+
---- header
|
113
|
+
|
114
|
+
require 'strscan'
|
115
|
+
|
116
|
+
module SimpleDB
|
117
|
+
|
118
|
+
---- inner
|
119
|
+
|
120
|
+
KEYWORDS = %w(
|
121
|
+
AND
|
122
|
+
ASC
|
123
|
+
BETWEEN
|
124
|
+
BY
|
125
|
+
CREATE
|
126
|
+
DELETE
|
127
|
+
DESC
|
128
|
+
DOMAINS
|
129
|
+
DOMAIN
|
130
|
+
DROP
|
131
|
+
EVERY
|
132
|
+
FROM
|
133
|
+
GET
|
134
|
+
INSERT
|
135
|
+
INTERSECTION
|
136
|
+
INTO
|
137
|
+
IN
|
138
|
+
IS
|
139
|
+
ITEMNAME
|
140
|
+
LIKE
|
141
|
+
LIMIT
|
142
|
+
NOT
|
143
|
+
ORDER
|
144
|
+
OR
|
145
|
+
SET
|
146
|
+
SHOW
|
147
|
+
UPDATE
|
148
|
+
VALUES
|
149
|
+
WHERE
|
150
|
+
)
|
151
|
+
|
152
|
+
KEYWORD_REGEXP = Regexp.compile("#{KEYWORDS.join '|'}\\b", Regexp::IGNORECASE)
|
153
|
+
|
154
|
+
def initialize(obj)
|
155
|
+
src = obj.is_a?(IO) ? obj.read : obj.to_s
|
156
|
+
@ss = StringScanner.new(src)
|
157
|
+
end
|
158
|
+
|
159
|
+
@@structs = {}
|
160
|
+
|
161
|
+
def struct(name, attrs = {})
|
162
|
+
unless (clazz = @@structs[name])
|
163
|
+
clazz = attrs.empty? ? Struct.new(name.to_s) : Struct.new(name.to_s, *attrs.keys)
|
164
|
+
@@structs[name] = clazz
|
165
|
+
end
|
166
|
+
|
167
|
+
obj = clazz.new
|
168
|
+
|
169
|
+
attrs.each do |key, val|
|
170
|
+
obj.send("#{key}=", val)
|
171
|
+
end
|
172
|
+
|
173
|
+
return obj
|
174
|
+
end
|
175
|
+
private :struct
|
176
|
+
|
177
|
+
def scan
|
178
|
+
tok = nil
|
179
|
+
|
180
|
+
until @ss.eos?
|
181
|
+
if (tok = @ss.scan /\s+/)
|
182
|
+
# nothing to do
|
183
|
+
elsif (tok = @ss.scan /(?:!=|>=|<=|>|<|=)/)
|
184
|
+
yield tok, tok
|
185
|
+
elsif (tok = @ss.scan KEYWORD_REGEXP)
|
186
|
+
yield tok.upcase.to_sym, tok
|
187
|
+
elsif (tok = @ss.scan /SELECT\b/i)
|
188
|
+
yield :SELECT, tok + @ss.scan(/.*/)
|
189
|
+
elsif (tok = @ss.scan /NULL\b/i)
|
190
|
+
yield :NULL, nil
|
191
|
+
elsif (tok = @ss.scan /`([^`]|``)*`/)
|
192
|
+
yield :IDENTIFIER, tok.slice(1...-1).gsub(/``/, '`')
|
193
|
+
elsif (tok = @ss.scan /'([^']|'')*'/) #'
|
194
|
+
yield :VALUE, tok.slice(1...-1).gsub(/''/, "'")
|
195
|
+
elsif (tok = @ss.scan /"([^"]|"")*"/) #"
|
196
|
+
yield :VALUE, tok.slice(1...-1).gsub(/""/, '"')
|
197
|
+
elsif (tok = @ss.scan /(0|[1-9]\d*)/)
|
198
|
+
yield :NATURAL_NUMBER, tok.to_i
|
199
|
+
elsif (tok = @ss.scan /[,\(\)\*]/)
|
200
|
+
yield tok, tok
|
201
|
+
elsif (tok = @ss.scan /[a-z_$][0-9a-z_$]*\b/i)
|
202
|
+
yield :IDENTIFIER, tok
|
203
|
+
else
|
204
|
+
raise Racc::ParseError, ('parse error on value "%s"' % @ss.rest.inspect)
|
205
|
+
end
|
206
|
+
end
|
207
|
+
|
208
|
+
yield false, '$'
|
209
|
+
end
|
210
|
+
private :scan
|
211
|
+
|
212
|
+
def parse
|
213
|
+
yyparse self, :scan
|
214
|
+
end
|
215
|
+
|
216
|
+
def self.parse(obj)
|
217
|
+
self.new(obj).parse
|
218
|
+
end
|
219
|
+
|
220
|
+
---- footer
|
221
|
+
|
222
|
+
end # module SimpleDB
|
@@ -0,0 +1,51 @@
|
|
1
|
+
require 'sdbcli/sdb-driver'
|
2
|
+
require 'sdbcli/sdb-parser.tab'
|
3
|
+
|
4
|
+
module SimpleDB
|
5
|
+
class Error < StandardError; end
|
6
|
+
|
7
|
+
class Runner
|
8
|
+
def initialize(accessKeyId, secretAccessKey, endpoint = 'sdb.amazonaws.com')
|
9
|
+
@driver = Driver.new(accessKeyId, secretAccessKey, endpoint)
|
10
|
+
end
|
11
|
+
|
12
|
+
def endpoint
|
13
|
+
@driver.endpoint
|
14
|
+
end
|
15
|
+
|
16
|
+
def endpoint=(v)
|
17
|
+
@driver.endpoint = v
|
18
|
+
end
|
19
|
+
|
20
|
+
def execute(query)
|
21
|
+
parsed = Parser.parse(query)
|
22
|
+
command = parsed.class.name.split('::').last.to_sym
|
23
|
+
|
24
|
+
case command
|
25
|
+
when :GET
|
26
|
+
@driver.get(parsed.domain, parsed.item_name, parsed.attr_names)
|
27
|
+
when :INSERT
|
28
|
+
@driver.insert(parsed.domain, parsed.item_name, parsed.attrs)
|
29
|
+
nil
|
30
|
+
when :UPDATE
|
31
|
+
@driver.update(parsed.domain, parsed.items)
|
32
|
+
nil
|
33
|
+
when :DELETE
|
34
|
+
@driver.delete(parsed.domain, parsed.items)
|
35
|
+
nil
|
36
|
+
when :SELECT
|
37
|
+
@driver.select(parsed.query)
|
38
|
+
when :CREATE
|
39
|
+
@driver.create_domain(parsed.domain)
|
40
|
+
nil
|
41
|
+
when :DROP
|
42
|
+
@driver.drop_domain(parsed.domain)
|
43
|
+
nil
|
44
|
+
when :SHOW
|
45
|
+
@driver.show_domains
|
46
|
+
else
|
47
|
+
raise 'must not happen'
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end # Runner
|
51
|
+
end # SimpleDB
|
data/lib/sdbcli.rb
ADDED
metadata
ADDED
@@ -0,0 +1,85 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: sdbcli
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
hash: 27
|
5
|
+
prerelease:
|
6
|
+
segments:
|
7
|
+
- 0
|
8
|
+
- 1
|
9
|
+
- 0
|
10
|
+
version: 0.1.0
|
11
|
+
platform: ruby
|
12
|
+
authors:
|
13
|
+
- winebarrel
|
14
|
+
autorequire:
|
15
|
+
bindir: bin
|
16
|
+
cert_chain: []
|
17
|
+
|
18
|
+
date: 2012-01-16 00:00:00 Z
|
19
|
+
dependencies:
|
20
|
+
- !ruby/object:Gem::Dependency
|
21
|
+
name: nokogiri
|
22
|
+
prerelease: false
|
23
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
24
|
+
none: false
|
25
|
+
requirements:
|
26
|
+
- - ">="
|
27
|
+
- !ruby/object:Gem::Version
|
28
|
+
hash: 3
|
29
|
+
segments:
|
30
|
+
- 0
|
31
|
+
version: "0"
|
32
|
+
type: :runtime
|
33
|
+
version_requirements: *id001
|
34
|
+
description:
|
35
|
+
email: sgwr_dts@yahoo.co.jp
|
36
|
+
executables:
|
37
|
+
- sdbcli
|
38
|
+
extensions: []
|
39
|
+
|
40
|
+
extra_rdoc_files: []
|
41
|
+
|
42
|
+
files:
|
43
|
+
- README
|
44
|
+
- bin/sdbcli
|
45
|
+
- lib/sdbcli/sdb-client.rb
|
46
|
+
- lib/sdbcli/sdb-driver.rb
|
47
|
+
- lib/sdbcli/sdb-parser.tab.rb
|
48
|
+
- lib/sdbcli/sdb-parser.y
|
49
|
+
- lib/sdbcli/sdb-runner.rb
|
50
|
+
- lib/sdbcli.rb
|
51
|
+
homepage: https://bitbucket.org/winebarrel/sdbcli
|
52
|
+
licenses: []
|
53
|
+
|
54
|
+
post_install_message:
|
55
|
+
rdoc_options: []
|
56
|
+
|
57
|
+
require_paths:
|
58
|
+
- lib
|
59
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
60
|
+
none: false
|
61
|
+
requirements:
|
62
|
+
- - ">="
|
63
|
+
- !ruby/object:Gem::Version
|
64
|
+
hash: 3
|
65
|
+
segments:
|
66
|
+
- 0
|
67
|
+
version: "0"
|
68
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
69
|
+
none: false
|
70
|
+
requirements:
|
71
|
+
- - ">="
|
72
|
+
- !ruby/object:Gem::Version
|
73
|
+
hash: 3
|
74
|
+
segments:
|
75
|
+
- 0
|
76
|
+
version: "0"
|
77
|
+
requirements: []
|
78
|
+
|
79
|
+
rubyforge_project:
|
80
|
+
rubygems_version: 1.8.11
|
81
|
+
signing_key:
|
82
|
+
specification_version: 3
|
83
|
+
summary: sdbcli is command line client of Amazon SimpleDB.
|
84
|
+
test_files: []
|
85
|
+
|