activerecord-sqlserver-adapter 4.2.18 → 5.0.0

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.
Files changed (82) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +8 -223
  3. data/Gemfile +18 -17
  4. data/RAILS5-TODO.md +36 -0
  5. data/README.md +27 -8
  6. data/RUNNING_UNIT_TESTS.md +0 -17
  7. data/Rakefile +2 -7
  8. data/VERSION +1 -1
  9. data/activerecord-sqlserver-adapter.gemspec +1 -1
  10. data/appveyor.yml +0 -2
  11. data/lib/active_record/connection_adapters/sqlserver/core_ext/explain.rb +15 -8
  12. data/lib/active_record/connection_adapters/sqlserver/database_statements.rb +45 -97
  13. data/lib/active_record/connection_adapters/sqlserver/database_tasks.rb +1 -2
  14. data/lib/active_record/connection_adapters/sqlserver/quoting.rb +31 -10
  15. data/lib/active_record/connection_adapters/sqlserver/schema_creation.rb +0 -18
  16. data/lib/active_record/connection_adapters/sqlserver/schema_dumper.rb +16 -0
  17. data/lib/active_record/connection_adapters/sqlserver/schema_statements.rb +101 -58
  18. data/lib/active_record/connection_adapters/sqlserver/showplan.rb +7 -7
  19. data/lib/active_record/connection_adapters/sqlserver/sql_type_metadata.rb +20 -0
  20. data/lib/active_record/connection_adapters/sqlserver/table_definition.rb +56 -32
  21. data/lib/active_record/connection_adapters/sqlserver/transaction.rb +1 -1
  22. data/lib/active_record/connection_adapters/sqlserver/type.rb +34 -32
  23. data/lib/active_record/connection_adapters/sqlserver/type/big_integer.rb +4 -0
  24. data/lib/active_record/connection_adapters/sqlserver/type/binary.rb +6 -0
  25. data/lib/active_record/connection_adapters/sqlserver/type/boolean.rb +3 -0
  26. data/lib/active_record/connection_adapters/sqlserver/type/char.rb +9 -20
  27. data/lib/active_record/connection_adapters/sqlserver/type/data.rb +30 -0
  28. data/lib/active_record/connection_adapters/sqlserver/type/date.rb +28 -4
  29. data/lib/active_record/connection_adapters/sqlserver/type/datetime.rb +28 -14
  30. data/lib/active_record/connection_adapters/sqlserver/type/datetime2.rb +2 -2
  31. data/lib/active_record/connection_adapters/sqlserver/type/datetimeoffset.rb +4 -16
  32. data/lib/active_record/connection_adapters/sqlserver/type/decimal.rb +9 -0
  33. data/lib/active_record/connection_adapters/sqlserver/type/float.rb +4 -0
  34. data/lib/active_record/connection_adapters/sqlserver/type/integer.rb +3 -0
  35. data/lib/active_record/connection_adapters/sqlserver/type/money.rb +5 -1
  36. data/lib/active_record/connection_adapters/sqlserver/type/real.rb +4 -0
  37. data/lib/active_record/connection_adapters/sqlserver/type/small_integer.rb +3 -1
  38. data/lib/active_record/connection_adapters/sqlserver/type/small_money.rb +5 -1
  39. data/lib/active_record/connection_adapters/sqlserver/type/smalldatetime.rb +8 -1
  40. data/lib/active_record/connection_adapters/sqlserver/type/text.rb +4 -0
  41. data/lib/active_record/connection_adapters/sqlserver/type/time.rb +20 -8
  42. data/lib/active_record/connection_adapters/sqlserver/type/time_value_fractional.rb +25 -10
  43. data/lib/active_record/connection_adapters/sqlserver/type/timestamp.rb +4 -0
  44. data/lib/active_record/connection_adapters/sqlserver/type/tiny_integer.rb +3 -0
  45. data/lib/active_record/connection_adapters/sqlserver/type/unicode_char.rb +6 -0
  46. data/lib/active_record/connection_adapters/sqlserver/type/unicode_text.rb +4 -0
  47. data/lib/active_record/connection_adapters/sqlserver/type/unicode_varchar.rb +7 -1
  48. data/lib/active_record/connection_adapters/sqlserver/type/unicode_varchar_max.rb +5 -1
  49. data/lib/active_record/connection_adapters/sqlserver/type/uuid.rb +15 -2
  50. data/lib/active_record/connection_adapters/sqlserver/type/varbinary.rb +7 -1
  51. data/lib/active_record/connection_adapters/sqlserver/type/varbinary_max.rb +5 -1
  52. data/lib/active_record/connection_adapters/sqlserver/type/varchar.rb +7 -1
  53. data/lib/active_record/connection_adapters/sqlserver/type/varchar_max.rb +5 -1
  54. data/lib/active_record/connection_adapters/sqlserver/utils.rb +10 -0
  55. data/lib/active_record/connection_adapters/sqlserver_adapter.rb +71 -57
  56. data/lib/active_record/connection_adapters/sqlserver_column.rb +5 -30
  57. data/lib/active_record/sqlserver_base.rb +1 -5
  58. data/lib/arel/visitors/sqlserver.rb +11 -20
  59. data/test/bin/setup.sh +4 -6
  60. data/test/cases/adapter_test_sqlserver.rb +11 -20
  61. data/test/cases/coerced_tests.rb +233 -138
  62. data/test/cases/column_test_sqlserver.rb +244 -227
  63. data/test/cases/connection_test_sqlserver.rb +5 -76
  64. data/test/cases/fully_qualified_identifier_test_sqlserver.rb +7 -7
  65. data/test/cases/helper_sqlserver.rb +4 -15
  66. data/test/cases/pessimistic_locking_test_sqlserver.rb +1 -1
  67. data/test/cases/rake_test_sqlserver.rb +20 -14
  68. data/test/cases/schema_dumper_test_sqlserver.rb +94 -63
  69. data/test/cases/schema_test_sqlserver.rb +2 -2
  70. data/test/cases/showplan_test_sqlserver.rb +1 -1
  71. data/test/cases/specific_schema_test_sqlserver.rb +7 -14
  72. data/test/cases/transaction_test_sqlserver.rb +1 -1
  73. data/test/cases/uuid_test_sqlserver.rb +0 -1
  74. data/test/config.yml +0 -10
  75. data/test/migrations/transaction_table/1_table_will_never_be_created.rb +1 -1
  76. data/test/schema/sqlserver_specific_schema.rb +0 -16
  77. data/test/support/coerceable_test_sqlserver.rb +6 -2
  78. data/test/support/connection_reflection.rb +0 -4
  79. data/test/support/sql_counter_sqlserver.rb +17 -21
  80. metadata +9 -7
  81. data/lib/active_record/connection_adapters/sqlserver/core_ext/odbc.rb +0 -34
  82. data/lib/active_record/connection_adapters/sqlserver/schema_cache.rb +0 -114
