activerecord-trilogy-adapter 2.2.0 → 3.1.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: a64e0395be9ae813e0aec59643758f1a2cc813099c290d95b5c6fbbf8c03746e
4
- data.tar.gz: 7a1e5be7180c1f84475a40b7a48fe3b717eca0b3c4550ec2e687351049dcfa4e
3
+ metadata.gz: 065e502503fb93e0e951b03e67c43b8ea257a01c681c077b5b904a95ddcb0c90
4
+ data.tar.gz: 2a85e79e0654196e0dba708f7bbc4146c413bf0f0b135894357bc174374c76fd
5
5
  SHA512:
6
- metadata.gz: b4e7aa7c78d2773783d578708d8267633f006db9f89eba45d58fb172e5fcb8a0bc8b0b4b70542c6cc4900ad0fd217706765db035601b0b862df1bbbf3d79c02e
7
- data.tar.gz: f508049eb78a987e12c2e18480516b2ffced87c41a8517aaa95a3e24585b2bbb6ae181e1dd4abf8f6889155bf76e351f5912bb74c5deeeff63fce970b303b835
6
+ metadata.gz: 7ed2509f2e8593d3d1b73c56b403875a1751f50c5e5ae99fc405fead7020ec43c5b9e0510e196b3818a5cc1335480062a8c75e2cfebb757ca19c46fa9d1404be
7
+ data.tar.gz: 45d9e001bee0aa227b2e7a7ac2f3b009d009f312cc2af128d5be0275c5f9ff2ce7b496ebde2ca7df1fedfd7a9a6b235df9fef1cfaf2309ca374357ba14d0a485
data/README.md CHANGED
@@ -1,23 +1,34 @@
1
1
  # Trilogy Adapter
2
2
 
