Class: ActiveRecord::ConnectionAdapters::TrilogyAdapter

Inherits:
AbstractMysqlAdapter
  • Object
show all
Includes:
ActiveRecord::ConnectionAdapters::Trilogy::DatabaseStatements
Defined in:
lib/active_record/connection_adapters/trilogy_adapter.rb

Constant Summary collapse

ER_BAD_DB_ERROR =
1049
ER_DBACCESS_DENIED_ERROR =
1044
ER_ACCESS_DENIED_ERROR =
1045
ER_SERVER_SHUTDOWN =
1053
ADAPTER_NAME =
"Trilogy"
SSL_MODES =
{
  SSL_MODE_DISABLED: ::Trilogy::SSL_DISABLED,
  SSL_MODE_PREFERRED: ::Trilogy::SSL_PREFERRED_NOVERIFY,
  SSL_MODE_REQUIRED: ::Trilogy::SSL_REQUIRED_NOVERIFY,
  SSL_MODE_VERIFY_CA: ::Trilogy::SSL_VERIFY_CA,
  SSL_MODE_VERIFY_IDENTITY: ::Trilogy::SSL_VERIFY_IDENTITY
}.freeze
TYPE_MAP =
Type::TypeMap.new.tap { |m| initialize_type_map(m) }

Class Method Summary collapse

Instance Method Summary collapse

Methods included from ActiveRecord::ConnectionAdapters::Trilogy::DatabaseStatements

#build_explain_clause, #exec_delete, #exec_insert, #exec_query, #execute, #explain, #high_precision_current_timestamp, #internal_exec_query, #select_all, #write_query?

Constructor Details

#initialize(connection, logger, connection_options, config) ⇒ TrilogyAdapter

Returns a new instance of TrilogyAdapter.



157
158
159
160
161
162
163
# File 'lib/active_record/connection_adapters/trilogy_adapter.rb', line 157

def initialize(connection, logger, connection_options, config)
  super
  # Ensure that we're treating prepared_statements in the same way that Rails 7.1 does
  @prepared_statements = self.class.type_cast_config_to_boolean(
    @config.fetch(:prepared_statements) { default_prepared_statements }
  )
end

Class Method Details

.dbconsole(config, options = {}) ⇒ Object



111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
# File 'lib/active_record/connection_adapters/trilogy_adapter.rb', line 111

def dbconsole(config, options = {})
  mysql_config = if ActiveRecord.version < ::Gem::Version.new('6.1.a')
                   config.config
                 else
                   config.configuration_hash
                 end

  args = {
    host: "--host",
    port: "--port",
    socket: "--socket",
    username: "--user",
    encoding: "--default-character-set",
    sslca: "--ssl-ca",
    sslcert: "--ssl-cert",
    sslcapath: "--ssl-capath",
    sslcipher: "--ssl-cipher",
    sslkey: "--ssl-key",
    ssl_mode: "--ssl-mode"
  }.filter_map { |opt, arg| "#{arg}=#{mysql_config[opt]}" if mysql_config[opt] }

  if mysql_config[:password] && options[:include_password]
    args << "--password=#{mysql_config[:password]}"
  elsif mysql_config[:password] && !mysql_config[:password].to_s.empty?
    args << "-p"
  end

  args << mysql_config[:database]

  find_cmd_and_exec(["mysql", "mysql5"], *args)
end

.find_cmd_and_exec(commands, *args) ⇒ Object

:doc:



243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
# File 'lib/active_record/connection_adapters/trilogy_adapter.rb', line 243

def self.find_cmd_and_exec(commands, *args) # :doc:
  commands = Array(commands)

  dirs_on_path = ENV["PATH"].to_s.split(File::PATH_SEPARATOR)
  unless (ext = RbConfig::CONFIG["EXEEXT"]).empty?
    commands = commands.map { |cmd| "#{cmd}#{ext}" }
  end

  full_path_command = nil
  found = commands.detect do |cmd|
    dirs_on_path.detect do |path|
      full_path_command = File.join(path, cmd)
      begin
        stat = File.stat(full_path_command)
      rescue SystemCallError
      else
        stat.file? && stat.executable?
      end
    end
  end

  if found
    exec full_path_command, *args
  else
    abort("Couldn't find database client: #{commands.join(', ')}. Check your $PATH and try again.")
  end
end

.new_client(config) ⇒ Object



80
81
82
83
84
85
# File 'lib/active_record/connection_adapters/trilogy_adapter.rb', line 80

def new_client(config)
  config[:ssl_mode] = parse_ssl_mode(config[:ssl_mode]) if config[:ssl_mode]
  ::Trilogy.new(config)
