sqlite3 2.1.0.rc1-x86_64-linux-musl → 2.1.0.rc2-x86_64-linux-musl

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: 6e80445cb812afd790310ae44ffedf1fd0ba59d351a5318b73a9686fcfa18b42
4
- data.tar.gz: 51a3c2410ded1ab3fb02c6cb29facf53460f90aac13c3990ae1f653f2a0652b8
3
+ metadata.gz: 41b6c5ca5fd65167d1631992e4d4290b4f6a8335e661bd1b6db2ff6d438b73c9
4
+ data.tar.gz: b91aa02992536b221ab6d415075c4d55db295ca9fb3b2fff14c1b55c966863f7
5
5
  SHA512:
6
- metadata.gz: 731a9d2f61c63b89eac5e0c63507c0a7a482eb5943e3f5e7a96147c0a475a26f9e5904f606f6565810fe17e5b7d6a9d6a63afea41cd32d02db6f8573fd8ba459
7
- data.tar.gz: 13ff9eb60ea3d126c7e04d93767057bbbac460fe7de3d7f77ad08582ef2a7982c5b20e1f351732b55115c6f211c3a16c60a3bc10b9016627aa7dc931d88965b1
6
+ metadata.gz: 00bea5e078d188a8829140822a74fbfeb6a531ebc85b122311fceb97803ae2ad0e0cf7ab30092f55d1f4296bc45551b18de55ec5194280d1b77ede861bc5362f
7
+ data.tar.gz: 664cdcf8ac70f883cd71bba3d0334405cfb64330af1ecdf96c88e56bc6aebd4d29c7452c159202d43a71455819c3d4788364094d325ffa423900a0d6826c3b98
data/CHANGELOG.md CHANGED
@@ -1,5 +1,12 @@
1
1
  # sqlite3-ruby Changelog
2
2
 
3
+ ## prerelease 2.1.0.rc2 / 2024-09-18
4
+
5
+ ### Improved
6
+
7
+ - Address a performance regression in 2.1.0.rc1.
8
+
9
+
3
10
  ## prerelease 2.1.0.rc1 / 2024-09-18
4
11
 
5
12
  ### Ruby
data/CONTRIBUTING.md CHANGED
@@ -16,20 +16,15 @@ please look there for additional information.
16
16
 
17
17
  All statements keep pointers back to their respective database connections.
18
18
  The `@connection` instance variable on the `Statement` handle keeps the database
19
- connection alive. Memory allocated for a statement handler will be freed in
20
- two cases:
19
+ connection alive.
21
20
 
22
- 1. `#close` is called on the statement
23
- 2. The `SQLite3::Database` object gets garbage collected
24
-
25
- We can't free the memory for the statement in the garbage collection function
26
- for the statement handler. The reason is because there exists a race
27
- condition. We cannot guarantee the order in which objects will be garbage
28
- collected. So, it is possible that a connection and a statement are up for
29
- garbage collection. If the database connection were to be free'd before the
30
- statement, then boom. Instead we'll be conservative and free unclosed
31
- statements when the connection is terminated.
21
+ We use `sqlite3_close_v2` in `Database#close` since v2.1.0 which defers _actually_ closing the
22
+ connection and freeing the underlying memory until all open statments are closed; though the
23
+ `Database` object will immediately behave as though it's been fully closed. If a Database is not
24
+ explicitly closed, it will be closed when it is GCed.
32
25
 
26
+ `Statement#close` finalizes the underlying statement. If a Statement is not explicitly closed, it
27
+ will be closed/finalized when it is GCed.
33
28
 
34
29
 
35
30
  ## Building gems
@@ -49,15 +49,16 @@ discard_db(sqlite3RubyPtr ctx)
49
49
  }
50
50
 
51
51
  ctx->db = NULL;
52
+ ctx->flags |= SQLITE3_RB_DATABASE_DISCARDED;
52
53
  }
53
54
 
54
55
  static void
55
56
  close_or_discard_db(sqlite3RubyPtr ctx)
