extralite 1.12 → 1.13

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.
@@ -1,702 +0,0 @@
1
- #include <stdio.h>
2
- #include "ruby.h"
3
- #include "ruby/thread.h"
4
- #include <sqlite3.h>
5
-
6
- VALUE cError;
7
- VALUE cSQLError;
8
- VALUE cBusyError;
9
-
10
- ID ID_KEYS;
11
- ID ID_STRIP;
12
- ID ID_TO_S;
13
-
14
- typedef struct Database_t {
15
- sqlite3 *sqlite3_db;
16
- } Database_t;
17
-
18
- static size_t Database_size(const void *ptr) {
19
- return sizeof(Database_t);
20
- }
21
-
22
- static void Database_free(void *ptr) {
23
- Database_t *db = ptr;
24
- if (db->sqlite3_db) {
25
- sqlite3_close(db->sqlite3_db);
26
- }
27
- // close db
28
- free(ptr);
29
- }
30
-
31
- static const rb_data_type_t Database_type = {
32
- "Database",
33
- {0, Database_free, Database_size,},
34
- 0, 0, RUBY_TYPED_FREE_IMMEDIATELY
35
- };
36
-
37
- static VALUE Database_allocate(VALUE klass) {
38
- Database_t *db = ALLOC(Database_t);
39
- db->sqlite3_db = 0;
40
- return TypedData_Wrap_Struct(klass, &Database_type, db);
41
- }
42
-
43
- #define GetDatabase(obj, database) \
44
- TypedData_Get_Struct((obj), Database_t, &Database_type, (database))
45
-
46
- // make sure the database is open
47
- #define GetOpenDatabase(obj, database) { \
48
- TypedData_Get_Struct((obj), Database_t, &Database_type, (database)); \
49
- if (!(database)->sqlite3_db) { \
50
- rb_raise(cError, "Database is closed"); \
51
- } \
52
- }
53
-
54
- /* call-seq: sqlite3_version
55
- *
56
- * Returns the sqlite3 version used by Extralite.
57
- */
58
-
59
- VALUE Extralite_sqlite3_version(VALUE self) {
60
- return rb_str_new_cstr(sqlite3_version);
61
- }
62
-
63
- /* call-seq: initialize(path)
64
- *
65
- * Initializes a new SQLite database with the given path.
66
- */
67
-
68
- VALUE Database_initialize(VALUE self, VALUE path) {
69
- int rc;
70
- Database_t *db;
71
- GetDatabase(self, db);
72
-
73
- rc = sqlite3_open(StringValueCStr(path), &db->sqlite3_db);
74
- if (rc) {
75
- sqlite3_close(db->sqlite3_db);
76
- rb_raise(cError, "%s", sqlite3_errmsg(db->sqlite3_db));
77
- }
78
-
79
- rc = sqlite3_enable_load_extension(db->sqlite3_db, 1);
80
- if (rc) {
81
- sqlite3_close(db->sqlite3_db);
82
- rb_raise(cError, "%s", sqlite3_errmsg(db->sqlite3_db));
83
- }
84
-
85
- return Qnil;
86
- }
87
-
88
- /* call-seq: close
89
- *
90
- * Closes the database.
91
- */
92
- VALUE Database_close(VALUE self) {
93
- int rc;
94
- Database_t *db;
95
- GetDatabase(self, db);
96
-
97
- rc = sqlite3_close(db->sqlite3_db);
98
- if (rc) {
99
- rb_raise(cError, "%s", sqlite3_errmsg(db->sqlite3_db));
100
- }
101
-
102
- db->sqlite3_db = 0;
103
- return self;
104
- }
105
-
106
- /* call-seq: closed?
107
- *
108
- * Returns true if the database is closed.
109
- */
110
- VALUE Database_closed_p(VALUE self) {
111
- Database_t *db;
112
- GetDatabase(self, db);
113
-
114
- return db->sqlite3_db ? Qfalse : Qtrue;
115
- }
116
-
117
- static inline VALUE get_column_value(sqlite3_stmt *stmt, int col, int type) {
118
- switch (type) {
119
- case SQLITE_NULL:
120
- return Qnil;
121
- case SQLITE_INTEGER:
122
- return LL2NUM(sqlite3_column_int64(stmt, col));
123
- case SQLITE_FLOAT:
124
- return DBL2NUM(sqlite3_column_double(stmt, col));
125
- case SQLITE_TEXT:
126
- return rb_str_new_cstr((char *)sqlite3_column_text(stmt, col));
127
- case SQLITE_BLOB:
128
- return rb_str_new((const char *)sqlite3_column_blob(stmt, col), (long)sqlite3_column_bytes(stmt, col));
129
- default:
130
- rb_raise(cError, "Unknown column type: %d", type);
131
- }
132
-
133
- return Qnil;
134
- }
135
-
136
- static void bind_parameter_value(sqlite3_stmt *stmt, int pos, VALUE value);
137
-
138
- static inline void bind_hash_parameter_values(sqlite3_stmt *stmt, VALUE hash) {
139
- VALUE keys = rb_funcall(hash, ID_KEYS, 0);
140
- long len = RARRAY_LEN(keys);
141
- for (long i = 0; i < len; i++) {
142
- VALUE k = RARRAY_AREF(keys, i);
143
- VALUE v = rb_hash_aref(hash, k);
144
-
145
- switch (TYPE(k)) {
146
- case T_FIXNUM:
147
- bind_parameter_value(stmt, NUM2INT(k), v);
148
- break;
149
- case T_SYMBOL:
150
- k = rb_funcall(k, ID_TO_S, 0);
151
- case T_STRING:
152
- if(RSTRING_PTR(k)[0] != ':') k = rb_str_plus(rb_str_new2(":"), k);
153
- int pos = sqlite3_bind_parameter_index(stmt, StringValuePtr(k));
154
- bind_parameter_value(stmt, pos, v);
155
- break;
156
- default:
157
- rb_raise(cError, "Cannot bind hash key value idx %ld", i);
158
- }
159
- }
160
- RB_GC_GUARD(keys);
161
- }
162
-
163
- static inline void bind_parameter_value(sqlite3_stmt *stmt, int pos, VALUE value) {
164
- switch (TYPE(value)) {
165
- case T_NIL:
166
- sqlite3_bind_null(stmt, pos);
167
- return;
168
- case T_FIXNUM:
169
- sqlite3_bind_int64(stmt, pos, NUM2LL(value));
170
- return;
171
- case T_FLOAT:
172
- sqlite3_bind_double(stmt, pos, NUM2DBL(value));
173
- return;
174
- case T_TRUE:
175
- sqlite3_bind_int(stmt, pos, 1);
176
- return;
177
- case T_FALSE:
178
- sqlite3_bind_int(stmt, pos, 0);
179
- return;
180
- case T_STRING:
181
- sqlite3_bind_text(stmt, pos, RSTRING_PTR(value), RSTRING_LEN(value), SQLITE_TRANSIENT);
182
- return;
183
- case T_HASH:
184
- bind_hash_parameter_values(stmt, value);
185
- return;
186
- default:
187
- rb_raise(cError, "Cannot bind parameter at position %d", pos);
188
- }
189
- }
190
-
191
- static inline void bind_all_parameters(sqlite3_stmt *stmt, int argc, VALUE *argv) {
192
- if (argc > 1) {
193
- for (int i = 1; i < argc; i++) {
194
- bind_parameter_value(stmt, i, argv[i]);
195
- }
196
- }
197
- }
198
-
199
- static inline VALUE get_column_names(sqlite3_stmt *stmt, int column_count) {
200
- VALUE arr = rb_ary_new2(column_count);
201
- for (int i = 0; i < column_count; i++) {
202
- VALUE name = ID2SYM(rb_intern(sqlite3_column_name(stmt, i)));
203
- rb_ary_push(arr, name);
204
- }
205
- return arr;
206
- }
207
-
208
- static inline VALUE row_to_hash(sqlite3_stmt *stmt, int column_count, VALUE column_names) {
209
- VALUE row = rb_hash_new();
210
- for (int i = 0; i < column_count; i++) {
211
- VALUE value = get_column_value(stmt, i, sqlite3_column_type(stmt, i));
212
- rb_hash_aset(row, RARRAY_AREF(column_names, i), value);
213
- }
214
- return row;
215
- }
216
-
217
- static inline VALUE row_to_ary(sqlite3_stmt *stmt, int column_count) {
218
- VALUE row = rb_ary_new2(column_count);
219
- for (int i = 0; i < column_count; i++) {
220
- VALUE value = get_column_value(stmt, i, sqlite3_column_type(stmt, i));
221
- rb_ary_push(row, value);
222
- }
223
- return row;
224
- }
225
-
226
- struct multi_stmt_ctx {
227
- sqlite3 *db;
228
- sqlite3_stmt **stmt;
229
- const char *str;
230
- long len;
231
- int rc;
232
- };
233
-
234
- void *prepare_multi_stmt_without_gvl(void *ptr) {
235
- struct multi_stmt_ctx *ctx = (struct multi_stmt_ctx *)ptr;
236
- const char *rest = NULL;
237
- const char *str = ctx->str;
238
- const char *end = ctx->str + ctx->len;
239
- while (1) {
240
- ctx->rc = sqlite3_prepare_v2(ctx->db, str, end - str, ctx->stmt, &rest);
241
- if (ctx->rc) {
242
- sqlite3_finalize(*ctx->stmt);
243
- return NULL;
244
- }
245
-
246
- if (rest == end) return NULL;
247
-
248
- // perform current query, but discard its results
249
- ctx->rc = sqlite3_step(*ctx->stmt);
250
- sqlite3_finalize(*ctx->stmt);
251
- switch (ctx->rc) {
252
- case SQLITE_BUSY:
253
- case SQLITE_ERROR:
254
- case SQLITE_MISUSE:
255
- return NULL;
256
- }
257
- str = rest;
258
- }
259
- return NULL;
260
- }
261
-
262
- /*
263
- This function prepares a statement from an SQL string containing one or more SQL
264
- statements. It will release the GVL while the statements are being prepared and
265
- executed. All statements excluding the last one are executed. The last statement
266
- is not executed, but instead handed back to the caller for looping over results.
267
- */
268
- static inline void prepare_multi_stmt(sqlite3 *db, sqlite3_stmt **stmt, VALUE sql) {
269
- struct multi_stmt_ctx ctx = {db, stmt, RSTRING_PTR(sql), RSTRING_LEN(sql), 0};
270
- rb_thread_call_without_gvl(prepare_multi_stmt_without_gvl, (void *)&ctx, RUBY_UBF_IO, 0);
271
- RB_GC_GUARD(sql);
272
-
273
- switch (ctx.rc) {
274
- case 0:
275
- return;
276
- case SQLITE_BUSY:
277
- rb_raise(cBusyError, "Database is busy");
278
- case SQLITE_ERROR:
279
- rb_raise(cSQLError, "%s", sqlite3_errmsg(db));
280
- default:
281
- rb_raise(cError, "Invalid return code for prepare_multi_stmt_without_gvl: %d (please open an issue on https://github.com/digital-fabric/extralite)", ctx.rc);
282
- }
283
- }
284
-
285
- struct step_ctx {
286
- sqlite3_stmt *stmt;
287
- int rc;
288
- };
289
-
290
- void *stmt_iterate_without_gvl(void *ptr) {
291
- struct step_ctx *ctx = (struct step_ctx *)ptr;
292
- ctx->rc = sqlite3_step(ctx->stmt);
293
- return NULL;
294
- }
295
-
296
- static inline int stmt_iterate(sqlite3_stmt *stmt, sqlite3 *db) {
297
- struct step_ctx ctx = {stmt, 0};
298
- rb_thread_call_without_gvl(stmt_iterate_without_gvl, (void *)&ctx, RUBY_UBF_IO, 0);
299
- switch (ctx.rc) {
300
- case SQLITE_ROW:
301
- return 1;
302
- case SQLITE_DONE:
303
- return 0;
304
- case SQLITE_BUSY:
305
- rb_raise(cBusyError, "Database is busy");
306
- case SQLITE_ERROR:
307
- rb_raise(cSQLError, "%s", sqlite3_errmsg(db));
308
- default:
309
- rb_raise(cError, "Invalid return code for sqlite3_step: %d (please open an issue on https://github.com/digital-fabric/extralite)", ctx.rc);
310
- }
311
-
312
- return 0;
313
- }
314
-
315
- typedef struct query_ctx {
316
- VALUE self;
317
- int argc;
318
- VALUE *argv;
319
- sqlite3_stmt *stmt;
320
- } query_ctx;
321
-
322
- VALUE cleanup_stmt(VALUE arg) {
323
- query_ctx *ctx = (query_ctx *)arg;
324
- if (ctx->stmt) sqlite3_finalize(ctx->stmt);
325
- return Qnil;
326
- }
327
-
328
- #define check_arity_and_prepare_sql(argc, argv, sql) { \
329
- rb_check_arity(argc, 1, UNLIMITED_ARGUMENTS); \
330
- sql = rb_funcall(argv[0], ID_STRIP, 0); \
331
- if (RSTRING_LEN(sql) == 0) return Qnil; \
332
- }
333
-
334
- VALUE safe_query_hash(VALUE arg) {
335
- query_ctx *ctx = (query_ctx *)arg;
336
- Database_t *db;
337
- VALUE result = ctx->self;
338
- int yield_to_block = rb_block_given_p();
339
- VALUE row;
340
- VALUE sql;
341
- int column_count;
342
- VALUE column_names;
343
-
344
- check_arity_and_prepare_sql(ctx->argc, ctx->argv, sql);
345
- GetOpenDatabase(ctx->self, db);
346
-
347
- prepare_multi_stmt(db->sqlite3_db, &ctx->stmt, sql);
348
- bind_all_parameters(ctx->stmt, ctx->argc, ctx->argv);
349
- column_count = sqlite3_column_count(ctx->stmt);
350
- column_names = get_column_names(ctx->stmt, column_count);
351
-
352
- // block not given, so prepare the array of records to be returned
353
- if (!yield_to_block) result = rb_ary_new();
354
-
355
- while (stmt_iterate(ctx->stmt, db->sqlite3_db)) {
356
- row = row_to_hash(ctx->stmt, column_count, column_names);
357
- if (yield_to_block) rb_yield(row); else rb_ary_push(result, row);
358
- }
359
-
360
- RB_GC_GUARD(column_names);
361
- RB_GC_GUARD(row);
362
- RB_GC_GUARD(result);
363
- return result;
364
- }
365
-
366
- /* call-seq:
367
- * query(sql, *parameters, &block)
368
- * query_hash(sql, *parameters, &block)
369
- *
370
- * Runs a query returning rows as hashes (with symbol keys). If a block is
371
- * given, it will be called for each row. Otherwise, an array containing all
372
- * rows is returned.
373
- *
374
- * Query parameters to be bound to placeholders in the query can be specified as
375
- * a list of values or as a hash mapping parameter names to values. When
376
- * parameters are given as a least, the query should specify parameters using
377
- * `?`:
378
- *
379
- * db.query('select * from foo where x = ?', 42)
380
- *
381
- * Named placeholders are specified using `:`. The placeholder values are
382
- * specified using a hash, where keys are either strings are symbols. String
383
- * keys can include or omit the `:` prefix. The following are equivalent:
384
- *
385
- * db.query('select * from foo where x = :bar', bar: 42)
386
- * db.query('select * from foo where x = :bar', 'bar' => 42)
387
- * db.query('select * from foo where x = :bar', ':bar' => 42)
388
- */
389
- VALUE Database_query_hash(int argc, VALUE *argv, VALUE self) {
390
- query_ctx ctx = { self, argc, argv, 0 };
391
- return rb_ensure(safe_query_hash, (VALUE)&ctx, cleanup_stmt, (VALUE)&ctx);
392
- }
393
-
394
- VALUE safe_query_ary(VALUE arg) {
395
- query_ctx *ctx = (query_ctx *)arg;
396
- Database_t *db;
397
- int column_count;
398
- VALUE result = ctx->self;
399
- int yield_to_block = rb_block_given_p();
400
- VALUE row;
401
- VALUE sql;
402
-
403
- check_arity_and_prepare_sql(ctx->argc, ctx->argv, sql);
404
- GetOpenDatabase(ctx->self, db);
405
-
406
- prepare_multi_stmt(db->sqlite3_db, &ctx->stmt, sql);
407
- bind_all_parameters(ctx->stmt, ctx->argc, ctx->argv);
408
- column_count = sqlite3_column_count(ctx->stmt);
409
-
410
- // block not given, so prepare the array of records to be returned
411
- if (!yield_to_block) result = rb_ary_new();
412
-
413
- while (stmt_iterate(ctx->stmt, db->sqlite3_db)) {
414
- row = row_to_ary(ctx->stmt, column_count);
415
- if (yield_to_block) rb_yield(row); else rb_ary_push(result, row);
416
- }
417
-
418
- RB_GC_GUARD(row);
419
- RB_GC_GUARD(result);
420
- return result;
421
- }
422
-
423
- /* call-seq: query_ary(sql, *parameters, &block)
424
- *
425
- * Runs a query returning rows as arrays. If a block is given, it will be called
426
- * for each row. Otherwise, an array containing all rows is returned.
427
- *
428
- * Query parameters to be bound to placeholders in the query can be specified as
429
- * a list of values or as a hash mapping parameter names to values. When
430
- * parameters are given as a least, the query should specify parameters using
431
- * `?`:
432
- *
433
- * db.query_ary('select * from foo where x = ?', 42)
434
- *
435
- * Named placeholders are specified using `:`. The placeholder values are
436
- * specified using a hash, where keys are either strings are symbols. String
437
- * keys can include or omit the `:` prefix. The following are equivalent:
438
- *
439
- * db.query_ary('select * from foo where x = :bar', bar: 42)
440
- * db.query_ary('select * from foo where x = :bar', 'bar' => 42)
441
- * db.query_ary('select * from foo where x = :bar', ':bar' => 42)
442
- */
443
- VALUE Database_query_ary(int argc, VALUE *argv, VALUE self) {
444
- query_ctx ctx = { self, argc, argv, 0 };
445
- return rb_ensure(safe_query_ary, (VALUE)&ctx, cleanup_stmt, (VALUE)&ctx);
446
- }
447
-
448
- VALUE safe_query_single_row(VALUE arg) {
449
- query_ctx *ctx = (query_ctx *)arg;
450
- Database_t *db;
451
- int column_count;
452
- VALUE sql;
453
- VALUE row = Qnil;
454
- VALUE column_names;
455
-
456
- check_arity_and_prepare_sql(ctx->argc, ctx->argv, sql);
457
- GetOpenDatabase(ctx->self, db);
458
-
459
- prepare_multi_stmt(db->sqlite3_db, &ctx->stmt, sql);
460
- bind_all_parameters(ctx->stmt, ctx->argc, ctx->argv);
461
- column_count = sqlite3_column_count(ctx->stmt);
462
- column_names = get_column_names(ctx->stmt, column_count);
463
-
464
- if (stmt_iterate(ctx->stmt, db->sqlite3_db))
465
- row = row_to_hash(ctx->stmt, column_count, column_names);
466
-
467
- RB_GC_GUARD(row);
468
- RB_GC_GUARD(column_names);
469
- return row;
470
- }
471
-
472
- /* call-seq: query_single_row(sql, *parameters)
473
- *
474
- * Runs a query returning a single row as a hash.
475
- *
476
- * Query parameters to be bound to placeholders in the query can be specified as
477
- * a list of values or as a hash mapping parameter names to values. When
478
- * parameters are given as a least, the query should specify parameters using
479
- * `?`:
480
- *
481
- * db.query_single_row('select * from foo where x = ?', 42)
482
- *
483
- * Named placeholders are specified using `:`. The placeholder values are
484
- * specified using a hash, where keys are either strings are symbols. String
485
- * keys can include or omit the `:` prefix. The following are equivalent:
486
- *
487
- * db.query_single_row('select * from foo where x = :bar', bar: 42)
488
- * db.query_single_row('select * from foo where x = :bar', 'bar' => 42)
489
- * db.query_single_row('select * from foo where x = :bar', ':bar' => 42)
490
- */
491
- VALUE Database_query_single_row(int argc, VALUE *argv, VALUE self) {
492
- query_ctx ctx = { self, argc, argv, 0 };
493
- return rb_ensure(safe_query_single_row, (VALUE)&ctx, cleanup_stmt, (VALUE)&ctx);
494
- }
495
-
496
- VALUE safe_query_single_column(VALUE arg) {
497
- query_ctx *ctx = (query_ctx *)arg;
498
-
499
- int column_count;
500
- Database_t *db;
501
- VALUE result = ctx->self;
502
- int yield_to_block = rb_block_given_p();
503
- VALUE sql;
504
- VALUE value;
505
-
506
- check_arity_and_prepare_sql(ctx->argc, ctx->argv, sql);
507
- GetOpenDatabase(ctx->self, db);
508
-
509
- prepare_multi_stmt(db->sqlite3_db, &ctx->stmt, sql);
510
- bind_all_parameters(ctx->stmt, ctx->argc, ctx->argv);
511
- column_count = sqlite3_column_count(ctx->stmt);
512
- if (column_count != 1)
513
- rb_raise(cError, "Expected query result to have 1 column");
514
-
515
- // block not given, so prepare the array of records to be returned
516
- if (!yield_to_block) result = rb_ary_new();
517
-
518
- while (stmt_iterate(ctx->stmt, db->sqlite3_db)) {
519
- value = get_column_value(ctx->stmt, 0, sqlite3_column_type(ctx->stmt, 0));
520
- if (yield_to_block) rb_yield(value); else rb_ary_push(result, value);
521
- }
522
-
523
- RB_GC_GUARD(value);
524
- RB_GC_GUARD(result);
525
- return result;
526
- }
527
-
528
- /* call-seq: query_single_column(sql, *parameters, &block)
529
- *
530
- * Runs a query returning single column values. If a block is given, it will be called
531
- * for each value. Otherwise, an array containing all values is returned.
532
- *
533
- * Query parameters to be bound to placeholders in the query can be specified as
534
- * a list of values or as a hash mapping parameter names to values. When
535
- * parameters are given as a least, the query should specify parameters using
536
- * `?`:
537
- *
538
- * db.query_single_column('select x from foo where x = ?', 42)
539
- *
540
- * Named placeholders are specified using `:`. The placeholder values are
541
- * specified using a hash, where keys are either strings are symbols. String
542
- * keys can include or omit the `:` prefix. The following are equivalent:
543
- *
544
- * db.query_single_column('select x from foo where x = :bar', bar: 42)
545
- * db.query_single_column('select x from foo where x = :bar', 'bar' => 42)
546
- * db.query_single_column('select x from foo where x = :bar', ':bar' => 42)
547
- */
548
- VALUE Database_query_single_column(int argc, VALUE *argv, VALUE self) {
549
- query_ctx ctx = { self, argc, argv, 0 };
550
- return rb_ensure(safe_query_single_column, (VALUE)&ctx, cleanup_stmt, (VALUE)&ctx);
551
- }
552
-
553
- VALUE safe_query_single_value(VALUE arg) {
554
- query_ctx *ctx = (query_ctx *)arg;
555
- int column_count;
556
- Database_t *db;
557
- VALUE sql;
558
- VALUE value = Qnil;
559
-
560
- check_arity_and_prepare_sql(ctx->argc, ctx->argv, sql);
561
- GetOpenDatabase(ctx->self, db);
562
-
563
- prepare_multi_stmt(db->sqlite3_db, &ctx->stmt, sql);
564
- bind_all_parameters(ctx->stmt, ctx->argc, ctx->argv);
565
- column_count = sqlite3_column_count(ctx->stmt);
566
- if (column_count != 1)
567
- rb_raise(cError, "Expected query result to have 1 column");
568
-
569
- if (stmt_iterate(ctx->stmt, db->sqlite3_db))
570
- value = get_column_value(ctx->stmt, 0, sqlite3_column_type(ctx->stmt, 0));
571
-
572
- RB_GC_GUARD(value);
573
- return value;
574
- }
575
-
576
- /* call-seq: query_single_value(sql, *parameters)
577
- *
578
- * Runs a query returning a single value from the first row.
579
- *
580
- * Query parameters to be bound to placeholders in the query can be specified as
581
- * a list of values or as a hash mapping parameter names to values. When
582
- * parameters are given as a least, the query should specify parameters using
583
- * `?`:
584
- *
585
- * db.query_single_value('select x from foo where x = ?', 42)
586
- *
587
- * Named placeholders are specified using `:`. The placeholder values are
588
- * specified using a hash, where keys are either strings are symbols. String
589
- * keys can include or omit the `:` prefix. The following are equivalent:
590
- *
591
- * db.query_single_value('select x from foo where x = :bar', bar: 42)
592
- * db.query_single_value('select x from foo where x = :bar', 'bar' => 42)
593
- * db.query_single_value('select x from foo where x = :bar', ':bar' => 42)
594
- */
595
- VALUE Database_query_single_value(int argc, VALUE *argv, VALUE self) {
596
- query_ctx ctx = { self, argc, argv, 0 };
597
- return rb_ensure(safe_query_single_value, (VALUE)&ctx, cleanup_stmt, (VALUE)&ctx);
598
- }
599
-
600
- /* call-seq: last_insert_rowid
601
- *
602
- * Returns the rowid of the last inserted row.
603
- */
604
- VALUE Database_last_insert_rowid(VALUE self) {
605
- Database_t *db;
606
- GetOpenDatabase(self, db);
607
-
608
- return INT2NUM(sqlite3_last_insert_rowid(db->sqlite3_db));
609
- }
610
-
611
- /* call-seq: changes
612
- *
613
- * Returns the number of changes made to the database by the last operation.
614
- */
615
- VALUE Database_changes(VALUE self) {
616
- Database_t *db;
617
- GetOpenDatabase(self, db);
618
-
619
- return INT2NUM(sqlite3_changes(db->sqlite3_db));
620
- }
621
-
622
- /* call-seq: filename
623
- *
624
- * Returns the database filename.
625
- */
626
- VALUE Database_filename(int argc, VALUE *argv, VALUE self) {
627
- const char *db_name;
628
- const char *filename;
629
- Database_t *db;
630
- GetOpenDatabase(self, db);
631
-
632
- rb_check_arity(argc, 0, 1);
633
- db_name = (argc == 1) ? StringValueCStr(argv[0]) : "main";
634
- filename = sqlite3_db_filename(db->sqlite3_db, db_name);
635
- return filename ? rb_str_new_cstr(filename) : Qnil;
636
- }
637
-
638
- /* call-seq: transaction_active?
639
- *
640
- * Returns true if a transaction is currently in progress.
641
- */
642
- VALUE Database_transaction_active_p(VALUE self) {
643
- Database_t *db;
644
- GetOpenDatabase(self, db);
645
-
646
- return sqlite3_get_autocommit(db->sqlite3_db) ? Qfalse : Qtrue;
647
- }
648
-
649
- /* call-seq: load_extension(path)
650
- *
651
- * Loads an extension with the given path.
652
- */
653
- VALUE Database_load_extension(VALUE self, VALUE path) {
654
- Database_t *db;
655
- GetOpenDatabase(self, db);
656
- char *err_msg;
657
-
658
- int rc = sqlite3_load_extension(db->sqlite3_db, RSTRING_PTR(path), 0, &err_msg);
659
- if (rc != SQLITE_OK) {
660
- VALUE error = rb_exc_new2(cError, err_msg);
661
- sqlite3_free(err_msg);
662
- rb_exc_raise(error);
663
- }
664
-
665
- return self;
666
- }
667
-
668
- void Init_Extralite() {
669
- VALUE mExtralite = rb_define_module("Extralite");
670
- rb_define_singleton_method(mExtralite, "sqlite3_version", Extralite_sqlite3_version, 0);
671
-
672
- VALUE cDatabase = rb_define_class_under(mExtralite, "Database", rb_cObject);
673
- rb_define_alloc_func(cDatabase, Database_allocate);
674
-
675
- rb_define_method(cDatabase, "initialize", Database_initialize, 1);
676
- rb_define_method(cDatabase, "close", Database_close, 0);
677
- rb_define_method(cDatabase, "closed?", Database_closed_p, 0);
678
-
679
- rb_define_method(cDatabase, "query", Database_query_hash, -1);
680
- rb_define_method(cDatabase, "query_hash", Database_query_hash, -1);
681
- rb_define_method(cDatabase, "query_ary", Database_query_ary, -1);
682
- rb_define_method(cDatabase, "query_single_row", Database_query_single_row, -1);
683
- rb_define_method(cDatabase, "query_single_column", Database_query_single_column, -1);
684
- rb_define_method(cDatabase, "query_single_value", Database_query_single_value, -1);
685
-
686
- rb_define_method(cDatabase, "last_insert_rowid", Database_last_insert_rowid, 0);
687
- rb_define_method(cDatabase, "changes", Database_changes, 0);
688
- rb_define_method(cDatabase, "filename", Database_filename, -1);
689
- rb_define_method(cDatabase, "transaction_active?", Database_transaction_active_p, 0);
690
- rb_define_method(cDatabase, "load_extension", Database_load_extension, 1);
691
-
692
- cError = rb_define_class_under(mExtralite, "Error", rb_eRuntimeError);
693
- cSQLError = rb_define_class_under(mExtralite, "SQLError", cError);
694
- cBusyError = rb_define_class_under(mExtralite, "BusyError", cError);
695
- rb_gc_register_mark_object(cError);
696
- rb_gc_register_mark_object(cSQLError);
697
- rb_gc_register_mark_object(cBusyError);
698
-
699
- ID_KEYS = rb_intern("keys");
700
- ID_STRIP = rb_intern("strip");
701
- ID_TO_S = rb_intern("to_s");
702
- }