activerecord-sqlserver-adapter 7.1.4 → 7.1.5
Sign up to get free protection for your applications and to get access to all the features.
- 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
|