libsql 0.1.0-x64-mingw32
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.
- checksums.yaml +7 -0
- data/CONTRIBUTING.md +60 -0
- data/HISTORY.md +6 -0
- data/LICENSE +31 -0
- data/Manifest.txt +96 -0
- data/README.md +59 -0
- data/Rakefile +28 -0
- data/TODO.md +57 -0
- data/examples/a.rb +9 -0
- data/examples/blob.rb +106 -0
- data/examples/define_aggregate.rb +75 -0
- data/examples/define_function.rb +104 -0
- data/examples/fts5.rb +152 -0
- data/examples/gem-db.rb +94 -0
- data/examples/schema-info.rb +34 -0
- data/ext/libsql/c/extconf.rb +86 -0
- data/ext/libsql/c/gen_constants.rb +353 -0
- data/ext/libsql/c/libsql_blob.c +240 -0
- data/ext/libsql/c/libsql_constants.c +1518 -0
- data/ext/libsql/c/libsql_database.c +1188 -0
- data/ext/libsql/c/libsql_ext.c +383 -0
- data/ext/libsql/c/libsql_ext.h +149 -0
- data/ext/libsql/c/libsql_statement.c +649 -0
- data/ext/libsql/c/notes.txt +134 -0
- data/ext/libsql/c/sqlite3.c +247030 -0
- data/ext/libsql/c/sqlite3.h +13436 -0
- data/lib/libsql/aggregate.rb +73 -0
- data/lib/libsql/blob.rb +186 -0
- data/lib/libsql/boolean.rb +42 -0
- data/lib/libsql/busy_timeout.rb +47 -0
- data/lib/libsql/column.rb +99 -0
- data/lib/libsql/csv_table_importer.rb +75 -0
- data/lib/libsql/database.rb +933 -0
- data/lib/libsql/function.rb +61 -0
- data/lib/libsql/index.rb +43 -0
- data/lib/libsql/libsql_ext.so +0 -0
- data/lib/libsql/memory_database.rb +15 -0
- data/lib/libsql/paths.rb +80 -0
- data/lib/libsql/profile_tap.rb +131 -0
- data/lib/libsql/progress_handler.rb +21 -0
- data/lib/libsql/schema.rb +225 -0
- data/lib/libsql/sqlite3/constants.rb +95 -0
- data/lib/libsql/sqlite3/database/function.rb +48 -0
- data/lib/libsql/sqlite3/database/status.rb +68 -0
- data/lib/libsql/sqlite3/libsql_version.rb +32 -0
- data/lib/libsql/sqlite3/status.rb +60 -0
- data/lib/libsql/sqlite3/version.rb +55 -0
- data/lib/libsql/sqlite3.rb +7 -0
- data/lib/libsql/statement.rb +421 -0
- data/lib/libsql/table.rb +91 -0
- data/lib/libsql/taps/console.rb +27 -0
- data/lib/libsql/taps/io.rb +74 -0
- data/lib/libsql/taps.rb +2 -0
- data/lib/libsql/trace_tap.rb +35 -0
- data/lib/libsql/type_map.rb +63 -0
- data/lib/libsql/type_maps/default_map.rb +166 -0
- data/lib/libsql/type_maps/storage_map.rb +38 -0
- data/lib/libsql/type_maps/text_map.rb +21 -0
- data/lib/libsql/version.rb +8 -0
- data/lib/libsql/view.rb +26 -0
- data/lib/libsql-ruby.rb +1 -0
- data/lib/libsql.rb +51 -0
- data/spec/aggregate_spec.rb +158 -0
- data/spec/blob_spec.rb +78 -0
- data/spec/boolean_spec.rb +24 -0
- data/spec/busy_handler.rb +157 -0
- data/spec/data/iso-3166-country.txt +242 -0
- data/spec/data/iso-3166-schema.sql +22 -0
- data/spec/data/iso-3166-subcountry.txt +3995 -0
- data/spec/data/make-iso-db.sh +12 -0
- data/spec/database_spec.rb +505 -0
- data/spec/default_map_spec.rb +92 -0
- data/spec/function_spec.rb +78 -0
- data/spec/integeration_spec.rb +97 -0
- data/spec/iso_3166_database.rb +58 -0
- data/spec/json_spec.rb +24 -0
- data/spec/libsql_spec.rb +4 -0
- data/spec/paths_spec.rb +28 -0
- data/spec/progress_handler_spec.rb +91 -0
- data/spec/rtree_spec.rb +66 -0
- data/spec/schema_spec.rb +131 -0
- data/spec/spec_helper.rb +48 -0
- data/spec/sqlite3/constants_spec.rb +108 -0
- data/spec/sqlite3/database_status_spec.rb +36 -0
- data/spec/sqlite3/libsql_version_spec.rb +16 -0
- data/spec/sqlite3/status_spec.rb +22 -0
- data/spec/sqlite3/version_spec.rb +28 -0
- data/spec/sqlite3_spec.rb +53 -0
- data/spec/statement_spec.rb +168 -0
- data/spec/storage_map_spec.rb +38 -0
- data/spec/tap_spec.rb +57 -0
- data/spec/text_map_spec.rb +20 -0
- data/spec/type_map_spec.rb +14 -0
- data/spec/version_spec.rb +8 -0
- data/tasks/custom.rake +134 -0
- data/tasks/default.rake +257 -0
- data/tasks/extension.rake +29 -0
- data/tasks/this.rb +208 -0
- metadata +328 -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
|
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
|