activerecord-jdbc-alt-adapter 50.7.0-java → 51.3.0-java
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitignore +0 -3
- data/.travis.yml +24 -28
- data/Gemfile +5 -2
- data/README.md +26 -20
- data/Rakefile +4 -30
- data/activerecord-jdbc-adapter.gemspec +2 -2
- data/activerecord-jdbc-alt-adapter.gemspec +4 -3
- data/lib/arel/visitors/sqlserver.rb +17 -3
- data/lib/arjdbc/abstract/core.rb +4 -2
- data/lib/arjdbc/abstract/database_statements.rb +2 -8
- data/lib/arjdbc/abstract/transaction_support.rb +2 -9
- data/lib/arjdbc/db2/adapter.rb +2 -52
- data/lib/arjdbc/jdbc/adapter_java.jar +0 -0
- data/lib/arjdbc/jdbc/column.rb +11 -5
- data/lib/arjdbc/jdbc/error.rb +1 -1
- data/lib/arjdbc/jdbc.rb +4 -0
- data/lib/arjdbc/mssql/adapter.rb +33 -39
- data/lib/arjdbc/mssql/connection_methods.rb +0 -5
- data/lib/arjdbc/mssql/database_statements.rb +1 -1
- data/lib/arjdbc/mssql/explain_support.rb +1 -1
- data/lib/arjdbc/mssql/{extensions.rb → extensions/attribute_methods.rb} +0 -0
- data/lib/arjdbc/mssql/extensions/calculations.rb +29 -0
- data/lib/arjdbc/mssql/schema_creation.rb +12 -0
- data/lib/arjdbc/mssql/schema_definitions.rb +17 -0
- data/lib/arjdbc/mssql/schema_dumper.rb +37 -0
- data/lib/arjdbc/mssql/schema_statements.rb +73 -44
- data/lib/arjdbc/mssql/types/date_and_time_types.rb +9 -9
- data/lib/arjdbc/mssql/utils.rb +1 -0
- data/lib/arjdbc/mssql.rb +1 -1
- data/lib/arjdbc/mysql/adapter.rb +12 -1
- data/lib/arjdbc/mysql/connection_methods.rb +7 -13
- data/lib/arjdbc/postgresql/adapter.rb +29 -12
- data/lib/arjdbc/postgresql/column.rb +3 -6
- data/lib/arjdbc/postgresql/connection_methods.rb +1 -3
- data/lib/arjdbc/postgresql/oid_types.rb +7 -12
- data/lib/arjdbc/sqlite3/adapter.rb +169 -139
- data/lib/arjdbc/sqlite3/connection_methods.rb +1 -2
- data/lib/arjdbc/version.rb +1 -1
- data/rakelib/01-tomcat.rake +2 -2
- data/rakelib/02-test.rake +2 -0
- data/rakelib/rails.rake +1 -1
- data/src/java/arjdbc/jdbc/RubyJdbcConnection.java +17 -68
- data/src/java/arjdbc/mssql/MSSQLRubyJdbcConnection.java +38 -282
- data/src/java/arjdbc/postgresql/ByteaUtils.java +1 -0
- data/src/java/arjdbc/postgresql/PostgreSQLRubyJdbcConnection.java +3 -3
- data/src/java/arjdbc/util/DateTimeUtils.java +5 -22
- metadata +20 -12
- data/lib/activerecord-jdbc-alt-adapter.rb +0 -1
data/lib/arjdbc/mssql/adapter.rb
CHANGED
@@ -7,6 +7,9 @@ require 'arel/visitors/bind_visitor'
|
|
7
7
|
require 'arel/visitors/sqlserver'
|
8
8
|
require 'active_record/connection_adapters/abstract_adapter'
|
9
9
|
|
10
|
+
require 'arjdbc/mssql/extensions/attribute_methods'
|
11
|
+
require 'arjdbc/mssql/extensions/calculations'
|
12
|
+
|
10
13
|
require 'arjdbc/abstract/core'
|
11
14
|
require 'arjdbc/abstract/connection_management'
|
12
15
|
require 'arjdbc/abstract/database_statements'
|
@@ -18,9 +21,9 @@ require 'arjdbc/mssql/types'
|
|
18
21
|
require 'arjdbc/mssql/quoting'
|
19
22
|
require 'arjdbc/mssql/schema_definitions'
|
20
23
|
require 'arjdbc/mssql/schema_statements'
|
24
|
+
require 'arjdbc/mssql/schema_dumper'
|
21
25
|
require 'arjdbc/mssql/database_statements'
|
22
26
|
require 'arjdbc/mssql/explain_support'
|
23
|
-
require 'arjdbc/mssql/extensions'
|
24
27
|
require 'arjdbc/mssql/transaction'
|
25
28
|
require 'arjdbc/mssql/errors'
|
26
29
|
require 'arjdbc/mssql/schema_creation'
|
@@ -51,6 +54,7 @@ module ActiveRecord
|
|
51
54
|
|
52
55
|
include MSSQL::Quoting
|
53
56
|
include MSSQL::SchemaStatements
|
57
|
+
include MSSQL::ColumnDumper
|
54
58
|
include MSSQL::DatabaseStatements
|
55
59
|
include MSSQL::ExplainSupport
|
56
60
|
|
@@ -81,38 +85,11 @@ module ActiveRecord
|
|
81
85
|
::ActiveRecord::ConnectionAdapters::MSSQLColumn
|
82
86
|
end
|
83
87
|
|
84
|
-
# Does this adapter support DDL rollbacks in transactions? That is, would
|
85
|
-
# CREATE TABLE or ALTER TABLE get rolled back by a transaction?
|
86
|
-
def supports_ddl_transactions?
|
87
|
-
true
|
88
|
-
end
|
89
|
-
|
90
|
-
# Can this adapter determine the primary key for tables not attached
|
91
|
-
# to an Active Record class, such as join tables?
|
92
|
-
def supports_primary_key?
|
93
|
-
true
|
94
|
-
end
|
95
|
-
|
96
88
|
# Does this adapter support creating foreign key constraints?
|
97
89
|
def supports_foreign_keys?
|
98
90
|
true
|
99
91
|
end
|
100
92
|
|
101
|
-
# Does this adapter support index sort order?
|
102
|
-
def supports_index_sort_order?
|
103
|
-
true
|
104
|
-
end
|
105
|
-
|
106
|
-
# Also known as filtered index
|
107
|
-
def supports_partial_index?
|
108
|
-
true
|
109
|
-
end
|
110
|
-
|
111
|
-
# Does this adapter support migrations?
|
112
|
-
def supports_migrations?
|
113
|
-
true
|
114
|
-
end
|
115
|
-
|
116
93
|
# Does this adapter support setting the isolation level for a transaction?
|
117
94
|
def supports_transaction_isolation?
|
118
95
|
true
|
@@ -123,6 +100,11 @@ module ActiveRecord
|
|
123
100
|
true
|
124
101
|
end
|
125
102
|
|
103
|
+
# Does this adapter support views?
|
104
|
+
def supports_views?
|
105
|
+
true
|
106
|
+
end
|
107
|
+
|
126
108
|
# Overrides abstract method which always returns false
|
127
109
|
def valid_type?(type)
|
128
110
|
!native_database_types[type].nil?
|
@@ -134,13 +116,6 @@ module ActiveRecord
|
|
134
116
|
super
|
135
117
|
end
|
136
118
|
|
137
|
-
def reset!
|
138
|
-
# execute 'IF @@TRANCOUNT > 0 ROLLBACK TRANSACTION'
|
139
|
-
# NOTE: it seems the above line interferes with the jdbc driver
|
140
|
-
# and ending up in connection closed, issue seen in rails 5.2 and 6.0
|
141
|
-
reconnect!
|
142
|
-
end
|
143
|
-
|
144
119
|
def disable_referential_integrity
|
145
120
|
tables = tables_with_referential_integrity
|
146
121
|
|
@@ -211,22 +186,37 @@ module ActiveRecord
|
|
211
186
|
alias_method :current_schema=, :default_schema=
|
212
187
|
|
213
188
|
# Overrides method in abstract adapter
|
189
|
+
# FIXME: This needs to be fixed the we find a way how to
|
190
|
+
# get the collation per column basis. At the moment we only use
|
191
|
+
# the global database collation
|
214
192
|
def case_sensitive_comparison(table, attribute, column, value)
|
215
193
|
if value.nil?
|
216
194
|
table[attribute].eq(value)
|
217
|
-
elsif
|
195
|
+
elsif [:string, :text].include?(column.type) && collation && !collation.match(/_CS/)
|
218
196
|
table[attribute].eq(Arel::Nodes::Bin.new(Arel::Nodes::BindParam.new))
|
197
|
+
# elsif value.acts_like?(:string)
|
198
|
+
# table[attribute].eq(Arel::Nodes::Bin.new(Arel::Nodes::BindParam.new))
|
219
199
|
else
|
220
200
|
table[attribute].eq(Arel::Nodes::BindParam.new)
|
221
201
|
end
|
222
202
|
end
|
223
203
|
|
224
204
|
def configure_connection
|
225
|
-
|
205
|
+
execute("SET LOCK_TIMEOUT #{lock_timeout}")
|
226
206
|
|
227
207
|
set_session_transaction_isolation
|
228
208
|
end
|
229
209
|
|
210
|
+
def lock_timeout
|
211
|
+
timeout = config[:lock_timeout].to_i
|
212
|
+
|
213
|
+
if timeout.positive?
|
214
|
+
timeout
|
215
|
+
else
|
216
|
+
5_000
|
217
|
+
end
|
218
|
+
end
|
219
|
+
|
230
220
|
def set_session_transaction_isolation
|
231
221
|
isolation_level = config[:transaction_isolation]
|
232
222
|
|
@@ -263,9 +253,9 @@ module ActiveRecord
|
|
263
253
|
end
|
264
254
|
end
|
265
255
|
|
266
|
-
|
256
|
+
private
|
267
257
|
|
268
|
-
def translate_exception(
|
258
|
+
def translate_exception(exception, message)
|
269
259
|
case message
|
270
260
|
when /(cannot insert duplicate key .* with unique index) | (violation of unique key constraint)/i
|
271
261
|
RecordNotUnique.new(message)
|
@@ -275,6 +265,10 @@ module ActiveRecord
|
|
275
265
|
ActiveRecord::InvalidForeignKey.new(message)
|
276
266
|
when /(String or binary data would be truncated)/i
|
277
267
|
ActiveRecord::ValueTooLong.new(message)
|
268
|
+
when /Cannot insert the value NULL into column .* does not allow nulls/
|
269
|
+
ActiveRecord::NotNullViolation.new(message)
|
270
|
+
when /Arithmetic overflow error converting expression/
|
271
|
+
ActiveRecord::RangeError.new(message)
|
278
272
|
else
|
279
273
|
super
|
280
274
|
end
|
@@ -52,8 +52,6 @@ ArJdbc::ConnectionMethods.module_eval do
|
|
52
52
|
|
53
53
|
# @note Assumes SQLServer SQL-JDBC driver on the class-path.
|
54
54
|
def sqlserver_connection(config)
|
55
|
-
config = config.deep_dup
|
56
|
-
|
57
55
|
config[:adapter_spec] ||= ::ArJdbc::MSSQL
|
58
56
|
config[:adapter_class] = ActiveRecord::ConnectionAdapters::MSSQLAdapter unless config.key?(:adapter_class)
|
59
57
|
|
@@ -62,15 +60,12 @@ ArJdbc::ConnectionMethods.module_eval do
|
|
62
60
|
config[:host] ||= 'localhost'
|
63
61
|
config[:driver] ||= 'com.microsoft.sqlserver.jdbc.SQLServerDriver'
|
64
62
|
config[:connection_alive_sql] ||= 'SELECT 1'
|
65
|
-
config[:lock_timeout] ||= 5000
|
66
63
|
|
67
64
|
config[:url] ||= begin
|
68
65
|
url = "jdbc:sqlserver://#{config[:host]}"
|
69
66
|
url << ( config[:port] ? ":#{config[:port]};" : ';' )
|
70
67
|
url << "databaseName=#{config[:database]};" if config[:database]
|
71
68
|
url << "instanceName=#{config[:instance]};" if config[:instance]
|
72
|
-
url << "loginTimeout=#{config[:login_timeout].to_i};" if config[:login_timeout]
|
73
|
-
url << "lockTimeout=#{config[:lock_timeout].to_i};"
|
74
69
|
app = config[:appname] || config[:application]
|
75
70
|
url << "applicationName=#{app};" if app
|
76
71
|
isc = config[:integrated_security] # Win only - needs sqljdbc_auth.dll
|
File without changes
|
@@ -0,0 +1,29 @@
|
|
1
|
+
require 'active_record/relation'
|
2
|
+
require 'active_record/version'
|
3
|
+
|
4
|
+
# NOTE: some improvements in active record broke sql calculations and habtm
|
5
|
+
# associations for this adapter and the supporting arel visitor.
|
6
|
+
# this extension fixes this issue in rails 5.1.4 onwards
|
7
|
+
#
|
8
|
+
# https://github.com/rails/rails/pull/29848
|
9
|
+
# https://github.com/rails/rails/pull/30686
|
10
|
+
|
11
|
+
module ActiveRecord
|
12
|
+
module ConnectionAdapters
|
13
|
+
module MSSQL
|
14
|
+
module Calculations
|
15
|
+
private
|
16
|
+
|
17
|
+
def build_count_subquery(relation, column_name, distinct)
|
18
|
+
super(relation.unscope(:order), column_name, distinct)
|
19
|
+
end
|
20
|
+
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
ActiveSupport.on_load(:active_record) do
|
27
|
+
mod = ActiveRecord::ConnectionAdapters::MSSQL::Calculations
|
28
|
+
ActiveRecord::Relation.prepend(mod)
|
29
|
+
end
|
@@ -15,6 +15,18 @@ module ActiveRecord
|
|
15
15
|
end
|
16
16
|
end
|
17
17
|
|
18
|
+
def add_column_options!(sql, options)
|
19
|
+
sql << " DEFAULT #{quote_default_expression(options[:default], options[:column])}" if options_include_default?(options)
|
20
|
+
|
21
|
+
sql << ' NOT NULL' if options[:null] == false
|
22
|
+
|
23
|
+
sql << ' IDENTITY(1,1)' if options[:is_identity] == true
|
24
|
+
|
25
|
+
sql << ' PRIMARY KEY' if options[:primary_key] == true
|
26
|
+
|
27
|
+
sql
|
28
|
+
end
|
29
|
+
|
18
30
|
# There is no RESTRICT in MSSQL but it has NO ACTION which behave
|
19
31
|
# same as RESTRICT, added this behave according rails api.
|
20
32
|
def action_sql(action, dependency)
|
@@ -2,6 +2,14 @@ module ActiveRecord
|
|
2
2
|
module ConnectionAdapters
|
3
3
|
module MSSQL
|
4
4
|
module ColumnMethods
|
5
|
+
def primary_key(name, type = :primary_key, **options)
|
6
|
+
if [:integer, :bigint].include?(type)
|
7
|
+
options[:is_identity] = true unless options.key?(:default)
|
8
|
+
end
|
9
|
+
|
10
|
+
super
|
11
|
+
end
|
12
|
+
|
5
13
|
# datetime with seconds always zero (:00) and without fractional seconds
|
6
14
|
def smalldatetime(*args, **options)
|
7
15
|
args.each { |name| column(name, :smalldatetime, options) }
|
@@ -64,6 +72,15 @@ module ActiveRecord
|
|
64
72
|
|
65
73
|
class TableDefinition < ActiveRecord::ConnectionAdapters::TableDefinition
|
66
74
|
include ColumnMethods
|
75
|
+
|
76
|
+
def new_column_definition(name, type, **options)
|
77
|
+
case type
|
78
|
+
when :primary_key
|
79
|
+
options[:is_identity] = true
|
80
|
+
end
|
81
|
+
|
82
|
+
super
|
83
|
+
end
|
67
84
|
end
|
68
85
|
|
69
86
|
class Table < ActiveRecord::ConnectionAdapters::Table
|
@@ -0,0 +1,37 @@
|
|
1
|
+
module ActiveRecord
|
2
|
+
module ConnectionAdapters
|
3
|
+
module MSSQL
|
4
|
+
module ColumnDumper # :nodoc:
|
5
|
+
MSSQL_NO_LIMIT_TYPES = [
|
6
|
+
'text',
|
7
|
+
'ntext',
|
8
|
+
'varchar(max)',
|
9
|
+
'nvarchar(max)',
|
10
|
+
'varbinary(max)'
|
11
|
+
].freeze
|
12
|
+
|
13
|
+
private
|
14
|
+
|
15
|
+
def schema_limit(column)
|
16
|
+
return if MSSQL_NO_LIMIT_TYPES.include?(column.sql_type)
|
17
|
+
|
18
|
+
super
|
19
|
+
end
|
20
|
+
|
21
|
+
def explicit_primary_key_default?(column)
|
22
|
+
!column.identity?
|
23
|
+
end
|
24
|
+
|
25
|
+
def default_primary_key?(column)
|
26
|
+
super && column.identity?
|
27
|
+
end
|
28
|
+
|
29
|
+
# def schema_collation(column)
|
30
|
+
# return unless column.collation
|
31
|
+
# column.collation if column.collation != collation
|
32
|
+
# end
|
33
|
+
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
@@ -5,7 +5,7 @@ module ActiveRecord
|
|
5
5
|
|
6
6
|
NATIVE_DATABASE_TYPES = {
|
7
7
|
# Logical Rails types to SQL Server types
|
8
|
-
primary_key: '
|
8
|
+
primary_key: 'bigint NOT NULL IDENTITY(1,1) PRIMARY KEY',
|
9
9
|
integer: { name: 'int', limit: 4 },
|
10
10
|
boolean: { name: 'bit' },
|
11
11
|
decimal: { name: 'decimal' },
|
@@ -41,43 +41,16 @@ module ActiveRecord
|
|
41
41
|
NATIVE_DATABASE_TYPES
|
42
42
|
end
|
43
43
|
|
44
|
-
# Returns an array of table names defined in the database.
|
45
|
-
def tables(name = nil)
|
46
|
-
if name
|
47
|
-
ActiveSupport::Deprecation.warn(<<-MSG.squish)
|
48
|
-
Passing arguments to #tables is deprecated without replacement.
|
49
|
-
MSG
|
50
|
-
end
|
51
|
-
|
52
|
-
@connection.tables(nil, name)
|
53
|
-
end
|
54
|
-
|
55
44
|
# Returns an array of Column objects for the table specified by +table_name+.
|
56
45
|
# See the concrete implementation for details on the expected parameter values.
|
57
46
|
# NOTE: This is ready, all implemented in the java part of adapter,
|
58
47
|
# it uses MSSQLColumn, SqlTypeMetadata, etc.
|
59
48
|
def columns(table_name)
|
60
|
-
|
49
|
+
@connection.columns(table_name)
|
61
50
|
rescue => e
|
62
51
|
raise translate_exception_class(e, nil)
|
63
52
|
end
|
64
53
|
|
65
|
-
# Returns an array of view names defined in the database.
|
66
|
-
# (to be implemented)
|
67
|
-
def views
|
68
|
-
[]
|
69
|
-
end
|
70
|
-
|
71
|
-
def table_exists?(table_name)
|
72
|
-
ActiveSupport::Deprecation.warn(<<-MSG.squish)
|
73
|
-
#table_exists? currently checks both tables and views.
|
74
|
-
This behavior is deprecated and will be changed with Rails 5.1 to only check tables.
|
75
|
-
Use #data_source_exists? instead.
|
76
|
-
MSG
|
77
|
-
|
78
|
-
tables.include?(table_name.to_s)
|
79
|
-
end
|
80
|
-
|
81
54
|
# Returns an array of indexes for the given table.
|
82
55
|
def indexes(table_name, name = nil)
|
83
56
|
@connection.indexes(table_name, name)
|
@@ -96,7 +69,7 @@ module ActiveRecord
|
|
96
69
|
end
|
97
70
|
|
98
71
|
def collation
|
99
|
-
select_value
|
72
|
+
@collation ||= select_value("SELECT Collation = CAST(SERVERPROPERTY('Collation') AS NVARCHAR(128))")
|
100
73
|
end
|
101
74
|
|
102
75
|
def current_database
|
@@ -178,10 +151,10 @@ module ActiveRecord
|
|
178
151
|
end
|
179
152
|
|
180
153
|
# @private these cannot specify a limit
|
181
|
-
NO_LIMIT_TYPES = %
|
154
|
+
NO_LIMIT_TYPES = %i[text binary boolean date].freeze
|
182
155
|
|
183
|
-
|
184
|
-
|
156
|
+
# Maps logical Rails types to MSSQL-specific data types.
|
157
|
+
def type_to_sql(type, limit: nil, precision: nil, scale: nil, **) # :nodoc:
|
185
158
|
# MSSQL's NVARCHAR(n | max) column supports either a number between 1 and
|
186
159
|
# 4000, or the word "MAX", which corresponds to 2**30-1 UCS-2 characters.
|
187
160
|
#
|
@@ -190,11 +163,14 @@ module ActiveRecord
|
|
190
163
|
#
|
191
164
|
# See: http://msdn.microsoft.com/en-us/library/ms186939.aspx
|
192
165
|
#
|
193
|
-
|
194
|
-
|
195
|
-
|
166
|
+
type = type.to_sym if type
|
167
|
+
native = native_database_types[type]
|
168
|
+
|
169
|
+
if type == :string && limit == 1_073_741_823
|
170
|
+
'nvarchar(max)'
|
171
|
+
elsif NO_LIMIT_TYPES.include?(type)
|
196
172
|
super(type)
|
197
|
-
elsif
|
173
|
+
elsif %i[int integer].include?(type)
|
198
174
|
if limit.nil? || limit == 4
|
199
175
|
'int'
|
200
176
|
elsif limit == 2
|
@@ -204,8 +180,22 @@ module ActiveRecord
|
|
204
180
|
else
|
205
181
|
'bigint'
|
206
182
|
end
|
207
|
-
elsif
|
208
|
-
|
183
|
+
elsif type == :uniqueidentifier
|
184
|
+
'uniqueidentifier'
|
185
|
+
elsif %i[datetime time].include?(type)
|
186
|
+
precision ||= 7
|
187
|
+
column_type_sql = (native.is_a?(Hash) ? native[:name] : native).dup
|
188
|
+
if (0..7).include?(precision)
|
189
|
+
column_type_sql << "(#{precision})"
|
190
|
+
else
|
191
|
+
raise(
|
192
|
+
ActiveRecordError,
|
193
|
+
"No #{native[:name]} type has precision of #{precision}. The " \
|
194
|
+
'allowed range of precision is from 0 to 7, even though the ' \
|
195
|
+
'sql type precision is 7 this adapter will persist up to 6 ' \
|
196
|
+
'precision only.'
|
197
|
+
)
|
198
|
+
end
|
209
199
|
else
|
210
200
|
super
|
211
201
|
end
|
@@ -241,7 +231,11 @@ module ActiveRecord
|
|
241
231
|
default = extract_new_default_value(default_or_changes)
|
242
232
|
unless default.nil?
|
243
233
|
column = columns(table_name).find { |c| c.name.to_s == column_name.to_s }
|
244
|
-
result = execute
|
234
|
+
result = execute(
|
235
|
+
"ALTER TABLE #{quote_table_name(table_name)} " \
|
236
|
+
"ADD CONSTRAINT DF_#{table_name}_#{column_name} " \
|
237
|
+
"DEFAULT #{quote_default_expression(default, column)} FOR #{quote_column_name(column_name)}"
|
238
|
+
)
|
245
239
|
result
|
246
240
|
end
|
247
241
|
end
|
@@ -257,11 +251,21 @@ module ActiveRecord
|
|
257
251
|
end
|
258
252
|
|
259
253
|
if !options[:null].nil? && options[:null] == false && !options[:default].nil?
|
260
|
-
execute
|
254
|
+
execute(
|
255
|
+
"UPDATE #{quote_table_name(table_name)} SET " \
|
256
|
+
"#{quote_column_name(column_name)}=#{quote_default_expression(options[:default], column)} " \
|
257
|
+
"WHERE #{quote_column_name(column_name)} IS NULL"
|
258
|
+
)
|
261
259
|
end
|
262
260
|
|
263
261
|
change_column_type(table_name, column_name, type, options)
|
264
|
-
|
262
|
+
|
263
|
+
if options_include_default?(options)
|
264
|
+
change_column_default(table_name, column_name, options[:default])
|
265
|
+
elsif options.key?(:default) && options[:null] == false
|
266
|
+
# Drop default constraint when null option is false
|
267
|
+
remove_default_constraint(table_name, column_name)
|
268
|
+
end
|
265
269
|
|
266
270
|
# add any removed indexes back
|
267
271
|
indexes.each do |index|
|
@@ -280,7 +284,7 @@ module ActiveRecord
|
|
280
284
|
end
|
281
285
|
sql_alter = [
|
282
286
|
"ALTER TABLE #{quoted_table}",
|
283
|
-
"ALTER COLUMN #{quoted_column} #{type_to_sql
|
287
|
+
"ALTER COLUMN #{quoted_column} #{type_to_sql(column.type, limit: column.limit, precision: column.precision, scale: column.scale)}",
|
284
288
|
(' NOT NULL' unless null)
|
285
289
|
]
|
286
290
|
|
@@ -289,8 +293,33 @@ module ActiveRecord
|
|
289
293
|
|
290
294
|
private
|
291
295
|
|
296
|
+
def data_source_sql(name = nil, type: nil)
|
297
|
+
scope = quoted_scope(name, type: type)
|
298
|
+
table_name = 'TABLE_NAME'
|
299
|
+
|
300
|
+
sql = "SELECT #{table_name}"
|
301
|
+
sql << ' FROM INFORMATION_SCHEMA.TABLES'
|
302
|
+
sql << ' WHERE TABLE_CATALOG = DB_NAME()'
|
303
|
+
sql << " AND TABLE_SCHEMA = #{quote(scope[:schema])}"
|
304
|
+
sql << " AND TABLE_NAME = #{quote(scope[:name])}" if scope[:name]
|
305
|
+
sql << " AND TABLE_TYPE = #{quote(scope[:type])}" if scope[:type]
|
306
|
+
sql << " ORDER BY #{table_name}"
|
307
|
+
sql
|
308
|
+
end
|
309
|
+
|
310
|
+
def quoted_scope(raw_name = nil, type: nil)
|
311
|
+
schema = ArJdbc::MSSQL::Utils.unqualify_table_schema(raw_name)
|
312
|
+
name = ArJdbc::MSSQL::Utils.unqualify_table_name(raw_name)
|
313
|
+
|
314
|
+
scope = {}
|
315
|
+
scope[:schema] = schema || 'dbo'
|
316
|
+
scope[:name] = name if name
|
317
|
+
scope[:type] = type if type
|
318
|
+
scope
|
319
|
+
end
|
320
|
+
|
292
321
|
def change_column_type(table_name, column_name, type, options = {})
|
293
|
-
sql = "ALTER TABLE #{quote_table_name(table_name)} ALTER COLUMN #{quote_column_name(column_name)} #{type_to_sql(type, options[:limit], options[:precision], options[:scale])}"
|
322
|
+
sql = "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])}"
|
294
323
|
sql << (options[:null] ? " NULL" : " NOT NULL") if options.has_key?(:null)
|
295
324
|
result = execute(sql)
|
296
325
|
result
|
@@ -8,12 +8,12 @@ module ActiveRecord
|
|
8
8
|
|
9
9
|
class DateTime2 < ActiveRecord::Type::DateTime
|
10
10
|
def type_cast_for_schema(value)
|
11
|
-
return "
|
11
|
+
return %("#{value}") if value.acts_like?(:string)
|
12
12
|
|
13
13
|
if value.usec > 0
|
14
|
-
"
|
14
|
+
%("#{value.to_s(:db)}.#{value.usec.to_s.remove(/0+$/)}")
|
15
15
|
else
|
16
|
-
"
|
16
|
+
%("#{value.to_s(:db)}")
|
17
17
|
end
|
18
18
|
end
|
19
19
|
|
@@ -49,12 +49,12 @@ module ActiveRecord
|
|
49
49
|
end
|
50
50
|
|
51
51
|
def type_cast_for_schema(value)
|
52
|
-
return "
|
52
|
+
return %("#{value}") if value.acts_like?(:string)
|
53
53
|
|
54
54
|
if value.usec > 0
|
55
|
-
"
|
55
|
+
%("#{value.to_s(:db)}.#{value.usec.to_s.remove(/0+$/)}")
|
56
56
|
else
|
57
|
-
"
|
57
|
+
%("#{value.to_s(:db)}")
|
58
58
|
end
|
59
59
|
end
|
60
60
|
|
@@ -95,12 +95,12 @@ module ActiveRecord
|
|
95
95
|
|
96
96
|
class Time < ActiveRecord::Type::Time
|
97
97
|
def type_cast_for_schema(value)
|
98
|
-
return "
|
98
|
+
return %("#{value}") if value.acts_like?(:string)
|
99
99
|
|
100
100
|
if value.usec > 0
|
101
|
-
"
|
101
|
+
%("#{value.to_s(:db)}.#{value.usec.to_s.remove(/0+$/)}")
|
102
102
|
else
|
103
|
-
"
|
103
|
+
%("#{value.to_s(:db)}")
|
104
104
|
end
|
105
105
|
end
|
106
106
|
|
data/lib/arjdbc/mssql/utils.rb
CHANGED
data/lib/arjdbc/mssql.rb
CHANGED
data/lib/arjdbc/mysql/adapter.rb
CHANGED
@@ -61,6 +61,10 @@ module ActiveRecord
|
|
61
61
|
true
|
62
62
|
end
|
63
63
|
|
64
|
+
def supports_transaction_isolation?
|
65
|
+
true
|
66
|
+
end
|
67
|
+
|
64
68
|
# HELPER METHODS ===========================================
|
65
69
|
|
66
70
|
# Reloading the type map in abstract/statement_cache.rb blows up postgres
|
@@ -92,7 +96,14 @@ module ActiveRecord
|
|
92
96
|
|
93
97
|
#--
|
94
98
|
# QUOTING ==================================================
|
95
|
-
|
99
|
+
#+
|
100
|
+
|
101
|
+
# FIXME: 5.1 crashes without this. I think this is Arel hitting a fallback path in to_sql.rb.
|
102
|
+
# So maybe an untested code path in their source. Still means we are doing something wrong to
|
103
|
+
# even hit it.
|
104
|
+
def quote(value, comment=nil)
|
105
|
+
super(value)
|
106
|
+
end
|
96
107
|
|
97
108
|
# NOTE: quote_string(string) provided by ArJdbc::MySQL (native code),
|
98
109
|
# this piece is also native (mysql2) under MRI: `@connection.escape(string)`
|
@@ -1,7 +1,6 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
ArJdbc::ConnectionMethods.module_eval do
|
3
3
|
def mysql_connection(config)
|
4
|
-
config = config.deep_dup
|
5
4
|
# NOTE: this isn't "really" necessary but Rails (in tests) assumes being able to :
|
6
5
|
# ActiveRecord::Base.mysql2_connection ActiveRecord::Base.configurations['arunit'].merge(database: ...)
|
7
6
|
config = symbolize_keys_if_necessary(config)
|
@@ -11,9 +10,11 @@ ArJdbc::ConnectionMethods.module_eval do
|
|
11
10
|
|
12
11
|
return jndi_connection(config) if jndi_config?(config)
|
13
12
|
|
14
|
-
driver = config[:driver]
|
15
|
-
|
16
|
-
|
13
|
+
driver = config[:driver] ||=
|
14
|
+
defined?(::Jdbc::MySQL.driver_name) ? ::Jdbc::MySQL.driver_name : 'com.mysql.jdbc.Driver'
|
15
|
+
|
16
|
+
mysql_driver = driver.start_with?('com.mysql.')
|
17
|
+
mariadb_driver = ! mysql_driver && driver.start_with?('org.mariadb.')
|
17
18
|
|
18
19
|
begin
|
19
20
|
require 'jdbc/mysql'
|
@@ -21,11 +22,6 @@ ArJdbc::ConnectionMethods.module_eval do
|
|
21
22
|
rescue LoadError # assuming driver.jar is on the class-path
|
22
23
|
end if mysql_driver
|
23
24
|
|
24
|
-
if driver.nil?
|
25
|
-
config[:driver] ||=
|
26
|
-
defined?(::Jdbc::MySQL.driver_name) ? ::Jdbc::MySQL.driver_name : 'com.mysql.jdbc.Driver'
|
27
|
-
end
|
28
|
-
|
29
25
|
config[:username] = 'root' unless config.key?(:username)
|
30
26
|
# jdbc:mysql://[host][,failoverhost...][:port]/[database]
|
31
27
|
# - if the host name is not specified, it defaults to 127.0.0.1
|
@@ -40,8 +36,7 @@ ArJdbc::ConnectionMethods.module_eval do
|
|
40
36
|
|
41
37
|
properties = ( config[:properties] ||= {} )
|
42
38
|
if mysql_driver
|
43
|
-
properties['zeroDateTimeBehavior'] ||=
|
44
|
-
config[:driver].to_s.start_with?('com.mysql.cj.') ? 'CONVERT_TO_NULL' : 'convertToNull'
|
39
|
+
properties['zeroDateTimeBehavior'] ||= 'convertToNull'
|
45
40
|
properties['jdbcCompliantTruncation'] ||= false
|
46
41
|
# NOTE: this is "better" than passing what users are used to set on MRI
|
47
42
|
# e.g. 'utf8mb4' will fail cause the driver will check for a Java charset
|
@@ -113,8 +108,7 @@ ArJdbc::ConnectionMethods.module_eval do
|
|
113
108
|
rescue LoadError # assuming driver.jar is on the class-path
|
114
109
|
end
|
115
110
|
|
116
|
-
config[:driver] ||=
|
117
|
-
defined?(::Jdbc::MariaDB.driver_name) ? ::Jdbc::MariaDB.driver_name : 'org.mariadb.jdbc.Driver'
|
111
|
+
config[:driver] ||= 'org.mariadb.jdbc.Driver'
|
118
112
|
|
119
113
|
mysql_connection(config)
|
120
114
|
end
|