libsql 0.1.0-x64-mingw-ucrt

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (100) hide show
  1. checksums.yaml +7 -0
  2. data/CONTRIBUTING.md +60 -0
  3. data/HISTORY.md +6 -0
  4. data/LICENSE +31 -0
  5. data/Manifest.txt +96 -0
  6. data/README.md +59 -0
  7. data/Rakefile +28 -0
  8. data/TODO.md +57 -0
  9. data/examples/a.rb +9 -0
  10. data/examples/blob.rb +106 -0
  11. data/examples/define_aggregate.rb +75 -0
  12. data/examples/define_function.rb +104 -0
  13. data/examples/fts5.rb +152 -0
  14. data/examples/gem-db.rb +94 -0
  15. data/examples/schema-info.rb +34 -0
  16. data/ext/libsql/c/extconf.rb +86 -0
  17. data/ext/libsql/c/gen_constants.rb +353 -0
  18. data/ext/libsql/c/libsql_blob.c +240 -0
  19. data/ext/libsql/c/libsql_constants.c +1518 -0
  20. data/ext/libsql/c/libsql_database.c +1188 -0
  21. data/ext/libsql/c/libsql_ext.c +383 -0
  22. data/ext/libsql/c/libsql_ext.h +149 -0
  23. data/ext/libsql/c/libsql_statement.c +649 -0
  24. data/ext/libsql/c/notes.txt +134 -0
  25. data/ext/libsql/c/sqlite3.c +247030 -0
  26. data/ext/libsql/c/sqlite3.h +13436 -0
  27. data/lib/libsql/3.1/libsql_ext.so +0 -0
  28. data/lib/libsql/3.2/libsql_ext.so +0 -0
  29. data/lib/libsql/aggregate.rb +73 -0
  30. data/lib/libsql/blob.rb +186 -0
  31. data/lib/libsql/boolean.rb +42 -0
  32. data/lib/libsql/busy_timeout.rb +47 -0
  33. data/lib/libsql/column.rb +99 -0
  34. data/lib/libsql/csv_table_importer.rb +75 -0
  35. data/lib/libsql/database.rb +933 -0
  36. data/lib/libsql/function.rb +61 -0
  37. data/lib/libsql/index.rb +43 -0
  38. data/lib/libsql/memory_database.rb +15 -0
  39. data/lib/libsql/paths.rb +80 -0
  40. data/lib/libsql/profile_tap.rb +131 -0
  41. data/lib/libsql/progress_handler.rb +21 -0
  42. data/lib/libsql/schema.rb +225 -0
  43. data/lib/libsql/sqlite3/constants.rb +95 -0
  44. data/lib/libsql/sqlite3/database/function.rb +48 -0
  45. data/lib/libsql/sqlite3/database/status.rb +68 -0
  46. data/lib/libsql/sqlite3/libsql_version.rb +32 -0
  47. data/lib/libsql/sqlite3/status.rb +60 -0
  48. data/lib/libsql/sqlite3/version.rb +55 -0
  49. data/lib/libsql/sqlite3.rb +7 -0
  50. data/lib/libsql/statement.rb +421 -0
  51. data/lib/libsql/table.rb +91 -0
  52. data/lib/libsql/taps/console.rb +27 -0
  53. data/lib/libsql/taps/io.rb +74 -0
  54. data/lib/libsql/taps.rb +2 -0
  55. data/lib/libsql/trace_tap.rb +35 -0
  56. data/lib/libsql/type_map.rb +63 -0
  57. data/lib/libsql/type_maps/default_map.rb +166 -0
  58. data/lib/libsql/type_maps/storage_map.rb +38 -0
  59. data/lib/libsql/type_maps/text_map.rb +21 -0
  60. data/lib/libsql/version.rb +8 -0
  61. data/lib/libsql/view.rb +26 -0
  62. data/lib/libsql-ruby.rb +1 -0
  63. data/lib/libsql.rb +51 -0
  64. data/spec/aggregate_spec.rb +158 -0
  65. data/spec/blob_spec.rb +78 -0
  66. data/spec/boolean_spec.rb +24 -0
  67. data/spec/busy_handler.rb +157 -0
  68. data/spec/data/iso-3166-country.txt +242 -0
  69. data/spec/data/iso-3166-schema.sql +22 -0
  70. data/spec/data/iso-3166-subcountry.txt +3995 -0
  71. data/spec/data/make-iso-db.sh +12 -0
  72. data/spec/database_spec.rb +505 -0
  73. data/spec/default_map_spec.rb +92 -0
  74. data/spec/function_spec.rb +78 -0
  75. data/spec/integeration_spec.rb +97 -0
  76. data/spec/iso_3166_database.rb +58 -0
  77. data/spec/json_spec.rb +24 -0
  78. data/spec/libsql_spec.rb +4 -0
  79. data/spec/paths_spec.rb +28 -0
  80. data/spec/progress_handler_spec.rb +91 -0
  81. data/spec/rtree_spec.rb +66 -0
  82. data/spec/schema_spec.rb +131 -0
  83. data/spec/spec_helper.rb +48 -0
  84. data/spec/sqlite3/constants_spec.rb +108 -0
  85. data/spec/sqlite3/database_status_spec.rb +36 -0
  86. data/spec/sqlite3/libsql_version_spec.rb +16 -0
  87. data/spec/sqlite3/status_spec.rb +22 -0
  88. data/spec/sqlite3/version_spec.rb +28 -0
  89. data/spec/sqlite3_spec.rb +53 -0
  90. data/spec/statement_spec.rb +168 -0
  91. data/spec/storage_map_spec.rb +38 -0
  92. data/spec/tap_spec.rb +57 -0
  93. data/spec/text_map_spec.rb +20 -0
  94. data/spec/type_map_spec.rb +14 -0
  95. data/spec/version_spec.rb +8 -0
  96. data/tasks/custom.rake +134 -0
  97. data/tasks/default.rake +257 -0
  98. data/tasks/extension.rake +29 -0
  99. data/tasks/this.rb +208 -0
  100. metadata +329 -0
