rhubarb 0.2.4 → 0.2.5

Sign up to get free protection for your applications and to get access to all the features.
data/CHANGES CHANGED
@@ -1,3 +1,9 @@
1
+ version 0.2.5
2
+
3
+ * Prepared statements are now optional to eliminate a strange bug
4
+ that appears in some environments. If you experience unusual table
5
+ locking errors, try running without prepared statements.
6
+
1
7
  version 0.2.4
2
8
 
3
9
  * More aggressive use of prepared statements, which should result
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.2.4
1
+ 0.2.5
@@ -49,28 +49,24 @@ module Rhubarb
49
49
  alias find_by_id find
50
50
 
51
51
  def find_by(arg_hash)
52
+ results = []
52
53
  arg_hash = arg_hash.dup
53
54
  valid_cols = self.colnames.intersection arg_hash.keys
54
55
  select_criteria = valid_cols.map {|col| "#{col.to_s} = #{col.inspect}"}.join(" AND ")
55
56
  arg_hash.each {|k,v| arg_hash[k] = v.row_id if v.respond_to? :row_id}
56
- find_by_text = "select * from #{table_name} where #{select_criteria} order by row_id"
57
- find_by_stmt = (db.stmts[find_by_text] ||= db.prepare(find_by_text))
58
- find_by_stmt.execute!(arg_hash).map {|tup| self.new(tup) }
57
+ db.do_query("select * from #{table_name} where #{select_criteria} order by row_id", arg_hash) {|tup| results << self.new(tup) }
58
+ results
59
59
  end
60
60
 
61
61
  # Does what it says on the tin. Since this will allocate an object for each row, it isn't recomended for huge tables.
62
62
  def find_all
63
63
  results = []
64
- find_all_text = "SELECT * from #{table_name}"
65
- find_all_stmt = (db.stmts[find_all_text] ||= db.prepare(find_all_text))
66
- find_all_stmt.execute! {|tup| results << self.new(tup)}
64
+ db.do_query("SELECT * from #{table_name}") {|tup| results << self.new(tup)}
67
65
  results
68
66
  end
69
67
 
70
68
  def delete_all
71
- da_text = "DELETE from #{table_name}"
72
- da_stmt = (db.stmts[da_text] ||= db.prepare(da_text))
73
- da_stmt.execute!
69
+ db.do_query("DELETE from #{table_name}")
74
70
  end
75
71
 
76
72
  def delete_where(arg_hash)
@@ -78,9 +74,7 @@ module Rhubarb
78
74
  valid_cols = self.colnames.intersection arg_hash.keys
79
75
  select_criteria = valid_cols.map {|col| "#{col.to_s} = #{col.inspect}"}.join(" AND ")
80
76
  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)
77
+ db.do_query("DELETE FROM #{table_name} WHERE #{select_criteria}", arg_hash)
84
78
  end
85
79
 
86
80
  # 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.
@@ -91,15 +85,16 @@ module Rhubarb
91
85
  # Declares a custom query method named +name+, and adds it to this class. The custom query method returns a list of objects corresponding to the rows returned by executing +query+ on the database. +query+ should select all fields (with +SELECT *+). If +query+ includes the string +\_\_TABLE\_\_+, it will be expanded to the table name. Typically, you will want to use +declare\_query+ instead; this method is most useful for self-joins.
92
86
  def declare_custom_query(name, query)
93
87
  klass = (class << self; self end)
88
+ processed_query = query.gsub("__TABLE__", "#{self.table_name}")
89
+
94
90
  klass.class_eval do
95
91
  define_method name.to_s do |*args|
96
92
  # handle reference parameters
97
93
  args = args.map {|arg| Util::rhubarb_fk_identity(arg)}
98
- cq_text = query.gsub("__TABLE__", "#{self.table_name}")
99
- cq_stmt = (db.stmts[cq_text] ||= db.prepare(cq_text))
100
94
 
101
- res = cq_stmt.execute!(args)
102
- res.map {|row| self.new(row) }
95
+ results = []
96
+ db.do_query(processed_query, args) {|tup| results << self.new(tup)}
97
+ results
103
98
  end
104
99
  end
105
100
  end
@@ -136,15 +131,14 @@ module Rhubarb
136
131
  klass = (class << self; self end)
137
132
  klass.class_eval do
138
133
  define_method find_method_name do |arg|
139
- fq_stmt = (self.db.stmts[find_query] ||= db.prepare(find_query))
140
- res = fq_stmt.execute!(arg)
141
- res.map {|row| self.new(row)}
134
+ results = []
135
+ db.do_query(find_query, arg) {|row| results << self.new(row)}
136
+ results
142
137
  end
143
138
 
144
139
  define_method find_first_method_name do |arg|
145
- fq_stmt = (self.db.stmts[find_query] ||= db.prepare(find_query))
146
140
  result = nil
147
- fq_stmt.execute!(arg) {|row| result = self.new(row) ; break }
141
+ db.do_query(find_query, arg) {|row| result = self.new(row) ; break }
148
142
  result
