sqlite3-ruby 0.6.0 → 0.9.0

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of sqlite3-ruby might be problematic. Click here for more details.

@@ -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
- loop do
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
- result = @driver.interrupt( @handle )
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.set_value nil
347
+ # func.result = nil
349
348
  # else
350
- # func.set_value value.split(//).sort.join
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
@@ -81,7 +81,7 @@ module SQLite3
81
81
  # can be rewound and reiterated.
82
82
  def reset( *bind_params )
83
83
  @driver.reset( @stmt.handle )
84
- @stmt.bind_params *bind_params
84
+ @stmt.bind_params( *bind_params )
85
85
  @eof = false
86
86
  commence
87
87
  end
@@ -35,7 +35,7 @@ module SQLite3
35
35
  module Version
36
36
 
37
37
  MAJOR = 0
38
- MINOR = 6
38
+ MINOR = 9
39
39
  TINY = 0
40
40
 
41
41
  STRING = [ MAJOR, MINOR, TINY ].join( "." )
@@ -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