rdbi 0.9.1 → 1.1.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|