sqlite-ruby 2.0.3

Sign up to get free protection for your applications and to get access to all the features.
data/ext/sqlite-api.c ADDED
@@ -0,0 +1,1412 @@
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
+
1274
+ static void
1275
+ static_function_callback( sqlite_func *func, int argc, const char **argv )
1276
+ {
1277
+ VALUE proc;
1278
+ VALUE args;
1279
+ VALUE protect_args;
1280
+ int index;
1281
+ int exception = 0;
1282
+
1283
+ proc = (VALUE)sqlite_user_data( func );
1284
+ if( TYPE(proc) == T_ARRAY )
1285
+ proc = rb_ary_entry( proc, 0 );
1286
+
1287
+ args = rb_ary_new2( argc + 1 );
1288
+ rb_ary_push( args, Data_Wrap_Struct( rb_cData, NULL, NULL, func ) );
1289
+
1290
+ for( index = 0; index < argc; index++ )
1291
+ {
1292
+ VALUE entry = Qnil;
1293
+
1294
+ if( argv[index] )
1295
+ entry = rb_str_new2( argv[index] );
1296
+
1297
+ rb_ary_push( args, entry );
1298
+ }
1299
+
1300
+ protect_args = rb_ary_new3( 2, proc, args );
1301
+ rb_protect( static_protected_function_callback,
1302
+ protect_args,
1303
+ &exception );
1304
+
1305
+ if( exception )
1306
+ {
1307
+ sqlite_set_result_error( func, "error occurred while processing function", -1 );
1308
+ }
1309
+ }
1310
+
1311
+ static void
1312
+ static_aggregate_finalize_callback( sqlite_func *func )
1313
+ {
1314
+ VALUE proc;
1315
+ VALUE args;
1316
+ VALUE protect_args;
1317
+ int exception = 0;
1318
+
1319
+ proc = rb_ary_entry( (VALUE)sqlite_user_data( func ), 1 );
1320
+ args = rb_ary_new3( 1, Data_Wrap_Struct( rb_cData, NULL, NULL, func ) );
1321
+
1322
+ protect_args = rb_ary_new3( 2, proc, args );
1323
+
1324
+ rb_protect( static_protected_function_callback,
1325
+ protect_args,
1326
+ &exception );
1327
+
1328
+ if( exception )
1329
+ {
1330
+ sqlite_set_result_error( func, "error occurred while processing aggregate finalize", -1 );
1331
+ }
1332
+ }
1333
+
1334
+ /*>=-----------------------------------------------------------------------=<*
1335
+ * MODULE INITIALIZATION
1336
+ * ------------------------------------------------------------------------
1337
+ * This is the "main" function for a Ruby extension. When Ruby loads the
1338
+ * extension, it will invoke this method to set things up. For this
1339
+ * extension, it defines the SQLite and SQLite::API modules, and then
1340
+ * declares the API method hooks.
1341
+ *>=-----------------------------------------------------------------------=<*/
1342
+ NO_RDOC
1343
+
1344
+ /**
1345
+ * Document-class: SQLite::API
1346
+ *
1347
+ * This is a one-to-one bridge between Ruby code and the C interface for SQLite.
1348
+ * It defines (more-or-less) one method per function (with #set_result being
1349
+ * one exception). It is generally not advisable to use these methods directly;
1350
+ * instead, you should use the SQLite::Database class and related interfaces,
1351
+ * which provide a more object-oriented view of this interface.
1352
+ */
1353
+ void Init_sqlite_api()
1354
+ {
1355
+ VALUE version;
1356
+
1357
+ idRow = rb_intern( "row" );
1358
+ idColumns = rb_intern( "columns" );
1359
+ idTypes = rb_intern( "types" );
1360
+ idCall = rb_intern( "call" );
1361
+
1362
+ mSQLite = rb_define_module( "SQLite" );
1363
+ mExceptions = rb_define_module_under( mSQLite, "Exceptions" );
1364
+
1365
+ DatabaseException = rb_define_class_under( mExceptions, "DatabaseException",
1366
+ rb_eStandardError );
1367
+
1368
+ static_configure_exception_classes();
1369
+
1370
+ mAPI = rb_define_module_under( mSQLite, "API" );
1371
+
1372
+ rb_define_const( mAPI, "VERSION", rb_str_new2( sqlite_libversion() ) );
1373
+ rb_define_const( mAPI, "ENCODING", rb_str_new2( sqlite_libencoding() ) );
1374
+ rb_define_const( mAPI, "NUMERIC", INT2FIX( SQLITE_NUMERIC ) );
1375
+ rb_define_const( mAPI, "TEXT", INT2FIX( SQLITE_TEXT ) );
1376
+ rb_define_const( mAPI, "ARGS", INT2FIX( SQLITE_ARGS ) );
1377
+
1378
+ rb_define_module_function( mAPI, "open", static_api_open, 2 );
1379
+ rb_define_module_function( mAPI, "close", static_api_close, 1 );
1380
+
1381
+ rb_define_module_function( mAPI, "compile", static_api_compile, 2 );
1382
+ rb_define_module_function( mAPI, "step", static_api_step, 1 );
1383
+ rb_define_module_function( mAPI, "finalize", static_api_finalize, 1 );
1384
+
1385
+ rb_define_module_function( mAPI, "last_insert_row_id",
1386
+ static_api_last_insert_row_id, 1 );
1387
+ rb_define_module_function( mAPI, "changes", static_api_changes, 1 );
1388
+
1389
+ rb_define_module_function( mAPI, "interrupt", static_api_interrupt, 1 );
1390
+
1391
+ rb_define_module_function( mAPI, "complete", static_api_complete, 1 );
1392
+
1393
+ rb_define_module_function( mAPI, "busy_handler", static_api_busy_handler, 2 );
1394
+ rb_define_module_function( mAPI, "busy_timeout", static_api_busy_timeout, 2 );
1395
+
1396
+ rb_define_module_function( mAPI, "create_function",
1397
+ static_api_create_function, 4 );
1398
+ rb_define_module_function( mAPI, "create_aggregate",
1399
+ static_api_create_aggregate, 5 );
1400
+ rb_define_module_function( mAPI, "function_type",
1401
+ static_api_function_type, 3 );
1402
+
1403
+ rb_define_module_function( mAPI, "set_result",
1404
+ static_api_set_result, 2 );
1405
+ rb_define_module_function( mAPI, "set_result_error",
1406
+ static_api_set_result_error, 2 );
1407
+
1408
+ rb_define_module_function( mAPI, "aggregate_context",
1409
+ static_api_aggregate_context, 1 );
1410
+ rb_define_module_function( mAPI, "aggregate_count",
1411
+ static_api_aggregate_count, 1 );
1412
+ }