activerecord-jdbcsqlserver-adapter 51.1.0 → 52.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.
- checksums.yaml +4 -4
- data/.travis.yml +1 -1
- data/CHANGELOG.md +22 -39
- data/{Dockerfile → Dockerfile.ci} +0 -0
- data/Gemfile +1 -3
- data/README.md +5 -8
- data/VERSION +1 -1
- data/activerecord-jdbcsqlserver-adapter.gemspec +2 -3
- data/docker-compose.ci.yml +7 -5
- data/lib/active_record/connection_adapters/sqlserver/core_ext/calculations.rb +25 -29
- data/lib/active_record/connection_adapters/sqlserver/core_ext/explain.rb +14 -18
- data/lib/active_record/connection_adapters/sqlserver/core_ext/finder_methods.rb +43 -0
- data/lib/active_record/connection_adapters/sqlserver/core_ext/query_methods.rb +26 -0
- data/lib/active_record/connection_adapters/sqlserver/database_limits.rb +13 -2
- data/lib/active_record/connection_adapters/sqlserver/database_statements.rb +53 -10
- data/lib/active_record/connection_adapters/sqlserver/database_tasks.rb +1 -0
- data/lib/active_record/connection_adapters/sqlserver/jdbc_overrides.rb +5 -13
- data/lib/active_record/connection_adapters/sqlserver/schema_creation.rb +2 -1
- data/lib/active_record/connection_adapters/sqlserver/schema_dumper.rb +2 -2
- data/lib/active_record/connection_adapters/sqlserver/schema_statements.rb +43 -27
- data/lib/active_record/connection_adapters/sqlserver/transaction.rb +3 -4
- data/lib/active_record/connection_adapters/sqlserver/type/json.rb +1 -1
- data/lib/active_record/connection_adapters/sqlserver/type/string.rb +7 -0
- data/lib/active_record/connection_adapters/sqlserver/type/time.rb +1 -0
- data/lib/active_record/connection_adapters/sqlserver_adapter.rb +20 -14
- data/lib/active_record/tasks/sqlserver_database_tasks.rb +3 -1
- data/lib/activerecord-jdbcsqlserver-adapter.rb +3 -0
- data/lib/arel/visitors/sqlserver.rb +1 -1
- data/lib/arel_sqlserver.rb +0 -1
- data/test/bin/install-freetds.sh +18 -0
- data/test/cases/adapter_test_sqlserver.rb +29 -21
- data/test/cases/change_column_null_test_sqlserver.rb +42 -0
- data/test/cases/coerced_tests.rb +304 -30
- data/test/cases/column_test_sqlserver.rb +496 -462
- data/test/cases/connection_test_sqlserver.rb +2 -2
- data/test/cases/fetch_test_sqlserver.rb +5 -5
- data/test/cases/helper_sqlserver.rb +6 -0
- data/test/cases/json_test_sqlserver.rb +6 -6
- data/test/cases/migration_test_sqlserver.rb +13 -3
- data/test/cases/order_test_sqlserver.rb +19 -19
- data/test/cases/pessimistic_locking_test_sqlserver.rb +9 -9
- data/test/cases/rake_test_sqlserver.rb +20 -20
- data/test/cases/schema_dumper_test_sqlserver.rb +34 -33
- data/test/cases/schema_test_sqlserver.rb +2 -2
- data/test/cases/showplan_test_sqlserver.rb +25 -10
- data/test/cases/specific_schema_test_sqlserver.rb +11 -11
- data/test/cases/transaction_test_sqlserver.rb +9 -9
- data/test/cases/trigger_test_sqlserver.rb +8 -8
- data/test/cases/utils_test_sqlserver.rb +36 -36
- data/test/cases/uuid_test_sqlserver.rb +8 -8
- data/test/migrations/create_clients_and_change_column_null.rb +23 -0
- data/test/schema/datatypes/2012.sql +1 -0
- data/test/schema/sqlserver_specific_schema.rb +9 -1
- data/test/support/core_ext/query_cache.rb +29 -0
- metadata +19 -10
- data/BACKERS.md +0 -32
@@ -140,25 +140,17 @@ module ActiveRecord
|
|
140
140
|
[sql, binds, pk, sequence_name]
|
141
141
|
end
|
142
142
|
|
143
|
+
# @Override original version uses driver specific query command
|
144
|
+
def sqlserver_version
|
145
|
+
@sqlserver_version ||= select_value('SELECT @@version').to_s
|
146
|
+
end
|
147
|
+
|
143
148
|
# @Override
|
144
149
|
def translate_exception(exception, message)
|
145
150
|
return ActiveRecord::ValueTooLong.new(message) if exception.message.include?('java.sql.DataTruncation')
|
146
151
|
super
|
147
152
|
end
|
148
153
|
|
149
|
-
# @Overwrite
|
150
|
-
# Made it so we don't use the internal calls from the gem
|
151
|
-
def version_year
|
152
|
-
return @version_year if defined?(@version_year)
|
153
|
-
@version_year = begin
|
154
|
-
vstring = select_value('SELECT @@version').to_s
|
155
|
-
return 2016 if vstring =~ /vNext/
|
156
|
-
/SQL Server (\d+)/.match(vstring).to_a.last.to_s.to_i
|
157
|
-
rescue Exception => e
|
158
|
-
2016
|
159
|
-
end
|
160
|
-
end
|
161
|
-
|
162
154
|
private
|
163
155
|
|
164
156
|
def _quote(value)
|
@@ -8,7 +8,8 @@ module ActiveRecord
|
|
8
8
|
def visit_TableDefinition(o)
|
9
9
|
if o.as
|
10
10
|
table_name = quote_table_name(o.temporary ? "##{o.name}" : o.name)
|
11
|
-
|
11
|
+
query = o.as.respond_to?(:to_sql) ? o.as.to_sql : o.as
|
12
|
+
projections, source = query.match(%r{SELECT\s+(.*)?\s+FROM\s+(.*)?}).captures
|
12
13
|
select_into = "SELECT #{projections} INTO #{table_name} FROM #{source}"
|
13
14
|
else
|
14
15
|
o.instance_variable_set :@as, nil
|
@@ -1,7 +1,7 @@
|
|
1
1
|
module ActiveRecord
|
2
2
|
module ConnectionAdapters
|
3
3
|
module SQLServer
|
4
|
-
|
4
|
+
class SchemaDumper < ConnectionAdapters::SchemaDumper
|
5
5
|
|
6
6
|
SQLSEVER_NO_LIMIT_TYPES = [
|
7
7
|
'text',
|
@@ -24,7 +24,7 @@ module ActiveRecord
|
|
24
24
|
|
25
25
|
def schema_collation(column)
|
26
26
|
return unless column.collation
|
27
|
-
column.collation if column.collation != collation
|
27
|
+
column.collation if column.collation != @connection.collation
|
28
28
|
end
|
29
29
|
|
30
30
|
def default_primary_key?(column)
|
@@ -32,22 +32,32 @@ module ActiveRecord
|
|
32
32
|
end
|
33
33
|
end
|
34
34
|
|
35
|
-
def indexes(table_name
|
36
|
-
data = (select("EXEC sp_helpindex #{quote(table_name)}",
|
35
|
+
def indexes(table_name)
|
36
|
+
data = (select("EXEC sp_helpindex #{quote(table_name)}", "SCHEMA") || []) rescue [] # JDBC returns nil instead of an array or erring out for no results
|
37
37
|
data.reduce([]) do |indexes, index|
|
38
38
|
index = index.with_indifferent_access
|
39
|
+
|
39
40
|
if index[:index_description] =~ /primary key/
|
40
41
|
indexes
|
41
42
|
else
|
42
43
|
name = index[:index_name]
|
43
44
|
unique = index[:index_description] =~ /unique/
|
44
45
|
where = select_value("SELECT [filter_definition] FROM sys.indexes WHERE name = #{quote(name)}")
|
45
|
-
|
46
|
+
orders = {}
|
47
|
+
columns = []
|
48
|
+
|
49
|
+
index[:index_keys].split(',').each do |column|
|
46
50
|
column.strip!
|
47
|
-
|
48
|
-
column
|
51
|
+
|
52
|
+
if column.ends_with?('(-)')
|
53
|
+
column.gsub! '(-)', ''
|
54
|
+
orders[column] = :desc
|
55
|
+
end
|
56
|
+
|
57
|
+
columns << column
|
49
58
|
end
|
50
|
-
|
59
|
+
|
60
|
+
indexes << IndexDefinition.new(table_name, name, unique, columns, where: where, orders: orders)
|
51
61
|
end
|
52
62
|
end
|
53
63
|
end
|
@@ -132,7 +142,13 @@ module ActiveRecord
|
|
132
142
|
sql_commands = []
|
133
143
|
indexes = []
|
134
144
|
column_object = schema_cache.columns(table_name).find { |c| c.name.to_s == column_name.to_s }
|
135
|
-
|
145
|
+
without_constraints = options.key?(:default) || options.key?(:limit)
|
146
|
+
default = if !options.key?(:default) && column_object
|
147
|
+
column_object.default
|
148
|
+
else
|
149
|
+
options[:default]
|
150
|
+
end
|
151
|
+
if without_constraints || (column_object && column_object.type != type.to_sym)
|
136
152
|
remove_default_constraint(table_name, column_name)
|
137
153
|
indexes = indexes(table_name).select { |index| index.columns.include?(column_name.to_s) }
|
138
154
|
remove_indexes(table_name, column_name)
|
@@ -140,10 +156,9 @@ module ActiveRecord
|
|
140
156
|
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?
|
141
157
|
sql_commands << "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])}"
|
142
158
|
sql_commands.last << ' NOT NULL' if !options[:null].nil? && options[:null] == false
|
143
|
-
if
|
144
|
-
|
145
|
-
|
146
|
-
sql_commands << "ALTER TABLE #{quote_table_name(table_name)} ADD CONSTRAINT #{default_constraint_name(table_name, column_name)} DEFAULT #{quote_default_expression(options[:default], column_object)} FOR #{quote_column_name(column_name)}"
|
159
|
+
if without_constraints
|
160
|
+
default = quote_default_expression(default, column_object || column_for(table_name, column_name))
|
161
|
+
sql_commands << "ALTER TABLE #{quote_table_name(table_name)} ADD CONSTRAINT #{default_constraint_name(table_name, column_name)} DEFAULT #{default} FOR #{quote_column_name(column_name)}"
|
147
162
|
end
|
148
163
|
# Add any removed indexes back
|
149
164
|
indexes.each do |index|
|
@@ -211,7 +226,8 @@ module ActiveRecord
|
|
211
226
|
case type.to_s
|
212
227
|
when 'integer'
|
213
228
|
case limit
|
214
|
-
when 1
|
229
|
+
when 1 then 'tinyint'
|
230
|
+
when 2 then 'smallint'
|
215
231
|
when 3..4, nil then 'integer'
|
216
232
|
when 5..8 then 'bigint'
|
217
233
|
else raise(ActiveRecordError, "No integer type has byte size #{limit}. Use a numeric with precision 0 instead.")
|
@@ -237,7 +253,8 @@ module ActiveRecord
|
|
237
253
|
s.gsub(/\s+(?:ASC|DESC)\b/i, '')
|
238
254
|
.gsub(/\s+NULLS\s+(?:FIRST|LAST)\b/i, '')
|
239
255
|
}.reject(&:blank?).map.with_index { |column, i| "#{column} AS alias_#{i}" }
|
240
|
-
|
256
|
+
|
257
|
+
(order_columns << super).join(", ")
|
241
258
|
end
|
242
259
|
|
243
260
|
def update_table_definition(table_name, base)
|
@@ -247,7 +264,7 @@ module ActiveRecord
|
|
247
264
|
def change_column_null(table_name, column_name, allow_null, default = nil)
|
248
265
|
table_id = SQLServer::Utils.extract_identifiers(table_name)
|
249
266
|
column_id = SQLServer::Utils.extract_identifiers(column_name)
|
250
|
-
column =
|
267
|
+
column = column_for(table_name, column_name)
|
251
268
|
if !allow_null.nil? && allow_null == false && !default.nil?
|
252
269
|
do_execute("UPDATE #{table_id} SET #{column_id}=#{quote(default)} WHERE #{column_id} IS NULL")
|
253
270
|
end
|
@@ -256,13 +273,17 @@ module ActiveRecord
|
|
256
273
|
do_execute sql
|
257
274
|
end
|
258
275
|
|
276
|
+
def create_schema_dumper(options)
|
277
|
+
SQLServer::SchemaDumper.create(self, options)
|
278
|
+
end
|
279
|
+
|
259
280
|
private
|
260
281
|
|
261
282
|
def data_source_sql(name = nil, type: nil)
|
262
283
|
scope = quoted_scope name, type: type
|
263
284
|
table_name = lowercase_schema_reflection_sql 'TABLE_NAME'
|
264
285
|
sql = "SELECT #{table_name}"
|
265
|
-
sql << ' FROM INFORMATION_SCHEMA.TABLES'
|
286
|
+
sql << ' FROM INFORMATION_SCHEMA.TABLES WITH (NOLOCK)'
|
266
287
|
sql << ' WHERE TABLE_CATALOG = DB_NAME()'
|
267
288
|
sql << " AND TABLE_SCHEMA = #{quote(scope[:schema])}"
|
268
289
|
sql << " AND TABLE_NAME = #{quote(scope[:name])}" if scope[:name]
|
@@ -408,11 +429,13 @@ module ActiveRecord
|
|
408
429
|
ci[:default_function] = begin
|
409
430
|
default = ci[:default_value]
|
410
431
|
if default.nil? && view_exists
|
411
|
-
default = select_value
|
432
|
+
default = select_value %{
|
412
433
|
SELECT c.COLUMN_DEFAULT
|
413
434
|
FROM #{database}.INFORMATION_SCHEMA.COLUMNS c
|
414
|
-
WHERE
|
415
|
-
|
435
|
+
WHERE
|
436
|
+
c.TABLE_NAME = '#{view_tblnm}'
|
437
|
+
AND c.COLUMN_NAME = '#{views_real_column_name(table_name, ci[:name])}'
|
438
|
+
}.squish, 'SCHEMA'
|
416
439
|
end
|
417
440
|
case default
|
418
441
|
when nil
|
@@ -431,7 +454,7 @@ module ActiveRecord
|
|
431
454
|
else ci[:type]
|
432
455
|
end
|
433
456
|
value = default.match(/\A\((.*)\)\Z/m)[1]
|
434
|
-
value = select_value
|
457
|
+
value = select_value("SELECT CAST(#{value} AS #{type}) AS value", 'SCHEMA')
|
435
458
|
[value, nil]
|
436
459
|
end
|
437
460
|
end
|
@@ -482,13 +505,6 @@ module ActiveRecord
|
|
482
505
|
"DF_#{table_name}_#{column_name}"
|
483
506
|
end
|
484
507
|
|
485
|
-
def detect_column_for!(table_name, column_name)
|
486
|
-
unless column = schema_cache.columns(table_name).find { |c| c.name == column_name.to_s }
|
487
|
-
raise ActiveRecordError, "No such column: #{table_name}.#{column_name}"
|
488
|
-
end
|
489
|
-
column
|
490
|
-
end
|
491
|
-
|
492
508
|
def lowercase_schema_reflection_sql(node)
|
493
509
|
lowercase_schema_reflection ? "LOWER(#{node})" : node
|
494
510
|
end
|
@@ -504,7 +520,7 @@ module ActiveRecord
|
|
504
520
|
@view_information ||= {}
|
505
521
|
@view_information[table_name] ||= begin
|
506
522
|
identifier = SQLServer::Utils.extract_identifiers(table_name)
|
507
|
-
view_info = select_one "SELECT * FROM INFORMATION_SCHEMA.VIEWS WHERE TABLE_NAME = #{quote(identifier.object)}", 'SCHEMA'
|
523
|
+
view_info = select_one "SELECT * FROM INFORMATION_SCHEMA.VIEWS WITH (NOLOCK) WHERE TABLE_NAME = #{quote(identifier.object)}", 'SCHEMA'
|
508
524
|
if view_info
|
509
525
|
view_info = view_info.with_indifferent_access
|
510
526
|
if view_info[:VIEW_DEFINITION].blank? || view_info[:VIEW_DEFINITION].length == 4000
|
@@ -26,13 +26,13 @@ module ActiveRecord
|
|
26
26
|
|
27
27
|
end
|
28
28
|
|
29
|
-
Transaction.send :
|
29
|
+
Transaction.send :prepend, SQLServerTransaction
|
30
30
|
|
31
31
|
module SQLServerRealTransaction
|
32
32
|
|
33
33
|
attr_reader :starting_isolation_level
|
34
34
|
|
35
|
-
def initialize(connection, options,
|
35
|
+
def initialize(connection, options, *args)
|
36
36
|
@connection = connection
|
37
37
|
@starting_isolation_level = current_isolation_level if options[:isolation]
|
38
38
|
super
|
@@ -58,7 +58,6 @@ module ActiveRecord
|
|
58
58
|
|
59
59
|
end
|
60
60
|
|
61
|
-
RealTransaction.send :
|
62
|
-
|
61
|
+
RealTransaction.send :prepend, SQLServerRealTransaction
|
63
62
|
end
|
64
63
|
end
|
@@ -7,6 +7,8 @@ require 'active_record/connection_adapters/sqlserver/core_ext/calculations'
|
|
7
7
|
require 'active_record/connection_adapters/sqlserver/core_ext/explain' unless defined? JRUBY_VERSION
|
8
8
|
require 'active_record/connection_adapters/sqlserver/core_ext/explain_subscriber'
|
9
9
|
require 'active_record/connection_adapters/sqlserver/core_ext/attribute_methods'
|
10
|
+
require 'active_record/connection_adapters/sqlserver/core_ext/finder_methods'
|
11
|
+
require 'active_record/connection_adapters/sqlserver/core_ext/query_methods'
|
10
12
|
require 'active_record/connection_adapters/sqlserver/version'
|
11
13
|
require 'active_record/connection_adapters/sqlserver/type'
|
12
14
|
require 'active_record/connection_adapters/sqlserver/database_limits'
|
@@ -34,7 +36,6 @@ module ActiveRecord
|
|
34
36
|
SQLServer::Quoting,
|
35
37
|
SQLServer::DatabaseStatements,
|
36
38
|
SQLServer::Showplan,
|
37
|
-
SQLServer::SchemaDumper,
|
38
39
|
SQLServer::SchemaStatements,
|
39
40
|
SQLServer::DatabaseLimits,
|
40
41
|
SQLServer::DatabaseTasks
|
@@ -53,6 +54,9 @@ module ActiveRecord
|
|
53
54
|
|
54
55
|
ADAPTER_NAME = 'SQLServer'.freeze
|
55
56
|
|
57
|
+
# Default precision for 'time' (See https://docs.microsoft.com/en-us/sql/t-sql/data-types/time-transact-sql)
|
58
|
+
DEFAULT_TIME_PRECISION = 7
|
59
|
+
|
56
60
|
attr_reader :spid
|
57
61
|
|
58
62
|
cattr_accessor :cs_equality_operator, instance_accessor: false
|
@@ -148,6 +152,10 @@ module ActiveRecord
|
|
148
152
|
false
|
149
153
|
end
|
150
154
|
|
155
|
+
def supports_savepoints?
|
156
|
+
true
|
157
|
+
end
|
158
|
+
|
151
159
|
def supports_in_memory_oltp?
|
152
160
|
@version_year >= 2014
|
153
161
|
end
|
@@ -201,7 +209,7 @@ module ActiveRecord
|
|
201
209
|
|
202
210
|
def tables_with_referential_integrity
|
203
211
|
schemas_and_tables = select_rows <<-SQL.strip_heredoc
|
204
|
-
SELECT s.name AS schema_name, o.name AS table_name
|
212
|
+
SELECT DISTINCT s.name AS schema_name, o.name AS table_name
|
205
213
|
FROM sys.foreign_keys i
|
206
214
|
INNER JOIN sys.objects o ON i.parent_object_id = o.OBJECT_ID
|
207
215
|
INNER JOIN sys.schemas s ON o.schema_id = s.schema_id
|
@@ -224,7 +232,7 @@ module ActiveRecord
|
|
224
232
|
end
|
225
233
|
|
226
234
|
def sqlserver_azure?
|
227
|
-
|
235
|
+
!!(sqlserver_version =~ /Azure/i)
|
228
236
|
end
|
229
237
|
|
230
238
|
def database_prefix_remote_server?
|
@@ -265,7 +273,7 @@ module ActiveRecord
|
|
265
273
|
|
266
274
|
# === Abstract Adapter (Misc Support) =========================== #
|
267
275
|
|
268
|
-
def initialize_type_map(m)
|
276
|
+
def initialize_type_map(m = type_map)
|
269
277
|
m.register_type %r{.*}, SQLServer::Type::UnicodeString.new
|
270
278
|
# Exact Numerics
|
271
279
|
register_class_with_limit m, 'bigint(8)', SQLServer::Type::BigInteger
|
@@ -305,8 +313,7 @@ module ActiveRecord
|
|
305
313
|
end
|
306
314
|
m.register_type 'smalldatetime', SQLServer::Type::SmallDateTime.new
|
307
315
|
m.register_type %r{\Atime}i do |sql_type|
|
308
|
-
|
309
|
-
precision = extract_precision(sql_type)
|
316
|
+
precision = extract_precision(sql_type) || DEFAULT_TIME_PRECISION
|
310
317
|
SQLServer::Type::Time.new precision: precision
|
311
318
|
end
|
312
319
|
# Character Strings
|
@@ -447,16 +454,15 @@ module ActiveRecord
|
|
447
454
|
end
|
448
455
|
|
449
456
|
def version_year
|
450
|
-
return
|
451
|
-
|
452
|
-
|
453
|
-
|
454
|
-
/SQL Server (\d+)/.match(vstring).to_a.last.to_s.to_i
|
455
|
-
rescue Exception => e
|
456
|
-
2016
|
457
|
-
end
|
457
|
+
return 2016 if sqlserver_version =~ /vNext/
|
458
|
+
/SQL Server (\d+)/.match(sqlserver_version).to_a.last.to_s.to_i
|
459
|
+
rescue StandardError => e
|
460
|
+
2016
|
458
461
|
end
|
459
462
|
|
463
|
+
def sqlserver_version
|
464
|
+
@sqlserver_version ||= _raw_select('SELECT @@version', fetch: :rows).first.first.to_s
|
465
|
+
end
|
460
466
|
end
|
461
467
|
end
|
462
468
|
end
|
@@ -49,9 +49,11 @@ module ActiveRecord
|
|
49
49
|
end
|
50
50
|
|
51
51
|
def structure_dump(filename, extra_flags)
|
52
|
+
server_arg = "-S #{Shellwords.escape(configuration['host'])}"
|
53
|
+
server_arg += ":#{Shellwords.escape(configuration['port'])}" if configuration['port']
|
52
54
|
command = [
|
53
55
|
"defncopy",
|
54
|
-
|
56
|
+
server_arg,
|
55
57
|
"-D #{Shellwords.escape(configuration['database'])}",
|
56
58
|
"-U #{Shellwords.escape(configuration['username'])}",
|
57
59
|
"-P #{Shellwords.escape(configuration['password'])}",
|
@@ -1,6 +1,9 @@
|
|
1
1
|
# Our core date/time overrides to support prepared statements
|
2
2
|
require 'active_record/connection_adapters/sqlserver/core_ext/date_time'
|
3
3
|
|
4
|
+
require 'active_support' # Need this for the next line
|
5
|
+
require 'active_record/log_subscriber' # Need to make sure this is loaded before we load Core for monkey patching
|
6
|
+
|
4
7
|
# Load the jar file for the jdbc driver
|
5
8
|
require_relative './jdbc_mssql_driver_loader'
|
6
9
|
|
@@ -14,7 +14,7 @@ module Arel
|
|
14
14
|
# SQLServer ToSql/Visitor (Overides)
|
15
15
|
|
16
16
|
def visit_Arel_Nodes_BindParam o, collector
|
17
|
-
collector.add_bind(o) { |i| "@#{i-1}" }
|
17
|
+
collector.add_bind(o.value) { |i| "@#{i-1}" }
|
18
18
|
end unless defined? JRUBY_VERSION # converts bind argument markers "?" to "@n", but JDBC wants "?"
|
19
19
|
|
20
20
|
def visit_Arel_Nodes_Bin o, collector
|
data/lib/arel_sqlserver.rb
CHANGED
@@ -0,0 +1,18 @@
|
|
1
|
+
#!/usr/bin/env bash
|
2
|
+
|
3
|
+
set -x
|
4
|
+
set -e
|
5
|
+
|
6
|
+
FREETDS_VERSION=1.00.21
|
7
|
+
|
8
|
+
wget http://www.freetds.org/files/stable/freetds-$FREETDS_VERSION.tar.gz
|
9
|
+
tar -xzf freetds-$FREETDS_VERSION.tar.gz
|
10
|
+
cd freetds-$FREETDS_VERSION
|
11
|
+
./configure --prefix=/opt/local \
|
12
|
+
--with-openssl=/opt/local \
|
13
|
+
--with-tdsver=7.3
|
14
|
+
make
|
15
|
+
make install
|
16
|
+
cd ..
|
17
|
+
rm -rf freetds-$FREETDS_VERSION
|
18
|
+
rm freetds-$FREETDS_VERSION.tar.gz
|
@@ -15,14 +15,15 @@ class AdapterTestSQLServer < ActiveRecord::TestCase
|
|
15
15
|
|
16
16
|
it 'has basic and non-sensitive information in the adapters inspect method' do
|
17
17
|
string = connection.inspect
|
18
|
-
|
19
|
-
string.must_match %r{
|
20
|
-
string.must_match %r{
|
21
|
-
string.must_match %r{
|
22
|
-
string.
|
23
|
-
string.wont_match %r{
|
24
|
-
string.wont_match %r{
|
25
|
-
string.wont_match %r{
|
18
|
+
|
19
|
+
_(string).must_match %r{ActiveRecord::ConnectionAdapters::SQLServerAdapter}
|
20
|
+
_(string).must_match %r{version\: \d+\.\d}
|
21
|
+
_(string).must_match %r{mode: (dblib|jdbc)}
|
22
|
+
_(string).must_match %r{azure: (true|false)}
|
23
|
+
_(string).wont_match %r{host}
|
24
|
+
_(string).wont_match %r{password}
|
25
|
+
_(string).wont_match %r{username}
|
26
|
+
_(string).wont_match %r{port}
|
26
27
|
end
|
27
28
|
|
28
29
|
it 'has a 128 max #table_alias_length' do
|
@@ -162,7 +163,7 @@ class AdapterTestSQLServer < ActiveRecord::TestCase
|
|
162
163
|
end
|
163
164
|
|
164
165
|
it 'return an empty array when calling #identity_columns for a table_name with no identity' do
|
165
|
-
connection.send(:identity_columns, Subscriber.table_name).must_equal []
|
166
|
+
_(connection.send(:identity_columns, Subscriber.table_name)).must_equal []
|
166
167
|
end
|
167
168
|
|
168
169
|
end
|
@@ -232,6 +233,11 @@ class AdapterTestSQLServer < ActiveRecord::TestCase
|
|
232
233
|
end
|
233
234
|
end
|
234
235
|
|
236
|
+
it 'not disable referential integrity for the same table twice' do
|
237
|
+
tables = SSTestHasPk.connection.tables_with_referential_integrity
|
238
|
+
assert_equal tables.size, tables.uniq.size
|
239
|
+
end
|
240
|
+
|
235
241
|
end
|
236
242
|
|
237
243
|
describe 'database statements' do
|
@@ -269,9 +275,12 @@ class AdapterTestSQLServer < ActiveRecord::TestCase
|
|
269
275
|
assert_equal 'integer', connection.type_to_sql(:integer, limit: 3)
|
270
276
|
end
|
271
277
|
|
272
|
-
it 'create smallints when limit is
|
278
|
+
it 'create smallints when limit is 2' do
|
273
279
|
assert_equal 'smallint', connection.type_to_sql(:integer, limit: 2)
|
274
|
-
|
280
|
+
end
|
281
|
+
|
282
|
+
it 'create tinyints when limit is 1' do
|
283
|
+
assert_equal 'tinyint', connection.type_to_sql(:integer, limit: 1)
|
275
284
|
end
|
276
285
|
|
277
286
|
it 'create bigints when limit is greateer than 4' do
|
@@ -296,7 +305,7 @@ class AdapterTestSQLServer < ActiveRecord::TestCase
|
|
296
305
|
end
|
297
306
|
|
298
307
|
it 'find SSTestCustomersView table name' do
|
299
|
-
connection.views.must_include 'sst_customers_view'
|
308
|
+
_(connection.views).must_include 'sst_customers_view'
|
300
309
|
end
|
301
310
|
|
302
311
|
it 'work with dynamic finders' do
|
@@ -337,9 +346,9 @@ class AdapterTestSQLServer < ActiveRecord::TestCase
|
|
337
346
|
end
|
338
347
|
|
339
348
|
it 'find identity column' do
|
340
|
-
SSTestCustomersView.primary_key.must_equal 'id'
|
341
|
-
connection.primary_key(SSTestCustomersView.table_name).must_equal 'id'
|
342
|
-
SSTestCustomersView.columns_hash['id'].must_be :is_identity?
|
349
|
+
_(SSTestCustomersView.primary_key).must_equal 'id'
|
350
|
+
_(connection.primary_key(SSTestCustomersView.table_name)).must_equal 'id'
|
351
|
+
_(SSTestCustomersView.columns_hash['id']).must_be :is_identity?
|
343
352
|
end
|
344
353
|
|
345
354
|
it 'find default values' do
|
@@ -364,9 +373,9 @@ class AdapterTestSQLServer < ActiveRecord::TestCase
|
|
364
373
|
end
|
365
374
|
|
366
375
|
it 'find identity column' do
|
367
|
-
SSTestStringDefaultsView.primary_key.must_equal 'id'
|
368
|
-
connection.primary_key(SSTestStringDefaultsView.table_name).must_equal 'id'
|
369
|
-
SSTestStringDefaultsView.columns_hash['id'].must_be :is_identity?
|
376
|
+
_(SSTestStringDefaultsView.primary_key).must_equal 'id'
|
377
|
+
_(connection.primary_key(SSTestStringDefaultsView.table_name)).must_equal 'id'
|
378
|
+
_(SSTestStringDefaultsView.columns_hash['id']).must_be :is_identity?
|
370
379
|
end
|
371
380
|
|
372
381
|
it 'find default values' do
|
@@ -415,12 +424,11 @@ class AdapterTestSQLServer < ActiveRecord::TestCase
|
|
415
424
|
|
416
425
|
it 'in_memory_oltp' do
|
417
426
|
if ENV['IN_MEMORY_OLTP'] && connection.supports_in_memory_oltp?
|
418
|
-
SSTMemory.primary_key.must_equal 'id'
|
419
|
-
SSTMemory.columns_hash['id'].must_be :is_identity?
|
427
|
+
_(SSTMemory.primary_key).must_equal 'id'
|
428
|
+
_(SSTMemory.columns_hash['id']).must_be :is_identity?
|
420
429
|
else
|
421
430
|
skip 'supports_in_memory_oltp? => false'
|
422
431
|
end
|
423
432
|
end
|
424
433
|
|
425
434
|
end
|
426
|
-
|