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.
Files changed (58) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +152 -0
  3. data/CONTRIBUTING.md +23 -1
  4. data/FAQ.md +0 -43
  5. data/INSTALLATION.md +13 -5
  6. data/LICENSE +18 -22
  7. data/README.md +75 -4
  8. data/dependencies.yml +10 -11
  9. data/ext/sqlite3/aggregator.c +142 -145
  10. data/ext/sqlite3/aggregator.h +2 -4
  11. data/ext/sqlite3/backup.c +74 -65
  12. data/ext/sqlite3/backup.h +2 -2
  13. data/ext/sqlite3/database.c +535 -482
  14. data/ext/sqlite3/database.h +7 -4
  15. data/ext/sqlite3/exception.c +111 -92
  16. data/ext/sqlite3/exception.h +3 -1
  17. data/ext/sqlite3/extconf.rb +21 -22
  18. data/ext/sqlite3/sqlite3.c +159 -115
  19. data/ext/sqlite3/sqlite3_ruby.h +2 -2
  20. data/ext/sqlite3/statement.c +516 -300
  21. data/ext/sqlite3/statement.h +3 -3
  22. data/ext/sqlite3/timespec.h +20 -0
  23. data/lib/sqlite3/3.0/sqlite3_native.so +0 -0
  24. data/lib/sqlite3/constants.rb +171 -47
  25. data/lib/sqlite3/database.rb +105 -165
  26. data/lib/sqlite3/errors.rb +26 -1
  27. data/lib/sqlite3/pragmas.rb +126 -136
  28. data/lib/sqlite3/resultset.rb +14 -97
  29. data/lib/sqlite3/statement.rb +58 -13
  30. data/lib/sqlite3/value.rb +17 -20
  31. data/lib/sqlite3/version.rb +1 -21
  32. data/lib/sqlite3.rb +6 -4
  33. metadata +3 -28
  34. data/API_CHANGES.md +0 -49
  35. data/ChangeLog.cvs +0 -88
  36. data/Gemfile +0 -10
  37. data/LICENSE-DEPENDENCIES +0 -20
  38. data/lib/sqlite3/translator.rb +0 -117
  39. data/test/helper.rb +0 -27
  40. data/test/test_backup.rb +0 -33
  41. data/test/test_collation.rb +0 -82
  42. data/test/test_database.rb +0 -668
  43. data/test/test_database_flags.rb +0 -95
  44. data/test/test_database_readonly.rb +0 -36
  45. data/test/test_database_readwrite.rb +0 -41
  46. data/test/test_deprecated.rb +0 -49
  47. data/test/test_encoding.rb +0 -165
  48. data/test/test_integration.rb +0 -507
  49. data/test/test_integration_aggregate.rb +0 -336
  50. data/test/test_integration_open_close.rb +0 -30
  51. data/test/test_integration_pending.rb +0 -115
  52. data/test/test_integration_resultset.rb +0 -142
  53. data/test/test_integration_statement.rb +0 -194
  54. data/test/test_pragmas.rb +0 -22
  55. data/test/test_result_set.rb +0 -47
  56. data/test/test_sqlite3.rb +0 -30
  57. data/test/test_statement.rb +0 -290
  58. data/test/test_statement_execute.rb +0 -39
@@ -6,76 +6,73 @@
6
6
 
7
7
  VALUE cSqlite3Statement;
8
8
 
9
- static size_t statement_memsize(const void *data)
9
+ static void
10
+ statement_deallocate(void *data)
10
11
  {
11
- const sqlite3StmtRubyPtr s = (const sqlite3StmtRubyPtr)data;
12
- // NB: can't account for s->st because the type is incomplete.
13
- return sizeof(*s);
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);
14
27
  }
15
28
 
16
29
  static const rb_data_type_t statement_type = {
17
- "SQLite3::Backup",
18
- {
19
- NULL,
20
- RUBY_TYPED_DEFAULT_FREE,
21
- statement_memsize,
22
- },
23
- 0,
24
- 0,
25
- RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED,
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,
26
39
  };
27
40
 
