toy-dynamo 0.1.3 → 0.1.4

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.
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