149
143
  end
150
144
  end
@@ -235,8 +229,8 @@ module Rhubarb
235
229
  end
236
230
 
237
231
  create_text = "insert into #{table_name} (#{colspec}) values (#{valspec})"
238
- create_stmt = (self.db.stmts[create_text] ||= db.prepare(create_text))
239
- create_stmt.execute!(new_row)
232
+ db.do_query(create_text, new_row)
233
+
240
234
  res = find(db.last_insert_row_id)
241
235
 
242
236
  res
@@ -297,8 +291,9 @@ module Rhubarb
297
291
 
298
292
  def find_tuple(tid)
299
293
  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]
294
+ result = nil
295
+ db.do_query(ft_text, tid) {|tup| result = tup; break}
296
+ result
302
297
  end
303
298
 
304
299
  include FindFreshest
@@ -10,10 +10,29 @@
10
10
  #
11
11
  # http://www.apache.org/licenses/LICENSE-2.0
12
12
 
13
- module Rhubarb
13
+ module Rhubarb
14
+
14
15
  module Persistence
16
+ module UsePreparedStatements
17
+ def do_query(stmt, *args, &blk)
18
+ the_stmt = (self.stmts[stmt] ||= self.prepare(stmt))
19
+ the_stmt.execute!(args, &blk)
20
+ end
21
+ end
22
+
23
+ module EschewPreparedStatements
24
+ def do_query(stmt, *args, &blk)
25
+ execute(stmt, args, &blk)
26
+ end
27
+ end
28
+
15
29
  class DbCollection < Hash
16
30
  alias orig_set []=
31
+ attr_accessor :use_prepared_stmts
32
+
33
+ def initialize
34
+ self.use_prepared_stmts = true
35
+ end
17
36
 
18
37
  def []=(key,db)
19
38
  setup_db(db) if db
@@ -31,12 +50,23 @@ module Rhubarb
31
50
  @rhubarb_stmts
32
51
  end
33
52
  end
53
+
54
+ if @use_prepared_stmts
55
+ class << db
56
+ include UsePreparedStatements
57
+ end
58
+ else
59
+ class << db
60
+ include EschewPreparedStatements
61
+ end
62
+ end
34
63
  end
35
64
  end
36
65
 
37
66
  @dbs = DbCollection.new
38
67
 
39
- def self.open(filename, which=:default)
68
+ def self.open(filename, which=:default, usePrepared=true)
69
+ dbs.use_prepared_stmts = usePrepared
40
70
  dbs[which] = SQLite3::Database.new(filename)
41
71
  end
42
72
 
@@ -62,9 +62,7 @@ module Rhubarb
62
62
  # Deletes the row corresponding to this object from the database;
63
63
  # invalidates =self= and any other objects backed by this row
64
64
  def delete
65
- delete_text = "delete from #{self.class.table_name} where row_id = ?"
66
- delete_stmt = (self.db.stmts[delete_text] ||= self.db.prepare(delete_text))
67
- delete_stmt.execute!(@row_id)
65
+ db.do_query("delete from #{self.class.table_name} where row_id = ?", @row_id)
68
66
  mark_dirty
69
67
  @tuple = nil
70
68
  @row_id = nil
@@ -121,9 +119,7 @@ module Rhubarb
121
119
  def update(attr_name, value)
122
120
  mark_dirty
123
121
 
124
- update_text = "update #{self.class.table_name} set #{attr_name} = ?, updated = ? where row_id = ?"
125
- update_stmt = (self.db.stmts[update_text] ||= self.db.prepare(update_text))
126
- update_stmt.execute!(value, Util::timestamp, @row_id)
122
+ db.do_query("update #{self.class.table_name} set #{attr_name} = ?, updated = ? where row_id = ?", value, Util::timestamp, @row_id)
127
123
  end
128
124
 
129
125
  # Resolve any fields that reference other tables, replacing row ids with referred objects
data/ruby-rhubarb.spec.in CHANGED
@@ -48,11 +48,17 @@ rm -rf %{buildroot}
48
48
  %{ruby_sitelib}/rhubarb/persistence.rb
49
49
 
50
50
  %changelog
51
+ * Wed Apr 14 2010 willb <willb@redhat> - 0.2.5-1.0
52
+ - Updated to version 0.2.5
53
+
54
+ * Wed Apr 7 2010 willb <willb@redhat> - 0.2.4-1.0
55
+ - Updated to version 0.2.4
56
+
51
57
  * Thu Feb 25 2010 willb <willb@redhat> - 0.2.3-1.0
52
- * updated to version 0.2.3 from source
58
+ - updated to version 0.2.3 from source
53
59
 
54
60
  * Thu Feb 25 2010 willb <willb@redhat> - 0.2.2-2.0
55
- * removed rubygems include
61
+ - removed rubygems include
56
62
 