28
- static VALUE allocate(VALUE klass)
41
+ static VALUE
42
+ allocate(VALUE klass)
29
43
  {
30
- sqlite3StmtRubyPtr ctx;
31
- return TypedData_Make_Struct(klass, sqlite3StmtRuby, &statement_type, ctx);
44
+ sqlite3StmtRubyPtr ctx;
45
+ return TypedData_Make_Struct(klass, sqlite3StmtRuby, &statement_type, ctx);
32
46
  }
33
47
 
34
- /* call-seq: SQLite3::Statement.new(db, sql)
35
- *
36
- * Create a new statement attached to the given Database instance, and which
37
- * encapsulates the given SQL text. If the text contains more than one
38
- * statement (i.e., separated by semicolons), then the #remainder property
39
- * will be set to the trailing text.
40
- */
41
- static VALUE initialize(VALUE self, VALUE db, VALUE sql)
48
+ static VALUE
49
+ prepare(VALUE self, VALUE db, VALUE sql)
42
50
  {
43
- sqlite3RubyPtr db_ctx = sqlite3_database_unwrap(db);
44
- sqlite3StmtRubyPtr ctx;
45
- const char *tail = NULL;
46
- int status;
47
-
48
- StringValue(sql);
49
-
50
- TypedData_Get_Struct(self, sqlite3StmtRuby, &statement_type, ctx);
51
+ sqlite3RubyPtr db_ctx = sqlite3_database_unwrap(db);
52
+ sqlite3StmtRubyPtr ctx;
53
+ const char *tail = NULL;
54
+ int status;
51
55
 
52
- if(!db_ctx->db)
53
- rb_raise(rb_eArgError, "prepare called on a closed database");
56
+ StringValue(sql);
54
57
 
55
- if(!UTF8_P(sql)) {
56
- sql = rb_str_export_to_enc(sql, rb_utf8_encoding());
57
- }
58
+ TypedData_Get_Struct(self, sqlite3StmtRuby, &statement_type, ctx);
58
59
 
59
60
  #ifdef HAVE_SQLITE3_PREPARE_V2
60
- status = sqlite3_prepare_v2(
61
+ status = sqlite3_prepare_v2(
61
62
  #else
62
- status = sqlite3_prepare(
63
+ status = sqlite3_prepare(
63
64
  #endif
64
- db_ctx->db,
65
- (const char *)StringValuePtr(sql),
66
- (int)RSTRING_LEN(sql),
67
- &ctx->st,
68
- &tail
69
- );
65
+ db_ctx->db,
66
+ (const char *)StringValuePtr(sql),
67
+ (int)RSTRING_LEN(sql),
68
+ &ctx->st,
69
+ &tail
70
+ );
70
71
 
71
- CHECK(db_ctx->db, status);
72
+ CHECK(db_ctx->db, status);
73
+ timespecclear(&db_ctx->stmt_deadline);
72
74
 
73
- rb_iv_set(self, "@connection", db);
74
- rb_iv_set(self, "@remainder", rb_str_new2(tail));
75
- rb_iv_set(self, "@columns", Qnil);
76
- rb_iv_set(self, "@types", Qnil);
77
-
78
- return self;
75
+ return rb_str_new2(tail);
79
76
  }
80
77
 
81
78
  /* call-seq: stmt.close
@@ -83,122 +80,124 @@ static VALUE initialize(VALUE self, VALUE db, VALUE sql)
83
80
  * Closes the statement by finalizing the underlying statement
84
81
  * handle. The statement must not be used after being closed.
85
82
  */
86
- static VALUE sqlite3_rb_close(VALUE self)
83
+ static VALUE
84
+ sqlite3_rb_close(VALUE self)
87
85
  {
88
- sqlite3StmtRubyPtr ctx;
86
+ sqlite3StmtRubyPtr ctx;
89
87
 
90
- TypedData_Get_Struct(self, sqlite3StmtRuby, &statement_type, ctx);
88
+ TypedData_Get_Struct(self, sqlite3StmtRuby, &statement_type, ctx);
91
89
 
92
- REQUIRE_OPEN_STMT(ctx);
90
+ REQUIRE_OPEN_STMT(ctx);
93
91
 
94
- sqlite3_finalize(ctx->st);
95
- ctx->st = NULL;
92
+ sqlite3_finalize(ctx->st);
93
+ ctx->st = NULL;
96
94
 
97
- return self;
95
+ return self;
98
96
  }
99
97
 
100
98
  /* call-seq: stmt.closed?
101
99
  *
102
100
  * Returns true if the statement has been closed.
103
101
  */
104
- static VALUE closed_p(VALUE self)
102
+ static VALUE
103
+ closed_p(VALUE self)
105
104
  {
106
- sqlite3StmtRubyPtr ctx;
107
- TypedData_Get_Struct(self, sqlite3StmtRuby, &statement_type, ctx);
105
+ sqlite3StmtRubyPtr ctx;
106
+ TypedData_Get_Struct(self, sqlite3StmtRuby, &statement_type, ctx);
108
107
 
109
- if(!ctx->st) return Qtrue;
108
+ if (!ctx->st) { return Qtrue; }
110
109
 
111
- return Qfalse;
110
+ return Qfalse;
112
111
  }
113
112
 
114
- static VALUE step(VALUE self)
113
+ static VALUE
114
+ step(VALUE self)
115
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
- {
129
- VALUE db = rb_iv_get(self, "@connection");
130
- rb_funcall(db, rb_intern("encoding"), 0);
131
- internal_encoding = rb_default_internal_encoding();
132
- }
133
-
134
- stmt = ctx->st;
135
-
136
- value = sqlite3_step(stmt);
137
- if (rb_errinfo() != Qnil) {
138
- /* some user defined function was invoked as a callback during step and
139
- * it raised an exception that has been suppressed until step returns.
140
- * Now re-raise it. */
141
- VALUE exception = rb_errinfo();
142
- rb_set_errinfo(Qnil);
143
- rb_exc_raise(exception);
144
- }
145
-
146
- length = sqlite3_column_count(stmt);
147
- list = rb_ary_new2((long)length);
148
-
149
- switch(value) {
150
- case SQLITE_ROW:
151
- {
152
- int i;
153
- for(i = 0; i < length; i++) {
154
- switch(sqlite3_column_type(stmt, i)) {
155
- case SQLITE_INTEGER:
156
- rb_ary_push(list, LL2NUM(sqlite3_column_int64(stmt, i)));
157
- break;
158
- case SQLITE_FLOAT:
159
- rb_ary_push(list, rb_float_new(sqlite3_column_double(stmt, i)));
160
- break;
161
- case SQLITE_TEXT:
162
- {
163
- VALUE str = rb_str_new(
164
- (const char *)sqlite3_column_text(stmt, i),
165
- (long)sqlite3_column_bytes(stmt, i)
166
- );
167
- rb_enc_associate_index(str, rb_utf8_encindex());
168
- if(internal_encoding)
169
- str = rb_str_export_to_enc(str, internal_encoding);
170
- rb_ary_push(list, str);
171
- }
172
- break;
173
- case SQLITE_BLOB:
174
- {
175
- VALUE str = rb_str_new(
176
- (const char *)sqlite3_column_blob(stmt, i),
177
- (long)sqlite3_column_bytes(stmt, i)
178
- );
179
- rb_ary_push(list, str);
180
- }
181
- break;
182
- case SQLITE_NULL:
183
- rb_ary_push(list, Qnil);
184
- break;
185
- default:
186
- rb_raise(rb_eRuntimeError, "bad type");
187
- }
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
+ }
188
186
  }
189
- }
190
- break;
191
- case SQLITE_DONE:
192
- ctx->done_p = 1;
193
- return Qnil;
194
- break;
195
- default:
196
- sqlite3_reset(stmt);
197
- ctx->done_p = 0;
198
- CHECK(sqlite3_db_handle(ctx->st), value);
199
- }
200
-
201
- return list;
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;
202
201
  }
