aws 2.3.34 → 2.4.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.
@@ -1,881 +0,0 @@
1
- #
2
- # Copyright (c) 2008 RightScale Inc
3
- #
4
- # Permission is hereby granted, free of charge, to any person obtaining
5
- # a copy of this software and associated documentation files (the
6
- # "Software"), to deal in the Software without restriction, including
7
- # without limitation the rights to use, copy, modify, merge, publish,
8
- # distribute, sublicense, and/or sell copies of the Software, and to
9
- # permit persons to whom the Software is furnished to do so, subject to
10
- # the following conditions:
11
- #
12
- # The above copyright notice and this permission notice shall be
13
- # included in all copies or substantial portions of the Software.
14
- #
15
- # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16
- # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17
- # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18
- # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
19
- # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
20
- # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
21
- # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22
- #
23
-
24
- require "aws"
25
-
26
- module Aws
27
-
28
- class SdbInterface < AwsBase
29
-
30
- include AwsBaseInterface
31
-
32
- DEFAULT_HOST = 'sdb.amazonaws.com'
33
- DEFAULT_PORT = 443
34
- DEFAULT_PROTOCOL = 'https'
35
- DEFAULT_SERVICE = '/'
36
- API_VERSION = '2009-04-15'
37
- DEFAULT_NIL_REPRESENTATION = 'nil'
38
-
39
- @@bench = AwsBenchmarkingBlock.new
40
-
41
- def self.bench_xml;
42
- @@bench.xml;
43
- end
44
-
45
- def self.bench_sdb;
46
- @@bench.service;
47
- end
48
-
49
- attr_reader :last_query_expression
50
-
51
- # Creates new RightSdb instance.
52
- #
53
- # Params:
54
- # { :server => 'sdb.amazonaws.com' # Amazon service host: 'sdb.amazonaws.com'(default)
55
- # :port => 443 # Amazon service port: 80(default) or 443
56
- # :protocol => 'https' # Amazon service protocol: 'http'(default) or 'https'
57
- # :signature_version => '2' # The signature version : '0', '1' or '2' (default)
58
- # DEPRECATED :multi_thread => true|false # Multi-threaded (connection per each thread): true or false(default)
59
- # :connection_mode => :default # options are :default (will use best known option, may change in the future)
60
- # :per_request (opens and closes a connection on every request to SDB)
61
- # :single - one connection shared across app (same as old multi_thread=>false)
62
- # :per_thread - one connection per ruby thread (same as old multi_thread=>true)
63
- # :pool (uses a connection pool with a maximum number of connections - NOT IMPLEMENTED YET)
64
- # :logger => Logger Object # Logger instance: logs to STDOUT if omitted
65
- # :nil_representation => 'mynil'} # interpret Ruby nil as this string value; i.e. use this string in SDB to represent Ruby nils (default is the string 'nil')
66
- # :service => '/' # Set this to /mdb/request.mgwsi for usage with M/DB #
67
- #
68
- # Example:
69
- #
70
- # sdb = Aws::SdbInterface.new('1E3GDYEOGFJPIT7XXXXXX','hgTHt68JY07JKUY08ftHYtERkjgtfERn57XXXXXX', {:connection_mode => :per_request, :logger => Logger.new('/tmp/x.log')}) #=> #<RightSdb:0xa6b8c27c>
71
- #
72
- # see: http://docs.amazonwebservices.com/AmazonSimpleDB/2007-11-07/DeveloperGuide/
73
- #
74
- def initialize(aws_access_key_id=nil, aws_secret_access_key=nil, params={})
75
- @nil_rep = params[:nil_representation] ? params[:nil_representation] : DEFAULT_NIL_REPRESENTATION
76
- params.delete(:nil_representation)
77
- init({:name => 'SDB',
78
- :default_host => ENV['SDB_URL'] ? URI.parse(ENV['SDB_URL']).host : DEFAULT_HOST,
79
- :default_port => ENV['SDB_URL'] ? URI.parse(ENV['SDB_URL']).port : DEFAULT_PORT,
80
- :default_protocol => ENV['SDB_URL'] ? URI.parse(ENV['SDB_URL']).scheme : DEFAULT_PROTOCOL,
81
- :default_service => ENV['SDB_URL'] ? URI.parse(ENV['SDB_URL']).path : DEFAULT_SERVICE},
82
- # :service_endpoint => ENV['SDB_URL'] ? URI.parse(ENV['SDB_URL']).path : DEFAULT_ENDPOINT },
83
- aws_access_key_id || ENV['AWS_ACCESS_KEY_ID'],
84
- aws_secret_access_key || ENV['AWS_SECRET_ACCESS_KEY'],
85
- params)
86
- end
87
-
88
- #-----------------------------------------------------------------
89
- # Requests
90
- #-----------------------------------------------------------------
91
- def generate_request(action, params={}, options={}) #:nodoc:
92
- generate_request2(@aws_access_key_id, @aws_secret_access_key, action, API_VERSION, @params, params, options)
93
- end
94
-
95
-
96
- # Sends request to Amazon and parses the response
97
- # Raises AwsError if any banana happened
98
- def request_info(request, parser, options={}) #:nodoc:
99
- # request_info2(request, parser, :sdb_connection)
100
- request_info2(request, parser, @params, :sdb_connection, @logger, @@bench, options)
101
-
102
- end
103
-
104
- def close_connection
105
- close_conn(:sdb_connection)
106
- end
107
-
108
- # Prepare attributes for putting.
109
- # (used by put_attributes)
110
- def pack_attributes(attributes, replace = false, key_prefix = "") #:nodoc:
111
- result = {}
112
- if attributes
113
- idx = 0
114
- skip_values = attributes.is_a?(Array)
115
- attributes.each do |attribute, values|
116
- # set replacement attribute
117
- result["#{key_prefix}Attribute.#{idx}.Replace"] = 'true' if replace
118
- # pack Name/Value
119
- unless values.nil?
120
- Array(values).each do |value|
121
- result["#{key_prefix}Attribute.#{idx}.Name"] = attribute
122
- result["#{key_prefix}Attribute.#{idx}.Value"] = ruby_to_sdb(value) unless skip_values
123
- idx += 1
124
- end
125
- else
126
- result["#{key_prefix}Attribute.#{idx}.Name"] = attribute
127
- result["#{key_prefix}Attribute.#{idx}.Value"] = ruby_to_sdb(nil) unless skip_values
128
- idx += 1
129
- end
130
- end
131
- end
132
- result
133
- end
134
-
135
-
136
- # Use this helper to manually escape the fields in the query expressions.
137
- # To escape the single quotes and backslashes and to wrap the string into the single quotes.
138
- #
139
- # see: http://docs.amazonwebservices.com/AmazonSimpleDB/2007-11-07/DeveloperGuide/SDB_API.html
140
- #
141
- def escape(value)
142
- %Q{'#{value.to_s.gsub(/(['\\])/) { "\\#{$1}" }}'} if value
143
- end
144
-
145
- # Convert a Ruby language value to a SDB value by replacing Ruby nil with the user's chosen string representation of nil.
146
- # Non-nil values are unaffected by this filter.
147
- def ruby_to_sdb(value)
148
- # puts "value #{value} is frozen? #{value.frozen?}"
149
- # value.nil? ? @nil_rep : ((value.frozen? || !value.is_a?(String)) ? value : value.force_encoding("UTF-8"))
150
- value.nil? ? @nil_rep : value
151
- end
152
-
153
- # Convert a SDB value to a Ruby language value by replacing the user's chosen string representation of nil with Ruby nil.
154
- # Values are unaffected by this filter unless they match the nil representation exactly.
155
- def sdb_to_ruby(value)
156
- value.eql?(@nil_rep) ? nil : value
157
- end
158
-
159
- # 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.
160
- # (This method affects on a passed response value)
161
- def select_response_to_ruby(response) #:nodoc:
162
- response[:items].each_with_index do |item, idx|
163
- item.each do |key, attributes|
164
- attributes.each do |name, values|
165
- values.collect! { |value| sdb_to_ruby(value) }
166
- end
167
- end
168
- end
169
- response
170
- end
171
-
172
- # Create query expression from an array.
173
- # (similar to ActiveRecord::Base#find using :conditions => ['query', param1, .., paramN])
174
- #
175
- def query_expression_from_array(params) #:nodoc:
176
- return '' if params.blank?
177
- query = params[0].to_s
178
- i = 1
179
- query.gsub(/(\\)?(\?)/) do
180
- if $1 # if escaped '\?' is found - replace it by '?' without backslash
181
- "?"
182
- else # well, if no backslash precedes '?' then replace it by next param from the list
183
- ret = escape(params[i])
184
- i +=1
185
- ret
186
- end
187
- end
188
- end
189
-
190
- def query_expression_from_hash(hash)
191
- return '' if hash.blank?
192
- expression = []
193
- hash.each do |key, value|
194
- expression << "#{key}=#{escape(value)}"
195
- end
196
- expression.join(' AND ')
197
- end
198
-
199
- # Retrieve a list of SDB domains from Amazon.
200
- #
201
- # Returns a hash:
202
- # { :domains => [domain1, ..., domainN],
203
- # :next_token => string || nil,
204
- # :box_usage => string,
205
- # :request_id => string }
206
- #
207
- # Example:
208
- #
209
- # sdb = Aws::SdbInterface.new
210
- # sdb.list_domains #=> { :box_usage => "0.0000071759",
211
- # :request_id => "976709f9-0111-2345-92cb-9ce90acd0982",
212
- # :domains => ["toys", "dolls"]}
213
- #
214
- # If a block is given, this method yields to it. If the block returns true, list_domains will continue looping the request. If the block returns false,
215
- # list_domains will end.
216
- #
217
- # sdb.list_domains(10) do |result| # list by 10 domains per iteration
218
- # puts result.inspect
219
- # true
220
- # end
221
- #
222
- # see: http://docs.amazonwebservices.com/AmazonSimpleDB/2007-11-07/DeveloperGuide/SDB_API_ListDomains.html
223
- #
224
- def list_domains(max_number_of_domains = nil, next_token = nil)
225
- request_params = {'MaxNumberOfDomains' => max_number_of_domains,
226
- 'NextToken' => next_token}
227
- link = generate_request("ListDomains", request_params)
228
- result = request_info(link, QSdbListDomainParser.new)
229
- # return result if no block given
230
- return result unless block_given?
231
- # loop if block if given
232
- begin
233
- # the block must return true if it wanna continue
234
- break unless yield(result) && result[:next_token]
235
- # make new request
236
- request_params['NextToken'] = result[:next_token]
237
- link = generate_request("ListDomains", request_params)
238
- result = request_info(link, QSdbListDomainParser.new)
239
- end while true
240
- rescue Exception
241
- on_exception
242
- end
243
-
244
- # Retrieve a list of SDB domains from Amazon.
245
- #
246
- # Returns a hash:
247
- # { :domains => [domain1, ..., domainN],
248
- # :next_token => string || nil,
249
- # :box_usage => string,
250
- # :request_id => string }
251
- #
252
- # Example:
253
- #
254
- # sdb = Aws::SdbInterface.new
255
- # sdb.list_domains #=> { :box_usage => "0.0000071759",
256
- # :request_id => "976709f9-0111-2345-92cb-9ce90acd0982",
257
- # :domains => ["toys", "dolls"]}
258
- #
259
- # If a block is given, this method yields to it. If the block returns true, list_domains will continue looping the request. If the block returns false,
260
- # list_domains will end.
261
- #
262
- # sdb.list_domains(10) do |result| # list by 10 domains per iteration
263
- # puts result.inspect
264
- # true
265
- # end
266
- #
267
- # see: http://docs.amazonwebservices.com/AmazonSimpleDB/2007-11-07/DeveloperGuide/SDB_API_ListDomains.html
268
- #
269
- def domain_metadata(domain_name)
270
- link = generate_request("DomainMetadata", 'DomainName' => domain_name)
271
- result = request_info(link, QSdbDomainMetadataParser.new)
272
- return result
273
- rescue Exception
274
- on_exception
275
- end
276
-
277
-
278
- # Create new SDB domain at Amazon.
279
- #
280
- # Returns a hash: { :box_usage, :request_id } on success or an exception on error.
281
- # (Amazon raises no errors if the domain already exists).
282
- #
283
- # Example:
284
- #
285
- # sdb = Aws::SdbInterface.new
286
- # sdb.create_domain('toys') # => { :box_usage => "0.0000071759",
287
- # :request_id => "976709f9-0111-2345-92cb-9ce90acd0982" }
288
- #
289
- # see: http://docs.amazonwebservices.com/AmazonSimpleDB/2007-11-07/DeveloperGuide/SDB_API_CreateDomain.html
290
- def create_domain(domain_name)
291
- link = generate_request("CreateDomain",
292
- 'DomainName' => domain_name)
293
- request_info(link, QSdbSimpleParser.new)
294
- rescue Exception
295
- on_exception
296
- end
297
-
298
- # Delete SDB domain at Amazon.
299
- #
300
- # Returns a hash: { :box_usage, :request_id } on success or an exception on error.
301
- # (Amazon raises no errors if the domain does not exist).
302
- #
303
- # Example:
304
- #
305
- # sdb = Aws::SdbInterface.new
306
- # sdb.delete_domain('toys') # => { :box_usage => "0.0000071759",
307
- # :request_id => "976709f9-0111-2345-92cb-9ce90acd0982" }
308
- #
309
- # see: http://docs.amazonwebservices.com/AmazonSimpleDB/2007-11-07/DeveloperGuide/SDB_API_DeleteDomain.html
310
- #
311
- def delete_domain(domain_name)
312
- link = generate_request("DeleteDomain",
313
- 'DomainName' => domain_name)
314
- request_info(link, QSdbSimpleParser.new)
315
- rescue Exception
316
- on_exception
317
- end
318
-
319
- # Add/Replace item attributes.
320
- #
321
- # Params:
322
- # domain_name = DomainName
323
- # item_name = ItemName
324
- # attributes = {
325
- # 'nameA' => [valueA1,..., valueAN],
326
- # ...
327
- # 'nameZ' => [valueZ1,..., valueZN]
328
- # }
329
- # replace = :replace | any other value to skip replacement
330
- # options:
331
- # :create_domain => If true and domain does not exist, it will be created. Default is false.
332
- #
333
- # Returns a hash: { :box_usage, :request_id } on success or an exception on error.
334
- # (Amazon raises no errors if the attribute was not overridden, as when the :replace param is unset).
335
- #
336
- # Example:
337
- #
338
- # sdb = Aws::SdbInterface.new
339
- # sdb.create_domain 'family'
340
- #
341
- # attributes = {}
342
- # # create attributes for Jon and Silvia
343
- # attributes['Jon'] = %w{ car beer }
344
- # attributes['Silvia'] = %w{ beetle rolling_pin kids }
345
- # sdb.put_attributes 'family', 'toys', attributes #=> ok
346
- # # now: Jon=>[car, beer], Silvia=>[beetle, rolling_pin, kids]
347
- #
348
- # # add attributes to Jon
349
- # attributes.delete('Silvia')
350
- # attributes['Jon'] = %w{ girls pub }
351
- # sdb.put_attributes 'family', 'toys', attributes #=> ok
352
- # # now: Jon=>[car, beer, girls, pub], Silvia=>[beetle, rolling_pin, kids]
353
- #
354
- # # replace attributes for Jon and add to a cat (the cat had no attributes before)
355
- # attributes['Jon'] = %w{ vacuum_cleaner hammer spade }
356
- # attributes['cat'] = %w{ mouse clew Jons_socks }
357
- # sdb.put_attributes 'family', 'toys', attributes, :replace #=> ok
358
- # # now: Jon=>[vacuum_cleaner, hammer, spade], Silvia=>[beetle, rolling_pin, kids], cat=>[mouse, clew, Jons_socks]
359
- #
360
- # see: http://docs.amazonwebservices.com/AmazonSimpleDB/2007-11-07/DeveloperGuide/SDB_API_PutAttributes.html
361
- #
362
- def put_attributes(domain_name, item_name, attributes, replace = false, options={})
363
- params = {'DomainName' => domain_name,
364
- 'ItemName' => item_name}.merge(pack_attributes(attributes, replace))
365
- logger.debug 'PUT=' + params.inspect
366
- link = generate_request("PutAttributes", params)
367
- begin
368
- request_info(link, QSdbSimpleParser.new, options)
369
- rescue Aws::AwsError => ex
370
- # puts "RESCUED in put_attributes: " + $!
371
- if options[:create_domain] && create_domain_if_not_exist(ex, domain_name)
372
- options.delete(:create_domain)
373
- put_attributes(domain_name, item_name, attributes, replace, options)
374
- else
375
- raise ex
376
- end
377
- end
378
- rescue Exception
379
- on_exception
380
- end
381
-
382
- def create_domain_if_not_exist(ex, domain_name)
383
- if ex.message().index("NoSuchDomain")
384
- create_domain(domain_name)
385
- return true
386
- end
387
- return false
388
- end
389
-
390
- #
391
- # items is an array of Aws::SdbInterface::Item.new(o.id, o.attributes, true)
392
- def batch_put_attributes(domain_name, items, options={})
393
- params = {'DomainName' => domain_name}
394
- i = 0
395
- items.each do |item|
396
- prefix = "Item." + i.to_s + "."
397
- params[prefix + "ItemName"] = item.item_name
398
- params.merge!(pack_attributes(item.attributes, item.replace, prefix))
399
- i += 1
400
- end
401
- link = generate_request("BatchPutAttributes", params)
402
- begin
403
- request_info(link, QSdbSimpleParser.new, options)
404
- rescue Aws::AwsError => ex
405
- # puts "RESCUED in batch_put_attributes: " + $!
406
- if options[:create_domain] && create_domain_if_not_exist(ex, domain_name)
407
- options.delete(:create_domain)
408
- batch_put_attributes(domain_name, items, options)
409
- else
410
- raise ex
411
- end
412
- end
413
- rescue Exception
414
- on_exception
415
- end
416
-
417
- #
418
- # items is an array item_name's or Aws::SdbInterface::Item.new(o.id, o.attributes, true)
419
- def batch_delete_attributes(domain_name, items)
420
- params = {'DomainName' => domain_name}
421
- i = 0
422
- items.each do |item|
423
- prefix = "Item." + i.to_s + "."
424
- if item.is_a?(String)
425
- params[prefix + "ItemName"] = item
426
- else
427
- params[prefix + "ItemName"] = item.item_name
428
- params.merge!(pack_attributes(item.attributes, item.replace, prefix))
429
- end
430
- i += 1
431
- end
432
- link = generate_request("BatchDeleteAttributes", params)
433
- request_info(link, QSdbSimpleParser.new)
434
- rescue Exception
435
- on_exception
436
- end
437
-
438
- # Retrieve SDB item's attribute(s).
439
- #
440
- # Returns a hash:
441
- # { :box_usage => string,
442
- # :request_id => string,
443
- # :attributes => { 'nameA' => [valueA1,..., valueAN],
444
- # ... ,
445
- # 'nameZ' => [valueZ1,..., valueZN] } }
446
- #
447
- # Example:
448
- # # request all attributes
449
- # sdb.get_attributes('family', 'toys') # => { :attributes => {"cat" => ["clew", "Jons_socks", "mouse"] },
450
- # "Silvia" => ["beetle", "rolling_pin", "kids"],
451
- # "Jon" => ["vacuum_cleaner", "hammer", "spade"]},
452
- # :box_usage => "0.0000093222",
453
- # :request_id => "81273d21-000-1111-b3f9-512d91d29ac8" }
454
- #
455
- # # request cat's attributes only
456
- # sdb.get_attributes('family', 'toys', 'cat') # => { :attributes => {"cat" => ["clew", "Jons_socks", "mouse"] },
457
- # :box_usage => "0.0000093222",
458
- # :request_id => "81273d21-001-1111-b3f9-512d91d29ac8" }
459
- #
460
- # see: http://docs.amazonwebservices.com/AmazonSimpleDB/2007-11-07/DeveloperGuide/SDB_API_GetAttributes.html
461
- #
462
- def get_attributes(domain_name, item_name, attribute_name=nil, consistent_read = nil)
463
- link = generate_request("GetAttributes", 'DomainName' => domain_name,
464
- 'ItemName' => item_name,
465
- 'AttributeName' => attribute_name,
466
- 'ConsistentRead' => consistent_read)
467
- res = request_info(link, QSdbGetAttributesParser.new)
468
- res[:attributes].each_value do |values|
469
- values.collect! { |e| sdb_to_ruby(e) }
470
- end
471
- res
472
- rescue Exception
473
- on_exception
474
- end
475
-
476
- # Delete value, attribute or item.
477
- #
478
- # Example:
479
- # # delete 'vodka' and 'girls' from 'Jon' and 'mice' from 'cat'.
480
- # sdb.delete_attributes 'family', 'toys', { 'Jon' => ['vodka', 'girls'], 'cat' => ['mice'] }
481
- #
482
- # # delete the all the values from attributes (i.e. delete the attributes)
483
- # sdb.delete_attributes 'family', 'toys', { 'Jon' => [], 'cat' => [] }
484
- # # or
485
- # sdb.delete_attributes 'family', 'toys', [ 'Jon', 'cat' ]
486
- #
487
- # # delete all the attributes from item 'toys' (i.e. delete the item)
488
- # sdb.delete_attributes 'family', 'toys'
489
- #
490
- # see http://docs.amazonwebservices.com/AmazonSimpleDB/2007-11-07/DeveloperGuide/SDB_API_DeleteAttributes.html
491
- #
492
- def delete_attributes(domain_name, item_name, attributes = nil)
493
- params = {'DomainName' => domain_name,
494
- 'ItemName' => item_name}.merge(pack_attributes(attributes))
495
- link = generate_request("DeleteAttributes", params)
496
- request_info(link, QSdbSimpleParser.new)
497
- rescue Exception
498
- on_exception
499
- end
500
-
501
-
502
- # QUERY:
503
-
504
- # Perform a query on SDB.
505
- #
506
- # Returns a hash:
507
- # { :box_usage => string,
508
- # :request_id => string,
509
- # :next_token => string,
510
- # :items => [ItemName1,..., ItemNameN] }
511
- #
512
- # Example:
513
- #
514
- # query = "['cat' = 'clew']"
515
- # sdb.query('family', query) #=> hash of data
516
- # sdb.query('family', query, 10) #=> hash of data with max of 10 items
517
- #
518
- # If a block is given, query will iteratively yield results to it as long as the block continues to return true.
519
- #
520
- # # List 10 items per iteration. Don't
521
- # # forget to escape single quotes and backslashes and wrap all the items in single quotes.
522
- # query = "['cat'='clew'] union ['dog'='Jon\\'s boot']"
523
- # sdb.query('family', query, 10) do |result|
524
- # puts result.inspect
525
- # true
526
- # end
527
- #
528
- # # Same query using automatic escaping...to use the auto escape, pass the query and its params as an array:
529
- # query = [ "['cat'=?] union ['dog'=?]", "clew", "Jon's boot" ]
530
- # sdb.query('family', query)
531
- #
532
- # query = [ "['cat'=?] union ['dog'=?] sort 'cat' desc", "clew", "Jon's boot" ]
533
- # sdb.query('family', query)
534
- #
535
- # see: http://docs.amazonwebservices.com/AmazonSimpleDB/2007-11-07/DeveloperGuide/SDB_API_Query.html
536
- # http://docs.amazonwebservices.com/AmazonSimpleDB/2007-11-07/DeveloperGuide/index.html?SortingData.html
537
- #
538
- def query(domain_name, query_expression = nil, max_number_of_items = nil, next_token = nil, consistent_read = nil)
539
- query_expression = query_expression_from_array(query_expression) if query_expression.is_a?(Array)
540
- @last_query_expression = query_expression
541
- #
542
- request_params = {'DomainName' => domain_name,
543
- 'QueryExpression' => query_expression,
544
- 'MaxNumberOfItems' => max_number_of_items,
545
- 'NextToken' => next_token,
546
- 'ConsistentRead' => consistent_read}
547
- link = generate_request("Query", request_params)
548
- result = request_info(link, QSdbQueryParser.new)
549
- # return result if no block given
550
- return result unless block_given?
551
- # loop if block if given
552
- begin
553
- # the block must return true if it wanna continue
554
- break unless yield(result) && result[:next_token]
555
- # make new request
556
- request_params['NextToken'] = result[:next_token]
557
- link = generate_request("Query", request_params)
558
- result = request_info(link, QSdbQueryParser.new)
559
- end while true
560
- rescue Exception
561
- on_exception
562
- end
563
-
564
- # Perform a query and fetch specified attributes.
565
- # If attributes are not specified then fetches the whole list of attributes.
566
- #
567
- #
568
- # Returns a hash:
569
- # { :box_usage => string,
570
- # :request_id => string,
571
- # :next_token => string,
572
- # :items => [ { ItemName1 => { attribute1 => value1, ... attributeM => valueM } },
573
- # { ItemName2 => {...}}, ... ]
574
- #
575
- # Example:
576
- #
577
- # sdb.query_with_attributes(domain, ['hobby', 'country'], "['gender'='female'] intersection ['name' starts-with ''] sort 'name'") #=>
578
- # { :request_id => "06057228-70d0-4487-89fb-fd9c028580d3",
579
- # :items =>
580
- # [ { "035f1ba8-dbd8-11dd-80bd-001bfc466dd7"=>
581
- # { "hobby" => ["cooking", "flowers", "cats"],
582
- # "country" => ["Russia"]}},
583
- # { "0327614a-dbd8-11dd-80bd-001bfc466dd7"=>
584
- # { "hobby" => ["patchwork", "bundle jumping"],
585
- # "country" => ["USA"]}}, ... ],
586
- # :box_usage=>"0.0000504786"}
587
- #
588
- # sdb.query_with_attributes(domain, [], "['gender'='female'] intersection ['name' starts-with ''] sort 'name'") #=>
589
- # { :request_id => "75bb19db-a529-4f69-b86f-5e3800f79a45",
590
- # :items =>
591
- # [ { "035f1ba8-dbd8-11dd-80bd-001bfc466dd7"=>
592
- # { "hobby" => ["cooking", "flowers", "cats"],
593
- # "name" => ["Mary"],
594
- # "country" => ["Russia"],
595
- # "gender" => ["female"],
596
- # "id" => ["035f1ba8-dbd8-11dd-80bd-001bfc466dd7"]}},
597
- # { "0327614a-dbd8-11dd-80bd-001bfc466dd7"=>
598
- # { "hobby" => ["patchwork", "bundle jumping"],
599
- # "name" => ["Mary"],
600
- # "country" => ["USA"],
601
- # "gender" => ["female"],
602
- # "id" => ["0327614a-dbd8-11dd-80bd-001bfc466dd7"]}}, ... ],
603
- # :box_usage=>"0.0000506668"}
604
- #
605
- # see: http://docs.amazonwebservices.com/AmazonSimpleDB/2007-11-07/DeveloperGuide/index.html?SDB_API_QueryWithAttributes.html
606
- #
607
- def query_with_attributes(domain_name, attributes=[], query_expression = nil, max_number_of_items = nil, next_token = nil, consistent_read = nil)
608
- attributes = attributes.to_a
609
- query_expression = query_expression_from_array(query_expression) if query_expression.is_a?(Array)
610
- @last_query_expression = query_expression
611
- #
612
- request_params = {'DomainName' => domain_name,
613
- 'QueryExpression' => query_expression,
614
- 'MaxNumberOfItems' => max_number_of_items,
615
- 'NextToken' => next_token,
616
- 'ConsistentRead' => consistent_read}
617
- attributes.each_with_index do |attribute, idx|
618
- request_params["AttributeName.#{idx+1}"] = attribute
619
- end
620
- link = generate_request("QueryWithAttributes", request_params)
621
- result = select_response_to_ruby(request_info(link, QSdbQueryWithAttributesParser.new))
622
- # return result if no block given
623
- return result unless block_given?
624
- # loop if block if given
625
- begin
626
- # the block must return true if it wanna continue
627
- break unless yield(result) && result[:next_token]
628
- # make new request
629
- request_params['NextToken'] = result[:next_token]
630
- link = generate_request("QueryWithAttributes", request_params)
631
- result = select_response_to_ruby(request_info(link, QSdbQueryWithAttributesParser.new))
632
- end while true
633
- rescue Exception
634
- on_exception
635
- end
636
-
637
- # Perform SQL-like select and fetch attributes.
638
- # 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.
639
- # (Use array to pass select_expression params to avoid manual escaping).
640
- #
641
- # sdb.select(["select * from my_domain where gender=?", 'female']) #=>
642
- # {:request_id =>"8241b843-0fb9-4d66-9100-effae12249ec",
643
- # :items =>
644
- # [ { "035f1ba8-dbd8-11dd-80bd-001bfc466dd7"=>
645
- # {"hobby" => ["cooking", "flowers", "cats"],
646
- # "name" => ["Mary"],
647
- # "country" => ["Russia"],
648
- # "gender" => ["female"],
649
- # "id" => ["035f1ba8-dbd8-11dd-80bd-001bfc466dd7"]}},
650
- # { "0327614a-dbd8-11dd-80bd-001bfc466dd7"=>
651
- # {"hobby" => ["patchwork", "bundle jumping"],
652
- # "name" => ["Mary"],
653
- # "country" => ["USA"],
654
- # "gender" => ["female"],
655
- # "id" => ["0327614a-dbd8-11dd-80bd-001bfc466dd7"]}}, ... ]
656
- # :box_usage =>"0.0000506197"}
657
- #
658
- # sdb.select('select country, name from my_domain') #=>
659
- # {:request_id=>"b1600198-c317-413f-a8dc-4e7f864a940a",
660
- # :items=>
661
- # [ { "035f1ba8-dbd8-11dd-80bd-001bfc466dd7"=> {"name"=>["Mary"], "country"=>["Russia"]} },
662
- # { "376d2e00-75b0-11dd-9557-001bfc466dd7"=> {"name"=>["Putin"], "country"=>["Russia"]} },
663
- # { "0327614a-dbd8-11dd-80bd-001bfc466dd7"=> {"name"=>["Mary"], "country"=>["USA"]} },
664
- # { "372ebbd4-75b0-11dd-9557-001bfc466dd7"=> {"name"=>["Bush"], "country"=>["USA"]} },
665
- # { "37a4e552-75b0-11dd-9557-001bfc466dd7"=> {"name"=>["Medvedev"], "country"=>["Russia"]} },
666
- # { "38278dfe-75b0-11dd-9557-001bfc466dd7"=> {"name"=>["Mary"], "country"=>["Russia"]} },
667
- # { "37df6c36-75b0-11dd-9557-001bfc466dd7"=> {"name"=>["Mary"], "country"=>["USA"]} } ],
668
- # :box_usage=>"0.0000777663"}
669
- #
670
- # options:
671
- # :next_token
672
- # :consistent_read
673
- # :retries => maximum number of times to retry this query on an error response.
674
- #
675
- # see: http://docs.amazonwebservices.com/AmazonSimpleDB/2007-11-07/DeveloperGuide/index.html?SDB_API_Select.html
676
- # http://docs.amazonwebservices.com/AmazonSimpleDB/2007-11-07/DeveloperGuide/index.html?UsingSelect.html
677
- # http://docs.amazonwebservices.com/AmazonSimpleDB/2007-11-07/DeveloperGuide/index.html?SDBLimits.html
678
- #
679
- def select(select_expression, next_token = nil, consistent_read = nil)
680
- select_expression = query_expression_from_array(select_expression) if select_expression.is_a?(Array)
681
- @last_query_expression = select_expression
682
-
683
- options = {}
684
- if next_token.is_a?(Hash)
685
- options = next_token
686
- next_token = options[:next_token]
687
- consistent_read = options[:consistent_read]
688
- end
689
-
690
- #
691
- request_params = {'SelectExpression' => select_expression,
692
- 'NextToken' => next_token,
693
- 'ConsistentRead' => consistent_read}
694
- link = generate_request("Select", request_params, options)
695
- result = select_response_to_ruby(request_info(link, QSdbSelectParser.new, options))
696
- return result unless block_given?
697
- # loop if block if given
698
- begin
699
- # the block must return true if it wanna continue
700
- break unless yield(result) && result[:next_token]
701
- # make new request
702
- request_params['NextToken'] = result[:next_token]
703
- link = generate_request("Select", request_params)
704
- result = select_response_to_ruby(request_info(link, QSdbSelectParser.new, options))
705
- end while true
706
- rescue Exception
707
- on_exception
708
- end
709
-
710
- class Item
711
- attr_accessor :item_name, :attributes, :replace
712
-
713
- def initialize(item_name, attributes, replace = false)
714
- @item_name = item_name
715
- @attributes = attributes
716
- @replace = replace
717
- end
718
- end
719
-
720
- #-----------------------------------------------------------------
721
- # PARSERS:
722
- #-----------------------------------------------------------------
723
- class QSdbListDomainParser < AwsParser #:nodoc:
724
- def reset
725
- @result = {:domains => []}
726
- end
727
-
728
- def tagend(name)
729
- case name
730
- when 'NextToken' then
731
- @result[:next_token] = @text
732
- when 'DomainName' then
733
- @result[:domains] << @text
734
- when 'BoxUsage' then
735
- @result[:box_usage] = @text
736
- when 'RequestId' then
737
- @result[:request_id] = @text
738
- end
739
- end
740
- end
741
-
742
- class QSdbDomainMetadataParser < AwsParser #:nodoc:
743
- def reset
744
- @result = {}
745
- end
746
-
747
- def tagend(name)
748
- case name
749
- when 'Timestamp' then
750
- @result[:timestamp] = @text
751
- when 'ItemCount' then
752
- @result[:item_count] = @text.to_i
753
- when 'AttributeValueCount' then
754
- @result[:attribute_value_count] = @text.to_i
755
- when 'AttributeNameCount' then
756
- @result[:attribute_name_acount] = @text.to_i
757
- when 'ItemNamesSizeBytes' then
758
- @result[:item_names_size_bytes] = @text.to_i
759
- when 'AttributeValuesSizeBytes' then
760
- @result[:attributes_values_size_bytes] = @text.to_i
761
- when 'AttributeNamesSizeBytes' then
762
- @result[:attributes_names_size_bytes] = @text.to_i
763
-
764
- end
765
- end
766
- end
767
-
768
-
769
- class QSdbSimpleParser < AwsParser #:nodoc:
770
- def reset
771
- @result = {}
772
- end
773
-
774
- def tagend(name)
775
- case name
776
- when 'BoxUsage' then
777
- @result[:box_usage] = @text
778
- when 'RequestId' then
779
- @result[:request_id] = @text
780
- end
781
- end
782
- end
783
-
784
- class QSdbGetAttributesParser < AwsParser #:nodoc:
785
- def reset
786
- @last_attribute_name = nil
787
- @result = {:attributes => {}}
788
- end
789
-
790
- def tagend(name)
791
- case name
792
- when 'Name' then
793
- @last_attribute_name = @text
794
- when 'Value' then
795
- (@result[:attributes][@last_attribute_name] ||= []) << @text
796
- when 'BoxUsage' then
797
- @result[:box_usage] = @text
798
- when 'RequestId' then
799
- @result[:request_id] = @text
800
- end
801
- end
802
- end
803
-
804
- class QSdbQueryParser < AwsParser #:nodoc:
805
- def reset
806
- @result = {:items => []}
807
- end
808
-
809
- def tagend(name)
810
- case name
811
- when 'ItemName' then
812
- @result[:items] << @text
813
- when 'BoxUsage' then
814
- @result[:box_usage] = @text
815
- when 'RequestId' then
816
- @result[:request_id] = @text
817
- when 'NextToken' then
818
- @result[:next_token] = @text
819
- end
820
- end
821
- end
822
-
823
- class QSdbQueryWithAttributesParser < AwsParser #:nodoc:
824
- def reset
825
- @result = {:items => []}
826
- end
827
-
828
- def tagend(name)
829
- case name
830
- when 'Name'
831
- case @xmlpath
832
- when 'QueryWithAttributesResponse/QueryWithAttributesResult/Item'
833
- @item = @text
834
- @result[:items] << {@item => {}}
835
- when 'QueryWithAttributesResponse/QueryWithAttributesResult/Item/Attribute'
836
- @attribute = @text
837
- @result[:items].last[@item][@attribute] ||= []
838
- end
839
- when 'RequestId' then
840
- @result[:request_id] = @text
841
- when 'BoxUsage' then
842
- @result[:box_usage] = @text
843
- when 'NextToken' then
844
- @result[:next_token] = @text
845
- when 'Value' then
846
- @result[:items].last[@item][@attribute] << @text
847
- end
848
- end
849
- end
850
-
851
- class QSdbSelectParser < AwsParser #:nodoc:
852
- def reset
853
- @result = {:items => []}
854
- end
855
-
856
- def tagend(name)
857
- case name
858
- when 'Name'
859
- case @xmlpath
860
- when 'SelectResponse/SelectResult/Item'
861
- @item = @text
862
- @result[:items] << {@item => {}}
863
- when 'SelectResponse/SelectResult/Item/Attribute'
864
- @attribute = @text
865
- @result[:items].last[@item][@attribute] ||= []
866
- end
867
- when 'RequestId' then
868
- @result[:request_id] = @text
869
- when 'BoxUsage' then
870
- @result[:box_usage] = @text
871
- when 'NextToken' then
872
- @result[:next_token] = @text
873
- when 'Value' then
874
- @result[:items].last[@item][@attribute] << @text
875
- end
876
- end
877
- end
878
-
879
- end
880
-
881
- end