activerecord-jdbc-adapter 1.3.17 → 1.3.18

Sign up to get free protection for your applications and to get access to all the features.
Files changed (54) hide show
  1. checksums.yaml +4 -4
  2. data/.travis.yml +24 -5
  3. data/History.md +54 -0
  4. data/lib/arel/visitors/compat.rb +30 -2
  5. data/lib/arel/visitors/db2.rb +118 -29
  6. data/lib/arel/visitors/derby.rb +84 -29
  7. data/lib/arel/visitors/firebird.rb +66 -9
  8. data/lib/arel/visitors/h2.rb +16 -0
  9. data/lib/arel/visitors/hsqldb.rb +6 -3
  10. data/lib/arel/visitors/postgresql_jdbc.rb +6 -0
  11. data/lib/arel/visitors/sql_server.rb +121 -40
  12. data/lib/arel/visitors/sql_server/ng42.rb +293 -0
  13. data/lib/arjdbc.rb +1 -7
  14. data/lib/arjdbc/db2.rb +1 -0
  15. data/lib/arjdbc/db2/adapter.rb +118 -18
  16. data/lib/arjdbc/derby/adapter.rb +29 -8
  17. data/lib/arjdbc/firebird.rb +1 -0
  18. data/lib/arjdbc/firebird/adapter.rb +126 -11
  19. data/lib/arjdbc/hsqldb/adapter.rb +3 -0
  20. data/lib/arjdbc/informix.rb +1 -0
  21. data/lib/arjdbc/jdbc.rb +17 -0
  22. data/lib/arjdbc/jdbc/adapter.rb +28 -3
  23. data/lib/arjdbc/jdbc/adapter_java.jar +0 -0
  24. data/lib/arjdbc/jdbc/column.rb +7 -3
  25. data/lib/arjdbc/jdbc/type_cast.rb +2 -0
  26. data/lib/arjdbc/jdbc/type_converter.rb +28 -15
  27. data/lib/arjdbc/mimer.rb +1 -0
  28. data/lib/arjdbc/mssql.rb +2 -1
  29. data/lib/arjdbc/mssql/adapter.rb +105 -30
  30. data/lib/arjdbc/mssql/column.rb +30 -7
  31. data/lib/arjdbc/mssql/limit_helpers.rb +22 -9
  32. data/lib/arjdbc/mssql/types.rb +343 -0
  33. data/lib/arjdbc/mssql/utils.rb +25 -2
  34. data/lib/arjdbc/mysql/adapter.rb +22 -21
  35. data/lib/arjdbc/oracle.rb +1 -0
  36. data/lib/arjdbc/oracle/adapter.rb +291 -19
  37. data/lib/arjdbc/oracle/column.rb +9 -5
  38. data/lib/arjdbc/oracle/connection_methods.rb +4 -1
  39. data/lib/arjdbc/postgresql/_bc_time_cast_patch.rb +21 -0
  40. data/lib/arjdbc/postgresql/adapter.rb +7 -1
  41. data/lib/arjdbc/postgresql/oid/bytea.rb +3 -0
  42. data/lib/arjdbc/postgresql/oid_types.rb +2 -1
  43. data/lib/arjdbc/tasks/database_tasks.rb +3 -0
  44. data/lib/arjdbc/util/quoted_cache.rb +2 -2
  45. data/lib/arjdbc/util/serialized_attributes.rb +11 -0
  46. data/lib/arjdbc/version.rb +1 -1
  47. data/rakelib/02-test.rake +1 -1
  48. data/rakelib/db.rake +3 -1
  49. data/src/java/arjdbc/firebird/FirebirdRubyJdbcConnection.java +190 -0
  50. data/src/java/arjdbc/jdbc/RubyJdbcConnection.java +259 -61
  51. data/src/java/arjdbc/mssql/MSSQLRubyJdbcConnection.java +13 -2
  52. data/src/java/arjdbc/oracle/OracleRubyJdbcConnection.java +192 -15
  53. data/src/java/arjdbc/postgresql/PostgreSQLRubyJdbcConnection.java +10 -2
  54. metadata +9 -4
