activerecord-enhancedsqlite3-adapter 0.2.0 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: f138b7e075e546691856c8e45f22413a1e381df3024c6ef30e467dbde830c896
4
- data.tar.gz: 0e6bde9f85883cacc12893f8ab2b1ca5820deea6d6a1357a262fb24401ed4980
3
+ metadata.gz: 24efb62453474faa0b37357d98f5b0f8ba13fa98d7e633b5d3a7de5e16d875f6
4
+ data.tar.gz: 0de2b8cae842c4262d81932c577df7731e570f347f0a22a2151ef9671bd8648d
5
5
  SHA512:
6
- metadata.gz: dafd2a35c78565843b9aa384fb5988818c48bdc6852da55363c7e18e447a752b8194ef08ea4a40c9b482f30317cd7afc8e9501e22cb38abbab51dd16f3d6c7a7
7
- data.tar.gz: 5c0d6b07eb0b3e90c4fd6f8859f90d944e33d90e100ee96981f24b4d1cb1212266045f81abe935b4ad1913caf22d43cb3386a73bdb0670b15f8686e680619a77
6
+ metadata.gz: a55c35f42fef85b0373df52f06d1b50b66c4191382844ee6a9836049af03386085bfe9616de8bfc259fcfd6325d5a84f4cc8ca396d721ff87fdcfc49c80dae17
7
+ data.tar.gz: b50f2484872aa18a0681c31abfd4d6a56e044ff9610cb288c73611cb0f56ed8b8242a771b9c4e95a07119ec094aef5bcf6c85f1bc363fd08e59d45a57b162902
data/CHANGELOG.md CHANGED
@@ -1,5 +1,16 @@
1
1
  ## [Unreleased]
2
2
 
3
+ ## [0.3.0] - 2023-12-06
4
+
5
+ - Added a more performant implementation of the the `timeout` mechanism
6
+
7
+ ## [0.2.0] - 2023-09-28
8
+
9
+ - Added support for deferrable constraints
10
+
3
11
  ## [0.1.0] - 2023-09-28
4
12
 
5
13
  - Initial release
14
+ - Added support for virtual columns
15
+ - Added support setting PRAGMA statements via the `config/database.yml` file
16
+ - Added support for loading extensions via the `config/database.yml` file
data/README.md CHANGED
@@ -1,24 +1,85 @@
1
- # Activerecord::Enhanced::Sqlite3::Adapter
1
+ # ActiveRecord Enhanced SQLite3 Adapter
2
2
 
3
- TODO: Delete this and the text below, and describe your gem
3
+ Enhance ActiveRecord's 7.1 SQLite3 adapter. Adds support for:
4
4
 
5
- Welcome to your new gem! In this directory, you'll find the files you need to be able to package up your Ruby library into a gem. Put your Ruby code in the file `lib/activerecord/enhanced/sqlite3/adapter`. To experiment with that code, run `bin/console` for an interactive prompt.
5
+ * generated columns,
6
+ * deferred foreign keys,
7
+ * `PRAGMA` tuning,
8
+ * and extension loading
6
9
 
7
10
  ## Installation
8
11
 
9
- TODO: Replace `UPDATE_WITH_YOUR_GEM_NAME_PRIOR_TO_RELEASE_TO_RUBYGEMS_ORG` with your gem name right after releasing it to RubyGems.org. Please do not do it earlier due to security reasons. Alternatively, replace this section with instructions to install your gem from git if you don't plan to release to RubyGems.org.
10
-
11
12
  Install the gem and add to the application's Gemfile by executing:
12
13
 
13
- $ bundle add UPDATE_WITH_YOUR_GEM_NAME_PRIOR_TO_RELEASE_TO_RUBYGEMS_ORG
14
+ ```shell
15
+ $ bundle add activerecord-enhancedsqlite3-adapter
16
+ ```
14
17
 
15
- If bundler is not being used to manage dependencies, install the gem by executing:
18
+ ## Usage
16
19
 
17
- $ gem install UPDATE_WITH_YOUR_GEM_NAME_PRIOR_TO_RELEASE_TO_RUBYGEMS_ORG
20
+ This gem hooks into your Rails application to enhance the `SQLite3Adapter` automatically. No setup required!
18
21
 
