activerecord-jdbc-alt-adapter 71.0.0-java → 72.0.0.rc1-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/README.md +2 -2
- data/activerecord-jdbc-adapter.gemspec +1 -1
- data/activerecord-jdbc-alt-adapter.gemspec +1 -1
- data/lib/arel/visitors/sqlserver.rb +13 -9
- data/lib/arjdbc/abstract/core.rb +10 -1
- data/lib/arjdbc/abstract/database_statements.rb +1 -1
- data/lib/arjdbc/abstract/transaction_support.rb +3 -1
- data/lib/arjdbc/jdbc/adapter.rb +0 -1
- data/lib/arjdbc/jdbc/adapter_java.jar +0 -0
- data/lib/arjdbc/mssql/adapter.rb +18 -15
- data/lib/arjdbc/mssql/adapter_hash_config.rb +53 -0
- data/lib/arjdbc/mssql/column.rb +16 -7
- data/lib/arjdbc/mssql/database_statements.rb +7 -2
- data/lib/arjdbc/mssql/quoting.rb +56 -36
- data/lib/arjdbc/mssql/schema_creation.rb +16 -0
- data/lib/arjdbc/mssql/schema_statements.rb +44 -19
- data/lib/arjdbc/mssql.rb +1 -1
- data/lib/arjdbc/mysql/adapter.rb +8 -11
- data/lib/arjdbc/mysql/adapter_hash_config.rb +159 -0
- data/lib/arjdbc/mysql.rb +1 -1
- data/lib/arjdbc/postgresql/adapter.rb +17 -11
- data/lib/arjdbc/postgresql/adapter_hash_config.rb +98 -0
- data/lib/arjdbc/postgresql/base/array_encoder.rb +3 -1
- data/lib/arjdbc/postgresql/oid_types.rb +2 -2
- data/lib/arjdbc/postgresql.rb +1 -1
- data/lib/arjdbc/sqlite3/adapter.rb +193 -90
- data/lib/arjdbc/sqlite3/adapter_hash_config.rb +91 -0
- data/lib/arjdbc/sqlite3/column.rb +17 -3
- data/lib/arjdbc/sqlite3/pragmas.rb +105 -0
- data/lib/arjdbc/sqlite3.rb +1 -1
- data/lib/arjdbc/version.rb +1 -1
- data/lib/arjdbc.rb +16 -1
- data/src/java/arjdbc/jdbc/RubyJdbcConnection.java +5 -0
- data/src/java/arjdbc/sqlite3/SQLite3RubyJdbcConnection.java +12 -2
- metadata +12 -8
- data/lib/arjdbc/jdbc/base_ext.rb +0 -17
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 0f7f249466042cd80343c394b99718ff78c5754a2105f06eaf87672f25d2d54e
|
4
|
+
data.tar.gz: cc61ff60b8f74d3fa100156f59c4cdd198865e87d9be401bf833a2e0ed623291
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 25c0368cbbeecad8536caa0ffadff34c28aacb0ff4a66f2085016224322645add68206976dbcef42475bdc39c1ffd47da761eacd919292ae15e6711c44935317
|
7
|
+
data.tar.gz: 9beed2af43699a9349a9284c252fd97db3c0110510892ac6937b5ace94df6be02269fb7360caa653fb864a4326d6582e958bea1afe4c69d8adaabec96af2a671
|
data/README.md
CHANGED
@@ -175,7 +175,7 @@ adapters are available:
|
|
175
175
|
|
176
176
|
```yml
|
177
177
|
development:
|
178
|
-
adapter: mysql2
|
178
|
+
adapter: mysql2
|
179
179
|
database: blog_development
|
180
180
|
username: blog
|
181
181
|
password: 1234
|
@@ -199,7 +199,7 @@ or preferably using the *properties:* syntax:
|
|
199
199
|
|
200
200
|
```yml
|
201
201
|
production:
|
202
|
-
adapter:
|
202
|
+
adapter: mysql2
|
203
203
|
username: blog
|
204
204
|
password: blog
|
205
205
|
url: "jdbc:mysql://localhost:3306/blog?profileSQL=true"
|
@@ -41,7 +41,7 @@ Gem::Specification.new do |gem|
|
|
41
41
|
gem.executables = gem.files.grep(%r{^bin/}).map { |f| File.basename(f) }
|
42
42
|
gem.test_files = gem.files.grep(%r{^test/})
|
43
43
|
|
44
|
-
gem.add_dependency
|
44
|
+
gem.add_dependency "activerecord", "~> 7.2.2"
|
45
45
|
|
46
46
|
#gem.add_development_dependency 'test-unit', '2.5.4'
|
47
47
|
#gem.add_development_dependency 'test-unit-context', '>= 0.3.0'
|
@@ -43,7 +43,7 @@ Gem::Specification.new do |gem|
|
|
43
43
|
gem.executables = gem.files.grep(%r{^bin/}).map { |f| File.basename(f) }
|
44
44
|
gem.test_files = gem.files.grep(%r{^test/})
|
45
45
|
|
46
|
-
gem.add_dependency
|
46
|
+
gem.add_dependency "activerecord", "~> 7.2.2"
|
47
47
|
|
48
48
|
#gem.add_development_dependency 'test-unit', '2.5.4'
|
49
49
|
#gem.add_development_dependency 'test-unit-context', '>= 0.3.0'
|
@@ -83,15 +83,17 @@ module Arel
|
|
83
83
|
@select_statement = nil
|
84
84
|
end
|
85
85
|
|
86
|
-
def visit_Arel_Table
|
86
|
+
def visit_Arel_Table(o, collector)
|
87
87
|
# Apparently, o.engine.connection can actually be a different adapter
|
88
88
|
# than sqlserver. Can be removed if fixed in ActiveRecord. See:
|
89
89
|
# github.com/rails-sqlserver/activerecord-sqlserver-adapter/issues/450
|
90
90
|
table_name = begin
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
91
|
+
o.class.engine.with_connection do |connection|
|
92
|
+
if connection.respond_to?(:sqlserver?) && connection.database_prefix_remote_server?
|
93
|
+
remote_server_table_name(o)
|
94
|
+
else
|
95
|
+
quote_table_name(o.name)
|
96
|
+
end
|
95
97
|
end
|
96
98
|
rescue Exception => e
|
97
99
|
quote_table_name(o.name)
|
@@ -259,10 +261,12 @@ module Arel
|
|
259
261
|
column_name ? t[column_name] : nil
|
260
262
|
end
|
261
263
|
|
262
|
-
def remote_server_table_name
|
263
|
-
|
264
|
-
|
265
|
-
|
264
|
+
def remote_server_table_name(o)
|
265
|
+
o.class.engine.with_connection do |connection|
|
266
|
+
ActiveRecord::ConnectionAdapters::SQLServer::Utils.extract_identifiers(
|
267
|
+
"#{connection.database_prefix}#{o.name}"
|
268
|
+
).quoted
|
269
|
+
end
|
266
270
|
end
|
267
271
|
|
268
272
|
# Need to remove ordering from subqueries unless TOP/OFFSET also used. Otherwise, SQLServer
|
data/lib/arjdbc/abstract/core.rb
CHANGED
@@ -60,7 +60,16 @@ module ArJdbc
|
|
60
60
|
# this version of log() automatically fills type_casted_binds from binds if necessary
|
61
61
|
def log(sql, name = "SQL", binds = [], type_casted_binds = [], statement_name = nil, async: false)
|
62
62
|
if binds.any? && (type_casted_binds.nil? || type_casted_binds.empty?)
|
63
|
-
type_casted_binds =
|
63
|
+
type_casted_binds = lambda {
|
64
|
+
# extract_raw_bind_values
|
65
|
+
binds.map do |bind|
|
66
|
+
if bind.respond_to?(:value_for_database)
|
67
|
+
bind.value_for_database
|
68
|
+
else
|
69
|
+
bind
|
70
|
+
end
|
71
|
+
end
|
72
|
+
}
|
64
73
|
end
|
65
74
|
super
|
66
75
|
end
|
@@ -79,7 +79,7 @@ module ArJdbc
|
|
79
79
|
alias :exec_delete :exec_update
|
80
80
|
|
81
81
|
# overridden to support legacy binds
|
82
|
-
def select_all(arel, name = nil, binds = NO_BINDS, preparable: nil, async: false)
|
82
|
+
def select_all(arel, name = nil, binds = NO_BINDS, preparable: nil, async: false, allow_retry: false)
|
83
83
|
binds = convert_legacy_binds_to_attributes(binds) if binds.first.is_a?(Array)
|
84
84
|
super
|
85
85
|
end
|
data/lib/arjdbc/jdbc/adapter.rb
CHANGED
Binary file
|
data/lib/arjdbc/mssql/adapter.rb
CHANGED
@@ -30,6 +30,8 @@ require 'arjdbc/mssql/errors'
|
|
30
30
|
require 'arjdbc/mssql/schema_creation'
|
31
31
|
require 'arjdbc/mssql/database_limits'
|
32
32
|
|
33
|
+
require "arjdbc/mssql/adapter_hash_config"
|
34
|
+
|
33
35
|
require "arjdbc/abstract/relation_query_attribute_monkey_patch"
|
34
36
|
|
35
37
|
module ActiveRecord
|
@@ -44,6 +46,7 @@ module ActiveRecord
|
|
44
46
|
# include ArJdbc::Abstract::DatabaseStatements
|
45
47
|
# include ArJdbc::Abstract::StatementCache
|
46
48
|
include ArJdbc::Abstract::TransactionSupport
|
49
|
+
include ArJdbc::MSSQLConfig
|
47
50
|
|
48
51
|
include MSSQL::Quoting
|
49
52
|
include MSSQL::SchemaStatements
|
@@ -51,6 +54,7 @@ module ActiveRecord
|
|
51
54
|
include MSSQL::ExplainSupport
|
52
55
|
include MSSQL::DatabaseLimits
|
53
56
|
|
57
|
+
# Latin1-General, case-sensitive, accent-sensitive, kanatype-insensitive, width-sensitive
|
54
58
|
@cs_equality_operator = 'COLLATE Latin1_General_CS_AS_WS'
|
55
59
|
|
56
60
|
class << self
|
@@ -81,7 +85,8 @@ module ActiveRecord
|
|
81
85
|
# configure_connection happens in super
|
82
86
|
super
|
83
87
|
|
84
|
-
|
88
|
+
# assign arjdbc extra connection params
|
89
|
+
conn_params = build_connection_config(@config.compact)
|
85
90
|
|
86
91
|
@raw_connection = nil
|
87
92
|
|
@@ -261,29 +266,25 @@ module ActiveRecord
|
|
261
266
|
|
262
267
|
alias_method :current_schema=, :default_schema=
|
263
268
|
|
264
|
-
# FIXME: This needs to be fixed when we implement the collation per
|
265
|
-
|
266
|
-
def default_uniqueness_comparison(attribute, value) # :nodoc:
|
269
|
+
# FIXME: This needs to be fixed when we implement the collation per column
|
270
|
+
def case_sensitive_comparison(attribute, value)
|
267
271
|
column = column_for_attribute(attribute)
|
268
272
|
|
269
|
-
|
270
|
-
|
271
|
-
|
273
|
+
case_sensitive = collation && collation.match(/_CS/)
|
274
|
+
|
275
|
+
if %i[string text].include?(column.type) && !case_sensitive && !value.nil?
|
272
276
|
attribute.eq(Arel::Nodes::Bin.new(value))
|
273
277
|
else
|
274
278
|
super
|
275
279
|
end
|
276
280
|
end
|
277
281
|
|
278
|
-
def
|
279
|
-
|
282
|
+
def can_perform_case_insensitive_comparison_for?(column)
|
283
|
+
case_sensitive = collation && collation.match(/_CS/)
|
280
284
|
|
281
|
-
|
282
|
-
attribute.eq(Arel::Nodes::Bin.new(value))
|
283
|
-
else
|
284
|
-
super
|
285
|
-
end
|
285
|
+
%i[string text].include?(column.type) && !case_sensitive
|
286
286
|
end
|
287
|
+
private :can_perform_case_insensitive_comparison_for?
|
287
288
|
|
288
289
|
def configure_connection
|
289
290
|
# Here goes initial settings per connection
|
@@ -340,7 +341,7 @@ module ActiveRecord
|
|
340
341
|
|
341
342
|
schemas_and_tables.map do |schema_table|
|
342
343
|
schema, table = schema_table
|
343
|
-
"#{
|
344
|
+
"#{self.class.mssql_quote_name_part(schema)}.#{self.class.mssql_quote_name_part(table)}"
|
344
345
|
end
|
345
346
|
end
|
346
347
|
|
@@ -481,6 +482,8 @@ module ActiveRecord
|
|
481
482
|
ConnectionNotEstablished.new(exception)
|
482
483
|
when /(cannot insert duplicate key .* with unique index) | (violation of unique key constraint)/i
|
483
484
|
RecordNotUnique.new(message, sql: sql, binds: binds)
|
485
|
+
when /Violation of PRIMARY KEY constraint .* Cannot insert duplicate key in object .* The duplicate key value is/i
|
486
|
+
RecordNotUnique.new(message, sql: sql, binds: binds)
|
484
487
|
when /Lock request time out period exceeded/i
|
485
488
|
LockTimeout.new(message, sql: sql, binds: binds)
|
486
489
|
when /The .* statement conflicted with the FOREIGN KEY constraint/
|
@@ -0,0 +1,53 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module ArJdbc
|
4
|
+
module MSSQLConfig
|
5
|
+
def build_connection_config(config)
|
6
|
+
config = config.deep_dup
|
7
|
+
|
8
|
+
load_jdbc_driver
|
9
|
+
|
10
|
+
config[:driver] ||= database_driver_name
|
11
|
+
|
12
|
+
config[:host] ||= "localhost"
|
13
|
+
config[:connection_alive_sql] ||= "SELECT 1"
|
14
|
+
config[:lock_timeout] ||= 5000
|
15
|
+
|
16
|
+
config[:url] ||= build_connection_url(config)
|
17
|
+
|
18
|
+
config
|
19
|
+
end
|
20
|
+
|
21
|
+
private
|
22
|
+
|
23
|
+
def load_jdbc_driver
|
24
|
+
require "jdbc/mssql"
|
25
|
+
|
26
|
+
::Jdbc::Mssql.load_driver if defined?(::Jdbc::Mssql.load_driver)
|
27
|
+
rescue LoadError
|
28
|
+
# assuming driver.jar is on the class-path
|
29
|
+
end
|
30
|
+
|
31
|
+
def database_driver_name
|
32
|
+
"com.microsoft.sqlserver.jdbc.SQLServerDriver"
|
33
|
+
end
|
34
|
+
|
35
|
+
def build_connection_url(config)
|
36
|
+
url = "".dup
|
37
|
+
url << "jdbc:sqlserver://#{config[:host]}"
|
38
|
+
url << ( config[:port] ? ":#{config[:port]};" : ';' )
|
39
|
+
url << "databaseName=#{config[:database]};" if config[:database]
|
40
|
+
url << "instanceName=#{config[:instance]};" if config[:instance]
|
41
|
+
url << "sendTimeAsDatetime=#{config[:send_time_as_datetime] || false};"
|
42
|
+
url << "loginTimeout=#{config[:login_timeout].to_i};" if config[:login_timeout]
|
43
|
+
url << "lockTimeout=#{config[:lock_timeout].to_i};"
|
44
|
+
url << "encrypt=#{config[:encrypt]};" if config.key?(:encrypt)
|
45
|
+
url << "trustServerCertificate=#{config[:trust_server_certificate]};" if config.key?(:trust_server_certificate)
|
46
|
+
app = config[:application_name] || config[:appname] || config[:application]
|
47
|
+
url << "applicationName=#{app};" if app
|
48
|
+
isc = config[:integrated_security] # Win only - needs sqljdbc_auth.dll
|
49
|
+
url << "integratedSecurity=#{isc};" unless isc.nil?
|
50
|
+
url
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
data/lib/arjdbc/mssql/column.rb
CHANGED
@@ -9,17 +9,26 @@ module ActiveRecord
|
|
9
9
|
def initialize(name, raw_default, sql_type_metadata = nil, null = true, table_name = nil, default_function = nil, collation = nil, comment: nil)
|
10
10
|
@table_name = table_name
|
11
11
|
|
12
|
-
|
12
|
+
default_val, default_fun = extract_default(raw_default)
|
13
13
|
|
14
|
-
super(name,
|
14
|
+
super(name, default_val, sql_type_metadata, null, default_fun, collation: collation, comment: comment)
|
15
15
|
end
|
16
16
|
|
17
17
|
def extract_default(value)
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
18
|
+
return [nil, nil] unless value
|
19
|
+
|
20
|
+
case value
|
21
|
+
when /\A\(N?'(.*)'\)\Z/m
|
22
|
+
[unquote_string(Regexp.last_match[1]), nil]
|
23
|
+
when /\A\(\((.*)\)\)\Z/
|
24
|
+
[unquote_string(Regexp.last_match[1]), nil]
|
25
|
+
when /\A\((\w+\(\))\)\Z/
|
26
|
+
[nil, unquote_string(Regexp.last_match[1])]
|
27
|
+
else
|
28
|
+
# return nil if default does not match the patterns to avoid
|
29
|
+
# any unexpected errors.
|
30
|
+
[nil, nil]
|
31
|
+
end
|
23
32
|
end
|
24
33
|
|
25
34
|
def unquote_string(string)
|
@@ -31,6 +31,8 @@ module ActiveRecord
|
|
31
31
|
|
32
32
|
def write_query?(sql) # :nodoc:
|
33
33
|
!READ_QUERY.match?(sql)
|
34
|
+
rescue ArgumentError # Invalid encoding
|
35
|
+
!READ_QUERY.match?(sql.b)
|
34
36
|
end
|
35
37
|
|
36
38
|
# Internal method to test different isolation levels supported by this
|
@@ -90,7 +92,7 @@ module ActiveRecord
|
|
90
92
|
end
|
91
93
|
end
|
92
94
|
|
93
|
-
def internal_exec_query(sql, name = 'SQL', binds = [], prepare: false, async: false)
|
95
|
+
def internal_exec_query(sql, name = 'SQL', binds = [], prepare: false, async: false, allow_retry: false)
|
94
96
|
sql = transform_query(sql)
|
95
97
|
|
96
98
|
check_if_write_query(sql)
|
@@ -176,6 +178,9 @@ module ActiveRecord
|
|
176
178
|
log(sql, name, binds) do
|
177
179
|
with_raw_connection do |conn|
|
178
180
|
result = conditional_indentity_insert(sql) do
|
181
|
+
# DEPRECATION WARNING: to_time will always preserve the timezone offset of the receiver in Rails 8.0.
|
182
|
+
# To opt in to the new behavior, set `ActiveSupport.to_time_preserves_timezone = true`.
|
183
|
+
# (called from block in execute_insert_pk
|
179
184
|
conn.execute_insert_pk(sql, binds, pk)
|
180
185
|
end
|
181
186
|
verified!
|
@@ -244,7 +249,7 @@ module ActiveRecord
|
|
244
249
|
end
|
245
250
|
|
246
251
|
def raw_jdbc_connection
|
247
|
-
|
252
|
+
any_raw_connection
|
248
253
|
end
|
249
254
|
|
250
255
|
# It seems the truncate_tables is mostly used for testing
|
data/lib/arjdbc/mssql/quoting.rb
CHANGED
@@ -4,6 +4,62 @@ module ActiveRecord
|
|
4
4
|
module ConnectionAdapters
|
5
5
|
module MSSQL
|
6
6
|
module Quoting
|
7
|
+
extend ActiveSupport::Concern
|
8
|
+
|
9
|
+
QUOTED_COLUMN_NAMES = Concurrent::Map.new # :nodoc:
|
10
|
+
QUOTED_TABLE_NAMES = Concurrent::Map.new # :nodoc:
|
11
|
+
|
12
|
+
module ClassMethods # :nodoc:
|
13
|
+
def column_name_matcher
|
14
|
+
/
|
15
|
+
\A
|
16
|
+
(
|
17
|
+
(?:
|
18
|
+
# \[table_name\].\[column_name\] | function(one or no argument)
|
19
|
+
((?:\w+\.|\[\w+\]\.)?(?:\w+|\[\w+\])) | \w+\((?:|\g<2>)\)
|
20
|
+
)
|
21
|
+
(?:\s+AS\s+(?:\w+|\[\w+\]))?
|
22
|
+
)
|
23
|
+
(?:\s*,\s*\g<1>)*
|
24
|
+
\z
|
25
|
+
/ix
|
26
|
+
end
|
27
|
+
|
28
|
+
def column_name_with_order_matcher
|
29
|
+
/
|
30
|
+
\A
|
31
|
+
(
|
32
|
+
(?:
|
33
|
+
# \[table_name\].\[column_name\] | function(one or no argument)
|
34
|
+
((?:\w+\.|\[\w+\]\.)?(?:\w+|\[\w+\])) | \w+\((?:|\g<2>)\)
|
35
|
+
)
|
36
|
+
(?:\s+ASC|\s+DESC)?
|
37
|
+
)
|
38
|
+
(?:\s*,\s*\g<1>)*
|
39
|
+
\z
|
40
|
+
/ix
|
41
|
+
end
|
42
|
+
|
43
|
+
def quote_column_name(name)
|
44
|
+
QUOTED_COLUMN_NAMES[name] ||= mssql_quote_column_name(name)
|
45
|
+
end
|
46
|
+
|
47
|
+
def quote_table_name(name)
|
48
|
+
QUOTED_TABLE_NAMES[name] ||= mssql_quote_column_name(name)
|
49
|
+
end
|
50
|
+
|
51
|
+
def mssql_quote_column_name(name)
|
52
|
+
name = name.to_s.split(".")
|
53
|
+
name.map! { |n| mssql_quote_name_part(n) } # "[#{name}]"
|
54
|
+
name.join(".")
|
55
|
+
end
|
56
|
+
|
57
|
+
# Implements the quoting style for SQL Server
|
58
|
+
def mssql_quote_name_part(part)
|
59
|
+
part =~ /^\[.*\]$/ ? part : "[#{part.gsub(']', ']]')}]"
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
7
63
|
QUOTED_TRUE = '1'
|
8
64
|
QUOTED_FALSE = '0'
|
9
65
|
|
@@ -88,42 +144,6 @@ module ActiveRecord
|
|
88
144
|
# @see #quote in old adapter
|
89
145
|
BLOB_VALUE_MARKER = "''"
|
90
146
|
|
91
|
-
def column_name_matcher
|
92
|
-
COLUMN_NAME
|
93
|
-
end
|
94
|
-
|
95
|
-
def column_name_with_order_matcher
|
96
|
-
COLUMN_NAME_WITH_ORDER
|
97
|
-
end
|
98
|
-
|
99
|
-
COLUMN_NAME = /
|
100
|
-
\A
|
101
|
-
(
|
102
|
-
(?:
|
103
|
-
# \[table_name\].\[column_name\] | function(one or no argument)
|
104
|
-
((?:\w+\.|\[\w+\]\.)?(?:\w+|\[\w+\])) | \w+\((?:|\g<2>)\)
|
105
|
-
)
|
106
|
-
(?:\s+AS\s+(?:\w+|\[\w+\]))?
|
107
|
-
)
|
108
|
-
(?:\s*,\s*\g<1>)*
|
109
|
-
\z
|
110
|
-
/ix
|
111
|
-
|
112
|
-
COLUMN_NAME_WITH_ORDER = /
|
113
|
-
\A
|
114
|
-
(
|
115
|
-
(?:
|
116
|
-
# \[table_name\].\[column_name\] | function(one or no argument)
|
117
|
-
((?:\w+\.|\[\w+\]\.)?(?:\w+|\[\w+\])) | \w+\((?:|\g<2>)\)
|
118
|
-
)
|
119
|
-
(?:\s+ASC|\s+DESC)?
|
120
|
-
)
|
121
|
-
(?:\s*,\s*\g<1>)*
|
122
|
-
\z
|
123
|
-
/ix
|
124
|
-
|
125
|
-
private_constant :COLUMN_NAME, :COLUMN_NAME_WITH_ORDER
|
126
|
-
|
127
147
|
private
|
128
148
|
|
129
149
|
def time_with_db_timezone(value)
|
@@ -38,6 +38,22 @@ module ActiveRecord
|
|
38
38
|
end
|
39
39
|
end
|
40
40
|
|
41
|
+
def visit_CreateIndexDefinition(o)
|
42
|
+
index = o.index
|
43
|
+
|
44
|
+
sql = []
|
45
|
+
sql << "IF NOT EXISTS (SELECT name FROM sysindexes WHERE name = '#{o.index.name}')" if o.if_not_exists
|
46
|
+
sql << "CREATE"
|
47
|
+
sql << "UNIQUE" if index.unique
|
48
|
+
sql << index.type.upcase if index.type
|
49
|
+
sql << "INDEX"
|
50
|
+
sql << "#{quote_column_name(index.name)} ON #{quote_table_name(index.table)}"
|
51
|
+
sql << "(#{quoted_columns(index)})"
|
52
|
+
sql << "WHERE #{index.where}" if index.where
|
53
|
+
|
54
|
+
sql.join(" ")
|
55
|
+
end
|
56
|
+
|
41
57
|
def add_column_options!(sql, options)
|
42
58
|
sql << " DEFAULT #{quote_default_expression(options[:default], options[:column])}" if options_include_default?(options)
|
43
59
|
|
@@ -80,8 +80,50 @@ module ActiveRecord
|
|
80
80
|
valid_raw_connection.primary_keys(table_name)
|
81
81
|
end
|
82
82
|
|
83
|
+
def build_change_column_definition(table_name, column_name, type, **options) # :nodoc:
|
84
|
+
td = create_table_definition(table_name)
|
85
|
+
cd = td.new_column_definition(column_name, type, **options)
|
86
|
+
ChangeColumnDefinition.new(cd, column_name)
|
87
|
+
end
|
88
|
+
|
89
|
+
def build_change_column_default_definition(table_name, column_name, default_or_changes) # :nodoc:
|
90
|
+
column = column_for(table_name, column_name)
|
91
|
+
return unless column
|
92
|
+
|
93
|
+
default = extract_new_default_value(default_or_changes)
|
94
|
+
ChangeColumnDefaultDefinition.new(column, default)
|
95
|
+
end
|
96
|
+
|
83
97
|
def foreign_keys(table_name)
|
84
|
-
valid_raw_connection.foreign_keys(table_name)
|
98
|
+
# valid_raw_connection.foreign_keys(table_name)
|
99
|
+
fk_info = execute_procedure(:sp_fkeys, nil, nil, nil, table_name, nil)
|
100
|
+
|
101
|
+
grouped_fk = fk_info.group_by { |row| row["FK_NAME"] }.values.each { |group| group.sort_by! { |row| row["KEY_SEQ"] } }
|
102
|
+
grouped_fk.map do |group|
|
103
|
+
row = group.first
|
104
|
+
options = {
|
105
|
+
name: row["FK_NAME"],
|
106
|
+
on_update: extract_foreign_key_action("update", row["FK_NAME"]),
|
107
|
+
on_delete: extract_foreign_key_action("delete", row["FK_NAME"])
|
108
|
+
}
|
109
|
+
|
110
|
+
if group.one?
|
111
|
+
options[:column] = row["FKCOLUMN_NAME"]
|
112
|
+
options[:primary_key] = row["PKCOLUMN_NAME"]
|
113
|
+
else
|
114
|
+
options[:column] = group.map { |row| row["FKCOLUMN_NAME"] }
|
115
|
+
options[:primary_key] = group.map { |row| row["PKCOLUMN_NAME"] }
|
116
|
+
end
|
117
|
+
|
118
|
+
ForeignKeyDefinition.new(table_name, row["PKTABLE_NAME"], options)
|
119
|
+
end
|
120
|
+
end
|
121
|
+
|
122
|
+
def extract_foreign_key_action(action, fk_name)
|
123
|
+
case select_value("SELECT #{action}_referential_action_desc FROM sys.foreign_keys WHERE name = '#{fk_name}'")
|
124
|
+
when "CASCADE" then :cascade
|
125
|
+
when "SET_NULL" then :nullify
|
126
|
+
end
|
85
127
|
end
|
86
128
|
|
87
129
|
def charset
|
@@ -182,20 +224,8 @@ module ActiveRecord
|
|
182
224
|
rename_table_indexes(table_name, new_name)
|
183
225
|
end
|
184
226
|
|
185
|
-
# This is the same as the abstract method
|
186
|
-
def quote_table_name(name)
|
187
|
-
quote_column_name(name)
|
188
|
-
end
|
189
|
-
|
190
|
-
# This overrides the abstract method to be specific to SQL Server.
|
191
|
-
def quote_column_name(name)
|
192
|
-
name = name.to_s.split('.')
|
193
|
-
name.map! { |n| quote_name_part(n) } # "[#{name}]"
|
194
|
-
name.join('.')
|
195
|
-
end
|
196
|
-
|
197
227
|
def quote_database_name(name)
|
198
|
-
|
228
|
+
self.class.mssql_quote_name_part(name.to_s)
|
199
229
|
end
|
200
230
|
|
201
231
|
# @private these cannot specify a limit
|
@@ -439,11 +469,6 @@ module ActiveRecord
|
|
439
469
|
result
|
440
470
|
end
|
441
471
|
|
442
|
-
# Implements the quoting style for SQL Server
|
443
|
-
def quote_name_part(part)
|
444
|
-
part =~ /^\[.*\]$/ ? part : "[#{part.gsub(']', ']]')}]"
|
445
|
-
end
|
446
|
-
|
447
472
|
def remove_check_constraints(table_name, column_name)
|
448
473
|
constraints = select_values "SELECT CONSTRAINT_NAME FROM INFORMATION_SCHEMA.CONSTRAINT_COLUMN_USAGE where TABLE_NAME = '#{quote_string(table_name)}' and COLUMN_NAME = '#{quote_string(column_name)}'", 'SCHEMA'
|
449
474
|
constraints.each do |constraint|
|
data/lib/arjdbc/mssql.rb
CHANGED
data/lib/arjdbc/mysql/adapter.rb
CHANGED
@@ -11,6 +11,8 @@ require 'arjdbc/abstract/database_statements'
|
|
11
11
|
require 'arjdbc/abstract/statement_cache'
|
12
12
|
require 'arjdbc/abstract/transaction_support'
|
13
13
|
|
14
|
+
require "arjdbc/mysql/adapter_hash_config"
|
15
|
+
|
14
16
|
require "arjdbc/abstract/relation_query_attribute_monkey_patch"
|
15
17
|
|
16
18
|
module ActiveRecord
|
@@ -34,6 +36,7 @@ module ActiveRecord
|
|
34
36
|
include ArJdbc::Abstract::TransactionSupport
|
35
37
|
|
36
38
|
include ArJdbc::MySQL
|
39
|
+
include ArJdbc::MysqlConfig
|
37
40
|
|
38
41
|
class << self
|
39
42
|
def jdbc_connection_class
|
@@ -68,6 +71,9 @@ module ActiveRecord
|
|
68
71
|
|
69
72
|
@config[:flags] ||= 0
|
70
73
|
|
74
|
+
# assign arjdbc extra connection params
|
75
|
+
conn_params = build_connection_config(@config.compact)
|
76
|
+
|
71
77
|
# JDBC mysql appears to use found rows by default: https://dev.mysql.com/doc/connector-j/en/connector-j-connp-props-connection.html
|
72
78
|
# if @config[:flags].kind_of? Array
|
73
79
|
# @config[:flags].push "FOUND_ROWS"
|
@@ -75,16 +81,7 @@ module ActiveRecord
|
|
75
81
|
# @config[:flags] |= ::Mysql2::Client::FOUND_ROWS
|
76
82
|
# end
|
77
83
|
|
78
|
-
@connection_parameters
|
79
|
-
end
|
80
|
-
|
81
|
-
def self.database_exists?(config)
|
82
|
-
conn = ActiveRecord::Base.mysql2_connection(config)
|
83
|
-
conn && conn.really_valid?
|
84
|
-
rescue ActiveRecord::NoDatabaseError
|
85
|
-
false
|
86
|
-
ensure
|
87
|
-
conn.disconnect! if conn
|
84
|
+
@connection_parameters = conn_params
|
88
85
|
end
|
89
86
|
|
90
87
|
def supports_json?
|
@@ -244,7 +241,7 @@ module ActiveRecord
|
|
244
241
|
|
245
242
|
# e.g. "5.7.20-0ubuntu0.16.04.1"
|
246
243
|
def full_version
|
247
|
-
|
244
|
+
database_version.full_version_string
|
248
245
|
end
|
249
246
|
|
250
247
|
def get_full_version
|