right_aws 1.9.0 → 1.10.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/History.txt +25 -0
- data/README.txt +5 -3
- data/Rakefile +15 -6
- data/lib/acf/right_acf_interface.rb +1 -1
- data/lib/awsbase/right_awsbase.rb +89 -9
- data/lib/ec2/right_ec2.rb +105 -21
- data/lib/right_aws.rb +1 -1
- data/lib/s3/right_s3_interface.rb +32 -42
- data/lib/sdb/active_sdb.rb +178 -21
- data/lib/sdb/right_sdb_interface.rb +222 -27
- data/lib/sqs/right_sqs_gen2_interface.rb +14 -20
- data/lib/sqs/right_sqs_interface.rb +4 -11
- data/test/acf/test_right_acf.rb +1 -1
- data/test/ec2/test_right_ec2.rb +32 -0
- data/test/s3/test_right_s3.rb +2 -2
- data/test/sdb/test_active_sdb.rb +50 -7
- data/test/sdb/test_right_sdb.rb +59 -10
- metadata +6 -6
data/lib/sdb/active_sdb.rb
CHANGED
@@ -24,7 +24,7 @@
|
|
24
24
|
begin
|
25
25
|
require 'uuidtools'
|
26
26
|
rescue LoadError => e
|
27
|
-
STDERR.puts("RightSDB
|
27
|
+
STDERR.puts("RightSDB requires the uuidtools gem. Run \'gem install uuidtools\' and try again.")
|
28
28
|
exit
|
29
29
|
end
|
30
30
|
|
@@ -294,6 +294,8 @@ module RightAws
|
|
294
294
|
# Client.find(:first) #=> #<Client:0xb77d0d40 @attributes={"id"=>"2937601a-e45d-11dc-a75f-001bfc466dd7"}, @new_record=false>
|
295
295
|
# Client.find(:first, :auto_load => true) #=> #<Client:0xb77d0d40 @attributes={"id"=>"2937601a-e45d-11dc-a75f-001bfc466dd7", "name"=>["Cat"], "toys"=>["Jons socks", "clew", "mice"]}, @new_record=false>
|
296
296
|
#
|
297
|
+
# see http://docs.amazonwebservices.com/AmazonSimpleDB/2007-11-07/DeveloperGuide/index.html?UsingQuery.html
|
298
|
+
#
|
297
299
|
def find(*args)
|
298
300
|
options = args.last.is_a?(Hash) ? args.pop : {}
|
299
301
|
case args.first
|
@@ -303,12 +305,137 @@ module RightAws
|
|
303
305
|
end
|
304
306
|
end
|
305
307
|
|
308
|
+
# Perform a SQL-like select request.
|
309
|
+
#
|
310
|
+
# Single record:
|
311
|
+
#
|
312
|
+
# Client.select(:first)
|
313
|
+
# Client.select(:first, :conditions=> [ "name=? AND wife=?", "Jon", "Sandy"])
|
314
|
+
# Client.select(:first, :conditions=> { :name=>"Jon", :wife=>"Sandy" }, :select => :girfriends)
|
315
|
+
#
|
316
|
+
# Bunch of records:
|
317
|
+
#
|
318
|
+
# Client.select(:all)
|
319
|
+
# Client.select(:all, :limit => 10)
|
320
|
+
# Client.select(:all, :conditions=> [ "name=? AND 'girlfriend'=?", "Jon", "Judy"])
|
321
|
+
# Client.select(:all, :conditions=> { :name=>"Sandy" }, :limit => 3)
|
322
|
+
#
|
323
|
+
# Records by ids:
|
324
|
+
#
|
325
|
+
# Client.select('1')
|
326
|
+
# Client.select('1234987b4583475347523948')
|
327
|
+
# Client.select('1','2','3','4', :conditions=> ["toys=?", "beer"])
|
328
|
+
#
|
329
|
+
# Find helpers: RightAws::ActiveSdb::Base.select_by_... and RightAws::ActiveSdb::Base.select_all_by_...
|
330
|
+
#
|
331
|
+
# Client.select_by_name('Matias Rust')
|
332
|
+
# Client.select_by_name_and_city('Putin','Moscow')
|
333
|
+
# Client.select_by_name_and_city_and_post('Medvedev','Moscow','president')
|
334
|
+
#
|
335
|
+
# Client.select_all_by_author('G.Bush jr')
|
336
|
+
# Client.select_all_by_age_and_gender_and_ethnicity('34','male','russian')
|
337
|
+
# Client.select_all_by_gender_and_country('male', 'Russia', :order => 'name')
|
338
|
+
#
|
339
|
+
# Continue listing:
|
340
|
+
#
|
341
|
+
# # initial listing
|
342
|
+
# Client.select(:all, :limit => 10)
|
343
|
+
# # continue listing
|
344
|
+
# begin
|
345
|
+
# Client.select(:all, :limit => 10, :next_token => Client.next_token)
|
346
|
+
# end while Client.next_token
|
347
|
+
#
|
348
|
+
# Sort oder:
|
349
|
+
# If :order=>'attribute' option is specified then result response (ordered by 'attribute') will contain only items where attribute is defined (is not null).
|
350
|
+
#
|
351
|
+
# Client.select(:all) # returns all records
|
352
|
+
# Client.select(:all, :order => 'gender') # returns all records ordered by gender where gender attribute exists
|
353
|
+
# Client.select(:all, :order => 'name desc') # returns all records ordered by name in desc order where name attribute exists
|
354
|
+
#
|
355
|
+
# see http://docs.amazonwebservices.com/AmazonSimpleDB/2007-11-07/DeveloperGuide/index.html?UsingSelect.html
|
356
|
+
#
|
357
|
+
def select(*args)
|
358
|
+
options = args.last.is_a?(Hash) ? args.pop : {}
|
359
|
+
case args.first
|
360
|
+
when :all then sql_select(options)
|
361
|
+
when :first then sql_select(options.merge(:limit => 1)).first
|
362
|
+
else select_from_ids args, options
|
363
|
+
end
|
364
|
+
end
|
365
|
+
|
366
|
+
def generate_id # :nodoc:
|
367
|
+
UUID.timestamp_create().to_s
|
368
|
+
end
|
369
|
+
|
306
370
|
protected
|
307
371
|
|
372
|
+
# Select
|
373
|
+
|
374
|
+
def select_from_ids(args, options) # :nodoc:
|
375
|
+
cond = []
|
376
|
+
# detect amount of records requested
|
377
|
+
bunch_of_records_requested = args.size > 1 || args.first.is_a?(Array)
|
378
|
+
# flatten ids
|
379
|
+
args = args.to_a.flatten
|
380
|
+
args.each { |id| cond << "id=#{self.connection.escape(id)}" }
|
381
|
+
ids_cond = "(#{cond.join(' OR ')})"
|
382
|
+
# user defined :conditions to string (if it was defined)
|
383
|
+
options[:conditions] = build_conditions(options[:conditions])
|
384
|
+
# join ids condition and user defined conditions
|
385
|
+
options[:conditions] = options[:conditions].blank? ? ids_cond : "(#{options[:conditions]}) AND #{ids_cond}"
|
386
|
+
result = sql_select(options)
|
387
|
+
# if one record was requested then return it
|
388
|
+
unless bunch_of_records_requested
|
389
|
+
record = result.first
|
390
|
+
# railse if nothing was found
|
391
|
+
raise ActiveSdbError.new("Couldn't find #{name} with ID #{args}") unless record
|
392
|
+
record
|
393
|
+
else
|
394
|
+
# if a bunch of records was requested then return check that we found all of them
|
395
|
+
# and return as an array
|
396
|
+
unless args.size == result.size
|
397
|
+
id_list = args.map{|i| "'#{i}'"}.join(',')
|
398
|
+
raise ActiveSdbError.new("Couldn't find all #{name} with IDs (#{id_list}) (found #{result.size} results, but was looking for #{args.size})")
|
399
|
+
else
|
400
|
+
result
|
401
|
+
end
|
402
|
+
end
|
403
|
+
end
|
404
|
+
|
405
|
+
def sql_select(options) # :nodoc:
|
406
|
+
@next_token = options[:next_token]
|
407
|
+
select_expression = build_select(options)
|
408
|
+
# request items
|
409
|
+
query_result = self.connection.select(select_expression, @next_token)
|
410
|
+
@next_token = query_result[:next_token]
|
411
|
+
items = query_result[:items].map do |hash|
|
412
|
+
id, attributes = hash.shift
|
413
|
+
new_item = self.new( attributes.merge({ 'id' => id }))
|
414
|
+
new_item.mark_as_old
|
415
|
+
new_item
|
416
|
+
end
|
417
|
+
items
|
418
|
+
end
|
419
|
+
|
420
|
+
# select_by helpers
|
421
|
+
def select_all_by_(format_str, args, options) # :nodoc:
|
422
|
+
fields = format_str.to_s.sub(/^select_(all_)?by_/,'').split('_and_')
|
423
|
+
conditions = fields.map { |field| "#{field}=?" }.join(' AND ')
|
424
|
+
options[:conditions] = [conditions, *args]
|
425
|
+
select(:all, options)
|
426
|
+
end
|
427
|
+
|
428
|
+
def select_by_(format_str, args, options) # :nodoc:
|
429
|
+
options[:limit] = 1
|
430
|
+
select_all_by_(format_str, args, options).first
|
431
|
+
end
|
432
|
+
|
433
|
+
# Query
|
434
|
+
|
308
435
|
# Returns an array of query attributes.
|
309
436
|
# Query_expression must be a well formated SDB query string:
|
310
437
|
# query_attributes("['title' starts-with 'O\\'Reily'] intersection ['year' = '2007']") #=> ["title", "year"]
|
311
|
-
def query_attributes(query_expression)
|
438
|
+
def query_attributes(query_expression) # :nodoc:
|
312
439
|
attrs = []
|
313
440
|
array = query_expression.scan(/['"](.*?[^\\])['"]/).flatten
|
314
441
|
until array.empty? do
|
@@ -334,8 +461,7 @@ module RightAws
|
|
334
461
|
#
|
335
462
|
def query(options) # :nodoc:
|
336
463
|
@next_token = options[:next_token]
|
337
|
-
query_expression = options[:query_expression]
|
338
|
-
query_expression = connection.query_expression_from_array(query_expression) if query_expression.is_a?(Array)
|
464
|
+
query_expression = build_conditions(options[:query_expression])
|
339
465
|
# add sort_options to the query_expression
|
340
466
|
if options[:sort_option]
|
341
467
|
sort_by, sort_order = sort_options(options[:sort_option])
|
@@ -358,14 +484,19 @@ module RightAws
|
|
358
484
|
items = query_result[:items].map do |name|
|
359
485
|
new_item = self.new('id' => name)
|
360
486
|
new_item.mark_as_old
|
361
|
-
|
487
|
+
reload_if_exists(record) if options[:auto_load]
|
362
488
|
new_item
|
363
489
|
end
|
364
490
|
items
|
365
491
|
end
|
366
492
|
|
493
|
+
# reload a record unless it is nil
|
494
|
+
def reload_if_exists(record) # :nodoc:
|
495
|
+
record && record.reload
|
496
|
+
end
|
497
|
+
|
367
498
|
def reload_all_records(*list) # :nodoc:
|
368
|
-
list.flatten.each { |record| record
|
499
|
+
list.flatten.each { |record| reload_if_exists(record) }
|
369
500
|
end
|
370
501
|
|
371
502
|
def find_every(options) # :nodoc:
|
@@ -391,15 +522,16 @@ module RightAws
|
|
391
522
|
args.each { |id| cond << "'id'=#{self.connection.escape(id)}" }
|
392
523
|
ids_cond = "[#{cond.join(' OR ')}]"
|
393
524
|
# user defined :conditions to string (if it was defined)
|
394
|
-
|
395
|
-
options[:conditions] = connection.query_expression_from_array(options[:conditions])
|
396
|
-
end
|
525
|
+
options[:conditions] = build_conditions(options[:conditions])
|
397
526
|
# join ids condition and user defined conditions
|
398
527
|
options[:conditions] = options[:conditions].blank? ? ids_cond : "#{options[:conditions]} intersection #{ids_cond}"
|
399
528
|
result = find_every(options)
|
400
529
|
# if one record was requested then return it
|
401
530
|
unless bunch_of_records_requested
|
402
|
-
|
531
|
+
record = result.first
|
532
|
+
# railse if nothing was found
|
533
|
+
raise ActiveSdbError.new("Couldn't find #{name} with ID #{args}") unless record
|
534
|
+
options[:auto_load] ? reload_all_records(record).first : record
|
403
535
|
else
|
404
536
|
# if a bunch of records was requested then return check that we found all of them
|
405
537
|
# and return as an array
|
@@ -425,22 +557,39 @@ module RightAws
|
|
425
557
|
find_all_by_(format_str, args, options).first
|
426
558
|
end
|
427
559
|
|
560
|
+
# Misc
|
561
|
+
|
428
562
|
def method_missing(method, *args) # :nodoc:
|
429
|
-
if method.to_s[/^(find_all_by_|find_by_)/]
|
563
|
+
if method.to_s[/^(find_all_by_|find_by_|select_all_by_|select_by_)/]
|
430
564
|
options = args.last.is_a?(Hash) ? args.pop : {}
|
431
|
-
|
432
|
-
find_all_by_(method, args, options)
|
433
|
-
else
|
434
|
-
find_by_(method, args, options)
|
435
|
-
end
|
565
|
+
__send__($1, method, args, options)
|
436
566
|
else
|
437
567
|
super(method, *args)
|
438
568
|
end
|
439
569
|
end
|
440
|
-
|
441
|
-
|
442
|
-
|
443
|
-
|
570
|
+
|
571
|
+
def build_select(options) # :nodoc:
|
572
|
+
select = options[:select] || '*'
|
573
|
+
from = options[:from] || domain
|
574
|
+
conditions = options[:conditions] ? " WHERE #{build_conditions(options[:conditions])}" : ''
|
575
|
+
order = options[:order] ? " ORDER BY #{options[:order]}" : ''
|
576
|
+
limit = options[:limit] ? " LIMIT #{options[:limit]}" : ''
|
577
|
+
# mix sort by argument (it must present in response)
|
578
|
+
unless order.blank?
|
579
|
+
sort_by, sort_order = sort_options(options[:order])
|
580
|
+
conditions << (conditions.blank? ? " WHERE " : " AND ") << "(#{sort_by} IS NOT NULL)"
|
581
|
+
end
|
582
|
+
"SELECT #{select} FROM #{from}#{conditions}#{order}#{limit}"
|
583
|
+
end
|
584
|
+
|
585
|
+
def build_conditions(conditions) # :nodoc:
|
586
|
+
case
|
587
|
+
when conditions.is_a?(Array) then connection.query_expression_from_array(conditions)
|
588
|
+
when conditions.is_a?(Hash) then connection.query_expression_from_hash(conditions)
|
589
|
+
else conditions
|
590
|
+
end
|
591
|
+
end
|
592
|
+
|
444
593
|
end
|
445
594
|
|
446
595
|
public
|
@@ -695,7 +844,15 @@ module RightAws
|
|
695
844
|
attrs.delete('id')
|
696
845
|
unless attrs.blank?
|
697
846
|
connection.delete_attributes(domain, id, attrs)
|
698
|
-
attrs.each
|
847
|
+
attrs.each do |attribute, values|
|
848
|
+
# remove the values from the attribute
|
849
|
+
if @attributes[attribute]
|
850
|
+
@attributes[attribute] -= values
|
851
|
+
else
|
852
|
+
# if the attribute is unknown remove it from a resulting list of fixed attributes
|
853
|
+
attrs.delete(attribute)
|
854
|
+
end
|
855
|
+
end
|
699
856
|
end
|
700
857
|
attrs
|
701
858
|
end
|
@@ -78,28 +78,25 @@ module RightAws
|
|
78
78
|
params.delete_if {|key,value| value.nil? }
|
79
79
|
#params_string = params.to_a.collect{|key,val| key + "=#{CGI::escape(val.to_s)}" }.join("&")
|
80
80
|
# prepare service data
|
81
|
-
|
82
|
-
|
83
|
-
"
|
84
|
-
"
|
85
|
-
"SignatureVersion" => signature_version }
|
81
|
+
service = '/'
|
82
|
+
service_hash = {"Action" => action,
|
83
|
+
"AWSAccessKeyId" => @aws_access_key_id,
|
84
|
+
"Version" => API_VERSION }
|
86
85
|
service_hash.update(params)
|
87
|
-
|
88
|
-
string_to_sign = case signature_version
|
89
|
-
when '0' then service_hash["Action"] + service_hash["Timestamp"]
|
90
|
-
when '1' then service_hash.sort{|a,b| (a[0].to_s.downcase)<=>(b[0].to_s.downcase)}.to_s
|
91
|
-
end
|
92
|
-
service_hash.update('Signature' => AwsUtils::sign(@aws_secret_access_key, string_to_sign))
|
93
|
-
service_string = service_hash.to_a.collect{|key,val| key + "=#{CGI::escape(val.to_s)}" }.join("&")
|
86
|
+
service_params = signed_service_params(@aws_secret_access_key, service_hash, :get, @params[:server], service)
|
94
87
|
#
|
95
88
|
# use POST method if the length of the query string is too large
|
96
89
|
# see http://docs.amazonwebservices.com/AmazonSimpleDB/2007-11-07/DeveloperGuide/MakingRESTRequests.html
|
97
|
-
if
|
98
|
-
|
99
|
-
|
90
|
+
if service_params.size > 2000
|
91
|
+
if signature_version == '2'
|
92
|
+
# resign the request because HTTP verb is included into signature
|
93
|
+
service_params = signed_service_params(@aws_secret_access_key, service_hash, :post, @params[:server], service)
|
94
|
+
end
|
95
|
+
request = Net::HTTP::Post.new(service)
|
96
|
+
request.body = service_params
|
97
|
+
request['Content-Type'] = 'application/x-www-form-urlencoded'
|
100
98
|
else
|
101
|
-
|
102
|
-
request = Net::HTTP::Get.new("/?#{service_string}")
|
99
|
+
request = Net::HTTP::Get.new("#{service}?#{service_params}")
|
103
100
|
end
|
104
101
|
# prepare output hash
|
105
102
|
{ :request => request,
|
@@ -163,23 +160,44 @@ module RightAws
|
|
163
160
|
def sdb_to_ruby(value)
|
164
161
|
value.eql?(@nil_rep) ? nil : value
|
165
162
|
end
|
166
|
-
|
163
|
+
|
164
|
+
# Convert select and query_with_attributes responses to a Ruby language values by replacing the user's chosen string representation of nil with Ruby nil.
|
165
|
+
# (This method affects on a passed response value)
|
166
|
+
def select_response_to_ruby(response) #:nodoc:
|
167
|
+
response[:items].each_with_index do |item, idx|
|
168
|
+
item.each do |key, attributes|
|
169
|
+
attributes.each do |name, values|
|
170
|
+
values.collect! { |value| sdb_to_ruby(value) }
|
171
|
+
end
|
172
|
+
end
|
173
|
+
end
|
174
|
+
response
|
175
|
+
end
|
176
|
+
|
167
177
|
# Create query expression from an array.
|
168
178
|
# (similar to ActiveRecord::Base#find using :conditions => ['query', param1, .., paramN])
|
169
179
|
#
|
170
180
|
def query_expression_from_array(params) #:nodoc:
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
end
|
181
|
+
return '' if params.blank?
|
182
|
+
query = params.shift.to_s
|
183
|
+
query.gsub(/(\\)?(\?)/) do
|
184
|
+
if $1 # if escaped '\?' is found - replace it by '?' without backslash
|
185
|
+
"?"
|
186
|
+
else # well, if no backslash precedes '?' then replace it by next param from the list
|
187
|
+
escape(params.shift)
|
179
188
|
end
|
180
189
|
end
|
181
190
|
end
|
182
|
-
|
191
|
+
|
192
|
+
def query_expression_from_hash(hash)
|
193
|
+
return '' if hash.blank?
|
194
|
+
expression = []
|
195
|
+
hash.each do |key, value|
|
196
|
+
expression << "#{key}=#{escape(value)}"
|
197
|
+
end
|
198
|
+
expression.join(' AND ')
|
199
|
+
end
|
200
|
+
|
183
201
|
# Retrieve a list of SDB domains from Amazon.
|
184
202
|
#
|
185
203
|
# Returns a hash:
|
@@ -440,6 +458,137 @@ module RightAws
|
|
440
458
|
on_exception
|
441
459
|
end
|
442
460
|
|
461
|
+
# Perform a query and fetch specified attributes.
|
462
|
+
# If attributes are not specified then fetches the whole list of attributes.
|
463
|
+
#
|
464
|
+
#
|
465
|
+
# Returns a hash:
|
466
|
+
# { :box_usage => string,
|
467
|
+
# :request_id => string,
|
468
|
+
# :next_token => string,
|
469
|
+
# :items => [ { ItemName1 => { attribute1 => value1, ... attributeM => valueM } },
|
470
|
+
# { ItemName2 => {...}}, ... ]
|
471
|
+
#
|
472
|
+
# Example:
|
473
|
+
#
|
474
|
+
# sdb.query_with_attributes(domain, ['hobby', 'country'], "['gender'='female'] intersection ['name' starts-with ''] sort 'name'") #=>
|
475
|
+
# { :request_id => "06057228-70d0-4487-89fb-fd9c028580d3",
|
476
|
+
# :items =>
|
477
|
+
# [ { "035f1ba8-dbd8-11dd-80bd-001bfc466dd7"=>
|
478
|
+
# { "hobby" => ["cooking", "flowers", "cats"],
|
479
|
+
# "country" => ["Russia"]}},
|
480
|
+
# { "0327614a-dbd8-11dd-80bd-001bfc466dd7"=>
|
481
|
+
# { "hobby" => ["patchwork", "bundle jumping"],
|
482
|
+
# "country" => ["USA"]}}, ... ],
|
483
|
+
# :box_usage=>"0.0000504786"}
|
484
|
+
#
|
485
|
+
# sdb.query_with_attributes(domain, [], "['gender'='female'] intersection ['name' starts-with ''] sort 'name'") #=>
|
486
|
+
# { :request_id => "75bb19db-a529-4f69-b86f-5e3800f79a45",
|
487
|
+
# :items =>
|
488
|
+
# [ { "035f1ba8-dbd8-11dd-80bd-001bfc466dd7"=>
|
489
|
+
# { "hobby" => ["cooking", "flowers", "cats"],
|
490
|
+
# "name" => ["Mary"],
|
491
|
+
# "country" => ["Russia"],
|
492
|
+
# "gender" => ["female"],
|
493
|
+
# "id" => ["035f1ba8-dbd8-11dd-80bd-001bfc466dd7"]}},
|
494
|
+
# { "0327614a-dbd8-11dd-80bd-001bfc466dd7"=>
|
495
|
+
# { "hobby" => ["patchwork", "bundle jumping"],
|
496
|
+
# "name" => ["Mary"],
|
497
|
+
# "country" => ["USA"],
|
498
|
+
# "gender" => ["female"],
|
499
|
+
# "id" => ["0327614a-dbd8-11dd-80bd-001bfc466dd7"]}}, ... ],
|
500
|
+
# :box_usage=>"0.0000506668"}
|
501
|
+
#
|
502
|
+
# see: http://docs.amazonwebservices.com/AmazonSimpleDB/2007-11-07/DeveloperGuide/index.html?SDB_API_QueryWithAttributes.html
|
503
|
+
#
|
504
|
+
def query_with_attributes(domain_name, attributes=[], query_expression = nil, max_number_of_items = nil, next_token = nil)
|
505
|
+
attributes = attributes.to_a
|
506
|
+
query_expression = query_expression_from_array(query_expression) if query_expression.is_a?(Array)
|
507
|
+
@last_query_expression = query_expression
|
508
|
+
#
|
509
|
+
request_params = { 'DomainName' => domain_name,
|
510
|
+
'QueryExpression' => query_expression,
|
511
|
+
'MaxNumberOfItems' => max_number_of_items,
|
512
|
+
'NextToken' => next_token }
|
513
|
+
attributes.each_with_index do |attribute, idx|
|
514
|
+
request_params["AttributeName.#{idx+1}"] = attribute
|
515
|
+
end
|
516
|
+
link = generate_request("QueryWithAttributes", request_params)
|
517
|
+
result = select_response_to_ruby(request_info( link, QSdbQueryWithAttributesParser.new ))
|
518
|
+
# return result if no block given
|
519
|
+
return result unless block_given?
|
520
|
+
# loop if block if given
|
521
|
+
begin
|
522
|
+
# the block must return true if it wanna continue
|
523
|
+
break unless yield(result) && result[:next_token]
|
524
|
+
# make new request
|
525
|
+
request_params['NextToken'] = result[:next_token]
|
526
|
+
link = generate_request("QueryWithAttributes", request_params)
|
527
|
+
result = select_response_to_ruby(request_info( link, QSdbQueryWithAttributesParser.new ))
|
528
|
+
end while true
|
529
|
+
rescue Exception
|
530
|
+
on_exception
|
531
|
+
end
|
532
|
+
|
533
|
+
# Perform SQL-like select and fetch attributes.
|
534
|
+
# Attribute values must be quoted with a single or double quote. If a quote appears within the attribute value, it must be escaped with the same quote symbol as shown in the following example.
|
535
|
+
# (Use array to pass select_expression params to avoid manual escaping).
|
536
|
+
#
|
537
|
+
# sdb.select(["select * from my_domain where gender=?", 'female']) #=>
|
538
|
+
# {:request_id =>"8241b843-0fb9-4d66-9100-effae12249ec",
|
539
|
+
# :items =>
|
540
|
+
# [ { "035f1ba8-dbd8-11dd-80bd-001bfc466dd7"=>
|
541
|
+
# {"hobby" => ["cooking", "flowers", "cats"],
|
542
|
+
# "name" => ["Mary"],
|
543
|
+
# "country" => ["Russia"],
|
544
|
+
# "gender" => ["female"],
|
545
|
+
# "id" => ["035f1ba8-dbd8-11dd-80bd-001bfc466dd7"]}},
|
546
|
+
# { "0327614a-dbd8-11dd-80bd-001bfc466dd7"=>
|
547
|
+
# {"hobby" => ["patchwork", "bundle jumping"],
|
548
|
+
# "name" => ["Mary"],
|
549
|
+
# "country" => ["USA"],
|
550
|
+
# "gender" => ["female"],
|
551
|
+
# "id" => ["0327614a-dbd8-11dd-80bd-001bfc466dd7"]}}, ... ]
|
552
|
+
# :box_usage =>"0.0000506197"}
|
553
|
+
#
|
554
|
+
# sdb.select('select country, name from my_domain') #=>
|
555
|
+
# {:request_id=>"b1600198-c317-413f-a8dc-4e7f864a940a",
|
556
|
+
# :items=>
|
557
|
+
# [ { "035f1ba8-dbd8-11dd-80bd-001bfc466dd7"=> {"name"=>["Mary"], "country"=>["Russia"]} },
|
558
|
+
# { "376d2e00-75b0-11dd-9557-001bfc466dd7"=> {"name"=>["Putin"], "country"=>["Russia"]} },
|
559
|
+
# { "0327614a-dbd8-11dd-80bd-001bfc466dd7"=> {"name"=>["Mary"], "country"=>["USA"]} },
|
560
|
+
# { "372ebbd4-75b0-11dd-9557-001bfc466dd7"=> {"name"=>["Bush"], "country"=>["USA"]} },
|
561
|
+
# { "37a4e552-75b0-11dd-9557-001bfc466dd7"=> {"name"=>["Medvedev"], "country"=>["Russia"]} },
|
562
|
+
# { "38278dfe-75b0-11dd-9557-001bfc466dd7"=> {"name"=>["Mary"], "country"=>["Russia"]} },
|
563
|
+
# { "37df6c36-75b0-11dd-9557-001bfc466dd7"=> {"name"=>["Mary"], "country"=>["USA"]} } ],
|
564
|
+
# :box_usage=>"0.0000777663"}
|
565
|
+
#
|
566
|
+
# see: http://docs.amazonwebservices.com/AmazonSimpleDB/2007-11-07/DeveloperGuide/index.html?SDB_API_Select.html
|
567
|
+
# http://docs.amazonwebservices.com/AmazonSimpleDB/2007-11-07/DeveloperGuide/index.html?UsingSelect.html
|
568
|
+
# http://docs.amazonwebservices.com/AmazonSimpleDB/2007-11-07/DeveloperGuide/index.html?SDBLimits.html
|
569
|
+
#
|
570
|
+
def select(select_expression, next_token = nil)
|
571
|
+
select_expression = query_expression_from_array(select_expression) if select_expression.is_a?(Array)
|
572
|
+
@last_query_expression = select_expression
|
573
|
+
#
|
574
|
+
request_params = { 'SelectExpression' => select_expression,
|
575
|
+
'NextToken' => next_token }
|
576
|
+
link = generate_request("Select", request_params)
|
577
|
+
result = select_response_to_ruby(request_info( link, QSdbSelectParser.new ))
|
578
|
+
return result unless block_given?
|
579
|
+
# loop if block if given
|
580
|
+
begin
|
581
|
+
# the block must return true if it wanna continue
|
582
|
+
break unless yield(result) && result[:next_token]
|
583
|
+
# make new request
|
584
|
+
request_params['NextToken'] = result[:next_token]
|
585
|
+
link = generate_request("Select", request_params)
|
586
|
+
result = select_response_to_ruby(request_info( link, QSdbSelectParser.new ))
|
587
|
+
end while true
|
588
|
+
rescue Exception
|
589
|
+
on_exception
|
590
|
+
end
|
591
|
+
|
443
592
|
#-----------------------------------------------------------------
|
444
593
|
# PARSERS:
|
445
594
|
#-----------------------------------------------------------------
|
@@ -498,6 +647,52 @@ module RightAws
|
|
498
647
|
end
|
499
648
|
end
|
500
649
|
|
650
|
+
class QSdbQueryWithAttributesParser < RightAWSParser #:nodoc:
|
651
|
+
def reset
|
652
|
+
@result = { :items => [] }
|
653
|
+
end
|
654
|
+
def tagend(name)
|
655
|
+
case name
|
656
|
+
when 'Name'
|
657
|
+
case @xmlpath
|
658
|
+
when 'QueryWithAttributesResponse/QueryWithAttributesResult/Item'
|
659
|
+
@item = @text
|
660
|
+
@result[:items] << { @item => {} }
|
661
|
+
when 'QueryWithAttributesResponse/QueryWithAttributesResult/Item/Attribute'
|
662
|
+
@attribute = @text
|
663
|
+
@result[:items].last[@item][@attribute] ||= []
|
664
|
+
end
|
665
|
+
when 'RequestId' then @result[:request_id] = @text
|
666
|
+
when 'BoxUsage' then @result[:box_usage] = @text
|
667
|
+
when 'NextToken' then @result[:next_token] = @text
|
668
|
+
when 'Value' then @result[:items].last[@item][@attribute] << @text
|
669
|
+
end
|
670
|
+
end
|
671
|
+
end
|
672
|
+
|
673
|
+
class QSdbSelectParser < RightAWSParser #:nodoc:
|
674
|
+
def reset
|
675
|
+
@result = { :items => [] }
|
676
|
+
end
|
677
|
+
def tagend(name)
|
678
|
+
case name
|
679
|
+
when 'Name'
|
680
|
+
case @xmlpath
|
681
|
+
when 'SelectResponse/SelectResult/Item'
|
682
|
+
@item = @text
|
683
|
+
@result[:items] << { @item => {} }
|
684
|
+
when 'SelectResponse/SelectResult/Item/Attribute'
|
685
|
+
@attribute = @text
|
686
|
+
@result[:items].last[@item][@attribute] ||= []
|
687
|
+
end
|
688
|
+
when 'RequestId' then @result[:request_id] = @text
|
689
|
+
when 'BoxUsage' then @result[:box_usage] = @text
|
690
|
+
when 'NextToken' then @result[:next_token] = @text
|
691
|
+
when 'Value' then @result[:items].last[@item][@attribute] << @text
|
692
|
+
end
|
693
|
+
end
|
694
|
+
end
|
695
|
+
|
501
696
|
end
|
502
697
|
|
503
698
|
end
|