activerecord-jdbc-alt-adapter 52.5.1-java → 60.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 (89) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +2 -0
  3. data/.nvimlog +0 -0
  4. data/.travis.yml +61 -37
  5. data/Gemfile +10 -3
  6. data/README.md +44 -28
  7. data/Rakefile +1 -1
  8. data/Rakefile.jdbc +8 -1
  9. data/activerecord-jdbc-adapter.gemspec +5 -8
  10. data/activerecord-jdbc-alt-adapter.gemspec +5 -8
  11. data/lib/arel/visitors/sqlserver.rb +33 -23
  12. data/lib/arjdbc/abstract/connection_management.rb +7 -0
  13. data/lib/arjdbc/abstract/core.rb +16 -23
  14. data/lib/arjdbc/abstract/database_statements.rb +24 -0
  15. data/lib/arjdbc/abstract/statement_cache.rb +2 -5
  16. data/lib/arjdbc/abstract/transaction_support.rb +5 -3
  17. data/lib/arjdbc/db2/column.rb +0 -39
  18. data/lib/arjdbc/derby/adapter.rb +1 -20
  19. data/lib/arjdbc/firebird/adapter.rb +0 -21
  20. data/lib/arjdbc/h2/adapter.rb +0 -15
  21. data/lib/arjdbc/hsqldb/adapter.rb +0 -14
  22. data/lib/arjdbc/informix/adapter.rb +0 -23
  23. data/lib/arjdbc/jdbc/adapter.rb +3 -1
  24. data/lib/arjdbc/jdbc/adapter_java.jar +0 -0
  25. data/lib/arjdbc/jdbc/adapter_require.rb +3 -1
  26. data/lib/arjdbc/jdbc/base_ext.rb +3 -1
  27. data/lib/arjdbc/jdbc/callbacks.rb +2 -0
  28. data/lib/arjdbc/jdbc/column.rb +2 -0
  29. data/lib/arjdbc/jdbc/connection.rb +2 -0
  30. data/lib/arjdbc/jdbc/connection_methods.rb +2 -0
  31. data/lib/arjdbc/jdbc/error.rb +2 -0
  32. data/lib/arjdbc/jdbc/extension.rb +2 -0
  33. data/lib/arjdbc/jdbc/java.rb +3 -1
  34. data/lib/arjdbc/jdbc/railtie.rb +3 -1
  35. data/lib/arjdbc/jdbc/rake_tasks.rb +3 -1
  36. data/lib/arjdbc/jdbc/serialized_attributes_helper.rb +3 -1
  37. data/lib/arjdbc/jdbc/type_cast.rb +2 -0
  38. data/lib/arjdbc/jdbc/type_converter.rb +2 -0
  39. data/lib/arjdbc/mssql/adapter.rb +105 -36
  40. data/lib/arjdbc/mssql/column.rb +5 -1
  41. data/lib/arjdbc/mssql/connection_methods.rb +8 -2
  42. data/lib/arjdbc/mssql/database_limits.rb +2 -0
  43. data/lib/arjdbc/mssql/database_statements.rb +43 -5
  44. data/lib/arjdbc/mssql/errors.rb +2 -0
  45. data/lib/arjdbc/mssql/explain_support.rb +3 -1
  46. data/lib/arjdbc/mssql/extensions/attribute_methods.rb +5 -1
  47. data/lib/arjdbc/mssql/extensions/calculations.rb +2 -0
  48. data/lib/arjdbc/mssql/quoting.rb +38 -0
  49. data/lib/arjdbc/mssql/schema_creation.rb +24 -2
  50. data/lib/arjdbc/mssql/schema_definitions.rb +10 -0
  51. data/lib/arjdbc/mssql/schema_dumper.rb +2 -0
  52. data/lib/arjdbc/mssql/schema_statements.rb +63 -21
  53. data/lib/arjdbc/mssql/transaction.rb +2 -0
  54. data/lib/arjdbc/mssql/types/binary_types.rb +2 -0
  55. data/lib/arjdbc/mssql/types/date_and_time_types.rb +2 -0
  56. data/lib/arjdbc/mssql/types/deprecated_types.rb +2 -0
  57. data/lib/arjdbc/mssql/types/numeric_types.rb +2 -0
  58. data/lib/arjdbc/mssql/types/string_types.rb +2 -0
  59. data/lib/arjdbc/mssql/types.rb +2 -0
  60. data/lib/arjdbc/mssql/utils.rb +2 -0
  61. data/lib/arjdbc/mssql.rb +3 -1
  62. data/lib/arjdbc/mysql/adapter.rb +47 -18
  63. data/lib/arjdbc/postgresql/adapter.rb +240 -214
  64. data/lib/arjdbc/postgresql/base/array_decoder.rb +2 -0
  65. data/lib/arjdbc/postgresql/base/array_encoder.rb +4 -2
  66. data/lib/arjdbc/postgresql/base/array_parser.rb +4 -2
  67. data/lib/arjdbc/postgresql/base/pgconn.rb +2 -0
  68. data/lib/arjdbc/postgresql/column.rb +6 -4
  69. data/lib/arjdbc/postgresql/name.rb +2 -0
  70. data/lib/arjdbc/postgresql/oid_types.rb +3 -1
  71. data/lib/arjdbc/sqlite3/adapter.rb +188 -180
  72. data/lib/arjdbc/sqlite3/connection_methods.rb +15 -4
  73. data/lib/arjdbc/tasks/databases.rake +13 -10
  74. data/lib/arjdbc/tasks/mssql_database_tasks.rb +49 -5
  75. data/lib/arjdbc/util/quoted_cache.rb +3 -1
  76. data/lib/arjdbc/util/serialized_attributes.rb +3 -1
  77. data/lib/arjdbc/util/table_copier.rb +3 -1
  78. data/lib/arjdbc/version.rb +1 -1
  79. data/pom.xml +4 -4
  80. data/rakelib/01-tomcat.rake +2 -2
  81. data/src/java/arjdbc/ArJdbcModule.java +5 -5
  82. data/src/java/arjdbc/jdbc/DriverWrapper.java +1 -9
  83. data/src/java/arjdbc/jdbc/RubyJdbcConnection.java +406 -629
  84. data/src/java/arjdbc/mssql/MSSQLRubyJdbcConnection.java +88 -0
  85. data/src/java/arjdbc/mysql/MySQLRubyJdbcConnection.java +13 -23
  86. data/src/java/arjdbc/postgresql/PostgreSQLRubyJdbcConnection.java +56 -30
  87. data/src/java/arjdbc/sqlite3/SQLite3RubyJdbcConnection.java +94 -99
  88. data/src/java/arjdbc/util/DateTimeUtils.java +12 -4
  89. metadata +7 -16
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module ActiveRecord
2
4
  module ConnectionAdapters
