activerecord-jdbc-alt-adapter 51.7.0-java → 52.2.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.
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