activerecord-sqlserver-adapter 7.1.4 → 7.1.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +7 -0
- data/README.md +2 -1
- data/VERSION +1 -1
- data/lib/active_record/connection_adapters/sqlserver/schema_dumper.rb +11 -0
- data/lib/active_record/connection_adapters/sqlserver/schema_statements.rb +37 -12
- data/test/cases/adapter_test_sqlserver.rb +14 -2
- data/test/cases/schema_dumper_test_sqlserver.rb +23 -2
- data/test/cases/schema_test_sqlserver.rb +47 -1
- data/test/models/sqlserver/table_with_spaces.rb +5 -0
- data/test/schema/sqlserver_specific_schema.rb +4 -0
- metadata +6 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: eea983d328f36bfb590c26ff592292369634d60b63ff38acc43e28c87e09c7ee
|
4
|
+
data.tar.gz: 7e9ab05308f76eb6be6ef5745977f4c0de684c608494d45d9d49d3ac54e1a4cb
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 67f76bc1083712be03b8a8b3eb5a2c48b9d4efc44442b8573604aecaff23ccbd0bd1586529948497776aca6b7c18257ead5d62e239f2b69d92e2ec14e5675192
|
7
|
+
data.tar.gz: 845923a58bda81c5f32a81b40a61157b1d36c909352ac258bd848d2e604f95ee94e09878f3c8f475f3d770725c8492b8b58c4c87146c4965e0b29d91b64872fc
|
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,10 @@
|
|
1
|
+
## v7.1.5
|
2
|
+
|
3
|
+
#### Added
|
4
|
+
|
5
|
+
- [#1201](https://github.com/rails-sqlserver/activerecord-sqlserver-adapter/pull/1201) Support non-dbo schemas in schema dumper
|
6
|
+
- [#1206](https://github.com/rails-sqlserver/activerecord-sqlserver-adapter/pull/1206) Support table names containing spaces
|
7
|
+
|
1
8
|
## v7.1.4
|
2
9
|
|
3
10
|
#### Fixed
|
data/README.md
CHANGED
@@ -13,7 +13,8 @@ Interested in older versions? We follow a rational versioning policy that tracks
|
|
13
13
|
|
14
14
|
| Adapter Version | Rails Version | Support | Branch |
|
15
15
|
|-----------------|---------------|---------|--------------------------------------------------------------------------------------------------|
|
16
|
-
|
|
16
|
+
| Unreleased | `7.2.x` | In Development | [main](https://github.com/rails-sqlserver/activerecord-sqlserver-adapter/tree/main) |
|
17
|
+
| `7.1.5` | `7.1.x` | Active | [7-1-stable](https://github.com/rails-sqlserver/activerecord-sqlserver-adapter/tree/7-1-stable) |
|
17
18
|
| `7.0.7` | `7.0.x` | Active | [7-0-stable](https://github.com/rails-sqlserver/activerecord-sqlserver-adapter/tree/7-0-stable) |
|
18
19
|
| `6.1.3.0` | `6.1.x` | Active | [6-1-stable](https://github.com/rails-sqlserver/activerecord-sqlserver-adapter/tree/6-1-stable) |
|
19
20
|
| `6.0.3` | `6.0.x` | Ended | [6-0-stable](https://github.com/rails-sqlserver/activerecord-sqlserver-adapter/tree/6-0-stable) |
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
7.1.
|
1
|
+
7.1.5
|
@@ -39,6 +39,17 @@ module ActiveRecord
|
|
39
39
|
def default_primary_key?(column)
|
40
40
|
super && column.is_identity?
|
41
41
|
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
|
42
53
|
end
|
43
54
|
end
|
44
55
|
end
|
@@ -393,19 +393,37 @@ module ActiveRecord
|
|
393
393
|
execute "DROP SCHEMA [#{schema_name}]"
|
394
394
|
end
|
395
395
|
|
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
|
+
|
396
409
|
private
|
397
410
|
|
398
411
|
def data_source_sql(name = nil, type: nil)
|
399
|
-
scope = quoted_scope
|
412
|
+
scope = quoted_scope(name, type: type)
|
400
413
|
|
401
|
-
|
402
|
-
|
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]}." : ""
|
403
417
|
table_catalog = scope[:database].present? ? quote(scope[:database]) : "DB_NAME()"
|
404
418
|
|
405
|
-
sql = "SELECT
|
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"
|
406
424
|
sql += " FROM #{database}INFORMATION_SCHEMA.TABLES WITH (NOLOCK)"
|
407
425
|
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]
|
409
427
|
sql += " AND TABLE_NAME = #{quote(scope[:name])}" if scope[:name]
|
410
428
|
sql += " AND TABLE_TYPE = #{quote(scope[:type])}" if scope[:type]
|
411
429
|
sql += " ORDER BY #{table_name}"
|
@@ -414,9 +432,10 @@ module ActiveRecord
|
|
414
432
|
|
415
433
|
def quoted_scope(name = nil, type: nil)
|
416
434
|
identifier = SQLServer::Utils.extract_identifiers(name)
|
435
|
+
|
417
436
|
{}.tap do |scope|
|
418
437
|
scope[:database] = identifier.database if identifier.database
|
419
|
-
scope[:schema] = identifier.schema || "dbo"
|
438
|
+
scope[:schema] = identifier.schema || "dbo" if name.present?
|
420
439
|
scope[:name] = identifier.object if identifier.object
|
421
440
|
scope[:type] = type if type
|
422
441
|
end
|
@@ -654,12 +673,18 @@ module ActiveRecord
|
|
654
673
|
|
655
674
|
# Parses the raw table name that is used in the SQL. Table name could include database/schema/etc.
|
656
675
|
def get_raw_table_name(sql)
|
657
|
-
|
658
|
-
|
659
|
-
|
660
|
-
|
661
|
-
|
662
|
-
|
676
|
+
s = sql.gsub(/^\s*EXEC sp_executesql N'/i, "")
|
677
|
+
|
678
|
+
if s.match?(/^\s*INSERT INTO.*/i)
|
679
|
+
s.split(/INSERT INTO/i)[1]
|
680
|
+
.split(/OUTPUT INSERTED/i)[0]
|
681
|
+
.split(/(DEFAULT)?\s+VALUES/i)[0]
|
682
|
+
.match(/\s*([^(]*)/i)[0]
|
683
|
+
elsif s.match?(/^\s*UPDATE\s+.*/i)
|
684
|
+
s.match(/UPDATE\s+([^\(\s]+)\s*/i)[1]
|
685
|
+
else
|
686
|
+
s.match(/FROM\s+((\[[^\(\]]+\])|[^\(\s]+)\s*/i)[1]
|
687
|
+
end.strip
|
663
688
|
end
|
664
689
|
|
665
690
|
def default_constraint_name(table_name, column_name)
|
@@ -550,11 +550,23 @@ class AdapterTestSQLServer < ActiveRecord::TestCase
|
|
550
550
|
|
551
551
|
describe 'table is in non-dbo schema' do
|
552
552
|
it "records can be created successfully" do
|
553
|
-
Alien.
|
553
|
+
assert_difference("Alien.count", 1) do
|
554
|
+
Alien.create!(name: 'Trisolarans')
|
555
|
+
end
|
554
556
|
end
|
555
557
|
|
556
558
|
it 'records can be inserted using SQL' do
|
557
|
-
Alien.
|
559
|
+
assert_difference("Alien.count", 2) do
|
560
|
+
Alien.connection.exec_insert("insert into [test].[aliens] (id, name) VALUES(1, 'Trisolarans'), (2, 'Xenomorph')")
|
561
|
+
end
|
562
|
+
end
|
563
|
+
end
|
564
|
+
|
565
|
+
describe 'table names contains spaces' do
|
566
|
+
it 'records can be created successfully' do
|
567
|
+
assert_difference("TableWithSpaces.count", 1) do
|
568
|
+
TableWithSpaces.create!(name: 'Bob')
|
569
|
+
end
|
558
570
|
end
|
559
571
|
end
|
560
572
|
|
@@ -1,6 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
require "cases/helper_sqlserver"
|
4
|
+
require "stringio"
|
4
5
|
|
5
6
|
class SchemaDumperTestSQLServer < ActiveRecord::TestCase
|
6
7
|
before { all_tables }
|
@@ -141,7 +142,7 @@ class SchemaDumperTestSQLServer < ActiveRecord::TestCase
|
|
141
142
|
it "honor nonstandard primary keys" do
|
142
143
|
generate_schema_for_table("movies") do |output|
|
143
144
|
match = output.match(%r{create_table "movies"(.*)do})
|
144
|
-
assert_not_nil(match, "
|
145
|
+
assert_not_nil(match, "non-standard primary key table not found")
|
145
146
|
assert_match %r(primary_key: "movieid"), match[1], "non-standard primary key not preserved"
|
146
147
|
end
|
147
148
|
end
|
@@ -159,14 +160,32 @@ class SchemaDumperTestSQLServer < ActiveRecord::TestCase
|
|
159
160
|
_(output.scan('t.integer "unique_field"').length).must_equal(1)
|
160
161
|
end
|
161
162
|
|
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, 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_mulitple_schema"'
|
177
|
+
end
|
178
|
+
|
162
179
|
private
|
163
180
|
|
164
181
|
def generate_schema_for_table(*table_names)
|
165
|
-
|
182
|
+
previous_ignore_tables = ActiveRecord::SchemaDumper.ignore_tables
|
183
|
+
ActiveRecord::SchemaDumper.ignore_tables = all_tables - table_names
|
166
184
|
|
167
185
|
stream = StringIO.new
|
168
186
|
ActiveRecord::SchemaDumper.ignore_tables = all_tables - table_names
|
169
187
|
ActiveRecord::SchemaDumper.dump(ActiveRecord::Base.connection, stream)
|
188
|
+
|
170
189
|
@generated_schema = stream.string
|
171
190
|
yield @generated_schema if block_given?
|
172
191
|
@schema_lines = Hash.new
|
@@ -177,6 +196,8 @@ class SchemaDumperTestSQLServer < ActiveRecord::TestCase
|
|
177
196
|
@schema_lines[Regexp.last_match[1]] = SchemaLine.new(line)
|
178
197
|
end
|
179
198
|
@generated_schema
|
199
|
+
ensure
|
200
|
+
ActiveRecord::SchemaDumper.ignore_tables = previous_ignore_tables
|
180
201
|
end
|
181
202
|
|
182
203
|
def line(column_name)
|
@@ -39,7 +39,7 @@ class SchemaTestSQLServer < ActiveRecord::TestCase
|
|
39
39
|
assert_equal 1, columns.select { |c| c.is_identity? }.size
|
40
40
|
end
|
41
41
|
|
42
|
-
it "return correct varchar and nvarchar column limit length when table is in non
|
42
|
+
it "return correct varchar and nvarchar column limit length when table is in non-dbo schema" do
|
43
43
|
columns = connection.columns("test.sst_schema_columns")
|
44
44
|
|
45
45
|
assert_equal 255, columns.find { |c| c.name == "name" }.limit
|
@@ -48,4 +48,50 @@ class SchemaTestSQLServer < ActiveRecord::TestCase
|
|
48
48
|
assert_equal 1000, columns.find { |c| c.name == "n_description" }.limit
|
49
49
|
end
|
50
50
|
end
|
51
|
+
|
52
|
+
describe "parsing table name from raw SQL" do
|
53
|
+
describe 'SELECT statements' do
|
54
|
+
it do
|
55
|
+
assert_equal "[sst_schema_columns]", connection.send(:get_raw_table_name, "SELECT [sst_schema_columns].[id] FROM [sst_schema_columns]")
|
56
|
+
end
|
57
|
+
|
58
|
+
it do
|
59
|
+
assert_equal "sst_schema_columns", connection.send(:get_raw_table_name, "SELECT [sst_schema_columns].[id] FROM sst_schema_columns")
|
60
|
+
end
|
61
|
+
|
62
|
+
it do
|
63
|
+
assert_equal "[WITH - SPACES]", connection.send(:get_raw_table_name, "SELECT id FROM [WITH - SPACES]")
|
64
|
+
end
|
65
|
+
|
66
|
+
it do
|
67
|
+
assert_equal "[WITH - SPACES$DOLLAR]", connection.send(:get_raw_table_name, "SELECT id FROM [WITH - SPACES$DOLLAR]")
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
describe 'INSERT statements' do
|
72
|
+
it do
|
73
|
+
assert_equal "[dashboards]", connection.send(:get_raw_table_name, "INSERT INTO [dashboards] DEFAULT VALUES; SELECT CAST(SCOPE_IDENTITY() AS bigint) AS Ident")
|
74
|
+
end
|
75
|
+
|
76
|
+
it do
|
77
|
+
assert_equal "lock_without_defaults", connection.send(:get_raw_table_name, "INSERT INTO lock_without_defaults(title) VALUES('title1')")
|
78
|
+
end
|
79
|
+
|
80
|
+
it do
|
81
|
+
assert_equal "json_data_type", connection.send(:get_raw_table_name, "insert into json_data_type (payload) VALUES ('null')")
|
82
|
+
end
|
83
|
+
|
84
|
+
it do
|
85
|
+
assert_equal "[auto_increments]", connection.send(:get_raw_table_name, "INSERT INTO [auto_increments] OUTPUT INSERTED.[id] DEFAULT VALUES")
|
86
|
+
end
|
87
|
+
|
88
|
+
it do
|
89
|
+
assert_equal "[WITH - SPACES]", connection.send(:get_raw_table_name, "EXEC sp_executesql N'INSERT INTO [WITH - SPACES] ([external_id]) OUTPUT INSERTED.[id] VALUES (@0)', N'@0 bigint', @0 = 10")
|
90
|
+
end
|
91
|
+
|
92
|
+
it do
|
93
|
+
assert_equal "[test].[aliens]", connection.send(:get_raw_table_name, "EXEC sp_executesql N'INSERT INTO [test].[aliens] ([name]) OUTPUT INSERTED.[id] VALUES (@0)', N'@0 varchar(255)', @0 = 'Trisolarans'")
|
94
|
+
end
|
95
|
+
end
|
96
|
+
end
|
51
97
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: activerecord-sqlserver-adapter
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 7.1.
|
4
|
+
version: 7.1.5
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Ken Collins
|
@@ -15,7 +15,7 @@ authors:
|
|
15
15
|
autorequire:
|
16
16
|
bindir: bin
|
17
17
|
cert_chain: []
|
18
|
-
date: 2024-07-
|
18
|
+
date: 2024-07-25 00:00:00.000000000 Z
|
19
19
|
dependencies:
|
20
20
|
- !ruby/object:Gem::Dependency
|
21
21
|
name: activerecord
|
@@ -212,6 +212,7 @@ files:
|
|
212
212
|
- test/models/sqlserver/string_default.rb
|
213
213
|
- test/models/sqlserver/string_defaults_big_view.rb
|
214
214
|
- test/models/sqlserver/string_defaults_view.rb
|
215
|
+
- test/models/sqlserver/table_with_spaces.rb
|
215
216
|
- test/models/sqlserver/tinyint_pk.rb
|
216
217
|
- test/models/sqlserver/trigger.rb
|
217
218
|
- test/models/sqlserver/trigger_history.rb
|
@@ -239,8 +240,8 @@ licenses:
|
|
239
240
|
- MIT
|
240
241
|
metadata:
|
241
242
|
bug_tracker_uri: https://github.com/rails-sqlserver/activerecord-sqlserver-adapter/issues
|
242
|
-
changelog_uri: https://github.com/rails-sqlserver/activerecord-sqlserver-adapter/blob/v7.1.
|
243
|
-
source_code_uri: https://github.com/rails-sqlserver/activerecord-sqlserver-adapter/tree/v7.1.
|
243
|
+
changelog_uri: https://github.com/rails-sqlserver/activerecord-sqlserver-adapter/blob/v7.1.5/CHANGELOG.md
|
244
|
+
source_code_uri: https://github.com/rails-sqlserver/activerecord-sqlserver-adapter/tree/v7.1.5
|
244
245
|
post_install_message:
|
245
246
|
rdoc_options: []
|
246
247
|
require_paths:
|
@@ -329,6 +330,7 @@ test_files:
|
|
329
330
|
- test/models/sqlserver/string_default.rb
|
330
331
|
- test/models/sqlserver/string_defaults_big_view.rb
|
331
332
|
- test/models/sqlserver/string_defaults_view.rb
|
333
|
+
- test/models/sqlserver/table_with_spaces.rb
|
332
334
|
- test/models/sqlserver/tinyint_pk.rb
|
333
335
|
- test/models/sqlserver/trigger.rb
|
334
336
|
- test/models/sqlserver/trigger_history.rb
|