3
5
  module MSSQL
@@ -23,6 +25,15 @@ module ActiveRecord
23
25
  end
24
26
  alias_method :execute_procedure, :exec_proc # AR-SQLServer-Adapter naming
25
27
 
28
+ READ_QUERY = ActiveRecord::ConnectionAdapters::AbstractAdapter.build_read_query_regexp(
29
+ :begin, :commit, :explain, :select, :set, :show, :release, :savepoint, :rollback, :with
30
+ ) # :nodoc:
31
+ private_constant :READ_QUERY
32
+
33
+ def write_query?(sql) # :nodoc:
34
+ !READ_QUERY.match?(sql)
35
+ end
36
+
26
37
  def execute(sql, name = nil)
27
38
  # with identity insert on block
28
39
  if insert_sql?(sql)
@@ -52,11 +63,6 @@ module ActiveRecord
52
63
  end
53
64
  end
54
65
 
55
- # Implements the truncate method.
56
- def truncate(table_name, name = nil)
57
- execute "TRUNCATE TABLE #{quote_table_name(table_name)}", name
58
- end
59
-
60
66
  # Not a rails method, own method to test different isolation
61
67
  # levels supported by the mssql adapter.
62
68
  def supports_transaction_isolation_level?(level)
@@ -95,8 +101,40 @@ module ActiveRecord
95
101
  end
96
102
  end
97
103
 
104
+ # Implements the truncate method.
105
+ def truncate(table_name, name = nil)
106
+ execute "TRUNCATE TABLE #{quote_table_name(table_name)}", name
107
+ end
108
+
109
+ def truncate_tables(*table_names) # :nodoc:
110
+ return if table_names.empty?
111
+
112
+ disable_referential_integrity do
113
+ table_names.each do |table_name|
114
+ mssql_truncate(table_name)
115
+ end
116
+ end
117
+ end
118
+
98
119
  private
99
120
 
