mockley_crew 1.1.0 → 1.1.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (69) hide show
  1. checksums.yaml +4 -4
  2. data/lib/mockley_crew/version.rb +1 -1
  3. data/vendor/gems/sqlite3/cache/sqlite3-1.3.13.gem +0 -0
  4. data/vendor/gems/sqlite3/extensions/x86_64-linux/2.5.0/sqlite3-1.3.13/gem.build_complete +0 -0
  5. data/vendor/gems/sqlite3/extensions/x86_64-linux/2.5.0/sqlite3-1.3.13/gem_make.out +33 -0
  6. data/vendor/gems/sqlite3/extensions/x86_64-linux/2.5.0/sqlite3-1.3.13/mkmf.log +592 -0
  7. data/vendor/gems/sqlite3/extensions/x86_64-linux/2.5.0/sqlite3-1.3.13/sqlite3/sqlite3_native.so +0 -0
  8. data/vendor/gems/sqlite3/gems/sqlite3-1.3.13/API_CHANGES.rdoc +50 -0
  9. data/vendor/gems/sqlite3/gems/sqlite3-1.3.13/CHANGELOG.rdoc +292 -0
  10. data/vendor/gems/sqlite3/gems/sqlite3-1.3.13/ChangeLog.cvs +88 -0
  11. data/vendor/gems/sqlite3/gems/sqlite3-1.3.13/Gemfile +15 -0
  12. data/vendor/gems/sqlite3/gems/sqlite3-1.3.13/LICENSE +27 -0
  13. data/vendor/gems/sqlite3/gems/sqlite3-1.3.13/Manifest.txt +52 -0
  14. data/vendor/gems/sqlite3/gems/sqlite3-1.3.13/README.rdoc +118 -0
  15. data/vendor/gems/sqlite3/gems/sqlite3-1.3.13/Rakefile +10 -0
  16. data/vendor/gems/sqlite3/gems/sqlite3-1.3.13/ext/sqlite3/Makefile +263 -0
  17. data/vendor/gems/sqlite3/gems/sqlite3-1.3.13/ext/sqlite3/backup.c +168 -0
  18. data/vendor/gems/sqlite3/gems/sqlite3-1.3.13/ext/sqlite3/backup.h +15 -0
  19. data/vendor/gems/sqlite3/gems/sqlite3-1.3.13/ext/sqlite3/backup.o +0 -0
  20. data/vendor/gems/sqlite3/gems/sqlite3-1.3.13/ext/sqlite3/database.c +888 -0
  21. data/vendor/gems/sqlite3/gems/sqlite3-1.3.13/ext/sqlite3/database.h +15 -0
  22. data/vendor/gems/sqlite3/gems/sqlite3-1.3.13/ext/sqlite3/database.o +0 -0
  23. data/vendor/gems/sqlite3/gems/sqlite3-1.3.13/ext/sqlite3/exception.c +94 -0
  24. data/vendor/gems/sqlite3/gems/sqlite3-1.3.13/ext/sqlite3/exception.h +8 -0
  25. data/vendor/gems/sqlite3/gems/sqlite3-1.3.13/ext/sqlite3/exception.o +0 -0
  26. data/vendor/gems/sqlite3/gems/sqlite3-1.3.13/ext/sqlite3/extconf.rb +71 -0
  27. data/vendor/gems/sqlite3/gems/sqlite3-1.3.13/ext/sqlite3/sqlite3.c +152 -0
  28. data/vendor/gems/sqlite3/gems/sqlite3-1.3.13/ext/sqlite3/sqlite3.o +0 -0
  29. data/vendor/gems/sqlite3/gems/sqlite3-1.3.13/ext/sqlite3/sqlite3_native.so +0 -0
  30. data/vendor/gems/sqlite3/gems/sqlite3-1.3.13/ext/sqlite3/sqlite3_ruby.h +52 -0
  31. data/vendor/gems/sqlite3/gems/sqlite3-1.3.13/ext/sqlite3/statement.c +447 -0
  32. data/vendor/gems/sqlite3/gems/sqlite3-1.3.13/ext/sqlite3/statement.h +16 -0
  33. data/vendor/gems/sqlite3/gems/sqlite3-1.3.13/ext/sqlite3/statement.o +0 -0
  34. data/vendor/gems/sqlite3/gems/sqlite3-1.3.13/faq/faq.rb +145 -0
  35. data/vendor/gems/sqlite3/gems/sqlite3-1.3.13/faq/faq.yml +426 -0
  36. data/vendor/gems/sqlite3/gems/sqlite3-1.3.13/lib/sqlite3/constants.rb +49 -0
  37. data/vendor/gems/sqlite3/gems/sqlite3-1.3.13/lib/sqlite3/database.rb +591 -0
  38. data/vendor/gems/sqlite3/gems/sqlite3-1.3.13/lib/sqlite3/errors.rb +44 -0
  39. data/vendor/gems/sqlite3/gems/sqlite3-1.3.13/lib/sqlite3/pragmas.rb +588 -0
  40. data/vendor/gems/sqlite3/gems/sqlite3-1.3.13/lib/sqlite3/resultset.rb +195 -0
  41. data/vendor/gems/sqlite3/gems/sqlite3-1.3.13/lib/sqlite3/sqlite3_native.so +0 -0
  42. data/vendor/gems/sqlite3/gems/sqlite3-1.3.13/lib/sqlite3/statement.rb +144 -0
  43. data/vendor/gems/sqlite3/gems/sqlite3-1.3.13/lib/sqlite3/translator.rb +118 -0
  44. data/vendor/gems/sqlite3/gems/sqlite3-1.3.13/lib/sqlite3/value.rb +57 -0
  45. data/vendor/gems/sqlite3/gems/sqlite3-1.3.13/lib/sqlite3/version.rb +25 -0
  46. data/vendor/gems/sqlite3/gems/sqlite3-1.3.13/lib/sqlite3.rb +15 -0
  47. data/vendor/gems/sqlite3/gems/sqlite3-1.3.13/setup.rb +1333 -0
  48. data/vendor/gems/sqlite3/gems/sqlite3-1.3.13/tasks/faq.rake +9 -0
  49. data/vendor/gems/sqlite3/gems/sqlite3-1.3.13/tasks/gem.rake +38 -0
  50. data/vendor/gems/sqlite3/gems/sqlite3-1.3.13/tasks/native.rake +52 -0
  51. data/vendor/gems/sqlite3/gems/sqlite3-1.3.13/tasks/vendor_sqlite3.rake +97 -0
  52. data/vendor/gems/sqlite3/gems/sqlite3-1.3.13/test/helper.rb +18 -0
  53. data/vendor/gems/sqlite3/gems/sqlite3-1.3.13/test/test_backup.rb +33 -0
  54. data/vendor/gems/sqlite3/gems/sqlite3-1.3.13/test/test_collation.rb +82 -0
  55. data/vendor/gems/sqlite3/gems/sqlite3-1.3.13/test/test_database.rb +430 -0
  56. data/vendor/gems/sqlite3/gems/sqlite3-1.3.13/test/test_database_readonly.rb +36 -0
  57. data/vendor/gems/sqlite3/gems/sqlite3-1.3.13/test/test_deprecated.rb +44 -0
  58. data/vendor/gems/sqlite3/gems/sqlite3-1.3.13/test/test_encoding.rb +155 -0
  59. data/vendor/gems/sqlite3/gems/sqlite3-1.3.13/test/test_integration.rb +576 -0
  60. data/vendor/gems/sqlite3/gems/sqlite3-1.3.13/test/test_integration_open_close.rb +30 -0
  61. data/vendor/gems/sqlite3/gems/sqlite3-1.3.13/test/test_integration_pending.rb +115 -0
  62. data/vendor/gems/sqlite3/gems/sqlite3-1.3.13/test/test_integration_resultset.rb +159 -0
  63. data/vendor/gems/sqlite3/gems/sqlite3-1.3.13/test/test_integration_statement.rb +194 -0
  64. data/vendor/gems/sqlite3/gems/sqlite3-1.3.13/test/test_result_set.rb +37 -0
  65. data/vendor/gems/sqlite3/gems/sqlite3-1.3.13/test/test_sqlite3.rb +21 -0
  66. data/vendor/gems/sqlite3/gems/sqlite3-1.3.13/test/test_statement.rb +260 -0
  67. data/vendor/gems/sqlite3/gems/sqlite3-1.3.13/test/test_statement_execute.rb +35 -0
  68. data/vendor/gems/sqlite3/specifications/sqlite3-1.3.13.gemspec +56 -0
  69. metadata +67 -1