203
202
 
204
203
  /* call-seq: stmt.bind_param(key, value)
@@ -209,91 +208,93 @@ static VALUE step(VALUE self)
209
208
  *
210
209
  * See also #bind_params.
211
210
  */
212
- static VALUE bind_param(VALUE self, VALUE key, VALUE value)
211
+ static VALUE
212
+ bind_param(VALUE self, VALUE key, VALUE value)
213
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
- switch(TYPE(value)) {
236
- case T_STRING:
237
- if(CLASS_OF(value) == cSqlite3Blob
238
- || rb_enc_get_index(value) == rb_ascii8bit_encindex()
239
- ) {
240
- status = sqlite3_bind_blob(
241
- ctx->st,
242
- index,
243
- (const char *)StringValuePtr(value),
244
- (int)RSTRING_LEN(value),
245
- SQLITE_TRANSIENT
246
- );
247
- } else {
248
-
249
-
250
- if (UTF16_LE_P(value) || UTF16_BE_P(value)) {
251
- status = sqlite3_bind_text16(
252
- ctx->st,
253
- index,
254
- (const char *)StringValuePtr(value),
255
- (int)RSTRING_LEN(value),
256
- SQLITE_TRANSIENT
257
- );
258
- } else {
259
- if (!UTF8_P(value) || !USASCII_P(value)) {
260
- value = rb_str_encode(value, rb_enc_from_encoding(rb_utf8_encoding()), 0, Qnil);
261
- }
262
- status = sqlite3_bind_text(
263
- ctx->st,
264
- index,
265
- (const char *)StringValuePtr(value),
266
- (int)RSTRING_LEN(value),
267
- SQLITE_TRANSIENT
268
- );
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
+ }
269
279
  }
270
- }
271
- break;
272
- case T_BIGNUM: {
273
- sqlite3_int64 num64;
274
- if (bignum_to_int64(value, &num64)) {
275
- status = sqlite3_bind_int64(ctx->st, index, num64);
276
- break;
277
- }
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;
278
293
  }
