extralite 1.10 → 1.13

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.
data/extralite.gemspec CHANGED
@@ -19,7 +19,7 @@ Gem::Specification.new do |s|
19
19
  s.extra_rdoc_files = ["README.md"]
20
20
  s.extensions = ["ext/extralite/extconf.rb"]
21
21
  s.require_paths = ["lib"]
22
- s.required_ruby_version = '>= 2.6'
22
+ s.required_ruby_version = '>= 2.7'
23
23
 
24
24
  s.add_development_dependency 'rake-compiler', '1.1.6'
25
25
  s.add_development_dependency 'minitest', '5.15.0'
@@ -1,3 +1,3 @@
1
1
  module Extralite
2
- VERSION = '1.10'
2
+ VERSION = '1.13'
3
3
  end
Binary file
Binary file
data/test/helper.rb CHANGED
@@ -3,3 +3,5 @@
3
3
  require 'bundler/setup'
4
4
  require 'extralite'
5
5
  require 'minitest/autorun'
6
+
7
+ puts "sqlite3 version: #{Extralite.sqlite3_version}"
data/test/perf_hash.rb CHANGED
@@ -4,8 +4,8 @@ require 'bundler/inline'
4
4
 
5
5
  gemfile do
6
6
  source 'https://rubygems.org'
7
- gem 'sqlite3'
8
7
  gem 'extralite', path: '..'
8
+ gem 'sqlite3'
9
9
  gem 'benchmark-ips'
10
10
  end
11
11
 
@@ -0,0 +1,64 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'bundler/inline'
4
+
5
+ gemfile do
6
+ source 'https://rubygems.org'
7
+ gem 'extralite', path: '..'
8
+ gem 'sqlite3'
9
+ gem 'benchmark-ips'
10
+ end
11
+
12
+ require 'benchmark/ips'
13
+ require 'fileutils'
14
+
15
+ DB_PATH = '/tmp/extralite_sqlite3_perf.db'
16
+
17
+ def prepare_database(count)
18
+ FileUtils.rm(DB_PATH) rescue nil
19
+ db = Extralite::Database.new(DB_PATH)
20
+ db.query('create table foo ( a integer primary key, b text )')
21
+ db.query('begin')
22
+ count.times { db.query('insert into foo (b) values (?)', "hello#{rand(1000)}" )}
23
+ db.query('commit')
24
+ end
25
+
26
+ def sqlite3_prepare
27
+ db = SQLite3::Database.new(DB_PATH, :results_as_hash => true)
28
+ db.prepare('select * from foo')
29
+ end
30
+
31
+ def sqlite3_run(stmt, count)
32
+ # db = SQLite3::Database.new(DB_PATH, :results_as_hash => true)
33
+ results = stmt.execute.to_a
34
+ raise unless results.size == count
35
+ end
36
+
37
+ def extralite_prepare
38
+ db = Extralite::Database.new(DB_PATH)
39
+ db.prepare('select * from foo')
40
+ end
41
+
42
+ def extralite_run(stmt, count)
43
+ # db = Extralite::Database.new(DB_PATH)
44
+ results = stmt.query
45
+ raise unless results.size == count
46
+ end
47
+
48
+ [10, 1000, 100000].each do |c|
49
+ puts; puts; puts "Record count: #{c}"
50
+
51
+ prepare_database(c)
52
+
53
+ sqlite3_stmt = sqlite3_prepare
54
+ extralite_stmt = extralite_prepare
55
+
56
+ Benchmark.ips do |x|
57
+ x.config(:time => 3, :warmup => 1)
58
+
59
+ x.report("sqlite3") { sqlite3_run(sqlite3_stmt, c) }
60
+ x.report("extralite") { extralite_run(extralite_stmt, c) }
61
+
62
+ x.compare!
63
+ end
64
+ end
@@ -163,6 +163,20 @@ end
163
163
  r = @db.query_single_value('select null')
164
164
  assert_nil r
165
165
  end
166
+
167
+
168
+
169
+ def test_extension_loading
170
+ case RUBY_PLATFORM
171
+ when /linux/
172
+ @db.load_extension(File.join(__dir__, 'extensions/text.so'))
173
+ when /darwin/
174
+ @db.load_extension(File.join(__dir__, 'extensions/text.dylib'))
175
+ end
176
+
177
+ r = @db.query_single_value("select reverse('abcd')")
178
+ assert_equal 'dcba', r
179
+ end
166
180
  end
167
181
 
168
182
  class ScenarioTest < MiniTest::Test
