extralite 2.8.1 → 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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 49fbb44a887747091953d2ec2239050036dd1c5c37290d9f651521b47a84fdfb
4
- data.tar.gz: 5200205e84f47abad1a9e3c936999edd77defa53e187941d81d50a91926cd520
3
+ metadata.gz: a7adc40dd1b275c571a25ff887b4d7a82e25c0a562b878cfd9f8988828d105ce
4
+ data.tar.gz: c7dea7923b4c861a8aefe839c2395ec12fc84715514006e7961e96a728921861
5
5
  SHA512:
6
- metadata.gz: 1fd77a5ebe191923ba6159eb79b6c60ac5c8311280a5a8513262e6ff6accf2020422a9394df25308718971b98ff25ab50409f50bf81c931cb41274f7401334e4
7
- data.tar.gz: 0dde4d327858617ae1b3ad88432a705593303a312e93177a91c2fc25029cf505eaf952ce98a2cbbd4cced57d733a5a2c045cbf9d7909899c42972ca2c59e1cbd
6
+ metadata.gz: e4113425b3651e5875f44085691ce4e7bc7186391bf968d0882de07196908415c73af58add1367bad4a992ed6c3c30c2dd0ae115b56071a7ef20287febe35a6f
7
+ data.tar.gz: a4ab94ee82dddf6ed6c0edcb0127b7213101a41606a2995343d50fb14998bd5f84f01b9ad5c6c03a45e8b50fa189951d5bdd7097ac3392a389cde9e32ec3fb19
@@ -11,11 +11,13 @@ jobs:
11
11
  strategy:
12
12
  fail-fast: false
13
13
  matrix:
14
- os: [ubuntu-latest, macos-latest]
15
- ruby: ['3.0', '3.1', '3.2', '3.3']
14
+ # macos-latest uses arm64, macos-13 uses x86
15
+ os: [ubuntu-latest, macos-latest, macos-13]
16
+ ruby: ['3.0', '3.1', '3.2', '3.3', 'head']
16
17
 
17
- name: >-
18
- ${{matrix.os}}, ${{matrix.ruby}}
18
+ name: ${{matrix.os}}, ${{matrix.ruby}}
19
+
20
+ if: github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name != github.event.pull_request.base.repo.full_name
19
21
 
20
22
  runs-on: ${{matrix.os}}
21
23
  steps:
@@ -12,10 +12,11 @@ jobs:
12
12
  fail-fast: false
13
13
  matrix:
14
14
  os: [ubuntu-latest, macos-latest]
15
- ruby: ['3.0', '3.1', '3.2', '3.3', 'head']
15
+ ruby: ['3.2', '3.3', '3.4', 'head']
16
16
 
17
- name: >-
18
- ${{matrix.os}}, ${{matrix.ruby}}
17
+ name: ${{matrix.os}}, ${{matrix.ruby}}
18
+
19
+ if: github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name != github.event.pull_request.base.repo.full_name
19
20
 
20
21
  runs-on: ${{matrix.os}}
21
22
  steps:
@@ -23,7 +24,8 @@ jobs:
23
24
  - uses: ruby/setup-ruby@v1
24
25
  with:
25
26
  ruby-version: ${{matrix.ruby}}
26
- bundler-cache: true # 'bundle install' and cache
27
+ bundler-cache: true
28
+ apt-get: libsqlite3-dev
27
29
  - name: Compile C-extension
28
30
  run: bundle exec rake compile
29
31
  - name: Run tests
data/CHANGELOG.md CHANGED
@@ -1,3 +1,17 @@
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
+
11
+ ## 2.8.2 2024-06-02
12
+
13
+ - Update bundled SQLite to version 3.46.0. [#74](https://github.com/digital-fabric/extralite/pull/74)
14
+
1
15
  ## 2.8.1 2024-04-15
2
16
 
3
17
  - Update bundled sqlite to version 3.45.3.
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.45.3](https://sqlite.org/releaselog/3_45_3.html)), offering access to the
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
@@ -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
- static inline VALUE get_column_names(sqlite3_stmt *stmt, int column_count) {
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, VALUE column_names) {
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
- for (int i = 0; i < column_count; i++) {
150
- VALUE value = get_column_value(stmt, i, sqlite3_column_type(stmt, i));
151
- rb_hash_aset(row, RARRAY_AREF(column_names, i), value);
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
- VALUE column_names = get_column_names(ctx->stmt, column_count);
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, column_names);
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(column_names);
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
- VALUE column_names;
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, column_names);
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(column_names);
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
- VALUE column_names = get_column_names(ctx->stmt, column_count);
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, column_names);
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(column_names);
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 get_column_names(ctx->stmt, sqlite3_column_count(ctx->stmt));
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.7'
21
- s.add_development_dependency 'minitest', '5.22.2'
22
- s.add_development_dependency 'simplecov', '0.17.1'
23
- s.add_development_dependency 'yard', '0.9.34'
24
- s.add_development_dependency 'sequel', '5.77.0'
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
@@ -1,4 +1,4 @@
1
1
  module Extralite
