activerecord-enhancedsqlite3-adapter 0.6.0 → 0.8.0

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: e0d679b0ee45b0838fc294f50e43b806301fba662e54f280b3d0e747de3e7670
4
- data.tar.gz: 5b345ff772a3cba527a4fe638724bb372f488bc8ec3ceb4d3e8b76ee40b2f434
3
+ metadata.gz: 822503d22973552ab533017c76ee5e40c8687e2283c2b97f17013967a4d981ee
4
+ data.tar.gz: 99b0f6b59a9e3b5fb49624a0d9258056d0027c34c7cfe430d58fda8af601fa13
5
5
  SHA512:
6
- metadata.gz: 47288376cd918173cce7edf28fc2a8cbb8a86c749aa44aaf88e4b2f81fc922b3b5369e579abb8e9bab7585f7c8b2ae732c3f6a8601117e935a61effcf7d86276
7
- data.tar.gz: 22ae8604263b8a75379a0f9c132d60cf4616d6695665742b4a6a358f24f0fa4daf1b5b1708ecf5599617293bc4a8fc76db89fbd204deaa70b430233db2f6891a
6
+ metadata.gz: e7c2b49a47f755752a71b7aa7c0e5dbeadb1fd64473c4bf56ff93f104d2c6a5f86ee1273b7f57fb20fcb3e0fdc380662f97c8f462b9a7096c2a7f57f25826141
7
+ data.tar.gz: b93e48d2dd251aa60495afac78364c2cbb2552d52fa8ca16bb2868468b4b0c10c1807a4ebd571a458cebb48330e96b471a955859ab5af96a04203a46e4e96718
data/CHANGELOG.md CHANGED
@@ -1,5 +1,13 @@
1
1
  ## [Unreleased]
2
2
 
