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.
Files changed (54) hide show
  1. checksums.yaml +5 -5
  2. data/.gemtest +0 -0
  3. data/{API_CHANGES.rdoc → API_CHANGES.md} +3 -4
  4. data/CHANGELOG.md +419 -0
  5. data/CONTRIBUTING.md +24 -0
  6. data/Gemfile +2 -15
  7. data/LICENSE-DEPENDENCIES +20 -0
  8. data/README.md +233 -0
  9. data/ext/sqlite3/aggregator.c +273 -0
  10. data/ext/sqlite3/aggregator.h +12 -0
  11. data/ext/sqlite3/database.c +210 -182
  12. data/ext/sqlite3/database.h +2 -0
  13. data/ext/sqlite3/exception.c +6 -2
  14. data/ext/sqlite3/extconf.rb +148 -39
  15. data/ext/sqlite3/sqlite3.c +67 -1
  16. data/ext/sqlite3/sqlite3_ruby.h +0 -7
  17. data/ext/sqlite3/statement.c +15 -20
  18. data/faq/faq.md +431 -0
  19. data/faq/faq.yml +1 -1
  20. data/lib/sqlite3/2.6/sqlite3_native.so +0 -0
  21. data/lib/sqlite3/2.7/sqlite3_native.so +0 -0
  22. data/lib/sqlite3/3.0/sqlite3_native.so +0 -0
  23. data/lib/sqlite3/constants.rb +2 -1
  24. data/lib/sqlite3/database.rb +209 -58
  25. data/lib/sqlite3/errors.rb +1 -10
  26. data/lib/sqlite3/pragmas.rb +372 -57
  27. data/lib/sqlite3/resultset.rb +2 -10
  28. data/lib/sqlite3/statement.rb +2 -1
  29. data/lib/sqlite3/translator.rb +1 -1
  30. data/lib/sqlite3/version.rb +4 -4
  31. data/lib/sqlite3.rb +5 -0
  32. data/test/helper.rb +9 -0
  33. data/test/test_database.rb +180 -9
  34. data/test/test_database_flags.rb +95 -0
  35. data/test/test_database_readonly.rb +9 -2
  36. data/test/test_database_readwrite.rb +41 -0
  37. data/test/test_integration.rb +12 -77
  38. data/test/test_integration_aggregate.rb +336 -0
  39. data/test/test_integration_resultset.rb +0 -17
  40. data/test/test_sqlite3.rb +16 -0
  41. data/test/test_statement.rb +12 -9
  42. metadata +55 -84
  43. data/CHANGELOG.rdoc +0 -287
  44. data/Manifest.txt +0 -52
  45. data/README.rdoc +0 -101
  46. data/Rakefile +0 -10
  47. data/lib/sqlite3/2.0/sqlite3_native.so +0 -0
  48. data/lib/sqlite3/2.1/sqlite3_native.so +0 -0
  49. data/lib/sqlite3/2.2/sqlite3_native.so +0 -0
  50. data/setup.rb +0 -1333
  51. data/tasks/faq.rake +0 -9
  52. data/tasks/gem.rake +0 -38
  53. data/tasks/native.rake +0 -52
  54. data/tasks/vendor_sqlite3.rake +0 -97
@@ -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
- /* call-seq: SQLite3::Database.new(file, options = {})
34
- *
35
- * Create a new Database object that opens the given file. If utf16
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
- rb_scan_args(argc, argv, "12", &file, &opts, &zvfs);
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
- rb_iv_set(self, "@tracefunc", Qnil);
109
- rb_iv_set(self, "@authorizer", Qnil);
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
- if(rb_block_given_p()) {
123
- rb_yield(self);
124
- rb_funcall(self, rb_intern("close"), 0);
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 self;
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
- static VALUE sqlite3val2rb(sqlite3_value * val)
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 rb_tainted_str_new2((const char *)sqlite3_value_text(val));
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 and rb_tainted_str_new apparently create string with ASCII-8BIT (BINARY) encoding,
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 rb_tainted_str_new((const char *)sqlite3_value_blob(val), len);
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
- static void set_sqlite3_func_result(sqlite3_context * ctx, VALUE result)
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
- sqlite3_result_text(
326
- ctx,
327
- (const char *)StringValuePtr(result),
328
- (int)RSTRING_LEN(result),
329
- SQLITE_TRANSIENT
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 * params = NULL;
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
- RB_GC_GUARD(param);
351
- params[i] = param;
316
+ rb_ary_push(params, param);
352
317
  }
353
318
  }
354
319
 
355
- result = rb_funcall2(callable, rb_intern("call"), argc, params);
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: define_function(name) { |args,...| }
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 define_function(VALUE self, VALUE name)
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
- SQLITE_UTF8,
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
- static int sqlite3_obj_method_arity(VALUE obj, ID id)
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 an aggregate function named +name+ using the object +aggregator+.
436
- * +aggregator+ must respond to +step+ and +finalize+. +step+ will be called
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 define_aggregator(VALUE self, VALUE name, VALUE aggregator)
371
+ static VALUE define_function(VALUE self, VALUE name)
441
372
  {
442
- sqlite3RubyPtr ctx;
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
- rb_define_method(cSqlite3Database, "initialize", initialize, -1);
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, "define_aggregator", define_aggregator, 2);
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
- id_utf16 = rb_intern("utf16");
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
@@ -11,5 +11,7 @@ typedef struct _sqlite3Ruby sqlite3Ruby;
11
11
  typedef sqlite3Ruby * sqlite3RubyPtr;
12
12
 
13
13
  void init_sqlite3_database();
14
+ void set_sqlite3_func_result(sqlite3_context * ctx, VALUE result);
15
+ VALUE sqlite3val2rb(sqlite3_value * val);
14
16
 
15
17
  #endif
@@ -4,7 +4,9 @@ void rb_sqlite3_raise(sqlite3 * db, int status)
4
4
  {
5
5
  VALUE klass = Qnil;
6
6
 
7
- switch(status) {
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
- rb_raise(klass, "%s", sqlite3_errmsg(db));
95
+ klass = rb_exc_new2(klass, sqlite3_errmsg(db));
96
+ rb_iv_set(klass, "@code", INT2FIX(status));
97
+ rb_exc_raise(klass);
94
98
  }