sqlite3 1.3.13-x64-mingw32 → 1.5.0-x64-mingw32

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

Potentially problematic release.


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

Files changed (54) hide show
  1. checksums.yaml +5 -5
  2. data/.gemtest +0 -0
  3. data/{API_CHANGES.rdoc → API_CHANGES.md} +3 -4
  4. data/CHANGELOG.md +425 -0
  5. data/CONTRIBUTING.md +24 -0
  6. data/Gemfile +2 -14
  7. data/LICENSE-DEPENDENCIES +20 -0
  8. data/README.md +233 -0
  9. data/ext/sqlite3/aggregator.c +274 -0
  10. data/ext/sqlite3/aggregator.h +12 -0
  11. data/ext/sqlite3/database.c +171 -206
  12. data/ext/sqlite3/database.h +2 -0
  13. data/ext/sqlite3/exception.c +6 -2
  14. data/ext/sqlite3/extconf.rb +236 -55
  15. data/ext/sqlite3/sqlite3.c +12 -1
  16. data/ext/sqlite3/sqlite3_ruby.h +3 -7
  17. data/ext/sqlite3/statement.c +15 -20
  18. data/faq/faq.md +431 -0
  19. data/faq/faq.yml +1 -1
  20. data/lib/sqlite3/2.6/sqlite3_native.so +0 -0
  21. data/lib/sqlite3/2.7/sqlite3_native.so +0 -0
  22. data/lib/sqlite3/3.0/sqlite3_native.so +0 -0
  23. data/lib/sqlite3/constants.rb +2 -1
  24. data/lib/sqlite3/database.rb +202 -52
  25. data/lib/sqlite3/errors.rb +1 -10
  26. data/lib/sqlite3/pragmas.rb +17 -10
  27. data/lib/sqlite3/resultset.rb +2 -10
  28. data/lib/sqlite3/statement.rb +2 -1
  29. data/lib/sqlite3/translator.rb +1 -1
  30. data/lib/sqlite3/version.rb +3 -5
  31. data/test/helper.rb +9 -0
  32. data/test/test_database.rb +126 -11
  33. data/test/test_database_flags.rb +95 -0
  34. data/test/test_database_readwrite.rb +41 -0
  35. data/test/test_integration.rb +12 -81
  36. data/test/test_integration_aggregate.rb +336 -0
  37. data/test/test_integration_resultset.rb +0 -17
  38. data/test/test_sqlite3.rb +9 -0
  39. data/test/test_statement.rb +11 -8
  40. metadata +54 -85
  41. data/CHANGELOG.rdoc +0 -292
  42. data/Manifest.txt +0 -52
  43. data/README.rdoc +0 -118
  44. data/Rakefile +0 -10
  45. data/lib/sqlite3/2.0/sqlite3_native.so +0 -0
  46. data/lib/sqlite3/2.1/sqlite3_native.so +0 -0
  47. data/lib/sqlite3/2.2/sqlite3_native.so +0 -0
  48. data/lib/sqlite3/2.3/sqlite3_native.so +0 -0
  49. data/lib/sqlite3/2.4/sqlite3_native.so +0 -0
  50. data/setup.rb +0 -1333
  51. data/tasks/faq.rake +0 -9
  52. data/tasks/gem.rake +0 -38
  53. data/tasks/native.rake +0 -52
  54. data/tasks/vendor_sqlite3.rake +0 -97
@@ -54,12 +54,73 @@ 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
+ file = file.to_path if file.respond_to? :to_path
69
+ if file.encoding == ::Encoding::UTF_16LE || file.encoding == ::Encoding::UTF_16BE || options[:utf16]
70
+ open16 file
71
+ else
72
+ # The three primary flag values for sqlite3_open_v2 are:
73
+ # SQLITE_OPEN_READONLY
74
+ # SQLITE_OPEN_READWRITE
75
+ # SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE -- always used for sqlite3_open and sqlite3_open16
76
+ mode = Constants::Open::READONLY if options[:readonly]
77
+
78
+ if options[:readwrite]
79
+ raise "conflicting options: readonly and readwrite" if options[:readonly]
80
+ mode = Constants::Open::READWRITE
81
+ end
82
+
83
+ if options[:flags]
84
+ if options[:readonly] || options[:readwrite]
85
+ raise "conflicting options: flags with readonly and/or readwrite"
86
+ end
87
+ mode = options[:flags]
88
+ end
89
+
90
+ open_v2 file.encode("utf-8"), mode, zvfs
91
+
92
+ if options[:strict]
93
+ disable_quirk_mode
94
+ end
95
+ end
96
+
97
+ @tracefunc = nil
98
+ @authorizer = nil
99
+ @encoding = nil
100
+ @busy_handler = nil
101
+ @collations = {}
102
+ @functions = {}
103
+ @results_as_hash = options[:results_as_hash]
104
+ @type_translation = options[:type_translation]
105
+ @type_translator = make_type_translator @type_translation
106
+ @readonly = mode & Constants::Open::READONLY != 0
107
+
108
+ if block_given?
109
+ begin
110
+ yield self
111
+ ensure
112
+ close
113
+ end
114
+ end
115
+ end
116
+
57
117
  def type_translation= value # :nodoc:
