amalgalite 1.1.2-x86-mingw32 → 1.4.0-x86-mingw32

Sign up to get free protection for your applications and to get access to all the features.
Files changed (79) hide show
  1. data/CONTRIBUTING.md +49 -0
  2. data/{HISTORY.rdoc → HISTORY.md} +102 -73
  3. data/LICENSE +2 -2
  4. data/Manifest.txt +104 -0
  5. data/README.md +73 -0
  6. data/Rakefile +25 -0
  7. data/TODO.md +49 -0
  8. data/ext/amalgalite/{amalgalite3.c → c/amalgalite.c} +12 -12
  9. data/ext/amalgalite/{amalgalite3.h → c/amalgalite.h} +5 -5
  10. data/ext/amalgalite/{amalgalite3_blob.c → c/amalgalite_blob.c} +2 -2
  11. data/ext/amalgalite/{amalgalite3_constants.c → c/amalgalite_constants.c} +2 -2
  12. data/ext/amalgalite/{amalgalite3_database.c → c/amalgalite_database.c} +49 -21
  13. data/ext/amalgalite/{amalgalite3_requires_bootstrap.c → c/amalgalite_requires_bootstrap.c} +131 -58
  14. data/ext/amalgalite/{amalgalite3_statement.c → c/amalgalite_statement.c} +2 -2
  15. data/ext/amalgalite/{extconf.rb → c/extconf.rb} +6 -5
  16. data/ext/amalgalite/{gen_constants.rb → c/gen_constants.rb} +3 -3
  17. data/ext/amalgalite/c/notes.txt +134 -0
  18. data/ext/amalgalite/{sqlite3.c → c/sqlite3.c} +111793 -83396
  19. data/ext/amalgalite/{sqlite3.h → c/sqlite3.h} +1597 -383
  20. data/ext/amalgalite/{sqlite3_options.h → c/sqlite3_options.h} +0 -0
  21. data/ext/amalgalite/{sqlite3ext.h → c/sqlite3ext.h} +114 -17
  22. data/lib/amalgalite.rb +13 -6
  23. data/lib/amalgalite/1.9/amalgalite.so +0 -0
  24. data/lib/amalgalite/2.0/amalgalite.so +0 -0
  25. data/lib/amalgalite/2.1/amalgalite.so +0 -0
  26. data/lib/amalgalite/column.rb +7 -5
  27. data/lib/amalgalite/database.rb +18 -10
  28. data/lib/amalgalite/packer.rb +5 -2
  29. data/lib/amalgalite/requires.rb +47 -16
  30. data/lib/amalgalite/schema.rb +63 -36
  31. data/lib/amalgalite/sqlite3/version.rb +0 -1
  32. data/lib/amalgalite/statement.rb +7 -5
  33. data/lib/amalgalite/table.rb +9 -8
  34. data/lib/amalgalite/type_maps/default_map.rb +0 -1
  35. data/lib/amalgalite/type_maps/storage_map.rb +0 -2
  36. data/lib/amalgalite/type_maps/text_map.rb +0 -1
  37. data/lib/amalgalite/version.rb +3 -32
  38. data/spec/aggregate_spec.rb +1 -1
  39. data/spec/amalgalite_spec.rb +1 -1
  40. data/spec/blob_spec.rb +1 -1
  41. data/spec/boolean_spec.rb +2 -1
  42. data/spec/busy_handler.rb +1 -1
  43. data/spec/database_spec.rb +18 -13
  44. data/spec/default_map_spec.rb +1 -1
  45. data/spec/function_spec.rb +1 -1
  46. data/spec/integeration_spec.rb +2 -1
  47. data/spec/packer_spec.rb +4 -4
  48. data/spec/paths_spec.rb +1 -1
  49. data/spec/progress_handler_spec.rb +4 -5
  50. data/spec/requires_spec.rb +36 -2
  51. data/spec/rtree_spec.rb +6 -5
  52. data/spec/schema_spec.rb +28 -20
  53. data/spec/spec_helper.rb +7 -7
  54. data/spec/sqlite3/constants_spec.rb +1 -1
  55. data/spec/sqlite3/database_status_spec.rb +4 -4
  56. data/spec/sqlite3/status_spec.rb +5 -5
  57. data/spec/sqlite3/version_spec.rb +12 -12
  58. data/spec/sqlite3_spec.rb +3 -3
  59. data/spec/statement_spec.rb +3 -4
  60. data/spec/storage_map_spec.rb +1 -1
  61. data/spec/tap_spec.rb +4 -4
  62. data/spec/text_map_spec.rb +1 -1
  63. data/spec/type_map_spec.rb +1 -1
  64. data/spec/version_spec.rb +3 -10
  65. data/tasks/custom.rake +102 -0
  66. data/tasks/default.rake +247 -0
  67. data/tasks/extension.rake +28 -202
  68. data/tasks/this.rb +206 -0
  69. metadata +194 -236
  70. data/README.rdoc +0 -54
  71. data/gemspec.rb +0 -63
  72. data/lib/amalgalite/1.8/amalgalite3.so +0 -0
  73. data/lib/amalgalite/1.9/amalgalite3.so +0 -0
  74. data/tasks/announce.rake +0 -44
  75. data/tasks/config.rb +0 -107
  76. data/tasks/distribution.rake +0 -77
  77. data/tasks/documentation.rake +0 -36
  78. data/tasks/rspec.rake +0 -30
  79. data/tasks/utils.rb +0 -80