2
2
  # Extralite version
3
- VERSION = '2.8.1'
3
+ VERSION = '2.10'
4
4
  end
Binary file
Binary file
Binary file
@@ -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
@@ -277,10 +290,14 @@ class DatabaseTest < Minitest::Test
277
290
 
278
291
  def test_extension_loading
279
292
  case RUBY_PLATFORM
280
- when /linux/
281
- @db.load_extension(File.join(__dir__, 'extensions/text.so'))
282
- when /darwin/
283
- @db.load_extension(File.join(__dir__, 'extensions/text.dylib'))
293
+ when /aarch64-linux/
294
+ @db.load_extension(File.join(__dir__, 'extensions/arm64/text.so'))
295
+ when /x86_64-linux/
296
+ @db.load_extension(File.join(__dir__, 'extensions/x86/text.so'))
297
+ when /arm64-darwin/
298
+ @db.load_extension(File.join(__dir__, 'extensions/arm64/text.dylib'))
299
+ when /x86_64-darwin/
300
+ @db.load_extension(File.join(__dir__, 'extensions/x86/text.dylib'))
284
301
  end
285
302
 
286
303
  r = @db.query_single_splat("select reverse('abcd')")
@@ -359,7 +376,6 @@ class DatabaseTest < Minitest::Test
359
376
  [1, '2', 3],
360
377
  ['4', 5, 6]
361
378
  ]
362
-
363
379
  changes = @db.batch_execute('insert into foo values (?, ?, ?)', records)
364
380
 
365
381
  assert_equal 2, changes
@@ -369,6 +385,23 @@ class DatabaseTest < Minitest::Test
369
385
  ], @db.query('select * from foo')
370
386
  end
371
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
+
372
405
  def test_batch_execute_single_values
373
406
  @db.query('create table foo (bar)')
374
407
  assert_equal [], @db.query('select * from foo')
@@ -1355,6 +1388,12 @@ class ConcurrencyTest < Minitest::Test
1355
1388
  def test_progress_handler_simple
1356
1389
  db = Extralite::Database.new(':memory:')
1357
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
+
1358
1397
  buf = []
1359
1398
  db.on_progress(period: 1) { buf << :progress }
1360
1399
 
@@ -1373,6 +1412,12 @@ class ConcurrencyTest < Minitest::Test
1373
1412
  def test_progress_handler_normal_mode
1374
1413
  db = Extralite::Database.new(':memory:')
1375
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
+
1376
1421
  count = 0
1377
1422
  db.on_progress(period: 1) { count += 1 }
1378
1423
  db.query('select 1 as a')
@@ -1393,6 +1438,12 @@ class ConcurrencyTest < Minitest::Test
1393
1438
  def test_progress_handler_at_least_once_mode
1394
1439
  db = Extralite::Database.new(':memory:')
1395
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
+
1396
1447
  count = 0
1397
1448
  db.on_progress(period: 1) { count += 1 }
1398
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.8.1
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: 2024-04-16 00:00:00.000000000 Z
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.7
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.7
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.22.2
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.22.2
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.17.1
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.17.1
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.34
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.34
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.77.0
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.77.0
83
- description:
81
+ version: 5.88.0
84
82
  email: sharon@noteflakes.com
85
83
  executables: []
86
84
  extensions:
@@ -123,8 +121,10 @@ files:
123
121
  - lib/extralite.rb
124
122
  - lib/extralite/version.rb
125
123
  - lib/sequel/adapters/extralite.rb
126
- - test/extensions/text.dylib
127
- - test/extensions/text.so
124
+ - test/extensions/arm64/text.dylib
125
+ - test/extensions/arm64/text.so
126
+ - test/extensions/x86/text.dylib
127
+ - test/extensions/x86/text.so
128
128
  - test/fixtures/image.png
129
129
  - test/helper.rb
130
130
  - test/issue-38.rb
@@ -151,7 +151,6 @@ metadata:
151
151
  homepage_uri: https://github.com/digital-fabric/extralite
152
152
  documentation_uri: https://www.rubydoc.info/gems/extralite
153
153
  changelog_uri: https://github.com/digital-fabric/extralite/blob/master/CHANGELOG.md
154
- post_install_message:
155
154
  rdoc_options:
156
155
  - "--title"
157
156
  - Extralite
@@ -170,8 +169,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
170
169
  - !ruby/object:Gem::Version
171
170
  version: '0'
172
171
  requirements: []
173
- rubygems_version: 3.5.3
174
- signing_key:
172
+ rubygems_version: 3.6.2
175
173
  specification_version: 4
176
174
  summary: Extra-lightweight SQLite3 wrapper for Ruby
177
175
  test_files: []
Binary file