@@ -0,0 +1,14 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'helper'
4
+
5
+ class ExtraliteTest < MiniTest::Test
6
+ SQLITE3_C_PATH = File.expand_path('../ext/extralite/sqlite3.c', __dir__)
7
+ SQLITE_VERSION_DEFINE_REGEXP = /#define SQLITE_VERSION\s+"([\d\.]+)"/m.freeze
8
+
9
+ def test_sqlite3_version
10
+ version = IO.read(SQLITE3_C_PATH).match(SQLITE_VERSION_DEFINE_REGEXP)[1]
11
+
12
+ assert_equal version, Extralite.sqlite3_version
13
+ end
14
+ end
@@ -0,0 +1,165 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'helper'
4
+
5
+ class PreparedStatementTest < MiniTest::Test
6
+ def setup
7
+ @db = Extralite::Database.new(':memory:')
8
+ @db.query('create table if not exists t (x,y,z)')
9
+ @db.query('delete from t')
10
+ @db.query('insert into t values (1, 2, 3)')
11
+ @db.query('insert into t values (4, 5, 6)')
12
+
13
+ @stmt = @db.prepare('select * from t where x = ?')
14
+ end
15
+
16
+ # def test_foo
17
+ # stmt = @db.prepare('select 1')
18
+ # assert_equal 1, stmt.query_single_value
19
+ # end
20
+
21
+ def test_prepared_statement_props
22
+ assert_kind_of Extralite::PreparedStatement, @stmt
23
+ assert_equal @db, @stmt.database
24
+ assert_equal @db, @stmt.db
25
+ assert_equal 'select * from t where x = ?', @stmt.sql
26
+ end
27
+
28
+ def test_prepared_statement_query
29
+ assert_equal [{ x: 1, y: 2, z: 3 }], @stmt.query(1)
30
+
31
+ buf = []
32
+ @stmt.query(1) { |r| buf << r }
33
+ assert_equal [{ x: 1, y: 2, z: 3 }], buf
34
+ end
35
+
36
+ def test_prepared_statement_with_invalid_sql
37
+ assert_raises(Extralite::SQLError) { @db.prepare('blah') }
38
+ end
39
+
40
+ def test_prepared_statement_query_hash
41
+ r = @stmt.query_hash(4)
42
+ assert_equal [{x: 4, y: 5, z: 6}], r
43
+
44
+ r = @stmt.query_hash(5)
45
+ assert_equal [], r
46
+ end
47
+
48
+ def test_prepared_statement_query_ary
49
+ r = @stmt.query_ary(1)
50
+ assert_equal [[1, 2, 3]], r
51
+
52
+ r = @stmt.query_ary(2)
53
+ assert_equal [], r
54
+ end
55
+
56
+ def test_prepared_statement_query_single_row
57
+ r = @stmt.query_single_row(4)
58
+ assert_equal({ x: 4, y: 5, z: 6 }, r)
59
+
60
+ r = @stmt.query_single_row(5)
61
+ assert_nil r
62
+ end
63
+
64
+ def test_prepared_statement_query_single_column
65
+ stmt =
66
+ r = @db.prepare('select y from t').query_single_column
67
+ assert_equal [2, 5], r
68
+
69
+ r = @db.prepare('select y from t where x = 2').query_single_column
70
+ assert_equal [], r
71
+ end
72
+
73
+ def test_prepared_statement_query_single_value
74
+ r = @db.prepare('select z from t order by Z desc limit 1').query_single_value
75
+ assert_equal 6, r
76
+
77
+ r = @db.prepare('select z from t where x = 2').query_single_value
78
+ assert_nil r
79
+ end
80
+
81
+ def test_prepared_statement_multiple_statements
82
+ assert_raises(Extralite::Error) {
83
+ @db.prepare("insert into t values ('a', 'b', 'c'); insert into t values ('d', 'e', 'f');")
84
+ }
85
+ end
86
+
87
+ def test_prepared_statement_multiple_statements_with_bad_sql
88
+ error = nil
89
+ begin
90
+ stmt =@db.prepare("insert into t values foo; insert into t values ('d', 'e', 'f');")
91
+ stmt.query
92
+ rescue => error
93
+ end
94
+
95
+ assert_kind_of Extralite::SQLError, error
96
+ assert_equal 'near "foo": syntax error', error.message
97
+ end
98
+
99
+ def test_prepared_statement_repeated_execution_missing_param
100
+ r = @stmt.query_hash(4)
101
+ assert_equal [{x: 4, y: 5, z: 6}], r
102
+
103
+ r = @stmt.query_hash
104
+ assert_equal [], r
105
+ end
106
+
107
+ def test_prepared_statement_empty_sql
108
+ assert_raises(Extralite::Error) { @db.prepare(' ') }
109
+
110
+ r = @db.prepare('select 1 as foo; ').query
111
+ assert_equal [{ foo: 1 }], r
112
+ end
113
+
114
+ def test_prepared_statement_parameter_binding_simple
115
+ r = @db.prepare('select x, y, z from t where x = ?').query(1)
116
+ assert_equal [{ x: 1, y: 2, z: 3 }], r
117
+
118
+ r = @db.prepare('select x, y, z from t where z = ?').query(6)
119
+ assert_equal [{ x: 4, y: 5, z: 6 }], r
120
+ end
121
+
122
+ def test_prepared_statement_parameter_binding_with_index
123
+ r = @db.prepare('select x, y, z from t where x = ?2').query(0, 1)
124
+ assert_equal [{ x: 1, y: 2, z: 3 }], r
125
+
126
+ r = @db.prepare('select x, y, z from t where z = ?3').query(3, 4, 6)
127
+ assert_equal [{ x: 4, y: 5, z: 6 }], r
128
+ end
129
+
130
+ def test_prepared_statement_parameter_binding_with_name
131
+ r = @db.prepare('select x, y, z from t where x = :x').query(x: 1, y: 2)
132
+ assert_equal [{ x: 1, y: 2, z: 3 }], r
133
+
134
+ r = @db.prepare('select x, y, z from t where z = :zzz').query('zzz' => 6)
135
+ assert_equal [{ x: 4, y: 5, z: 6 }], r
136
+
137
+ r = @db.prepare('select x, y, z from t where z = :bazzz').query(':bazzz' => 6)
138
+ assert_equal [{ x: 4, y: 5, z: 6 }], r
139
+ end
140
+
141
+ def test_prepared_statement_parameter_binding_with_index_key
142
+ r = @db.prepare('select x, y, z from t where z = ?').query(1 => 3)
143
+ assert_equal [{ x: 1, y: 2, z: 3 }], r
144
+
145
+ r = @db.prepare('select x, y, z from t where x = ?2').query(1 => 42, 2 => 4)
146
+ assert_equal [{ x: 4, y: 5, z: 6 }], r
147
+ end
148
+
149
+ def test_prepared_statement_value_casting
150
+ r = @db.prepare("select 'abc'").query_single_value
151
+ assert_equal 'abc', r
152
+
153
+ r = @db.prepare('select 123').query_single_value
154
+ assert_equal 123, r
155
+
156
+ r = @db.prepare('select 12.34').query_single_value
157
+ assert_equal 12.34, r
158
+
159
+ r = @db.prepare('select zeroblob(4)').query_single_value
160
+ assert_equal "\x00\x00\x00\x00", r
161
+
162
+ r = @db.prepare('select null').query_single_value
163
+ assert_nil r
164
+ end
165
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: extralite
3
3
  version: !ruby/object:Gem::Version
