Skip to content

Commit fe137e0

Browse files
committed
Code cleanup for #426 and #427 linked server support.
* Rename `remote_server?` to `database_prefix_remote_server?` * Make `database_prefix_remote_server?` stronger by checking if #object is left blank. Misc refactors. * Remove `@config` init ivar. Not used. * Use `connection_options` helper in tests for terse win. cc @jippeholwerda
1 parent e66106a commit fe137e0

File tree

8 files changed

+71
-50
lines changed

8 files changed

+71
-50
lines changed

‎CHANGELOG.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33

44
#### Fixed
55

6-
* Allow linked servers for table names. Fixes #426. Thanks @jippeholwerda
6+
* Allow linked servers for table names. Fixes #426. Fixes #427. Thanks @jippeholwerda
77

88

99
## v4.2.5

‎lib/active_record/connection_adapters/sqlserver/database_statements.rb

+1-1
Original file line numberDiff line numberDiff line change
@@ -216,7 +216,7 @@ def select(sql, name = nil, binds = [])
216216
end
217217

218218
def sql_for_insert(sql, pk, id_value, sequence_name, binds)
219-
sql = if pk && self.class.use_output_inserted && !remote_server?
219+
sql = if pk && self.class.use_output_inserted && !database_prefix_remote_server?
220220
quoted_pk = SQLServer::Utils.extract_identifiers(pk).quoted
221221
sql.insert sql.index(/ (DEFAULT )?VALUES/), " OUTPUT INSERTED.#{quoted_pk}"
222222
else

‎lib/active_record/connection_adapters/sqlserver/schema_statements.rb

+3-3
Original file line numberDiff line numberDiff line change
@@ -220,10 +220,10 @@ def initialize_native_database_types
220220
end
221221

222222
def column_definitions(table_name)
223-
if remote_server?
224-
identifier = SQLServer::Utils.extract_identifiers("#{database_prefix}#{table_name}")
223+
identifier = if database_prefix_remote_server?
224+
SQLServer::Utils.extract_identifiers("#{database_prefix}#{table_name}")
225225
else
226-
identifier = SQLServer::Utils.extract_identifiers(table_name)
226+
SQLServer::Utils.extract_identifiers(table_name)
227227
end
228228
database = identifier.fully_qualified_database_quoted
229229
view_exists = schema_cache.view_exists?(table_name)

‎lib/active_record/connection_adapters/sqlserver_adapter.rb

+4-3
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,6 @@ def initialize(connection, logger, pool, config)
5454
@visitor = Arel::Visitors::SQLServer.new self
5555
@prepared_statements = true
5656
# Our Responsibility
57-
@config = config
5857
@connection_options = config
5958
connect
6059
@sqlserver_azure = !!(select_value('SELECT @@version', 'SCHEMA') =~ /Azure/i)
@@ -181,8 +180,10 @@ def sqlserver_azure?
181180
@sqlserver_azure
182181
end
183182

184-
def remote_server?
185-
!!database_prefix and SQLServer::Utils.extract_identifiers(@connection_options[:database_prefix]).fully_qualified?
183+
def database_prefix_remote_server?
184+
return false if database_prefix.blank?
185+
name = SQLServer::Utils.extract_identifiers(database_prefix)
186+
name.fully_qualified? && name.object.blank?
186187
end
187188

188189
def database_prefix

‎lib/arel/visitors/sqlserver.rb

+1-1
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,7 @@ def visit_Arel_Nodes_SelectStatement o, collector
7474
end
7575

7676
def visit_Arel_Table o, collector
77-
table_name = if o.engine.connection.remote_server?
77+
table_name = if o.engine.connection.database_prefix_remote_server?
7878
remote_server_table_name(o)
7979
else
8080
quote_table_name(o.name)

‎test/cases/adapter_test_sqlserver.rb

+14-10
Original file line numberDiff line numberDiff line change
@@ -416,24 +416,28 @@ class AdapterTestSQLServer < ActiveRecord::TestCase
416416

417417
end
418418

419-
describe 'remote_server?' do
419+
describe 'database_prefix_remote_server?' do
420+
421+
let(:connection_options) { connection.instance_variable_get(:@connection_options) }
422+
420423
after do
421-
connection.instance_variable_get(:@connection_options).delete(:database_prefix)
424+
connection_options.delete(:database_prefix)
422425
end
423426

424-
it 'should return false if database_prefix is not configured' do
425-
assert_equal false, connection.remote_server?
427+
it 'returns false if database_prefix is not configured' do
428+
assert_equal false, connection.database_prefix_remote_server?
426429
end
427430

428-
it 'should return true if database_prefix has been set' do
429-
connection.instance_variable_get(:@connection_options)[:database_prefix] = "server.database.schema."
430-
assert_equal true, connection.remote_server?
431+
it 'returns true if database_prefix has been set' do
432+
connection_options[:database_prefix] = "server.database.schema."
433+
assert_equal true, connection.database_prefix_remote_server?
431434
end
432435