3
+ ## [0.8.0] - 2024-05-05
4
+
5
+ - Load `sqlpkg` extensions if listed and present ([@fractaledmind](https://github.com/fractaledmind/activerecord-enhancedsqlite3-adapter/pull/17))
6
+
7
+ ## [0.7.0] - 2024-04-29
8
+
9
+ - Loosen the `sqlite3` dependency to allow for `>= 1.4.0` (including 2.x) ([@fractaledmind](https://github.com/fractaledmind/activerecord-enhancedsqlite3-adapter/pull/15))
10
+
3
11
  ## [0.6.0] - 2024-04-10
4
12
 
5
13
  - Use the same busy_handler function as will be in the sqlite3-ruby gem ([@fractaledmind](https://github.com/fractaledmind/activerecord-enhancedsqlite3-adapter/pull/11))
@@ -1,12 +1,12 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  # supports concatenation in default functions: https://github.com/rails/rails/pull/49287
4
- # supports insert returning values: https://github.com/rails/rails/pull/49290
5
4
  # supports configuring busy_handler: https://github.com/rails/rails/pull/49352
6
5
 
7
6
  require "active_record/connection_adapters/sqlite3_adapter"
8
7
  require "enhanced_sqlite3/supports_virtual_columns"
9
8
  require "enhanced_sqlite3/supports_deferrable_constraints"
9
+ require "enhanced_sqlite3/supports_insert_returning"
10
10
 
11
11
  module EnhancedSQLite3
12
12
  module Adapter
@@ -48,6 +48,7 @@ module EnhancedSQLite3
48
48
 
49
49
  EnhancedSQLite3::SupportsVirtualColumns.apply! unless try(:supports_virtual_columns?)
50
50
  EnhancedSQLite3::SupportsDeferrableConstraints.apply! unless try(:supports_deferrable_constraints?)
51
+ EnhancedSQLite3::SupportsInsertReturning.apply! unless try(:supports_insert_returning?)
51
52
  end
52
53
 
53
54
  # Patch the #transaction method to ensure that all transactions are sent to the writing role database connection pool.
@@ -72,22 +73,17 @@ module EnhancedSQLite3
72
73
  def configure_busy_handler_timeout
73
74
  return unless @config.key?(:timeout)
74
75
 
75
- timeout = self.class.type_cast_config_to_integer(@config[:timeout])
76
- timeout_seconds = timeout.fdiv(1000)
77
- retry_interval = 6e-5 # 60 microseconds
76
+ timeout_milliseconds = self.class.type_cast_config_to_integer(@config[:timeout])
77
+ timeout_seconds = timeout_milliseconds.fdiv(1000)
78
78
 
79
79
  @raw_connection.busy_handler do |count|
80
- timed_out = false
81
- # keep track of elapsed time every 100 iterations (to lower load)
82
- if (count % 100).zero?
83
- # fail if we exceed the timeout value (captured from the timeout config option, converted to seconds)
84
- timed_out = (count * retry_interval) > timeout_seconds
85
- end
86
- if timed_out
87
- false # this will cause the BusyException to be raised
80
+ now = Process.clock_gettime(Process::CLOCK_MONOTONIC)
81
+ if count.zero?
82
+ @timeout_deadline = now + timeout_seconds
83
+ elsif now > @timeout_deadline
84
+ next false
88
85
  else
89
- sleep(retry_interval)
90
- true
86
+ sleep(0.001)
91
87
  end
92
88
  end
93
89
  end
@@ -130,11 +126,21 @@ module EnhancedSQLite3
130
126
  def configure_extensions
131
127
  @raw_connection.enable_load_extension(true)
132
128
  @config.fetch(:extensions, []).each do |extension_name|
133
- require extension_name
134
- extension_classname = extension_name.camelize
135
- extension_class = extension_classname.constantize
136
- extension_class.load(@raw_connection)
129
+ if extension_name.include?("/")
130
+ raise LoadError unless Dir.exist?(".sqlpkg/#{extension_name}")
131
+ Dir.glob(".sqlpkg/#{extension_name}/*.{dll,so,dylib}") do |extension_path|
132
+ @raw_connection.load_extension(extension_path)
133
+ end
134
+ else
135
+ require extension_name
136
+ extension_classname = extension_name.camelize
137
+ extension_class = extension_classname.constantize
138
+ extension_class.load(@raw_connection)
139
+ end
137
140
  rescue LoadError
141
+ Dir.glob(".sqlpkg/**/*.{dll,so,dylib}") do |extension_path|
142
+ @raw_connection.load_extension(extension_path)
143
+ end
138
144
  Rails.logger.error("Failed to find the SQLite extension gem: #{extension_name}. Skipping...")
139
145
  rescue NameError
140
146
  Rails.logger.error("Failed to find the SQLite extension class: #{extension_classname}. Skipping...")
@@ -40,7 +40,7 @@ module EnhancedSQLite3
40
40
  )
41
41
 
42
42
  # Replace the single production configuration with two separate reader and writer configurations
43
- self.configurations = remaining_configs + [reader, writer]
43
+ self.configurations = remaining_configs + [writer, reader]
44
44
  else
45
45
  reader = env_configs.find { |config| config.name == "reader" }
46
46
  writer = env_configs.find { |config| config.name == "writer" }
@@ -0,0 +1,56 @@
1
+ # frozen_string_literal: true
2
+
3
+ # see: https://github.com/rails/rails/pull/49290
4
+ module EnhancedSQLite3
5
+ module SupportsInsertReturning
6
+ def self.apply!
7
+ EnhancedSQLite3::Adapter.include(Adapter)
8
+ ActiveRecord::ConnectionAdapters::SQLite3::DatabaseStatements.include(DatabaseStatements)
9
+ end
10
+
11
+ module Adapter
12
+ def supports_insert_returning?
13
+ database_version >= "3.35.0"
14
+ end
15
+
16
+ def return_value_after_insert?(column) # :nodoc:
17
+ column.auto_populated?
18
+ end
19
+
20
+ def use_insert_returning?
21
+ @use_insert_returning ||= @config.key?(:insert_returning) ? self.class.type_cast_config_to_boolean(@config[:insert_returning]) : true
22
+ end
23
+
24
+ def build_insert_sql(insert) # :nodoc:
25
+ sql = super(insert)
26
+ sql << " RETURNING #{insert.returning}" if insert.returning
27
+ sql
28
+ end
29
+ end
30
+
31
+ module DatabaseStatements
32
+ def sql_for_insert(sql, pk, binds, returning) # :nodoc:
33
+ if supports_insert_returning?
34
+ if pk.nil?
35
+ # Extract the table from the insert sql. Yuck.
36
+ table_ref = extract_table_ref_from_insert_sql(sql)
37
+ pk = primary_key(table_ref) if table_ref
38
+ end
39
+
40
+ returning_columns = returning || Array(pk)
41
+
42
+ returning_columns_statement = returning_columns.map { |c| quote_column_name(c) }.join(", ")
43
+ sql = "#{sql} RETURNING #{returning_columns_statement}" if returning_columns.any?
44
+ end
45
+
46
+ [sql, binds]
47
+ end
48
+
49
+ def extract_table_ref_from_insert_sql(sql)
50
+ if sql =~ /into\s("[A-Za-z0-9_."\[\]\s]+"|[A-Za-z0-9_."\[\]]+)\s*/im
51
+ $1.strip
52
+ end
53
+ end
54
+ end
55
+ end
56
+ end
@@ -1,3 +1,3 @@
1
1
  module EnhancedSQLite3
2
- VERSION = "0.6.0"
2
+ VERSION = "0.8.0"
3
3
  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.6.0
4
+ version: 0.8.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: 2024-04-10 00:00:00.000000000 Z
11
+ date: 2024-05-05 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activerecord
@@ -28,14 +28,14 @@ dependencies:
28
28
  name: sqlite3
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
- - - "~>"
31
+ - - ">="
32
32
  - !ruby/object:Gem::Version
33
33
  version: '1.6'
34
34
  type: :runtime
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
- - - "~>"
38
+ - - ">="
39
39
  - !ruby/object:Gem::Version
40
40
  version: '1.6'
41
41
  - !ruby/object:Gem::Dependency
@@ -113,6 +113,7 @@ files:
113
113
  - lib/enhanced_sqlite3/railtie.rb
114
114
  - lib/enhanced_sqlite3/resolver.rb
115
115
  - lib/enhanced_sqlite3/supports_deferrable_constraints.rb
116
+ - lib/enhanced_sqlite3/supports_insert_returning.rb
116
117
  - lib/enhanced_sqlite3/supports_virtual_columns.rb
117
118
  - lib/enhanced_sqlite3/version.rb
118
119
  homepage: https://github.com/fractaledmind/activerecord-enhancedsqlite3-adapter