activerecord-jdbc-alt-adapter 51.7.0-java → 52.2.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 +2 -3
- data/README.md +27 -19
- data/Rakefile +4 -30
- data/activerecord-jdbc-adapter.gemspec +2 -2
- data/activerecord-jdbc-alt-adapter.gemspec +4 -4
- data/lib/arel/visitors/sqlserver.rb +2 -1
- data/lib/arjdbc/abstract/core.rb +12 -2
- data/lib/arjdbc/abstract/database_statements.rb +22 -8
- data/lib/arjdbc/abstract/statement_cache.rb +1 -0
- data/lib/arjdbc/db2/adapter.rb +77 -8
- data/lib/arjdbc/db2/as400.rb +12 -0
- data/lib/arjdbc/db2/column.rb +3 -0
- data/lib/arjdbc/db2/connection_methods.rb +4 -0
- data/lib/arjdbc/jdbc/adapter.rb +4 -6
- data/lib/arjdbc/jdbc/adapter_java.jar +0 -0
- data/lib/arjdbc/jdbc/column.rb +14 -6
- data/lib/arjdbc/jdbc.rb +7 -0
- data/lib/arjdbc/mssql/adapter.rb +20 -32
- data/lib/arjdbc/mssql/connection_methods.rb +1 -5
- data/lib/arjdbc/mssql/database_limits.rb +29 -0
- data/lib/arjdbc/mssql/database_statements.rb +41 -1
- data/lib/arjdbc/mssql/explain_support.rb +6 -1
- data/lib/arjdbc/mssql/quoting.rb +9 -2
- data/lib/arjdbc/mssql/schema_creation.rb +2 -1
- data/lib/arjdbc/mssql/schema_dumper.rb +1 -1
- data/lib/arjdbc/mssql/schema_statements.rb +11 -3
- data/lib/arjdbc/mssql/transaction.rb +3 -3
- data/lib/arjdbc/mssql.rb +1 -1
- data/lib/arjdbc/mysql/adapter.rb +20 -4
- data/lib/arjdbc/mysql/connection_methods.rb +7 -13
- data/lib/arjdbc/postgresql/adapter.rb +23 -20
- data/lib/arjdbc/postgresql/column.rb +3 -6
- data/lib/arjdbc/postgresql/connection_methods.rb +1 -3
- data/lib/arjdbc/postgresql/oid_types.rb +6 -11
- data/lib/arjdbc/sqlite3/adapter.rb +86 -91
- data/lib/arjdbc/sqlite3/connection_methods.rb +0 -1
- data/lib/arjdbc/tasks/database_tasks.rb +1 -0
- data/lib/arjdbc/tasks/sqlite_database_tasks_patch.rb +17 -0
- 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 +10 -65
- data/src/java/arjdbc/mssql/MSSQLRubyJdbcConnection.java +38 -282
- data/src/java/arjdbc/postgresql/PostgreSQLResult.java +69 -4
- data/src/java/arjdbc/postgresql/PostgreSQLRubyJdbcConnection.java +69 -13
- data/src/java/arjdbc/util/DateTimeUtils.java +17 -28
- data/src/java/arjdbc/util/PG.java +8 -0
- metadata +15 -12
- data/lib/activerecord-jdbc-alt-adapter.rb +0 -1
data/lib/arjdbc/jdbc/column.rb
CHANGED
@@ -26,12 +26,20 @@ module ActiveRecord
|
|
26
26
|
end
|
27
27
|
end
|
28
28
|
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
29
|
+
if ArJdbc::AR52
|
30
|
+
# undefined method `cast' for #<ActiveRecord::ConnectionAdapters::SqlTypeMetadata> on AR52
|
31
|
+
elsif ArJdbc::AR50
|
32
|
+
default = args[0].cast(default)
|
33
|
+
|
34
|
+
sql_type = args.delete_at(1)
|
35
|
+
type = args.delete_at(0)
|
36
|
+
|
37
|
+
args.unshift(SqlTypeMetadata.new(:sql_type => sql_type, :type => type))
|
38
|
+
elsif ArJdbc::AR42
|
39
|
+
default = args[0].type_cast_from_database(default)
|
40
|
+
else
|
41
|
+
default = default_value(default)
|
42
|
+
end
|
35
43
|
|
36
44
|
# super <= 4.1: (name, default, sql_type = nil, null = true)
|
37
45
|
# super >= 4.2: (name, default, cast_type, sql_type = nil, null = true)
|
data/lib/arjdbc/jdbc.rb
CHANGED
@@ -2,8 +2,15 @@ require 'active_support/deprecation'
|
|
2
2
|
|
3
3
|
module ArJdbc
|
4
4
|
|
5
|
+
# @private
|
6
|
+
AR40 = ::ActiveRecord::VERSION::MAJOR > 3
|
5
7
|
# @private
|
6
8
|
AR42 = ::ActiveRecord::VERSION::STRING >= '4.2'
|
9
|
+
# @private
|
10
|
+
AR50 = ::ActiveRecord::VERSION::MAJOR > 4
|
11
|
+
|
12
|
+
# @private
|
13
|
+
AR52 = ::ActiveRecord::VERSION::STRING >= '5.2'
|
7
14
|
|
8
15
|
class << self
|
9
16
|
|
data/lib/arjdbc/mssql/adapter.rb
CHANGED
@@ -3,7 +3,6 @@
|
|
3
3
|
ArJdbc.load_java_part :MSSQL
|
4
4
|
|
5
5
|
require 'arel'
|
6
|
-
require 'arel/visitors/bind_visitor'
|
7
6
|
require 'arel/visitors/sqlserver'
|
8
7
|
require 'active_record/connection_adapters/abstract_adapter'
|
9
8
|
|
@@ -27,6 +26,7 @@ require 'arjdbc/mssql/explain_support'
|
|
27
26
|
require 'arjdbc/mssql/transaction'
|
28
27
|
require 'arjdbc/mssql/errors'
|
29
28
|
require 'arjdbc/mssql/schema_creation'
|
29
|
+
require 'arjdbc/mssql/database_limits'
|
30
30
|
|
31
31
|
module ActiveRecord
|
32
32
|
module ConnectionAdapters
|
@@ -54,9 +54,9 @@ module ActiveRecord
|
|
54
54
|
|
55
55
|
include MSSQL::Quoting
|
56
56
|
include MSSQL::SchemaStatements
|
57
|
-
include MSSQL::ColumnDumper
|
58
57
|
include MSSQL::DatabaseStatements
|
59
58
|
include MSSQL::ExplainSupport
|
59
|
+
include MSSQL::DatabaseLimits
|
60
60
|
|
61
61
|
@cs_equality_operator = 'COLLATE Latin1_General_CS_AS_WS'
|
62
62
|
|
@@ -85,12 +85,6 @@ module ActiveRecord
|
|
85
85
|
::ActiveRecord::ConnectionAdapters::MSSQLColumn
|
86
86
|
end
|
87
87
|
|
88
|
-
# Does this adapter support DDL rollbacks in transactions? That is, would
|
89
|
-
# CREATE TABLE or ALTER TABLE get rolled back by a transaction?
|
90
|
-
def supports_ddl_transactions?
|
91
|
-
true
|
92
|
-
end
|
93
|
-
|
94
88
|
# Does this adapter support creating foreign key constraints?
|
95
89
|
def supports_foreign_keys?
|
96
90
|
true
|
@@ -106,16 +100,6 @@ module ActiveRecord
|
|
106
100
|
true
|
107
101
|
end
|
108
102
|
|
109
|
-
# Does this adapter support index sort order?
|
110
|
-
def supports_index_sort_order?
|
111
|
-
true
|
112
|
-
end
|
113
|
-
|
114
|
-
# Also known as filtered index
|
115
|
-
def supports_partial_index?
|
116
|
-
true
|
117
|
-
end
|
118
|
-
|
119
103
|
# Does this adapter support views?
|
120
104
|
def supports_views?
|
121
105
|
true
|
@@ -132,13 +116,6 @@ module ActiveRecord
|
|
132
116
|
super
|
133
117
|
end
|
134
118
|
|
135
|
-
def reset!
|
136
|
-
# execute 'IF @@TRANCOUNT > 0 ROLLBACK TRANSACTION'
|
137
|
-
# NOTE: it seems the above line interferes with the jdbc driver
|
138
|
-
# and ending up in connection closed, issue seen in rails 5.2 and 6.0
|
139
|
-
reconnect!
|
140
|
-
end
|
141
|
-
|
142
119
|
def disable_referential_integrity
|
143
120
|
tables = tables_with_referential_integrity
|
144
121
|
|
@@ -213,23 +190,31 @@ module ActiveRecord
|
|
213
190
|
# get the collation per column basis. At the moment we only use
|
214
191
|
# the global database collation
|
215
192
|
def case_sensitive_comparison(table, attribute, column, value)
|
216
|
-
if
|
217
|
-
table[attribute].eq(value)
|
218
|
-
elsif [:string, :text].include?(column.type) && collation && !collation.match(/_CS/)
|
219
|
-
table[attribute].eq(Arel::Nodes::Bin.new(Arel::Nodes::BindParam.new))
|
193
|
+
if [:string, :text].include?(column.type) && collation && !collation.match(/_CS/)
|
194
|
+
table[attribute].eq(Arel::Nodes::Bin.new(value))
|
220
195
|
# elsif value.acts_like?(:string)
|
221
196
|
# table[attribute].eq(Arel::Nodes::Bin.new(Arel::Nodes::BindParam.new))
|
222
197
|
else
|
223
|
-
|
198
|
+
super
|
224
199
|
end
|
225
200
|
end
|
226
201
|
|
227
202
|
def configure_connection
|
228
|
-
|
203
|
+
execute("SET LOCK_TIMEOUT #{lock_timeout}")
|
229
204
|
|
230
205
|
set_session_transaction_isolation
|
231
206
|
end
|
232
207
|
|
208
|
+
def lock_timeout
|
209
|
+
timeout = config[:lock_timeout].to_i
|
210
|
+
|
211
|
+
if timeout.positive?
|
212
|
+
timeout
|
213
|
+
else
|
214
|
+
5_000
|
215
|
+
end
|
216
|
+
end
|
217
|
+
|
233
218
|
def set_session_transaction_isolation
|
234
219
|
isolation_level = config[:transaction_isolation]
|
235
220
|
|
@@ -290,7 +275,7 @@ module ActiveRecord
|
|
290
275
|
# This method is called indirectly by the abstract method
|
291
276
|
# 'fetch_type_metadata' which then it is called by the java part when
|
292
277
|
# calculating a table's columns.
|
293
|
-
def initialize_type_map(map)
|
278
|
+
def initialize_type_map(map = type_map)
|
294
279
|
# Build the type mapping from SQL Server to ActiveRecord
|
295
280
|
|
296
281
|
# Integer types.
|
@@ -359,6 +344,9 @@ module ActiveRecord
|
|
359
344
|
register_class_with_precision map, %r{\Adatetime2\(\d+\)}i, MSSQL::Type::DateTime2
|
360
345
|
map.register_type 'datetime2(7)', MSSQL::Type::DateTime2.new
|
361
346
|
|
347
|
+
# TODO: we should have identity separated from the sql_type
|
348
|
+
# let's say in another attribute (this will help to pass more AR tests),
|
349
|
+
# also we add collation attribute per column.
|
362
350
|
# aliases
|
363
351
|
map.alias_type 'int identity', 'int'
|
364
352
|
map.alias_type 'bigint identity', 'bigint'
|
@@ -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,13 @@ 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 << "
|
73
|
-
url << "lockTimeout=#{config[:lock_timeout].to_i};"
|
69
|
+
url << "sendTimeAsDatetime=#{config[:send_time_as_datetime] || false};"
|
74
70
|
app = config[:appname] || config[:application]
|
75
71
|
url << "applicationName=#{app};" if app
|
76
72
|
isc = config[:integrated_security] # Win only - needs sqljdbc_auth.dll
|
@@ -0,0 +1,29 @@
|
|
1
|
+
module ActiveRecord
|
2
|
+
module ConnectionAdapters
|
3
|
+
module MSSQL
|
4
|
+
module DatabaseLimits
|
5
|
+
|
6
|
+
# Returns the maximum number of elements in an IN (x,y,z) clause.
|
7
|
+
# NOTE: Could not find a limit for IN in mssql but 10000 seems to work
|
8
|
+
# with the active record tests
|
9
|
+
def in_clause_length
|
10
|
+
10_000
|
11
|
+
end
|
12
|
+
|
13
|
+
private
|
14
|
+
|
15
|
+
# the max bind params is 2100 but it seems
|
16
|
+
# the jdbc uses 2 for something
|
17
|
+
def bind_params_length
|
18
|
+
2_098
|
19
|
+
end
|
20
|
+
|
21
|
+
# max number of insert rows in mssql
|
22
|
+
def insert_rows_length
|
23
|
+
1_000
|
24
|
+
end
|
25
|
+
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -71,8 +71,48 @@ module ActiveRecord
|
|
71
71
|
@connection.get_transaction_isolation
|
72
72
|
end
|
73
73
|
|
74
|
+
def insert_fixtures_set(fixture_set, tables_to_delete = [])
|
75
|
+
fixture_inserts = []
|
76
|
+
|
77
|
+
fixture_set.each do |table_name, fixtures|
|
78
|
+
fixtures.each_slice(insert_rows_length) do |batch|
|
79
|
+
fixture_inserts << build_fixture_sql(batch, table_name)
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
table_deletes = tables_to_delete.map do |table|
|
84
|
+
"DELETE FROM #{quote_table_name(table)}".dup
|
85
|
+
end
|
86
|
+
total_sql = Array.wrap(combine_multi_statements(table_deletes + fixture_inserts))
|
87
|
+
|
88
|
+
disable_referential_integrity do
|
89
|
+
transaction(requires_new: true) do
|
90
|
+
total_sql.each do |sql|
|
91
|
+
execute sql, 'Fixtures Load'
|
92
|
+
yield if block_given?
|
93
|
+
end
|
94
|
+
end
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
74
98
|
private
|
75
99
|
|
100
|
+
# Overrides method in abstract class, combining the sqls with semicolon
|
101
|
+
# affects disable_referential_integrity in mssql specially when multiple
|
102
|
+
# tables are involved.
|
103
|
+
def combine_multi_statements(total_sql)
|
104
|
+
total_sql
|
105
|
+
end
|
106
|
+
|
107
|
+
def default_insert_value(column)
|
108
|
+
if column.identity?
|
109
|
+
table_name = quote(quote_table_name(column.table_name))
|
110
|
+
Arel.sql("IDENT_CURRENT(#{table_name}) + IDENT_INCR(#{table_name})")
|
111
|
+
else
|
112
|
+
super
|
113
|
+
end
|
114
|
+
end
|
115
|
+
|
76
116
|
def insert_sql?(sql)
|
77
117
|
!(sql =~ /^\s*(INSERT|EXEC sp_executesql N'INSERT)/i).nil?
|
78
118
|
end
|
@@ -87,7 +127,7 @@ module ActiveRecord
|
|
87
127
|
end
|
88
128
|
|
89
129
|
def identity_column_name(table_name)
|
90
|
-
for column in
|
130
|
+
for column in columns(table_name)
|
91
131
|
return column.name if column.identity?
|
92
132
|
end
|
93
133
|
nil
|
@@ -18,9 +18,14 @@ module ActiveRecord
|
|
18
18
|
def explain(arel, binds = [])
|
19
19
|
return if DISABLED
|
20
20
|
|
21
|
+
if arel.respond_to?(:to_sql)
|
22
|
+
raw_sql, raw_binds = to_sql_and_binds(arel, binds)
|
23
|
+
else
|
24
|
+
raw_sql, raw_binds = arel, binds
|
25
|
+
end
|
21
26
|
# sql = to_sql(arel, binds)
|
22
27
|
# result = with_showplan_on { exec_query(sql, 'EXPLAIN', binds) }
|
23
|
-
sql = interpolate_sql_statement(
|
28
|
+
sql = interpolate_sql_statement(raw_sql, raw_binds)
|
24
29
|
result = with_showplan_on do
|
25
30
|
exec_query(sql, 'EXPLAIN', [])
|
26
31
|
end
|
data/lib/arjdbc/mssql/quoting.rb
CHANGED
@@ -2,6 +2,9 @@ module ActiveRecord
|
|
2
2
|
module ConnectionAdapters
|
3
3
|
module MSSQL
|
4
4
|
module Quoting
|
5
|
+
QUOTED_TRUE = '1'.freeze
|
6
|
+
QUOTED_FALSE = '0'.freeze
|
7
|
+
|
5
8
|
# Quote date/time values for use in SQL input, includes microseconds
|
6
9
|
# with three digits only if the value is a Time responding to usec.
|
7
10
|
# The JDBC drivers does not work with 6 digits microseconds
|
@@ -29,17 +32,21 @@ module ActiveRecord
|
|
29
32
|
cast_type = lookup_cast_type(column.sql_type)
|
30
33
|
if cast_type.type == :uuid && value =~ /\(\)/
|
31
34
|
value
|
35
|
+
elsif column.type == :datetime_basic && value.is_a?(String)
|
36
|
+
# let's trust the user to set a right default value for this
|
37
|
+
# legacy type something like: '2017-02-28 01:59:19.789'
|
38
|
+
quote(value)
|
32
39
|
else
|
33
40
|
super
|
34
41
|
end
|
35
42
|
end
|
36
43
|
|
37
44
|
def quoted_true
|
38
|
-
|
45
|
+
QUOTED_TRUE
|
39
46
|
end
|
40
47
|
|
41
48
|
def quoted_false
|
42
|
-
|
49
|
+
QUOTED_FALSE
|
43
50
|
end
|
44
51
|
|
45
52
|
# @override
|
@@ -7,7 +7,8 @@ module ActiveRecord
|
|
7
7
|
def visit_TableDefinition(o)
|
8
8
|
if o.as
|
9
9
|
table_name = quote_table_name(o.temporary ? "##{o.name}" : o.name)
|
10
|
-
|
10
|
+
query = o.as.respond_to?(:to_sql) ? o.as.to_sql : o.as
|
11
|
+
projections, source = query.match(%r{SELECT\s+(.*)?\s+FROM\s+(.*)?}).captures
|
11
12
|
select_into = "SELECT #{projections} INTO #{table_name} FROM #{source}"
|
12
13
|
else
|
13
14
|
o.instance_variable_set :@as, nil
|
@@ -46,9 +46,13 @@ module ActiveRecord
|
|
46
46
|
# NOTE: This is ready, all implemented in the java part of adapter,
|
47
47
|
# it uses MSSQLColumn, SqlTypeMetadata, etc.
|
48
48
|
def columns(table_name)
|
49
|
-
|
49
|
+
@connection.columns(table_name)
|
50
50
|
rescue => e
|
51
|
-
raise translate_exception_class(e, nil)
|
51
|
+
# raise translate_exception_class(e, nil)
|
52
|
+
# FIXME: this breaks one arjdbc test but fixes activerecord tests
|
53
|
+
# (table name alias). Also it behaves similarly to the CRuby adapter
|
54
|
+
# which returns an empty array too. (postgres throws a exception)
|
55
|
+
[]
|
52
56
|
end
|
53
57
|
|
54
58
|
# Returns an array of indexes for the given table.
|
@@ -213,7 +217,11 @@ module ActiveRecord
|
|
213
217
|
.gsub(/\s+NULLS\s+(?:FIRST|LAST)\b/i, '')
|
214
218
|
}.reject(&:blank?).map.with_index { |column, i| "#{column} AS alias_#{i}" }
|
215
219
|
|
216
|
-
|
220
|
+
(order_columns << super).join(', ')
|
221
|
+
end
|
222
|
+
|
223
|
+
def create_schema_dumper(options)
|
224
|
+
MSSQL::SchemaDumper.create(self, options)
|
217
225
|
end
|
218
226
|
|
219
227
|
def rename_column(table_name, column_name, new_column_name)
|
@@ -25,7 +25,7 @@ module ActiveRecord
|
|
25
25
|
module RealTransactionExt
|
26
26
|
attr_reader :initial_transaction_isolation
|
27
27
|
|
28
|
-
def initialize(connection, options,
|
28
|
+
def initialize(connection, options, *args)
|
29
29
|
@connection = connection
|
30
30
|
|
31
31
|
if options[:isolation]
|
@@ -58,11 +58,11 @@ module ActiveRecord
|
|
58
58
|
end
|
59
59
|
|
60
60
|
class Transaction
|
61
|
-
|
61
|
+
prepend MSSQL::TransactionExt
|
62
62
|
end
|
63
63
|
|
64
64
|
class RealTransaction
|
65
|
-
|
65
|
+
prepend MSSQL::RealTransactionExt
|
66
66
|
end
|
67
67
|
|
68
68
|
end
|
data/lib/arjdbc/mssql.rb
CHANGED
data/lib/arjdbc/mysql/adapter.rb
CHANGED
@@ -65,6 +65,10 @@ module ActiveRecord
|
|
65
65
|
true
|
66
66
|
end
|
67
67
|
|
68
|
+
def supports_set_server_option?
|
69
|
+
false
|
70
|
+
end
|
71
|
+
|
68
72
|
# HELPER METHODS ===========================================
|
69
73
|
|
70
74
|
# Reloading the type map in abstract/statement_cache.rb blows up postgres
|
@@ -90,10 +94,6 @@ module ActiveRecord
|
|
90
94
|
exception.error_code if exception.is_a?(JDBCError)
|
91
95
|
end
|
92
96
|
|
93
|
-
def create_table(table_name, **options) #:nodoc:
|
94
|
-
super(table_name, options: "ENGINE=InnoDB", **options)
|
95
|
-
end
|
96
|
-
|
97
97
|
#--
|
98
98
|
# QUOTING ==================================================
|
99
99
|
#+
|
@@ -146,6 +146,22 @@ module ActiveRecord
|
|
146
146
|
::ActiveRecord::ConnectionAdapters::MySQL::Column
|
147
147
|
end
|
148
148
|
|
149
|
+
# defined in MySQL::DatabaseStatements which is not included
|
150
|
+
def default_insert_value(column)
|
151
|
+
Arel.sql("DEFAULT") unless column.auto_increment?
|
152
|
+
end
|
153
|
+
|
154
|
+
# FIXME: optimize insert_fixtures_set by using JDBC Statement.addBatch()/executeBatch()
|
155
|
+
def combine_multi_statements(total_sql)
|
156
|
+
total_sql
|
157
|
+
end
|
158
|
+
|
159
|
+
def with_multi_statements
|
160
|
+
yield
|
161
|
+
end
|
162
|
+
|
163
|
+
def discard_remaining_results
|
164
|
+
end
|
149
165
|
end
|
150
166
|
end
|
151
167
|
end
|
@@ -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
|
@@ -8,6 +8,7 @@ require 'active_record/connection_adapters/postgresql/explain_pretty_printer'
|
|
8
8
|
require 'active_record/connection_adapters/postgresql/quoting'
|
9
9
|
require 'active_record/connection_adapters/postgresql/referential_integrity'
|
10
10
|
require 'active_record/connection_adapters/postgresql/schema_creation'
|
11
|
+
require 'active_record/connection_adapters/postgresql/schema_definitions'
|
11
12
|
require 'active_record/connection_adapters/postgresql/schema_dumper'
|
12
13
|
require 'active_record/connection_adapters/postgresql/schema_statements'
|
13
14
|
require 'active_record/connection_adapters/postgresql/type_metadata'
|
@@ -30,9 +31,6 @@ module ArJdbc
|
|
30
31
|
# @private
|
31
32
|
IndexDefinition = ::ActiveRecord::ConnectionAdapters::IndexDefinition
|
32
33
|
|
33
|
-
# @private
|
34
|
-
ForeignKeyDefinition = ::ActiveRecord::ConnectionAdapters::ForeignKeyDefinition
|
35
|
-
|
36
34
|
# @private
|
37
35
|
Type = ::ActiveRecord::Type
|
38
36
|
|
@@ -50,7 +48,6 @@ module ArJdbc
|
|
50
48
|
ADAPTER_NAME
|
51
49
|
end
|
52
50
|
|
53
|
-
# TODO: Update this to pull info from the DatabaseMetaData object?
|
54
51
|
def postgresql_version
|
55
52
|
@postgresql_version ||=
|
56
53
|
begin
|
@@ -247,6 +244,8 @@ module ArJdbc
|
|
247
244
|
|
248
245
|
def supports_foreign_keys?; true end
|
249
246
|
|
247
|
+
def supports_validate_constraints?; true end
|
248
|
+
|
250
249
|
def supports_index_sort_order?; true end
|
251
250
|
|
252
251
|
def supports_partial_index?; true end
|
@@ -257,6 +256,8 @@ module ArJdbc
|
|
257
256
|
|
258
257
|
def supports_views?; true end
|
259
258
|
|
259
|
+
def supports_bulk_alter?; true end
|
260
|
+
|
260
261
|
def supports_datetime_with_precision?; true end
|
261
262
|
|
262
263
|
def supports_comments?; true end
|
@@ -267,6 +268,10 @@ module ArJdbc
|
|
267
268
|
@standard_conforming_strings != :unsupported
|
268
269
|
end
|
269
270
|
|
271
|
+
def supports_foreign_tables? # we don't really support this yet, its a reminder :)
|
272
|
+
postgresql_version >= 90300
|
273
|
+
end
|
274
|
+
|
270
275
|
def supports_hex_escaped_bytea?
|
271
276
|
postgresql_version >= 90000
|
272
277
|
end
|
@@ -374,8 +379,8 @@ module ArJdbc
|
|
374
379
|
end
|
375
380
|
|
376
381
|
def explain(arel, binds = [])
|
377
|
-
sql =
|
378
|
-
ActiveRecord::ConnectionAdapters::PostgreSQL::ExplainPrettyPrinter.new.pp(exec_query(sql, 'EXPLAIN', binds))
|
382
|
+
sql, binds = to_sql_and_binds(arel, binds)
|
383
|
+
ActiveRecord::ConnectionAdapters::PostgreSQL::ExplainPrettyPrinter.new.pp(exec_query("EXPLAIN #{sql}", 'EXPLAIN', binds))
|
379
384
|
end
|
380
385
|
|
381
386
|
# @note Only for "better" AR 4.0 compatibility.
|
@@ -435,10 +440,8 @@ module ArJdbc
|
|
435
440
|
|
436
441
|
# Set the client message level.
|
437
442
|
def client_min_messages=(level)
|
438
|
-
#
|
439
|
-
|
440
|
-
return nil if redshift? # not supported on Redshift
|
441
|
-
execute("SET client_min_messages TO '#{level}'", 'SCHEMA')
|
443
|
+
# Not supported on Redshift
|
444
|
+
redshift? ? nil : super
|
442
445
|
end
|
443
446
|
|
444
447
|
# ORDER BY clause for the passed order option.
|
@@ -580,6 +583,10 @@ module ArJdbc
|
|
580
583
|
::ActiveRecord::SerializationFailure.new(message)
|
581
584
|
when /deadlock detected/
|
582
585
|
::ActiveRecord::Deadlocked.new(message)
|
586
|
+
when /lock timeout/
|
587
|
+
::ActiveRecord::LockWaitTimeout.new(message)
|
588
|
+
when /canceling statement/ # This needs to come after lock timeout because the lock timeout message also contains "canceling statement"
|
589
|
+
::ActiveRecord::QueryCanceled.new(message)
|
583
590
|
else
|
584
591
|
super
|
585
592
|
end
|
@@ -612,6 +619,10 @@ module ArJdbc
|
|
612
619
|
@local_tz ||= execute('SHOW TIME ZONE', 'SCHEMA').first["TimeZone"]
|
613
620
|
end
|
614
621
|
|
622
|
+
def bind_params_length
|
623
|
+
32767
|
624
|
+
end
|
625
|
+
|
615
626
|
end
|
616
627
|
end
|
617
628
|
|
@@ -627,7 +638,6 @@ module ActiveRecord::ConnectionAdapters
|
|
627
638
|
|
628
639
|
# Try to use as much of the built in postgres logic as possible
|
629
640
|
# maybe someday we can extend the actual adapter
|
630
|
-
include ActiveRecord::ConnectionAdapters::PostgreSQL::ColumnDumper
|
631
641
|
include ActiveRecord::ConnectionAdapters::PostgreSQL::ReferentialIntegrity
|
632
642
|
include ActiveRecord::ConnectionAdapters::PostgreSQL::SchemaStatements
|
633
643
|
include ActiveRecord::ConnectionAdapters::PostgreSQL::Quoting
|
@@ -658,7 +668,8 @@ module ActiveRecord::ConnectionAdapters
|
|
658
668
|
|
659
669
|
super(connection, logger, config) # configure_connection happens in super
|
660
670
|
|
661
|
-
|
671
|
+
@type_map = Type::HashLookupTypeMap.new
|
672
|
+
initialize_type_map
|
662
673
|
|
663
674
|
@use_insert_returning = @config.key?(:insert_returning) ?
|
664
675
|
self.class.type_cast_config_to_boolean(@config[:insert_returning]) : nil
|
@@ -680,14 +691,6 @@ module ActiveRecord::ConnectionAdapters
|
|
680
691
|
|
681
692
|
public :sql_for_insert
|
682
693
|
|
683
|
-
def schema_creation # :nodoc:
|
684
|
-
PostgreSQL::SchemaCreation.new self
|
685
|
-
end
|
686
|
-
|
687
|
-
def update_table_definition(table_name, base)
|
688
|
-
Table.new(table_name, base)
|
689
|
-
end
|
690
|
-
|
691
694
|
def jdbc_connection_class(spec)
|
692
695
|
::ArJdbc::PostgreSQL.jdbc_connection_class
|
693
696
|
end
|
@@ -15,7 +15,7 @@ module ArJdbc
|
|
15
15
|
end
|
16
16
|
|
17
17
|
# Extracts the value from a PostgreSQL column default definition.
|
18
|
-
def extract_value_from_default(default)
|
18
|
+
def extract_value_from_default(default) # :nodoc:
|
19
19
|
case default
|
20
20
|
# Quoted types
|
21
21
|
when /\A[\(B]?'(.*)'.*::"?([\w. ]+)"?(?:\[\])?\z/m
|
@@ -41,13 +41,10 @@ module ArJdbc
|
|
41
41
|
end
|
42
42
|
end
|
43
43
|
|
44
|
-
def extract_default_function(default_value, default)
|
45
|
-
default if
|
44
|
+
def extract_default_function(default_value, default) # :nodoc:
|
45
|
+
default if ! default_value && ( %r{\w+\(.*\)|\(.*\)::\w+} === default )
|
46
46
|
end
|
47
47
|
|
48
|
-
def has_default_function?(default_value, default)
|
49
|
-
!default_value && %r{\w+\(.*\)|\(.*\)::\w+|CURRENT_DATE|CURRENT_TIMESTAMP} === default
|
50
|
-
end
|
51
48
|
end
|
52
49
|
|
53
50
|
end
|