sqlite3 1.3.13 → 1.4.2

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.
@@ -43,11 +43,9 @@ static VALUE initialize(VALUE self, VALUE db, VALUE sql)
43
43
  if(!db_ctx->db)
44
44
  rb_raise(rb_eArgError, "prepare called on a closed database");
45
45
 
46
- #ifdef HAVE_RUBY_ENCODING_H
47
46
  if(!UTF8_P(sql)) {
48
47
  sql = rb_str_export_to_enc(sql, rb_utf8_encoding());
49
48
  }
50
- #endif
51
49
 
52
50
  #ifdef HAVE_SQLITE3_PREPARE_V2
53
51
  status = sqlite3_prepare_v2(
@@ -110,9 +108,7 @@ static VALUE step(VALUE self)
110
108
  sqlite3_stmt *stmt;
111
109
  int value, length;
112
110
  VALUE list;
113
- #ifdef HAVE_RUBY_ENCODING_H
114
111
  rb_encoding * internal_encoding;
115
- #endif
116
112
 
117
113
  Data_Get_Struct(self, sqlite3StmtRuby, ctx);
118
114
 
@@ -120,17 +116,24 @@ static VALUE step(VALUE self)
120
116
 
121
117
  if(ctx->done_p) return Qnil;
122
118
 
123
- #ifdef HAVE_RUBY_ENCODING_H
124
119
  {
125
120
  VALUE db = rb_iv_get(self, "@connection");
126
121
  rb_funcall(db, rb_intern("encoding"), 0);
127
122
  internal_encoding = rb_default_internal_encoding();
128
123
  }
129
- #endif
130
124
 
131
125
  stmt = ctx->st;
132
126
 
133
127
  value = sqlite3_step(stmt);
128
+ if (rb_errinfo() != Qnil) {
129
+ /* some user defined function was invoked as a callback during step and
130
+ * it raised an exception that has been suppressed until step returns.
131
+ * Now re-raise it. */
132
+ VALUE exception = rb_errinfo();
133
+ rb_set_errinfo(Qnil);
134
+ rb_exc_raise(exception);
135
+ }
136
+
134
137
  length = sqlite3_column_count(stmt);
135
138
  list = rb_ary_new2((long)length);
136
139
 
@@ -148,21 +151,19 @@ static VALUE step(VALUE self)
148
151
  break;
149
152
  case SQLITE_TEXT:
150
153
  {
151
- VALUE str = rb_tainted_str_new(
154
+ VALUE str = rb_str_new(
152
155
  (const char *)sqlite3_column_text(stmt, i),
153
156
  (long)sqlite3_column_bytes(stmt, i)
154
157
  );
155
- #ifdef HAVE_RUBY_ENCODING_H
156
158
  rb_enc_associate_index(str, rb_utf8_encindex());
157
159
  if(internal_encoding)
158
160
  str = rb_str_export_to_enc(str, internal_encoding);
159
- #endif
160
161
  rb_ary_push(list, str);
161
162
  }
162
163
  break;
163
164
  case SQLITE_BLOB:
164
165
  {
165
- VALUE str = rb_tainted_str_new(
166
+ VALUE str = rb_str_new(
166
167
  (const char *)sqlite3_column_blob(stmt, i),
167
168
  (long)sqlite3_column_bytes(stmt, i)
168
169
  );
@@ -225,9 +226,7 @@ static VALUE bind_param(VALUE self, VALUE key, VALUE value)
225
226
  switch(TYPE(value)) {
226
227
  case T_STRING:
227
228
  if(CLASS_OF(value) == cSqlite3Blob
228
- #ifdef HAVE_RUBY_ENCODING_H
229
229
  || rb_enc_get_index(value) == rb_ascii8bit_encindex()
230
- #endif
231
230
  ) {
232
231
  status = sqlite3_bind_blob(
233
232
  ctx->st,
@@ -239,7 +238,6 @@ static VALUE bind_param(VALUE self, VALUE key, VALUE value)
239
238
  } else {
240
239
 
241
240
 
242
- #ifdef HAVE_RUBY_ENCODING_H
243
241
  if (UTF16_LE_P(value) || UTF16_BE_P(value)) {
244
242
  status = sqlite3_bind_text16(
245
243
  ctx->st,
@@ -252,7 +250,6 @@ static VALUE bind_param(VALUE self, VALUE key, VALUE value)
252
250
  if (!UTF8_P(value) || !USASCII_P(value)) {
253
251
  value = rb_str_encode(value, rb_enc_from_encoding(rb_utf8_encoding()), 0, Qnil);
254
252
  }
255
- #endif
256
253
  status = sqlite3_bind_text(
257
254
  ctx->st,
258
255
  index,
@@ -260,9 +257,7 @@ static VALUE bind_param(VALUE self, VALUE key, VALUE value)
260
257
  (int)RSTRING_LEN(value),
261
258
  SQLITE_TRANSIENT
262
259
  );
263
- #ifdef HAVE_RUBY_ENCODING_H
264
260
  }
265
- #endif
266
261
  }
267
262
  break;
268
263
  case T_BIGNUM: {
@@ -316,7 +311,7 @@ static VALUE reset_bang(VALUE self)
316
311
  * Resets the statement. This is typically done internally, though it might
317
312
  * occassionally be necessary to manually reset the statement.
318
313
  */
319
- static VALUE clear_bindings(VALUE self)
314
+ static VALUE clear_bindings_bang(VALUE self)
320
315
  {
321
316
  sqlite3StmtRubyPtr ctx;
322
317
 
@@ -433,7 +428,7 @@ void init_sqlite3_statement()
433
428
  rb_define_method(cSqlite3Statement, "closed?", closed_p, 0);
434
429
  rb_define_method(cSqlite3Statement, "bind_param", bind_param, 2);
435
430
  rb_define_method(cSqlite3Statement, "reset!", reset_bang, 0);
436
- rb_define_method(cSqlite3Statement, "clear_bindings!", clear_bindings, 0);
431
+ rb_define_method(cSqlite3Statement, "clear_bindings!", clear_bindings_bang, 0);
437
432
  rb_define_method(cSqlite3Statement, "step", step, 0);
438
433
  rb_define_method(cSqlite3Statement, "done?", done_p, 0);
439
434
  rb_define_method(cSqlite3Statement, "column_count", column_count, 0);
@@ -6,6 +6,7 @@ module SQLite3 ; module Constants
6
6
  UTF16BE = 3
7
7
  UTF16 = 4
8
8
  ANY = 5
9
+ DETERMINISTIC = 0x800
9
10
  end
10
11
 
11
12
  module ColumnType
@@ -54,12 +54,68 @@ module SQLite3
54
54
  # as hashes or not. By default, rows are returned as arrays.
55
55
  attr_accessor :results_as_hash
56
56
 
57
+ # call-seq: SQLite3::Database.new(file, options = {})
58
+ #
59
+ # Create a new Database object that opens the given file. If utf16
60
+ # is +true+, the filename is interpreted as a UTF-16 encoded string.
61
+ #
62
+ # By default, the new database will return result rows as arrays
63
+ # (#results_as_hash) and has type translation disabled (#type_translation=).
64
+
65
+ def initialize file, options = {}, zvfs = nil
66
+ mode = Constants::Open::READWRITE | Constants::Open::CREATE
67
+
68
+ if file.encoding == ::Encoding::UTF_16LE || file.encoding == ::Encoding::UTF_16BE || options[:utf16]
69
+ open16 file
70
+ else
71
+ # The three primary flag values for sqlite3_open_v2 are:
72
+ # SQLITE_OPEN_READONLY
73
+ # SQLITE_OPEN_READWRITE
74
+ # SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE -- always used for sqlite3_open and sqlite3_open16
75
+ mode = Constants::Open::READONLY if options[:readonly]
76
+
77
+ if options[:readwrite]
78
+ raise "conflicting options: readonly and readwrite" if options[:readonly]
79
+ mode = Constants::Open::READWRITE
80
+ end
81
+
82
+ if options[:flags]
83
+ if options[:readonly] || options[:readwrite]
84
+ raise "conflicting options: flags with readonly and/or readwrite"
85
+ end
86
+ mode = options[:flags]
87
+ end
88
+
89
+ open_v2 file.encode("utf-8"), mode, zvfs
90
+ end
91
+
92
+ @tracefunc = nil
93
+ @authorizer = nil
94
+ @encoding = nil
95
+ @busy_handler = nil
96
+ @collations = {}
97
+ @functions = {}
98
+ @results_as_hash = options[:results_as_hash]
99
+ @type_translation = options[:type_translation]
100
+ @type_translator = make_type_translator @type_translation
101
+ @readonly = mode & Constants::Open::READONLY != 0
102
+
103
+ if block_given?
104
+ begin
105
+ yield self
106
+ ensure
107
+ close
108
+ end
109
+ end
110
+ end
111
+
57
112
  def type_translation= value # :nodoc:
58
113
  warn(<<-eowarn) if $VERBOSE
59
114
  #{caller[0]} is calling SQLite3::Database#type_translation=
60
115
  SQLite3::Database#type_translation= is deprecated and will be removed
61
116
  in version 2.0.0.
62
117
  eowarn
118
+ @type_translator = make_type_translator value
63
119
  @type_translation = value
64
120
  end
65
121
  attr_reader :type_translation # :nodoc:
@@ -136,25 +192,14 @@ Support for bind parameters as *args will be removed in 2.0.0.
136
192
 
137
193
  prepare( sql ) do |stmt|
138
194
  stmt.bind_params(bind_vars)
139
- columns = stmt.columns
140
- stmt = ResultSet.new(self, stmt).to_a if type_translation
195
+ stmt = ResultSet.new self, stmt
141
196
 
142
197
  if block_given?
143
198
  stmt.each do |row|
144
- if @results_as_hash
145
- yield type_translation ? row : ordered_map_for(columns, row)
146
- else
147
- yield row
148
- end
199
+ yield row
149
200
  end
150
201
  else
151
- if @results_as_hash
152
- stmt.map { |row|
153
- type_translation ? row : ordered_map_for(columns, row)
154
- }
155
- else
156
- stmt.to_a
157
- end
202
+ stmt.to_a
158
203
  end
159
204
  end
160
205
  end
@@ -190,6 +235,9 @@ Support for bind parameters as *args will be removed in 2.0.0.
190
235
  #
191
236
  # This always returns +nil+, making it unsuitable for queries that return
192
237
  # rows.
238
+ #
239
+ # See also #execute_batch2 for additional ways of
240
+ # executing statments.
193
241
  def execute_batch( sql, bind_vars = [], *args )
194
242
  # FIXME: remove this stuff later
195
243
  unless [Array, Hash].include?(bind_vars.class)
@@ -234,6 +282,30 @@ Support for this behavior will be removed in version 2.0.0.
234
282
  nil
235
283
  end
236
284
 
285
+ # Executes all SQL statements in the given string. By contrast, the other
286
+ # means of executing queries will only execute the first statement in the
287
+ # string, ignoring all subsequent statements. This will execute each one
288
+ # in turn. Bind parameters cannot be passed to #execute_batch2.
289
+ #
290
+ # If a query is made, all values will be returned as strings.
291
+ # If no query is made, an empty array will be returned.
292
+ #
293
+ # Because all values except for 'NULL' are returned as strings,
294
+ # a block can be passed to parse the values accordingly.
295
+ #
296
+ # See also #execute_batch for additional ways of
297
+ # executing statments.
298
+ def execute_batch2(sql, &block)
299
+ if block_given?
300
+ result = exec_batch(sql, @results_as_hash)
301
+ result.map do |val|
302
+ yield val
303
+ end
304
+ else
305
+ exec_batch(sql, @results_as_hash)
306
+ end
307
+ end
308
+
237
309
  # This is a convenience method for creating a statement, binding
238
310
  # paramters to it, and calling execute:
239
311
  #
@@ -287,7 +359,11 @@ Support for this will be removed in version 2.0.0.
287
359
  #
288
360
  # See also #get_first_row.
289
361
  def get_first_value( sql, *bind_vars )
290
- execute( sql, *bind_vars ) { |row| return row[0] }
362
+ query( sql, bind_vars ) do |rs|
363
+ if (row = rs.next)
364
+ return @results_as_hash ? row[rs.columns[0]] : row[0]
365
+ end
366
+ end
291
367
  nil
292
368
  end
293
369
 
@@ -316,8 +392,8 @@ Support for this will be removed in version 2.0.0.
316
392
  # end
317
393
  #
318
394
  # puts db.get_first_value( "select maim(name) from table" )
319
- def create_function name, arity, text_rep=Constants::TextRep::ANY, &block
320
- define_function(name) do |*args|
395
+ def create_function name, arity, text_rep=Constants::TextRep::UTF8, &block
396
+ define_function_with_flags(name, text_rep) do |*args|
321
397
  fp = FunctionProxy.new
322
398
  block.call(fp, *args)
323
399
  fp.result
@@ -364,42 +440,52 @@ Support for this will be removed in version 2.0.0.
364
440
  def create_aggregate( name, arity, step=nil, finalize=nil,
365
441
  text_rep=Constants::TextRep::ANY, &block )
366
442
 
367
- factory = Class.new do
443
+ proxy = Class.new do
368
444
  def self.step( &block )
369
- define_method(:step, &block)
445
+ define_method(:step_with_ctx, &block)
370
446
  end
371
447
 
372
448
  def self.finalize( &block )
373
- define_method(:finalize, &block)
449
+ define_method(:finalize_with_ctx, &block)
374
450
  end
375
451
  end
376
452
 
377
453
  if block_given?
378
- factory.instance_eval(&block)
454
+ proxy.instance_eval(&block)
379
455
  else
380
- factory.class_eval do
381
- define_method(:step, step)
382
- define_method(:finalize, finalize)
456
+ proxy.class_eval do
457
+ define_method(:step_with_ctx, step)
458
+ define_method(:finalize_with_ctx, finalize)
383
459
  end
384
460
  end
385
461
 
386
- proxy = factory.new
387
- proxy.extend(Module.new {
388
- attr_accessor :ctx
462
+ proxy.class_eval do
463
+ # class instance variables
464
+ @name = name
465
+ @arity = arity
466
+
467
+ def self.name
468
+ @name
469
+ end
470
+
471
+ def self.arity
472
+ @arity
473
+ end
474
+
475
+ def initialize
476
+ @ctx = FunctionProxy.new
477
+ end
389
478
 
390
479
  def step( *args )
391
- super(@ctx, *args)
480
+ step_with_ctx(@ctx, *args)
392
481
  end
393
482
 
394
483
  def finalize
395
- super(@ctx)
396
- result = @ctx.result
397
- @ctx = FunctionProxy.new
398
- result
484
+ finalize_with_ctx(@ctx)
485
+ @ctx.result
399
486
  end
400
- })
401
- proxy.ctx = FunctionProxy.new
402
- define_aggregator(name, proxy)
487
+ end
488
+ define_aggregator2(proxy, name)
403
489
  end
404
490
 
405
491
  # This is another approach to creating an aggregate function (see
@@ -450,29 +536,75 @@ Support for this will be removed in version 2.0.0.
450
536
  # db.create_aggregate_handler( LengthsAggregateHandler )
451
537
  # puts db.get_first_value( "select lengths(name) from A" )
452
538
  def create_aggregate_handler( handler )
453
- proxy = Class.new do
454
- def initialize klass
455
- @klass = klass
456
- @fp = FunctionProxy.new
539
+ # This is a compatiblity shim so the (basically pointless) FunctionProxy
540
+ # "ctx" object is passed as first argument to both step() and finalize().
541
+ # Now its up to the library user whether he prefers to store his
542
+ # temporaries as instance varibales or fields in the FunctionProxy.
543
+ # The library user still must set the result value with
544
+ # FunctionProxy.result= as there is no backwards compatible way to
545
+ # change this.
546
+ proxy = Class.new(handler) do
547
+ def initialize
548
+ super
549
+ @fp = FunctionProxy.new
457
550
  end
458
551
 
459
552
  def step( *args )
460
- instance.step(@fp, *args)
553
+ super(@fp, *args)
461
554
  end
462
555
 
463
556
  def finalize
464
- instance.finalize @fp
465
- @instance = nil
557
+ super(@fp)
466
558
  @fp.result
467
559
  end
560
+ end
561
+ define_aggregator2(proxy, proxy.name)
562
+ self
563
+ end
468
564
 
469
- private
565
+ # Define an aggregate function named +name+ using a object template
566
+ # object +aggregator+. +aggregator+ must respond to +step+ and +finalize+.
567
+ # +step+ will be called with row information and +finalize+ must return the
568
+ # return value for the aggregator function.
569
+ #
570
+ # _API Change:_ +aggregator+ must also implement +clone+. The provided
571
+ # +aggregator+ object will serve as template that is cloned to provide the
572
+ # individual instances of the aggregate function. Regular ruby objects
573
+ # already provide a suitable +clone+.
574
+ # The functions arity is the arity of the +step+ method.
575
+ def define_aggregator( name, aggregator )
576
+ # Previously, this has been implemented in C. Now this is just yet
577
+ # another compatiblity shim
578
+ proxy = Class.new do
579
+ @template = aggregator
580
+ @name = name
470
581
 
471
- def instance
472
- @instance ||= @klass.new
582
+ def self.template
583
+ @template
584
+ end
585
+
586
+ def self.name
587
+ @name
588
+ end
589
+
590
+ def self.arity
591
+ # this is what sqlite3_obj_method_arity did before
592
+ @template.method(:step).arity
593
+ end
594
+
595
+ def initialize
596
+ @klass = self.class.template.clone
597
+ end
598
+
599
+ def step(*args)
600
+ @klass.step(*args)
601
+ end
602
+
603
+ def finalize
604
+ @klass.finalize
473
605
  end
474
606
  end
475
- define_aggregator(handler.name, proxy.new(handler))
607
+ define_aggregator2(proxy, name)
476
608
  self
477
609
  end
478
610
 
@@ -499,7 +631,7 @@ Support for this will be removed in version 2.0.0.
499
631
  abort = false
500
632
  begin
501
633
  yield self
502
- rescue ::Object
634
+ rescue
503
635
  abort = true
504
636
  raise
505
637
  ensure
@@ -580,12 +712,25 @@ Support for this will be removed in version 2.0.0.
580
712
  end
581
713
  end
582
714
 
715
+ # Translates a +row+ of data from the database with the given +types+
716
+ def translate_from_db types, row
717
+ @type_translator.call types, row
718
+ end
719
+
583
720
  private
584
721
 
585
- def ordered_map_for columns, row
586
- h = Hash[*columns.zip(row).flatten]
587
- row.each_with_index { |r, i| h[i] = r }
588
- h
722
+ NULL_TRANSLATOR = lambda { |_, row| row }
723
+
724
+ def make_type_translator should_translate
725
+ if should_translate
726
+ lambda { |types, row|
727
+ types.zip(row).map do |type, value|
728
+ translator.translate( type, value )
729
+ end
730
+ }
731
+ else
732
+ NULL_TRANSLATOR
733
+ end
589
734
  end
590
735
  end
591
736
  end
@@ -2,17 +2,8 @@ require 'sqlite3/constants'
2
2
 
3
3
  module SQLite3
4
4
  class Exception < ::StandardError
5
- @code = 0
6
-
7
- # The numeric error code that this exception represents.
8
- def self.code
9
- @code
10
- end
11
-
12
5
  # A convenience for accessing the error code for this exception.
13
- def code
14
- self.class.code
15
- end
6
+ attr_reader :code
16
7
  end
17
8
 
18
9
  class SQLException < Exception; end
@@ -19,19 +19,19 @@ module SQLite3
19
19
  # integer that represents truth.
20
20
  def set_boolean_pragma( name, mode )
21
21
  case mode
22
- when String
22
+ when String
23
23
  case mode.downcase
24
- when "on", "yes", "true", "y", "t"; mode = "'ON'"
25
- when "off", "no", "false", "n", "f"; mode = "'OFF'"
26
- else
24
+ when "on", "yes", "true", "y", "t"; mode = "'ON'"
25
+ when "off", "no", "false", "n", "f"; mode = "'OFF'"
26
+ else
27
27
  raise Exception,
28
28
  "unrecognized pragma parameter #{mode.inspect}"
29
29
  end
30
- when true, 1
30
+ when true, 1
31
31
  mode = "ON"
32
- when false, 0, nil
32
+ when false, 0, nil
33
33
  mode = "OFF"
34
- else
34
+ else
35
35
  raise Exception,
36
36
  "unrecognized pragma parameter #{mode.inspect}"
37
37
  end
@@ -108,11 +108,7 @@ object that created this object
108
108
  row = @stmt.step
109
109
  return nil if @stmt.done?
110
110
 
111
- if @db.type_translation
112
- row = @stmt.types.zip(row).map do |type, value|
113
- @db.translator.translate( type, value )
114
- end
115
- end
111
+ row = @db.translate_from_db @stmt.types, row
116
112
 
117
113
  if row.respond_to?(:fields)
118
114
  # FIXME: this can only happen if the translator returns something
@@ -176,11 +172,7 @@ object that created this object
176
172
 
177
173
  # FIXME: type translation is deprecated, so this can be removed
178
174
  # in 2.0
179
- if @db.type_translation
180
- row = @stmt.types.zip(row).map do |type, value|
181
- @db.translator.translate( type, value )
182
- end
183
- end
175
+ row = @db.translate_from_db @stmt.types, row
184
176
 
185
177
  # FIXME: this can be switched to a regular hash in 2.0
186
178
  row = HashWithTypesAndFields[*@stmt.columns.zip(row).flatten]
@@ -1,12 +1,12 @@
1
1
  module SQLite3
2
2
 
3
- VERSION = '1.3.13'
3
+ VERSION = '1.4.2'
4
4
 
5
5
  module VersionProxy
6
6
 
7
7
  MAJOR = 1
8
- MINOR = 3
9
- TINY = 13
8
+ MINOR = 4
9
+ TINY = 2
10
10
  BUILD = nil
11
11
 
12
12
  STRING = [ MAJOR, MINOR, TINY, BUILD ].compact.join( "." )
File without changes
@@ -6,14 +6,14 @@ rescue LoadError
6
6
  require 'hoe'
7
7
  end
8
8
 
9
- Hoe.plugin :debugging, :doofus, :git, :minitest, :bundler
9
+ Hoe.plugin :debugging, :doofus, :git, :minitest, :bundler, :gemspec
10
10
 
11
11
  HOE = Hoe.spec 'sqlite3' do
12
12
  developer 'Jamis Buck', 'jamis@37signals.com'
13
13
  developer 'Luis Lavena', 'luislavena@gmail.com'
14
14
  developer 'Aaron Patterson', 'aaron@tenderlovemaking.com'
15
15
 
16
- license "BSD-3"
16
+ license "BSD-3-Clause"
17
17
 
18
18
  self.readme_file = 'README.rdoc'
19
19
  self.history_file = 'CHANGELOG.rdoc'
@@ -23,12 +23,14 @@ HOE = Hoe.spec 'sqlite3' do
23
23
  require_rubygems_version ">= 1.3.5"
24
24
 
25
25
  spec_extras[:extensions] = ["ext/sqlite3/extconf.rb"]
26
+ spec_extras[:metadata] = {'msys2_mingw_dependencies' => 'sqlite3'}
26
27
 
27
- extra_dev_deps << ['rake-compiler', "~> 0.9.3"]
28
- extra_dev_deps << ['rake-compiler-dock', "~> 0.5.2"]
28
+ extra_dev_deps << ['rake-compiler', "~> 1.0"]
29
+ extra_dev_deps << ['rake-compiler-dock', "~> 0.6.0"]
29
30
  extra_dev_deps << ["mini_portile", "~> 0.6.2"]
30
31
  extra_dev_deps << ["minitest", "~> 5.0"]
31
32
  extra_dev_deps << ["hoe-bundler", "~> 1.0"]
33
+ extra_dev_deps << ["hoe-gemspec", "~> 1.0"]
32
34
 
33
35
  clean_globs.push('**/test.db')
34
36
  end
@@ -40,6 +40,10 @@ RUBY_EXTENSION = Rake::ExtensionTask.new('sqlite3_native', HOE.spec) do |ext|
40
40
  Rake::ExtensionCompiler.mingw_host
41
41
  ext.cross_compile = true
42
42
  ext.cross_platform = ['i386-mswin32-60', 'i386-mingw32', 'x64-mingw32']
43
+ ext.cross_compiling do |spec|
44
+ # The fat binary gem doesn't depend on the sqlite3 package, since it bundles the library.
45
+ spec.metadata.delete('msys2_mingw_dependencies')
46
+ end
43
47
  rescue RuntimeError
44
48
  # noop
45
49
  end
File without changes