121
+ # It seems the truncate_tables is mostly used for testing
122
+ # this a workaround to the fact that SQL Server truncate tables
123
+ # referenced by a foreign key, it may not be required to reset
124
+ # the identity column too, more at:
125
+ # https://docs.microsoft.com/en-us/sql/t-sql/statements/truncate-table-transact-sql?view=sql-server-ver15
126
+ # TODO: improve is with pure T-SQL, use statements
127
+ # such as TRY CATCH and reset identity with DBCC CHECKIDENT
128
+ def mssql_truncate(table_name)
129
+ execute "TRUNCATE TABLE #{quote_table_name(table_name)}", 'Truncate Tables'
130
+ rescue => e
131
+ if e.message =~ /Cannot truncate table .* because it is being referenced by a FOREIGN KEY constraint/
132
+ execute "DELETE FROM #{quote_table_name(table_name)}", 'Truncate Tables with Delete'
133
+ else
134
+ raise
135
+ end
136
+ end
137
+
100
138
  # Overrides method in abstract class, combining the sqls with semicolon
101
139
  # affects disable_referential_integrity in mssql specially when multiple
102
140
  # tables are involved.
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module ActiveRecord
2
4
  # Error raised when adapter determines the database could not acquire
3
5
  # a necessary lock before timing out
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'active_support/core_ext/string'
2
4
 
3
5
  module ActiveRecord
@@ -108,7 +110,7 @@ module ActiveRecord
108
110
  end
109
111
 
110
112
  def build_separator
111
- '+' << @widths.map {|w| '-' * (w + (cell_padding * 2))}.join('+') << '+'
113
+ '+'.dup << @widths.map {|w| '-' * (w + (cell_padding * 2))}.join('+') << '+'
112
114
  end
113
115
 
114
116
  def build_cells(items)
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  # This file contains extensions, overrides, and monkey patches to core parts
2
4
  # of active record to allow SQL Server work properly.
3
5
  #
@@ -15,7 +17,9 @@ module ActiveRecord
15
17
  # this behaviour, even the current comments for that method says that
16
18
  # it rejects primary key but it doesn't (maybe a rails bug?)
17
19
  def attributes_for_update(attribute_names)
18
- attribute_names.reject do |name|
20
+ attribute_names &= self.class.column_names
21
+
22
+ attribute_names.delete_if do |name|
19
23
  # It seems is only required to check if column in identity or not.
20
24
  # This allows to update rails custom primary keys
21
25
  next true if readonly_attribute?(name)
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'active_record/relation'
2
4
  require 'active_record/version'
3
5
 
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module ActiveRecord
2
4
  module ConnectionAdapters
3
5
  module MSSQL
@@ -64,6 +66,42 @@ module ActiveRecord
64
66
  # @see #quote in old adapter
65
67
  BLOB_VALUE_MARKER = "''"
66
68
 
69
+ def column_name_matcher
70
+ COLUMN_NAME
71
+ end
72
+
73
+ def column_name_with_order_matcher
74
+ COLUMN_NAME_WITH_ORDER
75
+ end
76
+
77
+ COLUMN_NAME = /
78
+ \A
79
+ (
80
+ (?:
81
+ # \[table_name\].\[column_name\] | function(one or no argument)
82
+ ((?:\w+\.|\[\w+\]\.)?(?:\w+|\[\w+\])) | \w+\((?:|\g<2>)\)
83
+ )
84
+ (?:\s+AS\s+(?:\w+|\[\w+\]))?
85
+ )
86
+ (?:\s*,\s*\g<1>)*
87
+ \z
88
+ /ix
89
+
90
+ COLUMN_NAME_WITH_ORDER = /
91
+ \A
92
+ (
93
+ (?:
94
+ # \[table_name\].\[column_name\] | function(one or no argument)
95
+ ((?:\w+\.|\[\w+\]\.)?(?:\w+|\[\w+\])) | \w+\((?:|\g<2>)\)
96
+ )
97
+ (?:\s+ASC|\s+DESC)?
98
+ )
99
+ (?:\s*,\s*\g<1>)*
100
+ \z
101
+ /ix
102
+
103
+ private_constant :COLUMN_NAME, :COLUMN_NAME_WITH_ORDER
104
+
67
105
  private
68
106
 
69
107
  def time_with_db_timezone(value)
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module ActiveRecord
2
4
  module ConnectionAdapters
3
5
  module MSSQL
@@ -11,8 +13,28 @@ module ActiveRecord
11
13
  projections, source = query.match(%r{SELECT\s+(.*)?\s+FROM\s+(.*)?}).captures
12
14
  select_into = "SELECT #{projections} INTO #{table_name} FROM #{source}"
13
15
  else