58
118
  warn(<<-eowarn) if $VERBOSE
59
119
  #{caller[0]} is calling SQLite3::Database#type_translation=
60
120
  SQLite3::Database#type_translation= is deprecated and will be removed
61
121
  in version 2.0.0.
62
122
  eowarn
123
+ @type_translator = make_type_translator value
63
124
  @type_translation = value
64
125
  end
65
126
  attr_reader :type_translation # :nodoc:
@@ -136,25 +197,14 @@ Support for bind parameters as *args will be removed in 2.0.0.
136
197
 
137
198
  prepare( sql ) do |stmt|
138
199
  stmt.bind_params(bind_vars)
139
- columns = stmt.columns
140
- stmt = ResultSet.new(self, stmt).to_a if type_translation
200
+ stmt = ResultSet.new self, stmt
141
201
 
142
202
  if block_given?
143
203
  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
204
+ yield row
149
205
  end
150
206
  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
207
+ stmt.to_a
158
208
  end
159
209
  end
160
210
  end
@@ -190,6 +240,9 @@ Support for bind parameters as *args will be removed in 2.0.0.
190
240
  #
191
241
  # This always returns +nil+, making it unsuitable for queries that return
192
242
  # rows.
243
+ #
244
+ # See also #execute_batch2 for additional ways of
245
+ # executing statements.
193
246
  def execute_batch( sql, bind_vars = [], *args )
194
247
  # FIXME: remove this stuff later
195
248
  unless [Array, Hash].include?(bind_vars.class)
@@ -234,8 +287,32 @@ Support for this behavior will be removed in version 2.0.0.
234
287
  nil
235
288
  end
236
289
 
290
+ # Executes all SQL statements in the given string. By contrast, the other
291
+ # means of executing queries will only execute the first statement in the
292
+ # string, ignoring all subsequent statements. This will execute each one
293
+ # in turn. Bind parameters cannot be passed to #execute_batch2.
294
+ #
295
+ # If a query is made, all values will be returned as strings.
296
+ # If no query is made, an empty array will be returned.
297
+ #
298
+ # Because all values except for 'NULL' are returned as strings,
299
+ # a block can be passed to parse the values accordingly.
300
+ #
301
+ # See also #execute_batch for additional ways of
302
+ # executing statements.
303
+ def execute_batch2(sql, &block)
304
+ if block_given?
305
+ result = exec_batch(sql, @results_as_hash)
306
+ result.map do |val|
307
+ yield val
308
+ end
309
+ else
310
+ exec_batch(sql, @results_as_hash)
311
+ end
312
+ end
313
+
237
314
  # This is a convenience method for creating a statement, binding
238
- # paramters to it, and calling execute:
315
+ # parameters to it, and calling execute:
239
316
  #
240
317
  # result = db.query( "select * from foo where a=?", [5])
241
318
  # # is the same as
@@ -287,7 +364,11 @@ Support for this will be removed in version 2.0.0.
287
364
  #
288
365
  # See also #get_first_row.
289
366
  def get_first_value( sql, *bind_vars )
290
- execute( sql, *bind_vars ) { |row| return row[0] }
367
+ query( sql, bind_vars ) do |rs|
368
+ if (row = rs.next)
369
+ return @results_as_hash ? row[rs.columns[0]] : row[0]
370
+ end
371
+ end
291
372
  nil
292
373
  end
293
374
 
@@ -316,8 +397,8 @@ Support for this will be removed in version 2.0.0.
316
397
  # end
317
398
  #
318
399
  # 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|
400
+ def create_function name, arity, text_rep=Constants::TextRep::UTF8, &block
401
+ define_function_with_flags(name, text_rep) do |*args|
321
402
  fp = FunctionProxy.new
322
403
  block.call(fp, *args)
323
404
  fp.result
@@ -364,42 +445,52 @@ Support for this will be removed in version 2.0.0.
364
445
  def create_aggregate( name, arity, step=nil, finalize=nil,
365
446
  text_rep=Constants::TextRep::ANY, &block )
366
447
 
367
- factory = Class.new do
448
+ proxy = Class.new do
368
449
  def self.step( &block )
369
- define_method(:step, &block)
450
+ define_method(:step_with_ctx, &block)
370
451
  end
