activerecord-sqlserver-adapter 6.0.0.rc1 → 6.1.0.0.rc1
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/.github/workflows/ci.yml +26 -0
- data/.gitignore +1 -0
- data/.rubocop.yml +29 -0
- data/CHANGELOG.md +18 -23
- data/Gemfile +11 -5
- data/Guardfile +9 -8
- data/README.md +32 -3
- data/RUNNING_UNIT_TESTS.md +1 -1
- data/Rakefile +12 -16
- data/VERSION +1 -1
- data/activerecord-sqlserver-adapter.gemspec +4 -4
- data/lib/active_record/connection_adapters/sqlserver/core_ext/active_record.rb +0 -4
- data/lib/active_record/connection_adapters/sqlserver/core_ext/attribute_methods.rb +1 -4
- data/lib/active_record/connection_adapters/sqlserver/core_ext/calculations.rb +3 -13
- data/lib/active_record/connection_adapters/sqlserver/core_ext/explain.rb +8 -5
- data/lib/active_record/connection_adapters/sqlserver/core_ext/finder_methods.rb +2 -3
- data/lib/active_record/connection_adapters/sqlserver/core_ext/query_methods.rb +2 -3
- data/lib/active_record/connection_adapters/sqlserver/database_limits.rb +0 -4
- data/lib/active_record/connection_adapters/sqlserver/database_statements.rb +58 -43
- data/lib/active_record/connection_adapters/sqlserver/database_tasks.rb +7 -12
- data/lib/active_record/connection_adapters/sqlserver/errors.rb +0 -3
- data/lib/active_record/connection_adapters/sqlserver/quoting.rb +15 -15
- data/lib/active_record/connection_adapters/sqlserver/schema_creation.rb +22 -3
- data/lib/active_record/connection_adapters/sqlserver/schema_dumper.rb +16 -10
- data/lib/active_record/connection_adapters/sqlserver/schema_statements.rb +131 -105
- data/lib/active_record/connection_adapters/sqlserver/showplan.rb +6 -8
- data/lib/active_record/connection_adapters/sqlserver/showplan/printer_table.rb +2 -2
- data/lib/active_record/connection_adapters/sqlserver/showplan/printer_xml.rb +1 -1
- data/lib/active_record/connection_adapters/sqlserver/sql_type_metadata.rb +25 -7
- data/lib/active_record/connection_adapters/sqlserver/table_definition.rb +1 -5
- data/lib/active_record/connection_adapters/sqlserver/transaction.rb +6 -10
- data/lib/active_record/connection_adapters/sqlserver/type.rb +36 -35
- data/lib/active_record/connection_adapters/sqlserver/type/big_integer.rb +0 -2
- data/lib/active_record/connection_adapters/sqlserver/type/binary.rb +0 -2
- data/lib/active_record/connection_adapters/sqlserver/type/boolean.rb +0 -2
- data/lib/active_record/connection_adapters/sqlserver/type/char.rb +2 -2
- data/lib/active_record/connection_adapters/sqlserver/type/data.rb +0 -2
- data/lib/active_record/connection_adapters/sqlserver/type/date.rb +2 -3
- data/lib/active_record/connection_adapters/sqlserver/type/datetime.rb +2 -3
- data/lib/active_record/connection_adapters/sqlserver/type/datetime2.rb +0 -2
- data/lib/active_record/connection_adapters/sqlserver/type/datetimeoffset.rb +0 -2
- data/lib/active_record/connection_adapters/sqlserver/type/decimal.rb +0 -2
- data/lib/active_record/connection_adapters/sqlserver/type/decimal_without_scale.rb +22 -0
- data/lib/active_record/connection_adapters/sqlserver/type/float.rb +0 -2
- data/lib/active_record/connection_adapters/sqlserver/type/integer.rb +0 -2
- data/lib/active_record/connection_adapters/sqlserver/type/json.rb +0 -1
- data/lib/active_record/connection_adapters/sqlserver/type/money.rb +0 -2
- data/lib/active_record/connection_adapters/sqlserver/type/real.rb +0 -2
- data/lib/active_record/connection_adapters/sqlserver/type/small_integer.rb +0 -2
- data/lib/active_record/connection_adapters/sqlserver/type/small_money.rb +0 -2
- data/lib/active_record/connection_adapters/sqlserver/type/smalldatetime.rb +0 -2
- data/lib/active_record/connection_adapters/sqlserver/type/string.rb +0 -2
- data/lib/active_record/connection_adapters/sqlserver/type/text.rb +0 -2
- data/lib/active_record/connection_adapters/sqlserver/type/time.rb +2 -3
- data/lib/active_record/connection_adapters/sqlserver/type/time_value_fractional.rb +6 -9
- data/lib/active_record/connection_adapters/sqlserver/type/timestamp.rb +0 -2
- data/lib/active_record/connection_adapters/sqlserver/type/tiny_integer.rb +0 -2
- data/lib/active_record/connection_adapters/sqlserver/type/unicode_char.rb +1 -3
- data/lib/active_record/connection_adapters/sqlserver/type/unicode_string.rb +0 -2
- data/lib/active_record/connection_adapters/sqlserver/type/unicode_text.rb +0 -2
- data/lib/active_record/connection_adapters/sqlserver/type/unicode_varchar.rb +0 -2
- data/lib/active_record/connection_adapters/sqlserver/type/unicode_varchar_max.rb +0 -2
- data/lib/active_record/connection_adapters/sqlserver/type/uuid.rb +1 -2
- data/lib/active_record/connection_adapters/sqlserver/type/varbinary.rb +1 -3
- data/lib/active_record/connection_adapters/sqlserver/type/varbinary_max.rb +0 -2
- data/lib/active_record/connection_adapters/sqlserver/type/varchar.rb +1 -3
- data/lib/active_record/connection_adapters/sqlserver/type/varchar_max.rb +0 -2
- data/lib/active_record/connection_adapters/sqlserver/utils.rb +8 -11
- data/lib/active_record/connection_adapters/sqlserver/version.rb +0 -2
- data/lib/active_record/connection_adapters/sqlserver_adapter.rb +170 -136
- data/lib/active_record/connection_adapters/sqlserver_column.rb +16 -1
- data/lib/active_record/sqlserver_base.rb +9 -15
- data/lib/active_record/tasks/sqlserver_database_tasks.rb +36 -39
- data/lib/activerecord-sqlserver-adapter.rb +1 -1
- data/lib/arel/visitors/sqlserver.rb +126 -50
- data/lib/arel_sqlserver.rb +2 -2
- data/test/cases/adapter_test_sqlserver.rb +203 -190
- data/test/cases/change_column_collation_test_sqlserver.rb +33 -0
- data/test/cases/change_column_null_test_sqlserver.rb +12 -12
- data/test/cases/coerced_tests.rb +656 -318
- data/test/cases/column_test_sqlserver.rb +285 -284
- data/test/cases/connection_test_sqlserver.rb +15 -20
- data/test/cases/disconnected_test_sqlserver.rb +39 -0
- data/test/cases/execute_procedure_test_sqlserver.rb +26 -19
- data/test/cases/fetch_test_sqlserver.rb +14 -22
- data/test/cases/fully_qualified_identifier_test_sqlserver.rb +12 -18
- data/test/cases/helper_sqlserver.rb +13 -15
- data/test/cases/in_clause_test_sqlserver.rb +36 -9
- data/test/cases/index_test_sqlserver.rb +13 -15
- data/test/cases/json_test_sqlserver.rb +23 -25
- data/test/cases/lateral_test_sqlserver.rb +35 -0
- data/test/cases/migration_test_sqlserver.rb +71 -26
- data/test/cases/optimizer_hints_test_sqlserver.rb +72 -0
- data/test/cases/order_test_sqlserver.rb +57 -53
- data/test/cases/pessimistic_locking_test_sqlserver.rb +25 -33
- data/test/cases/primary_keys_test_sqlserver.rb +103 -0
- data/test/cases/rake_test_sqlserver.rb +33 -46
- data/test/cases/schema_dumper_test_sqlserver.rb +121 -108
- data/test/cases/schema_test_sqlserver.rb +18 -26
- data/test/cases/scratchpad_test_sqlserver.rb +2 -4
- data/test/cases/showplan_test_sqlserver.rb +24 -33
- data/test/cases/specific_schema_test_sqlserver.rb +66 -65
- data/test/cases/transaction_test_sqlserver.rb +16 -19
- data/test/cases/trigger_test_sqlserver.rb +12 -12
- data/test/cases/utils_test_sqlserver.rb +68 -70
- data/test/cases/uuid_test_sqlserver.rb +11 -13
- data/test/debug.rb +6 -6
- data/test/migrations/create_clients_and_change_column_collation.rb +19 -0
- data/test/migrations/create_clients_and_change_column_null.rb +1 -1
- data/test/migrations/transaction_table/1_table_will_never_be_created.rb +2 -4
- data/test/models/sqlserver/booking.rb +1 -1
- data/test/models/sqlserver/customers_view.rb +1 -1
- data/test/models/sqlserver/dollar_table_name.rb +1 -1
- data/test/models/sqlserver/edge_schema.rb +1 -3
- data/test/models/sqlserver/fk_has_fk.rb +1 -1
- data/test/models/sqlserver/fk_has_pk.rb +1 -1
- data/test/models/sqlserver/natural_pk_data.rb +2 -2
- data/test/models/sqlserver/natural_pk_int_data.rb +1 -1
- data/test/models/sqlserver/no_pk_data.rb +1 -1
- data/test/models/sqlserver/object_default.rb +1 -1
- data/test/models/sqlserver/quoted_table.rb +2 -2
- data/test/models/sqlserver/quoted_view_1.rb +1 -1
- data/test/models/sqlserver/quoted_view_2.rb +1 -1
- data/test/models/sqlserver/sst_memory.rb +1 -1
- data/test/models/sqlserver/sst_string_collation.rb +3 -0
- data/test/models/sqlserver/string_default.rb +1 -1
- data/test/models/sqlserver/string_defaults_big_view.rb +1 -1
- data/test/models/sqlserver/string_defaults_view.rb +1 -1
- data/test/models/sqlserver/tinyint_pk.rb +1 -1
- data/test/models/sqlserver/trigger.rb +2 -2
- data/test/models/sqlserver/trigger_history.rb +1 -1
- data/test/models/sqlserver/upper.rb +1 -1
- data/test/models/sqlserver/uppered.rb +1 -1
- data/test/models/sqlserver/uuid.rb +1 -1
- data/test/schema/sqlserver_specific_schema.rb +36 -21
- data/test/support/coerceable_test_sqlserver.rb +1 -4
- data/test/support/connection_reflection.rb +1 -2
- data/test/support/core_ext/query_cache.rb +1 -1
- data/test/support/load_schema_sqlserver.rb +3 -5
- data/test/support/marshal_compatibility_fixtures/SQLServer/rails_6_0_topic.dump +0 -0
- data/test/support/marshal_compatibility_fixtures/SQLServer/rails_6_0_topic_associations.dump +0 -0
- data/test/support/minitest_sqlserver.rb +1 -1
- data/test/support/paths_sqlserver.rb +9 -11
- data/test/support/rake_helpers.rb +12 -10
- data/test/support/sql_counter_sqlserver.rb +14 -16
- data/test/support/test_in_memory_oltp.rb +7 -7
- metadata +31 -11
- data/.travis.yml +0 -23
|
@@ -4,21 +4,20 @@ module ActiveRecord
|
|
|
4
4
|
module ConnectionAdapters
|
|
5
5
|
module SQLServer
|
|
6
6
|
module Quoting
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
QUOTED_STRING_PREFIX = 'N'.freeze
|
|
7
|
+
QUOTED_TRUE = "1".freeze
|
|
8
|
+
QUOTED_FALSE = "0".freeze
|
|
9
|
+
QUOTED_STRING_PREFIX = "N".freeze
|
|
11
10
|
|
|
12
11
|
def fetch_type_metadata(sql_type, sqlserver_options = {})
|
|
13
12
|
cast_type = lookup_cast_type(sql_type)
|
|
14
|
-
|
|
13
|
+
simple_type = SqlTypeMetadata.new(
|
|
15
14
|
sql_type: sql_type,
|
|
16
15
|
type: cast_type.type,
|
|
17
16
|
limit: cast_type.limit,
|
|
18
17
|
precision: cast_type.precision,
|
|
19
|
-
scale: cast_type.scale
|
|
20
|
-
sqlserver_options: sqlserver_options
|
|
18
|
+
scale: cast_type.scale
|
|
21
19
|
)
|
|
20
|
+
SQLServer::TypeMetadata.new(simple_type, sqlserver_options: sqlserver_options)
|
|
22
21
|
end
|
|
23
22
|
|
|
24
23
|
def quote_string(s)
|
|
@@ -63,10 +62,12 @@ module ActiveRecord
|
|
|
63
62
|
end
|
|
64
63
|
|
|
65
64
|
def quoted_date(value)
|
|
66
|
-
if value.acts_like?(:
|
|
67
|
-
Type::Date.new.serialize(value)
|
|
68
|
-
else value.acts_like?(:time)
|
|
65
|
+
if value.acts_like?(:time)
|
|
69
66
|
Type::DateTime.new.serialize(value)
|
|
67
|
+
elsif value.acts_like?(:date)
|
|
68
|
+
Type::Date.new.serialize(value)
|
|
69
|
+
else
|
|
70
|
+
value
|
|
70
71
|
end
|
|
71
72
|
end
|
|
72
73
|
|
|
@@ -82,8 +83,8 @@ module ActiveRecord
|
|
|
82
83
|
\A
|
|
83
84
|
(
|
|
84
85
|
(?:
|
|
85
|
-
# [table_name].[column_name] | function(one or no argument)
|
|
86
|
-
((?:\w+\.|\[\w+\]\.)?(?:\w+|\[\w+\])) | \w+\((?:|\g<2>)\)
|
|
86
|
+
# [database_name].[database_owner].[table_name].[column_name] | function(one or no argument)
|
|
87
|
+
((?:\w+\.|\[\w+\]\.)?(?:\w+\.|\[\w+\]\.)?(?:\w+\.|\[\w+\]\.)?(?:\w+|\[\w+\])) | \w+\((?:|\g<2>)\)
|
|
87
88
|
)
|
|
88
89
|
(?:\s+AS\s+(?:\w+|\[\w+\]))?
|
|
89
90
|
)
|
|
@@ -95,8 +96,8 @@ module ActiveRecord
|
|
|
95
96
|
\A
|
|
96
97
|
(
|
|
97
98
|
(?:
|
|
98
|
-
# [table_name].[column_name] | function(one or no argument)
|
|
99
|
-
((?:\w+\.|\[\w+\]\.)?(?:\w+|\[\w+\])) | \w+\((?:|\g<2>)\)
|
|
99
|
+
# [database_name].[database_owner].[table_name].[column_name] | function(one or no argument)
|
|
100
|
+
((?:\w+\.|\[\w+\]\.)?(?:\w+\.|\[\w+\]\.)?(?:\w+\.|\[\w+\]\.)?(?:\w+|\[\w+\])) | \w+\((?:|\g<2>)\)
|
|
100
101
|
)
|
|
101
102
|
(?:\s+ASC|\s+DESC)?
|
|
102
103
|
(?:\s+NULLS\s+(?:FIRST|LAST))?
|
|
@@ -130,7 +131,6 @@ module ActiveRecord
|
|
|
130
131
|
super
|
|
131
132
|
end
|
|
132
133
|
end
|
|
133
|
-
|
|
134
134
|
end
|
|
135
135
|
end
|
|
136
136
|
end
|
|
@@ -3,10 +3,13 @@
|
|
|
3
3
|
module ActiveRecord
|
|
4
4
|
module ConnectionAdapters
|
|
5
5
|
module SQLServer
|
|
6
|
-
class SchemaCreation <
|
|
7
|
-
|
|
6
|
+
class SchemaCreation < SchemaCreation
|
|
8
7
|
private
|
|
9
8
|
|
|
9
|
+
def supports_index_using?
|
|
10
|
+
false
|
|
11
|
+
end
|
|
12
|
+
|
|
10
13
|
def visit_TableDefinition(o)
|
|
11
14
|
if_not_exists = o.if_not_exists
|
|
12
15
|
|
|
@@ -30,11 +33,28 @@ module ActiveRecord
|
|
|
30
33
|
sql
|
|
31
34
|
end
|
|
32
35
|
|
|
36
|
+
def visit_CreateIndexDefinition(o)
|
|
37
|
+
if_not_exists = o.if_not_exists
|
|
38
|
+
|
|
39
|
+
o.if_not_exists = false
|
|
40
|
+
|
|
41
|
+
sql = super
|
|
42
|
+
|
|
43
|
+
if if_not_exists
|
|
44
|
+
sql = "IF NOT EXISTS (SELECT name FROM sysindexes WHERE name = '#{o.index.name}') #{sql}"
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
sql
|
|
48
|
+
end
|
|
49
|
+
|
|
33
50
|
def add_column_options!(sql, options)
|
|
34
51
|
sql << " DEFAULT #{quote_default_expression(options[:default], options[:column])}" if options_include_default?(options)
|
|
35
52
|
if options[:null] == false
|
|
36
53
|
sql << " NOT NULL"
|
|
37
54
|
end
|
|
55
|
+
if options[:collation].present?
|
|
56
|
+
sql << " COLLATE #{options[:collation]}"
|
|
57
|
+
end
|
|
38
58
|
if options[:is_identity] == true
|
|
39
59
|
sql << " IDENTITY(1,1)"
|
|
40
60
|
end
|
|
@@ -63,7 +83,6 @@ module ActiveRecord
|
|
|
63
83
|
def options_primary_key_with_nil_default?(options)
|
|
64
84
|
options[:primary_key] && options.include?(:default) && options[:default].nil?
|
|
65
85
|
end
|
|
66
|
-
|
|
67
86
|
end
|
|
68
87
|
end
|
|
69
88
|
end
|
|
@@ -4,35 +4,41 @@ module ActiveRecord
|
|
|
4
4
|
module ConnectionAdapters
|
|
5
5
|
module SQLServer
|
|
6
6
|
class SchemaDumper < ConnectionAdapters::SchemaDumper
|
|
7
|
-
|
|
8
7
|
SQLSEVER_NO_LIMIT_TYPES = [
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
8
|
+
"text",
|
|
9
|
+
"ntext",
|
|
10
|
+
"varchar(max)",
|
|
11
|
+
"nvarchar(max)",
|
|
12
|
+
"varbinary(max)"
|
|
14
13
|
].freeze
|
|
15
14
|
|
|
16
15
|
private
|
|
17
16
|
|
|
18
17
|
def explicit_primary_key_default?(column)
|
|
19
|
-
column.
|
|
18
|
+
column.type == :integer && !column.is_identity?
|
|
20
19
|
end
|
|
21
20
|
|
|
22
21
|
def schema_limit(column)
|
|
23
22
|
return if SQLSEVER_NO_LIMIT_TYPES.include?(column.sql_type)
|
|
23
|
+
|
|
24
24
|
super
|
|
25
25
|
end
|
|
26
26
|
|
|
27
27
|
def schema_collation(column)
|
|
28
28
|
return unless column.collation
|
|
29
|
-
|
|
29
|
+
|
|
30
|
+
# use inspect to ensure collation is dumped as string. Without this it's dumped as
|
|
31
|
+
# a constant ('collation: SQL_Latin1_General_CP1_CI_AS')
|
|
32
|
+
collation = column.collation.inspect
|
|
33
|
+
# use inspect to ensure string comparison
|
|
34
|
+
default_collation = @connection.collation.inspect
|
|
35
|
+
|
|
36
|
+
collation if collation != default_collation
|
|
30
37
|
end
|
|
31
38
|
|
|
32
39
|
def default_primary_key?(column)
|
|
33
|
-
super && column.
|
|
40
|
+
super && column.is_identity?
|
|
34
41
|
end
|
|
35
|
-
|
|
36
42
|
end
|
|
37
43
|
end
|
|
38
44
|
end
|
|
@@ -4,7 +4,6 @@ module ActiveRecord
|
|
|
4
4
|
module ConnectionAdapters
|
|
5
5
|
module SQLServer
|
|
6
6
|
module SchemaStatements
|
|
7
|
-
|
|
8
7
|
def native_database_types
|
|
9
8
|
@native_database_types ||= initialize_native_database_types.freeze
|
|
10
9
|
end
|
|
@@ -19,16 +18,16 @@ module ActiveRecord
|
|
|
19
18
|
# Mimic CASCADE option as best we can.
|
|
20
19
|
if options[:force] == :cascade
|
|
21
20
|
execute_procedure(:sp_fkeys, pktable_name: table_name).each do |fkdata|
|
|
22
|
-
fktable = fkdata[
|
|
23
|
-
fkcolmn = fkdata[
|
|
24
|
-
pktable = fkdata[
|
|
25
|
-
pkcolmn = fkdata[
|
|
26
|
-
remove_foreign_key fktable, name: fkdata[
|
|
21
|
+
fktable = fkdata["FKTABLE_NAME"]
|
|
22
|
+
fkcolmn = fkdata["FKCOLUMN_NAME"]
|
|
23
|
+
pktable = fkdata["PKTABLE_NAME"]
|
|
24
|
+
pkcolmn = fkdata["PKCOLUMN_NAME"]
|
|
25
|
+
remove_foreign_key fktable, name: fkdata["FK_NAME"]
|
|
27
26
|
do_execute "DELETE FROM #{quote_table_name(fktable)} WHERE #{quote_column_name(fkcolmn)} IN ( SELECT #{quote_column_name(pkcolmn)} FROM #{quote_table_name(pktable)} )"
|
|
28
27
|
end
|
|
29
28
|
end
|
|
30
29
|
if options[:if_exists] && @version_year < 2016
|
|
31
|
-
execute "IF EXISTS(SELECT * FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = #{quote(table_name)}) DROP TABLE #{quote_table_name(table_name)}"
|
|
30
|
+
execute "IF EXISTS(SELECT * FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = #{quote(table_name)}) DROP TABLE #{quote_table_name(table_name)}", "SCHEMA"
|
|
32
31
|
else
|
|
33
32
|
super
|
|
34
33
|
end
|
|
@@ -49,11 +48,11 @@ module ActiveRecord
|
|
|
49
48
|
orders = {}
|
|
50
49
|
columns = []
|
|
51
50
|
|
|
52
|
-
index[:index_keys].split(
|
|
51
|
+
index[:index_keys].split(",").each do |column|
|
|
53
52
|
column.strip!
|
|
54
53
|
|
|
55
|
-
if column.
|
|
56
|
-
column.gsub!
|
|
54
|
+
if column.end_with?("(-)")
|
|
55
|
+
column.gsub! "(-)", ""
|
|
57
56
|
orders[column] = :desc
|
|
58
57
|
end
|
|
59
58
|
|
|
@@ -67,6 +66,7 @@ module ActiveRecord
|
|
|
67
66
|
|
|
68
67
|
def columns(table_name)
|
|
69
68
|
return [] if table_name.blank?
|
|
69
|
+
|
|
70
70
|
column_definitions(table_name).map do |ci|
|
|
71
71
|
sqlserver_options = ci.slice :ordinal_position, :is_primary, :is_identity, :table_name
|
|
72
72
|
sql_type_metadata = fetch_type_metadata ci[:type], sqlserver_options
|
|
@@ -105,7 +105,7 @@ module ActiveRecord
|
|
|
105
105
|
identifier = database_prefix_identifier(table_name)
|
|
106
106
|
database = identifier.fully_qualified_database_quoted
|
|
107
107
|
sql = %{
|
|
108
|
-
SELECT KCU.COLUMN_NAME AS [name]
|
|
108
|
+
SELECT #{lowercase_schema_reflection_sql('KCU.COLUMN_NAME')} AS [name]
|
|
109
109
|
FROM #{database}.INFORMATION_SCHEMA.KEY_COLUMN_USAGE AS KCU
|
|
110
110
|
LEFT OUTER JOIN #{database}.INFORMATION_SCHEMA.TABLE_CONSTRAINTS AS TC
|
|
111
111
|
ON KCU.CONSTRAINT_NAME = TC.CONSTRAINT_NAME
|
|
@@ -117,12 +117,12 @@ module ActiveRecord
|
|
|
117
117
|
AND KCU.TABLE_SCHEMA = #{identifier.schema.blank? ? 'schema_name()' : (prepared_statements ? '@1' : quote(identifier.schema))}
|
|
118
118
|
AND TC.CONSTRAINT_TYPE = N'PRIMARY KEY'
|
|
119
119
|
ORDER BY KCU.ORDINAL_POSITION ASC
|
|
120
|
-
}.gsub(/[[:space:]]/,
|
|
120
|
+
}.gsub(/[[:space:]]/, " ")
|
|
121
121
|
binds = []
|
|
122
122
|
nv128 = SQLServer::Type::UnicodeVarchar.new limit: 128
|
|
123
|
-
binds << Relation::QueryAttribute.new(
|
|
124
|
-
binds << Relation::QueryAttribute.new(
|
|
125
|
-
sp_executesql(sql,
|
|
123
|
+
binds << Relation::QueryAttribute.new("TABLE_NAME", identifier.object, nv128)
|
|
124
|
+
binds << Relation::QueryAttribute.new("TABLE_SCHEMA", identifier.schema, nv128) unless identifier.schema.blank?
|
|
125
|
+
sp_executesql(sql, "SCHEMA", binds).map { |r| r["name"] }
|
|
126
126
|
end
|
|
127
127
|
|
|
128
128
|
def rename_table(table_name, new_name)
|
|
@@ -130,8 +130,10 @@ module ActiveRecord
|
|
|
130
130
|
rename_table_indexes(table_name, new_name)
|
|
131
131
|
end
|
|
132
132
|
|
|
133
|
-
def remove_column(table_name, column_name, type = nil, options
|
|
134
|
-
raise ArgumentError.new(
|
|
133
|
+
def remove_column(table_name, column_name, type = nil, **options)
|
|
134
|
+
raise ArgumentError.new("You must specify at least one column name. Example: remove_column(:people, :first_name)") if column_name.is_a? Array
|
|
135
|
+
return if options[:if_exists] == true && !column_exists?(table_name, column_name)
|
|
136
|
+
|
|
135
137
|
remove_check_constraints(table_name, column_name)
|
|
136
138
|
remove_default_constraint(table_name, column_name)
|
|
137
139
|
remove_indexes(table_name, column_name)
|
|
@@ -144,10 +146,10 @@ module ActiveRecord
|
|
|
144
146
|
column_object = schema_cache.columns(table_name).find { |c| c.name.to_s == column_name.to_s }
|
|
145
147
|
without_constraints = options.key?(:default) || options.key?(:limit)
|
|
146
148
|
default = if !options.key?(:default) && column_object
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
149
|
+
column_object.default
|
|
150
|
+
else
|
|
151
|
+
options[:default]
|
|
152
|
+
end
|
|
151
153
|
if without_constraints || (column_object && column_object.type != type.to_sym)
|
|
152
154
|
remove_default_constraint(table_name, column_name)
|
|
153
155
|
indexes = indexes(table_name).select { |index| index.columns.include?(column_name.to_s) }
|
|
@@ -155,7 +157,8 @@ module ActiveRecord
|
|
|
155
157
|
end
|
|
156
158
|
sql_commands << "UPDATE #{quote_table_name(table_name)} SET #{quote_column_name(column_name)}=#{quote_default_expression(options[:default], column_object)} WHERE #{quote_column_name(column_name)} IS NULL" if !options[:null].nil? && options[:null] == false && !options[:default].nil?
|
|
157
159
|
alter_command = "ALTER TABLE #{quote_table_name(table_name)} ALTER COLUMN #{quote_column_name(column_name)} #{type_to_sql(type, limit: options[:limit], precision: options[:precision], scale: options[:scale])}"
|
|
158
|
-
alter_command +=
|
|
160
|
+
alter_command += " COLLATE #{options[:collation]}" if options[:collation].present?
|
|
161
|
+
alter_command += " NOT NULL" if !options[:null].nil? && options[:null] == false
|
|
159
162
|
sql_commands << alter_command
|
|
160
163
|
if without_constraints
|
|
161
164
|
default = quote_default_expression(default, column_object || column_for(table_name, column_name))
|
|
@@ -173,6 +176,7 @@ module ActiveRecord
|
|
|
173
176
|
clear_cache!
|
|
174
177
|
column = column_for(table_name, column_name)
|
|
175
178
|
return unless column
|
|
179
|
+
|
|
176
180
|
remove_default_constraint(table_name, column_name)
|
|
177
181
|
default = extract_new_default_value(default_or_changes)
|
|
178
182
|
do_execute "ALTER TABLE #{quote_table_name(table_name)} ADD CONSTRAINT #{default_constraint_name(table_name, column_name)} DEFAULT #{quote_default_expression(default, column)} FOR #{quote_column_name(column_name)}"
|
|
@@ -182,15 +186,16 @@ module ActiveRecord
|
|
|
182
186
|
def rename_column(table_name, column_name, new_column_name)
|
|
183
187
|
clear_cache!
|
|
184
188
|
identifier = SQLServer::Utils.extract_identifiers("#{table_name}.#{column_name}")
|
|
185
|
-
execute_procedure :sp_rename, identifier.quoted, new_column_name,
|
|
189
|
+
execute_procedure :sp_rename, identifier.quoted, new_column_name, "COLUMN"
|
|
186
190
|
rename_column_indexes(table_name, column_name, new_column_name)
|
|
187
191
|
clear_cache!
|
|
188
192
|
end
|
|
189
193
|
|
|
190
194
|
def rename_index(table_name, old_name, new_name)
|
|
191
|
-
raise ArgumentError, "Index name '#{new_name}' on table '#{table_name}' is too long; the limit is #{
|
|
195
|
+
raise ArgumentError, "Index name '#{new_name}' on table '#{table_name}' is too long; the limit is #{index_name_length} characters" if new_name.length > index_name_length
|
|
196
|
+
|
|
192
197
|
identifier = SQLServer::Utils.extract_identifiers("#{table_name}.#{old_name}")
|
|
193
|
-
execute_procedure :sp_rename, identifier.quoted, new_name,
|
|
198
|
+
execute_procedure :sp_rename, identifier.quoted, new_name, "INDEX"
|
|
194
199
|
end
|
|
195
200
|
|
|
196
201
|
def remove_index!(table_name, index_name)
|
|
@@ -202,13 +207,13 @@ module ActiveRecord
|
|
|
202
207
|
fk_info = execute_procedure :sp_fkeys, nil, identifier.schema, nil, identifier.object, identifier.schema
|
|
203
208
|
fk_info.map do |row|
|
|
204
209
|
from_table = identifier.object
|
|
205
|
-
to_table = row[
|
|
210
|
+
to_table = row["PKTABLE_NAME"]
|
|
206
211
|
options = {
|
|
207
|
-
name: row[
|
|
208
|
-
column: row[
|
|
209
|
-
primary_key: row[
|
|
210
|
-
on_update: extract_foreign_key_action(
|
|
211
|
-
on_delete: extract_foreign_key_action(
|
|
212
|
+
name: row["FK_NAME"],
|
|
213
|
+
column: row["FKCOLUMN_NAME"],
|
|
214
|
+
primary_key: row["PKCOLUMN_NAME"],
|
|
215
|
+
on_update: extract_foreign_key_action("update", row["FK_NAME"]),
|
|
216
|
+
on_delete: extract_foreign_key_action("delete", row["FK_NAME"])
|
|
212
217
|
}
|
|
213
218
|
ForeignKeyDefinition.new from_table, to_table, options
|
|
214
219
|
end
|
|
@@ -216,8 +221,8 @@ module ActiveRecord
|
|
|
216
221
|
|
|
217
222
|
def extract_foreign_key_action(action, fk_name)
|
|
218
223
|
case select_value("SELECT #{action}_referential_action_desc FROM sys.foreign_keys WHERE name = '#{fk_name}'")
|
|
219
|
-
when
|
|
220
|
-
when
|
|
224
|
+
when "CASCADE" then :cascade
|
|
225
|
+
when "SET_NULL" then :nullify
|
|
221
226
|
end
|
|
222
227
|
end
|
|
223
228
|
|
|
@@ -225,15 +230,15 @@ module ActiveRecord
|
|
|
225
230
|
type_limitable = %w(string integer float char nchar varchar nvarchar).include?(type.to_s)
|
|
226
231
|
limit = nil unless type_limitable
|
|
227
232
|
case type.to_s
|
|
228
|
-
when
|
|
233
|
+
when "integer"
|
|
229
234
|
case limit
|
|
230
|
-
when 1 then
|
|
231
|
-
when 2 then
|
|
232
|
-
when 3..4, nil then
|
|
233
|
-
when 5..8 then
|
|
235
|
+
when 1 then "tinyint"
|
|
236
|
+
when 2 then "smallint"
|
|
237
|
+
when 3..4, nil then "integer"
|
|
238
|
+
when 5..8 then "bigint"
|
|
234
239
|
else raise(ActiveRecordError, "No integer type has byte size #{limit}. Use a numeric with precision 0 instead.")
|
|
235
240
|
end
|
|
236
|
-
when
|
|
241
|
+
when "datetime2"
|
|
237
242
|
column_type_sql = super
|
|
238
243
|
if precision
|
|
239
244
|
if (0..7) === precision
|
|
@@ -249,11 +254,11 @@ module ActiveRecord
|
|
|
249
254
|
end
|
|
250
255
|
|
|
251
256
|
def columns_for_distinct(columns, orders)
|
|
252
|
-
order_columns = orders.reject(&:blank?).map{ |s|
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
+
order_columns = orders.reject(&:blank?).map { |s|
|
|
258
|
+
s = s.to_sql unless s.is_a?(String)
|
|
259
|
+
s.gsub(/\s+(?:ASC|DESC)\b/i, "")
|
|
260
|
+
.gsub(/\s+NULLS\s+(?:FIRST|LAST)\b/i, "")
|
|
261
|
+
}.reject(&:blank?).map.with_index { |column, i| "#{column} AS alias_#{i}" }
|
|
257
262
|
|
|
258
263
|
(order_columns << super).join(", ")
|
|
259
264
|
end
|
|
@@ -270,7 +275,7 @@ module ActiveRecord
|
|
|
270
275
|
do_execute("UPDATE #{table_id} SET #{column_id}=#{quote(default)} WHERE #{column_id} IS NULL")
|
|
271
276
|
end
|
|
272
277
|
sql = "ALTER TABLE #{table_id} ALTER COLUMN #{column_id} #{type_to_sql column.type, limit: column.limit, precision: column.precision, scale: column.scale}"
|
|
273
|
-
sql +=
|
|
278
|
+
sql += " NOT NULL" if !allow_null.nil? && allow_null == false
|
|
274
279
|
do_execute sql
|
|
275
280
|
end
|
|
276
281
|
|
|
@@ -278,14 +283,33 @@ module ActiveRecord
|
|
|
278
283
|
SQLServer::SchemaDumper.create(self, options)
|
|
279
284
|
end
|
|
280
285
|
|
|
286
|
+
def create_schema(schema_name, authorization = nil)
|
|
287
|
+
sql = "CREATE SCHEMA [#{schema_name}]"
|
|
288
|
+
sql += " AUTHORIZATION [#{authorization}]" if authorization
|
|
289
|
+
|
|
290
|
+
execute sql
|
|
291
|
+
end
|
|
292
|
+
|
|
293
|
+
def change_table_schema(schema_name, table_name)
|
|
294
|
+
execute "ALTER SCHEMA [#{schema_name}] TRANSFER [#{table_name}]"
|
|
295
|
+
end
|
|
296
|
+
|
|
297
|
+
def drop_schema(schema_name)
|
|
298
|
+
execute "DROP SCHEMA [#{schema_name}]"
|
|
299
|
+
end
|
|
300
|
+
|
|
281
301
|
private
|
|
282
302
|
|
|
283
303
|
def data_source_sql(name = nil, type: nil)
|
|
284
304
|
scope = quoted_scope name, type: type
|
|
305
|
+
|
|
285
306
|
table_name = lowercase_schema_reflection_sql 'TABLE_NAME'
|
|
307
|
+
database = scope[:database].present? ? "#{scope[:database]}." : ""
|
|
308
|
+
table_catalog = scope[:database].present? ? quote(scope[:database]) : "DB_NAME()"
|
|
309
|
+
|
|
286
310
|
sql = "SELECT #{table_name}"
|
|
287
|
-
sql +=
|
|
288
|
-
sql +=
|
|
311
|
+
sql += " FROM #{database}INFORMATION_SCHEMA.TABLES WITH (NOLOCK)"
|
|
312
|
+
sql += " WHERE TABLE_CATALOG = #{table_catalog}"
|
|
289
313
|
sql += " AND TABLE_SCHEMA = #{quote(scope[:schema])}"
|
|
290
314
|
sql += " AND TABLE_NAME = #{quote(scope[:name])}" if scope[:name]
|
|
291
315
|
sql += " AND TABLE_TYPE = #{quote(scope[:type])}" if scope[:type]
|
|
@@ -296,7 +320,8 @@ module ActiveRecord
|
|
|
296
320
|
def quoted_scope(name = nil, type: nil)
|
|
297
321
|
identifier = SQLServer::Utils.extract_identifiers(name)
|
|
298
322
|
{}.tap do |scope|
|
|
299
|
-
scope[:
|
|
323
|
+
scope[:database] = identifier.database if identifier.database
|
|
324
|
+
scope[:schema] = identifier.schema || "dbo"
|
|
300
325
|
scope[:name] = identifier.object if identifier.object
|
|
301
326
|
scope[:type] = type if type
|
|
302
327
|
end
|
|
@@ -306,37 +331,37 @@ module ActiveRecord
|
|
|
306
331
|
|
|
307
332
|
def initialize_native_database_types
|
|
308
333
|
{
|
|
309
|
-
primary_key:
|
|
310
|
-
primary_key_nonclustered:
|
|
311
|
-
integer: { name:
|
|
312
|
-
bigint: { name:
|
|
313
|
-
boolean: { name:
|
|
314
|
-
decimal: { name:
|
|
315
|
-
money: { name:
|
|
316
|
-
smallmoney: { name:
|
|
317
|
-
float: { name:
|
|
318
|
-
real: { name:
|
|
319
|
-
date: { name:
|
|
320
|
-
datetime: { name:
|
|
321
|
-
datetime2: { name:
|
|
322
|
-
datetimeoffset: { name:
|
|
323
|
-
smalldatetime: { name:
|
|
324
|
-
timestamp: { name:
|
|
325
|
-
time: { name:
|
|
326
|
-
char: { name:
|
|
327
|
-
varchar: { name:
|
|
328
|
-
varchar_max: { name:
|
|
329
|
-
text_basic: { name:
|
|
330
|
-
nchar: { name:
|
|
331
|
-
string: { name:
|
|
332
|
-
text: { name:
|
|
333
|
-
ntext: { name:
|
|
334
|
-
binary_basic: { name:
|
|
335
|
-
varbinary: { name:
|
|
336
|
-
binary: { name:
|
|
337
|
-
uuid: { name:
|
|
338
|
-
ss_timestamp: { name:
|
|
339
|
-
json: { name:
|
|
334
|
+
primary_key: "bigint NOT NULL IDENTITY(1,1) PRIMARY KEY",
|
|
335
|
+
primary_key_nonclustered: "bigint NOT NULL IDENTITY(1,1) PRIMARY KEY NONCLUSTERED",
|
|
336
|
+
integer: { name: "int", limit: 4 },
|
|
337
|
+
bigint: { name: "bigint" },
|
|
338
|
+
boolean: { name: "bit" },
|
|
339
|
+
decimal: { name: "decimal" },
|
|
340
|
+
money: { name: "money" },
|
|
341
|
+
smallmoney: { name: "smallmoney" },
|
|
342
|
+
float: { name: "float" },
|
|
343
|
+
real: { name: "real" },
|
|
344
|
+
date: { name: "date" },
|
|
345
|
+
datetime: { name: "datetime" },
|
|
346
|
+
datetime2: { name: "datetime2" },
|
|
347
|
+
datetimeoffset: { name: "datetimeoffset" },
|
|
348
|
+
smalldatetime: { name: "smalldatetime" },
|
|
349
|
+
timestamp: { name: "datetime" },
|
|
350
|
+
time: { name: "time" },
|
|
351
|
+
char: { name: "char" },
|
|
352
|
+
varchar: { name: "varchar", limit: 8000 },
|
|
353
|
+
varchar_max: { name: "varchar(max)" },
|
|
354
|
+
text_basic: { name: "text" },
|
|
355
|
+
nchar: { name: "nchar" },
|
|
356
|
+
string: { name: "nvarchar", limit: 4000 },
|
|
357
|
+
text: { name: "nvarchar(max)" },
|
|
358
|
+
ntext: { name: "ntext" },
|
|
359
|
+
binary_basic: { name: "binary" },
|
|
360
|
+
varbinary: { name: "varbinary", limit: 8000 },
|
|
361
|
+
binary: { name: "varbinary(max)" },
|
|
362
|
+
uuid: { name: "uniqueidentifier" },
|
|
363
|
+
ss_timestamp: { name: "timestamp" },
|
|
364
|
+
json: { name: "nvarchar(max)" }
|
|
340
365
|
}
|
|
341
366
|
end
|
|
342
367
|
|
|
@@ -350,9 +375,9 @@ module ActiveRecord
|
|
|
350
375
|
|
|
351
376
|
binds = []
|
|
352
377
|
nv128 = SQLServer::Type::UnicodeVarchar.new limit: 128
|
|
353
|
-
binds << Relation::QueryAttribute.new(
|
|
354
|
-
binds << Relation::QueryAttribute.new(
|
|
355
|
-
results = sp_executesql(sql,
|
|
378
|
+
binds << Relation::QueryAttribute.new("TABLE_NAME", identifier.object, nv128)
|
|
379
|
+
binds << Relation::QueryAttribute.new("TABLE_SCHEMA", identifier.schema, nv128) unless identifier.schema.blank?
|
|
380
|
+
results = sp_executesql(sql, "SCHEMA", binds)
|
|
356
381
|
results.map do |ci|
|
|
357
382
|
ci = ci.symbolize_keys
|
|
358
383
|
ci[:_type] = ci[:type]
|
|
@@ -383,7 +408,7 @@ module ActiveRecord
|
|
|
383
408
|
WHERE
|
|
384
409
|
c.TABLE_NAME = '#{view_tblnm}'
|
|
385
410
|
AND c.COLUMN_NAME = '#{views_real_column_name(table_name, ci[:name])}'
|
|
386
|
-
}.squish,
|
|
411
|
+
}.squish, "SCHEMA"
|
|
387
412
|
end
|
|
388
413
|
case default
|
|
389
414
|
when nil
|
|
@@ -402,7 +427,7 @@ module ActiveRecord
|
|
|
402
427
|
else ci[:type]
|
|
403
428
|
end
|
|
404
429
|
value = default.match(/\A\((.*)\)\Z/m)[1]
|
|
405
|
-
value = select_value("SELECT CAST(#{value} AS #{type}) AS value",
|
|
430
|
+
value = select_value("SELECT CAST(#{value} AS #{type}) AS value", "SCHEMA")
|
|
406
431
|
[value, nil]
|
|
407
432
|
end
|
|
408
433
|
end
|
|
@@ -415,11 +440,11 @@ module ActiveRecord
|
|
|
415
440
|
end
|
|
416
441
|
|
|
417
442
|
def column_definitions_sql(database, identifier)
|
|
418
|
-
object_name = prepared_statements ?
|
|
419
|
-
schema_name = if identifier.schema.blank?
|
|
420
|
-
|
|
443
|
+
object_name = prepared_statements ? "@0" : quote(identifier.object)
|
|
444
|
+
schema_name = if identifier.schema.blank?
|
|
445
|
+
"schema_name()"
|
|
421
446
|
else
|
|
422
|
-
prepared_statements ?
|
|
447
|
+
prepared_statements ? "@1" : quote(identifier.schema)
|
|
423
448
|
end
|
|
424
449
|
|
|
425
450
|
%{
|
|
@@ -469,6 +494,7 @@ module ActiveRecord
|
|
|
469
494
|
AND c.default_object_id = d.object_id
|
|
470
495
|
LEFT OUTER JOIN #{database}.sys.key_constraints k
|
|
471
496
|
ON c.object_id = k.parent_object_id
|
|
497
|
+
AND k.type = 'PK'
|
|
472
498
|
LEFT OUTER JOIN #{database}.sys.index_columns ic
|
|
473
499
|
ON k.parent_object_id = ic.object_id
|
|
474
500
|
AND k.unique_index_id = ic.index_id
|
|
@@ -478,11 +504,11 @@ module ActiveRecord
|
|
|
478
504
|
AND s.name = #{schema_name}
|
|
479
505
|
ORDER BY
|
|
480
506
|
c.column_id
|
|
481
|
-
}.gsub(/[ \t\r\n]+/,
|
|
507
|
+
}.gsub(/[ \t\r\n]+/, " ").strip
|
|
482
508
|
end
|
|
483
509
|
|
|
484
510
|
def remove_check_constraints(table_name, column_name)
|
|
485
|
-
constraints = select_values "SELECT CONSTRAINT_NAME FROM INFORMATION_SCHEMA.CONSTRAINT_COLUMN_USAGE where TABLE_NAME = '#{quote_string(table_name)}' and COLUMN_NAME = '#{quote_string(column_name)}'",
|
|
511
|
+
constraints = select_values "SELECT CONSTRAINT_NAME FROM INFORMATION_SCHEMA.CONSTRAINT_COLUMN_USAGE where TABLE_NAME = '#{quote_string(table_name)}' and COLUMN_NAME = '#{quote_string(column_name)}'", "SCHEMA"
|
|
486
512
|
constraints.each do |constraint|
|
|
487
513
|
do_execute "ALTER TABLE #{quote_table_name(table_name)} DROP CONSTRAINT #{quote_column_name(constraint)}"
|
|
488
514
|
end
|
|
@@ -490,8 +516,8 @@ module ActiveRecord
|
|
|
490
516
|
|
|
491
517
|
def remove_default_constraint(table_name, column_name)
|
|
492
518
|
# If their are foreign keys in this table, we could still get back a 2D array, so flatten just in case.
|
|
493
|
-
execute_procedure(:sp_helpconstraint, table_name,
|
|
494
|
-
row[
|
|
519
|
+
execute_procedure(:sp_helpconstraint, table_name, "nomsg").flatten.select do |row|
|
|
520
|
+
row["constraint_type"] == "DEFAULT on column #{column_name}"
|
|
495
521
|
end.each do |row|
|
|
496
522
|
do_execute "ALTER TABLE #{quote_table_name(table_name)} DROP CONSTRAINT #{row['constraint_name']}"
|
|
497
523
|
end
|
|
@@ -507,12 +533,12 @@ module ActiveRecord
|
|
|
507
533
|
|
|
508
534
|
def get_table_name(sql)
|
|
509
535
|
tn = if sql =~ /^\s*(INSERT|EXEC sp_executesql N'INSERT)(\s+INTO)?\s+([^\(\s]+)\s*|^\s*update\s+([^\(\s]+)\s*/i
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
536
|
+
Regexp.last_match[3] || Regexp.last_match[4]
|
|
537
|
+
elsif sql =~ /FROM\s+([^\(\s]+)\s*/i
|
|
538
|
+
Regexp.last_match[1]
|
|
539
|
+
else
|
|
540
|
+
nil
|
|
541
|
+
end
|
|
516
542
|
SQLServer::Utils.extract_identifiers(tn).object
|
|
517
543
|
end
|
|
518
544
|
|
|
@@ -528,22 +554,22 @@ module ActiveRecord
|
|
|
528
554
|
|
|
529
555
|
def view_table_name(table_name)
|
|
530
556
|
view_info = view_information(table_name)
|
|
531
|
-
view_info ? get_table_name(view_info[
|
|
557
|
+
view_info ? get_table_name(view_info["VIEW_DEFINITION"]) : table_name
|
|
532
558
|
end
|
|
533
559
|
|
|
534
560
|
def view_information(table_name)
|
|
535
561
|
@view_information ||= {}
|
|
536
562
|
@view_information[table_name] ||= begin
|
|
537
563
|
identifier = SQLServer::Utils.extract_identifiers(table_name)
|
|
538
|
-
view_info = select_one "SELECT * FROM INFORMATION_SCHEMA.VIEWS WITH (NOLOCK) WHERE TABLE_NAME = #{quote(identifier.object)}",
|
|
564
|
+
view_info = select_one "SELECT * FROM INFORMATION_SCHEMA.VIEWS WITH (NOLOCK) WHERE TABLE_NAME = #{quote(identifier.object)}", "SCHEMA"
|
|
539
565
|
if view_info
|
|
540
566
|
view_info = view_info.with_indifferent_access
|
|
541
567
|
if view_info[:VIEW_DEFINITION].blank? || view_info[:VIEW_DEFINITION].length == 4000
|
|
542
568
|
view_info[:VIEW_DEFINITION] = begin
|
|
543
|
-
select_values("EXEC sp_helptext #{identifier.object_quoted}",
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
569
|
+
select_values("EXEC sp_helptext #{identifier.object_quoted}", "SCHEMA").join
|
|
570
|
+
rescue
|
|
571
|
+
warn "No view definition found, possible permissions problem.\nPlease run GRANT VIEW DEFINITION TO your_user;"
|
|
572
|
+
nil
|
|
547
573
|
end
|
|
548
574
|
end
|
|
549
575
|
end
|
|
@@ -554,6 +580,7 @@ module ActiveRecord
|
|
|
554
580
|
def views_real_column_name(table_name, column_name)
|
|
555
581
|
view_definition = view_information(table_name)[:VIEW_DEFINITION]
|
|
556
582
|
return column_name unless view_definition
|
|
583
|
+
|
|
557
584
|
match_data = view_definition.match(/([\w-]*)\s+as\s+#{column_name}/im)
|
|
558
585
|
match_data ? match_data[1] : column_name
|
|
559
586
|
end
|
|
@@ -561,7 +588,6 @@ module ActiveRecord
|
|
|
561
588
|
def create_table_definition(*args, **options)
|
|
562
589
|
SQLServer::TableDefinition.new(self, *args, **options)
|
|
563
590
|
end
|
|
564
|
-
|
|
565
591
|
end
|
|
566
592
|
end
|
|
567
593
|
end
|