activerecord-jdbc-alt-adapter 50.7.0-java → 51.3.0-java
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/.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
|