19
- ## Usage
22
+ Once installed, you can take advantage of the added features.
23
+
24
+ ### Generated columns
25
+
26
+ You can now create `virtual` columns, both stored and dynamic. The [SQLite docs](https://www.sqlite.org/gencol.html) explain the difference:
27
+
28
+ > Generated columns can be either VIRTUAL or STORED. The value of a VIRTUAL column is computed when read, whereas the value of a STORED column is computed when the row is written. STORED columns take up space in the database file, whereas VIRTUAL columns use more CPU cycles when being read.
29
+
30
+ The default is to create dynamic/virtual columns.
31
+
32
+ ```ruby
33
+ create_table :virtual_columns, force: true do |t|
34
+ t.string :name
35
+ t.virtual :upper_name, type: :string, as: "UPPER(name)", stored: true
36
+ t.virtual :lower_name, type: :string, as: "LOWER(name)", stored: false
37
+ t.virtual :octet_name, type: :integer, as: "LENGTH(name)"
38
+ end
39
+ ```
40
+
41
+ ### Deferred foreign keys
42
+
43
+ You can now specify whether or not a foreign key should be deferrable, whether `:deferred` or `:immediate`.
44
+
45
+ `:deferred` foreign keys mean that the constraint check will be done once the transaction is committed and allows the constraint behavior to change within transaction. `:immediate` means that constraint check is immediate and allows the constraint behavior to change within transaction. The default is `:immediate`.
46
+
47
+ ```ruby
48
+ add_reference :person, :alias, foreign_key: { deferrable: :deferred }
49
+ add_reference :alias, :person, foreign_key: { deferrable: :deferred }
50
+ ```
51
+
52
+ ### `PRAGMA` tuning
53
+
54
+ Pass any [`PRAGMA` key-value pair](https://www.sqlite.org/pragma.html) under a `pragmas` list in your `config/database.yml` file to ensure that these configuration settings are applied to all database connections.
55
+
56
+ ```yaml
57
+ default: &default
58
+ adapter: sqlite3
59
+ pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %>
60
+ pragmas:
61
+ # level of database durability, 2 = "FULL" (sync on every write), other values include 1 = "NORMAL" (sync every 1000 written pages) and 0 = "NONE"
62
+ # https://www.sqlite.org/pragma.html#pragma_synchronous
63
+ synchronous: "FULL"
64
+ ```
65
+
66
+ ### Extension loading
67
+
68
+ There are a number of [SQLite extensions available as Ruby gems](https://github.com/asg017/sqlite-ecosystem). In order to load the extensions, you need to install the gem (`bundle add {extension-name}`) and then load it into the database connections. In order to support the latter, this gem enhances the `config/database.yml` file to support an `extensions` array. For example, to install and load [an extension](https://github.com/asg017/sqlite-ulid) for supporting [<abbr title="Universally Unique Lexicographically Sortable Identifiers">ULIDs</abbr>](https://github.com/ulid/spec), we would do:
69
+
70
+ ```shell
71
+ $ bundle add sqlite_ulid
72
+ ```
73
+
74
+ then
20
75
 
21
- TODO: Write usage instructions here
76
+ ```yaml
77
+ default: &default
78
+ adapter: sqlite3
79
+ pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %>
80
+ extensions:
81
+ - sqlite_ulid
82
+ ```
22
83
 
23
84
  ## Development
24
85
 
@@ -28,7 +89,7 @@ To install this gem onto your local machine, run `bundle exec rake install`. To
28
89
 
29
90
  ## Contributing
30
91
 
31
- Bug reports and pull requests are welcome on GitHub at https://github.com/[USERNAME]/activerecord-enhancedsqlite3-adapter.
92
+ Bug reports and pull requests are welcome on GitHub at https://github.com/fractaledmind/activerecord-enhancedsqlite3-adapter.
32
93
 
33
94
  ## License
34
95
 
@@ -22,6 +22,7 @@ module EnhancedSQLite3
22
22
  def configure_connection
23
23
  super
24
24
 
25
+ configure_busy_handler_timeout
25
26
  configure_pragmas
26
27
  configure_extensions
27
28
 
@@ -31,6 +32,28 @@ module EnhancedSQLite3
31
32
 
32
33
  private
33
34
 
35
+ def configure_busy_handler_timeout
36
+ return unless @config.key?(:timeout)
37
+
38
+ timeout = self.class.type_cast_config_to_integer(@config[:timeout])
39
+ @raw_connection.busy_handler do |count|
40
+ timed_out = false
41
+ # capture the start time of this blocked write
42
+ @start_time = Process.clock_gettime(Process::CLOCK_MONOTONIC) if count == 0
43
+ # keep track of elapsed time every 100 iterations (to lower load)
44
+ if count % 100 == 0
45
+ @elapsed_time = Process.clock_gettime(Process::CLOCK_MONOTONIC) - @start_time
46
+ # fail if we exceed the timeout value (captured from the timeout config option, converted to seconds)
47
+ timed_out = @elapsed_time > timeout
48
+ end
49
+ if timed_out
50
+ false # this will cause the BusyException to be raised
51
+ else
52
+ sleep 0.001 # sleep 1 millisecond (or whatever)
53
+ end
54
+ end
55
+ end
56
+
34
57
  def configure_pragmas
35
58
  @config.fetch(:pragmas, []).each do |key, value|
36
59
  execute("PRAGMA #{key} = #{value}", "SCHEMA")
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module EnhancedSQLite3
4
- VERSION = "0.2.0"
4
+ VERSION = '0.3.0'
5
5
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: activerecord-enhancedsqlite3-adapter
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.0
4
+ version: 0.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Stephen Margheim
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2023-10-09 00:00:00.000000000 Z
11
+ date: 2023-12-06 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activerecord