sqlite3 1.3.5 → 1.3.13
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/CHANGELOG.rdoc +84 -0
- data/Gemfile +15 -0
- data/Manifest.txt +2 -0
- data/README.rdoc +29 -6
- data/ext/sqlite3/database.c +131 -27
- data/ext/sqlite3/extconf.rb +31 -7
- data/ext/sqlite3/sqlite3.c +112 -0
- data/ext/sqlite3/sqlite3_ruby.h +12 -4
- data/ext/sqlite3/statement.c +33 -22
- data/faq/faq.yml +1 -1
- data/lib/sqlite3.rb +6 -1
- data/lib/sqlite3/database.rb +36 -24
- data/lib/sqlite3/pragmas.rb +357 -49
- data/lib/sqlite3/resultset.rb +94 -25
- data/lib/sqlite3/statement.rb +13 -17
- data/lib/sqlite3/version.rb +2 -2
- data/setup.rb +2 -2
- data/tasks/gem.rake +12 -6
- data/tasks/native.rake +22 -7
- data/tasks/vendor_sqlite3.rake +69 -20
- data/test/helper.rb +17 -2
- data/test/test_backup.rb +2 -2
- data/test/test_collation.rb +1 -1
- data/test/test_database.rb +102 -7
- data/test/test_database_readonly.rb +10 -3
- data/test/test_deprecated.rb +8 -1
- data/test/test_encoding.rb +35 -1
- data/test/test_integration.rb +36 -15
- data/test/test_integration_open_close.rb +1 -1
- data/test/test_integration_pending.rb +2 -2
- data/test/test_integration_resultset.rb +6 -3
- data/test/test_integration_statement.rb +2 -2
- data/test/test_result_set.rb +37 -0
- data/test/test_sqlite3.rb +13 -1
- data/test/test_statement.rb +26 -4
- data/test/test_statement_execute.rb +1 -1
- metadata +125 -121
- data/.gemtest +0 -0
data/ext/sqlite3/extconf.rb
CHANGED
@@ -6,14 +6,29 @@ require 'mkmf'
|
|
6
6
|
|
7
7
|
RbConfig::MAKEFILE_CONFIG['CC'] = ENV['CC'] if ENV['CC']
|
8
8
|
|
9
|
-
# --with-sqlite3-{dir,include,lib}
|
10
|
-
dir_config("sqlite3")
|
11
9
|
|
12
|
-
|
13
|
-
|
14
|
-
|
10
|
+
|
11
|
+
ldflags = cppflags = nil
|
12
|
+
if RbConfig::CONFIG["host_os"] =~ /darwin/
|
13
|
+
begin
|
14
|
+
brew_prefix = `brew --prefix sqlite3`.chomp
|
15
|
+
ldflags = "#{brew_prefix}/lib"
|
16
|
+
cppflags = "#{brew_prefix}/include"
|
17
|
+
pkg_conf = "#{brew_prefix}/lib/pkgconfig"
|
18
|
+
|
19
|
+
# pkg_config should be less error prone than parsing compiler
|
20
|
+
# commandline options, but we need to set default ldflags and cpp flags
|
21
|
+
# in case the user doesn't have pkg-config installed
|
22
|
+
ENV['PKG_CONFIG_PATH'] ||= pkg_conf
|
23
|
+
rescue
|
24
|
+
end
|
15
25
|
end
|
16
26
|
|
27
|
+
pkg_config("sqlite3")
|
28
|
+
|
29
|
+
# --with-sqlite3-{dir,include,lib}
|
30
|
+
dir_config("sqlite3", cppflags, ldflags)
|
31
|
+
|
17
32
|
if RbConfig::CONFIG["host_os"] =~ /mswin/
|
18
33
|
$CFLAGS << ' -W3'
|
19
34
|
end
|
@@ -24,24 +39,33 @@ def asplode missing
|
|
24
39
|
"http://www.sqlite.org/ first."
|
25
40
|
else
|
26
41
|
abort <<-error
|
27
|
-
#{missing} is missing. Try '
|
28
|
-
|
42
|
+
#{missing} is missing. Try 'brew install sqlite3',
|
43
|
+
'yum install sqlite-devel' or 'apt-get install libsqlite3-dev'
|
44
|
+
and check your shared library search path (the
|
29
45
|
location where your sqlite3 shared library is located).
|
30
46
|
error
|
31
47
|
end
|
32
48
|
end
|
33
49
|
|
34
50
|
asplode('sqlite3.h') unless find_header 'sqlite3.h'
|
51
|
+
find_library 'pthread', 'pthread_create' # 1.8 support. *shrug*
|
35
52
|
asplode('sqlite3') unless find_library 'sqlite3', 'sqlite3_libversion_number'
|
36
53
|
|
37
54
|
# Functions defined in 1.9 but not 1.8
|
38
55
|
have_func('rb_proc_arity')
|
39
56
|
|
57
|
+
# Functions defined in 2.1 but not 2.0
|
58
|
+
have_func('rb_integer_pack')
|
59
|
+
|
40
60
|
# These functions may not be defined
|
41
61
|
have_func('sqlite3_initialize')
|
42
62
|
have_func('sqlite3_backup_init')
|
43
63
|
have_func('sqlite3_column_database_name')
|
44
64
|
have_func('sqlite3_enable_load_extension')
|
45
65
|
have_func('sqlite3_load_extension')
|
66
|
+
have_func('sqlite3_open_v2')
|
67
|
+
have_func('sqlite3_prepare_v2')
|
68
|
+
have_type('sqlite3_int64', 'sqlite3.h')
|
69
|
+
have_type('sqlite3_uint64', 'sqlite3.h')
|
46
70
|
|
47
71
|
create_makefile('sqlite3/sqlite3_native')
|
data/ext/sqlite3/sqlite3.c
CHANGED
@@ -3,11 +3,121 @@
|
|
3
3
|
VALUE mSqlite3;
|
4
4
|
VALUE cSqlite3Blob;
|
5
5
|
|
6
|
+
int bignum_to_int64(VALUE value, sqlite3_int64 *result)
|
7
|
+
{
|
8
|
+
#ifdef HAVE_RB_INTEGER_PACK
|
9
|
+
const int nails = 0;
|
10
|
+
int t = rb_integer_pack(value, result, 1, sizeof(*result), nails,
|
11
|
+
INTEGER_PACK_NATIVE_BYTE_ORDER|
|
12
|
+
INTEGER_PACK_2COMP);
|
13
|
+
switch (t) {
|
14
|
+
case -2: case +2:
|
15
|
+
return 0;
|
16
|
+
case +1:
|
17
|
+
if (!nails) {
|
18
|
+
if (*result < 0) return 0;
|
19
|
+
}
|
20
|
+
break;
|
21
|
+
case -1:
|
22
|
+
if (!nails) {
|
23
|
+
if (*result >= 0) return 0;
|
24
|
+
}
|
25
|
+
else {
|
26
|
+
*result += INT64_MIN;
|
27
|
+
}
|
28
|
+
break;
|
29
|
+
}
|
30
|
+
return 1;
|
31
|
+
#else
|
32
|
+
# ifndef RBIGNUM_LEN
|
33
|
+
# define RBIGNUM_LEN(x) RBIGNUM(x)->len
|
34
|
+
# endif
|
35
|
+
const long len = RBIGNUM_LEN(value);
|
36
|
+
if (len == 0) {
|
37
|
+
*result = 0;
|
38
|
+
return 1;
|
39
|
+
}
|
40
|
+
if (len > 63 / (SIZEOF_BDIGITS * CHAR_BIT) + 1) return 0;
|
41
|
+
if (len == 63 / (SIZEOF_BDIGITS * CHAR_BIT) + 1) {
|
42
|
+
const BDIGIT *digits = RBIGNUM_DIGITS(value);
|
43
|
+
BDIGIT blast = digits[len-1];
|
44
|
+
BDIGIT bmax = (BDIGIT)1UL << (63 % (CHAR_BIT * SIZEOF_BDIGITS));
|
45
|
+
if (blast > bmax) return 0;
|
46
|
+
if (blast == bmax) {
|
47
|
+
if (RBIGNUM_POSITIVE_P(value)) {
|
48
|
+
return 0;
|
49
|
+
}
|
50
|
+
else {
|
51
|
+
long i = len-1;
|
52
|
+
while (i) {
|
53
|
+
if (digits[--i]) return 0;
|
54
|
+
}
|
55
|
+
}
|
56
|
+
}
|
57
|
+
}
|
58
|
+
*result = (sqlite3_int64)NUM2LL(value);
|
59
|
+
return 1;
|
60
|
+
#endif
|
61
|
+
}
|
62
|
+
|
6
63
|
static VALUE libversion(VALUE UNUSED(klass))
|
7
64
|
{
|
8
65
|
return INT2NUM(sqlite3_libversion_number());
|
9
66
|
}
|
10
67
|
|
68
|
+
/* Returns the compile time setting of the SQLITE_THREADSAFE flag.
|
69
|
+
* See: https://www.sqlite.org/c3ref/threadsafe.html
|
70
|
+
*/
|
71
|
+
static VALUE threadsafe_p(VALUE UNUSED(klass))
|
72
|
+
{
|
73
|
+
return INT2NUM(sqlite3_threadsafe());
|
74
|
+
}
|
75
|
+
|
76
|
+
void init_sqlite3_constants()
|
77
|
+
{
|
78
|
+
VALUE mSqlite3Constants;
|
79
|
+
VALUE mSqlite3Open;
|
80
|
+
|
81
|
+
mSqlite3Constants = rb_define_module_under(mSqlite3, "Constants");
|
82
|
+
|
83
|
+
/* sqlite3_open_v2 flags for Database::new */
|
84
|
+
mSqlite3Open = rb_define_module_under(mSqlite3Constants, "Open");
|
85
|
+
|
86
|
+
/* symbols = IO.readlines('sqlite3.h').map { |n| /\A#define\s+(SQLITE_OPEN_\w+)\s/ =~ n && $1 }.compact
|
87
|
+
* pad = symbols.map(&:length).max - 9
|
88
|
+
* symbols.each { |s| printf %Q{ rb_define_const(mSqlite3Open, %-#{pad}s INT2FIX(#{s}));\n}, '"' + s[12..-1] + '",' }
|
89
|
+
*/
|
90
|
+
rb_define_const(mSqlite3Open, "READONLY", INT2FIX(SQLITE_OPEN_READONLY));
|
91
|
+
rb_define_const(mSqlite3Open, "READWRITE", INT2FIX(SQLITE_OPEN_READWRITE));
|
92
|
+
rb_define_const(mSqlite3Open, "CREATE", INT2FIX(SQLITE_OPEN_CREATE));
|
93
|
+
rb_define_const(mSqlite3Open, "DELETEONCLOSE", INT2FIX(SQLITE_OPEN_DELETEONCLOSE));
|
94
|
+
rb_define_const(mSqlite3Open, "EXCLUSIVE", INT2FIX(SQLITE_OPEN_EXCLUSIVE));
|
95
|
+
rb_define_const(mSqlite3Open, "MAIN_DB", INT2FIX(SQLITE_OPEN_MAIN_DB));
|
96
|
+
rb_define_const(mSqlite3Open, "TEMP_DB", INT2FIX(SQLITE_OPEN_TEMP_DB));
|
97
|
+
rb_define_const(mSqlite3Open, "TRANSIENT_DB", INT2FIX(SQLITE_OPEN_TRANSIENT_DB));
|
98
|
+
rb_define_const(mSqlite3Open, "MAIN_JOURNAL", INT2FIX(SQLITE_OPEN_MAIN_JOURNAL));
|
99
|
+
rb_define_const(mSqlite3Open, "TEMP_JOURNAL", INT2FIX(SQLITE_OPEN_TEMP_JOURNAL));
|
100
|
+
rb_define_const(mSqlite3Open, "SUBJOURNAL", INT2FIX(SQLITE_OPEN_SUBJOURNAL));
|
101
|
+
rb_define_const(mSqlite3Open, "MASTER_JOURNAL", INT2FIX(SQLITE_OPEN_MASTER_JOURNAL));
|
102
|
+
rb_define_const(mSqlite3Open, "NOMUTEX", INT2FIX(SQLITE_OPEN_NOMUTEX));
|
103
|
+
rb_define_const(mSqlite3Open, "FULLMUTEX", INT2FIX(SQLITE_OPEN_FULLMUTEX));
|
104
|
+
#ifdef SQLITE_OPEN_AUTOPROXY
|
105
|
+
/* SQLITE_VERSION_NUMBER>=3007002 */
|
106
|
+
rb_define_const(mSqlite3Open, "AUTOPROXY", INT2FIX(SQLITE_OPEN_AUTOPROXY));
|
107
|
+
rb_define_const(mSqlite3Open, "SHAREDCACHE", INT2FIX(SQLITE_OPEN_SHAREDCACHE));
|
108
|
+
rb_define_const(mSqlite3Open, "PRIVATECACHE", INT2FIX(SQLITE_OPEN_PRIVATECACHE));
|
109
|
+
rb_define_const(mSqlite3Open, "WAL", INT2FIX(SQLITE_OPEN_WAL));
|
110
|
+
#endif
|
111
|
+
#ifdef SQLITE_OPEN_URI
|
112
|
+
/* SQLITE_VERSION_NUMBER>=3007007 */
|
113
|
+
rb_define_const(mSqlite3Open, "URI", INT2FIX(SQLITE_OPEN_URI));
|
114
|
+
#endif
|
115
|
+
#ifdef SQLITE_OPEN_MEMORY
|
116
|
+
/* SQLITE_VERSION_NUMBER>=3007013 */
|
117
|
+
rb_define_const(mSqlite3Open, "MEMORY", INT2FIX(SQLITE_OPEN_MEMORY));
|
118
|
+
#endif
|
119
|
+
}
|
120
|
+
|
11
121
|
void Init_sqlite3_native()
|
12
122
|
{
|
13
123
|
/*
|
@@ -28,6 +138,7 @@ void Init_sqlite3_native()
|
|
28
138
|
sqlite3_initialize();
|
29
139
|
#endif
|
30
140
|
|
141
|
+
init_sqlite3_constants();
|
31
142
|
init_sqlite3_database();
|
32
143
|
init_sqlite3_statement();
|
33
144
|
#ifdef HAVE_SQLITE3_BACKUP_INIT
|
@@ -35,6 +146,7 @@ void Init_sqlite3_native()
|
|
35
146
|
#endif
|
36
147
|
|
37
148
|
rb_define_singleton_method(mSqlite3, "libversion", libversion, 0);
|
149
|
+
rb_define_singleton_method(mSqlite3, "threadsafe", threadsafe_p, 0);
|
38
150
|
rb_define_const(mSqlite3, "SQLITE_VERSION", rb_str_new2(SQLITE_VERSION));
|
39
151
|
rb_define_const(mSqlite3, "SQLITE_VERSION_NUMBER", INT2FIX(SQLITE_VERSION_NUMBER));
|
40
152
|
}
|
data/ext/sqlite3/sqlite3_ruby.h
CHANGED
@@ -12,15 +12,13 @@
|
|
12
12
|
# define UNUSED(x) x
|
13
13
|
#endif
|
14
14
|
|
15
|
-
#ifndef RBIGNUM_LEN
|
16
|
-
#define RBIGNUM_LEN(x) RBIGNUM(x)->len
|
17
|
-
#endif
|
18
|
-
|
19
15
|
#ifdef HAVE_RUBY_ENCODING_H
|
20
16
|
#include <ruby/encoding.h>
|
21
17
|
|
18
|
+
#define USASCII_P(_obj) (rb_enc_get_index(_obj) == rb_usascii_encindex())
|
22
19
|
#define UTF8_P(_obj) (rb_enc_get_index(_obj) == rb_utf8_encindex())
|
23
20
|
#define UTF16_LE_P(_obj) (rb_enc_get_index(_obj) == rb_enc_find_index("UTF-16LE"))
|
21
|
+
#define UTF16_BE_P(_obj) (rb_enc_get_index(_obj) == rb_enc_find_index("UTF-16BE"))
|
24
22
|
#define SQLITE3_UTF8_STR_NEW2(_obj) \
|
25
23
|
(rb_enc_associate_index(rb_str_new2(_obj), rb_utf8_encindex()))
|
26
24
|
|
@@ -33,6 +31,14 @@
|
|
33
31
|
|
34
32
|
#include <sqlite3.h>
|
35
33
|
|
34
|
+
#ifndef HAVE_TYPE_SQLITE3_INT64
|
35
|
+
typedef sqlite_int64 sqlite3_int64;
|
36
|
+
#endif
|
37
|
+
|
38
|
+
#ifndef HAVE_TYPE_SQLITE3_UINT64
|
39
|
+
typedef sqlite_uint64 sqlite3_uint64;
|
40
|
+
#endif
|
41
|
+
|
36
42
|
extern VALUE mSqlite3;
|
37
43
|
extern VALUE cSqlite3Blob;
|
38
44
|
|
@@ -41,4 +47,6 @@ extern VALUE cSqlite3Blob;
|
|
41
47
|
#include <exception.h>
|
42
48
|
#include <backup.h>
|
43
49
|
|
50
|
+
int bignum_to_int64(VALUE big, sqlite3_int64 *result);
|
51
|
+
|
44
52
|
#endif
|
data/ext/sqlite3/statement.c
CHANGED
@@ -49,7 +49,11 @@ static VALUE initialize(VALUE self, VALUE db, VALUE sql)
|
|
49
49
|
}
|
50
50
|
#endif
|
51
51
|
|
52
|
+
#ifdef HAVE_SQLITE3_PREPARE_V2
|
52
53
|
status = sqlite3_prepare_v2(
|
54
|
+
#else
|
55
|
+
status = sqlite3_prepare(
|
56
|
+
#endif
|
53
57
|
db_ctx->db,
|
54
58
|
(const char *)StringValuePtr(sql),
|
55
59
|
(int)RSTRING_LEN(sql),
|
@@ -75,15 +79,12 @@ static VALUE initialize(VALUE self, VALUE db, VALUE sql)
|
|
75
79
|
static VALUE sqlite3_rb_close(VALUE self)
|
76
80
|
{
|
77
81
|
sqlite3StmtRubyPtr ctx;
|
78
|
-
sqlite3 * db;
|
79
82
|
|
80
83
|
Data_Get_Struct(self, sqlite3StmtRuby, ctx);
|
81
84
|
|
82
85
|
REQUIRE_OPEN_STMT(ctx);
|
83
86
|
|
84
|
-
|
85
|
-
CHECK(db, sqlite3_finalize(ctx->st));
|
86
|
-
|
87
|
+
sqlite3_finalize(ctx->st);
|
87
88
|
ctx->st = NULL;
|
88
89
|
|
89
90
|
return self;
|
@@ -111,7 +112,6 @@ static VALUE step(VALUE self)
|
|
111
112
|
VALUE list;
|
112
113
|
#ifdef HAVE_RUBY_ENCODING_H
|
113
114
|
rb_encoding * internal_encoding;
|
114
|
-
int enc_index;
|
115
115
|
#endif
|
116
116
|
|
117
117
|
Data_Get_Struct(self, sqlite3StmtRuby, ctx);
|
@@ -123,8 +123,7 @@ static VALUE step(VALUE self)
|
|
123
123
|
#ifdef HAVE_RUBY_ENCODING_H
|
124
124
|
{
|
125
125
|
VALUE db = rb_iv_get(self, "@connection");
|
126
|
-
|
127
|
-
enc_index = NIL_P(encoding) ? rb_utf8_encindex() : rb_to_encoding_index(encoding);
|
126
|
+
rb_funcall(db, rb_intern("encoding"), 0);
|
128
127
|
internal_encoding = rb_default_internal_encoding();
|
129
128
|
}
|
130
129
|
#endif
|
@@ -154,7 +153,7 @@ static VALUE step(VALUE self)
|
|
154
153
|
(long)sqlite3_column_bytes(stmt, i)
|
155
154
|
);
|
156
155
|
#ifdef HAVE_RUBY_ENCODING_H
|
157
|
-
rb_enc_associate_index(str,
|
156
|
+
rb_enc_associate_index(str, rb_utf8_encindex());
|
158
157
|
if(internal_encoding)
|
159
158
|
str = rb_str_export_to_enc(str, internal_encoding);
|
160
159
|
#endif
|
@@ -184,6 +183,8 @@ static VALUE step(VALUE self)
|
|
184
183
|
return Qnil;
|
185
184
|
break;
|
186
185
|
default:
|
186
|
+
sqlite3_reset(stmt);
|
187
|
+
ctx->done_p = 0;
|
187
188
|
CHECK(sqlite3_db_handle(ctx->st), value);
|
188
189
|
}
|
189
190
|
|
@@ -236,15 +237,22 @@ static VALUE bind_param(VALUE self, VALUE key, VALUE value)
|
|
236
237
|
SQLITE_TRANSIENT
|
237
238
|
);
|
238
239
|
} else {
|
240
|
+
|
241
|
+
|
239
242
|
#ifdef HAVE_RUBY_ENCODING_H
|
240
|
-
if(
|
241
|
-
|
242
|
-
|
243
|
-
|
244
|
-
|
243
|
+
if (UTF16_LE_P(value) || UTF16_BE_P(value)) {
|
244
|
+
status = sqlite3_bind_text16(
|
245
|
+
ctx->st,
|
246
|
+
index,
|
247
|
+
(const char *)StringValuePtr(value),
|
248
|
+
(int)RSTRING_LEN(value),
|
249
|
+
SQLITE_TRANSIENT
|
250
|
+
);
|
251
|
+
} else {
|
252
|
+
if (!UTF8_P(value) || !USASCII_P(value)) {
|
253
|
+
value = rb_str_encode(value, rb_enc_from_encoding(rb_utf8_encoding()), 0, Qnil);
|
245
254
|
}
|
246
255
|
#endif
|
247
|
-
|
248
256
|
status = sqlite3_bind_text(
|
249
257
|
ctx->st,
|
250
258
|
index,
|
@@ -252,13 +260,18 @@ static VALUE bind_param(VALUE self, VALUE key, VALUE value)
|
|
252
260
|
(int)RSTRING_LEN(value),
|
253
261
|
SQLITE_TRANSIENT
|
254
262
|
);
|
263
|
+
#ifdef HAVE_RUBY_ENCODING_H
|
264
|
+
}
|
265
|
+
#endif
|
255
266
|
}
|
256
267
|
break;
|
257
|
-
case T_BIGNUM:
|
258
|
-
|
259
|
-
|
268
|
+
case T_BIGNUM: {
|
269
|
+
sqlite3_int64 num64;
|
270
|
+
if (bignum_to_int64(value, &num64)) {
|
271
|
+
status = sqlite3_bind_int64(ctx->st, index, num64);
|
260
272
|
break;
|
261
273
|
}
|
274
|
+
}
|
262
275
|
case T_FLOAT:
|
263
276
|
status = sqlite3_bind_double(ctx->st, index, NUM2DBL(value));
|
264
277
|
break;
|
@@ -287,12 +300,11 @@ static VALUE bind_param(VALUE self, VALUE key, VALUE value)
|
|
287
300
|
static VALUE reset_bang(VALUE self)
|
288
301
|
{
|
289
302
|
sqlite3StmtRubyPtr ctx;
|
290
|
-
int status;
|
291
303
|
|
292
304
|
Data_Get_Struct(self, sqlite3StmtRuby, ctx);
|
293
305
|
REQUIRE_OPEN_STMT(ctx);
|
294
306
|
|
295
|
-
|
307
|
+
sqlite3_reset(ctx->st);
|
296
308
|
|
297
309
|
ctx->done_p = 0;
|
298
310
|
|
@@ -307,12 +319,11 @@ static VALUE reset_bang(VALUE self)
|
|
307
319
|
static VALUE clear_bindings(VALUE self)
|
308
320
|
{
|
309
321
|
sqlite3StmtRubyPtr ctx;
|
310
|
-
int status;
|
311
322
|
|
312
323
|
Data_Get_Struct(self, sqlite3StmtRuby, ctx);
|
313
324
|
REQUIRE_OPEN_STMT(ctx);
|
314
325
|
|
315
|
-
|
326
|
+
sqlite3_clear_bindings(ctx->st);
|
316
327
|
|
317
328
|
ctx->done_p = 0;
|
318
329
|
|
@@ -359,7 +370,7 @@ static VALUE column_name(VALUE self, VALUE index)
|
|
359
370
|
|
360
371
|
name = sqlite3_column_name(ctx->st, (int)NUM2INT(index));
|
361
372
|
|
362
|
-
if(name) return
|
373
|
+
if(name) return SQLITE3_UTF8_STR_NEW2(name);
|
363
374
|
return Qnil;
|
364
375
|
}
|
365
376
|
|
data/faq/faq.yml
CHANGED
data/lib/sqlite3.rb
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
# support multiple ruby version (fat binaries under windows)
|
2
2
|
begin
|
3
|
-
RUBY_VERSION =~ /(\d
|
3
|
+
RUBY_VERSION =~ /(\d+\.\d+)/
|
4
4
|
require "sqlite3/#{$1}/sqlite3_native"
|
5
5
|
rescue LoadError
|
6
6
|
require 'sqlite3/sqlite3_native'
|
@@ -8,3 +8,8 @@ end
|
|
8
8
|
|
9
9
|
require 'sqlite3/database'
|
10
10
|
require 'sqlite3/version'
|
11
|
+
|
12
|
+
module SQLite3
|
13
|
+
# Was sqlite3 compiled with thread safety on?
|
14
|
+
def self.threadsafe?; threadsafe > 0; end
|
15
|
+
end
|
data/lib/sqlite3/database.rb
CHANGED
@@ -94,10 +94,17 @@ in version 2.0.0.
|
|
94
94
|
begin
|
95
95
|
yield stmt
|
96
96
|
ensure
|
97
|
-
stmt.close
|
97
|
+
stmt.close unless stmt.closed?
|
98
98
|
end
|
99
99
|
end
|
100
100
|
|
101
|
+
# Returns the filename for the database named +db_name+. +db_name+ defaults
|
102
|
+
# to "main". Main return `nil` or an empty string if the database is
|
103
|
+
# temporary or in-memory.
|
104
|
+
def filename db_name = 'main'
|
105
|
+
db_filename db_name
|
106
|
+
end
|
107
|
+
|
101
108
|
# Executes the given SQL statement. If additional parameters are given,
|
102
109
|
# they are treated as bind variables, and are bound to the placeholders in
|
103
110
|
# the query.
|
@@ -113,10 +120,6 @@ in version 2.0.0.
|
|
113
120
|
# See also #execute2, #query, and #execute_batch for additional ways of
|
114
121
|
# executing statements.
|
115
122
|
def execute sql, bind_vars = [], *args, &block
|
116
|
-
# FIXME: This is a terrible hack and should be removed but is required
|
117
|
-
# for older versions of rails
|
118
|
-
hack = Object.const_defined?(:ActiveRecord) && sql =~ /^PRAGMA index_list/
|
119
|
-
|
120
123
|
if bind_vars.nil? || !args.empty?
|
121
124
|
if args.empty?
|
122
125
|
bind_vars = []
|
@@ -147,12 +150,7 @@ Support for bind parameters as *args will be removed in 2.0.0.
|
|
147
150
|
else
|
148
151
|
if @results_as_hash
|
149
152
|
stmt.map { |row|
|
150
|
-
|
151
|
-
|
152
|
-
# FIXME UGH TERRIBLE HACK!
|
153
|
-
h['unique'] = h['unique'].to_s if hack
|
154
|
-
|
155
|
-
h
|
153
|
+
type_translation ? row : ordered_map_for(columns, row)
|
156
154
|
}
|
157
155
|
else
|
158
156
|
stmt.to_a
|
@@ -221,22 +219,25 @@ Support for this behavior will be removed in version 2.0.0.
|
|
221
219
|
sql = sql.strip
|
222
220
|
until sql.empty? do
|
223
221
|
prepare( sql ) do |stmt|
|
224
|
-
|
225
|
-
|
226
|
-
|
227
|
-
stmt.
|
222
|
+
unless stmt.closed?
|
223
|
+
# FIXME: this should probably use sqlite3's api for batch execution
|
224
|
+
# This implementation requires stepping over the results.
|
225
|
+
if bind_vars.length == stmt.bind_parameter_count
|
226
|
+
stmt.bind_params(bind_vars)
|
227
|
+
end
|
228
|
+
stmt.step
|
228
229
|
end
|
229
|
-
stmt.step
|
230
230
|
sql = stmt.remainder.strip
|
231
231
|
end
|
232
232
|
end
|
233
|
+
# FIXME: we should not return `nil` as a success return value
|
233
234
|
nil
|
234
235
|
end
|
235
236
|
|
236
237
|
# This is a convenience method for creating a statement, binding
|
237
238
|
# paramters to it, and calling execute:
|
238
239
|
#
|
239
|
-
# result = db.query( "select * from foo where a=?", 5
|
240
|
+
# result = db.query( "select * from foo where a=?", [5])
|
240
241
|
# # is the same as
|
241
242
|
# result = db.prepare( "select * from foo where a=?" ).execute( 5 )
|
242
243
|
#
|
@@ -250,7 +251,7 @@ Support for this behavior will be removed in version 2.0.0.
|
|
250
251
|
if args.empty?
|
251
252
|
bind_vars = []
|
252
253
|
else
|
253
|
-
bind_vars = [
|
254
|
+
bind_vars = [bind_vars] + args
|
254
255
|
end
|
255
256
|
|
256
257
|
warn(<<-eowarn) if $VERBOSE
|
@@ -392,6 +393,9 @@ Support for this will be removed in version 2.0.0.
|
|
392
393
|
|
393
394
|
def finalize
|
394
395
|
super(@ctx)
|
396
|
+
result = @ctx.result
|
397
|
+
@ctx = FunctionProxy.new
|
398
|
+
result
|
395
399
|
end
|
396
400
|
})
|
397
401
|
proxy.ctx = FunctionProxy.new
|
@@ -428,6 +432,7 @@ Support for this will be removed in version 2.0.0.
|
|
428
432
|
#
|
429
433
|
# class LengthsAggregateHandler
|
430
434
|
# def self.arity; 1; end
|
435
|
+
# def self.name; 'lengths'; end
|
431
436
|
#
|
432
437
|
# def initialize
|
433
438
|
# @total = 0
|
@@ -446,21 +451,28 @@ Support for this will be removed in version 2.0.0.
|
|
446
451
|
# puts db.get_first_value( "select lengths(name) from A" )
|
447
452
|
def create_aggregate_handler( handler )
|
448
453
|
proxy = Class.new do
|
449
|
-
def initialize
|
450
|
-
@
|
451
|
-
@fp
|
454
|
+
def initialize klass
|
455
|
+
@klass = klass
|
456
|
+
@fp = FunctionProxy.new
|
452
457
|
end
|
453
458
|
|
454
459
|
def step( *args )
|
455
|
-
|
460
|
+
instance.step(@fp, *args)
|
456
461
|
end
|
457
462
|
|
458
463
|
def finalize
|
459
|
-
|
464
|
+
instance.finalize @fp
|
465
|
+
@instance = nil
|
460
466
|
@fp.result
|
461
467
|
end
|
468
|
+
|
469
|
+
private
|
470
|
+
|
471
|
+
def instance
|
472
|
+
@instance ||= @klass.new
|
473
|
+
end
|
462
474
|
end
|
463
|
-
define_aggregator(handler.name, proxy.new(handler
|
475
|
+
define_aggregator(handler.name, proxy.new(handler))
|
464
476
|
self
|
465
477
|
end
|
466
478
|
|