@@ -25,7 +25,7 @@ module ActiveRecord
25
25
 
26
26
  attr_reader :starting_isolation_level
27
27
 
28
- def initialize(connection, options)
28
+ def initialize(connection, options, run_commit_callbacks: false)
29
29
  @connection = connection
30
30
  @starting_isolation_level = current_isolation_level if options[:isolation]
31
31
  super
@@ -1,43 +1,45 @@
1
1
  require 'active_record/type'
2
+ # Behaviors
3
+ require 'active_record/connection_adapters/sqlserver/type/data'
4
+ require 'active_record/connection_adapters/sqlserver/type/time_value_fractional'
2
5
  # Exact Numerics
3
- require 'active_record/connection_adapters/sqlserver/type/integer.rb'
4
- require 'active_record/connection_adapters/sqlserver/type/big_integer.rb'
5
- require 'active_record/connection_adapters/sqlserver/type/small_integer.rb'
6
- require 'active_record/connection_adapters/sqlserver/type/tiny_integer.rb'
7
- require 'active_record/connection_adapters/sqlserver/type/boolean.rb'
8
- require 'active_record/connection_adapters/sqlserver/type/decimal.rb'
9
- require 'active_record/connection_adapters/sqlserver/type/money.rb'
10
- require 'active_record/connection_adapters/sqlserver/type/small_money.rb'
6
+ require 'active_record/connection_adapters/sqlserver/type/integer'
7
+ require 'active_record/connection_adapters/sqlserver/type/big_integer'
8
+ require 'active_record/connection_adapters/sqlserver/type/small_integer'
9
+ require 'active_record/connection_adapters/sqlserver/type/tiny_integer'
10
+ require 'active_record/connection_adapters/sqlserver/type/boolean'
11
+ require 'active_record/connection_adapters/sqlserver/type/decimal'
12
+ require 'active_record/connection_adapters/sqlserver/type/money'
13
+ require 'active_record/connection_adapters/sqlserver/type/small_money'
11
14
  # Approximate Numerics
