activerecord-trilogy-adapter 2.2.0 → 3.1.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: 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: []