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 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.3.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-21}
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 type
62
+ def begin_batch
63
63
  raise ActiveRecord::ActiveRecordError.new("Batch already started. Finish it before start new batch") \
64
- if defined?(@batch_type) && !@batch_type.nil?
64
+ if batch_started
65
65
 
66
- @batch_type = type
66
+ @batch_started = true
67
67
  end
68
68
 
69
- def commit_batch
70
- log({:type => @batch_type, :count => batch_pool.count }.inspect, "SimpleDB Batch Operation") do
71
- case @batch_type
72
- when :update
73
- @connection.batch_put_attributes domain_name, batch_pool
74
- when :delete
75
- @connection.batch_delete_attributes domain_name, batch_pool
76
- end
77
- clear_batch
78
- end
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
- def clear_batch
82
- batch_pool.clear
83
- @batch_type = nil
80
+ clear_batch type
81
+ end
84
82
  end
85
83
 
86
- def is_batch type
87
- type = :update if type == :insert
88
- defined?(@batch_type) && @batch_type == type
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 += "(batched)" if is_batch sql[:action]
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 is_batch :update
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 is_batch :update
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 is_batch :delete
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 = @connection.select(sql, nil, true)
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
- batch_pool << Aws::SdbInterface::Item.new(item_name, attributes, replace)
249
- if batch_pool.count == MAX_BATCH_ITEM_COUNT
250
- type = @batch_type
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
@@ -56,8 +56,8 @@ module ActiveRecord
56
56
  end
57
57
  end
58
58
 
59
- def self.batch type = :update, &block
60
- connection.begin_batch type
59
+ def self.batch &block
60
+ connection.begin_batch
61
61
  block.call
62
62
  connection.commit_batch
63
63
  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(:delete) do
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: 19
4
+ hash: 15
5
5
  prerelease: false
6
6
  segments:
7
7
  - 0
8
- - 3
8
+ - 4
9
9
  - 0
10
- version: 0.3.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-21 00:00:00 +04:00
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