Skip to content

Eliminate missed lease_connection calls #1187

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 4 commits into from
May 23, 2024
Merged
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
70 changes: 38 additions & 32 deletions lib/active_record/tasks/sqlserver_database_tasks.rb
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ module Tasks
class SQLServerDatabaseTasks
DEFAULT_COLLATION = "SQL_Latin1_General_CP1_CI_AS"

delegate :lease_connection, :establish_connection, to: ActiveRecord::Base
delegate :with_connection, :establish_connection, to: ActiveRecord::Base

def self.using_database_configurations?
true
Expand All @@ -23,8 +23,10 @@ def initialize(configuration)

def create(master_established = false)
establish_master_connection unless master_established
lease_connection.create_database configuration.database, configuration_hash.merge(collation: default_collation)
establish_connection configuration
with_connection do |connection|
connection.create_database(configuration.database, configuration_hash.merge(collation: default_collation))
end
establish_connection(configuration)
rescue ActiveRecord::StatementInvalid => e
if /database .* already exists/i === e.message
raise DatabaseAlreadyExists
Expand All @@ -35,15 +37,15 @@ def create(master_established = false)

def drop
establish_master_connection
lease_connection.drop_database configuration.database
with_connection { |connection| connection.drop_database(configuration.database) }
end

def charset
lease_connection.charset
with_connection { |connection| connection.charset }
end

def collation
lease_connection.collation
with_connection { |connection| connection.collation }
end

def purge
Expand All @@ -56,34 +58,38 @@ def clear_active_connections!
ActiveRecord::Base.connection_handler.clear_active_connections!(:all)
end

def structure_dump(filename, extra_flags)
server_arg = "-S #{Shellwords.escape(configuration_hash[:host])}"
server_arg += ":#{Shellwords.escape(configuration_hash[:port])}" if configuration_hash[:port]
command = [
"defncopy-ttds",
server_arg,
"-D #{Shellwords.escape(configuration_hash[:database])}",
"-U #{Shellwords.escape(configuration_hash[:username])}",
"-P #{Shellwords.escape(configuration_hash[:password])}",
"-o #{Shellwords.escape(filename)}",
]
table_args = lease_connection.tables.map { |t| Shellwords.escape(t) }
command.concat(table_args)
view_args = lease_connection.views.map { |v| Shellwords.escape(v) }
command.concat(view_args)
raise "Error dumping database" unless Kernel.system(command.join(" "))

dump = File.read(filename)
dump.gsub!(/^USE .*$\nGO\n/, "") # Strip db USE statements
dump.gsub!(/^GO\n/, "") # Strip db GO statements
dump.gsub!(/nvarchar\(8000\)/, "nvarchar(4000)") # Fix nvarchar(8000) column defs
dump.gsub!(/nvarchar\(-1\)/, "nvarchar(max)") # Fix nvarchar(-1) column defs
dump.gsub!(/text\(\d+\)/, "text") # Fix text(16) column defs
File.open(filename, "w") { |file| file.puts dump }
def structure_dump(filename, _extra_flags)
with_connection do |connection|
server_arg = "-S #{Shellwords.escape(configuration_hash[:host])}"
server_arg += ":#{Shellwords.escape(configuration_hash[:port])}" if configuration_hash[:port]
command = [
"defncopy-ttds",
server_arg,
"-D #{Shellwords.escape(configuration_hash[:database])}",
"-U #{Shellwords.escape(configuration_hash[:username])}",
"-P #{Shellwords.escape(configuration_hash[:password])}",
"-o #{Shellwords.escape(filename)}",
]
table_args = connection.tables.map { |t| Shellwords.escape(t) }
command.concat(table_args)
view_args = connection.views.map { |v| Shellwords.escape(v) }
command.concat(view_args)
raise "Error dumping database" unless Kernel.system(command.join(" "))

dump = File.read(filename)
dump.gsub!(/^USE .*$\nGO\n/, "") # Strip db USE statements
dump.gsub!(/^GO\n/, "") # Strip db GO statements
dump.gsub!(/nvarchar\(8000\)/, "nvarchar(4000)") # Fix nvarchar(8000) column defs
dump.gsub!(/nvarchar\(-1\)/, "nvarchar(max)") # Fix nvarchar(-1) column defs
dump.gsub!(/text\(\d+\)/, "text") # Fix text(16) column defs
File.open(filename, "w") { |file| file.puts dump }
end
end

def structure_load(filename, extra_flags)
lease_connection.execute File.read(filename)
def structure_load(filename, _extra_flags)
with_connection do |connection|
connection.execute File.read(filename)
end
end

private
Expand Down
22 changes: 13 additions & 9 deletions lib/arel/visitors/sqlserver.rb
Original file line number Diff line number Diff line change
Expand Up @@ -129,10 +129,12 @@ def visit_Arel_Table(o, collector)
# github.com/rails-sqlserver/activerecord-sqlserver-adapter/issues/450
table_name =
begin
if o.class.engine.lease_connection.respond_to?(:sqlserver?) && o.class.engine.lease_connection.database_prefix_remote_server?
remote_server_table_name(o)
else
quote_table_name(o.name)
o.class.engine.with_connection do |connection|
if connection.respond_to?(:sqlserver?) && connection.database_prefix_remote_server?
remote_server_table_name(o)
else
quote_table_name(o.name)
end
end
rescue Exception
quote_table_name(o.name)
Expand Down Expand Up @@ -315,14 +317,16 @@ def primary_Key_From_Table(t)
end

def remote_server_table_name(o)
ActiveRecord::ConnectionAdapters::SQLServer::Utils.extract_identifiers(
"#{o.class.engine.lease_connection.database_prefix}#{o.name}"
).quoted
o.class.engine.with_connection do |connection|
ActiveRecord::ConnectionAdapters::SQLServer::Utils.extract_identifiers(
"#{connection.database_prefix}#{o.name}"
).quoted
end
end

# Need to remove ordering from subqueries unless TOP/OFFSET also used. Otherwise, SQLServer
# Need to remove ordering from sub-queries unless TOP/OFFSET also used. Otherwise, SQLServer
# returns error "The ORDER BY clause is invalid in views, inline functions, derived tables,
# subqueries, and common table expressions, unless TOP, OFFSET or FOR XML is also specified."
# sub-queries, and common table expressions, unless TOP, OFFSET or FOR XML is also specified."
def remove_invalid_ordering_from_select_statement(node)
return unless Arel::Nodes::SelectStatement === node

Expand Down
Loading