279
- case T_FLOAT:
280
- status = sqlite3_bind_double(ctx->st, index, NUM2DBL(value));
281
- break;
282
- case T_FIXNUM:
283
- status = sqlite3_bind_int64(ctx->st, index, (sqlite3_int64)FIX2LONG(value));
284
- break;
285
- case T_NIL:
286
- status = sqlite3_bind_null(ctx->st, index);
287
- break;
288
- default:
289
- rb_raise(rb_eRuntimeError, "can't prepare %s",
290
- rb_class2name(CLASS_OF(value)));
291
- break;
292
- }
293
-
294
- CHECK(sqlite3_db_handle(ctx->st), status);
295
-
296
- return self;
294
+
295
+ CHECK(sqlite3_db_handle(ctx->st), status);
296
+
297
+ return self;
297
298
  }
298
299
 
299
300
  /* call-seq: stmt.reset!
@@ -301,18 +302,19 @@ static VALUE bind_param(VALUE self, VALUE key, VALUE value)
301
302
  * Resets the statement. This is typically done internally, though it might
302
303
  * occasionally be necessary to manually reset the statement.
303
304
  */
304
- static VALUE reset_bang(VALUE self)
305
+ static VALUE
306
+ reset_bang(VALUE self)
305
307
  {
306
- sqlite3StmtRubyPtr ctx;
308
+ sqlite3StmtRubyPtr ctx;
307
309
 
308
- TypedData_Get_Struct(self, sqlite3StmtRuby, &statement_type, ctx);
309
- REQUIRE_OPEN_STMT(ctx);
310
+ TypedData_Get_Struct(self, sqlite3StmtRuby, &statement_type, ctx);
311
+ REQUIRE_OPEN_STMT(ctx);
310
312
 
311
- sqlite3_reset(ctx->st);
313
+ sqlite3_reset(ctx->st);
312
314
 
313
- ctx->done_p = 0;
315
+ ctx->done_p = 0;
314
316
 
315
- return self;
317
+ return self;
316
318
  }
317
319
 
318
320
  /* call-seq: stmt.clear_bindings!
@@ -320,94 +322,263 @@ static VALUE reset_bang(VALUE self)
320
322
  * Resets the statement. This is typically done internally, though it might
321
323
  * occasionally be necessary to manually reset the statement.
322
324
  */
