rhubarb 0.2.4 → 0.2.5
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 +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"
|