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,36 @@
1
+ require 'spec_helper'
2
+ require 'libsql/sqlite3'
3
+ require 'rbconfig'
4
+
5
+ describe "::Libsql::SQLite3::Database::Status" do
6
+ before(:each) do
7
+ @db = ::Libsql::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,16 @@
1
+ require 'spec_helper'
2
+ require 'libsql/sqlite3/libsql_version'
3
+
4
+ describe "::Libsql::SQLite3::LibsqlVersion" do
5
+ it "should have the libsql version" do
6
+ expect(::Libsql::SQLite3::LIBSQL_VERSION).to match(/\d+\.\d+\.\d+/)
7
+ expect(::Libsql::SQLite3::LibsqlVersion.to_s).to match(/\d+\.\d+\.\d+/)
8
+ expect(::Libsql::SQLite3::LibsqlVersion.runtime_version).to match( /\d+\.\d+\.\d+/ )
9
+ expect(::Libsql::SQLite3::LibsqlVersion.compiled_version).to match( /\d+\.\d+\.\d+/ )
10
+
11
+ ::Libsql::SQLite3::LIBSQL_VERSION.should be == "0.2.1"
12
+ ::Libsql::SQLite3::LibsqlVersion.compiled_version.should be == "0.2.1"
13
+ ::Libsql::SQLite3::LibsqlVersion.runtime_version.should be == "0.2.1"
14
+ ::Libsql::SQLite3::LibsqlVersion.to_s.should be == "0.2.1"
15
+ end
16
+ end
@@ -0,0 +1,22 @@
1
+ require 'spec_helper'
2
+ require 'libsql/sqlite3'
3
+ require 'rbconfig'
4
+
5
+ describe "::Libsql::SQLite3::Status" do
6
+ it "knows how much memory it has used" do
7
+ ::Libsql::SQLite3.status.memory_used.current.should be >= 0
8
+ ::Libsql::SQLite3.status.memory_used.highwater.should be >= 0
9
+ end
10
+
11
+ it "can reset the highwater value" do
12
+ before = ::Libsql::SQLite3.status.memory_used.highwater
13
+ before.should be > 0
14
+
15
+ current = ::Libsql::SQLite3.status.memory_used.current
16
+ ::Libsql::SQLite3.status.memory_used.reset!
17
+ ::Libsql::SQLite3.status.memory_used.highwater.should be == current
18
+
19
+ after = ::Libsql::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 'libsql/sqlite3/version'
3
+
4
+ describe "::Libsql::SQLite3::Version" do
5
+ it "should have the sqlite3 version" do
6
+ expect(::Libsql::SQLite3::VERSION).to match(/\d+\.\d+\.\d+/)
7
+ expect(::Libsql::SQLite3::Version.to_s).to match( /\d+\.\d+\.\d+/ )
8
+ expect(::Libsql::SQLite3::Version.runtime_version).to match( /\d+\.\d+\.\d+/ )
9
+
10
+ ::Libsql::SQLite3::Version.to_i.should eql(3042000)
11
+ ::Libsql::SQLite3::Version.runtime_version_number.should eql(3042000)
12
+
13
+ ::Libsql::SQLite3::Version::MAJOR.should eql(3)
14
+ ::Libsql::SQLite3::Version::MINOR.should eql(42)
15
+ ::Libsql::SQLite3::Version::RELEASE.should eql(0)
16
+ expect(::Libsql::SQLite3::Version.to_a.size).to eql(3)
17
+
18
+ ::Libsql::SQLite3::Version.compiled_version.should be == "3.42.0"
19
+ ::Libsql::SQLite3::Version.compiled_version_number.should be == 3042000
20
+ ::Libsql::SQLite3::Version.compiled_matches_runtime?.should be == true
21
+ end
22
+
23
+ it "should have the sqlite3 source id" do
24
+ source_id = "2023-03-11 23:21:21 dc9f025dc43cb8008e7d8d644175d8b2d084e602a1513803c40c513d1e99alt1"
25
+ ::Libsql::SQLite3::Version.compiled_source_id.should be == source_id
26
+ ::Libsql::SQLite3::Version.runtime_source_id.should be == source_id
27
+ end
28
+ end
@@ -0,0 +1,53 @@
1
+ require 'spec_helper'
2
+ require 'libsql/sqlite3'
3
+ require 'rbconfig'
4
+
5
+ describe "::Libsql::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
+ ::Libsql::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
+ ::Libsql::SQLite3.complete?("SELECT * FROM sometable;").should eql(true)
12
+ #::Libsql::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
+ ::Libsql::SQLite3.complete?("SELECT * FROM sometable ").should eql(false)
17
+ #::Libsql::SQLite3.complete?("SELECT * FROM sometable WHERE ", :utf16 => true).should eql(false)
18
+ end
19
+
20
+ it "can produce random data" do
21
+ ::Libsql::SQLite3.randomness( 42 ).size.should eql(42)
22
+ end
23
+
24
+ it "has nil for the default sqlite temporary directory" do
25
+ ::Libsql::SQLite3.temp_directory.should eql(nil)
26
+ end
27
+
28
+ it "can set the temporary directory" do
29
+ ::Libsql::SQLite3.temp_directory.should eql(nil)
30
+ ::Libsql::SQLite3.temp_directory = "/tmp/testing"
31
+ ::Libsql::SQLite3.temp_directory.should eql("/tmp/testing")
32
+ ::Libsql::SQLite3.temp_directory = nil
33
+ ::Libsql::SQLite3.temp_directory.should eql(nil)
34
+ end
35
+
36
+ it "can escape quoted strings" do
37
+ ::Libsql::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
+ ::Libsql::SQLite3.escape( :stuff ).should eql("stuff")
42
+ ::Libsql::SQLite3.escape( :"stuff'n" ).should eql("stuff''n")
43
+ end
44
+
45
+ it "can quote and escape single quoted strings" do
46
+ ::Libsql::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
+ ::Libsql::SQLite3.quote( :stuff ).should eql("'stuff'")
51
+ ::Libsql::SQLite3.quote( :"stuff'n" ).should eql("'stuff''n'")
52
+ end
53
+ end
@@ -0,0 +1,168 @@
1
+ require 'spec_helper'
2
+
3
+ describe ::Libsql::Statement do
4
+ before(:each) do
5
+ @db = ::Libsql::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( ::Libsql::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(::Libsql::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 = ::Libsql::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 = ::Libsql::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 'libsql/type_maps/storage_map'
3
+
4
+ describe ::Libsql::TypeMaps::StorageMap do
5
+ before(:each) do
6
+ @map = ::Libsql::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 == ::Libsql::SQLite3::Constants::DataType::FLOAT
13
+ end
14
+
15
+ it "Integer is bound to DataType::INTGER" do
16
+ @map.bind_type_of( 42 ).should == ::Libsql::SQLite3::Constants::DataType::INTEGER
17
+ end
18
+
19
+ it "nil is bound to DataType::NULL" do
20
+ @map.bind_type_of( nil ).should == ::Libsql::SQLite3::Constants::DataType::NULL
21
+ end
22
+
23
+ it "::Libsql::Blob is bound to DataType::BLOB" do
24
+ @map.bind_type_of( ::Libsql::Blob.new( :string => "testing mapping", :column => true ) ).should == ::Libsql::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 == ::Libsql::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 'libsql'
4
+ require 'libsql/trace_tap'
5
+ require 'libsql/profile_tap'
6
+ require 'libsql/taps/console'
7
+ require 'stringio'
8
+
9
+ describe ::Libsql::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 = ::Libsql::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{ ::Libsql::TraceTap.new( Object.new ) }.should raise_error( ::Libsql::Error )
19
+ end
20
+ end
21
+
22
+ describe ::Libsql::ProfileTap do
23
+ it "raises an error if an the wrapped object does not respond to the indicated method" do
24
+ lambda{ ::Libsql::ProfileTap.new( Object.new ) }.should raise_error( ::Libsql::Error )
25
+ end
26
+ end
27
+
28
+ describe ::Libsql::Taps::StringIO do
29
+ it "dumps profile information" do
30
+ s = ::Libsql::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
+ ::Libsql::Taps::Stdout.new
38
+ end
39
+
40
+ it "has a stderr tap" do
41
+ ::Libsql::Taps::Stderr.new
42
+ end
43
+ end
44
+
45
+ describe ::Libsql::ProfileSampler do
46
+ it "aggregates samples" do
47
+ s = ::Libsql::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 'libsql/type_maps/text_map'
3
+
4
+ describe ::Libsql::TypeMaps::TextMap do
5
+ before(:each) do
6
+ @map = ::Libsql::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 == ::Libsql::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 'libsql/type_map'
3
+
4
+ describe ::Libsql::TypeMap do
5
+ it "#bind_type_of raises NotImplemented error" do
6
+ tm = ::Libsql::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 = ::Libsql::TypeMap.new
12
+ lambda { tm.result_value_of( "foo", Object.new ) }.should raise_error( NotImplementedError )
13
+ end
14
+ end
@@ -0,0 +1,8 @@
1
+ require 'spec_helper'
2
+ require 'libsql/version'
3
+
4
+ describe "::Libsql::VERSION" do
5
+ it "should have a version string" do
6
+ expect(::Libsql::VERSION).to match( /\d+\.\d+\.\d+/ )
7
+ end
8
+ end
data/tasks/custom.rake ADDED
@@ -0,0 +1,134 @@
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 libsql 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/libsql/c/libsql*.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 the latest version of libsql"
60
+ task :update_libsql, [:version] do |task, args|
61
+ require 'uri'
62
+ require 'open-uri'
63
+
64
+ asset_regex = /\Alibsql-amalgamation-(\d+\.\d+\.\d+)\.tar\.gz\Z/
65
+
66
+ asset = nil
67
+ require 'debug'
68
+
69
+ if args[:version] then
70
+ all_releases_uri = "https://api.github.com/repos/libsql/libsql/releases"
71
+ all_releases_json = ::URI.parse(all_releases_uri).read
72
+ all_releases_parsed = JSON.parse(all_releases_json)
73
+ version_release = all_releases_parsed.find { |p| p['tag_name'] == "libsql-#{args[:version]}" }
74
+ if version_release then
75
+ assets_url = version_release['assets_url']
76
+ assets_json = ::URI.parse(assets_url).read
77
+ assets_parsed = JSON.parse(assets_json)
78
+ asset = assets_parsed.find { |a| a['name'] =~ asset_regex }
79
+ else
80
+ msg = [
81
+ "Unable to find release for `libsql-#{args[:version]}`. Found releases for:"
82
+ ]
83
+ all_releases_parsed.map{ |p| p['tag_name'] }.each do |tag|
84
+ msg << " #{tag}"
85
+ end
86
+
87
+ abort msg.join("\n")
88
+ end
89
+ else
90
+ latest_uri = "https://api.github.com/repos/libsql/libsql/releases/latest"
91
+ latest_json = ::URI.parse(latest_uri).read
92
+ latest_parsed = JSON.parse(latest_json)
93
+ asset = latest_parsed['assets'].find { |a| a['name'] =~ asset_regex }
94
+ end
95
+
96
+ asset_name = asset['name']
97
+ tarball_uri = ::URI.parse(asset['browser_download_url'])
98
+ puts "Downloading from #{tarball_uri}"
99
+ file = "tmp/#{File.basename(tarball_uri.path)}"
100
+ puts " to #{file}"
101
+
102
+ FileUtils.mkdir "tmp" unless File.directory?( "tmp" )
103
+ if File.exist?(file) then
104
+ puts " #{file} already exists.."
105
+ else
106
+ File.open( file, "wb+") do |f|
107
+ tarball_uri.open do |input|
108
+ f.write( input.read )
109
+ end
110
+ end
111
+ end
112
+
113
+ puts "extracting"
114
+ upstream_files = %w[ sqlite3.h sqlite3.c ]
115
+
116
+ require 'rubygems'
117
+ # Using the built in rubygems tar reader since we know it exists
118
+ ::Zlib::GzipReader.open(file) do |gz|
119
+ ::Gem::Package::TarReader.new(gz) do |reader|
120
+ reader.each do |entry|
121
+ next unless entry.file?
122
+ bname = File.basename(entry.full_name)
123
+ if upstream_files.include?(bname) then
124
+ dest_path = File.join( "ext", "libsql", "c", bname )
125
+ puts "updating #{dest_path}"
126
+ File.open(dest_path, "w+") do |dest_file|
127
+ dest_file.write(entry.read)
128
+ end
129
+ end
130
+ end
131
+ end
132
+ end
133
+ end
134
+ end