activerecord-sqlserver-adapter 6.1.2.1 → 7.2.4
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/.devcontainer/Dockerfile +30 -0
- data/.devcontainer/boot.sh +22 -0
- data/.devcontainer/devcontainer.json +38 -0
- data/.devcontainer/docker-compose.yml +42 -0
- data/.github/workflows/ci.yml +7 -4
- data/.gitignore +3 -1
- data/CHANGELOG.md +19 -42
- data/Dockerfile.ci +3 -3
- data/Gemfile +6 -1
- data/MIT-LICENSE +1 -1
- data/README.md +113 -27
- data/RUNNING_UNIT_TESTS.md +27 -14
- data/Rakefile +2 -6
- data/VERSION +1 -1
- data/activerecord-sqlserver-adapter.gemspec +3 -3
- data/appveyor.yml +4 -6
- data/docker-compose.ci.yml +2 -1
- data/lib/active_record/connection_adapters/sqlserver/core_ext/abstract_adapter.rb +20 -0
- data/lib/active_record/connection_adapters/sqlserver/core_ext/attribute_methods.rb +6 -4
- data/lib/active_record/connection_adapters/sqlserver/core_ext/calculations.rb +5 -23
- data/lib/active_record/connection_adapters/sqlserver/core_ext/explain.rb +10 -7
- 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 +12 -2
- data/lib/active_record/connection_adapters/sqlserver/core_ext/preloader.rb +24 -16
- data/lib/active_record/connection_adapters/sqlserver/database_limits.rb +0 -31
- data/lib/active_record/connection_adapters/sqlserver/database_statements.rb +143 -155
- data/lib/active_record/connection_adapters/sqlserver/database_tasks.rb +5 -5
- data/lib/active_record/connection_adapters/sqlserver/quoting.rb +57 -56
- data/lib/active_record/connection_adapters/sqlserver/savepoints.rb +26 -0
- data/lib/active_record/connection_adapters/sqlserver/schema_creation.rb +14 -12
- data/lib/active_record/connection_adapters/sqlserver/schema_dumper.rb +11 -0
- data/lib/active_record/connection_adapters/sqlserver/schema_statements.rb +213 -57
- data/lib/active_record/connection_adapters/sqlserver/showplan.rb +3 -3
- data/lib/active_record/connection_adapters/sqlserver/table_definition.rb +13 -2
- data/lib/active_record/connection_adapters/sqlserver/transaction.rb +4 -6
- data/lib/active_record/connection_adapters/sqlserver/type/data.rb +19 -1
- data/lib/active_record/connection_adapters/sqlserver/type/date.rb +1 -1
- data/lib/active_record/connection_adapters/sqlserver/type/datetime.rb +1 -1
- data/lib/active_record/connection_adapters/sqlserver/type/time.rb +1 -1
- data/lib/active_record/connection_adapters/sqlserver/utils.rb +21 -10
- data/lib/active_record/connection_adapters/sqlserver_adapter.rb +187 -187
- data/lib/active_record/connection_adapters/sqlserver_column.rb +1 -0
- data/lib/active_record/tasks/sqlserver_database_tasks.rb +42 -33
- data/lib/arel/visitors/sqlserver.rb +77 -34
- data/test/cases/active_schema_test_sqlserver.rb +127 -0
- data/test/cases/adapter_test_sqlserver.rb +114 -26
- data/test/cases/coerced_tests.rb +1121 -340
- data/test/cases/column_test_sqlserver.rb +67 -64
- data/test/cases/connection_test_sqlserver.rb +3 -6
- data/test/cases/dbconsole.rb +19 -0
- data/test/cases/disconnected_test_sqlserver.rb +8 -5
- data/test/cases/eager_load_too_many_ids_test_sqlserver.rb +18 -0
- data/test/cases/enum_test_sqlserver.rb +49 -0
- data/test/cases/execute_procedure_test_sqlserver.rb +9 -5
- data/test/cases/fetch_test_sqlserver.rb +19 -0
- data/test/cases/helper_sqlserver.rb +11 -5
- data/test/cases/index_test_sqlserver.rb +8 -6
- data/test/cases/json_test_sqlserver.rb +1 -1
- data/test/cases/lateral_test_sqlserver.rb +2 -2
- data/test/cases/migration_test_sqlserver.rb +19 -1
- data/test/cases/optimizer_hints_test_sqlserver.rb +21 -12
- data/test/cases/pessimistic_locking_test_sqlserver.rb +8 -7
- data/test/cases/primary_keys_test_sqlserver.rb +2 -2
- data/test/cases/rake_test_sqlserver.rb +10 -5
- data/test/cases/schema_dumper_test_sqlserver.rb +155 -109
- data/test/cases/schema_test_sqlserver.rb +64 -1
- data/test/cases/showplan_test_sqlserver.rb +7 -7
- data/test/cases/specific_schema_test_sqlserver.rb +17 -13
- data/test/cases/transaction_test_sqlserver.rb +13 -8
- data/test/cases/trigger_test_sqlserver.rb +20 -0
- data/test/cases/utils_test_sqlserver.rb +2 -2
- data/test/cases/uuid_test_sqlserver.rb +8 -0
- data/test/cases/view_test_sqlserver.rb +58 -0
- data/test/config.yml +1 -2
- data/test/migrations/transaction_table/1_table_will_never_be_created.rb +1 -1
- data/test/models/sqlserver/alien.rb +5 -0
- data/test/models/sqlserver/table_with_spaces.rb +5 -0
- data/test/models/sqlserver/trigger.rb +8 -0
- data/test/schema/sqlserver_specific_schema.rb +54 -6
- data/test/support/coerceable_test_sqlserver.rb +4 -4
- data/test/support/connection_reflection.rb +3 -9
- data/test/support/core_ext/query_cache.rb +7 -1
- data/test/support/marshal_compatibility_fixtures/SQLServer/rails_6_1_topic.dump +0 -0
- data/test/support/marshal_compatibility_fixtures/SQLServer/rails_6_1_topic_associations.dump +0 -0
- data/test/support/marshal_compatibility_fixtures/SQLServer/rails_7_1_topic.dump +0 -0
- data/test/support/marshal_compatibility_fixtures/SQLServer/rails_7_1_topic_associations.dump +0 -0
- data/test/support/query_assertions.rb +49 -0
- data/test/support/rake_helpers.rb +3 -1
- data/test/support/table_definition_sqlserver.rb +24 -0
- data/test/support/test_in_memory_oltp.rb +2 -2
- metadata +41 -17
- data/lib/active_record/sqlserver_base.rb +0 -18
- data/test/cases/scratchpad_test_sqlserver.rb +0 -8
- data/test/support/marshal_compatibility_fixtures/SQLServer/rails_6_0_topic.dump +0 -0
- data/test/support/marshal_compatibility_fixtures/SQLServer/rails_6_0_topic_associations.dump +0 -0
- data/test/support/sql_counter_sqlserver.rb +0 -29
@@ -1,5 +1,6 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require "tiny_tds"
|
3
4
|
require "base64"
|
4
5
|
require "active_record"
|
5
6
|
require "arel_sqlserver"
|
@@ -11,11 +12,13 @@ require "active_record/connection_adapters/sqlserver/core_ext/explain_subscriber
|
|
11
12
|
require "active_record/connection_adapters/sqlserver/core_ext/attribute_methods"
|
12
13
|
require "active_record/connection_adapters/sqlserver/core_ext/finder_methods"
|
13
14
|
require "active_record/connection_adapters/sqlserver/core_ext/preloader"
|
15
|
+
require "active_record/connection_adapters/sqlserver/core_ext/abstract_adapter"
|
14
16
|
require "active_record/connection_adapters/sqlserver/version"
|
15
17
|
require "active_record/connection_adapters/sqlserver/type"
|
16
18
|
require "active_record/connection_adapters/sqlserver/database_limits"
|
17
19
|
require "active_record/connection_adapters/sqlserver/database_statements"
|
18
20
|
require "active_record/connection_adapters/sqlserver/database_tasks"
|
21
|
+
require "active_record/connection_adapters/sqlserver/savepoints"
|
19
22
|
require "active_record/connection_adapters/sqlserver/transaction"
|
20
23
|
require "active_record/connection_adapters/sqlserver/errors"
|
21
24
|
require "active_record/connection_adapters/sqlserver/schema_creation"
|
@@ -26,12 +29,13 @@ require "active_record/connection_adapters/sqlserver/showplan"
|
|
26
29
|
require "active_record/connection_adapters/sqlserver/table_definition"
|
27
30
|
require "active_record/connection_adapters/sqlserver/quoting"
|
28
31
|
require "active_record/connection_adapters/sqlserver/utils"
|
29
|
-
require "active_record/sqlserver_base"
|
30
32
|
require "active_record/connection_adapters/sqlserver_column"
|
31
33
|
require "active_record/tasks/sqlserver_database_tasks"
|
32
34
|
|
33
35
|
module ActiveRecord
|
34
36
|
module ConnectionAdapters
|
37
|
+
register "sqlserver", "ActiveRecord::ConnectionAdapters::SQLServerAdapter", "active_record/connection_adapters/sqlserver_adapter"
|
38
|
+
|
35
39
|
class SQLServerAdapter < AbstractAdapter
|
36
40
|
include SQLServer::Version,
|
37
41
|
SQLServer::Quoting,
|
@@ -39,7 +43,8 @@ module ActiveRecord
|
|
39
43
|
SQLServer::Showplan,
|
40
44
|
SQLServer::SchemaStatements,
|
41
45
|
SQLServer::DatabaseLimits,
|
42
|
-
SQLServer::DatabaseTasks
|
46
|
+
SQLServer::DatabaseTasks,
|
47
|
+
SQLServer::Savepoints
|
43
48
|
|
44
49
|
ADAPTER_NAME = "SQLServer".freeze
|
45
50
|
|
@@ -59,63 +64,31 @@ module ActiveRecord
|
|
59
64
|
self.exclude_output_inserted_table_names = Concurrent::Map.new { false }
|
60
65
|
|
61
66
|
class << self
|
62
|
-
def
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
67
|
+
def dbconsole(config, options = {})
|
68
|
+
sqlserver_config = config.configuration_hash
|
69
|
+
args = []
|
70
|
+
|
71
|
+
args += ["-d", "#{config.database}"] if config.database
|
72
|
+
args += ["-U", "#{sqlserver_config[:username]}"] if sqlserver_config[:username]
|
73
|
+
args += ["-P", "#{sqlserver_config[:password]}"] if sqlserver_config[:password]
|
74
|
+
|
75
|
+
if sqlserver_config[:host]
|
76
|
+
host_arg = +"tcp:#{sqlserver_config[:host]}"
|
77
|
+
host_arg << ",#{sqlserver_config[:port]}" if sqlserver_config[:port]
|
78
|
+
args += ["-S", host_arg]
|
69
79
|
end
|
70
|
-
end
|
71
80
|
|
72
|
-
|
73
|
-
TinyTds::Client.new(
|
74
|
-
dataserver: config[:dataserver],
|
75
|
-
host: config[:host],
|
76
|
-
port: config[:port],
|
77
|
-
username: config[:username],
|
78
|
-
password: config[:password],
|
79
|
-
database: config[:database],
|
80
|
-
tds_version: config[:tds_version] || "7.3",
|
81
|
-
appname: config_appname(config),
|
82
|
-
login_timeout: config_login_timeout(config),
|
83
|
-
timeout: config_timeout(config),
|
84
|
-
encoding: config_encoding(config),
|
85
|
-
azure: config[:azure],
|
86
|
-
contained: config[:contained]
|
87
|
-
).tap do |client|
|
88
|
-
if config[:azure]
|
89
|
-
client.execute("SET ANSI_NULLS ON").do
|
90
|
-
client.execute("SET ANSI_NULL_DFLT_ON ON").do
|
91
|
-
client.execute("SET ANSI_PADDING ON").do
|
92
|
-
client.execute("SET ANSI_WARNINGS ON").do
|
93
|
-
else
|
94
|
-
client.execute("SET ANSI_DEFAULTS ON").do
|
95
|
-
end
|
96
|
-
client.execute("SET QUOTED_IDENTIFIER ON").do
|
97
|
-
client.execute("SET CURSOR_CLOSE_ON_COMMIT OFF").do
|
98
|
-
client.execute("SET IMPLICIT_TRANSACTIONS OFF").do
|
99
|
-
client.execute("SET TEXTSIZE 2147483647").do
|
100
|
-
client.execute("SET CONCAT_NULL_YIELDS_NULL ON").do
|
101
|
-
end
|
102
|
-
rescue TinyTds::Error => e
|
103
|
-
raise ActiveRecord::NoDatabaseError if e.message.match(/database .* does not exist/i)
|
104
|
-
raise e
|
81
|
+
find_cmd_and_exec("sqlcmd", *args)
|
105
82
|
end
|
106
83
|
|
107
|
-
def
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
README for further information."
|
115
|
-
MSG
|
84
|
+
def new_client(config)
|
85
|
+
TinyTds::Client.new(config)
|
86
|
+
rescue TinyTds::Error => error
|
87
|
+
if error.message.match(/database .* does not exist/i)
|
88
|
+
raise ActiveRecord::NoDatabaseError
|
89
|
+
else
|
90
|
+
raise
|
116
91
|
end
|
117
|
-
|
118
|
-
config[:appname] || rails_application_name
|
119
92
|
end
|
120
93
|
|
121
94
|
def rails_application_name
|
@@ -123,30 +96,24 @@ module ActiveRecord
|
|
123
96
|
rescue
|
124
97
|
nil # Might not be in a Rails context so we fallback to `nil`.
|
125
98
|
end
|
99
|
+
end
|
126
100
|
|
127
|
-
|
128
|
-
|
129
|
-
end
|
130
|
-
|
131
|
-
def config_timeout(config)
|
132
|
-
config[:timeout].present? ? config[:timeout].to_i / 1000 : nil
|
133
|
-
end
|
101
|
+
def initialize(...)
|
102
|
+
super
|
134
103
|
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
104
|
+
@config[:tds_version] = "7.3" unless @config[:tds_version]
|
105
|
+
@config[:appname] = self.class.rails_application_name unless @config[:appname]
|
106
|
+
@config[:login_timeout] = @config[:login_timeout].present? ? @config[:login_timeout].to_i : nil
|
107
|
+
@config[:timeout] = @config[:timeout].present? ? @config[:timeout].to_i / 1000 : nil
|
108
|
+
@config[:encoding] = @config[:encoding].present? ? @config[:encoding] : nil
|
139
109
|
|
140
|
-
|
141
|
-
super(connection, logger, config)
|
142
|
-
@connection_options = config
|
143
|
-
configure_connection
|
110
|
+
@connection_parameters ||= @config
|
144
111
|
end
|
145
112
|
|
146
113
|
# === Abstract Adapter ========================================== #
|
147
114
|
|
148
115
|
def arel_visitor
|
149
|
-
Arel::Visitors::SQLServer.new
|
116
|
+
Arel::Visitors::SQLServer.new(self)
|
150
117
|
end
|
151
118
|
|
152
119
|
def valid_type?(type)
|
@@ -154,13 +121,7 @@ module ActiveRecord
|
|
154
121
|
end
|
155
122
|
|
156
123
|
def schema_creation
|
157
|
-
SQLServer::SchemaCreation.new
|
158
|
-
end
|
159
|
-
|
160
|
-
def self.database_exists?(config)
|
161
|
-
!!ActiveRecord::Base.sqlserver_connection(config)
|
162
|
-
rescue ActiveRecord::NoDatabaseError
|
163
|
-
false
|
124
|
+
SQLServer::SchemaCreation.new(self)
|
164
125
|
end
|
165
126
|
|
166
127
|
def supports_ddl_transactions?
|
@@ -211,8 +172,12 @@ module ActiveRecord
|
|
211
172
|
true
|
212
173
|
end
|
213
174
|
|
175
|
+
def supports_check_constraints?
|
176
|
+
true
|
177
|
+
end
|
178
|
+
|
214
179
|
def supports_json?
|
215
|
-
|
180
|
+
version_year >= 2016
|
216
181
|
end
|
217
182
|
|
218
183
|
def supports_comments?
|
@@ -231,12 +196,16 @@ module ActiveRecord
|
|
231
196
|
true
|
232
197
|
end
|
233
198
|
|
199
|
+
def supports_common_table_expressions?
|
200
|
+
true
|
201
|
+
end
|
202
|
+
|
234
203
|
def supports_lazy_transactions?
|
235
204
|
true
|
236
205
|
end
|
237
206
|
|
238
207
|
def supports_in_memory_oltp?
|
239
|
-
|
208
|
+
version_year >= 2014
|
240
209
|
end
|
241
210
|
|
242
211
|
def supports_insert_returning?
|
@@ -255,58 +224,52 @@ module ActiveRecord
|
|
255
224
|
false
|
256
225
|
end
|
257
226
|
|
227
|
+
def return_value_after_insert?(column) # :nodoc:
|
228
|
+
column.is_primary? || column.is_identity?
|
229
|
+
end
|
230
|
+
|
258
231
|
def disable_referential_integrity
|
259
232
|
tables = tables_with_referential_integrity
|
260
|
-
tables.each { |t|
|
233
|
+
tables.each { |t| execute "ALTER TABLE #{quote_table_name(t)} NOCHECK CONSTRAINT ALL" }
|
261
234
|
yield
|
262
235
|
ensure
|
263
|
-
tables.each { |t|
|
236
|
+
tables.each { |t| execute "ALTER TABLE #{quote_table_name(t)} CHECK CONSTRAINT ALL" }
|
264
237
|
end
|
265
238
|
|
266
239
|
# === Abstract Adapter (Connection Management) ================== #
|
267
240
|
|
268
241
|
def active?
|
269
|
-
|
270
|
-
|
271
|
-
raw_connection_do "SELECT 1"
|
272
|
-
true
|
242
|
+
@raw_connection&.active?
|
273
243
|
rescue *connection_errors
|
274
244
|
false
|
275
245
|
end
|
276
246
|
|
277
|
-
def reconnect
|
278
|
-
|
279
|
-
|
247
|
+
def reconnect
|
248
|
+
@raw_connection&.close rescue nil
|
249
|
+
@raw_connection = nil
|
250
|
+
@spid = nil
|
251
|
+
@collation = nil
|
252
|
+
|
280
253
|
connect
|
281
254
|
end
|
282
255
|
|
283
256
|
def disconnect!
|
284
257
|
super
|
285
|
-
|
286
|
-
|
287
|
-
|
288
|
-
end
|
289
|
-
@connection = nil
|
258
|
+
|
259
|
+
@raw_connection&.close rescue nil
|
260
|
+
@raw_connection = nil
|
290
261
|
@spid = nil
|
291
262
|
@collation = nil
|
292
263
|
end
|
293
264
|
|
294
|
-
def clear_cache!
|
265
|
+
def clear_cache!(...)
|
295
266
|
@view_information = nil
|
296
267
|
super
|
297
268
|
end
|
298
269
|
|
299
270
|
def reset!
|
300
271
|
reset_transaction
|
301
|
-
|
302
|
-
end
|
303
|
-
|
304
|
-
def configure_connection
|
305
|
-
@spid = _raw_select("SELECT @@SPID", fetch: :rows).first.first
|
306
|
-
@version_year = version_year
|
307
|
-
|
308
|
-
initialize_dateformatter
|
309
|
-
use_database
|
272
|
+
execute "IF @@TRANCOUNT > 0 ROLLBACK TRANSACTION"
|
310
273
|
end
|
311
274
|
|
312
275
|
# === Abstract Adapter (Misc Support) =========================== #
|
@@ -347,7 +310,7 @@ module ActiveRecord
|
|
347
310
|
end
|
348
311
|
|
349
312
|
def database_prefix
|
350
|
-
@
|
313
|
+
@connection_parameters[:database_prefix]
|
351
314
|
end
|
352
315
|
|
353
316
|
def database_prefix_identifier(name)
|
@@ -362,10 +325,6 @@ module ActiveRecord
|
|
362
325
|
self.class::VERSION
|
363
326
|
end
|
364
327
|
|
365
|
-
def inspect
|
366
|
-
"#<#{self.class} version: #{version}, mode: #{@connection_options[:mode]}, azure: #{sqlserver_azure?.inspect}>"
|
367
|
-
end
|
368
|
-
|
369
328
|
def combine_bind_parameters(from_clause: [], join_clause: [], where_clause: [], having_clause: [], limit: nil, offset: nil)
|
370
329
|
result = from_clause + join_clause + where_clause + having_clause
|
371
330
|
result << offset if offset
|
@@ -377,83 +336,99 @@ module ActiveRecord
|
|
377
336
|
version_year
|
378
337
|
end
|
379
338
|
|
380
|
-
|
381
|
-
|
382
|
-
|
339
|
+
def check_version # :nodoc:
|
340
|
+
if schema_cache.database_version < 2012
|
341
|
+
raise "Your version of SQL Server (#{database_version}) is too old. SQL Server Active Record supports 2012 or higher."
|
342
|
+
end
|
343
|
+
end
|
383
344
|
|
384
|
-
|
385
|
-
|
386
|
-
|
387
|
-
|
388
|
-
|
389
|
-
|
390
|
-
|
391
|
-
|
392
|
-
|
393
|
-
|
394
|
-
|
395
|
-
|
396
|
-
|
397
|
-
|
398
|
-
|
399
|
-
|
400
|
-
|
401
|
-
|
402
|
-
|
403
|
-
|
404
|
-
|
345
|
+
class << self
|
346
|
+
protected
|
347
|
+
|
348
|
+
def initialize_type_map(m)
|
349
|
+
m.register_type %r{.*}, SQLServer::Type::UnicodeString.new
|
350
|
+
|
351
|
+
# Exact Numerics
|
352
|
+
register_class_with_limit m, "bigint(8)", SQLServer::Type::BigInteger
|
353
|
+
m.alias_type "bigint", "bigint(8)"
|
354
|
+
register_class_with_limit m, "int(4)", SQLServer::Type::Integer
|
355
|
+
m.alias_type "integer", "int(4)"
|
356
|
+
m.alias_type "int", "int(4)"
|
357
|
+
register_class_with_limit m, "smallint(2)", SQLServer::Type::SmallInteger
|
358
|
+
m.alias_type "smallint", "smallint(2)"
|
359
|
+
register_class_with_limit m, "tinyint(1)", SQLServer::Type::TinyInteger
|
360
|
+
m.alias_type "tinyint", "tinyint(1)"
|
361
|
+
m.register_type "bit", SQLServer::Type::Boolean.new
|
362
|
+
m.register_type %r{\Adecimal}i do |sql_type|
|
363
|
+
scale = extract_scale(sql_type)
|
364
|
+
precision = extract_precision(sql_type)
|
365
|
+
if scale == 0
|
366
|
+
SQLServer::Type::DecimalWithoutScale.new(precision: precision)
|
367
|
+
else
|
368
|
+
SQLServer::Type::Decimal.new(precision: precision, scale: scale)
|
369
|
+
end
|
405
370
|
end
|
406
|
-
|
407
|
-
|
408
|
-
|
409
|
-
|
410
|
-
|
411
|
-
|
412
|
-
|
413
|
-
|
414
|
-
|
415
|
-
|
416
|
-
|
417
|
-
|
418
|
-
|
419
|
-
|
420
|
-
|
421
|
-
|
422
|
-
|
371
|
+
m.alias_type %r{\Anumeric}i, "decimal"
|
372
|
+
m.register_type "money", SQLServer::Type::Money.new
|
373
|
+
m.register_type "smallmoney", SQLServer::Type::SmallMoney.new
|
374
|
+
|
375
|
+
# Approximate Numerics
|
376
|
+
m.register_type "float", SQLServer::Type::Float.new
|
377
|
+
m.register_type "real", SQLServer::Type::Real.new
|
378
|
+
|
379
|
+
# Date and Time
|
380
|
+
m.register_type "date", SQLServer::Type::Date.new
|
381
|
+
m.register_type %r{\Adatetime} do |sql_type|
|
382
|
+
precision = extract_precision(sql_type)
|
383
|
+
if precision
|
384
|
+
SQLServer::Type::DateTime2.new precision: precision
|
385
|
+
else
|
386
|
+
SQLServer::Type::DateTime.new
|
387
|
+
end
|
423
388
|
end
|
389
|
+
m.register_type %r{\Adatetimeoffset}i do |sql_type|
|
390
|
+
precision = extract_precision(sql_type)
|
391
|
+
SQLServer::Type::DateTimeOffset.new precision: precision
|
392
|
+
end
|
393
|
+
m.register_type "smalldatetime", SQLServer::Type::SmallDateTime.new
|
394
|
+
m.register_type %r{\Atime}i do |sql_type|
|
395
|
+
precision = extract_precision(sql_type) || DEFAULT_TIME_PRECISION
|
396
|
+
SQLServer::Type::Time.new precision: precision
|
397
|
+
end
|
398
|
+
|
399
|
+
# Character Strings
|
400
|
+
register_class_with_limit m, %r{\Achar}i, SQLServer::Type::Char
|
401
|
+
register_class_with_limit m, %r{\Avarchar}i, SQLServer::Type::Varchar
|
402
|
+
m.register_type "varchar(max)", SQLServer::Type::VarcharMax.new
|
403
|
+
m.register_type "text", SQLServer::Type::Text.new
|
404
|
+
|
405
|
+
# Unicode Character Strings
|
406
|
+
register_class_with_limit m, %r{\Anchar}i, SQLServer::Type::UnicodeChar
|
407
|
+
register_class_with_limit m, %r{\Anvarchar}i, SQLServer::Type::UnicodeVarchar
|
408
|
+
m.alias_type "string", "nvarchar(4000)"
|
409
|
+
m.register_type "nvarchar(max)", SQLServer::Type::UnicodeVarcharMax.new
|
410
|
+
m.register_type "nvarchar(max)", SQLServer::Type::UnicodeVarcharMax.new
|
411
|
+
m.register_type "ntext", SQLServer::Type::UnicodeText.new
|
412
|
+
|
413
|
+
# Binary Strings
|
414
|
+
register_class_with_limit m, %r{\Abinary}i, SQLServer::Type::Binary
|
415
|
+
register_class_with_limit m, %r{\Avarbinary}i, SQLServer::Type::Varbinary
|
416
|
+
m.register_type "varbinary(max)", SQLServer::Type::VarbinaryMax.new
|
417
|
+
|
418
|
+
# Other Data Types
|
419
|
+
m.register_type "uniqueidentifier", SQLServer::Type::Uuid.new
|
420
|
+
m.register_type "timestamp", SQLServer::Type::Timestamp.new
|
424
421
|
end
|
425
|
-
|
426
|
-
precision = extract_precision(sql_type)
|
427
|
-
SQLServer::Type::DateTimeOffset.new precision: precision
|
428
|
-
end
|
429
|
-
m.register_type "smalldatetime", SQLServer::Type::SmallDateTime.new
|
430
|
-
m.register_type %r{\Atime}i do |sql_type|
|
431
|
-
precision = extract_precision(sql_type) || DEFAULT_TIME_PRECISION
|
432
|
-
SQLServer::Type::Time.new precision: precision
|
433
|
-
end
|
422
|
+
end
|
434
423
|
|
435
|
-
|
436
|
-
register_class_with_limit m, %r{\Achar}i, SQLServer::Type::Char
|
437
|
-
register_class_with_limit m, %r{\Avarchar}i, SQLServer::Type::Varchar
|
438
|
-
m.register_type "varchar(max)", SQLServer::Type::VarcharMax.new
|
439
|
-
m.register_type "text", SQLServer::Type::Text.new
|
424
|
+
TYPE_MAP = Type::TypeMap.new.tap { |m| initialize_type_map(m) }
|
440
425
|
|
441
|
-
|
442
|
-
register_class_with_limit m, %r{\Anchar}i, SQLServer::Type::UnicodeChar
|
443
|
-
register_class_with_limit m, %r{\Anvarchar}i, SQLServer::Type::UnicodeVarchar
|
444
|
-
m.alias_type "string", "nvarchar(4000)"
|
445
|
-
m.register_type "nvarchar(max)", SQLServer::Type::UnicodeVarcharMax.new
|
446
|
-
m.register_type "nvarchar(max)", SQLServer::Type::UnicodeVarcharMax.new
|
447
|
-
m.register_type "ntext", SQLServer::Type::UnicodeText.new
|
426
|
+
protected
|
448
427
|
|
449
|
-
|
450
|
-
register_class_with_limit m, %r{\Abinary}i, SQLServer::Type::Binary
|
451
|
-
register_class_with_limit m, %r{\Avarbinary}i, SQLServer::Type::Varbinary
|
452
|
-
m.register_type "varbinary(max)", SQLServer::Type::VarbinaryMax.new
|
428
|
+
# === Abstract Adapter (Misc Support) =========================== #
|
453
429
|
|
454
|
-
|
455
|
-
|
456
|
-
m.register_type "timestamp", SQLServer::Type::Timestamp.new
|
430
|
+
def type_map
|
431
|
+
TYPE_MAP
|
457
432
|
end
|
458
433
|
|
459
434
|
def translate_exception(e, message:, sql:, binds:)
|
@@ -467,7 +442,7 @@ module ActiveRecord
|
|
467
442
|
when /has been chosen as the deadlock victim/i
|
468
443
|
DeadlockVictim.new(message, sql: sql, binds: binds)
|
469
444
|
when /database .* does not exist/i
|
470
|
-
NoDatabaseError.new(message
|
445
|
+
NoDatabaseError.new(message)
|
471
446
|
when /data would be truncated/
|
472
447
|
ValueTooLong.new(message, sql: sql, binds: binds)
|
473
448
|
when /connection timed out/
|
@@ -494,7 +469,7 @@ module ActiveRecord
|
|
494
469
|
# === SQLServer Specific (Connection Management) ================ #
|
495
470
|
|
496
471
|
def connection_errors
|
497
|
-
@
|
472
|
+
@raw_connection_errors ||= [].tap do |errors|
|
498
473
|
errors << TinyTds::Error if defined?(TinyTds::Error)
|
499
474
|
end
|
500
475
|
end
|
@@ -515,22 +490,47 @@ module ActiveRecord
|
|
515
490
|
end
|
516
491
|
|
517
492
|
def version_year
|
518
|
-
|
519
|
-
|
520
|
-
|
521
|
-
|
522
|
-
|
493
|
+
@version_year ||= begin
|
494
|
+
if sqlserver_version =~ /vNext/
|
495
|
+
2016
|
496
|
+
else
|
497
|
+
/SQL Server (\d+)/.match(sqlserver_version).to_a.last.to_s.to_i
|
498
|
+
end
|
499
|
+
rescue StandardError
|
500
|
+
2016
|
501
|
+
end
|
523
502
|
end
|
524
503
|
|
525
504
|
def sqlserver_version
|
526
|
-
@sqlserver_version ||= _raw_select("SELECT @@version",
|
505
|
+
@sqlserver_version ||= _raw_select("SELECT @@version", @raw_connection).first.first.to_s
|
527
506
|
end
|
528
507
|
|
529
508
|
private
|
530
509
|
|
531
510
|
def connect
|
532
|
-
@
|
533
|
-
|
511
|
+
@raw_connection = self.class.new_client(@connection_parameters)
|
512
|
+
end
|
513
|
+
|
514
|
+
def configure_connection
|
515
|
+
if @config[:azure]
|
516
|
+
@raw_connection.execute("SET ANSI_NULLS ON").do
|
517
|
+
@raw_connection.execute("SET ANSI_NULL_DFLT_ON ON").do
|
518
|
+
@raw_connection.execute("SET ANSI_PADDING ON").do
|
519
|
+
@raw_connection.execute("SET ANSI_WARNINGS ON").do
|
520
|
+
else
|
521
|
+
@raw_connection.execute("SET ANSI_DEFAULTS ON").do
|
522
|
+
end
|
523
|
+
|
524
|
+
@raw_connection.execute("SET QUOTED_IDENTIFIER ON").do
|
525
|
+
@raw_connection.execute("SET CURSOR_CLOSE_ON_COMMIT OFF").do
|
526
|
+
@raw_connection.execute("SET IMPLICIT_TRANSACTIONS OFF").do
|
527
|
+
@raw_connection.execute("SET TEXTSIZE 2147483647").do
|
528
|
+
@raw_connection.execute("SET CONCAT_NULL_YIELDS_NULL ON").do
|
529
|
+
|
530
|
+
@spid = _raw_select("SELECT @@SPID", @raw_connection).first.first
|
531
|
+
|
532
|
+
initialize_dateformatter
|
533
|
+
use_database
|
534
534
|
end
|
535
535
|
end
|
536
536
|
end
|