433-
it 'should return false if database_prefix has been set incorrectly' do
434-
connection.instance_variable_get(:@connection_options)[:database_prefix] = "server.database.schema"
435-
assert_equal false, connection.remote_server?
436+
it 'returns false if database_prefix has been set incorrectly' do
437+
connection_options[:database_prefix] = "server.database.schema"
438+
assert_equal false, connection.database_prefix_remote_server?
436439
end
440+
437441
end
438442

439443
end

‎test/cases/fully_qualified_identifier_test_sqlserver.rb

+10-2
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,27 @@
11
require 'cases/helper_sqlserver'
22

33
class FullyQualifiedIdentifierTestSQLServer < ActiveRecord::TestCase
4+
5+
let(:connection_options) { connection.instance_variable_get(:@connection_options) }
6+
47
describe 'local server' do
8+
59
it 'should use table name in select projections' do
610
table = Arel::Table.new(:table)
711
expected_sql = "SELECT [table].[name] FROM [table]"
812
assert_equal expected_sql, table.project(table[:name]).to_sql
913
end
14+
1015
end
1116

1217
describe 'remote server' do
18+
1319
before do
14-
connection.instance_variable_get(:@connection_options)[:database_prefix] = "[my.server].db.schema."
20+
connection_options[:database_prefix] = "[my.server].db.schema."
1521
end
1622

1723
after do
18-
connection.instance_variable_get(:@connection_options).delete(:database_prefix)
24+
connection_options.delete :database_prefix
1925
end
2026

2127
it 'should use fully qualified table name in select from clause' do
@@ -66,5 +72,7 @@ class FullyQualifiedIdentifierTestSQLServer < ActiveRecord::TestCase
6672
expected_sql = "DELETE FROM [my.server].[db].[schema].[table] WHERE [table].[id] = 42"
6773
assert_equal expected_sql, manager.to_sql
6874
end
75+
6976
end
77+
7078
end

‎test/cases/utils_test_sqlserver.rb

+37-29
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ class UtilsTestSQLServer < ActiveRecord::TestCase
4242

4343
it 'extracts and returns #object identifier unquoted by default or quoted as needed' do
4444
valid_names.each do |n|
45-
name = SQLServer::Utils.extract_identifiers(n)
45+
name = extract_identifiers(n)
4646
name.object.must_equal 'object', "With #{n.inspect} for #object"
4747
name.object_quoted.must_equal '[object]', "With #{n.inspect} for #object_quoted"
4848
end
@@ -53,12 +53,12 @@ class UtilsTestSQLServer < ActiveRecord::TestCase
5353
it "extracts and returns #{part} identifier unquoted by default or quoted as needed" do
5454
present, blank = send(:"#{part}_names")
5555
present.each do |n|
56-
name = SQLServer::Utils.extract_identifiers(n)
56+
name = extract_identifiers(n)
5757
name.send(:"#{part}").must_equal "#{part}", "With #{n.inspect} for ##{part} method"
5858
name.send(:"#{part}_quoted").must_equal "[#{part}]", "With #{n.inspect} for ##{part}_quoted method"
5959
end
6060
blank.each do |n|
61-
name = SQLServer::Utils.extract_identifiers(n)
61+
name = extract_identifiers(n)
6262
name.send(:"#{part}").must_be_nil "With #{n.inspect} for ##{part} method"
6363
name.send(:"#{part}_quoted").must_be_nil "With #{n.inspect} for ##{part}_quoted method"
6464
end
@@ -67,51 +67,59 @@ class UtilsTestSQLServer < ActiveRecord::TestCase
6767
end
6868

6969
it 'does not blow up on nil or blank string name' do
70-
SQLServer::Utils.extract_identifiers(nil).object.must_be_nil
71-
SQLServer::Utils.extract_identifiers(' ').object.must_be_nil
70+
extract_identifiers(nil).object.must_be_nil
71+
extract_identifiers(' ').object.must_be_nil
7272
end
7373

7474
it 'has a #quoted that returns a fully quoted name with all identifiers as orginially passed in' do
75-
SQLServer::Utils.extract_identifiers('object').quoted.must_equal '[object]'
76-
SQLServer::Utils.extract_identifiers('server.database..object').quoted.must_equal '[server].[database]..[object]'
77-
SQLServer::Utils.extract_identifiers('[server]...[object]').quoted.must_equal '[server]...[object]'
75+
extract_identifiers('object').quoted.must_equal '[object]'
76+
extract_identifiers('server.database..object').quoted.must_equal '[server].[database]..[object]'
77+
extract_identifiers('[server]...[object]').quoted.must_equal '[server]...[object]'
7878
end
7979

