sqlite3 1.3.8-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 (55) hide show
  1. data/.gemtest +0 -0
  2. data/API_CHANGES.rdoc +50 -0
  3. data/CHANGELOG.rdoc +265 -0
  4. data/ChangeLog.cvs +88 -0
  5. data/Gemfile +15 -0
  6. data/LICENSE +27 -0
  7. data/Manifest.txt +52 -0
  8. data/README.rdoc +95 -0
  9. data/Rakefile +10 -0
  10. data/ext/sqlite3/backup.c +168 -0
  11. data/ext/sqlite3/backup.h +15 -0
  12. data/ext/sqlite3/database.c +822 -0
  13. data/ext/sqlite3/database.h +15 -0
  14. data/ext/sqlite3/exception.c +94 -0
  15. data/ext/sqlite3/exception.h +8 -0
  16. data/ext/sqlite3/extconf.rb +51 -0
  17. data/ext/sqlite3/sqlite3.c +40 -0
  18. data/ext/sqlite3/sqlite3_ruby.h +53 -0
  19. data/ext/sqlite3/statement.c +439 -0
  20. data/ext/sqlite3/statement.h +16 -0
  21. data/faq/faq.rb +145 -0
  22. data/faq/faq.yml +426 -0
  23. data/lib/sqlite3.rb +10 -0
  24. data/lib/sqlite3/2.0/sqlite3_native.so +0 -0
  25. data/lib/sqlite3/constants.rb +49 -0
  26. data/lib/sqlite3/database.rb +579 -0
  27. data/lib/sqlite3/errors.rb +44 -0
  28. data/lib/sqlite3/pragmas.rb +280 -0
  29. data/lib/sqlite3/resultset.rb +195 -0
  30. data/lib/sqlite3/statement.rb +144 -0
  31. data/lib/sqlite3/translator.rb +118 -0
  32. data/lib/sqlite3/value.rb +57 -0
  33. data/lib/sqlite3/version.rb +25 -0
  34. data/setup.rb +1333 -0
  35. data/tasks/faq.rake +9 -0
  36. data/tasks/gem.rake +37 -0
  37. data/tasks/native.rake +45 -0
  38. data/tasks/vendor_sqlite3.rake +87 -0
  39. data/test/helper.rb +18 -0
  40. data/test/test_backup.rb +33 -0
  41. data/test/test_collation.rb +82 -0
  42. data/test/test_database.rb +350 -0
  43. data/test/test_database_readonly.rb +29 -0
  44. data/test/test_deprecated.rb +44 -0
  45. data/test/test_encoding.rb +121 -0
  46. data/test/test_integration.rb +555 -0
  47. data/test/test_integration_open_close.rb +30 -0
  48. data/test/test_integration_pending.rb +115 -0
  49. data/test/test_integration_resultset.rb +159 -0
  50. data/test/test_integration_statement.rb +194 -0
  51. data/test/test_result_set.rb +37 -0
  52. data/test/test_sqlite3.rb +9 -0
  53. data/test/test_statement.rb +256 -0
  54. data/test/test_statement_execute.rb +35 -0
  55. metadata +246 -0
