sqlite3 1.3.13 → 1.4.0
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/.travis.yml +32 -0
- data/CHANGELOG.rdoc +15 -1
- data/Gemfile +6 -4
- data/Manifest.txt +12 -4
- data/README.rdoc +1 -1
- data/Rakefile +0 -2
- data/appveyor.yml +36 -0
- data/ext/sqlite3/aggregator.c +273 -0
- data/ext/sqlite3/aggregator.h +12 -0
- data/ext/sqlite3/database.c +134 -199
- data/ext/sqlite3/database.h +2 -0
- data/ext/sqlite3/exception.c +6 -2
- data/ext/sqlite3/extconf.rb +39 -10
- data/ext/sqlite3/sqlite3.c +10 -1
- data/ext/sqlite3/sqlite3_ruby.h +0 -7
- data/ext/sqlite3/statement.c +11 -16
- data/lib/sqlite3/constants.rb +1 -0
- data/lib/sqlite3/database.rb +196 -51
- data/lib/sqlite3/errors.rb +1 -10
- data/lib/sqlite3/pragmas.rb +7 -7
- data/lib/sqlite3/resultset.rb +2 -10
- data/lib/sqlite3/version.rb +1 -1
- data/{tasks → rakelib}/faq.rake +0 -0
- data/{tasks → rakelib}/gem.rake +6 -4
- data/{tasks → rakelib}/native.rake +4 -0
- data/{tasks → rakelib}/vendor_sqlite3.rake +0 -0
- data/test/test_database.rb +79 -6
- 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_statement.rb +11 -3
- metadata +56 -27
data/ext/sqlite3/database.c
CHANGED
@@ -1,11 +1,11 @@
|
|
1
1
|
#include <sqlite3_ruby.h>
|
2
|
+
#include <aggregator.h>
|
2
3
|
|
3
4
|
#define REQUIRE_OPEN_DB(_ctxt) \
|
4
5
|
if(!_ctxt->db) \
|
5
6
|
rb_raise(rb_path2class("SQLite3::Exception"), "cannot use a closed database");
|
6
7
|
|
7
8
|
VALUE cSqlite3Database;
|
8
|
-
static VALUE sym_utf16, sym_results_as_hash, sym_type_translation;
|
9
9
|
|
10
10
|
static void deallocate(void * ctx)
|
11
11
|
{
|
@@ -32,126 +32,30 @@ utf16_string_value_ptr(VALUE str)
|
|
32
32
|
|
33
33
|
static VALUE sqlite3_rb_close(VALUE self);
|
34
34
|
|
35
|
-
|
36
|
-
*
|
37
|
-
* Create a new Database object that opens the given file. If utf16
|
38
|
-
* is +true+, the filename is interpreted as a UTF-16 encoded string.
|
39
|
-
*
|
40
|
-
* By default, the new database will return result rows as arrays
|
41
|
-
* (#results_as_hash) and has type translation disabled (#type_translation=).
|
42
|
-
*/
|
43
|
-
static VALUE initialize(int argc, VALUE *argv, VALUE self)
|
35
|
+
static VALUE rb_sqlite3_open_v2(VALUE self, VALUE file, VALUE mode, VALUE zvfs)
|
44
36
|
{
|
45
37
|
sqlite3RubyPtr ctx;
|
46
|
-
VALUE file;
|
47
|
-
VALUE opts;
|
48
|
-
VALUE zvfs;
|
49
38
|
VALUE flags;
|
50
|
-
#ifdef HAVE_SQLITE3_OPEN_V2
|
51
|
-
int mode = SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE;
|
52
|
-
#endif
|
53
39
|
int status;
|
54
40
|
|
55
41
|
Data_Get_Struct(self, sqlite3Ruby, ctx);
|
56
42
|
|
57
|
-
rb_scan_args(argc, argv, "12", &file, &opts, &zvfs);
|
58
43
|
#if defined StringValueCStr
|
59
44
|
StringValuePtr(file);
|
60
45
|
rb_check_safe_obj(file);
|
61
46
|
#else
|
62
47
|
Check_SafeStr(file);
|
63
48
|
#endif
|
64
|
-
if(NIL_P(opts)) opts = rb_hash_new();
|
65
|
-
else Check_Type(opts, T_HASH);
|
66
49
|
|
67
|
-
#ifdef HAVE_RUBY_ENCODING_H
|
68
|
-
if(UTF16_LE_P(file) || UTF16_BE_P(file)) {
|
69
|
-
status = sqlite3_open16(utf16_string_value_ptr(file), &ctx->db);
|
70
|
-
} else {
|
71
|
-
#endif
|
72
|
-
|
73
|
-
if(Qtrue == rb_hash_aref(opts, sym_utf16)) {
|
74
|
-
status = sqlite3_open16(utf16_string_value_ptr(file), &ctx->db);
|
75
|
-
} else {
|
76
|
-
|
77
|
-
#ifdef HAVE_RUBY_ENCODING_H
|
78
|
-
if(!UTF8_P(file)) {
|
79
|
-
file = rb_str_export_to_enc(file, rb_utf8_encoding());
|
80
|
-
}
|
81
|
-
#endif
|
82
|
-
|
83
|
-
/* The three primary flag values for sqlite3_open_v2 are:
|
84
|
-
* SQLITE_OPEN_READONLY
|
85
|
-
* SQLITE_OPEN_READWRITE
|
86
|
-
* SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE -- always used for sqlite3_open and sqlite3_open16
|
87
|
-
*/
|
88
|
-
if (Qtrue == rb_hash_aref(opts, ID2SYM(rb_intern("readonly")))) {
|
89
|
-
#ifdef HAVE_SQLITE3_OPEN_V2
|
90
|
-
mode = SQLITE_OPEN_READONLY;
|
91
|
-
#else
|
92
|
-
rb_raise(rb_eNotImpError, "sqlite3-ruby was compiled against a version of sqlite that does not support readonly databases");
|
93
|
-
#endif
|
94
|
-
}
|
95
|
-
if (Qtrue == rb_hash_aref(opts, ID2SYM(rb_intern("readwrite")))) {
|
96
|
-
#ifdef HAVE_SQLITE3_OPEN_V2
|
97
|
-
if (mode == SQLITE_OPEN_READONLY) {
|
98
|
-
rb_raise(rb_eRuntimeError, "conflicting options: readonly and readwrite");
|
99
|
-
}
|
100
|
-
mode = SQLITE_OPEN_READWRITE;
|
101
|
-
#else
|
102
|
-
rb_raise(rb_eNotImpError, "sqlite3-ruby was compiled against a version of sqlite that does not support readwrite without create");
|
103
|
-
#endif
|
104
|
-
}
|
105
|
-
flags = rb_hash_aref(opts, ID2SYM(rb_intern("flags")));
|
106
|
-
if (flags != Qnil) {
|
107
|
-
#ifdef HAVE_SQLITE3_OPEN_V2
|
108
|
-
if ((mode & SQLITE_OPEN_CREATE) == 0) {
|
109
|
-
rb_raise(rb_eRuntimeError, "conflicting options: flags with readonly and/or readwrite");
|
110
|
-
}
|
111
|
-
mode = (int)NUM2INT(flags);
|
112
|
-
#else
|
113
|
-
rb_raise(rb_eNotImpError, "sqlite3-ruby was compiled against a version of sqlite that does not support flags on open");
|
114
|
-
#endif
|
115
|
-
}
|
116
|
-
#ifdef HAVE_SQLITE3_OPEN_V2
|
117
50
|
status = sqlite3_open_v2(
|
118
51
|
StringValuePtr(file),
|
119
52
|
&ctx->db,
|
120
|
-
mode,
|
53
|
+
NUM2INT(mode),
|
121
54
|
NIL_P(zvfs) ? NULL : StringValuePtr(zvfs)
|
122
55
|
);
|
123
|
-
#else
|
124
|
-
status = sqlite3_open(
|
125
|
-
StringValuePtr(file),
|
126
|
-
&ctx->db
|
127
|
-
);
|
128
|
-
#endif
|
129
|
-
}
|
130
|
-
|
131
|
-
#ifdef HAVE_RUBY_ENCODING_H
|
132
|
-
}
|
133
|
-
#endif
|
134
56
|
|
135
57
|
CHECK(ctx->db, status)
|
136
58
|
|
137
|
-
rb_iv_set(self, "@tracefunc", Qnil);
|
138
|
-
rb_iv_set(self, "@authorizer", Qnil);
|
139
|
-
rb_iv_set(self, "@encoding", Qnil);
|
140
|
-
rb_iv_set(self, "@busy_handler", Qnil);
|
141
|
-
rb_iv_set(self, "@collations", rb_hash_new());
|
142
|
-
rb_iv_set(self, "@functions", rb_hash_new());
|
143
|
-
rb_iv_set(self, "@results_as_hash", rb_hash_aref(opts, sym_results_as_hash));
|
144
|
-
rb_iv_set(self, "@type_translation", rb_hash_aref(opts, sym_type_translation));
|
145
|
-
#ifdef HAVE_SQLITE3_OPEN_V2
|
146
|
-
rb_iv_set(self, "@readonly", (mode & SQLITE_OPEN_READONLY) ? Qtrue : Qfalse);
|
147
|
-
#else
|
148
|
-
rb_iv_set(self, "@readonly", Qfalse);
|
149
|
-
#endif
|
150
|
-
|
151
|
-
if(rb_block_given_p()) {
|
152
|
-
rb_ensure(rb_yield, self, sqlite3_rb_close, self);
|
153
|
-
}
|
154
|
-
|
155
59
|
return self;
|
156
60
|
}
|
157
61
|
|
@@ -170,6 +74,8 @@ static VALUE sqlite3_rb_close(VALUE self)
|
|
170
74
|
|
171
75
|
ctx->db = NULL;
|
172
76
|
|
77
|
+
rb_iv_set(self, "-aggregators", Qnil);
|
78
|
+
|
173
79
|
return self;
|
174
80
|
}
|
175
81
|
|
@@ -297,7 +203,7 @@ static VALUE last_insert_row_id(VALUE self)
|
|
297
203
|
return LL2NUM(sqlite3_last_insert_rowid(ctx->db));
|
298
204
|
}
|
299
205
|
|
300
|
-
|
206
|
+
VALUE sqlite3val2rb(sqlite3_value * val)
|
301
207
|
{
|
302
208
|
switch(sqlite3_value_type(val)) {
|
303
209
|
case SQLITE_INTEGER:
|
@@ -316,14 +222,7 @@ static VALUE sqlite3val2rb(sqlite3_value * val)
|
|
316
222
|
which is what we want, as blobs are binary
|
317
223
|
*/
|
318
224
|
int len = sqlite3_value_bytes(val);
|
319
|
-
#ifdef HAVE_RUBY_ENCODING_H
|
320
225
|
return rb_tainted_str_new((const char *)sqlite3_value_blob(val), len);
|
321
|
-
#else
|
322
|
-
/* When encoding is not available, make it class SQLite3::Blob. */
|
323
|
-
VALUE strargv[1];
|
324
|
-
strargv[0] = rb_tainted_str_new((const char *)sqlite3_value_blob(val), len);
|
325
|
-
return rb_class_new_instance(1, strargv, cSqlite3Blob);
|
326
|
-
#endif
|
327
226
|
break;
|
328
227
|
}
|
329
228
|
case SQLITE_NULL:
|
@@ -334,7 +233,7 @@ static VALUE sqlite3val2rb(sqlite3_value * val)
|
|
334
233
|
}
|
335
234
|
}
|
336
235
|
|
337
|
-
|
236
|
+
void set_sqlite3_func_result(sqlite3_context * ctx, VALUE result)
|
338
237
|
{
|
339
238
|
switch(TYPE(result)) {
|
340
239
|
case T_NIL:
|
@@ -358,9 +257,7 @@ static void set_sqlite3_func_result(sqlite3_context * ctx, VALUE result)
|
|
358
257
|
break;
|
359
258
|
case T_STRING:
|
360
259
|
if(CLASS_OF(result) == cSqlite3Blob
|
361
|
-
#ifdef HAVE_RUBY_ENCODING_H
|
362
260
|
|| rb_enc_get_index(result) == rb_ascii8bit_encindex()
|
363
|
-
#endif
|
364
261
|
) {
|
365
262
|
sqlite3_result_blob(
|
366
263
|
ctx,
|
@@ -409,12 +306,12 @@ int rb_proc_arity(VALUE self)
|
|
409
306
|
}
|
410
307
|
#endif
|
411
308
|
|
412
|
-
/* call-seq:
|
309
|
+
/* call-seq: define_function_with_flags(name, flags) { |args,...| }
|
413
310
|
*
|
414
|
-
* Define a function named +name+ with +args+. The arity of the block
|
311
|
+
* Define a function named +name+ with +args+ using TextRep bitflags +flags+. The arity of the block
|
415
312
|
* will be used as the arity for the function defined.
|
416
313
|
*/
|
417
|
-
static VALUE
|
314
|
+
static VALUE define_function_with_flags(VALUE self, VALUE name, VALUE flags)
|
418
315
|
{
|
419
316
|
sqlite3RubyPtr ctx;
|
420
317
|
VALUE block;
|
@@ -429,7 +326,7 @@ static VALUE define_function(VALUE self, VALUE name)
|
|
429
326
|
ctx->db,
|
430
327
|
StringValuePtr(name),
|
431
328
|
rb_proc_arity(block),
|
432
|
-
|
329
|
+
NUM2INT(flags),
|
433
330
|
(void *)block,
|
434
331
|
rb_sqlite3_func,
|
435
332
|
NULL,
|
@@ -443,70 +340,14 @@ static VALUE define_function(VALUE self, VALUE name)
|
|
443
340
|
return self;
|
444
341
|
}
|
445
342
|
|
446
|
-
|
447
|
-
{
|
448
|
-
VALUE method = rb_funcall(obj, rb_intern("method"), 1, ID2SYM(id));
|
449
|
-
VALUE arity = rb_funcall(method, rb_intern("arity"), 0);
|
450
|
-
|
451
|
-
return (int)NUM2INT(arity);
|
452
|
-
}
|
453
|
-
|
454
|
-
static void rb_sqlite3_step(sqlite3_context * ctx, int argc, sqlite3_value **argv)
|
455
|
-
{
|
456
|
-
VALUE callable = (VALUE)sqlite3_user_data(ctx);
|
457
|
-
VALUE * params = NULL;
|
458
|
-
int i;
|
459
|
-
|
460
|
-
if (argc > 0) {
|
461
|
-
params = xcalloc((size_t)argc, sizeof(VALUE *));
|
462
|
-
for(i = 0; i < argc; i++) {
|
463
|
-
params[i] = sqlite3val2rb(argv[i]);
|
464
|
-
}
|
465
|
-
}
|
466
|
-
rb_funcall2(callable, rb_intern("step"), argc, params);
|
467
|
-
xfree(params);
|
468
|
-
}
|
469
|
-
|
470
|
-
static void rb_sqlite3_final(sqlite3_context * ctx)
|
471
|
-
{
|
472
|
-
VALUE callable = (VALUE)sqlite3_user_data(ctx);
|
473
|
-
VALUE result = rb_funcall(callable, rb_intern("finalize"), 0);
|
474
|
-
set_sqlite3_func_result(ctx, result);
|
475
|
-
}
|
476
|
-
|
477
|
-
/* call-seq: define_aggregator(name, aggregator)
|
343
|
+
/* call-seq: define_function(name) { |args,...| }
|
478
344
|
*
|
479
|
-
* Define
|
480
|
-
*
|
481
|
-
* with row information and +finalize+ must return the return value for the
|
482
|
-
* aggregator function.
|
345
|
+
* Define a function named +name+ with +args+. The arity of the block
|
346
|
+
* will be used as the arity for the function defined.
|
483
347
|
*/
|
484
|
-
static VALUE
|
348
|
+
static VALUE define_function(VALUE self, VALUE name)
|
485
349
|
{
|
486
|
-
|
487
|
-
int arity, status;
|
488
|
-
|
489
|
-
Data_Get_Struct(self, sqlite3Ruby, ctx);
|
490
|
-
REQUIRE_OPEN_DB(ctx);
|
491
|
-
|
492
|
-
arity = sqlite3_obj_method_arity(aggregator, rb_intern("step"));
|
493
|
-
|
494
|
-
status = sqlite3_create_function(
|
495
|
-
ctx->db,
|
496
|
-
StringValuePtr(name),
|
497
|
-
arity,
|
498
|
-
SQLITE_UTF8,
|
499
|
-
(void *)aggregator,
|
500
|
-
NULL,
|
501
|
-
rb_sqlite3_step,
|
502
|
-
rb_sqlite3_final
|
503
|
-
);
|
504
|
-
|
505
|
-
rb_iv_set(self, "@agregator", aggregator);
|
506
|
-
|
507
|
-
CHECK(ctx->db, status);
|
508
|
-
|
509
|
-
return self;
|
350
|
+
return define_function_with_flags(self, name, INT2FIX(SQLITE_UTF8));
|
510
351
|
}
|
511
352
|
|
512
353
|
/* call-seq: interrupt
|
@@ -654,23 +495,36 @@ static VALUE set_busy_timeout(VALUE self, VALUE timeout)
|
|
654
495
|
return self;
|
655
496
|
}
|
656
497
|
|
498
|
+
/* call-seq: db.extended_result_codes = true
|
499
|
+
*
|
500
|
+
* Enable extended result codes in SQLite. These result codes allow for more
|
501
|
+
* detailed exception reporting, such a which type of constraint is violated.
|
502
|
+
*/
|
503
|
+
static VALUE set_extended_result_codes(VALUE self, VALUE enable)
|
504
|
+
{
|
505
|
+
sqlite3RubyPtr ctx;
|
506
|
+
Data_Get_Struct(self, sqlite3Ruby, ctx);
|
507
|
+
REQUIRE_OPEN_DB(ctx);
|
508
|
+
|
509
|
+
CHECK(ctx->db, sqlite3_extended_result_codes(ctx->db, RTEST(enable) ? 1 : 0));
|
510
|
+
|
511
|
+
return self;
|
512
|
+
}
|
513
|
+
|
657
514
|
int rb_comparator_func(void * ctx, int a_len, const void * a, int b_len, const void * b)
|
658
515
|
{
|
659
516
|
VALUE comparator;
|
660
517
|
VALUE a_str;
|
661
518
|
VALUE b_str;
|
662
519
|
VALUE comparison;
|
663
|
-
#ifdef HAVE_RUBY_ENCODING_H
|
664
520
|
rb_encoding * internal_encoding;
|
665
521
|
|
666
522
|
internal_encoding = rb_default_internal_encoding();
|
667
|
-
#endif
|
668
523
|
|
669
524
|
comparator = (VALUE)ctx;
|
670
525
|
a_str = rb_str_new((const char *)a, a_len);
|
671
526
|
b_str = rb_str_new((const char *)b, b_len);
|
672
527
|
|
673
|
-
#ifdef HAVE_RUBY_ENCODING_H
|
674
528
|
rb_enc_associate_index(a_str, rb_utf8_encindex());
|
675
529
|
rb_enc_associate_index(b_str, rb_utf8_encindex());
|
676
530
|
|
@@ -678,7 +532,6 @@ int rb_comparator_func(void * ctx, int a_len, const void * a, int b_len, const v
|
|
678
532
|
a_str = rb_str_export_to_enc(a_str, internal_encoding);
|
679
533
|
b_str = rb_str_export_to_enc(b_str, internal_encoding);
|
680
534
|
}
|
681
|
-
#endif
|
682
535
|
|
683
536
|
comparison = rb_funcall(comparator, rb_intern("compare"), 2, a_str, b_str);
|
684
537
|
|
@@ -765,7 +618,6 @@ static VALUE enable_load_extension(VALUE self, VALUE onoff)
|
|
765
618
|
}
|
766
619
|
#endif
|
767
620
|
|
768
|
-
#ifdef HAVE_RUBY_ENCODING_H
|
769
621
|
static int enc_cb(void * _self, int UNUSED(columns), char **data, char **UNUSED(names))
|
770
622
|
{
|
771
623
|
VALUE self = (VALUE)_self;
|
@@ -776,16 +628,6 @@ static int enc_cb(void * _self, int UNUSED(columns), char **data, char **UNUSED(
|
|
776
628
|
|
777
629
|
return 0;
|
778
630
|
}
|
779
|
-
#else
|
780
|
-
static int enc_cb(void * _self, int UNUSED(columns), char **data, char **UNUSED(names))
|
781
|
-
{
|
782
|
-
VALUE self = (VALUE)_self;
|
783
|
-
|
784
|
-
rb_iv_set(self, "@encoding", rb_str_new2(data[0]));
|
785
|
-
|
786
|
-
return 0;
|
787
|
-
}
|
788
|
-
#endif
|
789
631
|
|
790
632
|
/* call-seq: db.encoding
|
791
633
|
*
|
@@ -822,6 +664,78 @@ static VALUE transaction_active_p(VALUE self)
|
|
822
664
|
return sqlite3_get_autocommit(ctx->db) ? Qfalse : Qtrue;
|
823
665
|
}
|
824
666
|
|
667
|
+
static int hash_callback_function(VALUE callback_ary, int count, char **data, char **columns)
|
668
|
+
{
|
669
|
+
VALUE new_hash = rb_hash_new();
|
670
|
+
int i;
|
671
|
+
|
672
|
+
for (i = 0; i < count; i++) {
|
673
|
+
if (data[i] == NULL) {
|
674
|
+
rb_hash_aset(new_hash, rb_str_new_cstr(columns[i]), Qnil);
|
675
|
+
} else {
|
676
|
+
rb_hash_aset(new_hash, rb_str_new_cstr(columns[i]), rb_str_new_cstr(data[i]));
|
677
|
+
}
|
678
|
+
}
|
679
|
+
|
680
|
+
rb_ary_push(callback_ary, new_hash);
|
681
|
+
|
682
|
+
return 0;
|
683
|
+
}
|
684
|
+
|
685
|
+
static int regular_callback_function(VALUE callback_ary, int count, char **data, char **columns)
|
686
|
+
{
|
687
|
+
VALUE new_ary = rb_ary_new();
|
688
|
+
int i;
|
689
|
+
|
690
|
+
for (i = 0; i < count; i++) {
|
691
|
+
if (data[i] == NULL) {
|
692
|
+
rb_ary_push(new_ary, Qnil);
|
693
|
+
} else {
|
694
|
+
rb_ary_push(new_ary, rb_str_new_cstr(data[i]));
|
695
|
+
}
|
696
|
+
}
|
697
|
+
|
698
|
+
rb_ary_push(callback_ary, new_ary);
|
699
|
+
|
700
|
+
return 0;
|
701
|
+
}
|
702
|
+
|
703
|
+
|
704
|
+
/* Is invoked by calling db.execute_batch2(sql, &block)
|
705
|
+
*
|
706
|
+
* Executes all statments in a given string separated by semicolons.
|
707
|
+
* If a query is made, all values returned are strings
|
708
|
+
* (except for 'NULL' values which return nil),
|
709
|
+
* so the user may parse values with a block.
|
710
|
+
* If no query is made, an empty array will be returned.
|
711
|
+
*/
|
712
|
+
static VALUE exec_batch(VALUE self, VALUE sql, VALUE results_as_hash)
|
713
|
+
{
|
714
|
+
sqlite3RubyPtr ctx;
|
715
|
+
int status;
|
716
|
+
VALUE callback_ary = rb_ary_new();
|
717
|
+
char *errMsg;
|
718
|
+
VALUE errexp;
|
719
|
+
|
720
|
+
Data_Get_Struct(self, sqlite3Ruby, ctx);
|
721
|
+
REQUIRE_OPEN_DB(ctx);
|
722
|
+
|
723
|
+
if(results_as_hash == Qtrue) {
|
724
|
+
status = sqlite3_exec(ctx->db, StringValuePtr(sql), hash_callback_function, callback_ary, &errMsg);
|
725
|
+
} else {
|
726
|
+
status = sqlite3_exec(ctx->db, StringValuePtr(sql), regular_callback_function, callback_ary, &errMsg);
|
727
|
+
}
|
728
|
+
|
729
|
+
if (status != SQLITE_OK)
|
730
|
+
{
|
731
|
+
errexp = rb_exc_new2(rb_eRuntimeError, errMsg);
|
732
|
+
sqlite3_free(errMsg);
|
733
|
+
rb_exc_raise(errexp);
|
734
|
+
}
|
735
|
+
|
736
|
+
return callback_ary;
|
737
|
+
}
|
738
|
+
|
825
739
|
/* call-seq: db.db_filename(database_name)
|
826
740
|
*
|
827
741
|
* Returns the file associated with +database_name+. Can return nil or an
|
@@ -840,16 +754,37 @@ static VALUE db_filename(VALUE self, VALUE db_name)
|
|
840
754
|
return Qnil;
|
841
755
|
}
|
842
756
|
|
757
|
+
static VALUE rb_sqlite3_open16(VALUE self, VALUE file)
|
758
|
+
{
|
759
|
+
int status;
|
760
|
+
sqlite3RubyPtr ctx;
|
761
|
+
|
762
|
+
Data_Get_Struct(self, sqlite3Ruby, ctx);
|
763
|
+
|
764
|
+
#if defined StringValueCStr
|
765
|
+
StringValuePtr(file);
|
766
|
+
rb_check_safe_obj(file);
|
767
|
+
#else
|
768
|
+
Check_SafeStr(file);
|
769
|
+
#endif
|
770
|
+
|
771
|
+
status = sqlite3_open16(utf16_string_value_ptr(file), &ctx->db);
|
772
|
+
|
773
|
+
CHECK(ctx->db, status)
|
774
|
+
|
775
|
+
return INT2NUM(status);
|
776
|
+
}
|
777
|
+
|
843
778
|
void init_sqlite3_database()
|
844
779
|
{
|
845
|
-
ID id_utf16, id_results_as_hash, id_type_translation;
|
846
780
|
#if 0
|
847
781
|
VALUE mSqlite3 = rb_define_module("SQLite3");
|
848
782
|
#endif
|
849
783
|
cSqlite3Database = rb_define_class_under(mSqlite3, "Database", rb_cObject);
|
850
784
|
|
851
785
|
rb_define_alloc_func(cSqlite3Database, allocate);
|
852
|
-
|
786
|
+
rb_define_private_method(cSqlite3Database, "open_v2", rb_sqlite3_open_v2, 3);
|
787
|
+
rb_define_private_method(cSqlite3Database, "open16", rb_sqlite3_open16, 1);
|
853
788
|
rb_define_method(cSqlite3Database, "collation", collation, 2);
|
854
789
|
rb_define_method(cSqlite3Database, "close", sqlite3_rb_close, 0);
|
855
790
|
rb_define_method(cSqlite3Database, "closed?", closed_p, 0);
|
@@ -857,7 +792,10 @@ void init_sqlite3_database()
|
|
857
792
|
rb_define_method(cSqlite3Database, "trace", trace, -1);
|
858
793
|
rb_define_method(cSqlite3Database, "last_insert_row_id", last_insert_row_id, 0);
|
859
794
|
rb_define_method(cSqlite3Database, "define_function", define_function, 1);
|
860
|
-
rb_define_method(cSqlite3Database, "
|
795
|
+
rb_define_method(cSqlite3Database, "define_function_with_flags", define_function_with_flags, 2);
|
796
|
+
/* public "define_aggregator" is now a shim around define_aggregator2
|
797
|
+
* implemented in Ruby */
|
798
|
+
rb_define_private_method(cSqlite3Database, "define_aggregator2", rb_sqlite3_define_aggregator2, 2);
|
861
799
|
rb_define_method(cSqlite3Database, "interrupt", interrupt, 0);
|
862
800
|
rb_define_method(cSqlite3Database, "errmsg", errmsg, 0);
|
863
801
|
rb_define_method(cSqlite3Database, "errcode", errcode_, 0);
|
@@ -866,7 +804,9 @@ void init_sqlite3_database()
|
|
866
804
|
rb_define_method(cSqlite3Database, "authorizer=", set_authorizer, 1);
|
867
805
|
rb_define_method(cSqlite3Database, "busy_handler", busy_handler, -1);
|
868
806
|
rb_define_method(cSqlite3Database, "busy_timeout=", set_busy_timeout, 1);
|
807
|
+
rb_define_method(cSqlite3Database, "extended_result_codes=", set_extended_result_codes, 1);
|
869
808
|
rb_define_method(cSqlite3Database, "transaction_active?", transaction_active_p, 0);
|
809
|
+
rb_define_private_method(cSqlite3Database, "exec_batch", exec_batch, 2);
|
870
810
|
rb_define_private_method(cSqlite3Database, "db_filename", db_filename, 1);
|
871
811
|
|
872
812
|
#ifdef HAVE_SQLITE3_LOAD_EXTENSION
|
@@ -879,10 +819,5 @@ void init_sqlite3_database()
|
|
879
819
|
|
880
820
|
rb_define_method(cSqlite3Database, "encoding", db_encoding, 0);
|
881
821
|
|
882
|
-
|
883
|
-
sym_utf16 = ID2SYM(id_utf16);
|
884
|
-
id_results_as_hash = rb_intern("results_as_hash");
|
885
|
-
sym_results_as_hash = ID2SYM(id_results_as_hash);
|
886
|
-
id_type_translation = rb_intern("type_translation");
|
887
|
-
sym_type_translation = ID2SYM(id_type_translation);
|
822
|
+
rb_sqlite3_aggregator_init();
|
888
823
|
}
|