57
63
  * Fri Feb 5 2010 <rrat@redhat> - 0.2.0-0.3
58
64
  - Explicitly list files
data/test/test_rhubarb.rb CHANGED
@@ -12,6 +12,7 @@
12
12
  # http://www.apache.org/licenses/LICENSE-2.0
13
13
 
14
14
  require 'helper'
15
+ require 'fileutils'
15
16
 
16
17
  class TestClass
17
18
  include Rhubarb::Persisting
@@ -92,9 +93,21 @@ class BlobTestTable
92
93
  declare_column :info, :blob
93
94
  end
94
95
 
95
- class BackendBasicTests < Test::Unit::TestCase
96
+ class PreparedStmtBackendTests < Test::Unit::TestCase
97
+ def dbfile
98
+ ENV['RHUBARB_TEST_DB'] || ":memory:"
99
+ end
100
+
101
+ def use_prepared
102
+ true
103
+ end
104
+
96
105
  def setup
97
- Rhubarb::Persistence::open(":memory:")
106
+ unless dbfile == ":memory:"
107
+ FileUtils::safe_unlink(dbfile)
108
+ end
109
+
110
+ Rhubarb::Persistence::open(dbfile, :default, use_prepared)
98
111
  klasses = []
99
112
  klasses << TestClass
100
113
  klasses << TestClass2
@@ -216,6 +229,13 @@ class BackendBasicTests < Test::Unit::TestCase
216
229
  end
217
230
  end
218
231
 
232
+ def test_delete_all
233
+ freshness_query_fixture
234
+ assert(FreshTestTable.find_all.size > 0)
235
+ FreshTestTable.delete_all
236
+ assert_equal([], FreshTestTable.find_all)
237
+ end
238
+
219
239
  def test_class_methods
220
240
  ["foo", "bar"].each do |prefix|
221
241
  ["find_by_#{prefix}", "find_first_by_#{prefix}"].each do |m|
@@ -711,3 +731,9 @@ class BackendBasicTests < Test::Unit::TestCase
711
731
  end
712
732
 
713
733
  end
734
+
735
+ class NoPreparedStmtBackendTests < PreparedStmtBackendTests
736
+ def use_prepared
737
+ false
738
+ end
739
+ end
metadata CHANGED
@@ -1,12 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rhubarb
3
3
  version: !ruby/object:Gem::Version
4
- prerelease: false
5
- segments:
6
- - 0
7
- - 2
8
- - 4
9
- version: 0.2.4
4
+ version: 0.2.5
10
5
  platform: ruby
11
6
  authors:
12
7
  - William Benton
@@ -14,37 +9,29 @@ autorequire:
14
9
  bindir: bin
15
10
  cert_chain: []
16
11
 
17
- date: 2010-03-23 00:00:00 -05:00
12
+ date: 2010-04-20 00:00:00 -05:00
18
13
  default_executable:
19
14
  dependencies:
20
15
  - !ruby/object:Gem::Dependency
21
16
  name: rspec
22
- prerelease: false
23
- requirement: &id001 !ruby/object:Gem::Requirement
17
+ type: :development
18
+ version_requirement:
19
+ version_requirements: !ruby/object:Gem::Requirement
24
20
  requirements:
25
21
  - - ">="
26
22
  - !ruby/object:Gem::Version
27
- segments:
28
- - 1
29
- - 2
30
- - 9
31
23
  version: 1.2.9
32
- type: :development
33
- version_requirements: *id001
24
+ version:
34
25
  - !ruby/object:Gem::Dependency
35
26
  name: sqlite3-ruby
36
- prerelease: false
37
- requirement: &id002 !ruby/object:Gem::Requirement
27
+ type: :runtime
28
+ version_requirement:
29
+ version_requirements: !ruby/object:Gem::Requirement
38
30
  requirements:
39
31
  - - ">="
40
32
  - !ruby/object:Gem::Version
41
- segments:
42
- - 1
43
- - 2
44
- - 2
45
33
  version: 1.2.2
46
- type: :runtime
47
- version_requirements: *id002
34
+ version:
48
35
  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.
49
36
  email: willb@redhat.com
50
37
  executables: []
@@ -88,20 +75,18 @@ required_ruby_version: !ruby/object:Gem::Requirement
88
75
  requirements:
89
76
  - - ">="
90
77
  - !ruby/object:Gem::Version
91
- segments:
92
- - 0
93
78
  version: "0"
79
+ version:
94
80
  required_rubygems_version: !ruby/object:Gem::Requirement
95
81
  requirements:
96
82
  - - ">="
97
83
  - !ruby/object:Gem::Version
98
- segments:
99
- - 0
100
84
  version: "0"
85
+ version:
101
86
  requirements: []
102
87
 
103
88
  rubyforge_project:
104
- rubygems_version: 1.3.6
89
+ rubygems_version: 1.3.5
105
90
  signing_key:
106
91
  specification_version: 3
107
92
  summary: "Rhubarb: object graph persistence, easy as pie"