@@ -245,6 +245,9 @@ module ArJdbc
245
245
  # @override
246
246
  def supports_views?; true end
247
247
 
248
+ # @override
249
+ def supports_foreign_keys?; true end
250
+
248
251
  # @override
249
252
  def structure_dump
250
253
  execute('SCRIPT').map do |result|
@@ -2,3 +2,4 @@ require 'arjdbc'
2
2
  ArJdbc.load_java_part :Informix
3
3
  require 'arjdbc/informix/adapter'
4
4
  require 'arjdbc/informix/connection_methods'
5
+ ArJdbc.warn_unsupported_adapter 'informix', [4, 2] # warns on AR >= 4.2
@@ -6,9 +6,26 @@ module ArJdbc
6
6
  AR40 = ::ActiveRecord::VERSION::MAJOR > 3
7
7
  # @private
8
8
  AR42 = ::ActiveRecord::VERSION::STRING >= '4.2'
9
+ # @private
10
+ AR50 = ::ActiveRecord::VERSION::MAJOR > 4
9
11
 
10
12
  class << self
11
13
 
14
+ # @private Internal API
15
+ def warn_unsupported_adapter(adapter, version = nil)
16
+ warn_prefix = 'NOTE:'
17
+ if version # e.g. [4, 2]
18
+ ar_version = [ ActiveRecord::VERSION::MAJOR, ActiveRecord::VERSION::MINOR, ActiveRecord::VERSION::TINY ]
19
+ if ( ar_version <=> version ) >= 0 # e.g. 4.2.0 > 4.2
20
+ warn_prefix = "NOTE: ActiveRecord #{version.join('.')} with"
21
+ else
22
+ warn_prefix = nil
23
+ end
24
+ end
25
+ warn "#{warn_prefix} adapter: #{adapter} is not (yet) fully supported by AR-JDBC," <<
26
+ " please consider helping us out." if warn_prefix
27
+ end
28
+
12
29
  def warn(message, once = nil)
13
30
  super(message) || true if warn?(message, once)
14
31
  end
@@ -593,6 +593,17 @@ module ActiveRecord
593
593
  end
594
594
  private :_execute
595
595
 
596
+ # Kind of `execute(sql) rescue nil` but logging failures at debug level only.
597
+ def execute_quietly(sql, name = 'SQL')
598
+ log(sql, name) do
599
+ begin
600
+ _execute(sql)
601
+ rescue => e
602
+ logger.debug("#{e.class}: #{e.message}: #{sql}")
603
+ end
604
+ end
605
+ end
606
+
596
607
  # @override
597
608
  def tables(name = nil)
598
609
  @connection.tables
@@ -624,6 +635,18 @@ module ActiveRecord
624
635
  @connection.primary_keys(table)
625
636
  end
626
637
 
638
+ # @override
639
+ def foreign_keys(table_name)
640
+ @connection.foreign_keys(table_name)
641
+ end if ArJdbc::AR42
642
+
643
+ # Does our database (+ its JDBC driver) support foreign-keys?
644
+ # @since 1.3.18
645
+ # @override
646
+ def supports_foreign_keys?
647
+ @connection.supports_foreign_keys?
648
+ end if ArJdbc::AR42
649
+
627
650
  # @deprecated Rather use {#update_lob_value} instead.
628
651
  def write_large_object(*args)
629
652
  @connection.write_large_object(*args)
@@ -934,10 +957,12 @@ module ActiveRecord
934
957
 
935
958
  end
936
959
 
937
-
938
960
  if ActiveRecord::VERSION::MAJOR < 4 # emulating Rails 3.x compatibility
