sqlite3 1.3.5 → 1.3.13
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.
- 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
|
|