amalgalite 1.6.0-x64-mingw32

Sign up to get free protection for your applications and to get access to all the features.
Files changed (111) hide show
  1. checksums.yaml +7 -0
  2. data/CONTRIBUTING.md +49 -0
  3. data/HISTORY.md +346 -0
  4. data/LICENSE +31 -0
  5. data/Manifest.txt +104 -0
  6. data/README.md +65 -0
  7. data/Rakefile +26 -0
  8. data/TODO.md +57 -0
  9. data/bin/amalgalite-pack +147 -0
  10. data/examples/a.rb +9 -0
  11. data/examples/blob.rb +88 -0
  12. data/examples/bootstrap.rb +36 -0
  13. data/examples/define_aggregate.rb +75 -0
  14. data/examples/define_function.rb +104 -0
  15. data/examples/fts5.rb +152 -0
  16. data/examples/gem-db.rb +94 -0
  17. data/examples/require_me.rb +11 -0
  18. data/examples/requires.rb +42 -0
  19. data/examples/schema-info.rb +34 -0
  20. data/ext/amalgalite/c/amalgalite.c +355 -0
  21. data/ext/amalgalite/c/amalgalite.h +151 -0
  22. data/ext/amalgalite/c/amalgalite_blob.c +240 -0
  23. data/ext/amalgalite/c/amalgalite_constants.c +1226 -0
  24. data/ext/amalgalite/c/amalgalite_database.c +1178 -0
  25. data/ext/amalgalite/c/amalgalite_requires_bootstrap.c +282 -0
  26. data/ext/amalgalite/c/amalgalite_statement.c +649 -0
  27. data/ext/amalgalite/c/extconf.rb +62 -0
  28. data/ext/amalgalite/c/gen_constants.rb +330 -0
  29. data/ext/amalgalite/c/notes.txt +134 -0
  30. data/ext/amalgalite/c/sqlite3.c +205352 -0
  31. data/ext/amalgalite/c/sqlite3.h +10727 -0
  32. data/ext/amalgalite/c/sqlite3_options.h +4 -0
  33. data/ext/amalgalite/c/sqlite3ext.h +578 -0
  34. data/lib/amalgalite.rb +51 -0
  35. data/lib/amalgalite/2.0/amalgalite.so +0 -0
  36. data/lib/amalgalite/2.1/amalgalite.so +0 -0
  37. data/lib/amalgalite/2.2/amalgalite.so +0 -0
  38. data/lib/amalgalite/2.3/amalgalite.so +0 -0
  39. data/lib/amalgalite/2.4/amalgalite.so +0 -0
  40. data/lib/amalgalite/aggregate.rb +67 -0
  41. data/lib/amalgalite/blob.rb +186 -0
  42. data/lib/amalgalite/boolean.rb +42 -0
  43. data/lib/amalgalite/busy_timeout.rb +47 -0
  44. data/lib/amalgalite/column.rb +99 -0
  45. data/lib/amalgalite/core_ext/kernel/require.rb +21 -0
  46. data/lib/amalgalite/csv_table_importer.rb +74 -0
  47. data/lib/amalgalite/database.rb +984 -0
  48. data/lib/amalgalite/function.rb +61 -0
  49. data/lib/amalgalite/index.rb +43 -0
  50. data/lib/amalgalite/memory_database.rb +15 -0
  51. data/lib/amalgalite/packer.rb +231 -0
  52. data/lib/amalgalite/paths.rb +80 -0
  53. data/lib/amalgalite/profile_tap.rb +131 -0
  54. data/lib/amalgalite/progress_handler.rb +21 -0
  55. data/lib/amalgalite/requires.rb +151 -0
  56. data/lib/amalgalite/schema.rb +225 -0
  57. data/lib/amalgalite/sqlite3.rb +6 -0
  58. data/lib/amalgalite/sqlite3/constants.rb +95 -0
  59. data/lib/amalgalite/sqlite3/database/function.rb +48 -0
  60. data/lib/amalgalite/sqlite3/database/status.rb +68 -0
  61. data/lib/amalgalite/sqlite3/status.rb +60 -0
  62. data/lib/amalgalite/sqlite3/version.rb +55 -0
  63. data/lib/amalgalite/statement.rb +418 -0
  64. data/lib/amalgalite/table.rb +91 -0
  65. data/lib/amalgalite/taps.rb +2 -0
  66. data/lib/amalgalite/taps/console.rb +27 -0
  67. data/lib/amalgalite/taps/io.rb +71 -0
  68. data/lib/amalgalite/trace_tap.rb +35 -0
  69. data/lib/amalgalite/type_map.rb +63 -0
  70. data/lib/amalgalite/type_maps/default_map.rb +166 -0
  71. data/lib/amalgalite/type_maps/storage_map.rb +38 -0
  72. data/lib/amalgalite/type_maps/text_map.rb +21 -0
  73. data/lib/amalgalite/version.rb +8 -0
  74. data/lib/amalgalite/view.rb +26 -0
  75. data/spec/aggregate_spec.rb +154 -0
  76. data/spec/amalgalite_spec.rb +4 -0
  77. data/spec/blob_spec.rb +78 -0
  78. data/spec/boolean_spec.rb +24 -0
  79. data/spec/busy_handler.rb +157 -0
  80. data/spec/data/iso-3166-country.txt +242 -0
  81. data/spec/data/iso-3166-schema.sql +22 -0
  82. data/spec/data/iso-3166-subcountry.txt +3995 -0
  83. data/spec/data/make-iso-db.sh +12 -0
  84. data/spec/database_spec.rb +508 -0
  85. data/spec/default_map_spec.rb +92 -0
  86. data/spec/function_spec.rb +78 -0
  87. data/spec/integeration_spec.rb +97 -0
  88. data/spec/iso_3166_database.rb +58 -0
  89. data/spec/packer_spec.rb +60 -0
  90. data/spec/paths_spec.rb +28 -0
  91. data/spec/progress_handler_spec.rb +91 -0
  92. data/spec/requires_spec.rb +54 -0
  93. data/spec/rtree_spec.rb +66 -0
  94. data/spec/schema_spec.rb +131 -0
  95. data/spec/spec_helper.rb +48 -0
  96. data/spec/sqlite3/constants_spec.rb +108 -0
  97. data/spec/sqlite3/database_status_spec.rb +36 -0
  98. data/spec/sqlite3/status_spec.rb +22 -0
  99. data/spec/sqlite3/version_spec.rb +28 -0
  100. data/spec/sqlite3_spec.rb +53 -0
  101. data/spec/statement_spec.rb +168 -0
  102. data/spec/storage_map_spec.rb +38 -0
  103. data/spec/tap_spec.rb +57 -0
  104. data/spec/text_map_spec.rb +20 -0
  105. data/spec/type_map_spec.rb +14 -0
  106. data/spec/version_spec.rb +8 -0
  107. data/tasks/custom.rake +102 -0
  108. data/tasks/default.rake +240 -0
  109. data/tasks/extension.rake +38 -0
  110. data/tasks/this.rb +208 -0
  111. metadata +318 -0
