activerecord-sqlserver-adapter 5.2.1 → 6.0.2
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/.editorconfig +9 -0
- data/.github/issue_template.md +23 -0
- data/.github/workflows/ci.yml +26 -0
- data/.gitignore +1 -0
- data/.rubocop.yml +29 -0
- data/CHANGELOG.md +58 -20
- data/{Dockerfile → Dockerfile.ci} +1 -1
- data/Gemfile +48 -41
- data/Guardfile +9 -8
- data/README.md +28 -31
- data/RUNNING_UNIT_TESTS.md +3 -0
- data/Rakefile +14 -16
- data/VERSION +1 -1
- data/activerecord-sqlserver-adapter.gemspec +25 -14
- data/appveyor.yml +24 -17
- data/docker-compose.ci.yml +7 -5
- data/guides/RELEASING.md +11 -0
- data/lib/active_record/connection_adapters/sqlserver/core_ext/active_record.rb +2 -4
- data/lib/active_record/connection_adapters/sqlserver/core_ext/attribute_methods.rb +3 -4
- data/lib/active_record/connection_adapters/sqlserver/core_ext/calculations.rb +5 -4
- data/lib/active_record/connection_adapters/sqlserver/core_ext/explain.rb +3 -3
- data/lib/active_record/connection_adapters/sqlserver/core_ext/explain_subscriber.rb +2 -0
- data/lib/active_record/connection_adapters/sqlserver/core_ext/finder_methods.rb +8 -7
- data/lib/active_record/connection_adapters/sqlserver/core_ext/preloader.rb +36 -0
- data/lib/active_record/connection_adapters/sqlserver/core_ext/query_methods.rb +6 -4
- data/lib/active_record/connection_adapters/sqlserver/database_limits.rb +9 -0
- data/lib/active_record/connection_adapters/sqlserver/database_statements.rb +88 -44
- data/lib/active_record/connection_adapters/sqlserver/database_tasks.rb +9 -12
- data/lib/active_record/connection_adapters/sqlserver/errors.rb +2 -3
- data/lib/active_record/connection_adapters/sqlserver/quoting.rb +46 -8
- data/lib/active_record/connection_adapters/sqlserver/schema_creation.rb +16 -5
- data/lib/active_record/connection_adapters/sqlserver/schema_dumper.rb +9 -7
- data/lib/active_record/connection_adapters/sqlserver/schema_statements.rb +210 -163
- data/lib/active_record/connection_adapters/sqlserver/showplan.rb +8 -8
- data/lib/active_record/connection_adapters/sqlserver/showplan/printer_table.rb +4 -2
- data/lib/active_record/connection_adapters/sqlserver/showplan/printer_xml.rb +3 -1
- data/lib/active_record/connection_adapters/sqlserver/sql_type_metadata.rb +2 -2
- data/lib/active_record/connection_adapters/sqlserver/table_definition.rb +43 -44
- data/lib/active_record/connection_adapters/sqlserver/transaction.rb +7 -9
- data/lib/active_record/connection_adapters/sqlserver/type.rb +38 -35
- data/lib/active_record/connection_adapters/sqlserver/type/big_integer.rb +3 -3
- data/lib/active_record/connection_adapters/sqlserver/type/binary.rb +5 -4
- data/lib/active_record/connection_adapters/sqlserver/type/boolean.rb +3 -3
- data/lib/active_record/connection_adapters/sqlserver/type/char.rb +7 -4
- data/lib/active_record/connection_adapters/sqlserver/type/data.rb +2 -2
- data/lib/active_record/connection_adapters/sqlserver/type/date.rb +4 -3
- data/lib/active_record/connection_adapters/sqlserver/type/datetime.rb +8 -8
- data/lib/active_record/connection_adapters/sqlserver/type/datetime2.rb +2 -2
- data/lib/active_record/connection_adapters/sqlserver/type/datetimeoffset.rb +2 -2
- data/lib/active_record/connection_adapters/sqlserver/type/decimal.rb +5 -4
- data/lib/active_record/connection_adapters/sqlserver/type/decimal_without_scale.rb +22 -0
- data/lib/active_record/connection_adapters/sqlserver/type/float.rb +3 -3
- data/lib/active_record/connection_adapters/sqlserver/type/integer.rb +3 -3
- data/lib/active_record/connection_adapters/sqlserver/type/json.rb +2 -1
- data/lib/active_record/connection_adapters/sqlserver/type/money.rb +4 -4
- data/lib/active_record/connection_adapters/sqlserver/type/real.rb +3 -3
- data/lib/active_record/connection_adapters/sqlserver/type/small_integer.rb +3 -3
- data/lib/active_record/connection_adapters/sqlserver/type/small_money.rb +4 -4
- data/lib/active_record/connection_adapters/sqlserver/type/smalldatetime.rb +3 -3
- data/lib/active_record/connection_adapters/sqlserver/type/string.rb +2 -2
- data/lib/active_record/connection_adapters/sqlserver/type/text.rb +3 -3
- data/lib/active_record/connection_adapters/sqlserver/type/time.rb +6 -6
- data/lib/active_record/connection_adapters/sqlserver/type/time_value_fractional.rb +8 -9
- data/lib/active_record/connection_adapters/sqlserver/type/timestamp.rb +3 -3
- data/lib/active_record/connection_adapters/sqlserver/type/tiny_integer.rb +3 -3
- data/lib/active_record/connection_adapters/sqlserver/type/unicode_char.rb +5 -4
- data/lib/active_record/connection_adapters/sqlserver/type/unicode_string.rb +2 -2
- data/lib/active_record/connection_adapters/sqlserver/type/unicode_text.rb +3 -3
- data/lib/active_record/connection_adapters/sqlserver/type/unicode_varchar.rb +6 -5
- data/lib/active_record/connection_adapters/sqlserver/type/unicode_varchar_max.rb +4 -4
- data/lib/active_record/connection_adapters/sqlserver/type/uuid.rb +4 -3
- data/lib/active_record/connection_adapters/sqlserver/type/varbinary.rb +6 -5
- data/lib/active_record/connection_adapters/sqlserver/type/varbinary_max.rb +4 -4
- data/lib/active_record/connection_adapters/sqlserver/type/varchar.rb +6 -5
- data/lib/active_record/connection_adapters/sqlserver/type/varchar_max.rb +4 -4
- data/lib/active_record/connection_adapters/sqlserver/utils.rb +10 -11
- data/lib/active_record/connection_adapters/sqlserver/version.rb +2 -2
- data/lib/active_record/connection_adapters/sqlserver_adapter.rb +145 -94
- data/lib/active_record/connection_adapters/sqlserver_column.rb +9 -5
- data/lib/active_record/sqlserver_base.rb +9 -1
- data/lib/active_record/tasks/sqlserver_database_tasks.rb +28 -32
- data/lib/activerecord-sqlserver-adapter.rb +3 -1
- data/lib/arel/visitors/sqlserver.rb +108 -34
- data/lib/arel_sqlserver.rb +4 -2
- data/test/appveyor/dbsetup.ps1 +4 -4
- data/test/cases/adapter_test_sqlserver.rb +246 -171
- data/test/cases/change_column_null_test_sqlserver.rb +14 -12
- data/test/cases/coerced_tests.rb +722 -381
- data/test/cases/column_test_sqlserver.rb +287 -285
- data/test/cases/connection_test_sqlserver.rb +17 -20
- data/test/cases/execute_procedure_test_sqlserver.rb +20 -20
- data/test/cases/fetch_test_sqlserver.rb +16 -22
- data/test/cases/fully_qualified_identifier_test_sqlserver.rb +15 -19
- data/test/cases/helper_sqlserver.rb +15 -15
- data/test/cases/in_clause_test_sqlserver.rb +36 -0
- data/test/cases/index_test_sqlserver.rb +15 -15
- data/test/cases/json_test_sqlserver.rb +25 -25
- data/test/cases/lateral_test_sqlserver.rb +35 -0
- data/test/cases/migration_test_sqlserver.rb +67 -27
- data/test/cases/optimizer_hints_test_sqlserver.rb +72 -0
- data/test/cases/order_test_sqlserver.rb +53 -54
- data/test/cases/pessimistic_locking_test_sqlserver.rb +27 -33
- data/test/cases/rake_test_sqlserver.rb +33 -45
- data/test/cases/schema_dumper_test_sqlserver.rb +115 -109
- data/test/cases/schema_test_sqlserver.rb +20 -26
- data/test/cases/scratchpad_test_sqlserver.rb +4 -4
- data/test/cases/showplan_test_sqlserver.rb +28 -35
- data/test/cases/specific_schema_test_sqlserver.rb +68 -65
- data/test/cases/transaction_test_sqlserver.rb +18 -20
- data/test/cases/trigger_test_sqlserver.rb +14 -13
- data/test/cases/utils_test_sqlserver.rb +70 -70
- data/test/cases/uuid_test_sqlserver.rb +13 -14
- data/test/debug.rb +8 -6
- data/test/migrations/create_clients_and_change_column_null.rb +3 -1
- data/test/migrations/transaction_table/1_table_will_never_be_created.rb +4 -4
- data/test/models/sqlserver/booking.rb +3 -1
- data/test/models/sqlserver/customers_view.rb +3 -1
- data/test/models/sqlserver/datatype.rb +2 -0
- data/test/models/sqlserver/datatype_migration.rb +2 -0
- data/test/models/sqlserver/dollar_table_name.rb +3 -1
- data/test/models/sqlserver/edge_schema.rb +3 -3
- data/test/models/sqlserver/fk_has_fk.rb +3 -1
- data/test/models/sqlserver/fk_has_pk.rb +3 -1
- data/test/models/sqlserver/natural_pk_data.rb +4 -2
- data/test/models/sqlserver/natural_pk_int_data.rb +3 -1
- data/test/models/sqlserver/no_pk_data.rb +3 -1
- data/test/models/sqlserver/object_default.rb +3 -1
- data/test/models/sqlserver/quoted_table.rb +4 -2
- data/test/models/sqlserver/quoted_view_1.rb +3 -1
- data/test/models/sqlserver/quoted_view_2.rb +3 -1
- data/test/models/sqlserver/sst_memory.rb +3 -1
- data/test/models/sqlserver/string_default.rb +3 -1
- data/test/models/sqlserver/string_defaults_big_view.rb +3 -1
- data/test/models/sqlserver/string_defaults_view.rb +3 -1
- data/test/models/sqlserver/tinyint_pk.rb +3 -1
- data/test/models/sqlserver/trigger.rb +4 -2
- data/test/models/sqlserver/trigger_history.rb +3 -1
- data/test/models/sqlserver/upper.rb +3 -1
- data/test/models/sqlserver/uppered.rb +3 -1
- data/test/models/sqlserver/uuid.rb +3 -1
- data/test/schema/sqlserver_specific_schema.rb +31 -21
- data/test/support/coerceable_test_sqlserver.rb +15 -9
- data/test/support/connection_reflection.rb +3 -2
- data/test/support/core_ext/query_cache.rb +4 -1
- data/test/support/load_schema_sqlserver.rb +5 -5
- data/test/support/minitest_sqlserver.rb +3 -1
- data/test/support/paths_sqlserver.rb +11 -11
- data/test/support/rake_helpers.rb +13 -10
- data/test/support/sql_counter_sqlserver.rb +3 -4
- data/test/support/test_in_memory_oltp.rb +9 -7
- metadata +27 -12
- data/.travis.yml +0 -25
|
@@ -1,17 +1,17 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
module ActiveRecord
|
|
2
4
|
module ConnectionAdapters
|
|
3
5
|
module SQLServer
|
|
4
6
|
module Type
|
|
5
7
|
class Timestamp < Binary
|
|
6
|
-
|
|
7
8
|
def type
|
|
8
9
|
:ss_timestamp
|
|
9
10
|
end
|
|
10
11
|
|
|
11
12
|
def sqlserver_type
|
|
12
|
-
|
|
13
|
+
"timestamp"
|
|
13
14
|
end
|
|
14
|
-
|
|
15
15
|
end
|
|
16
16
|
end
|
|
17
17
|
end
|
|
@@ -1,11 +1,12 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
module ActiveRecord
|
|
2
4
|
module ConnectionAdapters
|
|
3
5
|
module SQLServer
|
|
4
6
|
module Type
|
|
5
7
|
class TinyInteger < Integer
|
|
6
|
-
|
|
7
8
|
def sqlserver_type
|
|
8
|
-
|
|
9
|
+
"tinyint"
|
|
9
10
|
end
|
|
10
11
|
|
|
11
12
|
private
|
|
@@ -17,7 +18,6 @@ module ActiveRecord
|
|
|
17
18
|
def min_value
|
|
18
19
|
0
|
|
19
20
|
end
|
|
20
|
-
|
|
21
21
|
end
|
|
22
22
|
end
|
|
23
23
|
end
|
|
@@ -1,19 +1,20 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
module ActiveRecord
|
|
2
4
|
module ConnectionAdapters
|
|
3
5
|
module SQLServer
|
|
4
6
|
module Type
|
|
5
7
|
class UnicodeChar < UnicodeString
|
|
6
|
-
|
|
7
8
|
def type
|
|
8
9
|
:nchar
|
|
9
10
|
end
|
|
10
11
|
|
|
11
12
|
def sqlserver_type
|
|
12
|
-
|
|
13
|
-
type
|
|
13
|
+
"nchar".yield_self do |type|
|
|
14
|
+
type += "(#{limit})" if limit
|
|
15
|
+
type
|
|
14
16
|
end
|
|
15
17
|
end
|
|
16
|
-
|
|
17
18
|
end
|
|
18
19
|
end
|
|
19
20
|
end
|
|
@@ -1,17 +1,17 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
module ActiveRecord
|
|
2
4
|
module ConnectionAdapters
|
|
3
5
|
module SQLServer
|
|
4
6
|
module Type
|
|
5
7
|
class UnicodeText < UnicodeVarcharMax
|
|
6
|
-
|
|
7
8
|
def type
|
|
8
9
|
:ntext
|
|
9
10
|
end
|
|
10
11
|
|
|
11
12
|
def sqlserver_type
|
|
12
|
-
|
|
13
|
+
"ntext"
|
|
13
14
|
end
|
|
14
|
-
|
|
15
15
|
end
|
|
16
16
|
end
|
|
17
17
|
end
|
|
@@ -1,10 +1,11 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
module ActiveRecord
|
|
2
4
|
module ConnectionAdapters
|
|
3
5
|
module SQLServer
|
|
4
6
|
module Type
|
|
5
7
|
class UnicodeVarchar < UnicodeChar
|
|
6
|
-
|
|
7
|
-
def initialize(*args)
|
|
8
|
+
def initialize(**args)
|
|
8
9
|
super
|
|
9
10
|
@limit = 4000 if @limit.to_i == 0
|
|
10
11
|
end
|
|
@@ -14,11 +15,11 @@ module ActiveRecord
|
|
|
14
15
|
end
|
|
15
16
|
|
|
16
17
|
def sqlserver_type
|
|
17
|
-
|
|
18
|
-
type
|
|
18
|
+
"nvarchar".yield_self do |type|
|
|
19
|
+
type += "(#{limit})" if limit
|
|
20
|
+
type
|
|
19
21
|
end
|
|
20
22
|
end
|
|
21
|
-
|
|
22
23
|
end
|
|
23
24
|
end
|
|
24
25
|
end
|
|
@@ -1,10 +1,11 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
module ActiveRecord
|
|
2
4
|
module ConnectionAdapters
|
|
3
5
|
module SQLServer
|
|
4
6
|
module Type
|
|
5
7
|
class UnicodeVarcharMax < UnicodeVarchar
|
|
6
|
-
|
|
7
|
-
def initialize(*args)
|
|
8
|
+
def initialize(**args)
|
|
8
9
|
super
|
|
9
10
|
@limit = 2_147_483_647
|
|
10
11
|
end
|
|
@@ -14,9 +15,8 @@ module ActiveRecord
|
|
|
14
15
|
end
|
|
15
16
|
|
|
16
17
|
def sqlserver_type
|
|
17
|
-
|
|
18
|
+
"nvarchar(max)"
|
|
18
19
|
end
|
|
19
|
-
|
|
20
20
|
end
|
|
21
21
|
end
|
|
22
22
|
end
|
|
@@ -1,9 +1,10 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
module ActiveRecord
|
|
2
4
|
module ConnectionAdapters
|
|
3
5
|
module SQLServer
|
|
4
6
|
module Type
|
|
5
7
|
class Uuid < String
|
|
6
|
-
|
|
7
8
|
ACCEPTABLE_UUID = %r{\A\{?([a-fA-F0-9]{4}-?){8}\}?\z}x
|
|
8
9
|
|
|
9
10
|
alias_method :serialize, :deserialize
|
|
@@ -13,11 +14,12 @@ module ActiveRecord
|
|
|
13
14
|
end
|
|
14
15
|
|
|
15
16
|
def sqlserver_type
|
|
16
|
-
|
|
17
|
+
"uniqueidentifier"
|
|
17
18
|
end
|
|
18
19
|
|
|
19
20
|
def serialize(value)
|
|
20
21
|
return unless value
|
|
22
|
+
|
|
21
23
|
Data.new super, self
|
|
22
24
|
end
|
|
23
25
|
|
|
@@ -28,7 +30,6 @@ module ActiveRecord
|
|
|
28
30
|
def quoted(value)
|
|
29
31
|
Utils.quote_string_single(value) if value
|
|
30
32
|
end
|
|
31
|
-
|
|
32
33
|
end
|
|
33
34
|
end
|
|
34
35
|
end
|
|
@@ -1,10 +1,11 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
module ActiveRecord
|
|
2
4
|
module ConnectionAdapters
|
|
3
5
|
module SQLServer
|
|
4
6
|
module Type
|
|
5
7
|
class Varbinary < Binary
|
|
6
|
-
|
|
7
|
-
def initialize(*args)
|
|
8
|
+
def initialize(**args)
|
|
8
9
|
super
|
|
9
10
|
@limit = 8000 if @limit.to_i == 0
|
|
10
11
|
end
|
|
@@ -14,11 +15,11 @@ module ActiveRecord
|
|
|
14
15
|
end
|
|
15
16
|
|
|
16
17
|
def sqlserver_type
|
|
17
|
-
|
|
18
|
-
type
|
|
18
|
+
"varbinary".yield_self do |type|
|
|
19
|
+
type += "(#{limit})" if limit
|
|
20
|
+
type
|
|
19
21
|
end
|
|
20
22
|
end
|
|
21
|
-
|
|
22
23
|
end
|
|
23
24
|
end
|
|
24
25
|
end
|
|
@@ -1,10 +1,11 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
module ActiveRecord
|
|
2
4
|
module ConnectionAdapters
|
|
3
5
|
module SQLServer
|
|
4
6
|
module Type
|
|
5
7
|
class VarbinaryMax < Varbinary
|
|
6
|
-
|
|
7
|
-
def initialize(*args)
|
|
8
|
+
def initialize(**args)
|
|
8
9
|
super
|
|
9
10
|
@limit = 2_147_483_647
|
|
10
11
|
end
|
|
@@ -14,9 +15,8 @@ module ActiveRecord
|
|
|
14
15
|
end
|
|
15
16
|
|
|
16
17
|
def sqlserver_type
|
|
17
|
-
|
|
18
|
+
"varbinary(max)"
|
|
18
19
|
end
|
|
19
|
-
|
|
20
20
|
end
|
|
21
21
|
end
|
|
22
22
|
end
|
|
@@ -1,10 +1,11 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
module ActiveRecord
|
|
2
4
|
module ConnectionAdapters
|
|
3
5
|
module SQLServer
|
|
4
6
|
module Type
|
|
5
7
|
class Varchar < Char
|
|
6
|
-
|
|
7
|
-
def initialize(*args)
|
|
8
|
+
def initialize(**args)
|
|
8
9
|
super
|
|
9
10
|
@limit = 8000 if @limit.to_i == 0
|
|
10
11
|
end
|
|
@@ -14,11 +15,11 @@ module ActiveRecord
|
|
|
14
15
|
end
|
|
15
16
|
|
|
16
17
|
def sqlserver_type
|
|
17
|
-
|
|
18
|
-
type
|
|
18
|
+
"varchar".yield_self do |type|
|
|
19
|
+
type += "(#{limit})" if limit
|
|
20
|
+
type
|
|
19
21
|
end
|
|
20
22
|
end
|
|
21
|
-
|
|
22
23
|
end
|
|
23
24
|
end
|
|
24
25
|
end
|
|
@@ -1,10 +1,11 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
module ActiveRecord
|
|
2
4
|
module ConnectionAdapters
|
|
3
5
|
module SQLServer
|
|
4
6
|
module Type
|
|
5
7
|
class VarcharMax < Varchar
|
|
6
|
-
|
|
7
|
-
def initialize(*args)
|
|
8
|
+
def initialize(**args)
|
|
8
9
|
super
|
|
9
10
|
@limit = 2_147_483_647
|
|
10
11
|
end
|
|
@@ -14,9 +15,8 @@ module ActiveRecord
|
|
|
14
15
|
end
|
|
15
16
|
|
|
16
17
|
def sqlserver_type
|
|
17
|
-
|
|
18
|
+
"varchar(max)"
|
|
18
19
|
end
|
|
19
|
-
|
|
20
20
|
end
|
|
21
21
|
end
|
|
22
22
|
end
|
|
@@ -1,17 +1,17 @@
|
|
|
1
|
-
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "strscan"
|
|
2
4
|
|
|
3
5
|
module ActiveRecord
|
|
4
6
|
module ConnectionAdapters
|
|
5
7
|
module SQLServer
|
|
6
8
|
module Utils
|
|
7
|
-
|
|
8
|
-
QUOTED_STRING_PREFIX = 'N'
|
|
9
|
+
QUOTED_STRING_PREFIX = "N"
|
|
9
10
|
|
|
10
11
|
# Value object to return identifiers from SQL Server names http://bit.ly/1CZ3EiL
|
|
11
12
|
# Inspiried from Rails PostgreSQL::Name adapter object in their own Utils.
|
|
12
13
|
#
|
|
13
14
|
class Name
|
|
14
|
-
|
|
15
15
|
SEPARATOR = "."
|
|
16
16
|
UNQUOTED_SCANNER = /\]?\./
|
|
17
17
|
QUOTED_SCANNER = /\A\[.*?\]\./
|
|
@@ -54,15 +54,15 @@ module ActiveRecord
|
|
|
54
54
|
end
|
|
55
55
|
|
|
56
56
|
def quoted
|
|
57
|
-
parts.map{ |p| quote(p) if p }.join SEPARATOR
|
|
57
|
+
parts.map { |p| quote(p) if p }.join SEPARATOR
|
|
58
58
|
end
|
|
59
59
|
|
|
60
60
|
def quoted_raw
|
|
61
61
|
quote @raw_name
|
|
62
62
|
end
|
|
63
63
|
|
|
64
|
-
def ==(
|
|
65
|
-
|
|
64
|
+
def ==(other)
|
|
65
|
+
other.class == self.class && other.parts == parts
|
|
66
66
|
end
|
|
67
67
|
alias_method :eql?, :==
|
|
68
68
|
|
|
@@ -75,6 +75,7 @@ module ActiveRecord
|
|
|
75
75
|
def parse_raw_name
|
|
76
76
|
@parts = []
|
|
77
77
|
return if raw_name.blank?
|
|
78
|
+
|
|
78
79
|
scanner = StringScanner.new(raw_name)
|
|
79
80
|
matched = scanner.exist?(QUOTED_CHECKER) ? scanner.scan_until(QUOTED_SCANNER) : scanner.scan_until(UNQUOTED_SCANNER)
|
|
80
81
|
while matched
|
|
@@ -91,7 +92,7 @@ module ActiveRecord
|
|
|
91
92
|
@schema = @parts.first
|
|
92
93
|
end
|
|
93
94
|
rest = scanner.rest
|
|
94
|
-
rest = rest.starts_with?(
|
|
95
|
+
rest = rest.starts_with?(".") ? rest[1..-1] : rest[0..-1]
|
|
95
96
|
@object = unquote(rest)
|
|
96
97
|
@parts << @object
|
|
97
98
|
end
|
|
@@ -101,7 +102,7 @@ module ActiveRecord
|
|
|
101
102
|
end
|
|
102
103
|
|
|
103
104
|
def unquote(part)
|
|
104
|
-
if part && part.start_with?(
|
|
105
|
+
if part && part.start_with?("[")
|
|
105
106
|
part[1..-2]
|
|
106
107
|
else
|
|
107
108
|
part
|
|
@@ -111,7 +112,6 @@ module ActiveRecord
|
|
|
111
112
|
def parts
|
|
112
113
|
@parts
|
|
113
114
|
end
|
|
114
|
-
|
|
115
115
|
end
|
|
116
116
|
|
|
117
117
|
extend self
|
|
@@ -139,7 +139,6 @@ module ActiveRecord
|
|
|
139
139
|
def extract_identifiers(name)
|
|
140
140
|
SQLServer::Utils::Name.new(name)
|
|
141
141
|
end
|
|
142
|
-
|
|
143
142
|
end
|
|
144
143
|
end
|
|
145
144
|
end
|
|
@@ -1,37 +1,39 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
require
|
|
4
|
-
require
|
|
5
|
-
require
|
|
6
|
-
require
|
|
7
|
-
require
|
|
8
|
-
require
|
|
9
|
-
require
|
|
10
|
-
require
|
|
11
|
-
require
|
|
12
|
-
require
|
|
13
|
-
require
|
|
14
|
-
require
|
|
15
|
-
require
|
|
16
|
-
require
|
|
17
|
-
require
|
|
18
|
-
require
|
|
19
|
-
require
|
|
20
|
-
require
|
|
21
|
-
require
|
|
22
|
-
require
|
|
23
|
-
require
|
|
24
|
-
require
|
|
25
|
-
require
|
|
26
|
-
require
|
|
27
|
-
require
|
|
28
|
-
require
|
|
29
|
-
require
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "base64"
|
|
4
|
+
require "active_record"
|
|
5
|
+
require "arel_sqlserver"
|
|
6
|
+
require "active_record/connection_adapters/abstract_adapter"
|
|
7
|
+
require "active_record/connection_adapters/sqlserver/core_ext/active_record"
|
|
8
|
+
require "active_record/connection_adapters/sqlserver/core_ext/calculations"
|
|
9
|
+
require "active_record/connection_adapters/sqlserver/core_ext/explain"
|
|
10
|
+
require "active_record/connection_adapters/sqlserver/core_ext/explain_subscriber"
|
|
11
|
+
require "active_record/connection_adapters/sqlserver/core_ext/attribute_methods"
|
|
12
|
+
require "active_record/connection_adapters/sqlserver/core_ext/finder_methods"
|
|
13
|
+
require "active_record/connection_adapters/sqlserver/core_ext/query_methods"
|
|
14
|
+
require "active_record/connection_adapters/sqlserver/core_ext/preloader"
|
|
15
|
+
require "active_record/connection_adapters/sqlserver/version"
|
|
16
|
+
require "active_record/connection_adapters/sqlserver/type"
|
|
17
|
+
require "active_record/connection_adapters/sqlserver/database_limits"
|
|
18
|
+
require "active_record/connection_adapters/sqlserver/database_statements"
|
|
19
|
+
require "active_record/connection_adapters/sqlserver/database_tasks"
|
|
20
|
+
require "active_record/connection_adapters/sqlserver/transaction"
|
|
21
|
+
require "active_record/connection_adapters/sqlserver/errors"
|
|
22
|
+
require "active_record/connection_adapters/sqlserver/schema_creation"
|
|
23
|
+
require "active_record/connection_adapters/sqlserver/schema_dumper"
|
|
24
|
+
require "active_record/connection_adapters/sqlserver/schema_statements"
|
|
25
|
+
require "active_record/connection_adapters/sqlserver/sql_type_metadata"
|
|
26
|
+
require "active_record/connection_adapters/sqlserver/showplan"
|
|
27
|
+
require "active_record/connection_adapters/sqlserver/table_definition"
|
|
28
|
+
require "active_record/connection_adapters/sqlserver/quoting"
|
|
29
|
+
require "active_record/connection_adapters/sqlserver/utils"
|
|
30
|
+
require "active_record/sqlserver_base"
|
|
31
|
+
require "active_record/connection_adapters/sqlserver_column"
|
|
32
|
+
require "active_record/tasks/sqlserver_database_tasks"
|
|
30
33
|
|
|
31
34
|
module ActiveRecord
|
|
32
35
|
module ConnectionAdapters
|
|
33
36
|
class SQLServerAdapter < AbstractAdapter
|
|
34
|
-
|
|
35
37
|
include SQLServer::Version,
|
|
36
38
|
SQLServer::Quoting,
|
|
37
39
|
SQLServer::DatabaseStatements,
|
|
@@ -40,7 +42,7 @@ module ActiveRecord
|
|
|
40
42
|
SQLServer::DatabaseLimits,
|
|
41
43
|
SQLServer::DatabaseTasks
|
|
42
44
|
|
|
43
|
-
ADAPTER_NAME =
|
|
45
|
+
ADAPTER_NAME = "SQLServer".freeze
|
|
44
46
|
|
|
45
47
|
# Default precision for 'time' (See https://docs.microsoft.com/en-us/sql/t-sql/data-types/time-transact-sql)
|
|
46
48
|
DEFAULT_TIME_PRECISION = 7
|
|
@@ -53,7 +55,7 @@ module ActiveRecord
|
|
|
53
55
|
cattr_accessor :showplan_option, instance_accessor: false
|
|
54
56
|
cattr_accessor :lowercase_schema_reflection
|
|
55
57
|
|
|
56
|
-
self.cs_equality_operator =
|
|
58
|
+
self.cs_equality_operator = "COLLATE Latin1_General_CS_AS_WS"
|
|
57
59
|
self.use_output_inserted = true
|
|
58
60
|
self.exclude_output_inserted_table_names = Concurrent::Map.new { false }
|
|
59
61
|
|
|
@@ -80,6 +82,12 @@ module ActiveRecord
|
|
|
80
82
|
SQLServer::SchemaCreation.new self
|
|
81
83
|
end
|
|
82
84
|
|
|
85
|
+
def self.database_exists?(config)
|
|
86
|
+
!!ActiveRecord::Base.sqlserver_connection(config)
|
|
87
|
+
rescue ActiveRecord::NoDatabaseError
|
|
88
|
+
false
|
|
89
|
+
end
|
|
90
|
+
|
|
83
91
|
def supports_ddl_transactions?
|
|
84
92
|
true
|
|
85
93
|
end
|
|
@@ -144,10 +152,34 @@ module ActiveRecord
|
|
|
144
152
|
true
|
|
145
153
|
end
|
|
146
154
|
|
|
155
|
+
def supports_optimizer_hints?
|
|
156
|
+
true
|
|
157
|
+
end
|
|
158
|
+
|
|
159
|
+
def supports_lazy_transactions?
|
|
160
|
+
true
|
|
161
|
+
end
|
|
162
|
+
|
|
147
163
|
def supports_in_memory_oltp?
|
|
148
164
|
@version_year >= 2014
|
|
149
165
|
end
|
|
150
166
|
|
|
167
|
+
def supports_insert_returning?
|
|
168
|
+
true
|
|
169
|
+
end
|
|
170
|
+
|
|
171
|
+
def supports_insert_on_duplicate_skip?
|
|
172
|
+
false
|
|
173
|
+
end
|
|
174
|
+
|
|
175
|
+
def supports_insert_on_duplicate_update?
|
|
176
|
+
false
|
|
177
|
+
end
|
|
178
|
+
|
|
179
|
+
def supports_insert_conflict_target?
|
|
180
|
+
false
|
|
181
|
+
end
|
|
182
|
+
|
|
151
183
|
def disable_referential_integrity
|
|
152
184
|
tables = tables_with_referential_integrity
|
|
153
185
|
tables.each { |t| do_execute "ALTER TABLE #{quote_table_name(t)} NOCHECK CONSTRAINT ALL" }
|
|
@@ -160,7 +192,8 @@ module ActiveRecord
|
|
|
160
192
|
|
|
161
193
|
def active?
|
|
162
194
|
return false unless @connection
|
|
163
|
-
|
|
195
|
+
|
|
196
|
+
raw_connection_do "SELECT 1"
|
|
164
197
|
true
|
|
165
198
|
rescue *connection_errors
|
|
166
199
|
false
|
|
@@ -190,13 +223,13 @@ module ActiveRecord
|
|
|
190
223
|
|
|
191
224
|
def reset!
|
|
192
225
|
reset_transaction
|
|
193
|
-
do_execute
|
|
226
|
+
do_execute "IF @@TRANCOUNT > 0 ROLLBACK TRANSACTION"
|
|
194
227
|
end
|
|
195
228
|
|
|
196
229
|
# === Abstract Adapter (Misc Support) =========================== #
|
|
197
230
|
|
|
198
231
|
def tables_with_referential_integrity
|
|
199
|
-
schemas_and_tables = select_rows
|
|
232
|
+
schemas_and_tables = select_rows <<~SQL.squish
|
|
200
233
|
SELECT DISTINCT s.name, o.name
|
|
201
234
|
FROM sys.foreign_keys i
|
|
202
235
|
INNER JOIN sys.objects o ON i.parent_object_id = o.OBJECT_ID
|
|
@@ -225,6 +258,7 @@ module ActiveRecord
|
|
|
225
258
|
|
|
226
259
|
def database_prefix_remote_server?
|
|
227
260
|
return false if database_prefix.blank?
|
|
261
|
+
|
|
228
262
|
name = SQLServer::Utils.extract_identifiers(database_prefix)
|
|
229
263
|
name.fully_qualified? && name.object.blank?
|
|
230
264
|
end
|
|
@@ -256,37 +290,47 @@ module ActiveRecord
|
|
|
256
290
|
result
|
|
257
291
|
end
|
|
258
292
|
|
|
293
|
+
def get_database_version # :nodoc:
|
|
294
|
+
version_year
|
|
295
|
+
end
|
|
259
296
|
|
|
260
297
|
protected
|
|
261
298
|
|
|
262
299
|
# === Abstract Adapter (Misc Support) =========================== #
|
|
263
300
|
|
|
264
301
|
def initialize_type_map(m = type_map)
|
|
265
|
-
m.register_type %r{.*},
|
|
302
|
+
m.register_type %r{.*}, SQLServer::Type::UnicodeString.new
|
|
303
|
+
|
|
266
304
|
# Exact Numerics
|
|
267
|
-
register_class_with_limit m,
|
|
268
|
-
m.alias_type
|
|
269
|
-
register_class_with_limit m,
|
|
270
|
-
m.alias_type
|
|
271
|
-
m.alias_type
|
|
272
|
-
register_class_with_limit m,
|
|
273
|
-
m.alias_type
|
|
274
|
-
register_class_with_limit m,
|
|
275
|
-
m.alias_type
|
|
276
|
-
m.register_type
|
|
305
|
+
register_class_with_limit m, "bigint(8)", SQLServer::Type::BigInteger
|
|
306
|
+
m.alias_type "bigint", "bigint(8)"
|
|
307
|
+
register_class_with_limit m, "int(4)", SQLServer::Type::Integer
|
|
308
|
+
m.alias_type "integer", "int(4)"
|
|
309
|
+
m.alias_type "int", "int(4)"
|
|
310
|
+
register_class_with_limit m, "smallint(2)", SQLServer::Type::SmallInteger
|
|
311
|
+
m.alias_type "smallint", "smallint(2)"
|
|
312
|
+
register_class_with_limit m, "tinyint(1)", SQLServer::Type::TinyInteger
|
|
313
|
+
m.alias_type "tinyint", "tinyint(1)"
|
|
314
|
+
m.register_type "bit", SQLServer::Type::Boolean.new
|
|
277
315
|
m.register_type %r{\Adecimal}i do |sql_type|
|
|
278
|
-
scale
|
|
316
|
+
scale = extract_scale(sql_type)
|
|
279
317
|
precision = extract_precision(sql_type)
|
|
280
|
-
|
|
318
|
+
if scale == 0
|
|
319
|
+
SQLServer::Type::DecimalWithoutScale.new(precision: precision)
|
|
320
|
+
else
|
|
321
|
+
SQLServer::Type::Decimal.new(precision: precision, scale: scale)
|
|
322
|
+
end
|
|
281
323
|
end
|
|
282
|
-
m.alias_type %r{\Anumeric}i,
|
|
283
|
-
m.register_type
|
|
284
|
-
m.register_type
|
|
324
|
+
m.alias_type %r{\Anumeric}i, "decimal"
|
|
325
|
+
m.register_type "money", SQLServer::Type::Money.new
|
|
326
|
+
m.register_type "smallmoney", SQLServer::Type::SmallMoney.new
|
|
327
|
+
|
|
285
328
|
# Approximate Numerics
|
|
286
|
-
m.register_type
|
|
287
|
-
m.register_type
|
|
329
|
+
m.register_type "float", SQLServer::Type::Float.new
|
|
330
|
+
m.register_type "real", SQLServer::Type::Real.new
|
|
331
|
+
|
|
288
332
|
# Date and Time
|
|
289
|
-
m.register_type
|
|
333
|
+
m.register_type "date", SQLServer::Type::Date.new
|
|
290
334
|
m.register_type %r{\Adatetime} do |sql_type|
|
|
291
335
|
precision = extract_precision(sql_type)
|
|
292
336
|
if precision
|
|
@@ -295,48 +339,54 @@ module ActiveRecord
|
|
|
295
339
|
SQLServer::Type::DateTime.new
|
|
296
340
|
end
|
|
297
341
|
end
|
|
298
|
-
m.register_type
|
|
342
|
+
m.register_type %r{\Adatetimeoffset}i do |sql_type|
|
|
299
343
|
precision = extract_precision(sql_type)
|
|
300
344
|
SQLServer::Type::DateTimeOffset.new precision: precision
|
|
301
345
|
end
|
|
302
|
-
m.register_type
|
|
346
|
+
m.register_type "smalldatetime", SQLServer::Type::SmallDateTime.new
|
|
303
347
|
m.register_type %r{\Atime}i do |sql_type|
|
|
304
348
|
precision = extract_precision(sql_type) || DEFAULT_TIME_PRECISION
|
|
305
349
|
SQLServer::Type::Time.new precision: precision
|
|
306
350
|
end
|
|
351
|
+
|
|
307
352
|
# Character Strings
|
|
308
353
|
register_class_with_limit m, %r{\Achar}i, SQLServer::Type::Char
|
|
309
354
|
register_class_with_limit m, %r{\Avarchar}i, SQLServer::Type::Varchar
|
|
310
|
-
m.register_type
|
|
311
|
-
m.register_type
|
|
355
|
+
m.register_type "varchar(max)", SQLServer::Type::VarcharMax.new
|
|
356
|
+
m.register_type "text", SQLServer::Type::Text.new
|
|
357
|
+
|
|
312
358
|
# Unicode Character Strings
|
|
313
359
|
register_class_with_limit m, %r{\Anchar}i, SQLServer::Type::UnicodeChar
|
|
314
360
|
register_class_with_limit m, %r{\Anvarchar}i, SQLServer::Type::UnicodeVarchar
|
|
315
|
-
m.alias_type
|
|
316
|
-
m.register_type
|
|
317
|
-
m.register_type
|
|
318
|
-
m.register_type
|
|
361
|
+
m.alias_type "string", "nvarchar(4000)"
|
|
362
|
+
m.register_type "nvarchar(max)", SQLServer::Type::UnicodeVarcharMax.new
|
|
363
|
+
m.register_type "nvarchar(max)", SQLServer::Type::UnicodeVarcharMax.new
|
|
364
|
+
m.register_type "ntext", SQLServer::Type::UnicodeText.new
|
|
365
|
+
|
|
319
366
|
# Binary Strings
|
|
320
367
|
register_class_with_limit m, %r{\Abinary}i, SQLServer::Type::Binary
|
|
321
368
|
register_class_with_limit m, %r{\Avarbinary}i, SQLServer::Type::Varbinary
|
|
322
|
-
m.register_type
|
|
369
|
+
m.register_type "varbinary(max)", SQLServer::Type::VarbinaryMax.new
|
|
370
|
+
|
|
323
371
|
# Other Data Types
|
|
324
|
-
m.register_type
|
|
325
|
-
m.register_type
|
|
372
|
+
m.register_type "uniqueidentifier", SQLServer::Type::Uuid.new
|
|
373
|
+
m.register_type "timestamp", SQLServer::Type::Timestamp.new
|
|
326
374
|
end
|
|
327
375
|
|
|
328
|
-
def translate_exception(e, message)
|
|
376
|
+
def translate_exception(e, message:, sql:, binds:)
|
|
329
377
|
case message
|
|
330
378
|
when /(cannot insert duplicate key .* with unique index) | (violation of unique key constraint)/i
|
|
331
|
-
RecordNotUnique.new(message)
|
|
332
|
-
when /conflicted with the foreign key constraint/i
|
|
333
|
-
InvalidForeignKey.new(message)
|
|
379
|
+
RecordNotUnique.new(message, sql: sql, binds: binds)
|
|
380
|
+
when /(conflicted with the foreign key constraint) | (The DELETE statement conflicted with the REFERENCE constraint)/i
|
|
381
|
+
InvalidForeignKey.new(message, sql: sql, binds: binds)
|
|
334
382
|
when /has been chosen as the deadlock victim/i
|
|
335
|
-
DeadlockVictim.new(message)
|
|
383
|
+
DeadlockVictim.new(message, sql: sql, binds: binds)
|
|
336
384
|
when /database .* does not exist/i
|
|
337
|
-
NoDatabaseError.new(message)
|
|
385
|
+
NoDatabaseError.new(message, sql: sql, binds: binds)
|
|
338
386
|
when /data would be truncated/
|
|
339
|
-
ValueTooLong.new(message)
|
|
387
|
+
ValueTooLong.new(message, sql: sql, binds: binds)
|
|
388
|
+
when /connection timed out/
|
|
389
|
+
StatementTimeout.new(message, sql: sql, binds: binds)
|
|
340
390
|
when /Column '(.*)' is not the same data type as referencing column '(.*)' in foreign key/
|
|
341
391
|
pk_id, fk_id = SQLServer::Utils.extract_identifiers($1), SQLServer::Utils.extract_identifiers($2)
|
|
342
392
|
MismatchedForeignKey.new(
|
|
@@ -348,9 +398,9 @@ module ActiveRecord
|
|
|
348
398
|
primary_key: pk_id.object
|
|
349
399
|
)
|
|
350
400
|
when /Cannot insert the value NULL into column.*does not allow nulls/
|
|
351
|
-
NotNullViolation.new(message)
|
|
401
|
+
NotNullViolation.new(message, sql: sql, binds: binds)
|
|
352
402
|
when /Arithmetic overflow error/
|
|
353
|
-
RangeError.new(message)
|
|
403
|
+
RangeError.new(message, sql: sql, binds: binds)
|
|
354
404
|
else
|
|
355
405
|
super
|
|
356
406
|
end
|
|
@@ -364,7 +414,7 @@ module ActiveRecord
|
|
|
364
414
|
when :dblib
|
|
365
415
|
dblib_connect(config)
|
|
366
416
|
end
|
|
367
|
-
@spid = _raw_select(
|
|
417
|
+
@spid = _raw_select("SELECT @@SPID", fetch: :rows).first.first
|
|
368
418
|
@version_year = version_year
|
|
369
419
|
configure_connection
|
|
370
420
|
end
|
|
@@ -383,32 +433,32 @@ module ActiveRecord
|
|
|
383
433
|
username: config[:username],
|
|
384
434
|
password: config[:password],
|
|
385
435
|
database: config[:database],
|
|
386
|
-
tds_version: config[:tds_version] ||
|
|
436
|
+
tds_version: config[:tds_version] || "7.3",
|
|
387
437
|
appname: config_appname(config),
|
|
388
438
|
login_timeout: config_login_timeout(config),
|
|
389
439
|
timeout: config_timeout(config),
|
|
390
|
-
encoding:
|
|
440
|
+
encoding: config_encoding(config),
|
|
391
441
|
azure: config[:azure],
|
|
392
442
|
contained: config[:contained]
|
|
393
443
|
).tap do |client|
|
|
394
444
|
if config[:azure]
|
|
395
|
-
client.execute(
|
|
396
|
-
client.execute(
|
|
397
|
-
client.execute(
|
|
398
|
-
client.execute(
|
|
445
|
+
client.execute("SET ANSI_NULLS ON").do
|
|
446
|
+
client.execute("SET ANSI_NULL_DFLT_ON ON").do
|
|
447
|
+
client.execute("SET ANSI_PADDING ON").do
|
|
448
|
+
client.execute("SET ANSI_WARNINGS ON").do
|
|
399
449
|
else
|
|
400
|
-
client.execute(
|
|
450
|
+
client.execute("SET ANSI_DEFAULTS ON").do
|
|
401
451
|
end
|
|
402
|
-
client.execute(
|
|
403
|
-
client.execute(
|
|
404
|
-
client.execute(
|
|
405
|
-
client.execute(
|
|
406
|
-
client.execute(
|
|
452
|
+
client.execute("SET QUOTED_IDENTIFIER ON").do
|
|
453
|
+
client.execute("SET CURSOR_CLOSE_ON_COMMIT OFF").do
|
|
454
|
+
client.execute("SET IMPLICIT_TRANSACTIONS OFF").do
|
|
455
|
+
client.execute("SET TEXTSIZE 2147483647").do
|
|
456
|
+
client.execute("SET CONCAT_NULL_YIELDS_NULL ON").do
|
|
407
457
|
end
|
|
408
458
|
end
|
|
409
459
|
|
|
410
460
|
def config_appname(config)
|
|
411
|
-
config[:appname] || configure_application_name || Rails.application.class.name.split(
|
|
461
|
+
config[:appname] || configure_application_name || Rails.application.class.name.split("::").first rescue nil
|
|
412
462
|
end
|
|
413
463
|
|
|
414
464
|
def config_login_timeout(config)
|
|
@@ -423,18 +473,18 @@ module ActiveRecord
|
|
|
423
473
|
config[:encoding].present? ? config[:encoding] : nil
|
|
424
474
|
end
|
|
425
475
|
|
|
426
|
-
def configure_connection
|
|
476
|
+
def configure_connection; end
|
|
427
477
|
|
|
428
|
-
def configure_application_name
|
|
478
|
+
def configure_application_name; end
|
|
429
479
|
|
|
430
480
|
def initialize_dateformatter
|
|
431
481
|
@database_dateformat = user_options_dateformat
|
|
432
482
|
a, b, c = @database_dateformat.each_char.to_a
|
|
433
|
-
[a, b, c].each { |f| f.upcase! if f ==
|
|
483
|
+
[a, b, c].each { |f| f.upcase! if f == "y" }
|
|
434
484
|
dateformat = "%#{a}-%#{b}-%#{c}"
|
|
435
485
|
::Date::DATE_FORMATS[:_sqlserver_dateformat] = dateformat
|
|
436
486
|
::Time::DATE_FORMATS[:_sqlserver_dateformat] = dateformat
|
|
437
|
-
::Time::DATE_FORMATS[:_sqlserver_time] =
|
|
487
|
+
::Time::DATE_FORMATS[:_sqlserver_time] = "%H:%M:%S"
|
|
438
488
|
::Time::DATE_FORMATS[:_sqlserver_datetime] = "#{dateformat} %H:%M:%S"
|
|
439
489
|
::Time::DATE_FORMATS[:_sqlserver_datetimeoffset] = lambda { |time|
|
|
440
490
|
time.strftime "#{dateformat} %H:%M:%S.%9N #{time.formatted_offset}"
|
|
@@ -443,13 +493,14 @@ module ActiveRecord
|
|
|
443
493
|
|
|
444
494
|
def version_year
|
|
445
495
|
return 2016 if sqlserver_version =~ /vNext/
|
|
496
|
+
|
|
446
497
|
/SQL Server (\d+)/.match(sqlserver_version).to_a.last.to_s.to_i
|
|
447
|
-
rescue StandardError
|
|
498
|
+
rescue StandardError
|
|
448
499
|
2016
|
|
449
500
|
end
|
|
450
501
|
|
|
451
502
|
def sqlserver_version
|
|
452
|
-
@sqlserver_version ||= _raw_select(
|
|
503
|
+
@sqlserver_version ||= _raw_select("SELECT @@version", fetch: :rows).first.first.to_s
|
|
453
504
|
end
|
|
454
505
|
end
|
|
455
506
|
end
|