371
452
 
372
453
  def self.finalize( &block )
373
- define_method(:finalize, &block)
454
+ define_method(:finalize_with_ctx, &block)
374
455
  end
375
456
  end
376
457
 
377
458
  if block_given?
378
- factory.instance_eval(&block)
459
+ proxy.instance_eval(&block)
379
460
  else
380
- factory.class_eval do
381
- define_method(:step, step)
382
- define_method(:finalize, finalize)
461
+ proxy.class_eval do
462
+ define_method(:step_with_ctx, step)
463
+ define_method(:finalize_with_ctx, finalize)
383
464
  end
384
465
  end
385
466
 
386
- proxy = factory.new
387
- proxy.extend(Module.new {
388
- attr_accessor :ctx
467
+ proxy.class_eval do
468
+ # class instance variables
469
+ @name = name
470
+ @arity = arity
471
+
472
+ def self.name
473
+ @name
474
+ end
475
+
476
+ def self.arity
477
+ @arity
478
+ end
479
+
480
+ def initialize
481
+ @ctx = FunctionProxy.new
482
+ end
389
483
 
390
484
  def step( *args )
391
- super(@ctx, *args)
485
+ step_with_ctx(@ctx, *args)
392
486
  end
393
487
 
394
488
  def finalize
395
- super(@ctx)
396
- result = @ctx.result
397
- @ctx = FunctionProxy.new
398
- result
489
+ finalize_with_ctx(@ctx)
490
+ @ctx.result
399
491
  end
400
- })
401
- proxy.ctx = FunctionProxy.new
402
- define_aggregator(name, proxy)
492
+ end
493
+ define_aggregator2(proxy, name)
403
494
  end
404
495
 
405
496
  # This is another approach to creating an aggregate function (see
@@ -450,29 +541,75 @@ Support for this will be removed in version 2.0.0.
450
541
  # db.create_aggregate_handler( LengthsAggregateHandler )
451
542
  # puts db.get_first_value( "select lengths(name) from A" )
452
543
  def create_aggregate_handler( handler )
453
- proxy = Class.new do
454
- def initialize klass
455
- @klass = klass
456
- @fp = FunctionProxy.new
544
+ # This is a compatibility shim so the (basically pointless) FunctionProxy
545
+ # "ctx" object is passed as first argument to both step() and finalize().
546
+ # Now its up to the library user whether he prefers to store his
547
+ # temporaries as instance variables or fields in the FunctionProxy.
548
+ # The library user still must set the result value with
549
+ # FunctionProxy.result= as there is no backwards compatible way to
550
+ # change this.
551
+ proxy = Class.new(handler) do
552
+ def initialize
553
+ super
554
+ @fp = FunctionProxy.new
457
555
  end
458
556
 
459
557
  def step( *args )
460
- instance.step(@fp, *args)
558
+ super(@fp, *args)
461
559
  end
462
560
 
463
561
  def finalize
464
- instance.finalize @fp
465
- @instance = nil
562
+ super(@fp)
466
563
  @fp.result
467
564
  end
565
+ end
566
+ define_aggregator2(proxy, proxy.name)
567
+ self
568
+ end
468
569
 
469
- private
570
+ # Define an aggregate function named +name+ using a object template
571
+ # object +aggregator+. +aggregator+ must respond to +step+ and +finalize+.
572
+ # +step+ will be called with row information and +finalize+ must return the
573
+ # return value for the aggregator function.
574
+ #
575
+ # _API Change:_ +aggregator+ must also implement +clone+. The provided
576
+ # +aggregator+ object will serve as template that is cloned to provide the
577
+ # individual instances of the aggregate function. Regular ruby objects
578
+ # already provide a suitable +clone+.
579
+ # The functions arity is the arity of the +step+ method.
580
+ def define_aggregator( name, aggregator )
581
+ # Previously, this has been implemented in C. Now this is just yet
582
+ # another compatibility shim
583
+ proxy = Class.new do
584
+ @template = aggregator
585
+ @name = name
586
+
587
+ def self.template
588
+ @template
589
+ end
590
+
591
+ def self.name
592
+ @name
593
+ end
594
+
595
+ def self.arity
596
+ # this is what sqlite3_obj_method_arity did before
597
+ @template.method(:step).arity
598
+ end
599
+
600
+ def initialize
601
+ @klass = self.class.template.clone
602
+ end
470
603
 
471
- def instance
472
- @instance ||= @klass.new
604
+ def step(*args)
605
+ @klass.step(*args)
606
+ end
607
+
608
+ def finalize
609
+ @klass.finalize
473
610
  end
474
611
  end
