extralite 2.8.2 → 2.10
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 +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: []
|