@@ -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
@@ -36,7 +36,6 @@ module Amalgalite
36
36
  # Version of SQLite that ships with Amalgalite
37
37
  VERSION = Version.to_s.freeze
38
38
  end
39
- Version.freeze
40
39
  end
41
40
 
42
41
  unless Amalgalite::SQLite3::Version.compiled_matches_runtime? then
@@ -103,9 +103,10 @@ module Amalgalite
103
103
  end
104
104
  ensure
105
105
  s = $!
106
- begin
106
+ begin
107
107
  reset_for_next_execute!
108
- rescue => e
108
+ rescue
109
+ # rescuing nothing on purpose
109
110
  end
110
111
  raise s if s != s_before
111
112
  end
@@ -343,9 +344,10 @@ module Amalgalite
343
344
  column_meta.schema = ::Amalgalite::Column.new( db_name, tbl_name, col_name, idx )
344
345
  column_meta.schema.declared_data_type = @stmt_api.column_declared_type( idx )
345
346
 
346
- # only check for rowid if we have a table name and it is not the
347
- # sqlite_master table. We could get recursion in those cases.
348
- if not using_rowid_column? and tbl_name and tbl_name != 'sqlite_master' and is_column_rowid?( tbl_name, col_name ) then
347
+ # only check for rowid if we have a table name and it is not one of the
348
+ # sqlite_master tables. We could get recursion in those cases.
349
+ if not using_rowid_column? and tbl_name and
350
+ not %w[ sqlite_master sqlite_temp_master].include?( tbl_name ) and is_column_rowid?( tbl_name, col_name ) then
349
351
  @rowid_index = idx
350
352
  end
351
353
 
@@ -5,7 +5,7 @@
5
5
  require 'set'
6
6
  module Amalgalite
7
7
  #
8
- # a class representing the meta information about an SQLite table
8
+ # a class representing the meta information about an SQLite table
9
9
  #
10
10
  class Table
11
11
  # the schema object the table is associated with
@@ -25,19 +25,20 @@ module Amalgalite
25
25
  # in this table. keys are the column names
26
26
  attr_accessor :columns
27
27
 
28
- def initialize( name, sql = nil )
29
- @name = name
30
- @sql = sql
31
- @indexes = {}
32
- @columns = {}
28
+ def initialize( name, sql = nil )
29
+ @name = name
30
+ @sql = sql
31
+ @indexes = {}
32
+ @columns = {}
33
+ @schema = nil
34
+ @primary_key = nil
33
35
  end
34
36
 
35
37
  # Is the table a temporary table or not
36
38
  def temporary?
37
- !sql
39
+ schema.temporary?
38
40
  end
39
41
 
40
-
41
42
  # the Columns in original definition order
42
43
  def columns_in_order
43
44
  @columns.values.sort_by { |c| c.order }
@@ -3,7 +3,6 @@
3
3
  # All rights reserved. See LICENSE and/or COPYING for details.
4
4
  #++
5
5
 
6
- require 'amalgalite/type_map'
7
6
  require 'time'
8
7
  require 'date'
9
8
 
@@ -3,8 +3,6 @@
3
3
  # All rights reserved. See LICENSE and/or COPYING for details.
