amalgalite 0.10.1-x86-mingw32

Sign up to get free protection for your applications and to get access to all the features.
Files changed (100) hide show
  1. data/HISTORY +201 -0
  2. data/LICENSE +29 -0
  3. data/README +51 -0
  4. data/bin/amalgalite-pack +126 -0
  5. data/examples/a.rb +9 -0
  6. data/examples/blob.rb +88 -0
  7. data/examples/bootstrap.rb +36 -0
  8. data/examples/define_aggregate.rb +75 -0
  9. data/examples/define_function.rb +104 -0
  10. data/examples/gem-db.rb +94 -0
  11. data/examples/gems.db +0 -0
  12. data/examples/require_me.rb +11 -0
  13. data/examples/requires.rb +42 -0
  14. data/examples/schema-info.rb +34 -0
  15. data/ext/amalgalite/amalgalite3.c +290 -0
  16. data/ext/amalgalite/amalgalite3.h +151 -0
  17. data/ext/amalgalite/amalgalite3_blob.c +240 -0
  18. data/ext/amalgalite/amalgalite3_constants.c +221 -0
  19. data/ext/amalgalite/amalgalite3_database.c +1148 -0
  20. data/ext/amalgalite/amalgalite3_requires_bootstrap.c +210 -0
  21. data/ext/amalgalite/amalgalite3_statement.c +639 -0
  22. data/ext/amalgalite/extconf.rb +36 -0
  23. data/ext/amalgalite/gen_constants.rb +130 -0
  24. data/ext/amalgalite/sqlite3.c +106729 -0
  25. data/ext/amalgalite/sqlite3.h +5626 -0
  26. data/ext/amalgalite/sqlite3_options.h +4 -0
  27. data/ext/amalgalite/sqlite3ext.h +380 -0
  28. data/gemspec.rb +60 -0
  29. data/lib/amalgalite.rb +43 -0
  30. data/lib/amalgalite/1.8/amalgalite3.so +0 -0
  31. data/lib/amalgalite/1.9/amalgalite3.so +0 -0
  32. data/lib/amalgalite/aggregate.rb +67 -0
  33. data/lib/amalgalite/blob.rb +186 -0
  34. data/lib/amalgalite/boolean.rb +42 -0
  35. data/lib/amalgalite/busy_timeout.rb +47 -0
  36. data/lib/amalgalite/column.rb +97 -0
  37. data/lib/amalgalite/core_ext/kernel/require.rb +21 -0
  38. data/lib/amalgalite/database.rb +947 -0
  39. data/lib/amalgalite/function.rb +61 -0
  40. data/lib/amalgalite/index.rb +43 -0
  41. data/lib/amalgalite/packer.rb +226 -0
  42. data/lib/amalgalite/paths.rb +70 -0
  43. data/lib/amalgalite/profile_tap.rb +131 -0
  44. data/lib/amalgalite/progress_handler.rb +21 -0
  45. data/lib/amalgalite/requires.rb +120 -0
  46. data/lib/amalgalite/schema.rb +191 -0
  47. data/lib/amalgalite/sqlite3.rb +6 -0
  48. data/lib/amalgalite/sqlite3/constants.rb +80 -0
  49. data/lib/amalgalite/sqlite3/database/function.rb +48 -0
  50. data/lib/amalgalite/sqlite3/database/status.rb +68 -0
  51. data/lib/amalgalite/sqlite3/status.rb +60 -0
  52. data/lib/amalgalite/sqlite3/version.rb +37 -0
  53. data/lib/amalgalite/statement.rb +414 -0
  54. data/lib/amalgalite/table.rb +90 -0
  55. data/lib/amalgalite/taps.rb +2 -0
  56. data/lib/amalgalite/taps/console.rb +27 -0
  57. data/lib/amalgalite/taps/io.rb +71 -0
  58. data/lib/amalgalite/trace_tap.rb +35 -0
  59. data/lib/amalgalite/type_map.rb +63 -0
  60. data/lib/amalgalite/type_maps/default_map.rb +167 -0
  61. data/lib/amalgalite/type_maps/storage_map.rb +40 -0
  62. data/lib/amalgalite/type_maps/text_map.rb +22 -0
  63. data/lib/amalgalite/version.rb +37 -0
  64. data/lib/amalgalite/view.rb +26 -0
  65. data/spec/aggregate_spec.rb +169 -0
  66. data/spec/amalgalite_spec.rb +4 -0
  67. data/spec/blob_spec.rb +81 -0
  68. data/spec/boolean_spec.rb +23 -0
  69. data/spec/busy_handler.rb +165 -0
  70. data/spec/database_spec.rb +494 -0
  71. data/spec/default_map_spec.rb +87 -0
  72. data/spec/function_spec.rb +94 -0
  73. data/spec/integeration_spec.rb +111 -0
  74. data/spec/packer_spec.rb +60 -0
  75. data/spec/paths_spec.rb +28 -0
  76. data/spec/progress_handler_spec.rb +105 -0
  77. data/spec/requires_spec.rb +23 -0
  78. data/spec/rtree_spec.rb +71 -0
  79. data/spec/schema_spec.rb +120 -0
  80. data/spec/spec_helper.rb +27 -0
  81. data/spec/sqlite3/constants_spec.rb +65 -0
  82. data/spec/sqlite3/database_status_spec.rb +36 -0
  83. data/spec/sqlite3/status_spec.rb +18 -0
  84. data/spec/sqlite3/version_spec.rb +14 -0
  85. data/spec/sqlite3_spec.rb +53 -0
  86. data/spec/statement_spec.rb +161 -0
  87. data/spec/storage_map_spec.rb +41 -0
  88. data/spec/tap_spec.rb +59 -0
  89. data/spec/text_map_spec.rb +23 -0
  90. data/spec/type_map_spec.rb +17 -0
  91. data/spec/version_spec.rb +15 -0
  92. data/tasks/announce.rake +43 -0
  93. data/tasks/config.rb +107 -0
  94. data/tasks/distribution.rake +77 -0
  95. data/tasks/documentation.rake +32 -0
  96. data/tasks/extension.rake +141 -0
  97. data/tasks/rspec.rake +33 -0
  98. data/tasks/rubyforge.rake +59 -0
  99. data/tasks/utils.rb +80 -0
  100. metadata +237 -0