12
- require 'active_record/connection_adapters/sqlserver/type/float.rb'
13
- require 'active_record/connection_adapters/sqlserver/type/real.rb'
15
+ require 'active_record/connection_adapters/sqlserver/type/float'
16
+ require 'active_record/connection_adapters/sqlserver/type/real'
14
17
  # Date and Time
15
- require 'active_record/connection_adapters/sqlserver/type/time_value_fractional.rb'
16
- require 'active_record/connection_adapters/sqlserver/type/date.rb'
17
- require 'active_record/connection_adapters/sqlserver/type/datetime.rb'
18
- require 'active_record/connection_adapters/sqlserver/type/datetime2.rb'
19
- require 'active_record/connection_adapters/sqlserver/type/datetimeoffset.rb'
20
- require 'active_record/connection_adapters/sqlserver/type/smalldatetime.rb'
21
- require 'active_record/connection_adapters/sqlserver/type/time.rb'
18
+ require 'active_record/connection_adapters/sqlserver/type/date'
19
+ require 'active_record/connection_adapters/sqlserver/type/datetime'
20
+ require 'active_record/connection_adapters/sqlserver/type/datetime2'
21
+ require 'active_record/connection_adapters/sqlserver/type/datetimeoffset'
22
+ require 'active_record/connection_adapters/sqlserver/type/smalldatetime'
23
+ require 'active_record/connection_adapters/sqlserver/type/time'
22
24
  # Character Strings
23
- require 'active_record/connection_adapters/sqlserver/type/string.rb'
24
- require 'active_record/connection_adapters/sqlserver/type/char.rb'
25
- require 'active_record/connection_adapters/sqlserver/type/varchar.rb'
26
- require 'active_record/connection_adapters/sqlserver/type/varchar_max.rb'
27
- require 'active_record/connection_adapters/sqlserver/type/text.rb'
25
+ require 'active_record/connection_adapters/sqlserver/type/string'
26
+ require 'active_record/connection_adapters/sqlserver/type/char'
27
+ require 'active_record/connection_adapters/sqlserver/type/varchar'
28
+ require 'active_record/connection_adapters/sqlserver/type/varchar_max'
29
+ require 'active_record/connection_adapters/sqlserver/type/text'
28
30
  # Unicode Character Strings
