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.
@@ -24,7 +24,7 @@
24
24
  begin
25
25
  require 'uuidtools'
26
26
  rescue LoadError => e
27
- STDERR.puts("RightSDB Alpha requires the uuidtools gem. Run \'gem install uuidtools\' and try again.")
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
- new_item.reload if options[:auto_load]
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.reload }
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
- if options[:conditions].is_a?(Array)
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
- options[:auto_load] ? reload_all_records(result.first).first : result.first
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
- if method.to_s[/^find_all_by_/]
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
- end
441
-
442
- def self.generate_id # :nodoc:
443
- UUID.timestamp_create().to_s
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 { |attribute, values| @attributes[attribute] -= values }
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
- service_hash = {"Action" => action,
82
- "AWSAccessKeyId" => @aws_access_key_id,
83
- "Version" => API_VERSION,
84
- "Timestamp" => Time.now.utc.strftime("%Y-%m-%dT%H:%M:%S.000Z"),
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
- # prepare string to sight
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 service_string.size > 2000
98
- request = Net::HTTP::Post.new("/")
99
- request.body = service_string
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
- #params_string = "&#{params_string}" unless params_string.blank?
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
- unless params.blank?
172
- query = params.shift.to_s
173
- query.gsub(/(\\)?(\?)/) do
174
- if $1 # if escaped '\?' is found - replace it by '?' without backslash
175
- "?"
176
- else # well, if no backslash precedes '?' then replace it by next param from the list
177
- escape(params.shift)
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