939
- JdbcConnection.raw_date_time = true if JdbcConnection.raw_date_time? == nil
940
- JdbcConnection.raw_boolean = true if JdbcConnection.raw_boolean? == nil
961
+ JdbcConnection.raw_date_time = true if JdbcConnection.raw_date_time?.nil?
962
+ JdbcConnection.raw_boolean = true if JdbcConnection.raw_boolean?.nil?
963
+ elsif ArJdbc::AR42 # AR::Type should do the conversion - for better accuracy
964
+ JdbcConnection.raw_date_time = true if JdbcConnection.raw_date_time?.nil?
965
+ JdbcConnection.raw_boolean = true if JdbcConnection.raw_boolean?.nil?
941
966
  end
942
967
 
943
968
  end
@@ -10,7 +10,8 @@ module ActiveRecord
10
10
  # specific type.
11
11
  # @see JdbcAdapter#jdbc_column_class
12
12
  class JdbcColumn < Column
13
- attr_writer :limit, :precision
13
+ # @deprecated attribute writers will be removed in 1.4
14
+ attr_writer :limit, :precision # unless ArJdbc::AR42
14
15
 
15
16
  def initialize(config, name, *args)
16
17
  if self.class == JdbcColumn
@@ -24,9 +25,12 @@ module ActiveRecord
24
25
  default = args.shift
25
26
  end
26
27
  end
28
+ default = default_value(default)
29
+ default = args[0].type_cast_from_database(default) if ArJdbc::AR42
30
+
27
31
  # super <= 4.1: (name, default, sql_type = nil, null = true)
28
32
  # super >= 4.2: (name, default, cast_type, sql_type = nil, null = true)
29
- super(name, default_value(default), *args)
33
+ super(name, default, *args)
30
34
  init_column(name, default, *args)
31
35
  end
32
36
 
@@ -34,7 +38,7 @@ module ActiveRecord
34
38
  def init_column(*args); end
35
39
 
36
40
  # Similar to `ActiveRecord`'s `extract_value_from_default(default)`.
37
- # @return default value for a given column
41
+ # @return default value for a column (possibly extracted from driver value)
38
42
  def default_value(value); value; end
39
43
 
40
44
  protected
@@ -33,6 +33,7 @@ module ActiveRecord::ConnectionAdapters
33
33
  def string_to_time(string)
34
34
  return string unless string.is_a?(String)
35
35
  return nil if string.empty?
36
+ return string if string =~ /^-?infinity$/.freeze
36
37
 
37
38
  fast_string_to_time(string) || fallback_string_to_time(string)
38
39
  end
@@ -134,6 +135,7 @@ module ActiveRecord::ConnectionAdapters
134
135
  def fallback_string_to_time(string)
135
136
  time_hash = Date._parse(string)
136
137
  time_hash[:sec_fraction] = microseconds(time_hash)
138
+ time_hash[:year] *= -1 if time_hash[:zone] == 'BC'
137
139
 
138
140
  new_time(*time_hash.values_at(:year, :mon, :mday, :hour, :min, :sec, :sec_fraction, :offset))
139
141
  end
@@ -5,10 +5,23 @@ module ActiveRecord
5
5
  # but apparently a database driver can return multiple types for a given
6
6
  # java.sql.Types constant. So this type converter uses some heuristics to try to pick
7
7
  # the best (most common) type to use. It's not great, it would be better to just
8
- # delegate to each database's existin AR adapter's native_database_types method, but I
8
+ # delegate to each database's existing AR adapter's native_database_types method, but I
9
9
  # wanted to try to do this in a way that didn't pull in all the other adapters as
10
- # dependencies. Suggestions appreciated.
10
+ # dependencies. Improvements appreciated.
11
11
  class JdbcTypeConverter