3
- Active Record database adapter for [Trilogy](https://github.com/github/trilogy)
3
+ Ruby on Rails Active Record database adapter for [Trilogy](https://github.com/trilogy-libraries/trilogy), a client library for MySQL-compatible database servers, designed for performance, flexibility, and ease of embedding.
4
+
5
+ This gem offers Trilogy support for versions of Active Record prior to v7.1. Currently supports:
6
+
7
+ - ⚠️ Rails v7.1+ includes Trilogy support by default making this gem unnecessary
8
+ - ✅ Rails v7.0.x
9
+ - ✅ Rails v6.1.x
10
+ - ✅ Rails v6.0.x
4
11
 
5
12
  ## Requirements
6
13
 
7
- - [Ruby](https://www.ruby-lang.org) 2.7 or higher
8
- - [Active Record](https://github.com/rails/rails) 7.1 or higher
9
- - [Trilogy](https://github.com/github/trilogy) 2.1.1 or higher
14
+ - [Ruby](https://www.ruby-lang.org) v2.7 or higher
15
+ - [Active Record](https://github.com/rails/rails) v6.0.x or higher
16
+ - [Trilogy](https://github.com/trilogy-libraries/trilogy) v2.4.0 or higher, which is included as a dependency of this gem.
10
17
 
11
18
  ## Setup
12
19
 
13
- * Add the following to your Gemfile:
20
+ 1. Add the following to your `Gemfile` and run `bundle install`:
14
21
 
15
- ```rb
16
- gem "activerecord-trilogy-adapter"
17
- ```
22
+ ```rb
23
+ # Gemfile
24
+ gem "activerecord-trilogy-adapter"
25
+ ```
26
+ 2. Update your application's database configuration to use `trilogy` as the adapter:
18
27
 
19
- * Update your database configuration (e.g. `config/database.yml`) to use
20
- `trilogy` as the adapter.
28
+ ```yaml
29
+ # config/database.yml
30
+ adapter: trilogy
31
+ ```
21
32
 
22
33
  ## Versioning
23
34
 
@@ -0,0 +1,124 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ActiveRecord
4
+ module ConnectionAdapters
5
+ module Trilogy
6
+ module DatabaseStatements
7
+ READ_QUERY = ActiveRecord::ConnectionAdapters::AbstractAdapter.build_read_query_regexp(
8
+ :desc, :describe, :set, :show, :use
9
+ ) # :nodoc:
10
+ private_constant :READ_QUERY
11
+
12
+ HIGH_PRECISION_CURRENT_TIMESTAMP = Arel.sql("CURRENT_TIMESTAMP(6)").freeze # :nodoc:
13
+ private_constant :HIGH_PRECISION_CURRENT_TIMESTAMP
14
+
15
+ def write_query?(sql) # :nodoc:
16
+ !READ_QUERY.match?(sql)
17
+ rescue ArgumentError # Invalid encoding
18
+ !READ_QUERY.match?(sql.b)
19
+ end
20
+
21
+ def explain(arel, binds = [])
22
+ sql = "EXPLAIN #{to_sql(arel, binds)}"
23
+ start = Process.clock_gettime(Process::CLOCK_MONOTONIC)
24
+ result = internal_exec_query(sql, "EXPLAIN", binds)
25
+ elapsed = Process.clock_gettime(Process::CLOCK_MONOTONIC) - start
26
+
27
+ MySQL::ExplainPrettyPrinter.new.pp(result, elapsed)
28
+ end
29
+
30
+ def select_all(*, **) # :nodoc:
31
+ result = super
32
+ with_trilogy_connection do |conn|
33
+ conn.next_result while conn.more_results_exist?
34
+ end
35
+ result
36
+ end
37
+
38
+ def exec_query(sql, name = "SQL", binds = [], prepare: false, **kwargs)
39
+ internal_exec_query(sql, name, binds, prepare: prepare, **kwargs)
40
+ end
41
+
42
+ def internal_exec_query(sql, name = "SQL", binds = [], prepare: false, async: false) # :nodoc:
43
+ sql = transform_query(sql)
44
+ check_if_write_query(sql)
45
+ mark_transaction_written_if_write(sql)
46
+
47
+ result = raw_execute(sql, name, async: async)
48
+ ActiveRecord::Result.new(result.fields, result.to_a)
49
+ end
50
+
51
+ def exec_insert(sql, name, binds, pk = nil, sequence_name = nil, returning: nil) # :nodoc:
52
+ sql = transform_query(sql)
53
+ check_if_write_query(sql)
54
+ mark_transaction_written_if_write(sql)
55
+
56
+ raw_execute(to_sql(sql, binds), name)
57
+ end
58
+
59
+ def exec_delete(sql, name = nil, binds = []) # :nodoc:
60
+ sql = transform_query(sql)
61
+ check_if_write_query(sql)
62
+ mark_transaction_written_if_write(sql)
63
+
64
+ result = raw_execute(to_sql(sql, binds), name)
65
+ result.affected_rows
66
+ end
67
+
68
+ alias :exec_update :exec_delete # :nodoc:
69
+
70
+ def high_precision_current_timestamp
71
+ HIGH_PRECISION_CURRENT_TIMESTAMP
72
+ end
73
+
74
+ private
75
+ if ActiveRecord.version < ::Gem::Version.new('7.0.a') # ActiveRecord <= 6.1 support
76
+ def raw_execute(sql, name, uses_transaction: true, **_kwargs)
77
+ # Same as mark_transaction_written_if_write(sql)
78
+ transaction = current_transaction
79
+ if transaction.respond_to?(:written) && transaction.open?
80
+ transaction.written ||= write_query?(sql)
81
+ end
82
+
83
+ log(sql, name) do
84
+ with_trilogy_connection(uses_transaction: uses_transaction) do |conn|
85
+ sync_timezone_changes(conn)
86
+ conn.query(sql)
87
+ end
88
+ end
89
+ end
90
+
91
+ def transform_query(sql); sql; end
92
+ def check_if_write_query(*args); end
93
+
94
+ if ActiveRecord.version < ::Gem::Version.new('6.1.a') # ActiveRecord <= 6.0 support
95
+ def mark_transaction_written_if_write(*args); end
96
+ end
97
+ else # ActiveRecord 7.0 support
98
+ def raw_execute(sql, name, uses_transaction: true, async: false, allow_retry: false)
99
+ mark_transaction_written_if_write(sql)
100
+ log(sql, name, async: async) do
101
+ with_trilogy_connection(uses_transaction: uses_transaction, allow_retry: allow_retry) do |conn|
102
+ sync_timezone_changes(conn)
103
+ conn.query(sql)
104
+ end
105
+ end
106
+ end
107
+ end
108
+
109
+ def last_inserted_id(result)
110
+ result.last_insert_id
111
+ end
112
+
113
+ def sync_timezone_changes(conn)
114
+ # Sync any changes since connection last established.
115
+ if default_timezone == :local
116
+ conn.query_flags |= ::Trilogy::QUERY_FLAGS_LOCAL_TIMEZONE
117
+ else
118
+ conn.query_flags &= ~::Trilogy::QUERY_FLAGS_LOCAL_TIMEZONE
119
+ end
120
+ end
121
+ end
122
+ end
123
+ end
124
+ end
@@ -4,76 +4,82 @@ require "trilogy"
4
4
  require "active_record/connection_adapters/abstract_mysql_adapter"
5
5
 
6
6
  require "active_record/tasks/trilogy_database_tasks"
7
+ require "active_record/connection_adapters/trilogy/database_statements"
7
8
  require "trilogy_adapter/lost_connection_exception_translator"
8
9
 
9
10
  module ActiveRecord
10
- module ConnectionAdapters
11
- class TrilogyAdapter < ::ActiveRecord::ConnectionAdapters::AbstractMysqlAdapter
12
- module DatabaseStatements
13
- READ_QUERY = ActiveRecord::ConnectionAdapters::AbstractAdapter.build_read_query_regexp(
14
- :desc, :describe, :set, :show, :use
15
- ) # :nodoc:
16
- private_constant :READ_QUERY
17
-
18
- def write_query?(sql) # :nodoc:
19
- !READ_QUERY.match?(sql)
20
- rescue ArgumentError # Invalid encoding
21
- !READ_QUERY.match?(sql.b)
22
- end
23
-
24
- def explain(arel, binds = [])
25
- sql = "EXPLAIN #{to_sql(arel, binds)}"
26
- start = Process.clock_gettime(Process::CLOCK_MONOTONIC)
27
- result = exec_query(sql, "EXPLAIN", binds)
28
- elapsed = Process.clock_gettime(Process::CLOCK_MONOTONIC) - start
11
+ # ActiveRecord <= 6.1 support
12
+ if ActiveRecord.version < ::Gem::Version.new('7.0.a')
13
+ class DatabaseConnectionError < ConnectionNotEstablished
14
+ def initialize(message = nil)
15
+ super(message || "Database connection error")
16
+ end
29
17
 
30
- MySQL::ExplainPrettyPrinter.new.pp(result, elapsed)
18
+ class << self
19
+ def hostname_error(hostname)
20
+ DatabaseConnectionError.new(<<~MSG)
21
+ There is an issue connecting with your hostname: #{hostname}.\n
22
+ Please check your database configuration and ensure there is a valid connection to your database.
23
+ MSG
31
24
  end
32
25
 
33
- def exec_query(sql, name = "SQL", binds = [], prepare: false, async: false)
34
- result = execute(sql, name, async: async)
35
- ActiveRecord::Result.new(result.fields, result.to_a)
26
+ def username_error(username)
27
+ DatabaseConnectionError.new(<<~MSG)
28
+ There is an issue connecting to your database with your username/password, username: #{username}.\n
29
+ Please check your database configuration to ensure the username/password are valid.
30
+ MSG
36
31
  end
32
+ end
33
+ end
37
34
 
38
- alias exec_without_stmt exec_query
35
+ NoDatabaseError.class_exec do
36
+ def self.db_error(db_name)
37
+ NoDatabaseError.new(<<~MSG)
38
+ We could not find your database: #{db_name}. Available database configurations can be found in config/database.yml file.
39
39
 
40
- def exec_insert(sql, name, binds, pk = nil, sequence_name = nil)
41
- execute(to_sql(sql, binds), name)
42
- end
40
+ To resolve this error:
43
41
 
44
- def exec_delete(sql, name = nil, binds = [])
45
- result = execute(to_sql(sql, binds), name)
46
- result.affected_rows
47
- end
42
+ - Did you create the database for this app, or delete it? You may need to create your database.
43
+ - Has the database name changed? Check your database.yml config has the correct database name.
48
44
 
49
- alias :exec_update :exec_delete
45
+ To create your database, run:\n\n bin/rails db:create
46
+ MSG
47
+ end
48
+ end
49
+ end
50
50
 
51
- private
52
- def last_inserted_id(result)
53
- result.last_insert_id
54
- end
51
+ if ActiveRecord.version < ::Gem::Version.new('6.1.a') # ActiveRecord <= 6.0 support
52
+ require "active_record/database_configurations"
53
+ DatabaseConfigurations.class_exec do
54
+ def resolve(config) # :nodoc:
55
+ @resolver ||= ::ActiveRecord::ConnectionAdapters::ConnectionSpecification::Resolver.new(::ActiveRecord::Base.configurations)
56
+ @resolver.resolve(config)
55
57
  end
58
+ end
59
+ end
56
60
 
61
+ module ConnectionAdapters
62
+ class TrilogyAdapter < ::ActiveRecord::ConnectionAdapters::AbstractMysqlAdapter
57
63
  ER_BAD_DB_ERROR = 1049
58
64
  ER_ACCESS_DENIED_ERROR = 1045
59
65
 
60
66
  ADAPTER_NAME = "Trilogy"
61
67
 
62
- include DatabaseStatements
68
+ include Trilogy::DatabaseStatements
63
69
 
64
70
  SSL_MODES = {
65
- SSL_MODE_DISABLED: Trilogy::SSL_DISABLED,
66
- SSL_MODE_PREFERRED: Trilogy::SSL_PREFERRED_NOVERIFY,
67
- SSL_MODE_REQUIRED: Trilogy::SSL_REQUIRED_NOVERIFY,
68
- SSL_MODE_VERIFY_CA: Trilogy::SSL_VERIFY_CA,
69
- SSL_MODE_VERIFY_IDENTITY: Trilogy::SSL_VERIFY_IDENTITY
71
+ SSL_MODE_DISABLED: ::Trilogy::SSL_DISABLED,
72
+ SSL_MODE_PREFERRED: ::Trilogy::SSL_PREFERRED_NOVERIFY,
73
+ SSL_MODE_REQUIRED: ::Trilogy::SSL_REQUIRED_NOVERIFY,
74
+ SSL_MODE_VERIFY_CA: ::Trilogy::SSL_VERIFY_CA,
75
+ SSL_MODE_VERIFY_IDENTITY: ::Trilogy::SSL_VERIFY_IDENTITY
70
76
  }.freeze
71
77
 
72
78
  class << self
73
79
  def new_client(config)
74
80
  config[:ssl_mode] = parse_ssl_mode(config[:ssl_mode]) if config[:ssl_mode]
75
81
  ::Trilogy.new(config)
76
- rescue Trilogy::ConnectionError, Trilogy::ProtocolError => error
82
+ rescue ::Trilogy::ConnectionError, ::Trilogy::ProtocolError => error
77
83
  raise translate_connect_error(config, error)
78
84
  end
79
85
 
@@ -81,7 +87,6 @@ module ActiveRecord
81
87
  return mode if mode.is_a? Integer
82
88
 
83
89
  m = mode.to_s.upcase
84
- # enable Mysql2 client compatibility
85
90
  m = "SSL_MODE_#{m}" unless m.start_with? "SSL_MODE_"
86
91
 
87
92
  SSL_MODES.fetch(m.to_sym, mode)
@@ -94,15 +99,38 @@ module ActiveRecord
94
99
  when ER_ACCESS_DENIED_ERROR
95
100
  ActiveRecord::DatabaseConnectionError.username_error(config[:username])
96
101
  else
97
- if error.message.match?(/TRILOGY_DNS_ERROR/)
102
+ if error.message.include?("TRILOGY_DNS_ERROR")
98
103
  ActiveRecord::DatabaseConnectionError.hostname_error(config[:host])
99
104
  else
100
105
  ActiveRecord::ConnectionNotEstablished.new(error.message)
101
106
  end
102
107
  end
103
108
  end
109
+
110
+ private
111
+ def initialize_type_map(m)
112
+ super if ActiveRecord.version >= ::Gem::Version.new('7.0.a')
113
+
114
+ m.register_type(%r(char)i) do |sql_type|
115
+ limit = extract_limit(sql_type)
116
+ Type.lookup(:string, adapter: :trilogy, limit: limit)
117
+ end
118
+
119
+ m.register_type %r(^enum)i, Type.lookup(:string, adapter: :trilogy)
120
+ m.register_type %r(^set)i, Type.lookup(:string, adapter: :trilogy)
121
+ end
104
122
  end
105
123
 
124
+ def initialize(connection, logger, connection_options, config)
125
+ super
126
+ # Ensure that we're treating prepared_statements in the same way that Rails 7.1 does
127
+ @prepared_statements = self.class.type_cast_config_to_boolean(
128
+ @config.fetch(:prepared_statements) { default_prepared_statements }
129
+ )
130
+ end
131
+
132
+ TYPE_MAP = Type::TypeMap.new.tap { |m| initialize_type_map(m) }
133
+
106
134
  def supports_json?
107
135
  !mariadb? && database_version >= "5.7.8"
108
136
  end
@@ -128,12 +156,41 @@ module ActiveRecord
128
156
  end
129
157
 
130
158
  def quote_string(string)
131
- with_raw_connection(allow_retry: true, uses_transaction: false) do |conn|
159
+ with_trilogy_connection(allow_retry: true, uses_transaction: false) do |conn|
132
160
  conn.escape(string)
133
161
  end
134
162
  end
135
163
 
164
+ def connect!
165
+ verify!
166
+ self
167
+ end
168
+
169
+ def reconnect!
170
+ @lock.synchronize do
171
+ disconnect!
172
+ connect
173
+ end
174
+ end
175
+
176
+ def with_trilogy_connection(uses_transaction: true, **_kwargs)
177
+ @lock.synchronize do
178
+ verify!
179
+ materialize_transactions if uses_transaction
180
+ yield connection
181
+ end
182
+ end
183
+
184
+ def execute(sql, name = nil, allow_retry: false, **kwargs)
185
+ sql = transform_query(sql)
186
+ check_if_write_query(sql)
187
+
188
+ raw_execute(sql, name, allow_retry: allow_retry, **kwargs)
189
+ end
190
+
136
191
  def active?
192
+ return false if connection&.closed?
193
+
137
194
  connection&.ping || false
138
195
  rescue ::Trilogy::Error
139
196
  false
@@ -150,39 +207,41 @@ module ActiveRecord
150
207
  end
151
208
 
152
209
  def discard!
153
- self.connection = nil
210
+ super
211
+ unless connection.nil?
212
+ connection.discard!
213
+ self.connection = nil
214
+ end
154
215
  end
155
216
 
156
- def each_hash(result)
157
- return to_enum(:each_hash, result) unless block_given?
158
-
159
- keys = result.fields.map(&:to_sym)
160
- result.rows.each do |row|
161
- hash = {}
162
- idx = 0
163
- row.each do |value|
164
- hash[keys[idx]] = value
165
- idx += 1
166
- end
167
- yield hash
217
+ private
218
+ def text_type?(type)
219
+ TYPE_MAP.lookup(type).is_a?(Type::String) || TYPE_MAP.lookup(type).is_a?(Type::Text)
168
220
  end
169
221
 
170
- nil
171
- end
222
+ def each_hash(result)
223
+ return to_enum(:each_hash, result) unless block_given?
172
224
 
173
- def error_number(exception)
174
- exception.error_code if exception.respond_to?(:error_code)
175
- end
225
+ keys = result.fields.map(&:to_sym)
226
+ result.rows.each do |row|
227
+ hash = {}
228
+ idx = 0
229
+ row.each do |value|
230
+ hash[keys[idx]] = value
231
+ idx += 1
232
+ end
233
+ yield hash
234
+ end
176
235
 
177
- private
178
- def connection
179
- @raw_connection
236
+ nil
180
237
  end
181
238
 
182
- def connection=(conn)
183
- @raw_connection = conn
239
+ def error_number(exception)
240
+ exception.error_code if exception.respond_to?(:error_code)
184
241
  end
185
242
 
243
+ attr_accessor :connection
244
+
186
245
  def connect
187
246
  self.connection = self.class.new_client(@config)
188
247
  end
@@ -193,26 +252,85 @@ module ActiveRecord
193
252
  connect
194
253
  end
195
254
 
196
- def sync_timezone_changes(conn)
197
- # Sync any changes since connection last established.
198
- if default_timezone == :local
199
- conn.query_flags |= ::Trilogy::QUERY_FLAGS_LOCAL_TIMEZONE
255
+ def execute_batch(statements, name = nil)
256
+ statements = statements.map { |sql| transform_query(sql) } if respond_to?(:transform_query)
257
+ combine_multi_statements(statements).each do |statement|
258
+ with_trilogy_connection do |conn|
259
+ raw_execute(statement, name)
260
+ conn.next_result while conn.more_results_exist?
261
+ end
262
+ end
263
+ end
264
+
265
+ def multi_statements_enabled?
266
+ !!@config[:multi_statement]
267
+ end
268
+
269
+ def with_multi_statements
270
+ if multi_statements_enabled?
271
+ return yield
272
+ end
273
+
274
+ with_trilogy_connection do |conn|
275
+ conn.set_server_option(::Trilogy::SET_SERVER_MULTI_STATEMENTS_ON)
276
+
277
+ yield
278
+ ensure
279
+ conn.set_server_option(::Trilogy::SET_SERVER_MULTI_STATEMENTS_OFF)
280
+ end
281
+ end
282
+
283
+ def combine_multi_statements(total_sql)
284
+ total_sql.each_with_object([]) do |sql, total_sql_chunks|
285
+ previous_packet = total_sql_chunks.last
286
+ if max_allowed_packet_reached?(sql, previous_packet)
287
+ total_sql_chunks << +sql
288
+ else
289
+ previous_packet << ";\n"
290
+ previous_packet << sql
291
+ end
292
+ end
293
+ end
294
+
295
+ def max_allowed_packet_reached?(current_packet, previous_packet)
296
+ if current_packet.bytesize > max_allowed_packet
297
+ raise ActiveRecordError,
298
+ "Fixtures set is too large #{current_packet.bytesize}. Consider increasing the max_allowed_packet variable."
299
+ elsif previous_packet.nil?
300
+ true
200
301
  else
201
- conn.query_flags &= ~::Trilogy::QUERY_FLAGS_LOCAL_TIMEZONE
302
+ (current_packet.bytesize + previous_packet.bytesize + 2) > max_allowed_packet
202
303
  end
203
304
  end
204
305
 
306
+ def max_allowed_packet
307
+ @max_allowed_packet ||= show_variable("max_allowed_packet")
308
+ end
309
+
205
310
  def full_version
206
311
  schema_cache.database_version.full_version_string
207
312
  end
208
313
 
209
314
  def get_full_version
210
- with_raw_connection(allow_retry: true, uses_transaction: false) do |conn|
315
+ with_trilogy_connection(allow_retry: true, uses_transaction: false) do |conn|
211
316
  conn.server_info[:version]
212
317
  end
213
318
  end
214
319
 
320
+ if ActiveRecord.version < ::Gem::Version.new('7.0.a') # For ActiveRecord <= 6.1
321
+ def default_timezone
322
+ ActiveRecord::Base.default_timezone
323
+ end
324
+ else # For ActiveRecord 7.0
325
+ def default_timezone
326
+ ActiveRecord.default_timezone
327
+ end
328
+ end
329
+
215
330
  def translate_exception(exception, message:, sql:, binds:)
331
+ if exception.is_a?(::Trilogy::TimeoutError) && !exception.error_code
332
+ return ActiveRecord::AdapterTimeout.new(message, sql: sql, binds: binds)
333
+ end
216
334
  error_code = exception.error_code if exception.respond_to?(:error_code)
217
335
 
218
336
  ::TrilogyAdapter::LostConnectionExceptionTranslator.
@@ -222,6 +340,61 @@ module ActiveRecord
222
340
  def default_prepared_statements
223
341
  false
224
342
  end
343
+
344
+ if ActiveRecord.version < ::Gem::Version.new('6.1.a') # For ActiveRecord <= 6.0
345
+ def prepared_statements?
346
+ @prepared_statements && !prepared_statements_disabled_cache.include?(object_id)
347
+ end
348
+ end
349
+
350
+ ActiveRecord::Type.register(:immutable_string, adapter: :trilogy) do |_, **args|
351
+ Type::ImmutableString.new(true: "1", false: "0", **args)
352
+ end
353
+
354
+ ActiveRecord::Type.register(:string, adapter: :trilogy) do |_, **args|
355
+ Type::String.new(true: "1", false: "0", **args)
356
+ end
357
+
358
+ ActiveRecord::Type.register(:unsigned_integer, Type::UnsignedInteger, adapter: :trilogy)
359
+ end
360
+
361
+ if ActiveRecord.version < ::Gem::Version.new('6.1.a') # For ActiveRecord <= 6.0
362
+ class PoolConfig < ConnectionSpecification
363
+ def initialize(connection_class, db_config, *args)
364
+ super("primary", db_config, "#{db_config[:adapter]}_connection")
365
+ end
366
+ end
367
+
368
+ SchemaCache.class_exec do
369
+ def self.load_from(filename)
370
+ return unless File.file?(filename)
371
+
372
+ read(filename) do |file|
373
+ if filename.include?(".dump")
374
+ Marshal.load(file)
375
+ else
376
+ if YAML.respond_to?(:unsafe_load)
377
+ YAML.unsafe_load(file)
378
+ else
379
+ YAML.load(file)
380
+ end
381
+ end
382
+ end
383
+ end
384
+
385
+ def self.read(filename, &block)
386
+ if File.extname(filename) == ".gz"
387
+ Zlib::GzipReader.open(filename) { |gz|
388
+ yield gz.read
389
+ }
390
+ else
391
+ yield File.read(filename)
392
+ end
393
+ end
394
+ private_class_method :read
395
+ end
225
396
  end
397
+
398
+ ActiveSupport.run_load_hooks(:active_record_trilogyadapter, TrilogyAdapter)
226
399
  end
227
400
  end
@@ -1,45 +1,54 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ if ActiveRecord.version < ::Gem::Version.new('6.1.a') # ActiveRecord <= 6.0 support
4
+ module ::ActiveRecord
5
+ class QueryAborted < ::ActiveRecord::StatementInvalid
6
+ end
7
+ class AdapterTimeout < ::ActiveRecord::QueryAborted
8
+ end
9
+ end
10
+ end
11
+
3
12
  module TrilogyAdapter
4
13
  module Errors
5
14
  # ServerShutdown will be raised when the database server was shutdown.
6
- class ServerShutdown < ActiveRecord::ConnectionFailed
15
+ class ServerShutdown < ::ActiveRecord::QueryAborted
7
16
  end
8
17
 
9
18
  # ServerLost will be raised when the database connection was lost.
10
- class ServerLost < ActiveRecord::ConnectionFailed
19
+ class ServerLost < ::ActiveRecord::QueryAborted
11
20
  end
12
21
 
13
22
  # ServerGone will be raised when the database connection is gone.
14
- class ServerGone < ActiveRecord::ConnectionFailed
23
+ class ServerGone < ::ActiveRecord::QueryAborted
15
24
  end
16
25
 
17
26
  # BrokenPipe will be raised when a system process connection fails.
18
- class BrokenPipe < ActiveRecord::ConnectionFailed
27
+ class BrokenPipe < ::ActiveRecord::QueryAborted
19
28
  end
20
29
 
21
30
  # SocketError will be raised when Ruby encounters a network error.
22
- class SocketError < ActiveRecord::ConnectionFailed
31
+ class SocketError < ::ActiveRecord::QueryAborted
23
32
  end
24
33
 
25
34
  # ConnectionResetByPeer will be raised when a network connection is closed
26
35
  # outside the sytstem process.
27
- class ConnectionResetByPeer < ActiveRecord::ConnectionFailed
36
+ class ConnectionResetByPeer < ::ActiveRecord::QueryAborted
28
37
  end
29
38
 
30
39
  # ClosedConnection will be raised when the Trilogy encounters a closed
31
40
  # connection.
32
- class ClosedConnection < ActiveRecord::ConnectionFailed
41
+ class ClosedConnection < ::ActiveRecord::QueryAborted
33
42
  end
34
43
 
35
44
  # InvalidSequenceId will be raised when Trilogy ecounters an invalid sequence
36
45
  # id.
37
- class InvalidSequenceId < ActiveRecord::ConnectionFailed
46
+ class InvalidSequenceId < ::ActiveRecord::QueryAborted
38
47
  end
39
48
 
40
49
  # UnexpectedPacket will be raised when Trilogy ecounters an unexpected
41
50
  # response packet.
42
- class UnexpectedPacket < ActiveRecord::ConnectionFailed
51
+ class UnexpectedPacket < ::ActiveRecord::QueryAborted
43
52
  end
44
53
  end
45
54
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module TrilogyAdapter
4
- VERSION = "2.2.0"
4
+ VERSION = "3.1.0"
5
5
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: activerecord-trilogy-adapter
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.2.0
4
+ version: 3.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - GitHub Engineering
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2023-03-02 00:00:00.000000000 Z
11
+ date: 2023-07-07 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: trilogy
@@ -16,26 +16,32 @@ dependencies:
16
16
  requirements:
17
17
  - - ">="
18
18
  - !ruby/object:Gem::Version
19
- version: 2.3.0
19
+ version: 2.4.0
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
24
  - - ">="
25
25
  - !ruby/object:Gem::Version
26
- version: 2.3.0
26
+ version: 2.4.0
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: activerecord
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
- - - "~>"
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: 6.0.a
34
+ - - "<"
32
35
  - !ruby/object:Gem::Version
33
36
  version: 7.1.a
34
37
  type: :runtime
35
38
  prerelease: false
36
39
  version_requirements: !ruby/object:Gem::Requirement
37
40
  requirements:
38
- - - "~>"
41
+ - - ">="
42
+ - !ruby/object:Gem::Version
43
+ version: 6.0.a
44
+ - - "<"
39
45
  - !ruby/object:Gem::Version
40
46
  version: 7.1.a
41
47
  - !ruby/object:Gem::Dependency
@@ -105,6 +111,7 @@ extra_rdoc_files:
105
111
  files:
106
112
  - LICENSE.md
107
113
  - README.md
114
+ - lib/active_record/connection_adapters/trilogy/database_statements.rb
108
115
  - lib/active_record/connection_adapters/trilogy_adapter.rb
109
116
  - lib/active_record/tasks/trilogy_database_tasks.rb
110
117
  - lib/activerecord-trilogy-adapter.rb
@@ -113,13 +120,13 @@ files:
113
120
  - lib/trilogy_adapter/lost_connection_exception_translator.rb
114
121
  - lib/trilogy_adapter/railtie.rb
115
122
  - lib/trilogy_adapter/version.rb
116
- homepage: https://github.com/github/activerecord-trilogy-adapter
123
+ homepage: https://github.com/trilogy-libraries/activerecord-trilogy-adapter
117
124
  licenses:
118
125
  - MIT
119
126
  metadata:
120
- source_code_uri: https://github.com/github/activerecord-trilogy-adapter
121
- changelog_uri: https://github.com/github/activerecord-trilogy-adapter/blob/master/CHANGELOG.md
122
- bug_tracker_uri: https://github.com/github/activerecord-trilogy-adapter/issues
127
+ source_code_uri: https://github.com/trilogy-libraries/activerecord-trilogy-adapter
128
+ changelog_uri: https://github.com/trilogy-libraries/activerecord-trilogy-adapter/blob/master/CHANGELOG.md
129
+ bug_tracker_uri: https://github.com/trilogy-libraries/activerecord-trilogy-adapter/issues
123
130
  post_install_message:
124
131
  rdoc_options: []
125
132
  require_paths:
@@ -138,5 +145,5 @@ requirements: []
138
145
  rubygems_version: 3.2.33
139
146
  signing_key:
140
147
  specification_version: 4
141
- summary: Active Record adapter for https://github.com/github/trilogy.
148
+ summary: Active Record adapter for https://github.com/trilogy-libraries/trilogy.
142
149
  test_files: []