@@ -0,0 +1,23 @@
1
+ require 'rubygems'
2
+ require 'spec'
3
+
4
+ $: << File.expand_path(File.join(File.dirname(__FILE__),"..","lib"))
5
+ #require 'amalgalite/requires'
6
+
7
+ #describe Amalgalite::Requires do
8
+ # it "#require_order has all files in 'lib' and no more" do
9
+ # dir_files = Dir.glob( File.join( Amalgalite::Paths.lib_path , "**", "*.rb" ) )
10
+ # require_files = Amalgalite::Requires.require_order.collect { |r| Amalgalite::Paths.lib_path r }
11
+ # dir_files.size.should == require_files.size
12
+ # (dir_files - require_files).size.should == 0
13
+ # (require_files - dir_files).size.should == 0
14
+ # end
15
+ #
16
+ # it "can compress and uncompress data" do
17
+ # s = IO.read( __FILE__ )
18
+ # s_gz = Amalgalite::Requires.gzip( s )
19
+ # s.should == Amalgalite::Requires.gunzip( s_gz )
20
+ # end
21
+ #end
22
+
23
+
@@ -0,0 +1,71 @@
1
+ require 'rubygems'
2
+ require 'spec'
3
+ require File.expand_path( File.join( File.dirname(__FILE__), 'spec_helper'))
4
+
5
+ $: << File.expand_path(File.join(File.dirname(__FILE__),"..","lib"))
6
+ require 'amalgalite'
7
+ require 'amalgalite/database'
8
+
9
+ # Example from http://sqlite.org/rtree.html
10
+ #
11
+ describe "SQLite3 R*Tree extension" do
12
+ before( :each ) do
13
+ @db = Amalgalite::Database.new( ":memory:" )
14
+ x = @db.execute_batch <<-sql
15
+ CREATE VIRTUAL TABLE demo_index USING rtree(
16
+ id, -- Integer primary key
17
+ minX, maxX, -- Minimum and maximum X coordinate
18
+ minY, maxY -- Minimum and maximum Y coordinate
19
+ );
20
+ --
21
+ INSERT INTO demo_index VALUES(
22
+ 1, -- Primary key
23
+ -80.7749, -80.7747, -- Longitude range
24
+ 30.3776, 30.3778 -- Latitude range
25
+ );
26
+ INSERT INTO demo_index VALUES(
27
+ 2,
28
+ -81.0, -79.6,
29
+ 35.0, 36.2
30
+ );
31
+ sql
32
+ x.should == 3
33
+ end
34
+
35
+ after( :each ) do
36
+ @db.close
37
+ end
38
+
39
+ it "has 2 rows" do
40
+ r = @db.first_value_from( "SELECT count(*) FROM demo_index")
41
+ r.should == 2
42
+ end
43
+
44
+ it "queries normally" do
45
+ r = @db.execute "SELECT * FROM demo_index WHERE id=1;"
46
+ r.size.should == 1
47
+ row = r.first
48
+ row['id'].should == 1
49
+ end
50
+
51
+ it "does a 'contained within' query" do
52
+ r = @db.execute <<-sql
53
+ SELECT id FROM demo_index
54
+ WHERE minX>=-81.08 AND maxX<=-80.58
55
+ AND minY>=30.00 AND maxY<=30.44;
56
+ sql
57
+
58
+ r.size.should == 1
59
+ r.first['id'].should == 1
60
+ end
61
+
62
+ it "does an 'overlapping' query" do
63
+ r = @db.execute <<-sql
64
+ SELECT id FROM demo_index
65
+ WHERE maxX>=-81.08 AND minX<=-80.58
66
+ AND maxY>=30.00 AND minY<=35.44;
67
+ sql
68
+ r.size.should == 2
69
+ end
70
+ end
71
+
@@ -0,0 +1,120 @@
1
+ require 'rubygems'
2
+ require 'spec'
3
+
4
+ $: << File.expand_path(File.join(File.dirname(__FILE__),"..","lib"))
5
+ require 'amalgalite'
6
+ require 'amalgalite/schema'
7
+
8
+ describe Amalgalite::Schema do
9
+ before(:each) do
10
+ @schema = IO.read( SpecInfo.test_schema_file )
11
+ @iso_db_file = SpecInfo.make_iso_db
12
+ @iso_db = Amalgalite::Database.new( SpecInfo.make_iso_db )
13
+ end
14
+
15
+ after(:each) do
16
+ File.unlink SpecInfo.test_db if File.exist?( SpecInfo.test_db )
17
+ @iso_db.close
18
+ File.unlink @iso_db_file if File.exist?( @iso_db_file )
19
+ end
20
+
21
+ it "loads the schema of a database" do
22
+ schema = @iso_db.schema
23
+ schema.load_tables
24
+ schema.tables.size.should eql(2)
25
+ end
26
+
27
+ it "lazily loads new table schema" do
28
+ @iso_db.schema.tables.size.should eql(2)
29
+ sql = "CREATE TABLE t1 ( a, b, c )"
30
+ @iso_db.execute( sql )
31
+ @iso_db.schema.tables.size.should eql(2)
32
+ @iso_db.schema.dirty!
33
+ @iso_db.schema.tables['t1'].column_names.should eql(%w[ a b c ])
34
+ @iso_db.schema.tables.size.should eql(3)
35
+ end
36
+
37
+ it "loads the views in the database" do
38
+ sql = "CREATE VIEW v1 AS SELECT c.name, c.two_letter, s.name, s.subdivision FROM country AS c JOIN subcountry AS s ON c.two_letter = s.country"
39
+ @iso_db.execute( sql )
40
+ @iso_db.schema.load_views
41
+ @iso_db.schema.views.size.should eql(1)
42
+ @iso_db.schema.views["v1"].sql.should eql(sql)
43
+ end
44
+
45
+ it "removes quotes from around default values in columns" do
46
+ sql = "CREATE TABLE t1( d1 default 't' )"
47
+ @iso_db.execute( sql )
48
+ @iso_db.schema.dirty!
49
+ tt = @iso_db.schema.tables['t1']
50
+ tt.columns['d1'].default_value.should == "t"
51
+ end
52
+
53
+ it "loads the tables and columns" do
54
+ ct = @iso_db.schema.tables['country']
55
+ ct.name.should eql("country")
56
+ ct.columns.size.should eql(3)
57
+ ct.indexes.size.should eql(2)
58
+ ct.column_names.should eql(%w[ name two_letter id ])
59
+ @iso_db.schema.tables.size.should eql(2)
60
+
61
+
62
+ ct.columns['two_letter'].should be_primary_key
63
+ ct.columns['two_letter'].declared_data_type.should eql("TEXT")
64
+ ct.columns['name'].should_not be_nullable
65
+ ct.columns['name'].should be_not_null_constraint
66
+ ct.columns['name'].should_not be_has_default_value
67
+ ct.columns['id'].should_not be_auto_increment
68
+ end
69
+
70
+ it "knows what the primary key of a table is" do
71
+ ct = @iso_db.schema.tables['country']
72
+ ct.primary_key.should == [ ct.columns['two_letter'] ]
73
+ end
74
+
75
+ it "knows the primary key of a table even without an explicity unique index" do
76
+ sql = "CREATE TABLE u( id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL , other text )"
77
+ @iso_db.execute( sql )
78
+ @iso_db.schema.dirty!
79
+ ut = @iso_db.schema.tables['u']
80
+ ut.primary_key.should == [ ut.columns['id'] ]
81
+ end
82
+
83
+ it "knows the primary key of a temporary table" do
84
+ @iso_db.execute "CREATE TEMPORARY TABLE tt( a, b INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, c )"
85
+ @iso_db.schema.dirty!
86
+ tt = @iso_db.schema.load_table( 'tt' )
87
+ tt.primary_key.should == [ tt.columns['b'] ]
88
+
89
+ end
90
+
91
+ it "knows what the primary key of a table is when it is a multiple column primary key" do
92
+ sql = "CREATE TABLE m ( id1, id2, PRIMARY KEY (id2, id1) )"
93
+ @iso_db.execute( sql )
94
+ @iso_db.schema.dirty!
95
+ mt = @iso_db.schema.tables['m']
96
+ mt.primary_key.should == [ mt.columns['id2'], mt.columns['id1'] ]
97
+ end
98
+
99
+ it "loads the indexes" do
100
+ c = @iso_db.schema.tables['country']
101
+ c.indexes.size.should eql(2)
102
+ c.indexes['country_name'].columns.size.should eql(1)
103
+ c.indexes['country_name'].should_not be_unique
104
+ c.indexes['country_name'].sequence_number.should eql(0)
105
+ c.indexes['country_name'].columns.first.should eql(@iso_db.schema.tables['country'].columns['name'])
106
+ c.indexes['sqlite_autoindex_country_1'].should be_unique
107
+
108
+ subc = @iso_db.schema.tables['subcountry']
109
+ subc.indexes.size.should eql(3)
110
+ subc.indexes['subcountry_country'].columns.first.should eql(@iso_db.schema.tables['subcountry'].columns['country'])
111
+ end
112
+
113
+ it "can load the schema of a temporary table" do
114
+ @iso_db.execute "CREATE TEMPORARY TABLE tt( a, b, c )"
115
+ @iso_db.schema.dirty!
116
+ @iso_db.schema.tables['tt'].should be_nil
117
+ @iso_db.schema.load_table('tt').should_not be_nil
118
+ @iso_db.schema.tables['tt'].should be_temporary
119
+ end
120
+ end
@@ -0,0 +1,27 @@
1
+ require 'rubygems'
2
+ require 'spec'
3
+
4
+ $: << File.expand_path(File.join(File.dirname(__FILE__),"..","lib"))
5
+
6
+ require 'amalgalite'
7
+
8
+ class SpecInfo
9
+ class << self
10
+ def test_db
11
+ @test_db ||= File.expand_path(File.join(File.dirname(__FILE__), "test.db"))
12
+ end
13
+
14
+ def test_schema_file
15
+ @test_schema_file ||= File.expand_path(File.join(File.dirname(__FILE__),"iso-3166-schema.sql"))
16
+ end
17
+
18
+ def make_iso_db
19
+ @iso_db ||= File.expand_path(File.join(File.dirname(__FILE__), "iso-3166.db"))
20
+ @new_is_db = File.expand_path(File.join(File.dirname(__FILE__), "iso-3166-testing.db"))
21
+ FileUtils.cp @iso_db, @new_is_db
22
+ return @new_is_db
23
+ end
24
+
25
+ end
26
+ end
27
+
@@ -0,0 +1,65 @@
1
+ require File.expand_path(File.join(File.dirname(__FILE__),%w[ .. spec_helper.rb ]))
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
+ it "has DataType constants" do
12
+ Amalgalite::SQLite3::Constants::DataType::BLOB.should > 0
13
+ end
14
+
15
+ it "has ResultCode constants" do
16
+ end
17
+
18
+ describe 'ResultCode' do
19
+ it "has constants" do
20
+ Amalgalite::SQLite3::Constants::ResultCode::OK.should == 0
21
+ end
22
+
23
+ it "can return the constant from a number" do
24
+ c = Amalgalite::SQLite3::Constants::ResultCode.name_from_value( 21 )
25
+ c.should == "MISUSE"
26
+ end
27
+
28
+ it "can return the number from a name" do
29
+ v = Amalgalite::SQLite3::Constants::ResultCode.value_from_name( "MISUSE" )
30
+ v.should == 21
31
+ end
32
+ end
33
+
34
+ describe 'Status' do
35
+ it "has constants" do
36
+ Amalgalite::SQLite3::Constants::Status::MEMORY_USED.should == 0
37
+ end
38
+
39
+ it "can return the constant from a number" do
40
+ c = Amalgalite::SQLite3::Constants::Status.name_from_value( 3 )
41
+ c.should == "SCRATCH_USED"
42
+ end
43
+
44
+ it "can return the number from a name" do
45
+ v = Amalgalite::SQLite3::Constants::Status.value_from_name( "memory_used" )
46
+ v.should == 0
47
+ end
48
+ end
49
+
50
+ describe 'DBStatus' do
51
+ it "has constants" do
52
+ Amalgalite::SQLite3::Constants::DBStatus::LOOKASIDE_USED.should == 0
53
+ end
54
+
55
+ it "can return the constant from a number" do
56
+ c = Amalgalite::SQLite3::Constants::DBStatus.name_from_value( 0 )
57
+ c.should == "LOOKASIDE_USED"
58
+ end
59
+
60
+ it "can return the number from a name" do
61
+ v = Amalgalite::SQLite3::Constants::DBStatus.value_from_name( "lookaside_used" )
62
+ v.should == 0
63
+ end
64
+ end
65
+ end
@@ -0,0 +1,36 @@
1
+ require File.expand_path(File.join(File.dirname(__FILE__), "..", "spec_helper.rb"))
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 > 0
22
+ @db.api.status.lookaside_used.current.should >= 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 > 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,18 @@
1
+ require File.expand_path(File.join(File.dirname(__FILE__), "..", "spec_helper.rb"))
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 >= 0
8
+ Amalgalite::SQLite3.status.memory_used.highwater.should >= 0
9
+ end
10
+
11
+ it "can reset the highwater value" do
12
+ before = Amalgalite::SQLite3.status.memory_used.highwater
13
+ Amalgalite::SQLite3.status.memory_used.reset!
14
+ Amalgalite::SQLite3.status.memory_used.highwater.should > 0
15
+ after = Amalgalite::SQLite3.status.memory_used.highwater
16
+ after.should_not eql(before)
17
+ end
18
+ end
@@ -0,0 +1,14 @@
1
+ require File.expand_path(File.join(File.dirname(__FILE__),"..","spec_helper.rb"))
2
+ require 'amalgalite/sqlite3/version'
3
+
4
+ describe "Amalgalite::SQLite3::Version" do
5
+ it "should have the sqlite3 version" do
6
+ Amalgalite::SQLite3::VERSION.should =~ /\d\.\d\.\d/
7
+ Amalgalite::SQLite3::Version.to_s.should =~ /\d\.\d\.\d/
8
+ Amalgalite::SQLite3::Version.to_i.should eql(3006016)
9
+ Amalgalite::SQLite3::Version::MAJOR.should eql(3)
10
+ Amalgalite::SQLite3::Version::MINOR.should eql(6)
11
+ Amalgalite::SQLite3::Version::RELEASE.should eql(16)
12
+ Amalgalite::SQLite3::Version.to_a.should have(3).items
13
+ end
14
+ end
@@ -0,0 +1,53 @@
1
+ require File.expand_path(File.join(File.dirname(__FILE__),"spec_helper.rb"))
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 (#{Config::CONFIG['configure_args'].include?( "--enable-pthread" )})" do
7
+ Amalgalite::SQLite3.threadsafe?.should eql(Config::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,161 @@
1
+ require 'rubygems'
2
+ require 'spec'
3
+
4
+ require File.expand_path( File.join( File.dirname( __FILE__ ), "spec_helper.rb" ) )
5
+
6
+ require 'amalgalite'
7
+
8
+ describe Amalgalite::Statement do
9
+ before(:each) do
10
+ @db = Amalgalite::Database.new( SpecInfo.test_db )
11
+ @schema_sql = IO.read( SpecInfo.test_schema_file )
12
+ @iso_db_file = SpecInfo.make_iso_db
13
+ @iso_db = Amalgalite::Database.new( SpecInfo.make_iso_db )
14
+ end
15
+
16
+ after(:each) do
17
+ @db.close
18
+ File.unlink SpecInfo.test_db if File.exist?( SpecInfo.test_db )
19
+
20
+ @iso_db.close
21
+ File.unlink @iso_db_file if File.exist?( @iso_db_file )
22
+ end
23
+
24
+ it "a statement has a copy of the sql it was prepared with" do
25
+ stmt = @db.prepare( "SELECT strftime('%Y-%m-%d %H:%M:%S', 'now')")
26
+ stmt.sql.should eql("SELECT strftime('%Y-%m-%d %H:%M:%S', 'now')")
27
+ stmt.close
28
+ end
29
+
30
+ it "steps through results" do
31
+ now = Time.new.utc.strftime("%Y-%m-%d %H:%M")
32
+ @db.prepare( "SELECT strftime('%Y-%m-%d %H:%M', 'now') as now") do |stmt|
33
+ stmt.should_not eql(nil)
34
+ stmt.each do |row|
35
+ row['now'].should eql(now)
36
+ end
37
+ end
38
+ end
39
+
40
+ it "can prepare a statement without a block" do
41
+ stmt = @iso_db.prepare("SELECT * FROM country WHERE two_letter = :two")
42
+ rs = stmt.execute( ":two" => "JP" )
43
+ rs.size.should eql(1)
44
+ stmt.close
45
+ end
46
+
47
+ it "knows how many parameters are in the statement" do
48
+ @iso_db.prepare("SELECT * FROM country WHERE two_letter = :two") do |stmt|
49
+ stmt.check_parameter_count!( 1 ).should eql(1)
50
+ end
51
+ end
52
+
53
+ it "raises an error if there are not enough parameters are passed in a statement" do
54
+ @iso_db.prepare("SELECT * FROM country WHERE two_letter = :two") do |stmt|
55
+ lambda{ stmt.execute }.should raise_error( Amalgalite::Error )
56
+ end
57
+ end
58
+
59
+
60
+ it "can run a query with a named parameter" do
61
+ @iso_db.prepare("SELECT * FROM country WHERE two_letter = :two") do |stmt|
62
+ all_rows = stmt.execute( ":two" => "JP" )
63
+ all_rows.size.should eql(1)
64
+ all_rows.first['name'].should eql("Japan")
65
+ end
66
+ end
67
+
68
+ it "it can execute a query with a named parameter and yield the rows" do
69
+ @iso_db.prepare("SELECT * FROM country WHERE id = @id ORDER BY name") do |stmt|
70
+ rows = []
71
+ stmt.execute( "@id" => 891 ) do |row|
72
+ rows << row
73
+ end
74
+ rows.size.should eql(2)
75
+ rows.last['name'].should eql("Yugoslavia")
76
+ rows.first['two_letter'].should eql("CS")
77
+ end
78
+ end
79
+
80
+ it "can execute the same prepared statement multiple times" do
81
+ @db.execute(" CREATE TABLE t(x,y); ")
82
+ values = {}
83
+ @db.prepare("INSERT INTO t( x, y ) VALUES( $x, $y )" ) do |stmt|
84
+ 20.times do |x|
85
+ y = rand( x )
86
+ stmt.execute( { "$x" => x, "$y" => y } )
87
+ values[x] = y
88
+ end
89
+ end
90
+ c = 0
91
+ @db.execute("SELECT * from t") do |row|
92
+ c += 1
93
+ values[ row['x'] ].should eql(row['y'])
94
+ end
95
+ c.should eql(20)
96
+ end
97
+
98
+ it "binds a integer variable correctly" do
99
+ @iso_db.prepare("SELECT * FROM country WHERE id = ? ORDER BY name ") do |stmt|
100
+ all_rows = stmt.execute( 891 )
101
+ all_rows.size.should eql(2)
102
+ all_rows.last['name'].should eql("Yugoslavia")
103
+ all_rows.first['two_letter'].should eql("CS")
104
+ end
105
+ end
106
+
107
+ it "raises and error if an invaliding binding is attempted" do
108
+ @iso_db.prepare("SELECT * FROM country WHERE id = :somevar ORDER BY name ") do |stmt|
109
+ lambda{ stmt.execute( "blah" => 42 ) }.should raise_error(Amalgalite::Error)
110
+ end
111
+ end
112
+
113
+ it "can reset the statement to the state it was before executing" do
114
+ stmt = @iso_db.prepare("SELECT * FROM country WHERE id = :somevar ORDER BY name ")
115
+ stmt.reset_and_clear_bindings!
116
+ stmt.close
117
+ end
118
+
119
+ it "can execute a single sql command and say if there is remaining sql to execute" do
120
+ db = Amalgalite::Database.new( SpecInfo.test_db )
121
+ stmt = @db.prepare( @schema_sql )
122
+ stmt.execute
123
+ stmt.remaining_sql.size.should > 0
124
+ stmt.close
125
+ end
126
+
127
+ it "can select the rowid from the table" do
128
+ db = Amalgalite::Database.new( ":memory:" )
129
+ db.execute( "create table t1(c1,c2,c3)" )
130
+ db.execute("insert into t1(c1,c2,c3) values (1,2,'abc')")
131
+ rows = db.execute( "select rowid,* from t1")
132
+ rows.size.should eql(1)
133
+ rows.first['rowid'].should eql(1)
134
+ rows.first['c1'].should eql(1 )
135
+ rows.first['c3'].should eql('abc')
136
+ end
137
+
138
+ it "shows that the rowid column is rowid column" do
139
+ db = Amalgalite::Database.new( ":memory:" )
140
+ db.execute( "create table t1(c1,c2,c3)" )
141
+ db.execute("insert into t1(c1,c2,c3) values (1,2,'abc')")
142
+ db.prepare( "select oid,* from t1" ) do |stmt|
143
+ rows = stmt.execute
144
+ stmt.should be_using_rowid_column
145
+ end
146
+
147
+ db.prepare( "select * from t1" ) do |stmt|
148
+ stmt.execute
149
+ stmt.should_not be_using_rowid_column
150
+ end
151
+ end
152
+
153
+ it "has index based access to the result set" do
154
+ @iso_db.prepare("SELECT * FROM country WHERE id = ? ORDER BY name ") do |stmt|
155
+ all_rows = stmt.execute( 891 )
156
+ all_rows.size.should eql(2)
157
+ all_rows.last.first.should eql("Yugoslavia")
158
+ all_rows.first[1].should eql("CS")
159
+ end
160
+ end
161
+ end