14
- o.instance_variable_set :@as, nil
15
- super
16
+ # o.instance_variable_set :@as, nil
17
+ # super
18
+ create_sql = +''
19
+
20
+ create_sql << "IF NOT EXISTS (SELECT 1 FROM sysobjects WHERE name='#{o.name}' and xtype='U') " if o.if_not_exists
21
+ create_sql << "CREATE#{table_modifier_in_create(o)} TABLE "
22
+ create_sql << "#{quote_table_name(o.name)} "
23
+
24
+ statements = o.columns.map { |c| accept c }
25
+ statements << accept(o.primary_keys) if o.primary_keys
26
+
27
+ if supports_indexes_in_create?
28
+ statements.concat(o.indexes.map { |column_name, options| index_in_create(o.name, column_name, options) })
29
+ end
30
+
31
+ if supports_foreign_keys?
32
+ statements.concat(o.foreign_keys.map { |to_table, options| foreign_key_in_create(o.name, to_table, options) })
33
+ end
34
+
35
+ create_sql << "(#{statements.join(', ')})" if statements.present?
36
+ add_table_options!(create_sql, table_options(o))
37
+ create_sql
16
38
  end
17
39
  end
18
40
 
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module ActiveRecord
2
4
  module ConnectionAdapters
3
5
  module MSSQL
@@ -81,6 +83,14 @@ module ActiveRecord
81
83
 
82
84
  super
83
85
  end
86
+
87
+ def timestamps(**options)
88
+ if !options.key?(:precision) && @conn.supports_datetime_with_precision?
89
+ options[:precision] = 7
90
+ end
91
+
92
+ super
93
+ end
84
94
  end
85
95
 
86
96
  class Table < ActiveRecord::ConnectionAdapters::Table
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module ActiveRecord
2
4
  module ConnectionAdapters
3
5
  module MSSQL
@@ -1,7 +1,9 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module ActiveRecord
2
4
  module ConnectionAdapters
3
5
  module MSSQL
4
- module SchemaStatements
6
+ module SchemaStatements # :nodoc:
5
7
 
