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.
- data/CONTRIBUTING.md +49 -0
- data/{HISTORY.rdoc → HISTORY.md} +102 -73
- data/LICENSE +2 -2
- data/Manifest.txt +104 -0
- data/README.md +73 -0
- data/Rakefile +25 -0
- data/TODO.md +49 -0
- data/ext/amalgalite/{amalgalite3.c → c/amalgalite.c} +12 -12
- data/ext/amalgalite/{amalgalite3.h → c/amalgalite.h} +5 -5
- data/ext/amalgalite/{amalgalite3_blob.c → c/amalgalite_blob.c} +2 -2
- data/ext/amalgalite/{amalgalite3_constants.c → c/amalgalite_constants.c} +2 -2
- data/ext/amalgalite/{amalgalite3_database.c → c/amalgalite_database.c} +49 -21
- data/ext/amalgalite/{amalgalite3_requires_bootstrap.c → c/amalgalite_requires_bootstrap.c} +131 -58
- data/ext/amalgalite/{amalgalite3_statement.c → c/amalgalite_statement.c} +2 -2
- data/ext/amalgalite/{extconf.rb → c/extconf.rb} +6 -5
- data/ext/amalgalite/{gen_constants.rb → c/gen_constants.rb} +3 -3
- data/ext/amalgalite/c/notes.txt +134 -0
- data/ext/amalgalite/{sqlite3.c → c/sqlite3.c} +111793 -83396
- data/ext/amalgalite/{sqlite3.h → c/sqlite3.h} +1597 -383
- data/ext/amalgalite/{sqlite3_options.h → c/sqlite3_options.h} +0 -0
- data/ext/amalgalite/{sqlite3ext.h → c/sqlite3ext.h} +114 -17
- data/lib/amalgalite.rb +13 -6
- data/lib/amalgalite/1.9/amalgalite.so +0 -0
- data/lib/amalgalite/2.0/amalgalite.so +0 -0
- data/lib/amalgalite/2.1/amalgalite.so +0 -0
- data/lib/amalgalite/column.rb +7 -5
- data/lib/amalgalite/database.rb +18 -10
- data/lib/amalgalite/packer.rb +5 -2
- data/lib/amalgalite/requires.rb +47 -16
- data/lib/amalgalite/schema.rb +63 -36
- data/lib/amalgalite/sqlite3/version.rb +0 -1
- data/lib/amalgalite/statement.rb +7 -5
- data/lib/amalgalite/table.rb +9 -8
- data/lib/amalgalite/type_maps/default_map.rb +0 -1
- data/lib/amalgalite/type_maps/storage_map.rb +0 -2
- data/lib/amalgalite/type_maps/text_map.rb +0 -1
- data/lib/amalgalite/version.rb +3 -32
- data/spec/aggregate_spec.rb +1 -1
- data/spec/amalgalite_spec.rb +1 -1
- data/spec/blob_spec.rb +1 -1
- data/spec/boolean_spec.rb +2 -1
- data/spec/busy_handler.rb +1 -1
- data/spec/database_spec.rb +18 -13
- data/spec/default_map_spec.rb +1 -1
- data/spec/function_spec.rb +1 -1
- data/spec/integeration_spec.rb +2 -1
- data/spec/packer_spec.rb +4 -4
- data/spec/paths_spec.rb +1 -1
- data/spec/progress_handler_spec.rb +4 -5
- data/spec/requires_spec.rb +36 -2
- data/spec/rtree_spec.rb +6 -5
- data/spec/schema_spec.rb +28 -20
- data/spec/spec_helper.rb +7 -7
- data/spec/sqlite3/constants_spec.rb +1 -1
- data/spec/sqlite3/database_status_spec.rb +4 -4
- data/spec/sqlite3/status_spec.rb +5 -5
- data/spec/sqlite3/version_spec.rb +12 -12
- data/spec/sqlite3_spec.rb +3 -3
- data/spec/statement_spec.rb +3 -4
- data/spec/storage_map_spec.rb +1 -1
- data/spec/tap_spec.rb +4 -4
- data/spec/text_map_spec.rb +1 -1
- data/spec/type_map_spec.rb +1 -1
- data/spec/version_spec.rb +3 -10
- data/tasks/custom.rake +102 -0
- data/tasks/default.rake +247 -0
- data/tasks/extension.rake +28 -202
- data/tasks/this.rb +206 -0
- metadata +194 -236
- data/README.rdoc +0 -54
- data/gemspec.rb +0 -63
- data/lib/amalgalite/1.8/amalgalite3.so +0 -0
- data/lib/amalgalite/1.9/amalgalite3.so +0 -0
- data/tasks/announce.rake +0 -44
- data/tasks/config.rb +0 -107
- data/tasks/distribution.rake +0 -77
- data/tasks/documentation.rake +0 -36
- data/tasks/rspec.rake +0 -30
- data/tasks/utils.rb +0 -80
data/lib/amalgalite/schema.rb
CHANGED
@@ -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
|
-
|
22
|
+
|
23
|
+
# The schema_version at the time this schema was taken.
|
20
24
|
attr_reader :schema_version
|
21
|
-
|
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',
|
28
|
-
@db
|
29
|
-
@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
|
38
|
-
|
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
|
-
|
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
|
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
|
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
|
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(
|
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(
|
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
|
-
|
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
|
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
|
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
|
data/lib/amalgalite/statement.rb
CHANGED
@@ -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
|
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
|
348
|
-
if not using_rowid_column? and tbl_name and
|
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
|
|
data/lib/amalgalite/table.rb
CHANGED
@@ -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
|
30
|
-
@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
|
-
|
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 }
|
data/lib/amalgalite/version.rb
CHANGED
@@ -1,37 +1,8 @@
|
|
1
1
|
#--
|
2
2
|
# Copyright (c) 2008 Jeremy Hinegardner
|
3
|
-
# All rights reserved. See LICENSE and/or COPYING for
|
3
|
+
# All rights reserved. See LICENSE and/or COPYING for licensing details
|
4
4
|
#++
|
5
5
|
|
6
6
|
module Amalgalite
|
7
|
-
|
8
|
-
|
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
|
data/spec/aggregate_spec.rb
CHANGED
data/spec/amalgalite_spec.rb
CHANGED
data/spec/blob_spec.rb
CHANGED
data/spec/boolean_spec.rb
CHANGED
data/spec/busy_handler.rb
CHANGED
data/spec/database_spec.rb
CHANGED
@@ -1,6 +1,6 @@
|
|
1
|
-
require
|
1
|
+
require 'spec_helper'
|
2
2
|
|
3
|
-
|
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
|
-
|
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
|
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
|
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
|
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",
|
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
|
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",
|
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
|
-
|
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
|