toy-dynamo 0.1.3 → 0.1.4

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 55543749d5aada53a2339255fecf85562746b958
4
- data.tar.gz: ae3a9255c0d8d90187c4de0651ea3e262cf9c807
3
+ metadata.gz: 5a081dc7fc7b298bb5a17919dc56688f9aa504d4
4
+ data.tar.gz: 97616bc8ba2f9443c7915d9ea250ef5e50b0306c
5
5
  SHA512:
6
- metadata.gz: 82d0ac9c53c7ec511df84d4afe592c946bf8567c5c1dce86c913b667937b033f9f408b71275c895a3a1889a03a1de7ecfc42ffea5345e2b006579c5a9e0c551f
7
- data.tar.gz: 8e08548bbc6a408cc179d2f2c358e16f7b10eeef69aaf772ff14b1117a483a5d8f2fec85d26bf26a8a3efdd4595ffc89854f367255d35a0fb5ffe61eaece5983
6
+ metadata.gz: c6d12a4a8cbd03bbb98f8d1ba283d28771e1896b73c9b5480ef750c3b17865c9bb75ae32f654863aa3ee023a4816b37b9f34aead2bf55f29f92802c5a8daacc9
7
+ data.tar.gz: 8a345618f030321fc03c0695a35467d6e79166ba7bc22e06eb1f71079462b5d4ec882c4ab018f84b871d1d9bee9651d6d25ab579cde485b643fe9d40fe7d5069
@@ -14,7 +14,7 @@ module Toy
14
14
  # Loop results in given batch size until limit is hit or no more results
15
15
  # read_range("1", :range => { :varname.eq => "2"}, :batch => 10, :limit => 1000)
16
16
  def read_range(hash_value, options={})
17
- raise ArgumentError, "no range_key specified for this table" if dynamo_table.range_keys.blank?
17
+ raise ArgumentError, "no range_key specified for this table" if dynamo_table.range_keys.blank? && global_secondary_indexes.blank?
18
18
  aggregated_results = []
19
19
 
20
20
  batch_size = options.delete(:batch) || DEFAULT_BATCH_SIZE
@@ -50,6 +50,7 @@ module Toy
50
50
  :attribute_definitions => attribute_definitions
51
51
  }
52
52
  schema[:local_secondary_indexes] = local_secondary_indexes unless local_secondary_indexes.blank?
53
+ schema[:global_secondary_indexes] = global_secondary_indexes unless global_secondary_indexes.blank?
53
54
  schema
54
55
  end
55
56
 
@@ -94,6 +95,12 @@ module Toy
94
95
  keys << lsi[:key_schema].select{|h| h[:key_type] == "RANGE"}.first[:attribute_name]
95
96
  end
96
97
 
98
+ global_secondary_indexes.each do |lsi|
99
+ lsi[:key_schema].each do |a|
100
+ keys << a[:attribute_name]
101
+ end
102
+ end
103
+
97
104
  definitions = keys.uniq.collect do |k|
98
105
  attr = self.attributes[k.to_s]
