amalgalite 1.4.1-x86-mingw32 → 1.7.0-x86-mingw32

Sign up to get free protection for your applications and to get access to all the features.
Files changed (47) hide show
  1. checksums.yaml +5 -5
  2. data/CONTRIBUTING.md +11 -0
  3. data/HISTORY.md +45 -0
  4. data/LICENSE +2 -0
  5. data/Manifest.txt +2 -1
  6. data/README.md +10 -14
  7. data/Rakefile +5 -5
  8. data/examples/fts5.rb +152 -0
  9. data/ext/amalgalite/c/amalgalite.c +26 -0
  10. data/ext/amalgalite/c/amalgalite_constants.c +1110 -56
  11. data/ext/amalgalite/c/amalgalite_database.c +80 -70
  12. data/ext/amalgalite/c/extconf.rb +31 -4
  13. data/ext/amalgalite/c/gen_constants.rb +313 -153
  14. data/ext/amalgalite/c/sqlite3.c +103967 -33836
  15. data/ext/amalgalite/c/sqlite3.h +5438 -1061
  16. data/ext/amalgalite/c/sqlite3ext.h +148 -12
  17. data/lib/amalgalite/2.2/amalgalite.so +0 -0
  18. data/lib/amalgalite/2.3/amalgalite.so +0 -0
  19. data/lib/amalgalite/2.4/amalgalite.so +0 -0
  20. data/lib/amalgalite/2.5/amalgalite.so +0 -0
  21. data/lib/amalgalite/2.6/amalgalite.so +0 -0
  22. data/lib/amalgalite/aggregate.rb +6 -0
  23. data/lib/amalgalite/csv_table_importer.rb +1 -1
  24. data/lib/amalgalite/database.rb +2 -53
  25. data/lib/amalgalite/profile_tap.rb +2 -2
  26. data/lib/amalgalite/statement.rb +5 -2
  27. data/lib/amalgalite/taps/io.rb +5 -2
  28. data/lib/amalgalite/trace_tap.rb +1 -1
  29. data/lib/amalgalite/type_maps/default_map.rb +2 -2
  30. data/lib/amalgalite/type_maps/storage_map.rb +1 -1
  31. data/lib/amalgalite/version.rb +1 -1
  32. data/spec/aggregate_spec.rb +4 -0
  33. data/spec/database_spec.rb +12 -15
  34. data/spec/default_map_spec.rb +1 -1
  35. data/spec/integeration_spec.rb +2 -2
  36. data/spec/json_spec.rb +24 -0
  37. data/spec/sqlite3/version_spec.rb +15 -9
  38. data/spec/storage_map_spec.rb +1 -1
  39. data/tasks/default.rake +3 -10
  40. data/tasks/extension.rake +4 -4
  41. data/tasks/this.rb +7 -5
  42. metadata +33 -25
  43. data/examples/fts3.rb +0 -144
  44. data/lib/amalgalite/1.8/amalgalite.so +0 -0
  45. data/lib/amalgalite/1.9/amalgalite.so +0 -0
  46. data/lib/amalgalite/2.0/amalgalite.so +0 -0
  47. data/lib/amalgalite/2.1/amalgalite.so +0 -0
@@ -328,22 +328,59 @@ VALUE am_sqlite3_database_exec(VALUE self, VALUE rSQL)
328
328
  }
329
329
 
330
330
  /**
331
- * This function is registered with a sqlite3 database using the sqlite3_trace
332
- * function. During the registration process a handle on a VALUE is also
333
- * registered.
331
+ * This function is registered with a sqlite3 database using the
332
+ * sqlite3_trace_v2 function. During the registration process a handle on a
333
+ * VALUE is also registered.
334
334
  *
335
335
  * When this function is called, it calls the 'trace' method on the tap object,
336
- * which is the VALUE that was registered during the sqlite3_trace call.
336
+ * which is the VALUE that was registered during the sqlite3_trace_v2 call.
337
337
  *
338
- * This function corresponds to the SQLite xTrace function specification.
338
+ * This function corresponds to the SQLite xCallback function specification.
339
+ *
340
+ * https://sqlite.org/c3ref/c_trace.html
339
341
  *
340
342
  */
341
- void amalgalite_xTrace(void* tap, const char* msg)
343
+ int amalgalite_xTraceCallback(unsigned trace_type, void* tap, void* prepared_statement, void* extra)
342
344
  {
343
345
  VALUE trace_obj = (VALUE) tap;
346
+ char* msg;
347
+ sqlite3_uint64 time;
348
+
349
+ switch(trace_type) {
350
+ case SQLITE_TRACE_STMT:
351
+ msg = (char*)extra;
352
+
353
+ /* The callback can compute the same text that would have been returned by the
354
+ * legacy sqlite3_trace() interface by using the X argument when X begins with
355
+ * "--" and invoking sqlite3_expanded_sql(P) otherwise.
356
+ */
357
+ if (0 != strncmp(msg, "--", 2)) {
358
+ msg = sqlite3_expanded_sql(prepared_statement);
359
+ }
360
+
361
+ rb_funcall( trace_obj, rb_intern("trace"), 1, rb_str_new2( msg ) );
362
+ break;
344
363
 
345
- rb_funcall( trace_obj, rb_intern("trace"), 1, rb_str_new2( msg ) );
346
- return;
364
+ case SQLITE_TRACE_PROFILE:
365
+ msg = sqlite3_expanded_sql(prepared_statement);
366
+ time = *(sqlite3_uint64*)extra;
367
+ rb_funcall( trace_obj, rb_intern("profile"),
368
+ 2, rb_str_new2( msg ), SQLUINT64_2NUM(time) );
369
+ break;
370
+
371
+ case SQLITE_TRACE_ROW:
372
+ /* not implemented */
373
+ break;
374
+
375
+ case SQLITE_TRACE_CLOSE:
376
+ /* not implemented */
377
+ break;
378
+
379
+ default:
380
+ /* nothing */
381
+ break;
382
+ }
383
+ return 0;
347
384
  }
