right_aws-yodal 1.10.7 → 1.10.10

Sign up to get free protection for your applications and to get access to all the features.
Files changed (49) hide show
  1. data/History.txt +46 -1
  2. data/Manifest.txt +4 -0
  3. data/README.txt +0 -0
  4. data/Rakefile +0 -0
  5. data/lib/acf/right_acf_interface.rb +105 -33
  6. data/lib/acf/right_acf_origin_access_identities.rb +230 -0
  7. data/lib/acf/right_acf_streaming_interface.rb +236 -0
  8. data/lib/acw/right_acw_interface.rb +3 -3
  9. data/lib/as/right_as_interface.rb +55 -46
  10. data/lib/awsbase/benchmark_fix.rb +0 -0
  11. data/lib/awsbase/right_awsbase.rb +71 -12
  12. data/lib/awsbase/support.rb +0 -0
  13. data/lib/ec2/right_ec2.rb +22 -244
  14. data/lib/ec2/right_ec2_ebs.rb +23 -22
  15. data/lib/ec2/right_ec2_images.rb +21 -21
  16. data/lib/ec2/right_ec2_instances.rb +49 -54
  17. data/lib/ec2/right_ec2_reserved_instances.rb +7 -4
  18. data/lib/ec2/right_ec2_security_groups.rb +277 -0
  19. data/lib/ec2/right_ec2_spot_instances.rb +399 -0
  20. data/lib/ec2/right_ec2_vpc.rb +4 -4
  21. data/lib/elb/right_elb_interface.rb +112 -23
  22. data/lib/rds/right_rds_interface.rb +4 -4
  23. data/lib/right_aws.rb +8 -4
  24. data/lib/s3/right_s3.rb +25 -1
  25. data/lib/s3/right_s3_interface.rb +6 -2
  26. data/lib/sdb/active_sdb.rb +202 -10
  27. data/lib/sdb/right_sdb_interface.rb +61 -11
  28. data/lib/sqs/right_sqs.rb +0 -0
  29. data/lib/sqs/right_sqs_gen2.rb +0 -0
  30. data/lib/sqs/right_sqs_gen2_interface.rb +5 -4
  31. data/lib/sqs/right_sqs_interface.rb +0 -0
  32. data/test/acf/test_helper.rb +0 -0
  33. data/test/acf/test_right_acf.rb +10 -18
  34. data/test/ec2/test_helper.rb +0 -0
  35. data/test/ec2/test_right_ec2.rb +0 -0
  36. data/test/http_connection.rb +0 -0
  37. data/test/s3/test_helper.rb +0 -0
  38. data/test/s3/test_right_s3.rb +10 -8
  39. data/test/s3/test_right_s3_stubbed.rb +6 -4
  40. data/test/sdb/test_active_sdb.rb +70 -12
  41. data/test/sdb/test_batch_put_attributes.rb +54 -0
  42. data/test/sdb/test_helper.rb +0 -0
  43. data/test/sdb/test_right_sdb.rb +13 -7
  44. data/test/sqs/test_helper.rb +0 -0
  45. data/test/sqs/test_right_sqs.rb +0 -0
  46. data/test/sqs/test_right_sqs_gen2.rb +21 -33
  47. data/test/test_credentials.rb +0 -0
  48. data/test/ts_right_aws.rb +0 -0
  49. metadata +16 -4
@@ -316,8 +316,8 @@ module RightAws
316
316
  # rds.describe_db_security_groups('kd3')
317
317
  #
318
318
  def describe_db_security_groups(*db_security_group_name, &block)
319
- item, params = AwsUtils::split_items_and_params(db_security_group_name)
320
- params['DBSecurityGroupName'] = item if item
319
+ items, params = AwsUtils::split_items_and_params(db_security_group_name)
320
+ params['DBSecurityGroupName'] = items.first unless items.blank?
321
321
  result = []
322
322
  incrementally_list_items('DescribeDBSecurityGroups', DescribeDbSecurityGroupsParser, params) do |response|
323
323
  result += response[:db_security_groups]
@@ -433,8 +433,8 @@ module RightAws
433
433
  # end
434
434
  #
435
435
  def describe_db_parameter_groups(*db_parameter_group_name, &block)
