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 +6 -0
- data/VERSION +1 -1
- data/lib/rhubarb/classmixins.rb +20 -25
- data/lib/rhubarb/persistence.rb +32 -2
- data/lib/rhubarb/persisting.rb +2 -6
- data/ruby-rhubarb.spec.in +8 -2
- data/test/test_rhubarb.rb +28 -2
- metadata +13 -28
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.
|
1
|
+
0.2.5
|
data/lib/rhubarb/classmixins.rb
CHANGED
@@ -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
|
-
|
57
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
102
|
-
|
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
|
-
|
140
|
-
|
141
|
-
|
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
|
-
|
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
|
-
|
239
|
-
|
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
|
-
|
301
|
-
|
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
|
data/lib/rhubarb/persistence.rb
CHANGED
@@ -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
|
|
data/lib/rhubarb/persisting.rb
CHANGED
@@ -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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
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
|
-
|
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
|
-
|
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-
|
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
|
-
|
23
|
-
|
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
|
-
|
33
|
-
version_requirements: *id001
|
24
|
+
version:
|
34
25
|
- !ruby/object:Gem::Dependency
|
35
26
|
name: sqlite3-ruby
|
36
|
-
|
37
|
-
|
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
|
-
|
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.
|
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"
|