extralite 2.8.2 → 2.10
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 +4 -4
- data/CHANGELOG.md +11 -1
- data/README.md +1 -1
- data/ext/extralite/common.c +61 -19
- data/gemspec.rb +5 -5
- data/lib/extralite/version.rb +1 -1
- data/test/test_database.rb +48 -1
- metadata +13 -17
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: a7adc40dd1b275c571a25ff887b4d7a82e25c0a562b878cfd9f8988828d105ce
|
4
|
+
data.tar.gz: c7dea7923b4c861a8aefe839c2395ec12fc84715514006e7961e96a728921861
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: e4113425b3651e5875f44085691ce4e7bc7186391bf968d0882de07196908415c73af58add1367bad4a992ed6c3c30c2dd0ae115b56071a7ef20287febe35a6f
|
7
|
+
data.tar.gz: a4ab94ee82dddf6ed6c0edcb0127b7213101a41606a2995343d50fb14998bd5f84f01b9ad5c6c03a45e8b50fa189951d5bdd7097ac3392a389cde9e32ec3fb19
|
data/.github/workflows/test.yml
CHANGED
@@ -11,9 +11,8 @@ jobs:
|
|
11
11
|
strategy:
|
12
12
|
fail-fast: false
|
13
13
|
matrix:
|
14
|
-
|
15
|
-
|
16
|
-
ruby: ['3.0', '3.1', '3.2', '3.3', 'head']
|
14
|
+
os: [ubuntu-latest, macos-latest]
|
15
|
+
ruby: ['3.2', '3.3', '3.4', 'head']
|
17
16
|
|
18
17
|
name: ${{matrix.os}}, ${{matrix.ruby}}
|
19
18
|
|
@@ -25,7 +24,8 @@ jobs:
|
|
25
24
|
- uses: ruby/setup-ruby@v1
|
26
25
|
with:
|
27
26
|
ruby-version: ${{matrix.ruby}}
|
28
|
-
bundler-cache: true
|
27
|
+
bundler-cache: true
|
28
|
+
apt-get: libsqlite3-dev
|
29
29
|
- name: Compile C-extension
|
30
30
|
run: bundle exec rake compile
|
31
31
|
- name: Run tests
|
data/CHANGELOG.md
CHANGED
@@ -1,6 +1,16 @@
|
|
1
|
+
## 2.10 2025-02-17
|
2
|
+
|
3
|
+
- Update bundled SQLite to version 3.49.0.
|
4
|
+
|
5
|
+
## 2.9 2025-01-18
|
6
|
+
|
7
|
+
- Update dependencies, test matrix.
|
8
|
+
- Update bundled SQLite to version 3.48.0.
|
9
|
+
- Optimize getting column names when returning rows as hashes.
|
10
|
+
|
1
11
|
## 2.8.2 2024-06-02
|
2
12
|
|
3
|
-
- Update bundled SQLite to version 3.46.0
|
13
|
+
- Update bundled SQLite to version 3.46.0. [#74](https://github.com/digital-fabric/extralite/pull/74)
|
4
14
|
|
5
15
|
## 2.8.1 2024-04-15
|
6
16
|
|
data/README.md
CHANGED
@@ -32,7 +32,7 @@ databases.
|
|
32
32
|
Extralite comes in two flavors: the `extralite` gem which uses the
|
33
33
|
system-installed sqlite3 library, and the `extralite-bundle` gem which bundles
|
34
34
|
the latest version of SQLite
|
35
|
-
([3.
|
35
|
+
([3.49.0](https://sqlite.org/releaselog/3_49_0.html)), offering access to the
|
36
36
|
latest features and enhancements.
|
37
37
|
|
38
38
|
## Features
|
data/ext/extralite/common.c
CHANGED
@@ -135,7 +135,44 @@ inline void bind_all_parameters_from_object(sqlite3_stmt *stmt, VALUE obj) {
|
|
135
135
|
bind_parameter_value(stmt, 1, obj);
|
136
136
|
}
|
137
137
|
|
138
|
-
|
138
|
+
#define MAX_EMBEDDED_COLUMN_NAMES 12
|
139
|
+
|
140
|
+
struct column_names {
|
141
|
+
int count;
|
142
|
+
union {
|
143
|
+
VALUE array;
|
144
|
+
VALUE names[MAX_EMBEDDED_COLUMN_NAMES];
|
145
|
+
};
|
146
|
+
};
|
147
|
+
|
148
|
+
static inline void column_names_setup(struct column_names *names, int count) {
|
149
|
+
names->count = count;
|
150
|
+
names->array = (count > MAX_EMBEDDED_COLUMN_NAMES) ? rb_ary_new2(count) : Qnil;
|
151
|
+
}
|
152
|
+
|
153
|
+
static inline void column_names_set(struct column_names *names, int idx, VALUE value) {
|
154
|
+
if (names->count <= MAX_EMBEDDED_COLUMN_NAMES)
|
155
|
+
names->names[idx] = value;
|
156
|
+
else
|
157
|
+
rb_ary_push(names->array, value);
|
158
|
+
}
|
159
|
+
|
160
|
+
static inline VALUE column_names_get(struct column_names *names, int idx) {
|
161
|
+
return (names->count <= MAX_EMBEDDED_COLUMN_NAMES) ?
|
162
|
+
names->names[idx] : RARRAY_AREF(names->array, idx);
|
163
|
+
}
|
164
|
+
|
165
|
+
static inline struct column_names get_column_names(sqlite3_stmt *stmt, int column_count) {
|
166
|
+
struct column_names names;
|
167
|
+
column_names_setup(&names, column_count);
|
168
|
+
for (int i = 0; i < column_count; i++) {
|
169
|
+
VALUE name = ID2SYM(rb_intern(sqlite3_column_name(stmt, i)));
|
170
|
+
column_names_set(&names, i, name);
|
171
|
+
}
|
172
|
+
return names;
|
173
|
+
}
|
174
|
+
|
175
|
+
static inline VALUE get_column_names_array(sqlite3_stmt *stmt, int column_count) {
|
139
176
|
VALUE arr = rb_ary_new2(column_count);
|
140
177
|
for (int i = 0; i < column_count; i++) {
|
141
178
|
VALUE name = ID2SYM(rb_intern(sqlite3_column_name(stmt, i)));
|
@@ -144,11 +181,19 @@ static inline VALUE get_column_names(sqlite3_stmt *stmt, int column_count) {
|
|
144
181
|
return arr;
|
145
182
|
}
|
146
183
|
|
147
|
-
static inline VALUE row_to_hash(sqlite3_stmt *stmt, int column_count,
|
184
|
+
static inline VALUE row_to_hash(sqlite3_stmt *stmt, int column_count, struct column_names *names) {
|
148
185
|
VALUE row = rb_hash_new();
|
149
|
-
|
150
|
-
|
151
|
-
|
186
|
+
if (names->count <= MAX_EMBEDDED_COLUMN_NAMES) {
|
187
|
+
for (int i = 0; i < column_count; i++) {
|
188
|
+
VALUE value = get_column_value(stmt, i, sqlite3_column_type(stmt, i));
|
189
|
+
rb_hash_aset(row, names->names[i], value);
|
190
|
+
}
|
191
|
+
}
|
192
|
+
else {
|
193
|
+
for (int i = 0; i < column_count; i++) {
|
194
|
+
VALUE value = get_column_value(stmt, i, sqlite3_column_type(stmt, i));
|
195
|
+
rb_hash_aset(row, RARRAY_AREF(names->array, i), value);
|
196
|
+
}
|
152
197
|
}
|
153
198
|
return row;
|
154
199
|
}
|
@@ -327,12 +372,12 @@ VALUE safe_query_hash(query_ctx *ctx) {
|
|
327
372
|
VALUE array = ROW_MULTI_P(ctx->row_mode) ? rb_ary_new() : Qnil;
|
328
373
|
VALUE row = Qnil;
|
329
374
|
int column_count = sqlite3_column_count(ctx->stmt);
|
330
|
-
|
375
|
+
struct column_names names = get_column_names(ctx->stmt, column_count);
|
331
376
|
int row_count = 0;
|
332
377
|
int do_transform = !NIL_P(ctx->transform_proc);
|
333
378
|
|
334
379
|
while (stmt_iterate(ctx)) {
|
335
|
-
row = row_to_hash(ctx->stmt, column_count,
|
380
|
+
row = row_to_hash(ctx->stmt, column_count, &names);
|
336
381
|
if (do_transform)
|
337
382
|
row = rb_funcall(ctx->transform_proc, ID_call, 1, row);
|
338
383
|
row_count++;
|
@@ -350,7 +395,7 @@ VALUE safe_query_hash(query_ctx *ctx) {
|
|
350
395
|
return ROW_MULTI_P(ctx->row_mode) ? array : ctx->self;
|
351
396
|
}
|
352
397
|
|
353
|
-
RB_GC_GUARD(
|
398
|
+
RB_GC_GUARD(names.array);
|
354
399
|
RB_GC_GUARD(row);
|
355
400
|
RB_GC_GUARD(array);
|
356
401
|
return ROW_MULTI_P(ctx->row_mode) ? array : Qnil;
|
@@ -445,21 +490,18 @@ VALUE safe_query_array(query_ctx *ctx) {
|
|
445
490
|
}
|
446
491
|
|
447
492
|
VALUE safe_query_single_row_hash(query_ctx *ctx) {
|
448
|
-
int column_count;
|
493
|
+
int column_count = sqlite3_column_count(ctx->stmt);
|
449
494
|
VALUE row = Qnil;
|
450
|
-
|
451
|
-
|
452
|
-
column_count = sqlite3_column_count(ctx->stmt);
|
453
|
-
column_names = get_column_names(ctx->stmt, column_count);
|
495
|
+
struct column_names names = get_column_names(ctx->stmt, column_count);
|
454
496
|
|
455
497
|
if (stmt_iterate(ctx)) {
|
456
|
-
row = row_to_hash(ctx->stmt, column_count,
|
498
|
+
row = row_to_hash(ctx->stmt, column_count, &names);
|
457
499
|
if (!NIL_P(ctx->transform_proc))
|
458
500
|
row = rb_funcall(ctx->transform_proc, ID_call, 1, row);
|
459
501
|
}
|
460
502
|
|
461
503
|
RB_GC_GUARD(row);
|
462
|
-
RB_GC_GUARD(
|
504
|
+
RB_GC_GUARD(names.array);
|
463
505
|
return row;
|
464
506
|
}
|
465
507
|
|
@@ -506,17 +548,17 @@ static inline VALUE batch_iterate_hash(query_ctx *ctx) {
|
|
506
548
|
VALUE rows = rb_ary_new();
|
507
549
|
VALUE row = Qnil;
|
508
550
|
int column_count = sqlite3_column_count(ctx->stmt);
|
509
|
-
|
551
|
+
struct column_names names = get_column_names(ctx->stmt, column_count);
|
510
552
|
const int do_transform = !NIL_P(ctx->transform_proc);
|
511
553
|
|
512
554
|
while (stmt_iterate(ctx)) {
|
513
|
-
row = row_to_hash(ctx->stmt, column_count,
|
555
|
+
row = row_to_hash(ctx->stmt, column_count, &names);
|
514
556
|
if (do_transform)
|
515
557
|
row = rb_funcall(ctx->transform_proc, ID_call, 1, row);
|
516
558
|
rb_ary_push(rows, row);
|
517
559
|
}
|
518
560
|
|
519
|
-
RB_GC_GUARD(
|
561
|
+
RB_GC_GUARD(names.array);
|
520
562
|
RB_GC_GUARD(row);
|
521
563
|
RB_GC_GUARD(rows);
|
522
564
|
return rows;
|
@@ -733,7 +775,7 @@ VALUE safe_batch_query_splat(query_ctx *ctx) {
|
|
733
775
|
}
|
734
776
|
|
735
777
|
VALUE safe_query_columns(query_ctx *ctx) {
|
736
|
-
return
|
778
|
+
return get_column_names_array(ctx->stmt, sqlite3_column_count(ctx->stmt));
|
737
779
|
}
|
738
780
|
|
739
781
|
VALUE safe_query_changes(query_ctx *ctx) {
|
data/gemspec.rb
CHANGED
@@ -17,9 +17,9 @@ def common_spec(s)
|
|
17
17
|
s.require_paths = ['lib']
|
18
18
|
s.required_ruby_version = '>= 3.0'
|
19
19
|
|
20
|
-
s.add_development_dependency 'rake-compiler', '1.2.
|
21
|
-
s.add_development_dependency 'minitest', '5.
|
22
|
-
s.add_development_dependency 'simplecov', '0.
|
23
|
-
s.add_development_dependency 'yard', '0.9.
|
24
|
-
s.add_development_dependency 'sequel', '5.
|
20
|
+
s.add_development_dependency 'rake-compiler', '1.2.9'
|
21
|
+
s.add_development_dependency 'minitest', '5.25.4'
|
22
|
+
s.add_development_dependency 'simplecov', '0.22.0'
|
23
|
+
s.add_development_dependency 'yard', '0.9.37'
|
24
|
+
s.add_development_dependency 'sequel', '5.88.0'
|
25
25
|
end
|
data/lib/extralite/version.rb
CHANGED
data/test/test_database.rb
CHANGED
@@ -40,6 +40,19 @@ class DatabaseTest < Minitest::Test
|
|
40
40
|
assert_equal [], r
|
41
41
|
end
|
42
42
|
|
43
|
+
def test_query_hash_with_many_columns
|
44
|
+
# this tests correct processing cof column names when column count is more than
|
45
|
+
# MAX_EMBEDDED_COLUMN_NAMES
|
46
|
+
r = @db.query_hash("
|
47
|
+
select 1 as a, 2 as b, 3 as c, 4 as d, 5 as e, 6 as f, 7 as g, 8 as h, 9 as i, 10 as j,
|
48
|
+
11 as k, 12 as l, 13 as m, 14 as n, 15 as o, 16 as p, 17 as q, 18 as r, 19 as s, 20 as t
|
49
|
+
")
|
50
|
+
assert_equal [{
|
51
|
+
a: 1, b: 2, c: 3, d: 4, e: 5, f: 6, g: 7, h: 8, i: 9, j: 10,
|
52
|
+
k: 11, l: 12, m: 13, n: 14, o: 15, p: 16, q: 17, r: 18, s: 19, t: 20
|
53
|
+
}], r
|
54
|
+
end
|
55
|
+
|
43
56
|
def test_query_array
|
44
57
|
r = @db.query_array('select * from t')
|
45
58
|
assert_equal [[1, 2, 3], [4, 5, 6]], r
|
@@ -363,7 +376,6 @@ class DatabaseTest < Minitest::Test
|
|
363
376
|
[1, '2', 3],
|
364
377
|
['4', 5, 6]
|
365
378
|
]
|
366
|
-
|
367
379
|
changes = @db.batch_execute('insert into foo values (?, ?, ?)', records)
|
368
380
|
|
369
381
|
assert_equal 2, changes
|
@@ -373,6 +385,23 @@ class DatabaseTest < Minitest::Test
|
|
373
385
|
], @db.query('select * from foo')
|
374
386
|
end
|
375
387
|
|
388
|
+
def test_batch_execute_with_array_of_hashes
|
389
|
+
@db.query('create table foo (a, b, c)')
|
390
|
+
assert_equal [], @db.query('select * from foo')
|
391
|
+
|
392
|
+
records = [
|
393
|
+
{ a: 1, b: '2', c: 3 },
|
394
|
+
{ a: '4', b: 5, c: 6 }
|
395
|
+
]
|
396
|
+
changes = @db.batch_execute('insert into foo values (:a, :b, :c)', records)
|
397
|
+
|
398
|
+
# assert_equal 2, changes
|
399
|
+
assert_equal [
|
400
|
+
{ a: 1, b: '2', c: 3 },
|
401
|
+
{ a: '4', b: 5, c: 6 }
|
402
|
+
], @db.query('select * from foo')
|
403
|
+
end
|
404
|
+
|
376
405
|
def test_batch_execute_single_values
|
377
406
|
@db.query('create table foo (bar)')
|
378
407
|
assert_equal [], @db.query('select * from foo')
|
@@ -1359,6 +1388,12 @@ class ConcurrencyTest < Minitest::Test
|
|
1359
1388
|
def test_progress_handler_simple
|
1360
1389
|
db = Extralite::Database.new(':memory:')
|
1361
1390
|
|
1391
|
+
# SQLite's behaviour post 3.46.0 has changed, such that the first time the
|
1392
|
+
# query is ran, the progress handler is called more times than in later
|
1393
|
+
# invocations, so here we run it once before measuring, in order to have
|
1394
|
+
# reliable figures.
|
1395
|
+
result = db.query_single('select 1 as a, 2 as b, 3 as c')
|
1396
|
+
|
1362
1397
|
buf = []
|
1363
1398
|
db.on_progress(period: 1) { buf << :progress }
|
1364
1399
|
|
@@ -1377,6 +1412,12 @@ class ConcurrencyTest < Minitest::Test
|
|
1377
1412
|
def test_progress_handler_normal_mode
|
1378
1413
|
db = Extralite::Database.new(':memory:')
|
1379
1414
|
|
1415
|
+
# SQLite's behaviour post 3.46.0 has changed, such that the first time the
|
1416
|
+
# query is ran, the progress handler is called more times than in later
|
1417
|
+
# invocations, so here we run it once before measuring, in order to have
|
1418
|
+
# reliable figures.
|
1419
|
+
db.query('select 1 as a')
|
1420
|
+
|
1380
1421
|
count = 0
|
1381
1422
|
db.on_progress(period: 1) { count += 1 }
|
1382
1423
|
db.query('select 1 as a')
|
@@ -1397,6 +1438,12 @@ class ConcurrencyTest < Minitest::Test
|
|
1397
1438
|
def test_progress_handler_at_least_once_mode
|
1398
1439
|
db = Extralite::Database.new(':memory:')
|
1399
1440
|
|
1441
|
+
# SQLite's behaviour post 3.46.0 has changed, such that the first time the
|
1442
|
+
# query is ran, the progress handler is called more times than in later
|
1443
|
+
# invocations, so here we run it once before measuring, in order to have
|
1444
|
+
# reliable figures.
|
1445
|
+
db.query('select 1 as a')
|
1446
|
+
|
1400
1447
|
count = 0
|
1401
1448
|
db.on_progress(period: 1) { count += 1 }
|
1402
1449
|
db.query('select 1 as a')
|
metadata
CHANGED
@@ -1,14 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: extralite
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.
|
4
|
+
version: '2.10'
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Sharon Rosner
|
8
|
-
autorequire:
|
9
8
|
bindir: bin
|
10
9
|
cert_chain: []
|
11
|
-
date:
|
10
|
+
date: 2025-02-17 00:00:00.000000000 Z
|
12
11
|
dependencies:
|
13
12
|
- !ruby/object:Gem::Dependency
|
14
13
|
name: rake-compiler
|
@@ -16,71 +15,70 @@ dependencies:
|
|
16
15
|
requirements:
|
17
16
|
- - '='
|
18
17
|
- !ruby/object:Gem::Version
|
19
|
-
version: 1.2.
|
18
|
+
version: 1.2.9
|
20
19
|
type: :development
|
21
20
|
prerelease: false
|
22
21
|
version_requirements: !ruby/object:Gem::Requirement
|
23
22
|
requirements:
|
24
23
|
- - '='
|
25
24
|
- !ruby/object:Gem::Version
|
26
|
-
version: 1.2.
|
25
|
+
version: 1.2.9
|
27
26
|
- !ruby/object:Gem::Dependency
|
28
27
|
name: minitest
|
29
28
|
requirement: !ruby/object:Gem::Requirement
|
30
29
|
requirements:
|
31
30
|
- - '='
|
32
31
|
- !ruby/object:Gem::Version
|
33
|
-
version: 5.
|
32
|
+
version: 5.25.4
|
34
33
|
type: :development
|
35
34
|
prerelease: false
|
36
35
|
version_requirements: !ruby/object:Gem::Requirement
|
37
36
|
requirements:
|
38
37
|
- - '='
|
39
38
|
- !ruby/object:Gem::Version
|
40
|
-
version: 5.
|
39
|
+
version: 5.25.4
|
41
40
|
- !ruby/object:Gem::Dependency
|
42
41
|
name: simplecov
|
43
42
|
requirement: !ruby/object:Gem::Requirement
|
44
43
|
requirements:
|
45
44
|
- - '='
|
46
45
|
- !ruby/object:Gem::Version
|
47
|
-
version: 0.
|
46
|
+
version: 0.22.0
|
48
47
|
type: :development
|
49
48
|
prerelease: false
|
50
49
|
version_requirements: !ruby/object:Gem::Requirement
|
51
50
|
requirements:
|
52
51
|
- - '='
|
53
52
|
- !ruby/object:Gem::Version
|
54
|
-
version: 0.
|
53
|
+
version: 0.22.0
|
55
54
|
- !ruby/object:Gem::Dependency
|
56
55
|
name: yard
|
57
56
|
requirement: !ruby/object:Gem::Requirement
|
58
57
|
requirements:
|
59
58
|
- - '='
|
60
59
|
- !ruby/object:Gem::Version
|
61
|
-
version: 0.9.
|
60
|
+
version: 0.9.37
|
62
61
|
type: :development
|
63
62
|
prerelease: false
|
64
63
|
version_requirements: !ruby/object:Gem::Requirement
|
65
64
|
requirements:
|
66
65
|
- - '='
|
67
66
|
- !ruby/object:Gem::Version
|
68
|
-
version: 0.9.
|
67
|
+
version: 0.9.37
|
69
68
|
- !ruby/object:Gem::Dependency
|
70
69
|
name: sequel
|
71
70
|
requirement: !ruby/object:Gem::Requirement
|
72
71
|
requirements:
|
73
72
|
- - '='
|
74
73
|
- !ruby/object:Gem::Version
|
75
|
-
version: 5.
|
74
|
+
version: 5.88.0
|
76
75
|
type: :development
|
77
76
|
prerelease: false
|
78
77
|
version_requirements: !ruby/object:Gem::Requirement
|
79
78
|
requirements:
|
80
79
|
- - '='
|
81
80
|
- !ruby/object:Gem::Version
|
82
|
-
version: 5.
|
83
|
-
description:
|
81
|
+
version: 5.88.0
|
84
82
|
email: sharon@noteflakes.com
|
85
83
|
executables: []
|
86
84
|
extensions:
|
@@ -153,7 +151,6 @@ metadata:
|
|
153
151
|
homepage_uri: https://github.com/digital-fabric/extralite
|
154
152
|
documentation_uri: https://www.rubydoc.info/gems/extralite
|
155
153
|
changelog_uri: https://github.com/digital-fabric/extralite/blob/master/CHANGELOG.md
|
156
|
-
post_install_message:
|
157
154
|
rdoc_options:
|
158
155
|
- "--title"
|
159
156
|
- Extralite
|
@@ -172,8 +169,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
172
169
|
- !ruby/object:Gem::Version
|
173
170
|
version: '0'
|
174
171
|
requirements: []
|
175
|
-
rubygems_version: 3.
|
176
|
-
signing_key:
|
172
|
+
rubygems_version: 3.6.2
|
177
173
|
specification_version: 4
|
178
174
|
summary: Extra-lightweight SQLite3 wrapper for Ruby
|
179
175
|
test_files: []
|