436
- item, params = AwsUtils::split_items_and_params(db_parameter_group_name)
437
- params['DBParameterGroupName'] = item if item
436
+ items, params = AwsUtils::split_items_and_params(db_parameter_group_name)
437
+ params['DBParameterGroupName'] = items.first unless items.blank?
438
438
  result = []
439
439
  incrementally_list_items('DescribeDBParameterGroups', DescribeDbParameterGroupsParser, params) do |response|
440
440
  result += response[:db_parameter_groups]
@@ -41,6 +41,8 @@ require 'awsbase/right_awsbase'
41
41
  require 'ec2/right_ec2'
42
42
  require 'ec2/right_ec2_images'
43
43
  require 'ec2/right_ec2_instances'
44
+ require 'ec2/right_ec2_security_groups'
45
+ require 'ec2/right_ec2_spot_instances'
44
46
  require 'ec2/right_ec2_ebs'
45
47
  require 'ec2/right_ec2_reserved_instances'
46
48
  require 'ec2/right_ec2_vpc'
@@ -56,16 +58,18 @@ require 'sqs/right_sqs_gen2_interface'
56
58
  require 'sqs/right_sqs_gen2'
57
59
  require 'sdb/right_sdb_interface'
58
60
  require 'acf/right_acf_interface'
61
+ require 'acf/right_acf_streaming_interface'
62
+ require 'acf/right_acf_origin_access_identities'
59
63
  require 'rds/right_rds_interface'
60
64
 
61
65
 
62
66
  module RightAws #:nodoc:
63
67
  module VERSION #:nodoc:
64
- MAJOR = 1
65
- MINOR = 11
66
- TINY = 0
68
+ MAJOR = 2 unless defined?(MAJOR)
69
+ MINOR = 0 unless defined?(MINOR)
70
+ TINY = 1 unless defined?(TINY)
67
71
 
68
- STRING = [MAJOR, MINOR, TINY].join('.')
72
+ STRING = [MAJOR, MINOR, TINY].join('.') unless defined?(STRING)
69
73
  end
70
74
  end
71
75
 
@@ -460,6 +460,30 @@ module RightAws
460
460
  get if !@data and exists?
461
461
  @data
462
462
  end
463
+
464
+ # Getter for the 'content-type' metadata
465
+ def content_type
466
+ @headers['content-type'] if @headers
467
+ end
468
+
469
+ # Helper to get and URI-decode a header metadata.
470
+ # Metadata have to be HTTP encoded (rfc2616) as we use the Amazon S3 REST api
471
+ # see http://docs.amazonwebservices.com/AmazonS3/latest/index.html?UsingMetadata.html
472
+ def decoded_meta_headers(key = nil)
473
+ if key
474
+ # Get one metadata value by its key
475
+ URI.decode(@meta_headers[key.to_s])
476
+ else
477
+ # Get a hash of all metadata with a decoded value
478
+ @decoded_meta_headers ||= begin
479
+ metadata = {}
480
+ @meta_headers.each do |key, value|
481
+ metadata[key.to_sym] = URI.decode(value)
482
+ end
483
+ metadata
484
+ end
485
+ end
486
+ end
463
487
 
464
488
  # Retrieve object data and attributes from Amazon.
465
489
  # Returns a +String+.
@@ -759,7 +783,7 @@ module RightAws
759
783
  @thing = thing
760
784
  @id = id
761
785
  @name = name
762
- @perms = perms.to_a
786
+ @perms = Array(perms)
763
787
  case action
764
788
  when :apply then apply
765
789
  when :refresh then refresh
@@ -93,7 +93,11 @@ module RightAws
93
93
  s3_headers = {}
94
94
  headers.each do |key, value|
95
95
  key = key.downcase
