rdbi 0.9.1 → 1.1.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.
- checksums.yaml +7 -0
- data/.gemtest +0 -0
- data/History.txt +13 -0
- data/Manifest.txt +28 -0
- data/{README.rdoc → README.txt} +9 -9
- data/Rakefile +39 -133
- data/lib/rdbi.rb +44 -32
- data/lib/rdbi/database.rb +61 -20
- data/lib/rdbi/driver.rb +4 -1
- data/lib/rdbi/pool.rb +10 -0
- data/lib/rdbi/result.rb +94 -123
- data/lib/rdbi/schema.rb +8 -1
- data/lib/rdbi/statement.rb +22 -3
- data/lib/rdbi/types.rb +2 -0
- data/rdbi.gemspec +2 -4
- data/test/helper.rb +29 -1
- data/test/test_database.rb +95 -6
- data/test/test_pool.rb +11 -2
- data/test/test_rdbi.rb +54 -1
- data/test/test_result.rb +129 -7
- data/test/test_statement.rb +1 -1
- data/test/test_util.rb +2 -4
- metadata +201 -137
- data/.document +0 -5
- data/VERSION +0 -1
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 54de058484d15e39b1555c43dd208f2ae7d061ba
|
4
|
+
data.tar.gz: 96fd6fa385652f31d50f12cf04f2ee1b7ad4e03e
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 25751397efafcd45de071d2ed98f5669c4bf59b8070e9d64393ddc84fdd67d0e97aecbe6bc53811839dfc82f224e5dfcadefedacdc926287a10319d8b5ab06f6
|
7
|
+
data.tar.gz: eecff757dba45e463dab45b88fb553625350937c6f4847af0280651f5b128ab4e7b50b842258f22318c2c6e575bf4d4f373c2d7667694f27cde43f3ffe201b22
|
data/.gemtest
ADDED
File without changes
|
data/History.txt
ADDED
@@ -0,0 +1,13 @@
|
|
1
|
+
=== 2013-03-16 / 1.1.0
|
2
|
+
* Bump version
|
3
|
+
* [deprecation] Statement#prep_finalizer considered harmful
|
4
|
+
Internal API: driver authors, do not use. RDBI::Util offers upon_finalize!
|
5
|
+
but this may not be needed as RDBI's own finalizations now will finish()
|
6
|
+
driver sth and result set data objects.
|
7
|
+
* [bugfix] issue#33 (memory leak) addressed with new finalization and weakened
|
8
|
+
sth objects held by Result objects.
|
9
|
+
* [bugfix] Result no longer finish()es Statement (issue#34)
|
10
|
+
|
11
|
+
=== Prehistory / 2011-01-30
|
12
|
+
|
13
|
+
* First use of Hoe.
|
data/Manifest.txt
ADDED
@@ -0,0 +1,28 @@
|
|
1
|
+
.gemtest
|
2
|
+
History.txt
|
3
|
+
LICENSE
|
4
|
+
Manifest.txt
|
5
|
+
README.txt
|
6
|
+
Rakefile
|
7
|
+
docs/external-api.pdf
|
8
|
+
docs/external-api.texi
|
9
|
+
lib/rdbi.rb
|
10
|
+
lib/rdbi/cursor.rb
|
11
|
+
lib/rdbi/database.rb
|
12
|
+
lib/rdbi/driver.rb
|
13
|
+
lib/rdbi/pool.rb
|
14
|
+
lib/rdbi/result.rb
|
15
|
+
lib/rdbi/schema.rb
|
16
|
+
lib/rdbi/statement.rb
|
17
|
+
lib/rdbi/types.rb
|
18
|
+
perf/bench.rb
|
19
|
+
perf/profile.rb
|
20
|
+
rdbi.gemspec
|
21
|
+
test/helper.rb
|
22
|
+
test/test_database.rb
|
23
|
+
test/test_pool.rb
|
24
|
+
test/test_rdbi.rb
|
25
|
+
test/test_result.rb
|
26
|
+
test/test_statement.rb
|
27
|
+
test/test_types.rb
|
28
|
+
test/test_util.rb
|
data/{README.rdoc → README.txt}
RENAMED
@@ -44,22 +44,22 @@ path down the rabbit hole:
|
|
44
44
|
dbh = RDBI.connect(:SQLite3, :database => ":memory:")
|
45
45
|
|
46
46
|
# execute this CREATE TABLE statement:
|
47
|
-
dbh.execute("create table
|
47
|
+
dbh.execute("create table tbl (string varchar(32), number integer)")
|
48
48
|
|
49
49
|
# prepare an insert statement for execution with two placeholders:
|
50
|
-
dbh.prepare("insert into
|
50
|
+
dbh.prepare("insert into tbl (string, number) values (?, ?)") do |sth|
|
51
51
|
|
52
|
-
# and execute it with bound variables:
|
53
|
-
sth.execute(
|
54
|
-
sth.execute(
|
55
|
-
sth.execute(
|
52
|
+
# and execute it three times with bound variables:
|
53
|
+
sth.execute("foo", -37)
|
54
|
+
sth.execute("bar", 127)
|
55
|
+
sth.execute("quux", 1024)
|
56
56
|
end
|
57
57
|
|
58
58
|
# get a result handle from a select statement:
|
59
|
-
result = dbh.execute("select * from
|
59
|
+
result = dbh.execute("select * from tbl")
|
60
60
|
|
61
61
|
# and fetch the first row
|
62
|
-
result.fetch(:first) # [
|
62
|
+
result.fetch(:first) # ["foo", -37]
|
63
63
|
|
64
64
|
== What +is+ RDBI all about, anyway?
|
65
65
|
|
@@ -154,7 +154,7 @@ Aaaaaand here are some things RDBI won't do:
|
|
154
154
|
== Show me even more awesome!
|
155
155
|
|
156
156
|
# retrieve cached handles 5 times -- handles will be yielded twice if there
|
157
|
-
# is a smaller Pool size:
|
157
|
+
# is a smaller Pool size:
|
158
158
|
5.times do
|
159
159
|
RDBI.connect_cached(:SQLite3, :database => ":memory:")
|
160
160
|
end
|
data/Rakefile
CHANGED
@@ -1,147 +1,53 @@
|
|
1
|
-
|
2
|
-
require 'rake'
|
3
|
-
|
4
|
-
version = (File.exist?('VERSION') ? File.read('VERSION') : "").chomp
|
5
|
-
|
6
|
-
begin
|
7
|
-
require 'jeweler'
|
8
|
-
Jeweler::Tasks.new do |gem|
|
9
|
-
gem.name = "rdbi"
|
10
|
-
gem.summary = %Q{RDBI provides sane query-level database access with low magic.}
|
11
|
-
gem.description = %Q{RDBI is a rearchitecture of the Ruby/DBI project by its maintainer and others. It intends to fully supplant Ruby/DBI in the future for similar database access needs.}
|
12
|
-
gem.email = "erik@hollensbe.org"
|
13
|
-
gem.homepage = "http://github.com/RDBI/rdbi"
|
14
|
-
gem.authors = ["Erik Hollensbe"]
|
15
|
-
|
16
|
-
gem.add_development_dependency 'rdbi-driver-mock'
|
17
|
-
gem.add_development_dependency 'test-unit'
|
18
|
-
gem.add_development_dependency 'rdoc'
|
19
|
-
## for now, install hanna from here: http://github.com/erikh/hanna
|
20
|
-
#gem.add_development_dependency 'hanna'
|
21
|
-
gem.add_development_dependency 'fastercsv'
|
1
|
+
# -*- ruby -*-
|
22
2
|
|
23
|
-
|
24
|
-
|
25
|
-
gem.add_dependency 'typelib'
|
26
|
-
|
27
|
-
# gem is a Gem::Specification... see http://www.rubygems.org/read/chapter/20 for additional settings
|
28
|
-
end
|
29
|
-
Jeweler::GemcutterTasks.new
|
30
|
-
rescue LoadError
|
31
|
-
puts "Jeweler (or a dependency) not available. Install it with: gem install jeweler"
|
32
|
-
end
|
33
|
-
|
34
|
-
begin
|
35
|
-
gem 'test-unit'
|
36
|
-
require 'rake/testtask'
|
37
|
-
Rake::TestTask.new(:test) do |test|
|
38
|
-
test.libs << 'lib' << 'test'
|
39
|
-
test.pattern = 'test/**/test_*.rb'
|
40
|
-
test.verbose = true
|
41
|
-
end
|
42
|
-
rescue LoadError
|
43
|
-
task :test do
|
44
|
-
abort "test-unit gem is not available. In order to run test-unit, you must: sudo gem install test-unit"
|
45
|
-
end
|
46
|
-
end
|
3
|
+
require 'rubygems'
|
4
|
+
require 'hoe'
|
47
5
|
|
6
|
+
Hoe.plugins.delete :rubyforge
|
7
|
+
Hoe.plugin :git
|
8
|
+
Hoe.plugin :rcov
|
9
|
+
Hoe.plugin :roodi
|
10
|
+
Hoe.plugin :reek
|
48
11
|
|
49
|
-
|
50
|
-
|
51
|
-
Rcov::RcovTask.new do |test|
|
52
|
-
test.libs << 'test'
|
53
|
-
test.pattern = 'test/**/test_*.rb'
|
54
|
-
test.verbose = true
|
55
|
-
end
|
56
|
-
rescue LoadError
|
57
|
-
task :rcov do
|
58
|
-
abort "RCov is not available. In order to run rcov, you must: sudo gem install spicycode-rcov"
|
59
|
-
end
|
60
|
-
end
|
12
|
+
spec = Hoe.spec 'rdbi' do
|
13
|
+
developer 'Erik Hollensbe', 'erik@hollensbe.org'
|
61
14
|
|
62
|
-
|
15
|
+
self.rubyforge_name = nil
|
63
16
|
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
task :roodi do
|
72
|
-
abort "Roodi is not available. In order to run roodi, you must: sudo gem install roodi"
|
73
|
-
end
|
74
|
-
end
|
17
|
+
self.description = <<-EOF
|
18
|
+
RDBI is a database interface built out of small parts. A micro framework for
|
19
|
+
databases, RDBI works with and extends libraries like 'typelib' and 'epoxy'
|
20
|
+
to provide type conversion and binding facilities. Via a driver/adapter
|
21
|
+
system it provides database access. RDBI itself provides pooling and other
|
22
|
+
enhanced database features.
|
23
|
+
EOF
|
75
24
|
|
76
|
-
|
25
|
+
self.summary = 'RDBI is a database interface built out of small parts.'
|
26
|
+
self.urls = %w[http://github.com/rdbi/rdbi]
|
77
27
|
|
78
|
-
|
79
|
-
require 'hanna'
|
80
|
-
require 'rdoc/task'
|
81
|
-
RDoc::Task.new do |rdoc|
|
82
|
-
version = File.exist?('VERSION') ? File.read('VERSION') : ""
|
28
|
+
require_ruby_version ">= 1.8.7"
|
83
29
|
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
rdoc_missing = lambda do
|
93
|
-
abort "What, were you born in a barn? Install rdoc and hanna at http://github.com/raggi/hanna ."
|
94
|
-
end
|
95
|
-
task :rdoc, &rdoc_missing
|
96
|
-
task :clobber_rdoc, &rdoc_missing
|
97
|
-
end
|
30
|
+
extra_dev_deps << ['rdbi-driver-mock']
|
31
|
+
extra_dev_deps << ['test-unit']
|
32
|
+
extra_dev_deps << ['rdoc']
|
33
|
+
extra_dev_deps << ['hanna-nouveau']
|
34
|
+
extra_dev_deps << ['fastercsv']
|
35
|
+
extra_dev_deps << ['hoe-roodi']
|
36
|
+
extra_dev_deps << ['hoe-reek']
|
37
|
+
extra_dev_deps << ['minitest']
|
98
38
|
|
99
|
-
|
100
|
-
|
101
|
-
end
|
39
|
+
extra_deps << ['epoxy', '>= 0.3.1']
|
40
|
+
extra_deps << ['typelib']
|
102
41
|
|
103
|
-
|
42
|
+
# waiting on a patch from hoe for this
|
43
|
+
#self.extra_rdoc_args = lambda do |rd|
|
44
|
+
#rd.generator = "hanna"
|
45
|
+
#end
|
104
46
|
|
105
|
-
|
106
|
-
sh "open rdoc/index.html"
|
47
|
+
desc "install a gem without sudo"
|
107
48
|
end
|
108
49
|
|
109
|
-
|
110
|
-
|
111
|
-
task :prep => [:install]
|
112
|
-
|
113
|
-
task :prepared_insert => [:prep] do
|
114
|
-
sh "ruby -I lib perf/profile.rb prepared_insert"
|
115
|
-
end
|
116
|
-
|
117
|
-
task :insert => [:prep] do
|
118
|
-
sh "ruby -I lib perf/profile.rb insert"
|
119
|
-
end
|
120
|
-
|
121
|
-
task :raw_select => [:prep] do
|
122
|
-
sh "ruby -I lib perf/profile.rb raw_select"
|
123
|
-
end
|
124
|
-
|
125
|
-
task :res_select => [:prep] do
|
126
|
-
sh "ruby -I lib perf/profile.rb res_select"
|
127
|
-
end
|
128
|
-
|
129
|
-
task :single_fetch => [:prep] do
|
130
|
-
sh "ruby -I lib perf/profile.rb single_fetch"
|
131
|
-
end
|
132
|
-
|
133
|
-
task :unprepared_raw_select => [:prep] do
|
134
|
-
sh "ruby -I lib perf/profile.rb unprepared_raw_select"
|
135
|
-
end
|
136
|
-
|
137
|
-
task :unprepared_res_select => [:prep] do
|
138
|
-
sh "ruby -I lib perf/profile.rb unprepared_res_select"
|
139
|
-
end
|
140
|
-
|
141
|
-
task :unprepared_single_fetch => [:prep] do
|
142
|
-
sh "ruby -I lib perf/profile.rb unprepared_single_fetch"
|
143
|
-
end
|
144
|
-
end
|
50
|
+
task :install => [:gem] do
|
51
|
+
sh "gem install pkg/#{spec.name}-#{spec.version}.gem"
|
145
52
|
end
|
146
|
-
|
147
|
-
# vim: syntax=ruby ts=2 et sw=2 sts=2
|
53
|
+
# vim: syntax=ruby
|
data/lib/rdbi.rb
CHANGED
@@ -1,6 +1,9 @@
|
|
1
1
|
require 'epoxy'
|
2
2
|
|
3
3
|
module RDBI
|
4
|
+
|
5
|
+
VERSION = '1.1.0'
|
6
|
+
|
4
7
|
class << self
|
5
8
|
#
|
6
9
|
# The last database handle allocated. This may come from pooled connections or regular ones.
|
@@ -21,7 +24,8 @@ module RDBI
|
|
21
24
|
#
|
22
25
|
# connect() returns an instance of RDBI::Database. In the instance a block
|
23
26
|
# is provided, it will be called upon connection success, with the
|
24
|
-
# RDBI::Database object provided in as the first argument
|
27
|
+
# RDBI::Database object provided in as the first argument, and the
|
28
|
+
# connection will be automatically disconnected at the end of the block.
|
25
29
|
def self.connect(klass, *args)
|
26
30
|
|
27
31
|
klass = RDBI::Util.class_from_class_or_symbol(klass, self::Driver)
|
@@ -29,8 +33,13 @@ module RDBI
|
|
29
33
|
driver = klass.new(*args)
|
30
34
|
dbh = self.last_dbh = driver.new_handle
|
31
35
|
|
32
|
-
|
33
|
-
|
36
|
+
return dbh unless block_given?
|
37
|
+
|
38
|
+
begin
|
39
|
+
yield dbh
|
40
|
+
ensure
|
41
|
+
dbh.disconnect rescue nil
|
42
|
+
end
|
34
43
|
end
|
35
44
|
|
36
45
|
#
|
@@ -43,14 +52,17 @@ module RDBI
|
|
43
52
|
#
|
44
53
|
# If a pool *already* exists, your connection arguments will be ignored and
|
45
54
|
# it will instantiate from the Pool's connection arguments.
|
55
|
+
#
|
56
|
+
# If a block is provided, the connection is *not* disconnected at the end
|
57
|
+
# of the block.
|
46
58
|
def self.connect_cached(klass, *args)
|
47
59
|
args = args[0]
|
48
60
|
pool_name = args[:pool_name] || :default
|
49
61
|
|
50
62
|
dbh = nil
|
51
63
|
|
52
|
-
if RDBI::Pool[pool_name]
|
53
|
-
dbh =
|
64
|
+
if pool = RDBI::Pool[pool_name]
|
65
|
+
dbh = pool.get_dbh
|
54
66
|
else
|
55
67
|
dbh = RDBI::Pool.new(pool_name, [klass, args]).get_dbh
|
56
68
|
end
|
@@ -134,39 +146,39 @@ module RDBI::Util
|
|
134
146
|
Marshal.load(Marshal.dump(obj))
|
135
147
|
end
|
136
148
|
|
137
|
-
#
|
138
|
-
# Takes an array and appropriate boxes/deboxes it based on what was
|
139
|
-
# requested.
|
140
|
-
#
|
141
|
-
#--
|
142
|
-
# FIXME this is a really poorly performing way of doing this.
|
143
|
-
#++
|
144
|
-
def self.format_results(row_count, ary)
|
145
|
-
case row_count
|
146
|
-
when :first, :last
|
147
|
-
ary = ary[0]
|
148
|
-
return nil if ary and ary.empty?
|
149
|
-
return ary
|
150
|
-
else
|
151
|
-
return ary
|
152
|
-
end
|
153
|
-
end
|
154
|
-
|
155
149
|
def self.index_binds(args, index_map)
|
156
150
|
# FIXME exception if mixed hash/indexed binds
|
157
|
-
|
151
|
+
|
152
|
+
if args.empty? or !args.find { |x| x.kind_of?(Hash) }
|
153
|
+
return args
|
154
|
+
end
|
155
|
+
|
156
|
+
if args.kind_of?(Hash)
|
158
157
|
binds = []
|
159
|
-
|
160
|
-
if index = index_map.index(key)
|
161
|
-
binds.insert(index, args[0][key])
|
162
|
-
end
|
163
|
-
end
|
164
|
-
return binds
|
158
|
+
hash = args
|
165
159
|
else
|
166
|
-
|
160
|
+
hashes, binds = args.partition { |x| x.kind_of?(Hash) }
|
161
|
+
hash = hashes.inject({ }, :merge)
|
162
|
+
end
|
163
|
+
|
164
|
+
hash.each do |key, value|
|
165
|
+
# XXX yes, we want to *assign* here.
|
166
|
+
if index = index_map.index(key)
|
167
|
+
binds.insert(index, value)
|
168
|
+
end
|
167
169
|
end
|
170
|
+
return binds
|
168
171
|
end
|
169
|
-
|
172
|
+
|
173
|
+
def self.upon_finalize!(what, o, meth, *args)
|
174
|
+
ObjectSpace.define_finalizer(what, make_fini_proc(o, meth, *args))
|
175
|
+
end
|
176
|
+
|
177
|
+
def self.make_fini_proc(obj, meth, *args)
|
178
|
+
proc { |object_id| obj.__send__(meth.to_sym, *args) rescue nil }
|
179
|
+
end
|
180
|
+
|
181
|
+
end # -- module RDBI::Util
|
170
182
|
|
171
183
|
require 'rdbi/types'
|
172
184
|
require 'rdbi/pool'
|
data/lib/rdbi/database.rb
CHANGED
@@ -22,7 +22,7 @@ class RDBI::Database
|
|
22
22
|
|
23
23
|
# the last statement handle allocated. affected by +prepare+ and +execute+.
|
24
24
|
attr_accessor :last_statement
|
25
|
-
|
25
|
+
|
26
26
|
# the last query sent, as a string.
|
27
27
|
attr_accessor :last_query
|
28
28
|
|
@@ -77,6 +77,7 @@ class RDBI::Database
|
|
77
77
|
@connected = true
|
78
78
|
@in_transaction = 0
|
79
79
|
@rewindable_result = false
|
80
|
+
@preprocess_quoter = nil
|
80
81
|
self.open_statements = { }
|
81
82
|
end
|
82
83
|
|
@@ -92,6 +93,7 @@ class RDBI::Database
|
|
92
93
|
#
|
93
94
|
def disconnect
|
94
95
|
@connected = false
|
96
|
+
# FIXME - this is not serving a useful purpose nor public API
|
95
97
|
self.open_statements.values.each { |x| x.finish if x }
|
96
98
|
self.open_statements = { }
|
97
99
|
end
|
@@ -153,53 +155,85 @@ class RDBI::Database
|
|
153
155
|
# end
|
154
156
|
#
|
155
157
|
def prepare(query)
|
156
|
-
sth =
|
158
|
+
sth = new_statement(query)
|
157
159
|
|
158
160
|
self.last_query = query
|
159
|
-
sth =
|
160
|
-
|
161
|
-
sth
|
161
|
+
self.open_statements[sth.object_id] = self.last_statement = ::WeakRef.new(sth)
|
162
|
+
|
163
|
+
return sth unless block_given?
|
162
164
|
|
163
|
-
|
165
|
+
begin
|
166
|
+
yield sth
|
167
|
+
ensure
|
168
|
+
sth.finish rescue nil
|
169
|
+
end
|
164
170
|
end
|
165
171
|
|
166
172
|
#
|
167
|
-
# Prepares and executes a statement.
|
173
|
+
# Prepares and executes a statement. Takes a string query and an optional
|
168
174
|
# number of variable type binds.
|
169
175
|
#
|
170
176
|
# ex:
|
171
177
|
# res = dbh.execute("select * from foo where item = ?", "an item")
|
172
178
|
# ary = res.to_a
|
173
179
|
#
|
174
|
-
#
|
175
|
-
#
|
180
|
+
# If invoked with a block, the result handle will be yielded and the handle
|
181
|
+
# and statement will be finished at the end of the block. Use this form
|
182
|
+
# when the result handle is not needed outside the block:
|
183
|
+
#
|
176
184
|
# dbh.execute("select * from foo where item = ?", "an item") do |res|
|
177
185
|
# res.as(:Struct).fetch(:all).each do |struct|
|
178
186
|
# p struct.item
|
179
187
|
# end
|
180
188
|
# end
|
181
189
|
#
|
182
|
-
#
|
190
|
+
# Block invocation may be considerably more efficient under some database
|
191
|
+
# drivers.
|
192
|
+
#
|
193
|
+
# For DDL and other statements which return no rows, see
|
194
|
+
# #execute_modification.
|
183
195
|
#
|
184
196
|
def execute(query, *binds)
|
185
197
|
res = nil
|
186
198
|
|
187
|
-
|
188
|
-
|
189
|
-
|
199
|
+
sth = prepare(query)
|
200
|
+
begin
|
201
|
+
res = sth.execute(*binds)
|
202
|
+
rescue Exception => e
|
203
|
+
sth.finish rescue nil
|
204
|
+
raise e
|
205
|
+
end
|
190
206
|
|
191
|
-
|
192
|
-
|
207
|
+
unless block_given?
|
208
|
+
RDBI::Util.upon_finalize!(res, sth, :finish)
|
209
|
+
return res
|
193
210
|
end
|
194
211
|
|
195
|
-
|
212
|
+
begin
|
213
|
+
yield res
|
214
|
+
ensure
|
215
|
+
res.finish rescue nil
|
216
|
+
sth.finish rescue nil
|
217
|
+
end
|
196
218
|
end
|
197
219
|
|
220
|
+
#
|
221
|
+
# Prepare, execute and finish a statement, returning the number of rows
|
222
|
+
# affected (number of rows INSERTed, DELETEd, etc.).
|
223
|
+
#
|
224
|
+
# Effectively equivalent to
|
225
|
+
#
|
226
|
+
# dbh.execute(sql_stmt) do |res|
|
227
|
+
# res.affected_count
|
228
|
+
# end
|
229
|
+
#
|
230
|
+
# but likely more efficient. See also RDBI::Statement#execute_modification
|
231
|
+
#
|
198
232
|
def execute_modification(query, *binds)
|
199
|
-
|
200
|
-
|
201
|
-
|
202
|
-
|
233
|
+
sth = prepare(query)
|
234
|
+
sth.execute_modification(*binds)
|
235
|
+
ensure
|
236
|
+
sth.finish rescue nil
|
203
237
|
end
|
204
238
|
|
205
239
|
#
|
@@ -237,6 +271,13 @@ class RDBI::Database
|
|
237
271
|
ep.quote(total_hash) { |x| %Q{'#{(total_hash[x] || binds[x]).to_s.gsub(/'/, "''")}'} }
|
238
272
|
end
|
239
273
|
end
|
274
|
+
|
275
|
+
#
|
276
|
+
# Quote a single item using a consistent quoting method.
|
277
|
+
#
|
278
|
+
def quote(item)
|
279
|
+
"\'#{item.to_s}\'"
|
280
|
+
end
|
240
281
|
end
|
241
282
|
|
242
283
|
# vim: syntax=ruby ts=2 et sw=2 sts=2
|