sqlite3 1.3.13-x64-mingw32 → 1.5.0.rc1-x64-mingw32
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/.gemtest +0 -0
- data/{API_CHANGES.rdoc → API_CHANGES.md} +3 -4
- data/CHANGELOG.md +419 -0
- data/CONTRIBUTING.md +24 -0
- data/Gemfile +2 -14
- data/LICENSE-DEPENDENCIES +20 -0
- data/README.md +233 -0
- data/ext/sqlite3/aggregator.c +273 -0
- data/ext/sqlite3/aggregator.h +12 -0
- data/ext/sqlite3/database.c +169 -204
- data/ext/sqlite3/database.h +2 -0
- data/ext/sqlite3/exception.c +6 -2
- data/ext/sqlite3/extconf.rb +154 -66
- data/ext/sqlite3/sqlite3.c +12 -1
- data/ext/sqlite3/sqlite3_ruby.h +0 -7
- data/ext/sqlite3/statement.c +15 -20
- data/faq/faq.md +431 -0
- data/faq/faq.yml +1 -1
- data/lib/sqlite3/2.6/sqlite3_native.so +0 -0
- data/lib/sqlite3/2.7/sqlite3_native.so +0 -0
- data/lib/sqlite3/3.0/sqlite3_native.so +0 -0
- data/lib/sqlite3/constants.rb +2 -1
- data/lib/sqlite3/database.rb +202 -52
- data/lib/sqlite3/errors.rb +1 -10
- data/lib/sqlite3/pragmas.rb +17 -10
- data/lib/sqlite3/resultset.rb +2 -10
- data/lib/sqlite3/statement.rb +2 -1
- data/lib/sqlite3/translator.rb +1 -1
- data/lib/sqlite3/version.rb +4 -4
- data/test/helper.rb +9 -0
- data/test/test_database.rb +119 -11
- data/test/test_database_flags.rb +95 -0
- data/test/test_database_readwrite.rb +41 -0
- data/test/test_integration.rb +12 -81
- data/test/test_integration_aggregate.rb +336 -0
- data/test/test_integration_resultset.rb +0 -17
- data/test/test_sqlite3.rb +4 -0
- data/test/test_statement.rb +11 -8
- metadata +55 -86
- data/CHANGELOG.rdoc +0 -292
- data/Manifest.txt +0 -52
- data/README.rdoc +0 -118
- data/Rakefile +0 -10
- data/lib/sqlite3/2.0/sqlite3_native.so +0 -0
- data/lib/sqlite3/2.1/sqlite3_native.so +0 -0
- data/lib/sqlite3/2.2/sqlite3_native.so +0 -0
- data/lib/sqlite3/2.3/sqlite3_native.so +0 -0
- data/lib/sqlite3/2.4/sqlite3_native.so +0 -0
- data/setup.rb +0 -1333
- data/tasks/faq.rake +0 -9
- data/tasks/gem.rake +0 -38
- data/tasks/native.rake +0 -52
- data/tasks/vendor_sqlite3.rake +0 -97
data/lib/sqlite3/database.rb
CHANGED
@@ -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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
#
|
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
|
-
|
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::
|
320
|
-
|
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
|
-
|
448
|
+
proxy = Class.new do
|
368
449
|
def self.step( &block )
|
369
|
-
define_method(:
|
450
|
+
define_method(:step_with_ctx, &block)
|
370
451
|
end
|
371
452
|
|
372
453
|
def self.finalize( &block )
|
373
|
-
define_method(:
|
454
|
+
define_method(:finalize_with_ctx, &block)
|
374
455
|
end
|
375
456
|
end
|
376
457
|
|
377
458
|
if block_given?
|
378
|
-
|
459
|
+
proxy.instance_eval(&block)
|
379
460
|
else
|
380
|
-
|
381
|
-
define_method(:
|
382
|
-
define_method(:
|
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
|
387
|
-
|
388
|
-
|
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
|
-
|
485
|
+
step_with_ctx(@ctx, *args)
|
392
486
|
end
|
393
487
|
|
394
488
|
def finalize
|
395
|
-
|
396
|
-
|
397
|
-
@ctx = FunctionProxy.new
|
398
|
-
result
|
489
|
+
finalize_with_ctx(@ctx)
|
490
|
+
@ctx.result
|
399
491
|
end
|
400
|
-
|
401
|
-
proxy
|
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
|
-
|
454
|
-
|
455
|
-
|
456
|
-
|
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
|
-
|
558
|
+
super(@fp, *args)
|
461
559
|
end
|
462
560
|
|
463
561
|
def finalize
|
464
|
-
|
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
|
-
|
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
|
472
|
-
@
|
604
|
+
def step(*args)
|
605
|
+
@klass.step(*args)
|
606
|
+
end
|
607
|
+
|
608
|
+
def finalize
|
609
|
+
@klass.finalize
|
473
610
|
end
|
474
611
|
end
|
475
|
-
|
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
|
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
|
-
|
586
|
-
|
587
|
-
|
588
|
-
|
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
|
data/lib/sqlite3/errors.rb
CHANGED
@@ -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
|
-
|
14
|
-
self.class.code
|
15
|
-
end
|
6
|
+
attr_reader :code
|
16
7
|
end
|
17
8
|
|
18
9
|
class SQLException < Exception; end
|
data/lib/sqlite3/pragmas.rb
CHANGED
@@ -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
|
-
|
22
|
+
when String
|
23
23
|
case mode.downcase
|
24
|
-
|
25
|
-
|
26
|
-
|
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
|
-
|
30
|
+
when true, 1
|
31
31
|
mode = "ON"
|
32
|
-
|
32
|
+
when false, 0, nil
|
33
33
|
mode = "OFF"
|
34
|
-
|
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, *
|
46
|
-
if
|
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 = "'" +
|
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
|
data/lib/sqlite3/resultset.rb
CHANGED
@@ -108,11 +108,7 @@ object that created this object
|
|
108
108
|
row = @stmt.step
|
109
109
|
return nil if @stmt.done?
|
110
110
|
|
111
|
-
|
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
|
-
|
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]
|
data/lib/sqlite3/statement.rb
CHANGED
data/lib/sqlite3/translator.rb
CHANGED
@@ -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
|
-
#
|
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 )
|
data/lib/sqlite3/version.rb
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
module SQLite3
|
2
2
|
|
3
|
-
VERSION =
|
3
|
+
VERSION = "1.5.0.rc1"
|
4
4
|
|
5
5
|
module VersionProxy
|
6
6
|
|
7
7
|
MAJOR = 1
|
8
|
-
MINOR =
|
9
|
-
TINY =
|
10
|
-
BUILD =
|
8
|
+
MINOR = 5
|
9
|
+
TINY = 0
|
10
|
+
BUILD = "rc1"
|
11
11
|
|
12
12
|
STRING = [ MAJOR, MINOR, TINY, BUILD ].compact.join( "." )
|
13
13
|
#:beta-tag:
|
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
|