348
385
 
349
386
 
@@ -351,12 +388,16 @@ void amalgalite_xTrace(void* tap, const char* msg)
351
388
  * call-seq:
352
389
  * database.register_trace_tap( tap_obj )
353
390
  *
354
- * This registers an object to be called with every trace event in SQLite.
391
+ * This registers an object to be called for all the trace objects in the sqlite
392
+ * system. From an SQLite perspective, the trace object is registered for both
393
+ * SQLITE_TRACE_STMT and SQLITE_TRACE_PROFILE.
355
394
  *
395
+ * The object must respond to both `trace` and `profile` methods. See
396
+ * Amalgalite::Trace::
356
397
  * This is an experimental api and is subject to change, or removal.
357
398
  *
358
399
  */
359
- VALUE am_sqlite3_database_register_trace_tap(VALUE self, VALUE tap)
400
+ VALUE am_sqlite3_database_register_trace_tap(VALUE self, VALUE tap )
360
401
  {
361
402
  am_sqlite3 *am_db;
362
403
 
@@ -367,7 +408,7 @@ VALUE am_sqlite3_database_register_trace_tap(VALUE self, VALUE tap)
367
408
  */
368
409
  if ( Qnil == tap ) {
369
410
 
370
- sqlite3_trace( am_db->db, NULL, NULL );
411
+ sqlite3_trace_v2( am_db->db, 0, NULL, NULL );
371
412
  rb_gc_unregister_address( &(am_db->trace_obj) );
372
413
  am_db->trace_obj = Qnil;
373
414
 
@@ -379,65 +420,12 @@ VALUE am_sqlite3_database_register_trace_tap(VALUE self, VALUE tap)
379
420
 
380
421
  am_db->trace_obj = tap;
381
422
  rb_gc_register_address( &(am_db->trace_obj) );
382
- sqlite3_trace( am_db->db, amalgalite_xTrace, (void *)am_db->trace_obj );
423
+ sqlite3_trace_v2( am_db->db, SQLITE_TRACE_STMT | SQLITE_TRACE_PROFILE, amalgalite_xTraceCallback, (void *)am_db->trace_obj );
383
424
  }
384
425
 
385
426
  return Qnil;
386
427
  }
387
428
 
388
-
389
- /**
390
- * the amagliate trace function to be registered with register_trace_tap
391
- * When it is called, it calls the 'trace' method on the tap object.
392
- *
393
- * This function conforms to the sqlite3 xProfile function specification.
394
- */
395
- void amalgalite_xProfile(void* tap, const char* msg, sqlite3_uint64 time)
396
- {
397
- VALUE trace_obj = (VALUE) tap;
398
-
399
- rb_funcall( trace_obj, rb_intern("profile"),
400
- 2, rb_str_new2( msg ), SQLUINT64_2NUM(time) );
401
-
402
- return;
403
- }
404
-
405
- /**
406
- * call-seq:
407
- * database.register_profile_tap( tap_obj )
408
- *
409
- * This registers an object to be called with every profile event in SQLite.
410
- *
411
- * This is an experimental api and is subject to change or removal.
412
- *
413
- */
414
- VALUE am_sqlite3_database_register_profile_tap(VALUE self, VALUE tap)
415
- {
416
- am_sqlite3 *am_db;
417
-
418
- Data_Get_Struct(self, am_sqlite3, am_db);
419
-
420
- /* Qnil, unregister the item and tell the garbage collector we are done with
421
- * it.
422
- */
423
-
424
- if ( tap == Qnil ) {
425
- sqlite3_profile( am_db->db, NULL, NULL );
426
- rb_gc_unregister_address( &(am_db->profile_obj) );
427
- am_db->profile_obj = Qnil;
428
-
429
- /* register the item and store the reference to the object in the am_db
430
- * structure. We also have to tell the Ruby garbage collector that we
431
- * point to the Ruby object from C.
432
- */
433
- } else {
434
- am_db->profile_obj = tap;
435
- rb_gc_register_address( &(am_db->profile_obj) );
436
- sqlite3_profile( am_db->db, amalgalite_xProfile, (void *)am_db->profile_obj );
437
- }
438
- return Qnil;
439
- }
440
-
441
429
  /**
442
430
  * invoke a ruby function. This is here to be used by rb_protect.
443
431
  */