99
106
  {
@@ -197,6 +204,66 @@ module Toy
197
204
  end
198
205
  end
199
206
 
207
+ def global_secondary_indexes
208
+ @global_secondary_indexes ||= []
209
+ end
210
+
211
+ # { hash_key: :hash_key_here, range_key: :optional_range_key_here }
212
+ # :name
213
+ # :projection
214
+ # :read_provision
215
+ # :write_provision
216
+ def global_secondary_index(index_name, options={})
217
+ options[:projection] ||= :keys_only
218
+ global_secondary_index_hash = {
219
+ :projection => {},
220
+ :provisioned_throughput => {
221
+ :read_capacity_units => options[:read_provision] || read_provision,
222
+ :write_capacity_units => options[:write_provision] || write_provision
223
+ }
224
+ }
225
+ if options[:projection].is_a?(Array) && options[:projection].size > 0
226
+ options[:projection].each do |non_key_attr|
227
+ attr = self.attributes[non_key_attr.to_s]
228
+ raise(ArgumentError, "Could not find attribute definition for projection on #{non_key_attr}") unless attr
229
+ (global_secondary_index_hash[:projection][:non_key_attributes] ||= []) << attr.name
230
+ end
231
+ global_secondary_index_hash[:projection][:projection_type] = PROJECTION_TYPE[:include]
232
+ else
233
+ raise(ArgumentError, 'projection must be :all, :keys_only, Array (or attrs)') unless options[:projection] == :keys_only || options[:projection] == :all
234
+ global_secondary_index_hash[:projection][:projection_type] = PROJECTION_TYPE[options[:projection]]
235
+ end
236
+
237
+ if !options.has_key?(:hash_key) || self.attributes[options[:hash_key].to_s].blank?
238
+ raise(ArgumentError, "Could not find attribute definition for global secondary index on hash_key specified")
239
+ end
240
+ hash_key_attr = self.attributes[options[:hash_key].to_s]
241
+
242
+ if options.has_key?(:range_key) && self.attributes[options[:range_key].to_s].blank?
243
+ raise(ArgumentError, "Could not find attribute definition for global secondary index on range_key specified")
244
+ end
245
+ range_key_attr = nil
246
+ range_key_attr = self.attributes[options[:range_key].to_s] if options.has_key?(:range_key)
247
+
248
+ ## Force naming of index_name for lookup later
249
+ #global_secondary_index_hash[:index_name] = (index_name.to_s || "#{hash_key_attr.name}#{"_#{range_key_attr.name}" if range_key_attr}_gsi_index".camelcase)
250
+ global_secondary_index_hash[:index_name] = index_name.to_s
251
+
252
+ global_secondary_index_hash[:key_schema] = [
253
+ {
254
+ :attribute_name => hash_key_attr.name,
255
+ :key_type => KEY_TYPE[:hash]
256
+ }
257
+ ]
258
+ global_secondary_index_hash[:key_schema] << {
259
+ :attribute_name => range_key_attr.name,
260
+ :key_type => KEY_TYPE[:range]
261
+ } if range_key_attr
262
+
263
+ return false if (@global_secondary_indexes ||= []).select {|i| i[:index_name] == global_secondary_index_hash[:index_name] }.present? # Do not add if we already have a range key set for this attr
264
+ (@global_secondary_indexes ||= []) << global_secondary_index_hash
265
+ end
266
+
200
267
  def local_secondary_indexes
201
268
  @local_secondary_indexes ||= []
202
269
  end
@@ -226,7 +293,7 @@ module Toy
226
293
 
227
294
  range_attr = self.attributes[range_key_attr.to_s]
228
295
  raise(ArgumentError, "Could not find attribute definition for local secondary index on #{range_key_attr}") unless range_attr
229
- local_secondary_index_hash[:index_name] = (options[:name] || "#{range_attr.name}_index".camelcase)
296
+ local_secondary_index_hash[:index_name] = (options[:name] || options[:index_name] || "#{range_attr.name}_index".camelcase)
230
297
 
231
298
  hash_key_attr = self.attributes[hash_key[:attribute_name].to_s]
232
299
  raise(ArgumentError, "Could not find attribute definition for hash_key") unless hash_key_attr
@@ -74,14 +74,15 @@ module Toy
74
74
  end
75
75
  end
76
76
 
77
- if @schema_loaded_from_dynamo[:table][:local_secondary_indexes]
78
- @schema_loaded_from_dynamo[:table][:local_secondary_indexes].each do |key|
79
- lsi_range_key = key[:key_schema].find{|h| h[:key_type] == "RANGE" }
80
- lsi_range_attribute = @table_schema[:attribute_definitions].find{|h| h[:attribute_name] == lsi_range_key[:attribute_name]}
81
- next if lsi_range_attribute.nil?
77
+ if @schema_loaded_from_dynamo[:table][:local_secondary_indexes] || @schema_loaded_from_dynamo[:table][:global_secondary_indexes]
78
+ ((@schema_loaded_from_dynamo[:table][:local_secondary_indexes] || []) + (@schema_loaded_from_dynamo[:table][:global_secondary_indexes] || [])).each do |key|
79
+ si_range_key = key[:key_schema].find{|h| h[:key_type] == "RANGE" }
80
+ next if si_range_key.nil?
81
+ si_range_attribute = @table_schema[:attribute_definitions].find{|h| h[:attribute_name] == si_range_key[:attribute_name]}
82
+ next if si_range_attribute.nil?
82
83
  (@range_keys ||= []) << {
83
- :attribute_name => lsi_range_key[:attribute_name],
84
- :attribute_type => lsi_range_attribute[:attribute_type],
84
+ :attribute_name => si_range_key[:attribute_name],
85
+ :attribute_type => si_range_attribute[:attribute_type],
85
86
  :index_name => key[:index_name]
86
87
  }
87
88
  end
@@ -96,8 +97,7 @@ module Toy
96
97
  { hash_key => { hash_key_type => value } }
97
98
  end
98
99
 
99
- def hash_key_condition_param(value)
100
- hash_key = @table_schema[:key_schema].find{|h| h[:key_type] == "HASH"}[:attribute_name]
100
+ def hash_key_condition_param(hash_key, value)
101
101
  hash_key_type = @table_schema[:attribute_definitions].find{|h| h[:attribute_name] == hash_key}[:attribute_type]
102
102
  {
103
103
  hash_key => {
@@ -142,7 +142,17 @@ module Toy
142
142
  #options[:exclusive_start_key]
143
143
 
144
144
  key_conditions = {}
145
- key_conditions.merge!(hash_key_condition_param(hash_key_value))
145
+ gsi = nil
146
+ if options[:global_secondary_index]
147
+ # TODO
148
+ gsi = @table_schema[:global_secondary_indexes].select{ |gsi| gsi[:index_name].to_s == options[:global_secondary_index].to_s}.first
149
+ raise ArgumentError, "Could not find Global Secondary Index '#{options[:global_secondary_index]}'" unless gsi
150
+ gsi_hash_key = gsi[:key_schema].find{|h| h[:key_type] == "HASH"}[:attribute_name]
151
+ key_conditions.merge!(hash_key_condition_param(gsi_hash_key, hash_key_value))
152
+ else
153
+ hash_key = @table_schema[:key_schema].find{|h| h[:key_type] == "HASH"}[:attribute_name]
154
+ key_conditions.merge!(hash_key_condition_param(hash_key, hash_key_value))
155
+ end
146
156
 
147
157
  query_request = {
148
158
  :table_name => options[:table_name] || self.table_name,
@@ -153,14 +163,24 @@ module Toy
153
163
  }
154
164
 
155
165
  if options[:range]
156
- raise ArgumentError, "Expected a 1 element Hash for :range (ex {:age.gt => 13})" unless options[:range].is_a?(Hash) && options[:range].keys.size == 1
166
+ raise ArgumentError, "Expected a 1 element Hash for :range (ex {:age.gt => 13})" unless options[:range].is_a?(Hash) && options[:range].keys.size == 1 && options[:range].keys.first.is_a?(String)
157
167
  range_key_name, comparison_operator = options[:range].keys.first.split(".")
158
168
  raise ArgumentError, "Comparison operator must be one of (#{(COMPARISON_OPERATOR.keys - COMPARISON_OPERATOR_SCAN_ONLY).join(", ")})" unless COMPARISON_OPERATOR.keys.include?(comparison_operator.to_sym)
159
- range_key = @range_keys.find{|k| k[:attribute_name] == range_key_name}
169
+ range_key = nil
170
+ #[{:attribute_name=>"health_check_guid", :attribute_type=>"S", :primary_range_key=>true}]
171
+ #raise @range_keys.inspect
172
+ #if options[:global_secondary_index]
173
+ #raise @table_schema.inspect
174
+ #hash_key_type = @table_schema[:attribute_definitions].find{|h| h[:attribute_name] == hash_key}[:attribute_type]
175
+ #raise gsi[:key_schema].inspect
176
+ ##range_key = gsi.find{|k| k[:attribute_name] == range_key_name}
177
+ #else
178
+ range_key = @range_keys.find{|k| k[:attribute_name] == range_key_name}
179
+ #end
160
180
  raise ArgumentError, ":range key must be a valid Range attribute" unless range_key
161
181
  raise ArgumentError, ":range key must be a Range if using the operator BETWEEN" if comparison_operator == "between" && !options[:range].values.first.is_a?(Range)
162
182
 
163
- if range_key.has_key?(:index_name) # Local Secondary Index
183
+ if range_key.has_key?(:index_name) # Local/Global Secondary Index
164
184
  #options[:select] = :projected unless options[:select].present?
165
185
  query_request.merge!(:index_name => range_key[:index_name])
166
186
  end
@@ -183,6 +203,10 @@ module Toy
183
203
  })
184
204
  end
185
205
 
206
+ if options[:global_secondary_index] # Override index_name if using GSI
207
+ query_request.merge!(:index_name => gsi[:index_name])
208
+ end
209
+
186
210
  # Default if not already set
187
211
  options[:select] ||= :all # :all, :projected, :count, []
188
212
  if options[:select].is_a?(Array)
@@ -1,5 +1,5 @@
1
1
  module Toy
2
2
  module Dynamo
3
- VERSION = "0.1.3"
3
+ VERSION = "0.1.4"
4
4
  end
5
5
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: toy-dynamo
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.3
4
+ version: 0.1.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - Cary Dunn
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2013-12-04 00:00:00.000000000 Z
11
+ date: 2013-12-20 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler