sqlite3-ruby 1.2.5-x86-mswin32 → 1.3.0.beta.1-x86-mswin32

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 (51) hide show
  1. data/API_CHANGES.rdoc +48 -0
  2. data/{History.txt → CHANGELOG.rdoc} +24 -0
  3. data/Manifest.txt +14 -14
  4. data/{README.txt → README.rdoc} +1 -6
  5. data/Rakefile +8 -3
  6. data/ext/sqlite3/database.c +687 -0
  7. data/ext/sqlite3/database.h +15 -0
  8. data/ext/sqlite3/exception.c +94 -0
  9. data/ext/sqlite3/exception.h +8 -0
  10. data/ext/sqlite3/extconf.rb +26 -0
  11. data/ext/sqlite3/sqlite3.c +33 -0
  12. data/ext/sqlite3/sqlite3_ruby.h +43 -0
  13. data/ext/sqlite3/statement.c +412 -0
  14. data/ext/sqlite3/statement.h +16 -0
  15. data/lib/sqlite3.rb +9 -0
  16. data/lib/sqlite3/1.8/sqlite3_native.so +0 -0
  17. data/lib/sqlite3/1.9/sqlite3_native.so +0 -0
  18. data/lib/sqlite3/database.rb +94 -302
  19. data/lib/sqlite3/errors.rb +0 -24
  20. data/lib/sqlite3/pragmas.rb +16 -7
  21. data/lib/sqlite3/resultset.rb +25 -81
  22. data/lib/sqlite3/statement.rb +22 -107
  23. data/lib/sqlite3/version.rb +4 -4
  24. data/setup.rb +2 -2
  25. data/tasks/native.rake +13 -17
  26. data/tasks/vendor_sqlite3.rake +10 -7
  27. data/test/helper.rb +1 -65
  28. data/test/test_database.rb +239 -189
  29. data/test/test_encoding.rb +115 -0
  30. data/test/test_integration.rb +38 -35
  31. data/test/test_integration_open_close.rb +1 -1
  32. data/test/test_integration_pending.rb +6 -4
  33. data/test/test_integration_resultset.rb +20 -8
  34. data/test/test_integration_statement.rb +1 -2
  35. data/test/test_sqlite3.rb +9 -0
  36. data/test/test_statement.rb +193 -0
  37. metadata +84 -49
  38. data/ext/sqlite3_api/extconf.rb +0 -10
  39. data/ext/sqlite3_api/sqlite3_api.i +0 -362
  40. data/ext/sqlite3_api/sqlite3_api_wrap.c +0 -5018
  41. data/lib/1.8/sqlite3_api.so +0 -0
  42. data/lib/1.9/sqlite3_api.so +0 -0
  43. data/lib/sqlite3/driver/dl/api.rb +0 -152
  44. data/lib/sqlite3/driver/dl/driver.rb +0 -307
  45. data/lib/sqlite3/driver/native/driver.rb +0 -219
  46. data/tasks/benchmark.rake +0 -9
  47. data/tasks/gem.rake +0 -32
  48. data/test/bm.rb +0 -140
  49. data/test/driver/dl/tc_driver.rb +0 -292
  50. data/test/native-vs-dl.rb +0 -126
  51. data/test/test_errors.rb +0 -17