@@ -0,0 +1,888 @@
1
+ #include <sqlite3_ruby.h>
2
+
3
+ #define REQUIRE_OPEN_DB(_ctxt) \
4
+ if(!_ctxt->db) \
5
+ rb_raise(rb_path2class("SQLite3::Exception"), "cannot use a closed database");
6
+
7
+ VALUE cSqlite3Database;
8
+ static VALUE sym_utf16, sym_results_as_hash, sym_type_translation;
9
+
10
+ static void deallocate(void * ctx)
11
+ {
12
+ sqlite3RubyPtr c = (sqlite3RubyPtr)ctx;
13
+ sqlite3 * db = c->db;
14
+
15
+ if(db) sqlite3_close(db);
16
+ xfree(c);
17
+ }
18
+
19
+ static VALUE allocate(VALUE klass)
20
+ {
21
+ sqlite3RubyPtr ctx = xcalloc((size_t)1, sizeof(sqlite3Ruby));
22
+ return Data_Wrap_Struct(klass, NULL, deallocate, ctx);
23
+ }
24
+
25
+ static char *
26
+ utf16_string_value_ptr(VALUE str)
27
+ {
28
+ StringValue(str);
29
+ rb_str_buf_cat(str, "\x00", 1L);
30
+ return RSTRING_PTR(str);
31
+ }
32
+
33
+ static VALUE sqlite3_rb_close(VALUE self);
34
+
35
+ /* call-seq: SQLite3::Database.new(file, options = {})
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)
44
+ {
45
+ sqlite3RubyPtr ctx;
46
+ VALUE file;
47
+ VALUE opts;
48
+ VALUE zvfs;
49
+ VALUE flags;
50
+ #ifdef HAVE_SQLITE3_OPEN_V2
51
+ int mode = SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE;
52
+ #endif
53
+ int status;
54
+
55
+ Data_Get_Struct(self, sqlite3Ruby, ctx);
56
+
57
+ rb_scan_args(argc, argv, "12", &file, &opts, &zvfs);
58
+ #if defined StringValueCStr
59
+ StringValuePtr(file);
60
+ rb_check_safe_obj(file);
61
+ #else
62
+ Check_SafeStr(file);
63
+ #endif
64
+ if(NIL_P(opts)) opts = rb_hash_new();
65
+ else Check_Type(opts, T_HASH);
66
+
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
+ status = sqlite3_open_v2(
118
+ StringValuePtr(file),
119
+ &ctx->db,
120
+ mode,
121
+ NIL_P(zvfs) ? NULL : StringValuePtr(zvfs)
122
+ );
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
+
135
+ CHECK(ctx->db, status)
136
+
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
+ return self;
156
+ }
157
+
158
+ /* call-seq: db.close
159
+ *
160
+ * Closes this database.
161
+ */
162
+ static VALUE sqlite3_rb_close(VALUE self)
163
+ {
164
+ sqlite3RubyPtr ctx;
165
+ sqlite3 * db;
166
+ Data_Get_Struct(self, sqlite3Ruby, ctx);
167
+
168
+ db = ctx->db;
169
+ CHECK(db, sqlite3_close(ctx->db));
170
+
171
+ ctx->db = NULL;
172
+
173
+ return self;
174
+ }
175
+
176
+ /* call-seq: db.closed?
177
+ *
178
+ * Returns +true+ if this database instance has been closed (see #close).
179
+ */
180
+ static VALUE closed_p(VALUE self)
181
+ {
182
+ sqlite3RubyPtr ctx;
183
+ Data_Get_Struct(self, sqlite3Ruby, ctx);
184
+
185
+ if(!ctx->db) return Qtrue;
186
+
187
+ return Qfalse;
188
+ }
189
+
190
+ /* call-seq: total_changes
191
+ *
192
+ * Returns the total number of changes made to this database instance
193
+ * since it was opened.
194
+ */
195
+ static VALUE total_changes(VALUE self)
196
+ {
197
+ sqlite3RubyPtr ctx;
198
+ Data_Get_Struct(self, sqlite3Ruby, ctx);
199
+ REQUIRE_OPEN_DB(ctx);
200
+
201
+ return INT2NUM((long)sqlite3_total_changes(ctx->db));
202
+ }
203
+
204
+ static void tracefunc(void * data, const char *sql)
205
+ {
206
+ VALUE self = (VALUE)data;
207
+ VALUE thing = rb_iv_get(self, "@tracefunc");
208
+ rb_funcall(thing, rb_intern("call"), 1, rb_str_new2(sql));
209
+ }
210
+
211
+ /* call-seq:
212
+ * trace { |sql| ... }
213
+ * trace(Class.new { def call sql; end }.new)
214
+ *
215
+ * Installs (or removes) a block that will be invoked for every SQL
216
+ * statement executed. The block receives one parameter: the SQL statement
217
+ * executed. If the block is +nil+, any existing tracer will be uninstalled.
218
+ */
219
+ static VALUE trace(int argc, VALUE *argv, VALUE self)
220
+ {
221
+ sqlite3RubyPtr ctx;
222
+ VALUE block;
223
+
224
+ Data_Get_Struct(self, sqlite3Ruby, ctx);
225
+ REQUIRE_OPEN_DB(ctx);
226
+
227
+ rb_scan_args(argc, argv, "01", &block);
228
+
229
+ if(NIL_P(block) && rb_block_given_p()) block = rb_block_proc();
230
+
231
+ rb_iv_set(self, "@tracefunc", block);
232
+
233
+ sqlite3_trace(ctx->db, NIL_P(block) ? NULL : tracefunc, (void *)self);
234
+
235
+ return self;
236
+ }
237
+
238
+ static int rb_sqlite3_busy_handler(void * ctx, int count)
239
+ {
240
+ VALUE self = (VALUE)(ctx);
241
+ VALUE handle = rb_iv_get(self, "@busy_handler");
242
+ VALUE result = rb_funcall(handle, rb_intern("call"), 1, INT2NUM((long)count));
243
+
244
+ if(Qfalse == result) return 0;
245
+
246
+ return 1;
247
+ }
248
+
249
+ /* call-seq:
250
+ * busy_handler { |count| ... }
251
+ * busy_handler(Class.new { def call count; end }.new)
252
+ *
253
+ * Register a busy handler with this database instance. When a requested
254
+ * resource is busy, this handler will be invoked. If the handler returns
255
+ * +false+, the operation will be aborted; otherwise, the resource will
256
+ * be requested again.
257
+ *
258
+ * The handler will be invoked with the name of the resource that was
259
+ * busy, and the number of times it has been retried.
260
+ *
261
+ * See also the mutually exclusive #busy_timeout.
262
+ */
263
+ static VALUE busy_handler(int argc, VALUE *argv, VALUE self)
264
+ {
265
+ sqlite3RubyPtr ctx;
266
+ VALUE block;
267
+ int status;
268
+
269
+ Data_Get_Struct(self, sqlite3Ruby, ctx);
270
+ REQUIRE_OPEN_DB(ctx);
271
+
272
+ rb_scan_args(argc, argv, "01", &block);
273
+
274
+ if(NIL_P(block) && rb_block_given_p()) block = rb_block_proc();
275
+
276
+ rb_iv_set(self, "@busy_handler", block);
277
+
278
+ status = sqlite3_busy_handler(
279
+ ctx->db, NIL_P(block) ? NULL : rb_sqlite3_busy_handler, (void *)self);
280
+
281
+ CHECK(ctx->db, status);
282
+
283
+ return self;
284
+ }
285
+
286
+ /* call-seq: last_insert_row_id
287
+ *
288
+ * Obtains the unique row ID of the last row to be inserted by this Database
289
+ * instance.
290
+ */
291
+ static VALUE last_insert_row_id(VALUE self)
292
+ {
293
+ sqlite3RubyPtr ctx;
294
+ Data_Get_Struct(self, sqlite3Ruby, ctx);
295
+ REQUIRE_OPEN_DB(ctx);
296
+
297
+ return LL2NUM(sqlite3_last_insert_rowid(ctx->db));
298
+ }
299
+
300
+ static VALUE sqlite3val2rb(sqlite3_value * val)
301
+ {
302
+ switch(sqlite3_value_type(val)) {
303
+ case SQLITE_INTEGER:
304
+ return LL2NUM(sqlite3_value_int64(val));
305
+ break;
306
+ case SQLITE_FLOAT:
307
+ return rb_float_new(sqlite3_value_double(val));
308
+ break;
309
+ case SQLITE_TEXT:
310
+ return rb_tainted_str_new2((const char *)sqlite3_value_text(val));
311
+ break;
312
+ case SQLITE_BLOB: {
313
+ /* Sqlite warns calling sqlite3_value_bytes may invalidate pointer from sqlite3_value_blob,
314
+ so we explicitly get the length before getting blob pointer.
315
+ Note that rb_str_new and rb_tainted_str_new apparently create string with ASCII-8BIT (BINARY) encoding,
316
+ which is what we want, as blobs are binary
317
+ */
318
+ int len = sqlite3_value_bytes(val);
319
+ #ifdef HAVE_RUBY_ENCODING_H
320
+ 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
+ break;
328
+ }
329
+ case SQLITE_NULL:
330
+ return Qnil;
331
+ break;
332
+ default:
333
+ rb_raise(rb_eRuntimeError, "bad type"); /* FIXME */
334
+ }
335
+ }
336
+
337
+ static void set_sqlite3_func_result(sqlite3_context * ctx, VALUE result)
338
+ {
339
+ switch(TYPE(result)) {
340
+ case T_NIL:
341
+ sqlite3_result_null(ctx);
342
+ break;
343
+ case T_FIXNUM:
344
+ sqlite3_result_int64(ctx, (sqlite3_int64)FIX2LONG(result));
345
+ break;
346
+ case T_BIGNUM: {
347
+ #if SIZEOF_LONG < 8
348
+ sqlite3_int64 num64;
349
+
350
+ if (bignum_to_int64(result, &num64)) {
351
+ sqlite3_result_int64(ctx, num64);
352
+ break;
353
+ }
354
+ #endif
355
+ }
356
+ case T_FLOAT:
357
+ sqlite3_result_double(ctx, NUM2DBL(result));
358
+ break;
359
+ case T_STRING:
360
+ if(CLASS_OF(result) == cSqlite3Blob
361
+ #ifdef HAVE_RUBY_ENCODING_H
362
+ || rb_enc_get_index(result) == rb_ascii8bit_encindex()
363
+ #endif
364
+ ) {
365
+ sqlite3_result_blob(
366
+ ctx,
367
+ (const void *)StringValuePtr(result),
368
+ (int)RSTRING_LEN(result),
369
+ SQLITE_TRANSIENT
370
+ );
371
+ } else {
372
+ sqlite3_result_text(
373
+ ctx,
374
+ (const char *)StringValuePtr(result),
375
+ (int)RSTRING_LEN(result),
376
+ SQLITE_TRANSIENT
377
+ );
378
+ }
379
+ break;
380
+ default:
381
+ rb_raise(rb_eRuntimeError, "can't return %s",
382
+ rb_class2name(CLASS_OF(result)));
383
+ }
384
+ }
385
+
386
+ static void rb_sqlite3_func(sqlite3_context * ctx, int argc, sqlite3_value **argv)
387
+ {
388
+ VALUE callable = (VALUE)sqlite3_user_data(ctx);
389
+ VALUE params = rb_ary_new2(argc);
390
+ VALUE result;
391
+ int i;
392
+
393
+ if (argc > 0) {
394
+ for(i = 0; i < argc; i++) {
395
+ VALUE param = sqlite3val2rb(argv[i]);
396
+ rb_ary_push(params, param);
397
+ }
398
+ }
399
+
400
+ result = rb_apply(callable, rb_intern("call"), params);
401
+
402
+ set_sqlite3_func_result(ctx, result);
403
+ }
404
+
405
+ #ifndef HAVE_RB_PROC_ARITY
406
+ int rb_proc_arity(VALUE self)
407
+ {
408
+ return (int)NUM2INT(rb_funcall(self, rb_intern("arity"), 0));
409
+ }
410
+ #endif
411
+
412
+ /* call-seq: define_function(name) { |args,...| }
413
+ *
414
+ * Define a function named +name+ with +args+. The arity of the block
415
+ * will be used as the arity for the function defined.
416
+ */
417
+ static VALUE define_function(VALUE self, VALUE name)
418
+ {
419
+ sqlite3RubyPtr ctx;
420
+ VALUE block;
421
+ int status;
422
+
423
+ Data_Get_Struct(self, sqlite3Ruby, ctx);
424
+ REQUIRE_OPEN_DB(ctx);
425
+
426
+ block = rb_block_proc();
427
+
428
+ status = sqlite3_create_function(
429
+ ctx->db,
430
+ StringValuePtr(name),
431
+ rb_proc_arity(block),
432
+ SQLITE_UTF8,
433
+ (void *)block,
434
+ rb_sqlite3_func,
435
+ NULL,
436
+ NULL
437
+ );
438
+
439
+ CHECK(ctx->db, status);
440
+
441
+ rb_hash_aset(rb_iv_get(self, "@functions"), name, block);
442
+
443
+ return self;
444
+ }
445
+
446
+ static int sqlite3_obj_method_arity(VALUE obj, ID id)
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)
478
+ *
479
+ * Define an aggregate function named +name+ using the object +aggregator+.
480
+ * +aggregator+ must respond to +step+ and +finalize+. +step+ will be called
481
+ * with row information and +finalize+ must return the return value for the
482
+ * aggregator function.
483
+ */
484
+ static VALUE define_aggregator(VALUE self, VALUE name, VALUE aggregator)
485
+ {
486
+ sqlite3RubyPtr ctx;
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;
510
+ }
511
+
512
+ /* call-seq: interrupt
513
+ *
514
+ * Interrupts the currently executing operation, causing it to abort.
515
+ */
516
+ static VALUE interrupt(VALUE self)
517
+ {
518
+ sqlite3RubyPtr ctx;
519
+ Data_Get_Struct(self, sqlite3Ruby, ctx);
520
+ REQUIRE_OPEN_DB(ctx);
521
+
522
+ sqlite3_interrupt(ctx->db);
523
+
524
+ return self;
525
+ }
526
+
527
+ /* call-seq: errmsg
528
+ *
529
+ * Return a string describing the last error to have occurred with this
530
+ * database.
531
+ */
532
+ static VALUE errmsg(VALUE self)
533
+ {
534
+ sqlite3RubyPtr ctx;
535
+ Data_Get_Struct(self, sqlite3Ruby, ctx);
536
+ REQUIRE_OPEN_DB(ctx);
537
+
538
+ return rb_str_new2(sqlite3_errmsg(ctx->db));
539
+ }
540
+
541
+ /* call-seq: errcode
542
+ *
543
+ * Return an integer representing the last error to have occurred with this
544
+ * database.
545
+ */
546
+ static VALUE errcode_(VALUE self)
547
+ {
548
+ sqlite3RubyPtr ctx;
549
+ Data_Get_Struct(self, sqlite3Ruby, ctx);
550
+ REQUIRE_OPEN_DB(ctx);
551
+
552
+ return INT2NUM((long)sqlite3_errcode(ctx->db));
553
+ }
554
+
555
+ /* call-seq: complete?(sql)
556
+ *
557
+ * Return +true+ if the string is a valid (ie, parsable) SQL statement, and
558
+ * +false+ otherwise.
559
+ */
560
+ static VALUE complete_p(VALUE UNUSED(self), VALUE sql)
561
+ {
562
+ if(sqlite3_complete(StringValuePtr(sql)))
563
+ return Qtrue;
564
+
565
+ return Qfalse;
566
+ }
567
+
568
+ /* call-seq: changes
569
+ *
570
+ * Returns the number of changes made to this database instance by the last
571
+ * operation performed. Note that a "delete from table" without a where
572
+ * clause will not affect this value.
573
+ */
574
+ static VALUE changes(VALUE self)
575
+ {
576
+ sqlite3RubyPtr ctx;
577
+ Data_Get_Struct(self, sqlite3Ruby, ctx);
578
+ REQUIRE_OPEN_DB(ctx);
579
+
580
+ return INT2NUM(sqlite3_changes(ctx->db));
581
+ }
582
+
583
+ static int rb_sqlite3_auth(
584
+ void *ctx,
585
+ int _action,
586
+ const char * _a,
587
+ const char * _b,
588
+ const char * _c,
589
+ const char * _d)
590
+ {
591
+ VALUE self = (VALUE)ctx;
592
+ VALUE action = INT2NUM(_action);
593
+ VALUE a = _a ? rb_str_new2(_a) : Qnil;
594
+ VALUE b = _b ? rb_str_new2(_b) : Qnil;
595
+ VALUE c = _c ? rb_str_new2(_c) : Qnil;
596
+ VALUE d = _d ? rb_str_new2(_d) : Qnil;
597
+ VALUE callback = rb_iv_get(self, "@authorizer");
598
+ VALUE result = rb_funcall(callback, rb_intern("call"), 5, action, a, b, c, d);
599
+
600
+ if(T_FIXNUM == TYPE(result)) return (int)NUM2INT(result);
601
+ if(Qtrue == result) return SQLITE_OK;
602
+ if(Qfalse == result) return SQLITE_DENY;
603
+
604
+ return SQLITE_IGNORE;
605
+ }
606
+
607
+ /* call-seq: set_authorizer = auth
608
+ *
609
+ * Set the authorizer for this database. +auth+ must respond to +call+, and
610
+ * +call+ must take 5 arguments.
611
+ *
612
+ * Installs (or removes) a block that will be invoked for every access
613
+ * to the database. If the block returns 0 (or +true+), the statement
614
+ * is allowed to proceed. Returning 1 or false causes an authorization error to
615
+ * occur, and returning 2 or nil causes the access to be silently denied.
616
+ */
617
+ static VALUE set_authorizer(VALUE self, VALUE authorizer)
618
+ {
619
+ sqlite3RubyPtr ctx;
620
+ int status;
621
+
622
+ Data_Get_Struct(self, sqlite3Ruby, ctx);
623
+ REQUIRE_OPEN_DB(ctx);
624
+
625
+ status = sqlite3_set_authorizer(
626
+ ctx->db, NIL_P(authorizer) ? NULL : rb_sqlite3_auth, (void *)self
627
+ );
628
+
629
+ CHECK(ctx->db, status);
630
+
631
+ rb_iv_set(self, "@authorizer", authorizer);
632
+
633
+ return self;
634
+ }
635
+
636
+ /* call-seq: db.busy_timeout = ms
637
+ *
638
+ * Indicates that if a request for a resource terminates because that
639
+ * resource is busy, SQLite should sleep and retry for up to the indicated
640
+ * number of milliseconds. By default, SQLite does not retry
641
+ * busy resources. To restore the default behavior, send 0 as the
642
+ * +ms+ parameter.
643
+ *
644
+ * See also the mutually exclusive #busy_handler.
645
+ */
646
+ static VALUE set_busy_timeout(VALUE self, VALUE timeout)
647
+ {
648
+ sqlite3RubyPtr ctx;
649
+ Data_Get_Struct(self, sqlite3Ruby, ctx);
650
+ REQUIRE_OPEN_DB(ctx);
651
+
652
+ CHECK(ctx->db, sqlite3_busy_timeout(ctx->db, (int)NUM2INT(timeout)));
653
+
654
+ return self;
655
+ }
656
+
657
+ int rb_comparator_func(void * ctx, int a_len, const void * a, int b_len, const void * b)
658
+ {
659
+ VALUE comparator;
660
+ VALUE a_str;
661
+ VALUE b_str;
662
+ VALUE comparison;
663
+ #ifdef HAVE_RUBY_ENCODING_H
664
+ rb_encoding * internal_encoding;
665
+
666
+ internal_encoding = rb_default_internal_encoding();
667
+ #endif
668
+
669
+ comparator = (VALUE)ctx;
670
+ a_str = rb_str_new((const char *)a, a_len);
671
+ b_str = rb_str_new((const char *)b, b_len);
672
+
673
+ #ifdef HAVE_RUBY_ENCODING_H
674
+ rb_enc_associate_index(a_str, rb_utf8_encindex());
675
+ rb_enc_associate_index(b_str, rb_utf8_encindex());
676
+
677
+ if(internal_encoding) {
678
+ a_str = rb_str_export_to_enc(a_str, internal_encoding);
679
+ b_str = rb_str_export_to_enc(b_str, internal_encoding);
680
+ }
681
+ #endif
682
+
683
+ comparison = rb_funcall(comparator, rb_intern("compare"), 2, a_str, b_str);
684
+
685
+ return NUM2INT(comparison);
686
+ }
687
+
688
+ /* call-seq: db.collation(name, comparator)
689
+ *
690
+ * Add a collation with name +name+, and a +comparator+ object. The
691
+ * +comparator+ object should implement a method called "compare" that takes
692
+ * two parameters and returns an integer less than, equal to, or greater than
693
+ * 0.
694
+ */
695
+ static VALUE collation(VALUE self, VALUE name, VALUE comparator)
696
+ {
697
+ sqlite3RubyPtr ctx;
698
+ Data_Get_Struct(self, sqlite3Ruby, ctx);
699
+ REQUIRE_OPEN_DB(ctx);
700
+
701
+ CHECK(ctx->db, sqlite3_create_collation(
702
+ ctx->db,
703
+ StringValuePtr(name),
704
+ SQLITE_UTF8,
705
+ (void *)comparator,
706
+ NIL_P(comparator) ? NULL : rb_comparator_func));
707
+
708
+ /* Make sure our comparator doesn't get garbage collected. */
709
+ rb_hash_aset(rb_iv_get(self, "@collations"), name, comparator);
710
+
711
+ return self;
712
+ }
713
+
714
+ #ifdef HAVE_SQLITE3_LOAD_EXTENSION
715
+ /* call-seq: db.load_extension(file)
716
+ *
717
+ * Loads an SQLite extension library from the named file. Extension
718
+ * loading must be enabled using db.enable_load_extension(true) prior
719
+ * to calling this API.
720
+ */
721
+ static VALUE load_extension(VALUE self, VALUE file)
722
+ {
723
+ sqlite3RubyPtr ctx;
724
+ int status;
725
+ char *errMsg;
726
+ VALUE errexp;
727
+ Data_Get_Struct(self, sqlite3Ruby, ctx);
728
+ REQUIRE_OPEN_DB(ctx);
729
+
730
+ status = sqlite3_load_extension(ctx->db, RSTRING_PTR(file), 0, &errMsg);
731
+ if (status != SQLITE_OK)
732
+ {
733
+ errexp = rb_exc_new2(rb_eRuntimeError, errMsg);
734
+ sqlite3_free(errMsg);
735
+ rb_exc_raise(errexp);
736
+ }
737
+
738
+ return self;
739
+ }
740
+ #endif
741
+
742
+ #ifdef HAVE_SQLITE3_ENABLE_LOAD_EXTENSION
743
+ /* call-seq: db.enable_load_extension(onoff)
744
+ *
745
+ * Enable or disable extension loading.
746
+ */
747
+ static VALUE enable_load_extension(VALUE self, VALUE onoff)
748
+ {
749
+ sqlite3RubyPtr ctx;
750
+ int onoffparam;
751
+ Data_Get_Struct(self, sqlite3Ruby, ctx);
752
+ REQUIRE_OPEN_DB(ctx);
753
+
754
+ if (Qtrue == onoff) {
755
+ onoffparam = 1;
756
+ } else if (Qfalse == onoff) {
757
+ onoffparam = 0;
758
+ } else {
759
+ onoffparam = (int)NUM2INT(onoff);
760
+ }
761
+
762
+ CHECK(ctx->db, sqlite3_enable_load_extension(ctx->db, onoffparam));
763
+
764
+ return self;
765
+ }
766
+ #endif
767
+
768
+ #ifdef HAVE_RUBY_ENCODING_H
769
+ static int enc_cb(void * _self, int UNUSED(columns), char **data, char **UNUSED(names))
770
+ {
771
+ VALUE self = (VALUE)_self;
772
+
773
+ int index = rb_enc_find_index(data[0]);
774
+ rb_encoding * e = rb_enc_from_index(index);
775
+ rb_iv_set(self, "@encoding", rb_enc_from_encoding(e));
776
+
777
+ return 0;
778
+ }
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
+
790
+ /* call-seq: db.encoding
791
+ *
792
+ * Fetch the encoding set on this database
793
+ */
794
+ static VALUE db_encoding(VALUE self)
795
+ {
796
+ sqlite3RubyPtr ctx;
797
+ VALUE enc;
798
+
799
+ Data_Get_Struct(self, sqlite3Ruby, ctx);
800
+ REQUIRE_OPEN_DB(ctx);
801
+
802
+ enc = rb_iv_get(self, "@encoding");
803
+
804
+ if(NIL_P(enc)) {
805
+ sqlite3_exec(ctx->db, "PRAGMA encoding", enc_cb, (void *)self, NULL);
806
+ }
807
+
808
+ return rb_iv_get(self, "@encoding");
809
+ }
810
+
811
+ /* call-seq: db.transaction_active?
812
+ *
813
+ * Returns +true+ if there is a transaction active, and +false+ otherwise.
814
+ *
815
+ */
816
+ static VALUE transaction_active_p(VALUE self)
817
+ {
818
+ sqlite3RubyPtr ctx;
819
+ Data_Get_Struct(self, sqlite3Ruby, ctx);
820
+ REQUIRE_OPEN_DB(ctx);
821
+
822
+ return sqlite3_get_autocommit(ctx->db) ? Qfalse : Qtrue;
823
+ }
824
+
825
+ /* call-seq: db.db_filename(database_name)
826
+ *
827
+ * Returns the file associated with +database_name+. Can return nil or an
828
+ * empty string if the database is temporary, or in-memory.
829
+ */
830
+ static VALUE db_filename(VALUE self, VALUE db_name)
831
+ {
832
+ sqlite3RubyPtr ctx;
833
+ const char * fname;
834
+ Data_Get_Struct(self, sqlite3Ruby, ctx);
835
+ REQUIRE_OPEN_DB(ctx);
836
+
837
+ fname = sqlite3_db_filename(ctx->db, StringValueCStr(db_name));
838
+
839
+ if(fname) return SQLITE3_UTF8_STR_NEW2(fname);
840
+ return Qnil;
841
+ }
842
+
843
+ void init_sqlite3_database()
844
+ {
845
+ ID id_utf16, id_results_as_hash, id_type_translation;
846
+ #if 0
847
+ VALUE mSqlite3 = rb_define_module("SQLite3");
848
+ #endif
849
+ cSqlite3Database = rb_define_class_under(mSqlite3, "Database", rb_cObject);
850
+
851
+ rb_define_alloc_func(cSqlite3Database, allocate);
852
+ rb_define_method(cSqlite3Database, "initialize", initialize, -1);
853
+ rb_define_method(cSqlite3Database, "collation", collation, 2);
854
+ rb_define_method(cSqlite3Database, "close", sqlite3_rb_close, 0);
855
+ rb_define_method(cSqlite3Database, "closed?", closed_p, 0);
856
+ rb_define_method(cSqlite3Database, "total_changes", total_changes, 0);
857
+ rb_define_method(cSqlite3Database, "trace", trace, -1);
858
+ rb_define_method(cSqlite3Database, "last_insert_row_id", last_insert_row_id, 0);
859
+ rb_define_method(cSqlite3Database, "define_function", define_function, 1);
860
+ rb_define_method(cSqlite3Database, "define_aggregator", define_aggregator, 2);
861
+ rb_define_method(cSqlite3Database, "interrupt", interrupt, 0);
862
+ rb_define_method(cSqlite3Database, "errmsg", errmsg, 0);
863
+ rb_define_method(cSqlite3Database, "errcode", errcode_, 0);
864
+ rb_define_method(cSqlite3Database, "complete?", complete_p, 1);
865
+ rb_define_method(cSqlite3Database, "changes", changes, 0);
866
+ rb_define_method(cSqlite3Database, "authorizer=", set_authorizer, 1);
867
+ rb_define_method(cSqlite3Database, "busy_handler", busy_handler, -1);
868
+ rb_define_method(cSqlite3Database, "busy_timeout=", set_busy_timeout, 1);
869
+ rb_define_method(cSqlite3Database, "transaction_active?", transaction_active_p, 0);
870
+ rb_define_private_method(cSqlite3Database, "db_filename", db_filename, 1);
871
+
872
+ #ifdef HAVE_SQLITE3_LOAD_EXTENSION
873
+ rb_define_method(cSqlite3Database, "load_extension", load_extension, 1);
874
+ #endif
875
+
876
+ #ifdef HAVE_SQLITE3_ENABLE_LOAD_EXTENSION
877
+ rb_define_method(cSqlite3Database, "enable_load_extension", enable_load_extension, 1);
878
+ #endif
879
+
880
+ rb_define_method(cSqlite3Database, "encoding", db_encoding, 0);
881
+
882
+ id_utf16 = rb_intern("utf16");
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);
888
+ }