dm-adapter-simpledb 1.2.0 → 1.3.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.
- 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.
|