4
4
  #++
5
5
 
6
- require 'amalgalite/type_map'
7
-
8
6
  module Amalgalite::TypeMaps
9
7
  ##
10
8
  # An Amalagliate TypeMap that has a one-to-one conversion between SQLite types
@@ -3,7 +3,6 @@
3
3
  # All rights reserved. See LICENSE and/or COPYING for details.
4
4
  #++
5
5
  #
6
- require 'amalgalite/type_map'
7
6
 
8
7
  module Amalgalite::TypeMaps
9
8
  ##
@@ -1,37 +1,8 @@
1
1
  #--
2
2
  # Copyright (c) 2008 Jeremy Hinegardner
3
- # All rights reserved. See LICENSE and/or COPYING for licensingn details
3
+ # All rights reserved. See LICENSE and/or COPYING for licensing details
4
4
  #++
5
5
 
6
6
  module Amalgalite
7
- # Version information for Amagalite
8
- module Version
9
-
10
- MAJOR = 1
11
- MINOR = 1
12
- BUILD = 2
13
-
14
- #
15
- # return the Version as an array of MAJOR, MINOR, BUILD
16
- #
17
- def self.to_a
18
- [MAJOR, MINOR, BUILD]
19
- end
20
-
21
- # return the Version as a dotted String MAJOR.MINOR.BUILD
22
- def self.to_s
23
- to_a.join(".")
24
- end
25
-
26
- # return the Vesion as a hash
27
- def self.to_hash
28
- { :major => MAJOR, :minor => MINOR, :build => BUILD }
29
- end
30
-
31
- # Version string constant
32
- STRING = Version.to_s.freeze
33
- end
34
-
35
- # Version string constant
36
- VERSION = Version.to_s.freeze
37
- end
7
+ VERSION = "1.4.0"
8
+ end
@@ -1,4 +1,4 @@
1
- require File.expand_path( File.join( File.dirname( __FILE__ ), "spec_helper.rb" ) )
1
+ require 'spec_helper'
2
2
 
3
3
  class AggregateTest1 < ::Amalgalite::Aggregate
4
4
  def initialize
@@ -1,4 +1,4 @@
1
- require File.expand_path(File.join(File.dirname(__FILE__),"spec_helper.rb"))
1
+ require 'spec_helper'
2
2
 
3
3
  describe Amalgalite do
4
4
  end
data/spec/blob_spec.rb CHANGED
@@ -1,4 +1,4 @@
1
- require File.expand_path( File.join( File.dirname(__FILE__), 'spec_helper'))
1
+ require 'spec_helper'
2
2
 
3
3
  describe Amalgalite::Blob do
4
4
 
data/spec/boolean_spec.rb CHANGED
@@ -1,4 +1,5 @@
1
- $: << File.expand_path(File.join(File.dirname(__FILE__),"..","lib"))
1
+ require 'spec_helper'
2
+
2
3
  require 'amalgalite'
3
4
  require 'amalgalite/boolean'
4
5
 
data/spec/busy_handler.rb CHANGED
@@ -1,4 +1,4 @@
1
- require File.expand_path(File.join(File.dirname(__FILE__), 'spec_helper.rb' ) )
1
+ require 'spec_helper'
2
2
 
3
3
  class BusyHandlerTest < Amalgalite::BusyHandler
4
4
  attr_accessor :call_count
@@ -1,6 +1,6 @@
1
- require File.expand_path( File.join( File.dirname(__FILE__), 'spec_helper'))
1
+ require 'spec_helper'
2
2
 
3
- $: << File.expand_path(File.join(File.dirname(__FILE__),"..","lib"))
3
+ require 'thread'
4
4
  require 'amalgalite'
5
5
  require 'amalgalite/taps/io'
6
6
  require 'amalgalite/taps/console'
@@ -59,7 +59,7 @@ describe Amalgalite::Database do
59
59
 
60
60
  it "closes normally" do
61
61
  db = Amalgalite::Database.new( SpecInfo.test_db )
62
- lambda { db.close }.should_not raise_error( Amalgalite::SQLite3::Error )
62
+ expect { db.close }.not_to raise_error
63
63
  end
64
64
 
65
65
  it "returns the id of the last inserted row" do
@@ -222,7 +222,7 @@ describe Amalgalite::Database do
222
222
  db.in_transaction?.should eql(true)