6
8
  NATIVE_DATABASE_TYPES = {
7
9
  # Logical Rails types to SQL Server types
@@ -41,23 +43,36 @@ module ActiveRecord
41
43
  NATIVE_DATABASE_TYPES
42
44
  end
43
45
 
44
- # Returns an array of Column objects for the table specified by +table_name+.
45
- # See the concrete implementation for details on the expected parameter values.
46
- # NOTE: This is ready, all implemented in the java part of adapter,
47
- # it uses MSSQLColumn, SqlTypeMetadata, etc.
48
- def columns(table_name)
49
- log('JDBC: GETCOLUMNS', 'SCHEMA') { @connection.columns(table_name) }
50
- rescue => e
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
- []
56
- end
57
-
58
46
  # Returns an array of indexes for the given table.
59
- def indexes(table_name, name = nil)
60
- @connection.indexes(table_name, name)
47
+ def indexes(table_name)
48
+ data = select("EXEC sp_helpindex #{quote(table_name)}", "SCHEMA") rescue []
49
+
50
+ data.reduce([]) do |indexes, index|
51
+ index = index.with_indifferent_access
52
+
53
+ if index[:index_description] =~ /primary key/
54
+ indexes
55
+ else
56
+ name = index[:index_name]
57
+ unique = index[:index_description].to_s.match?(/unique/)
58
+ where = select_value("SELECT [filter_definition] FROM sys.indexes WHERE name = #{quote(name)}")
59
+ orders = {}
60
+ columns = []
61
+
62
+ index[:index_keys].split(',').each do |column|
63
+ column.strip!
64
+
65
+ if column.ends_with?('(-)')
66
+ column.gsub! '(-)', ''
67
+ orders[column] = :desc
68
+ end
69
+
70
+ columns << column
71
+ end
72
+
73
+ indexes << IndexDefinition.new(table_name, name, unique, columns, where: where, orders: orders)
74
+ end
75
+ end
61
76
  end
62
77
 
63
78
  def primary_keys(table_name)
@@ -124,7 +139,7 @@ module ActiveRecord
124
139
  end
125
140
  end
126
141
 
127
- if options[:if_exists] && @mssql_major_version < 13
142
+ if options[:if_exists] && mssql_major_version < 13
128
143
  # this is for sql server 2012 and 2014
129
144
  execute "IF EXISTS(SELECT * FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = #{quote(table_name)}) DROP TABLE #{quote_table_name(table_name)}"
130
145
  else
@@ -193,7 +208,7 @@ module ActiveRecord
193
208
  column_type_sql << "(#{precision})"
194
209
  else
195
210
  raise(
196
- ActiveRecordError,
211
+ ArgumentError,
197
212
  "No #{native[:name]} type has precision of #{precision}. The " \
198
213
  'allowed range of precision is from 0 to 7, even though the ' \
199
214
  'sql type precision is 7 this adapter will persist up to 6 ' \
@@ -220,6 +235,14 @@ module ActiveRecord
220
235
  (order_columns << super).join(', ')
221
236
  end
222
237
 
238
+ def add_timestamps(table_name, options = {})
239
+ if !options.key?(:precision) && supports_datetime_with_precision?
240
+ options[:precision] = 7
241
+ end
242
+
243
+ super
244
+ end
245
+
223
246
  def create_schema_dumper(options)
224
247
  MSSQL::SchemaDumper.create(self, options)
225
248
  end
@@ -299,13 +322,30 @@ module ActiveRecord
299
322
  execute(sql_alter.join(' '))
300
323
  end
301
324
 
325
+ def update_table_definition(table_name, base) #:nodoc:
326
+ MSSQL::Table.new(table_name, base)
327
+ end
328
+
302
329
  private
303
330
 
331
+ def schema_creation
332
+ MSSQL::SchemaCreation.new(self)
333
+ end
334
+
335
+ def create_table_definition(*args)
336
+ MSSQL::TableDefinition.new(self, *args)
337
+ end
338
+
339
+ def new_column_from_field(table_name, field)
340
+ field
341
+ end
342
+
304
343
  def data_source_sql(name = nil, type: nil)
305
344
  scope = quoted_scope(name, type: type)
306
345
  table_name = 'TABLE_NAME'
307
346
 
308
- sql = "SELECT #{table_name}"
347
+ sql = ''.dup
348
+ sql << "SELECT #{table_name}"
309
349
  sql << ' FROM INFORMATION_SCHEMA.TABLES'
310
350
  sql << ' WHERE TABLE_CATALOG = DB_NAME()'
311
351
  sql << " AND TABLE_SCHEMA = #{quote(scope[:schema])}"
@@ -327,7 +367,9 @@ module ActiveRecord
327
367
  end
328
368
 
329
369
  def change_column_type(table_name, column_name, type, options = {})
330
- sql = "ALTER TABLE #{quote_table_name(table_name)} ALTER COLUMN #{quote_column_name(column_name)} #{type_to_sql(type, limit: options[:limit], precision: options[:precision], scale: options[:scale])}"
370
+ sql = ''.dup
371
+
372
+ sql << "ALTER TABLE #{quote_table_name(table_name)} ALTER COLUMN #{quote_column_name(column_name)} #{type_to_sql(type, limit: options[:limit], precision: options[:precision], scale: options[:scale])}"
331
373
  sql << (options[:null] ? " NULL" : " NOT NULL") if options.has_key?(:null)
332
374
  result = execute(sql)
333
375
  result
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'active_record/connection_adapters/abstract/transaction'
2
4
 
3
5
  # MSSQL doe not restore the initial transaction isolation when the transaction
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  # MSSQL binary types definitions
2
4
  module ActiveRecord
3
5
  module ConnectionAdapters
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  # MSSQL date and time types definitions
2
4
  module ActiveRecord
3
5
  module ConnectionAdapters
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  # MSSQL deprecated type definitions
2
4
  module ActiveRecord
3
5
  module ConnectionAdapters
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  # MSSQL numeric types definitions
2
4
  module ActiveRecord
3
5
  module ConnectionAdapters
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  # MSSQL string types definitions
2
4
  module ActiveRecord
3
5
  module ConnectionAdapters
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'arjdbc/mssql/types/numeric_types'
2
4
  require 'arjdbc/mssql/types/string_types'
3
5
  require 'arjdbc/mssql/types/binary_types'
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  # NOTE: file contains code adapted from **sqlserver** adapter, license follows
2
4
  =begin
3
5
  Copyright (c) 2008-2015
data/lib/arjdbc/mssql.rb CHANGED
@@ -1,7 +1,9 @@
1
1
  require 'arjdbc'
2
2
  require 'arjdbc/mssql/adapter'
3
3
  require 'arjdbc/mssql/connection_methods'
4
+
4
5
  module ArJdbc
5
6
  MsSQL = MSSQL # compatibility with 1.2
6
7
  end
7
- ArJdbc.warn_unsupported_adapter 'mssql', [5, 2] # warns on AR >= 4.2
8
+
9
+ ArJdbc.warn_unsupported_adapter 'mssql', [6, 0] # warns on AR >= 4.2
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  ArJdbc.load_java_part :MySQL
2
4
 
3
5
  require 'bigdecimal'
@@ -19,7 +21,7 @@ module ActiveRecord
19
21
  remove_const(:Mysql2Adapter) if const_defined?(:Mysql2Adapter)
20
22
 
21
23
  class Mysql2Adapter < AbstractMysqlAdapter
22
- ADAPTER_NAME = 'Mysql2'.freeze
24
+ ADAPTER_NAME = 'Mysql2'
23
25
 
24
26
  include Jdbc::ConnectionPoolCallbacks
25
27
 
@@ -32,21 +34,30 @@ module ActiveRecord
32
34
  include ArJdbc::MySQL
33
35
 
34
36
  def initialize(connection, logger, connection_parameters, config)
35
- # workaround to skip version check on JNDI to be lazy, dummy version is high enough for Rails 5.0 - 6.0
36
- is_jndi = ::ActiveRecord::ConnectionAdapters::JdbcConnection.jndi_config?(config)
37
- @version = '8.1.5' if is_jndi
38
-
39
37
  super
40
38
 
41
- # set to nil to have it lazy-load the real value when required
42
- @version = nil if is_jndi
43
-
44
39
  @prepared_statements = false unless config.key?(:prepared_statements)
45
40
  # configure_connection taken care of at ArJdbc::Abstract::Core
46
41
  end
47
42
 
43
+ def self.database_exists?(config)
44
+ conn = ActiveRecord::Base.mysql2_connection(config)
45
+ conn && conn.really_valid?
46
+ rescue ActiveRecord::NoDatabaseError
47
+ false
48
+ ensure
49
+ conn.disconnect! if conn
50
+ end
51
+
52
+ def check_version
53
+ # for JNDI, don't check version as the whole connection should be lazy
54
+ return if ::ActiveRecord::ConnectionAdapters::JdbcConnection.jndi_config?(config)
55
+
56
+ super
57
+ end
58
+
48
59
  def supports_json?
49
- !mariadb? && version >= '5.7.8'
60
+ !mariadb? && database_version >= '5.7.8'
50
61
  end
51
62
 
52
63
  def supports_comments?
@@ -61,6 +72,10 @@ module ActiveRecord
61
72
  true
62
73
  end
63
74
 
75
+ def supports_lazy_transactions?
76
+ true
77
+ end
78
+
64
79
  def supports_transaction_isolation?
65
80
  true
66
81
  end
@@ -71,6 +86,16 @@ module ActiveRecord
71
86
 
72
87
  # HELPER METHODS ===========================================
73
88
 
89
+ # from MySQL::DatabaseStatements
90
+ READ_QUERY = ActiveRecord::ConnectionAdapters::AbstractAdapter.build_read_query_regexp(
91
+ :begin, :commit, :explain, :select, :set, :show, :release, :savepoint, :rollback, :describe, :desc
92
+ ) # :nodoc:
93
+ private_constant :READ_QUERY
94
+
95
+ def write_query?(sql) # :nodoc:
96
+ !READ_QUERY.match?(sql)
97
+ end
98
+
74
99
  # Reloading the type map in abstract/statement_cache.rb blows up postgres
75
100
  def clear_cache!
76
101
  reload_type_map
@@ -136,7 +161,13 @@ module ActiveRecord
136
161
  private
137
162
 
138
163
  # e.g. "5.7.20-0ubuntu0.16.04.1"
139
- def full_version; @full_version ||= @connection.full_version end
164
+ def full_version
165
+ schema_cache.database_version.full_version_string
166
+ end
167
+
168
+ def get_full_version
169
+ @full_version ||= @connection.full_version
170
+ end
140
171
 
141
172
  def jdbc_connection_class(spec)
142
173
  ::ActiveRecord::ConnectionAdapters::MySQLJdbcConnection
@@ -152,15 +183,13 @@ module ActiveRecord
152
183
  end
153
184
 
154
185
  # 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
186
 
163
- def discard_remaining_results
187
+ def combine_multi_statements(total_sql)
188
+ if total_sql.length == 1
189
+ total_sql.first
190
+ else
191
+ total_sql
192
+ end
164
193
  end
165
194
  end
166
195
  end