475
- define_aggregator(handler.name, proxy.new(handler))
612
+ define_aggregator2(proxy, name)
476
613
  self
477
614
  end
478
615
 
@@ -499,7 +636,7 @@ Support for this will be removed in version 2.0.0.
499
636
  abort = false
500
637
  begin
501
638
  yield self
502
- rescue ::Object
639
+ rescue
503
640
  abort = true
504
641
  raise
505
642
  ensure
@@ -580,12 +717,25 @@ Support for this will be removed in version 2.0.0.
580
717
  end
581
718
  end
582
719
 
720
+ # Translates a +row+ of data from the database with the given +types+
721
+ def translate_from_db types, row
722
+ @type_translator.call types, row
723
+ end
724
+
583
725
  private
584
726
 
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
727
+ NULL_TRANSLATOR = lambda { |_, row| row }
728
+
729
+ def make_type_translator should_translate
730
+ if should_translate
731
+ lambda { |types, row|
732
+ types.zip(row).map do |type, value|
733
+ translator.translate( type, value )
734
+ end
735
+ }
736
+ else
737
+ NULL_TRANSLATOR
738
+ end
589
739
  end
590
740
  end
591
741
  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
@@ -42,11 +42,11 @@ module SQLite3
42
42
  # Requests the given pragma (and parameters), and if the block is given,
43
43
  # each row of the result set will be yielded to it. Otherwise, the results
44
44
  # are returned as an array.
45
- def get_query_pragma( name, *parms, &block ) # :yields: row
46
- if parms.empty?
45
+ def get_query_pragma( name, *params, &block ) # :yields: row
46
+ if params.empty?
47
47
  execute( "PRAGMA #{name}", &block )
48
48
  else
49
- args = "'" + parms.join("','") + "'"
49
+ args = "'" + params.join("','") + "'"
50
50
  execute( "PRAGMA #{name}( #{args} )", &block )
51
51
  end
52
52
  end
@@ -543,6 +543,13 @@ module SQLite3
543
543
 
544
544
  tweak_default(new_row) if needs_tweak_default
545
545
 
546
+ # Ensure the type value is downcased. On Mac and Windows
547
+ # platforms this value is now being returned as all upper
548
+ # case.
549
+ if new_row['type']
550
+ new_row['type'] = new_row['type'].downcase
551
+ end
552
+
546
553
  if block_given?
547
554
  yield new_row
548
555
  else
@@ -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]
@@ -137,7 +137,8 @@ module SQLite3
137
137
  column_name column
138
138
  end
139
139
  @types = Array.new(column_count) do |column|
140
- column_decltype column
140
+ val = column_decltype(column)
141
+ val.nil? ? nil : val.downcase
141
142
  end
142
143
  end
143
144
  end
@@ -43,7 +43,7 @@ Built in translators are deprecated and will be removed in version 2.0.0
43
43
  end
44
44
 
45
45
  # Translate the given string value to a value of the given type. In the
46
- # absense of an installed translator block for the given type, the value
46
+ # absence of an installed translator block for the given type, the value
47
47
  # itself is always returned. Further, +nil+ values are never translated,
48
48
  # and are always passed straight through regardless of the type parameter.
49
49
  def translate( type, value )
@@ -1,16 +1,14 @@
1
1
  module SQLite3
2
2
 
3
- VERSION = '1.3.13'
3
+ VERSION = "1.5.0"
4
4
 
5
5
  module VersionProxy
6
-
7
6
  MAJOR = 1
8
- MINOR = 3
9
- TINY = 13
7
+ MINOR = 5
8
+ TINY = 0
10
9
  BUILD = nil
11
10
 
12
11
  STRING = [ MAJOR, MINOR, TINY, BUILD ].compact.join( "." )
13
- #:beta-tag:
14
12
 
15
13
  VERSION = ::SQLite3::VERSION
16
14
  end
data/test/helper.rb CHANGED
@@ -1,6 +1,15 @@
1
1
  require 'sqlite3'
2
2
  require 'minitest/autorun'
3
3
 
4
+ if ENV['GITHUB_ACTIONS'] == 'true' || ENV['CI']
5
+ $VERBOSE = nil
6
+ end
7
+
8
+ puts "info: sqlite3-ruby version: #{SQLite3::VERSION}/#{SQLite3::VersionProxy::STRING}"
9
+ puts "info: sqlite3 version: #{SQLite3::SQLITE_VERSION}/#{SQLite3::SQLITE_LOADED_VERSION}"
10
+ puts "info: sqlcipher?: #{SQLite3.sqlcipher?}"
11
+ puts "info: threadsafe?: #{SQLite3.threadsafe?}"
12
+
4
13
  unless RUBY_VERSION >= "1.9"
5
14
  require 'iconv'
6
15
  end