Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,5 +11,6 @@
- [#1397](https://github.com/rails-sqlserver/activerecord-sqlserver-adapter/pull/1397) Treat "DBPROCESS is dead or not enabled" as ConnectionNotEstablished.
- [#1406](https://github.com/rails-sqlserver/activerecord-sqlserver-adapter/pull/1406) Stop deserializing column defaults.
- [#1405](https://github.com/rails-sqlserver/activerecord-sqlserver-adapter/pull/1405) Fix `insert_all`/`upsert_all` for single character, temporary, non-ASCII and three part table names, and stop an aliased target being included in the `MERGE` table name.
- [#1412](https://github.com/rails-sqlserver/activerecord-sqlserver-adapter/pull/1412) Use TinyTDS `Client#ping(timeout:)` from `active?` when available.

Please check [8-1-stable](https://github.com/rails-sqlserver/activerecord-sqlserver-adapter/blob/8-1-stable/CHANGELOG.md) for previous changes.
32 changes: 31 additions & 1 deletion lib/active_record/connection_adapters/sqlserver_adapter.rb
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,11 @@ class SQLServerAdapter < AbstractAdapter
# Default precision for 'time' (See https://docs.microsoft.com/en-us/sql/t-sql/data-types/time-transact-sql)
DEFAULT_TIME_PRECISION = 7

# FreeTDS-bounded checkout ping timeout (seconds) when TinyTDS provides
# Client#ping. Override with config :ping_timeout (0 disables ping).
# See rails-sqlserver/tiny_tds#609 and activerecord-sqlserver-adapter#1396.
DEFAULT_PING_TIMEOUT = 2

attr_reader :spid

cattr_accessor :cs_equality_operator, instance_accessor: false
Expand Down Expand Up @@ -143,6 +148,13 @@ def initialize(...)
@config[:appname] = self.class.rails_application_name unless @config[:appname]
@config[:login_timeout] = @config[:login_timeout].present? ? @config[:login_timeout].to_i : nil
@config[:timeout] = @config[:timeout].present? ? @config[:timeout].to_i / 1000 : nil
# 0 disables checkout ping; nil uses DEFAULT_PING_TIMEOUT. Avoid .present?
# so an explicit 0 is not treated as missing.
@config[:ping_timeout] = if @config.key?(:ping_timeout) && !@config[:ping_timeout].nil?
@config[:ping_timeout].to_i
else
DEFAULT_PING_TIMEOUT
end
@config[:encoding] = @config[:encoding].present? ? @config[:encoding] : nil

@connection_parameters ||= @config
Expand Down Expand Up @@ -285,7 +297,14 @@ def disable_referential_integrity
# === Abstract Adapter (Connection Management) ================== #

def active?
if @raw_connection&.active?
return false unless @raw_connection

if raw_connection_ping_enabled?
return false unless @raw_connection.ping(timeout: ping_timeout_seconds)

verified!
true
elsif @raw_connection.active?
verified!
true
end
Expand Down Expand Up @@ -518,6 +537,17 @@ def connection_errors
end
end

def raw_connection_ping_enabled?
@raw_connection.respond_to?(:ping) && ping_timeout_seconds.positive?
end

def ping_timeout_seconds
seconds = @config[:ping_timeout]
return DEFAULT_PING_TIMEOUT if seconds.nil?

seconds.to_i
end

def initialize_dateformatter
@database_dateformat = user_options_dateformat
a, b, c = @database_dateformat.each_char.to_a
Expand Down
Loading