323
- static VALUE clear_bindings_bang(VALUE self)
325
+ static VALUE
326
+ clear_bindings_bang(VALUE self)
324
327
  {
325
- sqlite3StmtRubyPtr ctx;
328
+ sqlite3StmtRubyPtr ctx;
326
329
 
327
- TypedData_Get_Struct(self, sqlite3StmtRuby, &statement_type, ctx);
328
- REQUIRE_OPEN_STMT(ctx);
330
+ TypedData_Get_Struct(self, sqlite3StmtRuby, &statement_type, ctx);
331
+ REQUIRE_OPEN_STMT(ctx);
329
332
 
330
- sqlite3_clear_bindings(ctx->st);
333
+ sqlite3_clear_bindings(ctx->st);
331
334
 
332
- ctx->done_p = 0;
335
+ ctx->done_p = 0;
333
336
 
334
- return self;
337
+ return self;
335
338
  }
336
339
 
337
340
  /* call-seq: stmt.done?
338
341
  *
339
342
  * returns true if all rows have been returned.
340
343
  */
341
- static VALUE done_p(VALUE self)
344
+ static VALUE
345
+ done_p(VALUE self)
342
346
  {
343
- sqlite3StmtRubyPtr ctx;
344
- TypedData_Get_Struct(self, sqlite3StmtRuby, &statement_type, ctx);
347
+ sqlite3StmtRubyPtr ctx;
348
+ TypedData_Get_Struct(self, sqlite3StmtRuby, &statement_type, ctx);
345
349
 
346
- if(ctx->done_p) return Qtrue;
347
- return Qfalse;
350
+ if (ctx->done_p) { return Qtrue; }
351
+ return Qfalse;
348
352
  }
349
353
 
350
354
  /* call-seq: stmt.column_count
351
355
  *
352
356
  * Returns the number of columns to be returned for this statement
353
357
  */
354
- static VALUE column_count(VALUE self)
358
+ static VALUE
359
+ column_count(VALUE self)
355
360
  {
356
- sqlite3StmtRubyPtr ctx;
357
- TypedData_Get_Struct(self, sqlite3StmtRuby, &statement_type, ctx);
358
- REQUIRE_OPEN_STMT(ctx);
361
+ sqlite3StmtRubyPtr ctx;
362
+ TypedData_Get_Struct(self, sqlite3StmtRuby, &statement_type, ctx);
363
+ REQUIRE_OPEN_STMT(ctx);
359
364
 
360
- return INT2NUM(sqlite3_column_count(ctx->st));
365
+ return INT2NUM(sqlite3_column_count(ctx->st));
361
366
  }
362
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
+
363
383
  /* call-seq: stmt.column_name(index)
364
384
  *
365
385
  * Get the column name at +index+. 0 based.
366
386
  */
367
- static VALUE column_name(VALUE self, VALUE index)
387
+ static VALUE
388
+ column_name(VALUE self, VALUE index)
368
389
  {
369
- sqlite3StmtRubyPtr ctx;
370
- const char * name;
390
+ sqlite3StmtRubyPtr ctx;
391
+ const char *name;
371
392
 
372
- TypedData_Get_Struct(self, sqlite3StmtRuby, &statement_type, ctx);
373
- REQUIRE_OPEN_STMT(ctx);
393
+ TypedData_Get_Struct(self, sqlite3StmtRuby, &statement_type, ctx);
394
+ REQUIRE_OPEN_STMT(ctx);
374
395
 
375
- name = sqlite3_column_name(ctx->st, (int)NUM2INT(index));
396
+ name = sqlite3_column_name(ctx->st, (int)NUM2INT(index));
376
397
 
377
- if(name) return SQLITE3_UTF8_STR_NEW2(name);
378
- return Qnil;
398
+ VALUE ret = Qnil;
399
+
400
+ if (name) {
401
+ ret = interned_utf8_cstr(name);
402
+ }
403
+ return ret;
379
404
  }
380
405
 
381
406
  /* call-seq: stmt.column_decltype(index)
382
407
  *
383
408
  * Get the column type at +index+. 0 based.
384
409
  */