56
57
  {
57
58
  if (ctx->db) {
58
- int isReadonly = (ctx->flags & SQLITE_OPEN_READONLY);
59
+ int is_readonly = (ctx->flags & SQLITE3_RB_DATABASE_READONLY);
59
60
 
60
- if (isReadonly || ctx->owner == getpid()) {
61
+ if (is_readonly || ctx->owner == getpid()) {
61
62
  // Ordinary close.
62
63
  sqlite3_close_v2(ctx->db);
63
64
  ctx->db = NULL;
@@ -153,7 +154,9 @@ rb_sqlite3_open_v2(VALUE self, VALUE file, VALUE mode, VALUE zvfs)
153
154
  );
154
155
 
155
156
  CHECK(ctx->db, status);
156
- ctx->flags = flags;
157
+ if (flags & SQLITE_OPEN_READONLY) {
158
+ ctx->flags |= SQLITE3_RB_DATABASE_READONLY;
159
+ }
157
160
 
158
161
  return self;
159
162
  }
@@ -943,11 +946,10 @@ rb_sqlite3_open16(VALUE self, VALUE file)
943
946
  #endif
944
947
  #endif
945
948
 
946
- status = sqlite3_open16(utf16_string_value_ptr(file), &ctx->db);
947
-
948
- // these are the perm flags used implicitly by sqlite3_open16,
949
+ // sqlite3_open16 implicitly uses flags (SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE)
949
950
  // see https://www.sqlite.org/capi3ref.html#sqlite3_open
950
- ctx->flags = SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE;
951
+ // so we do not ever set SQLITE3_RB_DATABASE_READONLY in ctx->flags
952
+ status = sqlite3_open16(utf16_string_value_ptr(file), &ctx->db);
951
953
 
952
954
  CHECK(ctx->db, status)
953
955
 
@@ -3,6 +3,10 @@
3
3
 
4
4
  #include <sqlite3_ruby.h>
5
5
 
6
+ /* bits in the `flags` field */
7
+ #define SQLITE3_RB_DATABASE_READONLY 0x01
8
+ #define SQLITE3_RB_DATABASE_DISCARDED 0x02
9
+
6
10
  struct _sqlite3Ruby {
7
11
  sqlite3 *db;
8
12
  VALUE busy_handler;
@@ -1,22 +1,12 @@
1
1
  #include <sqlite3_ruby.h>
2
2
 
3
3
  #define REQUIRE_OPEN_STMT(_ctxt) \
4
- if(!_ctxt->st) \
4
+ if (!_ctxt->st) \
5
5
  rb_raise(rb_path2class("SQLite3::Exception"), "cannot use a closed statement");
6
6
 
7
- static void
8
- require_open_db(VALUE stmt_rb)
9
- {
10
- VALUE closed_p = rb_funcall(
11
- rb_iv_get(stmt_rb, "@connection"),
12
- rb_intern("closed?"), 0);
13
-
14
- if (RTEST(closed_p)) {
15
- rb_raise(rb_path2class("SQLite3::Exception"),
16
- "cannot use a statement associated with a closed database");
17
- }
18
- }
19
-
7
+ #define REQUIRE_LIVE_DB(_ctxt) \
8
+ if (_ctxt->db->flags & SQLITE3_RB_DATABASE_DISCARDED) \
9
+ rb_raise(rb_path2class("SQLite3::Exception"), "cannot use a statement associated with a discarded database");
20
10
 
21
11
  VALUE cSqlite3Statement;
22
12
 
@@ -71,6 +61,11 @@ prepare(VALUE self, VALUE db, VALUE sql)
71
61
 
72
62
  TypedData_Get_Struct(self, sqlite3StmtRuby, &statement_type, ctx);
73
63
 
64
+ /* Dereferencing a pointer to the database struct will be faster than accessing it through the
65
+ * instance variable @connection. The struct pointer is guaranteed to be live because instance
66
+ * variable will keep it from being GCed. */
67
+ ctx->db = db_ctx;
68
+
74
69
  #ifdef HAVE_SQLITE3_PREPARE_V2
75
70
  status = sqlite3_prepare_v2(
76
71
  #else
@@ -135,7 +130,7 @@ step(VALUE self)
135
130
 
136
131
  TypedData_Get_Struct(self, sqlite3StmtRuby, &statement_type, ctx);
137
132
 
138
- require_open_db(self);
133
+ REQUIRE_LIVE_DB(ctx);
139
134
  REQUIRE_OPEN_STMT(ctx);
140
135
 
141
136
  if (ctx->done_p) { return Qnil; }
@@ -232,7 +227,7 @@ bind_param(VALUE self, VALUE key, VALUE value)
232
227
 
233
228
  TypedData_Get_Struct(self, sqlite3StmtRuby, &statement_type, ctx);
234
229
 
235
- require_open_db(self);
230
+ REQUIRE_LIVE_DB(ctx);
236
231
  REQUIRE_OPEN_STMT(ctx);
237
232
 
238
233
  switch (TYPE(key)) {
@@ -326,7 +321,7 @@ reset_bang(VALUE self)
326
321
 
327
322
  TypedData_Get_Struct(self, sqlite3StmtRuby, &statement_type, ctx);
328
323
 
329
- require_open_db(self);
324
+ REQUIRE_LIVE_DB(ctx);
330
325
  REQUIRE_OPEN_STMT(ctx);
331
326
 
332
327
  sqlite3_reset(ctx->st);
@@ -348,7 +343,7 @@ clear_bindings_bang(VALUE self)
348
343
 
349
344
  TypedData_Get_Struct(self, sqlite3StmtRuby, &statement_type, ctx);
350
345
 
351
- require_open_db(self);
346
+ REQUIRE_LIVE_DB(ctx);
352
347
  REQUIRE_OPEN_STMT(ctx);
353
348
 
354
349
  sqlite3_clear_bindings(ctx->st);
@@ -382,7 +377,7 @@ column_count(VALUE self)
382
377
  sqlite3StmtRubyPtr ctx;
383
378
  TypedData_Get_Struct(self, sqlite3StmtRuby, &statement_type, ctx);
384
379
 
385
- require_open_db(self);
380
+ REQUIRE_LIVE_DB(ctx);
386
381
  REQUIRE_OPEN_STMT(ctx);
387
382
 
388
383
  return INT2NUM(sqlite3_column_count(ctx->st));
@@ -415,7 +410,7 @@ column_name(VALUE self, VALUE index)
415
410
 
416
411
  TypedData_Get_Struct(self, sqlite3StmtRuby, &statement_type, ctx);
417
412
 
418
- require_open_db(self);
413
+ REQUIRE_LIVE_DB(ctx);
419
414
  REQUIRE_OPEN_STMT(ctx);
420
415
 
421
416
  name = sqlite3_column_name(ctx->st, (int)NUM2INT(index));
@@ -440,7 +435,7 @@ column_decltype(VALUE self, VALUE index)
440
435
 
441
436
  TypedData_Get_Struct(self, sqlite3StmtRuby, &statement_type, ctx);
442
437
 
443
- require_open_db(self);
438
+ REQUIRE_LIVE_DB(ctx);
444
439
  REQUIRE_OPEN_STMT(ctx);
445
440
 
446
441
  name = sqlite3_column_decltype(ctx->st, (int)NUM2INT(index));
@@ -459,7 +454,7 @@ bind_parameter_count(VALUE self)
459
454
  sqlite3StmtRubyPtr ctx;
460
455
  TypedData_Get_Struct(self, sqlite3StmtRuby, &statement_type, ctx);
461
456
 
462
- require_open_db(self);
457
+ REQUIRE_LIVE_DB(ctx);
463
458
  REQUIRE_OPEN_STMT(ctx);
464
459
 
465
460
  return INT2NUM(sqlite3_bind_parameter_count(ctx->st));
@@ -568,7 +563,7 @@ stats_as_hash(VALUE self)
568
563
  sqlite3StmtRubyPtr ctx;
569
564
  TypedData_Get_Struct(self, sqlite3StmtRuby, &statement_type, ctx);
570
565
 
571
- require_open_db(self);
566
+ REQUIRE_LIVE_DB(ctx);
572
567
  REQUIRE_OPEN_STMT(ctx);
573
568
 
574
569
  VALUE arg = rb_hash_new();
@@ -587,7 +582,7 @@ stat_for(VALUE self, VALUE key)
587
582
  sqlite3StmtRubyPtr ctx;
588
583
  TypedData_Get_Struct(self, sqlite3StmtRuby, &statement_type, ctx);
589
584
 
590
- require_open_db(self);
585
+ REQUIRE_LIVE_DB(ctx);
591
586
  REQUIRE_OPEN_STMT(ctx);
592
587
 
593
588
  if (SYMBOL_P(key)) {
@@ -609,7 +604,7 @@ memused(VALUE self)
609
604
  sqlite3StmtRubyPtr ctx;
610
605
  TypedData_Get_Struct(self, sqlite3StmtRuby, &statement_type, ctx);
611
606
 
612
- require_open_db(self);
607
+ REQUIRE_LIVE_DB(ctx);
613
608
  REQUIRE_OPEN_STMT(ctx);
614
609
 
615
610
  return INT2NUM(sqlite3_stmt_status(ctx->st, SQLITE_STMTSTATUS_MEMUSED, 0));
@@ -628,7 +623,7 @@ database_name(VALUE self, VALUE index)
628
623
  sqlite3StmtRubyPtr ctx;
629
624
  TypedData_Get_Struct(self, sqlite3StmtRuby, &statement_type, ctx);
630
625
 
631
- require_open_db(self);
626
+ REQUIRE_LIVE_DB(ctx);
632
627
  REQUIRE_OPEN_STMT(ctx);
633
628
 
634
629
  return SQLITE3_UTF8_STR_NEW2(
@@ -647,7 +642,7 @@ get_sql(VALUE self)
647
642
  sqlite3StmtRubyPtr ctx;
648
643
  TypedData_Get_Struct(self, sqlite3StmtRuby, &statement_type, ctx);
649
644
 
650
- require_open_db(self);
645
+ REQUIRE_LIVE_DB(ctx);
651
646
  REQUIRE_OPEN_STMT(ctx);
652
647
 
653
648
  return rb_obj_freeze(SQLITE3_UTF8_STR_NEW2(sqlite3_sql(ctx->st)));
@@ -667,7 +662,7 @@ get_expanded_sql(VALUE self)
667
662
 
668
663
  TypedData_Get_Struct(self, sqlite3StmtRuby, &statement_type, ctx);
669
664
 
670
- require_open_db(self);
665
+ REQUIRE_LIVE_DB(ctx);
671
666
  REQUIRE_OPEN_STMT(ctx);
672
667
 
673
668
  expanded_sql = sqlite3_expanded_sql(ctx->st);
@@ -5,6 +5,7 @@
5
5
 
6
6
  struct _sqlite3StmtRuby {
7
7
  sqlite3_stmt *st;
8
+ sqlite3Ruby *db;
8
9
  int done_p;
9
10
  };
10
11
 
Binary file
Binary file
Binary file
@@ -1,3 +1,3 @@
1
1
  module SQLite3
2
- VERSION = "2.1.0.rc1"
2
+ VERSION = "2.1.0.rc2"
3
3
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: sqlite3
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.1.0.rc1
4
+ version: 2.1.0.rc2
5
5
  platform: x86_64-linux-musl
6
6
  authors:
7
7
  - Jamis Buck
@@ -11,7 +11,7 @@ authors:
11
11
  autorequire:
12
12
  bindir: bin
13
13
  cert_chain: []
14
- date: 2024-09-18 00:00:00.000000000 Z
14
+ date: 2024-09-19 00:00:00.000000000 Z
15
15
  dependencies: []
16
16
  description: |
17
17
  Ruby library to interface with the SQLite3 database engine (http://www.sqlite.org). Precompiled