@@ -0,0 +1,15 @@
1
+ #ifndef SQLITE3_DATABASE_RUBY
2
+ #define SQLITE3_DATABASE_RUBY
3
+
4
+ #include <sqlite3_ruby.h>
5
+
6
+ struct _sqlite3Ruby {
7
+ sqlite3 *db;
8
+ };
9
+
10
+ typedef struct _sqlite3Ruby sqlite3Ruby;
11
+ typedef sqlite3Ruby * sqlite3RubyPtr;
12
+
13
+ void init_sqlite3_database();
14
+
15
+ #endif
@@ -0,0 +1,94 @@
1
+ #include <sqlite3_ruby.h>
2
+
3
+ void rb_sqlite3_raise(sqlite3 * db, int status)
4
+ {
5
+ VALUE klass = Qnil;
6
+
7
+ switch(status) {
8
+ case SQLITE_OK:
9
+ return;
10
+ break;
11
+ case SQLITE_ERROR:
12
+ klass = rb_path2class("SQLite3::SQLException");
13
+ break;
14
+ case SQLITE_INTERNAL:
15
+ klass = rb_path2class("SQLite3::InternalException");
16
+ break;
17
+ case SQLITE_PERM:
18
+ klass = rb_path2class("SQLite3::PermissionException");
19
+ break;
20
+ case SQLITE_ABORT:
21
+ klass = rb_path2class("SQLite3::AbortException");
22
+ break;
23
+ case SQLITE_BUSY:
24
+ klass = rb_path2class("SQLite3::BusyException");
25
+ break;
26
+ case SQLITE_LOCKED:
27
+ klass = rb_path2class("SQLite3::LockedException");
28
+ break;
29
+ case SQLITE_NOMEM:
30
+ klass = rb_path2class("SQLite3::MemoryException");
31
+ break;
32
+ case SQLITE_READONLY:
33
+ klass = rb_path2class("SQLite3::ReadOnlyException");
34
+ break;
35
+ case SQLITE_INTERRUPT:
36
+ klass = rb_path2class("SQLite3::InterruptException");
37
+ break;
38
+ case SQLITE_IOERR:
39
+ klass = rb_path2class("SQLite3::IOException");
40
+ break;
41
+ case SQLITE_CORRUPT:
42
+ klass = rb_path2class("SQLite3::CorruptException");
43
+ break;
44
+ case SQLITE_NOTFOUND:
45
+ klass = rb_path2class("SQLite3::NotFoundException");
46
+ break;
47
+ case SQLITE_FULL:
48
+ klass = rb_path2class("SQLite3::FullException");
49
+ break;
50
+ case SQLITE_CANTOPEN:
51
+ klass = rb_path2class("SQLite3::CantOpenException");
52
+ break;
53
+ case SQLITE_PROTOCOL:
54
+ klass = rb_path2class("SQLite3::ProtocolException");
55
+ break;
56
+ case SQLITE_EMPTY:
57
+ klass = rb_path2class("SQLite3::EmptyException");
58
+ break;
59
+ case SQLITE_SCHEMA:
60
+ klass = rb_path2class("SQLite3::SchemaChangedException");
61
+ break;
62
+ case SQLITE_TOOBIG:
63
+ klass = rb_path2class("SQLite3::TooBigException");
64
+ break;
65
+ case SQLITE_CONSTRAINT:
66
+ klass = rb_path2class("SQLite3::ConstraintException");
67
+ break;
68
+ case SQLITE_MISMATCH:
69
+ klass = rb_path2class("SQLite3::MismatchException");
70
+ break;
71
+ case SQLITE_MISUSE:
72
+ klass = rb_path2class("SQLite3::MisuseException");
73
+ break;
74
+ case SQLITE_NOLFS:
75
+ klass = rb_path2class("SQLite3::UnsupportedException");
76
+ break;
77
+ case SQLITE_AUTH:
78
+ klass = rb_path2class("SQLite3::AuthorizationException");
79
+ break;
80
+ case SQLITE_FORMAT:
81
+ klass = rb_path2class("SQLite3::FormatException");
82
+ break;
83
+ case SQLITE_RANGE:
84
+ klass = rb_path2class("SQLite3::RangeException");
85
+ break;
86
+ case SQLITE_NOTADB:
87
+ klass = rb_path2class("SQLite3::NotADatabaseException");
88
+ break;
89
+ default:
90
+ klass = rb_eRuntimeError;
91
+ }
92
+
93
+ rb_raise(klass, "%s", sqlite3_errmsg(db));
94
+ }
@@ -0,0 +1,8 @@
1
+ #ifndef SQLITE3_EXCEPTION_RUBY
2
+ #define SQLITE3_EXCEPTION_RUBY
3
+
4
+ #define CHECK(_db, _status) rb_sqlite3_raise(_db, _status);
5
+
6
+ void rb_sqlite3_raise(sqlite3 * db, int status);
7
+
8
+ #endif
@@ -0,0 +1,26 @@
1
+ ENV['RC_ARCHS'] = '' if RUBY_PLATFORM =~ /darwin/
2
+
3
+ require 'mkmf'
4
+
5
+ # :stopdoc:
6
+
7
+ RbConfig::MAKEFILE_CONFIG['CC'] = ENV['CC'] if ENV['CC']
8
+
9
+ $CFLAGS << ' -O3 -Wall -Wcast-qual -Wwrite-strings -Wconversion' <<
10
+ ' -Wmissing-noreturn -Winline'
11
+
12
+ sqlite = dir_config 'sqlite3', '/opt/local/include', '/opt/local/lib'
13
+
14
+ def asplode missing
15
+ abort "#{missing} is missing. Try 'port install sqlite3 +universal' " +
16
+ "or 'yum install sqlite3-devel'"
17
+ end
18
+
19
+ asplode('sqlite3.h') unless find_header 'sqlite3.h'
20
+ asplode('sqlite3') unless find_library 'sqlite3', 'sqlite3_libversion_number'
21
+
22
+ # Functions defined in 1.9 but not 1.8
23
+ have_func('rb_proc_arity')
24
+ have_func('rb_obj_method_arity')
25
+
26
+ create_makefile('sqlite3/sqlite3_native')
@@ -0,0 +1,33 @@
1
+ #include <sqlite3_ruby.h>
2
+
3
+ VALUE mSqlite3;
4
+ VALUE cSqlite3Blob;
5
+
6
+ static VALUE libversion(VALUE UNUSED(klass))
7
+ {
8
+ return INT2NUM(sqlite3_libversion_number());
9
+ }
10
+
11
+ void Init_sqlite3_native()
12
+ {
13
+ /*
14
+ * SQLite3 is a wrapper around the popular database
15
+ * sqlite[http://sqlite.org].
16
+ *
17
+ * For an example of usage, see SQLite3::Database.
18
+ */
19
+ mSqlite3 = rb_define_module("SQLite3");
20
+
21
+ /* A class for differentiating between strings and blobs, when binding them
22
+ * into statements.
23
+ */
24
+ cSqlite3Blob = rb_define_class_under(mSqlite3, "Blob", rb_cString);
25
+
26
+ /* Initialize the sqlite3 library */
27
+ sqlite3_initialize();
28
+
29
+ init_sqlite3_database();
30
+ init_sqlite3_statement();
31
+
32
+ rb_define_singleton_method(mSqlite3, "libversion", libversion, 0);
33
+ }
@@ -0,0 +1,43 @@
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
+ #ifndef RBIGNUM_LEN
16
+ #define RBIGNUM_LEN(x) RBIGNUM(x)->len
17
+ #endif
18
+
19
+ #ifdef HAVE_RUBY_ENCODING_H
20
+ #include <ruby/encoding.h>
21
+
22
+ #define UTF8_P(_obj) (rb_enc_get_index(_obj) == rb_utf8_encindex())
23
+ #define UTF16_LE_P(_obj) (rb_enc_get_index(_obj) == rb_enc_find_index("UTF-16LE"))
24
+ #define SQLITE3_UTF8_STR_NEW2(_obj) \
25
+ (rb_enc_associate_index(rb_str_new2(_obj), rb_utf8_encindex()))
26
+
27
+ #else
28
+
29
+ #define SQLITE3_UTF8_STR_NEW2(_obj) (rb_str_new2(_obj))
30
+
31
+ #endif
32
+
33
+
34
+ #include <sqlite3.h>
35
+
36
+ extern VALUE mSqlite3;
37
+ extern VALUE cSqlite3Blob;
38
+
39
+ #include <database.h>
40
+ #include <statement.h>
41
+ #include <exception.h>
42
+
43
+ #endif
@@ -0,0 +1,412 @@
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
+ Data_Get_Struct(db, sqlite3Ruby, db_ctx);
39
+ Data_Get_Struct(self, sqlite3StmtRuby, ctx);
40
+
41
+ if(!db_ctx->db)
42
+ rb_raise(rb_eArgError, "prepare called on a closed database");
43
+
44
+ #ifdef HAVE_RUBY_ENCODING_H
45
+ if(!UTF8_P(sql)) {
46
+ VALUE encoding = rb_funcall(db, rb_intern("encoding"), 0);
47
+ rb_encoding * enc = NIL_P(encoding) ? rb_utf8_encoding() :
48
+ rb_to_encoding(encoding);
49
+ sql = rb_str_export_to_enc(sql, enc);
50
+ }
51
+ #endif
52
+
53
+ status = sqlite3_prepare_v2(
54
+ db_ctx->db,
55
+ (const char *)StringValuePtr(sql),
56
+ (int)RSTRING_LEN(sql),
57
+ &ctx->st,
58
+ &tail
59
+ );
60
+
61
+ CHECK(db_ctx->db, status);
62
+
63
+ rb_iv_set(self, "@connection", db);
64
+ rb_iv_set(self, "@remainder", rb_str_new2(tail));
65
+ rb_iv_set(self, "@columns", Qnil);
66
+ rb_iv_set(self, "@types", Qnil);
67
+
68
+ return self;
69
+ }
70
+
71
+ /* call-seq: stmt.close
72
+ *
73
+ * Closes the statement by finalizing the underlying statement
74
+ * handle. The statement must not be used after being closed.
75
+ */
76
+ static VALUE sqlite3_rb_close(VALUE self)
77
+ {
78
+ sqlite3StmtRubyPtr ctx;
79
+ sqlite3 * db;
80
+
81
+ Data_Get_Struct(self, sqlite3StmtRuby, ctx);
82
+
83
+ REQUIRE_OPEN_STMT(ctx);
84
+
85
+ db = sqlite3_db_handle(ctx->st);
86
+ CHECK(db, sqlite3_finalize(ctx->st));
87
+
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
+ int enc_index;
116
+ #endif
117
+
118
+ Data_Get_Struct(self, sqlite3StmtRuby, ctx);
119
+
120
+ REQUIRE_OPEN_STMT(ctx);
121
+
122
+ if(ctx->done_p) return Qnil;
123
+
124
+ #ifdef HAVE_RUBY_ENCODING_H
125
+ {
126
+ VALUE db = rb_iv_get(self, "@connection");
127
+ VALUE encoding = rb_funcall(db, rb_intern("encoding"), 0);
128
+ enc_index = NIL_P(encoding) ? rb_utf8_encindex() : rb_to_encoding_index(encoding);
129
+ internal_encoding = rb_default_internal_encoding();
130
+ }
131
+ #endif
132
+
133
+ stmt = ctx->st;
134
+
135
+ value = sqlite3_step(stmt);
136
+ length = sqlite3_column_count(stmt);
137
+ list = rb_ary_new2((long)length);
138
+
139
+ switch(value) {
140
+ case SQLITE_ROW:
141
+ {
142
+ int i;
143
+ for(i = 0; i < length; i++) {
144
+ switch(sqlite3_column_type(stmt, i)) {
145
+ case SQLITE_INTEGER:
146
+ rb_ary_push(list, LL2NUM(sqlite3_column_int64(stmt, i)));
147
+ break;
148
+ case SQLITE_FLOAT:
149
+ rb_ary_push(list, rb_float_new(sqlite3_column_double(stmt, i)));
150
+ break;
151
+ case SQLITE_TEXT:
152
+ {
153
+ VALUE str = rb_tainted_str_new(
154
+ (const char *)sqlite3_column_text(stmt, i),
155
+ (long)sqlite3_column_bytes(stmt, i)
156
+ );
157
+ #ifdef HAVE_RUBY_ENCODING_H
158
+ rb_enc_associate_index(str, enc_index);
159
+ if(internal_encoding)
160
+ str = rb_str_export_to_enc(str, internal_encoding);
161
+ #endif
162
+ rb_ary_push(list, str);
163
+ }
164
+ break;
165
+ case SQLITE_BLOB:
166
+ {
167
+ VALUE str = rb_tainted_str_new(
168
+ (const char *)sqlite3_column_blob(stmt, i),
169
+ (long)sqlite3_column_bytes(stmt, i)
170
+ );
171
+ rb_ary_push(list, str);
172
+ }
173
+ break;
174
+ case SQLITE_NULL:
175
+ rb_ary_push(list, Qnil);
176
+ break;
177
+ default:
178
+ rb_raise(rb_eRuntimeError, "bad type");
179
+ }
180
+ }
181
+ }
182
+ break;
183
+ case SQLITE_DONE:
184
+ ctx->done_p = 1;
185
+ return Qnil;
186
+ break;
187
+ default:
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
+ #ifdef HAVE_RUBY_ENCODING_H
241
+ if(!UTF8_P(value)) {
242
+ VALUE db = rb_iv_get(self, "@connection");
243
+ VALUE encoding = rb_funcall(db, rb_intern("encoding"), 0);
244
+ rb_encoding * enc = rb_to_encoding(encoding);
245
+ value = rb_str_export_to_enc(value, enc);
246
+ }
247
+ #endif
248
+
249
+ status = sqlite3_bind_text(
250
+ ctx->st,
251
+ index,
252
+ (const char *)StringValuePtr(value),
253
+ (int)RSTRING_LEN(value),
254
+ SQLITE_TRANSIENT
255
+ );
256
+ }
257
+ break;
258
+ case T_BIGNUM:
259
+ #if SIZEOF_LONG < 8
260
+ if (RBIGNUM_LEN(value) * SIZEOF_BDIGITS <= 8) {
261
+ status = sqlite3_bind_int64(ctx->st, index, (sqlite3_int64)NUM2LL(value));
262
+ break;
263
+ }
264
+ #endif
265
+ case T_FLOAT:
266
+ status = sqlite3_bind_double(ctx->st, index, NUM2DBL(value));
267
+ break;
268
+ case T_FIXNUM:
269
+ status = sqlite3_bind_int64(ctx->st, index, (sqlite3_int64)FIX2LONG(value));
270
+ break;
271
+ case T_NIL:
272
+ status = sqlite3_bind_null(ctx->st, index);
273
+ break;
274
+ default:
275
+ rb_raise(rb_eRuntimeError, "can't prepare %s",
276
+ rb_class2name(CLASS_OF(value)));
277
+ break;
278
+ }
279
+
280
+ CHECK(sqlite3_db_handle(ctx->st), status);
281
+
282
+ return self;
283
+ }
284
+
285
+ /* call-seq: stmt.reset!
286
+ *
287
+ * Resets the statement. This is typically done internally, though it might
288
+ * occassionally be necessary to manually reset the statement.
289
+ */
290
+ static VALUE reset_bang(VALUE self)
291
+ {
292
+ sqlite3StmtRubyPtr ctx;
293
+ int status;
294
+
295
+ Data_Get_Struct(self, sqlite3StmtRuby, ctx);
296
+ REQUIRE_OPEN_STMT(ctx);
297
+
298
+ status = sqlite3_reset(ctx->st);
299
+ CHECK(sqlite3_db_handle(ctx->st), status);
300
+
301
+ ctx->done_p = 0;
302
+
303
+ return self;
304
+ }
305
+
306
+ /* call-seq: stmt.done?
307
+ *
308
+ * returns true if all rows have been returned.
309
+ */
310
+ static VALUE done_p(VALUE self)
311
+ {
312
+ sqlite3StmtRubyPtr ctx;
313
+ Data_Get_Struct(self, sqlite3StmtRuby, ctx);
314
+
315
+ if(ctx->done_p) return Qtrue;
316
+ return Qfalse;
317
+ }
318
+
319
+ /* call-seq: stmt.column_count
320
+ *
321
+ * Returns the number of columns to be returned for this statement
322
+ */
323
+ static VALUE column_count(VALUE self)
324
+ {
325
+ sqlite3StmtRubyPtr ctx;
326
+ Data_Get_Struct(self, sqlite3StmtRuby, ctx);
327
+ REQUIRE_OPEN_STMT(ctx);
328
+
329
+ return INT2NUM((long)sqlite3_column_count(ctx->st));
330
+ }
331
+
332
+ /* call-seq: stmt.column_name(index)
333
+ *
334
+ * Get the column name at +index+. 0 based.
335
+ */
336
+ static VALUE column_name(VALUE self, VALUE index)
337
+ {
338
+ sqlite3StmtRubyPtr ctx;
339
+ const char * name;
340
+
341
+ Data_Get_Struct(self, sqlite3StmtRuby, ctx);
342
+ REQUIRE_OPEN_STMT(ctx);
343
+
344
+ name = sqlite3_column_name(ctx->st, (int)NUM2INT(index));
345
+
346
+ if(name) return rb_str_new2(name);
347
+ return Qnil;
348
+ }
349
+
350
+ /* call-seq: stmt.column_decltype(index)
351
+ *
352
+ * Get the column type at +index+. 0 based.
353
+ */
354
+ static VALUE column_decltype(VALUE self, VALUE index)
355
+ {
356
+ sqlite3StmtRubyPtr ctx;
357
+ const char * name;
358
+
359
+ Data_Get_Struct(self, sqlite3StmtRuby, ctx);
360
+ REQUIRE_OPEN_STMT(ctx);
361
+
362
+ name = sqlite3_column_decltype(ctx->st, (int)NUM2INT(index));
363
+
364
+ if(name) return rb_str_new2(name);
365
+ return Qnil;
366
+ }
367
+
368
+ /* call-seq: stmt.bind_parameter_count
369
+ *
370
+ * Return the number of bind parameters
371
+ */
372
+ static VALUE bind_parameter_count(VALUE self)
373
+ {
374
+ sqlite3StmtRubyPtr ctx;
375
+ Data_Get_Struct(self, sqlite3StmtRuby, ctx);
376
+ REQUIRE_OPEN_STMT(ctx);
377
+
378
+ return INT2NUM((long)sqlite3_bind_parameter_count(ctx->st));
379
+ }
380
+
381
+ /* call-seq: stmt.database_name(column_index)
382
+ *
383
+ * Return the database name for the column at +column_index+
384
+ */
385
+ static VALUE database_name(VALUE self, VALUE index)
386
+ {
387
+ sqlite3StmtRubyPtr ctx;
388
+ Data_Get_Struct(self, sqlite3StmtRuby, ctx);
389
+ REQUIRE_OPEN_STMT(ctx);
390
+
391
+ return SQLITE3_UTF8_STR_NEW2(
392
+ sqlite3_column_database_name(ctx->st, NUM2INT(index)));
393
+ }
394
+
395
+ void init_sqlite3_statement()
396
+ {
397
+ cSqlite3Statement = rb_define_class_under(mSqlite3, "Statement", rb_cObject);
398
+
399
+ rb_define_alloc_func(cSqlite3Statement, allocate);
400
+ rb_define_method(cSqlite3Statement, "initialize", initialize, 2);
401
+ rb_define_method(cSqlite3Statement, "close", sqlite3_rb_close, 0);
402
+ rb_define_method(cSqlite3Statement, "closed?", closed_p, 0);
403
+ rb_define_method(cSqlite3Statement, "bind_param", bind_param, 2);
404
+ rb_define_method(cSqlite3Statement, "reset!", reset_bang, 0);
405
+ rb_define_method(cSqlite3Statement, "step", step, 0);
406
+ rb_define_method(cSqlite3Statement, "done?", done_p, 0);
407
+ rb_define_method(cSqlite3Statement, "column_count", column_count, 0);
408
+ rb_define_method(cSqlite3Statement, "column_name", column_name, 1);
409
+ rb_define_method(cSqlite3Statement, "column_decltype", column_decltype, 1);
410
+ rb_define_method(cSqlite3Statement, "bind_parameter_count", bind_parameter_count, 0);
411
+ rb_define_method(cSqlite3Statement, "database_name", database_name, 1);
412
+ }