extralite-bundle 1.14

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 707b5791f03fe03812e63a1e46ff61ab7c0113558cadcff9d23b6cc4c30489ac
4
+ data.tar.gz: d2d9539f7cba8b25c2aea0ed2d3263c5f77cc83f037bf3580afe6cef2d755a8b
5
+ SHA512:
6
+ metadata.gz: 12b635439146811bd212ec0c1efc2e0ddd772e125799eb5f94b505357d6ad2d933bd4e4e1a8e6e21e63f938a27880673e2d66db8c71597d22df9abb22643823a
7
+ data.tar.gz: 986f47ea415902b9dd1c1a1728328384d50748d1fdb7cbfa290439a44aad4489bb40bd0719055115e4e0d77a0df871e75fab2f5186a1930474c69860403331ea
@@ -0,0 +1 @@
1
+ github: ciconia
@@ -0,0 +1,26 @@
1
+ name: Tests
2
+
3
+ on: [push, pull_request]
4
+
5
+ jobs:
6
+ build:
7
+ strategy:
8
+ fail-fast: false
9
+ matrix:
10
+ os: [ubuntu-latest, macos-10.15]
11
+ ruby: [2.7, 3.0, 3.1, truffleruby]
12
+
13
+ name: >-
14
+ ${{matrix.os}}, ${{matrix.ruby}}
15
+
16
+ runs-on: ${{matrix.os}}
17
+ steps:
18
+ - uses: actions/checkout@v1
19
+ - uses: ruby/setup-ruby@v1
20
+ with:
21
+ ruby-version: ${{matrix.ruby}}
22
+ bundler-cache: true # 'bundle install' and cache
23
+ - name: Compile C-extension
24
+ run: bundle exec rake compile
25
+ - name: Run tests
26
+ run: bundle exec rake test
data/.gitignore ADDED
@@ -0,0 +1,57 @@
1
+ *.gem
2
+ *.rbc
3
+ /.config
4
+ /coverage/
5
+ /InstalledFiles
6
+ /pkg/
7
+ /spec/reports/
8
+ /spec/examples.txt
9
+ /test/tmp/
10
+ /test/version_tmp/
11
+ /tmp/
12
+ lib/extralite_ext.*
13
+
14
+ # Used by dotenv library to load environment variables.
15
+ # .env
16
+
17
+ # Ignore Byebug command history file.
18
+ .byebug_history
19
+
20
+ ## Specific to RubyMotion:
21
+ .dat*
22
+ .repl_history
23
+ build/
24
+ *.bridgesupport
25
+ build-iPhoneOS/
26
+ build-iPhoneSimulator/
27
+
28
+ ## Specific to RubyMotion (use of CocoaPods):
29
+ #
30
+ # We recommend against adding the Pods directory to your .gitignore. However
31
+ # you should judge for yourself, the pros and cons are mentioned at:
32
+ # https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control
33
+ #
34
+ # vendor/Pods/
35
+
36
+ ## Documentation cache and generated files:
37
+ /.yardoc/
38
+ /_yardoc/
39
+ /doc/
40
+ /rdoc/
41
+
42
+ ## Environment normalization:
43
+ /.bundle/
44
+ /vendor/bundle
45
+ /lib/bundler/man/
46
+
47
+ # for a library or gem, you might want to ignore these files since the code is
48
+ # intended to run in multiple environments; otherwise, check them in:
49
+ # Gemfile.lock
50
+ # .ruby-version
51
+ # .ruby-gemset
52
+
53
+ # unless supporting rvm < 1.11.0 or doing something fancy, ignore this:
54
+ .rvmrc
55
+
56
+ # Used by RuboCop. Remote config files pulled in from inherit_from directive.
57
+ # .rubocop-https?--*
data/CHANGELOG.md ADDED
@@ -0,0 +1,96 @@
1
+ ## 1.14 2022-02-28
2
+
3
+ - Introduce `extralite-bundle` gem for bundling SQLite, use system lib by
4
+ default.
5
+
6
+ ## 1.13.1 2022-02-27
7
+
8
+ - Fix compilation on TruffleRuby
9
+
10
+ ## 1.13 2022-02-27
11
+
12
+ - Implement prepared statements (#7)
13
+ - Update SQLite to 3.38.0 (#6)
14
+
15
+ ## 1.12 2022-02-15
16
+
17
+ - Add `Extralite.sqlite3_version` method
18
+ - Bundle sqlite3 in gem
19
+
20
+ ## 1.11 2021-12-17
21
+
22
+ - Fix compilation on MacOS (#3)
23
+
24
+ ## 1.10 2021-12-15
25
+
26
+ - Fix mutliple parameter binding with hash
27
+
28
+ ## 1.9 2021-12-15
29
+
30
+ - Add support for reading BLOBs
31
+
32
+ ## 1.8.2 2021-12-15
33
+
34
+ - Add documentation
35
+
36
+ ## 1.7 2021-12-13
37
+
38
+ - Add extralite Sequel adapter
39
+ - Add support for binding hash parameters
40
+
41
+ ## 1.6 2021-12-13
42
+
43
+ - Release GVL while fetching rows
44
+
45
+ ## 1.5 2021-12-13
46
+
47
+ - Release GVL while preparing statements
48
+ - Use `sqlite3_prepare_v2` instead of deprecated `sqlite_prepare`
49
+
50
+ ## 1.4 2021-08-25
51
+
52
+ - Fix possible segfault in cleanup_stmt
53
+
54
+ ## 1.3 2021-08-17
55
+
56
+ - Pin error classes (for better compatibility with `GC.compact`)
57
+
58
+ ## 1.2 2021-06-06
59
+
60
+ - Add support for big integers
61
+
62
+ ## 1.1 2021-06-02
63
+
64
+ - Add `#close`, `#closed?` methods
65
+
66
+ ## 1.0 2021-05-27
67
+
68
+ - Refactor C code
69
+ - Use `rb_ensure` to finalize stmt
70
+ - Remove bundled `sqlite3.h`, use system-wide header file instead
71
+
72
+ ## 0.6 2021-05-25
73
+
74
+ - Add more specific errors: `SQLError`, `BusyError`
75
+
76
+ ## 0.5 2021-05-25
77
+
78
+ - Implement `Database#query_single_row`
79
+
80
+ ## 0.4 2021-05-24
81
+
82
+ - Add support for loading extensions
83
+
84
+ ## 0.3 2021-05-24
85
+
86
+ - Add support for running multiple statements
87
+
88
+ ## 0.2 2021-05-23
89
+
90
+ - Implement `Database#transaction_active?`
91
+ - Add tests
92
+
93
+ ## 0.1 2021-05-21
94
+
95
+ - First release
96
+
data/Gemfile ADDED
@@ -0,0 +1,3 @@
1
+ source 'https://rubygems.org'
2
+
3
+ gemspec name: 'extralite'
data/Gemfile.lock ADDED
@@ -0,0 +1,37 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ extralite (1.14)
5
+
6
+ GEM
7
+ remote: https://rubygems.org/
8
+ specs:
9
+ docile (1.4.0)
10
+ json (2.6.1)
11
+ minitest (5.15.0)
12
+ rake (13.0.6)
13
+ rake-compiler (1.1.6)
14
+ rake
15
+ sequel (5.51.0)
16
+ simplecov (0.17.1)
17
+ docile (~> 1.1)
18
+ json (>= 1.8, < 3)
19
+ simplecov-html (~> 0.10.0)
20
+ simplecov-html (0.10.2)
21
+ webrick (1.7.0)
22
+ yard (0.9.27)
23
+ webrick (~> 1.7.0)
24
+
25
+ PLATFORMS
26
+ ruby
27
+
28
+ DEPENDENCIES
29
+ extralite!
30
+ minitest (= 5.15.0)
31
+ rake-compiler (= 1.1.6)
32
+ sequel (= 5.51.0)
33
+ simplecov (= 0.17.1)
34
+ yard (= 0.9.27)
35
+
36
+ BUNDLED WITH
37
+ 2.3.3
data/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2022 Sharon Rosner
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,248 @@
1
+ <h1 align="center">
2
+ Extralite
3
+ </h1>
4
+
5
+ <h4 align="center">A fast Ruby gem for working with SQLite3 databases</h4>
6
+
7
+ <p align="center">
8
+ <a href="http://rubygems.org/gems/extralite">
9
+ <img src="https://badge.fury.io/rb/extralite.svg" alt="Ruby gem">
10
+ </a>
11
+ <a href="https://github.com/digital-fabric/extralite/actions?query=workflow%3ATests">
12
+ <img src="https://github.com/digital-fabric/extralite/workflows/Tests/badge.svg" alt="Tests">
13
+ </a>
14
+ <a href="https://github.com/digital-fabric/extralite/blob/master/LICENSE">
15
+ <img src="https://img.shields.io/badge/license-MIT-blue.svg" alt="MIT License">
16
+ </a>
17
+ </p>
18
+
19
+ <p align="center">
20
+ <a href="https://www.rubydoc.info/gems/extralite">DOCS</a> |
21
+ <a href="https://noteflakes.com/articles/2021-12-15-extralite">BLOG POST</a>
22
+ </p>
23
+
24
+ ## What is Extralite?
25
+
26
+ Extralite is a fast, extra-lightweight (about 600 lines of C-code) SQLite3
27
+ wrapper for Ruby. It provides a minimal set of methods for interacting with an
28
+ SQLite3 database, as well as prepared statements.
29
+
30
+ Extralite comes in two flavors: the `extralite` gem which uses the
31
+ system-installed sqlite3 library, and the `extralite-bundle` gem which bundles
32
+ the latest version of SQLite
33
+ ([3.38.0](https://sqlite.org/releaselog/3_38_0.html)), offering access to the
34
+ latest features and enhancements.
35
+
36
+ ## Features
37
+
38
+ - A variety of methods for different data access patterns: rows as hashes, rows
39
+ as arrays, single row, single column, single value.
40
+ - Prepared statements.
41
+ - Super fast - [up to 12.5x faster](#performance) than the
42
+ [sqlite3](https://github.com/sparklemotion/sqlite3-ruby) gem (see also
43
+ [comparison](#why-not-just-use-the-sqlite3-gem).)
44
+ - Improved [concurrency](#concurrency) for multithreaded apps: the Ruby GVL is
45
+ released while preparing SQL statements and while iterating over results.
46
+ - Iterate over records with a block, or collect records into an array.
47
+ - Parameter binding.
48
+ - Automatically execute SQL strings containing multiple semicolon-separated
49
+ queries (handy for creating/modifying schemas).
50
+ - Get last insert rowid.
51
+ - Get number of rows changed by last query.
52
+ - Load extensions (loading of extensions is autmatically enabled. You can find
53
+ some useful extensions here: https://github.com/nalgeon/sqlean.)
54
+ - Includes a [Sequel adapter](#usage-with-sequel).
55
+
56
+ ## Installation
57
+
58
+ To use Extralite in your Ruby app, add the following to your `Gemfile`:
59
+
60
+ ```ruby
61
+ gem 'extralite'
62
+ ```
63
+
64
+ You can also run `gem install extralite` if you just want to check it out.
65
+
66
+ ## Installing the Extralite-SQLite3 bundle
67
+
68
+ If you don't have sqlite3 installed on your system, do not want to use the
69
+ system-installed version of SQLite3, or would like to use the latest version of
70
+ SQLite3, you can install the `extralite-bundle` gem, which integrates the
71
+ SQLite3 source code.
72
+
73
+ > **Important note**: The `extralite-bundle` will take a while to install (on my
74
+ > modest machine it takes about a minute), due to the size of the sqlite3 code.
75
+
76
+ Usage of the `extralite-bundle` gem is identical to the usage of the normal
77
+ `extralite` gem.
78
+
79
+ ## Usage
80
+
81
+ ```ruby
82
+ require 'extralite'
83
+
84
+ # get sqlite3 version
85
+ Extralite.sqlite3_version #=> "3.35.2"
86
+
87
+ # open a database
88
+ db = Extralite::Database.new('/tmp/my.db')
89
+
90
+ # get query results as array of hashes
91
+ db.query('select 1 as foo') #=> [{ :foo => 1 }]
92
+ # or:
93
+ db.query_hash('select 1 as foo') #=> [{ :foo => 1 }]
94
+ # or iterate over results
95
+ db.query('select 1 as foo') { |r| p r }
96
+ # { :foo => 1 }
97
+
98
+ # get query results as array of arrays
99
+ db.query_ary('select 1, 2, 3') #=> [[1, 2, 3]]
100
+ # or iterate over results
101
+ db.query_ary('select 1, 2, 3') { |r| p r }
102
+ # [1, 2, 3]
103
+
104
+ # get a single row as a hash
105
+ db.query_single_row("select 1 as foo") #=> { :foo => 1 }
106
+
107
+ # get single column query results as array of values
108
+ db.query_single_column('select 42') #=> [42]
109
+ # or iterate over results
110
+ db.query_single_column('select 42') { |v| p v }
111
+ # 42
112
+
113
+ # get single value from first row of results
114
+ db.query_single_value("select 'foo'") #=> "foo"
115
+
116
+ # parameter binding (works for all query_xxx methods)
117
+ db.query_hash('select ? as foo, ? as bar', 1, 2) #=> [{ :foo => 1, :bar => 2 }]
118
+
119
+ # parameter binding of named parameters
120
+ db.query('select * from foo where bar = :bar', bar: 42)
121
+ db.query('select * from foo where bar = :bar', 'bar' => 42)
122
+ db.query('select * from foo where bar = :bar', ':bar' => 42)
123
+
124
+ # prepared statements
125
+ stmt = db.prepare('select ? as foo, ? as bar') #=> Extralite::PreparedStatement
126
+ stmt.query(1, 2) #=> [{ :foo => 1, :bar => 2 }]
127
+ # PreparedStatement offers the same data access methods as the Database class,
128
+ # but without the sql parameter.
129
+
130
+ # get last insert rowid
131
+ rowid = db.last_insert_rowid
132
+
133
+ # get number of rows changed in last query
134
+ number_of_rows_affected = db.changes
135
+
136
+ # get db filename
137
+ db.filename #=> "/tmp/my.db"
138
+
139
+ # load an extension
140
+ db.load_extension('/path/to/extension.so')
141
+
142
+ # close database
143
+ db.close
144
+ db.closed? #=> true
145
+ ```
146
+
147
+ ## Usage with Sequel
148
+
149
+ Extralite includes an adapter for
150
+ [Sequel](https://github.com/jeremyevans/sequel). To use the Extralite adapter,
151
+ just use the `extralite` scheme instead of `sqlite`:
152
+
153
+ ```ruby
154
+ DB = Sequel.connect('extralite://blog.db')
155
+ articles = DB[:articles]
156
+ p articles.to_a
157
+ ```
158
+
159
+ (Make sure you include `extralite` as a dependency in your `Gemfile`.)
160
+
161
+ ## Why not just use the sqlite3 gem?
162
+
163
+ The [sqlite3-ruby](https://github.com/sparklemotion/sqlite3-ruby) gem is a
164
+ popular, solid, well-maintained project, used by thousands of developers. I've
165
+ been doing a lot of work with SQLite3 databases lately, and wanted to have a
166
+ simpler API that gives me query results in a variety of ways. Thus extralite was
167
+ born.
168
+
169
+ Extralite is quite a bit [faster](#performance) than sqlite3-ruby and is also
170
+ [thread-friendly](#concurrency). On the other hand, Extralite does not have
171
+ support for defining custom functions, aggregates and collations. If you're
172
+ using any of those features, you'll have to stick to sqlite3-ruby.
173
+
174
+ Here's a table summarizing the differences between the two gems:
175
+
176
+ | |sqlite3-ruby|Extralite|
177
+ |-|-|-|
178
+ |SQLite3 dependency|depends on OS-installed libsqlite3|bundles latest version of SQLite3|
179
+ |API design|multiple classes|single class|
180
+ |Query results|row as hash, row as array, single row, single value|row as hash, row as array, __single column__, single row, single value|
181
+ |Execute multiple statements|separate API (#execute_batch)|integrated|
182
+ |Prepared statements|yes|yes|
183
+ |custom functions in Ruby|yes|no|
184
+ |custom collations|yes|no|
185
+ |custom aggregate functions|yes|no|
186
+ |Multithread friendly|no|[yes](#concurrency)|
187
+ |Code size|~2650LoC|~600LoC|
188
+ |Performance|1x|1.5x to 12.5x (see [below](#performance))|
189
+
190
+ ## Concurrency
191
+
192
+ Extralite releases the GVL while making blocking calls to the sqlite3 library,
193
+ that is while preparing SQL statements and fetching rows. Releasing the GVL
194
+ allows other threads to run while the sqlite3 library is busy compiling SQL into
195
+ bytecode, or fetching the next row. This does not seem to hurt Extralite's
196
+ performance:
197
+
198
+ ## Performance
199
+
200
+ A benchmark script is included, creating a table of various row counts, then
201
+ fetching the entire table using either `sqlite3` or `extralite`. This benchmark
202
+ shows Extralite to be up to ~12 times faster than `sqlite3` when fetching a
203
+ large number of rows.
204
+
205
+ ### Rows as hashes
206
+
207
+ [Benchmark source code](https://github.com/digital-fabric/extralite/blob/main/test/perf_hash.rb)
208
+
209
+ |Row count|sqlite3-ruby|Extralite|Advantage|
210
+ |-:|-:|-:|-:|
211
+ |10|75.3K rows/s|134.2K rows/s|__1.78x__|
212
+ |1K|286.8K rows/s|2106.4K rows/s|__7.35x__|
213
+ |100K|181.0K rows/s|2275.3K rows/s|__12.53x__|
214
+
215
+ ### Rows as arrays
216
+
217
+ [Benchmark source code](https://github.com/digital-fabric/extralite/blob/main/test/perf_ary.rb)
218
+
219
+ |Row count|sqlite3-ruby|Extralite|Advantage|
220
+ |-:|-:|-:|-:|
221
+ |10|64.3K rows/s|94.0K rows/s|__1.46x__|
222
+ |1K|498.9K rows/s|2478.2K rows/s|__4.97x__|
223
+ |100K|441.1K rows/s|3023.4K rows/s|__6.85x__|
224
+
225
+ ### Prepared statements
226
+
227
+ [Benchmark source code](https://github.com/digital-fabric/extralite/blob/main/test/perf_prepared.rb)
228
+
229
+ |Row count|sqlite3-ruby|Extralite|Advantage|
230
+ |-:|-:|-:|-:|
231
+ |10|241.8K rows/s|888K rows/s|__3.67x__|
232
+ |1K|298.6K rows/s|2606K rows/s|__8.73x__|
233
+ |100K|201.6K rows/s|1934K rows/s|__9.6x__|
234
+
235
+ As those benchmarks show, Extralite is capabale of reading up to 3M rows/second
236
+ when fetching rows as arrays, and up to 2.6M rows/second when fetching
237
+ rows as hashes.
238
+
239
+ ## License
240
+
241
+ The source code for Extralite is published under the [MIT license](LICENSE). The
242
+ source code for SQLite is in the [public
243
+ domain](https://sqlite.org/copyright.html).
244
+
245
+ ## Contributing
246
+
247
+ Contributions in the form of issues, PRs or comments will be greatly
248
+ appreciated!
data/Rakefile ADDED
@@ -0,0 +1,46 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'rake/clean'
4
+
5
+ require 'rake/extensiontask'
6
+ Rake::ExtensionTask.new('extralite_ext') do |ext|
7
+ ext.ext_dir = 'ext/extralite'
8
+ end
9
+
10
+ task :recompile => [:clean, :compile]
11
+
12
+ task :default => [:compile, :doc, :test]
13
+ task :doc => :yard
14
+ task :test do
15
+ exec 'ruby test/run.rb'
16
+ end
17
+
18
+ CLEAN.include 'lib/*.o', 'lib/*.so', 'lib/*.so.*', 'lib/*.a', 'lib/*.bundle', 'lib/*.jar', 'pkg', 'tmp'
19
+
20
+ require 'yard'
21
+ YARD_FILES = FileList['ext/extralite/extralite.c', 'lib/extralite.rb', 'lib/sequel/adapters/extralite.rb']
22
+
23
+ YARD::Rake::YardocTask.new do |t|
24
+ t.files = YARD_FILES
25
+ t.options = %w(-o doc --readme README.md)
26
+ end
27
+
28
+ task :release do
29
+ require_relative './lib/extralite/version'
30
+ version = Extralite::VERSION
31
+
32
+ puts 'Building extralite...'
33
+ `gem build extralite.gemspec`
34
+
35
+ puts 'Building extralite-bundle...'
36
+ `gem build extralite-bundle.gemspec`
37
+
38
+ puts "Pushing extralite #{version}..."
39
+ # `gem push extralite-#{version}.gem`
40
+
41
+ puts "Pushing extralite-bundle #{version}..."
42
+ `gem push extralite-bundle-#{version}.gem`
43
+
44
+ puts "Cleaning up..."
45
+ `rm *.gem`
46
+ end
data/TODO.md ADDED
File without changes
@@ -0,0 +1,26 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ version = ARGV[0]
5
+ raise "Please specify version" unless version
6
+
7
+ require 'fileutils'
8
+ require 'date'
9
+
10
+ FileUtils.cd '/tmp'
11
+
12
+ version_id = version.gsub('.', '')
13
+ version_id += '0' * (7 - version_id.length)
14
+ url = "https://sqlite.org/#{Date.today.year}/sqlite-amalgamation-#{version_id}.zip"
15
+ dest = File.expand_path('../ext/extralite', __dir__)
16
+
17
+ puts "Downloading from #{url}..."
18
+ `curl #{url} > #{version_id}.zip`
19
+
20
+ puts "Unzipping zip file..."
21
+ `unzip -o #{version_id}.zip`
22
+
23
+ puts "Copying source files"
24
+ `cp sqlite-amalgamation-#{version_id}/sqlite3.* #{dest}/`
25
+
26
+ puts 'Done updating source files'