sqlite3 1.7.3-x64-mingw32 → 2.0.0-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 +4 -4
- data/CHANGELOG.md +152 -0
- data/CONTRIBUTING.md +23 -1
- data/FAQ.md +0 -43
- data/INSTALLATION.md +13 -5
- data/LICENSE +18 -22
- data/README.md +75 -4
- data/dependencies.yml +10 -11
- data/ext/sqlite3/aggregator.c +142 -145
- data/ext/sqlite3/aggregator.h +2 -4
- data/ext/sqlite3/backup.c +74 -65
- data/ext/sqlite3/backup.h +2 -2
- data/ext/sqlite3/database.c +535 -482
- data/ext/sqlite3/database.h +7 -4
- data/ext/sqlite3/exception.c +111 -92
- data/ext/sqlite3/exception.h +3 -1
- data/ext/sqlite3/extconf.rb +21 -22
- data/ext/sqlite3/sqlite3.c +159 -115
- data/ext/sqlite3/sqlite3_ruby.h +2 -2
- data/ext/sqlite3/statement.c +516 -300
- data/ext/sqlite3/statement.h +3 -3
- data/ext/sqlite3/timespec.h +20 -0
- data/lib/sqlite3/3.0/sqlite3_native.so +0 -0
- data/lib/sqlite3/constants.rb +171 -47
- data/lib/sqlite3/database.rb +105 -165
- data/lib/sqlite3/errors.rb +26 -1
- data/lib/sqlite3/pragmas.rb +126 -136
- data/lib/sqlite3/resultset.rb +14 -97
- data/lib/sqlite3/statement.rb +58 -13
- data/lib/sqlite3/value.rb +17 -20
- data/lib/sqlite3/version.rb +1 -21
- data/lib/sqlite3.rb +6 -4
- metadata +3 -28
- data/API_CHANGES.md +0 -49
- data/ChangeLog.cvs +0 -88
- data/Gemfile +0 -10
- data/LICENSE-DEPENDENCIES +0 -20
- data/lib/sqlite3/translator.rb +0 -117
- data/test/helper.rb +0 -27
- data/test/test_backup.rb +0 -33
- data/test/test_collation.rb +0 -82
- data/test/test_database.rb +0 -668
- data/test/test_database_flags.rb +0 -95
- data/test/test_database_readonly.rb +0 -36
- data/test/test_database_readwrite.rb +0 -41
- data/test/test_deprecated.rb +0 -49
- data/test/test_encoding.rb +0 -165
- data/test/test_integration.rb +0 -507
- data/test/test_integration_aggregate.rb +0 -336
- data/test/test_integration_open_close.rb +0 -30
- data/test/test_integration_pending.rb +0 -115
- data/test/test_integration_resultset.rb +0 -142
- data/test/test_integration_statement.rb +0 -194
- data/test/test_pragmas.rb +0 -22
- data/test/test_result_set.rb +0 -47
- data/test/test_sqlite3.rb +0 -30
- data/test/test_statement.rb +0 -290
- data/test/test_statement_execute.rb +0 -39
data/ext/sqlite3/database.c
CHANGED
@@ -12,98 +12,110 @@
|
|
12
12
|
|
13
13
|
VALUE cSqlite3Database;
|
14
14
|
|
15
|
-
static void
|
15
|
+
static void
|
16
|
+
database_mark(void *ctx)
|
16
17
|
{
|
17
|
-
|
18
|
-
|
18
|
+
sqlite3RubyPtr c = (sqlite3RubyPtr)ctx;
|
19
|
+
rb_gc_mark(c->busy_handler);
|
20
|
+
}
|
21
|
+
|
22
|
+
static void
|
23
|
+
deallocate(void *ctx)
|
24
|
+
{
|
25
|
+
sqlite3RubyPtr c = (sqlite3RubyPtr)ctx;
|
26
|
+
sqlite3 *db = c->db;
|
19
27
|
|
20
|
-
|
21
|
-
|
28
|
+
if (db) { sqlite3_close(db); }
|
29
|
+
xfree(c);
|
22
30
|
}
|
23
31
|
|
24
|
-
static size_t
|
32
|
+
static size_t
|
33
|
+
database_memsize(const void *ctx)
|
25
34
|
{
|
26
|
-
|
27
|
-
|
28
|
-
|
35
|
+
const sqlite3RubyPtr c = (const sqlite3RubyPtr)ctx;
|
36
|
+
// NB: can't account for ctx->db because the type is incomplete.
|
37
|
+
return sizeof(*c);
|
29
38
|
}
|
30
39
|
|
31
40
|
static const rb_data_type_t database_type = {
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
0,
|
40
|
-
RUBY_TYPED_WB_PROTECTED, // Not freed immediately because the dfree function do IOs.
|
41
|
+
.wrap_struct_name = "SQLite3::Backup",
|
42
|
+
.function = {
|
43
|
+
.dmark = database_mark,
|
44
|
+
.dfree = deallocate,
|
45
|
+
.dsize = database_memsize,
|
46
|
+
},
|
47
|
+
.flags = RUBY_TYPED_WB_PROTECTED, // Not freed immediately because the dfree function do IOs.
|
41
48
|
};
|
42
49
|
|
43
|
-
static VALUE
|
50
|
+
static VALUE
|
51
|
+
allocate(VALUE klass)
|
44
52
|
{
|
45
|
-
|
46
|
-
|
53
|
+
sqlite3RubyPtr ctx;
|
54
|
+
return TypedData_Make_Struct(klass, sqlite3Ruby, &database_type, ctx);
|
47
55
|
}
|
48
56
|
|
49
57
|
static char *
|
50
58
|
utf16_string_value_ptr(VALUE str)
|
51
59
|
{
|
52
|
-
|
53
|
-
|
54
|
-
|
60
|
+
StringValue(str);
|
61
|
+
rb_str_buf_cat(str, "\x00\x00", 2L);
|
62
|
+
return RSTRING_PTR(str);
|
55
63
|
}
|
56
64
|
|
57
65
|
static VALUE sqlite3_rb_close(VALUE self);
|
58
66
|
|
59
|
-
sqlite3RubyPtr
|
60
|
-
|
61
|
-
|
62
|
-
|
67
|
+
sqlite3RubyPtr
|
68
|
+
sqlite3_database_unwrap(VALUE database)
|
69
|
+
{
|
70
|
+
sqlite3RubyPtr ctx;
|
71
|
+
TypedData_Get_Struct(database, sqlite3Ruby, &database_type, ctx);
|
72
|
+
return ctx;
|
63
73
|
}
|
64
74
|
|
65
|
-
static VALUE
|
75
|
+
static VALUE
|
76
|
+
rb_sqlite3_open_v2(VALUE self, VALUE file, VALUE mode, VALUE zvfs)
|
66
77
|
{
|
67
|
-
|
68
|
-
|
78
|
+
sqlite3RubyPtr ctx;
|
79
|
+
int status;
|
69
80
|
|
70
|
-
|
81
|
+
TypedData_Get_Struct(self, sqlite3Ruby, &database_type, ctx);
|
71
82
|
|
72
83
|
#if defined TAINTING_SUPPORT
|
73
84
|
# if defined StringValueCStr
|
74
|
-
|
75
|
-
|
85
|
+
StringValuePtr(file);
|
86
|
+
rb_check_safe_obj(file);
|
76
87
|
# else
|
77
|
-
|
88
|
+
Check_SafeStr(file);
|
78
89
|
# endif
|
79
90
|
#endif
|
80
91
|
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
92
|
+
status = sqlite3_open_v2(
|
93
|
+
StringValuePtr(file),
|
94
|
+
&ctx->db,
|
95
|
+
NUM2INT(mode),
|
96
|
+
NIL_P(zvfs) ? NULL : StringValuePtr(zvfs)
|
97
|
+
);
|
87
98
|
|
88
|
-
|
99
|
+
CHECK(ctx->db, status)
|
89
100
|
|
90
|
-
|
101
|
+
return self;
|
91
102
|
}
|
92
103
|
|
93
|
-
static VALUE
|
104
|
+
static VALUE
|
105
|
+
rb_sqlite3_disable_quirk_mode(VALUE self)
|
94
106
|
{
|
95
107
|
#if defined SQLITE_DBCONFIG_DQS_DDL
|
96
|
-
|
97
|
-
|
108
|
+
sqlite3RubyPtr ctx;
|
109
|
+
TypedData_Get_Struct(self, sqlite3Ruby, &database_type, ctx);
|
98
110
|
|
99
|
-
|
111
|
+
if (!ctx->db) { return Qfalse; }
|
100
112
|
|
101
|
-
|
102
|
-
|
113
|
+
sqlite3_db_config(ctx->db, SQLITE_DBCONFIG_DQS_DDL, 0, (void *)0);
|
114
|
+
sqlite3_db_config(ctx->db, SQLITE_DBCONFIG_DQS_DML, 0, (void *)0);
|
103
115
|
|
104
|
-
|
116
|
+
return Qtrue;
|
105
117
|
#else
|
106
|
-
|
118
|
+
return Qfalse;
|
107
119
|
#endif
|
108
120
|
}
|
109
121
|
|
@@ -111,34 +123,36 @@ static VALUE rb_sqlite3_disable_quirk_mode(VALUE self)
|
|
111
123
|
*
|
112
124
|
* Closes this database.
|
113
125
|
*/
|
114
|
-
static VALUE
|
126
|
+
static VALUE
|
127
|
+
sqlite3_rb_close(VALUE self)
|
115
128
|
{
|
116
|
-
|
117
|
-
|
118
|
-
|
129
|
+
sqlite3RubyPtr ctx;
|
130
|
+
sqlite3 *db;
|
131
|
+
TypedData_Get_Struct(self, sqlite3Ruby, &database_type, ctx);
|
119
132
|
|
120
|
-
|
121
|
-
|
133
|
+
db = ctx->db;
|
134
|
+
CHECK(db, sqlite3_close(ctx->db));
|
122
135
|
|
123
|
-
|
136
|
+
ctx->db = NULL;
|
124
137
|
|
125
|
-
|
138
|
+
rb_iv_set(self, "-aggregators", Qnil);
|
126
139
|
|
127
|
-
|
140
|
+
return self;
|
128
141
|
}
|
129
142
|
|
130
143
|
/* call-seq: db.closed?
|
131
144
|
*
|
132
145
|
* Returns +true+ if this database instance has been closed (see #close).
|
133
146
|
*/
|
134
|
-
static VALUE
|
147
|
+
static VALUE
|
148
|
+
closed_p(VALUE self)
|
135
149
|
{
|
136
|
-
|
137
|
-
|
150
|
+
sqlite3RubyPtr ctx;
|
151
|
+
TypedData_Get_Struct(self, sqlite3Ruby, &database_type, ctx);
|
138
152
|
|
139
|
-
|
153
|
+
if (!ctx->db) { return Qtrue; }
|
140
154
|
|
141
|
-
|
155
|
+
return Qfalse;
|
142
156
|
}
|
143
157
|
|
144
158
|
/* call-seq: total_changes
|
@@ -146,20 +160,22 @@ static VALUE closed_p(VALUE self)
|
|
146
160
|
* Returns the total number of changes made to this database instance
|
147
161
|
* since it was opened.
|
148
162
|
*/
|
149
|
-
static VALUE
|
163
|
+
static VALUE
|
164
|
+
total_changes(VALUE self)
|
150
165
|
{
|
151
|
-
|
152
|
-
|
153
|
-
|
166
|
+
sqlite3RubyPtr ctx;
|
167
|
+
TypedData_Get_Struct(self, sqlite3Ruby, &database_type, ctx);
|
168
|
+
REQUIRE_OPEN_DB(ctx);
|
154
169
|
|
155
|
-
|
170
|
+
return INT2NUM(sqlite3_total_changes(ctx->db));
|
156
171
|
}
|
157
172
|
|
158
|
-
static void
|
173
|
+
static void
|
174
|
+
tracefunc(void *data, const char *sql)
|
159
175
|
{
|
160
|
-
|
161
|
-
|
162
|
-
|
176
|
+
VALUE self = (VALUE)data;
|
177
|
+
VALUE thing = rb_iv_get(self, "@tracefunc");
|
178
|
+
rb_funcall(thing, rb_intern("call"), 1, rb_str_new2(sql));
|
163
179
|
}
|
164
180
|
|
165
181
|
/* call-seq:
|
@@ -170,34 +186,37 @@ static void tracefunc(void * data, const char *sql)
|
|
170
186
|
* statement executed. The block receives one parameter: the SQL statement
|
171
187
|
* executed. If the block is +nil+, any existing tracer will be uninstalled.
|
172
188
|
*/
|
173
|
-
static VALUE
|
189
|
+
static VALUE
|
190
|
+
trace(int argc, VALUE *argv, VALUE self)
|
174
191
|
{
|
175
|
-
|
176
|
-
|
192
|
+
sqlite3RubyPtr ctx;
|
193
|
+
VALUE block;
|
177
194
|
|
178
|
-
|
179
|
-
|
195
|
+
TypedData_Get_Struct(self, sqlite3Ruby, &database_type, ctx);
|
196
|
+
REQUIRE_OPEN_DB(ctx);
|
180
197
|
|
181
|
-
|
198
|
+
rb_scan_args(argc, argv, "01", &block);
|
182
199
|
|
183
|
-
|
200
|
+
if (NIL_P(block) && rb_block_given_p()) { block = rb_block_proc(); }
|
184
201
|
|
185
|
-
|
202
|
+
rb_iv_set(self, "@tracefunc", block);
|
186
203
|
|
187
|
-
|
204
|
+
sqlite3_trace(ctx->db, NIL_P(block) ? NULL : tracefunc, (void *)self);
|
188
205
|
|
189
|
-
|
206
|
+
return self;
|
190
207
|
}
|
191
208
|
|
192
|
-
static int
|
209
|
+
static int
|
210
|
+
rb_sqlite3_busy_handler(void *context, int count)
|
193
211
|
{
|
194
|
-
|
195
|
-
|
196
|
-
|
212
|
+
sqlite3RubyPtr ctx = (sqlite3RubyPtr)context;
|
213
|
+
|
214
|
+
VALUE handle = ctx->busy_handler;
|
215
|
+
VALUE result = rb_funcall(handle, rb_intern("call"), 1, INT2NUM(count));
|
197
216
|
|
198
|
-
|
217
|
+
if (Qfalse == result) { return 0; }
|
199
218
|
|
200
|
-
|
219
|
+
return 1;
|
201
220
|
}
|
202
221
|
|
203
222
|
/* call-seq:
|
@@ -214,27 +233,68 @@ static int rb_sqlite3_busy_handler(void * ctx, int count)
|
|
214
233
|
*
|
215
234
|
* See also the mutually exclusive #busy_timeout.
|
216
235
|
*/
|
217
|
-
static VALUE
|
236
|
+
static VALUE
|
237
|
+
busy_handler(int argc, VALUE *argv, VALUE self)
|
218
238
|
{
|
219
|
-
|
220
|
-
|
221
|
-
|
239
|
+
sqlite3RubyPtr ctx;
|
240
|
+
VALUE block;
|
241
|
+
int status;
|
242
|
+
|
243
|
+
TypedData_Get_Struct(self, sqlite3Ruby, &database_type, ctx);
|
244
|
+
REQUIRE_OPEN_DB(ctx);
|
222
245
|
|
223
|
-
|
224
|
-
|
246
|
+
rb_scan_args(argc, argv, "01", &block);
|
247
|
+
|
248
|
+
if (NIL_P(block) && rb_block_given_p()) { block = rb_block_proc(); }
|
249
|
+
ctx->busy_handler = block;
|
250
|
+
|
251
|
+
status = sqlite3_busy_handler(
|
252
|
+
ctx->db,
|
253
|
+
NIL_P(block) ? NULL : rb_sqlite3_busy_handler,
|
254
|
+
(void *)ctx
|
255
|
+
);
|
256
|
+
|
257
|
+
CHECK(ctx->db, status);
|
258
|
+
|
259
|
+
return self;
|
260
|
+
}
|
261
|
+
|
262
|
+
static int
|
263
|
+
rb_sqlite3_statement_timeout(void *context)
|
264
|
+
{
|
265
|
+
sqlite3RubyPtr ctx = (sqlite3RubyPtr)context;
|
266
|
+
struct timespec currentTime;
|
267
|
+
clock_gettime(CLOCK_MONOTONIC, ¤tTime);
|
225
268
|
|
226
|
-
|
269
|
+
if (!timespecisset(&ctx->stmt_deadline)) {
|
270
|
+
// Set stmt_deadline if not already set
|
271
|
+
ctx->stmt_deadline = currentTime;
|
272
|
+
} else if (timespecafter(¤tTime, &ctx->stmt_deadline)) {
|
273
|
+
return 1;
|
274
|
+
}
|
227
275
|
|
228
|
-
|
276
|
+
return 0;
|
277
|
+
}
|
229
278
|
|
230
|
-
|
279
|
+
/* call-seq: db.statement_timeout = ms
|
280
|
+
*
|
281
|
+
* Indicates that if a query lasts longer than the indicated number of
|
282
|
+
* milliseconds, SQLite should interrupt that query and return an error.
|
283
|
+
* By default, SQLite does not interrupt queries. To restore the default
|
284
|
+
* behavior, send 0 as the +ms+ parameter.
|
285
|
+
*/
|
286
|
+
static VALUE
|
287
|
+
set_statement_timeout(VALUE self, VALUE milliseconds)
|
288
|
+
{
|
289
|
+
sqlite3RubyPtr ctx;
|
290
|
+
TypedData_Get_Struct(self, sqlite3Ruby, &database_type, ctx);
|
231
291
|
|
232
|
-
|
233
|
-
|
292
|
+
ctx->stmt_timeout = NUM2INT(milliseconds);
|
293
|
+
int n = NUM2INT(milliseconds) == 0 ? -1 : 1000;
|
234
294
|
|
235
|
-
|
295
|
+
sqlite3_progress_handler(ctx->db, n, rb_sqlite3_statement_timeout, (void *)ctx);
|
236
296
|
|
237
|
-
|
297
|
+
return self;
|
238
298
|
}
|
239
299
|
|
240
300
|
/* call-seq: last_insert_row_id
|
@@ -242,115 +302,122 @@ static VALUE busy_handler(int argc, VALUE *argv, VALUE self)
|
|
242
302
|
* Obtains the unique row ID of the last row to be inserted by this Database
|
243
303
|
* instance.
|
244
304
|
*/
|
245
|
-
static VALUE
|
246
|
-
|
247
|
-
|
248
|
-
|
249
|
-
|
250
|
-
|
251
|
-
|
252
|
-
|
253
|
-
|
254
|
-
|
255
|
-
|
256
|
-
|
257
|
-
|
258
|
-
|
259
|
-
|
260
|
-
|
261
|
-
|
262
|
-
|
263
|
-
|
264
|
-
|
265
|
-
|
266
|
-
|
267
|
-
|
268
|
-
|
269
|
-
|
270
|
-
|
271
|
-
|
272
|
-
|
273
|
-
|
274
|
-
|
305
|
+
static VALUE
|
306
|
+
last_insert_row_id(VALUE self)
|
307
|
+
{
|
308
|
+
sqlite3RubyPtr ctx;
|
309
|
+
TypedData_Get_Struct(self, sqlite3Ruby, &database_type, ctx);
|
310
|
+
REQUIRE_OPEN_DB(ctx);
|
311
|
+
|
312
|
+
return LL2NUM(sqlite3_last_insert_rowid(ctx->db));
|
313
|
+
}
|
314
|
+
|
315
|
+
VALUE
|
316
|
+
sqlite3val2rb(sqlite3_value *val)
|
317
|
+
{
|
318
|
+
VALUE rb_val;
|
319
|
+
|
320
|
+
switch (sqlite3_value_type(val)) {
|
321
|
+
case SQLITE_INTEGER:
|
322
|
+
rb_val = LL2NUM(sqlite3_value_int64(val));
|
323
|
+
break;
|
324
|
+
case SQLITE_FLOAT:
|
325
|
+
rb_val = rb_float_new(sqlite3_value_double(val));
|
326
|
+
break;
|
327
|
+
case SQLITE_TEXT: {
|
328
|
+
rb_val = rb_utf8_str_new_cstr((const char *)sqlite3_value_text(val));
|
329
|
+
rb_obj_freeze(rb_val);
|
330
|
+
break;
|
331
|
+
}
|
332
|
+
case SQLITE_BLOB: {
|
333
|
+
int len = sqlite3_value_bytes(val);
|
334
|
+
rb_val = rb_str_new((const char *)sqlite3_value_blob(val), len);
|
335
|
+
rb_obj_freeze(rb_val);
|
336
|
+
break;
|
337
|
+
}
|
338
|
+
case SQLITE_NULL:
|
339
|
+
rb_val = Qnil;
|
340
|
+
break;
|
341
|
+
default:
|
342
|
+
rb_raise(rb_eRuntimeError, "bad type");
|
275
343
|
}
|
276
|
-
|
277
|
-
|
278
|
-
|
279
|
-
|
280
|
-
|
281
|
-
|
282
|
-
|
283
|
-
|
284
|
-
|
285
|
-
|
286
|
-
|
287
|
-
|
288
|
-
|
289
|
-
|
290
|
-
|
291
|
-
sqlite3_result_int64(ctx, (sqlite3_int64)FIX2LONG(result));
|
292
|
-
break;
|
293
|
-
case T_BIGNUM: {
|
344
|
+
|
345
|
+
return rb_val;
|
346
|
+
}
|
347
|
+
|
348
|
+
void
|
349
|
+
set_sqlite3_func_result(sqlite3_context *ctx, VALUE result)
|
350
|
+
{
|
351
|
+
switch (TYPE(result)) {
|
352
|
+
case T_NIL:
|
353
|
+
sqlite3_result_null(ctx);
|
354
|
+
break;
|
355
|
+
case T_FIXNUM:
|
356
|
+
sqlite3_result_int64(ctx, (sqlite3_int64)FIX2LONG(result));
|
357
|
+
break;
|
358
|
+
case T_BIGNUM: {
|
294
359
|
#if SIZEOF_LONG < 8
|
295
|
-
|
360
|
+
sqlite3_int64 num64;
|
296
361
|
|
297
|
-
|
298
|
-
|
299
|
-
|
300
|
-
|
362
|
+
if (bignum_to_int64(result, &num64)) {
|
363
|
+
sqlite3_result_int64(ctx, num64);
|
364
|
+
break;
|
365
|
+
}
|
301
366
|
#endif
|
367
|
+
}
|
368
|
+
case T_FLOAT:
|
369
|
+
sqlite3_result_double(ctx, NUM2DBL(result));
|
370
|
+
break;
|
371
|
+
case T_STRING:
|
372
|
+
if (CLASS_OF(result) == cSqlite3Blob
|
373
|
+
|| rb_enc_get_index(result) == rb_ascii8bit_encindex()
|
374
|
+
) {
|
375
|
+
sqlite3_result_blob(
|
376
|
+
ctx,
|
377
|
+
(const void *)StringValuePtr(result),
|
378
|
+
(int)RSTRING_LEN(result),
|
379
|
+
SQLITE_TRANSIENT
|
380
|
+
);
|
381
|
+
} else {
|
382
|
+
sqlite3_result_text(
|
383
|
+
ctx,
|
384
|
+
(const char *)StringValuePtr(result),
|
385
|
+
(int)RSTRING_LEN(result),
|
386
|
+
SQLITE_TRANSIENT
|
387
|
+
);
|
388
|
+
}
|
389
|
+
break;
|
390
|
+
default:
|
391
|
+
rb_raise(rb_eRuntimeError, "can't return %s",
|
392
|
+
rb_class2name(CLASS_OF(result)));
|
302
393
|
}
|
303
|
-
|
304
|
-
|
305
|
-
|
306
|
-
|
307
|
-
|
308
|
-
|
309
|
-
|
310
|
-
|
311
|
-
|
312
|
-
|
313
|
-
|
314
|
-
|
315
|
-
|
316
|
-
|
317
|
-
|
318
|
-
ctx,
|
319
|
-
(const char *)StringValuePtr(result),
|
320
|
-
(int)RSTRING_LEN(result),
|
321
|
-
SQLITE_TRANSIENT
|
322
|
-
);
|
323
|
-
}
|
324
|
-
break;
|
325
|
-
default:
|
326
|
-
rb_raise(rb_eRuntimeError, "can't return %s",
|
327
|
-
rb_class2name(CLASS_OF(result)));
|
328
|
-
}
|
329
|
-
}
|
330
|
-
|
331
|
-
static void rb_sqlite3_func(sqlite3_context * ctx, int argc, sqlite3_value **argv)
|
332
|
-
{
|
333
|
-
VALUE callable = (VALUE)sqlite3_user_data(ctx);
|
334
|
-
VALUE params = rb_ary_new2(argc);
|
335
|
-
VALUE result;
|
336
|
-
int i;
|
337
|
-
|
338
|
-
if (argc > 0) {
|
339
|
-
for(i = 0; i < argc; i++) {
|
340
|
-
VALUE param = sqlite3val2rb(argv[i]);
|
341
|
-
rb_ary_push(params, param);
|
394
|
+
}
|
395
|
+
|
396
|
+
static void
|
397
|
+
rb_sqlite3_func(sqlite3_context *ctx, int argc, sqlite3_value **argv)
|
398
|
+
{
|
399
|
+
VALUE callable = (VALUE)sqlite3_user_data(ctx);
|
400
|
+
VALUE params = rb_ary_new2(argc);
|
401
|
+
VALUE result;
|
402
|
+
int i;
|
403
|
+
|
404
|
+
if (argc > 0) {
|
405
|
+
for (i = 0; i < argc; i++) {
|
406
|
+
VALUE param = sqlite3val2rb(argv[i]);
|
407
|
+
rb_ary_push(params, param);
|
408
|
+
}
|
342
409
|
}
|
343
|
-
}
|
344
410
|
|
345
|
-
|
411
|
+
result = rb_apply(callable, rb_intern("call"), params);
|
346
412
|
|
347
|
-
|
413
|
+
set_sqlite3_func_result(ctx, result);
|
348
414
|
}
|
349
415
|
|
350
416
|
#ifndef HAVE_RB_PROC_ARITY
|
351
|
-
int
|
417
|
+
int
|
418
|
+
rb_proc_arity(VALUE self)
|
352
419
|
{
|
353
|
-
|
420
|
+
return (int)NUM2INT(rb_funcall(self, rb_intern("arity"), 0));
|
354
421
|
}
|
355
422
|
#endif
|
356
423
|
|
@@ -359,33 +426,34 @@ int rb_proc_arity(VALUE self)
|
|
359
426
|
* Define a function named +name+ with +args+ using TextRep bitflags +flags+. The arity of the block
|
360
427
|
* will be used as the arity for the function defined.
|
361
428
|
*/
|
362
|
-
static VALUE
|
429
|
+
static VALUE
|
430
|
+
define_function_with_flags(VALUE self, VALUE name, VALUE flags)
|
363
431
|
{
|
364
|
-
|
365
|
-
|
366
|
-
|
432
|
+
sqlite3RubyPtr ctx;
|
433
|
+
VALUE block;
|
434
|
+
int status;
|
367
435
|
|
368
|
-
|
369
|
-
|
436
|
+
TypedData_Get_Struct(self, sqlite3Ruby, &database_type, ctx);
|
437
|
+
REQUIRE_OPEN_DB(ctx);
|
370
438
|
|
371
|
-
|
439
|
+
block = rb_block_proc();
|
372
440
|
|
373
|
-
|
374
|
-
|
375
|
-
|
376
|
-
|
377
|
-
|
378
|
-
|
379
|
-
|
380
|
-
|
381
|
-
|
382
|
-
|
441
|
+
status = sqlite3_create_function(
|
442
|
+
ctx->db,
|
443
|
+
StringValuePtr(name),
|
444
|
+
rb_proc_arity(block),
|
445
|
+
NUM2INT(flags),
|
446
|
+
(void *)block,
|
447
|
+
rb_sqlite3_func,
|
448
|
+
NULL,
|
449
|
+
NULL
|
450
|
+
);
|
383
451
|
|
384
|
-
|
452
|
+
CHECK(ctx->db, status);
|
385
453
|
|
386
|
-
|
454
|
+
rb_hash_aset(rb_iv_get(self, "@functions"), name, block);
|
387
455
|
|
388
|
-
|
456
|
+
return self;
|
389
457
|
}
|
390
458
|
|
391
459
|
/* call-seq: define_function(name) { |args,...| }
|
@@ -393,24 +461,26 @@ static VALUE define_function_with_flags(VALUE self, VALUE name, VALUE flags)
|
|
393
461
|
* Define a function named +name+ with +args+. The arity of the block
|
394
462
|
* will be used as the arity for the function defined.
|
395
463
|
*/
|
396
|
-
static VALUE
|
464
|
+
static VALUE
|
465
|
+
define_function(VALUE self, VALUE name)
|
397
466
|
{
|
398
|
-
|
467
|
+
return define_function_with_flags(self, name, INT2FIX(SQLITE_UTF8));
|
399
468
|
}
|
400
469
|
|
401
470
|
/* call-seq: interrupt
|
402
471
|
*
|
403
472
|
* Interrupts the currently executing operation, causing it to abort.
|
404
473
|
*/
|
405
|
-
static VALUE
|
474
|
+
static VALUE
|
475
|
+
interrupt(VALUE self)
|
406
476
|
{
|
407
|
-
|
408
|
-
|
409
|
-
|
477
|
+
sqlite3RubyPtr ctx;
|
478
|
+
TypedData_Get_Struct(self, sqlite3Ruby, &database_type, ctx);
|
479
|
+
REQUIRE_OPEN_DB(ctx);
|
410
480
|
|
411
|
-
|
481
|
+
sqlite3_interrupt(ctx->db);
|
412
482
|
|
413
|
-
|
483
|
+
return self;
|
414
484
|
}
|
415
485
|
|
416
486
|
/* call-seq: errmsg
|
@@ -418,13 +488,14 @@ static VALUE interrupt(VALUE self)
|
|
418
488
|
* Return a string describing the last error to have occurred with this
|
419
489
|
* database.
|
420
490
|
*/
|
421
|
-
static VALUE
|
491
|
+
static VALUE
|
492
|
+
errmsg(VALUE self)
|
422
493
|
{
|
423
|
-
|
424
|
-
|
425
|
-
|
494
|
+
sqlite3RubyPtr ctx;
|
495
|
+
TypedData_Get_Struct(self, sqlite3Ruby, &database_type, ctx);
|
496
|
+
REQUIRE_OPEN_DB(ctx);
|
426
497
|
|
427
|
-
|
498
|
+
return rb_str_new2(sqlite3_errmsg(ctx->db));
|
428
499
|
}
|
429
500
|
|
430
501
|
/* call-seq: errcode
|
@@ -432,13 +503,14 @@ static VALUE errmsg(VALUE self)
|
|
432
503
|
* Return an integer representing the last error to have occurred with this
|
433
504
|
* database.
|
434
505
|
*/
|
435
|
-
static VALUE
|
506
|
+
static VALUE
|
507
|
+
errcode_(VALUE self)
|
436
508
|
{
|
437
|
-
|
438
|
-
|
439
|
-
|
509
|
+
sqlite3RubyPtr ctx;
|
510
|
+
TypedData_Get_Struct(self, sqlite3Ruby, &database_type, ctx);
|
511
|
+
REQUIRE_OPEN_DB(ctx);
|
440
512
|
|
441
|
-
|
513
|
+
return INT2NUM(sqlite3_errcode(ctx->db));
|
442
514
|
}
|
443
515
|
|
444
516
|
/* call-seq: complete?(sql)
|
@@ -446,12 +518,14 @@ static VALUE errcode_(VALUE self)
|
|
446
518
|
* Return +true+ if the string is a valid (ie, parsable) SQL statement, and
|
447
519
|
* +false+ otherwise.
|
448
520
|
*/
|
449
|
-
static VALUE
|
521
|
+
static VALUE
|
522
|
+
complete_p(VALUE UNUSED(self), VALUE sql)
|
450
523
|
{
|
451
|
-
|
452
|
-
|
524
|
+
if (sqlite3_complete(StringValuePtr(sql))) {
|
525
|
+
return Qtrue;
|
526
|
+
}
|
453
527
|
|
454
|
-
|
528
|
+
return Qfalse;
|
455
529
|
}
|
456
530
|
|
457
531
|
/* call-seq: changes
|
@@ -460,37 +534,39 @@ static VALUE complete_p(VALUE UNUSED(self), VALUE sql)
|
|
460
534
|
* operation performed. Note that a "delete from table" without a where
|
461
535
|
* clause will not affect this value.
|
462
536
|
*/
|
463
|
-
static VALUE
|
537
|
+
static VALUE
|
538
|
+
changes(VALUE self)
|
464
539
|
{
|
465
|
-
|
466
|
-
|
467
|
-
|
540
|
+
sqlite3RubyPtr ctx;
|
541
|
+
TypedData_Get_Struct(self, sqlite3Ruby, &database_type, ctx);
|
542
|
+
REQUIRE_OPEN_DB(ctx);
|
468
543
|
|
469
|
-
|
544
|
+
return INT2NUM(sqlite3_changes(ctx->db));
|
470
545
|
}
|
471
546
|
|
472
|
-
static int
|
547
|
+
static int
|
548
|
+
rb_sqlite3_auth(
|
473
549
|
void *ctx,
|
474
550
|
int _action,
|
475
|
-
const char *
|
476
|
-
const char *
|
477
|
-
const char *
|
478
|
-
const char *
|
551
|
+
const char *_a,
|
552
|
+
const char *_b,
|
553
|
+
const char *_c,
|
554
|
+
const char *_d)
|
479
555
|
{
|
480
|
-
|
481
|
-
|
482
|
-
|
483
|
-
|
484
|
-
|
485
|
-
|
486
|
-
|
487
|
-
|
556
|
+
VALUE self = (VALUE)ctx;
|
557
|
+
VALUE action = INT2NUM(_action);
|
558
|
+
VALUE a = _a ? rb_str_new2(_a) : Qnil;
|
559
|
+
VALUE b = _b ? rb_str_new2(_b) : Qnil;
|
560
|
+
VALUE c = _c ? rb_str_new2(_c) : Qnil;
|
561
|
+
VALUE d = _d ? rb_str_new2(_d) : Qnil;
|
562
|
+
VALUE callback = rb_iv_get(self, "@authorizer");
|
563
|
+
VALUE result = rb_funcall(callback, rb_intern("call"), 5, action, a, b, c, d);
|
488
564
|
|
489
|
-
|
490
|
-
|
491
|
-
|
565
|
+
if (T_FIXNUM == TYPE(result)) { return (int)NUM2INT(result); }
|
566
|
+
if (Qtrue == result) { return SQLITE_OK; }
|
567
|
+
if (Qfalse == result) { return SQLITE_DENY; }
|
492
568
|
|
493
|
-
|
569
|
+
return SQLITE_IGNORE;
|
494
570
|
}
|
495
571
|
|
496
572
|
/* call-seq: set_authorizer = auth
|
@@ -503,23 +579,24 @@ static int rb_sqlite3_auth(
|
|
503
579
|
* is allowed to proceed. Returning 1 or false causes an authorization error to
|
504
580
|
* occur, and returning 2 or nil causes the access to be silently denied.
|
505
581
|
*/
|
506
|
-
static VALUE
|
582
|
+
static VALUE
|
583
|
+
set_authorizer(VALUE self, VALUE authorizer)
|
507
584
|
{
|
508
|
-
|
509
|
-
|
585
|
+
sqlite3RubyPtr ctx;
|
586
|
+
int status;
|
510
587
|
|
511
|
-
|
512
|
-
|
588
|
+
TypedData_Get_Struct(self, sqlite3Ruby, &database_type, ctx);
|
589
|
+
REQUIRE_OPEN_DB(ctx);
|
513
590
|
|
514
|
-
|
515
|
-
|
516
|
-
|
591
|
+
status = sqlite3_set_authorizer(
|
592
|
+
ctx->db, NIL_P(authorizer) ? NULL : rb_sqlite3_auth, (void *)self
|
593
|
+
);
|
517
594
|
|
518
|
-
|
595
|
+
CHECK(ctx->db, status);
|
519
596
|
|
520
|
-
|
597
|
+
rb_iv_set(self, "@authorizer", authorizer);
|
521
598
|
|
522
|
-
|
599
|
+
return self;
|
523
600
|
}
|
524
601
|
|
525
602
|
/* call-seq: db.busy_timeout = ms
|
@@ -532,15 +609,16 @@ static VALUE set_authorizer(VALUE self, VALUE authorizer)
|
|
532
609
|
*
|
533
610
|
* See also the mutually exclusive #busy_handler.
|
534
611
|
*/
|
535
|
-
static VALUE
|
612
|
+
static VALUE
|
613
|
+
set_busy_timeout(VALUE self, VALUE timeout)
|
536
614
|
{
|
537
|
-
|
538
|
-
|
539
|
-
|
615
|
+
sqlite3RubyPtr ctx;
|
616
|
+
TypedData_Get_Struct(self, sqlite3Ruby, &database_type, ctx);
|
617
|
+
REQUIRE_OPEN_DB(ctx);
|
540
618
|
|
541
|
-
|
619
|
+
CHECK(ctx->db, sqlite3_busy_timeout(ctx->db, (int)NUM2INT(timeout)));
|
542
620
|
|
543
|
-
|
621
|
+
return self;
|
544
622
|
}
|
545
623
|
|
546
624
|
/* call-seq: db.extended_result_codes = true
|
@@ -548,42 +626,44 @@ static VALUE set_busy_timeout(VALUE self, VALUE timeout)
|
|
548
626
|
* Enable extended result codes in SQLite. These result codes allow for more
|
549
627
|
* detailed exception reporting, such a which type of constraint is violated.
|
550
628
|
*/
|
551
|
-
static VALUE
|
629
|
+
static VALUE
|
630
|
+
set_extended_result_codes(VALUE self, VALUE enable)
|
552
631
|
{
|
553
|
-
|
554
|
-
|
555
|
-
|
632
|
+
sqlite3RubyPtr ctx;
|
633
|
+
TypedData_Get_Struct(self, sqlite3Ruby, &database_type, ctx);
|
634
|
+
REQUIRE_OPEN_DB(ctx);
|
556
635
|
|
557
|
-
|
636
|
+
CHECK(ctx->db, sqlite3_extended_result_codes(ctx->db, RTEST(enable) ? 1 : 0));
|
558
637
|
|
559
|
-
|
638
|
+
return self;
|
560
639
|
}
|
561
640
|
|
562
|
-
int
|
641
|
+
int
|
642
|
+
rb_comparator_func(void *ctx, int a_len, const void *a, int b_len, const void *b)
|
563
643
|
{
|
564
|
-
|
565
|
-
|
566
|
-
|
567
|
-
|
568
|
-
|
644
|
+
VALUE comparator;
|
645
|
+
VALUE a_str;
|
646
|
+
VALUE b_str;
|
647
|
+
VALUE comparison;
|
648
|
+
rb_encoding *internal_encoding;
|
569
649
|
|
570
|
-
|
650
|
+
internal_encoding = rb_default_internal_encoding();
|
571
651
|
|
572
|
-
|
573
|
-
|
574
|
-
|
652
|
+
comparator = (VALUE)ctx;
|
653
|
+
a_str = rb_str_new((const char *)a, a_len);
|
654
|
+
b_str = rb_str_new((const char *)b, b_len);
|
575
655
|
|
576
|
-
|
577
|
-
|
656
|
+
rb_enc_associate_index(a_str, rb_utf8_encindex());
|
657
|
+
rb_enc_associate_index(b_str, rb_utf8_encindex());
|
578
658
|
|
579
|
-
|
580
|
-
|
581
|
-
|
582
|
-
|
659
|
+
if (internal_encoding) {
|
660
|
+
a_str = rb_str_export_to_enc(a_str, internal_encoding);
|
661
|
+
b_str = rb_str_export_to_enc(b_str, internal_encoding);
|
662
|
+
}
|
583
663
|
|
584
|
-
|
664
|
+
comparison = rb_funcall(comparator, rb_intern("compare"), 2, a_str, b_str);
|
585
665
|
|
586
|
-
|
666
|
+
return NUM2INT(comparison);
|
587
667
|
}
|
588
668
|
|
589
669
|
/* call-seq: db.collation(name, comparator)
|
@@ -593,23 +673,24 @@ int rb_comparator_func(void * ctx, int a_len, const void * a, int b_len, const v
|
|
593
673
|
* two parameters and returns an integer less than, equal to, or greater than
|
594
674
|
* 0.
|
595
675
|
*/
|
596
|
-
static VALUE
|
676
|
+
static VALUE
|
677
|
+
collation(VALUE self, VALUE name, VALUE comparator)
|
597
678
|
{
|
598
|
-
|
599
|
-
|
600
|
-
|
679
|
+
sqlite3RubyPtr ctx;
|
680
|
+
TypedData_Get_Struct(self, sqlite3Ruby, &database_type, ctx);
|
681
|
+
REQUIRE_OPEN_DB(ctx);
|
601
682
|
|
602
|
-
|
603
|
-
|
604
|
-
|
605
|
-
|
606
|
-
|
607
|
-
|
683
|
+
CHECK(ctx->db, sqlite3_create_collation(
|
684
|
+
ctx->db,
|
685
|
+
StringValuePtr(name),
|
686
|
+
SQLITE_UTF8,
|
687
|
+
(void *)comparator,
|
688
|
+
NIL_P(comparator) ? NULL : rb_comparator_func));
|
608
689
|
|
609
|
-
|
610
|
-
|
690
|
+
/* Make sure our comparator doesn't get garbage collected. */
|
691
|
+
rb_hash_aset(rb_iv_get(self, "@collations"), name, comparator);
|
611
692
|
|
612
|
-
|
693
|
+
return self;
|
613
694
|
}
|
614
695
|
|
615
696
|
#ifdef HAVE_SQLITE3_LOAD_EXTENSION
|
@@ -619,24 +700,21 @@ static VALUE collation(VALUE self, VALUE name, VALUE comparator)
|
|
619
700
|
* loading must be enabled using db.enable_load_extension(true) prior
|
620
701
|
* to calling this API.
|
621
702
|
*/
|
622
|
-
static VALUE
|
703
|
+
static VALUE
|
704
|
+
load_extension(VALUE self, VALUE file)
|
623
705
|
{
|
624
|
-
|
625
|
-
|
626
|
-
|
627
|
-
|
628
|
-
|
629
|
-
|
706
|
+
sqlite3RubyPtr ctx;
|
707
|
+
int status;
|
708
|
+
char *errMsg;
|
709
|
+
|
710
|
+
TypedData_Get_Struct(self, sqlite3Ruby, &database_type, ctx);
|
711
|
+
REQUIRE_OPEN_DB(ctx);
|
712
|
+
|
713
|
+
status = sqlite3_load_extension(ctx->db, StringValuePtr(file), 0, &errMsg);
|
630
714
|
|
631
|
-
|
632
|
-
if (status != SQLITE_OK)
|
633
|
-
{
|
634
|
-
errexp = rb_exc_new2(rb_eRuntimeError, errMsg);
|
635
|
-
sqlite3_free(errMsg);
|
636
|
-
rb_exc_raise(errexp);
|
637
|
-
}
|
715
|
+
CHECK_MSG(ctx->db, status, errMsg);
|
638
716
|
|
639
|
-
|
717
|
+
return self;
|
640
718
|
}
|
641
719
|
#endif
|
642
720
|
|
@@ -645,107 +723,79 @@ static VALUE load_extension(VALUE self, VALUE file)
|
|
645
723
|
*
|
646
724
|
* Enable or disable extension loading.
|
647
725
|
*/
|
648
|
-
static VALUE
|
649
|
-
|
650
|
-
|
651
|
-
|
652
|
-
|
653
|
-
|
654
|
-
|
655
|
-
|
656
|
-
|
657
|
-
|
658
|
-
|
659
|
-
|
660
|
-
|
661
|
-
|
726
|
+
static VALUE
|
727
|
+
enable_load_extension(VALUE self, VALUE onoff)
|
728
|
+
{
|
729
|
+
sqlite3RubyPtr ctx;
|
730
|
+
int onoffparam;
|
731
|
+
TypedData_Get_Struct(self, sqlite3Ruby, &database_type, ctx);
|
732
|
+
REQUIRE_OPEN_DB(ctx);
|
733
|
+
|
734
|
+
if (Qtrue == onoff) {
|
735
|
+
onoffparam = 1;
|
736
|
+
} else if (Qfalse == onoff) {
|
737
|
+
onoffparam = 0;
|
738
|
+
} else {
|
739
|
+
onoffparam = (int)NUM2INT(onoff);
|
740
|
+
}
|
662
741
|
|
663
|
-
|
742
|
+
CHECK(ctx->db, sqlite3_enable_load_extension(ctx->db, onoffparam));
|
664
743
|
|
665
|
-
|
744
|
+
return self;
|
666
745
|
}
|
667
746
|
#endif
|
668
747
|
|
669
|
-
static int enc_cb(void * _self, int UNUSED(columns), char **data, char **UNUSED(names))
|
670
|
-
{
|
671
|
-
VALUE self = (VALUE)_self;
|
672
|
-
|
673
|
-
int index = rb_enc_find_index(data[0]);
|
674
|
-
rb_encoding * e = rb_enc_from_index(index);
|
675
|
-
rb_iv_set(self, "@encoding", rb_enc_from_encoding(e));
|
676
|
-
|
677
|
-
return 0;
|
678
|
-
}
|
679
|
-
|
680
|
-
/* call-seq: db.encoding
|
681
|
-
*
|
682
|
-
* Fetch the encoding set on this database
|
683
|
-
*/
|
684
|
-
static VALUE db_encoding(VALUE self)
|
685
|
-
{
|
686
|
-
sqlite3RubyPtr ctx;
|
687
|
-
VALUE enc;
|
688
|
-
|
689
|
-
TypedData_Get_Struct(self, sqlite3Ruby, &database_type, ctx);
|
690
|
-
REQUIRE_OPEN_DB(ctx);
|
691
|
-
|
692
|
-
enc = rb_iv_get(self, "@encoding");
|
693
|
-
|
694
|
-
if(NIL_P(enc)) {
|
695
|
-
sqlite3_exec(ctx->db, "PRAGMA encoding", enc_cb, (void *)self, NULL);
|
696
|
-
}
|
697
|
-
|
698
|
-
return rb_iv_get(self, "@encoding");
|
699
|
-
}
|
700
|
-
|
701
748
|
/* call-seq: db.transaction_active?
|
702
749
|
*
|
703
750
|
* Returns +true+ if there is a transaction active, and +false+ otherwise.
|
704
751
|
*
|
705
752
|
*/
|
706
|
-
static VALUE
|
753
|
+
static VALUE
|
754
|
+
transaction_active_p(VALUE self)
|
707
755
|
{
|
708
|
-
|
709
|
-
|
710
|
-
|
756
|
+
sqlite3RubyPtr ctx;
|
757
|
+
TypedData_Get_Struct(self, sqlite3Ruby, &database_type, ctx);
|
758
|
+
REQUIRE_OPEN_DB(ctx);
|
711
759
|
|
712
|
-
|
760
|
+
return sqlite3_get_autocommit(ctx->db) ? Qfalse : Qtrue;
|
713
761
|
}
|
714
762
|
|
715
|
-
static int
|
763
|
+
static int
|
764
|
+
hash_callback_function(VALUE callback_ary, int count, char **data, char **columns)
|
716
765
|
{
|
717
|
-
|
718
|
-
|
766
|
+
VALUE new_hash = rb_hash_new();
|
767
|
+
int i;
|
719
768
|
|
720
|
-
|
721
|
-
|
722
|
-
|
723
|
-
|
724
|
-
|
769
|
+
for (i = 0; i < count; i++) {
|
770
|
+
if (data[i] == NULL) {
|
771
|
+
rb_hash_aset(new_hash, rb_str_new_cstr(columns[i]), Qnil);
|
772
|
+
} else {
|
773
|
+
rb_hash_aset(new_hash, rb_str_new_cstr(columns[i]), rb_str_new_cstr(data[i]));
|
774
|
+
}
|
725
775
|
}
|
726
|
-
}
|
727
776
|
|
728
|
-
|
777
|
+
rb_ary_push(callback_ary, new_hash);
|
729
778
|
|
730
|
-
|
779
|
+
return 0;
|
731
780
|
}
|
732
781
|
|
733
|
-
static int
|
782
|
+
static int
|
783
|
+
regular_callback_function(VALUE callback_ary, int count, char **data, char **columns)
|
734
784
|
{
|
735
|
-
|
736
|
-
|
785
|
+
VALUE new_ary = rb_ary_new();
|
786
|
+
int i;
|
737
787
|
|
738
|
-
|
739
|
-
|
740
|
-
|
741
|
-
|
742
|
-
|
788
|
+
for (i = 0; i < count; i++) {
|
789
|
+
if (data[i] == NULL) {
|
790
|
+
rb_ary_push(new_ary, Qnil);
|
791
|
+
} else {
|
792
|
+
rb_ary_push(new_ary, rb_str_new_cstr(data[i]));
|
793
|
+
}
|
743
794
|
}
|
744
|
-
}
|
745
795
|
|
746
|
-
|
796
|
+
rb_ary_push(callback_ary, new_ary);
|
747
797
|
|
748
|
-
|
798
|
+
return 0;
|
749
799
|
}
|
750
800
|
|
751
801
|
|
@@ -757,31 +807,30 @@ static int regular_callback_function(VALUE callback_ary, int count, char **data,
|
|
757
807
|
* so the user may parse values with a block.
|
758
808
|
* If no query is made, an empty array will be returned.
|
759
809
|
*/
|
760
|
-
static VALUE
|
810
|
+
static VALUE
|
811
|
+
exec_batch(VALUE self, VALUE sql, VALUE results_as_hash)
|
761
812
|
{
|
762
|
-
|
763
|
-
|
764
|
-
|
765
|
-
|
766
|
-
VALUE errexp;
|
813
|
+
sqlite3RubyPtr ctx;
|
814
|
+
int status;
|
815
|
+
VALUE callback_ary = rb_ary_new();
|
816
|
+
char *errMsg;
|
767
817
|
|
768
|
-
|
769
|
-
|
818
|
+
TypedData_Get_Struct(self, sqlite3Ruby, &database_type, ctx);
|
819
|
+
REQUIRE_OPEN_DB(ctx);
|
770
820
|
|
771
|
-
|
772
|
-
|
773
|
-
|
774
|
-
|
775
|
-
|
821
|
+
if (results_as_hash == Qtrue) {
|
822
|
+
status = sqlite3_exec(ctx->db, StringValuePtr(sql), (sqlite3_callback)hash_callback_function,
|
823
|
+
(void *)callback_ary,
|
824
|
+
&errMsg);
|
825
|
+
} else {
|
826
|
+
status = sqlite3_exec(ctx->db, StringValuePtr(sql), (sqlite3_callback)regular_callback_function,
|
827
|
+
(void *)callback_ary,
|
828
|
+
&errMsg);
|
829
|
+
}
|
776
830
|
|
777
|
-
|
778
|
-
{
|
779
|
-
errexp = rb_exc_new2(rb_eRuntimeError, errMsg);
|
780
|
-
sqlite3_free(errMsg);
|
781
|
-
rb_exc_raise(errexp);
|
782
|
-
}
|
831
|
+
CHECK_MSG(ctx->db, status, errMsg);
|
783
832
|
|
784
|
-
|
833
|
+
return callback_ary;
|
785
834
|
}
|
786
835
|
|
787
836
|
/* call-seq: db.db_filename(database_name)
|
@@ -789,88 +838,92 @@ static VALUE exec_batch(VALUE self, VALUE sql, VALUE results_as_hash)
|
|
789
838
|
* Returns the file associated with +database_name+. Can return nil or an
|
790
839
|
* empty string if the database is temporary, or in-memory.
|
791
840
|
*/
|
792
|
-
static VALUE
|
841
|
+
static VALUE
|
842
|
+
db_filename(VALUE self, VALUE db_name)
|
793
843
|
{
|
794
|
-
|
795
|
-
|
796
|
-
|
797
|
-
|
844
|
+
sqlite3RubyPtr ctx;
|
845
|
+
const char *fname;
|
846
|
+
TypedData_Get_Struct(self, sqlite3Ruby, &database_type, ctx);
|
847
|
+
REQUIRE_OPEN_DB(ctx);
|
798
848
|
|
799
|
-
|
849
|
+
fname = sqlite3_db_filename(ctx->db, StringValueCStr(db_name));
|
800
850
|
|
801
|
-
|
802
|
-
|
851
|
+
if (fname) { return SQLITE3_UTF8_STR_NEW2(fname); }
|
852
|
+
return Qnil;
|
803
853
|
}
|
804
854
|
|
805
|
-
static VALUE
|
855
|
+
static VALUE
|
856
|
+
rb_sqlite3_open16(VALUE self, VALUE file)
|
806
857
|
{
|
807
|
-
|
808
|
-
|
858
|
+
int status;
|
859
|
+
sqlite3RubyPtr ctx;
|
809
860
|
|
810
|
-
|
861
|
+
TypedData_Get_Struct(self, sqlite3Ruby, &database_type, ctx);
|
811
862
|
|
812
863
|
#if defined TAINTING_SUPPORT
|
813
864
|
#if defined StringValueCStr
|
814
|
-
|
815
|
-
|
865
|
+
StringValuePtr(file);
|
866
|
+
rb_check_safe_obj(file);
|
816
867
|
#else
|
817
|
-
|
868
|
+
Check_SafeStr(file);
|
818
869
|
#endif
|
819
870
|
#endif
|
820
871
|
|
821
|
-
|
872
|
+
status = sqlite3_open16(utf16_string_value_ptr(file), &ctx->db);
|
822
873
|
|
823
|
-
|
874
|
+
CHECK(ctx->db, status)
|
824
875
|
|
825
|
-
|
876
|
+
return INT2NUM(status);
|
826
877
|
}
|
827
878
|
|
828
|
-
void
|
879
|
+
void
|
880
|
+
init_sqlite3_database(void)
|
829
881
|
{
|
830
882
|
#if 0
|
831
|
-
|
883
|
+
VALUE mSqlite3 = rb_define_module("SQLite3");
|
884
|
+
#endif
|
885
|
+
cSqlite3Database = rb_define_class_under(mSqlite3, "Database", rb_cObject);
|
886
|
+
|
887
|
+
rb_define_alloc_func(cSqlite3Database, allocate);
|
888
|
+
rb_define_private_method(cSqlite3Database, "open_v2", rb_sqlite3_open_v2, 3);
|
889
|
+
rb_define_private_method(cSqlite3Database, "open16", rb_sqlite3_open16, 1);
|
890
|
+
rb_define_method(cSqlite3Database, "collation", collation, 2);
|
891
|
+
rb_define_method(cSqlite3Database, "close", sqlite3_rb_close, 0);
|
892
|
+
rb_define_method(cSqlite3Database, "closed?", closed_p, 0);
|
893
|
+
rb_define_method(cSqlite3Database, "total_changes", total_changes, 0);
|
894
|
+
rb_define_method(cSqlite3Database, "trace", trace, -1);
|
895
|
+
rb_define_method(cSqlite3Database, "last_insert_row_id", last_insert_row_id, 0);
|
896
|
+
rb_define_method(cSqlite3Database, "define_function", define_function, 1);
|
897
|
+
rb_define_method(cSqlite3Database, "define_function_with_flags", define_function_with_flags, 2);
|
898
|
+
/* public "define_aggregator" is now a shim around define_aggregator2
|
899
|
+
* implemented in Ruby */
|
900
|
+
rb_define_private_method(cSqlite3Database, "define_aggregator2", rb_sqlite3_define_aggregator2, 2);
|
901
|
+
rb_define_private_method(cSqlite3Database, "disable_quirk_mode", rb_sqlite3_disable_quirk_mode, 0);
|
902
|
+
rb_define_method(cSqlite3Database, "interrupt", interrupt, 0);
|
903
|
+
rb_define_method(cSqlite3Database, "errmsg", errmsg, 0);
|
904
|
+
rb_define_method(cSqlite3Database, "errcode", errcode_, 0);
|
905
|
+
rb_define_method(cSqlite3Database, "complete?", complete_p, 1);
|
906
|
+
rb_define_method(cSqlite3Database, "changes", changes, 0);
|
907
|
+
rb_define_method(cSqlite3Database, "authorizer=", set_authorizer, 1);
|
908
|
+
rb_define_method(cSqlite3Database, "busy_handler", busy_handler, -1);
|
909
|
+
rb_define_method(cSqlite3Database, "busy_timeout=", set_busy_timeout, 1);
|
910
|
+
#ifndef SQLITE_OMIT_PROGRESS_CALLBACK
|
911
|
+
rb_define_method(cSqlite3Database, "statement_timeout=", set_statement_timeout, 1);
|
832
912
|
#endif
|
833
|
-
|
834
|
-
|
835
|
-
|
836
|
-
|
837
|
-
rb_define_private_method(cSqlite3Database, "open16", rb_sqlite3_open16, 1);
|
838
|
-
rb_define_method(cSqlite3Database, "collation", collation, 2);
|
839
|
-
rb_define_method(cSqlite3Database, "close", sqlite3_rb_close, 0);
|
840
|
-
rb_define_method(cSqlite3Database, "closed?", closed_p, 0);
|
841
|
-
rb_define_method(cSqlite3Database, "total_changes", total_changes, 0);
|
842
|
-
rb_define_method(cSqlite3Database, "trace", trace, -1);
|
843
|
-
rb_define_method(cSqlite3Database, "last_insert_row_id", last_insert_row_id, 0);
|
844
|
-
rb_define_method(cSqlite3Database, "define_function", define_function, 1);
|
845
|
-
rb_define_method(cSqlite3Database, "define_function_with_flags", define_function_with_flags, 2);
|
846
|
-
/* public "define_aggregator" is now a shim around define_aggregator2
|
847
|
-
* implemented in Ruby */
|
848
|
-
rb_define_private_method(cSqlite3Database, "define_aggregator2", rb_sqlite3_define_aggregator2, 2);
|
849
|
-
rb_define_private_method(cSqlite3Database, "disable_quirk_mode", rb_sqlite3_disable_quirk_mode, 0);
|
850
|
-
rb_define_method(cSqlite3Database, "interrupt", interrupt, 0);
|
851
|
-
rb_define_method(cSqlite3Database, "errmsg", errmsg, 0);
|
852
|
-
rb_define_method(cSqlite3Database, "errcode", errcode_, 0);
|
853
|
-
rb_define_method(cSqlite3Database, "complete?", complete_p, 1);
|
854
|
-
rb_define_method(cSqlite3Database, "changes", changes, 0);
|
855
|
-
rb_define_method(cSqlite3Database, "authorizer=", set_authorizer, 1);
|
856
|
-
rb_define_method(cSqlite3Database, "busy_handler", busy_handler, -1);
|
857
|
-
rb_define_method(cSqlite3Database, "busy_timeout=", set_busy_timeout, 1);
|
858
|
-
rb_define_method(cSqlite3Database, "extended_result_codes=", set_extended_result_codes, 1);
|
859
|
-
rb_define_method(cSqlite3Database, "transaction_active?", transaction_active_p, 0);
|
860
|
-
rb_define_private_method(cSqlite3Database, "exec_batch", exec_batch, 2);
|
861
|
-
rb_define_private_method(cSqlite3Database, "db_filename", db_filename, 1);
|
913
|
+
rb_define_method(cSqlite3Database, "extended_result_codes=", set_extended_result_codes, 1);
|
914
|
+
rb_define_method(cSqlite3Database, "transaction_active?", transaction_active_p, 0);
|
915
|
+
rb_define_private_method(cSqlite3Database, "exec_batch", exec_batch, 2);
|
916
|
+
rb_define_private_method(cSqlite3Database, "db_filename", db_filename, 1);
|
862
917
|
|
863
918
|
#ifdef HAVE_SQLITE3_LOAD_EXTENSION
|
864
|
-
|
919
|
+
rb_define_method(cSqlite3Database, "load_extension", load_extension, 1);
|
865
920
|
#endif
|
866
921
|
|
867
922
|
#ifdef HAVE_SQLITE3_ENABLE_LOAD_EXTENSION
|
868
|
-
|
923
|
+
rb_define_method(cSqlite3Database, "enable_load_extension", enable_load_extension, 1);
|
869
924
|
#endif
|
870
925
|
|
871
|
-
|
872
|
-
|
873
|
-
rb_sqlite3_aggregator_init();
|
926
|
+
rb_sqlite3_aggregator_init();
|
874
927
|
}
|
875
928
|
|
876
929
|
#ifdef _MSC_VER
|