rhubarb 0.2.3 → 0.2.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.
data/CHANGES CHANGED
@@ -1,4 +1,15 @@
1
- version 0.2.3
1
+ version 0.2.4
2
+
3
+ * More aggressive use of prepared statements, which should result
4
+ in more speedups. (In particular, finding tuples by identity now
5
+ uses a prepared statement.)
6
+
7
+ * Persisting#to_hash method added.
8
+
9
+ * delete_where method added to persisting classes; it enables deleting
10
+ many rows satisfying some criterion in a single query.
11
+
12
+ version 0.2.3 (20bee926a142d505441716762a72a82cbfb87378)
2
13
 
3
14
  * Rhubarb now uses prepared statements almost exclusively. This
4
15
  should result in an appreciable speedup (I observed around 10% on
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.2.3
1
+ 0.2.4
@@ -68,7 +68,19 @@ module Rhubarb
68
68
  end
69
69
 
70
70
  def delete_all
71
- self.db.execute("DELETE from #{table_name}")
71
+ da_text = "DELETE from #{table_name}"
72
+ da_stmt = (db.stmts[da_text] ||= db.prepare(da_text))
73
+ da_stmt.execute!
74
+ end
75
+
76
+ def delete_where(arg_hash)
77
+ arg_hash = arg_hash.dup
78
+ valid_cols = self.colnames.intersection arg_hash.keys
79
+ select_criteria = valid_cols.map {|col| "#{col.to_s} = #{col.inspect}"}.join(" AND ")
80
+ arg_hash.each {|k,v| arg_hash[k] = v.row_id if v.respond_to? :row_id}
81
+ dw_text = "DELETE FROM #{table_name} WHERE #{select_criteria}"
82
+ dw_stmt = (db.stmts[dw_text] ||= db.prepare(dw_text))
83
+ dw_stmt.execute!(arg_hash)
72
84
  end
73
85
 
74
86
  # Declares a query method named +name+ and adds it to this class. The query method returns a list of objects corresponding to the rows returned by executing "+SELECT * FROM+ _table_ +WHERE+ _query_" on the database.
@@ -109,7 +121,7 @@ module Rhubarb
109
121
 
110
122
  find_method_name = "find_by_#{cname}".to_sym
111
123
  find_first_method_name = "find_first_by_#{cname}".to_sym
112
- find_query = "select * from #{table_name} where #{cname} = ?"
124
+ find_query = "select * from #{table_name} where #{cname} = ? order by row_id"
113
125
 
114
126
  get_method_name = "#{cname}".to_sym
115
127
  set_method_name = "#{cname}=".to_sym
@@ -124,13 +136,16 @@ module Rhubarb
124
136
  klass = (class << self; self end)
125
137
  klass.class_eval do
126
138
  define_method find_method_name do |arg|
127
- res = self.db.execute(find_query, arg)
139
+ fq_stmt = (self.db.stmts[find_query] ||= db.prepare(find_query))
140
+ res = fq_stmt.execute!(arg)
128
141
  res.map {|row| self.new(row)}
129
142
  end
130
143
 
131
144
  define_method find_first_method_name do |arg|
132
- res = self.db.get_first_row(find_query, arg)
133
- res ? self.new(res) : nil
145
+ fq_stmt = (self.db.stmts[find_query] ||= db.prepare(find_query))
146
+ result = nil
147
+ fq_stmt.execute!(arg) {|row| result = self.new(row) ; break }
148
+ result
134
149
  end
135
150
  end
136
151
 
@@ -281,7 +296,9 @@ module Rhubarb
281
296
  end
282
297
 
283
298
  def find_tuple(tid)
284
- self.db.get_first_row("select * from #{table_name} where row_id = ?", tid)
299
+ ft_text = "select * from #{table_name} where row_id = ?"
300
+ ft_stmt = (self.db.stmts[ft_text] ||= db.prepare(ft_text))
301
+ return ft_stmt.execute!(tid)[0]
285
302
  end
286
303
 
287
304
  include FindFreshest
@@ -70,6 +70,14 @@ module Rhubarb
70
70
  @row_id = nil
71
71
  end
72
72
 
73
+ def to_hash
74
+ result = {}
75
+ @tuple.each_pair do |key, value|
76
+ result[key.to_sym] = value unless key.class == Fixnum
77
+ end
78
+ result
79
+ end
80
+
73
81
  ## Begin private methods
74
82
 
75
83
  private
@@ -132,6 +140,5 @@ module Rhubarb
132
140
  end
133
141
  end
134
142
  end
135
-
136
143
  end
137
144
  end
data/test/test_rhubarb.rb CHANGED
@@ -171,6 +171,41 @@ class BackendBasicTests < Test::Unit::TestCase
171
171
  end
172
172
  end
173
173
  end
174
+
175
+ def test_to_hash
176
+ (0..5).each do |foo|
177
+ ("A".."C").each do |bar|
178
+ TestClass.create(:foo=>foo, :bar=>bar)
179
+ end
180
+ end
181
+
182
+ TestClass.find_all.each do |tc|
183
+ tch = tc.to_hash
184
+ [:foo,:bar,:created,:updated].each do |msg|
185
+ assert_equal(tch[msg], tc.send(msg))
186
+ end
187
+ end
188
+ end
189
+
190
+ def test_delete_where
191
+ (0..10).each do |foo|
192
+ ("A".."G").each do |bar|
193
+ TestClass.create(:foo=>foo, :bar=>bar)
194
+ end
195
+ end
196
+
197
+ old_count = TestClass.count
198
+
199
+ TestClass.delete_where(:foo=>1, :bar=>"B")
200
+
201
+ assert_equal(old_count - 1, TestClass.count)
202
+ assert_equal([], TestClass.find_by(:foo=>1, :bar=>"B"))
203
+
204
+ TestClass.delete_where(:bar=>"C")
205
+ assert_equal(old_count - 12, TestClass.count)
206
+ assert_equal([], TestClass.find_by(:bar=>"C"))
207
+
208
+ end
174
209
 
175
210
  def test_instance_methods_dont_include_class_methods
176
211
  ["foo", "bar"].each do |prefix|
metadata CHANGED
@@ -1,7 +1,12 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rhubarb
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.3
4
+ prerelease: false
5
+ segments:
6
+ - 0
7
+ - 2
8
+ - 4
9
+ version: 0.2.4
5
10
  platform: ruby
6
11
  authors:
7
12
  - William Benton
@@ -9,29 +14,37 @@ autorequire:
9
14
  bindir: bin
10
15
  cert_chain: []
11
16
 
12
- date: 2010-02-26 00:00:00 -06:00
17
+ date: 2010-03-23 00:00:00 -05:00
13
18
  default_executable:
14
19
  dependencies:
15
20
  - !ruby/object:Gem::Dependency
16
21
  name: rspec
17
- type: :development
18
- version_requirement:
19
- version_requirements: !ruby/object:Gem::Requirement
22
+ prerelease: false
23
+ requirement: &id001 !ruby/object:Gem::Requirement
20
24
  requirements:
21
25
  - - ">="
22
26
  - !ruby/object:Gem::Version
27
+ segments:
28
+ - 1
29
+ - 2
30
+ - 9
23
31
  version: 1.2.9
24
- version:
32
+ type: :development
33
+ version_requirements: *id001
25
34
  - !ruby/object:Gem::Dependency
26
35
  name: sqlite3-ruby
27
- type: :runtime
28
- version_requirement:
29
- version_requirements: !ruby/object:Gem::Requirement
36
+ prerelease: false
37
+ requirement: &id002 !ruby/object:Gem::Requirement
30
38
  requirements:
31
39
  - - ">="
32
40
  - !ruby/object:Gem::Version
41
+ segments:
42
+ - 1
43
+ - 2
44
+ - 2
33
45
  version: 1.2.2
34
- version:
46
+ type: :runtime
47
+ version_requirements: *id002
35
48
  description: Rhubarb is a simple object-graph persistence library implemented as a mixin. It also works with the SPQR library for straightforward object publishing over QMF.
36
49
  email: willb@redhat.com
37
50
  executables: []
@@ -75,18 +88,20 @@ required_ruby_version: !ruby/object:Gem::Requirement
75
88
  requirements:
76
89
  - - ">="
77
90
  - !ruby/object:Gem::Version
91
+ segments:
92
+ - 0
78
93
  version: "0"
79
- version:
80
94
  required_rubygems_version: !ruby/object:Gem::Requirement
81
95
  requirements:
82
96
  - - ">="
83
97
  - !ruby/object:Gem::Version
98
+ segments:
99
+ - 0
84
100
  version: "0"
85
- version:
86
101
  requirements: []
87
102
 
88
103
  rubyforge_project:
89
- rubygems_version: 1.3.5
104
+ rubygems_version: 1.3.6
90
105
  signing_key:
91
106
  specification_version: 3
92
107
  summary: "Rhubarb: object graph persistence, easy as pie"