sqlite 1.0.2
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
+
}
|