96
- s3_headers[key] = value.to_s.strip if key[/^#{AMAZON_HEADER_PREFIX}|^content-md5$|^content-type$|^date$/o]
96
+ value = case
97
+ when value.is_a?(Array) then value.join('')
98
+ else value.to_s
99
+ end
100
+ s3_headers[key] = value.strip if key[/^#{AMAZON_HEADER_PREFIX}|^content-md5$|^content-type$|^date$/o]
97
101
  end
98
102
  s3_headers['content-type'] ||= ''
99
103
  s3_headers['content-md5'] ||= ''
@@ -740,7 +744,7 @@ module RightAws
740
744
  else
741
745
  result[:grantees][key] =
742
746
  { :display_name => grantee[:display_name] || grantee[:uri].to_s[/[^\/]*$/],
743
- :permissions => grantee[:permissions].to_a,
747
+ :permissions => Array(grantee[:permissions]),
744
748
  :attributes => grantee[:attributes] }
745
749
  end
746
750
  end
@@ -92,6 +92,59 @@ module RightAws
92
92
  # # remove domain
93
93
  # Client.delete_domain
94
94
  #
95
+ # # Dynamic attribute accessors
96
+ #
97
+ # class KdClient < RightAws::ActiveSdb::Base
98
+ # end
99
+ #
100
+ # client = KdClient.select(:all, :order => 'expiration').first
101
+ # pp client.attributes #=>
102
+ # {"name"=>["Putin"],
103
+ # "post"=>["president"],
104
+ # "country"=>["Russia"],
105
+ # "expiration"=>["2008"],
106
+ # "id"=>"376d2e00-75b0-11dd-9557-001bfc466dd7",
107
+ # "gender"=>["male"]}
108
+ #
109
+ # pp client.name #=> ["Putin"]
110
+ # pp client.country #=> ["Russia"]
111
+ # pp client.post #=> ["president"]
112
+ #
113
+ # # Columns and simple typecasting
114
+ #
115
+ # class Person < RightAws::ActiveSdb::Base
116
+ # columns do
117
+ # name
118
+ # email
119
+ # score :Integer
120
+ # is_active :Boolean
121
+ # registered_at :DateTime
122
+ # created_at :DateTime, :default => lambda{ Time.now }
123
+ # end
124
+ # end
125
+ # Person::create( :name => 'Yetta E. Andrews', :email => 'nulla.facilisis@metus.com', :score => 100, :is_active => true, :registered_at => Time.local(2000, 1, 1) )
126
+ #
127
+ # person = Person.find_by_email 'nulla.facilisis@metus.com'
128
+ # person.reload
129
+ #
130
+ # pp person.attributes #=>
131
+ # {"name"=>["Yetta E. Andrews"],
132
+ # "created_at"=>["2010-04-02T20:51:58+0400"],
133
+ # "id"=>"0ee24946-3e60-11df-9d4c-0025b37efad0",
134
+ # "registered_at"=>["2000-01-01T00:00:00+0300"],
135
+ # "is_active"=>["T"],
136
+ # "score"=>["100"],
137
+ # "email"=>["nulla.facilisis@metus.com"]}
138
+ # pp person.name #=> "Yetta E. Andrews"
139
+ # pp person.name.class #=> String
140
+ # pp person.registered_at.to_s #=> "2000-01-01T00:00:00+03:00"
141
+ # pp person.registered_at.class #=> DateTime
142
+ # pp person.is_active #=> true
143
+ # pp person.is_active.class #=> TrueClass
144
+ # pp person.score #=> 100
145
+ # pp person.score.class #=> Fixnum
146
+ # pp person.created_at.to_s #=> "2010-04-02T20:51:58+04:00"
147
+ #
95
148
  class ActiveSdb
96
149
 
97
150
  module ActiveSdbConnect
@@ -242,7 +295,31 @@ module RightAws
242
295
  def delete_domain
243
296
  connection.delete_domain(domain)
244
297
  end
245
-
298
+
299
+ def columns(&block)
300
+ @columns ||= ColumnSet.new
301
+ @columns.instance_eval(&block) if block
302
+ @columns
303
+ end
304
+
305
+ def column?(col_name)
306
+ columns.include?(col_name)
307
+ end
308
+
309
+ def type_of(col_name)
310
+ columns.type_of(col_name)
311
+ end
312
+
313
+ def serialize(attribute, value)
314
+ s = serialization_for_type(type_of(attribute))
315
+ s ? s.serialize(value) : value.to_s
316
+ end
317
+
318
+ def deserialize(attribute, value)
319
+ s = serialization_for_type(type_of(attribute))
320
+ s ? s.deserialize(value) : value
321
+ end
322
+
246
323
  # Perform a find request.
247
324
  #
248
325
  # Single record:
@@ -364,7 +441,11 @@ module RightAws
364
441
  end
365
442
 
366
443
  def generate_id # :nodoc:
367
- UUIDTools::UUID.timestamp_create().to_s
444
+ if UUID::VERSION::STRING < '2.0.0'
445
+ UUID.timestamp_create().to_s
446
+ else
447
+ UUIDTools::UUID.timestamp_create().to_s
448
+ end
368
449
  end
369
450
 
370
451
  protected
@@ -376,7 +457,7 @@ module RightAws
376
457
  # detect amount of records requested
377
458
  bunch_of_records_requested = args.size > 1 || args.first.is_a?(Array)
378
459
  # flatten ids
379
- args = args.to_a.flatten
460
+ args = Array(args).flatten
380
461
  args.each { |id| cond << "id=#{self.connection.escape(id)}" }
381
462
  ids_cond = "(#{cond.join(' OR ')})"
382
463
  # user defined :conditions to string (if it was defined)
@@ -518,7 +599,7 @@ module RightAws
518
599
  # detect amount of records requested
519
600
  bunch_of_records_requested = args.size > 1 || args.first.is_a?(Array)
520
601
  # flatten ids
521
- args = args.to_a.flatten
602
+ args = Array(args).flatten
522
603
  args.each { |id| cond << "'id'=#{self.connection.escape(id)}" }
523
604
  ids_cond = "[#{cond.join(' OR ')}]"
524
605
  # user defined :conditions to string (if it was defined)
@@ -590,6 +671,13 @@ module RightAws
590
671
  end
591
672
  end
592
673
 
674
+ def serialization_for_type(type)
675
+ @serializations ||= {}
676
+ unless @serializations.has_key? type
677
+ @serializations[type] = ::RightAws::ActiveSdb.const_get("#{type}Serialization") rescue false
678
+ end
679
+ @serializations[type]
680
+ end
593
681
  end
594
682
 
595
683
  public
@@ -661,7 +749,11 @@ module RightAws
661
749
  self.attributes
662
750
  end
663
751
 
664
- def connection
752
+ def columns
753
+ self.class.columns
754
+ end
755
+
756
+ def connection
665
757
  self.class.connection
666
758
  end
667
759
 
@@ -675,7 +767,8 @@ module RightAws
675
767
  # puts item['Cat'].inspect #=> ["Jons socks", "clew", "mice"]
676
768
  #
677
769
  def [](attribute)
678
- @attributes[attribute.to_s]
770
+ raw = @attributes[attribute.to_s]
771
+ self.class.column?(attribute) && raw ? self.class.deserialize(attribute, raw.first) : raw
679
772
  end
680
773
 
681
774
  # Updates the attribute identified by +attribute+ with the specified +values+.
@@ -686,7 +779,14 @@ module RightAws
686
779
  #
687
780
  def []=(attribute, values)
688
781
  attribute = attribute.to_s
689
- @attributes[attribute] = attribute == 'id' ? values.to_s : values.to_a.uniq
782
+ @attributes[attribute] = case
783
+ when attribute == 'id'
784
+ values.to_s
785
+ when self.class.column?(attribute)
786
+ self.class.serialize(attribute, values)
787
+ else
788
+ Array(values).uniq
789
+ end
690
790
  end
691
791
 
692
792
  # Reload attributes from SDB. Replaces in-memory attributes.
@@ -906,25 +1006,117 @@ module RightAws
906
1006
  @new_record = false
907
1007
  end
908
1008
 
909
- private
910
-
1009
+ # support accessing attribute values via method call
1010
+ def method_missing(method_sym, *args)
1011
+ method_name = method_sym.to_s
1012
+ setter = method_name[-1,1] == '='
1013
+ method_name.chop! if setter
1014
+
1015
+ if @attributes.has_key?(method_name) || self.class.column?(method_name)
1016
+ setter ? self[method_name] = args.first : self[method_name]
1017
+ else
1018
+ super
1019
+ end
1020
+ end
1021
+
1022
+ private
1023
+
911
1024
  def raise_on_id_absence
912
1025
  raise ActiveSdbError.new('Unknown record id') unless id
913
1026
  end
914
1027
 
915
1028
  def prepare_for_update
916
1029
  @attributes['id'] = self.class.generate_id if @attributes['id'].blank?
1030
+ columns.all.each do |col_name|
1031
+ self[col_name] ||= columns.default(col_name)
1032
+ end
917
1033
  end
918
1034
 
919
1035
  def uniq_values(attributes=nil) # :nodoc:
920
1036
  attrs = {}
921
1037
  attributes.each do |attribute, values|
922
1038
  attribute = attribute.to_s
923
- attrs[attribute] = attribute == 'id' ? values.to_s : values.to_a.uniq
1039
+ attrs[attribute] = case
1040
+ when attribute == 'id'
1041
+ values.to_s
1042
+ when self.class.column?(attribute)
1043
+ values.is_a?(String) ? values : self.class.serialize(attribute, values)
1044
+ else
1045
+ Array(values).uniq
1046
+ end
924
1047
  attrs.delete(attribute) if values.blank?
925
1048
  end
926
1049
  attrs
927
1050
  end
928
1051
  end
1052
+
1053
+ class ColumnSet
1054
+ attr_accessor :columns
1055
+ def initialize
1056
+ @columns = {}
1057
+ end
1058
+
1059
+ def all
1060
+ @columns.keys
1061
+ end
1062
+
1063
+ def column(col_name)
1064
+ @columns[col_name.to_s]
1065
+ end
1066
+ alias_method :include?, :column
1067
+
1068
+ def type_of(col_name)
1069
+ column(col_name) && column(col_name)[:type]
1070
+ end
1071
+
1072
+ def default(col_name)
1073
+ return nil unless include?(col_name)
1074
+ default = column(col_name)[:default]
1075
+ default.respond_to?(:call) ? default.call : default
1076
+ end
1077
+
1078
+ def method_missing(method_sym, *args)
1079
+ data_type = args.shift || :String
1080
+ options = args.shift || {}
1081
+ @columns[method_sym.to_s] = options.merge( :type => data_type )
1082
+ end
1083
+ end
1084
+
1085
+ class DateTimeSerialization
1086
+ class << self
1087
+ def serialize(date)
1088
+ date.strftime('%Y-%m-%dT%H:%M:%S%z')
1089
+ end
1090
+
1091
+ def deserialize(string)
1092
+ r = DateTime.parse(string) rescue nil
1093
+ end
1094
+ end
1095
+ end
1096
+
1097
+ class BooleanSerialization
1098
+ class << self
1099
+ def serialize(boolean)
1100
+ boolean ? 'T' : 'F'
1101
+ end
1102
+
1103
+ def deserialize(string)
1104
+ string == 'T'
1105
+ end
1106
+ end
1107
+ end
1108
+
1109
+ class IntegerSerialization
1110
+ class << self
1111
+ def serialize(int)
1112
+ int.to_s
1113
+ end
1114
+
1115
+ def deserialize(string)
1116
+ string.to_i
1117
+ end
1118
+ end
1119
+ end
1120
+
929
1121
  end
930
1122
  end
@@ -33,7 +33,7 @@ module RightAws
33
33
  DEFAULT_PORT = 443
34
34
  DEFAULT_PROTOCOL = 'https'
35
35
  DEFAULT_PATH = '/'
36
- API_VERSION = '2007-11-07'
36
+ API_VERSION = '2009-04-15'
37
37
  DEFAULT_NIL_REPRESENTATION = 'nil'
38
38
 
39
39
  @@bench = AwsBenchmarkingBlock.new
@@ -89,24 +89,42 @@ module RightAws
89
89
 
90
90
  # Prepare attributes for putting.
91
91
  # (used by put_attributes)
92
- def pack_attributes(attributes, replace = false) #:nodoc:
92
+ def pack_attributes(items_or_attributes, replace = false, batch = false) #:nodoc:
93
+ if batch
94
+ index = 0
95
+ items_or_attributes.inject({}){|result, (item_name, attributes)|
96
+ item_prefix = "Item.#{index}."
97
+ result["#{item_prefix}ItemName"] = item_name.to_s
98
+ result.merge!(
99
+ pack_single_item_attributes(attributes, replace, item_prefix))
100
+ index += 1
101
+ result
102
+ }
103
+ else
104
+ pack_single_item_attributes(items_or_attributes, replace)
105
+ end
106
+ end
107
+
108
+ def pack_single_item_attributes(attributes, replace, prefix = "")
93
109
  result = {}
94
110
  if attributes
95
111
  idx = 0
96
112
  skip_values = attributes.is_a?(Array)
97
113
  attributes.each do |attribute, values|
98
114
  # set replacement attribute
99
- result["Attribute.#{idx}.Replace"] = 'true' if replace
115
+ result["#{prefix}Attribute.#{idx}.Replace"] = 'true' if replace
100
116
  # pack Name/Value
101
117
  unless values.nil?
102
- Array(values).each do |value|
103
- result["Attribute.#{idx}.Name"] = attribute
104
- result["Attribute.#{idx}.Value"] = ruby_to_sdb(value) unless skip_values
118
+ # Array(values) does not work here:
119
+ # - Array('') => [] but we wanna get here ['']
120
+ [values].flatten.each do |value|
121
+ result["#{prefix}Attribute.#{idx}.Name"] = attribute
122
+ result["#{prefix}Attribute.#{idx}.Value"] = ruby_to_sdb(value) unless skip_values
105
123
  idx += 1
106
124
  end
107
125
  else
108
- result["Attribute.#{idx}.Name"] = attribute
109
- result["Attribute.#{idx}.Value"] = ruby_to_sdb(nil) unless skip_values
126
+ result["#{prefix}Attribute.#{idx}.Name"] = attribute
127
+ result["#{prefix}Attribute.#{idx}.Value"] = ruby_to_sdb(nil) unless skip_values
110
128
  idx += 1
111
129
  end
112
130
  end
@@ -307,6 +325,37 @@ module RightAws
307
325
  rescue Exception
308
326
  on_exception
309
327
  end
328
+
329
+ # Add/Replace attributes for multiple items at a time.
330
+ #
331
+ # Params:
332
+ # domain_name = DomainName
333
+ # items = {
334
+ # 'Item1' => {
335
+ # 'nameA' => [valueA1, valueA2,..., valueAN],
336
+ # ...
337
+ # 'nameB' => [valueB1, valueB2,..., valueBN]
338
+ # },
339
+ # 'Item2' => {
340
+ # 'nameC' => [valueC1, valueC2,..., valueCN],
341
+ # ...
342
+ # 'nameD' => [valueD1, valueD2,..., valueDN]
343
+ # }
344
+ # }
345
+ # replace = :replace | any other value to skip replacement
346
+ #
347
+ # Usage of batch_put_attributes is similar to put_attributes except that
348
+ # instead of supplying an item_name and a hash of attributes, you supply a
349
+ # hash of item names to attributes.
350
+ #
351
+ # See: http://docs.amazonwebservices.com/AmazonSimpleDB/latest/DeveloperGuide/index.html?SDB_API_BatchPutAttributes.html
352
+ def batch_put_attributes(domain_name, items, replace = false)
353
+ params = { 'DomainName' => domain_name }.merge(pack_attributes(items, replace, true))
354
+ link = generate_request("BatchPutAttributes", params)
355
+ request_info( link, QSdbSimpleParser.new)
356
+ rescue Exception
357
+ on_exception
358
+ end
310
359
 
311
360
  # Retrieve SDB item's attribute(s).
312
361
  #
@@ -332,10 +381,11 @@ module RightAws
332
381
  #
333
382
  # see: http://docs.amazonwebservices.com/AmazonSimpleDB/2007-11-07/DeveloperGuide/SDB_API_GetAttributes.html
334
383
  #
335
- def get_attributes(domain_name, item_name, attribute_name=nil)
384
+ def get_attributes(domain_name, item_name, attribute_name=nil, consistent_read=false)
336
385
  link = generate_request("GetAttributes", 'DomainName' => domain_name,
337
386
  'ItemName' => item_name,
338
- 'AttributeName' => attribute_name )
387
+ 'AttributeName' => attribute_name,
388
+ 'ConsistentRead' => consistent_read )
339
389
  res = request_info(link, QSdbGetAttributesParser.new)
340
390
  res[:attributes].each_value do |values|
341
391
  values.collect! { |e| sdb_to_ruby(e) }
@@ -476,7 +526,7 @@ module RightAws
476
526
  # see: http://docs.amazonwebservices.com/AmazonSimpleDB/2007-11-07/DeveloperGuide/index.html?SDB_API_QueryWithAttributes.html
477
527
  #
478
528
  def query_with_attributes(domain_name, attributes=[], query_expression = nil, max_number_of_items = nil, next_token = nil)
479
- attributes = attributes.to_a
529
+ attributes = Array(attributes)
480
530
  query_expression = query_expression_from_array(query_expression) if query_expression.is_a?(Array)
481
531
  @last_query_expression = query_expression
482
532
  #