223
223
  raise "testing rollback"
224
224
  end
225
- rescue => e
225
+ rescue
226
226
  @iso_db.in_transaction?.should eql(false)
227
227
  @iso_db.execute("SELECT count(1) as cnt FROM country").first['cnt'].should eql(242)
228
228
  end
@@ -255,28 +255,28 @@ describe Amalgalite::Database do
255
255
  rescue MyExceptionTest
256
256
  db.transaction("EXCLUSIVE") { }
257
257
  end
258
- }.should_not raise_error( MyExceptionTest )
258
+ }.should_not raise_error
259
259
  end
260
260
 
261
261
  describe "#define_function" do
262
262
  it "does not allow mixing of arbitrary and mandatory arguments to an SQL function" do
263
- class FunctionTest2 < ::Amalgalite::Function
263
+ class DBFunctionTest2 < ::Amalgalite::Function
264
264
  def initialize
265
265
  super( 'ftest2', -2 )
266
266
  end
267
267
  def call( a, *args ); end
268
268
  end
269
- lambda { @iso_db.define_function("ftest2", FunctionTest2.new ) }.should raise_error( ::Amalgalite::Database::FunctionError )
269
+ lambda { @iso_db.define_function("ftest2", DBFunctionTest2.new ) }.should raise_error( ::Amalgalite::Database::FunctionError )
270
270
  end
271
271
 
272
272
  it "does not allow outrageous arity" do
273
- class FunctionTest3 < ::Amalgalite::Function
273
+ class DBFunctionTest3 < ::Amalgalite::Function
274
274
  def initialize
275
275
  super( 'ftest3', 128 )
276
276
  end
277
277
  def call( *args) ; end
278
278
  end
279
- lambda { @iso_db.define_function("ftest3", FunctionTest3.new ) }.should raise_error( ::Amalgalite::SQLite3::Error )
279
+ lambda { @iso_db.define_function("ftest3", DBFunctionTest3.new ) }.should raise_error( ::Amalgalite::SQLite3::Error )
280
280
  end
281
281
 
282
282
  end
@@ -364,7 +364,7 @@ describe Amalgalite::Database do
364
364
  end
365
365
 
366
366
  rudeness = Thread.new( @iso_db ) do |db|
367
- sent = control_queue.deq
367
+ control_queue.deq
368
368
  count = 0
369
369
  loop do
370
370
  @iso_db.interrupt!
@@ -410,13 +410,12 @@ describe Amalgalite::Database do
410
410
  end
411
411
 
412
412
  it "rolls back a savepoint" do
413
- all_sub = @iso_db.execute("SELECT count(*) as cnt from subcountry").first['cnt']
414
413
  us_sub = @iso_db.execute("SELECT count(*) as cnt from subcountry where country = 'US'").first['cnt']
415
414
  lambda {
416
415
  @iso_db.savepoint( "t1" ) do |s|
417
416
  s.execute("DELETE FROM subcountry where country = 'US'")
418
417
  as = @iso_db.execute("SELECT count(*) as cnt from subcountry where country = 'US'").first['cnt']
419
- as.should == 0
418
+ as.should be == 0
420
419
  raise "sample error"
421
420
  end
422
421
  }.should raise_error( StandardError, /sample error/ )
@@ -494,7 +493,7 @@ describe Amalgalite::Database do
494
493
  @iso_db.replicate_to( fdb )
495
494
  @iso_db.close
496
495
 
497
- File.exist?( SpecInfo.test_db ).should == true
496
+ File.exist?( SpecInfo.test_db ).should be == true
498
497
  fdb.execute("SELECT count(*) as cnt from subcountry").first['cnt'].should == all_sub
499
498
  end
500
499
 
@@ -502,4 +501,10 @@ describe Amalgalite::Database do
502
501
  lambda { @iso_db.replicate_to( false ) }.should raise_error( ArgumentError, /must be a String or a Database/ )
503
502
  end
504
503
 
504
+ it "imports batch statements" do
505
+ db = Amalgalite::Database.new(":memory:")
506
+ db.import("CREATE TABLE things(stuff TEXT); INSERT INTO things (stuff) VALUES (\"foobar\");").should be_truthy
507
+ db.first_value_from("SELECT stuff FROM things").should == "foobar"
508
+ end
509
+
505
510
  end