@@ -0,0 +1,92 @@
1
+ require 'spec_helper'
2
+ require 'amalgalite/type_maps/default_map'
3
+
4
+ describe Amalgalite::TypeMaps::DefaultMap do
5
+ before(:each) do
6
+ @map = Amalgalite::TypeMaps::DefaultMap.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( :column => true, :string => "just a test" ) ).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
+
34
+ describe "#result_value_of" do
35
+
36
+ it "Numeric's are returned" do
37
+ y = 42
38
+ x = @map.result_value_of( "INT", 42 )
39
+ x.object_id.should == y.object_id
40
+ end
41
+
42
+ it "Nil is returned" do
43
+ @map.result_value_of( "NULL", nil ).should == nil
44
+ end
45
+
46
+ it "DateTime is returned for delcared types of 'datetime'" do
47
+ @map.result_value_of( "DaTeTiME", "2008-04-01 23:23:23" ).should be_kind_of(DateTime)
48
+ end
49
+
50
+ it "Date is returned for declared types of 'date'" do
51
+ @map.result_value_of( "date", "2008-04-01 23:42:42" ).should be_kind_of(Date)
52
+ end
53
+
54
+ it "Time is returned for declared types of 'time'" do
55
+ @map.result_value_of( "timestamp", "2008-04-01T23:42:42" ).should be_kind_of(Time)
56
+ end
57
+
58
+ it "Float is returned for declared types of 'double'" do
59
+ @map.result_value_of( "double", "3.14" ).should be_kind_of(Float)
60
+ end
61
+
62
+ it "Float is returned for declared types of 'float'" do
63
+ @map.result_value_of( "float", "3.14" ).should be_kind_of(Float)
64
+ end
65
+
66
+ it "Integer is returned for declared types of 'int'" do
67
+ @map.result_value_of( "int", "42" ).should be_kind_of(Integer)
68
+ end
69
+
70
+ it "boolean is returned for declared types of 'bool'" do
71
+ @map.result_value_of( "bool", "True" ).should == true
72
+ end
73
+
74
+ it "Blob is returned for declared types of 'blob'" do
75
+ blob = @map.result_value_of( "blob", "stuff")
76
+ blob.to_s.should == "stuff"
77
+ end
78
+
79
+ it "String is returned for delcared types of 'string'" do
80
+ @map.result_value_of( "string", "stuff").should == "stuff"
81
+ end
82
+
83
+ it "raises and error if an unknown sql type is returned" do
84
+ x = nil
85
+ lambda{ x = @map.result_value_of( "footype", "foo" ) }.should raise_error( ::Amalgalite::Error )
86
+ end
87
+
88
+ it "raises and error if an ruby class is attempted to be mapped" do
89
+ lambda{ @map.result_value_of( "footype", 1..3 ) }.should raise_error( ::Amalgalite::Error )
90
+ end
91
+ end
92
+ end
@@ -0,0 +1,78 @@
1
+ require 'spec_helper'
2
+
3
+ describe "Scalar SQL Functions" do
4
+
5
+ it "can define a custom SQL function as a block with 0 params" do
6
+ @iso_db.define_function("foo") do
7
+ "foo"
8
+ end
9
+ r = @iso_db.execute("SELECT foo() AS f");
10
+ r.first['f'].should == "foo"
11
+ end
12
+
13
+ it "has a signature" do
14
+ ::Amalgalite::Function.new( "testing_name", 42 ).signature.should == "testing_name/42"
15
+ end
16
+
17
+ it "can define a custom SQL function as a lambda with 2 param" do
18
+ @iso_db.define_function("foo2", lambda{ |x,y| "foo2 -> #{x} #{y}" } )
19
+ r = @iso_db.execute("SELECT foo2( 'bar', 'baz' ) as f")
20
+ r.first['f'].should == "foo2 -> bar baz"
21
+ end
22
+
23
+ it "can define a custom SQL function as a class with N params" do
24
+ class FunctionTest1 < ::Amalgalite::Function
25
+ def initialize
26
+ super('ftest', -1)
27
+ end
28
+ def call( *args )
29
+ "#{args.length} args #{args.join(', ')}"
30
+ end
31
+ end
32
+
33
+ @iso_db.define_function("ftest1", FunctionTest1.new )
34
+ r = @iso_db.execute("SELECT ftest1(1,2,3,'baz') as f")
35
+ r.first['f'].should == "4 args 1, 2, 3, baz"
36
+ end
37
+
38
+ [ [ 1, lambda { true } ],
39
+ [ 0, lambda { false } ],
40
+ [ nil, lambda { nil } ],
41
+ [ "foo", lambda { "foo" } ],
42
+ [ 42, lambda { 42 } ],
43
+ [ 42.2 , lambda { 42.2 } ], ].each do |expected, func|
44
+ it "returns the appropriate class #{expected.class} " do
45
+ @iso_db.define_function("ctest", func )
46
+ r = @iso_db.execute( "SELECT ctest() AS c" )
47
+ r.first['c'].should == expected
48
+ end
49
+ end
50
+
51
+ it "does not allow outrageous arity" do
52
+ class FunctionTest3 < ::Amalgalite::Function
53
+ def initialize
54
+ super( 'ftest3', 128)
55
+ end
56
+ end
57
+ lambda { @iso_db.define_function("ftest3", FunctionTest3.new) }.should raise_error( ::Amalgalite::SQLite3::Error, /SQLITE_ERROR .* Library used incorrectly/ )
58
+ end
59
+
60
+ it "raises an error if the function returns a complex Ruby object" do
61
+ l = lambda { Hash.new }
62
+ @iso_db.define_function("htest", l)
63
+ begin
64
+ @iso_db.execute( "SELECT htest() AS h" )
65
+ rescue => e
66
+ e.should be_instance_of( ::Amalgalite::SQLite3::Error )
67
+ e.message.should =~ /Unable to convert ruby object to an SQL function result/
68
+ end
69
+ end
70
+
71
+ it "an error raised during the sql function is handled correctly" do
72
+ @iso_db.define_function( "etest" ) do
73
+ raise "error from within an sql function"
74
+ end
75
+ lambda { @iso_db.execute( "SELECT etest() AS e" ) }.should raise_error( ::Amalgalite::SQLite3::Error, /error from within an sql function/ )
76
+ end
77
+ end
78
+
@@ -0,0 +1,97 @@
1
+ require 'spec_helper'
2
+
3
+ require 'date'
4
+ require 'time'
5
+
6
+ describe "Integration specifications" do
7
+
8
+ describe " - invalid queries" do
9
+ it "raises error with an invalid syntax" do
10
+ lambda{ @iso_db.prepare "SELECT from country" }.should raise_error( ::Amalgalite::SQLite3::Error )
11
+ end
12
+
13
+ it "raises error with invalid table" do
14
+ lambda{ @iso_db.prepare "SELECT * FROM foo" }.should raise_error( ::Amalgalite::SQLite3::Error )
15
+ end
16
+
17
+ it "raises error with invalid column" do
18
+ lambda{ @iso_db.prepare "SELECT foo FROM country" }.should raise_error( ::Amalgalite::SQLite3::Error )
19
+ end
20
+ end
21
+
22
+ describe " - default types conversion" do
23
+
24
+ {
25
+ "datetime" => { :value => DateTime.now, :klass => DateTime },
26
+ "timestamp" => { :value => Time.now, :klass => Time } ,
27
+ "date" => { :value => Date.today, :klass => Date },
28
+ "integer" => { :value => 42, :klass => Integer },
29
+ "double" => { :value => 3.14, :klass => Float },
30
+ "varchar" => { :value => "foobarbaz", :klass => String },
31
+ "boolean" => { :value => true, :klass => TrueClass },
32
+ "varchar(2)"=> { :value => nil, :klass => NilClass }
33
+ }.each_pair do |sql_type, ruby_info|
34
+ it "converts a ruby obj (#{ruby_info[:value].to_s}) of #{ruby_info[:klass]} to an SQL type of #{sql_type} and back again " do
35
+ db = Amalgalite::Database.new( SpecInfo.test_db )
36
+ db.execute "CREATE TABLE t( c #{sql_type} )"
37
+ db.execute "insert into t (c) values ( ? )", ruby_info[:value]
38
+ rows = db.execute "select * from t"
39
+ rows.first['c'].should be_kind_of(ruby_info[:klass])
40
+
41
+ if [ DateTime, Time ].include?( ruby_info[:klass] ) then
42
+ rows.first['c'].strftime("%Y-%m-%d %H:%M:%S").should eql(ruby_info[:value].strftime("%Y-%m-%d %H:%M:%S"))
43
+ else
44
+ rows.first['c'].should eql(ruby_info[:value])
45
+ end
46
+ db.close
47
+ end
48
+ end
49
+ end
50
+
51
+ describe " - storage type conversion" do
52
+ {
53
+ "datetime" => { :value => DateTime.now, :result => DateTime.now.strftime("%Y-%m-%dT%H:%M:%S%Z") } ,
54
+ "timestamp" => { :value => Time.now, :result => Time.now.to_s },
55
+ "date" => { :value => Date.today, :result => Date.today.to_s },
56
+ "integer" => { :value => 42, :result => 42 } ,
57
+ "double" => { :value => 3.14, :result => 3.14 } ,
58
+ "varchar" => { :value => "foobarbaz", :result => "foobarbaz" },
59
+ "boolean" => { :value => true, :result => "true" },
60
+ "varchar(2)"=> { :value => nil, :result => nil }
61
+ }.each_pair do |sql_type, ruby_info|
62
+ it "converts a ruby obj (#{ruby_info[:value].to_s}) of class #{ruby_info[:value].class.name} to an SQL type of #{sql_type} and back to a storage type" do
63
+ db = Amalgalite::Database.new( SpecInfo.test_db )
64
+ db.type_map = Amalgalite::TypeMaps::StorageMap.new
65
+ db.execute "CREATE TABLE t( c #{sql_type} )"
66
+ db.execute "insert into t (c) values ( ? )", ruby_info[:value]
67
+ rows = db.execute "select * from t"
68
+ rows.first['c'].should eql(ruby_info[:result])
69
+ db.close
70
+ end
71
+ end
72
+ end
73
+
74
+ describe " - text type conversion" do
75
+ {
76
+ "datetime" => { :value => DateTime.now, :result => DateTime.now.strftime("%Y-%m-%dT%H:%M:%S%Z") } ,
77
+ "timestamp" => { :value => Time.now, :result => Time.now.to_s },
78
+ "date" => { :value => Date.today, :result => Date.today.to_s },
79
+ "integer" => { :value => 42, :result => "42" } ,
80
+ "double" => { :value => 3.14, :result => "3.14" } ,
81
+ "varchar" => { :value => "foobarbaz", :result => "foobarbaz" },
82
+ "boolean" => { :value => true, :result => "true" },
83
+ "varchar(2)"=> { :value => nil, :result => "" }
84
+ }.each_pair do |sql_type, ruby_info|
85
+ it "converts a ruby obj (#{ruby_info[:value].to_s}) of class #{ruby_info[:value].class.name} to an SQL type of #{sql_type} and back to text" do
86
+ db = Amalgalite::Database.new( SpecInfo.test_db )
87
+ db.type_map = Amalgalite::TypeMaps::TextMap.new
88
+ db.execute "CREATE TABLE t( c #{sql_type} )"
89
+ db.execute "insert into t (c) values ( ? )", ruby_info[:value]
90
+ rows = db.execute "select * from t"
91
+ rows.first['c'].should eql(ruby_info[:result])
92
+ db.close
93
+ end
94
+ end
95
+ end
96
+ end
97
+
@@ -0,0 +1,58 @@
1
+ require 'amalgalite'
2
+
3
+ module Amalgalite
4
+ class Iso3166Database < Database
5
+ def self.country_data_file
6
+ @country_data_file ||= File.expand_path( File.join( File.dirname(__FILE__), "data", "iso-3166-country.txt" ) )
7
+ end
8
+
9
+ def self.subcountry_data_file
10
+ @subcountry_data_file ||= File.expand_path( File.join( File.dirname(__FILE__), "data", "iso-3166-subcountry.txt" ) )
11
+ end
12
+
13
+ def self.schema_file
14
+ @schema_file ||= File.expand_path(File.join(File.dirname(__FILE__), "data", "iso-3166-schema.sql"))
15
+ end
16
+
17
+ def self.default_db_file
18
+ @db_file ||= File.expand_path(File.join(File.dirname(__FILE__), "data", "iso-3166.db"))
19
+
20
+ end
21
+
22
+ def self.memory
23
+ Iso3166Database.new( ":memory:" )
24
+ end
25
+
26
+ def initialize( path = Iso3166Database.default_db_file )
27
+ @path = path
28
+ super( @path )
29
+ install_schema( self )
30
+ populate( self )
31
+ end
32
+
33
+ def duplicate( slug )
34
+ dirname = File.dirname( @path )
35
+ bname = File.basename( @path, ".db" )
36
+ new_name = File.join( dirname, "#{bname}_#{slug}.db" )
37
+ File.unlink( new_name ) if File.exist?( new_name )
38
+ new_db = replicate_to( new_name )
39
+ new_db.close
40
+ return new_name
41
+ end
42
+
43
+ def install_schema( db )
44
+ db.execute_batch( IO.read( Iso3166Database.schema_file ) );
45
+ end
46
+
47
+ def populate( db )
48
+ db.import_csv_to_table( Iso3166Database.country_data_file, "country", :col_sep => "|" )
49
+ db.import_csv_to_table( Iso3166Database.subcountry_data_file, "subcountry", :col_sep => "|" )
50
+ end
51
+
52
+ def remove
53
+ File.unlink( @path ) if File.exist?( @path )
54
+ end
55
+ end
56
+ end
57
+
58
+
@@ -0,0 +1,60 @@
1
+ require 'spec_helper'
2
+
3
+ require 'amalgalite/packer'
4
+
5
+ describe "Amalgalite::Packer" do
6
+ before( :each ) do
7
+ @table = Amalgalite::Requires::Bootstrap::DEFAULT_BOOTSTRAP_TABLE
8
+ @packer = Amalgalite::Packer.new( :table_name => @table )
9
+ end
10
+
11
+ after( :each ) do
12
+ FileUtils.rm_f Amalgalite::Requires::Bootstrap::DEFAULT_DB
13
+ end
14
+
15
+ it "does not load the amalgalite/requires file" do
16
+ $LOADED_FEATURES.should_not be_include("amalgalite/requires")
17
+ end
18
+
19
+ it "packs amalgalite into a bootstrap database" do
20
+ @packer.pack( Amalgalite::Packer.amalgalite_require_order )
21
+ db = Amalgalite::Database.new( @packer.dbfile )
22
+ db.schema.tables[ @table ].should_not be_nil
23
+ count = db.execute("SELECT count(1) FROM #{@table}").first
24
+ count.first.should eql(Amalgalite::Packer.amalgalite_require_order.size)
25
+ end
26
+
27
+ it "recreates the table if :drop_table option is given " do
28
+ @packer.pack( Amalgalite::Packer.amalgalite_require_order )
29
+ db = Amalgalite::Database.new( @packer.dbfile )
30
+ db.schema.tables[ @table ].should_not be_nil
31
+ count = db.execute("SELECT count(1) FROM #{@table}").first
32
+ count.first.should eql(Amalgalite::Packer.amalgalite_require_order.size)
33
+
34
+ np = Amalgalite::Packer.new( :drop_table => true, :table_name => @table )
35
+ np.options[ :drop_table ].should eql(true)
36
+ np.check_db( db )
37
+ count = db.execute("SELECT count(1) FROM #{@table}").first
38
+ count.first.should eql(0)
39
+
40
+ end
41
+
42
+ it "compresses the content if told too" do
43
+ @packer.options[ :compressed ] = true
44
+ @packer.pack( Amalgalite::Packer.amalgalite_require_order )
45
+ db = Amalgalite::Database.new( @packer.dbfile )
46
+ orig = IO.read( File.join( File.dirname( __FILE__ ), "..", "lib", "amalgalite.rb" ) )
47
+ zipped = db.execute("SELECT contents FROM #{@table} WHERE filename = 'amalgalite'")
48
+ expanded = Amalgalite::Packer.gunzip( zipped.first['contents'].to_s )
49
+ expanded.should eql(orig)
50
+ end
51
+
52
+ it "has all the lib files in the amalgalite gem" do
53
+ ro = Amalgalite::Packer.amalgalite_require_order
54
+ glist = IO.readlines("Manifest.txt").select { |l| l.index("lib/amalgalite") == 0 }
55
+ glist.map! { |l| l.strip.sub("lib/","") }
56
+ (glist - ro).each do |l|
57
+ l.should_not =~ /amalgalite/
58
+ end
59
+ end
60
+ end
@@ -0,0 +1,28 @@
1
+ require 'spec_helper'
2
+
3
+ describe Amalgalite::Paths do
4
+ before(:each) do
5
+ @root_dir = File.expand_path(File.join(File.dirname(__FILE__), ".."))
6
+ @root_dir += "/"
7
+ end
8
+
9
+ it "root dir should be correct" do
10
+ Amalgalite::Paths.root_dir.should == @root_dir
11
+ end
12
+
13
+ it "config_path should be correct" do
14
+ Amalgalite::Paths.config_path.should == File.join(@root_dir, "config/")
15
+ end
16
+
17
+ it "data path should be correct" do
18
+ Amalgalite::Paths.data_path.should == File.join(@root_dir, "data/")
19
+ end
20
+
21
+ it "lib path should be correct" do
22
+ Amalgalite::Paths.lib_path.should == File.join(@root_dir, "lib/")
23
+ end
24
+
25
+ it "ext path should be correct" do
26
+ Amalgalite::Paths.ext_path.should == File.join(@root_dir, "ext/")
27
+ end
28
+ end
@@ -0,0 +1,91 @@
1
+ require 'spec_helper'
2
+
3
+ class PH < ::Amalgalite::ProgressHandler
4
+ attr_reader :call_count
5
+ def initialize( max = nil )
6
+ @call_count = 0
7
+ @max = max
8
+ end
9
+
10
+ def call
11
+ @call_count += 1
12
+ if @max && ( @call_count >= @max ) then
13
+ return false
14
+ end
15
+ return true
16
+ end
17
+ end
18
+
19
+ def query_thread( database )
20
+ Thread.new( database ) do |db|
21
+ begin
22
+ db.execute("select count(id) from country")
23
+ rescue => e
24
+ Thread.current[:exception] = e
25
+ end
26
+ end
27
+ end
28
+
29
+ describe "Progress Handlers" do
30
+
31
+ it "raises NotImplemented if #call is not overwritten" do
32
+ bh = ::Amalgalite::ProgressHandler.new
33
+ lambda { bh.call }.should raise_error( ::NotImplementedError, /The progress handler call\(\) method must be implemented/ )
34
+ end
35
+
36
+ it "can be registered as block" do
37
+ call_count = 0
38
+ @iso_db.progress_handler( 50 ) do ||
39
+ call_count += 1
40
+ true
41
+ end
42
+ qt = query_thread( @iso_db )
43
+ qt.join
44
+ call_count.should > 10
45
+ end
46
+
47
+ it "can be registered as lambda" do
48
+ call_count = 0
49
+ callable = lambda { || call_count += 1; true }
50
+ @iso_db.progress_handler( 42, callable )
51
+ qt = query_thread( @iso_db )
52
+ qt.join
53
+ call_count.should > 10
54
+ end
55
+
56
+ it "can be registered as a class" do
57
+ ph = PH.new
58
+ @iso_db.progress_handler( 5, ph )
59
+ qt = query_thread( @iso_db )
60
+ qt.join
61
+ ph.call_count.should > 100
62
+ end
63
+
64
+ it "behaves like #interrupt! if returning a false value" do
65
+ ph = PH.new( 25 )
66
+ @iso_db.progress_handler( 5, ph )
67
+ qt = query_thread( @iso_db )
68
+ qt.join
69
+ ph.call_count.should eql(25)
70
+ qt[:exception].should be_instance_of( ::Amalgalite::SQLite3::Error )
71
+ @iso_db.api.last_error_code.should be == 9
72
+ @iso_db.api.last_error_message.should =~ /interrupted/
73
+ qt[:exception].message.should =~ /interrupted/
74
+ end
75
+
76
+ it "cannot register a block with the wrong arity" do
77
+ lambda do
78
+ @iso_db.define_progress_handler { |x,y| puts "What!" }
79
+ end.should raise_error( ::Amalgalite::Database::ProgressHandlerError, /A progress handler expects 0 arguments, not 2/)
80
+ end
81
+
82
+ it "can remove a progress handler" do
83
+ ph = PH.new
84
+ @iso_db.progress_handler( 5, ph )
85
+ @iso_db.remove_progress_handler
86
+ qt = query_thread( @iso_db )
87
+ qt.join
88
+ ph.call_count.should eql(0)
89
+ qt[:exception].should be_nil
90
+ end
91
+ end