@@ -794,8 +782,11 @@ void amalgalite_xStep( sqlite3_context* context, int argc, sqlite3_value** argv
794
782
  VALUE klass = (VALUE) sqlite3_user_data( context );
795
783
  result = rb_protect( amalgalite_wrap_new_aggregate, klass, &state );
796
784
 
785
+ /* exception was raised during initialization */
797
786
  if ( state ) {
798
- VALUE msg = ERROR_INFO_MESSAGE();
787
+ *aggregate_context = rb_gv_get("$!");
788
+ rb_gc_register_address( aggregate_context );
789
+ VALUE msg = rb_obj_as_string( *aggregate_context );
799
790
  sqlite3_result_error( context, RSTRING_PTR(msg), (int)RSTRING_LEN(msg));
800
791
  return;
801
792
  } else {
@@ -844,8 +835,30 @@ void amalgalite_xFinal( sqlite3_context* context )
844
835
  VALUE result;
845
836
  int state;
846
837
  am_protected_t protected;
838
+ VALUE exception = Qnil;
847
839
  VALUE *aggregate_context = (VALUE*)sqlite3_aggregate_context( context, sizeof( VALUE ) );
848
- VALUE exception = rb_iv_get( *aggregate_context, "@_exception" );
840
+
841
+ /**
842
+ * check and see if an exception had been throw at some point during the
843
+ * initialization of hte aggregate or during the step function call
844
+ *
845
+ */
846
+ if (TYPE(*aggregate_context) == T_OBJECT) {
847
+ /* if there is a @_exception value and it has a value then there was an
848
+ * exception during step function execution
849
+ */
850
+ if (rb_ivar_defined( *aggregate_context, rb_intern("@_exception") )) {
851
+ exception = rb_iv_get( *aggregate_context, "@_exception" );
852
+ } else {
853
+
854
+ /* if the aggregate context itself is an exception, then there was
855
+ * an error during teh initialization of the aggregate context
856
+ */
857
+ if (rb_obj_is_kind_of( *aggregate_context, rb_eException )) {
858
+ exception = *aggregate_context;
859
+ }
860
+ }
861
+ }
849
862
 
850
863
  if ( Qnil == exception ) {
851
864
  /* gather all the data to make the protected call */
@@ -868,8 +881,6 @@ void amalgalite_xFinal( sqlite3_context* context )
868
881
  sqlite3_result_error( context, RSTRING_PTR(msg), (int)RSTRING_LEN(msg) );
869
882
  }
870
883
 
871
-
872
-
873
884
  /* release the aggregate instance from garbage collector protection */
874
885
  rb_gc_unregister_address( aggregate_context );
875
886
 
@@ -1151,7 +1162,6 @@ void Init_amalgalite_database( )
1151
1162
  rb_define_method(cAS_Database, "last_insert_rowid", am_sqlite3_database_last_insert_rowid, 0); /* in amalgalite_database.c */
1152
1163
  rb_define_method(cAS_Database, "autocommit?", am_sqlite3_database_is_autocommit, 0); /* in amalgalite_database.c */
1153
1164
  rb_define_method(cAS_Database, "register_trace_tap", am_sqlite3_database_register_trace_tap, 1); /* in amalgalite_database.c */
1154
- rb_define_method(cAS_Database, "register_profile_tap", am_sqlite3_database_register_profile_tap, 1); /* in amalgalite_database.c */
1155
1165
  rb_define_method(cAS_Database, "table_column_metadata", am_sqlite3_database_table_column_metadata, 3); /* in amalgalite_database.c */
1156
1166
  rb_define_method(cAS_Database, "row_changes", am_sqlite3_database_row_changes, 0); /* in amalgalite_database.c */
1157
1167
  rb_define_method(cAS_Database, "total_changes", am_sqlite3_database_total_changes, 0); /* in amalgalite_database.c */
@@ -6,13 +6,31 @@ require 'rbconfig'
6
6
  $ruby = ARGV.shift if ARGV[0]
7
7
 
8
8
  # make available table and column meta data api
9
+ $CFLAGS += " -DSQLITE_ENABLE_BYTECODE_VTAB=1"
9
10
  $CFLAGS += " -DSQLITE_ENABLE_COLUMN_METADATA=1"
10
11
  $CFLAGS += " -DSQLITE_ENABLE_DBSTAT_VTAB=1"
11
- $CFLAGS += " -DSQLITE_ENABLE_RTREE=1"
12
+ $CFLAGS += " -DSQLITE_ENABLE_DBPAGE_VTAB=1"
13
+ $CFLAGS += " -DSQLITE_ENABLE_DESERIALIZE=1"
14
+ $CFLAGS += " -DSQLITE_ENABLE_EXPLAIN_COMMENTS=1"
12
15
  $CFLAGS += " -DSQLITE_ENABLE_FTS3=1"
13
16
  $CFLAGS += " -DSQLITE_ENABLE_FTS3_PARENTHESIS=1"
14
17
  $CFLAGS += " -DSQLITE_ENABLE_FTS4=1"
18
+ $CFLAGS += " -DSQLITE_ENABLE_FTS5=1"
19
+ $CFLAGS += " -DSQLITE_ENABLE_GEOPOLY=1"
20
+ $CFLAGS += " -DSQLITE_ENABLE_JSON1=1"
21
+ $CFLAGS += " -DSQLITE_ENABLE_MEMORY_MANAGEMENT=1"
22
+ $CFLAGS += " -DSQLITE_ENABLE_NULL_TRIM=1"
23
+ $CFLAGS += " -DSQLITE_ENABLE_PREUPDATE_HOOK=1"
24
+ $CFLAGS ++ " -DSQLITE_EANBLE_QPSG=1"
25
+ $CFLAGS += " -DSQLITE_ENABLE_RBU=1"
26
+ $CFLAGS += " -DSQLITE_ENABLE_RTREE=1"
27
+ $CFLAGS += " -DSQLITE_ENABLE_SESSION=1"
28
+ $CFLAGS += " -DSQLITE_ENABLE_SNAPSHOT=1"
29
+ $CFLAGS += " -DSQLITE_ENABLE_STMTVTAB=1"
15
30
  $CFLAGS += " -DSQLITE_ENABLE_STAT4=1"
31
+ $CFLAGS += " -DSQLITE_ENABLE_UNLOCK_NOTIFY=1"
32
+
33
+ $CFLAGS += " -DSQLITE_OMIT_DEPRECATED=1"
16
34
 
17
35
  # we compile sqlite the same way that the installation of ruby is compiled.
18
36
  if RbConfig::MAKEFILE_CONFIG['configure_args'].include?( "--enable-pthread" ) then
@@ -23,12 +41,21 @@ end
23
41
 
24
42
  # remove the -g flags if it exists
25
43
  %w[ -ggdb\\d* -g\\d* ].each do |debug|
26
- $CFLAGS = $CFLAGS.gsub(/#{debug}/,'')
27
- RbConfig::MAKEFILE_CONFIG['debugflags'] = RbConfig::MAKEFILE_CONFIG['debugflags'].gsub(/#{debug}/,'') if RbConfig::MAKEFILE_CONFIG['debugflags']
44
+ $CFLAGS = $CFLAGS.gsub(/\s#{debug}\b/,'')
45
+ RbConfig::MAKEFILE_CONFIG['debugflags'] = RbConfig::MAKEFILE_CONFIG['debugflags'].gsub(/\s#{debug}\b/,'') if RbConfig::MAKEFILE_CONFIG['debugflags']
28
46
  end
29
47
 
30
48
  ignoreable_warnings = %w[ write-strings ]
31
- ignore_by_compiler = { "clang" => %w[ unused-const-variable shorten-64-to-32 incompatible-pointer-types-discards-qualifiers] }
49
+ ignore_by_compiler = {
50
+ "clang" => %w[
51
+ empty-body
52
+ incompatible-pointer-types-discards-qualifiers
53
+ shorten-64-to-32
54
+ sign-compare
55
+ unused-const-variable
56
+ unused-variable
57
+ ]
58
+ }
32
59
 
33
60
  if extras = ignore_by_compiler[RbConfig::MAKEFILE_CONFIG["CC"]] then
34
61
  ignoreable_warnings.concat(extras)
@@ -1,141 +1,311 @@
1
1
  #!/usr/bin/env ruby
2
2
 
3
- CONSTANTS = {
4
- "ResultCode" => {
5
- "OK" => "SQLITE_OK",
6
- "ERROR" => "SQLITE_ERROR",
7
- "INTERNAL" => "SQLITE_INTERNAL",
8
- "PERM" => "SQLITE_PERM",
9
- "ABORT" => "SQLITE_ABORT",
10
- "BUSY" => "SQLITE_BUSY",
11
- "LOCKED" => "SQLITE_LOCKED",
12
- "NOMEM" => "SQLITE_NOMEM",
13
- "READONLY" => "SQLITE_READONLY",
14
- "INTERRUPT" => "SQLITE_INTERRUPT",
15
- "IOERR" => "SQLITE_IOERR",
16
- "CORRUPT" => "SQLITE_CORRUPT",
17
- "NOTFOUND" => "SQLITE_NOTFOUND",
18
- "FULL" => "SQLITE_FULL",
19
- "CANTOPEN" => "SQLITE_CANTOPEN",
20
- "PROTOCOL" => "SQLITE_PROTOCOL",
21
- "EMPTY" => "SQLITE_EMPTY",
22
- "SCHEMA" => "SQLITE_SCHEMA",
23
- "TOOBIG" => "SQLITE_TOOBIG",
24
- "CONSTRAINT" => "SQLITE_CONSTRAINT",
25
- "MISMATCH" => "SQLITE_MISMATCH",
26
- "MISUSE" => "SQLITE_MISUSE",
27
- "NOLFS" => "SQLITE_NOLFS",
28
- "AUTH" => "SQLITE_AUTH",
29
- "FORMAT" => "SQLITE_FORMAT",
30
- "RANGE" => "SQLITE_RANGE",
31
- "NOTADB" => "SQLITE_NOTADB",
32
- "ROW" => "SQLITE_ROW",
33
- "DONE" => "SQLITE_DONE",
34
-
35
- "IOERR_READ" => "SQLITE_IOERR_READ",
36
- "IOERR_SHORT_READ" => "SQLITE_IOERR_SHORT_READ",
37
- "IOERR_WRITE" => "SQLITE_IOERR_WRITE",
38
- "IOERR_FSYNC" => "SQLITE_IOERR_FSYNC",
39
- "IOERR_DIR_FSYNC" => "SQLITE_IOERR_DIR_FSYNC",
40
- "IOERR_TRUNCATE" => "SQLITE_IOERR_TRUNCATE",
41
- "IOERR_FSTAT" => "SQLITE_IOERR_FSTAT",
42
- "IOERR_UNLOCK" => "SQLITE_IOERR_UNLOCK",
43
- "IOERR_RDLOCK" => "SQLITE_IOERR_RDLOCK",
44
- "IOERR_DELETE" => "SQLITE_IOERR_DELETE",
45
- "IOERR_BLOCKED" => "SQLITE_IOERR_BLOCKED",
46
- "IOERR_NOMEM" => "SQLITE_IOERR_NOMEM",
47
- "IOERR_ACCESS" => "SQLITE_IOERR_ACCESS",
48
- "IOERR_CHECKRESERVEDLOCK" => "SQLITE_IOERR_CHECKRESERVEDLOCK",
49
- "IOERR_LOCK" => "SQLITE_IOERR_LOCK",
50
- "IOERR_CLOSE" => "SQLITE_IOERR_CLOSE",
51
- "IOERR_DIR_CLOSE" => "SQLITE_IOERR_DIR_CLOSE",
52
- "IOERR_SHMOPEN" => "SQLITE_IOERR_SHMOPEN",
53
- "IOERR_SHMSIZE" => "SQLITE_IOERR_SHMSIZE",
54
- "IOERR_SHMLOCK" => "SQLITE_IOERR_SHMLOCK",
55
-
56
- "LOCKED_SHAREDCACHE" => "SQLITE_LOCKED_SHAREDCACHE",
57
- "BUSY_RECOVERY" => "SQLITE_BUSY_RECOVERY",
58
- "CANTOPEN_NOTEMPDIR" => "SQLITE_CANTOPEN_NOTEMPDIR",
59
- },
60
-
61
-
62
- "DataType" => {
63
- "INTEGER" => "SQLITE_INTEGER",
64
- "FLOAT" => "SQLITE_FLOAT",
65
- "BLOB" => "SQLITE_BLOB",
66
- "NULL" => "SQLITE_NULL",
67
- "TEXT" => "SQLITE_TEXT",
68
- },
69
-
70
- "Config" => {
71
- "SINGLETHREAD" => "SQLITE_CONFIG_SINGLETHREAD",
72
- "MULTITHREAD" => "SQLITE_CONFIG_MULTITHREAD",
73
- "SERIALIZED" => "SQLITE_CONFIG_SERIALIZED",
74
- "MALLOC" => "SQLITE_CONFIG_MALLOC",
75
- "GETMALLOC" => "SQLITE_CONFIG_GETMALLOC",
76
- "SCRATCH" => "SQLITE_CONFIG_SCRATCH",
77
- "PAGECACHE" => "SQLITE_CONFIG_PAGECACHE",
78
- "HEAP" => "SQLITE_CONFIG_HEAP",
79
- "MEMSTATUS" => "SQLITE_CONFIG_MEMSTATUS",
80
- "MUTEX" => "SQLITE_CONFIG_MUTEX",
81
- "GETMUTEX" => "SQLITE_CONFIG_GETMUTEX",
82
- "LOOKASIDE" => "SQLITE_CONFIG_LOOKASIDE",
83
- "PCACHE" => "SQLITE_CONFIG_PCACHE",
84
- "GETPCACHE" => "SQLITE_CONFIG_GETPCACHE",
85
- "LOG" => "SQLITE_CONFIG_LOG",
86
- },
87
-
88
- "Open" => {
89
- "READONLY" => "SQLITE_OPEN_READONLY",
90
- "READWRITE" => "SQLITE_OPEN_READWRITE",
91
- "CREATE" => "SQLITE_OPEN_CREATE",
92
- "DELETEONCLOSE" => "SQLITE_OPEN_DELETEONCLOSE",
93
- "EXCLUSIVE" => "SQLITE_OPEN_EXCLUSIVE",
94
- "AUTOPROXY" => "SQLITE_OPEN_AUTOPROXY",
95
- "MAIN_DB" => "SQLITE_OPEN_MAIN_DB",
96
- "TEMP_DB" => "SQLITE_OPEN_TEMP_DB",
97
- "TRANSIENT_DB" => "SQLITE_OPEN_TRANSIENT_DB",
98
- "MAIN_JOURNAL" => "SQLITE_OPEN_MAIN_JOURNAL",
99
- "TEMP_JOURNAL" => "SQLITE_OPEN_TEMP_JOURNAL",
100
- "SUBJOURNAL" => "SQLITE_OPEN_SUBJOURNAL",
101
- "MASTER_JOURNAL" => "SQLITE_OPEN_MASTER_JOURNAL",
102
- "NOMUTEX" => "SQLITE_OPEN_NOMUTEX",
103
- "FULLMUTEX" => "SQLITE_OPEN_FULLMUTEX",
104
- "SHAREDCACHE" => "SQLITE_OPEN_SHAREDCACHE",
105
- "PRIVATECACHE" => "SQLITE_OPEN_PRIVATECACHE",
106
- "WAL" => "SQLITE_OPEN_WAL",
107
- },
108
-
109
- "Status" => {
110
- "MEMORY_USED" => "SQLITE_STATUS_MEMORY_USED",
111
- "PAGECACHE_USED" => "SQLITE_STATUS_PAGECACHE_USED",
112
- "PAGECACHE_OVERFLOW" => "SQLITE_STATUS_PAGECACHE_OVERFLOW",
113
- "SCRATCH_USED" => "SQLITE_STATUS_SCRATCH_USED",
114
- "SCRATCH_OVERFLOW" => "SQLITE_STATUS_SCRATCH_OVERFLOW",
115
- "MALLOC_SIZE" => "SQLITE_STATUS_MALLOC_SIZE",
116
- "PARSER_STACK" => "SQLITE_STATUS_PARSER_STACK",
117
- "PAGECACHE_SIZE" => "SQLITE_STATUS_PAGECACHE_SIZE",
118
- "SCRATCH_SIZE" => "SQLITE_STATUS_SCRATCH_SIZE",
119
- "MALLOC_COUNT" => "SQLITE_STATUS_MALLOC_COUNT",
120
- },
121
-
122
- "DBStatus" => {
123
- "LOOKASIDE_USED" => "SQLITE_DBSTATUS_LOOKASIDE_USED",
124
- "CACHE_USED" => "SQLITE_DBSTATUS_CACHE_USED",
125
- "SCHEMA_USED" => "SQLITE_DBSTATUS_SCHEMA_USED",
126
- "STMT_USED" => "SQLITE_DBSTATUS_STMT_USED",
127
- "MAX" => "SQLITE_DBSTATUS_MAX",
128
- },
129
-
130
- "StatementStatus" => {
131
- "FULLSCAN_STEP" => "SQLITE_STMTSTATUS_FULLSCAN_STEP",
132
- "SORT" => "SQLITE_STMTSTATUS_SORT",
133
- "AUTOINDEX" => "SQLITE_STMTSTATUS_AUTOINDEX",
134
- }
3
+ require 'pp'
4
+
5
+ # readin in the sqlite3.h file and parse out all the #define lines
6
+ sqlite3_h_fname = File.expand_path(File.join(File.dirname(__FILE__), "sqlite3.h"))
7
+
8
+ # special handling for those that are function result codes
9
+ result_codes = %w[
10
+ SQLITE_OK
11
+ SQLITE_ERROR
12
+ SQLITE_INTERNAL
13
+ SQLITE_PERM
14
+ SQLITE_ABORT
15
+ SQLITE_BUSY
16
+ SQLITE_LOCKED
17
+ SQLITE_NOMEM
18
+ SQLITE_READONLY
19
+ SQLITE_INTERRUPT
20
+ SQLITE_IOERR
21
+ SQLITE_CORRUPT
22
+ SQLITE_NOTFOUND
23
+ SQLITE_FULL
24
+ SQLITE_CANTOPEN
25
+ SQLITE_PROTOCOL
26
+ SQLITE_EMPTY
27
+ SQLITE_SCHEMA
28
+ SQLITE_TOOBIG
29
+ SQLITE_CONSTRAINT
30
+ SQLITE_MISMATCH
31
+ SQLITE_MISUSE
32
+ SQLITE_NOLFS
33
+ SQLITE_AUTH
34
+ SQLITE_FORMAT
35
+ SQLITE_RANGE
36
+ SQLITE_NOTADB
37
+ SQLITE_NOTICE
38
+ SQLITE_WARNING
39
+ SQLITE_ROW
40
+ SQLITE_DONE
41
+ SQLITE_ERROR_MISSING_COLLSEQ
42
+ SQLITE_ERROR_RETRY
43
+ SQLITE_ERROR_SNAPSHOT
44
+ SQLITE_IOERR_READ
45
+ SQLITE_IOERR_SHORT_READ
46
+ SQLITE_IOERR_WRITE
47
+ SQLITE_IOERR_FSYNC
48
+ SQLITE_IOERR_DIR_FSYNC
49
+ SQLITE_IOERR_TRUNCATE
50
+ SQLITE_IOERR_FSTAT
51
+ SQLITE_IOERR_UNLOCK
52
+ SQLITE_IOERR_RDLOCK
53
+ SQLITE_IOERR_DELETE
54
+ SQLITE_IOERR_BLOCKED
55
+ SQLITE_IOERR_NOMEM
56
+ SQLITE_IOERR_ACCESS
57
+ SQLITE_IOERR_CHECKRESERVEDLOCK
58
+ SQLITE_IOERR_LOCK
59
+ SQLITE_IOERR_CLOSE
60
+ SQLITE_IOERR_DIR_CLOSE
61
+ SQLITE_IOERR_SHMOPEN
62
+ SQLITE_IOERR_SHMSIZE
63
+ SQLITE_IOERR_SHMLOCK
64
+ SQLITE_IOERR_SHMMAP
65
+ SQLITE_IOERR_SEEK
66
+ SQLITE_IOERR_DELETE_NOENT
67
+ SQLITE_IOERR_MMAP
68
+ SQLITE_IOERR_GETTEMPPATH
69
+ SQLITE_IOERR_CONVPATH
70
+ SQLITE_IOERR_VNODE
71
+ SQLITE_IOERR_AUTH
72
+ SQLITE_IOERR_BEGIN_ATOMIC
73
+ SQLITE_IOERR_COMMIT_ATOMIC
74
+ SQLITE_IOERR_ROLLBACK_ATOMIC
75
+ SQLITE_IOERR_DATA
76
+ SQLITE_IOERR_CORRUPTFS
77
+ SQLITE_LOCKED_SHAREDCACHE
78
+ SQLITE_LOCKED_VTAB
79
+ SQLITE_BUSY_RECOVERY
80
+ SQLITE_BUSY_SNAPSHOT
81
+ SQLITE_BUSY_TIMEOUT
82
+ SQLITE_CANTOPEN_NOTEMPDIR
83
+ SQLITE_CANTOPEN_ISDIR
84
+ SQLITE_CANTOPEN_FULLPATH
85
+ SQLITE_CANTOPEN_CONVPATH
86
+ SQLITE_CANTOPEN_DIRTYWAL
87
+ SQLITE_CANTOPEN_SYMLINK
88
+ SQLITE_CORRUPT_VTAB
89
+ SQLITE_CORRUPT_SEQUENCE
90
+ SQLITE_CORRUPT_INDEX
91
+ SQLITE_READONLY_RECOVERY
92
+ SQLITE_READONLY_CANTLOCK
93
+ SQLITE_READONLY_ROLLBACK
94
+ SQLITE_READONLY_DBMOVED
95
+ SQLITE_READONLY_CANTINIT
96
+ SQLITE_READONLY_DIRECTORY
97
+ SQLITE_ABORT_ROLLBACK
98
+ SQLITE_CONSTRAINT_CHECK
99
+ SQLITE_CONSTRAINT_COMMITHOOK
100
+ SQLITE_CONSTRAINT_FOREIGNKEY
101
+ SQLITE_CONSTRAINT_FUNCTION
102
+ SQLITE_CONSTRAINT_NOTNULL
103
+ SQLITE_CONSTRAINT_PRIMARYKEY
104
+ SQLITE_CONSTRAINT_TRIGGER
105
+ SQLITE_CONSTRAINT_UNIQUE
106
+ SQLITE_CONSTRAINT_VTAB
107
+ SQLITE_CONSTRAINT_ROWID
108
+ SQLITE_CONSTRAINT_PINNED
109
+ SQLITE_NOTICE_RECOVER_WAL
110
+ SQLITE_NOTICE_RECOVER_ROLLBACK
111
+ SQLITE_WARNING_AUTOINDEX
112
+ SQLITE_AUTH_USER
113
+ SQLITE_OK_LOAD_PERMANENTLY
114
+ SQLITE_OK_SYMLINK
115
+ ]
116
+
117
+ deprecated_codes = %w[ SQLITE_GET_LOCKPROXYFILE SQLITE_SET_LOCKPROXYFILE SQLITE_LAST_ERRNO ]
118
+ version_codes = %w[ SQLITE_VERSION SQLITE_VERSION_NUMBER SQLITE_SOURCE_ID ]
119
+ rtree_codes = %w[ NOT_WITHIN PARTLY_WITHIN FULLY_WITHIN ]
120
+
121
+ authorizer_codes = %w[
122
+ SQLITE_DENY
123
+ SQLITE_IGNORE
124
+ SQLITE_CREATE_INDEX
125
+ SQLITE_CREATE_TABLE
126
+ SQLITE_CREATE_TEMP_INDEX
127
+ SQLITE_CREATE_TEMP_TABLE
128
+ SQLITE_CREATE_TEMP_TRIGGER
129
+ SQLITE_CREATE_TEMP_VIEW
130
+ SQLITE_CREATE_TRIGGER
131
+ SQLITE_CREATE_VIEW
132
+ SQLITE_DELETE
133
+ SQLITE_DROP_INDEX
134
+ SQLITE_DROP_TABLE
135
+ SQLITE_DROP_TEMP_INDEX
136
+ SQLITE_DROP_TEMP_TABLE
137
+ SQLITE_DROP_TEMP_TRIGGER
138
+ SQLITE_DROP_TEMP_VIEW
139
+ SQLITE_DROP_TRIGGER
140
+ SQLITE_DROP_VIEW
141
+ SQLITE_INSERT
142
+ SQLITE_PRAGMA
143
+ SQLITE_READ
144
+ SQLITE_SELECT
145
+ SQLITE_TRANSACTION
146
+ SQLITE_UPDATE
147
+ SQLITE_ATTACH
148
+ SQLITE_DETACH
149
+ SQLITE_ALTER_TABLE
150
+ SQLITE_REINDEX
151
+ SQLITE_ANALYZE
152
+ SQLITE_CREATE_VTABLE
153
+ SQLITE_DROP_VTABLE
154
+ SQLITE_FUNCTION
155
+ SQLITE_SAVEPOINT
156
+ SQLITE_COPY
157
+ SQLITE_RECURSIVE
158
+ ]
159
+
160
+ text_encoding_codes = %w[
161
+ SQLITE_UTF8
162
+ SQLITE_UTF16LE
163
+ SQLITE_UTF16BE
164
+ SQLITE_UTF16
165
+ SQLITE_ANY
166
+ SQLITE_UTF16_ALIGNED
167
+ SQLITE_DETERMINISTIC
168
+ SQLITE_DIRECTONLY
169
+ SQLITE_SUBTYPE
170
+ SQLITE_INNOCUOUS
171
+ ]
172
+
173
+ data_type_codes = %w[
174
+ SQLITE_INTEGER
175
+ SQLITE_FLOAT
176
+ SQLITE_BLOB
177
+ SQLITE_NULL
178
+ SQLITE3_TEXT
179
+ ]
180
+
181
+ fts5_codes = %w[
182
+ FTS5_TOKENIZE_QUERY
183
+ FTS5_TOKENIZE_PREFIX
184
+ FTS5_TOKENIZE_DOCUMENT
185
+ FTS5_TOKENIZE_AUX
186
+ FTS5_TOKEN_COLOCATED
187
+ ]
188
+
189
+ ignore_codes = [
190
+ # vtab related
191
+ "SQLITE_ROLLBACK",
192
+ "SQLITE_FAIL",
193
+ "SQLITE_REPLACE",
194
+ "SQLITE_VTAB_CONSTRAINT_SUPPORT",
195
+ "SQLITE_VTAB_INNOCUOUS",
196
+ "SQLITE_VTAB_DIRECTONLY",
197
+
198
+ # sqlite destructor callback codes
199
+ "SQLITE_STATIC",
200
+ "SQLITE_TRANSIENT",
201
+ ]
202
+
203
+ # oddball name
204
+ module_name_mapping = {
135
205
 
206
+ "DBCONFIG" => "DBConfig",
207
+ "DBSTATUS" => "DBStatus",
208
+ "IOCAP" => "IOCap",
209
+ "SHM" => "SHM",
210
+ "SCANSTAT" => "ScanStat",
211
+ "STMTSTATUS" => "StatementStatus",
212
+ "CHANGESETAPPLY" => "ChangesetApply",
213
+ "CHANGESETSTART" => "ChangesetStart",
214
+ "TXN" => "Transaction",
136
215
  }
137
216
 
217
+ defines = []
218
+ IO.readlines(sqlite3_h_fname).each do |l|
219
+ result = {
220
+ "c_define" => nil,
221
+ "c_value" => nil,
222
+ "docstring" => nil,
223
+
224
+ "is_error_code" => false,
225
+
226
+ "r_module" => nil,
227
+ "r_constant" => nil,
228
+ }
229
+
230
+ if l =~ /beginning-of-error-codes/ .. l =~ /end-of-error-codes/ then
231
+ result["is_error_code"] = true
232
+ end
233
+
234
+ l.strip!
235
+ md = l.match(/\A#define\s+(\w+)\s+([^\/]+)\s*(\/\*(.*)\*\/)?\Z/)
236
+ next unless md
237
+
238
+ # Name munging
239
+ c_define = md[1]
240
+
241
+ c_parts = c_define.gsub(/^SQLITE_/,'').split("_")
242
+ r_module = c_parts.shift
243
+ r_constant = c_parts.join("_")
244
+
245
+
246
+ # custom module naming so they are human readable
247
+ r_module = module_name_mapping.fetch(r_module) { |m| r_module.capitalize }
248
+
249
+ case c_define
250
+ when *version_codes
251
+ next
252
+
253
+ when *deprecated_codes
254
+ next
255
+
256
+ when *rtree_codes
257
+ r_module = "RTree"
258
+ r_constant = c_define
259
+
260
+ when *result_codes
261
+ r_module = "ResultCode"
262
+ r_constant = c_define.gsub(/^SQLITE_/,'')
263
+
264
+ when *authorizer_codes
265
+ r_module = "Authorizer"
266
+ r_constant = c_define.gsub(/^SQLITE_/,'')
267
+
268
+ when *text_encoding_codes
269
+ r_module = "TextEncoding"
270
+ r_constant = c_define.gsub(/^SQLITE_/,'')
271
+
272
+ when *data_type_codes
273
+ r_module = "DataType"
274
+ r_constant = c_define.gsub(/^SQLITE(3)?_/,'')
275
+
276
+ when *fts5_codes
277
+ r_module = "FTS5"
278
+ r_constant = c_define.gsub(/^FTS5_/,'')
279
+
280
+ when *ignore_codes
281
+ next
282
+
283
+ when /TESTCTRL/ # sqlite3 codes used in testing
284
+ next
285
+
286
+ when /^__/ # sqlite3 internal items
287
+ next
288
+ end
289
+
290
+ result["c_define"] = c_define
291
+ result["c_value"] = md[2].strip
292
+ if !md[4].nil? && (md[4].strip.length > 0) then
293
+ result["docstring"] = md[4].strip
294
+ end
295
+ result["r_module"] = r_module
296
+ result["r_constant"] = r_constant
297
+
298
+ defines << result
299
+ end
300
+
301
+ #
302
+ # rework defines into constants
303
+ #
304
+ CONSTANTS = defines.group_by{ |d| d["r_module"] }
305
+
138
306
  fname = File.expand_path(File.join(File.dirname(__FILE__), "amalgalite_constants.c"))
307
+
308
+
139
309
  File.open(fname, "w+") do |f|
140
310
  f.puts "/* Generated by gen_constants.rb -- do not edit */"
141
311
  f.puts
@@ -157,35 +327,25 @@ File.open(fname, "w+") do |f|
157
327
  f.puts ' VALUE mC = rb_define_module_under( mas, "Constants");'
158
328
 
159
329
 
160
- error_code_lines = {}
161
- IO.readlines("sqlite3.h").each do |l|
162
- if l =~ /beginning-of-error-codes/ .. l =~ /end-of-error-codes/ then
163
- next if l =~ /of-error-codes/
164
- l.strip!
165
- md = l.match(/\A#define\s+(\w+)\s+(\d+)\s+\/\*(.*)\*\/\Z/)
166
- error_code_lines[md[1]] = { 'value' => md[2].strip, 'meaning' => md[3].strip }
167
- end
168
- end
169
-
170
- CONSTANTS.keys.sort.each do |klass|
171
- const_set = CONSTANTS[klass]
330
+ CONSTANTS.keys.sort.each do |mod|
172
331
  f.puts " /**"
173
- f.puts " * module encapsulating the SQLite3 C extension constants for #{klass}"
332
+ f.puts " * module encapsulating the SQLite3 C extension constants for #{mod}"
174
333
  f.puts " */"
175
- f.puts " VALUE mC_#{klass} = rb_define_module_under(mC, \"#{klass}\");"
334
+ f.puts " VALUE mC_#{mod} = rb_define_module_under(mC, \"#{mod}\");"
176
335
  f.puts
177
336
  end
178
337
 
179
- CONSTANTS.keys.sort.each do |klass|
180
- const_set = CONSTANTS[klass]
181
- const_set.keys.sort.each do |k|
182
- sql_const = const_set[k]
338
+ CONSTANTS.keys.sort.each do |mod|
339
+ const_set = CONSTANTS[mod]
340
+ const_set.sort_by { |c| c["c_define"] }.each do |result|
341
+ sql_const = result["c_define"]
183
342
  const_doc = " /* no meaningful autogenerated documentation -- constant is self explanatory ?*/"
184
- if ecl = error_code_lines[sql_const] then
185
- const_doc = " /* #{ecl['value']} -- #{ecl['meaning']} */"
343
+ if !result["docstring"].nil? then
344
+ const_doc = " /* #{result['c_value']} -- #{result['docstring']} */"
186
345
  end
346
+ ruby_constant = result['r_constant']
187
347
  f.puts const_doc
188
- f.puts " rb_define_const(mC_#{klass}, \"#{k}\", INT2FIX(#{sql_const}));"
348
+ f.puts " rb_define_const(mC_#{mod}, \"#{ruby_constant}\", INT2FIX(#{sql_const}));"
189
349
  f.puts
190
350
  end
191
351
  end