activerecord-trilogy-adapter 2.1.0 → 3.0.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: f6012f06cd5bd29a7bd180354fd0e65c3fd11784a6a7483fac9599d87baa1b68
4
- data.tar.gz: bde2129ca1f647d6b7308c131d00ae012d614ad4aba36450f16fd3551bc303ce
3
+ metadata.gz: 778687330e4ff0e83f8cf02ea27808b9e7197c625312611c0dd004d17627a29e
4
+ data.tar.gz: f3ddf11ab50accd31b5bd3a4b41899a781f4ac04555739d1e65eff3e884b8b38
5
5
  SHA512:
6
- metadata.gz: 0ae12198df3991bccc1a17a983050457b2483d33f40078d5bd4c99a2d475d5fbdb84a2510c0beb0db65c9ebb4e431e12115ab2830c0cd5901a75cea3dfd7f75a
7
- data.tar.gz: 0aed27beca07c98b513a092345b125129999f5ec0180ee9df0c78b39348c73be71ef0ad78448a644733f8966636f8059ec43aa248b247e66fa7cfda2cb3bdae8
6
+ metadata.gz: 7b2e8b370f301aeda40bef4e1a66c16dc0351b245a5c967341a22e1ab05830e4e11d5cd1de2de2e38a246cbd5fb492e27d8e906770d4484707512a34e9d8430c
7
+ data.tar.gz: 3471e795e4942858134083a06f632da5afebb69c60a87001631486c79ecb81dc3f90e5c5cbdf5eb408c48ca125f47055ca8c08c0af945324e1043aa7996b104e
data/README.md CHANGED
@@ -1,12 +1,16 @@
1
1
  # Trilogy Adapter
2
2
 
