activerecord-jdbc-alt-adapter 52.2.3-java → 60.1.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.
- checksums.yaml +4 -4
- data/.gitignore +3 -0
- data/.travis.yml +80 -52
- data/Gemfile +10 -3
- data/README.md +55 -37
- data/Rakefile +31 -5
- data/Rakefile.jdbc +8 -1
- data/activerecord-jdbc-adapter.gemspec +6 -9
- data/activerecord-jdbc-alt-adapter.gemspec +6 -9
- data/lib/arel/visitors/sqlserver.rb +33 -23
- data/lib/arjdbc/abstract/connection_management.rb +7 -0
- data/lib/arjdbc/abstract/core.rb +17 -24
- data/lib/arjdbc/abstract/database_statements.rb +31 -20
- data/lib/arjdbc/abstract/statement_cache.rb +2 -5
- data/lib/arjdbc/abstract/transaction_support.rb +5 -3
- data/lib/arjdbc/db2/column.rb +0 -39
- data/lib/arjdbc/derby/adapter.rb +1 -20
- data/lib/arjdbc/firebird/adapter.rb +0 -21
- data/lib/arjdbc/h2/adapter.rb +0 -15
- data/lib/arjdbc/hsqldb/adapter.rb +0 -14
- data/lib/arjdbc/informix/adapter.rb +0 -23
- data/lib/arjdbc/jdbc.rb +0 -4
- data/lib/arjdbc/jdbc/adapter.rb +3 -1
- data/lib/arjdbc/jdbc/adapter_require.rb +3 -1
- data/lib/arjdbc/jdbc/base_ext.rb +3 -1
- data/lib/arjdbc/jdbc/callbacks.rb +2 -0
- data/lib/arjdbc/jdbc/column.rb +3 -5
- data/lib/arjdbc/jdbc/connection.rb +2 -0
- data/lib/arjdbc/jdbc/connection_methods.rb +2 -0
- data/lib/arjdbc/jdbc/error.rb +2 -0
- data/lib/arjdbc/jdbc/extension.rb +2 -0
- data/lib/arjdbc/jdbc/java.rb +3 -1
- data/lib/arjdbc/jdbc/railtie.rb +3 -1
- data/lib/arjdbc/jdbc/rake_tasks.rb +3 -1
- data/lib/arjdbc/jdbc/serialized_attributes_helper.rb +3 -1
- data/lib/arjdbc/jdbc/type_cast.rb +2 -0
- data/lib/arjdbc/jdbc/type_converter.rb +2 -0
- data/lib/arjdbc/mssql.rb +3 -1
- data/lib/arjdbc/mssql/adapter.rb +112 -46
- data/lib/arjdbc/mssql/column.rb +5 -1
- data/lib/arjdbc/mssql/connection_methods.rb +13 -2
- data/lib/arjdbc/mssql/database_limits.rb +2 -0
- data/lib/arjdbc/mssql/database_statements.rb +44 -6
- data/lib/arjdbc/mssql/errors.rb +2 -0
- data/lib/arjdbc/mssql/explain_support.rb +3 -1
- data/lib/arjdbc/mssql/extensions/attribute_methods.rb +5 -1
- data/lib/arjdbc/mssql/extensions/calculations.rb +2 -0
- data/lib/arjdbc/mssql/quoting.rb +38 -0
- data/lib/arjdbc/mssql/schema_creation.rb +24 -2
- data/lib/arjdbc/mssql/schema_definitions.rb +10 -0
- data/lib/arjdbc/mssql/schema_dumper.rb +2 -0
- data/lib/arjdbc/mssql/schema_statements.rb +63 -21
- data/lib/arjdbc/mssql/transaction.rb +2 -0
- data/lib/arjdbc/mssql/types.rb +2 -0
- data/lib/arjdbc/mssql/types/binary_types.rb +2 -0
- data/lib/arjdbc/mssql/types/date_and_time_types.rb +2 -0
- data/lib/arjdbc/mssql/types/deprecated_types.rb +2 -0
- data/lib/arjdbc/mssql/types/numeric_types.rb +2 -0
- data/lib/arjdbc/mssql/types/string_types.rb +2 -0
- data/lib/arjdbc/mssql/utils.rb +2 -0
- data/lib/arjdbc/mysql/adapter.rb +47 -18
- data/lib/arjdbc/mysql/connection_methods.rb +13 -7
- data/lib/arjdbc/postgresql/adapter.rb +240 -214
- data/lib/arjdbc/postgresql/base/array_decoder.rb +2 -0
- data/lib/arjdbc/postgresql/base/array_encoder.rb +4 -2
- data/lib/arjdbc/postgresql/base/array_parser.rb +4 -2
- data/lib/arjdbc/postgresql/base/pgconn.rb +2 -0
- data/lib/arjdbc/postgresql/column.rb +11 -6
- data/lib/arjdbc/postgresql/connection_methods.rb +3 -1
- data/lib/arjdbc/postgresql/name.rb +2 -0
- data/lib/arjdbc/postgresql/oid_types.rb +3 -1
- data/lib/arjdbc/sqlite3/adapter.rb +188 -180
- data/lib/arjdbc/sqlite3/connection_methods.rb +16 -4
- data/lib/arjdbc/tasks/databases.rake +13 -10
- data/lib/arjdbc/tasks/mssql_database_tasks.rb +49 -5
- data/lib/arjdbc/util/quoted_cache.rb +3 -1
- data/lib/arjdbc/util/serialized_attributes.rb +3 -1
- data/lib/arjdbc/util/table_copier.rb +3 -1
- data/lib/arjdbc/version.rb +1 -1
- data/pom.xml +4 -4
- data/rakelib/01-tomcat.rake +2 -2
- data/rakelib/02-test.rake +0 -2
- data/rakelib/rails.rake +1 -1
- data/src/java/arjdbc/ArJdbcModule.java +5 -5
- data/src/java/arjdbc/jdbc/DriverWrapper.java +1 -9
- data/src/java/arjdbc/jdbc/RubyJdbcConnection.java +468 -637
- data/src/java/arjdbc/mssql/MSSQLRubyJdbcConnection.java +319 -38
- data/src/java/arjdbc/mysql/MySQLRubyJdbcConnection.java +13 -23
- data/src/java/arjdbc/postgresql/PostgreSQLRubyJdbcConnection.java +44 -31
- data/src/java/arjdbc/sqlite3/SQLite3RubyJdbcConnection.java +94 -99
- data/src/java/arjdbc/util/DateTimeUtils.java +34 -12
- metadata +7 -17
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
# This implements a basic encoder to work around ActiveRecord's dependence on the pg gem
|
2
4
|
module ActiveRecord::ConnectionAdapters::PostgreSQL::OID
|
3
5
|
class Array < ActiveModel::Type::Value
|
@@ -6,10 +8,10 @@ module ActiveRecord::ConnectionAdapters::PostgreSQL::OID
|
|
6
8
|
class Array
|
7
9
|
|
8
10
|
def initialize(name:, delimiter:)
|
9
|
-
@type = if name == 'string[]'
|
11
|
+
@type = if name == 'string[]'
|
10
12
|
'text'.freeze
|
11
13
|
else
|
12
|
-
base_type = name.chomp('[]'
|
14
|
+
base_type = name.chomp('[]').to_sym
|
13
15
|
ActiveRecord::Base.connection.native_database_types[base_type][:name]
|
14
16
|
end
|
15
17
|
end
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
# based on active_record/connection_adapters/postgresql/array_parser.rb
|
2
4
|
# until it's some day shareable with Rails ... this is not public API !
|
3
5
|
module ActiveRecord
|
@@ -33,7 +35,7 @@ module ActiveRecord
|
|
33
35
|
is_escaping = false
|
34
36
|
is_quoted = false
|
35
37
|
was_quoted = false
|
36
|
-
current_item = ''
|
38
|
+
current_item = ''.dup
|
37
39
|
|
38
40
|
local_index = index
|
39
41
|
while local_index
|
@@ -58,7 +60,7 @@ module ActiveRecord
|
|
58
60
|
is_escaping = true
|
59
61
|
when COMMA
|
60
62
|
add_item_to_array(array, current_item, was_quoted)
|
61
|
-
current_item = ''
|
63
|
+
current_item = ''.dup
|
62
64
|
was_quoted = false
|
63
65
|
when DOUBLE_QUOTE
|
64
66
|
is_quoted = true
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module ArJdbc
|
2
4
|
module PostgreSQL
|
3
5
|
|
@@ -15,18 +17,18 @@ module ArJdbc
|
|
15
17
|
end
|
16
18
|
|
17
19
|
# Extracts the value from a PostgreSQL column default definition.
|
18
|
-
def extract_value_from_default(default)
|
20
|
+
def extract_value_from_default(default)
|
19
21
|
case default
|
20
22
|
# Quoted types
|
21
23
|
when /\A[\(B]?'(.*)'.*::"?([\w. ]+)"?(?:\[\])?\z/m
|
22
24
|
# The default 'now'::date is CURRENT_DATE
|
23
|
-
if $1 == "now"
|
25
|
+
if $1 == "now" && $2 == "date"
|
24
26
|
nil
|
25
27
|
else
|
26
|
-
$1.gsub("''"
|
28
|
+
$1.gsub("''", "'")
|
27
29
|
end
|
28
30
|
# Boolean types
|
29
|
-
when 'true'
|
31
|
+
when 'true', 'false'
|
30
32
|
default
|
31
33
|
# Numeric types
|
32
34
|
when /\A\(?(-?\d+(\.\d*)?)\)?(::bigint)?\z/
|
@@ -41,10 +43,13 @@ module ArJdbc
|
|
41
43
|
end
|
42
44
|
end
|
43
45
|
|
44
|
-
def extract_default_function(default_value, default)
|
45
|
-
default if
|
46
|
+
def extract_default_function(default_value, default)
|
47
|
+
default if has_default_function?(default_value, default)
|
46
48
|
end
|
47
49
|
|
50
|
+
def has_default_function?(default_value, default)
|
51
|
+
!default_value && %r{\w+\(.*\)|\(.*\)::\w+|CURRENT_DATE|CURRENT_TIMESTAMP}.match?(default)
|
52
|
+
end
|
48
53
|
end
|
49
54
|
|
50
55
|
end
|
@@ -1,6 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
ArJdbc::ConnectionMethods.module_eval do
|
3
3
|
def postgresql_connection(config)
|
4
|
+
config = config.deep_dup
|
4
5
|
# NOTE: this isn't "really" necessary but Rails (in tests) assumes being able to :
|
5
6
|
# ActiveRecord::Base.postgresql_connection ActiveRecord::Base.configurations['arunit'].merge(:insert_returning => false)
|
6
7
|
# ... while using symbols by default but than configurations returning string keys ;(
|
@@ -16,7 +17,8 @@ ArJdbc::ConnectionMethods.module_eval do
|
|
16
17
|
::Jdbc::Postgres.load_driver(:require) if defined?(::Jdbc::Postgres.load_driver)
|
17
18
|
rescue LoadError # assuming driver.jar is on the class-path
|
18
19
|
end
|
19
|
-
driver = config[:driver] ||=
|
20
|
+
driver = (config[:driver] ||=
|
21
|
+
defined?(::Jdbc::Postgres.driver_name) ? ::Jdbc::Postgres.driver_name : 'org.postgresql.Driver')
|
20
22
|
|
21
23
|
host = config[:host] ||= ( config[:hostaddr] || ENV['PGHOST'] || 'localhost' )
|
22
24
|
port = config[:port] ||= ( ENV['PGPORT'] || 5432 )
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'thread'
|
2
4
|
|
3
5
|
module ArJdbc
|
@@ -211,7 +213,7 @@ module ArJdbc
|
|
211
213
|
if oid
|
212
214
|
if oid.is_a? Numeric || oid.match(/^\d+$/)
|
213
215
|
# numeric OID
|
214
|
-
query += "WHERE t.oid
|
216
|
+
query += "WHERE t.oid = %s" % oid
|
215
217
|
|
216
218
|
elsif m = oid.match(/"?(\w+)"?\."?(\w+)"?/)
|
217
219
|
# namespace and type name
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
ArJdbc.load_java_part :SQLite3
|
2
4
|
|
3
5
|
require "arjdbc/abstract/core"
|
@@ -30,7 +32,7 @@ module ArJdbc
|
|
30
32
|
SchemaCreation = ConnectionAdapters::SQLite3::SchemaCreation
|
31
33
|
SQLite3Adapter = ConnectionAdapters::AbstractAdapter
|
32
34
|
|
33
|
-
ADAPTER_NAME = 'SQLite'
|
35
|
+
ADAPTER_NAME = 'SQLite'
|
34
36
|
|
35
37
|
# DIFFERENCE: FQN
|
36
38
|
include ::ActiveRecord::ConnectionAdapters::SQLite3::Quoting
|
@@ -54,20 +56,8 @@ module ArJdbc
|
|
54
56
|
# DIFFERENCE: class_attribute in original adapter is moved down to our section which is a class
|
55
57
|
# since we cannot define it here in the module (original source this is a class).
|
56
58
|
|
57
|
-
class StatementPool < ConnectionAdapters::StatementPool
|
58
|
-
private
|
59
|
-
|
60
|
-
def dealloc(stmt)
|
61
|
-
stmt[:stmt].close unless stmt[:stmt].closed?
|
62
|
-
end
|
63
|
-
end
|
64
|
-
|
65
59
|
def initialize(connection, logger, connection_options, config)
|
66
60
|
super(connection, logger, config)
|
67
|
-
|
68
|
-
@active = true
|
69
|
-
@statements = StatementPool.new(self.class.type_cast_config_to_integer(config[:statement_limit]))
|
70
|
-
|
71
61
|
configure_connection
|
72
62
|
end
|
73
63
|
|
@@ -80,15 +70,19 @@ module ArJdbc
|
|
80
70
|
end
|
81
71
|
|
82
72
|
def supports_partial_index?
|
83
|
-
|
73
|
+
database_version >= "3.9.0"
|
74
|
+
end
|
75
|
+
|
76
|
+
def supports_expression_index?
|
77
|
+
database_version >= "3.9.0"
|
84
78
|
end
|
85
79
|
|
86
80
|
def requires_reloading?
|
87
81
|
true
|
88
82
|
end
|
89
83
|
|
90
|
-
def
|
91
|
-
|
84
|
+
def supports_foreign_keys?
|
85
|
+
true
|
92
86
|
end
|
93
87
|
|
94
88
|
def supports_views?
|
@@ -99,26 +93,22 @@ module ArJdbc
|
|
99
93
|
true
|
100
94
|
end
|
101
95
|
|
102
|
-
def
|
103
|
-
|
96
|
+
def supports_json?
|
97
|
+
true
|
104
98
|
end
|
105
99
|
|
106
|
-
def
|
107
|
-
|
100
|
+
def supports_common_table_expressions?
|
101
|
+
database_version >= "3.8.3"
|
108
102
|
end
|
109
103
|
|
110
|
-
|
111
|
-
|
112
|
-
def disconnect!
|
113
|
-
super
|
114
|
-
@active = false
|
115
|
-
@connection.close rescue nil
|
104
|
+
def supports_insert_on_conflict?
|
105
|
+
database_version >= "3.24.0"
|
116
106
|
end
|
107
|
+
alias supports_insert_on_duplicate_skip? supports_insert_on_conflict?
|
108
|
+
alias supports_insert_on_duplicate_update? supports_insert_on_conflict?
|
109
|
+
alias supports_insert_conflict_target? supports_insert_on_conflict?
|
117
110
|
|
118
|
-
#
|
119
|
-
def clear_cache!
|
120
|
-
@statements.clear
|
121
|
-
end
|
111
|
+
# DIFFERENCE: active?, reconnect!, disconnect! handles by arjdbc core
|
122
112
|
|
123
113
|
def supports_index_sort_order?
|
124
114
|
true
|
@@ -144,90 +134,68 @@ module ArJdbc
|
|
144
134
|
true
|
145
135
|
end
|
146
136
|
|
137
|
+
def supports_lazy_transactions?
|
138
|
+
true
|
139
|
+
end
|
140
|
+
|
147
141
|
# REFERENTIAL INTEGRITY ====================================
|
148
142
|
|
149
143
|
def disable_referential_integrity # :nodoc:
|
150
|
-
|
144
|
+
old_foreign_keys = query_value("PRAGMA foreign_keys")
|
145
|
+
old_defer_foreign_keys = query_value("PRAGMA defer_foreign_keys")
|
151
146
|
|
152
147
|
begin
|
148
|
+
execute("PRAGMA defer_foreign_keys = ON")
|
153
149
|
execute("PRAGMA foreign_keys = OFF")
|
154
150
|
yield
|
155
151
|
ensure
|
156
|
-
execute("PRAGMA
|
152
|
+
execute("PRAGMA defer_foreign_keys = #{old_defer_foreign_keys}")
|
153
|
+
execute("PRAGMA foreign_keys = #{old_foreign_keys}")
|
157
154
|
end
|
158
155
|
end
|
159
|
-
|
156
|
+
|
160
157
|
#--
|
161
158
|
# DATABASE STATEMENTS ======================================
|
162
159
|
#++
|
163
160
|
|
161
|
+
READ_QUERY = ActiveRecord::ConnectionAdapters::AbstractAdapter.build_read_query_regexp(
|
162
|
+
:begin, :commit, :explain, :select, :pragma, :release, :savepoint, :rollback, :with
|
163
|
+
) # :nodoc:
|
164
|
+
private_constant :READ_QUERY
|
165
|
+
|
166
|
+
def write_query?(sql) # :nodoc:
|
167
|
+
!READ_QUERY.match?(sql)
|
168
|
+
end
|
169
|
+
|
164
170
|
def explain(arel, binds = [])
|
165
171
|
sql = "EXPLAIN QUERY PLAN #{to_sql(arel, binds)}"
|
166
172
|
# DIFFERENCE: FQN
|
167
173
|
::ActiveRecord::ConnectionAdapters::SQLite3::ExplainPrettyPrinter.new.pp(exec_query(sql, "EXPLAIN", []))
|
168
174
|
end
|
169
175
|
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
log(sql, name, binds, type_casted_binds) do
|
174
|
-
ActiveSupport::Dependencies.interlock.permit_concurrent_loads do
|
175
|
-
# Don't cache statements if they are not prepared
|
176
|
-
unless prepare
|
177
|
-
stmt = @connection.prepare(sql)
|
178
|
-
begin
|
179
|
-
cols = stmt.columns
|
180
|
-
unless without_prepared_statement?(binds)
|
181
|
-
stmt.bind_params(type_casted_binds)
|
182
|
-
end
|
183
|
-
records = stmt.to_a
|
184
|
-
ensure
|
185
|
-
stmt.close
|
186
|
-
end
|
187
|
-
else
|
188
|
-
cache = @statements[sql] ||= {
|
189
|
-
stmt: @connection.prepare(sql)
|
190
|
-
}
|
191
|
-
stmt = cache[:stmt]
|
192
|
-
cols = cache[:cols] ||= stmt.columns
|
193
|
-
stmt.reset!
|
194
|
-
stmt.bind_params(type_casted_binds)
|
195
|
-
records = stmt.to_a
|
196
|
-
end
|
197
|
-
|
198
|
-
ActiveRecord::Result.new(cols, records)
|
199
|
-
end
|
200
|
-
end
|
201
|
-
end
|
176
|
+
# DIFFERENCE: implemented in ArJdbc::Abstract::DatabaseStatements
|
177
|
+
#def exec_query(sql, name = nil, binds = [], prepare: false)
|
202
178
|
|
203
|
-
|
204
|
-
|
205
|
-
@connection.changes
|
206
|
-
end
|
207
|
-
alias :exec_update :exec_delete
|
179
|
+
# DIFFERENCE: implemented in ArJdbc::Abstract::DatabaseStatements
|
180
|
+
#def exec_delete(sql, name = "SQL", binds = [])
|
208
181
|
|
209
182
|
def last_inserted_id(result)
|
210
183
|
@connection.last_insert_row_id
|
211
184
|
end
|
212
185
|
|
213
|
-
|
214
|
-
|
215
|
-
ActiveSupport::Dependencies.interlock.permit_concurrent_loads do
|
216
|
-
@connection.execute(sql)
|
217
|
-
end
|
218
|
-
end
|
219
|
-
end
|
186
|
+
# DIFFERENCE: implemented in ArJdbc::Abstract::DatabaseStatements
|
187
|
+
#def execute(sql, name = nil) #:nodoc:
|
220
188
|
|
221
189
|
def begin_db_transaction #:nodoc:
|
222
|
-
log("begin transaction",nil) { @connection.transaction }
|
190
|
+
log("begin transaction", nil) { @connection.transaction }
|
223
191
|
end
|
224
192
|
|
225
193
|
def commit_db_transaction #:nodoc:
|
226
|
-
log("commit transaction",nil) { @connection.commit }
|
194
|
+
log("commit transaction", nil) { @connection.commit }
|
227
195
|
end
|
228
196
|
|
229
197
|
def exec_rollback_db_transaction #:nodoc:
|
230
|
-
log("rollback transaction",nil) { @connection.rollback }
|
198
|
+
log("rollback transaction", nil) { @connection.rollback }
|
231
199
|
end
|
232
200
|
|
233
201
|
# SCHEMA STATEMENTS ========================================
|
@@ -251,13 +219,6 @@ module ArJdbc
|
|
251
219
|
rename_table_indexes(table_name, new_name)
|
252
220
|
end
|
253
221
|
|
254
|
-
# DIFFERENCE: deprecated causes a JRuby 9.1 bug where "super" calls itself -> do inline
|
255
|
-
def valid_alter_table_type?(type, options = {})
|
256
|
-
ActiveSupport::Deprecation.deprecation_warning(__method__)
|
257
|
-
!invalid_alter_table_type?(type, options)
|
258
|
-
end
|
259
|
-
#deprecate :valid_alter_table_type?
|
260
|
-
|
261
222
|
def add_column(table_name, column_name, type, options = {}) #:nodoc:
|
262
223
|
if invalid_alter_table_type?(type, options)
|
263
224
|
alter_table(table_name) do |definition|
|
@@ -268,9 +229,12 @@ module ArJdbc
|
|
268
229
|
end
|
269
230
|
end
|
270
231
|
|
271
|
-
def remove_column(table_name, column_name, type = nil, options
|
232
|
+
def remove_column(table_name, column_name, type = nil, **options) #:nodoc:
|
272
233
|
alter_table(table_name) do |definition|
|
273
234
|
definition.remove_column column_name
|
235
|
+
definition.foreign_keys.delete_if do |_, fk_options|
|
236
|
+
fk_options[:column] == column_name.to_s
|
237
|
+
end
|
274
238
|
end
|
275
239
|
end
|
276
240
|
|
@@ -330,14 +294,6 @@ module ArJdbc
|
|
330
294
|
end
|
331
295
|
end
|
332
296
|
|
333
|
-
def insert_fixtures(rows, table_name)
|
334
|
-
ActiveSupport::Deprecation.warn(<<-MSG.squish)
|
335
|
-
`insert_fixtures` is deprecated and will be removed in the next version of Rails.
|
336
|
-
Consider using `insert_fixtures_set` for performance improvement.
|
337
|
-
MSG
|
338
|
-
insert_fixtures_set(table_name => rows)
|
339
|
-
end
|
340
|
-
|
341
297
|
def insert_fixtures_set(fixture_set, tables_to_delete = [])
|
342
298
|
disable_referential_integrity do
|
343
299
|
transaction(requires_new: true) do
|
@@ -349,8 +305,50 @@ module ArJdbc
|
|
349
305
|
end
|
350
306
|
end
|
351
307
|
end
|
352
|
-
|
308
|
+
|
309
|
+
def build_insert_sql(insert) # :nodoc:
|
310
|
+
sql = +"INSERT #{insert.into} #{insert.values_list}"
|
311
|
+
|
312
|
+
if insert.skip_duplicates?
|
313
|
+
sql << " ON CONFLICT #{insert.conflict_target} DO NOTHING"
|
314
|
+
elsif insert.update_duplicates?
|
315
|
+
sql << " ON CONFLICT #{insert.conflict_target} DO UPDATE SET "
|
316
|
+
sql << insert.updatable_columns.map { |column| "#{column}=excluded.#{column}" }.join(",")
|
317
|
+
end
|
318
|
+
|
319
|
+
sql
|
320
|
+
end
|
321
|
+
|
322
|
+
def get_database_version # :nodoc:
|
323
|
+
SQLite3Adapter::Version.new(query_value("SELECT sqlite_version(*)"))
|
324
|
+
end
|
325
|
+
|
326
|
+
def build_truncate_statement(table_name)
|
327
|
+
"DELETE FROM #{quote_table_name(table_name)}"
|
328
|
+
end
|
329
|
+
|
330
|
+
def build_truncate_statements(*table_names)
|
331
|
+
table_names.flatten.map { |table_name| build_truncate_statement table_name }
|
332
|
+
end
|
333
|
+
|
334
|
+
def truncate(table_name, name = nil)
|
335
|
+
ActiveRecord::Base.clear_query_caches_for_current_thread if @query_cache_enabled
|
336
|
+
execute(build_truncate_statement(table_name), name)
|
337
|
+
end
|
338
|
+
|
339
|
+
def check_version
|
340
|
+
if database_version < "3.8.0"
|
341
|
+
raise "Your version of SQLite (#{database_version}) is too old. Active Record supports SQLite >= 3.8."
|
342
|
+
end
|
343
|
+
end
|
344
|
+
|
353
345
|
private
|
346
|
+
# See https://www.sqlite.org/limits.html,
|
347
|
+
# the default value is 999 when not configured.
|
348
|
+
def bind_params_length
|
349
|
+
999
|
350
|
+
end
|
351
|
+
|
354
352
|
def initialize_type_map(m = type_map)
|
355
353
|
super
|
356
354
|
register_class_with_limit m, %r(int)i, SQLite3Integer
|
@@ -366,17 +364,31 @@ module ArJdbc
|
|
366
364
|
# See: https://www.sqlite.org/lang_altertable.html
|
367
365
|
# SQLite has an additional restriction on the ALTER TABLE statement
|
368
366
|
def invalid_alter_table_type?(type, options)
|
369
|
-
type.to_sym == :primary_key || options[:primary_key]
|
367
|
+
type.to_sym == :primary_key || options[:primary_key] ||
|
368
|
+
options[:null] == false && options[:default].nil?
|
370
369
|
end
|
371
370
|
|
372
|
-
def alter_table(table_name,
|
371
|
+
def alter_table(table_name, foreign_keys = foreign_keys(table_name), **options)
|
373
372
|
altered_table_name = "a#{table_name}"
|
374
|
-
|
373
|
+
|
374
|
+
caller = lambda do |definition|
|
375
|
+
rename = options[:rename] || {}
|
376
|
+
foreign_keys.each do |fk|
|
377
|
+
if column = rename[fk.options[:column]]
|
378
|
+
fk.options[:column] = column
|
379
|
+
end
|
380
|
+
to_table = strip_table_name_prefix_and_suffix(fk.to_table)
|
381
|
+
definition.foreign_key(to_table, fk.options)
|
382
|
+
end
|
383
|
+
|
384
|
+
yield definition if block_given?
|
385
|
+
end
|
375
386
|
|
376
387
|
transaction do
|
377
|
-
|
378
|
-
|
379
|
-
|
388
|
+
disable_referential_integrity do
|
389
|
+
move_table(table_name, altered_table_name, options.merge(temporary: true))
|
390
|
+
move_table(altered_table_name, table_name, &caller)
|
391
|
+
end
|
380
392
|
end
|
381
393
|
end
|
382
394
|
|
@@ -395,23 +407,24 @@ module ArJdbc
|
|
395
407
|
end
|
396
408
|
columns(from).each do |column|
|
397
409
|
column_name = options[:rename] ?
|
398
|
-
|
399
|
-
|
400
|
-
|
410
|
+
(options[:rename][column.name] ||
|
411
|
+
options[:rename][column.name.to_sym] ||
|
412
|
+
column.name) : column.name
|
401
413
|
|
402
414
|
@definition.column(column_name, column.type,
|
403
|
-
|
404
|
-
|
405
|
-
|
406
|
-
|
415
|
+
limit: column.limit, default: column.default,
|
416
|
+
precision: column.precision, scale: column.scale,
|
417
|
+
null: column.null, collation: column.collation,
|
418
|
+
primary_key: column_name == from_primary_key
|
407
419
|
)
|
408
420
|
end
|
421
|
+
|
409
422
|
yield @definition if block_given?
|
410
423
|
end
|
411
424
|
copy_table_indexes(from, to, options[:rename] || {})
|
412
425
|
copy_table_contents(from, to,
|
413
|
-
|
414
|
-
|
426
|
+
@definition.columns.map(&:name),
|
427
|
+
options[:rename] || {})
|
415
428
|
end
|
416
429
|
|
417
430
|
def copy_table_indexes(from, to, rename = {})
|
@@ -426,9 +439,12 @@ module ArJdbc
|
|
426
439
|
name = name[1..-1]
|
427
440
|
end
|
428
441
|
|
429
|
-
|
430
|
-
|
431
|
-
to_column_names.
|
442
|
+
columns = index.columns
|
443
|
+
if columns.is_a?(Array)
|
444
|
+
to_column_names = columns(to).map(&:name)
|
445
|
+
columns = columns.map { |c| rename[c] || c }.select do |column|
|
446
|
+
to_column_names.include?(column)
|
447
|
+
end
|
432
448
|
end
|
433
449
|
|
434
450
|
unless columns.empty?
|
@@ -454,27 +470,23 @@ module ArJdbc
|
|
454
470
|
SELECT #{quoted_from_columns} FROM #{quote_table_name(from)}")
|
455
471
|
end
|
456
472
|
|
457
|
-
def
|
458
|
-
@sqlite_version ||= SQLite3Adapter::Version.new(select_value("select sqlite_version(*)"))
|
459
|
-
end
|
460
|
-
|
461
|
-
def translate_exception(exception, message)
|
473
|
+
def translate_exception(exception, message:, sql:, binds:)
|
462
474
|
case exception.message
|
463
|
-
|
464
|
-
|
465
|
-
|
466
|
-
|
467
|
-
|
468
|
-
|
469
|
-
|
470
|
-
|
471
|
-
|
472
|
-
|
473
|
-
|
474
|
-
|
475
|
-
|
476
|
-
|
477
|
-
|
475
|
+
# SQLite 3.8.2 returns a newly formatted error message:
|
476
|
+
# UNIQUE constraint failed: *table_name*.*column_name*
|
477
|
+
# Older versions of SQLite return:
|
478
|
+
# column *column_name* is not unique
|
479
|
+
when /column(s)? .* (is|are) not unique/, /UNIQUE constraint failed: .*/
|
480
|
+
# DIFFERENCE: FQN
|
481
|
+
::ActiveRecord::RecordNotUnique.new(message, sql: sql, binds: binds)
|
482
|
+
when /.* may not be NULL/, /NOT NULL constraint failed: .*/
|
483
|
+
# DIFFERENCE: FQN
|
484
|
+
::ActiveRecord::NotNullViolation.new(message, sql: sql, binds: binds)
|
485
|
+
when /FOREIGN KEY constraint failed/i
|
486
|
+
# DIFFERENCE: FQN
|
487
|
+
::ActiveRecord::InvalidForeignKey.new(message, sql: sql, binds: binds)
|
488
|
+
else
|
489
|
+
super
|
478
490
|
end
|
479
491
|
end
|
480
492
|
|
@@ -482,11 +494,11 @@ module ArJdbc
|
|
482
494
|
|
483
495
|
def table_structure_with_collation(table_name, basic_structure)
|
484
496
|
collation_hash = {}
|
485
|
-
sql =
|
486
|
-
|
487
|
-
|
488
|
-
|
489
|
-
|
497
|
+
sql = <<~SQL
|
498
|
+
SELECT sql FROM
|
499
|
+
(SELECT * FROM sqlite_master UNION ALL
|
500
|
+
SELECT * FROM sqlite_temp_master)
|
501
|
+
WHERE type = 'table' AND name = #{quote(table_name)}
|
490
502
|
SQL
|
491
503
|
|
492
504
|
# Result will have following sample string
|
@@ -495,9 +507,9 @@ module ArJdbc
|
|
495
507
|
result = exec_query(sql, "SCHEMA").first
|
496
508
|
|
497
509
|
if result
|
498
|
-
# Splitting with left parentheses and
|
510
|
+
# Splitting with left parentheses and discarding the first part will return all
|
499
511
|
# columns separated with comma(,).
|
500
|
-
columns_string = result["sql"].split("(").last
|
512
|
+
columns_string = result["sql"].split("(", 2).last
|
501
513
|
|
502
514
|
columns_string.split(",").each do |column_string|
|
503
515
|
# This regex will match the column name and collation type and will save
|
@@ -515,7 +527,7 @@ module ArJdbc
|
|
515
527
|
column
|
516
528
|
end
|
517
529
|
else
|
518
|
-
basic_structure.
|
530
|
+
basic_structure.to_a
|
519
531
|
end
|
520
532
|
end
|
521
533
|
|
@@ -597,24 +609,6 @@ module ActiveRecord::ConnectionAdapters
|
|
597
609
|
|
598
610
|
private
|
599
611
|
|
600
|
-
# @override {ActiveRecord::ConnectionAdapters::Column#simplified_type}
|
601
|
-
def simplified_type(field_type)
|
602
|
-
case field_type
|
603
|
-
when /boolean/i then :boolean
|
604
|
-
when /text/i then :text
|
605
|
-
when /varchar/i then :string
|
606
|
-
when /int/i then :integer
|
607
|
-
when /float/i then :float
|
608
|
-
when /real|decimal/i then
|
609
|
-
extract_scale(field_type) == 0 ? :integer : :decimal
|
610
|
-
when /datetime/i then :datetime
|
611
|
-
when /date/i then :date
|
612
|
-
when /time/i then :time
|
613
|
-
when /blob/i then :binary
|
614
|
-
else super
|
615
|
-
end
|
616
|
-
end
|
617
|
-
|
618
612
|
# @override {ActiveRecord::ConnectionAdapters::Column#extract_limit}
|
619
613
|
def extract_limit(sql_type)
|
620
614
|
return nil if sql_type =~ /^(real)\(\d+/i
|
@@ -646,28 +640,31 @@ module ActiveRecord::ConnectionAdapters
|
|
646
640
|
class SQLite3Adapter < AbstractAdapter
|
647
641
|
include ArJdbc::Abstract::Core
|
648
642
|
include ArJdbc::SQLite3
|
643
|
+
include ArJdbc::Abstract::ConnectionManagement
|
649
644
|
include ArJdbc::Abstract::DatabaseStatements
|
650
645
|
include ArJdbc::Abstract::StatementCache
|
651
646
|
include ArJdbc::Abstract::TransactionSupport
|
652
647
|
|
653
|
-
|
654
|
-
|
655
|
-
|
656
|
-
|
657
|
-
|
658
|
-
|
659
|
-
|
660
|
-
|
661
|
-
|
662
|
-
|
663
|
-
|
664
|
-
|
665
|
-
|
666
|
-
|
667
|
-
|
668
|
-
|
669
|
-
|
670
|
-
|
648
|
+
def self.represent_boolean_as_integer=(value) # :nodoc:
|
649
|
+
if value == false
|
650
|
+
raise "`.represent_boolean_as_integer=` is now always true, so make sure your application can work with it and remove this settings."
|
651
|
+
end
|
652
|
+
|
653
|
+
ActiveSupport::Deprecation.warn(
|
654
|
+
"`.represent_boolean_as_integer=` is now always true, so setting this is deprecated and will be removed in Rails 6.1."
|
655
|
+
)
|
656
|
+
end
|
657
|
+
|
658
|
+
def self.database_exists?(config)
|
659
|
+
config = config.symbolize_keys
|
660
|
+
if config[:database] == ":memory:"
|
661
|
+
return true
|
662
|
+
else
|
663
|
+
database_file = defined?(Rails.root) ? File.expand_path(config[:database], Rails.root) : config[:database]
|
664
|
+
File.exist?(database_file)
|
665
|
+
end
|
666
|
+
end
|
667
|
+
|
671
668
|
|
672
669
|
def supports_transaction_isolation?
|
673
670
|
false
|
@@ -676,7 +673,7 @@ module ActiveRecord::ConnectionAdapters
|
|
676
673
|
def begin_isolated_db_transaction(isolation)
|
677
674
|
raise ActiveRecord::TransactionIsolationError, 'adapter does not support setting transaction isolation'
|
678
675
|
end
|
679
|
-
|
676
|
+
|
680
677
|
# SQLite driver doesn't support all types of insert statements with executeUpdate so
|
681
678
|
# make it act like a regular query and the ids will be returned from #last_inserted_id
|
682
679
|
# example: INSERT INTO "aircraft" DEFAULT VALUES
|
@@ -699,5 +696,16 @@ module ActiveRecord::ConnectionAdapters
|
|
699
696
|
|
700
697
|
# Note: This is not an override of ours but a moved line from AR Sqlite3Adapter to register ours vs our copied module (which would be their class).
|
701
698
|
# ActiveSupport.run_load_hooks(:active_record_sqlite3adapter, SQLite3Adapter)
|
699
|
+
|
700
|
+
private
|
701
|
+
|
702
|
+
# because the JDBC driver doesn't like multiple SQL statements in one JDBC statement
|
703
|
+
def combine_multi_statements(total_sql)
|
704
|
+
if total_sql.length == 1
|
705
|
+
total_sql.first
|
706
|
+
else
|
707
|
+
total_sql
|
708
|
+
end
|
709
|
+
end
|
702
710
|
end
|
703
711
|
end
|