@@ -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( ::Libsql::SQLite3::Error )
11
+ end
12
+
13
+ it "raises error with invalid table" do
14
+ lambda{ @iso_db.prepare "SELECT * FROM foo" }.should raise_error( ::Libsql::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( ::Libsql::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 = ::Libsql::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 = ::Libsql::Database.new( SpecInfo.test_db )
64
+ db.type_map = ::Libsql::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 = ::Libsql::Database.new( SpecInfo.test_db )
87
+ db.type_map = ::Libsql::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 'libsql'
2
+
3
+ module ::Libsql
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
+
data/spec/json_spec.rb ADDED
@@ -0,0 +1,24 @@
1
+ require 'spec_helper'
2
+ require 'libsql/sqlite3'
3
+ require 'rbconfig'
4
+
5
+ describe "::Libsql handles the JSON extension" do
6
+ it "can parse a `json_each` call" do
7
+ db = ::Libsql::Database.new( ":memory:" )
8
+ values = %w[ a b c d e f g ]
9
+ db.execute("CREATE TABLE jtest(id, json)")
10
+ db.execute("INSERT INTO jtest(id, json) values (1, json($json))", { "$json" => values })
11
+ rows = db.execute("SELECT jtest.id as i, value as v FROM jtest, json_each(jtest.json)")
12
+
13
+ rows.size.should eq(values.size)
14
+ end
15
+
16
+ it "can return a proper json column" do
17
+ db = ::Libsql::Database.new( ":memory:" )
18
+ values = %w[ a b c d e f g ]
19
+ db.execute("CREATE TABLE jtest(id INTEGER, json JSON)")
20
+ db.execute("INSERT INTO jtest(id, json) values (1, json($json))", { "$json" => values })
21
+
22
+ db.execute("select * from jtest")
23
+ end
24
+ end
@@ -0,0 +1,4 @@
1
+ require 'spec_helper'
2
+
3
+ describe ::Libsql do
4
+ end
@@ -0,0 +1,28 @@
1
+ require 'spec_helper'
2
+
3
+ describe ::Libsql::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
+ ::Libsql::Paths.root_dir.should == @root_dir
11
+ end
12
+
13
+ it "config_path should be correct" do
14
+ ::Libsql::Paths.config_path.should == File.join(@root_dir, "config/")
15
+ end
16
+
17
+ it "data path should be correct" do
18
+ ::Libsql::Paths.data_path.should == File.join(@root_dir, "data/")
19
+ end
20
+
21
+ it "lib path should be correct" do
22
+ ::Libsql::Paths.lib_path.should == File.join(@root_dir, "lib/")
23
+ end
24
+
25
+ it "ext path should be correct" do
26
+ ::Libsql::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 < ::Libsql::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 = ::Libsql::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( ::Libsql::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( ::Libsql::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
@@ -0,0 +1,66 @@
1
+ require 'spec_helper'
2
+
3
+ #
4
+ # Example from http://sqlite.org/rtree.html
5
+ #
6
+ describe "SQLite3 R*Tree extension" do
7
+ before( :each ) do
8
+ @db = ::Libsql::Database.new( ":memory:" )
9
+ x = @db.execute_batch <<-sql
10
+ CREATE VIRTUAL TABLE demo_index USING rtree(
11
+ id, -- Integer primary key
12
+ minX, maxX, -- Minimum and maximum X coordinate
13
+ minY, maxY -- Minimum and maximum Y coordinate
14
+ );
15
+ --
16
+ INSERT INTO demo_index VALUES(
17
+ 1, -- Primary key
18
+ -80.7749, -80.7747, -- Longitude range
19
+ 30.3776, 30.3778 -- Latitude range
20
+ );
21
+ INSERT INTO demo_index VALUES(
22
+ 2,
23
+ -81.0, -79.6,
24
+ 35.0, 36.2
25
+ );
26
+ sql
27
+ x.should == 3
28
+ end
29
+
30
+ after( :each ) do
31
+ @db.close
32
+ end
33
+
34
+ it "has 2 rows" do
35
+ r = @db.first_value_from( "SELECT count(*) FROM demo_index")
36
+ r.should == 2
37
+ end
38
+
39
+ it "queries normally" do
40
+ r = @db.execute "SELECT * FROM demo_index WHERE id=1;"
41
+ r.size.should be == 1
42
+ row = r.first
43
+ row['id'].should be == 1
44
+ end
45
+
46
+ it "does a 'contained within' query" do
47
+ r = @db.execute <<-sql
48
+ SELECT id FROM demo_index
49
+ WHERE minX>=-81.08 AND maxX<=-80.58
50
+ AND minY>=30.00 AND maxY<=30.44;
51
+ sql
52
+
53
+ r.size.should be == 1
54
+ r.first['id'].should be == 1
55
+ end
56
+
57
+ it "does an 'overlapping' query" do
58
+ r = @db.execute <<-sql
59
+ SELECT id FROM demo_index
60
+ WHERE maxX>=-81.08 AND minX<=-80.58
61
+ AND maxY>=30.00 AND minY<=35.44;
62
+ sql
63
+ r.size.should == 2
64
+ end
65
+ end
66
+
@@ -0,0 +1,131 @@
1
+ require 'spec_helper'
2
+
3
+ require 'libsql'
4
+ require 'libsql/schema'
5
+
6
+ describe ::Libsql::Schema do
7
+
8
+ it "loads the schema of a database" do
9
+ schema = @iso_db.schema
10
+ schema.load_tables
11
+ schema.tables.size.should eql(2)
12
+ end
13
+
14
+ it "loads the views in the database" do
15
+ s = @iso_db.schema
16
+ 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"
17
+ @iso_db.execute( sql )
18
+ s.dirty?.should be == true
19
+ @iso_db.schema.load_views
20
+ @iso_db.schema.views.size.should eql(1)
21
+ @iso_db.schema.views["v1"].sql.should eql(sql)
22
+ end
23
+
24
+ it "removes quotes from around default values in columns" do
25
+ s = @iso_db.schema
26
+ sql = "CREATE TABLE t1( d1 default 't' )"
27
+ @iso_db.execute( sql )
28
+ s.dirty?.should be == true
29
+ tt = @iso_db.schema.tables['t1']
30
+ tt.columns['d1'].default_value.should be == "t"
31
+ end
32
+
33
+ it "loads the tables and columns" do
34
+ ct = @iso_db.schema.tables['country']
35
+ ct.name.should eql("country")
36
+ ct.columns.size.should eql(3)
37
+ ct.indexes.size.should eql(2)
38
+ ct.column_names.should eql(%w[ name two_letter id ])
39
+ @iso_db.schema.tables.size.should eql(2)
40
+
41
+
42
+ ct.columns['two_letter'].should be_primary_key
43
+ ct.columns['two_letter'].declared_data_type.should eql("TEXT")
44
+ ct.columns['name'].should_not be_nullable
45
+ ct.columns['name'].should be_not_null_constraint
46
+ ct.columns['name'].should_not be_has_default_value
47
+ ct.columns['id'].should_not be_auto_increment
48
+ end
49
+
50
+ it "knows what the primary key of a table is" do
51
+ ct = @iso_db.schema.tables['country']
52
+ ct.primary_key.should == [ ct.columns['two_letter'] ]
53
+ end
54
+
55
+ it "knows the primary key of a table even without an explicity unique index" do
56
+ s = @iso_db.schema
57
+ sql = "CREATE TABLE u( id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL , other text )"
58
+ @iso_db.execute( sql )
59
+ s.dirty?.should be == true
60
+ ut = @iso_db.schema.tables['u']
61
+ ut.primary_key.should == [ ut.columns['id'] ]
62
+ end
63
+
64
+ it "knows the primary key of a temporary table" do
65
+ @iso_db.execute "CREATE TEMPORARY TABLE tt( a, b INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, c )"
66
+ tt = @iso_db.schema.tables[ 'tt' ]
67
+ tt.primary_key.should == [ tt.columns['b'] ]
68
+ end
69
+
70
+ it "knows what the primary key of a table is when it is a multiple column primary key" do
71
+ sql = "CREATE TABLE m ( id1, id2, PRIMARY KEY (id2, id1) )"
72
+ s = @iso_db.schema
73
+ @iso_db.execute( sql )
74
+ s.dirty?.should be == true
75
+ mt = @iso_db.schema.tables['m']
76
+ mt.primary_key.should == [ mt.columns['id2'], mt.columns['id1'] ]
77
+ end
78
+
79
+ it "loads the indexes" do
80
+ c = @iso_db.schema.tables['country']
81
+ c.indexes.size.should eql(2)
82
+ c.indexes['country_name'].columns.size.should eql(1)
83
+ c.indexes['country_name'].should_not be_unique
84
+ c.indexes['country_name'].sequence_number.should eql(0)
85
+ c.indexes['country_name'].columns.first.should eql(@iso_db.schema.tables['country'].columns['name'])
86
+ c.indexes['sqlite_autoindex_country_1'].should be_unique
87
+
88
+ subc = @iso_db.schema.tables['subcountry']
89
+ subc.indexes.size.should eql(3)
90
+ subc.indexes['subcountry_country'].columns.first.should eql(@iso_db.schema.tables['subcountry'].columns['country'])
91
+ end
92
+
93
+ it "knows the schema is dirty when a table is created" do
94
+ s = @iso_db.schema
95
+ s.tables['country']
96
+ s.dirty?.should be == false
97
+ @iso_db.execute( "create table x1( a, b )" )
98
+ s.dirty?.should be == true
99
+ end
100
+
101
+ it "knows the schema is dirty when a table is dropped" do
102
+ s = @iso_db.schema
103
+ s.tables['country']
104
+ @iso_db.execute( "create table x1( a, b )" )
105
+ s.dirty?.should be == true
106
+
107
+ @iso_db.schema.load_schema!
108
+ s = @iso_db.schema
109
+
110
+ s.dirty?.should be == false
111
+ @iso_db.execute("drop table x1")
112
+ s.dirty?.should be == true
113
+ end
114
+
115
+ it "knows if a temporary table exists" do
116
+ @iso_db.execute "CREATE TEMPORARY TABLE tt(a,b,c)"
117
+ @iso_db.schema.tables.keys.include?('tt').should be == true
118
+ @iso_db.schema.tables['tt'].temporary?.should be == true
119
+ end
120
+
121
+ it "sees that temporary tables shadow real tables" do
122
+ @iso_db.execute "CREATE TABLE tt(x)"
123
+ @iso_db.schema.tables['tt'].temporary?.should be == false
124
+ @iso_db.execute "CREATE TEMP TABLE tt(a,b,c)"
125
+ @iso_db.schema.tables['tt'].temporary?.should be == true
126
+ @iso_db.execute "DROP TABLE tt"
127
+ @iso_db.schema.tables['tt'].temporary?.should be == false
128
+ @iso_db.schema.tables['tt'].columns.size.should be == 1
129
+ end
130
+
131
+ end
@@ -0,0 +1,48 @@
1
+ require 'rspec'
2
+ require 'fileutils'
3
+
4
+ require 'libsql'
5
+ require ::Libsql::Paths.spec_path( "iso_3166_database.rb" )
6
+
7
+ class SpecInfo
8
+ class << self
9
+ def test_db
10
+ @test_db ||= ::Libsql::Paths.spec_path("data", "test.db")
11
+ end
12
+
13
+ def make_master_iso_db
14
+ @master_db ||= ::Libsql::Iso3166Database.new
15
+ end
16
+
17
+ def make_clone_iso_db
18
+ make_master_iso_db.duplicate( 'testing' )
19
+ end
20
+ end
21
+ end
22
+
23
+ RSpec.configure do |config|
24
+ config.expect_with :rspec do |c|
25
+ c.syntax = [:should, :expect]
26
+ end
27
+
28
+ config.before(:all) do
29
+ SpecInfo.make_master_iso_db
30
+ end
31
+
32
+ config.after(:all) do
33
+ File.unlink( ::Libsql::Iso3166Database.default_db_file ) if File.exist?( ::Libsql::Iso3166Database.default_db_file )
34
+ end
35
+
36
+ config.before( :each ) do
37
+ @iso_db_path = SpecInfo.make_clone_iso_db
38
+ @iso_db = ::Libsql::Database.new( @iso_db_path )
39
+ @schema = IO.read( ::Libsql::Iso3166Database.schema_file )
40
+ end
41
+
42
+ config.after( :each ) do
43
+ @iso_db.close
44
+ File.unlink( @iso_db_path ) if File.exist?( @iso_db_path )
45
+ File.unlink( SpecInfo.test_db ) if File.exist?( SpecInfo.test_db )
46
+ end
47
+ end
48
+
@@ -0,0 +1,108 @@
1
+ require 'spec_helper'
2
+
3
+ require 'libsql/sqlite3/constants'
4
+
5
+ describe ::Libsql::SQLite3::Constants do
6
+
7
+ it "has Open constants" do
8
+ ::Libsql::SQLite3::Constants::Open::READONLY.should > 0
9
+ end
10
+
11
+ describe 'ResultCode' do
12
+ it "has constants" do
13
+ ::Libsql::SQLite3::Constants::ResultCode::OK.should == 0
14
+ end
15
+
16
+ it "can return the constant from a number" do
17
+ c = ::Libsql::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 = ::Libsql::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
+ ::Libsql::SQLite3::Constants::DataType::NULL.should == 5
30
+ end
31
+
32
+ it "can return the constant from a number" do
33
+ c = ::Libsql::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 = ::Libsql::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
+ ::Libsql::SQLite3::Constants::Config::HEAP.should == 8
47
+ end
48
+
49
+ it "can return the constant from a number" do
50
+ c = ::Libsql::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 = ::Libsql::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
+ ::Libsql::SQLite3::Constants::Status::MEMORY_USED.should == 0
64
+ end
65
+
66
+ it "can return the constant from a number" do
67
+ c = ::Libsql::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 = ::Libsql::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
+ ::Libsql::SQLite3::Constants::DBStatus::LOOKASIDE_USED.should == 0
80
+ end
81
+
82
+ it "can return the constant from a number" do
83
+ c = ::Libsql::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 = ::Libsql::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
+ ::Libsql::SQLite3::Constants::StatementStatus::AUTOINDEX.should == 3
96
+ end
97
+
98
+ it "can return the constant from a number" do
99
+ c = ::Libsql::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 = ::Libsql::SQLite3::Constants::StatementStatus.value_from_name( "autoindex" )
105
+ v.should == 3
106
+ end
107
+ end
108
+ end