29
- require 'active_record/connection_adapters/sqlserver/type/unicode_string.rb'
30
- require 'active_record/connection_adapters/sqlserver/type/unicode_char.rb'
31
- require 'active_record/connection_adapters/sqlserver/type/unicode_varchar.rb'
32
- require 'active_record/connection_adapters/sqlserver/type/unicode_varchar_max.rb'
33
- require 'active_record/connection_adapters/sqlserver/type/unicode_text.rb'
31
+ require 'active_record/connection_adapters/sqlserver/type/unicode_string'
32
+ require 'active_record/connection_adapters/sqlserver/type/unicode_char'
33
+ require 'active_record/connection_adapters/sqlserver/type/unicode_varchar'
34
+ require 'active_record/connection_adapters/sqlserver/type/unicode_varchar_max'
35
+ require 'active_record/connection_adapters/sqlserver/type/unicode_text'
34
36
  # Binary Strings
35
- require 'active_record/connection_adapters/sqlserver/type/binary.rb'
36
- require 'active_record/connection_adapters/sqlserver/type/varbinary.rb'
37
- require 'active_record/connection_adapters/sqlserver/type/varbinary_max.rb'
37
+ require 'active_record/connection_adapters/sqlserver/type/binary'
38
+ require 'active_record/connection_adapters/sqlserver/type/varbinary'
39
+ require 'active_record/connection_adapters/sqlserver/type/varbinary_max'
38
40
  # Other Data Types
39
- require 'active_record/connection_adapters/sqlserver/type/uuid.rb'
40
- require 'active_record/connection_adapters/sqlserver/type/timestamp.rb'
41
+ require 'active_record/connection_adapters/sqlserver/type/uuid'
42
+ require 'active_record/connection_adapters/sqlserver/type/timestamp'
41
43
 
42
44
  module ActiveRecord
43
45
  module Type
@@ -8,6 +8,10 @@ module ActiveRecord
8
8
  :bigint
9
9
  end
10
10
 
11
+ def sqlserver_type
12
+ 'bigint'.freeze
13
+ end
14
+
11
15
  end
12
16
  end
13
17
  end
@@ -8,6 +8,12 @@ module ActiveRecord
8
8
  :binary_basic
9
9
  end
10
10
 
11
+ def sqlserver_type
12
+ 'binary'.tap do |type|
13
+ type << "(#{limit})" if limit
14
+ end
15
+ end
16
+
11
17
  end
12
18
  end
13
19
  end
@@ -4,6 +4,9 @@ module ActiveRecord
4
4
  module Type
5
5
  class Boolean < ActiveRecord::Type::Boolean
6
6
 
7
+ def sqlserver_type
8
+ 'bit'.freeze
9
+ end
7
10
 
8
11
  end
9
12
  end
@@ -8,32 +8,21 @@ module ActiveRecord
8
8
  :char
9
9
  end
10
10
 
11
- def type_cast_for_database(value)
11
+ def serialize(value)
12
12
  return if value.nil?
13
13
  return value if value.is_a?(Data)
14
- Data.new(super)
14
+ Data.new super, self
15
15
  end
16
16
 
17
- class Data
18
-
19
- def initialize(value)
20
- @value = value.to_s
21
- end
22
-
23
- def quoted
24
- "'#{Utils.quote_string(@value)}'"
25
- end
26
-
27
- def to_s
28
- @value
29
- end
30
- alias_method :to_str, :to_s
31
-
32
- def ==(other)
33
- self.to_s == other.to_s
17
+ def sqlserver_type
18
+ 'char'.tap do |type|
19
+ type << "(#{limit})" if limit
34
20
  end
35
- alias_method :eql?, :==
21
+ end
36
22
 
23
+ def quoted(value)
24
+ return value.quoted_id if value.respond_to?(:quoted_id)
25
+ Utils.quote_string_single(value)
37
26
  end
38
27
 
39
28
  end
