amalgalite 1.1.2-x86-mswin32 → 1.3.0-x86-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.
Files changed (80) hide show
  1. checksums.yaml +7 -0
  2. data/CONTRIBUTING.md +49 -0
  3. data/{HISTORY.rdoc → HISTORY.md} +96 -73
  4. data/LICENSE +2 -2
  5. data/Manifest.txt +104 -0
  6. data/README.md +73 -0
  7. data/Rakefile +25 -0
  8. data/TODO.md +50 -0
  9. data/ext/amalgalite/{amalgalite3.c → c/amalgalite.c} +12 -12
  10. data/ext/amalgalite/{amalgalite3.h → c/amalgalite.h} +5 -5
  11. data/ext/amalgalite/{amalgalite3_blob.c → c/amalgalite_blob.c} +2 -2
  12. data/ext/amalgalite/{amalgalite3_constants.c → c/amalgalite_constants.c} +2 -2
  13. data/ext/amalgalite/{amalgalite3_database.c → c/amalgalite_database.c} +49 -21
  14. data/ext/amalgalite/{amalgalite3_requires_bootstrap.c → c/amalgalite_requires_bootstrap.c} +131 -58
  15. data/ext/amalgalite/{amalgalite3_statement.c → c/amalgalite_statement.c} +2 -2
  16. data/ext/amalgalite/{extconf.rb → c/extconf.rb} +4 -4
  17. data/ext/amalgalite/{gen_constants.rb → c/gen_constants.rb} +3 -3
  18. data/ext/amalgalite/c/notes.txt +134 -0
  19. data/ext/amalgalite/{sqlite3.c → c/sqlite3.c} +94602 -80497
  20. data/ext/amalgalite/{sqlite3.h → c/sqlite3.h} +1047 -216
  21. data/ext/amalgalite/{sqlite3_options.h → c/sqlite3_options.h} +0 -0
  22. data/ext/amalgalite/{sqlite3ext.h → c/sqlite3ext.h} +40 -13
  23. data/lib/amalgalite.rb +13 -6
  24. data/lib/amalgalite/1.8/amalgalite.so +0 -0
  25. data/lib/amalgalite/1.9/amalgalite.so +0 -0
  26. data/lib/amalgalite/2.0/amalgalite.so +0 -0
  27. data/lib/amalgalite/column.rb +7 -5
  28. data/lib/amalgalite/database.rb +18 -10
  29. data/lib/amalgalite/packer.rb +5 -2
  30. data/lib/amalgalite/requires.rb +47 -16
  31. data/lib/amalgalite/schema.rb +63 -36
  32. data/lib/amalgalite/sqlite3/version.rb +0 -1
  33. data/lib/amalgalite/statement.rb +7 -5
  34. data/lib/amalgalite/table.rb +9 -8
  35. data/lib/amalgalite/type_maps/default_map.rb +0 -1
  36. data/lib/amalgalite/type_maps/storage_map.rb +0 -2
  37. data/lib/amalgalite/type_maps/text_map.rb +0 -1
  38. data/lib/amalgalite/version.rb +3 -32
  39. data/spec/aggregate_spec.rb +1 -1
  40. data/spec/amalgalite_spec.rb +1 -1
  41. data/spec/blob_spec.rb +1 -1
  42. data/spec/boolean_spec.rb +2 -1
  43. data/spec/busy_handler.rb +1 -1
  44. data/spec/database_spec.rb +16 -11
  45. data/spec/default_map_spec.rb +1 -1
  46. data/spec/function_spec.rb +1 -1
  47. data/spec/integeration_spec.rb +2 -1
  48. data/spec/packer_spec.rb +4 -4
  49. data/spec/paths_spec.rb +1 -1
  50. data/spec/progress_handler_spec.rb +4 -5
  51. data/spec/requires_spec.rb +36 -2
  52. data/spec/rtree_spec.rb +6 -5
  53. data/spec/schema_spec.rb +28 -20
  54. data/spec/spec_helper.rb +2 -7
  55. data/spec/sqlite3/constants_spec.rb +1 -1
  56. data/spec/sqlite3/database_status_spec.rb +4 -4
  57. data/spec/sqlite3/status_spec.rb +5 -5
  58. data/spec/sqlite3/version_spec.rb +7 -7
  59. data/spec/sqlite3_spec.rb +3 -3
  60. data/spec/statement_spec.rb +3 -4
  61. data/spec/storage_map_spec.rb +1 -1
  62. data/spec/tap_spec.rb +4 -4
  63. data/spec/text_map_spec.rb +1 -1
  64. data/spec/type_map_spec.rb +1 -1
  65. data/spec/version_spec.rb +2 -9
  66. data/tasks/custom.rake +99 -0
  67. data/tasks/default.rake +277 -0
  68. data/tasks/extension.rake +28 -202
  69. data/tasks/this.rb +209 -0
  70. metadata +102 -191
  71. data/README.rdoc +0 -54
  72. data/gemspec.rb +0 -63
  73. data/lib/amalgalite/1.8/amalgalite3.so +0 -0
  74. data/lib/amalgalite/1.9/amalgalite3.so +0 -0
  75. data/tasks/announce.rake +0 -44
  76. data/tasks/config.rb +0 -107
  77. data/tasks/distribution.rake +0 -77
  78. data/tasks/documentation.rake +0 -36
  79. data/tasks/rspec.rake +0 -30
  80. data/tasks/utils.rb +0 -80