385
- static VALUE column_decltype(VALUE self, VALUE index)
410
+ static VALUE
411
+ column_decltype(VALUE self, VALUE index)
386
412
  {
387
- sqlite3StmtRubyPtr ctx;
388
- const char * name;
413
+ sqlite3StmtRubyPtr ctx;
414
+ const char *name;
389
415
 
390
- TypedData_Get_Struct(self, sqlite3StmtRuby, &statement_type, ctx);
391
- REQUIRE_OPEN_STMT(ctx);
416
+ TypedData_Get_Struct(self, sqlite3StmtRuby, &statement_type, ctx);
417
+ REQUIRE_OPEN_STMT(ctx);
392
418
 
393
- name = sqlite3_column_decltype(ctx->st, (int)NUM2INT(index));
419
+ name = sqlite3_column_decltype(ctx->st, (int)NUM2INT(index));
394
420
 
395
- if(name) return rb_str_new2(name);
396
- return Qnil;
421
+ if (name) { return rb_str_new2(name); }
422
+ return Qnil;
397
423
  }
398
424
 
399
425
  /* call-seq: stmt.bind_parameter_count
400
426
  *
401
427
  * Return the number of bind parameters
402
428
  */
403
- static VALUE bind_parameter_count(VALUE self)
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)
404
554
  {
405
- sqlite3StmtRubyPtr ctx;
406
- TypedData_Get_Struct(self, sqlite3StmtRuby, &statement_type, ctx);
407
- REQUIRE_OPEN_STMT(ctx);
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
+ }
408
566
 
409
- return INT2NUM(sqlite3_bind_parameter_count(ctx->st));
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));
410
580
  }
581
+ #endif
411
582
 
412
583
  #ifdef HAVE_SQLITE3_COLUMN_DATABASE_NAME
413
584
 
@@ -415,37 +586,82 @@ static VALUE bind_parameter_count(VALUE self)
415
586
  *
416
587
  * Return the database name for the column at +column_index+
417
588
  */
418
- static VALUE database_name(VALUE self, VALUE index)
589
+ static VALUE
590
+ database_name(VALUE self, VALUE index)
419
591
  {
420
- sqlite3StmtRubyPtr ctx;
421
- TypedData_Get_Struct(self, sqlite3StmtRuby, &statement_type, ctx);
422
- REQUIRE_OPEN_STMT(ctx);
592
+ sqlite3StmtRubyPtr ctx;
593
+ TypedData_Get_Struct(self, sqlite3StmtRuby, &statement_type, ctx);
594
+ REQUIRE_OPEN_STMT(ctx);
423
595
 
424
- return SQLITE3_UTF8_STR_NEW2(
425
- sqlite3_column_database_name(ctx->st, NUM2INT(index)));
596
+ return SQLITE3_UTF8_STR_NEW2(
597
+ sqlite3_column_database_name(ctx->st, NUM2INT(index)));
426
598
  }
427
599
 
428
600
  #endif
429
601
 
430
- void init_sqlite3_statement(void)
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)
431
608
  {
432
- cSqlite3Statement = rb_define_class_under(mSqlite3, "Statement", rb_cObject);
433
-
434
- rb_define_alloc_func(cSqlite3Statement, allocate);
435
- rb_define_method(cSqlite3Statement, "initialize", initialize, 2);
436
- rb_define_method(cSqlite3Statement, "close", sqlite3_rb_close, 0);
437
- rb_define_method(cSqlite3Statement, "closed?", closed_p, 0);
438
- rb_define_method(cSqlite3Statement, "bind_param", bind_param, 2);
439
- rb_define_method(cSqlite3Statement, "reset!", reset_bang, 0);
440
- rb_define_method(cSqlite3Statement, "clear_bindings!", clear_bindings_bang, 0);
441
- rb_define_method(cSqlite3Statement, "step", step, 0);
442
- rb_define_method(cSqlite3Statement, "done?", done_p, 0);
443
- rb_define_method(cSqlite3Statement, "column_count", column_count, 0);
444
- rb_define_method(cSqlite3Statement, "column_name", column_name, 1);
445
- rb_define_method(cSqlite3Statement, "column_decltype", column_decltype, 1);
446
- rb_define_method(cSqlite3Statement, "bind_parameter_count", bind_parameter_count, 0);
609
+ sqlite3StmtRubyPtr ctx;
610
+ TypedData_Get_Struct(self, sqlite3StmtRuby, &statement_type, ctx);
611
+ REQUIRE_OPEN_STMT(ctx);
447
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);
448
657
  #ifdef HAVE_SQLITE3_COLUMN_DATABASE_NAME
449
- rb_define_method(cSqlite3Statement, "database_name", database_name, 1);
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);
450
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);
451
667
  }