sqlite3-ruby 0.6.0 → 0.9.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.
Potentially problematic release.
This version of sqlite3-ruby might be problematic. Click here for more details.
- data/doc/faq/faq.html +28 -28
- data/ext/sqlite3_api/MANIFEST +4 -0
- data/ext/sqlite3_api/extconf.rb +8 -0
- data/ext/sqlite3_api/post-clean.rb +3 -0
- data/ext/sqlite3_api/post-distclean.rb +4 -0
- data/ext/sqlite3_api/sqlite3_api.i +339 -0
- data/lib/sqlite3/database.rb +14 -12
- data/lib/sqlite3/driver/dl/driver.rb +20 -6
- data/lib/sqlite3/driver/native/driver.rb +218 -0
- data/lib/sqlite3/resultset.rb +1 -1
- data/lib/sqlite3/version.rb +1 -1
- data/test/native-vs-dl.rb +126 -0
- data/test/tc_database.rb +2 -1
- data/test/tc_integration.rb +838 -0
- data/test/tests.rb +1 -0
- metadata +15 -5
- data/lib/sqlite3/driver/dl/api.rb~ +0 -182
data/lib/sqlite3/database.rb
CHANGED
@@ -249,12 +249,12 @@ module SQLite3
|
|
249
249
|
# This always returns +nil+, making it unsuitable for queries that return
|
250
250
|
# rows.
|
251
251
|
def execute_batch( sql, *bind_vars )
|
252
|
-
|
252
|
+
sql = sql.strip
|
253
|
+
until sql.empty? do
|
253
254
|
prepare( sql ) do |stmt|
|
254
255
|
stmt.execute( *bind_vars )
|
255
|
-
sql = stmt.remainder
|
256
|
+
sql = stmt.remainder.strip
|
256
257
|
end
|
257
|
-
break if sql.length < 1
|
258
258
|
end
|
259
259
|
nil
|
260
260
|
end
|
@@ -299,8 +299,7 @@ module SQLite3
|
|
299
299
|
|
300
300
|
# Interrupts the currently executing operation, causing it to abort.
|
301
301
|
def interrupt
|
302
|
-
|
303
|
-
Error.check( result, self )
|
302
|
+
@driver.interrupt( @handle )
|
304
303
|
end
|
305
304
|
|
306
305
|
# Register a busy handler with this database instance. When a requested
|
@@ -345,9 +344,9 @@ module SQLite3
|
|
345
344
|
#
|
346
345
|
# db.create_function( "maim", 1 ) do |func, value|
|
347
346
|
# if value.nil?
|
348
|
-
# func.
|
347
|
+
# func.result = nil
|
349
348
|
# else
|
350
|
-
# func.
|
349
|
+
# func.result = value.split(//).sort.join
|
351
350
|
# end
|
352
351
|
# end
|
353
352
|
#
|
@@ -359,7 +358,7 @@ module SQLite3
|
|
359
358
|
begin
|
360
359
|
block.call( FunctionProxy.new( @driver, func ),
|
361
360
|
*args.map{|v| Value.new(self,v)} )
|
362
|
-
rescue Exception => e
|
361
|
+
rescue StandardError, Exception => e
|
363
362
|
@driver.result_error( func,
|
364
363
|
"#{e.message} (#{e.class})", -1 )
|
365
364
|
end
|
@@ -513,8 +512,8 @@ module SQLite3
|
|
513
512
|
ctx[ :handler ] ||= handler.new
|
514
513
|
begin
|
515
514
|
ctx[ :handler ].step( FunctionProxy.new( @driver, func, ctx ),
|
516
|
-
*args )
|
517
|
-
rescue Exception => e
|
515
|
+
*args.map{|v| Value.new(self,v)} )
|
516
|
+
rescue Exception, StandardError => e
|
518
517
|
ctx[ :__error ] = e
|
519
518
|
end
|
520
519
|
end
|
@@ -548,6 +547,9 @@ module SQLite3
|
|
548
547
|
# by SQLite, so attempting to nest a transaction will result in a runtime
|
549
548
|
# exception.
|
550
549
|
#
|
550
|
+
# The +mode+ parameter may be either <tt>:deferred</tt> (the default),
|
551
|
+
# <tt>:immediate</tt>, or <tt>:exclusive</tt>.
|
552
|
+
#
|
551
553
|
# If a block is given, the database instance is yielded to it, and the
|
552
554
|
# transaction is committed when the block terminates. If the block
|
553
555
|
# raises an exception, a rollback will be performed instead. Note that if
|
@@ -557,8 +559,8 @@ module SQLite3
|
|
557
559
|
# If a block is not given, it is the caller's responsibility to end the
|
558
560
|
# transaction explicitly, either by calling #commit, or by calling
|
559
561
|
# #rollback.
|
560
|
-
def transaction
|
561
|
-
execute "begin transaction"
|
562
|
+
def transaction( mode = :deferred )
|
563
|
+
execute "begin #{mode.to_s} transaction"
|
562
564
|
@transaction_active = true
|
563
565
|
|
564
566
|
if block_given?
|
@@ -48,7 +48,7 @@ class DL::PtrData
|
|
48
48
|
def to_object
|
49
49
|
n = to_s(4).unpack("L").first
|
50
50
|
return nil if n < 1
|
51
|
-
ObjectSpace._id2ref(n)
|
51
|
+
ObjectSpace._id2ref(n) rescue self.to_s
|
52
52
|
end
|
53
53
|
|
54
54
|
def set_object(obj)
|
@@ -170,7 +170,7 @@ module SQLite3 ; module Driver ; module DL
|
|
170
170
|
|
171
171
|
unless @trace_handler_callback
|
172
172
|
@trace_handler_callback = ::DL.callback( "IPS" ) do |cookie,sql|
|
173
|
-
@trace_handler.call( cookie, sql ) || 0
|
173
|
+
@trace_handler.call( cookie ? cookie.to_object : nil, sql ) || 0
|
174
174
|
end
|
175
175
|
end
|
176
176
|
|
@@ -218,7 +218,7 @@ module SQLite3 ; module Driver ; module DL
|
|
218
218
|
def aggregate_context( context )
|
219
219
|
ptr = API.sqlite3_aggregate_context( context, 4 )
|
220
220
|
ptr.free = nil
|
221
|
-
obj = ptr.to_object
|
221
|
+
obj = ( ptr ? ptr.to_object : nil )
|
222
222
|
if obj.nil?
|
223
223
|
obj = Hash.new
|
224
224
|
ptr.set_object obj
|
@@ -237,6 +237,21 @@ module SQLite3 ; module Driver ; module DL
|
|
237
237
|
API.send( method, stmt, index, s, s.length, TRANSIENT )
|
238
238
|
end
|
239
239
|
|
240
|
+
def column_text( stmt, column )
|
241
|
+
result = API.sqlite3_column_text( stmt, column )
|
242
|
+
result ? result.to_s : nil
|
243
|
+
end
|
244
|
+
|
245
|
+
def column_name( stmt, column )
|
246
|
+
result = API.sqlite3_column_name( stmt, column )
|
247
|
+
result ? result.to_s : nil
|
248
|
+
end
|
249
|
+
|
250
|
+
def column_decltype( stmt, column )
|
251
|
+
result = API.sqlite3_column_decltype( stmt, column )
|
252
|
+
result ? result.to_s : nil
|
253
|
+
end
|
254
|
+
|
240
255
|
def self.api_delegate( name )
|
241
256
|
define_method( name ) { |*args| API.send( "sqlite3_#{name}", *args ) }
|
242
257
|
end
|
@@ -250,13 +265,12 @@ module SQLite3 ; module Driver ; module DL
|
|
250
265
|
api_delegate :busy_timeout
|
251
266
|
api_delegate :changes
|
252
267
|
api_delegate :close
|
268
|
+
api_delegate :column_bytes
|
269
|
+
api_delegate :column_bytes16
|
253
270
|
api_delegate :column_count
|
254
|
-
api_delegate :column_decltype
|
255
271
|
api_delegate :column_double
|
256
272
|
api_delegate :column_int
|
257
273
|
api_delegate :column_int64
|
258
|
-
api_delegate :column_name
|
259
|
-
api_delegate :column_text
|
260
274
|
api_delegate :column_type
|
261
275
|
api_delegate :data_count
|
262
276
|
api_delegate :errcode
|
@@ -0,0 +1,218 @@
|
|
1
|
+
#--
|
2
|
+
# =============================================================================
|
3
|
+
# Copyright (c) 2004, Jamis Buck (jgb3@email.byu.edu)
|
4
|
+
# All rights reserved.
|
5
|
+
#
|
6
|
+
# Redistribution and use in source and binary forms, with or without
|
7
|
+
# modification, are permitted provided that the following conditions are met:
|
8
|
+
#
|
9
|
+
# * Redistributions of source code must retain the above copyright notice,
|
10
|
+
# this list of conditions and the following disclaimer.
|
11
|
+
#
|
12
|
+
# * Redistributions in binary form must reproduce the above copyright
|
13
|
+
# notice, this list of conditions and the following disclaimer in the
|
14
|
+
# documentation and/or other materials provided with the distribution.
|
15
|
+
#
|
16
|
+
# * The names of its contributors may not be used to endorse or promote
|
17
|
+
# products derived from this software without specific prior written
|
18
|
+
# permission.
|
19
|
+
#
|
20
|
+
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
21
|
+
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
22
|
+
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
23
|
+
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
|
24
|
+
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
25
|
+
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
26
|
+
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
27
|
+
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
28
|
+
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
29
|
+
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
30
|
+
# =============================================================================
|
31
|
+
#++
|
32
|
+
|
33
|
+
require 'sqlite3_api'
|
34
|
+
|
35
|
+
module SQLite3 ; module Driver ; module Native
|
36
|
+
|
37
|
+
class Driver
|
38
|
+
|
39
|
+
def initialize
|
40
|
+
@callback_data = Hash.new
|
41
|
+
end
|
42
|
+
|
43
|
+
def complete?( sql, utf16=false )
|
44
|
+
API.send( utf16 ? :sqlite3_complete16 : :sqlite3_complete, sql ) != 0
|
45
|
+
end
|
46
|
+
|
47
|
+
def busy_handler( db, data=nil, &block )
|
48
|
+
if block
|
49
|
+
cb = API::CallbackData.new
|
50
|
+
cb.proc = block
|
51
|
+
cb.data = data
|
52
|
+
end
|
53
|
+
|
54
|
+
API.sqlite3_busy_handler( db,
|
55
|
+
block ? API::Sqlite3_ruby_busy_handler : nil, cb )
|
56
|
+
end
|
57
|
+
|
58
|
+
def set_authorizer( db, data=nil, &block )
|
59
|
+
if block
|
60
|
+
cb = API::CallbackData.new
|
61
|
+
cb.proc = block
|
62
|
+
cb.data = data
|
63
|
+
end
|
64
|
+
|
65
|
+
API.sqlite3_set_authorizer( db,
|
66
|
+
block ? API::Sqlite3_ruby_authorizer : nil, cb )
|
67
|
+
end
|
68
|
+
|
69
|
+
def trace( db, data=nil, &block )
|
70
|
+
if block
|
71
|
+
cb = API::CallbackData.new
|
72
|
+
cb.proc = block
|
73
|
+
cb.data = data
|
74
|
+
end
|
75
|
+
|
76
|
+
API.sqlite3_trace( db,
|
77
|
+
block ? API::Sqlite3_ruby_trace : nil, cb )
|
78
|
+
end
|
79
|
+
|
80
|
+
def open( filename, utf16=false )
|
81
|
+
API.send( utf16 ? :sqlite3_open16 : :sqlite3_open, filename )
|
82
|
+
end
|
83
|
+
|
84
|
+
def errmsg( db, utf16=false )
|
85
|
+
API.send( utf16 ? :sqlite3_errmsg16 : :sqlite3_errmsg, db )
|
86
|
+
end
|
87
|
+
|
88
|
+
def prepare( db, sql, utf16=false )
|
89
|
+
API.send( ( utf16 ? :sqlite3_prepare16 : :sqlite3_prepare ),
|
90
|
+
db, sql )
|
91
|
+
end
|
92
|
+
|
93
|
+
def bind_text( stmt, index, value, utf16=false )
|
94
|
+
API.send( ( utf16 ? :sqlite3_bind_text16 : :sqlite3_bind_text ),
|
95
|
+
stmt, index, value )
|
96
|
+
end
|
97
|
+
|
98
|
+
def column_name( stmt, index, utf16=false )
|
99
|
+
API.send( ( utf16 ? :sqlite3_column_name16 : :sqlite3_column_name ),
|
100
|
+
stmt, index )
|
101
|
+
end
|
102
|
+
|
103
|
+
def column_decltype( stmt, index, utf16=false )
|
104
|
+
API.send(
|
105
|
+
( utf16 ? :sqlite3_column_decltype16 : :sqlite3_column_decltype ),
|
106
|
+
stmt, index )
|
107
|
+
end
|
108
|
+
|
109
|
+
def column_text( stmt, index, utf16=false )
|
110
|
+
API.send( ( utf16 ? :sqlite3_column_text16 : :sqlite3_column_text ),
|
111
|
+
stmt, index )
|
112
|
+
end
|
113
|
+
|
114
|
+
def create_function( db, name, args, text, cookie, func, step, final )
|
115
|
+
if func || ( step && final )
|
116
|
+
cb = API::CallbackData.new
|
117
|
+
cb.proc = cb.proc2 = nil
|
118
|
+
cb.data = cookie
|
119
|
+
@callback_data[ name ] = cb
|
120
|
+
else
|
121
|
+
@callback_data.delete( name )
|
122
|
+
end
|
123
|
+
|
124
|
+
if func
|
125
|
+
cb.proc = func
|
126
|
+
|
127
|
+
func = API::Sqlite3_ruby_function_step
|
128
|
+
step = final = nil
|
129
|
+
elsif step && final
|
130
|
+
cb.proc = step
|
131
|
+
cb.proc2 = final
|
132
|
+
|
133
|
+
func = nil
|
134
|
+
step = API::Sqlite3_ruby_function_step
|
135
|
+
final = API::Sqlite3_ruby_function_final
|
136
|
+
end
|
137
|
+
|
138
|
+
API.sqlite3_create_function( db, name, args, text, cb, func, step, final )
|
139
|
+
end
|
140
|
+
|
141
|
+
def value_text( value, utf16=false )
|
142
|
+
method = case utf16
|
143
|
+
when nil, false then :sqlite3_value_text
|
144
|
+
when :le then :sqlite3_value_text16le
|
145
|
+
when :be then :sqlite3_value_text16be
|
146
|
+
else :sqlite3_value_text16
|
147
|
+
end
|
148
|
+
|
149
|
+
API.send( method, value )
|
150
|
+
end
|
151
|
+
|
152
|
+
def result_text( context, result, utf16=false )
|
153
|
+
method = case utf16
|
154
|
+
when nil, false then :sqlite3_result_text
|
155
|
+
when :le then :sqlite3_result_text16le
|
156
|
+
when :be then :sqlite3_result_text16be
|
157
|
+
else :sqlite3_result_text16
|
158
|
+
end
|
159
|
+
|
160
|
+
API.send( method, context, result.to_s )
|
161
|
+
end
|
162
|
+
|
163
|
+
def result_error( context, value, utf16=false )
|
164
|
+
API.send( ( utf16 ? :sqlite3_result_error16 : :sqlite3_result_error ),
|
165
|
+
context, value )
|
166
|
+
end
|
167
|
+
|
168
|
+
def self.api_delegate( name )
|
169
|
+
define_method( name ) { |*args| API.send( "sqlite3_#{name}", *args ) }
|
170
|
+
end
|
171
|
+
|
172
|
+
api_delegate :libversion
|
173
|
+
api_delegate :close
|
174
|
+
api_delegate :last_insert_rowid
|
175
|
+
api_delegate :changes
|
176
|
+
api_delegate :total_changes
|
177
|
+
api_delegate :interrupt
|
178
|
+
api_delegate :busy_timeout
|
179
|
+
api_delegate :errcode
|
180
|
+
api_delegate :bind_blob
|
181
|
+
api_delegate :bind_double
|
182
|
+
api_delegate :bind_int
|
183
|
+
api_delegate :bind_int64
|
184
|
+
api_delegate :bind_null
|
185
|
+
api_delegate :bind_parameter_count
|
186
|
+
api_delegate :bind_parameter_name
|
187
|
+
api_delegate :bind_parameter_index
|
188
|
+
api_delegate :column_count
|
189
|
+
api_delegate :step
|
190
|
+
api_delegate :data_count
|
191
|
+
api_delegate :column_blob
|
192
|
+
api_delegate :column_bytes
|
193
|
+
api_delegate :column_bytes16
|
194
|
+
api_delegate :column_double
|
195
|
+
api_delegate :column_int
|
196
|
+
api_delegate :column_int64
|
197
|
+
api_delegate :column_type
|
198
|
+
api_delegate :finalize
|
199
|
+
api_delegate :reset
|
200
|
+
api_delegate :aggregate_count
|
201
|
+
api_delegate :value_blob
|
202
|
+
api_delegate :value_bytes
|
203
|
+
api_delegate :value_bytes16
|
204
|
+
api_delegate :value_double
|
205
|
+
api_delegate :value_int
|
206
|
+
api_delegate :value_int64
|
207
|
+
api_delegate :value_type
|
208
|
+
api_delegate :result_blob
|
209
|
+
api_delegate :result_double
|
210
|
+
api_delegate :result_int
|
211
|
+
api_delegate :result_int64
|
212
|
+
api_delegate :result_null
|
213
|
+
api_delegate :result_value
|
214
|
+
api_delegate :aggregate_context
|
215
|
+
|
216
|
+
end
|
217
|
+
|
218
|
+
end ; end ; end
|
data/lib/sqlite3/resultset.rb
CHANGED
data/lib/sqlite3/version.rb
CHANGED
@@ -0,0 +1,126 @@
|
|
1
|
+
$:.unshift "../lib", "../ext/sqlite3_api"
|
2
|
+
|
3
|
+
require 'sqlite3'
|
4
|
+
|
5
|
+
require 'benchmark'
|
6
|
+
|
7
|
+
N = 1000
|
8
|
+
|
9
|
+
$VERBOSE=nil
|
10
|
+
|
11
|
+
puts "database creation..."
|
12
|
+
Benchmark.bm( 7 ) do |x|
|
13
|
+
x.report('dl') do
|
14
|
+
N.times do
|
15
|
+
File.delete "test.db" rescue nil
|
16
|
+
SQLite3::Database.open( "test.db", :driver => "DL" ).close
|
17
|
+
end
|
18
|
+
end
|
19
|
+
x.report('native') do
|
20
|
+
N.times do
|
21
|
+
File.delete "test.db" rescue nil
|
22
|
+
SQLite3::Database.open( "test.db", :driver => "Native" ).close
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
File.delete "test.db" rescue nil
|
27
|
+
|
28
|
+
SQLite3::Database.open( "test.db" ).close
|
29
|
+
|
30
|
+
puts
|
31
|
+
puts "database open..."
|
32
|
+
Benchmark.bm( 7 ) do |x|
|
33
|
+
x.report('dl') do
|
34
|
+
N.times do
|
35
|
+
SQLite3::Database.open( "test.db", :driver => "DL" ).close
|
36
|
+
end
|
37
|
+
end
|
38
|
+
x.report('native') do
|
39
|
+
N.times do
|
40
|
+
SQLite3::Database.open( "test.db", :driver => "Native" ).close
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
File.delete "test.db" rescue nil
|
45
|
+
|
46
|
+
dl = SQLite3::Database.open( "test-dl.db", :driver => "DL" )
|
47
|
+
native = SQLite3::Database.open( "test-native.db", :driver => "Native" )
|
48
|
+
|
49
|
+
dl.execute "create table foo (a,b)"
|
50
|
+
native.execute "create table foo (a,b)"
|
51
|
+
|
52
|
+
puts
|
53
|
+
puts "insertions"
|
54
|
+
Benchmark.bm( 7 ) do |x|
|
55
|
+
x.report('dl') do
|
56
|
+
dl.transaction do
|
57
|
+
N.times do |i|
|
58
|
+
dl.execute "insert into foo values (#{i}, #{i+1})"
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
x.report('native') do
|
63
|
+
native.transaction do
|
64
|
+
N.times do |i|
|
65
|
+
native.execute "insert into foo values (#{i}, #{i+1})"
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
puts
|
72
|
+
puts "insertions using prepared statement"
|
73
|
+
Benchmark.bm( 7 ) do |x|
|
74
|
+
x.report('dl') do
|
75
|
+
dl.transaction do
|
76
|
+
dl.prepare "insert into foo values (?,?)" do |stmt|
|
77
|
+
N.times { |i| stmt.execute i, i+1 }
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
81
|
+
x.report('native') do
|
82
|
+
native.transaction do
|
83
|
+
native.prepare( "insert into foo values (?,?)" ) do |stmt|
|
84
|
+
N.times { |i| stmt.execute i, i+1 }
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
dl.close
|
91
|
+
native.close
|
92
|
+
File.delete "test-dl.db" rescue nil
|
93
|
+
File.delete "test-native.db" rescue nil
|
94
|
+
|
95
|
+
dl = SQLite3::Database.open( "test-dl.db", :driver => "DL" )
|
96
|
+
native = SQLite3::Database.open( "test-native.db", :driver => "Native" )
|
97
|
+
|
98
|
+
dl.execute "create table foo (a,b)"
|
99
|
+
dl.execute "insert into foo values (1,2)"
|
100
|
+
dl.execute "insert into foo values (3,4)"
|
101
|
+
dl.execute "insert into foo values (5,6)"
|
102
|
+
|
103
|
+
native.execute "create table foo (a,b)"
|
104
|
+
native.execute "insert into foo values (1,2)"
|
105
|
+
native.execute "insert into foo values (3,4)"
|
106
|
+
native.execute "insert into foo values (5,6)"
|
107
|
+
|
108
|
+
puts
|
109
|
+
puts "queries"
|
110
|
+
Benchmark.bm( 7 ) do |x|
|
111
|
+
x.report('dl') do
|
112
|
+
N.times do
|
113
|
+
dl.execute "select * from foo"
|
114
|
+
end
|
115
|
+
end
|
116
|
+
x.report('native') do
|
117
|
+
N.times do
|
118
|
+
native.execute "select * from foo"
|
119
|
+
end
|
120
|
+
end
|
121
|
+
end
|
122
|
+
|
123
|
+
dl.close
|
124
|
+
native.close
|
125
|
+
File.delete "test-dl.db" rescue nil
|
126
|
+
File.delete "test-native.db" rescue nil
|