sqlite3-ruby 1.3.2 → 1.3.3.beta.1

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