Skip to content

Commit d361c49

Browse files
committed
Support non-dbo schemas in schema dumper (#1201)
1 parent 658fce5 commit d361c49

File tree

4 files changed

+66
-9
lines changed

4 files changed

+66
-9
lines changed

Diff for: CHANGELOG.md

+6
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,9 @@
1+
## Unreleased
2+
3+
#### Added
4+
5+
- [#](https://github.com/rails-sqlserver/activerecord-sqlserver-adapter/pull/) Support non-dbo schemas in schema dumper.
6+
17
## v7.1.4
28

39
#### Fixed

Diff for: lib/active_record/connection_adapters/sqlserver/schema_dumper.rb

+11
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,17 @@ def schema_collation(column)
3939
def default_primary_key?(column)
4040
super && column.is_identity?
4141
end
42+
43+
def schemas(stream)
44+
schema_names = @connection.schema_names
45+
46+
if schema_names.any?
47+
schema_names.sort.each do |name|
48+
stream.puts " create_schema #{name.inspect}"
49+
end
50+
stream.puts
51+
end
52+
end
4253
end
4354
end
4455
end

Diff for: lib/active_record/connection_adapters/sqlserver/schema_statements.rb

+25-6
Original file line numberDiff line numberDiff line change
@@ -393,19 +393,37 @@ def drop_schema(schema_name)
393393
execute "DROP SCHEMA [#{schema_name}]"
394394
end
395395

396+
# Returns an array of schema names.
397+
def schema_names
398+
sql = <<~SQL.squish
399+
SELECT name
400+
FROM sys.schemas
401+
WHERE
402+
name NOT LIKE 'db_%' AND
403+
name NOT IN ('INFORMATION_SCHEMA', 'sys')
404+
SQL
405+
406+
query_values(sql, "SCHEMA")
407+
end
408+
396409
private
397410

398411
def data_source_sql(name = nil, type: nil)
399-
scope = quoted_scope name, type: type
412+
scope = quoted_scope(name, type: type)
400413

401-
table_name = lowercase_schema_reflection_sql 'TABLE_NAME'
402-
database = scope[:database].present? ? "#{scope[:database]}." : ""
414+
table_schema = lowercase_schema_reflection_sql('TABLE_SCHEMA')
415+
table_name = lowercase_schema_reflection_sql('TABLE_NAME')
416+
database = scope[:database].present? ? "#{scope[:database]}." : ""
403417
table_catalog = scope[:database].present? ? quote(scope[:database]) : "DB_NAME()"
404418

405-
sql = "SELECT #{table_name}"
419+
sql = "SELECT "
420+
sql += " CASE"
421+
sql += " WHEN #{table_schema} = 'dbo' THEN #{table_name}"
422+
sql += " ELSE CONCAT(#{table_schema}, '.', #{table_name})"
423+
sql += " END"
406424
sql += " FROM #{database}INFORMATION_SCHEMA.TABLES WITH (NOLOCK)"
407425
sql += " WHERE TABLE_CATALOG = #{table_catalog}"
408-
sql += " AND TABLE_SCHEMA = #{quote(scope[:schema])}"
426+
sql += " AND TABLE_SCHEMA = #{quote(scope[:schema])}" if scope[:schema]
409427
sql += " AND TABLE_NAME = #{quote(scope[:name])}" if scope[:name]
410428
sql += " AND TABLE_TYPE = #{quote(scope[:type])}" if scope[:type]
411429
sql += " ORDER BY #{table_name}"
@@ -414,9 +432,10 @@ def data_source_sql(name = nil, type: nil)
414432

415433
def quoted_scope(name = nil, type: nil)
416434
identifier = SQLServer::Utils.extract_identifiers(name)
435+
417436
{}.tap do |scope|
418437
scope[:database] = identifier.database if identifier.database
419-
scope[:schema] = identifier.schema || "dbo"
438+
scope[:schema] = identifier.schema || "dbo" if name.present?
420439
scope[:name] = identifier.object if identifier.object
421440
scope[:type] = type if type
422441
end

Diff for: test/cases/schema_dumper_test_sqlserver.rb

+24-3
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
# frozen_string_literal: true
22

33
require "cases/helper_sqlserver"
4+
require "stringio"
45

56
class SchemaDumperTestSQLServer < ActiveRecord::TestCase
67
before { all_tables }
@@ -141,7 +142,7 @@ class SchemaDumperTestSQLServer < ActiveRecord::TestCase
141142
it "honor nonstandard primary keys" do
142143
generate_schema_for_table("movies") do |output|
143144
match = output.match(%r{create_table "movies"(.*)do})
144-
assert_not_nil(match, "nonstandardpk table not found")
145+
assert_not_nil(match, "non-standard primary key table not found")
145146
assert_match %r(primary_key: "movieid"), match[1], "non-standard primary key not preserved"
146147
end
147148
end
@@ -159,14 +160,32 @@ class SchemaDumperTestSQLServer < ActiveRecord::TestCase
159160
_(output.scan('t.integer "unique_field"').length).must_equal(1)
160161
end
161162

163+
it "schemas are dumped and tables names only include non-default schema" do
164+
stream = StringIO.new
165+
ActiveRecord::SchemaDumper.dump(ActiveRecord::Base.connection_pool, stream)
166+
generated_schema = stream.string
167+
168+
# Only generate non-default schemas. Default schema is 'dbo'.
169+
assert_not_includes generated_schema, 'create_schema "dbo"'
170+
assert_includes generated_schema, 'create_schema "test"'
171+
assert_includes generated_schema, 'create_schema "test2"'
172+
173+
# Only non-default schemas should be included in table names. Default schema is 'dbo'.
174+
assert_includes generated_schema, 'create_table "accounts"'
175+
assert_includes generated_schema, 'create_table "test.aliens"'
176+
assert_includes generated_schema, 'create_table "test2.sst_schema_test_multiple_schema"'
177+
end
178+
162179
private
163180

164181
def generate_schema_for_table(*table_names)
165-
require "stringio"
182+
previous_ignore_tables = ActiveRecord::SchemaDumper.ignore_tables
183+
ActiveRecord::SchemaDumper.ignore_tables = all_tables - table_names
166184

167185
stream = StringIO.new
168186
ActiveRecord::SchemaDumper.ignore_tables = all_tables - table_names
169-
ActiveRecord::SchemaDumper.dump(ActiveRecord::Base.connection, stream)
187+
ActiveRecord::SchemaDumper.dump(ActiveRecord::Base.connection_pool, stream)
188+
170189
@generated_schema = stream.string
171190
yield @generated_schema if block_given?
172191
@schema_lines = Hash.new
@@ -177,6 +196,8 @@ def generate_schema_for_table(*table_names)
177196
@schema_lines[Regexp.last_match[1]] = SchemaLine.new(line)
178197
end
179198
@generated_schema
199+
ensure
200+
ActiveRecord::SchemaDumper.ignore_tables = previous_ignore_tables
180201
end
181202

182203
def line(column_name)

0 commit comments

Comments
 (0)