12
+
13
+ # @private
14
+ TEXT_TYPES = [ Jdbc::Types::LONGVARCHAR, Jdbc::Types::CLOB ]
15
+ private_constant :TEXT_TYPES if respond_to? :private_constant
16
+
17
+ # @private
18
+ FLOAT_TYPES = [ Jdbc::Types::FLOAT, Jdbc::Types::DOUBLE, Jdbc::Types::REAL ]
19
+ private_constant :FLOAT_TYPES if respond_to? :private_constant
20
+
21
+ # @private
22
+ BINARY_TYPES = [ Jdbc::Types::LONGVARBINARY,Jdbc::Types::BINARY,Jdbc::Types::BLOB ]
23
+ private_constant :BINARY_TYPES if respond_to? :private_constant
24
+
12
25
  # The basic ActiveRecord types, mapped to an array of procs that are used to #select
13
26
  # the best type. The procs are used as selectors in order until there is only one
14
27
  # type left. If all the selectors are applied and there is still more than one
@@ -18,7 +31,7 @@ module ActiveRecord
18
31
  lambda {|r| r['type_name'] =~ /^varchar/i},
19
32
  lambda {|r| r['type_name'] =~ /^varchar$/i},
20
33
  lambda {|r| r['type_name'] =~ /varying/i}],
