sqlite3 1.3.11-x64-mingw32 → 1.5.0.rc1-x64-mingw32
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 +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 -15
- 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 +210 -182
- data/ext/sqlite3/database.h +2 -0
- data/ext/sqlite3/exception.c +6 -2
- data/ext/sqlite3/extconf.rb +148 -39
- data/ext/sqlite3/sqlite3.c +67 -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 +209 -58
- data/lib/sqlite3/errors.rb +1 -10
- data/lib/sqlite3/pragmas.rb +372 -57
- 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/lib/sqlite3.rb +5 -0
- data/test/helper.rb +9 -0
- data/test/test_database.rb +180 -9
- data/test/test_database_flags.rb +95 -0
- data/test/test_database_readonly.rb +9 -2
- data/test/test_database_readwrite.rb +41 -0
- data/test/test_integration.rb +12 -77
- data/test/test_integration_aggregate.rb +336 -0
- data/test/test_integration_resultset.rb +0 -17
- data/test/test_sqlite3.rb +16 -0
- data/test/test_statement.rb +12 -9
- metadata +55 -84
- data/CHANGELOG.rdoc +0 -287
- data/Manifest.txt +0 -52
- data/README.rdoc +0 -101
- 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/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/ext/sqlite3/database.c
CHANGED
@@ -1,11 +1,16 @@
|
|
1
1
|
#include <sqlite3_ruby.h>
|
2
|
+
#include <aggregator.h>
|
3
|
+
|
4
|
+
#ifdef _MSC_VER
|
5
|
+
#pragma warning( push )
|
6
|
+
#pragma warning( disable : 4028 )
|
7
|
+
#endif
|
2
8
|
|
3
9
|
#define REQUIRE_OPEN_DB(_ctxt) \
|
4
10
|
if(!_ctxt->db) \
|
5
11
|
rb_raise(rb_path2class("SQLite3::Exception"), "cannot use a closed database");
|
6
12
|
|
7
13
|
VALUE cSqlite3Database;
|
8
|
-
static VALUE sym_utf16, sym_results_as_hash, sym_type_translation;
|
9
14
|
|
10
15
|
static void deallocate(void * ctx)
|
11
16
|
{
|
@@ -30,101 +35,51 @@ utf16_string_value_ptr(VALUE str)
|
|
30
35
|
return RSTRING_PTR(str);
|
31
36
|
}
|
32
37
|
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
* is +true+, the filename is interpreted as a UTF-16 encoded string.
|
37
|
-
*
|
38
|
-
* By default, the new database will return result rows as arrays
|
39
|
-
* (#results_as_hash) and has type translation disabled (#type_translation=).
|
40
|
-
*/
|
41
|
-
static VALUE initialize(int argc, VALUE *argv, VALUE self)
|
38
|
+
static VALUE sqlite3_rb_close(VALUE self);
|
39
|
+
|
40
|
+
static VALUE rb_sqlite3_open_v2(VALUE self, VALUE file, VALUE mode, VALUE zvfs)
|
42
41
|
{
|
43
42
|
sqlite3RubyPtr ctx;
|
44
|
-
VALUE file;
|
45
|
-
VALUE opts;
|
46
|
-
VALUE zvfs;
|
47
|
-
#ifdef HAVE_SQLITE3_OPEN_V2
|
48
|
-
int mode = SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE;
|
49
|
-
#endif
|
50
43
|
int status;
|
51
44
|
|
52
45
|
Data_Get_Struct(self, sqlite3Ruby, ctx);
|
53
46
|
|
54
|
-
|
55
|
-
#if defined StringValueCStr
|
47
|
+
#if defined TAINTING_SUPPORT
|
48
|
+
# if defined StringValueCStr
|
56
49
|
StringValuePtr(file);
|
57
50
|
rb_check_safe_obj(file);
|
58
|
-
#else
|
51
|
+
# else
|
59
52
|
Check_SafeStr(file);
|
60
|
-
#endif
|
61
|
-
if(NIL_P(opts)) opts = rb_hash_new();
|
62
|
-
else Check_Type(opts, T_HASH);
|
63
|
-
|
64
|
-
#ifdef HAVE_RUBY_ENCODING_H
|
65
|
-
if(UTF16_LE_P(file) || UTF16_BE_P(file)) {
|
66
|
-
status = sqlite3_open16(utf16_string_value_ptr(file), &ctx->db);
|
67
|
-
} else {
|
53
|
+
# endif
|
68
54
|
#endif
|
69
55
|
|
70
|
-
if(Qtrue == rb_hash_aref(opts, sym_utf16)) {
|
71
|
-
status = sqlite3_open16(utf16_string_value_ptr(file), &ctx->db);
|
72
|
-
} else {
|
73
|
-
|
74
|
-
#ifdef HAVE_RUBY_ENCODING_H
|
75
|
-
if(!UTF8_P(file)) {
|
76
|
-
file = rb_str_export_to_enc(file, rb_utf8_encoding());
|
77
|
-
}
|
78
|
-
#endif
|
79
|
-
|
80
|
-
if (Qtrue == rb_hash_aref(opts, ID2SYM(rb_intern("readonly")))) {
|
81
|
-
#ifdef HAVE_SQLITE3_OPEN_V2
|
82
|
-
mode = SQLITE_OPEN_READONLY;
|
83
|
-
#else
|
84
|
-
rb_raise(rb_eNotImpError, "sqlite3-ruby was compiled against a version of sqlite that does not support readonly databases");
|
85
|
-
#endif
|
86
|
-
}
|
87
|
-
#ifdef HAVE_SQLITE3_OPEN_V2
|
88
56
|
status = sqlite3_open_v2(
|
89
57
|
StringValuePtr(file),
|
90
58
|
&ctx->db,
|
91
|
-
mode,
|
59
|
+
NUM2INT(mode),
|
92
60
|
NIL_P(zvfs) ? NULL : StringValuePtr(zvfs)
|
93
61
|
);
|
94
|
-
#else
|
95
|
-
status = sqlite3_open(
|
96
|
-
StringValuePtr(file),
|
97
|
-
&ctx->db
|
98
|
-
);
|
99
|
-
#endif
|
100
|
-
}
|
101
|
-
|
102
|
-
#ifdef HAVE_RUBY_ENCODING_H
|
103
|
-
}
|
104
|
-
#endif
|
105
62
|
|
106
63
|
CHECK(ctx->db, status)
|
107
64
|
|
108
|
-
|
109
|
-
|
110
|
-
rb_iv_set(self, "@encoding", Qnil);
|
111
|
-
rb_iv_set(self, "@busy_handler", Qnil);
|
112
|
-
rb_iv_set(self, "@collations", rb_hash_new());
|
113
|
-
rb_iv_set(self, "@functions", rb_hash_new());
|
114
|
-
rb_iv_set(self, "@results_as_hash", rb_hash_aref(opts, sym_results_as_hash));
|
115
|
-
rb_iv_set(self, "@type_translation", rb_hash_aref(opts, sym_type_translation));
|
116
|
-
#ifdef HAVE_SQLITE3_OPEN_V2
|
117
|
-
rb_iv_set(self, "@readonly", mode == SQLITE_OPEN_READONLY ? Qtrue : Qfalse);
|
118
|
-
#else
|
119
|
-
rb_iv_set(self, "@readonly", Qfalse);
|
120
|
-
#endif
|
65
|
+
return self;
|
66
|
+
}
|
121
67
|
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
68
|
+
static VALUE rb_sqlite3_disable_quirk_mode(VALUE self)
|
69
|
+
{
|
70
|
+
#if defined SQLITE_DBCONFIG_DQS_DDL
|
71
|
+
sqlite3RubyPtr ctx;
|
72
|
+
Data_Get_Struct(self, sqlite3Ruby, ctx);
|
126
73
|
|
127
|
-
return
|
74
|
+
if(!ctx->db) return Qfalse;
|
75
|
+
|
76
|
+
sqlite3_db_config(ctx->db, SQLITE_DBCONFIG_DQS_DDL, 0, (void*)0);
|
77
|
+
sqlite3_db_config(ctx->db, SQLITE_DBCONFIG_DQS_DML, 0, (void*)0);
|
78
|
+
|
79
|
+
return Qtrue;
|
80
|
+
#else
|
81
|
+
return Qfalse;
|
82
|
+
#endif
|
128
83
|
}
|
129
84
|
|
130
85
|
/* call-seq: db.close
|
@@ -142,6 +97,8 @@ static VALUE sqlite3_rb_close(VALUE self)
|
|
142
97
|
|
143
98
|
ctx->db = NULL;
|
144
99
|
|
100
|
+
rb_iv_set(self, "-aggregators", Qnil);
|
101
|
+
|
145
102
|
return self;
|
146
103
|
}
|
147
104
|
|
@@ -269,7 +226,7 @@ static VALUE last_insert_row_id(VALUE self)
|
|
269
226
|
return LL2NUM(sqlite3_last_insert_rowid(ctx->db));
|
270
227
|
}
|
271
228
|
|
272
|
-
|
229
|
+
VALUE sqlite3val2rb(sqlite3_value * val)
|
273
230
|
{
|
274
231
|
switch(sqlite3_value_type(val)) {
|
275
232
|
case SQLITE_INTEGER:
|
@@ -279,16 +236,16 @@ static VALUE sqlite3val2rb(sqlite3_value * val)
|
|
279
236
|
return rb_float_new(sqlite3_value_double(val));
|
280
237
|
break;
|
281
238
|
case SQLITE_TEXT:
|
282
|
-
return
|
239
|
+
return rb_str_new2((const char *)sqlite3_value_text(val));
|
283
240
|
break;
|
284
241
|
case SQLITE_BLOB: {
|
285
242
|
/* Sqlite warns calling sqlite3_value_bytes may invalidate pointer from sqlite3_value_blob,
|
286
243
|
so we explicitly get the length before getting blob pointer.
|
287
|
-
Note that rb_str_new
|
244
|
+
Note that rb_str_new apparently create string with ASCII-8BIT (BINARY) encoding,
|
288
245
|
which is what we want, as blobs are binary
|
289
246
|
*/
|
290
247
|
int len = sqlite3_value_bytes(val);
|
291
|
-
return
|
248
|
+
return rb_str_new((const char *)sqlite3_value_blob(val), len);
|
292
249
|
break;
|
293
250
|
}
|
294
251
|
case SQLITE_NULL:
|
@@ -299,7 +256,7 @@ static VALUE sqlite3val2rb(sqlite3_value * val)
|
|
299
256
|
}
|
300
257
|
}
|
301
258
|
|
302
|
-
|
259
|
+
void set_sqlite3_func_result(sqlite3_context * ctx, VALUE result)
|
303
260
|
{
|
304
261
|
switch(TYPE(result)) {
|
305
262
|
case T_NIL:
|
@@ -322,12 +279,23 @@ static void set_sqlite3_func_result(sqlite3_context * ctx, VALUE result)
|
|
322
279
|
sqlite3_result_double(ctx, NUM2DBL(result));
|
323
280
|
break;
|
324
281
|
case T_STRING:
|
325
|
-
|
326
|
-
|
327
|
-
|
328
|
-
|
329
|
-
|
330
|
-
|
282
|
+
if(CLASS_OF(result) == cSqlite3Blob
|
283
|
+
|| rb_enc_get_index(result) == rb_ascii8bit_encindex()
|
284
|
+
) {
|
285
|
+
sqlite3_result_blob(
|
286
|
+
ctx,
|
287
|
+
(const void *)StringValuePtr(result),
|
288
|
+
(int)RSTRING_LEN(result),
|
289
|
+
SQLITE_TRANSIENT
|
290
|
+
);
|
291
|
+
} else {
|
292
|
+
sqlite3_result_text(
|
293
|
+
ctx,
|
294
|
+
(const char *)StringValuePtr(result),
|
295
|
+
(int)RSTRING_LEN(result),
|
296
|
+
SQLITE_TRANSIENT
|
297
|
+
);
|
298
|
+
}
|
331
299
|
break;
|
332
300
|
default:
|
333
301
|
rb_raise(rb_eRuntimeError, "can't return %s",
|
@@ -338,22 +306,18 @@ static void set_sqlite3_func_result(sqlite3_context * ctx, VALUE result)
|
|
338
306
|
static void rb_sqlite3_func(sqlite3_context * ctx, int argc, sqlite3_value **argv)
|
339
307
|
{
|
340
308
|
VALUE callable = (VALUE)sqlite3_user_data(ctx);
|
341
|
-
VALUE
|
309
|
+
VALUE params = rb_ary_new2(argc);
|
342
310
|
VALUE result;
|
343
311
|
int i;
|
344
312
|
|
345
313
|
if (argc > 0) {
|
346
|
-
params = xcalloc((size_t)argc, sizeof(VALUE *));
|
347
|
-
|
348
314
|
for(i = 0; i < argc; i++) {
|
349
315
|
VALUE param = sqlite3val2rb(argv[i]);
|
350
|
-
|
351
|
-
params[i] = param;
|
316
|
+
rb_ary_push(params, param);
|
352
317
|
}
|
353
318
|
}
|
354
319
|
|
355
|
-
result =
|
356
|
-
xfree(params);
|
320
|
+
result = rb_apply(callable, rb_intern("call"), params);
|
357
321
|
|
358
322
|
set_sqlite3_func_result(ctx, result);
|
359
323
|
}
|
@@ -365,12 +329,12 @@ int rb_proc_arity(VALUE self)
|
|
365
329
|
}
|
366
330
|
#endif
|
367
331
|
|
368
|
-
/* call-seq:
|
332
|
+
/* call-seq: define_function_with_flags(name, flags) { |args,...| }
|
369
333
|
*
|
370
|
-
* Define a function named +name+ with +args+. The arity of the block
|
334
|
+
* Define a function named +name+ with +args+ using TextRep bitflags +flags+. The arity of the block
|
371
335
|
* will be used as the arity for the function defined.
|
372
336
|
*/
|
373
|
-
static VALUE
|
337
|
+
static VALUE define_function_with_flags(VALUE self, VALUE name, VALUE flags)
|
374
338
|
{
|
375
339
|
sqlite3RubyPtr ctx;
|
376
340
|
VALUE block;
|
@@ -385,7 +349,7 @@ static VALUE define_function(VALUE self, VALUE name)
|
|
385
349
|
ctx->db,
|
386
350
|
StringValuePtr(name),
|
387
351
|
rb_proc_arity(block),
|
388
|
-
|
352
|
+
NUM2INT(flags),
|
389
353
|
(void *)block,
|
390
354
|
rb_sqlite3_func,
|
391
355
|
NULL,
|
@@ -399,70 +363,14 @@ static VALUE define_function(VALUE self, VALUE name)
|
|
399
363
|
return self;
|
400
364
|
}
|
401
365
|
|
402
|
-
|
403
|
-
{
|
404
|
-
VALUE method = rb_funcall(obj, rb_intern("method"), 1, ID2SYM(id));
|
405
|
-
VALUE arity = rb_funcall(method, rb_intern("arity"), 0);
|
406
|
-
|
407
|
-
return (int)NUM2INT(arity);
|
408
|
-
}
|
409
|
-
|
410
|
-
static void rb_sqlite3_step(sqlite3_context * ctx, int argc, sqlite3_value **argv)
|
411
|
-
{
|
412
|
-
VALUE callable = (VALUE)sqlite3_user_data(ctx);
|
413
|
-
VALUE * params = NULL;
|
414
|
-
int i;
|
415
|
-
|
416
|
-
if (argc > 0) {
|
417
|
-
params = xcalloc((size_t)argc, sizeof(VALUE *));
|
418
|
-
for(i = 0; i < argc; i++) {
|
419
|
-
params[i] = sqlite3val2rb(argv[i]);
|
420
|
-
}
|
421
|
-
}
|
422
|
-
rb_funcall2(callable, rb_intern("step"), argc, params);
|
423
|
-
xfree(params);
|
424
|
-
}
|
425
|
-
|
426
|
-
static void rb_sqlite3_final(sqlite3_context * ctx)
|
427
|
-
{
|
428
|
-
VALUE callable = (VALUE)sqlite3_user_data(ctx);
|
429
|
-
VALUE result = rb_funcall(callable, rb_intern("finalize"), 0);
|
430
|
-
set_sqlite3_func_result(ctx, result);
|
431
|
-
}
|
432
|
-
|
433
|
-
/* call-seq: define_aggregator(name, aggregator)
|
366
|
+
/* call-seq: define_function(name) { |args,...| }
|
434
367
|
*
|
435
|
-
* Define
|
436
|
-
*
|
437
|
-
* with row information and +finalize+ must return the return value for the
|
438
|
-
* aggregator function.
|
368
|
+
* Define a function named +name+ with +args+. The arity of the block
|
369
|
+
* will be used as the arity for the function defined.
|
439
370
|
*/
|
440
|
-
static VALUE
|
371
|
+
static VALUE define_function(VALUE self, VALUE name)
|
441
372
|
{
|
442
|
-
|
443
|
-
int arity, status;
|
444
|
-
|
445
|
-
Data_Get_Struct(self, sqlite3Ruby, ctx);
|
446
|
-
REQUIRE_OPEN_DB(ctx);
|
447
|
-
|
448
|
-
arity = sqlite3_obj_method_arity(aggregator, rb_intern("step"));
|
449
|
-
|
450
|
-
status = sqlite3_create_function(
|
451
|
-
ctx->db,
|
452
|
-
StringValuePtr(name),
|
453
|
-
arity,
|
454
|
-
SQLITE_UTF8,
|
455
|
-
(void *)aggregator,
|
456
|
-
NULL,
|
457
|
-
rb_sqlite3_step,
|
458
|
-
rb_sqlite3_final
|
459
|
-
);
|
460
|
-
|
461
|
-
rb_iv_set(self, "@agregator", aggregator);
|
462
|
-
|
463
|
-
CHECK(ctx->db, status);
|
464
|
-
|
465
|
-
return self;
|
373
|
+
return define_function_with_flags(self, name, INT2FIX(SQLITE_UTF8));
|
466
374
|
}
|
467
375
|
|
468
376
|
/* call-seq: interrupt
|
@@ -610,23 +518,36 @@ static VALUE set_busy_timeout(VALUE self, VALUE timeout)
|
|
610
518
|
return self;
|
611
519
|
}
|
612
520
|
|
521
|
+
/* call-seq: db.extended_result_codes = true
|
522
|
+
*
|
523
|
+
* Enable extended result codes in SQLite. These result codes allow for more
|
524
|
+
* detailed exception reporting, such a which type of constraint is violated.
|
525
|
+
*/
|
526
|
+
static VALUE set_extended_result_codes(VALUE self, VALUE enable)
|
527
|
+
{
|
528
|
+
sqlite3RubyPtr ctx;
|
529
|
+
Data_Get_Struct(self, sqlite3Ruby, ctx);
|
530
|
+
REQUIRE_OPEN_DB(ctx);
|
531
|
+
|
532
|
+
CHECK(ctx->db, sqlite3_extended_result_codes(ctx->db, RTEST(enable) ? 1 : 0));
|
533
|
+
|
534
|
+
return self;
|
535
|
+
}
|
536
|
+
|
613
537
|
int rb_comparator_func(void * ctx, int a_len, const void * a, int b_len, const void * b)
|
614
538
|
{
|
615
539
|
VALUE comparator;
|
616
540
|
VALUE a_str;
|
617
541
|
VALUE b_str;
|
618
542
|
VALUE comparison;
|
619
|
-
#ifdef HAVE_RUBY_ENCODING_H
|
620
543
|
rb_encoding * internal_encoding;
|
621
544
|
|
622
545
|
internal_encoding = rb_default_internal_encoding();
|
623
|
-
#endif
|
624
546
|
|
625
547
|
comparator = (VALUE)ctx;
|
626
548
|
a_str = rb_str_new((const char *)a, a_len);
|
627
549
|
b_str = rb_str_new((const char *)b, b_len);
|
628
550
|
|
629
|
-
#ifdef HAVE_RUBY_ENCODING_H
|
630
551
|
rb_enc_associate_index(a_str, rb_utf8_encindex());
|
631
552
|
rb_enc_associate_index(b_str, rb_utf8_encindex());
|
632
553
|
|
@@ -634,7 +555,6 @@ int rb_comparator_func(void * ctx, int a_len, const void * a, int b_len, const v
|
|
634
555
|
a_str = rb_str_export_to_enc(a_str, internal_encoding);
|
635
556
|
b_str = rb_str_export_to_enc(b_str, internal_encoding);
|
636
557
|
}
|
637
|
-
#endif
|
638
558
|
|
639
559
|
comparison = rb_funcall(comparator, rb_intern("compare"), 2, a_str, b_str);
|
640
560
|
|
@@ -721,7 +641,6 @@ static VALUE enable_load_extension(VALUE self, VALUE onoff)
|
|
721
641
|
}
|
722
642
|
#endif
|
723
643
|
|
724
|
-
#ifdef HAVE_RUBY_ENCODING_H
|
725
644
|
static int enc_cb(void * _self, int UNUSED(columns), char **data, char **UNUSED(names))
|
726
645
|
{
|
727
646
|
VALUE self = (VALUE)_self;
|
@@ -732,16 +651,6 @@ static int enc_cb(void * _self, int UNUSED(columns), char **data, char **UNUSED(
|
|
732
651
|
|
733
652
|
return 0;
|
734
653
|
}
|
735
|
-
#else
|
736
|
-
static int enc_cb(void * _self, int UNUSED(columns), char **data, char **UNUSED(names))
|
737
|
-
{
|
738
|
-
VALUE self = (VALUE)_self;
|
739
|
-
|
740
|
-
rb_iv_set(self, "@encoding", rb_str_new2(data[0]));
|
741
|
-
|
742
|
-
return 0;
|
743
|
-
}
|
744
|
-
#endif
|
745
654
|
|
746
655
|
/* call-seq: db.encoding
|
747
656
|
*
|
@@ -778,16 +687,129 @@ static VALUE transaction_active_p(VALUE self)
|
|
778
687
|
return sqlite3_get_autocommit(ctx->db) ? Qfalse : Qtrue;
|
779
688
|
}
|
780
689
|
|
690
|
+
static int hash_callback_function(VALUE callback_ary, int count, char **data, char **columns)
|
691
|
+
{
|
692
|
+
VALUE new_hash = rb_hash_new();
|
693
|
+
int i;
|
694
|
+
|
695
|
+
for (i = 0; i < count; i++) {
|
696
|
+
if (data[i] == NULL) {
|
697
|
+
rb_hash_aset(new_hash, rb_str_new_cstr(columns[i]), Qnil);
|
698
|
+
} else {
|
699
|
+
rb_hash_aset(new_hash, rb_str_new_cstr(columns[i]), rb_str_new_cstr(data[i]));
|
700
|
+
}
|
701
|
+
}
|
702
|
+
|
703
|
+
rb_ary_push(callback_ary, new_hash);
|
704
|
+
|
705
|
+
return 0;
|
706
|
+
}
|
707
|
+
|
708
|
+
static int regular_callback_function(VALUE callback_ary, int count, char **data, char **columns)
|
709
|
+
{
|
710
|
+
VALUE new_ary = rb_ary_new();
|
711
|
+
int i;
|
712
|
+
|
713
|
+
for (i = 0; i < count; i++) {
|
714
|
+
if (data[i] == NULL) {
|
715
|
+
rb_ary_push(new_ary, Qnil);
|
716
|
+
} else {
|
717
|
+
rb_ary_push(new_ary, rb_str_new_cstr(data[i]));
|
718
|
+
}
|
719
|
+
}
|
720
|
+
|
721
|
+
rb_ary_push(callback_ary, new_ary);
|
722
|
+
|
723
|
+
return 0;
|
724
|
+
}
|
725
|
+
|
726
|
+
|
727
|
+
/* Is invoked by calling db.execute_batch2(sql, &block)
|
728
|
+
*
|
729
|
+
* Executes all statements in a given string separated by semicolons.
|
730
|
+
* If a query is made, all values returned are strings
|
731
|
+
* (except for 'NULL' values which return nil),
|
732
|
+
* so the user may parse values with a block.
|
733
|
+
* If no query is made, an empty array will be returned.
|
734
|
+
*/
|
735
|
+
static VALUE exec_batch(VALUE self, VALUE sql, VALUE results_as_hash)
|
736
|
+
{
|
737
|
+
sqlite3RubyPtr ctx;
|
738
|
+
int status;
|
739
|
+
VALUE callback_ary = rb_ary_new();
|
740
|
+
char *errMsg;
|
741
|
+
VALUE errexp;
|
742
|
+
|
743
|
+
Data_Get_Struct(self, sqlite3Ruby, ctx);
|
744
|
+
REQUIRE_OPEN_DB(ctx);
|
745
|
+
|
746
|
+
if(results_as_hash == Qtrue) {
|
747
|
+
status = sqlite3_exec(ctx->db, StringValuePtr(sql), (sqlite3_callback)hash_callback_function, (void*)callback_ary, &errMsg);
|
748
|
+
} else {
|
749
|
+
status = sqlite3_exec(ctx->db, StringValuePtr(sql), (sqlite3_callback)regular_callback_function, (void*)callback_ary, &errMsg);
|
750
|
+
}
|
751
|
+
|
752
|
+
if (status != SQLITE_OK)
|
753
|
+
{
|
754
|
+
errexp = rb_exc_new2(rb_eRuntimeError, errMsg);
|
755
|
+
sqlite3_free(errMsg);
|
756
|
+
rb_exc_raise(errexp);
|
757
|
+
}
|
758
|
+
|
759
|
+
return callback_ary;
|
760
|
+
}
|
761
|
+
|
762
|
+
/* call-seq: db.db_filename(database_name)
|
763
|
+
*
|
764
|
+
* Returns the file associated with +database_name+. Can return nil or an
|
765
|
+
* empty string if the database is temporary, or in-memory.
|
766
|
+
*/
|
767
|
+
static VALUE db_filename(VALUE self, VALUE db_name)
|
768
|
+
{
|
769
|
+
sqlite3RubyPtr ctx;
|
770
|
+
const char * fname;
|
771
|
+
Data_Get_Struct(self, sqlite3Ruby, ctx);
|
772
|
+
REQUIRE_OPEN_DB(ctx);
|
773
|
+
|
774
|
+
fname = sqlite3_db_filename(ctx->db, StringValueCStr(db_name));
|
775
|
+
|
776
|
+
if(fname) return SQLITE3_UTF8_STR_NEW2(fname);
|
777
|
+
return Qnil;
|
778
|
+
}
|
779
|
+
|
780
|
+
static VALUE rb_sqlite3_open16(VALUE self, VALUE file)
|
781
|
+
{
|
782
|
+
int status;
|
783
|
+
sqlite3RubyPtr ctx;
|
784
|
+
|
785
|
+
Data_Get_Struct(self, sqlite3Ruby, ctx);
|
786
|
+
|
787
|
+
#if defined TAINTING_SUPPORT
|
788
|
+
#if defined StringValueCStr
|
789
|
+
StringValuePtr(file);
|
790
|
+
rb_check_safe_obj(file);
|
791
|
+
#else
|
792
|
+
Check_SafeStr(file);
|
793
|
+
#endif
|
794
|
+
#endif
|
795
|
+
|
796
|
+
status = sqlite3_open16(utf16_string_value_ptr(file), &ctx->db);
|
797
|
+
|
798
|
+
CHECK(ctx->db, status)
|
799
|
+
|
800
|
+
return INT2NUM(status);
|
801
|
+
}
|
802
|
+
|
781
803
|
void init_sqlite3_database()
|
782
804
|
{
|
783
|
-
ID id_utf16, id_results_as_hash, id_type_translation;
|
784
805
|
#if 0
|
785
806
|
VALUE mSqlite3 = rb_define_module("SQLite3");
|
786
807
|
#endif
|
787
808
|
cSqlite3Database = rb_define_class_under(mSqlite3, "Database", rb_cObject);
|
788
809
|
|
789
810
|
rb_define_alloc_func(cSqlite3Database, allocate);
|
790
|
-
|
811
|
+
rb_define_private_method(cSqlite3Database, "open_v2", rb_sqlite3_open_v2, 3);
|
812
|
+
rb_define_private_method(cSqlite3Database, "open16", rb_sqlite3_open16, 1);
|
791
813
|
rb_define_method(cSqlite3Database, "collation", collation, 2);
|
792
814
|
rb_define_method(cSqlite3Database, "close", sqlite3_rb_close, 0);
|
793
815
|
rb_define_method(cSqlite3Database, "closed?", closed_p, 0);
|
@@ -795,7 +817,11 @@ void init_sqlite3_database()
|
|
795
817
|
rb_define_method(cSqlite3Database, "trace", trace, -1);
|
796
818
|
rb_define_method(cSqlite3Database, "last_insert_row_id", last_insert_row_id, 0);
|
797
819
|
rb_define_method(cSqlite3Database, "define_function", define_function, 1);
|
798
|
-
rb_define_method(cSqlite3Database, "
|
820
|
+
rb_define_method(cSqlite3Database, "define_function_with_flags", define_function_with_flags, 2);
|
821
|
+
/* public "define_aggregator" is now a shim around define_aggregator2
|
822
|
+
* implemented in Ruby */
|
823
|
+
rb_define_private_method(cSqlite3Database, "define_aggregator2", rb_sqlite3_define_aggregator2, 2);
|
824
|
+
rb_define_private_method(cSqlite3Database, "disable_quirk_mode", rb_sqlite3_disable_quirk_mode, 0);
|
799
825
|
rb_define_method(cSqlite3Database, "interrupt", interrupt, 0);
|
800
826
|
rb_define_method(cSqlite3Database, "errmsg", errmsg, 0);
|
801
827
|
rb_define_method(cSqlite3Database, "errcode", errcode_, 0);
|
@@ -804,7 +830,10 @@ void init_sqlite3_database()
|
|
804
830
|
rb_define_method(cSqlite3Database, "authorizer=", set_authorizer, 1);
|
805
831
|
rb_define_method(cSqlite3Database, "busy_handler", busy_handler, -1);
|
806
832
|
rb_define_method(cSqlite3Database, "busy_timeout=", set_busy_timeout, 1);
|
833
|
+
rb_define_method(cSqlite3Database, "extended_result_codes=", set_extended_result_codes, 1);
|
807
834
|
rb_define_method(cSqlite3Database, "transaction_active?", transaction_active_p, 0);
|
835
|
+
rb_define_private_method(cSqlite3Database, "exec_batch", exec_batch, 2);
|
836
|
+
rb_define_private_method(cSqlite3Database, "db_filename", db_filename, 1);
|
808
837
|
|
809
838
|
#ifdef HAVE_SQLITE3_LOAD_EXTENSION
|
810
839
|
rb_define_method(cSqlite3Database, "load_extension", load_extension, 1);
|
@@ -816,10 +845,9 @@ void init_sqlite3_database()
|
|
816
845
|
|
817
846
|
rb_define_method(cSqlite3Database, "encoding", db_encoding, 0);
|
818
847
|
|
819
|
-
|
820
|
-
sym_utf16 = ID2SYM(id_utf16);
|
821
|
-
id_results_as_hash = rb_intern("results_as_hash");
|
822
|
-
sym_results_as_hash = ID2SYM(id_results_as_hash);
|
823
|
-
id_type_translation = rb_intern("type_translation");
|
824
|
-
sym_type_translation = ID2SYM(id_type_translation);
|
848
|
+
rb_sqlite3_aggregator_init();
|
825
849
|
}
|
850
|
+
|
851
|
+
#ifdef _MSC_VER
|
852
|
+
#pragma warning( pop )
|
853
|
+
#endif
|
data/ext/sqlite3/database.h
CHANGED
data/ext/sqlite3/exception.c
CHANGED
@@ -4,7 +4,9 @@ void rb_sqlite3_raise(sqlite3 * db, int status)
|
|
4
4
|
{
|
5
5
|
VALUE klass = Qnil;
|
6
6
|
|
7
|
-
|
7
|
+
/* Consider only lower 8 bits, to work correctly when
|
8
|
+
extended result codes are enabled. */
|
9
|
+
switch(status & 0xff) {
|
8
10
|
case SQLITE_OK:
|
9
11
|
return;
|
10
12
|
break;
|
@@ -90,5 +92,7 @@ void rb_sqlite3_raise(sqlite3 * db, int status)
|
|
90
92
|
klass = rb_eRuntimeError;
|
91
93
|
}
|
92
94
|
|
93
|
-
|
95
|
+
klass = rb_exc_new2(klass, sqlite3_errmsg(db));
|
96
|
+
rb_iv_set(klass, "@code", INT2FIX(status));
|
97
|
+
rb_exc_raise(klass);
|
94
98
|
}
|