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 +4 -4
- data/README.md +7 -3
- data/lib/active_record/connection_adapters/trilogy_adapter.rb +131 -39
- data/lib/trilogy_adapter/connection.rb +5 -1
- data/lib/trilogy_adapter/errors.rb +9 -9
- data/lib/trilogy_adapter/lost_connection_exception_translator.rb +4 -2
- data/lib/trilogy_adapter/version.rb +1 -1
- metadata +19 -14
- data/lib/trilogy_adapter/rails/dbconsole.rb +0 -21
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 778687330e4ff0e83f8cf02ea27808b9e7197c625312611c0dd004d17627a29e
|
4
|
+
data.tar.gz: f3ddf11ab50accd31b5bd3a4b41899a781f4ac04555739d1e65eff3e884b8b38
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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/
|
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.
|
9
|
-
- [Trilogy](https://github.com/
|
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::
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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::
|
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::
|
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::
|
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::
|
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::
|
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::
|
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::
|
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::
|
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::
|
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
|
41
|
-
|
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
|
|
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:
|
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:
|
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.
|
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.
|
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.
|
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.
|
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/
|
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/
|
122
|
-
changelog_uri: https://github.com/
|
123
|
-
bug_tracker_uri: https://github.com/
|
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/
|
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
|