sqlite3 2.0.0-x86_64-linux-musl

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,667 @@
1
+ #include <sqlite3_ruby.h>
2
+
3
+ #define REQUIRE_OPEN_STMT(_ctxt) \
4
+ if(!_ctxt->st) \
5
+ rb_raise(rb_path2class("SQLite3::Exception"), "cannot use a closed statement");
6
+
7
+ VALUE cSqlite3Statement;
8
+
9
+ static void
10
+ statement_deallocate(void *data)
11
+ {
12
+ sqlite3StmtRubyPtr s = (sqlite3StmtRubyPtr)data;
13
+
14
+ if (s->st) {
15
+ sqlite3_finalize(s->st);
16
+ }
17
+
18
+ xfree(data);
19
+ }
20
+
21
+ static size_t
22
+ statement_memsize(const void *data)
23
+ {
24
+ const sqlite3StmtRubyPtr s = (const sqlite3StmtRubyPtr)data;
25
+ // NB: can't account for s->st because the type is incomplete.
26
+ return sizeof(*s);
27
+ }
28
+
29
+ static const rb_data_type_t statement_type = {
30
+ "SQLite3::Backup",
31
+ {
32
+ NULL,
33
+ statement_deallocate,
34
+ statement_memsize,
35
+ },
36
+ 0,
37
+ 0,
38
+ RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED,
39
+ };
40
+
41
+ static VALUE
42
+ allocate(VALUE klass)
43
+ {
44
+ sqlite3StmtRubyPtr ctx;
45
+ return TypedData_Make_Struct(klass, sqlite3StmtRuby, &statement_type, ctx);
46
+ }
47
+
48
+ static VALUE
49
+ prepare(VALUE self, VALUE db, VALUE sql)
50
+ {
51
+ sqlite3RubyPtr db_ctx = sqlite3_database_unwrap(db);
52
+ sqlite3StmtRubyPtr ctx;
53
+ const char *tail = NULL;
54
+ int status;
55
+
56
+ StringValue(sql);
57
+
58
+ TypedData_Get_Struct(self, sqlite3StmtRuby, &statement_type, ctx);
59
+
60
+ #ifdef HAVE_SQLITE3_PREPARE_V2
61
+ status = sqlite3_prepare_v2(
62
+ #else
63
+ status = sqlite3_prepare(
64
+ #endif
65
+ db_ctx->db,
66
+ (const char *)StringValuePtr(sql),
67
+ (int)RSTRING_LEN(sql),
68
+ &ctx->st,
69
+ &tail
70
+ );
71
+
72
+ CHECK(db_ctx->db, status);
73
+ timespecclear(&db_ctx->stmt_deadline);
74
+
75
+ return rb_str_new2(tail);
76
+ }
77
+
78
+ /* call-seq: stmt.close
79
+ *
80
+ * Closes the statement by finalizing the underlying statement
81
+ * handle. The statement must not be used after being closed.
82
+ */
83
+ static VALUE
84
+ sqlite3_rb_close(VALUE self)
85
+ {
86
+ sqlite3StmtRubyPtr ctx;
87
+
88
+ TypedData_Get_Struct(self, sqlite3StmtRuby, &statement_type, ctx);
89
+
90
+ REQUIRE_OPEN_STMT(ctx);
91
+
92
+ sqlite3_finalize(ctx->st);
93
+ ctx->st = NULL;
94
+
95
+ return self;
96
+ }
97
+
98
+ /* call-seq: stmt.closed?
99
+ *
100
+ * Returns true if the statement has been closed.
101
+ */
102
+ static VALUE
103
+ closed_p(VALUE self)
104
+ {
105
+ sqlite3StmtRubyPtr ctx;
106
+ TypedData_Get_Struct(self, sqlite3StmtRuby, &statement_type, ctx);
107
+
108
+ if (!ctx->st) { return Qtrue; }
109
+
110
+ return Qfalse;
111
+ }
112
+
113
+ static VALUE
114
+ step(VALUE self)
115
+ {
116
+ sqlite3StmtRubyPtr ctx;
117
+ sqlite3_stmt *stmt;
118
+ int value, length;
119
+ VALUE list;
120
+ rb_encoding *internal_encoding;
121
+
122
+ TypedData_Get_Struct(self, sqlite3StmtRuby, &statement_type, ctx);
123
+
124
+ REQUIRE_OPEN_STMT(ctx);
125
+
126
+ if (ctx->done_p) { return Qnil; }
127
+
128
+ internal_encoding = rb_default_internal_encoding();
129
+
130
+ stmt = ctx->st;
131
+
132
+ value = sqlite3_step(stmt);
133
+ if (rb_errinfo() != Qnil) {
134
+ /* some user defined function was invoked as a callback during step and
135
+ * it raised an exception that has been suppressed until step returns.
136
+ * Now re-raise it. */
137
+ VALUE exception = rb_errinfo();
138
+ rb_set_errinfo(Qnil);
139
+ rb_exc_raise(exception);
140
+ }
141
+
142
+ length = sqlite3_column_count(stmt);
143
+ list = rb_ary_new2((long)length);
144
+
145
+ switch (value) {
146
+ case SQLITE_ROW: {
147
+ int i;
148
+ for (i = 0; i < length; i++) {
149
+ VALUE val;
150
+
151
+ switch (sqlite3_column_type(stmt, i)) {
152
+ case SQLITE_INTEGER:
153
+ val = LL2NUM(sqlite3_column_int64(stmt, i));
154
+ break;
155
+ case SQLITE_FLOAT:
156
+ val = rb_float_new(sqlite3_column_double(stmt, i));
157
+ break;
158
+ case SQLITE_TEXT: {
159
+ val = rb_utf8_str_new(
160
+ (const char *)sqlite3_column_text(stmt, i),
161
+ (long)sqlite3_column_bytes(stmt, i)
162
+ );
163
+ if (internal_encoding) {
164
+ val = rb_str_export_to_enc(val, internal_encoding);
165
+ }
166
+ rb_obj_freeze(val);
167
+ }
168
+ break;
169
+ case SQLITE_BLOB: {
170
+ val = rb_str_new(
171
+ (const char *)sqlite3_column_blob(stmt, i),
172
+ (long)sqlite3_column_bytes(stmt, i)
173
+ );
174
+ rb_obj_freeze(val);
175
+ }
176
+ break;
177
+ case SQLITE_NULL:
178
+ val = Qnil;
179
+ break;
180
+ default:
181
+ rb_raise(rb_eRuntimeError, "bad type");
182
+ }
183
+
184
+ rb_ary_store(list, (long)i, val);
185
+ }
186
+ }
187
+ break;
188
+ case SQLITE_DONE:
189
+ ctx->done_p = 1;
190
+ return Qnil;
191
+ break;
192
+ default:
193
+ sqlite3_reset(stmt);
194
+ ctx->done_p = 0;
195
+ CHECK(sqlite3_db_handle(ctx->st), value);
196
+ }
197
+
198
+ rb_obj_freeze(list);
199
+
200
+ return list;
201
+ }
202
+
203
+ /* call-seq: stmt.bind_param(key, value)
204
+ *
205
+ * Binds value to the named (or positional) placeholder. If +param+ is a
206
+ * Fixnum, it is treated as an index for a positional placeholder.
207
+ * Otherwise it is used as the name of the placeholder to bind to.
208
+ *
209
+ * See also #bind_params.
210
+ */
211
+ static VALUE
212
+ bind_param(VALUE self, VALUE key, VALUE value)
213
+ {
214
+ sqlite3StmtRubyPtr ctx;
215
+ int status;
216
+ int index;
217
+
218
+ TypedData_Get_Struct(self, sqlite3StmtRuby, &statement_type, ctx);
219
+ REQUIRE_OPEN_STMT(ctx);
220
+
221
+ switch (TYPE(key)) {
222
+ case T_SYMBOL:
223
+ key = rb_funcall(key, rb_intern("to_s"), 0);
224
+ case T_STRING:
225
+ if (RSTRING_PTR(key)[0] != ':') { key = rb_str_plus(rb_str_new2(":"), key); }
226
+ index = sqlite3_bind_parameter_index(ctx->st, StringValuePtr(key));
227
+ break;
228
+ default:
229
+ index = (int)NUM2INT(key);
230
+ }
231
+
232
+ if (index == 0) {
233
+ rb_raise(rb_path2class("SQLite3::Exception"), "no such bind parameter");
234
+ }
235
+
236
+ switch (TYPE(value)) {
237
+ case T_STRING:
238
+ if (CLASS_OF(value) == cSqlite3Blob
239
+ || rb_enc_get_index(value) == rb_ascii8bit_encindex()
240
+ ) {
241
+ status = sqlite3_bind_blob(
242
+ ctx->st,
243
+ index,
244
+ (const char *)StringValuePtr(value),
245
+ (int)RSTRING_LEN(value),
246
+ SQLITE_TRANSIENT
247
+ );
248
+ } else {
249
+
250
+
251
+ if (UTF16_LE_P(value) || UTF16_BE_P(value)) {
252
+ status = sqlite3_bind_text16(
253
+ ctx->st,
254
+ index,
255
+ (const char *)StringValuePtr(value),
256
+ (int)RSTRING_LEN(value),
257
+ SQLITE_TRANSIENT
258
+ );
259
+ } else {
260
+ if (!UTF8_P(value) || !USASCII_P(value)) {
261
+ value = rb_str_encode(value, rb_enc_from_encoding(rb_utf8_encoding()), 0, Qnil);
262
+ }
263
+ status = sqlite3_bind_text(
264
+ ctx->st,
265
+ index,
266
+ (const char *)StringValuePtr(value),
267
+ (int)RSTRING_LEN(value),
268
+ SQLITE_TRANSIENT
269
+ );
270
+ }
271
+ }
272
+ break;
273
+ case T_BIGNUM: {
274
+ sqlite3_int64 num64;
275
+ if (bignum_to_int64(value, &num64)) {
276
+ status = sqlite3_bind_int64(ctx->st, index, num64);
277
+ break;
278
+ }
279
+ }
280
+ case T_FLOAT:
281
+ status = sqlite3_bind_double(ctx->st, index, NUM2DBL(value));
282
+ break;
283
+ case T_FIXNUM:
284
+ status = sqlite3_bind_int64(ctx->st, index, (sqlite3_int64)FIX2LONG(value));
285
+ break;
286
+ case T_NIL:
287
+ status = sqlite3_bind_null(ctx->st, index);
288
+ break;
289
+ default:
290
+ rb_raise(rb_eRuntimeError, "can't prepare %s",
291
+ rb_class2name(CLASS_OF(value)));
292
+ break;
293
+ }
294
+
295
+ CHECK(sqlite3_db_handle(ctx->st), status);
296
+
297
+ return self;
298
+ }
299
+
300
+ /* call-seq: stmt.reset!
301
+ *
302
+ * Resets the statement. This is typically done internally, though it might
303
+ * occasionally be necessary to manually reset the statement.
304
+ */
305
+ static VALUE
306
+ reset_bang(VALUE self)
307
+ {
308
+ sqlite3StmtRubyPtr ctx;
309
+
310
+ TypedData_Get_Struct(self, sqlite3StmtRuby, &statement_type, ctx);
311
+ REQUIRE_OPEN_STMT(ctx);
312
+
313
+ sqlite3_reset(ctx->st);
314
+
315
+ ctx->done_p = 0;
316
+
317
+ return self;
318
+ }
319
+
320
+ /* call-seq: stmt.clear_bindings!
321
+ *
322
+ * Resets the statement. This is typically done internally, though it might
323
+ * occasionally be necessary to manually reset the statement.
324
+ */
325
+ static VALUE
326
+ clear_bindings_bang(VALUE self)
327
+ {
328
+ sqlite3StmtRubyPtr ctx;
329
+
330
+ TypedData_Get_Struct(self, sqlite3StmtRuby, &statement_type, ctx);
331
+ REQUIRE_OPEN_STMT(ctx);
332
+
333
+ sqlite3_clear_bindings(ctx->st);
334
+
335
+ ctx->done_p = 0;
336
+
337
+ return self;
338
+ }
339
+
340
+ /* call-seq: stmt.done?
341
+ *
342
+ * returns true if all rows have been returned.
343
+ */
344
+ static VALUE
345
+ done_p(VALUE self)
346
+ {
347
+ sqlite3StmtRubyPtr ctx;
348
+ TypedData_Get_Struct(self, sqlite3StmtRuby, &statement_type, ctx);
349
+
350
+ if (ctx->done_p) { return Qtrue; }
351
+ return Qfalse;
352
+ }
353
+
354
+ /* call-seq: stmt.column_count
355
+ *
356
+ * Returns the number of columns to be returned for this statement
357
+ */
358
+ static VALUE
359
+ column_count(VALUE self)
360
+ {
361
+ sqlite3StmtRubyPtr ctx;
362
+ TypedData_Get_Struct(self, sqlite3StmtRuby, &statement_type, ctx);
363
+ REQUIRE_OPEN_STMT(ctx);
364
+
365
+ return INT2NUM(sqlite3_column_count(ctx->st));
366
+ }
367
+
368
+ #if HAVE_RB_ENC_INTERNED_STR_CSTR
369
+ static VALUE
370
+ interned_utf8_cstr(const char *str)
371
+ {
372
+ return rb_enc_interned_str_cstr(str, rb_utf8_encoding());
373
+ }
374
+ #else
375
+ static VALUE
376
+ interned_utf8_cstr(const char *str)
377
+ {
378
+ VALUE rb_str = rb_utf8_str_new_cstr(str);
379
+ return rb_funcall(rb_str, rb_intern("-@"), 0);
380
+ }
381
+ #endif
382
+
383
+ /* call-seq: stmt.column_name(index)
384
+ *
385
+ * Get the column name at +index+. 0 based.
386
+ */
387
+ static VALUE
388
+ column_name(VALUE self, VALUE index)
389
+ {
390
+ sqlite3StmtRubyPtr ctx;
391
+ const char *name;
392
+
393
+ TypedData_Get_Struct(self, sqlite3StmtRuby, &statement_type, ctx);
394
+ REQUIRE_OPEN_STMT(ctx);
395
+
396
+ name = sqlite3_column_name(ctx->st, (int)NUM2INT(index));
397
+
398
+ VALUE ret = Qnil;
399
+
400
+ if (name) {
401
+ ret = interned_utf8_cstr(name);
402
+ }
403
+ return ret;
404
+ }
405
+
406
+ /* call-seq: stmt.column_decltype(index)
407
+ *
408
+ * Get the column type at +index+. 0 based.
409
+ */
410
+ static VALUE
411
+ column_decltype(VALUE self, VALUE index)
412
+ {
413
+ sqlite3StmtRubyPtr ctx;
414
+ const char *name;
415
+
416
+ TypedData_Get_Struct(self, sqlite3StmtRuby, &statement_type, ctx);
417
+ REQUIRE_OPEN_STMT(ctx);
418
+
419
+ name = sqlite3_column_decltype(ctx->st, (int)NUM2INT(index));
420
+
421
+ if (name) { return rb_str_new2(name); }
422
+ return Qnil;
423
+ }
424
+
425
+ /* call-seq: stmt.bind_parameter_count
426
+ *
427
+ * Return the number of bind parameters
428
+ */
429
+ static VALUE
430
+ bind_parameter_count(VALUE self)
431
+ {
432
+ sqlite3StmtRubyPtr ctx;
433
+ TypedData_Get_Struct(self, sqlite3StmtRuby, &statement_type, ctx);
434
+ REQUIRE_OPEN_STMT(ctx);
435
+
436
+ return INT2NUM(sqlite3_bind_parameter_count(ctx->st));
437
+ }
438
+
439
+ enum stmt_stat_sym {
440
+ stmt_stat_sym_fullscan_steps,
441
+ stmt_stat_sym_sorts,
442
+ stmt_stat_sym_autoindexes,
443
+ stmt_stat_sym_vm_steps,
444
+ #ifdef SQLITE_STMTSTATUS_REPREPARE
445
+ stmt_stat_sym_reprepares,
446
+ #endif
447
+ #ifdef SQLITE_STMTSTATUS_RUN
448
+ stmt_stat_sym_runs,
449
+ #endif
450
+ #ifdef SQLITE_STMTSTATUS_FILTER_MISS
451
+ stmt_stat_sym_filter_misses,
452
+ #endif
453
+ #ifdef SQLITE_STMTSTATUS_FILTER_HIT
454
+ stmt_stat_sym_filter_hits,
455
+ #endif
456
+ stmt_stat_sym_last
457
+ };
458
+
459
+ static VALUE stmt_stat_symbols[stmt_stat_sym_last];
460
+
461
+ static void
462
+ setup_stmt_stat_symbols(void)
463
+ {
464
+ if (stmt_stat_symbols[0] == 0) {
465
+ #define S(s) stmt_stat_symbols[stmt_stat_sym_##s] = ID2SYM(rb_intern_const(#s))
466
+ S(fullscan_steps);
467
+ S(sorts);
468
+ S(autoindexes);
469
+ S(vm_steps);
470
+ #ifdef SQLITE_STMTSTATUS_REPREPARE
471
+ S(reprepares);
472
+ #endif
473
+ #ifdef SQLITE_STMTSTATUS_RUN
474
+ S(runs);
475
+ #endif
476
+ #ifdef SQLITE_STMTSTATUS_FILTER_MISS
477
+ S(filter_misses);
478
+ #endif
479
+ #ifdef SQLITE_STMTSTATUS_FILTER_HIT
480
+ S(filter_hits);
481
+ #endif
482
+ #undef S
483
+ }
484
+ }
485
+
486
+ static size_t
487
+ stmt_stat_internal(VALUE hash_or_sym, sqlite3_stmt *stmt)
488
+ {
489
+ VALUE hash = Qnil, key = Qnil;
490
+
491
+ setup_stmt_stat_symbols();
492
+
493
+ if (RB_TYPE_P(hash_or_sym, T_HASH)) {
494
+ hash = hash_or_sym;
495
+ } else if (SYMBOL_P(hash_or_sym)) {
496
+ key = hash_or_sym;
497
+ } else {
498
+ rb_raise(rb_eTypeError, "non-hash or symbol argument");
499
+ }
500
+
501
+ #define SET(name, stat_type) \
502
+ if (key == stmt_stat_symbols[stmt_stat_sym_##name]) \
503
+ return sqlite3_stmt_status(stmt, stat_type, 0); \
504
+ else if (hash != Qnil) \
505
+ rb_hash_aset(hash, stmt_stat_symbols[stmt_stat_sym_##name], SIZET2NUM(sqlite3_stmt_status(stmt, stat_type, 0)));
506
+
507
+ SET(fullscan_steps, SQLITE_STMTSTATUS_FULLSCAN_STEP);
508
+ SET(sorts, SQLITE_STMTSTATUS_SORT);
509
+ SET(autoindexes, SQLITE_STMTSTATUS_AUTOINDEX);
510
+ SET(vm_steps, SQLITE_STMTSTATUS_VM_STEP);
511
+ #ifdef SQLITE_STMTSTATUS_REPREPARE
512
+ SET(reprepares, SQLITE_STMTSTATUS_REPREPARE);
513
+ #endif
514
+ #ifdef SQLITE_STMTSTATUS_RUN
515
+ SET(runs, SQLITE_STMTSTATUS_RUN);
516
+ #endif
517
+ #ifdef SQLITE_STMTSTATUS_FILTER_MISS
518
+ SET(filter_misses, SQLITE_STMTSTATUS_FILTER_MISS);
519
+ #endif
520
+ #ifdef SQLITE_STMTSTATUS_FILTER_HIT
521
+ SET(filter_hits, SQLITE_STMTSTATUS_FILTER_HIT);
522
+ #endif
523
+ #undef SET
524
+
525
+ if (!NIL_P(key)) { /* matched key should return above */
526
+ rb_raise(rb_eArgError, "unknown key: %"PRIsVALUE, rb_sym2str(key));
527
+ }
528
+
529
+ return 0;
530
+ }
531
+
532
+ /* call-seq: stmt.stats_as_hash(hash)
533
+ *
534
+ * Returns a Hash containing information about the statement.
535
+ */
536
+ static VALUE
537
+ stats_as_hash(VALUE self)
538
+ {
539
+ sqlite3StmtRubyPtr ctx;
540
+ TypedData_Get_Struct(self, sqlite3StmtRuby, &statement_type, ctx);
541
+ REQUIRE_OPEN_STMT(ctx);
542
+ VALUE arg = rb_hash_new();
543
+
544
+ stmt_stat_internal(arg, ctx->st);
545
+ return arg;
546
+ }
547
+
548
+ /* call-seq: stmt.stmt_stat(hash_or_key)
549
+ *
550
+ * Returns a Hash containing information about the statement.
551
+ */
552
+ static VALUE
553
+ stat_for(VALUE self, VALUE key)
554
+ {
555
+ sqlite3StmtRubyPtr ctx;
556
+ TypedData_Get_Struct(self, sqlite3StmtRuby, &statement_type, ctx);
557
+ REQUIRE_OPEN_STMT(ctx);
558
+
559
+ if (SYMBOL_P(key)) {
560
+ size_t value = stmt_stat_internal(key, ctx->st);
561
+ return SIZET2NUM(value);
562
+ } else {
563
+ rb_raise(rb_eTypeError, "non-symbol given");
564
+ }
565
+ }
566
+
567
+ #ifdef SQLITE_STMTSTATUS_MEMUSED
568
+ /* call-seq: stmt.memory_used
569
+ *
570
+ * Return the approximate number of bytes of heap memory used to store the prepared statement
571
+ */
572
+ static VALUE
573
+ memused(VALUE self)
574
+ {
575
+ sqlite3StmtRubyPtr ctx;
576
+ TypedData_Get_Struct(self, sqlite3StmtRuby, &statement_type, ctx);
577
+ REQUIRE_OPEN_STMT(ctx);
578
+
579
+ return INT2NUM(sqlite3_stmt_status(ctx->st, SQLITE_STMTSTATUS_MEMUSED, 0));
580
+ }
581
+ #endif
582
+
583
+ #ifdef HAVE_SQLITE3_COLUMN_DATABASE_NAME
584
+
585
+ /* call-seq: stmt.database_name(column_index)
586
+ *
587
+ * Return the database name for the column at +column_index+
588
+ */
589
+ static VALUE
590
+ database_name(VALUE self, VALUE index)
591
+ {
592
+ sqlite3StmtRubyPtr ctx;
593
+ TypedData_Get_Struct(self, sqlite3StmtRuby, &statement_type, ctx);
594
+ REQUIRE_OPEN_STMT(ctx);
595
+
596
+ return SQLITE3_UTF8_STR_NEW2(
597
+ sqlite3_column_database_name(ctx->st, NUM2INT(index)));
598
+ }
599
+
600
+ #endif
601
+
602
+ /* call-seq: stmt.sql
603
+ *
604
+ * Returns the SQL statement used to create this prepared statement
605
+ */
606
+ static VALUE
607
+ get_sql(VALUE self)
608
+ {
609
+ sqlite3StmtRubyPtr ctx;
610
+ TypedData_Get_Struct(self, sqlite3StmtRuby, &statement_type, ctx);
611
+ REQUIRE_OPEN_STMT(ctx);
612
+
613
+ return rb_obj_freeze(SQLITE3_UTF8_STR_NEW2(sqlite3_sql(ctx->st)));
614
+ }
615
+
616
+ /* call-seq: stmt.expanded_sql
617
+ *
618
+ * Returns the SQL statement used to create this prepared statement, but
619
+ * with bind parameters substituted in to the statement.
620
+ */
621
+ static VALUE
622
+ get_expanded_sql(VALUE self)
623
+ {
624
+ sqlite3StmtRubyPtr ctx;
625
+ char *expanded_sql;
626
+ VALUE rb_expanded_sql;
627
+
628
+ TypedData_Get_Struct(self, sqlite3StmtRuby, &statement_type, ctx);
629
+ REQUIRE_OPEN_STMT(ctx);
630
+
631
+ expanded_sql = sqlite3_expanded_sql(ctx->st);
632
+ rb_expanded_sql = rb_obj_freeze(SQLITE3_UTF8_STR_NEW2(expanded_sql));
633
+ sqlite3_free(expanded_sql);
634
+
635
+ return rb_expanded_sql;
636
+ }
637
+
638
+ void
639
+ init_sqlite3_statement(void)
640
+ {
641
+ cSqlite3Statement = rb_define_class_under(mSqlite3, "Statement", rb_cObject);
642
+
643
+ rb_define_alloc_func(cSqlite3Statement, allocate);
644
+ rb_define_method(cSqlite3Statement, "close", sqlite3_rb_close, 0);
645
+ rb_define_method(cSqlite3Statement, "closed?", closed_p, 0);
646
+ rb_define_method(cSqlite3Statement, "bind_param", bind_param, 2);
647
+ rb_define_method(cSqlite3Statement, "reset!", reset_bang, 0);
648
+ rb_define_method(cSqlite3Statement, "clear_bindings!", clear_bindings_bang, 0);
649
+ rb_define_method(cSqlite3Statement, "step", step, 0);
650
+ rb_define_method(cSqlite3Statement, "done?", done_p, 0);
651
+ rb_define_method(cSqlite3Statement, "column_count", column_count, 0);
652
+ rb_define_method(cSqlite3Statement, "column_name", column_name, 1);
653
+ rb_define_method(cSqlite3Statement, "column_decltype", column_decltype, 1);
654
+ rb_define_method(cSqlite3Statement, "bind_parameter_count", bind_parameter_count, 0);
655
+ rb_define_method(cSqlite3Statement, "sql", get_sql, 0);
656
+ rb_define_method(cSqlite3Statement, "expanded_sql", get_expanded_sql, 0);
657
+ #ifdef HAVE_SQLITE3_COLUMN_DATABASE_NAME
658
+ rb_define_method(cSqlite3Statement, "database_name", database_name, 1);
659
+ #endif
660
+ #ifdef SQLITE_STMTSTATUS_MEMUSED
661
+ rb_define_method(cSqlite3Statement, "memused", memused, 0);
662
+ #endif
663
+
664
+ rb_define_private_method(cSqlite3Statement, "prepare", prepare, 2);
665
+ rb_define_private_method(cSqlite3Statement, "stats_as_hash", stats_as_hash, 0);
666
+ rb_define_private_method(cSqlite3Statement, "stat_for", stat_for, 1);
667
+ }
@@ -0,0 +1,16 @@
1
+ #ifndef SQLITE3_STATEMENT_RUBY
2
+ #define SQLITE3_STATEMENT_RUBY
3
+
4
+ #include <sqlite3_ruby.h>
5
+
6
+ struct _sqlite3StmtRuby {
7
+ sqlite3_stmt *st;
8
+ int done_p;
9
+ };
10
+
11
+ typedef struct _sqlite3StmtRuby sqlite3StmtRuby;
12
+ typedef sqlite3StmtRuby *sqlite3StmtRubyPtr;
13
+
14
+ void init_sqlite3_statement();
15
+
16
+ #endif
@@ -0,0 +1,20 @@
1
+ #define timespecclear(tsp) (tsp)->tv_sec = (tsp)->tv_nsec = 0
2
+ #define timespecisset(tsp) ((tsp)->tv_sec || (tsp)->tv_nsec)
3
+ #define timespecisvalid(tsp) \
4
+ ((tsp)->tv_nsec >= 0 && (tsp)->tv_nsec < 1000000000L)
5
+ #define timespeccmp(tsp, usp, cmp) \
6
+ (((tsp)->tv_sec == (usp)->tv_sec) ? \
7
+ ((tsp)->tv_nsec cmp (usp)->tv_nsec) : \
8
+ ((tsp)->tv_sec cmp (usp)->tv_sec))
9
+ #define timespecsub(tsp, usp, vsp) \
10
+ do { \
11
+ (vsp)->tv_sec = (tsp)->tv_sec - (usp)->tv_sec; \
12
+ (vsp)->tv_nsec = (tsp)->tv_nsec - (usp)->tv_nsec; \
13
+ if ((vsp)->tv_nsec < 0) { \
14
+ (vsp)->tv_sec--; \
15
+ (vsp)->tv_nsec += 1000000000L; \
16
+ } \
17
+ } while (0)
18
+ #define timespecafter(tsp, usp) \
19
+ (((tsp)->tv_sec > (usp)->tv_sec) || \
20
+ ((tsp)->tv_sec == (usp)->tv_sec && (tsp)->tv_nsec > (usp)->tv_nsec))
Binary file
Binary file
Binary file
Binary file