4
- version: '1.10'
4
+ version: '1.13'
5
5
  platform: ruby
6
6
  authors:
7
7
  - Sharon Rosner
8
- autorequire:
8
+ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2021-12-15 00:00:00.000000000 Z
11
+ date: 2022-02-27 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rake-compiler
@@ -80,7 +80,7 @@ dependencies:
80
80
  - - '='
81
81
  - !ruby/object:Gem::Version
82
82
  version: 5.51.0
83
- description:
83
+ description:
84
84
  email: sharon@noteflakes.com
85
85
  executables: []
86
86
  extensions:
@@ -98,18 +98,29 @@ files:
98
98
  - README.md
99
99
  - Rakefile
100
100
  - TODO.md
101
+ - bin/update_sqlite_source
102
+ - ext/extralite/common.c
103
+ - ext/extralite/database.c
101
104
  - ext/extralite/extconf.rb
102
- - ext/extralite/extralite.c
105
+ - ext/extralite/extralite.h
103
106
  - ext/extralite/extralite_ext.c
107
+ - ext/extralite/prepared_statement.c
108
+ - ext/extralite/sqlite3.c
109
+ - ext/extralite/sqlite3.h
104
110
  - extralite.gemspec
105
111
  - lib/extralite.rb
106
112
  - lib/extralite/version.rb
107
113
  - lib/sequel/adapters/extralite.rb
114
+ - test/extensions/text.dylib
115
+ - test/extensions/text.so
108
116
  - test/helper.rb
109
117
  - test/perf_ary.rb
110
118
  - test/perf_hash.rb
119
+ - test/perf_prepared.rb
111
120
  - test/run.rb
112
121
  - test/test_database.rb
122
+ - test/test_extralite.rb
123
+ - test/test_prepared_statement.rb
113
124
  - test/test_sequel.rb
114
125
  homepage: https://github.com/digital-fabric/extralite
115
126
  licenses:
@@ -119,7 +130,7 @@ metadata:
119
130
  documentation_uri: https://www.rubydoc.info/gems/extralite
120
131
  homepage_uri: https://github.com/digital-fabric/extralite
121
132
  changelog_uri: https://github.com/digital-fabric/extralite/blob/master/CHANGELOG.md
122
- post_install_message:
133
+ post_install_message:
123
134
  rdoc_options:
124
135
  - "--title"
125
136
  - extralite
@@ -131,15 +142,15 @@ required_ruby_version: !ruby/object:Gem::Requirement
131
142
  requirements:
132
143
  - - ">="
133
144
  - !ruby/object:Gem::Version
134
- version: '2.6'
145
+ version: '2.7'
135
146
  required_rubygems_version: !ruby/object:Gem::Requirement
136
147
  requirements:
137
148
  - - ">="
138
149
  - !ruby/object:Gem::Version
139
150
  version: '0'
140
151
  requirements: []
141
- rubygems_version: 3.1.6
142
- signing_key:
152
+ rubygems_version: 3.3.3
153
+ signing_key:
143
154
  specification_version: 4
144
155
  summary: Extra-lightweight SQLite3 wrapper for Ruby
145
156
  test_files: []