8080
it 'can take a symbol argument' do
81-
SQLServer::Utils.extract_identifiers(:object).object.must_equal 'object'
81+
extract_identifiers(:object).object.must_equal 'object'
8282
end
8383

8484
it 'allows identifiers with periods to work' do
85-
SQLServer::Utils.extract_identifiers('[obj.name]').quoted.must_equal '[obj.name]'
86-
SQLServer::Utils.extract_identifiers('[obj.name].[foo]').quoted.must_equal '[obj.name].[foo]'
85+
extract_identifiers('[obj.name]').quoted.must_equal '[obj.name]'
86+
extract_identifiers('[obj.name].[foo]').quoted.must_equal '[obj.name].[foo]'
8787
end
8888

8989
it 'should indicate if a name is fully qualitified' do
90-
SQLServer::Utils.extract_identifiers('object').fully_qualified?.must_equal false
91-
SQLServer::Utils.extract_identifiers('schema.object').fully_qualified?.must_equal false
92-
SQLServer::Utils.extract_identifiers('database.schema.object').fully_qualified?.must_equal false
93-
SQLServer::Utils.extract_identifiers('database.object').fully_qualified?.must_equal false
94-
SQLServer::Utils.extract_identifiers('server...object').fully_qualified?.must_equal false
95-
SQLServer::Utils.extract_identifiers('server.database..object').fully_qualified?.must_equal false
96-
SQLServer::Utils.extract_identifiers('server.database.schema.object').fully_qualified?.must_equal true
97-
SQLServer::Utils.extract_identifiers('server.database.schema.').fully_qualified?.must_equal true
98-
SQLServer::Utils.extract_identifiers('[obj.name]').fully_qualified?.must_equal false
99-
SQLServer::Utils.extract_identifiers('[schema].[obj.name]').fully_qualified?.must_equal false
100-
SQLServer::Utils.extract_identifiers('[database].[schema].[obj.name]').fully_qualified?.must_equal false
101-
SQLServer::Utils.extract_identifiers('[database].[obj.name]').fully_qualified?.must_equal false
102-
SQLServer::Utils.extract_identifiers('[server.name]...[obj.name]').fully_qualified?.must_equal false
103-
SQLServer::Utils.extract_identifiers('[server.name].[database]..[obj.name]').fully_qualified?.must_equal false
104-
SQLServer::Utils.extract_identifiers('[server.name].[database].[schema].[obj.name]').fully_qualified?.must_equal true
105-
SQLServer::Utils.extract_identifiers('[server.name].[database].[schema].').fully_qualified?.must_equal true
90+
extract_identifiers('object').fully_qualified?.must_equal false
91+
extract_identifiers('schema.object').fully_qualified?.must_equal false
92+
extract_identifiers('database.schema.object').fully_qualified?.must_equal false
93+
extract_identifiers('database.object').fully_qualified?.must_equal false
94+
extract_identifiers('server...object').fully_qualified?.must_equal false
95+
extract_identifiers('server.database..object').fully_qualified?.must_equal false
96+
extract_identifiers('server.database.schema.object').fully_qualified?.must_equal true
97+
extract_identifiers('server.database.schema.').fully_qualified?.must_equal true
98+
extract_identifiers('[obj.name]').fully_qualified?.must_equal false
99+
extract_identifiers('[schema].[obj.name]').fully_qualified?.must_equal false
100+
extract_identifiers('[database].[schema].[obj.name]').fully_qualified?.must_equal false
101+
extract_identifiers('[database].[obj.name]').fully_qualified?.must_equal false
102+
extract_identifiers('[server.name]...[obj.name]').fully_qualified?.must_equal false
103+
extract_identifiers('[server.name].[database]..[obj.name]').fully_qualified?.must_equal false
104+
extract_identifiers('[server.name].[database].[schema].[obj.name]').fully_qualified?.must_equal true
105+
extract_identifiers('[server.name].[database].[schema].').fully_qualified?.must_equal true
106106
end
107107

108108
it 'can return fully qualified quoted table name' do
109-
name = SQLServer::Utils.extract_identifiers('[server.name].[database].[schema].[object]')
109+
name = extract_identifiers('[my.server].db.schema.')
110+
name.fully_qualified_database_quoted.must_equal '[my.server].[db]'
111+
name = extract_identifiers('[server.name].[database].[schema].[object]')
110112
name.fully_qualified_database_quoted.must_equal '[server.name].[database]'
111-
name = SQLServer::Utils.extract_identifiers('server.database.schema.object')
113+
name = extract_identifiers('server.database.schema.object')
112114
name.fully_qualified_database_quoted.must_equal '[server].[database]'
113115
end
114116

115117
end
116118

119+
private
120+
121+
def extract_identifiers(name)
122+
SQLServer::Utils.extract_identifiers(name)
123+
end
124+
117125
end

0 commit comments

Comments
 (0)