sqlite 1.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/MIT-LICENSE +22 -0
- data/Rakefile +50 -0
- data/ext/sqlite/extconf.rb +14 -0
- data/ext/sqlite/main.c +12 -0
- data/ext/sqlite/ruby_sqlite3.c +368 -0
- data/ext/sqlite/ruby_sqlite3.h +11 -0
- data/ext/sqlite/ruby_sqlite3_stmt.c +342 -0
- data/ext/sqlite/ruby_sqlite3_stmt.h +13 -0
- data/ext/sqlite/sqlite3_dist.c +221817 -0
- data/lib/sqlite.rb +267 -0
- metadata +53 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: ace8345c8af9cd81314bed02337bb2572f5922ad
|
4
|
+
data.tar.gz: de1ed790c836c7dc9b9e4a3d08fc299eb3529cbc
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 40ce43c0b2abdc3c73bde7e7d72b059cd114f5a58e95f9e1c36a3f727498de6732c315c7d1c8df29aedc8bf3d9158d8af80ba229bd929ab005f43913cae48247
|
7
|
+
data.tar.gz: e8a255e05717d7dd918f37a3e30ff64b05765bf3a3f48673b3765b68d86a9e73242c0b7a6911c1ce5b8220687d498ec83ea4f85506fcc5f70ba0c58de7c7208c
|
data/MIT-LICENSE
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) RubyGems.org
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person
|
4
|
+
obtaining a copy of this software and associated documentation
|
5
|
+
files (the "Software"), to deal in the Software without
|
6
|
+
restriction, including without limitation the rights to use,
|
7
|
+
copy, modify, merge, publish, distribute, sublicense, and/or sell
|
8
|
+
copies of the Software, and to permit persons to whom the
|
9
|
+
Software is furnished to do so, subject to the following
|
10
|
+
conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be
|
13
|
+
included in all copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
16
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
17
|
+
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
18
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
19
|
+
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
20
|
+
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
21
|
+
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
22
|
+
OTHER DEALINGS IN THE SOFTWARE.
|
data/Rakefile
ADDED
@@ -0,0 +1,50 @@
|
|
1
|
+
require 'rake/extensiontask'
|
2
|
+
require 'rubygems/package_task'
|
3
|
+
|
4
|
+
Rake::ExtensionTask.new 'sqlite' do |ext|
|
5
|
+
|
6
|
+
# This causes the shared object to be placed in lib/sqlite/sqlite.so
|
7
|
+
#
|
8
|
+
# It allows lib/sqlite.rb to load different versions if you ship a
|
9
|
+
# precompiled extension that supports multiple ruby versions.
|
10
|
+
|
11
|
+
ext.lib_dir = 'lib/sqlite'
|
12
|
+
end
|
13
|
+
|
14
|
+
s = Gem::Specification.new 'sqlite', '1.0.2' do |s|
|
15
|
+
s.summary = 'Small, Simple SQLite extension'
|
16
|
+
s.authors = %w[mikeowens@gmail.com]
|
17
|
+
|
18
|
+
# This tells RubyGems to build an extension upon install
|
19
|
+
|
20
|
+
s.extensions = %w[ext/sqlite/extconf.rb]
|
21
|
+
|
22
|
+
# naturally you must include the extension source in the gem
|
23
|
+
|
24
|
+
s.files = %w[
|
25
|
+
MIT-LICENSE
|
26
|
+
Rakefile
|
27
|
+
ext/sqlite/extconf.rb
|
28
|
+
ext/sqlite/main.c
|
29
|
+
ext/sqlite/sqlite3_dist.c
|
30
|
+
ext/sqlite/ruby_sqlite3.c
|
31
|
+
ext/sqlite/ruby_sqlite3.h
|
32
|
+
ext/sqlite/ruby_sqlite3_stmt.c
|
33
|
+
ext/sqlite/ruby_sqlite3_stmt.h
|
34
|
+
lib/sqlite.rb
|
35
|
+
]
|
36
|
+
end
|
37
|
+
|
38
|
+
# The package task builds the gem in pkg/sqlite-1.0.gem so you can test
|
39
|
+
# installing it.
|
40
|
+
|
41
|
+
Gem::PackageTask.new s do end
|
42
|
+
|
43
|
+
# This isn't a good test, but does provide a sanity check
|
44
|
+
|
45
|
+
task test: %w[compile] do
|
46
|
+
ruby '-Ilib', '-rsqlite', '-e', 'p SQLite::Database.new()'
|
47
|
+
end
|
48
|
+
|
49
|
+
task default: :test
|
50
|
+
|
@@ -0,0 +1,14 @@
|
|
1
|
+
require 'mkmf'
|
2
|
+
|
3
|
+
# have_func returns false if a C function cannot be found. Sometimes this
|
4
|
+
# will be OK (the function changed names between versions) and sometimes it is
|
5
|
+
# not so you need to exit without creating the Makefile.
|
6
|
+
|
7
|
+
abort 'missing malloc()' unless have_func 'malloc'
|
8
|
+
abort 'missing free()' unless have_func 'free'
|
9
|
+
|
10
|
+
# Now we create the Makefile that will install the extension as
|
11
|
+
# lib/sqlite/sqlite.so.
|
12
|
+
|
13
|
+
create_makefile 'sqlite/sqlite'
|
14
|
+
|
data/ext/sqlite/main.c
ADDED
@@ -0,0 +1,368 @@
|
|
1
|
+
#include <stdbool.h>
|
2
|
+
#include <ruby.h>
|
3
|
+
|
4
|
+
#include "sqlite3.h"
|
5
|
+
#include "ruby_sqlite3.h"
|
6
|
+
#include "ruby_sqlite3_stmt.h"
|
7
|
+
|
8
|
+
#define CLASS_NAME "Database"
|
9
|
+
|
10
|
+
static VALUE m_aborted(VALUE self);
|
11
|
+
static VALUE m_init(VALUE self);
|
12
|
+
static VALUE m_open(VALUE self, VALUE db);
|
13
|
+
static VALUE m_close(VALUE self);
|
14
|
+
static VALUE m_prepare(VALUE self, VALUE sql);
|
15
|
+
static VALUE m_finalize(VALUE self, VALUE stmt);
|
16
|
+
static VALUE m_errno(VALUE self);
|
17
|
+
static VALUE m_error(VALUE self);
|
18
|
+
static VALUE m_begin(VALUE self);
|
19
|
+
static VALUE m_commit(VALUE self);
|
20
|
+
static VALUE m_rollback(VALUE self);
|
21
|
+
static VALUE m_exec(VALUE self, VALUE sql);
|
22
|
+
static VALUE m_insert_id(VALUE self);
|
23
|
+
|
24
|
+
typedef struct connection
|
25
|
+
{
|
26
|
+
sqlite3* handle;
|
27
|
+
int rc;
|
28
|
+
bool dont_delete;
|
29
|
+
} connection;
|
30
|
+
|
31
|
+
static connection* get_object(VALUE self);
|
32
|
+
|
33
|
+
static void deallocator(void* x)
|
34
|
+
{
|
35
|
+
if (x != NULL)
|
36
|
+
{
|
37
|
+
connection* c = (connection*)x;
|
38
|
+
|
39
|
+
if (c->handle != NULL)
|
40
|
+
{
|
41
|
+
if (c->dont_delete == false)
|
42
|
+
{
|
43
|
+
sqlite3_close(c->handle);
|
44
|
+
}
|
45
|
+
|
46
|
+
c->handle = NULL;
|
47
|
+
}
|
48
|
+
|
49
|
+
free(x);
|
50
|
+
}
|
51
|
+
}
|
52
|
+
|
53
|
+
static VALUE allocator(VALUE cls)
|
54
|
+
{
|
55
|
+
connection* c = (connection*)malloc(sizeof(connection));
|
56
|
+
|
57
|
+
// Set dont_delete to false -- we have to clean this up as we allocated it.
|
58
|
+
c->dont_delete == false;
|
59
|
+
|
60
|
+
return Data_Wrap_Struct(cls, NULL, deallocator, c);
|
61
|
+
}
|
62
|
+
|
63
|
+
static VALUE cls;
|
64
|
+
|
65
|
+
VALUE make_sqlite3_object(sqlite3* handle)
|
66
|
+
{
|
67
|
+
connection* c = (connection*)malloc(sizeof(connection));
|
68
|
+
|
69
|
+
// Store the handle
|
70
|
+
c->handle = handle;
|
71
|
+
|
72
|
+
// Set dont_delete to true -- we don't clean it up as we did not allocate
|
73
|
+
// it.
|
74
|
+
c->dont_delete == true;
|
75
|
+
|
76
|
+
return Data_Wrap_Struct(cls, NULL, deallocator, c);
|
77
|
+
}
|
78
|
+
|
79
|
+
void init_sqlite3(VALUE module)
|
80
|
+
{
|
81
|
+
cls = rb_define_class_under(module, CLASS_NAME, rb_cObject);
|
82
|
+
rb_define_alloc_func(cls, allocator);
|
83
|
+
|
84
|
+
rb_define_method(cls, "initialize", m_init, 0);
|
85
|
+
rb_define_method(cls, "open", m_open, 1);
|
86
|
+
rb_define_method(cls, "close", m_close, 0);
|
87
|
+
rb_define_method(cls, "prepare", m_prepare, 1);
|
88
|
+
rb_define_method(cls, "errno", m_errno, 0);
|
89
|
+
rb_define_method(cls, "error", m_error, 0);
|
90
|
+
rb_define_method(cls, "finalize", m_finalize, 1);
|
91
|
+
rb_define_method(cls, "begin", m_begin, 0);
|
92
|
+
rb_define_method(cls, "commit", m_commit, 0);
|
93
|
+
rb_define_method(cls, "rollback", m_rollback, 0);
|
94
|
+
rb_define_method(cls, "exec", m_exec, 1);
|
95
|
+
rb_define_method(cls, "insertId", m_insert_id, 0);
|
96
|
+
|
97
|
+
// SQLite constants
|
98
|
+
rb_define_global_const("SQLITE_OK", INT2NUM(SQLITE_OK));
|
99
|
+
rb_define_global_const("SQLITE_ERROR", INT2NUM(SQLITE_ERROR));
|
100
|
+
rb_define_global_const("SQLITE_INTERNAL", INT2NUM(SQLITE_INTERNAL));
|
101
|
+
rb_define_global_const("SQLITE_PERM", INT2NUM(SQLITE_PERM));
|
102
|
+
rb_define_global_const("SQLITE_ABORT", INT2NUM(SQLITE_ABORT));
|
103
|
+
rb_define_global_const("SQLITE_BUSY", INT2NUM(SQLITE_BUSY));
|
104
|
+
rb_define_global_const("SQLITE_LOCKED", INT2NUM(SQLITE_LOCKED));
|
105
|
+
rb_define_global_const("SQLITE_NOMEM", INT2NUM(SQLITE_NOMEM));
|
106
|
+
rb_define_global_const("SQLITE_READONLY", INT2NUM(SQLITE_READONLY));
|
107
|
+
rb_define_global_const("SQLITE_INTERRUPT", INT2NUM(SQLITE_INTERRUPT));
|
108
|
+
rb_define_global_const("SQLITE_IOERR", INT2NUM(SQLITE_IOERR));
|
109
|
+
rb_define_global_const("SQLITE_CORRUPT", INT2NUM(SQLITE_CORRUPT));
|
110
|
+
rb_define_global_const("SQLITE_NOTFOUND", INT2NUM(SQLITE_NOTFOUND));
|
111
|
+
rb_define_global_const("SQLITE_FULL", INT2NUM(SQLITE_FULL));
|
112
|
+
rb_define_global_const("SQLITE_CANTOPEN", INT2NUM(SQLITE_CANTOPEN));
|
113
|
+
rb_define_global_const("SQLITE_PROTOCOL", INT2NUM(SQLITE_PROTOCOL));
|
114
|
+
rb_define_global_const("SQLITE_EMPTY", INT2NUM(SQLITE_EMPTY));
|
115
|
+
rb_define_global_const("SQLITE_SCHEMA", INT2NUM(SQLITE_SCHEMA));
|
116
|
+
rb_define_global_const("SQLITE_TOOBIG", INT2NUM(SQLITE_TOOBIG));
|
117
|
+
rb_define_global_const("SQLITE_CONSTRAINT", INT2NUM(SQLITE_CONSTRAINT));
|
118
|
+
rb_define_global_const("SQLITE_MISMATCH", INT2NUM(SQLITE_MISMATCH));
|
119
|
+
rb_define_global_const("SQLITE_MISUSE", INT2NUM(SQLITE_MISUSE));
|
120
|
+
rb_define_global_const("SQLITE_NOLFS", INT2NUM(SQLITE_NOLFS));
|
121
|
+
rb_define_global_const("SQLITE_AUTH", INT2NUM(SQLITE_AUTH));
|
122
|
+
rb_define_global_const("SQLITE_ROW", INT2NUM(SQLITE_ROW));
|
123
|
+
rb_define_global_const("SQLITE_DONE", INT2NUM(SQLITE_DONE));
|
124
|
+
|
125
|
+
// SQLite storage classes
|
126
|
+
rb_define_global_const("SQLITE_INTEGER", INT2NUM(SQLITE_INTEGER));
|
127
|
+
rb_define_global_const("SQLITE_FLOAT", INT2NUM(SQLITE_FLOAT));
|
128
|
+
rb_define_global_const("SQLITE_BLOB", INT2NUM(SQLITE_BLOB));
|
129
|
+
rb_define_global_const("SQLITE_NULL", INT2NUM(SQLITE_NULL));
|
130
|
+
rb_define_global_const("SQLITE_TEXT", INT2NUM(SQLITE_TEXT));
|
131
|
+
}
|
132
|
+
|
133
|
+
VALUE m_init(VALUE self)
|
134
|
+
{
|
135
|
+
return self;
|
136
|
+
}
|
137
|
+
|
138
|
+
VALUE sqlite3_class()
|
139
|
+
{
|
140
|
+
return cls;
|
141
|
+
}
|
142
|
+
|
143
|
+
connection* get_object(VALUE self)
|
144
|
+
{
|
145
|
+
connection* c;
|
146
|
+
Data_Get_Struct(self, connection, c);
|
147
|
+
|
148
|
+
return c;
|
149
|
+
}
|
150
|
+
|
151
|
+
#define ENSURE_CONNECTION(x) \
|
152
|
+
if(x->handle == NULL) \
|
153
|
+
{ \
|
154
|
+
rb_raise( rb_eRuntimeError, "Invalid db handle"); \
|
155
|
+
}
|
156
|
+
|
157
|
+
sqlite3* get_sqlite3_handle(VALUE self)
|
158
|
+
{
|
159
|
+
connection* c;
|
160
|
+
Data_Get_Struct(self, connection, c);
|
161
|
+
|
162
|
+
return c->handle;
|
163
|
+
}
|
164
|
+
|
165
|
+
VALUE m_errno(VALUE self)
|
166
|
+
{
|
167
|
+
connection* c = get_object(self);
|
168
|
+
|
169
|
+
return INT2FIX(c->rc);
|
170
|
+
}
|
171
|
+
|
172
|
+
VALUE m_error(VALUE self)
|
173
|
+
{
|
174
|
+
connection* c = get_object(self);
|
175
|
+
|
176
|
+
ENSURE_CONNECTION(c)
|
177
|
+
|
178
|
+
return rb_str_new2(sqlite3_errmsg(c->handle));
|
179
|
+
}
|
180
|
+
|
181
|
+
VALUE m_open(VALUE self, VALUE db)
|
182
|
+
{
|
183
|
+
connection* c = get_object(self);
|
184
|
+
|
185
|
+
bool file_exists = (access(StringValuePtr(db), R_OK) == 0);
|
186
|
+
|
187
|
+
c->rc = SQLITE_OK;
|
188
|
+
c->rc = sqlite3_open(StringValuePtr(db), &c->handle);
|
189
|
+
|
190
|
+
//register_sql_functions(c->handle);
|
191
|
+
|
192
|
+
// If the file already exists
|
193
|
+
if (file_exists)
|
194
|
+
{
|
195
|
+
// sqlite3_open() will open anything and not complain. It does not check to
|
196
|
+
// see if the file is a valid SQLite database. We need to know this now. So
|
197
|
+
// we check to see if this is in fact a valid SQLite database file by
|
198
|
+
// compiling a simple statement. The compilation alone will force SQLite to
|
199
|
+
// go the the file for inforamtion, which will determine its validity. If
|
200
|
+
// this statement does not compile, we don't have a valid database.
|
201
|
+
|
202
|
+
const char* sql = "select count(*) from sqlite_master";
|
203
|
+
sqlite3_stmt* stmt;
|
204
|
+
c->rc = sqlite3_prepare(c->handle, sql, strlen(sql), &stmt, NULL);
|
205
|
+
sqlite3_finalize(stmt);
|
206
|
+
}
|
207
|
+
|
208
|
+
return INT2FIX(c->rc);
|
209
|
+
}
|
210
|
+
|
211
|
+
VALUE m_close(VALUE self)
|
212
|
+
{
|
213
|
+
connection* c = get_object(self);
|
214
|
+
|
215
|
+
ENSURE_CONNECTION(c)
|
216
|
+
|
217
|
+
if (c->handle != NULL)
|
218
|
+
{
|
219
|
+
c->rc = sqlite3_close(c->handle);
|
220
|
+
|
221
|
+
// If rc != SQLITE_OK, then there is an unfinalized statement, and the
|
222
|
+
// connection was not closed. We return c->rc to indicate this, so
|
223
|
+
// caller at least can check for this condition.
|
224
|
+
if (c->rc == SQLITE_OK)
|
225
|
+
{
|
226
|
+
// Closed. Set handle to NULL to indiciate this
|
227
|
+
c->handle = NULL;
|
228
|
+
}
|
229
|
+
}
|
230
|
+
else
|
231
|
+
{
|
232
|
+
c->rc = SQLITE_OK;
|
233
|
+
}
|
234
|
+
|
235
|
+
return INT2FIX(c->rc);
|
236
|
+
}
|
237
|
+
|
238
|
+
VALUE m_prepare(VALUE self, VALUE sql)
|
239
|
+
{
|
240
|
+
connection* c = get_object(self);
|
241
|
+
|
242
|
+
ENSURE_CONNECTION(c)
|
243
|
+
|
244
|
+
if (c->handle == NULL)
|
245
|
+
{
|
246
|
+
c->rc = SQLITE_ERROR;
|
247
|
+
|
248
|
+
return Qnil;
|
249
|
+
}
|
250
|
+
|
251
|
+
return make_sqlite3_stmt(self, c->handle, sql);
|
252
|
+
}
|
253
|
+
|
254
|
+
VALUE m_finalize(VALUE self, VALUE stmt_object)
|
255
|
+
{
|
256
|
+
Check_Type(stmt_object, T_DATA);
|
257
|
+
|
258
|
+
// Require that db be a C ext type
|
259
|
+
Check_Type(stmt_object, T_DATA);
|
260
|
+
|
261
|
+
// Require that db be of SQLite class
|
262
|
+
if (rb_obj_is_instance_of(stmt_object, sqlite3_stmt_class()) == Qfalse)
|
263
|
+
{
|
264
|
+
rb_raise( rb_eRuntimeError,
|
265
|
+
"wrong argument type %s (expected %s)",
|
266
|
+
rb_obj_classname(stmt_object),
|
267
|
+
rb_class2name(cls)
|
268
|
+
);
|
269
|
+
}
|
270
|
+
|
271
|
+
connection* c = get_object(self);
|
272
|
+
c->rc = SQLITE_OK;
|
273
|
+
|
274
|
+
statement* stmt;
|
275
|
+
Data_Get_Struct(stmt_object, statement, stmt);
|
276
|
+
|
277
|
+
c->rc = sqlite3_finalize(stmt->handle);
|
278
|
+
|
279
|
+
// Set to NULL so it won't be finalized by destructor
|
280
|
+
stmt->handle = NULL;
|
281
|
+
|
282
|
+
return INT2FIX(c->rc);
|
283
|
+
}
|
284
|
+
|
285
|
+
VALUE m_begin(VALUE self)
|
286
|
+
{
|
287
|
+
connection* c = get_object(self);
|
288
|
+
|
289
|
+
ENSURE_CONNECTION(c)
|
290
|
+
|
291
|
+
if (c->handle == NULL)
|
292
|
+
{
|
293
|
+
c->rc = SQLITE_ERROR;
|
294
|
+
|
295
|
+
return Qnil;
|
296
|
+
}
|
297
|
+
|
298
|
+
c->rc = sqlite3_exec(c->handle, "BEGIN", NULL, NULL, NULL);
|
299
|
+
|
300
|
+
return INT2FIX(c->rc);
|
301
|
+
}
|
302
|
+
|
303
|
+
VALUE m_commit(VALUE self)
|
304
|
+
{
|
305
|
+
connection* c = get_object(self);
|
306
|
+
|
307
|
+
ENSURE_CONNECTION(c)
|
308
|
+
|
309
|
+
if (c->handle == NULL)
|
310
|
+
{
|
311
|
+
c->rc = SQLITE_ERROR;
|
312
|
+
|
313
|
+
return Qnil;
|
314
|
+
}
|
315
|
+
|
316
|
+
c->rc = sqlite3_exec(c->handle, "COMMIT", NULL, NULL, NULL);
|
317
|
+
|
318
|
+
return INT2FIX(c->rc);
|
319
|
+
}
|
320
|
+
|
321
|
+
VALUE m_rollback(VALUE self)
|
322
|
+
{
|
323
|
+
connection* c = get_object(self);
|
324
|
+
|
325
|
+
ENSURE_CONNECTION(c)
|
326
|
+
|
327
|
+
if (c->handle == NULL)
|
328
|
+
{
|
329
|
+
c->rc = SQLITE_ERROR;
|
330
|
+
|
331
|
+
return Qnil;
|
332
|
+
}
|
333
|
+
|
334
|
+
c->rc = sqlite3_exec(c->handle, "ROLLBACK", NULL, NULL, NULL);
|
335
|
+
|
336
|
+
return INT2FIX(c->rc);
|
337
|
+
}
|
338
|
+
|
339
|
+
VALUE m_exec(VALUE self, VALUE sql)
|
340
|
+
{
|
341
|
+
connection* c = get_object(self);
|
342
|
+
|
343
|
+
ENSURE_CONNECTION(c)
|
344
|
+
|
345
|
+
if (c->handle == NULL)
|
346
|
+
{
|
347
|
+
c->rc = SQLITE_ERROR;
|
348
|
+
|
349
|
+
return Qnil;
|
350
|
+
}
|
351
|
+
|
352
|
+
Check_Type(sql, T_STRING);
|
353
|
+
|
354
|
+
const char* zSQL = StringValuePtr(sql);
|
355
|
+
|
356
|
+
c->rc = sqlite3_exec(c->handle, zSQL, NULL, NULL, NULL);
|
357
|
+
|
358
|
+
return INT2FIX(c->rc);
|
359
|
+
}
|
360
|
+
|
361
|
+
VALUE m_insert_id(VALUE self)
|
362
|
+
{
|
363
|
+
connection* c = get_object(self);
|
364
|
+
|
365
|
+
ENSURE_CONNECTION(c)
|
366
|
+
|
367
|
+
return INT2NUM(sqlite3_last_insert_rowid(c->handle));
|
368
|
+
}
|