@@ -0,0 +1,30 @@
1
+ module ActiveRecord
2
+ module ConnectionAdapters
3
+ module SQLServer
4
+ module Type
5
+ class Data
6
+
7
+ attr_reader :value, :type
8
+
9
+ def initialize(value, type)
10
+ @value, @type = value, type
11
+ end
12
+
13
+ def quoted
14
+ type.quoted(@value)
15
+ end
16
+
17
+ def to_s
18
+ @value
19
+ end
20
+ alias_method :to_str, :to_s
21
+
22
+ def inspect
23
+ @value.inspect
24
+ end
25
+
26
+ end
27
+ end
28
+ end
29
+ end
30
+ end
@@ -4,14 +4,38 @@ module ActiveRecord
4
4
  module Type
5
5
  class Date < ActiveRecord::Type::Date
6
6
 
7
- def type_cast_for_database(value)
7
+ def sqlserver_type
8
+ 'date'.freeze
9
+ end
10
+
11
+ def serialize(value)
8
12
  return unless value.present?
9
- return value if value.acts_like?(:string)
10
- value.to_s(:_sqlserver_dateformat)
13
+ date = super(value).to_s(:_sqlserver_dateformat)
14
+ Data.new date, self
15
+ end
16
+
17
+ def deserialize(value)
18
+ value.is_a?(Data) ? super(value.value) : super
11
19
  end
12
20
 
13
21
  def type_cast_for_schema(value)
14
- type_cast_for_database(value).inspect
22
+ serialize(value).quoted
23
+ end
24
+
25
+ def quoted(value)
26
+ Utils.quote_string_single(value)
27
+ end
28
+
29
+ private
30
+
31
+ def fast_string_to_date(string)
32
+ ::Date.strptime(string, fast_string_to_date_format)
33
+ rescue ArgumentError
34
+ super
35
+ end
36
+
37
+ def fast_string_to_date_format
38
+ ::Date::DATE_FORMATS[:_sqlserver_dateformat]
15
39
  end
16
40
 
17
41
  end
@@ -6,32 +6,46 @@ module ActiveRecord
6
6
 
7
7
  include TimeValueFractional
8
8
 
9
- def type_cast_for_database(value)
10
- return super unless value.acts_like?(:time)
11
- value = zone_conversion(value)
12
- datetime = value.to_s(:_sqlserver_datetime)
13
- "#{datetime}".tap do |v|
9
+ def sqlserver_type
10
+ 'datetime'.freeze
11
+ end
12
+
13
+ def serialize(value)
14
+ value = super
15
+ return value unless value.acts_like?(:time)
16
+ datetime = value.to_s(:_sqlserver_datetime).tap do |v|
14
17
  fraction = quote_fractional(value)
15
- v << ".#{fraction}" unless fraction.to_i.zero?
18
+ v << ".#{fraction}"
16
19
  end
20
+ Data.new datetime, self
21
+ end
22
+
23
+ def deserialize(value)
24
+ value.is_a?(Data) ? super(value.value) : super
17
25
  end
18
26
 
19
27
  def type_cast_for_schema(value)
20
- type_cast_for_database(value).inspect
28
+ serialize(value).quoted
21
29
  end
22
30
 
31
+ def quoted(value)
32
+ Utils.quote_string_single(value)
33
+ end
23
34
 
24
35
  private
25
36
 
26
- def cast_value(value)
27
- value = value.acts_like?(:time) ? value : super
28
- return unless value
29
- cast_fractional(value)
37
+ def fast_string_to_time(string)
38
+ fast_string_to_time_zone.strptime(string, fast_string_to_time_format).time
39
+ rescue ArgumentError
40
+ super
41
+ end
42
+
43
+ def fast_string_to_time_format
44
+ "#{::Time::DATE_FORMATS[:_sqlserver_datetime]}.%N".freeze
30
45
  end
31
46
 
32
- def zone_conversion(value)
33
- method = ActiveRecord::Base.default_timezone == :utc ? :getutc : :getlocal
34
- value.respond_to?(method) ? value.send(method) : value
47
+ def fast_string_to_time_zone
48
+ ::Time.zone || ActiveSupport::TimeZone['UTC']
35
49
  end
36
50
 
37
51
  end
