amalgalite 1.8.0-x64-mingw-ucrt
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/CONTRIBUTING.md +60 -0
- data/HISTORY.md +386 -0
- data/LICENSE +31 -0
- data/Manifest.txt +105 -0
- data/README.md +62 -0
- data/Rakefile +27 -0
- data/TODO.md +57 -0
- data/bin/amalgalite-pack +147 -0
- data/examples/a.rb +9 -0
- data/examples/blob.rb +88 -0
- data/examples/bootstrap.rb +36 -0
- data/examples/define_aggregate.rb +75 -0
- data/examples/define_function.rb +104 -0
- data/examples/fts5.rb +152 -0
- data/examples/gem-db.rb +94 -0
- data/examples/require_me.rb +11 -0
- data/examples/requires.rb +42 -0
- data/examples/schema-info.rb +34 -0
- data/ext/amalgalite/c/amalgalite.c +355 -0
- data/ext/amalgalite/c/amalgalite.h +151 -0
- data/ext/amalgalite/c/amalgalite_blob.c +240 -0
- data/ext/amalgalite/c/amalgalite_constants.c +1432 -0
- data/ext/amalgalite/c/amalgalite_database.c +1188 -0
- data/ext/amalgalite/c/amalgalite_requires_bootstrap.c +282 -0
- data/ext/amalgalite/c/amalgalite_statement.c +649 -0
- data/ext/amalgalite/c/extconf.rb +71 -0
- data/ext/amalgalite/c/gen_constants.rb +353 -0
- data/ext/amalgalite/c/notes.txt +134 -0
- data/ext/amalgalite/c/sqlite3.c +243616 -0
- data/ext/amalgalite/c/sqlite3.h +12894 -0
- data/ext/amalgalite/c/sqlite3_options.h +4 -0
- data/ext/amalgalite/c/sqlite3ext.h +705 -0
- data/lib/amalgalite/3.1/amalgalite.so +0 -0
- data/lib/amalgalite/aggregate.rb +73 -0
- data/lib/amalgalite/blob.rb +186 -0
- data/lib/amalgalite/boolean.rb +42 -0
- data/lib/amalgalite/busy_timeout.rb +47 -0
- data/lib/amalgalite/column.rb +99 -0
- data/lib/amalgalite/core_ext/kernel/require.rb +21 -0
- data/lib/amalgalite/csv_table_importer.rb +75 -0
- data/lib/amalgalite/database.rb +933 -0
- data/lib/amalgalite/function.rb +61 -0
- data/lib/amalgalite/index.rb +43 -0
- data/lib/amalgalite/memory_database.rb +15 -0
- data/lib/amalgalite/packer.rb +231 -0
- data/lib/amalgalite/paths.rb +80 -0
- data/lib/amalgalite/profile_tap.rb +131 -0
- data/lib/amalgalite/progress_handler.rb +21 -0
- data/lib/amalgalite/requires.rb +151 -0
- data/lib/amalgalite/schema.rb +225 -0
- data/lib/amalgalite/sqlite3/constants.rb +95 -0
- data/lib/amalgalite/sqlite3/database/function.rb +48 -0
- data/lib/amalgalite/sqlite3/database/status.rb +68 -0
- data/lib/amalgalite/sqlite3/status.rb +60 -0
- data/lib/amalgalite/sqlite3/version.rb +55 -0
- data/lib/amalgalite/sqlite3.rb +6 -0
- data/lib/amalgalite/statement.rb +421 -0
- data/lib/amalgalite/table.rb +91 -0
- data/lib/amalgalite/taps/console.rb +27 -0
- data/lib/amalgalite/taps/io.rb +74 -0
- data/lib/amalgalite/taps.rb +2 -0
- data/lib/amalgalite/trace_tap.rb +35 -0
- data/lib/amalgalite/type_map.rb +63 -0
- data/lib/amalgalite/type_maps/default_map.rb +166 -0
- data/lib/amalgalite/type_maps/storage_map.rb +38 -0
- data/lib/amalgalite/type_maps/text_map.rb +21 -0
- data/lib/amalgalite/version.rb +8 -0
- data/lib/amalgalite/view.rb +26 -0
- data/lib/amalgalite.rb +51 -0
- data/spec/aggregate_spec.rb +158 -0
- data/spec/amalgalite_spec.rb +4 -0
- data/spec/blob_spec.rb +78 -0
- data/spec/boolean_spec.rb +24 -0
- data/spec/busy_handler.rb +157 -0
- data/spec/data/iso-3166-country.txt +242 -0
- data/spec/data/iso-3166-schema.sql +22 -0
- data/spec/data/iso-3166-subcountry.txt +3995 -0
- data/spec/data/make-iso-db.sh +12 -0
- data/spec/database_spec.rb +505 -0
- data/spec/default_map_spec.rb +92 -0
- data/spec/function_spec.rb +78 -0
- data/spec/integeration_spec.rb +97 -0
- data/spec/iso_3166_database.rb +58 -0
- data/spec/json_spec.rb +24 -0
- data/spec/packer_spec.rb +60 -0
- data/spec/paths_spec.rb +28 -0
- data/spec/progress_handler_spec.rb +91 -0
- data/spec/requires_spec.rb +54 -0
- data/spec/rtree_spec.rb +66 -0
- data/spec/schema_spec.rb +131 -0
- data/spec/spec_helper.rb +48 -0
- data/spec/sqlite3/constants_spec.rb +108 -0
- data/spec/sqlite3/database_status_spec.rb +36 -0
- data/spec/sqlite3/status_spec.rb +22 -0
- data/spec/sqlite3/version_spec.rb +28 -0
- data/spec/sqlite3_spec.rb +53 -0
- data/spec/statement_spec.rb +168 -0
- data/spec/storage_map_spec.rb +38 -0
- data/spec/tap_spec.rb +57 -0
- data/spec/text_map_spec.rb +20 -0
- data/spec/type_map_spec.rb +14 -0
- data/spec/version_spec.rb +8 -0
- data/tasks/custom.rake +101 -0
- data/tasks/default.rake +244 -0
- data/tasks/extension.rake +28 -0
- data/tasks/this.rb +208 -0
- metadata +325 -0
@@ -0,0 +1,108 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
require 'amalgalite/sqlite3/constants'
|
4
|
+
|
5
|
+
describe Amalgalite::SQLite3::Constants do
|
6
|
+
|
7
|
+
it "has Open constants" do
|
8
|
+
Amalgalite::SQLite3::Constants::Open::READONLY.should > 0
|
9
|
+
end
|
10
|
+
|
11
|
+
describe 'ResultCode' do
|
12
|
+
it "has constants" do
|
13
|
+
Amalgalite::SQLite3::Constants::ResultCode::OK.should == 0
|
14
|
+
end
|
15
|
+
|
16
|
+
it "can return the constant from a number" do
|
17
|
+
c = Amalgalite::SQLite3::Constants::ResultCode.name_from_value( 21 )
|
18
|
+
c.should == "MISUSE"
|
19
|
+
end
|
20
|
+
|
21
|
+
it "can return the number from a name" do
|
22
|
+
v = Amalgalite::SQLite3::Constants::ResultCode.value_from_name( "MISUSE" )
|
23
|
+
v.should == 21
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
describe "DataType" do
|
28
|
+
it "has constants" do
|
29
|
+
Amalgalite::SQLite3::Constants::DataType::NULL.should == 5
|
30
|
+
end
|
31
|
+
|
32
|
+
it "can return the constant from a number" do
|
33
|
+
c = Amalgalite::SQLite3::Constants::DataType.name_from_value( 5 )
|
34
|
+
c.should == "NULL"
|
35
|
+
end
|
36
|
+
|
37
|
+
it "can return the number from a name" do
|
38
|
+
v = Amalgalite::SQLite3::Constants::DataType.value_from_name( "Null" )
|
39
|
+
v.should == 5
|
40
|
+
end
|
41
|
+
|
42
|
+
end
|
43
|
+
|
44
|
+
describe "Config" do
|
45
|
+
it "has constants" do
|
46
|
+
Amalgalite::SQLite3::Constants::Config::HEAP.should == 8
|
47
|
+
end
|
48
|
+
|
49
|
+
it "can return the constant from a number" do
|
50
|
+
c = Amalgalite::SQLite3::Constants::Config.name_from_value( 8 )
|
51
|
+
c.should == "HEAP"
|
52
|
+
end
|
53
|
+
|
54
|
+
it "can return the number from a name" do
|
55
|
+
v = Amalgalite::SQLite3::Constants::Config.value_from_name( "heap" )
|
56
|
+
v.should == 8
|
57
|
+
end
|
58
|
+
|
59
|
+
end
|
60
|
+
|
61
|
+
describe 'Status' do
|
62
|
+
it "has constants" do
|
63
|
+
Amalgalite::SQLite3::Constants::Status::MEMORY_USED.should == 0
|
64
|
+
end
|
65
|
+
|
66
|
+
it "can return the constant from a number" do
|
67
|
+
c = Amalgalite::SQLite3::Constants::Status.name_from_value( 3 )
|
68
|
+
c.should == "SCRATCH_USED"
|
69
|
+
end
|
70
|
+
|
71
|
+
it "can return the number from a name" do
|
72
|
+
v = Amalgalite::SQLite3::Constants::Status.value_from_name( "memory_used" )
|
73
|
+
v.should == 0
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
describe 'DBStatus' do
|
78
|
+
it "has constants" do
|
79
|
+
Amalgalite::SQLite3::Constants::DBStatus::LOOKASIDE_USED.should == 0
|
80
|
+
end
|
81
|
+
|
82
|
+
it "can return the constant from a number" do
|
83
|
+
c = Amalgalite::SQLite3::Constants::DBStatus.name_from_value( 0 )
|
84
|
+
c.should == "LOOKASIDE_USED"
|
85
|
+
end
|
86
|
+
|
87
|
+
it "can return the number from a name" do
|
88
|
+
v = Amalgalite::SQLite3::Constants::DBStatus.value_from_name( "lookaside_used" )
|
89
|
+
v.should == 0
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
describe "StatementStatus" do
|
94
|
+
it "has constants" do
|
95
|
+
Amalgalite::SQLite3::Constants::StatementStatus::AUTOINDEX.should == 3
|
96
|
+
end
|
97
|
+
|
98
|
+
it "can return the constant from a number" do
|
99
|
+
c = Amalgalite::SQLite3::Constants::StatementStatus.name_from_value( 3 )
|
100
|
+
c.should == "AUTOINDEX"
|
101
|
+
end
|
102
|
+
|
103
|
+
it "can return the number from a name" do
|
104
|
+
v = Amalgalite::SQLite3::Constants::StatementStatus.value_from_name( "autoindex" )
|
105
|
+
v.should == 3
|
106
|
+
end
|
107
|
+
end
|
108
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'amalgalite/sqlite3'
|
3
|
+
require 'rbconfig'
|
4
|
+
|
5
|
+
describe "Amalgalite::SQLite3::Database::Status" do
|
6
|
+
before(:each) do
|
7
|
+
@db = Amalgalite::Database.new( "lookaside-test.db" )
|
8
|
+
@db.execute(" create table t(a, b)")
|
9
|
+
20.times do |x|
|
10
|
+
@db.execute("insert into t(a, b) values (?,?);", x, x+1)
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
after(:each) do
|
15
|
+
@db.close
|
16
|
+
::FileUtils.rm_f "lookaside-test.db"
|
17
|
+
end
|
18
|
+
|
19
|
+
|
20
|
+
it "knows how much lookaside memory it has used" do
|
21
|
+
@db.api.status.lookaside_used.highwater.should be > 0
|
22
|
+
@db.api.status.lookaside_used.current.should be >= 0
|
23
|
+
end
|
24
|
+
|
25
|
+
it "can reset the highwater value" do
|
26
|
+
stat = @db.api.status.lookaside_used
|
27
|
+
before = stat.highwater
|
28
|
+
before.should be > 0
|
29
|
+
|
30
|
+
stat.reset!
|
31
|
+
after = stat.highwater
|
32
|
+
|
33
|
+
after.should eql(0)
|
34
|
+
after.should_not eql(before)
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'amalgalite/sqlite3'
|
3
|
+
require 'rbconfig'
|
4
|
+
|
5
|
+
describe "Amalgalite::SQLite3::Status" do
|
6
|
+
it "knows how much memory it has used" do
|
7
|
+
Amalgalite::SQLite3.status.memory_used.current.should be >= 0
|
8
|
+
Amalgalite::SQLite3.status.memory_used.highwater.should be >= 0
|
9
|
+
end
|
10
|
+
|
11
|
+
it "can reset the highwater value" do
|
12
|
+
before = Amalgalite::SQLite3.status.memory_used.highwater
|
13
|
+
before.should be > 0
|
14
|
+
|
15
|
+
current = Amalgalite::SQLite3.status.memory_used.current
|
16
|
+
Amalgalite::SQLite3.status.memory_used.reset!
|
17
|
+
Amalgalite::SQLite3.status.memory_used.highwater.should be == current
|
18
|
+
|
19
|
+
after = Amalgalite::SQLite3.status.memory_used.highwater
|
20
|
+
after.should_not eql(before)
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'amalgalite/sqlite3/version'
|
3
|
+
|
4
|
+
describe "Amalgalite::SQLite3::Version" do
|
5
|
+
it "should have the sqlite3 version" do
|
6
|
+
expect(Amalgalite::SQLite3::VERSION).to match(/\d+\.\d+\.\d+/)
|
7
|
+
expect(Amalgalite::SQLite3::Version.to_s).to match( /\d+\.\d+\.\d+/ )
|
8
|
+
expect(Amalgalite::SQLite3::Version.runtime_version).to match( /\d+\.\d+\.\d+/ )
|
9
|
+
|
10
|
+
Amalgalite::SQLite3::Version.to_i.should eql(3040001)
|
11
|
+
Amalgalite::SQLite3::Version.runtime_version_number.should eql(3040001)
|
12
|
+
|
13
|
+
Amalgalite::SQLite3::Version::MAJOR.should eql(3)
|
14
|
+
Amalgalite::SQLite3::Version::MINOR.should eql(40)
|
15
|
+
Amalgalite::SQLite3::Version::RELEASE.should eql(1)
|
16
|
+
expect(Amalgalite::SQLite3::Version.to_a.size).to eql(3)
|
17
|
+
|
18
|
+
Amalgalite::SQLite3::Version.compiled_version.should be == "3.40.1"
|
19
|
+
Amalgalite::SQLite3::Version.compiled_version_number.should be == 3040001
|
20
|
+
Amalgalite::SQLite3::Version.compiled_matches_runtime?.should be == true
|
21
|
+
end
|
22
|
+
|
23
|
+
it "should have the sqlite3 source id" do
|
24
|
+
source_id = "2022-12-28 14:03:47 df5c253c0b3dd24916e4ec7cf77d3db5294cc9fd45ae7b9c5e82ad8197f38a24"
|
25
|
+
Amalgalite::SQLite3::Version.compiled_source_id.should be == source_id
|
26
|
+
Amalgalite::SQLite3::Version.runtime_source_id.should be == source_id
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,53 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'amalgalite/sqlite3'
|
3
|
+
require 'rbconfig'
|
4
|
+
|
5
|
+
describe "Amalgalite::SQLite3" do
|
6
|
+
it "is threadsafe is ruby is compiled with pthread support, in this case that is (#{RbConfig::CONFIG['configure_args'].include?( "--enable-pthread" )})" do
|
7
|
+
Amalgalite::SQLite3.threadsafe?.should eql(RbConfig::CONFIG['configure_args'].include?( "--enable-pthread" ))
|
8
|
+
end
|
9
|
+
|
10
|
+
it "knows if an SQL statement is complete" do
|
11
|
+
Amalgalite::SQLite3.complete?("SELECT * FROM sometable;").should eql(true)
|
12
|
+
#Amalgalite::SQLite3.complete?("SELECT * FROM sometable;", :utf16 => true).should eql(true)
|
13
|
+
end
|
14
|
+
|
15
|
+
it "knows if an SQL statement is not complete" do
|
16
|
+
Amalgalite::SQLite3.complete?("SELECT * FROM sometable ").should eql(false)
|
17
|
+
#Amalgalite::SQLite3.complete?("SELECT * FROM sometable WHERE ", :utf16 => true).should eql(false)
|
18
|
+
end
|
19
|
+
|
20
|
+
it "can produce random data" do
|
21
|
+
Amalgalite::SQLite3.randomness( 42 ).size.should eql(42)
|
22
|
+
end
|
23
|
+
|
24
|
+
it "has nil for the default sqlite temporary directory" do
|
25
|
+
Amalgalite::SQLite3.temp_directory.should eql(nil)
|
26
|
+
end
|
27
|
+
|
28
|
+
it "can set the temporary directory" do
|
29
|
+
Amalgalite::SQLite3.temp_directory.should eql(nil)
|
30
|
+
Amalgalite::SQLite3.temp_directory = "/tmp/testing"
|
31
|
+
Amalgalite::SQLite3.temp_directory.should eql("/tmp/testing")
|
32
|
+
Amalgalite::SQLite3.temp_directory = nil
|
33
|
+
Amalgalite::SQLite3.temp_directory.should eql(nil)
|
34
|
+
end
|
35
|
+
|
36
|
+
it "can escape quoted strings" do
|
37
|
+
Amalgalite::SQLite3.escape( "It's a happy day!" ).should eql("It''s a happy day!")
|
38
|
+
end
|
39
|
+
|
40
|
+
it "can escape a symble into a string" do
|
41
|
+
Amalgalite::SQLite3.escape( :stuff ).should eql("stuff")
|
42
|
+
Amalgalite::SQLite3.escape( :"stuff'n" ).should eql("stuff''n")
|
43
|
+
end
|
44
|
+
|
45
|
+
it "can quote and escape single quoted strings" do
|
46
|
+
Amalgalite::SQLite3.quote( "It's a happy day!" ).should eql("'It''s a happy day!'")
|
47
|
+
end
|
48
|
+
|
49
|
+
it "can quote and escape symbols" do
|
50
|
+
Amalgalite::SQLite3.quote( :stuff ).should eql("'stuff'")
|
51
|
+
Amalgalite::SQLite3.quote( :"stuff'n" ).should eql("'stuff''n'")
|
52
|
+
end
|
53
|
+
end
|
@@ -0,0 +1,168 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Amalgalite::Statement do
|
4
|
+
before(:each) do
|
5
|
+
@db = Amalgalite::Database.new( SpecInfo.test_db )
|
6
|
+
end
|
7
|
+
|
8
|
+
after(:each) do
|
9
|
+
@db.close
|
10
|
+
end
|
11
|
+
|
12
|
+
it "a statement has a copy of the sql it was prepared with" do
|
13
|
+
stmt = @db.prepare( "SELECT strftime('%Y-%m-%d %H:%M:%S', 'now')")
|
14
|
+
stmt.sql.should eql("SELECT strftime('%Y-%m-%d %H:%M:%S', 'now')")
|
15
|
+
stmt.close
|
16
|
+
end
|
17
|
+
|
18
|
+
it "steps through results" do
|
19
|
+
now = Time.new.utc.strftime("%Y-%m-%d %H:%M")
|
20
|
+
@db.prepare( "SELECT strftime('%Y-%m-%d %H:%M', 'now') as now") do |stmt|
|
21
|
+
stmt.should_not eql(nil)
|
22
|
+
stmt.each do |row|
|
23
|
+
row['now'].should eql(now)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
it "can prepare a statement without a block" do
|
29
|
+
stmt = @iso_db.prepare("SELECT * FROM country WHERE two_letter = :two")
|
30
|
+
rs = stmt.execute( ":two" => "JP" )
|
31
|
+
rs.size.should eql(1)
|
32
|
+
stmt.close
|
33
|
+
end
|
34
|
+
|
35
|
+
it "knows how many parameters are in the statement" do
|
36
|
+
@iso_db.prepare("SELECT * FROM country WHERE two_letter = :two") do |stmt|
|
37
|
+
stmt.check_parameter_count!( 1 ).should eql(1)
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
it "raises an error if there are not enough parameters are passed in a statement" do
|
42
|
+
@iso_db.prepare("SELECT * FROM country WHERE two_letter = :two") do |stmt|
|
43
|
+
lambda{ stmt.execute }.should raise_error( Amalgalite::Error )
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
|
48
|
+
it "can run a query with a named parameter" do
|
49
|
+
@iso_db.prepare("SELECT * FROM country WHERE two_letter = :two") do |stmt|
|
50
|
+
all_rows = stmt.execute( ":two" => "JP" )
|
51
|
+
all_rows.size.should eql(1)
|
52
|
+
all_rows.first['name'].should eql("Japan")
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
it "it can execute a query with a named parameter and yield the rows" do
|
57
|
+
@iso_db.prepare("SELECT * FROM country WHERE id = @id ORDER BY name") do |stmt|
|
58
|
+
rows = []
|
59
|
+
stmt.execute( "@id" => 891 ) do |row|
|
60
|
+
rows << row
|
61
|
+
end
|
62
|
+
rows.size.should eql(2)
|
63
|
+
rows.last['name'].should eql("Yugoslavia")
|
64
|
+
rows.first['two_letter'].should eql("CS")
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
it "can execute the same prepared statement multiple times" do
|
69
|
+
@db.execute(" CREATE TABLE t(x,y); ")
|
70
|
+
values = {}
|
71
|
+
@db.prepare("INSERT INTO t( x, y ) VALUES( $x, $y )" ) do |stmt|
|
72
|
+
20.times do |x|
|
73
|
+
y = rand( x )
|
74
|
+
stmt.execute( { "$x" => x, "$y" => y } )
|
75
|
+
values[x] = y
|
76
|
+
end
|
77
|
+
end
|
78
|
+
c = 0
|
79
|
+
@db.execute("SELECT * from t") do |row|
|
80
|
+
c += 1
|
81
|
+
values[ row['x'] ].should eql(row['y'])
|
82
|
+
end
|
83
|
+
c.should eql(20)
|
84
|
+
end
|
85
|
+
|
86
|
+
it "expands an array when binding parameters" do
|
87
|
+
@db.execute(" CREATE TABLE t(x,y); ")
|
88
|
+
values = {}
|
89
|
+
@db.prepare( "INSERT INTO t( x, y ) VALUES( ?, ? )") do |stmt|
|
90
|
+
20.times do |x|
|
91
|
+
y = rand( x )
|
92
|
+
a = [ x, y ]
|
93
|
+
stmt.execute( a )
|
94
|
+
values[x] = y
|
95
|
+
end
|
96
|
+
end
|
97
|
+
c = 0
|
98
|
+
@db.execute("SELECT * from t") do |row|
|
99
|
+
c += 1
|
100
|
+
values[ row['x'] ].should eql(row['y'])
|
101
|
+
end
|
102
|
+
c.should eql(20)
|
103
|
+
|
104
|
+
end
|
105
|
+
|
106
|
+
it "binds a integer variable correctly" do
|
107
|
+
@iso_db.prepare("SELECT * FROM country WHERE id = ? ORDER BY name ") do |stmt|
|
108
|
+
all_rows = stmt.execute( 891 )
|
109
|
+
all_rows.size.should eql(2)
|
110
|
+
all_rows.last['name'].should eql("Yugoslavia")
|
111
|
+
all_rows.first['two_letter'].should eql("CS")
|
112
|
+
end
|
113
|
+
end
|
114
|
+
|
115
|
+
it "raises and error if an invaliding binding is attempted" do
|
116
|
+
@iso_db.prepare("SELECT * FROM country WHERE id = :somevar ORDER BY name ") do |stmt|
|
117
|
+
lambda{ stmt.execute( "blah" => 42 ) }.should raise_error(Amalgalite::Error)
|
118
|
+
end
|
119
|
+
end
|
120
|
+
|
121
|
+
it "can reset the statement to the state it was before executing" do
|
122
|
+
stmt = @iso_db.prepare("SELECT * FROM country WHERE id = :somevar ORDER BY name ")
|
123
|
+
stmt.reset_and_clear_bindings!
|
124
|
+
stmt.close
|
125
|
+
end
|
126
|
+
|
127
|
+
it "can execute a single sql command and say if there is remaining sql to execute" do
|
128
|
+
stmt = @db.prepare( @schema )
|
129
|
+
stmt.execute
|
130
|
+
stmt.remaining_sql.size.should be > 0
|
131
|
+
stmt.close
|
132
|
+
end
|
133
|
+
|
134
|
+
it "can select the rowid from the table" do
|
135
|
+
db = Amalgalite::Database.new( ":memory:" )
|
136
|
+
db.execute( "create table t1(c1,c2,c3)" )
|
137
|
+
db.execute("insert into t1(c1,c2,c3) values (1,2,'abc')")
|
138
|
+
rows = db.execute( "select rowid,* from t1")
|
139
|
+
rows.size.should eql(1)
|
140
|
+
rows.first['rowid'].should eql(1)
|
141
|
+
rows.first['c1'].should eql(1 )
|
142
|
+
rows.first['c3'].should eql('abc')
|
143
|
+
end
|
144
|
+
|
145
|
+
it "shows that the rowid column is rowid column" do
|
146
|
+
db = Amalgalite::Database.new( ":memory:" )
|
147
|
+
db.execute( "create table t1(c1,c2,c3)" )
|
148
|
+
db.execute("insert into t1(c1,c2,c3) values (1,2,'abc')")
|
149
|
+
db.prepare( "select oid,* from t1" ) do |stmt|
|
150
|
+
stmt.execute
|
151
|
+
stmt.should be_using_rowid_column
|
152
|
+
end
|
153
|
+
|
154
|
+
db.prepare( "select * from t1" ) do |stmt|
|
155
|
+
stmt.execute
|
156
|
+
stmt.should_not be_using_rowid_column
|
157
|
+
end
|
158
|
+
end
|
159
|
+
|
160
|
+
it "has index based access to the result set" do
|
161
|
+
@iso_db.prepare("SELECT * FROM country WHERE id = ? ORDER BY name ") do |stmt|
|
162
|
+
all_rows = stmt.execute( 891 )
|
163
|
+
all_rows.size.should eql(2)
|
164
|
+
all_rows.last.first.should eql("Yugoslavia")
|
165
|
+
all_rows.first[1].should eql("CS")
|
166
|
+
end
|
167
|
+
end
|
168
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'amalgalite/type_maps/storage_map'
|
3
|
+
|
4
|
+
describe Amalgalite::TypeMaps::StorageMap do
|
5
|
+
before(:each) do
|
6
|
+
@map = Amalgalite::TypeMaps::StorageMap.new
|
7
|
+
end
|
8
|
+
|
9
|
+
describe "#bind_type_of" do
|
10
|
+
|
11
|
+
it "Float is bound to DataType::FLOAT" do
|
12
|
+
@map.bind_type_of( 3.14 ).should == ::Amalgalite::SQLite3::Constants::DataType::FLOAT
|
13
|
+
end
|
14
|
+
|
15
|
+
it "Integer is bound to DataType::INTGER" do
|
16
|
+
@map.bind_type_of( 42 ).should == ::Amalgalite::SQLite3::Constants::DataType::INTEGER
|
17
|
+
end
|
18
|
+
|
19
|
+
it "nil is bound to DataType::NULL" do
|
20
|
+
@map.bind_type_of( nil ).should == ::Amalgalite::SQLite3::Constants::DataType::NULL
|
21
|
+
end
|
22
|
+
|
23
|
+
it "::Amalgalite::Blob is bound to DataType::BLOB" do
|
24
|
+
@map.bind_type_of( ::Amalgalite::Blob.new( :string => "testing mapping", :column => true ) ).should == ::Amalgalite::SQLite3::Constants::DataType::BLOB
|
25
|
+
end
|
26
|
+
|
27
|
+
it "everything else is bound to DataType::TEXT" do
|
28
|
+
@map.bind_type_of( "everything else" ).should == ::Amalgalite::SQLite3::Constants::DataType::TEXT
|
29
|
+
end
|
30
|
+
|
31
|
+
end
|
32
|
+
|
33
|
+
describe "#result_value_of" do
|
34
|
+
it "returns the original object for everything passed in" do
|
35
|
+
@map.result_value_of( "doesn't matter", 42 ).should == 42
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
data/spec/tap_spec.rb
ADDED
@@ -0,0 +1,57 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
require 'amalgalite'
|
4
|
+
require 'amalgalite/trace_tap'
|
5
|
+
require 'amalgalite/profile_tap'
|
6
|
+
require 'amalgalite/taps/console'
|
7
|
+
require 'stringio'
|
8
|
+
|
9
|
+
describe Amalgalite::TraceTap do
|
10
|
+
it "wraps up an object and delegates the 'trace' method to a method on that object" do
|
11
|
+
s = StringIO.new
|
12
|
+
tt = ::Amalgalite::TraceTap.new( s, 'puts' )
|
13
|
+
tt.trace('test trace')
|
14
|
+
s.string.should eql("test trace\n")
|
15
|
+
end
|
16
|
+
|
17
|
+
it "raises an error if an the wrapped object does not respond to the indicated method" do
|
18
|
+
lambda{ ::Amalgalite::TraceTap.new( Object.new ) }.should raise_error( Amalgalite::Error )
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
describe Amalgalite::ProfileTap do
|
23
|
+
it "raises an error if an the wrapped object does not respond to the indicated method" do
|
24
|
+
lambda{ ::Amalgalite::ProfileTap.new( Object.new ) }.should raise_error( Amalgalite::Error )
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
describe Amalgalite::Taps::StringIO do
|
29
|
+
it "dumps profile information" do
|
30
|
+
s = ::Amalgalite::Taps::StringIO.new
|
31
|
+
s.profile( 'test', 42 )
|
32
|
+
s.dump_profile
|
33
|
+
s.string.should eql("42 : test\n[test] => sum: 42, sumsq: 1764, n: 1, mean: 42.000000, stddev: 0.000000, min: 42, max: 42\n")
|
34
|
+
end
|
35
|
+
|
36
|
+
it "has a stdout tap" do
|
37
|
+
::Amalgalite::Taps::Stdout.new
|
38
|
+
end
|
39
|
+
|
40
|
+
it "has a stderr tap" do
|
41
|
+
::Amalgalite::Taps::Stderr.new
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
describe Amalgalite::ProfileSampler do
|
46
|
+
it "aggregates samples" do
|
47
|
+
s = Amalgalite::ProfileSampler.new( 'test1' )
|
48
|
+
s.sample( 42 )
|
49
|
+
s.sample( 84 )
|
50
|
+
s.sample( 21 )
|
51
|
+
h = s.to_h
|
52
|
+
h['min'].should eql(21)
|
53
|
+
h['max'].should eql(84)
|
54
|
+
h['mean'].should eql(49.0)
|
55
|
+
h['n'].should eql(3)
|
56
|
+
end
|
57
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'amalgalite/type_maps/text_map'
|
3
|
+
|
4
|
+
describe Amalgalite::TypeMaps::TextMap do
|
5
|
+
before(:each) do
|
6
|
+
@map = Amalgalite::TypeMaps::TextMap.new
|
7
|
+
end
|
8
|
+
|
9
|
+
describe "#bind_type_of" do
|
10
|
+
it "returnes text for everything" do
|
11
|
+
@map.bind_type_of( 3.14 ).should == ::Amalgalite::SQLite3::Constants::DataType::TEXT
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
describe "#result_value_of" do
|
16
|
+
it "returns the string value of the object for everything passed in" do
|
17
|
+
@map.result_value_of( "doesn't matter", 42 ).should == "42"
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'amalgalite/type_map'
|
3
|
+
|
4
|
+
describe Amalgalite::TypeMap do
|
5
|
+
it "#bind_type_of raises NotImplemented error" do
|
6
|
+
tm = Amalgalite::TypeMap.new
|
7
|
+
lambda { tm.bind_type_of( Object.new ) }.should raise_error( NotImplementedError )
|
8
|
+
end
|
9
|
+
|
10
|
+
it "#result_value_of raises NotImplemented error" do
|
11
|
+
tm = Amalgalite::TypeMap.new
|
12
|
+
lambda { tm.result_value_of( "foo", Object.new ) }.should raise_error( NotImplementedError )
|
13
|
+
end
|
14
|
+
end
|
data/tasks/custom.rake
ADDED
@@ -0,0 +1,101 @@
|
|
1
|
+
#-----------------------------------------------------------------------
|
2
|
+
# Custom tasks for this project
|
3
|
+
#-----------------------------------------------------------------------
|
4
|
+
require 'pathname'
|
5
|
+
namespace :util do
|
6
|
+
desc "List the sqlite api calls that are not implemented"
|
7
|
+
task :todo do
|
8
|
+
|
9
|
+
not_implementing = %w[
|
10
|
+
sqlite3_exec
|
11
|
+
sqlite3_open
|
12
|
+
sqlite3_os_end
|
13
|
+
sqlite3_os_init
|
14
|
+
sqlite3_malloc
|
15
|
+
sqlite3_realloc
|
16
|
+
sqlite3_free
|
17
|
+
sqlite3_get_table
|
18
|
+
sqlite3_free_table
|
19
|
+
sqlite3_key
|
20
|
+
sqlite3_rekey
|
21
|
+
sqlite3_next_stmt
|
22
|
+
sqlite3_release_memory
|
23
|
+
sqlite3_sleep
|
24
|
+
sqlite3_snprintf
|
25
|
+
sqlite3_vmprintf
|
26
|
+
sqlite3_strnicmp
|
27
|
+
sqlite3_test_control
|
28
|
+
sqlite3_unlock_notify
|
29
|
+
sqlite3_vfs_find
|
30
|
+
sqlite3_vfs_register
|
31
|
+
sqlite3_vfs_unregister
|
32
|
+
]
|
33
|
+
|
34
|
+
sqlite_h = File.join( *%w[ ext amalgalite c sqlite3.h ] )
|
35
|
+
api_todo = {}
|
36
|
+
IO.readlines( sqlite_h ).each do |line|
|
37
|
+
if line =~ /\ASQLITE_API/ then
|
38
|
+
if line !~ /SQLITE_DEPRECATED/ and line !~ /SQLITE_EXPERIMENTAL/ then
|
39
|
+
if md = line.match( /(sqlite3_[^(\s]+)\(/ ) then
|
40
|
+
next if not_implementing.include?(md.captures[0])
|
41
|
+
api_todo[md.captures[0]] = true
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
Dir.glob("ext/amalgalite/c/amalgalite*.c").each do |am_file|
|
48
|
+
IO.readlines( am_file ).each do |am_line|
|
49
|
+
if md = am_line.match( /(sqlite3_[^(\s]+)\(/ ) then
|
50
|
+
api_todo.delete( md.captures[0] )
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
puts "#{api_todo.keys.size} functions to still implement"
|
56
|
+
puts api_todo.keys.sort.join("\n")
|
57
|
+
end
|
58
|
+
|
59
|
+
desc "Download and integrate a version of sqlite"
|
60
|
+
task :update_sqlite, [:version,:year] do |task, args|
|
61
|
+
version = args[:version] or abort "A version of SQLite please `rake #{task.name}[version,year]`"
|
62
|
+
version_year = args[:year] or abort "The Year #{version} was released please `rake #{task.name}[version,year]`"
|
63
|
+
|
64
|
+
require 'uri'
|
65
|
+
require 'open-uri'
|
66
|
+
require 'archive/zip'
|
67
|
+
|
68
|
+
parts = version.split(".")
|
69
|
+
next_version = [ parts.shift.to_s ]
|
70
|
+
parts.each do |p|
|
71
|
+
next_version << "#{"%02d" % p }"
|
72
|
+
end
|
73
|
+
next_version << "00" if next_version.size == 3
|
74
|
+
|
75
|
+
next_version = next_version.join('')
|
76
|
+
|
77
|
+
url = ::URI.parse("http://sqlite.org/#{version_year}/sqlite-amalgamation-#{next_version}.zip")
|
78
|
+
puts "downloading #{url.to_s} ..."
|
79
|
+
file = "tmp/#{File.basename( url.path ) }"
|
80
|
+
FileUtils.mkdir "tmp" unless File.directory?( "tmp" )
|
81
|
+
File.open( file, "wb+") do |f|
|
82
|
+
url.open do |input|
|
83
|
+
f.write( input.read )
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
puts "extracting..."
|
88
|
+
upstream_files = %w[ sqlite3.h sqlite3.c sqlite3ext.h ]
|
89
|
+
Archive::Zip.open( file ) do |archive|
|
90
|
+
archive.each do |entry|
|
91
|
+
next unless entry.file?
|
92
|
+
bname = File.basename( entry.zip_path)
|
93
|
+
if upstream_files.include?( bname ) then
|
94
|
+
dest_file = File.join( "ext", "amalgalite", "c", bname )
|
95
|
+
puts "updating #{dest_file}"
|
96
|
+
entry.extract(file_path: dest_file)
|
97
|
+
end
|
98
|
+
end
|
99
|
+
end
|
100
|
+
end
|
101
|
+
end
|