sqlite3-static 3.12.2

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,52 @@
1
+ #ifndef SQLITE3_RUBY
2
+ #define SQLITE3_RUBY
3
+
4
+ #include <ruby.h>
5
+
6
+ #ifdef UNUSED
7
+ #elif defined(__GNUC__)
8
+ # define UNUSED(x) UNUSED_ ## x __attribute__((unused))
9
+ #elif defined(__LCLINT__)
10
+ # define UNUSED(x) /*@unused@*/ x
11
+ #else
12
+ # define UNUSED(x) x
13
+ #endif
14
+
15
+ #ifdef HAVE_RUBY_ENCODING_H
16
+ #include <ruby/encoding.h>
17
+
18
+ #define USASCII_P(_obj) (rb_enc_get_index(_obj) == rb_usascii_encindex())
19
+ #define UTF8_P(_obj) (rb_enc_get_index(_obj) == rb_utf8_encindex())
20
+ #define UTF16_LE_P(_obj) (rb_enc_get_index(_obj) == rb_enc_find_index("UTF-16LE"))
21
+ #define UTF16_BE_P(_obj) (rb_enc_get_index(_obj) == rb_enc_find_index("UTF-16BE"))
22
+ #define SQLITE3_UTF8_STR_NEW2(_obj) \
23
+ (rb_enc_associate_index(rb_str_new2(_obj), rb_utf8_encindex()))
24
+
25
+ #else
26
+
27
+ #define SQLITE3_UTF8_STR_NEW2(_obj) (rb_str_new2(_obj))
28
+
29
+ #endif
30
+
31
+
32
+ #include "sqlite3.h"
33
+
34
+ #ifndef HAVE_TYPE_SQLITE3_INT64
35
+ typedef sqlite_int64 sqlite3_int64;
36
+ #endif
37
+
38
+ #ifndef HAVE_TYPE_SQLITE3_UINT64
39
+ typedef sqlite_uint64 sqlite3_uint64;
40
+ #endif
41
+
42
+ extern VALUE mSqlite3;
43
+ extern VALUE cSqlite3Blob;
44
+
45
+ #include <database.h>
46
+ #include <statement.h>
47
+ #include <exception.h>
48
+ #include <backup.h>
49
+
50
+ int bignum_to_int64(VALUE big, sqlite3_int64 *result);
51
+
52
+ #endif
@@ -0,0 +1,447 @@
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 deallocate(void * ctx)
10
+ {
11
+ sqlite3StmtRubyPtr c = (sqlite3StmtRubyPtr)ctx;
12
+ xfree(c);
13
+ }
14
+
15
+ static VALUE allocate(VALUE klass)
16
+ {
17
+ sqlite3StmtRubyPtr ctx = xcalloc((size_t)1, sizeof(sqlite3StmtRuby));
18
+ ctx->st = NULL;
19
+ ctx->done_p = 0;
20
+
21
+ return Data_Wrap_Struct(klass, NULL, deallocate, ctx);
22
+ }
23
+
24
+ /* call-seq: SQLite3::Statement.new(db, sql)
25
+ *
26
+ * Create a new statement attached to the given Database instance, and which
27
+ * encapsulates the given SQL text. If the text contains more than one
28
+ * statement (i.e., separated by semicolons), then the #remainder property
29
+ * will be set to the trailing text.
30
+ */
31
+ static VALUE initialize(VALUE self, VALUE db, VALUE sql)
32
+ {
33
+ sqlite3RubyPtr db_ctx;
34
+ sqlite3StmtRubyPtr ctx;
35
+ const char *tail = NULL;
36
+ int status;
37
+
38
+ StringValue(sql);
39
+
40
+ Data_Get_Struct(db, sqlite3Ruby, db_ctx);
41
+ Data_Get_Struct(self, sqlite3StmtRuby, ctx);
42
+
43
+ if(!db_ctx->db)
44
+ rb_raise(rb_eArgError, "prepare called on a closed database");
45
+
46
+ #ifdef HAVE_RUBY_ENCODING_H
47
+ if(!UTF8_P(sql)) {
48
+ sql = rb_str_export_to_enc(sql, rb_utf8_encoding());
49
+ }
50
+ #endif
51
+
52
+ #ifdef HAVE_SQLITE3_PREPARE_V2
53
+ status = sqlite3_prepare_v2(
54
+ #else
55
+ status = sqlite3_prepare(
56
+ #endif
57
+ db_ctx->db,
58
+ (const char *)StringValuePtr(sql),
59
+ (int)RSTRING_LEN(sql),
60
+ &ctx->st,
61
+ &tail
62
+ );
63
+
64
+ CHECK(db_ctx->db, status);
65
+
66
+ rb_iv_set(self, "@connection", db);
67
+ rb_iv_set(self, "@remainder", rb_str_new2(tail));
68
+ rb_iv_set(self, "@columns", Qnil);
69
+ rb_iv_set(self, "@types", Qnil);
70
+
71
+ return self;
72
+ }
73
+
74
+ /* call-seq: stmt.close
75
+ *
76
+ * Closes the statement by finalizing the underlying statement
77
+ * handle. The statement must not be used after being closed.
78
+ */
79
+ static VALUE sqlite3_rb_close(VALUE self)
80
+ {
81
+ sqlite3StmtRubyPtr ctx;
82
+
83
+ Data_Get_Struct(self, sqlite3StmtRuby, ctx);
84
+
85
+ REQUIRE_OPEN_STMT(ctx);
86
+
87
+ sqlite3_finalize(ctx->st);
88
+ ctx->st = NULL;
89
+
90
+ return self;
91
+ }
92
+
93
+ /* call-seq: stmt.closed?
94
+ *
95
+ * Returns true if the statement has been closed.
96
+ */
97
+ static VALUE closed_p(VALUE self)
98
+ {
99
+ sqlite3StmtRubyPtr ctx;
100
+ Data_Get_Struct(self, sqlite3StmtRuby, ctx);
101
+
102
+ if(!ctx->st) return Qtrue;
103
+
104
+ return Qfalse;
105
+ }
106
+
107
+ static VALUE step(VALUE self)
108
+ {
109
+ sqlite3StmtRubyPtr ctx;
110
+ sqlite3_stmt *stmt;
111
+ int value, length;
112
+ VALUE list;
113
+ #ifdef HAVE_RUBY_ENCODING_H
114
+ rb_encoding * internal_encoding;
115
+ #endif
116
+
117
+ Data_Get_Struct(self, sqlite3StmtRuby, ctx);
118
+
119
+ REQUIRE_OPEN_STMT(ctx);
120
+
121
+ if(ctx->done_p) return Qnil;
122
+
123
+ #ifdef HAVE_RUBY_ENCODING_H
124
+ {
125
+ VALUE db = rb_iv_get(self, "@connection");
126
+ rb_funcall(db, rb_intern("encoding"), 0);
127
+ internal_encoding = rb_default_internal_encoding();
128
+ }
129
+ #endif
130
+
131
+ stmt = ctx->st;
132
+
133
+ value = sqlite3_step(stmt);
134
+ length = sqlite3_column_count(stmt);
135
+ list = rb_ary_new2((long)length);
136
+
137
+ switch(value) {
138
+ case SQLITE_ROW:
139
+ {
140
+ int i;
141
+ for(i = 0; i < length; i++) {
142
+ switch(sqlite3_column_type(stmt, i)) {
143
+ case SQLITE_INTEGER:
144
+ rb_ary_push(list, LL2NUM(sqlite3_column_int64(stmt, i)));
145
+ break;
146
+ case SQLITE_FLOAT:
147
+ rb_ary_push(list, rb_float_new(sqlite3_column_double(stmt, i)));
148
+ break;
149
+ case SQLITE_TEXT:
150
+ {
151
+ VALUE str = rb_tainted_str_new(
152
+ (const char *)sqlite3_column_text(stmt, i),
153
+ (long)sqlite3_column_bytes(stmt, i)
154
+ );
155
+ #ifdef HAVE_RUBY_ENCODING_H
156
+ rb_enc_associate_index(str, rb_utf8_encindex());
157
+ if(internal_encoding)
158
+ str = rb_str_export_to_enc(str, internal_encoding);
159
+ #endif
160
+ rb_ary_push(list, str);
161
+ }
162
+ break;
163
+ case SQLITE_BLOB:
164
+ {
165
+ VALUE str = rb_tainted_str_new(
166
+ (const char *)sqlite3_column_blob(stmt, i),
167
+ (long)sqlite3_column_bytes(stmt, i)
168
+ );
169
+ rb_ary_push(list, str);
170
+ }
171
+ break;
172
+ case SQLITE_NULL:
173
+ rb_ary_push(list, Qnil);
174
+ break;
175
+ default:
176
+ rb_raise(rb_eRuntimeError, "bad type");
177
+ }
178
+ }
179
+ }
180
+ break;
181
+ case SQLITE_DONE:
182
+ ctx->done_p = 1;
183
+ return Qnil;
184
+ break;
185
+ default:
186
+ sqlite3_reset(stmt);
187
+ ctx->done_p = 0;
188
+ CHECK(sqlite3_db_handle(ctx->st), value);
189
+ }
190
+
191
+ return list;
192
+ }
193
+
194
+ /* call-seq: stmt.bind_param(key, value)
195
+ *
196
+ * Binds value to the named (or positional) placeholder. If +param+ is a
197
+ * Fixnum, it is treated as an index for a positional placeholder.
198
+ * Otherwise it is used as the name of the placeholder to bind to.
199
+ *
200
+ * See also #bind_params.
201
+ */
202
+ static VALUE bind_param(VALUE self, VALUE key, VALUE value)
203
+ {
204
+ sqlite3StmtRubyPtr ctx;
205
+ int status;
206
+ int index;
207
+
208
+ Data_Get_Struct(self, sqlite3StmtRuby, ctx);
209
+ REQUIRE_OPEN_STMT(ctx);
210
+
211
+ switch(TYPE(key)) {
212
+ case T_SYMBOL:
213
+ key = rb_funcall(key, rb_intern("to_s"), 0);
214
+ case T_STRING:
215
+ if(RSTRING_PTR(key)[0] != ':') key = rb_str_plus(rb_str_new2(":"), key);
216
+ index = sqlite3_bind_parameter_index(ctx->st, StringValuePtr(key));
217
+ break;
218
+ default:
219
+ index = (int)NUM2INT(key);
220
+ }
221
+
222
+ if(index == 0)
223
+ rb_raise(rb_path2class("SQLite3::Exception"), "no such bind parameter");
224
+
225
+ switch(TYPE(value)) {
226
+ case T_STRING:
227
+ if(CLASS_OF(value) == cSqlite3Blob
228
+ #ifdef HAVE_RUBY_ENCODING_H
229
+ || rb_enc_get_index(value) == rb_ascii8bit_encindex()
230
+ #endif
231
+ ) {
232
+ status = sqlite3_bind_blob(
233
+ ctx->st,
234
+ index,
235
+ (const char *)StringValuePtr(value),
236
+ (int)RSTRING_LEN(value),
237
+ SQLITE_TRANSIENT
238
+ );
239
+ } else {
240
+
241
+
242
+ #ifdef HAVE_RUBY_ENCODING_H
243
+ if (UTF16_LE_P(value) || UTF16_BE_P(value)) {
244
+ status = sqlite3_bind_text16(
245
+ ctx->st,
246
+ index,
247
+ (const char *)StringValuePtr(value),
248
+ (int)RSTRING_LEN(value),
249
+ SQLITE_TRANSIENT
250
+ );
251
+ } else {
252
+ if (!UTF8_P(value) || !USASCII_P(value)) {
253
+ value = rb_str_encode(value, rb_enc_from_encoding(rb_utf8_encoding()), 0, Qnil);
254
+ }
255
+ #endif
256
+ status = sqlite3_bind_text(
257
+ ctx->st,
258
+ index,
259
+ (const char *)StringValuePtr(value),
260
+ (int)RSTRING_LEN(value),
261
+ SQLITE_TRANSIENT
262
+ );
263
+ #ifdef HAVE_RUBY_ENCODING_H
264
+ }
265
+ #endif
266
+ }
267
+ break;
268
+ case T_BIGNUM: {
269
+ sqlite3_int64 num64;
270
+ if (bignum_to_int64(value, &num64)) {
271
+ status = sqlite3_bind_int64(ctx->st, index, num64);
272
+ break;
273
+ }
274
+ }
275
+ case T_FLOAT:
276
+ status = sqlite3_bind_double(ctx->st, index, NUM2DBL(value));
277
+ break;
278
+ case T_FIXNUM:
279
+ status = sqlite3_bind_int64(ctx->st, index, (sqlite3_int64)FIX2LONG(value));
280
+ break;
281
+ case T_NIL:
282
+ status = sqlite3_bind_null(ctx->st, index);
283
+ break;
284
+ default:
285
+ rb_raise(rb_eRuntimeError, "can't prepare %s",
286
+ rb_class2name(CLASS_OF(value)));
287
+ break;
288
+ }
289
+
290
+ CHECK(sqlite3_db_handle(ctx->st), status);
291
+
292
+ return self;
293
+ }
294
+
295
+ /* call-seq: stmt.reset!
296
+ *
297
+ * Resets the statement. This is typically done internally, though it might
298
+ * occassionally be necessary to manually reset the statement.
299
+ */
300
+ static VALUE reset_bang(VALUE self)
301
+ {
302
+ sqlite3StmtRubyPtr ctx;
303
+
304
+ Data_Get_Struct(self, sqlite3StmtRuby, ctx);
305
+ REQUIRE_OPEN_STMT(ctx);
306
+
307
+ sqlite3_reset(ctx->st);
308
+
309
+ ctx->done_p = 0;
310
+
311
+ return self;
312
+ }
313
+
314
+ /* call-seq: stmt.clear_bindings!
315
+ *
316
+ * Resets the statement. This is typically done internally, though it might
317
+ * occassionally be necessary to manually reset the statement.
318
+ */
319
+ static VALUE clear_bindings(VALUE self)
320
+ {
321
+ sqlite3StmtRubyPtr ctx;
322
+
323
+ Data_Get_Struct(self, sqlite3StmtRuby, ctx);
324
+ REQUIRE_OPEN_STMT(ctx);
325
+
326
+ sqlite3_clear_bindings(ctx->st);
327
+
328
+ ctx->done_p = 0;
329
+
330
+ return self;
331
+ }
332
+
333
+ /* call-seq: stmt.done?
334
+ *
335
+ * returns true if all rows have been returned.
336
+ */
337
+ static VALUE done_p(VALUE self)
338
+ {
339
+ sqlite3StmtRubyPtr ctx;
340
+ Data_Get_Struct(self, sqlite3StmtRuby, ctx);
341
+
342
+ if(ctx->done_p) return Qtrue;
343
+ return Qfalse;
344
+ }
345
+
346
+ /* call-seq: stmt.column_count
347
+ *
348
+ * Returns the number of columns to be returned for this statement
349
+ */
350
+ static VALUE column_count(VALUE self)
351
+ {
352
+ sqlite3StmtRubyPtr ctx;
353
+ Data_Get_Struct(self, sqlite3StmtRuby, ctx);
354
+ REQUIRE_OPEN_STMT(ctx);
355
+
356
+ return INT2NUM((long)sqlite3_column_count(ctx->st));
357
+ }
358
+
359
+ /* call-seq: stmt.column_name(index)
360
+ *
361
+ * Get the column name at +index+. 0 based.
362
+ */
363
+ static VALUE column_name(VALUE self, VALUE index)
364
+ {
365
+ sqlite3StmtRubyPtr ctx;
366
+ const char * name;
367
+
368
+ Data_Get_Struct(self, sqlite3StmtRuby, ctx);
369
+ REQUIRE_OPEN_STMT(ctx);
370
+
371
+ name = sqlite3_column_name(ctx->st, (int)NUM2INT(index));
372
+
373
+ if(name) return SQLITE3_UTF8_STR_NEW2(name);
374
+ return Qnil;
375
+ }
376
+
377
+ /* call-seq: stmt.column_decltype(index)
378
+ *
379
+ * Get the column type at +index+. 0 based.
380
+ */
381
+ static VALUE column_decltype(VALUE self, VALUE index)
382
+ {
383
+ sqlite3StmtRubyPtr ctx;
384
+ const char * name;
385
+
386
+ Data_Get_Struct(self, sqlite3StmtRuby, ctx);
387
+ REQUIRE_OPEN_STMT(ctx);
388
+
389
+ name = sqlite3_column_decltype(ctx->st, (int)NUM2INT(index));
390
+
391
+ if(name) return rb_str_new2(name);
392
+ return Qnil;
393
+ }
394
+
395
+ /* call-seq: stmt.bind_parameter_count
396
+ *
397
+ * Return the number of bind parameters
398
+ */
399
+ static VALUE bind_parameter_count(VALUE self)
400
+ {
401
+ sqlite3StmtRubyPtr ctx;
402
+ Data_Get_Struct(self, sqlite3StmtRuby, ctx);
403
+ REQUIRE_OPEN_STMT(ctx);
404
+
405
+ return INT2NUM((long)sqlite3_bind_parameter_count(ctx->st));
406
+ }
407
+
408
+ #ifdef HAVE_SQLITE3_COLUMN_DATABASE_NAME
409
+
410
+ /* call-seq: stmt.database_name(column_index)
411
+ *
412
+ * Return the database name for the column at +column_index+
413
+ */
414
+ static VALUE database_name(VALUE self, VALUE index)
415
+ {
416
+ sqlite3StmtRubyPtr ctx;
417
+ Data_Get_Struct(self, sqlite3StmtRuby, ctx);
418
+ REQUIRE_OPEN_STMT(ctx);
419
+
420
+ return SQLITE3_UTF8_STR_NEW2(
421
+ sqlite3_column_database_name(ctx->st, NUM2INT(index)));
422
+ }
423
+
424
+ #endif
425
+
426
+ void init_sqlite3_statement()
427
+ {
428
+ cSqlite3Statement = rb_define_class_under(mSqlite3, "Statement", rb_cObject);
429
+
430
+ rb_define_alloc_func(cSqlite3Statement, allocate);
431
+ rb_define_method(cSqlite3Statement, "initialize", initialize, 2);
432
+ rb_define_method(cSqlite3Statement, "close", sqlite3_rb_close, 0);
433
+ rb_define_method(cSqlite3Statement, "closed?", closed_p, 0);
434
+ rb_define_method(cSqlite3Statement, "bind_param", bind_param, 2);
435
+ rb_define_method(cSqlite3Statement, "reset!", reset_bang, 0);
436
+ rb_define_method(cSqlite3Statement, "clear_bindings!", clear_bindings, 0);
437
+ rb_define_method(cSqlite3Statement, "step", step, 0);
438
+ rb_define_method(cSqlite3Statement, "done?", done_p, 0);
439
+ rb_define_method(cSqlite3Statement, "column_count", column_count, 0);
440
+ rb_define_method(cSqlite3Statement, "column_name", column_name, 1);
441
+ rb_define_method(cSqlite3Statement, "column_decltype", column_decltype, 1);
442
+ rb_define_method(cSqlite3Statement, "bind_parameter_count", bind_parameter_count, 0);
443
+
444
+ #ifdef HAVE_SQLITE3_COLUMN_DATABASE_NAME
445
+ rb_define_method(cSqlite3Statement, "database_name", database_name, 1);
446
+ #endif
447
+ }