activerecord-simpledb-adapter 0.3.0 → 0.4.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/README.md +12 -1
- data/activerecord-simpledb-adapter.gemspec +3 -2
- data/lib/active_record/connection_adapters/simpledb_adapter/adapter.rb +50 -36
- data/lib/active_record/connection_adapters/simpledb_adapter/base.rb +2 -2
- data/lib/arel/visitors/simpledb.rb +16 -2
- data/spec/active_record/batch_spec.rb +25 -1
- data/spec/active_record/offset_spec.rb +21 -0
- metadata +6 -4
data/README.md
CHANGED
@@ -28,6 +28,7 @@ for creating domain:
|
|
28
28
|
rake db:create
|
29
29
|
|
30
30
|
model example:
|
31
|
+
|
31
32
|
Person < ActiveRecord::Base
|
32
33
|
columns_definition do |t|
|
33
34
|
t.string :login
|
@@ -41,10 +42,20 @@ model example:
|
|
41
42
|
end
|
42
43
|
end
|
43
44
|
|
45
|
+
using batches:
|
46
|
+
|
47
|
+
#default batch type is update
|
48
|
+
Person.batch do
|
49
|
+
Person.create(some_valid_params)
|
50
|
+
end
|
51
|
+
#or for delete
|
52
|
+
Person.batch(:delete) do
|
53
|
+
person_item.destroy
|
54
|
+
end
|
55
|
+
|
44
56
|
# TODO
|
45
57
|
|
46
58
|
- Add some howtos to wiki
|
47
|
-
- Rewrite rails model generator
|
48
59
|
|
49
60
|
# LICENSE
|
50
61
|
|
@@ -5,11 +5,11 @@
|
|
5
5
|
|
6
6
|
Gem::Specification.new do |s|
|
7
7
|
s.name = %q{activerecord-simpledb-adapter}
|
8
|
-
s.version = "0.
|
8
|
+
s.version = "0.4.0"
|
9
9
|
|
10
10
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
11
|
s.authors = ["Ilia Ablamonov", "Alex Gorkunov", "Cloud Castle Inc."]
|
12
|
-
s.date = %q{2011-04-
|
12
|
+
s.date = %q{2011-04-22}
|
13
13
|
s.email = %q{ilia@flamefork.ru}
|
14
14
|
s.extra_rdoc_files = [
|
15
15
|
"LICENSE.txt",
|
@@ -47,6 +47,7 @@ Gem::Specification.new do |s|
|
|
47
47
|
"spec/active_record/core_actions_spec.rb",
|
48
48
|
"spec/active_record/defaults_spec.rb",
|
49
49
|
"spec/active_record/locking_spec.rb",
|
50
|
+
"spec/active_record/offset_spec.rb",
|
50
51
|
"spec/active_record/record_attributes_spec.rb",
|
51
52
|
"spec/active_record/validates_spec.rb",
|
52
53
|
"spec/active_record/where_spec.rb",
|
@@ -59,41 +59,45 @@ module ActiveRecord
|
|
59
59
|
end
|
60
60
|
#=======================================
|
61
61
|
#======== BATCHES ==========
|
62
|
-
def begin_batch
|
62
|
+
def begin_batch
|
63
63
|
raise ActiveRecord::ActiveRecordError.new("Batch already started. Finish it before start new batch") \
|
64
|
-
if
|
64
|
+
if batch_started
|
65
65
|
|
66
|
-
@
|
66
|
+
@batch_started = true
|
67
67
|
end
|
68
68
|
|
69
|
-
def commit_batch
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
end
|
69
|
+
def commit_batch type = nil
|
70
|
+
count = batch_pool.inject(0) {|sum, (key, value)| sum += value.count }
|
71
|
+
log({:count => count }.inspect, "SimpleDB Batch Operation") do
|
72
|
+
pool = batch_pool[:update]
|
73
|
+
@connection.batch_put_attributes(domain_name, pool) \
|
74
|
+
if pool && (type.nil? || type == :update)
|
75
|
+
|
76
|
+
pool = batch_pool[:delete]
|
77
|
+
@connection.batch_delete_attributes(domain_name, pool) \
|
78
|
+
if pool && (type.nil? || type == :delete)
|
80
79
|
|
81
|
-
|
82
|
-
|
83
|
-
@batch_type = nil
|
80
|
+
clear_batch type
|
81
|
+
end
|
84
82
|
end
|
85
83
|
|
86
|
-
def
|
87
|
-
|
88
|
-
|
84
|
+
def clear_batch type = nil
|
85
|
+
if type.nil?
|
86
|
+
batch_pool.clear
|
87
|
+
@batch_started = false
|
88
|
+
else
|
89
|
+
batch_pool[type].clear
|
90
|
+
end
|
89
91
|
end
|
90
92
|
|
91
93
|
#===========================
|
92
94
|
attr_reader :domain_name
|
95
|
+
attr_reader :batch_started
|
93
96
|
|
94
97
|
def initialize(connection, logger, aws_key, aws_secret, domain_name, connection_parameters, config)
|
95
98
|
super(connection, logger)
|
96
99
|
@config = config
|
100
|
+
@batch_started = false
|
97
101
|
@domain_name = domain_name
|
98
102
|
@connection_parameters = [
|
99
103
|
aws_key,
|
@@ -120,30 +124,30 @@ module ActiveRecord
|
|
120
124
|
end
|
121
125
|
|
122
126
|
def execute sql, name = nil, skip_logging = false
|
123
|
-
log_title = "SimpleDB"
|
124
|
-
log_title += "
|
127
|
+
log_title = "SimpleDB (#{sql[:action]})"
|
128
|
+
log_title += " *BATCHED*" if batch_started
|
125
129
|
log sql.inspect, log_title do
|
126
130
|
case sql[:action]
|
127
131
|
when :insert
|
128
132
|
item_name = get_id sql[:attrs]
|
129
133
|
item_name = sql[:attrs][:id] = generate_id unless item_name
|
130
|
-
if
|
131
|
-
add_to_batch item_name, sql[:attrs], true
|
134
|
+
if batch_started
|
135
|
+
add_to_batch :update, item_name, sql[:attrs], true
|
132
136
|
else
|
133
137
|
@connection.put_attributes domain_name, item_name, sql[:attrs], true
|
134
138
|
end
|
135
139
|
@last_insert_id = item_name
|
136
140
|
when :update
|
137
141
|
item_name = get_id sql[:wheres], true
|
138
|
-
if
|
139
|
-
add_to_batch item_name, sql[:attrs], true
|
142
|
+
if batch_started
|
143
|
+
add_to_batch :update, item_name, sql[:attrs], true
|
140
144
|
else
|
141
145
|
@connection.put_attributes domain_name, item_name, sql[:attrs], true, sql[:wheres]
|
142
146
|
end
|
143
147
|
when :delete
|
144
148
|
item_name = get_id sql[:wheres], true
|
145
|
-
if
|
146
|
-
add_to_batch item_name
|
149
|
+
if batch_started
|
150
|
+
add_to_batch :delete, item_name
|
147
151
|
else
|
148
152
|
@connection.delete_attributes domain_name, item_name, nil, sql[:wheres]
|
149
153
|
end
|
@@ -161,7 +165,18 @@ module ActiveRecord
|
|
161
165
|
def select sql, name = nil
|
162
166
|
log sql, "SimpleDB" do
|
163
167
|
result = []
|
164
|
-
response =
|
168
|
+
response = nil
|
169
|
+
if sql.offset
|
170
|
+
first_query = sql.gsub(/LIMIT\s+\d+/, "LIMIT #{sql.offset}")
|
171
|
+
first_query.gsub!(/SELECT(.+?)FROM/, "SELECT COUNT(*) FROM")
|
172
|
+
log first_query, "SimpleDB (offset partial)" do
|
173
|
+
response = @connection.select(first_query, nil, false) #without consistent read
|
174
|
+
end
|
175
|
+
puts response[:request_id]
|
176
|
+
response = @connection.select(sql, response[:request_id], true)
|
177
|
+
else
|
178
|
+
response = @connection.select(sql, nil, true)
|
179
|
+
end
|
165
180
|
collection_name = get_collection_column_and_name(sql)
|
166
181
|
columns = columns_definition(collection_name)
|
167
182
|
|
@@ -241,15 +256,14 @@ module ActiveRecord
|
|
241
256
|
|
242
257
|
MAX_BATCH_ITEM_COUNT = 25
|
243
258
|
def batch_pool
|
244
|
-
@batch_pool ||=
|
259
|
+
@batch_pool ||= {}
|
245
260
|
end
|
246
261
|
|
247
|
-
def add_to_batch item_name, attributes = nil, replace = nil
|
248
|
-
|
249
|
-
|
250
|
-
|
251
|
-
commit_batch
|
252
|
-
begin_batch type
|
262
|
+
def add_to_batch type, item_name, attributes = nil, replace = nil
|
263
|
+
type_batch_pool = (batch_pool[type] ||= [])
|
264
|
+
type_batch_pool << Aws::SdbInterface::Item.new(item_name, attributes, replace)
|
265
|
+
if type_batch_pool.count == MAX_BATCH_ITEM_COUNT
|
266
|
+
commit_batch type
|
253
267
|
end
|
254
268
|
end
|
255
269
|
end
|
@@ -42,7 +42,14 @@ module Arel
|
|
42
42
|
collection = o.cores.first.froms.name
|
43
43
|
o.cores.first.wheres << SqlLiteral.new("`#{@connection.collection_column_name(collection)}` = #{quote(collection)}")
|
44
44
|
o.cores.first.froms = Table.new @connection.domain_name
|
45
|
-
super
|
45
|
+
query = super
|
46
|
+
query.offset = o.offset.expr if o.offset
|
47
|
+
query.limit = o.limit.expr if o.limit
|
48
|
+
query
|
49
|
+
end
|
50
|
+
|
51
|
+
def visit_Arel_Nodes_Offset o
|
52
|
+
nil
|
46
53
|
end
|
47
54
|
|
48
55
|
def visit_Arel_Nodes_Values o
|
@@ -69,7 +76,11 @@ module Arel
|
|
69
76
|
|
70
77
|
def visit_Arel_Nodes_Equality o
|
71
78
|
right = o.right ? hash_value_quote(o.right, o.left.column) : nil
|
79
|
+
begin
|
72
80
|
left = o.left.column.name
|
81
|
+
rescue
|
82
|
+
puts $!.backtrace
|
83
|
+
end
|
73
84
|
{left => right}.tap { |m|
|
74
85
|
m.override_to_s "#{visit o.left} = #{quote(o.right, o.left.column)}"
|
75
86
|
}
|
@@ -112,7 +123,10 @@ module Arel
|
|
112
123
|
VISITORS['simpledb'] = Arel::Visitors::SimpleDB
|
113
124
|
end
|
114
125
|
end
|
115
|
-
|
126
|
+
class String
|
127
|
+
attr_accessor :offset
|
128
|
+
attr_accessor :limit
|
129
|
+
end
|
116
130
|
class Object
|
117
131
|
def override_to_s s
|
118
132
|
@override_to_s = s
|
@@ -38,17 +38,41 @@ describe "SimpleDBAdapter ActiveRecord batches operation" do
|
|
38
38
|
items.each { |item| item.is_valid? }
|
39
39
|
end
|
40
40
|
|
41
|
+
it "should work with usual update statments" do
|
42
|
+
count = 5
|
43
|
+
items = []
|
44
|
+
count.times { items << Person.create_valid }
|
45
|
+
Person.batch do
|
46
|
+
items.each {|item| item.update_attributes({:login => 'test'}); item.save! }
|
47
|
+
end
|
48
|
+
items = Person.all
|
49
|
+
items.count.should == count
|
50
|
+
items.each { |item| item.login.should == 'test' }
|
51
|
+
end
|
41
52
|
#this test doesn't work with fakesdb
|
42
53
|
it "should work with usual destroy statments" do
|
43
54
|
count = 5
|
44
55
|
items = []
|
45
56
|
count.times { items << Person.create_valid }
|
46
|
-
Person.batch
|
57
|
+
Person.batch do
|
47
58
|
items.each {|item| item.destroy }
|
48
59
|
end
|
49
60
|
Person.count.should == 0
|
50
61
|
end
|
51
62
|
|
63
|
+
it "should work with diferrent statments in one batch session" do
|
64
|
+
count = 5
|
65
|
+
items = []
|
66
|
+
count.times { items << Person.create_valid }
|
67
|
+
Person.batch do
|
68
|
+
items.each do |item|
|
69
|
+
item.destroy
|
70
|
+
Person.create_valid
|
71
|
+
end
|
72
|
+
end
|
73
|
+
Person.count.should == count
|
74
|
+
end
|
75
|
+
|
52
76
|
it "should auto split to several batches when count of items more than BATCH_MAX_ITEM_COUNT" do
|
53
77
|
count = 35
|
54
78
|
Person.batch do
|
@@ -0,0 +1,21 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
#testes
|
3
|
+
describe "SimpleDBAdapter ActiveRecord offset operation" do
|
4
|
+
|
5
|
+
before :each do
|
6
|
+
ActiveRecord::Base.logger = Logger.new(STDOUT)
|
7
|
+
ActiveRecord::Base.establish_connection($config)
|
8
|
+
ActiveRecord::Base.connection.create_domain($config[:domain_name])
|
9
|
+
50.times { |i| Person.create!({:login => "login#{i}"}) }
|
10
|
+
end
|
11
|
+
|
12
|
+
after :each do
|
13
|
+
ActiveRecord::Base.connection.delete_domain($config[:domain_name])
|
14
|
+
end
|
15
|
+
|
16
|
+
it "should work" do
|
17
|
+
Person.limit(10).offset(20).all.each_with_index do |person, i|
|
18
|
+
person.login.should == "login#{i + 20}"
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: activerecord-simpledb-adapter
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 15
|
5
5
|
prerelease: false
|
6
6
|
segments:
|
7
7
|
- 0
|
8
|
-
-
|
8
|
+
- 4
|
9
9
|
- 0
|
10
|
-
version: 0.
|
10
|
+
version: 0.4.0
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- Ilia Ablamonov
|
@@ -17,7 +17,7 @@ autorequire:
|
|
17
17
|
bindir: bin
|
18
18
|
cert_chain: []
|
19
19
|
|
20
|
-
date: 2011-04-
|
20
|
+
date: 2011-04-22 00:00:00 +04:00
|
21
21
|
default_executable:
|
22
22
|
dependencies:
|
23
23
|
- !ruby/object:Gem::Dependency
|
@@ -298,6 +298,7 @@ files:
|
|
298
298
|
- spec/active_record/core_actions_spec.rb
|
299
299
|
- spec/active_record/defaults_spec.rb
|
300
300
|
- spec/active_record/locking_spec.rb
|
301
|
+
- spec/active_record/offset_spec.rb
|
301
302
|
- spec/active_record/record_attributes_spec.rb
|
302
303
|
- spec/active_record/validates_spec.rb
|
303
304
|
- spec/active_record/where_spec.rb
|
@@ -345,6 +346,7 @@ test_files:
|
|
345
346
|
- spec/active_record/core_actions_spec.rb
|
346
347
|
- spec/active_record/defaults_spec.rb
|
347
348
|
- spec/active_record/locking_spec.rb
|
349
|
+
- spec/active_record/offset_spec.rb
|
348
350
|
- spec/active_record/record_attributes_spec.rb
|
349
351
|
- spec/active_record/validates_spec.rb
|
350
352
|
- spec/active_record/where_spec.rb
|