extralite 1.13.1 → 1.15
Sign up to get free protection for your applications and to get access to all the features.
- 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: []
|