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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +152 -0
- data/CONTRIBUTING.md +23 -1
- data/FAQ.md +0 -43
- data/INSTALLATION.md +13 -5
- data/LICENSE +18 -22
- data/README.md +75 -4
- data/dependencies.yml +10 -11
- data/ext/sqlite3/aggregator.c +142 -145
- data/ext/sqlite3/aggregator.h +2 -4
- data/ext/sqlite3/backup.c +74 -65
- data/ext/sqlite3/backup.h +2 -2
- data/ext/sqlite3/database.c +535 -482
- data/ext/sqlite3/database.h +7 -4
- data/ext/sqlite3/exception.c +111 -92
- data/ext/sqlite3/exception.h +3 -1
- data/ext/sqlite3/extconf.rb +21 -22
- data/ext/sqlite3/sqlite3.c +159 -115
- data/ext/sqlite3/sqlite3_ruby.h +2 -2
- data/ext/sqlite3/statement.c +516 -300
- data/ext/sqlite3/statement.h +3 -3
- data/ext/sqlite3/timespec.h +20 -0
- data/lib/sqlite3/3.0/sqlite3_native.so +0 -0
- data/lib/sqlite3/constants.rb +171 -47
- data/lib/sqlite3/database.rb +105 -165
- data/lib/sqlite3/errors.rb +26 -1
- data/lib/sqlite3/pragmas.rb +126 -136
- data/lib/sqlite3/resultset.rb +14 -97
- data/lib/sqlite3/statement.rb +58 -13
- data/lib/sqlite3/value.rb +17 -20
- data/lib/sqlite3/version.rb +1 -21
- data/lib/sqlite3.rb +6 -4
- metadata +3 -28
- data/API_CHANGES.md +0 -49
- data/ChangeLog.cvs +0 -88
- data/Gemfile +0 -10
- data/LICENSE-DEPENDENCIES +0 -20
- data/lib/sqlite3/translator.rb +0 -117
- data/test/helper.rb +0 -27
- data/test/test_backup.rb +0 -33
- data/test/test_collation.rb +0 -82
- data/test/test_database.rb +0 -668
- data/test/test_database_flags.rb +0 -95
- data/test/test_database_readonly.rb +0 -36
- data/test/test_database_readwrite.rb +0 -41
- data/test/test_deprecated.rb +0 -49
- data/test/test_encoding.rb +0 -165
- data/test/test_integration.rb +0 -507
- data/test/test_integration_aggregate.rb +0 -336
- data/test/test_integration_open_close.rb +0 -30
- data/test/test_integration_pending.rb +0 -115
- data/test/test_integration_resultset.rb +0 -142
- data/test/test_integration_statement.rb +0 -194
- data/test/test_pragmas.rb +0 -22
- data/test/test_result_set.rb +0 -47
- data/test/test_sqlite3.rb +0 -30
- data/test/test_statement.rb +0 -290
- data/test/test_statement_execute.rb +0 -39
data/ext/sqlite3/statement.c
CHANGED
@@ -6,76 +6,73 @@
|
|
6
6
|
|
7
7
|
VALUE cSqlite3Statement;
|
8
8
|
|
9
|
-
static
|
9
|
+
static void
|
10
|
+
statement_deallocate(void *data)
|
10
11
|
{
|
11
|
-
|
12
|
-
|
13
|
-
|
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
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
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
|
41
|
+
static VALUE
|
42
|
+
allocate(VALUE klass)
|
29
43
|
{
|
30
|
-
|
31
|
-
|
44
|
+
sqlite3StmtRubyPtr ctx;
|
45
|
+
return TypedData_Make_Struct(klass, sqlite3StmtRuby, &statement_type, ctx);
|
32
46
|
}
|
33
47
|
|
34
|
-
|
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
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
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
|
-
|
53
|
-
rb_raise(rb_eArgError, "prepare called on a closed database");
|
56
|
+
StringValue(sql);
|
54
57
|
|
55
|
-
|
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
|
-
|
61
|
+
status = sqlite3_prepare_v2(
|
61
62
|
#else
|
62
|
-
|
63
|
+
status = sqlite3_prepare(
|
63
64
|
#endif
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
65
|
+
db_ctx->db,
|
66
|
+
(const char *)StringValuePtr(sql),
|
67
|
+
(int)RSTRING_LEN(sql),
|
68
|
+
&ctx->st,
|
69
|
+
&tail
|
70
|
+
);
|
70
71
|
|
71
|
-
|
72
|
+
CHECK(db_ctx->db, status);
|
73
|
+
timespecclear(&db_ctx->stmt_deadline);
|
72
74
|
|
73
|
-
|
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
|
83
|
+
static VALUE
|
84
|
+
sqlite3_rb_close(VALUE self)
|
87
85
|
{
|
88
|
-
|
86
|
+
sqlite3StmtRubyPtr ctx;
|
89
87
|
|
90
|
-
|
88
|
+
TypedData_Get_Struct(self, sqlite3StmtRuby, &statement_type, ctx);
|
91
89
|
|
92
|
-
|
90
|
+
REQUIRE_OPEN_STMT(ctx);
|
93
91
|
|
94
|
-
|
95
|
-
|
92
|
+
sqlite3_finalize(ctx->st);
|
93
|
+
ctx->st = NULL;
|
96
94
|
|
97
|
-
|
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
|
102
|
+
static VALUE
|
103
|
+
closed_p(VALUE self)
|
105
104
|
{
|
106
|
-
|
107
|
-
|
105
|
+
sqlite3StmtRubyPtr ctx;
|
106
|
+
TypedData_Get_Struct(self, sqlite3StmtRuby, &statement_type, ctx);
|
108
107
|
|
109
|
-
|
108
|
+
if (!ctx->st) { return Qtrue; }
|
110
109
|
|
111
|
-
|
110
|
+
return Qfalse;
|
112
111
|
}
|
113
112
|
|
114
|
-
static VALUE
|
113
|
+
static VALUE
|
114
|
+
step(VALUE self)
|
115
115
|
{
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
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
|
-
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
|
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
|
211
|
+
static VALUE
|
212
|
+
bind_param(VALUE self, VALUE key, VALUE value)
|
213
213
|
{
|
214
|
-
|
215
|
-
|
216
|
-
|
217
|
-
|
218
|
-
|
219
|
-
|
220
|
-
|
221
|
-
|
222
|
-
|
223
|
-
|
224
|
-
|
225
|
-
|
226
|
-
|
227
|
-
|
228
|
-
|
229
|
-
|
230
|
-
|
231
|
-
|
232
|
-
|
233
|
-
|
234
|
-
|
235
|
-
|
236
|
-
|
237
|
-
|
238
|
-
|
239
|
-
|
240
|
-
|
241
|
-
|
242
|
-
|
243
|
-
|
244
|
-
|
245
|
-
|
246
|
-
|
247
|
-
|
248
|
-
|
249
|
-
|
250
|
-
|
251
|
-
|
252
|
-
|
253
|
-
|
254
|
-
|
255
|
-
|
256
|
-
|
257
|
-
|
258
|
-
|
259
|
-
|
260
|
-
|
261
|
-
|
262
|
-
|
263
|
-
|
264
|
-
|
265
|
-
|
266
|
-
|
267
|
-
|
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
|
-
|
272
|
-
|
273
|
-
|
274
|
-
|
275
|
-
|
276
|
-
|
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
|
-
|
280
|
-
|
281
|
-
|
282
|
-
|
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
|
305
|
+
static VALUE
|
306
|
+
reset_bang(VALUE self)
|
305
307
|
{
|
306
|
-
|
308
|
+
sqlite3StmtRubyPtr ctx;
|
307
309
|
|
308
|
-
|
309
|
-
|
310
|
+
TypedData_Get_Struct(self, sqlite3StmtRuby, &statement_type, ctx);
|
311
|
+
REQUIRE_OPEN_STMT(ctx);
|
310
312
|
|
311
|
-
|
313
|
+
sqlite3_reset(ctx->st);
|
312
314
|
|
313
|
-
|
315
|
+
ctx->done_p = 0;
|
314
316
|
|
315
|
-
|
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
|
325
|
+
static VALUE
|
326
|
+
clear_bindings_bang(VALUE self)
|
324
327
|
{
|
325
|
-
|
328
|
+
sqlite3StmtRubyPtr ctx;
|
326
329
|
|
327
|
-
|
328
|
-
|
330
|
+
TypedData_Get_Struct(self, sqlite3StmtRuby, &statement_type, ctx);
|
331
|
+
REQUIRE_OPEN_STMT(ctx);
|
329
332
|
|
330
|
-
|
333
|
+
sqlite3_clear_bindings(ctx->st);
|
331
334
|
|
332
|
-
|
335
|
+
ctx->done_p = 0;
|
333
336
|
|
334
|
-
|
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
|
344
|
+
static VALUE
|
345
|
+
done_p(VALUE self)
|
342
346
|
{
|
343
|
-
|
344
|
-
|
347
|
+
sqlite3StmtRubyPtr ctx;
|
348
|
+
TypedData_Get_Struct(self, sqlite3StmtRuby, &statement_type, ctx);
|
345
349
|
|
346
|
-
|
347
|
-
|
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
|
358
|
+
static VALUE
|
359
|
+
column_count(VALUE self)
|
355
360
|
{
|
356
|
-
|
357
|
-
|
358
|
-
|
361
|
+
sqlite3StmtRubyPtr ctx;
|
362
|
+
TypedData_Get_Struct(self, sqlite3StmtRuby, &statement_type, ctx);
|
363
|
+
REQUIRE_OPEN_STMT(ctx);
|
359
364
|
|
360
|
-
|
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
|
387
|
+
static VALUE
|
388
|
+
column_name(VALUE self, VALUE index)
|
368
389
|
{
|
369
|
-
|
370
|
-
|
390
|
+
sqlite3StmtRubyPtr ctx;
|
391
|
+
const char *name;
|
371
392
|
|
372
|
-
|
373
|
-
|
393
|
+
TypedData_Get_Struct(self, sqlite3StmtRuby, &statement_type, ctx);
|
394
|
+
REQUIRE_OPEN_STMT(ctx);
|
374
395
|
|
375
|
-
|
396
|
+
name = sqlite3_column_name(ctx->st, (int)NUM2INT(index));
|
376
397
|
|
377
|
-
|
378
|
-
|
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
|
410
|
+
static VALUE
|
411
|
+
column_decltype(VALUE self, VALUE index)
|
386
412
|
{
|
387
|
-
|
388
|
-
|
413
|
+
sqlite3StmtRubyPtr ctx;
|
414
|
+
const char *name;
|
389
415
|
|
390
|
-
|
391
|
-
|
416
|
+
TypedData_Get_Struct(self, sqlite3StmtRuby, &statement_type, ctx);
|
417
|
+
REQUIRE_OPEN_STMT(ctx);
|
392
418
|
|
393
|
-
|
419
|
+
name = sqlite3_column_decltype(ctx->st, (int)NUM2INT(index));
|
394
420
|
|
395
|
-
|
396
|
-
|
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
|
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
|
-
|
406
|
-
|
407
|
-
|
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
|
-
|
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
|
589
|
+
static VALUE
|
590
|
+
database_name(VALUE self, VALUE index)
|
419
591
|
{
|
420
|
-
|
421
|
-
|
422
|
-
|
592
|
+
sqlite3StmtRubyPtr ctx;
|
593
|
+
TypedData_Get_Struct(self, sqlite3StmtRuby, &statement_type, ctx);
|
594
|
+
REQUIRE_OPEN_STMT(ctx);
|
423
595
|
|
424
|
-
|
425
|
-
|
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
|
-
|
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
|
-
|
433
|
-
|
434
|
-
|
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
|
-
|
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
|
}
|