extralite 1.13.1 → 1.15
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 +4 -4
- data/.github/workflows/test.yml +2 -2
- data/CHANGELOG.md +10 -0
- data/Gemfile +1 -1
- data/Gemfile.lock +1 -1
- data/LICENSE +1 -1
- data/README.md +37 -10
- data/Rakefile +20 -1
- data/ext/extralite/common.c +5 -1
- data/ext/extralite/database.c +12 -2
- data/ext/extralite/extconf-bundle.rb +9 -0
- data/ext/extralite/extconf.rb +108 -2
- data/ext/extralite/extralite.h +6 -0
- data/ext/extralite/extralite_sqlite3.c +3 -0
- data/ext/extralite/prepared_statement.c +45 -0
- data/ext/{extralite → sqlite3}/sqlite3.c +0 -0
- data/ext/{extralite → sqlite3}/sqlite3.h +0 -0
- data/extralite-bundle.gemspec +8 -0
- data/extralite.gemspec +3 -25
- data/gemspec.rb +26 -0
- data/lib/extralite/version.rb +1 -1
- data/lib/extralite.rb +25 -1
- data/lib/sequel/adapters/extralite.rb +13 -13
- data/test/helper.rb +1 -1
- data/test/test_database.rb +30 -0
- data/test/test_extralite.rb +1 -6
- data/test/test_prepared_statement.rb +19 -0
- metadata +13 -9
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 0275df0298c578e4b166e392a43e7edcc4566d08eccdfe8c76ef0fd4e2a0c244
|
4
|
+
data.tar.gz: 312f5218786eaeaa879703c403ace437b351f76fe1fd5660d3d64fe6592f1c8a
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 8b2052fc2ca18c5d1e61c5ada2a094a1ef5e56053ab8434b8fbb55da35bd2633dcae0131b383caf0b7a9f2990a05205d8788a72ae98ce79b69854f8b517e4c6e
|
7
|
+
data.tar.gz: cff930e31e7f6d0050f2467c2661fa8369ba259bdaf9359154da1ba9ba5dc67ca3c6f327a34dbac73f0edf3d145962c2e973e12bee9c2f323a07612c5b984c03
|
data/.github/workflows/test.yml
CHANGED
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,13 @@
|
|
1
|
+
## 1.15 2022-10-01
|
2
|
+
|
3
|
+
- Add `Database#pragma` method
|
4
|
+
- Add `Database#tables` method
|
5
|
+
|
6
|
+
## 1.14 2022-02-28
|
7
|
+
|
8
|
+
- Introduce `extralite-bundle` gem for bundling SQLite, use system lib by
|
9
|
+
default.
|
10
|
+
|
1
11
|
## 1.13.1 2022-02-27
|
2
12
|
|
3
13
|
- Fix compilation on TruffleRuby
|
data/Gemfile
CHANGED
data/Gemfile.lock
CHANGED
data/LICENSE
CHANGED
data/README.md
CHANGED
@@ -25,17 +25,21 @@
|
|
25
25
|
|
26
26
|
Extralite is a fast, extra-lightweight (about 600 lines of C-code) SQLite3
|
27
27
|
wrapper for Ruby. It provides a minimal set of methods for interacting with an
|
28
|
-
SQLite3 database, as well as prepared statements.
|
29
|
-
|
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.
|
30
35
|
|
31
36
|
## Features
|
32
37
|
|
33
|
-
- Zero dependencies: Extralite bundles SQLite3 version
|
34
|
-
[3.38.0](https://sqlite.org/releaselog/3_38_0.html) - no need to install any
|
35
|
-
`libsqlite3` packages.
|
36
38
|
- A variety of methods for different data access patterns: rows as hashes, rows
|
37
39
|
as arrays, single row, single column, single value.
|
38
40
|
- Prepared statements.
|
41
|
+
- Use system-installed sqlite3, or the [bundled latest version of
|
42
|
+
SQLite3](#installing-the-extralite-sqlite3-bundle).
|
39
43
|
- Super fast - [up to 12.5x faster](#performance) than the
|
40
44
|
[sqlite3](https://github.com/sparklemotion/sqlite3-ruby) gem (see also
|
41
45
|
[comparison](#why-not-just-use-the-sqlite3-gem).)
|
@@ -61,9 +65,18 @@ gem 'extralite'
|
|
61
65
|
|
62
66
|
You can also run `gem install extralite` if you just want to check it out.
|
63
67
|
|
64
|
-
|
65
|
-
|
66
|
-
|
68
|
+
### Installing the Extralite-SQLite3 bundle
|
69
|
+
|
70
|
+
If you don't have sqlite3 installed on your system, do not want to use the
|
71
|
+
system-installed version of SQLite3, or would like to use the latest version of
|
72
|
+
SQLite3, you can install the `extralite-bundle` gem, which integrates the
|
73
|
+
SQLite3 source code.
|
74
|
+
|
75
|
+
> **Important note**: The `extralite-bundle` will take a while to install (on my
|
76
|
+
> modest machine it takes about a minute), due to the size of the sqlite3 code.
|
77
|
+
|
78
|
+
Usage of the `extralite-bundle` gem is identical to the usage of the normal
|
79
|
+
`extralite` gem.
|
67
80
|
|
68
81
|
## Usage
|
69
82
|
|
@@ -71,7 +84,7 @@ You can also run `gem install extralite` if you just want to check it out.
|
|
71
84
|
require 'extralite'
|
72
85
|
|
73
86
|
# get sqlite3 version
|
74
|
-
Extralite.sqlite3_version #=> "3.
|
87
|
+
Extralite.sqlite3_version #=> "3.35.2"
|
75
88
|
|
76
89
|
# open a database
|
77
90
|
db = Extralite::Database.new('/tmp/my.db')
|
@@ -125,6 +138,14 @@ number_of_rows_affected = db.changes
|
|
125
138
|
# get db filename
|
126
139
|
db.filename #=> "/tmp/my.db"
|
127
140
|
|
141
|
+
# get list of tables
|
142
|
+
db.tables #=> ['foo', 'bar']
|
143
|
+
|
144
|
+
# get and set pragmas
|
145
|
+
db.pragma(:journal_mode) #=> 'delete'
|
146
|
+
db.pragma(journal_mode: 'wal')
|
147
|
+
db.pragma(:journal_mode) #=> 'wal'
|
148
|
+
|
128
149
|
# load an extension
|
129
150
|
db.load_extension('/path/to/extension.so')
|
130
151
|
|
@@ -164,7 +185,7 @@ Here's a table summarizing the differences between the two gems:
|
|
164
185
|
|
165
186
|
| |sqlite3-ruby|Extralite|
|
166
187
|
|-|-|-|
|
167
|
-
|SQLite3 dependency|depends on OS-installed libsqlite3|
|
188
|
+
|SQLite3 dependency|depends on OS-installed libsqlite3|Use either system sqlite3 or [bundled latest version of SQLite3](#installing-the-extralite-sqlite3-bundle)|
|
168
189
|
|API design|multiple classes|single class|
|
169
190
|
|Query results|row as hash, row as array, single row, single value|row as hash, row as array, __single column__, single row, single value|
|
170
191
|
|Execute multiple statements|separate API (#execute_batch)|integrated|
|
@@ -225,6 +246,12 @@ As those benchmarks show, Extralite is capabale of reading up to 3M rows/second
|
|
225
246
|
when fetching rows as arrays, and up to 2.6M rows/second when fetching
|
226
247
|
rows as hashes.
|
227
248
|
|
249
|
+
## License
|
250
|
+
|
251
|
+
The source code for Extralite is published under the [MIT license](LICENSE). The
|
252
|
+
source code for SQLite is in the [public
|
253
|
+
domain](https://sqlite.org/copyright.html).
|
254
|
+
|
228
255
|
## Contributing
|
229
256
|
|
230
257
|
Contributions in the form of issues, PRs or comments will be greatly
|
data/Rakefile
CHANGED
@@ -1,6 +1,5 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require 'bundler/gem_tasks'
|
4
3
|
require 'rake/clean'
|
5
4
|
|
6
5
|
require 'rake/extensiontask'
|
@@ -25,3 +24,23 @@ YARD::Rake::YardocTask.new do |t|
|
|
25
24
|
t.files = YARD_FILES
|
26
25
|
t.options = %w(-o doc --readme README.md)
|
27
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/ext/extralite/common.c
CHANGED
@@ -31,7 +31,7 @@ void bind_hash_parameter_values(sqlite3_stmt *stmt, VALUE hash) {
|
|
31
31
|
|
32
32
|
switch (TYPE(k)) {
|
33
33
|
case T_FIXNUM:
|
34
|
-
bind_parameter_value(stmt,
|
34
|
+
bind_parameter_value(stmt, FIX2INT(k), v);
|
35
35
|
break;
|
36
36
|
case T_SYMBOL:
|
37
37
|
k = rb_funcall(k, ID_TO_S, 0);
|
@@ -345,3 +345,7 @@ VALUE safe_query_single_value(query_ctx *ctx) {
|
|
345
345
|
RB_GC_GUARD(value);
|
346
346
|
return value;
|
347
347
|
}
|
348
|
+
|
349
|
+
VALUE safe_query_columns(query_ctx *ctx) {
|
350
|
+
return get_column_names(ctx->stmt, sqlite3_column_count(ctx->stmt));
|
351
|
+
}
|
data/ext/extralite/database.c
CHANGED
@@ -263,6 +263,15 @@ VALUE Database_query_single_value(int argc, VALUE *argv, VALUE self) {
|
|
263
263
|
return Database_perform_query(argc, argv, self, safe_query_single_value);
|
264
264
|
}
|
265
265
|
|
266
|
+
/* call-seq:
|
267
|
+
* db.columns(sql) -> columns
|
268
|
+
*
|
269
|
+
* Returns the column names for the given query, without running it.
|
270
|
+
*/
|
271
|
+
VALUE Database_columns(VALUE self, VALUE sql) {
|
272
|
+
return Database_perform_query(1, &sql, self, safe_query_columns);
|
273
|
+
}
|
274
|
+
|
266
275
|
/* call-seq:
|
267
276
|
* db.last_insert_rowid -> int
|
268
277
|
*
|
@@ -272,7 +281,7 @@ VALUE Database_last_insert_rowid(VALUE self) {
|
|
272
281
|
Database_t *db;
|
273
282
|
GetOpenDatabase(self, db);
|
274
283
|
|
275
|
-
return
|
284
|
+
return INT2FIX(sqlite3_last_insert_rowid(db->sqlite3_db));
|
276
285
|
}
|
277
286
|
|
278
287
|
/* call-seq:
|
@@ -284,7 +293,7 @@ VALUE Database_changes(VALUE self) {
|
|
284
293
|
Database_t *db;
|
285
294
|
GetOpenDatabase(self, db);
|
286
295
|
|
287
|
-
return
|
296
|
+
return INT2FIX(sqlite3_changes(db->sqlite3_db));
|
288
297
|
}
|
289
298
|
|
290
299
|
/* call-seq:
|
@@ -362,6 +371,7 @@ void Init_ExtraliteDatabase() {
|
|
362
371
|
rb_define_method(cDatabase, "query_single_row", Database_query_single_row, -1);
|
363
372
|
rb_define_method(cDatabase, "query_single_column", Database_query_single_column, -1);
|
364
373
|
rb_define_method(cDatabase, "query_single_value", Database_query_single_value, -1);
|
374
|
+
rb_define_method(cDatabase, "columns", Database_columns, 1);
|
365
375
|
|
366
376
|
rb_define_method(cDatabase, "last_insert_rowid", Database_last_insert_rowid, 0);
|
367
377
|
rb_define_method(cDatabase, "changes", Database_changes, 0);
|
data/ext/extralite/extconf.rb
CHANGED
@@ -1,9 +1,115 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
# require 'rubygems'
|
4
|
+
# require 'mkmf'
|
5
|
+
|
6
|
+
# # $CFLAGS << "-Wdiscarded-qualifier"
|
7
|
+
# # $CFLAGS << " -Wno-comment"
|
8
|
+
# # $CFLAGS << " -Wno-unused-result"
|
9
|
+
# # $CFLAGS << " -Wno-dangling-else"
|
10
|
+
# # $CFLAGS << " -Wno-parentheses"
|
11
|
+
|
12
|
+
# dir_config 'extralite_ext'
|
13
|
+
# create_makefile 'extralite_ext'
|
14
|
+
|
15
|
+
ENV['RC_ARCHS'] = '' if RUBY_PLATFORM =~ /darwin/
|
16
|
+
|
3
17
|
require 'mkmf'
|
4
18
|
|
5
|
-
|
6
|
-
|
19
|
+
# :stopdoc:
|
20
|
+
|
21
|
+
RbConfig::MAKEFILE_CONFIG['CC'] = ENV['CC'] if ENV['CC']
|
22
|
+
|
23
|
+
ldflags = cppflags = nil
|
24
|
+
if RbConfig::CONFIG["host_os"] =~ /darwin/
|
25
|
+
begin
|
26
|
+
if with_config('sqlcipher')
|
27
|
+
brew_prefix = `brew --prefix sqlcipher`.chomp
|
28
|
+
ldflags = "#{brew_prefix}/lib"
|
29
|
+
cppflags = "#{brew_prefix}/include/sqlcipher"
|
30
|
+
pkg_conf = "#{brew_prefix}/lib/pkgconfig"
|
31
|
+
else
|
32
|
+
brew_prefix = `brew --prefix sqlite3`.chomp
|
33
|
+
ldflags = "#{brew_prefix}/lib"
|
34
|
+
cppflags = "#{brew_prefix}/include"
|
35
|
+
pkg_conf = "#{brew_prefix}/lib/pkgconfig"
|
36
|
+
end
|
37
|
+
|
38
|
+
# pkg_config should be less error prone than parsing compiler
|
39
|
+
# commandline options, but we need to set default ldflags and cpp flags
|
40
|
+
# in case the user doesn't have pkg-config installed
|
41
|
+
ENV['PKG_CONFIG_PATH'] ||= pkg_conf
|
42
|
+
rescue
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
if with_config('sqlcipher')
|
47
|
+
pkg_config("sqlcipher")
|
48
|
+
else
|
49
|
+
pkg_config("sqlite3")
|
50
|
+
end
|
51
|
+
|
52
|
+
# --with-sqlite3-{dir,include,lib}
|
53
|
+
if with_config('sqlcipher')
|
54
|
+
$CFLAGS << ' -DUSING_SQLCIPHER'
|
55
|
+
dir_config("sqlcipher", cppflags, ldflags)
|
56
|
+
else
|
57
|
+
dir_config("sqlite3", cppflags, ldflags)
|
58
|
+
end
|
59
|
+
|
60
|
+
if RbConfig::CONFIG["host_os"] =~ /mswin/
|
61
|
+
$CFLAGS << ' -W3'
|
62
|
+
end
|
63
|
+
|
64
|
+
if RUBY_VERSION < '2.7'
|
65
|
+
$CFLAGS << ' -DTAINTING_SUPPORT'
|
66
|
+
end
|
67
|
+
|
68
|
+
def asplode missing
|
69
|
+
if RUBY_PLATFORM =~ /mingw|mswin/
|
70
|
+
abort "#{missing} is missing. Install SQLite3 from " +
|
71
|
+
"http://www.sqlite.org/ first."
|
72
|
+
else
|
73
|
+
abort <<-error
|
74
|
+
#{missing} is missing. Try 'brew install sqlite3',
|
75
|
+
'yum install sqlite-devel' or 'apt-get install libsqlite3-dev'
|
76
|
+
and check your shared library search path (the
|
77
|
+
location where your sqlite3 shared library is located).
|
78
|
+
error
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
asplode('sqlite3.h') unless find_header 'sqlite3.h'
|
83
|
+
find_library 'pthread', 'pthread_create' # 1.8 support. *shrug*
|
84
|
+
|
85
|
+
have_library 'dl' # for static builds
|
86
|
+
|
87
|
+
if with_config('sqlcipher')
|
88
|
+
asplode('sqlcipher') unless find_library 'sqlcipher', 'sqlite3_libversion_number'
|
89
|
+
else
|
90
|
+
asplode('sqlite3') unless find_library 'sqlite3', 'sqlite3_libversion_number'
|
91
|
+
end
|
92
|
+
|
93
|
+
# Functions defined in 1.9 but not 1.8
|
94
|
+
have_func('rb_proc_arity')
|
95
|
+
|
96
|
+
# Functions defined in 2.1 but not 2.0
|
97
|
+
have_func('rb_integer_pack')
|
98
|
+
|
99
|
+
# These functions may not be defined
|
100
|
+
have_func('sqlite3_initialize')
|
101
|
+
have_func('sqlite3_enable_load_extension')
|
102
|
+
have_func('sqlite3_load_extension')
|
103
|
+
|
104
|
+
unless have_func('sqlite3_open_v2')
|
105
|
+
abort "Please use a newer version of SQLite3"
|
106
|
+
end
|
107
|
+
|
108
|
+
have_func('sqlite3_prepare_v2')
|
109
|
+
have_type('sqlite3_int64', 'sqlite3.h')
|
110
|
+
have_type('sqlite3_uint64', 'sqlite3.h')
|
111
|
+
|
112
|
+
$defs << "-DEXTRALITE_NO_BUNDLE"
|
7
113
|
|
8
114
|
dir_config('extralite_ext')
|
9
115
|
create_makefile('extralite_ext')
|
data/ext/extralite/extralite.h
CHANGED
@@ -3,7 +3,12 @@
|
|
3
3
|
|
4
4
|
#include "ruby.h"
|
5
5
|
#include "ruby/thread.h"
|
6
|
+
|
7
|
+
#ifdef EXTRALITE_NO_BUNDLE
|
6
8
|
#include <sqlite3.h>
|
9
|
+
#else
|
10
|
+
#include "../sqlite3/sqlite3.h"
|
11
|
+
#endif
|
7
12
|
|
8
13
|
// debug utility
|
9
14
|
#define INSPECT(str, obj) { \
|
@@ -48,6 +53,7 @@ VALUE safe_query_hash(query_ctx *ctx);
|
|
48
53
|
VALUE safe_query_single_column(query_ctx *ctx);
|
49
54
|
VALUE safe_query_single_row(query_ctx *ctx);
|
50
55
|
VALUE safe_query_single_value(query_ctx *ctx);
|
56
|
+
VALUE safe_query_columns(query_ctx *ctx);
|
51
57
|
|
52
58
|
void prepare_single_stmt(sqlite3 *db, sqlite3_stmt **stmt, VALUE sql);
|
53
59
|
void prepare_multi_stmt(sqlite3 *db, sqlite3_stmt **stmt, VALUE sql);
|
@@ -63,6 +63,9 @@ static inline VALUE PreparedStatement_perform_query(int argc, VALUE *argv, VALUE
|
|
63
63
|
PreparedStatement_t *stmt;
|
64
64
|
GetPreparedStatement(self, stmt);
|
65
65
|
|
66
|
+
if (!stmt->stmt)
|
67
|
+
rb_raise(cError, "Prepared statement is closed");
|
68
|
+
|
66
69
|
sqlite3_reset(stmt->stmt);
|
67
70
|
sqlite3_clear_bindings(stmt->stmt);
|
68
71
|
bind_all_parameters(stmt->stmt, argc, argv);
|
@@ -218,6 +221,43 @@ VALUE PreparedStatement_sql(VALUE self) {
|
|
218
221
|
return stmt->sql;
|
219
222
|
}
|
220
223
|
|
224
|
+
/* call-seq:
|
225
|
+
* stmt.columns -> columns
|
226
|
+
*
|
227
|
+
* Returns the column names for the prepared statement without running it.
|
228
|
+
*/
|
229
|
+
VALUE PreparedStatement_columns(VALUE self) {
|
230
|
+
return PreparedStatement_perform_query(0, NULL, self, safe_query_columns);
|
231
|
+
}
|
232
|
+
|
233
|
+
/* call-seq:
|
234
|
+
* stmt.close -> stmt
|
235
|
+
*
|
236
|
+
* Closes the prepared statement. Running a closed prepared statement will raise
|
237
|
+
* an error.
|
238
|
+
*/
|
239
|
+
VALUE PreparedStatement_close(VALUE self) {
|
240
|
+
PreparedStatement_t *stmt;
|
241
|
+
GetPreparedStatement(self, stmt);
|
242
|
+
if (stmt->stmt) {
|
243
|
+
sqlite3_finalize(stmt->stmt);
|
244
|
+
stmt->stmt = NULL;
|
245
|
+
}
|
246
|
+
return self;
|
247
|
+
}
|
248
|
+
|
249
|
+
/* call-seq:
|
250
|
+
* stmt.closed? -> closed
|
251
|
+
*
|
252
|
+
* Returns true if the prepared statement is closed.
|
253
|
+
*/
|
254
|
+
VALUE PreparedStatement_closed_p(VALUE self) {
|
255
|
+
PreparedStatement_t *stmt;
|
256
|
+
GetPreparedStatement(self, stmt);
|
257
|
+
|
258
|
+
return stmt->stmt ? Qfalse : Qtrue;
|
259
|
+
}
|
260
|
+
|
221
261
|
void Init_ExtralitePreparedStatement() {
|
222
262
|
VALUE mExtralite = rb_define_module("Extralite");
|
223
263
|
|
@@ -235,4 +275,9 @@ void Init_ExtralitePreparedStatement() {
|
|
235
275
|
rb_define_method(cPreparedStatement, "query_single_row", PreparedStatement_query_single_row, -1);
|
236
276
|
rb_define_method(cPreparedStatement, "query_single_column", PreparedStatement_query_single_column, -1);
|
237
277
|
rb_define_method(cPreparedStatement, "query_single_value", PreparedStatement_query_single_value, -1);
|
278
|
+
|
279
|
+
rb_define_method(cPreparedStatement, "columns", PreparedStatement_columns, 0);
|
280
|
+
|
281
|
+
rb_define_method(cPreparedStatement, "close", PreparedStatement_close, 0);
|
282
|
+
rb_define_method(cPreparedStatement, "closed?", PreparedStatement_closed_p, 0);
|
238
283
|
}
|
File without changes
|
File without changes
|
data/extralite.gemspec
CHANGED
@@ -1,30 +1,8 @@
|
|
1
|
-
require_relative './
|
1
|
+
require_relative './gemspec'
|
2
2
|
|
3
3
|
Gem::Specification.new do |s|
|
4
|
+
common_spec(s)
|
4
5
|
s.name = 'extralite'
|
5
|
-
s.version = Extralite::VERSION
|
6
|
-
s.licenses = ['MIT']
|
7
6
|
s.summary = 'Extra-lightweight SQLite3 wrapper for Ruby'
|
8
|
-
s.
|
9
|
-
s.email = 'sharon@noteflakes.com'
|
10
|
-
s.files = `git ls-files`.split
|
11
|
-
s.homepage = 'https://github.com/digital-fabric/extralite'
|
12
|
-
s.metadata = {
|
13
|
-
"source_code_uri" => "https://github.com/digital-fabric/extralite",
|
14
|
-
"documentation_uri" => "https://www.rubydoc.info/gems/extralite",
|
15
|
-
"homepage_uri" => "https://github.com/digital-fabric/extralite",
|
16
|
-
"changelog_uri" => "https://github.com/digital-fabric/extralite/blob/master/CHANGELOG.md"
|
17
|
-
}
|
18
|
-
s.rdoc_options = ["--title", "extralite", "--main", "README.md"]
|
19
|
-
s.extra_rdoc_files = ["README.md"]
|
20
|
-
s.extensions = ["ext/extralite/extconf.rb"]
|
21
|
-
s.require_paths = ["lib"]
|
22
|
-
s.required_ruby_version = '>= 2.7'
|
23
|
-
|
24
|
-
s.add_development_dependency 'rake-compiler', '1.1.6'
|
25
|
-
s.add_development_dependency 'minitest', '5.15.0'
|
26
|
-
s.add_development_dependency 'simplecov', '0.17.1'
|
27
|
-
s.add_development_dependency 'yard', '0.9.27'
|
28
|
-
|
29
|
-
s.add_development_dependency 'sequel', '5.51.0'
|
7
|
+
s.extensions = ["ext/extralite/extconf.rb"]
|
30
8
|
end
|
data/gemspec.rb
ADDED
@@ -0,0 +1,26 @@
|
|
1
|
+
require_relative './lib/extralite/version'
|
2
|
+
|
3
|
+
def common_spec(s)
|
4
|
+
s.version = Extralite::VERSION
|
5
|
+
s.licenses = ['MIT']
|
6
|
+
s.author = 'Sharon Rosner'
|
7
|
+
s.email = 'sharon@noteflakes.com'
|
8
|
+
s.files = `git ls-files`.split
|
9
|
+
s.homepage = 'https://github.com/digital-fabric/extralite'
|
10
|
+
s.metadata = {
|
11
|
+
"source_code_uri" => "https://github.com/digital-fabric/extralite",
|
12
|
+
"documentation_uri" => "https://www.rubydoc.info/gems/extralite",
|
13
|
+
"homepage_uri" => "https://github.com/digital-fabric/extralite",
|
14
|
+
"changelog_uri" => "https://github.com/digital-fabric/extralite/blob/master/CHANGELOG.md"
|
15
|
+
}
|
16
|
+
s.rdoc_options = ["--title", "extralite", "--main", "README.md"]
|
17
|
+
s.extra_rdoc_files = ["README.md"]
|
18
|
+
s.require_paths = ["lib"]
|
19
|
+
s.required_ruby_version = '>= 2.7'
|
20
|
+
|
21
|
+
s.add_development_dependency 'rake-compiler', '1.1.6'
|
22
|
+
s.add_development_dependency 'minitest', '5.15.0'
|
23
|
+
s.add_development_dependency 'simplecov', '0.17.1'
|
24
|
+
s.add_development_dependency 'yard', '0.9.27'
|
25
|
+
s.add_development_dependency 'sequel', '5.51.0'
|
26
|
+
end
|
data/lib/extralite/version.rb
CHANGED
data/lib/extralite.rb
CHANGED
@@ -17,5 +17,29 @@ module Extralite
|
|
17
17
|
|
18
18
|
# An SQLite database
|
19
19
|
class Database
|
20
|
+
alias_method :execute, :query
|
21
|
+
|
22
|
+
TABLES_SQL = <<~SQL
|
23
|
+
SELECT name FROM sqlite_schema
|
24
|
+
WHERE type ='table'
|
25
|
+
AND name NOT LIKE 'sqlite_%';
|
26
|
+
SQL
|
27
|
+
|
28
|
+
def tables
|
29
|
+
query_single_column(TABLES_SQL)
|
30
|
+
end
|
31
|
+
|
32
|
+
def pragma(value)
|
33
|
+
value.is_a?(Hash) ? pragma_set(value) : pragma_get(value)
|
34
|
+
end
|
35
|
+
|
36
|
+
def pragma_set(values)
|
37
|
+
sql = values.inject(+'') { |s, (k, v)| s += "pragma #{k}=#{v}; " }
|
38
|
+
query(sql)
|
39
|
+
end
|
40
|
+
|
41
|
+
def pragma_get(key)
|
42
|
+
query_single_value("pragma #{key}")
|
43
|
+
end
|
20
44
|
end
|
21
|
-
end
|
45
|
+
end
|
@@ -122,17 +122,17 @@ module Sequel
|
|
122
122
|
|
123
123
|
connection_pragmas.each{|s| log_connection_yield(s, db){db.query(s)}}
|
124
124
|
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
125
|
+
class << db
|
126
|
+
attr_reader :prepared_statements
|
127
|
+
end
|
128
|
+
db.instance_variable_set(:@prepared_statements, {})
|
129
129
|
|
130
130
|
db
|
131
131
|
end
|
132
132
|
|
133
133
|
# Disconnect given connections from the database.
|
134
134
|
def disconnect_connection(c)
|
135
|
-
|
135
|
+
c.prepared_statements.each_value{|v| v.first.close }
|
136
136
|
c.close
|
137
137
|
end
|
138
138
|
|
@@ -149,13 +149,13 @@ module Sequel
|
|
149
149
|
# Drop any prepared statements on the connection when executing DDL. This is because
|
150
150
|
# prepared statements lock the table in such a way that you can't drop or alter the
|
151
151
|
# table while a prepared statement that references it still exists.
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
152
|
+
def execute_ddl(sql, opts=OPTS)
|
153
|
+
synchronize(opts[:server]) do |conn|
|
154
|
+
conn.prepared_statements.values.each{|cps, s| cps.close}
|
155
|
+
conn.prepared_statements.clear
|
156
|
+
super
|
157
|
+
end
|
158
|
+
end
|
159
159
|
|
160
160
|
def execute_insert(sql, opts=OPTS)
|
161
161
|
_execute(:insert, sql, opts)
|
@@ -193,7 +193,7 @@ module Sequel
|
|
193
193
|
def _execute(type, sql, opts, &block)
|
194
194
|
begin
|
195
195
|
synchronize(opts[:server]) do |conn|
|
196
|
-
|
196
|
+
return execute_prepared_statement(conn, type, sql, opts, &block) if sql.is_a?(Symbol)
|
197
197
|
log_args = opts[:arguments]
|
198
198
|
args = {}
|
199
199
|
opts.fetch(:arguments, OPTS).each{|k, v| args[k] = prepared_statement_argument(v) }
|
data/test/helper.rb
CHANGED
data/test/test_database.rb
CHANGED
@@ -68,6 +68,11 @@ end
|
|
68
68
|
assert_nil r
|
69
69
|
end
|
70
70
|
|
71
|
+
def test_columns
|
72
|
+
r = @db.columns('select x, z from t')
|
73
|
+
assert_equal [:x, :z], r
|
74
|
+
end
|
75
|
+
|
71
76
|
def test_transaction_active?
|
72
77
|
assert_equal false, @db.transaction_active?
|
73
78
|
@db.query('begin')
|
@@ -177,6 +182,31 @@ end
|
|
177
182
|
r = @db.query_single_value("select reverse('abcd')")
|
178
183
|
assert_equal 'dcba', r
|
179
184
|
end
|
185
|
+
|
186
|
+
def test_tables
|
187
|
+
assert_equal ['t'], @db.tables
|
188
|
+
|
189
|
+
@db.query('create table foo (bar text)')
|
190
|
+
assert_equal ['t', 'foo'], @db.tables
|
191
|
+
|
192
|
+
@db.query('drop table t')
|
193
|
+
assert_equal ['foo'], @db.tables
|
194
|
+
|
195
|
+
@db.query('drop table foo')
|
196
|
+
assert_equal [], @db.tables
|
197
|
+
end
|
198
|
+
|
199
|
+
def test_pragma
|
200
|
+
assert_equal 'memory', @db.pragma('journal_mode')
|
201
|
+
assert_equal 2, @db.pragma('synchronous')
|
202
|
+
|
203
|
+
assert_equal 1, @db.pragma(:schema_version)
|
204
|
+
assert_equal 0, @db.pragma(:recursive_triggers)
|
205
|
+
|
206
|
+
assert_equal [], @db.pragma(schema_version: 33, recursive_triggers: 1)
|
207
|
+
assert_equal 33, @db.pragma(:schema_version)
|
208
|
+
assert_equal 1, @db.pragma(:recursive_triggers)
|
209
|
+
end
|
180
210
|
end
|
181
211
|
|
182
212
|
class ScenarioTest < MiniTest::Test
|
data/test/test_extralite.rb
CHANGED
@@ -3,12 +3,7 @@
|
|
3
3
|
require_relative 'helper'
|
4
4
|
|
5
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
6
|
def test_sqlite3_version
|
10
|
-
|
11
|
-
|
12
|
-
assert_equal version, Extralite.sqlite3_version
|
7
|
+
assert_match /^3\.\d+\.\d+$/, Extralite.sqlite3_version
|
13
8
|
end
|
14
9
|
end
|
@@ -162,4 +162,23 @@ end
|
|
162
162
|
r = @db.prepare('select null').query_single_value
|
163
163
|
assert_nil r
|
164
164
|
end
|
165
|
+
|
166
|
+
def test_prepared_statement_columns
|
167
|
+
r = @db.prepare("select 'abc' as a, 'def' as b").columns
|
168
|
+
assert_equal [:a, :b], r
|
169
|
+
end
|
170
|
+
|
171
|
+
def test_prepared_statement_close
|
172
|
+
p = @db.prepare("select 'abc'")
|
173
|
+
|
174
|
+
assert_equal false, p.closed?
|
175
|
+
|
176
|
+
p.close
|
177
|
+
assert_equal true, p.closed?
|
178
|
+
|
179
|
+
p.close
|
180
|
+
assert_equal true, p.closed?
|
181
|
+
|
182
|
+
assert_raises { p.query_single_value }
|
183
|
+
end
|
165
184
|
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.
|
4
|
+
version: '1.15'
|
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: 2022-
|
11
|
+
date: 2022-10-03 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:
|
@@ -101,13 +101,17 @@ files:
|
|
101
101
|
- bin/update_sqlite_source
|
102
102
|
- ext/extralite/common.c
|
103
103
|
- ext/extralite/database.c
|
104
|
+
- ext/extralite/extconf-bundle.rb
|
104
105
|
- ext/extralite/extconf.rb
|
105
106
|
- ext/extralite/extralite.h
|
106
107
|
- ext/extralite/extralite_ext.c
|
108
|
+
- ext/extralite/extralite_sqlite3.c
|
107
109
|
- ext/extralite/prepared_statement.c
|
108
|
-
- ext/
|
109
|
-
- ext/
|
110
|
+
- ext/sqlite3/sqlite3.c
|
111
|
+
- ext/sqlite3/sqlite3.h
|
112
|
+
- extralite-bundle.gemspec
|
110
113
|
- extralite.gemspec
|
114
|
+
- gemspec.rb
|
111
115
|
- lib/extralite.rb
|
112
116
|
- lib/extralite/version.rb
|
113
117
|
- lib/sequel/adapters/extralite.rb
|
@@ -130,7 +134,7 @@ metadata:
|
|
130
134
|
documentation_uri: https://www.rubydoc.info/gems/extralite
|
131
135
|
homepage_uri: https://github.com/digital-fabric/extralite
|
132
136
|
changelog_uri: https://github.com/digital-fabric/extralite/blob/master/CHANGELOG.md
|
133
|
-
post_install_message:
|
137
|
+
post_install_message:
|
134
138
|
rdoc_options:
|
135
139
|
- "--title"
|
136
140
|
- extralite
|
@@ -149,8 +153,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
149
153
|
- !ruby/object:Gem::Version
|
150
154
|
version: '0'
|
151
155
|
requirements: []
|
152
|
-
rubygems_version: 3.3.
|
153
|
-
signing_key:
|
156
|
+
rubygems_version: 3.3.7
|
157
|
+
signing_key:
|
154
158
|
specification_version: 4
|
155
159
|
summary: Extra-lightweight SQLite3 wrapper for Ruby
|
156
160
|
test_files: []
|