3
- Active Record database adapter for [Trilogy](https://github.com/github/trilogy)
3
+ Active Record database adapter for [Trilogy](https://github.com/trilogy-libraries/trilogy)
4
+
5
+ This gem offers Trilogy support for versions of ActiveRecord prior to 7.1. Currently supports:
6
+
7
+ - Rails v7.0.x
4
8
 
5
9
  ## Requirements
6
10
 
7
11
  - [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
12
+ - [Active Record](https://github.com/rails/rails) 7.0.x
13
+ - [Trilogy](https://github.com/trilogy-libraries/trilogy) 2.4.0 or higher
10
14
 
11
15
  ## Setup
12
16
 
@@ -15,6 +15,9 @@ module ActiveRecord
15
15
  ) # :nodoc:
16
16
  private_constant :READ_QUERY
17
17
 
18
+ HIGH_PRECISION_CURRENT_TIMESTAMP = Arel.sql("CURRENT_TIMESTAMP(6)").freeze # :nodoc:
19
+ private_constant :HIGH_PRECISION_CURRENT_TIMESTAMP
20
+
18
21
  def write_query?(sql) # :nodoc:
19
22
  !READ_QUERY.match?(sql)
20
23
  rescue ArgumentError # Invalid encoding
@@ -30,13 +33,6 @@ module ActiveRecord
30
33
  MySQL::ExplainPrettyPrinter.new.pp(result, elapsed)
31
34
  end
32
35
 
33
- def execute(sql, name = nil, async: false)
34
- sql = transform_query(sql)
35
- check_if_write_query(sql)
36
-
37
- raw_execute(sql, name, async: async)
38
- end
39
-
40
36
  def exec_query(sql, name = "SQL", binds = [], prepare: false, async: false)
41
37
  result = execute(sql, name, async: async)
42
38
  ActiveRecord::Result.new(result.fields, result.to_a)
@@ -55,6 +51,10 @@ module ActiveRecord
55
51
 
56
52
  alias :exec_update :exec_delete
57
53
 
54
+ def high_precision_current_timestamp
55
+ HIGH_PRECISION_CURRENT_TIMESTAMP
56
+ end
57
+
58
58
  private
59
59
  def last_inserted_id(result)
60
60
  result.last_insert_id
@@ -63,8 +63,6 @@ module ActiveRecord
63
63
 
64
64
  ER_BAD_DB_ERROR = 1049
65
65
  ER_ACCESS_DENIED_ERROR = 1045
66
- ER_CONN_HOST_ERROR = 2003
67
- ER_UNKNOWN_HOST_ERROR = 2005
68
66
 
69
67
  ADAPTER_NAME = "Trilogy"
70
68
 
@@ -82,7 +80,7 @@ module ActiveRecord
82
80
  def new_client(config)
83
81
  config[:ssl_mode] = parse_ssl_mode(config[:ssl_mode]) if config[:ssl_mode]
84
82
  ::Trilogy.new(config)
85
- rescue Trilogy::DatabaseError => error
83
+ rescue Trilogy::ConnectionError, Trilogy::ProtocolError => error
86
84
  raise translate_connect_error(config, error)
87
85
  end
88
86
 
@@ -102,14 +100,24 @@ module ActiveRecord
102
100
  ActiveRecord::NoDatabaseError.db_error(config[:database])
103
101
  when ER_ACCESS_DENIED_ERROR
104
102
  ActiveRecord::DatabaseConnectionError.username_error(config[:username])
105
- when ER_CONN_HOST_ERROR, ER_UNKNOWN_HOST_ERROR
106
- ActiveRecord::DatabaseConnectionError.hostname_error(config[:host])
107
103
  else
108
- ActiveRecord::ConnectionNotEstablished.new(error.message)
104
+ if error.message.match?(/TRILOGY_DNS_ERROR/)
105
+ ActiveRecord::DatabaseConnectionError.hostname_error(config[:host])
106
+ else
107
+ ActiveRecord::ConnectionNotEstablished.new(error.message)
108
+ end
109
109
  end
110
110
  end
111
111
  end
112
112
 
113
+ def initialize(connection, logger, connection_options, config)
114
+ super
115
+ # Ensure that we're treating prepared_statements in the same way that Rails 7.1 does
116
+ @prepared_statements = self.class.type_cast_config_to_boolean(
117
+ @config.fetch(:prepared_statements) { default_prepared_statements }
118
+ )
119
+ end
120
+
113
121
  def supports_json?
114
122
  !mariadb? && database_version >= "5.7.8"
115
123
  end
@@ -135,12 +143,53 @@ module ActiveRecord
135
143
  end
136
144
 
137
145
  def quote_string(string)
138
- with_raw_connection(allow_retry: true, uses_transaction: false) do |conn|
146
+ with_trilogy_connection(allow_retry: true, uses_transaction: false) do |conn|
139
147
  conn.escape(string)
140
148
  end
141
149
  end
142
150
 
151
+ def connect!
152
+ verify!
153
+ self
154
+ end
155
+
156
+ def reconnect!
157
+ @lock.synchronize do
158
+ disconnect!
159
+ connect
160
+ rescue StandardError => original_exception
161
+ raise translate_exception_class(original_exception, nil, nil)
162
+ end
163
+ end
164
+
165
+ def with_trilogy_connection(uses_transaction: true, **_kwargs)
166
+ @lock.synchronize do
167
+ verify!
168
+ materialize_transactions if uses_transaction
169
+ yield connection
170
+ end
171
+ end
172
+
173
+ def raw_execute(sql, name, async: false, allow_retry: false, uses_transaction: true)
174
+ mark_transaction_written_if_write(sql)
175
+
176
+ log(sql, name, async: async) do
177
+ with_trilogy_connection(allow_retry: allow_retry, uses_transaction: uses_transaction) do |conn|
178
+ sync_timezone_changes(conn)
179
+ conn.query(sql)
180
+ end
181
+ end
182
+ end
183
+
184
+ def execute(sql, name = nil, **kwargs)
185
+ sql = transform_query(sql)
186
+ check_if_write_query(sql)
187
+ super
188
+ end
189
+
143
190
  def active?
191
+ return false if connection&.closed?
192
+
144
193
  connection&.ping || false
145
194
  rescue ::Trilogy::Error
146
195
  false
@@ -149,6 +198,7 @@ module ActiveRecord
149
198
  alias reset! reconnect!
150
199
 
151
200
  def disconnect!
201
+ super
152
202
  unless connection.nil?
153
203
  connection.close
154
204
  self.connection = nil
@@ -159,23 +209,6 @@ module ActiveRecord
159
209
  self.connection = nil
160
210
  end
161
211
 
162
- def raw_execute(sql, name, async: false, allow_retry: false, uses_transaction: true)
163
- mark_transaction_written_if_write(sql)
164
-
165
- log(sql, name, async: async) do
166
- with_raw_connection(allow_retry: allow_retry, uses_transaction: uses_transaction) do |conn|
167
- # Sync any changes since connection last established.
168
- if default_timezone == :local
169
- conn.query_flags |= ::Trilogy::QUERY_FLAGS_LOCAL_TIMEZONE
170
- else
171
- conn.query_flags &= ~::Trilogy::QUERY_FLAGS_LOCAL_TIMEZONE
172
- end
173
-
174
- conn.query(sql)
175
- end
176
- end
177
- end
178
-
179
212
  def each_hash(result)
180
213
  return to_enum(:each_hash, result) unless block_given?
181
214
 
@@ -198,13 +231,7 @@ module ActiveRecord
198
231
  end
199
232
 
200
233
  private
201
- def connection
202
- @raw_connection
203
- end
204
-
205
- def connection=(conn)
206
- @raw_connection = conn
207
- end
234
+ attr_accessor :connection
208
235
 
209
236
  def connect
210
237
  self.connection = self.class.new_client(@config)
@@ -212,15 +239,80 @@ module ActiveRecord
212
239
 
213
240
  def reconnect
214
241
  connection&.close
242
+ self.connection = nil
215
243
  connect
216
244
  end
217
245
 
246
+ def sync_timezone_changes(conn)
247
+ # Sync any changes since connection last established.
248
+ if ActiveRecord.default_timezone == :local
249
+ conn.query_flags |= ::Trilogy::QUERY_FLAGS_LOCAL_TIMEZONE
250
+ else
251
+ conn.query_flags &= ~::Trilogy::QUERY_FLAGS_LOCAL_TIMEZONE
252
+ end
253
+ end
254
+
255
+ def execute_batch(statements, name = nil)
256
+ statements = statements.map { |sql| transform_query(sql) }
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
301
+ else
302
+ (current_packet.bytesize + previous_packet.bytesize + 2) > max_allowed_packet
303
+ end
304
+ end
305
+
306
+ def max_allowed_packet
307
+ @max_allowed_packet ||= show_variable("max_allowed_packet")
308
+ end
309
+
218
310
  def full_version
219
311
  schema_cache.database_version.full_version_string
220
312
  end
221
313
 
222
314
  def get_full_version
223
- with_raw_connection(allow_retry: true, uses_transaction: false) do |conn|
315
+ with_trilogy_connection(allow_retry: true, uses_transaction: false) do |conn|
224
316
  conn.server_info[:version]
225
317
  end
226
318
  end
@@ -14,6 +14,10 @@ module TrilogyAdapter
14
14
  # host: "localhost",
15
15
  # database: "demo_development"
16
16
  module Connection
17
+ def trilogy_adapter_class
18
+ ActiveRecord::ConnectionAdapters::TrilogyAdapter
19
+ end
20
+
17
21
  def trilogy_connection(config)
18
22
  configuration = config.dup
19
23
 
@@ -31,7 +35,7 @@ module TrilogyAdapter
31
35
  0
32
36
  ]
33
37
 
34
- ActiveRecord::ConnectionAdapters::TrilogyAdapter.new nil, logger, options, configuration
38
+ trilogy_adapter_class.new nil, logger, options, configuration
35
39
  end
36
40
  end
37
41
  end
@@ -3,43 +3,43 @@
3
3
  module TrilogyAdapter
4
4
  module Errors
5
5
  # ServerShutdown will be raised when the database server was shutdown.
6
- class ServerShutdown < ActiveRecord::ConnectionFailed
6
+ class ServerShutdown < ::ActiveRecord::QueryAborted
7
7
  end
8
8
 
9
9
  # ServerLost will be raised when the database connection was lost.
10
- class ServerLost < ActiveRecord::ConnectionFailed
10
+ class ServerLost < ::ActiveRecord::QueryAborted
11
11
  end
12
12
 
13
13
  # ServerGone will be raised when the database connection is gone.
14
- class ServerGone < ActiveRecord::ConnectionFailed
14
+ class ServerGone < ::ActiveRecord::QueryAborted
15
15
  end
16
16
 
17
17
  # BrokenPipe will be raised when a system process connection fails.
18
- class BrokenPipe < ActiveRecord::ConnectionFailed
18
+ class BrokenPipe < ::ActiveRecord::QueryAborted
19
19
  end
20
20
 
21
21
  # SocketError will be raised when Ruby encounters a network error.
22
- class SocketError < ActiveRecord::ConnectionFailed
22
+ class SocketError < ::ActiveRecord::QueryAborted
23
23
  end
24
24
 
25
25
  # ConnectionResetByPeer will be raised when a network connection is closed
26
26
  # outside the sytstem process.
27
- class ConnectionResetByPeer < ActiveRecord::ConnectionFailed
27
+ class ConnectionResetByPeer < ::ActiveRecord::QueryAborted
28
28
  end
29
29
 
30
30
  # ClosedConnection will be raised when the Trilogy encounters a closed
31
31
  # connection.
32
- class ClosedConnection < ActiveRecord::ConnectionFailed
32
+ class ClosedConnection < ::ActiveRecord::QueryAborted
33
33
  end
34
34
 
35
35
  # InvalidSequenceId will be raised when Trilogy ecounters an invalid sequence
36
36
  # id.
37
- class InvalidSequenceId < ActiveRecord::ConnectionFailed
37
+ class InvalidSequenceId < ::ActiveRecord::QueryAborted
38
38
  end
39
39
 
40
40
  # UnexpectedPacket will be raised when Trilogy ecounters an unexpected
41
41
  # response packet.
42
- class UnexpectedPacket < ActiveRecord::ConnectionFailed
42
+ class UnexpectedPacket < ::ActiveRecord::QueryAborted
43
43
  end
44
44
  end
45
45
  end
@@ -37,8 +37,10 @@ module TrilogyAdapter
37
37
  Errors::BrokenPipe.new(message)
38
38
  when SocketError, IOError
39
39
  Errors::SocketError.new(message)
40
- when Errno::ECONNRESET
41
- Errors::ConnectionResetByPeer.new(message)
40
+ when Trilogy::ConnectionError
41
+ if message.match?(/Connection reset by peer/)
42
+ Errors::ConnectionResetByPeer.new(message)
43
+ end
42
44
  end
43
45
  end
44
46
 
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module TrilogyAdapter
4
- VERSION = "2.1.0"
4
+ VERSION = "3.0.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.1.0
4
+ version: 3.0.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: 2022-09-26 00:00:00.000000000 Z
11
+ date: 2023-06-16 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: trilogy
@@ -16,28 +16,34 @@ dependencies:
16
16
  requirements:
17
17
  - - ">="
18
18
  - !ruby/object:Gem::Version
19
- version: 2.1.1
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.1.1
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: '7.0'
34
+ - - "<"
32
35
  - !ruby/object:Gem::Version
33
- version: 7.1.a
36
+ version: 7.1a
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: '7.0'
44
+ - - "<"
39
45
  - !ruby/object:Gem::Version
40
- version: 7.1.a
46
+ version: 7.1a
41
47
  - !ruby/object:Gem::Dependency
42
48
  name: minitest
43
49
  requirement: !ruby/object:Gem::Requirement
@@ -111,16 +117,15 @@ files:
111
117
  - lib/trilogy_adapter/connection.rb
112
118
  - lib/trilogy_adapter/errors.rb
113
119
  - lib/trilogy_adapter/lost_connection_exception_translator.rb
114
- - lib/trilogy_adapter/rails/dbconsole.rb
115
120
  - lib/trilogy_adapter/railtie.rb
116
121
  - lib/trilogy_adapter/version.rb
117
- homepage: https://github.com/github/activerecord-trilogy-adapter
122
+ homepage: https://github.com/trilogy-libraries/activerecord-trilogy-adapter
118
123
  licenses:
119
124
  - MIT
120
125
  metadata:
121
- source_code_uri: https://github.com/github/activerecord-trilogy-adapter
122
- changelog_uri: https://github.com/github/activerecord-trilogy-adapter/blob/master/CHANGELOG.md
123
- bug_tracker_uri: https://github.com/github/activerecord-trilogy-adapter/issues
126
+ source_code_uri: https://github.com/trilogy-libraries/activerecord-trilogy-adapter
127
+ changelog_uri: https://github.com/trilogy-libraries/activerecord-trilogy-adapter/blob/master/CHANGELOG.md
128
+ bug_tracker_uri: https://github.com/trilogy-libraries/activerecord-trilogy-adapter/issues
124
129
  post_install_message:
125
130
  rdoc_options: []
126
131
  require_paths:
@@ -139,5 +144,5 @@ requirements: []
139
144
  rubygems_version: 3.2.33
140
145
  signing_key:
141
146
  specification_version: 4
142
- summary: Active Record adapter for https://github.com/github/trilogy.
147
+ summary: Active Record adapter for https://github.com/trilogy-libraries/trilogy.
143
148
  test_files: []
@@ -1,21 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module TrilogyAdapter
4
- module Rails
5
- module DBConsole
6
- class AdapterAdapter < SimpleDelegator
7
- def adapter
8
- "mysql"
9
- end
10
- end
11
-
12
- def db_config
13
- if super.adapter == "trilogy"
14
- AdapterAdapter.new(super)
15
- else
16
- super
17
- end
18
- end
19
- end
20
- end
21
- end