dm-adapter-simpledb 1.2.0 → 1.3.0
Sign up to get free protection for your applications and to get access to all the features.
- data/History.txt +17 -0
- data/README +3 -9
- data/Rakefile +1 -1
- data/VERSION +1 -1
- data/lib/dm-adapter-simpledb.rb +1 -0
- data/lib/dm-adapter-simpledb/adapters/simpledb_adapter.rb +56 -28
- data/spec/integration/limit_and_order_spec.rb +6 -0
- data/spec/unit/simpledb_adapter_spec.rb +14 -1
- metadata +4 -4
data/History.txt
CHANGED
@@ -1,3 +1,20 @@
|
|
1
|
+
== 1.3.0 2010-01-19
|
2
|
+
|
3
|
+
* 1 major enhancement:
|
4
|
+
* Now supports :offset in queries. Combined with improved :limit support, this
|
5
|
+
makes it possible to efficiently paginate result sets.
|
6
|
+
|
7
|
+
* 1 minor enhancement:
|
8
|
+
* Better quoting of select statements using the 'sdbtools' library.
|
9
|
+
|
10
|
+
== 1.2.0 2010-01-13
|
11
|
+
|
12
|
+
* 2 minor enhancements:
|
13
|
+
* Better support for String attributes with multiple values which were not
|
14
|
+
created by the String chunking system.
|
15
|
+
* Now tries to take model and repository into account when determining storage
|
16
|
+
name for a table.
|
17
|
+
|
1
18
|
== 1.1.0 2009-11-24
|
2
19
|
|
3
20
|
* 2 major enhancements:
|
data/README
CHANGED
@@ -16,6 +16,7 @@ Features:
|
|
16
16
|
* Array properties
|
17
17
|
* Basic aggregation support (Model.count("..."))
|
18
18
|
* String "chunking" permits attributes to exceed the 1024-byte limit
|
19
|
+
* Support for efficient :limit and :offset, for result set paging
|
19
20
|
|
20
21
|
Note: as of version 1.0.0, this gem supports supports the DataMapper 0.10.*
|
21
22
|
series and breaks backwards compatibility with DataMapper 0.9.*.
|
@@ -39,6 +40,7 @@ http://github.com/devver/dm-adapter-simpledb/
|
|
39
40
|
== TODO
|
40
41
|
|
41
42
|
* More complete handling of NOT conditions in queries
|
43
|
+
* Support for ORs, parens, and nested queries in general
|
42
44
|
* Robust quoting in SELECT calls
|
43
45
|
* Handle exclusive ranges natively
|
44
46
|
Implement as inclusive range + filter step
|
@@ -48,15 +50,6 @@ http://github.com/devver/dm-adapter-simpledb/
|
|
48
50
|
- Store floats using exponential notation
|
49
51
|
* Option to store Date/Time/DateTime as ISO8601
|
50
52
|
* Full aggregate support (min/max/etc)
|
51
|
-
* Offset support
|
52
|
-
Note, from the SimpleDB documentation:
|
53
|
-
|
54
|
-
"The next token returned by count(*) and select are interchangeable as long
|
55
|
-
as the where and order by clauses match. For example, if you want to return
|
56
|
-
the 200 items after the first 10,000 (similar to an offset), you can perform
|
57
|
-
a count with a limit clause of 10,000 and use the next token to return the
|
58
|
-
next 200 items with select."
|
59
|
-
|
60
53
|
* Option to use libxml if available
|
61
54
|
* Parallelized queries for increased throughput
|
62
55
|
* Support of normalized 1:1 table:domain schemes that works with associations
|
@@ -64,6 +57,7 @@ http://github.com/devver/dm-adapter-simpledb/
|
|
64
57
|
* Support BatchPutAttributes
|
65
58
|
* Silence SSL warnings
|
66
59
|
See http://pivotallabs.com/users/carl/blog/articles/1079-standup-blog-11-24-2009-model-validations-without-backing-store-associations-to-array-and-ssl-with-aws
|
60
|
+
* Token cache for reduced requests when given an offset
|
67
61
|
|
68
62
|
== Usage
|
69
63
|
|
data/Rakefile
CHANGED
@@ -81,7 +81,7 @@ END
|
|
81
81
|
gem.add_dependency('dm-migrations', '~> 0.10.0')
|
82
82
|
gem.add_dependency('dm-types', '~> 0.10.0')
|
83
83
|
gem.add_dependency('uuidtools', '~> 2.0')
|
84
|
-
gem.add_dependency('
|
84
|
+
gem.add_dependency('sdbtools', '~> 0.2')
|
85
85
|
end
|
86
86
|
Jeweler::GemcutterTasks.new
|
87
87
|
rescue LoadError
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
1.
|
1
|
+
1.3.0
|
data/lib/dm-adapter-simpledb.rb
CHANGED
@@ -92,7 +92,16 @@ module DataMapper
|
|
92
92
|
query.conditions.operands.reject!{ |op|
|
93
93
|
!unsupported_conditions.include?(op)
|
94
94
|
}
|
95
|
-
|
95
|
+
|
96
|
+
# This used to be a simple call to Query#filter_records(), but that
|
97
|
+
# caused the result limit to be re-imposed on an already limited result
|
98
|
+
# set, with the upshot that too few records were returned. So here we do
|
99
|
+
# everything filter_records() does EXCEPT limiting.
|
100
|
+
records = proto_resources
|
101
|
+
records = records.uniq if query.unique?
|
102
|
+
records = query.match_records(records)
|
103
|
+
records = query.sort_records(records)
|
104
|
+
|
96
105
|
|
97
106
|
records
|
98
107
|
end
|
@@ -123,7 +132,10 @@ module DataMapper
|
|
123
132
|
end
|
124
133
|
|
125
134
|
def query(query_call, query_limit = 999999999)
|
126
|
-
|
135
|
+
SDBTools::Operation.new(sdb, :select, query_call).inject([]){
|
136
|
+
|a, results|
|
137
|
+
a.concat(results[:items].map{|i| i.values.first})
|
138
|
+
}[0...query_limit]
|
127
139
|
end
|
128
140
|
|
129
141
|
def aggregate(query)
|
@@ -147,7 +159,7 @@ module DataMapper
|
|
147
159
|
token = :none
|
148
160
|
begin
|
149
161
|
results = sdb.get_attributes(domain, '__dm_consistency_token', '__dm_consistency_token')
|
150
|
-
tokens = results[:attributes]['__dm_consistency_token']
|
162
|
+
tokens = Array(results[:attributes]['__dm_consistency_token'])
|
151
163
|
end until tokens.include?(@current_consistency_token)
|
152
164
|
end
|
153
165
|
|
@@ -227,43 +239,59 @@ module DataMapper
|
|
227
239
|
else
|
228
240
|
raise ArgumentError, "Unsupported inclusion op: #{op.value.inspect}"
|
229
241
|
end
|
242
|
+
when :or
|
243
|
+
# TODO There's no reason not to support OR
|
244
|
+
unsupported_conditions << op
|
230
245
|
else raise "Invalid query op: #{op.inspect}"
|
231
246
|
end
|
232
247
|
end
|
233
248
|
[conditions,order,unsupported_conditions]
|
234
249
|
end
|
235
250
|
|
236
|
-
def select(query_call, query_limit)
|
237
|
-
items = []
|
238
|
-
time = Benchmark.realtime do
|
239
|
-
sdb_continuation_key = nil
|
240
|
-
while (results = sdb.select(query_call, sdb_continuation_key)) do
|
241
|
-
sdb_continuation_key = results[:next_token]
|
242
|
-
items += results[:items]
|
243
|
-
break if items.length > query_limit
|
244
|
-
break if sdb_continuation_key.nil?
|
245
|
-
end
|
246
|
-
end; DataMapper.logger.debug(format_log_entry(query_call, time))
|
247
|
-
items[0...query_limit]
|
248
|
-
end
|
249
|
-
|
250
251
|
#gets all results or proper number of results depending on the :limit
|
251
252
|
def get_results(query, conditions, order)
|
252
253
|
fields_to_request = query.fields.map{|f| f.field}
|
253
254
|
fields_to_request << DmAdapterSimpledb::Record::METADATA_KEY
|
254
|
-
|
255
|
-
|
256
|
-
|
257
|
-
|
258
|
-
|
259
|
-
|
260
|
-
|
255
|
+
|
256
|
+
selection = SDBTools::Selection.new(
|
257
|
+
sdb,
|
258
|
+
domain,
|
259
|
+
:attributes => fields_to_request)
|
260
|
+
|
261
|
+
if query.order && query.order.length > 0
|
262
|
+
query_object = query.order[0]
|
263
|
+
#anything sorted on must be a condition for SDB
|
264
|
+
conditions << "#{query_object.target.name} IS NOT NULL"
|
265
|
+
selection.order_by = query_object.target.name
|
266
|
+
selection.order = case query_object.operator
|
267
|
+
when :asc then :ascending
|
268
|
+
when :desc then :descending
|
269
|
+
else raise "Unrecognized sort direction"
|
270
|
+
end
|
271
|
+
end
|
272
|
+
selection.conditions = conditions.compact.inject([]){|conds, cond|
|
273
|
+
conds << "AND" unless conds.empty?
|
274
|
+
conds << cond
|
275
|
+
}
|
276
|
+
if query.limit.nil?
|
277
|
+
selection.limit = :none
|
261
278
|
else
|
262
|
-
|
263
|
-
|
264
|
-
|
279
|
+
selection.limit = query.limit
|
280
|
+
end
|
281
|
+
unless query.offset.nil?
|
282
|
+
selection.offset = query.offset
|
265
283
|
end
|
266
|
-
|
284
|
+
|
285
|
+
items = []
|
286
|
+
time = Benchmark.realtime do
|
287
|
+
# TODO update Record to be created from name/attributes pair
|
288
|
+
selection.each do |name, value|
|
289
|
+
items << {name => value}
|
290
|
+
end
|
291
|
+
end
|
292
|
+
DataMapper.logger.debug(format_log_entry(selection.to_s, time))
|
293
|
+
|
294
|
+
items
|
267
295
|
end
|
268
296
|
|
269
297
|
# Creates an item name for a query
|
@@ -105,6 +105,12 @@ describe 'with multiple records saved' do
|
|
105
105
|
results = Hero.all(:limit => 110)
|
106
106
|
results.should have(110).entries
|
107
107
|
end
|
108
|
+
|
109
|
+
it "should be able to page through results" do
|
110
|
+
results1 = Hero.all(:limit => 10, :order => [:id.asc])
|
111
|
+
results2 = Hero.all(:offset => 9, :limit => 10, :order => [:id.asc])
|
112
|
+
results1.to_a.last.name.should be == results2.to_a.first.name
|
113
|
+
end
|
108
114
|
end
|
109
115
|
|
110
116
|
end
|
@@ -74,7 +74,20 @@ describe DataMapper::Adapters::SimpleDBAdapter do
|
|
74
74
|
])
|
75
75
|
@record = Product.first
|
76
76
|
end
|
77
|
-
|
78
77
|
end
|
79
78
|
|
79
|
+
# it "should be able to request items with an offset" do
|
80
|
+
# @sdb.should_receive(:select).
|
81
|
+
# with(/count(\*).*LIMIT 10000/, anything).
|
82
|
+
# exactly(1).times.
|
83
|
+
# ordered.
|
84
|
+
# and_return(:next_token => "TOKEN")
|
85
|
+
# @sdb.should_receive(:select).
|
86
|
+
# with(anything, "TOKEN").
|
87
|
+
# exactly(1).times.
|
88
|
+
# ordered.
|
89
|
+
# and_return(:items => [])
|
90
|
+
# @record = Product.all(:offset => 10000, :limit => 10)
|
91
|
+
# end
|
92
|
+
|
80
93
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: dm-adapter-simpledb
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.3.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Jeremy Boles
|
@@ -13,7 +13,7 @@ autorequire:
|
|
13
13
|
bindir: bin
|
14
14
|
cert_chain: []
|
15
15
|
|
16
|
-
date: 2010-01-
|
16
|
+
date: 2010-01-19 00:00:00 -05:00
|
17
17
|
default_executable:
|
18
18
|
dependencies:
|
19
19
|
- !ruby/object:Gem::Dependency
|
@@ -67,14 +67,14 @@ dependencies:
|
|
67
67
|
version: "2.0"
|
68
68
|
version:
|
69
69
|
- !ruby/object:Gem::Dependency
|
70
|
-
name:
|
70
|
+
name: sdbtools
|
71
71
|
type: :runtime
|
72
72
|
version_requirement:
|
73
73
|
version_requirements: !ruby/object:Gem::Requirement
|
74
74
|
requirements:
|
75
75
|
- - ~>
|
76
76
|
- !ruby/object:Gem::Version
|
77
|
-
version: "
|
77
|
+
version: "0.2"
|
78
78
|
version:
|
79
79
|
description: |
|
80
80
|
A DataMapper adapter for Amazon's SimpleDB service.
|