21
- :text => [ lambda {|r| [Jdbc::Types::LONGVARCHAR, Jdbc::Types::CLOB].include?(r['data_type'].to_i)},
34
+ :text => [ lambda {|r| TEXT_TYPES.include?(r['data_type'].to_i)},
22
35
  lambda {|r| r['type_name'] =~ /^text$/i}, # For Informix
23
36
  lambda {|r| r['type_name'] =~ /sub_type 1$/i}, # For FireBird
24
37
  lambda {|r| r['type_name'] =~ /^(text|clob)$/i},
@@ -35,7 +48,7 @@ module ActiveRecord
35
48
  lambda {|r| r['type_name'] =~ /^real$/i},
36
49
  lambda {|r| r['precision'] == '38'},
37
50
  lambda {|r| r['data_type'].to_i == Jdbc::Types::DECIMAL}],
38
- :float => [ lambda {|r| [Jdbc::Types::FLOAT,Jdbc::Types::DOUBLE, Jdbc::Types::REAL].include?(r['data_type'].to_i)},
51
+ :float => [ lambda {|r| FLOAT_TYPES.include?(r['data_type'].to_i)},
39
52
  lambda {|r| r['data_type'].to_i == Jdbc::Types::REAL}, #Prefer REAL to DOUBLE for Postgresql
40
53
  lambda {|r| r['type_name'] =~ /^float/i},
41
54
  lambda {|r| r['type_name'] =~ /^double$/i},
@@ -63,12 +76,13 @@ module ActiveRecord
63
76
  lambda {|r| r['type_name'] =~ /^date$/i},
64
77
  lambda {|r| r['type_name'] =~ /^date/i},
65
78
  lambda {|r| r['type_name'] =~ /^integer/i}], #Num of milliseconds for SQLite3 JDBC Driver3
66
- :binary => [ lambda {|r| [Jdbc::Types::LONGVARBINARY,Jdbc::Types::BINARY,Jdbc::Types::BLOB].include?(r['data_type'].to_i)},
79
+ :binary => [ lambda {|r| BINARY_TYPES.include?(r['data_type'].to_i)},
67
80
  lambda {|r| r['type_name'] =~ /^blob/i},
68
81
  lambda {|r| r['type_name'] =~ /sub_type 0$/i}, # For FireBird
69
82
  lambda {|r| r['type_name'] =~ /^varbinary$/i}, # We want this sucker for Mimer
70
83
  lambda {|r| r['type_name'] =~ /^binary$/i}, ],
71
- :boolean => [ lambda {|r| [Jdbc::Types::TINYINT].include?(r['data_type'].to_i)},
84
+ :boolean => [ lambda {|r| Jdbc::Types::BIT == r['data_type'].to_i && r['precision'].to_i == 1},
85
+ lambda {|r| Jdbc::Types::TINYINT == r['data_type'].to_i},
72
86
  lambda {|r| r['type_name'] =~ /^bool/i},
73
87
  lambda {|r| r['data_type'].to_i == Jdbc::Types::BIT},
74
88
  lambda {|r| r['type_name'] =~ /^tinyint$/i},
@@ -90,25 +104,24 @@ module ActiveRecord
90
104
  set_limit_to_nonzero_precision(type_map[k], row)
91
105
  end
92
106
 
93
- AR_TO_JDBC_TYPES.keys.each do |k|
94
- typerow = choose_type(k)
95
- type_map[k] = { :name => typerow['type_name'].downcase }
96
- case k
107
+ AR_TO_JDBC_TYPES.keys.each do |ar_type|
108
+ typerow = choose_type(ar_type)
109
+ type_map[ar_type] = { :name => typerow['type_name'].downcase }
110
+ case ar_type
97
111
  when :integer, :string, :decimal
98
- set_limit_to_nonzero_precision(type_map[k], typerow)
112
+ set_limit_to_nonzero_precision(type_map[ar_type], typerow)
99
113
  when :boolean
100
- type_map[k][:limit] = 1
114
+ type_map[ar_type][:limit] = 1
101
115
  end
102
116
  end
103
117
  type_map
104
118
  end
105
119
 
106
120
  def choose_type(ar_type)
107
- procs = AR_TO_JDBC_TYPES[ar_type]
108
121
  types = @types
109
- procs.each do |p|
122
+ AR_TO_JDBC_TYPES[ar_type].each do |proc|
110
123
  new_types = types.reject {|r| r["data_type"].to_i == Jdbc::Types::OTHER}
111
- new_types = new_types.select(&p)
124
+ new_types = new_types.select(&proc)
112
125
  new_types = new_types.inject([]) do |typs,t|
113
126
  typs << t unless typs.detect {|el| el['type_name'] == t['type_name']}
114
127
  typs
@@ -1,2 +1,3 @@
1
1
  require 'arjdbc'
2
2
  require 'arjdbc/mimer/adapter'
3
+ ArJdbc.warn_unsupported_adapter 'mimer', [4, 2] # warns on AR >= 4.2
@@ -3,4 +3,5 @@ require 'arjdbc/mssql/adapter'
3
3
  require 'arjdbc/mssql/connection_methods'
4
4
  module ArJdbc
5
5
  MsSQL = MSSQL # compatibility with 1.2
6
- end
6
+ end
7
+ ArJdbc.warn_unsupported_adapter 'mssql', [4, 2] # warns on AR >= 4.2
@@ -1,14 +1,41 @@
1
+ # NOTE: file contains code adapted from **sqlserver** adapter, license follows
2
+ =begin
3
+ Copyright (c) 2008-2015
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23
+ =end
24
+
1
25
  ArJdbc.load_java_part :MSSQL
2
26
 
3
27
  require 'strscan'
4
- require 'arjdbc/mssql/utils'
5
- require 'arjdbc/mssql/limit_helpers'
6
- require 'arjdbc/mssql/lock_methods'
7
- require 'arjdbc/mssql/column'
8
- require 'arjdbc/mssql/explain_support'
9
28
 
10
29
  module ArJdbc
11
30
  module MSSQL
31
+
32
+ require 'arjdbc/mssql/utils'
33
+ require 'arjdbc/mssql/limit_helpers'
34
+ require 'arjdbc/mssql/lock_methods'
35
+ require 'arjdbc/mssql/column'
36
+ require 'arjdbc/mssql/explain_support'
37
+ require 'arjdbc/mssql/types' if AR42
38
+
12
39
  include LimitHelpers
13
40
  include Utils
14
41
  include ExplainSupport
@@ -45,6 +72,17 @@ module ArJdbc
45
72
  # @see #update_lob_values?
46
73
  def self.update_lob_values=(update); @@update_lob_values = update; end
47
74
 
75
+ # @private
76
+ @@cs_equality_operator = 'COLLATE Latin1_General_CS_AS_WS'
77
+
78
+ # Operator for sorting strings in SQLServer, setup as :
79
+ #
80
+ # ArJdbc::MSSQL.cs_equality_operator = 'COLLATE Latin1_General_CS_AS_WS'
81
+ #
82
+ def self.cs_equality_operator; @@cs_equality_operator; end
83
+ # @see #cs_equality_operator
84
+ def self.cs_equality_operator=(operator); @@cs_equality_operator = operator; end
85
+
48
86
  # @see #quote
49
87
  # @private
50
88
  BLOB_VALUE_MARKER = "''"
@@ -70,6 +108,10 @@ module ArJdbc
70
108
  ::Arel::Visitors::SQLServer2000 : ::Arel::Visitors::SQLServer
71
109
  end
72
110
 
111
+ def self.arel_visitor_type(config)
112
+ require 'arel/visitors/sql_server'; ::Arel::Visitors::SQLServerNG
113
+ end if AR42
114
+
73
115
  # @deprecated no longer used
74
116
  # @see ActiveRecord::ConnectionAdapters::JdbcAdapter#arel2_visitors
75
117
  def self.arel2_visitors(config)
@@ -89,17 +131,54 @@ module ArJdbc
89
131
  end
90
132
  end
91
133
 
134
+ NATIVE_DATABASE_TYPES = {
135
+ :primary_key => 'int NOT NULL IDENTITY(1,1) PRIMARY KEY',
136
+ :integer => { :name => 'int', }, # :limit => 4
137
+ :boolean => { :name => 'bit' },
138
+ :decimal => { :name => 'decimal' },
139
+ :float => { :name => 'float' },
140
+ :bigint => { :name => 'bigint' },
141
+ :real => { :name => 'real' },
142
+ :date => { :name => 'date' },
143
+ :time => { :name => 'time' },
144
+ :datetime => { :name => 'datetime' },
145
+ :timestamp => { :name => 'datetime' },
146
+
147
+ :string => { :name => 'nvarchar', :limit => 4000 },
148
+ #:varchar => { :name => 'varchar' }, # limit: 8000
149
+ :text => { :name => 'nvarchar(max)' },
150
+ :text_basic => { :name => 'text' },
151
+ #:ntext => { :name => 'ntext' },
152
+ :char => { :name => 'char' },
153
+ #:nchar => { :name => 'nchar' },
154
+ :binary => { :name => 'image' }, # NOTE: :name => 'varbinary(max)'
155
+ :binary_basic => { :name => 'binary' },
156
+ :uuid => { :name => 'uniqueidentifier' },
157
+ :money => { :name => 'money' },
158
+ #:smallmoney => { :name => 'smallmoney' },
159
+ }
160
+
161
+ def native_database_types
162
+ # NOTE: due compatibility we're using the generic type resolution
163
+ # ... NATIVE_DATABASE_TYPES won't be used at all on SQLServer 2K
164
+ sqlserver_2000? ? super : super.merge(NATIVE_DATABASE_TYPES)
165
+ end
166
+
92
167
  def modify_types(types)
93
- types[:string] = { :name => "NVARCHAR", :limit => 255 }
94
168
  if sqlserver_2000?
95
- types[:text] = { :name => "NTEXT" }
169
+ types[:primary_key] = NATIVE_DATABASE_TYPES[:primary_key]
170
+ types[:string] = NATIVE_DATABASE_TYPES[:string]
171
+ types[:boolean] = NATIVE_DATABASE_TYPES[:boolean]
172
+ types[:text] = { :name => "ntext" }
173
+ types[:integer][:limit] = nil
174
+ types[:binary] = { :name => "image" }
96
175
  else
97
- types[:text] = { :name => "NVARCHAR(MAX)" }
176
+ # ~ private types for better "native" adapter compatibility
177
+ types[:varchar_max] = { :name => 'varchar(max)' }
178
+ types[:nvarchar_max] = { :name => 'nvarchar(max)' }
179
+ types[:varbinary_max] = { :name => 'varbinary(max)' }
98
180
  end
99
- types[:primary_key] = "int NOT NULL IDENTITY(1, 1) PRIMARY KEY"
100
- types[:integer][:limit] = nil
101
- types[:boolean] = { :name => "bit" }
102
- types[:binary] = { :name => "image" }
181
+ types[:string][:limit] = 255 unless AR40 # backwards compatibility
103
182
  types
104
183
  end
105
184
 
@@ -515,13 +594,6 @@ module ArJdbc
515
594
 
516
595
  # @private
517
596
  SKIP_COLUMNS_TABLE_NAMES_RE = /^information_schema\./i
518
- # @private
519
- IDENTITY_COLUMN_TYPE_RE = /identity/i
520
- # NOTE: these do not handle = equality as expected
521
- # see {#repair_special_columns}
522
- # (TEXT, NTEXT, and IMAGE data types are deprecated)
523
- # @private
524
- SPECIAL_COLUMN_TYPE_RE = /text|ntext|image|xml/i
525
597
 
526
598
  # @private
527
599
  EMPTY_ARRAY = [].freeze
@@ -537,12 +609,7 @@ module ArJdbc
537
609
  return default if table_name =~ SKIP_COLUMNS_TABLE_NAMES_RE
538
610
 
539
611
  unless columns = ( @table_columns ||= {} )[table_name]
540
- columns = super(table_name, name)
541
- for column in columns
542
- column.identity = true if column.sql_type =~ IDENTITY_COLUMN_TYPE_RE
543
- column.special = true if column.sql_type =~ SPECIAL_COLUMN_TYPE_RE
544
- end
545
- @table_columns[table_name] = columns
612
+ @table_columns[table_name] = columns = super(table_name, name)
546
613
  end
547
614
  columns
548
615
  end
@@ -572,14 +639,19 @@ module ArJdbc
572
639
  " #{enable ? 'ON' : 'OFF'} for table #{table_name} due : #{e.inspect}"
573
640
  end
574
641
 
642
+ def disable_referential_integrity
643
+ execute "EXEC sp_MSforeachtable 'ALTER TABLE ? NOCHECK CONSTRAINT ALL'"
644
+ yield
645
+ ensure
646
+ execute "EXEC sp_MSforeachtable 'ALTER TABLE ? CHECK CONSTRAINT ALL'"
647
+ end
648
+
575
649
  # @private
576
650
  # @see ArJdbc::MSSQL::LimitHelpers
577
651
  def determine_order_clause(sql)
578
652
  return $1 if sql =~ /ORDER BY (.*)$/i
579
- table_name = get_table_name(sql)
580
- # determine primary key for table :
581
- columns = self.columns(table_name)
582
- primary_column = columns.find { |column| column.primary || column.identity }
653
+ columns = self.columns(table_name = get_table_name(sql))
654
+ primary_column = columns.find { |column| column.primary? || column.identity? }
583
655
  unless primary_column # look for an id column and return it,
584
656
  # without changing case, to cover DBs with a case-sensitive collation :
585
657
  primary_column = columns.find { |column| column.name =~ /^id$/i }
@@ -708,7 +780,7 @@ module ArJdbc
708
780
  columns = self.columns(qualified_table_name, nil, nil)
709
781
  return columns if ! columns || columns.empty?
710
782
  special = []
711
- columns.each { |column| special << column.name if column.special }
783
+ columns.each { |column| special << column.name if column.special? }
712
784
  special
713
785
  end
714
786
 
@@ -735,6 +807,9 @@ module ActiveRecord::ConnectionAdapters
735
807
  setup_limit_offset!
736
808
  end
737
809
 
810
+ def self.cs_equality_operator; ::ArJdbc::MSSQL.cs_equality_operator end
811
+ def self.cs_equality_operator=(operator); ::ArJdbc::MSSQL.cs_equality_operator = operator end
812
+
738
813
  end
739
814
 
740
815
  class MSSQLColumn < JdbcColumn