sqlite3 2.0.0-aarch64-linux-musl

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.
@@ -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