sqlite-ruby 2.1.0-mswin32
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/README +34 -0
- data/doc/faq/faq.html +390 -0
- data/doc/faq/faq.rb +145 -0
- data/doc/faq/faq.yml +453 -0
- data/ext/extconf.rb +8 -0
- data/ext/sqlite-api.c +1414 -0
- data/lib/sqlite.rb +34 -0
- data/lib/sqlite/database.rb +682 -0
- data/lib/sqlite/parsed_statement.rb +233 -0
- data/lib/sqlite/pragmas.rb +236 -0
- data/lib/sqlite/resultset.rb +168 -0
- data/lib/sqlite/statement.rb +145 -0
- data/lib/sqlite/translator.rb +135 -0
- data/lib/sqlite/version.rb +45 -0
- data/lib/sqlite_api.so +0 -0
- data/test/db/fixtures.sql +25 -0
- data/test/tc_api_core.rb +201 -0
- data/test/tc_arrayfields.rb +74 -0
- data/test/tc_database.rb +335 -0
- data/test/tc_parsed_statement.rb +160 -0
- data/test/tc_pragmas.rb +207 -0
- data/test/tc_translator.rb +115 -0
- data/test/tc_type_translation.rb +55 -0
- data/test/tests.rb +133 -0
- metadata +67 -0
data/ext/extconf.rb
ADDED
data/ext/sqlite-api.c
ADDED
@@ -0,0 +1,1414 @@
|
|
1
|
+
/*-------------------------------------------------------------------------- *
|
2
|
+
* Copyright (c) 2004, Jamis Buck (jgb3@email.byu.edu)
|
3
|
+
* All rights reserved.
|
4
|
+
*
|
5
|
+
* Redistribution and use in source and binary forms, with or without
|
6
|
+
* modification, are permitted provided that the following conditions are met:
|
7
|
+
*
|
8
|
+
* * Redistributions of source code must retain the above copyright notice,
|
9
|
+
* this list of conditions and the following disclaimer.
|
10
|
+
*
|
11
|
+
* * Redistributions in binary form must reproduce the above copyright
|
12
|
+
* notice, this list of conditions and the following disclaimer in the
|
13
|
+
* documentation and/or other materials provided with the distribution.
|
14
|
+
*
|
15
|
+
* * The names of its contributors may not be used to endorse or promote
|
16
|
+
* products derived from this software without specific prior written
|
17
|
+
* permission.
|
18
|
+
*
|
19
|
+
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
20
|
+
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
21
|
+
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
22
|
+
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
23
|
+
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
24
|
+
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
25
|
+
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
26
|
+
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
27
|
+
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
28
|
+
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
29
|
+
* POSSIBILITY OF SUCH DAMAGE.
|
30
|
+
*-------------------------------------------------------------------------- */
|
31
|
+
|
32
|
+
#include <stdarg.h> /* for variable-arity methods */
|
33
|
+
#include <stdlib.h> /* malloc() */
|
34
|
+
#include <sqlite.h> /* for the SQLite API */
|
35
|
+
#include "ruby.h" /* for the Ruby API */
|
36
|
+
|
37
|
+
/* TODO: methods not yet implemented:
|
38
|
+
* sqlite_set_authorizer
|
39
|
+
* sqlite_trace
|
40
|
+
* sqlite_encode_binary
|
41
|
+
* sqlite_decode_binary
|
42
|
+
*
|
43
|
+
* sqlite_open_encrypted
|
44
|
+
* sqlite_rekey */
|
45
|
+
|
46
|
+
/*>=-----------------------------------------------------------------------=<*
|
47
|
+
* MACROS
|
48
|
+
* ------------------------------------------------------------------------
|
49
|
+
* These are for performing frequently requested tasks.
|
50
|
+
*>=-----------------------------------------------------------------------=<*/
|
51
|
+
|
52
|
+
#define GetDB(var,val) \
|
53
|
+
Data_Get_Struct( val, sqlite, var ); \
|
54
|
+
if( var == NULL ) { \
|
55
|
+
static_raise_db_error( -1, "attempt to access a closed database" ); \
|
56
|
+
}
|
57
|
+
|
58
|
+
#define GetVM(var,val) \
|
59
|
+
Data_Get_Struct( val, sqlite_vm, var ); \
|
60
|
+
if( var == NULL ) { \
|
61
|
+
return Qnil; \
|
62
|
+
}
|
63
|
+
|
64
|
+
#define GetFunc(var,val) \
|
65
|
+
Data_Get_Struct( val, sqlite_func, var )
|
66
|
+
|
67
|
+
/* special macro for helping RDoc to ignore "section"-level comments. */
|
68
|
+
#define NO_RDOC
|
69
|
+
|
70
|
+
/*>=-----------------------------------------------------------------------=<*
|
71
|
+
* CONSTANTS
|
72
|
+
* ------------------------------------------------------------------------
|
73
|
+
* These are constants used internally by the extension library.
|
74
|
+
*>=-----------------------------------------------------------------------=<*/
|
75
|
+
NO_RDOC
|
76
|
+
|
77
|
+
static VALUE mSQLite;
|
78
|
+
static VALUE mAPI;
|
79
|
+
static VALUE mExceptions;
|
80
|
+
|
81
|
+
static VALUE DatabaseException;
|
82
|
+
|
83
|
+
static ID idRow;
|
84
|
+
static ID idColumns;
|
85
|
+
static ID idTypes;
|
86
|
+
static ID idCall;
|
87
|
+
|
88
|
+
static struct {
|
89
|
+
char *name;
|
90
|
+
VALUE object;
|
91
|
+
} g_sqlite_exceptions[] = {
|
92
|
+
{ "OK", 0 },
|
93
|
+
{ "SQL", 0 },
|
94
|
+
{ "Internal", 0 },
|
95
|
+
{ "Permissions", 0 },
|
96
|
+
{ "Abort", 0 },
|
97
|
+
{ "Busy", 0 },
|
98
|
+
{ "Locked", 0 },
|
99
|
+
{ "OutOfMemory", 0 },
|
100
|
+
{ "ReadOnly", 0 },
|
101
|
+
{ "Interrupt", 0 },
|
102
|
+
{ "IOError", 0 },
|
103
|
+
{ "Corrupt", 0 },
|
104
|
+
{ "NotFound", 0 },
|
105
|
+
{ "Full", 0 },
|
106
|
+
{ "CantOpen", 0 },
|
107
|
+
{ "Protocol", 0 },
|
108
|
+
{ "Empty", 0 },
|
109
|
+
{ "SchemaChanged", 0 },
|
110
|
+
{ "TooBig", 0 },
|
111
|
+
{ "Constraint", 0 },
|
112
|
+
{ "Mismatch", 0 },
|
113
|
+
{ "Misuse", 0 },
|
114
|
+
{ "UnsupportedOSFeature", 0 },
|
115
|
+
{ "Authorization", 0 },
|
116
|
+
{ "Format", 0 },
|
117
|
+
{ "Range", 0 },
|
118
|
+
{ "NotADatabase", 0 },
|
119
|
+
{ NULL, 0 }
|
120
|
+
};
|
121
|
+
|
122
|
+
#ifdef DONT_DEFINE___RDOC_PURPOSES_ONLY
|
123
|
+
x = rb_define_class_under( mExceptions, "SQLException", DatabaseException )
|
124
|
+
x = rb_define_class_under( mExceptions, "InternalException", DatabaseException )
|
125
|
+
x = rb_define_class_under( mExceptions, "PermissionsException", DatabaseException )
|
126
|
+
x = rb_define_class_under( mExceptions, "AbortException", DatabaseException )
|
127
|
+
x = rb_define_class_under( mExceptions, "BusyException", DatabaseException )
|
128
|
+
x = rb_define_class_under( mExceptions, "LockedException", DatabaseException )
|
129
|
+
x = rb_define_class_under( mExceptions, "OutOfMemoryException", DatabaseException )
|
130
|
+
x = rb_define_class_under( mExceptions, "ReadOnlyException", DatabaseException )
|
131
|
+
x = rb_define_class_under( mExceptions, "InterruptException", DatabaseException )
|
132
|
+
x = rb_define_class_under( mExceptions, "IOErrorException", DatabaseException )
|
133
|
+
x = rb_define_class_under( mExceptions, "CorruptException", DatabaseException )
|
134
|
+
x = rb_define_class_under( mExceptions, "NotFoundException", DatabaseException )
|
135
|
+
x = rb_define_class_under( mExceptions, "FullException", DatabaseException )
|
136
|
+
x = rb_define_class_under( mExceptions, "CantOpenException", DatabaseException )
|
137
|
+
x = rb_define_class_under( mExceptions, "ProtocolException", DatabaseException )
|
138
|
+
x = rb_define_class_under( mExceptions, "EmptyException", DatabaseException )
|
139
|
+
x = rb_define_class_under( mExceptions, "SchemaChangedException", DatabaseException )
|
140
|
+
x = rb_define_class_under( mExceptions, "TooBigException", DatabaseException )
|
141
|
+
x = rb_define_class_under( mExceptions, "ConstraintException", DatabaseException )
|
142
|
+
x = rb_define_class_under( mExceptions, "MismatchException", DatabaseException )
|
143
|
+
x = rb_define_class_under( mExceptions, "MisuseException", DatabaseException )
|
144
|
+
x = rb_define_class_under( mExceptions, "UnsupportedOSFeatureException", DatabaseException )
|
145
|
+
x = rb_define_class_under( mExceptions, "AuthorizationException", DatabaseException )
|
146
|
+
x = rb_define_class_under( mExceptions, "FormatException", DatabaseException )
|
147
|
+
x = rb_define_class_under( mExceptions, "RangeException", DatabaseException )
|
148
|
+
x = rb_define_class_under( mExceptions, "NotADatabaseException", DatabaseException )
|
149
|
+
#endif
|
150
|
+
|
151
|
+
/*>=-----------------------------------------------------------------------=<*
|
152
|
+
* PUBLIC FUNCTION DECLARATIONS
|
153
|
+
* ------------------------------------------------------------------------
|
154
|
+
* These functions are exported, for Ruby to access directly.
|
155
|
+
*>=-----------------------------------------------------------------------=<*/
|
156
|
+
NO_RDOC
|
157
|
+
|
158
|
+
void Init_sqlite_api();
|
159
|
+
|
160
|
+
/*>=-----------------------------------------------------------------------=<*
|
161
|
+
* PRIVATE METHOD DECLARATIONS
|
162
|
+
* ------------------------------------------------------------------------
|
163
|
+
* These are the method hooks that will be used in this extension library.
|
164
|
+
*>=-----------------------------------------------------------------------=<*/
|
165
|
+
NO_RDOC
|
166
|
+
|
167
|
+
static VALUE
|
168
|
+
static_api_open( VALUE module, VALUE file_name, VALUE mode );
|
169
|
+
|
170
|
+
static VALUE
|
171
|
+
static_api_close( VALUE module, VALUE db );
|
172
|
+
|
173
|
+
static VALUE
|
174
|
+
static_api_compile( VALUE module, VALUE db, VALUE sql );
|
175
|
+
|
176
|
+
static VALUE
|
177
|
+
static_api_bind( VALUE module, VALUE vm, VALUE idx, VALUE value );
|
178
|
+
|
179
|
+
static VALUE
|
180
|
+
static_api_finalize( VALUE module, VALUE vm );
|
181
|
+
|
182
|
+
static VALUE
|
183
|
+
static_api_reset( VALUE module, VALUE vm );
|
184
|
+
|
185
|
+
static VALUE
|
186
|
+
static_api_last_insert_row_id( VALUE module, VALUE db );
|
187
|
+
|
188
|
+
static VALUE
|
189
|
+
static_api_changes( VALUE module, VALUE db );
|
190
|
+
|
191
|
+
static VALUE
|
192
|
+
static_api_interrupt( VALUE module, VALUE db );
|
193
|
+
|
194
|
+
static VALUE
|
195
|
+
static_api_complete( VALUE module, VALUE sql );
|
196
|
+
|
197
|
+
static VALUE
|
198
|
+
static_api_busy_handler( VALUE module, VALUE db, VALUE handler );
|
199
|
+
|
200
|
+
static VALUE
|
201
|
+
static_api_busy_timeout( VALUE module, VALUE db, VALUE ms );
|
202
|
+
|
203
|
+
static VALUE
|
204
|
+
static_api_progress_handler( VALUE module, VALUE db, VALUE n, VALUE handler );
|
205
|
+
|
206
|
+
static VALUE
|
207
|
+
static_api_commit_hook( VALUE module, VALUE db, VALUE handler );
|
208
|
+
|
209
|
+
static VALUE
|
210
|
+
static_api_create_function( VALUE module, VALUE db, VALUE name, VALUE n,
|
211
|
+
VALUE proc );
|
212
|
+
|
213
|
+
static VALUE
|
214
|
+
static_api_create_aggregate( VALUE module, VALUE db, VALUE name, VALUE n,
|
215
|
+
VALUE step, VALUE finalize );
|
216
|
+
|
217
|
+
static VALUE
|
218
|
+
static_api_function_type( VALUE module, VALUE db, VALUE name, VALUE type );
|
219
|
+
|
220
|
+
static VALUE
|
221
|
+
static_api_set_result( VALUE module, VALUE func, VALUE result );
|
222
|
+
|
223
|
+
static VALUE
|
224
|
+
static_api_set_result_error( VALUE module, VALUE func, VALUE string );
|
225
|
+
|
226
|
+
static VALUE
|
227
|
+
static_api_aggregate_context( VALUE module, VALUE func );
|
228
|
+
|
229
|
+
static VALUE
|
230
|
+
static_api_aggregate_count( VALUE module, VALUE func );
|
231
|
+
|
232
|
+
/*>=-----------------------------------------------------------------------=<*
|
233
|
+
* PRIVATE FUNCTION DECLARATIONS
|
234
|
+
* ------------------------------------------------------------------------
|
235
|
+
* These are the functions that will be used in this extension library.
|
236
|
+
*>=-----------------------------------------------------------------------=<*/
|
237
|
+
NO_RDOC
|
238
|
+
|
239
|
+
static void
|
240
|
+
static_configure_exception_classes();
|
241
|
+
|
242
|
+
static void
|
243
|
+
static_raise_db_error( int code, char *msg, ... );
|
244
|
+
|
245
|
+
static void
|
246
|
+
static_raise_db_error2( int code, char **msg );
|
247
|
+
|
248
|
+
static void
|
249
|
+
static_free_vm( sqlite_vm *vm );
|
250
|
+
|
251
|
+
static int
|
252
|
+
static_busy_handler( void* cookie, const char *entity, int times );
|
253
|
+
|
254
|
+
static int
|
255
|
+
static_progress_handler( void* cookie );
|
256
|
+
|
257
|
+
static int
|
258
|
+
static_commit_hook( void* cookie );
|
259
|
+
|
260
|
+
static void
|
261
|
+
static_function_callback( sqlite_func *func, int argc, const char **argv );
|
262
|
+
|
263
|
+
static void
|
264
|
+
static_aggregate_finalize_callback( sqlite_func *func );
|
265
|
+
|
266
|
+
/*>=-----------------------------------------------------------------------=<*
|
267
|
+
* PRIVATE METHOD IMPLEMENTATIONS
|
268
|
+
* ------------------------------------------------------------------------
|
269
|
+
* Here are the implementations of the methods declared in the previous
|
270
|
+
* section.
|
271
|
+
*>=-----------------------------------------------------------------------=<*/
|
272
|
+
NO_RDOC
|
273
|
+
|
274
|
+
/**
|
275
|
+
* call-seq:
|
276
|
+
* open( file_name, mode ) -> db
|
277
|
+
*
|
278
|
+
* Open the named database file. Returns the opaque handle.
|
279
|
+
*/
|
280
|
+
static VALUE
|
281
|
+
static_api_open( VALUE module, VALUE file_name, VALUE mode )
|
282
|
+
{
|
283
|
+
char *s_file_name;
|
284
|
+
char *errmsg;
|
285
|
+
int i_mode;
|
286
|
+
sqlite *db;
|
287
|
+
|
288
|
+
Check_Type( file_name, T_STRING );
|
289
|
+
Check_Type( mode, T_FIXNUM );
|
290
|
+
|
291
|
+
s_file_name = STR2CSTR( file_name );
|
292
|
+
i_mode = FIX2INT( mode );
|
293
|
+
|
294
|
+
db = sqlite_open( s_file_name, i_mode, &errmsg );
|
295
|
+
if( db == NULL )
|
296
|
+
{
|
297
|
+
static_raise_db_error2( -1, &errmsg );
|
298
|
+
/* "raise" does not return */
|
299
|
+
}
|
300
|
+
|
301
|
+
return Data_Wrap_Struct( rb_cData, NULL, sqlite_close, db );
|
302
|
+
}
|
303
|
+
|
304
|
+
/**
|
305
|
+
* call-seq:
|
306
|
+
* close( db )
|
307
|
+
*
|
308
|
+
* Closes the given opaque database handle. The handle _must_ be one that was
|
309
|
+
* returned by a call to #open.
|
310
|
+
*/
|
311
|
+
static VALUE
|
312
|
+
static_api_close( VALUE module, VALUE db )
|
313
|
+
{
|
314
|
+
sqlite *handle;
|
315
|
+
|
316
|
+
/* FIXME: should this be executed atomically? */
|
317
|
+
GetDB( handle, db );
|
318
|
+
sqlite_close( handle );
|
319
|
+
|
320
|
+
/* don't need to free the handle anymore */
|
321
|
+
RDATA(db)->dfree = NULL;
|
322
|
+
RDATA(db)->data = NULL;
|
323
|
+
|
324
|
+
return Qnil;
|
325
|
+
}
|
326
|
+
|
327
|
+
/**
|
328
|
+
* call-seq:
|
329
|
+
* compile( db, sql ) -> [ vm, remainder ]
|
330
|
+
*
|
331
|
+
* Compiles the given SQL statement and returns a new virtual machine handle
|
332
|
+
* for executing it. Returns a tuple: [ vm, remainder ], where +remainder+ is
|
333
|
+
* any text that follows the first complete SQL statement in the +sql+
|
334
|
+
* parameter.
|
335
|
+
*/
|
336
|
+
static VALUE
|
337
|
+
static_api_compile( VALUE module, VALUE db, VALUE sql )
|
338
|
+
{
|
339
|
+
sqlite *handle;
|
340
|
+
sqlite_vm *vm;
|
341
|
+
char *errmsg;
|
342
|
+
const char *sql_tail;
|
343
|
+
int result;
|
344
|
+
VALUE tuple;
|
345
|
+
|
346
|
+
GetDB( handle, db );
|
347
|
+
Check_Type( sql, T_STRING );
|
348
|
+
|
349
|
+
result = sqlite_compile( handle,
|
350
|
+
STR2CSTR( sql ),
|
351
|
+
&sql_tail,
|
352
|
+
&vm,
|
353
|
+
&errmsg );
|
354
|
+
|
355
|
+
if( result != SQLITE_OK )
|
356
|
+
{
|
357
|
+
static_raise_db_error2( result, &errmsg );
|
358
|
+
/* "raise" does not return */
|
359
|
+
}
|
360
|
+
|
361
|
+
tuple = rb_ary_new();
|
362
|
+
rb_ary_push( tuple, Data_Wrap_Struct( rb_cData, NULL, static_free_vm, vm ) );
|
363
|
+
rb_ary_push( tuple, rb_str_new2( sql_tail ) );
|
364
|
+
|
365
|
+
return tuple;
|
366
|
+
}
|
367
|
+
|
368
|
+
/**
|
369
|
+
* call-seq:
|
370
|
+
* step( vm ) -> hash | nil
|
371
|
+
*
|
372
|
+
* Steps through a single result for the given virtual machine. Returns a
|
373
|
+
* Hash object. If there was a valid row returned, the hash will contain
|
374
|
+
* a <tt>:row</tt> key, which maps to an array of values for that row.
|
375
|
+
* In addition, the hash will (nearly) always contain a <tt>:columns</tt>
|
376
|
+
* key (naming the columns in the result) and a <tt>:types</tt> key
|
377
|
+
* (giving the data types for each column).
|
378
|
+
*
|
379
|
+
* This will return +nil+ if there was an error previously.
|
380
|
+
*/
|
381
|
+
static VALUE
|
382
|
+
static_api_step( VALUE module, VALUE vm )
|
383
|
+
{
|
384
|
+
sqlite_vm *vm_ptr;
|
385
|
+
const char **values;
|
386
|
+
const char **metadata;
|
387
|
+
int columns;
|
388
|
+
int result;
|
389
|
+
int index;
|
390
|
+
VALUE hash;
|
391
|
+
VALUE value;
|
392
|
+
|
393
|
+
GetVM( vm_ptr, vm );
|
394
|
+
hash = rb_hash_new();
|
395
|
+
|
396
|
+
result = sqlite_step( vm_ptr,
|
397
|
+
&columns,
|
398
|
+
&values,
|
399
|
+
&metadata );
|
400
|
+
|
401
|
+
switch( result )
|
402
|
+
{
|
403
|
+
case SQLITE_BUSY:
|
404
|
+
static_raise_db_error( result, "busy in step" );
|
405
|
+
|
406
|
+
case SQLITE_ROW:
|
407
|
+
value = rb_ary_new2( columns );
|
408
|
+
for( index = 0; index < columns; index++ )
|
409
|
+
{
|
410
|
+
VALUE entry = Qnil;
|
411
|
+
|
412
|
+
if( values[index] != NULL )
|
413
|
+
entry = rb_str_new2( values[index] );
|
414
|
+
|
415
|
+
rb_ary_store( value, index, entry );
|
416
|
+
}
|
417
|
+
rb_hash_aset( hash, ID2SYM(idRow), value );
|
418
|
+
|
419
|
+
case SQLITE_DONE:
|
420
|
+
value = rb_ivar_get( vm, idColumns );
|
421
|
+
|
422
|
+
if( value == Qnil )
|
423
|
+
{
|
424
|
+
value = rb_ary_new2( columns );
|
425
|
+
for( index = 0; index < columns; index++ )
|
426
|
+
{
|
427
|
+
rb_ary_store( value, index, rb_str_new2( metadata[ index ] ) );
|
428
|
+
}
|
429
|
+
rb_ivar_set( vm, idColumns, value );
|
430
|
+
}
|
431
|
+
|
432
|
+
rb_hash_aset( hash, ID2SYM(idColumns), value );
|
433
|
+
|
434
|
+
value = rb_ivar_get( vm, idTypes );
|
435
|
+
|
436
|
+
if( value == Qnil )
|
437
|
+
{
|
438
|
+
value = rb_ary_new2( columns );
|
439
|
+
for( index = 0; index < columns; index++ )
|
440
|
+
{
|
441
|
+
VALUE item = Qnil;
|
442
|
+
if( metadata[ index+columns ] )
|
443
|
+
item = rb_str_new2( metadata[ index+columns ] );
|
444
|
+
rb_ary_store( value, index, item );
|
445
|
+
}
|
446
|
+
rb_ivar_set( vm, idTypes, value );
|
447
|
+
}
|
448
|
+
|
449
|
+
rb_hash_aset( hash, ID2SYM(idTypes), value );
|
450
|
+
break;
|
451
|
+
|
452
|
+
case SQLITE_ERROR:
|
453
|
+
case SQLITE_MISUSE:
|
454
|
+
{
|
455
|
+
char *msg = NULL;
|
456
|
+
sqlite_finalize( vm_ptr, &msg );
|
457
|
+
RDATA(vm)->dfree = NULL;
|
458
|
+
RDATA(vm)->data = NULL;
|
459
|
+
static_raise_db_error2( result, &msg );
|
460
|
+
}
|
461
|
+
/* "raise" doesn't return */
|
462
|
+
|
463
|
+
default:
|
464
|
+
static_raise_db_error( -1, "[BUG] unknown result %d from sqlite_step",
|
465
|
+
result );
|
466
|
+
/* "raise" doesn't return */
|
467
|
+
}
|
468
|
+
|
469
|
+
return hash;
|
470
|
+
}
|
471
|
+
|
472
|
+
/**
|
473
|
+
* call-seq:
|
474
|
+
* finalize( vm ) -> nil
|
475
|
+
*
|
476
|
+
* Destroys the given virtual machine and releases any associated memory. Once
|
477
|
+
* finalized, the VM should not be used.
|
478
|
+
*/
|
479
|
+
static VALUE
|
480
|
+
static_api_finalize( VALUE module, VALUE vm )
|
481
|
+
{
|
482
|
+
sqlite_vm *vm_ptr;
|
483
|
+
int result;
|
484
|
+
char *errmsg;
|
485
|
+
|
486
|
+
/* FIXME: should this be executed atomically? */
|
487
|
+
GetVM( vm_ptr, vm );
|
488
|
+
|
489
|
+
result = sqlite_finalize( vm_ptr, &errmsg );
|
490
|
+
if( result != SQLITE_OK )
|
491
|
+
{
|
492
|
+
static_raise_db_error2( result, &errmsg );
|
493
|
+
/* "raise" does not return */
|
494
|
+
}
|
495
|
+
|
496
|
+
/* don't need to free the handle anymore */
|
497
|
+
RDATA(vm)->dfree = NULL;
|
498
|
+
RDATA(vm)->data = NULL;
|
499
|
+
|
500
|
+
return Qnil;
|
501
|
+
}
|
502
|
+
|
503
|
+
/**
|
504
|
+
* call-seq:
|
505
|
+
* last_insert_row_id( db ) -> fixnum
|
506
|
+
*
|
507
|
+
* Returns the unique row ID of the last insert operation.
|
508
|
+
*/
|
509
|
+
static VALUE
|
510
|
+
static_api_last_insert_row_id( VALUE module, VALUE db )
|
511
|
+
{
|
512
|
+
sqlite *handle;
|
513
|
+
|
514
|
+
GetDB( handle, db );
|
515
|
+
|
516
|
+
return INT2FIX( sqlite_last_insert_rowid( handle ) );
|
517
|
+
}
|
518
|
+
|
519
|
+
/**
|
520
|
+
* call-seq:
|
521
|
+
* changes( db ) -> fixnum
|
522
|
+
*
|
523
|
+
* Returns the number of changed rows affected by the last operation.
|
524
|
+
* (Note: doing a "delete from table" without a where clause does not affect
|
525
|
+
* the result of this method--see the documentation for SQLite itself for
|
526
|
+
* the reason behind this.)
|
527
|
+
*/
|
528
|
+
static VALUE
|
529
|
+
static_api_changes( VALUE module, VALUE db )
|
530
|
+
{
|
531
|
+
sqlite *handle;
|
532
|
+
|
533
|
+
GetDB( handle, db );
|
534
|
+
|
535
|
+
return INT2FIX( sqlite_changes( handle ) );
|
536
|
+
}
|
537
|
+
|
538
|
+
/**
|
539
|
+
* call-seq:
|
540
|
+
* interrupt( db ) -> nil
|
541
|
+
*
|
542
|
+
* Interrupts the currently executing operation.
|
543
|
+
*/
|
544
|
+
static VALUE
|
545
|
+
static_api_interrupt( VALUE module, VALUE db )
|
546
|
+
{
|
547
|
+
sqlite *handle;
|
548
|
+
|
549
|
+
GetDB( handle, db );
|
550
|
+
sqlite_interrupt( handle );
|
551
|
+
|
552
|
+
return Qnil;
|
553
|
+
}
|
554
|
+
|
555
|
+
/**
|
556
|
+
* call-seq:
|
557
|
+
* complete( sql ) -> true | false
|
558
|
+
*
|
559
|
+
* Returns +true+ if the given SQL text is complete (parsable), and
|
560
|
+
* +false+ otherwise.
|
561
|
+
*/
|
562
|
+
static VALUE
|
563
|
+
static_api_complete( VALUE module, VALUE sql )
|
564
|
+
{
|
565
|
+
Check_Type( sql, T_STRING );
|
566
|
+
return ( sqlite_complete( STR2CSTR( sql ) ) ? Qtrue : Qfalse );
|
567
|
+
}
|
568
|
+
|
569
|
+
/**
|
570
|
+
* call-seq:
|
571
|
+
* busy_handler( db, handler ) -> nil
|
572
|
+
*
|
573
|
+
* Installs a callback to be invoked whenever a request cannot be honored
|
574
|
+
* because a database is busy. The handler should take two parameters: a
|
575
|
+
* string naming the resource that was being accessed, and an integer indicating
|
576
|
+
* how many times the current request has failed due to the resource being busy.
|
577
|
+
*
|
578
|
+
* If the handler returns +false+, the operation will be aborted, with a
|
579
|
+
* SQLite::BusyException being raised. Otherwise, SQLite will attempt to
|
580
|
+
* access the resource again.
|
581
|
+
*
|
582
|
+
* See #busy_timeout for an easier way to manage the common case.
|
583
|
+
*/
|
584
|
+
static VALUE
|
585
|
+
static_api_busy_handler( VALUE module, VALUE db, VALUE handler )
|
586
|
+
{
|
587
|
+
sqlite *handle;
|
588
|
+
|
589
|
+
GetDB( handle, db );
|
590
|
+
if( handler == Qnil )
|
591
|
+
{
|
592
|
+
sqlite_busy_handler( handle, NULL, NULL );
|
593
|
+
}
|
594
|
+
else
|
595
|
+
{
|
596
|
+
if( !rb_obj_is_kind_of( handler, rb_cProc ) )
|
597
|
+
{
|
598
|
+
rb_raise( rb_eArgError, "handler must be a proc" );
|
599
|
+
}
|
600
|
+
|
601
|
+
sqlite_busy_handler( handle, static_busy_handler, (void*)handler );
|
602
|
+
}
|
603
|
+
|
604
|
+
return Qnil;
|
605
|
+
}
|
606
|
+
|
607
|
+
/**
|
608
|
+
* call-seq:
|
609
|
+
* busy_timeout( db, ms ) -> nil
|
610
|
+
*
|
611
|
+
* Specifies the number of milliseconds that SQLite should wait before retrying
|
612
|
+
* to access a busy resource. Specifying zero milliseconds restores the default
|
613
|
+
* behavior.
|
614
|
+
*/
|
615
|
+
static VALUE
|
616
|
+
static_api_busy_timeout( VALUE module, VALUE db, VALUE ms )
|
617
|
+
{
|
618
|
+
sqlite *handle;
|
619
|
+
|
620
|
+
GetDB( handle, db );
|
621
|
+
Check_Type( ms, T_FIXNUM );
|
622
|
+
|
623
|
+
sqlite_busy_timeout( handle, FIX2INT( ms ) );
|
624
|
+
|
625
|
+
return Qnil;
|
626
|
+
}
|
627
|
+
|
628
|
+
/**
|
629
|
+
* call-seq:
|
630
|
+
* create_function( db, name, args, proc ) -> nil
|
631
|
+
*
|
632
|
+
* Defines a new function that may be invoked from within an SQL
|
633
|
+
* statement. The +args+ parameter specifies how many arguments the function
|
634
|
+
* expects--use -1 to specify variable arity. The +proc+ parameter must be
|
635
|
+
* a proc that expects +args+ + 1 parameters, with the first parameter
|
636
|
+
* being an opaque handle to the function object itself:
|
637
|
+
*
|
638
|
+
* proc do |func, *args|
|
639
|
+
* ...
|
640
|
+
* end
|
641
|
+
*
|
642
|
+
* The function object is used when calling the #set_result and
|
643
|
+
* #set_result_error methods.
|
644
|
+
*/
|
645
|
+
static VALUE
|
646
|
+
static_api_create_function( VALUE module, VALUE db, VALUE name, VALUE n,
|
647
|
+
VALUE proc )
|
648
|
+
{
|
649
|
+
sqlite *handle;
|
650
|
+
int result;
|
651
|
+
|
652
|
+
GetDB( handle, db );
|
653
|
+
Check_Type( name, T_STRING );
|
654
|
+
Check_Type( n, T_FIXNUM );
|
655
|
+
if( !rb_obj_is_kind_of( proc, rb_cProc ) )
|
656
|
+
{
|
657
|
+
rb_raise( rb_eArgError, "handler must be a proc" );
|
658
|
+
}
|
659
|
+
|
660
|
+
result = sqlite_create_function( handle,
|
661
|
+
StringValueCStr(name),
|
662
|
+
FIX2INT(n),
|
663
|
+
static_function_callback,
|
664
|
+
(void*)proc );
|
665
|
+
|
666
|
+
if( result != SQLITE_OK )
|
667
|
+
{
|
668
|
+
static_raise_db_error( result, "create function %s(%d)",
|
669
|
+
StringValueCStr(name), FIX2INT(n) );
|
670
|
+
/* "raise" does not return */
|
671
|
+
}
|
672
|
+
|
673
|
+
return Qnil;
|
674
|
+
}
|
675
|
+
|
676
|
+
/**
|
677
|
+
* call-seq:
|
678
|
+
* create_aggregate( db, name, args, step, finalize ) -> nil
|
679
|
+
*
|
680
|
+
* Defines a new aggregate function that may be invoked from within an SQL
|
681
|
+
* statement. The +args+ parameter specifies how many arguments the function
|
682
|
+
* expects--use -1 to specify variable arity.
|
683
|
+
*
|
684
|
+
* The +step+ parameter specifies a proc object that will be invoked for each
|
685
|
+
* row that the function processes. It should accept an opaque handle to the
|
686
|
+
* function object, followed by its expected arguments:
|
687
|
+
*
|
688
|
+
* step = proc do |func, *args|
|
689
|
+
* ...
|
690
|
+
* end
|
691
|
+
*
|
692
|
+
* The +finalize+ parameter specifies a proc object that will be invoked after
|
693
|
+
* all rows have been processed. This gives the function an opportunity to
|
694
|
+
* aggregate and finalize the results. It should accept a single parameter:
|
695
|
+
* the opaque function handle:
|
696
|
+
*
|
697
|
+
* finalize = proc do |func|
|
698
|
+
* ...
|
699
|
+
* end
|
700
|
+
*
|
701
|
+
* The function object is used when calling the #set_result,
|
702
|
+
* #set_result_error, #aggregate_context, and #aggregate_count methods.
|
703
|
+
*/
|
704
|
+
static VALUE
|
705
|
+
static_api_create_aggregate( VALUE module, VALUE db, VALUE name, VALUE n,
|
706
|
+
VALUE step, VALUE finalize )
|
707
|
+
{
|
708
|
+
sqlite *handle;
|
709
|
+
int result;
|
710
|
+
VALUE data;
|
711
|
+
|
712
|
+
GetDB( handle, db );
|
713
|
+
Check_Type( name, T_STRING );
|
714
|
+
Check_Type( n, T_FIXNUM );
|
715
|
+
if( !rb_obj_is_kind_of( step, rb_cProc ) )
|
716
|
+
{
|
717
|
+
rb_raise( rb_eArgError, "step must be a proc" );
|
718
|
+
}
|
719
|
+
if( !rb_obj_is_kind_of( finalize, rb_cProc ) )
|
720
|
+
{
|
721
|
+
rb_raise( rb_eArgError, "finalize must be a proc" );
|
722
|
+
}
|
723
|
+
|
724
|
+
/* FIXME: will the GC kill this before it is used? */
|
725
|
+
data = rb_ary_new3( 2, step, finalize );
|
726
|
+
|
727
|
+
result = sqlite_create_aggregate( handle,
|
728
|
+
StringValueCStr(name),
|
729
|
+
FIX2INT(n),
|
730
|
+
static_function_callback,
|
731
|
+
static_aggregate_finalize_callback,
|
732
|
+
(void*)data );
|
733
|
+
|
734
|
+
if( result != SQLITE_OK )
|
735
|
+
{
|
736
|
+
static_raise_db_error( result, "create aggregate %s(%d)",
|
737
|
+
StringValueCStr(name), FIX2INT(n) );
|
738
|
+
/* "raise" does not return */
|
739
|
+
}
|
740
|
+
|
741
|
+
return Qnil;
|
742
|
+
}
|
743
|
+
|
744
|
+
/**
|
745
|
+
* call-seq:
|
746
|
+
* function_type( db, name, type ) -> nil
|
747
|
+
*
|
748
|
+
* Allows you to specify the type of the data that the named function returns. If
|
749
|
+
* type is SQLite::API::NUMERIC, then the function is expected to return a numeric
|
750
|
+
* value. If it is SQLite::API::TEXT, then the function is expected to return a
|
751
|
+
* textual value. If it is SQLite::API::ARGS, then the function returns whatever its
|
752
|
+
* arguments are. And if it is a positive (or zero) integer, then the function
|
753
|
+
* returns whatever type the argument at that position is.
|
754
|
+
*/
|
755
|
+
static VALUE
|
756
|
+
static_api_function_type( VALUE module, VALUE db, VALUE name, VALUE type )
|
757
|
+
{
|
758
|
+
sqlite *handle;
|
759
|
+
int result;
|
760
|
+
|
761
|
+
GetDB( handle, db );
|
762
|
+
Check_Type( name, T_STRING );
|
763
|
+
Check_Type( type, T_FIXNUM );
|
764
|
+
|
765
|
+
result = sqlite_function_type( handle,
|
766
|
+
StringValuePtr( name ),
|
767
|
+
FIX2INT( type ) );
|
768
|
+
|
769
|
+
if( result != SQLITE_OK )
|
770
|
+
{
|
771
|
+
static_raise_db_error( result, "function type %s(%d)",
|
772
|
+
StringValuePtr(name), FIX2INT(type) );
|
773
|
+
/* "raise" does not return */
|
774
|
+
}
|
775
|
+
|
776
|
+
return Qnil;
|
777
|
+
}
|
778
|
+
|
779
|
+
/**
|
780
|
+
* call-seq:
|
781
|
+
* set_result( func, result ) -> result
|
782
|
+
*
|
783
|
+
* Sets the result of the given function to the given value. This is typically
|
784
|
+
* called in the callback function for #create_function or the finalize
|
785
|
+
* callback in #create_aggregate. The result must be either a string, an integer,
|
786
|
+
* or a double.
|
787
|
+
*
|
788
|
+
* The +func+ parameter must be the opaque function handle as given to the
|
789
|
+
* callback functions mentioned above.
|
790
|
+
*/
|
791
|
+
static VALUE
|
792
|
+
static_api_set_result( VALUE module, VALUE func, VALUE result )
|
793
|
+
{
|
794
|
+
sqlite_func *func_ptr;
|
795
|
+
|
796
|
+
GetFunc( func_ptr, func );
|
797
|
+
switch( TYPE(result) )
|
798
|
+
{
|
799
|
+
case T_STRING:
|
800
|
+
sqlite_set_result_string( func_ptr,
|
801
|
+
RSTRING(result)->ptr,
|
802
|
+
RSTRING(result)->len );
|
803
|
+
break;
|
804
|
+
|
805
|
+
case T_FIXNUM:
|
806
|
+
sqlite_set_result_int( func_ptr, FIX2INT(result) );
|
807
|
+
break;
|
808
|
+
|
809
|
+
case T_FLOAT:
|
810
|
+
sqlite_set_result_double( func_ptr, NUM2DBL(result) );
|
811
|
+
break;
|
812
|
+
|
813
|
+
default:
|
814
|
+
static_raise_db_error( -1, "bad type in set result (%d)",
|
815
|
+
TYPE(result) );
|
816
|
+
}
|
817
|
+
|
818
|
+
return result;
|
819
|
+
}
|
820
|
+
|
821
|
+
/**
|
822
|
+
* call-seq:
|
823
|
+
* set_result_error( func, string ) -> string
|
824
|
+
*
|
825
|
+
* Sets the result of the given function to be the error message given in the
|
826
|
+
* +string+ parameter. The +func+ parameter must be an opaque function handle
|
827
|
+
* as given to the callback function for #create_function or
|
828
|
+
* #create_aggregate.
|
829
|
+
*/
|
830
|
+
static VALUE
|
831
|
+
static_api_set_result_error( VALUE module, VALUE func, VALUE string )
|
832
|
+
{
|
833
|
+
sqlite_func *func_ptr;
|
834
|
+
|
835
|
+
GetFunc( func_ptr, func );
|
836
|
+
Check_Type( string, T_STRING );
|
837
|
+
|
838
|
+
sqlite_set_result_error( func_ptr, RSTRING(string)->ptr,
|
839
|
+
RSTRING(string)->len );
|
840
|
+
|
841
|
+
return string;
|
842
|
+
}
|
843
|
+
|
844
|
+
/**
|
845
|
+
* call-seq:
|
846
|
+
* aggregate_context( func ) -> hash
|
847
|
+
*
|
848
|
+
* Returns the aggregate context for the given function. This context is a
|
849
|
+
* Hash object that is allocated on demand and is available only to the
|
850
|
+
* current invocation of the function. It may be used by aggregate functions
|
851
|
+
* to accumulate data over multiple rows, prior to being finalized.
|
852
|
+
*
|
853
|
+
* The +func+ parameter must be an opaque function handle as given to the
|
854
|
+
* callbacks for #create_aggregate.
|
855
|
+
*
|
856
|
+
* See #create_aggregate and #aggregate_count.
|
857
|
+
*/
|
858
|
+
static VALUE
|
859
|
+
static_api_aggregate_context( VALUE module, VALUE func )
|
860
|
+
{
|
861
|
+
sqlite_func *func_ptr;
|
862
|
+
VALUE *ptr;
|
863
|
+
|
864
|
+
GetFunc( func_ptr, func );
|
865
|
+
|
866
|
+
/* FIXME: pointers to VALUEs...how nice is the GC about this kind of
|
867
|
+
* thing? Especially when someone else frees the memory? */
|
868
|
+
|
869
|
+
ptr = (VALUE*)sqlite_aggregate_context( func_ptr, sizeof(VALUE) );
|
870
|
+
|
871
|
+
if( *ptr == 0 )
|
872
|
+
*ptr = rb_hash_new();
|
873
|
+
|
874
|
+
return *ptr;
|
875
|
+
}
|
876
|
+
|
877
|
+
/**
|
878
|
+
* call-seq:
|
879
|
+
* aggregate_count( func ) -> fixnum
|
880
|
+
*
|
881
|
+
* Returns the number of rows that have been processed so far by the current
|
882
|
+
* aggregate function. This always includes the current row, so that number
|
883
|
+
* that is returned will always be at least 1.
|
884
|
+
*
|
885
|
+
* The +func+ parameter must be an opaque function handle as given to the
|
886
|
+
* callbacks for #create_aggregate.
|
887
|
+
*/
|
888
|
+
static VALUE
|
889
|
+
static_api_aggregate_count( VALUE module, VALUE func )
|
890
|
+
{
|
891
|
+
sqlite_func *func_ptr;
|
892
|
+
|
893
|
+
GetFunc( func_ptr, func );
|
894
|
+
return INT2FIX( sqlite_aggregate_count( func_ptr ) );
|
895
|
+
}
|
896
|
+
|
897
|
+
/*>=-----------------------------------------------------------------------=<*
|
898
|
+
* PRIVATE FUNCTION IMPLEMENTATIONS
|
899
|
+
* ------------------------------------------------------------------------
|
900
|
+
* Here are the implementations of the functions declared previously.
|
901
|
+
*>=-----------------------------------------------------------------------=<*/
|
902
|
+
NO_RDOC
|
903
|
+
|
904
|
+
/*
|
905
|
+
* Document-class: SQLite::Exceptions
|
906
|
+
*
|
907
|
+
* This module contains all exceptions thrown by SQLite routines.
|
908
|
+
*/
|
909
|
+
|
910
|
+
/*
|
911
|
+
* Document-class: SQLite::Exceptions::DatabaseException
|
912
|
+
*
|
913
|
+
* This is the root of the SQLite exception hierarchy. This exception will
|
914
|
+
* be thrown for any general errors, or for exceptions for which SQLite itself
|
915
|
+
* did not declare a specific error code.
|
916
|
+
*/
|
917
|
+
|
918
|
+
/*
|
919
|
+
* Document-class: SQLite::Exceptions::SQLException
|
920
|
+
*
|
921
|
+
* From the SQLite documentation:
|
922
|
+
*
|
923
|
+
* "This return value indicates that there was an error in the SQL that was
|
924
|
+
* passed into the sqlite_exec."
|
925
|
+
*/
|
926
|
+
|
927
|
+
/*
|
928
|
+
* Document-class: SQLite::Exceptions::InternalException
|
929
|
+
*
|
930
|
+
* From the SQLite documentation:
|
931
|
+
*
|
932
|
+
* "This value indicates that an internal consistency check within the SQLite
|
933
|
+
* library failed. This can only happen if there is a bug in the SQLite library.
|
934
|
+
* If you ever get an SQLITE_INTERNAL reply from an sqlite_exec call, please
|
935
|
+
* report the problem on the SQLite mailing list."
|
936
|
+
*/
|
937
|
+
|
938
|
+
/*
|
939
|
+
* Document-class: SQLite::Exceptions::PermissionsException
|
940
|
+
*
|
941
|
+
* From the SQLite documentation:
|
942
|
+
*
|
943
|
+
* "This return value says that the access permissions on the database file are
|
944
|
+
* such that the file cannot be opened."
|
945
|
+
*/
|
946
|
+
|
947
|
+
/*
|
948
|
+
* Document-class: SQLite::Exceptions::AbortException
|
949
|
+
*
|
950
|
+
* From the SQLite documentation:
|
951
|
+
*
|
952
|
+
* "This value is returned if the callback function returns non-zero."
|
953
|
+
*/
|
954
|
+
|
955
|
+
/*
|
956
|
+
* Document-class: SQLite::Exceptions::BusyException
|
957
|
+
*
|
958
|
+
* From the SQLite documentation:
|
959
|
+
*
|
960
|
+
* "This return code indicates that another program or thread has the database
|
961
|
+
* locked. SQLite allows two or more threads to read the database at the same
|
962
|
+
* time, but only one thread can have the database open for writing at the same
|
963
|
+
* time. Locking in SQLite is on the entire database."
|
964
|
+
*/
|
965
|
+
|
966
|
+
/*
|
967
|
+
* Document-class: SQLite::Exceptions::LockedException
|
968
|
+
*
|
969
|
+
* From the SQLite documentation:
|
970
|
+
*
|
971
|
+
* "This return code is similar to SQLITE_BUSY in that it indicates that the
|
972
|
+
* database is locked. But the source of the lock is a recursive call to
|
973
|
+
* sqlite_exec. This return can only occur if you attempt to invoke sqlite_exec
|
974
|
+
* from within a callback routine of a query from a prior invocation of
|
975
|
+
* sqlite_exec. Recursive calls to sqlite_exec are allowed as long as they do
|
976
|
+
* not attempt to write the same table."
|
977
|
+
*/
|
978
|
+
|
979
|
+
/*
|
980
|
+
* Document-class: SQLite::Exceptions::OutOfMemoryException
|
981
|
+
*
|
982
|
+
* From the SQLite documentation:
|
983
|
+
*
|
984
|
+
* "This value is returned if a call to malloc fails."
|
985
|
+
*/
|
986
|
+
|
987
|
+
/*
|
988
|
+
* Document-class: SQLite::Exceptions::ReadOnlyException
|
989
|
+
*
|
990
|
+
* From the SQLite documentation:
|
991
|
+
*
|
992
|
+
* "This return code indicates that an attempt was made to write to a database
|
993
|
+
* file that is opened for reading only."
|
994
|
+
*/
|
995
|
+
|
996
|
+
/*
|
997
|
+
* Document-class: SQLite::Exceptions::InterruptException
|
998
|
+
*
|
999
|
+
* From the SQLite documentation:
|
1000
|
+
*
|
1001
|
+
* "This value is returned if a call to sqlite_interrupt interrupts a database
|
1002
|
+
* operation in progress."
|
1003
|
+
*/
|
1004
|
+
|
1005
|
+
/*
|
1006
|
+
* Document-class: SQLite::Exceptions::IOErrorException
|
1007
|
+
*
|
1008
|
+
* From the SQLite documentation:
|
1009
|
+
*
|
1010
|
+
* "This value is returned if the operating system informs SQLite that it is
|
1011
|
+
* unable to perform some disk I/O operation. This could mean that there is no
|
1012
|
+
* more space left on the disk."
|
1013
|
+
*/
|
1014
|
+
|
1015
|
+
/*
|
1016
|
+
* Document-class: SQLite::Exceptions::CorruptException
|
1017
|
+
*
|
1018
|
+
* From the SQLite documentation:
|
1019
|
+
*
|
1020
|
+
* "This value is returned if SQLite detects that the database it is working on
|
1021
|
+
* has become corrupted. Corruption might occur due to a rogue process writing
|
1022
|
+
* to the database file or it might happen due to an perviously (sic) undetected
|
1023
|
+
* logic error in of SQLite. This value is also returned if a disk I/O error
|
1024
|
+
* occurs in such a way that SQLite is forced to leave the database file in a
|
1025
|
+
* corrupted state. The latter should only happen due to a hardware or operating
|
1026
|
+
* system malfunction."
|
1027
|
+
*/
|
1028
|
+
|
1029
|
+
/*
|
1030
|
+
* Document-class: SQLite::Exceptions::NotFoundException
|
1031
|
+
*
|
1032
|
+
* From the SQLite documentation:
|
1033
|
+
*
|
1034
|
+
* "(Internal Only) Table or record not found."
|
1035
|
+
*/
|
1036
|
+
|
1037
|
+
/*
|
1038
|
+
* Document-class: SQLite::Exceptions::FullException
|
1039
|
+
*
|
1040
|
+
* From the SQLite documentation:
|
1041
|
+
*
|
1042
|
+
* "This value is returned if an insertion failed because there is no space
|
1043
|
+
* left on the disk, or the database is too big to hold any more information.
|
1044
|
+
* The latter case should only occur for databases that are larger than 2GB in
|
1045
|
+
* size."
|
1046
|
+
*/
|
1047
|
+
|
1048
|
+
/*
|
1049
|
+
* Document-class: SQLite::Exceptions::CantOpenException
|
1050
|
+
*
|
1051
|
+
* From the SQLite documentation:
|
1052
|
+
*
|
1053
|
+
* "This value is returned if the database file could not be opened for some
|
1054
|
+
* reason."
|
1055
|
+
*/
|
1056
|
+
|
1057
|
+
/*
|
1058
|
+
* Document-class: SQLite::Exceptions::ProtocolException
|
1059
|
+
*
|
1060
|
+
* From the SQLite documentation:
|
1061
|
+
*
|
1062
|
+
* "This value is returned if some other process is messing with file locks and
|
1063
|
+
* has violated the file locking protocol that SQLite uses on its rollback
|
1064
|
+
* journal files."
|
1065
|
+
*/
|
1066
|
+
|
1067
|
+
/*
|
1068
|
+
* Document-class: SQLite::Exceptions::EmptyException
|
1069
|
+
*
|
1070
|
+
* From the SQLite documentation:
|
1071
|
+
*
|
1072
|
+
* "(Internal Only) Database table is empty"
|
1073
|
+
*/
|
1074
|
+
|
1075
|
+
/*
|
1076
|
+
* Document-class: SQLite::Exceptions::SchemaChangedException
|
1077
|
+
*
|
1078
|
+
* From the SQLite documentation:
|
1079
|
+
*
|
1080
|
+
* "When the database first opened, SQLite reads the database schema into
|
1081
|
+
* memory and uses that schema to parse new SQL statements. If another process
|
1082
|
+
* changes the schema, the command currently being processed will abort because
|
1083
|
+
* the virtual machine code generated assumed the old schema. This is the
|
1084
|
+
* return code for such cases. Retrying the command usually will clear the
|
1085
|
+
* problem."
|
1086
|
+
*/
|
1087
|
+
|
1088
|
+
/*
|
1089
|
+
* Document-class: SQLite::Exceptions::TooBigException
|
1090
|
+
*
|
1091
|
+
* From the SQLite documentation:
|
1092
|
+
*
|
1093
|
+
* "SQLite will not store more than about 1 megabyte of data in a single row of
|
1094
|
+
* a single table. If you attempt to store more than 1 megabyte in a single
|
1095
|
+
* row, this is the return code you get."
|
1096
|
+
*/
|
1097
|
+
|
1098
|
+
/*
|
1099
|
+
* Document-class: SQLite::Exceptions::ConstraintException
|
1100
|
+
*
|
1101
|
+
* From the SQLite documentation:
|
1102
|
+
*
|
1103
|
+
* "This constant is returned if the SQL statement would have violated a
|
1104
|
+
* database constraint."
|
1105
|
+
*/
|
1106
|
+
|
1107
|
+
/*
|
1108
|
+
* Document-class: SQLite::Exceptions::MismatchException
|
1109
|
+
*
|
1110
|
+
* From the SQLite documentation:
|
1111
|
+
*
|
1112
|
+
* "This error occurs when there is an attempt to insert non-integer data into
|
1113
|
+
* a column labeled INTEGER PRIMARY KEY. For most columns, SQLite ignores the
|
1114
|
+
* data type and allows any kind of data to be stored. But an INTEGER PRIMARY
|
1115
|
+
* KEY column is only allowed to store integer data."
|
1116
|
+
*/
|
1117
|
+
|
1118
|
+
/*
|
1119
|
+
* Document-class: SQLite::Exceptions::MisuseException
|
1120
|
+
*
|
1121
|
+
* From the SQLite documentation:
|
1122
|
+
*
|
1123
|
+
* "This error might occur if one or more of the SQLite API routines is used
|
1124
|
+
* incorrectly. Examples of incorrect usage include calling sqlite_exec after
|
1125
|
+
* the database has been closed using sqlite_close or calling sqlite_exec with
|
1126
|
+
* the same database pointer simultaneously from two separate threads."
|
1127
|
+
*/
|
1128
|
+
|
1129
|
+
/*
|
1130
|
+
* Document-class: SQLite::Exceptions::UnsupportedOSFeatureException
|
1131
|
+
*
|
1132
|
+
* From the SQLite documentation:
|
1133
|
+
*
|
1134
|
+
* "This error means that you have attempts to create or access a file
|
1135
|
+
* database file that is larger that 2GB on a legacy Unix machine that
|
1136
|
+
* lacks large file support."
|
1137
|
+
*/
|
1138
|
+
|
1139
|
+
/*
|
1140
|
+
* Document-class: SQLite::Exceptions::AuthorizationException
|
1141
|
+
*
|
1142
|
+
* From the SQLite documentation:
|
1143
|
+
*
|
1144
|
+
* "This error indicates that the authorizer callback has disallowed the SQL
|
1145
|
+
* you are attempting to execute."
|
1146
|
+
*/
|
1147
|
+
|
1148
|
+
/*
|
1149
|
+
* Document-class: SQLite::Exceptions::FormatException
|
1150
|
+
*
|
1151
|
+
* From the SQLite documentation:
|
1152
|
+
*
|
1153
|
+
* "Auxiliary database format error"
|
1154
|
+
*/
|
1155
|
+
|
1156
|
+
/*
|
1157
|
+
* Document-class: SQLite::Exceptions::RangeException
|
1158
|
+
*
|
1159
|
+
* From the SQLite documentation:
|
1160
|
+
*
|
1161
|
+
* "2nd parameter to sqlite_bind out of range"
|
1162
|
+
*/
|
1163
|
+
|
1164
|
+
/*
|
1165
|
+
* Document-class: SQLite::Exceptions::NotADatabaseException
|
1166
|
+
*
|
1167
|
+
* From the SQLite documentation:
|
1168
|
+
*
|
1169
|
+
* "File opened that is not a database file"
|
1170
|
+
*/
|
1171
|
+
|
1172
|
+
static void
|
1173
|
+
static_configure_exception_classes()
|
1174
|
+
{
|
1175
|
+
int i;
|
1176
|
+
|
1177
|
+
for( i = 1; g_sqlite_exceptions[ i ].name != NULL; i++ )
|
1178
|
+
{
|
1179
|
+
char name[ 128 ];
|
1180
|
+
|
1181
|
+
sprintf( name, "%sException", g_sqlite_exceptions[ i ].name );
|
1182
|
+
g_sqlite_exceptions[ i ].object = rb_define_class_under( mExceptions, name, DatabaseException );
|
1183
|
+
}
|
1184
|
+
}
|
1185
|
+
|
1186
|
+
static void
|
1187
|
+
static_raise_db_error( int code, char *msg, ... )
|
1188
|
+
{
|
1189
|
+
va_list args;
|
1190
|
+
char message[ 2048 ];
|
1191
|
+
VALUE exc;
|
1192
|
+
|
1193
|
+
va_start( args, msg );
|
1194
|
+
vsnprintf( message, sizeof( message ), msg, args );
|
1195
|
+
va_end( args );
|
1196
|
+
|
1197
|
+
exc = ( code <= 0 ? DatabaseException : g_sqlite_exceptions[ code ].object );
|
1198
|
+
|
1199
|
+
rb_raise( exc, message );
|
1200
|
+
}
|
1201
|
+
|
1202
|
+
static void
|
1203
|
+
static_raise_db_error2( int code, char **msg )
|
1204
|
+
{
|
1205
|
+
VALUE err = rb_str_new2( *msg ? *msg : "(no message)" );
|
1206
|
+
if( *msg ) free( *msg );
|
1207
|
+
*msg = NULL;
|
1208
|
+
|
1209
|
+
static_raise_db_error( code, "%s", STR2CSTR( err ) );
|
1210
|
+
}
|
1211
|
+
|
1212
|
+
static void
|
1213
|
+
static_free_vm( sqlite_vm *vm )
|
1214
|
+
{
|
1215
|
+
/* FIXME: can sqlite_finalize be called with a second parameter of NULL? */
|
1216
|
+
sqlite_finalize( vm, NULL );
|
1217
|
+
}
|
1218
|
+
|
1219
|
+
static int
|
1220
|
+
static_busy_handler( void* cookie, const char *entity, int times )
|
1221
|
+
{
|
1222
|
+
VALUE handler = (VALUE)cookie;
|
1223
|
+
VALUE result;
|
1224
|
+
|
1225
|
+
result = rb_funcall( handler, idCall, 2, rb_str_new2( entity ),
|
1226
|
+
INT2FIX( times ) );
|
1227
|
+
|
1228
|
+
if( result == Qnil || result == Qfalse )
|
1229
|
+
return 0;
|
1230
|
+
|
1231
|
+
return 1;
|
1232
|
+
}
|
1233
|
+
|
1234
|
+
static int
|
1235
|
+
static_progress_handler( void* cookie )
|
1236
|
+
{
|
1237
|
+
VALUE handler = (VALUE)cookie;
|
1238
|
+
VALUE result;
|
1239
|
+
|
1240
|
+
result = rb_funcall( handler, idCall, 0 );
|
1241
|
+
|
1242
|
+
if( result == Qnil || result == Qfalse )
|
1243
|
+
return 0;
|
1244
|
+
|
1245
|
+
return 1;
|
1246
|
+
}
|
1247
|
+
|
1248
|
+
static int
|
1249
|
+
static_commit_hook( void* cookie )
|
1250
|
+
{
|
1251
|
+
VALUE handler = (VALUE)cookie;
|
1252
|
+
VALUE result;
|
1253
|
+
|
1254
|
+
result = rb_funcall( handler, idCall, 0 );
|
1255
|
+
|
1256
|
+
if( result == Qnil || result == Qfalse )
|
1257
|
+
return 0;
|
1258
|
+
|
1259
|
+
return 1;
|
1260
|
+
}
|
1261
|
+
|
1262
|
+
static VALUE
|
1263
|
+
static_protected_function_callback( VALUE args )
|
1264
|
+
{
|
1265
|
+
VALUE proc;
|
1266
|
+
VALUE proc_args;
|
1267
|
+
|
1268
|
+
proc = rb_ary_entry( args, 0 );
|
1269
|
+
proc_args = rb_ary_entry( args, 1 );
|
1270
|
+
|
1271
|
+
rb_apply( proc, idCall, proc_args );
|
1272
|
+
|
1273
|
+
return Qnil;
|
1274
|
+
}
|
1275
|
+
|
1276
|
+
static void
|
1277
|
+
static_function_callback( sqlite_func *func, int argc, const char **argv )
|
1278
|
+
{
|
1279
|
+
VALUE proc;
|
1280
|
+
VALUE args;
|
1281
|
+
VALUE protect_args;
|
1282
|
+
int index;
|
1283
|
+
int exception = 0;
|
1284
|
+
|
1285
|
+
proc = (VALUE)sqlite_user_data( func );
|
1286
|
+
if( TYPE(proc) == T_ARRAY )
|
1287
|
+
proc = rb_ary_entry( proc, 0 );
|
1288
|
+
|
1289
|
+
args = rb_ary_new2( argc + 1 );
|
1290
|
+
rb_ary_push( args, Data_Wrap_Struct( rb_cData, NULL, NULL, func ) );
|
1291
|
+
|
1292
|
+
for( index = 0; index < argc; index++ )
|
1293
|
+
{
|
1294
|
+
VALUE entry = Qnil;
|
1295
|
+
|
1296
|
+
if( argv[index] )
|
1297
|
+
entry = rb_str_new2( argv[index] );
|
1298
|
+
|
1299
|
+
rb_ary_push( args, entry );
|
1300
|
+
}
|
1301
|
+
|
1302
|
+
protect_args = rb_ary_new3( 2, proc, args );
|
1303
|
+
rb_protect( static_protected_function_callback,
|
1304
|
+
protect_args,
|
1305
|
+
&exception );
|
1306
|
+
|
1307
|
+
if( exception )
|
1308
|
+
{
|
1309
|
+
sqlite_set_result_error( func, "error occurred while processing function", -1 );
|
1310
|
+
}
|
1311
|
+
}
|
1312
|
+
|
1313
|
+
static void
|
1314
|
+
static_aggregate_finalize_callback( sqlite_func *func )
|
1315
|
+
{
|
1316
|
+
VALUE proc;
|
1317
|
+
VALUE args;
|
1318
|
+
VALUE protect_args;
|
1319
|
+
int exception = 0;
|
1320
|
+
|
1321
|
+
proc = rb_ary_entry( (VALUE)sqlite_user_data( func ), 1 );
|
1322
|
+
args = rb_ary_new3( 1, Data_Wrap_Struct( rb_cData, NULL, NULL, func ) );
|
1323
|
+
|
1324
|
+
protect_args = rb_ary_new3( 2, proc, args );
|
1325
|
+
|
1326
|
+
rb_protect( static_protected_function_callback,
|
1327
|
+
protect_args,
|
1328
|
+
&exception );
|
1329
|
+
|
1330
|
+
if( exception )
|
1331
|
+
{
|
1332
|
+
sqlite_set_result_error( func, "error occurred while processing aggregate finalize", -1 );
|
1333
|
+
}
|
1334
|
+
}
|
1335
|
+
|
1336
|
+
/*>=-----------------------------------------------------------------------=<*
|
1337
|
+
* MODULE INITIALIZATION
|
1338
|
+
* ------------------------------------------------------------------------
|
1339
|
+
* This is the "main" function for a Ruby extension. When Ruby loads the
|
1340
|
+
* extension, it will invoke this method to set things up. For this
|
1341
|
+
* extension, it defines the SQLite and SQLite::API modules, and then
|
1342
|
+
* declares the API method hooks.
|
1343
|
+
*>=-----------------------------------------------------------------------=<*/
|
1344
|
+
NO_RDOC
|
1345
|
+
|
1346
|
+
/**
|
1347
|
+
* Document-class: SQLite::API
|
1348
|
+
*
|
1349
|
+
* This is a one-to-one bridge between Ruby code and the C interface for SQLite.
|
1350
|
+
* It defines (more-or-less) one method per function (with #set_result being
|
1351
|
+
* one exception). It is generally not advisable to use these methods directly;
|
1352
|
+
* instead, you should use the SQLite::Database class and related interfaces,
|
1353
|
+
* which provide a more object-oriented view of this interface.
|
1354
|
+
*/
|
1355
|
+
void Init_sqlite_api()
|
1356
|
+
{
|
1357
|
+
VALUE version;
|
1358
|
+
|
1359
|
+
idRow = rb_intern( "row" );
|
1360
|
+
idColumns = rb_intern( "columns" );
|
1361
|
+
idTypes = rb_intern( "types" );
|
1362
|
+
idCall = rb_intern( "call" );
|
1363
|
+
|
1364
|
+
mSQLite = rb_define_module( "SQLite" );
|
1365
|
+
mExceptions = rb_define_module_under( mSQLite, "Exceptions" );
|
1366
|
+
|
1367
|
+
DatabaseException = rb_define_class_under( mExceptions, "DatabaseException",
|
1368
|
+
rb_eStandardError );
|
1369
|
+
|
1370
|
+
static_configure_exception_classes();
|
1371
|
+
|
1372
|
+
mAPI = rb_define_module_under( mSQLite, "API" );
|
1373
|
+
|
1374
|
+
rb_define_const( mAPI, "VERSION", rb_str_new2( sqlite_libversion() ) );
|
1375
|
+
rb_define_const( mAPI, "ENCODING", rb_str_new2( sqlite_libencoding() ) );
|
1376
|
+
rb_define_const( mAPI, "NUMERIC", INT2FIX( SQLITE_NUMERIC ) );
|
1377
|
+
rb_define_const( mAPI, "TEXT", INT2FIX( SQLITE_TEXT ) );
|
1378
|
+
rb_define_const( mAPI, "ARGS", INT2FIX( SQLITE_ARGS ) );
|
1379
|
+
|
1380
|
+
rb_define_module_function( mAPI, "open", static_api_open, 2 );
|
1381
|
+
rb_define_module_function( mAPI, "close", static_api_close, 1 );
|
1382
|
+
|
1383
|
+
rb_define_module_function( mAPI, "compile", static_api_compile, 2 );
|
1384
|
+
rb_define_module_function( mAPI, "step", static_api_step, 1 );
|
1385
|
+
rb_define_module_function( mAPI, "finalize", static_api_finalize, 1 );
|
1386
|
+
|
1387
|
+
rb_define_module_function( mAPI, "last_insert_row_id",
|
1388
|
+
static_api_last_insert_row_id, 1 );
|
1389
|
+
rb_define_module_function( mAPI, "changes", static_api_changes, 1 );
|
1390
|
+
|
1391
|
+
rb_define_module_function( mAPI, "interrupt", static_api_interrupt, 1 );
|
1392
|
+
|
1393
|
+
rb_define_module_function( mAPI, "complete", static_api_complete, 1 );
|
1394
|
+
|
1395
|
+
rb_define_module_function( mAPI, "busy_handler", static_api_busy_handler, 2 );
|
1396
|
+
rb_define_module_function( mAPI, "busy_timeout", static_api_busy_timeout, 2 );
|
1397
|
+
|
1398
|
+
rb_define_module_function( mAPI, "create_function",
|
1399
|
+
static_api_create_function, 4 );
|
1400
|
+
rb_define_module_function( mAPI, "create_aggregate",
|
1401
|
+
static_api_create_aggregate, 5 );
|
1402
|
+
rb_define_module_function( mAPI, "function_type",
|
1403
|
+
static_api_function_type, 3 );
|
1404
|
+
|
1405
|
+
rb_define_module_function( mAPI, "set_result",
|
1406
|
+
static_api_set_result, 2 );
|
1407
|
+
rb_define_module_function( mAPI, "set_result_error",
|
1408
|
+
static_api_set_result_error, 2 );
|
1409
|
+
|
1410
|
+
rb_define_module_function( mAPI, "aggregate_context",
|
1411
|
+
static_api_aggregate_context, 1 );
|
1412
|
+
rb_define_module_function( mAPI, "aggregate_count",
|
1413
|
+
static_api_aggregate_count, 1 );
|
1414
|
+
}
|