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.
Files changed (53) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +0 -3
  3. data/.travis.yml +24 -28
  4. data/Gemfile +2 -3
  5. data/README.md +27 -19
  6. data/Rakefile +4 -30
  7. data/activerecord-jdbc-adapter.gemspec +2 -2
  8. data/activerecord-jdbc-alt-adapter.gemspec +4 -4
  9. data/lib/arel/visitors/sqlserver.rb +2 -1
  10. data/lib/arjdbc/abstract/core.rb +12 -2
  11. data/lib/arjdbc/abstract/database_statements.rb +22 -8
  12. data/lib/arjdbc/abstract/statement_cache.rb +1 -0
  13. data/lib/arjdbc/db2/adapter.rb +77 -8
  14. data/lib/arjdbc/db2/as400.rb +12 -0
  15. data/lib/arjdbc/db2/column.rb +3 -0
  16. data/lib/arjdbc/db2/connection_methods.rb +4 -0
  17. data/lib/arjdbc/jdbc/adapter.rb +4 -6
  18. data/lib/arjdbc/jdbc/adapter_java.jar +0 -0
  19. data/lib/arjdbc/jdbc/column.rb +14 -6
  20. data/lib/arjdbc/jdbc.rb +7 -0
  21. data/lib/arjdbc/mssql/adapter.rb +20 -32
  22. data/lib/arjdbc/mssql/connection_methods.rb +1 -5
  23. data/lib/arjdbc/mssql/database_limits.rb +29 -0
  24. data/lib/arjdbc/mssql/database_statements.rb +41 -1
  25. data/lib/arjdbc/mssql/explain_support.rb +6 -1
  26. data/lib/arjdbc/mssql/quoting.rb +9 -2
  27. data/lib/arjdbc/mssql/schema_creation.rb +2 -1
  28. data/lib/arjdbc/mssql/schema_dumper.rb +1 -1
  29. data/lib/arjdbc/mssql/schema_statements.rb +11 -3
  30. data/lib/arjdbc/mssql/transaction.rb +3 -3
  31. data/lib/arjdbc/mssql.rb +1 -1
  32. data/lib/arjdbc/mysql/adapter.rb +20 -4
  33. data/lib/arjdbc/mysql/connection_methods.rb +7 -13
  34. data/lib/arjdbc/postgresql/adapter.rb +23 -20
  35. data/lib/arjdbc/postgresql/column.rb +3 -6
  36. data/lib/arjdbc/postgresql/connection_methods.rb +1 -3
  37. data/lib/arjdbc/postgresql/oid_types.rb +6 -11
  38. data/lib/arjdbc/sqlite3/adapter.rb +86 -91
  39. data/lib/arjdbc/sqlite3/connection_methods.rb +0 -1
  40. data/lib/arjdbc/tasks/database_tasks.rb +1 -0
  41. data/lib/arjdbc/tasks/sqlite_database_tasks_patch.rb +17 -0
  42. data/lib/arjdbc/version.rb +1 -1
  43. data/rakelib/01-tomcat.rake +2 -2
  44. data/rakelib/02-test.rake +2 -0
  45. data/rakelib/rails.rake +1 -1
  46. data/src/java/arjdbc/jdbc/RubyJdbcConnection.java +10 -65
  47. data/src/java/arjdbc/mssql/MSSQLRubyJdbcConnection.java +38 -282
  48. data/src/java/arjdbc/postgresql/PostgreSQLResult.java +69 -4
  49. data/src/java/arjdbc/postgresql/PostgreSQLRubyJdbcConnection.java +69 -13
  50. data/src/java/arjdbc/util/DateTimeUtils.java +17 -28
  51. data/src/java/arjdbc/util/PG.java +8 -0
  52. metadata +15 -12
  53. data/lib/activerecord-jdbc-alt-adapter.rb +0 -1
@@ -26,12 +26,20 @@ module ActiveRecord
26
26
  end
27
27
  end
28
28
 
29
- default = args[0].cast(default)
30
-
31
- sql_type = args.delete_at(1)
32
- type = args.delete_at(0)
33
-
34
- args.unshift(SqlTypeMetadata.new(:sql_type => sql_type, :type => type))
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
 
@@ -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 value.nil?
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
- table[attribute].eq(Arel::Nodes::BindParam.new)
198
+ super
224
199
  end
225
200
  end
226
201
 
227
202
  def configure_connection
228
- # Here goes initial settings per connection
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 << "loginTimeout=#{config[:login_timeout].to_i};" if config[:login_timeout]
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 schema_cache.columns(table_name)
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(arel, binds)
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
@@ -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
- 1
45
+ QUOTED_TRUE
39
46
  end
40
47
 
41
48
  def quoted_false
42
- 0
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
- projections, source = @conn.to_sql(o.as).match(%r{SELECT\s+(.*)?\s+FROM\s+(.*)?}).captures
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
@@ -1,7 +1,7 @@
1
1
  module ActiveRecord
2
2
  module ConnectionAdapters
3
3
  module MSSQL
4
- module ColumnDumper # :nodoc:
4
+ class SchemaDumper < ConnectionAdapters::SchemaDumper
5
5
  MSSQL_NO_LIMIT_TYPES = [
6
6
  'text',
7
7
  'ntext',
@@ -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
- log('JDBC: GETCOLUMNS', 'SCHEMA') { @connection.columns(table_name) }
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
- [super, *order_columns].join(', ')
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, run_commit_callbacks: false)
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
- include MSSQL::TransactionExt
61
+ prepend MSSQL::TransactionExt
62
62
  end
63
63
 
64
64
  class RealTransaction
65
- include MSSQL::RealTransactionExt
65
+ prepend MSSQL::RealTransactionExt
66
66
  end
67
67
 
68
68
  end
data/lib/arjdbc/mssql.rb CHANGED
@@ -4,4 +4,4 @@ require 'arjdbc/mssql/connection_methods'
4
4
  module ArJdbc
5
5
  MsSQL = MSSQL # compatibility with 1.2
6
6
  end
7
- ArJdbc.warn_unsupported_adapter 'mssql', [5, 1] # warns on AR >= 4.2
7
+ ArJdbc.warn_unsupported_adapter 'mssql', [5, 2] # warns on AR >= 4.2
@@ -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
- mysql_driver = driver.nil? || driver.to_s.start_with?('com.mysql.')
16
- mariadb_driver = ! mysql_driver && driver.to_s.start_with?('org.mariadb.')
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 = "EXPLAIN #{to_sql(arel, binds)}"
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
- # NOTE: for now simply ignore the writer (no warn on Redshift) so that
439
- # the AR copy-pasted PpstgreSQL parts stay the same as much as possible
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
- initialize_type_map(@type_map = Type::HashLookupTypeMap.new)
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 has_default_function?(default_value, default)
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