@@ -0,0 +1,52 @@
1
+ API_CHANGES.rdoc
2
+ CHANGELOG.rdoc
3
+ ChangeLog.cvs
4
+ Gemfile
5
+ LICENSE
6
+ Manifest.txt
7
+ README.rdoc
8
+ Rakefile
9
+ ext/sqlite3/backup.c
10
+ ext/sqlite3/backup.h
11
+ ext/sqlite3/database.c
12
+ ext/sqlite3/database.h
13
+ ext/sqlite3/exception.c
14
+ ext/sqlite3/exception.h
15
+ ext/sqlite3/extconf.rb
16
+ ext/sqlite3/sqlite3.c
17
+ ext/sqlite3/sqlite3_ruby.h
18
+ ext/sqlite3/statement.c
19
+ ext/sqlite3/statement.h
20
+ faq/faq.rb
21
+ faq/faq.yml
22
+ lib/sqlite3.rb
23
+ lib/sqlite3/constants.rb
24
+ lib/sqlite3/database.rb
25
+ lib/sqlite3/errors.rb
26
+ lib/sqlite3/pragmas.rb
27
+ lib/sqlite3/resultset.rb
28
+ lib/sqlite3/statement.rb
29
+ lib/sqlite3/translator.rb
30
+ lib/sqlite3/value.rb
31
+ lib/sqlite3/version.rb
32
+ setup.rb
33
+ tasks/faq.rake
34
+ tasks/gem.rake
35
+ tasks/native.rake
36
+ tasks/vendor_sqlite3.rake
37
+ test/helper.rb
38
+ test/test_backup.rb
39
+ test/test_collation.rb
40
+ test/test_database.rb
41
+ test/test_database_readonly.rb
42
+ test/test_deprecated.rb
43
+ test/test_encoding.rb
44
+ test/test_integration.rb
45
+ test/test_integration_open_close.rb
46
+ test/test_integration_pending.rb
47
+ test/test_integration_resultset.rb
48
+ test/test_integration_statement.rb
49
+ test/test_result_set.rb
50
+ test/test_sqlite3.rb
51
+ test/test_statement.rb
52
+ test/test_statement_execute.rb
@@ -0,0 +1,95 @@
1
+ = SQLite3/Ruby Interface
2
+
3
+ * http://github.com/luislavena/sqlite3-ruby
4
+ * http://groups.google.com/group/sqlite3-ruby
5
+
6
+ == DESCRIPTION
7
+
8
+ This module allows Ruby programs to interface with the SQLite3
9
+ database engine (http://www.sqlite.org). You must have the
10
+ SQLite engine installed in order to build this module.
11
+
12
+ Note that this module is only compatible with SQLite 3.6.16 or newer.
13
+
14
+ == SYNOPSIS
15
+
16
+ require "sqlite3"
17
+
18
+ # Open a database
19
+ db = SQLite3::Database.new "test.db"
20
+
21
+ # Create a database
22
+ rows = db.execute <<-SQL
23
+ create table numbers (
24
+ name varchar(30),
25
+ val int
26
+ );
27
+ SQL
28
+
29
+ # Execute a few inserts
30
+ {
31
+ "one" => 1,
32
+ "two" => 2,
33
+ }.each do |pair|
34
+ db.execute "insert into numbers values ( ?, ? )", pair
35
+ end
36
+
37
+ # Find a few rows
38
+ db.execute( "select * from numbers" ) do |row|
39
+ p row
40
+ end
41
+
42
+
43
+ == Compilation and Installation
44
+
45
+ Install SQLite3, enabling the option SQLITE_ENABLE_COLUMN_METADATA (see
46
+ www.sqlite.org/compile.html for details).
47
+
48
+ Then do the following:
49
+
50
+ ruby setup.rb config
51
+ ruby setup.rb setup
52
+ ruby setup.rb install
53
+
54
+ Alternatively, you can download and install the RubyGem package for
55
+ SQLite3/Ruby (you must have RubyGems and SQLite3 installed, first):
56
+
57
+ gem install sqlite3
58
+
59
+ If you have sqlite3 installed in a non-standard location, you can specify the location of the include and lib files by doing:
60
+
61
+ gem install sqlite3 -- --with-sqlite3-include=/opt/local/include \
62
+ --with-sqlite3-lib=/opt/local/lib
63
+
64
+ = SUPPORT!!!
65
+
66
+ == OMG! Something has gone wrong! Where do I get help?
67
+
68
+ The best place to get help is from the
69
+ {sqlite3-ruby mailing list}[http://groups.google.com/group/sqlite3-ruby] which
70
+ can be found here:
71
+
72
+ * http://groups.google.com/group/sqlite3-ruby
73
+
74
+ == I've found a bug! Where do I file it?
75
+
76
+ Uh oh. After contacting the mailing list, you've found that you've actually
77
+ discovered a bug. You can file the bug at the
78
+ {github issues page}[http://github.com/luislavena/sqlite3-ruby/issues]
79
+ which can be found here:
80
+
81
+ * http://github.com/luislavena/sqlite3-ruby/issues
82
+
83
+ == Usage
84
+
85
+ For help figuring out the SQLite3/Ruby interface, check out the
86
+ SYNOPSIS as well as the RDoc. It includes examples of
87
+ usage. If you have any questions that you feel should be address in the
88
+ FAQ, please send them to {the mailing list}[http://groups.google.com/group/sqlite3-ruby]
89
+
90
+ == Source Code
91
+
92
+ The source repository is accessible via git:
93
+
94
+ git clone git://github.com/luislavena/sqlite3-ruby.git
95
+
@@ -0,0 +1,10 @@
1
+ #
2
+ # NOTE: Keep this file clean.
3
+ # Add your customizations inside tasks directory.
4
+ # Thank You.
5
+ #
6
+
7
+ # load rakefile extensions (tasks)
8
+ Dir['tasks/*.rake'].sort.each { |f| load f }
9
+
10
+ # vim: syntax=ruby
@@ -0,0 +1,168 @@
1
+ #ifdef HAVE_SQLITE3_BACKUP_INIT
2
+
3
+ #include <sqlite3_ruby.h>
4
+
5
+ #define REQUIRE_OPEN_BACKUP(_ctxt) \
6
+ if(!_ctxt->p) \
7
+ rb_raise(rb_path2class("SQLite3::Exception"), "cannot use a closed backup");
8
+
9
+ VALUE cSqlite3Backup;
10
+
11
+ static void deallocate(void * ctx)
12
+ {
13
+ sqlite3BackupRubyPtr c = (sqlite3BackupRubyPtr)ctx;
14
+ xfree(c);
15
+ }
16
+
17
+ static VALUE allocate(VALUE klass)
18
+ {
19
+ sqlite3BackupRubyPtr ctx = xcalloc((size_t)1, sizeof(sqlite3BackupRuby));
20
+ return Data_Wrap_Struct(klass, NULL, deallocate, ctx);
21
+ }
22
+
23
+ /* call-seq: SQLite3::Backup.new(dstdb, dstname, srcdb, srcname)
24
+ *
25
+ * Initialize backup the backup.
26
+ *
27
+ * dstdb:
28
+ * the destination SQLite3::Database object.
29
+ * dstname:
30
+ * the destination's database name.
31
+ * srcdb:
32
+ * the source SQLite3::Database object.
33
+ * srcname:
34
+ * the source's database name.
35
+ *
36
+ * The database name is "main", "temp", or the name specified in an
37
+ * ATTACH statement.
38
+ *
39
+ * This feature requires SQLite 3.6.11 or later.
40
+ *
41
+ * require 'sqlite3'
42
+ * sdb = SQLite3::Database.new('src.sqlite3')
43
+ *
44
+ * ddb = SQLite3::Database.new(':memory:')
45
+ * b = SQLite3::Backup.new(ddb, 'main', sdb, 'main')
46
+ * p [b.remaining, b.pagecount] # invalid value; for example [0, 0]
47
+ * begin
48
+ * p b.step(1) #=> OK or DONE
49
+ * p [b.remaining, b.pagecount]
50
+ * end while b.remaining > 0
51
+ * b.finish
52
+ *
53
+ * ddb = SQLite3::Database.new(':memory:')
54
+ * b = SQLite3::Backup.new(ddb, 'main', sdb, 'main')
55
+ * b.step(-1) #=> DONE
56
+ * b.finish
57
+ *
58
+ */
59
+ static VALUE initialize(VALUE self, VALUE dstdb, VALUE dstname, VALUE srcdb, VALUE srcname)
60
+ {
61
+ sqlite3BackupRubyPtr ctx;
62
+ sqlite3RubyPtr ddb_ctx, sdb_ctx;
63
+ sqlite3_backup *pBackup;
64
+
65
+ Data_Get_Struct(self, sqlite3BackupRuby, ctx);
66
+ Data_Get_Struct(dstdb, sqlite3Ruby, ddb_ctx);
67
+ Data_Get_Struct(srcdb, sqlite3Ruby, sdb_ctx);
68
+
69
+ if(!sdb_ctx->db)
70
+ rb_raise(rb_eArgError, "cannot backup from a closed database");
71
+ if(!ddb_ctx->db)
72
+ rb_raise(rb_eArgError, "cannot backup to a closed database");
73
+
74
+ pBackup = sqlite3_backup_init(ddb_ctx->db, StringValuePtr(dstname),
75
+ sdb_ctx->db, StringValuePtr(srcname));
76
+ if( pBackup ){
77
+ ctx->p = pBackup;
78
+ }
79
+ else {
80
+ CHECK(ddb_ctx->db, sqlite3_errcode(ddb_ctx->db));
81
+ }
82
+
83
+ return self;
84
+ }
85
+
86
+ /* call-seq: SQLite3::Backup#step(nPage)
87
+ *
88
+ * Copy database pages up to +nPage+.
89
+ * If negative, copy all remaining source pages.
90
+ *
91
+ * If all pages are copied, it returns SQLite3::Constants::ErrorCode::DONE.
92
+ * When coping is not done, it returns SQLite3::Constants::ErrorCode::OK.
93
+ * When some errors occur, it returns the error code.
94
+ */
95
+ static VALUE step(VALUE self, VALUE nPage)
96
+ {
97
+ sqlite3BackupRubyPtr ctx;
98
+ int status;
99
+
100
+ Data_Get_Struct(self, sqlite3BackupRuby, ctx);
101
+ REQUIRE_OPEN_BACKUP(ctx);
102
+ status = sqlite3_backup_step(ctx->p, NUM2INT(nPage));
103
+ return INT2NUM(status);
104
+ }
105
+
106
+ /* call-seq: SQLite3::Backup#finish
107
+ *
108
+ * Destroy the backup object.
109
+ */
110
+ static VALUE finish(VALUE self)
111
+ {
112
+ sqlite3BackupRubyPtr ctx;
113
+
114
+ Data_Get_Struct(self, sqlite3BackupRuby, ctx);
115
+ REQUIRE_OPEN_BACKUP(ctx);
116
+ (void)sqlite3_backup_finish(ctx->p);
117
+ ctx->p = NULL;
118
+ return Qnil;
119
+ }
120
+
121
+ /* call-seq: SQLite3::Backup#remaining
122
+ *
123
+ * Returns the number of pages still to be backed up.
124
+ *
125
+ * Note that the value is only updated after step() is called,
126
+ * so before calling step() returned value is invalid.
127
+ */
128
+ static VALUE remaining(VALUE self)
129
+ {
130
+ sqlite3BackupRubyPtr ctx;
131
+
132
+ Data_Get_Struct(self, sqlite3BackupRuby, ctx);
133
+ REQUIRE_OPEN_BACKUP(ctx);
134
+ return INT2NUM(sqlite3_backup_remaining(ctx->p));
135
+ }
136
+
137
+ /* call-seq: SQLite3::Backup#pagecount
138
+ *
139
+ * Returns the total number of pages in the source database file.
140
+ *
141
+ * Note that the value is only updated after step() is called,
142
+ * so before calling step() returned value is invalid.
143
+ */
144
+ static VALUE pagecount(VALUE self)
145
+ {
146
+ sqlite3BackupRubyPtr ctx;
147
+
148
+ Data_Get_Struct(self, sqlite3BackupRuby, ctx);
149
+ REQUIRE_OPEN_BACKUP(ctx);
150
+ return INT2NUM(sqlite3_backup_pagecount(ctx->p));
151
+ }
152
+
153
+ void init_sqlite3_backup()
154
+ {
155
+ #if 0
156
+ VALUE mSqlite3 = rb_define_module("SQLite3");
157
+ #endif
158
+ cSqlite3Backup = rb_define_class_under(mSqlite3, "Backup", rb_cObject);
159
+
160
+ rb_define_alloc_func(cSqlite3Backup, allocate);
161
+ rb_define_method(cSqlite3Backup, "initialize", initialize, 4);
162
+ rb_define_method(cSqlite3Backup, "step", step, 1);
163
+ rb_define_method(cSqlite3Backup, "finish", finish, 0);
164
+ rb_define_method(cSqlite3Backup, "remaining", remaining, 0);
165
+ rb_define_method(cSqlite3Backup, "pagecount", pagecount, 0);
166
+ }
167
+
168
+ #endif
@@ -0,0 +1,15 @@
1
+ #if !defined(SQLITE3_BACKUP_RUBY) && defined(HAVE_SQLITE3_BACKUP_INIT)
2
+ #define SQLITE3_BACKUP_RUBY
3
+
4
+ #include <sqlite3_ruby.h>
5
+
6
+ struct _sqlite3BackupRuby {
7
+ sqlite3_backup *p;
8
+ };
9
+
10
+ typedef struct _sqlite3BackupRuby sqlite3BackupRuby;
11
+ typedef sqlite3BackupRuby * sqlite3BackupRubyPtr;
12
+
13
+ void init_sqlite3_backup();
14
+
15
+ #endif
@@ -0,0 +1,822 @@
1
+ #include <sqlite3_ruby.h>
2
+
3
+ #define REQUIRE_OPEN_DB(_ctxt) \
4
+ if(!_ctxt->db) \
5
+ rb_raise(rb_path2class("SQLite3::Exception"), "cannot use a closed database");
6
+
7
+ VALUE cSqlite3Database;
8
+ static VALUE sym_utf16, sym_results_as_hash, sym_type_translation;
9
+
10
+ static void deallocate(void * ctx)
11
+ {
12
+ sqlite3RubyPtr c = (sqlite3RubyPtr)ctx;
13
+ sqlite3 * db = c->db;
14
+
15
+ if(db) sqlite3_close(db);
16
+ xfree(c);
17
+ }
18
+
19
+ static VALUE allocate(VALUE klass)
20
+ {
21
+ sqlite3RubyPtr ctx = xcalloc((size_t)1, sizeof(sqlite3Ruby));
22
+ return Data_Wrap_Struct(klass, NULL, deallocate, ctx);
23
+ }
24
+
25
+ static char *
26
+ utf16_string_value_ptr(VALUE str)
27
+ {
28
+ StringValue(str);
29
+ rb_str_buf_cat(str, "\x00", 1L);
30
+ return RSTRING_PTR(str);
31
+ }
32
+
33
+ /* call-seq: SQLite3::Database.new(file, options = {})
34
+ *
35
+ * Create a new Database object that opens the given file. If utf16
36
+ * is +true+, the filename is interpreted as a UTF-16 encoded string.
37
+ *
38
+ * By default, the new database will return result rows as arrays
39
+ * (#results_as_hash) and has type translation disabled (#type_translation=).
40
+ */
41
+ static VALUE initialize(int argc, VALUE *argv, VALUE self)
42
+ {
43
+ sqlite3RubyPtr ctx;
44
+ VALUE file;
45
+ VALUE opts;
46
+ VALUE zvfs;
47
+ #ifdef HAVE_SQLITE3_OPEN_V2
48
+ int mode = SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE;
49
+ #endif
50
+ int status;
51
+
52
+ Data_Get_Struct(self, sqlite3Ruby, ctx);
53
+
54
+ rb_scan_args(argc, argv, "12", &file, &opts, &zvfs);
55
+ #if defined StringValueCStr
56
+ StringValuePtr(file);
57
+ rb_check_safe_obj(file);
58
+ #else
59
+ Check_SafeStr(file);
60
+ #endif
61
+ if(NIL_P(opts)) opts = rb_hash_new();
62
+ else Check_Type(opts, T_HASH);
63
+
64
+ #ifdef HAVE_RUBY_ENCODING_H
65
+ if(UTF16_LE_P(file) || UTF16_BE_P(file)) {
66
+ status = sqlite3_open16(utf16_string_value_ptr(file), &ctx->db);
67
+ } else {
68
+ #endif
69
+
70
+ if(Qtrue == rb_hash_aref(opts, sym_utf16)) {
71
+ status = sqlite3_open16(utf16_string_value_ptr(file), &ctx->db);
72
+ } else {
73
+
74
+ #ifdef HAVE_RUBY_ENCODING_H
75
+ if(!UTF8_P(file)) {
76
+ file = rb_str_export_to_enc(file, rb_utf8_encoding());
77
+ }
78
+ #endif
79
+
80
+ if (Qtrue == rb_hash_aref(opts, ID2SYM(rb_intern("readonly")))) {
81
+ #ifdef HAVE_SQLITE3_OPEN_V2
82
+ mode = SQLITE_OPEN_READONLY;
83
+ #else
84
+ rb_raise(rb_eNotImpError, "sqlite3-ruby was compiled against a version of sqlite that does not support readonly databases");
85
+ #endif
86
+ }
87
+ #ifdef HAVE_SQLITE3_OPEN_V2
88
+ status = sqlite3_open_v2(
89
+ StringValuePtr(file),
90
+ &ctx->db,
91
+ mode,
92
+ NIL_P(zvfs) ? NULL : StringValuePtr(zvfs)
93
+ );
94
+ #else
95
+ status = sqlite3_open(
96
+ StringValuePtr(file),
97
+ &ctx->db
98
+ );
99
+ #endif
100
+ }
101
+
102
+ #ifdef HAVE_RUBY_ENCODING_H
103
+ }
104
+ #endif
105
+
106
+ CHECK(ctx->db, status)
107
+
108
+ rb_iv_set(self, "@tracefunc", Qnil);
109
+ rb_iv_set(self, "@authorizer", Qnil);
110
+ rb_iv_set(self, "@encoding", Qnil);
111
+ rb_iv_set(self, "@busy_handler", Qnil);
112
+ rb_iv_set(self, "@collations", rb_hash_new());
113
+ rb_iv_set(self, "@functions", rb_hash_new());
114
+ rb_iv_set(self, "@results_as_hash", rb_hash_aref(opts, sym_results_as_hash));
115
+ rb_iv_set(self, "@type_translation", rb_hash_aref(opts, sym_type_translation));
116
+ #ifdef HAVE_SQLITE3_OPEN_V2
117
+ rb_iv_set(self, "@readonly", mode == SQLITE_OPEN_READONLY ? Qtrue : Qfalse);
118
+ #else
119
+ rb_iv_set(self, "@readonly", Qfalse);
120
+ #endif
121
+
122
+ if(rb_block_given_p()) {
123
+ rb_yield(self);
124
+ rb_funcall(self, rb_intern("close"), 0);
125
+ }
126
+
127
+ return self;
128
+ }
129
+
130
+ /* call-seq: db.close
131
+ *
132
+ * Closes this database.
133
+ */
134
+ static VALUE sqlite3_rb_close(VALUE self)
135
+ {
136
+ sqlite3RubyPtr ctx;
137
+ sqlite3 * db;
138
+ Data_Get_Struct(self, sqlite3Ruby, ctx);
139
+
140
+ db = ctx->db;
141
+ CHECK(db, sqlite3_close(ctx->db));
142
+
143
+ ctx->db = NULL;
144
+
145
+ return self;
146
+ }
147
+
148
+ /* call-seq: db.closed?
149
+ *
150
+ * Returns +true+ if this database instance has been closed (see #close).
151
+ */
152
+ static VALUE closed_p(VALUE self)
153
+ {
154
+ sqlite3RubyPtr ctx;
155
+ Data_Get_Struct(self, sqlite3Ruby, ctx);
156
+
157
+ if(!ctx->db) return Qtrue;
158
+
159
+ return Qfalse;
160
+ }
161
+
162
+ /* call-seq: total_changes
163
+ *
164
+ * Returns the total number of changes made to this database instance
165
+ * since it was opened.
166
+ */
167
+ static VALUE total_changes(VALUE self)
168
+ {
169
+ sqlite3RubyPtr ctx;
170
+ Data_Get_Struct(self, sqlite3Ruby, ctx);
171
+ REQUIRE_OPEN_DB(ctx);
172
+
173
+ return INT2NUM((long)sqlite3_total_changes(ctx->db));
174
+ }
175
+
176
+ static void tracefunc(void * data, const char *sql)
177
+ {
178
+ VALUE self = (VALUE)data;
179
+ VALUE thing = rb_iv_get(self, "@tracefunc");
180
+ rb_funcall(thing, rb_intern("call"), 1, rb_str_new2(sql));
181
+ }
182
+
183
+ /* call-seq:
184
+ * trace { |sql| ... }
185
+ * trace(Class.new { def call sql; end }.new)
186
+ *
187
+ * Installs (or removes) a block that will be invoked for every SQL
188
+ * statement executed. The block receives one parameter: the SQL statement
189
+ * executed. If the block is +nil+, any existing tracer will be uninstalled.
190
+ */
191
+ static VALUE trace(int argc, VALUE *argv, VALUE self)
192
+ {
193
+ sqlite3RubyPtr ctx;
194
+ VALUE block;
195
+
196
+ Data_Get_Struct(self, sqlite3Ruby, ctx);
197
+ REQUIRE_OPEN_DB(ctx);
198
+
199
+ rb_scan_args(argc, argv, "01", &block);
200
+
201
+ if(NIL_P(block) && rb_block_given_p()) block = rb_block_proc();
202
+
203
+ rb_iv_set(self, "@tracefunc", block);
204
+
205
+ sqlite3_trace(ctx->db, NIL_P(block) ? NULL : tracefunc, (void *)self);
206
+
207
+ return self;
208
+ }
209
+
210
+ static int rb_sqlite3_busy_handler(void * ctx, int count)
211
+ {
212
+ VALUE self = (VALUE)(ctx);
213
+ VALUE handle = rb_iv_get(self, "@busy_handler");
214
+ VALUE result = rb_funcall(handle, rb_intern("call"), 1, INT2NUM((long)count));
215
+
216
+ if(Qfalse == result) return 0;
217
+
218
+ return 1;
219
+ }
220
+
221
+ /* call-seq:
222
+ * busy_handler { |count| ... }
223
+ * busy_handler(Class.new { def call count; end }.new)
224
+ *
225
+ * Register a busy handler with this database instance. When a requested
226
+ * resource is busy, this handler will be invoked. If the handler returns
227
+ * +false+, the operation will be aborted; otherwise, the resource will
228
+ * be requested again.
229
+ *
230
+ * The handler will be invoked with the name of the resource that was
231
+ * busy, and the number of times it has been retried.
232
+ *
233
+ * See also the mutually exclusive #busy_timeout.
234
+ */
235
+ static VALUE busy_handler(int argc, VALUE *argv, VALUE self)
236
+ {
237
+ sqlite3RubyPtr ctx;
238
+ VALUE block;
239
+ int status;
240
+
241
+ Data_Get_Struct(self, sqlite3Ruby, ctx);
242
+ REQUIRE_OPEN_DB(ctx);
243
+
244
+ rb_scan_args(argc, argv, "01", &block);
245
+
246
+ if(NIL_P(block) && rb_block_given_p()) block = rb_block_proc();
247
+
248
+ rb_iv_set(self, "@busy_handler", block);
249
+
250
+ status = sqlite3_busy_handler(
251
+ ctx->db, NIL_P(block) ? NULL : rb_sqlite3_busy_handler, (void *)self);
252
+
253
+ CHECK(ctx->db, status);
254
+
255
+ return self;
256
+ }
257
+
258
+ /* call-seq: last_insert_row_id
259
+ *
260
+ * Obtains the unique row ID of the last row to be inserted by this Database
261
+ * instance.
262
+ */
263
+ static VALUE last_insert_row_id(VALUE self)
264
+ {
265
+ sqlite3RubyPtr ctx;
266
+ Data_Get_Struct(self, sqlite3Ruby, ctx);
267
+ REQUIRE_OPEN_DB(ctx);
268
+
269
+ return LL2NUM(sqlite3_last_insert_rowid(ctx->db));
270
+ }
271
+
272
+ static VALUE sqlite3val2rb(sqlite3_value * val)
273
+ {
274
+ switch(sqlite3_value_type(val)) {
275
+ case SQLITE_INTEGER:
276
+ return LL2NUM(sqlite3_value_int64(val));
277
+ break;
278
+ case SQLITE_FLOAT:
279
+ return rb_float_new(sqlite3_value_double(val));
280
+ break;
281
+ case SQLITE_TEXT:
282
+ return rb_tainted_str_new2((const char *)sqlite3_value_text(val));
283
+ break;
284
+ case SQLITE_BLOB: {
285
+ /* Sqlite warns calling sqlite3_value_bytes may invalidate pointer from sqlite3_value_blob,
286
+ so we explicitly get the length before getting blob pointer.
287
+ Note that rb_str_new and rb_tainted_str_new apparently create string with ASCII-8BIT (BINARY) encoding,
288
+ which is what we want, as blobs are binary
289
+ */
290
+ int len = sqlite3_value_bytes(val);
291
+ return rb_tainted_str_new((const char *)sqlite3_value_blob(val), len);
292
+ break;
293
+ }
294
+ case SQLITE_NULL:
295
+ return Qnil;
296
+ break;
297
+ default:
298
+ rb_raise(rb_eRuntimeError, "bad type"); /* FIXME */
299
+ }
300
+ }
301
+
302
+ static void set_sqlite3_func_result(sqlite3_context * ctx, VALUE result)
303
+ {
304
+ switch(TYPE(result)) {
305
+ case T_NIL:
306
+ sqlite3_result_null(ctx);
307
+ break;
308
+ case T_FIXNUM:
309
+ sqlite3_result_int64(ctx, (sqlite3_int64)FIX2LONG(result));
310
+ break;
311
+ case T_BIGNUM:
312
+ #if SIZEOF_LONG < 8
313
+ if (RBIGNUM_LEN(result) * SIZEOF_BDIGITS <= 8) {
314
+ sqlite3_result_int64(ctx, NUM2LL(result));
315
+ break;
316
+ }
317
+ #endif
318
+ case T_FLOAT:
319
+ sqlite3_result_double(ctx, NUM2DBL(result));
320
+ break;
321
+ case T_STRING:
322
+ sqlite3_result_text(
323
+ ctx,
324
+ (const char *)StringValuePtr(result),
325
+ (int)RSTRING_LEN(result),
326
+ SQLITE_TRANSIENT
327
+ );
328
+ break;
329
+ default:
330
+ rb_raise(rb_eRuntimeError, "can't return %s",
331
+ rb_class2name(CLASS_OF(result)));
332
+ }
333
+ }
334
+
335
+ static void rb_sqlite3_func(sqlite3_context * ctx, int argc, sqlite3_value **argv)
336
+ {
337
+ VALUE callable = (VALUE)sqlite3_user_data(ctx);
338
+ VALUE * params = NULL;
339
+ VALUE result;
340
+ int i;
341
+
342
+ if (argc > 0) {
343
+ params = xcalloc((size_t)argc, sizeof(VALUE *));
344
+
345
+ for(i = 0; i < argc; i++) {
346
+ VALUE param = sqlite3val2rb(argv[i]);
347
+ RB_GC_GUARD(param);
348
+ params[i] = param;
349
+ }
350
+ }
351
+
352
+ result = rb_funcall2(callable, rb_intern("call"), argc, params);
353
+ xfree(params);
354
+
355
+ set_sqlite3_func_result(ctx, result);
356
+ }
357
+
358
+ #ifndef HAVE_RB_PROC_ARITY
359
+ int rb_proc_arity(VALUE self)
360
+ {
361
+ return (int)NUM2INT(rb_funcall(self, rb_intern("arity"), 0));
362
+ }
363
+ #endif
364
+
365
+ /* call-seq: define_function(name) { |args,...| }
366
+ *
367
+ * Define a function named +name+ with +args+. The arity of the block
368
+ * will be used as the arity for the function defined.
369
+ */
370
+ static VALUE define_function(VALUE self, VALUE name)
371
+ {
372
+ sqlite3RubyPtr ctx;
373
+ VALUE block;
374
+ int status;
375
+
376
+ Data_Get_Struct(self, sqlite3Ruby, ctx);
377
+ REQUIRE_OPEN_DB(ctx);
378
+
379
+ block = rb_block_proc();
380
+
381
+ status = sqlite3_create_function(
382
+ ctx->db,
383
+ StringValuePtr(name),
384
+ rb_proc_arity(block),
385
+ SQLITE_UTF8,
386
+ (void *)block,
387
+ rb_sqlite3_func,
388
+ NULL,
389
+ NULL
390
+ );
391
+
392
+ CHECK(ctx->db, status);
393
+
394
+ rb_hash_aset(rb_iv_get(self, "@functions"), name, block);
395
+
396
+ return self;
397
+ }
398
+
399
+ static int sqlite3_obj_method_arity(VALUE obj, ID id)
400
+ {
401
+ VALUE method = rb_funcall(obj, rb_intern("method"), 1, ID2SYM(id));
402
+ VALUE arity = rb_funcall(method, rb_intern("arity"), 0);
403
+
404
+ return (int)NUM2INT(arity);
405
+ }
406
+
407
+ static void rb_sqlite3_step(sqlite3_context * ctx, int argc, sqlite3_value **argv)
408
+ {
409
+ VALUE callable = (VALUE)sqlite3_user_data(ctx);
410
+ VALUE * params = NULL;
411
+ int i;
412
+
413
+ if (argc > 0) {
414
+ params = xcalloc((size_t)argc, sizeof(VALUE *));
415
+ for(i = 0; i < argc; i++) {
416
+ params[i] = sqlite3val2rb(argv[i]);
417
+ }
418
+ }
419
+ rb_funcall2(callable, rb_intern("step"), argc, params);
420
+ xfree(params);
421
+ }
422
+
423
+ static void rb_sqlite3_final(sqlite3_context * ctx)
424
+ {
425
+ VALUE callable = (VALUE)sqlite3_user_data(ctx);
426
+ VALUE result = rb_funcall(callable, rb_intern("finalize"), 0);
427
+ set_sqlite3_func_result(ctx, result);
428
+ }
429
+
430
+ /* call-seq: define_aggregator(name, aggregator)
431
+ *
432
+ * Define an aggregate function named +name+ using the object +aggregator+.
433
+ * +aggregator+ must respond to +step+ and +finalize+. +step+ will be called
434
+ * with row information and +finalize+ must return the return value for the
435
+ * aggregator function.
436
+ */
437
+ static VALUE define_aggregator(VALUE self, VALUE name, VALUE aggregator)
438
+ {
439
+ sqlite3RubyPtr ctx;
440
+ int arity, status;
441
+
442
+ Data_Get_Struct(self, sqlite3Ruby, ctx);
443
+ REQUIRE_OPEN_DB(ctx);
444
+
445
+ arity = sqlite3_obj_method_arity(aggregator, rb_intern("step"));
446
+
447
+ status = sqlite3_create_function(
448
+ ctx->db,
449
+ StringValuePtr(name),
450
+ arity,
451
+ SQLITE_UTF8,
452
+ (void *)aggregator,
453
+ NULL,
454
+ rb_sqlite3_step,
455
+ rb_sqlite3_final
456
+ );
457
+
458
+ rb_iv_set(self, "@agregator", aggregator);
459
+
460
+ CHECK(ctx->db, status);
461
+
462
+ return self;
463
+ }
464
+
465
+ /* call-seq: interrupt
466
+ *
467
+ * Interrupts the currently executing operation, causing it to abort.
468
+ */
469
+ static VALUE interrupt(VALUE self)
470
+ {
471
+ sqlite3RubyPtr ctx;
472
+ Data_Get_Struct(self, sqlite3Ruby, ctx);
473
+ REQUIRE_OPEN_DB(ctx);
474
+
475
+ sqlite3_interrupt(ctx->db);
476
+
477
+ return self;
478
+ }
479
+
480
+ /* call-seq: errmsg
481
+ *
482
+ * Return a string describing the last error to have occurred with this
483
+ * database.
484
+ */
485
+ static VALUE errmsg(VALUE self)
486
+ {
487
+ sqlite3RubyPtr ctx;
488
+ Data_Get_Struct(self, sqlite3Ruby, ctx);
489
+ REQUIRE_OPEN_DB(ctx);
490
+
491
+ return rb_str_new2(sqlite3_errmsg(ctx->db));
492
+ }
493
+
494
+ /* call-seq: errcode
495
+ *
496
+ * Return an integer representing the last error to have occurred with this
497
+ * database.
498
+ */
499
+ static VALUE errcode_(VALUE self)
500
+ {
501
+ sqlite3RubyPtr ctx;
502
+ Data_Get_Struct(self, sqlite3Ruby, ctx);
503
+ REQUIRE_OPEN_DB(ctx);
504
+
505
+ return INT2NUM((long)sqlite3_errcode(ctx->db));
506
+ }
507
+
508
+ /* call-seq: complete?(sql)
509
+ *
510
+ * Return +true+ if the string is a valid (ie, parsable) SQL statement, and
511
+ * +false+ otherwise.
512
+ */
513
+ static VALUE complete_p(VALUE UNUSED(self), VALUE sql)
514
+ {
515
+ if(sqlite3_complete(StringValuePtr(sql)))
516
+ return Qtrue;
517
+
518
+ return Qfalse;
519
+ }
520
+
521
+ /* call-seq: changes
522
+ *
523
+ * Returns the number of changes made to this database instance by the last
524
+ * operation performed. Note that a "delete from table" without a where
525
+ * clause will not affect this value.
526
+ */
527
+ static VALUE changes(VALUE self)
528
+ {
529
+ sqlite3RubyPtr ctx;
530
+ Data_Get_Struct(self, sqlite3Ruby, ctx);
531
+ REQUIRE_OPEN_DB(ctx);
532
+
533
+ return INT2NUM(sqlite3_changes(ctx->db));
534
+ }
535
+
536
+ static int rb_sqlite3_auth(
537
+ void *ctx,
538
+ int _action,
539
+ const char * _a,
540
+ const char * _b,
541
+ const char * _c,
542
+ const char * _d)
543
+ {
544
+ VALUE self = (VALUE)ctx;
545
+ VALUE action = INT2NUM(_action);
546
+ VALUE a = _a ? rb_str_new2(_a) : Qnil;
547
+ VALUE b = _b ? rb_str_new2(_b) : Qnil;
548
+ VALUE c = _c ? rb_str_new2(_c) : Qnil;
549
+ VALUE d = _d ? rb_str_new2(_d) : Qnil;
550
+ VALUE callback = rb_iv_get(self, "@authorizer");
551
+ VALUE result = rb_funcall(callback, rb_intern("call"), 5, action, a, b, c, d);
552
+
553
+ if(T_FIXNUM == TYPE(result)) return (int)NUM2INT(result);
554
+ if(Qtrue == result) return SQLITE_OK;
555
+ if(Qfalse == result) return SQLITE_DENY;
556
+
557
+ return SQLITE_IGNORE;
558
+ }
559
+
560
+ /* call-seq: set_authorizer = auth
561
+ *
562
+ * Set the authorizer for this database. +auth+ must respond to +call+, and
563
+ * +call+ must take 5 arguments.
564
+ *
565
+ * Installs (or removes) a block that will be invoked for every access
566
+ * to the database. If the block returns 0 (or +true+), the statement
567
+ * is allowed to proceed. Returning 1 or false causes an authorization error to
568
+ * occur, and returning 2 or nil causes the access to be silently denied.
569
+ */
570
+ static VALUE set_authorizer(VALUE self, VALUE authorizer)
571
+ {
572
+ sqlite3RubyPtr ctx;
573
+ int status;
574
+
575
+ Data_Get_Struct(self, sqlite3Ruby, ctx);
576
+ REQUIRE_OPEN_DB(ctx);
577
+
578
+ status = sqlite3_set_authorizer(
579
+ ctx->db, NIL_P(authorizer) ? NULL : rb_sqlite3_auth, (void *)self
580
+ );
581
+
582
+ CHECK(ctx->db, status);
583
+
584
+ rb_iv_set(self, "@authorizer", authorizer);
585
+
586
+ return self;
587
+ }
588
+
589
+ /* call-seq: db.busy_timeout = ms
590
+ *
591
+ * Indicates that if a request for a resource terminates because that
592
+ * resource is busy, SQLite should sleep and retry for up to the indicated
593
+ * number of milliseconds. By default, SQLite does not retry
594
+ * busy resources. To restore the default behavior, send 0 as the
595
+ * +ms+ parameter.
596
+ *
597
+ * See also the mutually exclusive #busy_handler.
598
+ */
599
+ static VALUE set_busy_timeout(VALUE self, VALUE timeout)
600
+ {
601
+ sqlite3RubyPtr ctx;
602
+ Data_Get_Struct(self, sqlite3Ruby, ctx);
603
+ REQUIRE_OPEN_DB(ctx);
604
+
605
+ CHECK(ctx->db, sqlite3_busy_timeout(ctx->db, (int)NUM2INT(timeout)));
606
+
607
+ return self;
608
+ }
609
+
610
+ int rb_comparator_func(void * ctx, int a_len, const void * a, int b_len, const void * b)
611
+ {
612
+ VALUE comparator;
613
+ VALUE a_str;
614
+ VALUE b_str;
615
+ VALUE comparison;
616
+ #ifdef HAVE_RUBY_ENCODING_H
617
+ rb_encoding * internal_encoding;
618
+
619
+ internal_encoding = rb_default_internal_encoding();
620
+ #endif
621
+
622
+ comparator = (VALUE)ctx;
623
+ a_str = rb_str_new((const char *)a, a_len);
624
+ b_str = rb_str_new((const char *)b, b_len);
625
+
626
+ #ifdef HAVE_RUBY_ENCODING_H
627
+ rb_enc_associate_index(a_str, rb_utf8_encindex());
628
+ rb_enc_associate_index(b_str, rb_utf8_encindex());
629
+
630
+ if(internal_encoding) {
631
+ a_str = rb_str_export_to_enc(a_str, internal_encoding);
632
+ b_str = rb_str_export_to_enc(b_str, internal_encoding);
633
+ }
634
+ #endif
635
+
636
+ comparison = rb_funcall(comparator, rb_intern("compare"), 2, a_str, b_str);
637
+
638
+ return NUM2INT(comparison);
639
+ }
640
+
641
+ /* call-seq: db.collation(name, comparator)
642
+ *
643
+ * Add a collation with name +name+, and a +comparator+ object. The
644
+ * +comparator+ object should implement a method called "compare" that takes
645
+ * two parameters and returns an integer less than, equal to, or greater than
646
+ * 0.
647
+ */
648
+ static VALUE collation(VALUE self, VALUE name, VALUE comparator)
649
+ {
650
+ sqlite3RubyPtr ctx;
651
+ Data_Get_Struct(self, sqlite3Ruby, ctx);
652
+ REQUIRE_OPEN_DB(ctx);
653
+
654
+ CHECK(ctx->db, sqlite3_create_collation(
655
+ ctx->db,
656
+ StringValuePtr(name),
657
+ SQLITE_UTF8,
658
+ (void *)comparator,
659
+ NIL_P(comparator) ? NULL : rb_comparator_func));
660
+
661
+ /* Make sure our comparator doesn't get garbage collected. */
662
+ rb_hash_aset(rb_iv_get(self, "@collations"), name, comparator);
663
+
664
+ return self;
665
+ }
666
+
667
+ #ifdef HAVE_SQLITE3_LOAD_EXTENSION
668
+ /* call-seq: db.load_extension(file)
669
+ *
670
+ * Loads an SQLite extension library from the named file. Extension
671
+ * loading must be enabled using db.enable_load_extension(true) prior
672
+ * to calling this API.
673
+ */
674
+ static VALUE load_extension(VALUE self, VALUE file)
675
+ {
676
+ sqlite3RubyPtr ctx;
677
+ int status;
678
+ char *errMsg;
679
+ VALUE errexp;
680
+ Data_Get_Struct(self, sqlite3Ruby, ctx);
681
+ REQUIRE_OPEN_DB(ctx);
682
+
683
+ status = sqlite3_load_extension(ctx->db, RSTRING_PTR(file), 0, &errMsg);
684
+ if (status != SQLITE_OK)
685
+ {
686
+ errexp = rb_exc_new2(rb_eRuntimeError, errMsg);
687
+ sqlite3_free(errMsg);
688
+ rb_exc_raise(errexp);
689
+ }
690
+
691
+ return self;
692
+ }
693
+ #endif
694
+
695
+ #ifdef HAVE_SQLITE3_ENABLE_LOAD_EXTENSION
696
+ /* call-seq: db.enable_load_extension(onoff)
697
+ *
698
+ * Enable or disable extension loading.
699
+ */
700
+ static VALUE enable_load_extension(VALUE self, VALUE onoff)
701
+ {
702
+ sqlite3RubyPtr ctx;
703
+ int onoffparam;
704
+ Data_Get_Struct(self, sqlite3Ruby, ctx);
705
+ REQUIRE_OPEN_DB(ctx);
706
+
707
+ if (Qtrue == onoff) {
708
+ onoffparam = 1;
709
+ } else if (Qfalse == onoff) {
710
+ onoffparam = 0;
711
+ } else {
712
+ onoffparam = (int)NUM2INT(onoff);
713
+ }
714
+
715
+ CHECK(ctx->db, sqlite3_enable_load_extension(ctx->db, onoffparam));
716
+
717
+ return self;
718
+ }
719
+ #endif
720
+
721
+ #ifdef HAVE_RUBY_ENCODING_H
722
+ static int enc_cb(void * _self, int UNUSED(columns), char **data, char **UNUSED(names))
723
+ {
724
+ VALUE self = (VALUE)_self;
725
+
726
+ int index = rb_enc_find_index(data[0]);
727
+ rb_encoding * e = rb_enc_from_index(index);
728
+ rb_iv_set(self, "@encoding", rb_enc_from_encoding(e));
729
+
730
+ return 0;
731
+ }
732
+ #else
733
+ static int enc_cb(void * _self, int UNUSED(columns), char **data, char **UNUSED(names))
734
+ {
735
+ VALUE self = (VALUE)_self;
736
+
737
+ rb_iv_set(self, "@encoding", rb_str_new2(data[0]));
738
+
739
+ return 0;
740
+ }
741
+ #endif
742
+
743
+ /* call-seq: db.encoding
744
+ *
745
+ * Fetch the encoding set on this database
746
+ */
747
+ static VALUE db_encoding(VALUE self)
748
+ {
749
+ sqlite3RubyPtr ctx;
750
+ VALUE enc;
751
+
752
+ Data_Get_Struct(self, sqlite3Ruby, ctx);
753
+ REQUIRE_OPEN_DB(ctx);
754
+
755
+ enc = rb_iv_get(self, "@encoding");
756
+
757
+ if(NIL_P(enc)) {
758
+ sqlite3_exec(ctx->db, "PRAGMA encoding", enc_cb, (void *)self, NULL);
759
+ }
760
+
761
+ return rb_iv_get(self, "@encoding");
762
+ }
763
+
764
+ /* call-seq: db.transaction_active?
765
+ *
766
+ * Returns +true+ if there is a transaction active, and +false+ otherwise.
767
+ *
768
+ */
769
+ static VALUE transaction_active_p(VALUE self)
770
+ {
771
+ sqlite3RubyPtr ctx;
772
+ Data_Get_Struct(self, sqlite3Ruby, ctx);
773
+ REQUIRE_OPEN_DB(ctx);
774
+
775
+ return sqlite3_get_autocommit(ctx->db) ? Qfalse : Qtrue;
776
+ }
777
+
778
+ void init_sqlite3_database()
779
+ {
780
+ ID id_utf16, id_results_as_hash, id_type_translation;
781
+ #if 0
782
+ VALUE mSqlite3 = rb_define_module("SQLite3");
783
+ #endif
784
+ cSqlite3Database = rb_define_class_under(mSqlite3, "Database", rb_cObject);
785
+
786
+ rb_define_alloc_func(cSqlite3Database, allocate);
787
+ rb_define_method(cSqlite3Database, "initialize", initialize, -1);
788
+ rb_define_method(cSqlite3Database, "collation", collation, 2);
789
+ rb_define_method(cSqlite3Database, "close", sqlite3_rb_close, 0);
790
+ rb_define_method(cSqlite3Database, "closed?", closed_p, 0);
791
+ rb_define_method(cSqlite3Database, "total_changes", total_changes, 0);
792
+ rb_define_method(cSqlite3Database, "trace", trace, -1);
793
+ rb_define_method(cSqlite3Database, "last_insert_row_id", last_insert_row_id, 0);
794
+ rb_define_method(cSqlite3Database, "define_function", define_function, 1);
795
+ rb_define_method(cSqlite3Database, "define_aggregator", define_aggregator, 2);
796
+ rb_define_method(cSqlite3Database, "interrupt", interrupt, 0);
797
+ rb_define_method(cSqlite3Database, "errmsg", errmsg, 0);
798
+ rb_define_method(cSqlite3Database, "errcode", errcode_, 0);
799
+ rb_define_method(cSqlite3Database, "complete?", complete_p, 1);
800
+ rb_define_method(cSqlite3Database, "changes", changes, 0);
801
+ rb_define_method(cSqlite3Database, "authorizer=", set_authorizer, 1);
802
+ rb_define_method(cSqlite3Database, "busy_handler", busy_handler, -1);
803
+ rb_define_method(cSqlite3Database, "busy_timeout=", set_busy_timeout, 1);
804
+ rb_define_method(cSqlite3Database, "transaction_active?", transaction_active_p, 0);
805
+
806
+ #ifdef HAVE_SQLITE3_LOAD_EXTENSION
807
+ rb_define_method(cSqlite3Database, "load_extension", load_extension, 1);
808
+ #endif
809
+
810
+ #ifdef HAVE_SQLITE3_ENABLE_LOAD_EXTENSION
811
+ rb_define_method(cSqlite3Database, "enable_load_extension", enable_load_extension, 1);
812
+ #endif
813
+
814
+ rb_define_method(cSqlite3Database, "encoding", db_encoding, 0);
815
+
816
+ id_utf16 = rb_intern("utf16");
817
+ sym_utf16 = ID2SYM(id_utf16);
818
+ id_results_as_hash = rb_intern("results_as_hash");
819
+ sym_results_as_hash = ID2SYM(id_results_as_hash);
820
+ id_type_translation = rb_intern("type_translation");
821
+ sym_type_translation = ID2SYM(id_type_translation);
822
+ }