@@ -6,8 +6,8 @@ module ActiveRecord
6
6
 
7
7
  include TimeValueFractional2
8
8
 
9
- def type
10
- :datetime2
9
+ def sqlserver_type
10
+ "datetime2(#{precision.to_i})"
11
11
  end
12
12
 
13
13
  end
@@ -4,24 +4,12 @@ module ActiveRecord
4
4
  module Type
5
5
  class DateTimeOffset < DateTime2
6
6
 
7
- def type
8
- :datetimeoffset
7
+ def sqlserver_type
8
+ "datetimeoffset(#{precision.to_i})"
9
9
  end
10
10
 
11
- def type_cast_for_database(value)
12
- return super unless value.acts_like?(:time)
13
- value.to_s :_sqlserver_datetimeoffset
14
- end
15
-
16
- def type_cast_for_schema(value)
17
- type_cast_for_database(value).inspect
18
- end
19
-
20
-
21
- private
22
-
23
- def zone_conversion(value)
24
- value
11
+ def quoted(value)
12
+ Utils.quote_string_single(value)
25
13
  end
26
14
 
27
15
  end
@@ -4,6 +4,15 @@ module ActiveRecord
4
4
  module Type
5
5
  class Decimal < ActiveRecord::Type::Decimal
6
6
 
7
+ def sqlserver_type
8
+ 'decimal'.tap do |type|
9
+ type << "(#{precision.to_i},#{scale.to_i})" if precision || scale
10
+ end
11
+ end
12
+
13
+ def type_cast_for_schema(value)
14
+ value.is_a?(BigDecimal) ? value.to_s : value.inspect
15
+ end
7
16
 
8
17
  end
9
18
  end
@@ -8,6 +8,10 @@ module ActiveRecord
8
8
  :float
9
9
  end
10
10
 
11
+ def sqlserver_type
12
+ 'float'.freeze
13
+ end
14
+
11
15
  end
12
16
  end
13
17
  end
@@ -4,6 +4,9 @@ module ActiveRecord
4
4
  module Type
5
5
  class Integer < ActiveRecord::Type::Integer
6
6
 
7
+ def sqlserver_type
8
+ 'int'.freeze
9
+ end
7
10
 
8
11
  end
9
12
  end
@@ -4,7 +4,7 @@ module ActiveRecord
4
4
  module Type
5
5
  class Money < Decimal
6
6
 
7
- def initialize(options = {})
7
+ def initialize(*args)
8
8
  super
9
9
  @precision = 19
10
10
  @scale = 4
@@ -14,6 +14,10 @@ module ActiveRecord
14
14
  :money
15
15
  end
16
16
 
17
+ def sqlserver_type
18
+ 'money'.freeze
19
+ end
20
+
17
21
  end
18
22
  end
19
23
  end
@@ -8,6 +8,10 @@ module ActiveRecord
8
8
  :real
9
9
  end
10
10
 
11
+ def sqlserver_type
12
+ 'real'.freeze
13
+ end
14
+
11
15
  end
12
16
  end
13
17
  end
@@ -4,7 +4,9 @@ module ActiveRecord
4
4
  module Type
5
5
  class SmallInteger < Integer
6
6
 
7
-
7
+ def sqlserver_type
8
+ 'smallint'.freeze
9
+ end
8
10
 
9
11
  end
10
12
  end
@@ -4,7 +4,7 @@ module ActiveRecord
4
4
  module Type
5
5
  class SmallMoney < Money
6
6
 
7
- def initialize(options = {})
7
+ def initialize(*args)
8
8
  super
9
9
  @precision = 10
10
10
  @scale = 4
@@ -14,6 +14,10 @@ module ActiveRecord
14
14
  :smallmoney
15
15
  end
16
16
 
17
+ def sqlserver_type
18
+ 'smallmoney'.freeze
19
+ end
20
+
17
21
  end
18
22
  end
19
23
  end