@@ -49,8 +49,10 @@ struct sqlite3_api_routines {
49
49
  int (*busy_timeout)(sqlite3*,int ms);
50
50
  int (*changes)(sqlite3*);
51
51
  int (*close)(sqlite3*);
52
- int (*collation_needed)(sqlite3*,void*,void(*)(void*,sqlite3*,int eTextRep,const char*));
53
- int (*collation_needed16)(sqlite3*,void*,void(*)(void*,sqlite3*,int eTextRep,const void*));
52
+ int (*collation_needed)(sqlite3*,void*,void(*)(void*,sqlite3*,
53
+ int eTextRep,const char*));
54
+ int (*collation_needed16)(sqlite3*,void*,void(*)(void*,sqlite3*,
55
+ int eTextRep,const void*));
54
56
  const void * (*column_blob)(sqlite3_stmt*,int iCol);
55
57
  int (*column_bytes)(sqlite3_stmt*,int iCol);
56
58
  int (*column_bytes16)(sqlite3_stmt*,int iCol);
@@ -75,10 +77,18 @@ struct sqlite3_api_routines {
75
77
  void * (*commit_hook)(sqlite3*,int(*)(void*),void*);
76
78
  int (*complete)(const char*sql);
77
79
  int (*complete16)(const void*sql);
78
- int (*create_collation)(sqlite3*,const char*,int,void*,int(*)(void*,int,const void*,int,const void*));
79
- int (*create_collation16)(sqlite3*,const void*,int,void*,int(*)(void*,int,const void*,int,const void*));
80
- int (*create_function)(sqlite3*,const char*,int,int,void*,void (*xFunc)(sqlite3_context*,int,sqlite3_value**),void (*xStep)(sqlite3_context*,int,sqlite3_value**),void (*xFinal)(sqlite3_context*));
81
- int (*create_function16)(sqlite3*,const void*,int,int,void*,void (*xFunc)(sqlite3_context*,int,sqlite3_value**),void (*xStep)(sqlite3_context*,int,sqlite3_value**),void (*xFinal)(sqlite3_context*));
80
+ int (*create_collation)(sqlite3*,const char*,int,void*,
81
+ int(*)(void*,int,const void*,int,const void*));
82
+ int (*create_collation16)(sqlite3*,const void*,int,void*,
83
+ int(*)(void*,int,const void*,int,const void*));
84
+ int (*create_function)(sqlite3*,const char*,int,int,void*,
85
+ void (*xFunc)(sqlite3_context*,int,sqlite3_value**),
86
+ void (*xStep)(sqlite3_context*,int,sqlite3_value**),
87
+ void (*xFinal)(sqlite3_context*));
88
+ int (*create_function16)(sqlite3*,const void*,int,int,void*,
89
+ void (*xFunc)(sqlite3_context*,int,sqlite3_value**),
90
+ void (*xStep)(sqlite3_context*,int,sqlite3_value**),
91
+ void (*xFinal)(sqlite3_context*));
82
92
  int (*create_module)(sqlite3*,const char*,const sqlite3_module*,void*);
83
93
  int (*data_count)(sqlite3_stmt*pStmt);
84
94
  sqlite3 * (*db_handle)(sqlite3_stmt*);
@@ -123,16 +133,19 @@ struct sqlite3_api_routines {
123
133
  void (*result_text16le)(sqlite3_context*,const void*,int,void(*)(void*));
124
134
  void (*result_value)(sqlite3_context*,sqlite3_value*);
125
135
  void * (*rollback_hook)(sqlite3*,void(*)(void*),void*);
126
- int (*set_authorizer)(sqlite3*,int(*)(void*,int,const char*,const char*,const char*,const char*),void*);
136
+ int (*set_authorizer)(sqlite3*,int(*)(void*,int,const char*,const char*,
137
+ const char*,const char*),void*);
127
138
  void (*set_auxdata)(sqlite3_context*,int,void*,void (*)(void*));
128
139
  char * (*snprintf)(int,char*,const char*,...);
129
140
  int (*step)(sqlite3_stmt*);
130
- int (*table_column_metadata)(sqlite3*,const char*,const char*,const char*,char const**,char const**,int*,int*,int*);
141
+ int (*table_column_metadata)(sqlite3*,const char*,const char*,const char*,
142
+ char const**,char const**,int*,int*,int*);
131
143
  void (*thread_cleanup)(void);
132
144
  int (*total_changes)(sqlite3*);
133
145
  void * (*trace)(sqlite3*,void(*xTrace)(void*,const char*),void*);
134
146
  int (*transfer_bindings)(sqlite3_stmt*,sqlite3_stmt*);
135
- void * (*update_hook)(sqlite3*,void(*)(void*,int ,char const*,char const*,sqlite_int64),void*);
147
+ void * (*update_hook)(sqlite3*,void(*)(void*,int ,char const*,char const*,
148
+ sqlite_int64),void*);
136
149
  void * (*user_data)(sqlite3_context*);
137
150
  const void * (*value_blob)(sqlite3_value*);
138
151
  int (*value_bytes)(sqlite3_value*);
@@ -154,15 +167,19 @@ struct sqlite3_api_routines {
154
167
  int (*prepare16_v2)(sqlite3*,const void*,int,sqlite3_stmt**,const void**);
155
168
  int (*clear_bindings)(sqlite3_stmt*);
156
169
  /* Added by 3.4.1 */
157
- int (*create_module_v2)(sqlite3*,const char*,const sqlite3_module*,void*,void (*xDestroy)(void *));
170
+ int (*create_module_v2)(sqlite3*,const char*,const sqlite3_module*,void*,
171
+ void (*xDestroy)(void *));
158
172
  /* Added by 3.5.0 */
159
173
  int (*bind_zeroblob)(sqlite3_stmt*,int,int);
160
174
  int (*blob_bytes)(sqlite3_blob*);
161
175
  int (*blob_close)(sqlite3_blob*);
162
- int (*blob_open)(sqlite3*,const char*,const char*,const char*,sqlite3_int64,int,sqlite3_blob**);
176
+ int (*blob_open)(sqlite3*,const char*,const char*,const char*,sqlite3_int64,
177
+ int,sqlite3_blob**);
163
178
  int (*blob_read)(sqlite3_blob*,void*,int,int);
164
179
  int (*blob_write)(sqlite3_blob*,const void*,int,int);
165
- int (*create_collation_v2)(sqlite3*,const char*,int,void*,int(*)(void*,int,const void*,int,const void*),void(*)(void*));
180
+ int (*create_collation_v2)(sqlite3*,const char*,int,void*,
181
+ int(*)(void*,int,const void*,int,const void*),
182
+ void(*)(void*));
166
183
  int (*file_control)(sqlite3*,const char*,int,void*);
167
184
  sqlite3_int64 (*memory_highwater)(int);
168
185
  sqlite3_int64 (*memory_used)(void);
@@ -198,7 +215,11 @@ struct sqlite3_api_routines {
198
215
  int (*backup_step)(sqlite3_backup*,int);
199
216
  const char *(*compileoption_get)(int);
200
217
  int (*compileoption_used)(const char*);
201
- int (*create_function_v2)(sqlite3*,const char*,int,int,void*,void (*xFunc)(sqlite3_context*,int,sqlite3_value**),void (*xStep)(sqlite3_context*,int,sqlite3_value**),void (*xFinal)(sqlite3_context*),void(*xDestroy)(void*));
218
+ int (*create_function_v2)(sqlite3*,const char*,int,int,void*,
219
+ void (*xFunc)(sqlite3_context*,int,sqlite3_value**),
220
+ void (*xStep)(sqlite3_context*,int,sqlite3_value**),
221
+ void (*xFinal)(sqlite3_context*),
222
+ void(*xDestroy)(void*));
202
223
  int (*db_config)(sqlite3*,int,...);
203
224
  sqlite3_mutex *(*db_mutex)(sqlite3*);
204
225
  int (*db_status)(sqlite3*,int,int*,int*,int);
@@ -212,6 +233,9 @@ struct sqlite3_api_routines {
212
233
  int (*wal_autocheckpoint)(sqlite3*,int);
213
234
  int (*wal_checkpoint)(sqlite3*,const char*);
214
235
  void *(*wal_hook)(sqlite3*,int(*)(void*,sqlite3*,const char*,int),void*);
236
+ int (*blob_reopen)(sqlite3_blob*,sqlite3_int64);
237
+ int (*vtab_config)(sqlite3*,int op,...);
238
+ int (*vtab_on_conflict)(sqlite3*);
215
239
  };
216
240
 
217
241
  /*
@@ -412,6 +436,9 @@ struct sqlite3_api_routines {
412
436
  #define sqlite3_wal_autocheckpoint sqlite3_api->wal_autocheckpoint
413
437
  #define sqlite3_wal_checkpoint sqlite3_api->wal_checkpoint
414
438
  #define sqlite3_wal_hook sqlite3_api->wal_hook
439
+ #define sqlite3_blob_reopen sqlite3_api->blob_reopen
440
+ #define sqlite3_vtab_config sqlite3_api->vtab_config
441
+ #define sqlite3_vtab_on_conflict sqlite3_api->vtab_on_conflict
415
442
  #endif /* SQLITE_CORE */
416
443
 
417
444
  #define SQLITE_EXTENSION_INIT1 const sqlite3_api_routines *sqlite3_api = 0;
data/lib/amalgalite.rb CHANGED
@@ -5,8 +5,8 @@
5
5
 
6
6
  # check if sqlite3 has already been required. Amalgalite conflicts with system
7
7
  # level sqlite3 libraries.
8
- unless $LOADED_FEATURES.grep( /sqlite3/ ).empty? then
9
- raise LoadError, "amalgalite conflicts with sqlite3-ruby, please choose one or the other."
8
+ unless $LOADED_FEATURES.grep( /\Asqlite3/ ).empty? then
9
+ raise LoadError, "amalgalite conflicts with sqlite3, please choose one or the other."
10
10
  end
11
11
 
12
12
  module Amalgalite
@@ -16,10 +16,17 @@ module Amalgalite
16
16
  class Error < ::StandardError; end
17
17
  end
18
18
 
19
- # use a version subdirectory for extensions, initially to support windows, but
20
- # why make a special case, it doesn't hurt anyone to have an extra subdir
21
- # someplace
22
- require "amalgalite/#{RUBY_VERSION.sub(/\.\d$/,'')}/amalgalite3"
19
+ # Load the binary extension, try loading one for the specific version of ruby
20
+ # and if that fails, then fall back to one in the top of the library.
21
+ # this is the method recommended by rake-compiler
22
+ begin
23
+ # this will be for windows
24
+ require "amalgalite/#{RUBY_VERSION.sub(/\.\d$/,'')}/amalgalite"
25
+ rescue LoadError
26
+ # everyone else.
27
+ require 'amalgalite/amalgalite'
28
+ end
29
+
23
30
 
24
31
  require 'amalgalite/aggregate'
25
32
  require 'amalgalite/blob'
Binary file
Binary file
Binary file
@@ -16,15 +16,17 @@ module Amalgalite
16
16
  # the schema object this column is associated with
17
17
  attr_accessor :schema
18
18
 
19
- # the database name this column belongs to
19
+ # the database name this column belongs to. This will be 'main' for the main
20
+ # database, 'temp' for the temp database and whatever an attached database
21
+ # was attached as.
20
22
  attr_accessor :db
21
23
 
22
- # the column name
23
- attr_accessor :name
24
-
25
24
  # the table to which this column belongs
26
25
  attr_accessor :table
27
26
 
27
+ # the column name
28
+ attr_accessor :name
29
+
28
30
  # the default value of the column. This may not have a value and that
29
31
  # either means that there is no default value, or one could not be
30
32
  # determined.
@@ -47,8 +49,8 @@ module Amalgalite
47
49
  #
48
50
  def initialize( db, table, name, order)
49
51
  @db = db
50
- @name = name
51
52
  @table = table
53
+ @name = name
52
54
  @order = Float(order).to_i
53
55
  @declared_data_type = nil
54
56
  @default_value = nil
@@ -326,6 +326,14 @@ module Amalgalite
326
326
  return count
327
327
  end
328
328
 
329
+ ##
330
+ # Execute a batch of statements via sqlite3_exec. This does the same as
331
+ # execute_batch, but doesn't update the statement statistics.
332
+ #
333
+ def import(sql)
334
+ @api.execute_batch(sql)
335
+ end
336
+
329
337
  ##
330
338
  # clear all the current taps
331
339
  #
@@ -486,11 +494,11 @@ module Amalgalite
486
494
  ##
487
495
  # :call-seq:
488
496
  # db.schema( dbname = "main" ) -> Schema
489
- #
490
- # Returns a Schema object containing the table and column structure of the
497
+ #
498
+ # Returns a Schema object containing the table and column structure of the
491
499
  # database.
492
500
  #
493
- def schema( dbname = "main" )
501
+ def schema( dbname = "main" )
494
502
  @schema ||= ::Amalgalite::Schema.new( self, dbname )
495
503
  if @schema and @schema.dirty?
496
504
  reload_schema!( dbname )
@@ -512,7 +520,7 @@ module Amalgalite
512
520
 
513
521
  ##
514
522
  # Run a pragma command against the database
515
- #
523
+ #
516
524
  # Returns the result set of the pragma
517
525
  def pragma( cmd, &block )
518
526
  execute("PRAGMA #{cmd}", &block)
@@ -741,9 +749,9 @@ module Amalgalite
741
749
  to_remove = possibles
742
750
  end
743
751
 
744
- to_remove.each do |db_function|
745
- @api.remove_function( db_function.name, db_function)
746
- @functions.delete( db_function.signature )
752
+ to_remove.each do |db_func|
753
+ @api.remove_function( db_func.name, db_func)
754
+ @functions.delete( db_func.signature )
747
755
  end
748
756
  end
749
757
 
@@ -802,9 +810,9 @@ module Amalgalite
802
810
  to_remove = possibles
803
811
  end
804
812
 
805
- to_remove.each do |db_aggregate|
806
- i = db_aggregate.new
807
- @api.remove_aggregate( i.name, i.arity, db_aggregate )
813
+ to_remove.each do |db_agg|
814
+ i = db_agg.new
815
+ @api.remove_aggregate( i.name, i.arity, db_agg)
808
816
  @aggregates.delete( i.signature )
809
817
  end
810
818
  end
@@ -105,7 +105,7 @@ module Amalgalite
105
105
  # The SQL to create the table for storing ruby code
106
106
  #
107
107
  def create_table_sql
108
- sql = <<-create
108
+ <<-create
109
109
  CREATE TABLE #{options[:table_name]} (
110
110
  id INTEGER PRIMARY KEY AUTOINCREMENT,
111
111
  #{options[:filename_column]} TEXT UNIQUE,
@@ -211,7 +211,10 @@ module Amalgalite
211
211
  STDERR.puts "Unable to add #{f} to the manifest, cannot find the file on disk"
212
212
  next
213
213
  end
214
- m.require_path = m.require_path.to_s[ /\A(.*)\.rb\Z/, 1]
214
+ # Make sure that we can handle files without the .rb extension
215
+ # if we have to. This means bin/foo works as a require path
216
+ # without requiring bin/foo to actually be bin/foo.rb
217
+ m.require_path = m.require_path.to_s.sub(/\.rb\Z/,'')
215
218
  manifest << m
216
219
  end
217
220
  return manifest
@@ -18,17 +18,24 @@ module Amalgalite
18
18
  end
19
19
 
20
20
  #
21
- # Allocate a database connection to the given filename
21
+ # Allocate a database connection to the given filename. For
22
+ # file databases, this means giving the same connection
23
+ # back if you ask for a connection to the same file.
24
+ # For in-memory databases, you get a new one each time.
22
25
  #
23
26
  def db_connection_to( dbfile_name )
24
- unless connection = load_path_db_connections[ dbfile_name ]
25
- connection = ::Amalgalite::Database.new( dbfile_name )
26
- load_path_db_connections[dbfile_name] = connection
27
+ if dbfile_name == ":memory:"
28
+ return ::Amalgalite::Database.new( dbfile_name )
29
+ else
30
+ unless connection = load_path_db_connections[ dbfile_name ]
31
+ connection = ::Amalgalite::Database.new( dbfile_name )
32
+ load_path_db_connections[dbfile_name] = connection
33
+ end
34
+ return connection
27
35
  end
28
- return connection
29
36
  end
30
37
 
31
- #
38
+ #
32
39
  # Setting a class level variable as a flag to know what we are currently
33
40
  # in the middle of requiring
34
41
  #
@@ -55,7 +62,7 @@ module Amalgalite
55
62
  raise ::LoadError, "amalgalite has no such file to load -- #{filename}"
56
63
  end
57
64
  end
58
- end
65
+ end
59
66
 
60
67
  attr_reader :dbfile_name
61
68
  attr_reader :table_name
@@ -96,16 +103,12 @@ module Amalgalite
96
103
  else
97
104
  begin
98
105
  filename = filename.gsub(/\.rb\Z/,'')
99
- rows = db_connection.execute(sql, filename)
100
- if rows.size > 0 then
101
- row = rows.first
102
- contents = row[contents_column].to_s
103
- if row[compressed_column] then
104
- contents = ::Amalgalite::Packer.gunzip( contents )
105
- end
106
106
 
107
- eval( contents, TOPLEVEL_BINDING, row[filename_column] )
108
- $LOADED_FEATURES << row[filename_column]
107
+ contents = file_contents(filename)
108
+
109
+ if contents
110
+ eval( contents, TOPLEVEL_BINDING, filename )
111
+ $LOADED_FEATURES << filename
109
112
  return true
110
113
  else
111
114
  return false
@@ -115,6 +118,34 @@ module Amalgalite
115
118
  end
116
119
  end
117
120
  end
121
+
122
+ #
123
+ # Return the contents of the named file.
124
+ #
125
+ def file_contents(filename)
126
+ rows = db_connection.execute(sql, filename)
127
+ if rows.size > 0 then
128
+ row = rows.first
129
+
130
+ contents = row[contents_column].to_s
131
+ if row[compressed_column] then
132
+ contents = ::Amalgalite::Packer.gunzip( contents )
133
+ end
134
+
135
+ return contents
136
+ else
137
+ return nil
138
+ end
139
+ end
140
+
141
+
142
+ #
143
+ # Import an SQL dump into the fake file system.
144
+ #
145
+ def import(sql)
146
+ db_connection.import(sql)
147
+ end
148
+
118
149
  end
119
150
  end
120
151
  require 'amalgalite/core_ext/kernel/require'
@@ -15,31 +15,52 @@ module Amalgalite
15
15
  #
16
16
  class Schema
17
17
 
18
+ # The internal database that this schema is for. Most of the time this will
19
+ # be 'main' for the main database. For the temp tables, this will be 'temp'
20
+ # and for any attached databsae, this is the name of attached database.
18
21
  attr_reader :catalog
19
- attr_reader :schema
22
+
23
+ # The schema_version at the time this schema was taken.
20
24
  attr_reader :schema_version
21
- attr_writer :dirty
25
+
26
+ # The Amalagalite::Database this schema is associated with.
22
27
  attr_reader :db
23
28
 
24
29
  #
25
30
  # Create a new instance of Schema
26
31
  #
27
- def initialize( db, catalog = 'main', schema = 'sqlite')
28
- @db = db
29
- @catalog = catalog
30
- @schema = schema
32
+ def initialize( db, catalog = 'main', master_table = 'sqlite_master' )
33
+ @db = db
34
+ @catalog = catalog
31
35
  @schema_version = nil
32
- @tables = {}
33
- @views = {}
36
+ @tables = {}
37
+ @views = {}
38
+ @master_table = master_table
39
+
40
+ if @master_table == 'sqlite_master' then
41
+ @temp_schema = ::Amalgalite::Schema.new( db, 'temp', 'sqlite_temp_master')
42
+ else
43
+ @temp_schema = nil
44
+ end
34
45
  load_schema!
35
46
  end
36
47
 
37
- def dirty?()
38
- return (@schema_version != self.current_version)
48
+ def catalog_master_table
49
+ "#{catalog}.#{@master_table}"
50
+ end
51
+
52
+ def temporary?
53
+ catalog == "temp"
54
+ end
55
+
56
+ def dirty?()
57
+ return true if (@schema_version != self.current_version)
58
+ return false unless @temp_schema
59
+ return @temp_schema.dirty?
39
60
  end
40
61
 
41
62
  def current_version
42
- @db.first_value_from("PRAGMA schema_version")
63
+ @db.first_value_from("PRAGMA #{catalog}.schema_version")
43
64
  end
44
65
 
45
66
  #
@@ -47,15 +68,24 @@ module Amalgalite
47
68
  def load_schema!
48
69
  load_tables
49
70
  load_views
71
+ if @temp_schema then
72
+ @temp_schema.load_schema!
73
+ end
50
74
  @schema_version = self.current_version
51
75
  nil
52
76
  end
53
77
 
54
78
  ##
55
- # return the tables, reloading if dirty
79
+ # return the tables, reloading if dirty.
80
+ # If there is a temp table and a normal table with the same name, then the
81
+ # temp table is the one that is returned in the hash.
56
82
  def tables
57
83
  load_schema! if dirty?
58
- return @tables
84
+ t = @tables
85
+ if @temp_schema then
86
+ t = @tables.merge( @temp_schema.tables )
87
+ end
88
+ return t
59
89
  end
60
90
 
61
91
  ##
@@ -63,7 +93,7 @@ module Amalgalite
63
93
  #
64
94
  def load_tables
65
95
  @tables = {}
66
- @db.execute("SELECT tbl_name FROM sqlite_master WHERE type = 'table' AND name != 'sqlite_sequence'") do |table_info|
96
+ @db.execute("SELECT tbl_name FROM #{catalog_master_table} WHERE type = 'table' AND name != 'sqlite_sequence'") do |table_info|
67
97
  table = load_table( table_info['tbl_name'] )
68
98
  table.indexes = load_indexes( table )
69
99
  @tables[table.name] = table
@@ -74,36 +104,26 @@ module Amalgalite
74
104
  ##
75
105
  # Load a single table
76
106
  def load_table( table_name )
77
- rows = @db.execute("SELECT tbl_name, sql FROM sqlite_master WHERE type = 'table' AND tbl_name = ?", table_name)
107
+ rows = @db.execute("SELECT tbl_name, sql FROM #{catalog_master_table} WHERE type = 'table' AND tbl_name = ?", table_name)
78
108
  table_info = rows.first
79
109
  table = nil
80
- if table_info then
110
+ if table_info then
81
111
  table = Amalgalite::Table.new( table_info['tbl_name'], table_info['sql'] )
82
- table.columns = load_columns( table )
83
112
  table.schema = self
113
+ table.columns = load_columns( table )
84
114
  table.indexes = load_indexes( table )
85
- @tables[table.name] = table
86
- else
87
- # might be a temporary table
88
- table = Amalgalite::Table.new( table_name, nil )
89
- cols = load_columns( table )
90
- if cols.size > 0 then
91
- table.columns = cols
92
- table.schema = self
93
- table.indexes = load_indexes( table )
94
- @tables[table.name] = table
95
- end
115
+ @tables[table.name] = table
96
116
  end
97
117
  return table
98
118
  end
99
119
 
100
- ##
120
+ ##
101
121
  # load all the indexes for a particular table
102
122
  #
103
123
  def load_indexes( table )
104
124
  indexes = {}
105
125
 
106
- @db.prepare("SELECT name, sql FROM sqlite_master WHERE type ='index' and tbl_name = $name") do |idx_stmt|
126
+ @db.prepare("SELECT name, sql FROM #{catalog_master_table} WHERE type ='index' and tbl_name = $name") do |idx_stmt|
107
127
  idx_stmt.execute( "$name" => table.name) do |idx_info|
108
128
  indexes[idx_info['name']] = Amalgalite::Index.new( idx_info['name'], idx_info['sql'], table )
109
129
  end
@@ -134,8 +154,8 @@ module Amalgalite
134
154
  def load_columns( table )
135
155
  cols = {}
136
156
  idx = 0
137
- @db.execute("PRAGMA table_info(#{@db.quote(table.name)})") do |row|
138
- col = Amalgalite::Column.new( "main", table.name, row['name'], row['cid'])
157
+ @db.execute("PRAGMA #{catalog}.table_info(#{@db.quote(table.name)})") do |row|
158
+ col = Amalgalite::Column.new( catalog, table.name, row['name'], row['cid'])
139
159
 
140
160
  col.default_value = row['dflt_value']
141
161
 
@@ -154,7 +174,7 @@ module Amalgalite
154
174
 
155
175
  unless table.temporary? then
156
176
  # get more exact information
157
- @db.api.table_column_metadata( "main", table.name, col.name ).each_pair do |key, value|
177
+ @db.api.table_column_metadata( catalog, table.name, col.name ).each_pair do |key, value|
158
178
  col.send("#{key}=", value)
159
179
  end
160
180
  end
@@ -168,16 +188,23 @@ module Amalgalite
168
188
  ##
169
189
  # return the views, reloading if dirty
170
190
  #
191
+ # If there is a temp view, and a regular view of the same name, then the
192
+ # temporary view is the one that is returned in the hash.
193
+ #
171
194
  def views
172
195
  reload_schema! if dirty?
173
- return @views
196
+ v = @views
197
+ if @temp_schema then
198
+ v = @views.merge( @temp_schema.views )
199
+ end
200
+ return v
174
201
  end
175
202
 
176
203
  ##
177
204
  # load a single view
178
205
  #
179
206
  def load_view( name )
180
- rows = @db.execute("SELECT name, sql FROM sqlite_master WHERE type = 'view' AND name = ?", name )
207
+ rows = @db.execute("SELECT name, sql FROM #{catalog_master_table} WHERE type = 'view' AND name = ?", name )
181
208
  view_info = rows.first
182
209
  view = Amalgalite::View.new( view_info['name'], view_info['sql'] )
183
210
  view.schema = self
@@ -188,7 +215,7 @@ module Amalgalite
188
215
  # load all the views for the database
189
216
  #
190
217
  def load_views
191
- @db.execute("SELECT name, sql FROM sqlite_master WHERE type = 'view'") do |view_info|
218
+ @db.execute("SELECT name, sql FROM #{catalog_master_table} WHERE type = 'view'") do |view_info|
192
219
  view = load_view( view_info['name'] )
193
220
  @views[view.name] = view
194
221
  end