rescue ::Trilogy::ConnectionError, ::Trilogy::ProtocolError => error
  raise translate_connect_error(config, error)
end

.parse_ssl_mode(mode) ⇒ Object



87
88
89
90
91
92
93
94
# File 'lib/active_record/connection_adapters/trilogy_adapter.rb', line 87

def parse_ssl_mode(mode)
  return mode if mode.is_a? Integer

  m = mode.to_s.upcase
  m = "SSL_MODE_#{m}" unless m.start_with? "SSL_MODE_"

  SSL_MODES.fetch(m.to_sym, mode)
end

.translate_connect_error(config, error) ⇒ Object



96
97
98
99
100
101
102
103
104
105
106
107
108
109
# File 'lib/active_record/connection_adapters/trilogy_adapter.rb', line 96

def translate_connect_error(config, error)
  case error.error_code
  when ER_BAD_DB_ERROR
    ActiveRecord::NoDatabaseError.db_error(config[:database])
  when ER_ACCESS_DENIED_ERROR
    ActiveRecord::DatabaseConnectionError.username_error(config[:username])
  else
    if error.message.include?("TRILOGY_DNS_ERROR")
      ActiveRecord::DatabaseConnectionError.hostname_error(config[:host])
    else
      ActiveRecord::ConnectionNotEstablished.new(error.message)
    end
  end
end

Instance Method Details

#active?Boolean

Returns:

  • (Boolean)


217
218
219
220
221
222
223
# File 'lib/active_record/connection_adapters/trilogy_adapter.rb', line 217

def active?
  return false if connection&.closed?

  connection&.ping || false
rescue ::Trilogy::Error
  false
end

#connect!Object



197
198
199
200
# File 'lib/active_record/connection_adapters/trilogy_adapter.rb', line 197

def connect!
  verify!
  self
end

#discard!Object



235
236
237
238
239
240
241
# File 'lib/active_record/connection_adapters/trilogy_adapter.rb', line 235

def discard!
  super
  unless connection.nil?
    connection.discard!
    self.connection = nil
  end
end

#disconnect!Object



227
228
229
230
231
232
233
# File 'lib/active_record/connection_adapters/trilogy_adapter.rb', line 227

def disconnect!
  super
  unless connection.nil?
    connection.close
    self.connection = nil
  end
end

#quote_string(string) ⇒ Object



191
192
193
194
195
# File 'lib/active_record/connection_adapters/trilogy_adapter.rb', line 191

def quote_string(string)
  with_trilogy_connection(allow_retry: true, materialize_transactions: false) do |conn|
    conn.escape(string)
  end
end

#reconnect!Object Also known as: reset!



202
203
204
205
206
207
# File 'lib/active_record/connection_adapters/trilogy_adapter.rb', line 202

def reconnect!
  @lock.synchronize do
    disconnect!
    connect
  end
end

#savepoint_errors_invalidate_transactions?Boolean

Returns:

  • (Boolean)


183
184
185
# File 'lib/active_record/connection_adapters/trilogy_adapter.rb', line 183

def savepoint_errors_invalidate_transactions?
  true
end

#supports_comments?Boolean

Returns:

  • (Boolean)


171
172
173
# File 'lib/active_record/connection_adapters/trilogy_adapter.rb', line 171

def supports_comments?
  true
end

#supports_comments_in_create?Boolean

Returns:

  • (Boolean)


175
176
177
# File 'lib/active_record/connection_adapters/trilogy_adapter.rb', line 175

def supports_comments_in_create?
  true
end

#supports_json?Boolean

Returns:

  • (Boolean)


167
168
169
# File 'lib/active_record/connection_adapters/trilogy_adapter.rb', line 167

def supports_json?
  !mariadb? && database_version >= "5.7.8"
end

#supports_lazy_transactions?Boolean

Returns:

  • (Boolean)


187
188
189
# File 'lib/active_record/connection_adapters/trilogy_adapter.rb', line 187

def supports_lazy_transactions?
  true
end

#supports_savepoints?Boolean

Returns:

  • (Boolean)


179
180
181
# File 'lib/active_record/connection_adapters/trilogy_adapter.rb', line 179

def supports_savepoints?
  true
end

#with_trilogy_connection(materialize_transactions: true, **_kwargs) ⇒ Object



209
210
211
212
213
214
215
# File 'lib/active_record/connection_adapters/trilogy_adapter.rb', line 209

def with_trilogy_connection(materialize_transactions: true, **_kwargs)
  @lock.synchronize do
    verify!
    self.materialize_transactions if materialize_transactions
    yield connection
  end
end