activerecord-jdbc-alt-adapter 52.4.0-java → 61.0.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/.nvimlog +0 -0
- data/.travis.yml +63 -39
- data/Gemfile +11 -4
- data/README.md +55 -35
- data/Rakefile +1 -1
- data/Rakefile.jdbc +8 -1
- data/activerecord-jdbc-adapter.gemspec +6 -9
- data/activerecord-jdbc-alt-adapter.gemspec +9 -12
- data/lib/arel/visitors/postgresql_jdbc.rb +1 -1
- data/lib/arel/visitors/sqlserver.rb +49 -23
- data/lib/arjdbc/abstract/connection_management.rb +7 -0
- data/lib/arjdbc/abstract/core.rb +17 -23
- data/lib/arjdbc/abstract/database_statements.rb +30 -2
- data/lib/arjdbc/abstract/statement_cache.rb +2 -5
- data/lib/arjdbc/abstract/transaction_support.rb +22 -7
- 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/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 +2 -0
- 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 +114 -36
- data/lib/arjdbc/mssql/column.rb +19 -1
- data/lib/arjdbc/mssql/connection_methods.rb +10 -2
- data/lib/arjdbc/mssql/database_limits.rb +9 -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 +6 -2
- data/lib/arjdbc/mssql/extensions/calculations.rb +2 -0
- data/lib/arjdbc/mssql/quoting.rb +38 -0
- data/lib/arjdbc/mssql/schema_creation.rb +25 -3
- 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 +92 -22
- 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 +59 -21
- data/lib/arjdbc/mysql/connection_methods.rb +6 -1
- data/lib/arjdbc/postgresql/adapter.rb +257 -219
- 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 +6 -4
- data/lib/arjdbc/postgresql/connection_methods.rb +1 -0
- data/lib/arjdbc/postgresql/name.rb +2 -0
- data/lib/arjdbc/postgresql/oid_types.rb +7 -4
- data/lib/arjdbc/sqlite3/adapter.rb +266 -221
- data/lib/arjdbc/sqlite3/connection_methods.rb +26 -4
- data/lib/arjdbc/tasks/databases.rake +21 -13
- data/lib/arjdbc/tasks/mssql_database_tasks.rb +126 -25
- 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 +3 -1
- data/pom.xml +4 -4
- data/rakelib/01-tomcat.rake +2 -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 +549 -691
- data/src/java/arjdbc/mssql/MSSQLRubyJdbcConnection.java +88 -0
- data/src/java/arjdbc/mysql/MySQLRubyJdbcConnection.java +13 -23
- data/src/java/arjdbc/postgresql/PostgreSQLRubyJdbcConnection.java +125 -53
- data/src/java/arjdbc/sqlite3/SQLite3RubyJdbcConnection.java +97 -103
- data/src/java/arjdbc/util/DateTimeUtils.java +12 -4
- metadata +10 -18
|
@@ -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
|
|
|
@@ -20,13 +22,13 @@ module ArJdbc
|
|
|
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/
|
|
@@ -46,7 +48,7 @@ module ArJdbc
|
|
|
46
48
|
end
|
|
47
49
|
|
|
48
50
|
def has_default_function?(default_value, default)
|
|
49
|
-
!default_value && %r{\w+\(.*\)|\(.*\)::\w+|CURRENT_DATE|CURRENT_TIMESTAMP}
|
|
51
|
+
!default_value && default && %r{\w+\(.*\)|\(.*\)::\w+|CURRENT_DATE|CURRENT_TIMESTAMP}.match?(default)
|
|
50
52
|
end
|
|
51
53
|
end
|
|
52
54
|
|
|
@@ -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 ;(
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
require 'thread'
|
|
2
4
|
|
|
3
5
|
module ArJdbc
|
|
@@ -143,7 +145,7 @@ module ArJdbc
|
|
|
143
145
|
m.register_type 'uuid', OID::Uuid.new
|
|
144
146
|
m.register_type 'xml', OID::Xml.new
|
|
145
147
|
m.register_type 'tsvector', OID::SpecializedString.new(:tsvector)
|
|
146
|
-
m.register_type 'macaddr', OID::
|
|
148
|
+
m.register_type 'macaddr', OID::Macaddr.new
|
|
147
149
|
m.register_type 'citext', OID::SpecializedString.new(:citext)
|
|
148
150
|
m.register_type 'ltree', OID::SpecializedString.new(:ltree)
|
|
149
151
|
m.register_type 'line', OID::SpecializedString.new(:line)
|
|
@@ -153,9 +155,9 @@ module ArJdbc
|
|
|
153
155
|
m.register_type 'polygon', OID::SpecializedString.new(:polygon)
|
|
154
156
|
m.register_type 'circle', OID::SpecializedString.new(:circle)
|
|
155
157
|
|
|
156
|
-
m.register_type 'interval' do
|
|
158
|
+
m.register_type 'interval' do |*args, sql_type|
|
|
157
159
|
precision = extract_precision(sql_type)
|
|
158
|
-
OID::
|
|
160
|
+
OID::Interval.new(precision: precision)
|
|
159
161
|
end
|
|
160
162
|
|
|
161
163
|
register_class_with_precision m, 'time', Type::Time
|
|
@@ -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
|
|
@@ -242,6 +244,7 @@ module ArJdbc
|
|
|
242
244
|
ActiveRecord::Type.register(:enum, OID::Enum, adapter: :postgresql)
|
|
243
245
|
ActiveRecord::Type.register(:hstore, OID::Hstore, adapter: :postgresql)
|
|
244
246
|
ActiveRecord::Type.register(:inet, OID::Inet, adapter: :postgresql)
|
|
247
|
+
ActiveRecord::Type.register(:interval, OID::Interval, adapter: :postgresql)
|
|
245
248
|
ActiveRecord::Type.register(:json, Type::Json, adapter: :postgresql)
|
|
246
249
|
ActiveRecord::Type.register(:jsonb, OID::Jsonb, adapter: :postgresql)
|
|
247
250
|
ActiveRecord::Type.register(:money, OID::Money, adapter: :postgresql)
|
|
@@ -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"
|
|
@@ -14,6 +16,33 @@ require "active_record/connection_adapters/sqlite3/schema_dumper"
|
|
|
14
16
|
require "active_record/connection_adapters/sqlite3/schema_statements"
|
|
15
17
|
require "active_support/core_ext/class/attribute"
|
|
16
18
|
|
|
19
|
+
module SQLite3
|
|
20
|
+
module Constants
|
|
21
|
+
module Open
|
|
22
|
+
READONLY = 0x00000001
|
|
23
|
+
READWRITE = 0x00000002
|
|
24
|
+
CREATE = 0x00000004
|
|
25
|
+
DELETEONCLOSE = 0x00000008
|
|
26
|
+
EXCLUSIVE = 0x00000010
|
|
27
|
+
AUTOPROXY = 0x00000020
|
|
28
|
+
URI = 0x00000040
|
|
29
|
+
MEMORY = 0x00000080
|
|
30
|
+
MAIN_DB = 0x00000100
|
|
31
|
+
TEMP_DB = 0x00000200
|
|
32
|
+
TRANSIENT_DB = 0x00000400
|
|
33
|
+
MAIN_JOURNAL = 0x00000800
|
|
34
|
+
TEMP_JOURNAL = 0x00001000
|
|
35
|
+
SUBJOURNAL = 0x00002000
|
|
36
|
+
MASTER_JOURNAL = 0x00004000
|
|
37
|
+
NOMUTEX = 0x00008000
|
|
38
|
+
FULLMUTEX = 0x00010000
|
|
39
|
+
SHAREDCACHE = 0x00020000
|
|
40
|
+
PRIVATECACHE = 0x00040000
|
|
41
|
+
WAL = 0x00080000
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
|
|
17
46
|
module ArJdbc
|
|
18
47
|
# All the code in this module is a copy of ConnectionAdapters::SQLite3Adapter from active_record 5.
|
|
19
48
|
# The constants at the front of this file are to allow the rest of the file to remain with no modifications
|
|
@@ -30,7 +59,7 @@ module ArJdbc
|
|
|
30
59
|
SchemaCreation = ConnectionAdapters::SQLite3::SchemaCreation
|
|
31
60
|
SQLite3Adapter = ConnectionAdapters::AbstractAdapter
|
|
32
61
|
|
|
33
|
-
ADAPTER_NAME = 'SQLite'
|
|
62
|
+
ADAPTER_NAME = 'SQLite'
|
|
34
63
|
|
|
35
64
|
# DIFFERENCE: FQN
|
|
36
65
|
include ::ActiveRecord::ConnectionAdapters::SQLite3::Quoting
|
|
@@ -54,20 +83,8 @@ module ArJdbc
|
|
|
54
83
|
# DIFFERENCE: class_attribute in original adapter is moved down to our section which is a class
|
|
55
84
|
# since we cannot define it here in the module (original source this is a class).
|
|
56
85
|
|
|
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
86
|
def initialize(connection, logger, connection_options, config)
|
|
66
87
|
super(connection, logger, config)
|
|
67
|
-
|
|
68
|
-
@active = true
|
|
69
|
-
@statements = StatementPool.new(self.class.type_cast_config_to_integer(config[:statement_limit]))
|
|
70
|
-
|
|
71
88
|
configure_connection
|
|
72
89
|
end
|
|
73
90
|
|
|
@@ -79,16 +96,28 @@ module ArJdbc
|
|
|
79
96
|
true
|
|
80
97
|
end
|
|
81
98
|
|
|
99
|
+
def supports_transaction_isolation?
|
|
100
|
+
true
|
|
101
|
+
end
|
|
102
|
+
|
|
82
103
|
def supports_partial_index?
|
|
83
|
-
|
|
104
|
+
database_version >= "3.9.0"
|
|
105
|
+
end
|
|
106
|
+
|
|
107
|
+
def supports_expression_index?
|
|
108
|
+
database_version >= "3.9.0"
|
|
84
109
|
end
|
|
85
110
|
|
|
86
111
|
def requires_reloading?
|
|
87
112
|
true
|
|
88
113
|
end
|
|
89
114
|
|
|
90
|
-
def
|
|
91
|
-
|
|
115
|
+
def supports_foreign_keys?
|
|
116
|
+
true
|
|
117
|
+
end
|
|
118
|
+
|
|
119
|
+
def supports_check_constraints?
|
|
120
|
+
true
|
|
92
121
|
end
|
|
93
122
|
|
|
94
123
|
def supports_views?
|
|
@@ -99,38 +128,27 @@ module ArJdbc
|
|
|
99
128
|
true
|
|
100
129
|
end
|
|
101
130
|
|
|
102
|
-
def
|
|
103
|
-
|
|
131
|
+
def supports_json?
|
|
132
|
+
true
|
|
104
133
|
end
|
|
105
134
|
|
|
106
|
-
def
|
|
107
|
-
|
|
135
|
+
def supports_common_table_expressions?
|
|
136
|
+
database_version >= "3.8.3"
|
|
108
137
|
end
|
|
109
138
|
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
def disconnect!
|
|
113
|
-
super
|
|
114
|
-
@active = false
|
|
115
|
-
@connection.close rescue nil
|
|
139
|
+
def supports_insert_on_conflict?
|
|
140
|
+
database_version >= "3.24.0"
|
|
116
141
|
end
|
|
142
|
+
alias supports_insert_on_duplicate_skip? supports_insert_on_conflict?
|
|
143
|
+
alias supports_insert_on_duplicate_update? supports_insert_on_conflict?
|
|
144
|
+
alias supports_insert_conflict_target? supports_insert_on_conflict?
|
|
117
145
|
|
|
118
|
-
#
|
|
119
|
-
def clear_cache!
|
|
120
|
-
@statements.clear
|
|
121
|
-
end
|
|
146
|
+
# DIFFERENCE: active?, reconnect!, disconnect! handles by arjdbc core
|
|
122
147
|
|
|
123
148
|
def supports_index_sort_order?
|
|
124
149
|
true
|
|
125
150
|
end
|
|
126
151
|
|
|
127
|
-
# Returns 62. SQLite supports index names up to 64
|
|
128
|
-
# characters. The rest is used by Rails internally to perform
|
|
129
|
-
# temporary rename operations
|
|
130
|
-
def allowed_index_name_length
|
|
131
|
-
index_name_length - 2
|
|
132
|
-
end
|
|
133
|
-
|
|
134
152
|
def native_database_types #:nodoc:
|
|
135
153
|
NATIVE_DATABASE_TYPES
|
|
136
154
|
end
|
|
@@ -144,90 +162,68 @@ module ArJdbc
|
|
|
144
162
|
true
|
|
145
163
|
end
|
|
146
164
|
|
|
165
|
+
def supports_lazy_transactions?
|
|
166
|
+
true
|
|
167
|
+
end
|
|
168
|
+
|
|
147
169
|
# REFERENTIAL INTEGRITY ====================================
|
|
148
170
|
|
|
149
171
|
def disable_referential_integrity # :nodoc:
|
|
150
|
-
|
|
172
|
+
old_foreign_keys = query_value("PRAGMA foreign_keys")
|
|
173
|
+
old_defer_foreign_keys = query_value("PRAGMA defer_foreign_keys")
|
|
151
174
|
|
|
152
175
|
begin
|
|
176
|
+
execute("PRAGMA defer_foreign_keys = ON")
|
|
153
177
|
execute("PRAGMA foreign_keys = OFF")
|
|
154
178
|
yield
|
|
155
179
|
ensure
|
|
156
|
-
execute("PRAGMA
|
|
180
|
+
execute("PRAGMA defer_foreign_keys = #{old_defer_foreign_keys}")
|
|
181
|
+
execute("PRAGMA foreign_keys = #{old_foreign_keys}")
|
|
157
182
|
end
|
|
158
183
|
end
|
|
159
|
-
|
|
184
|
+
|
|
160
185
|
#--
|
|
161
186
|
# DATABASE STATEMENTS ======================================
|
|
162
187
|
#++
|
|
163
188
|
|
|
189
|
+
READ_QUERY = ActiveRecord::ConnectionAdapters::AbstractAdapter.build_read_query_regexp(
|
|
190
|
+
:pragma
|
|
191
|
+
) # :nodoc:
|
|
192
|
+
private_constant :READ_QUERY
|
|
193
|
+
|
|
194
|
+
def write_query?(sql) # :nodoc:
|
|
195
|
+
!READ_QUERY.match?(sql)
|
|
196
|
+
end
|
|
197
|
+
|
|
164
198
|
def explain(arel, binds = [])
|
|
165
199
|
sql = "EXPLAIN QUERY PLAN #{to_sql(arel, binds)}"
|
|
166
200
|
# DIFFERENCE: FQN
|
|
167
201
|
::ActiveRecord::ConnectionAdapters::SQLite3::ExplainPrettyPrinter.new.pp(exec_query(sql, "EXPLAIN", []))
|
|
168
202
|
end
|
|
169
203
|
|
|
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
|
|
204
|
+
# DIFFERENCE: implemented in ArJdbc::Abstract::DatabaseStatements
|
|
205
|
+
#def exec_query(sql, name = nil, binds = [], prepare: false)
|
|
202
206
|
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
@connection.changes
|
|
206
|
-
end
|
|
207
|
-
alias :exec_update :exec_delete
|
|
207
|
+
# DIFFERENCE: implemented in ArJdbc::Abstract::DatabaseStatements
|
|
208
|
+
#def exec_delete(sql, name = "SQL", binds = [])
|
|
208
209
|
|
|
209
210
|
def last_inserted_id(result)
|
|
210
211
|
@connection.last_insert_row_id
|
|
211
212
|
end
|
|
212
213
|
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
ActiveSupport::Dependencies.interlock.permit_concurrent_loads do
|
|
216
|
-
@connection.execute(sql)
|
|
217
|
-
end
|
|
218
|
-
end
|
|
219
|
-
end
|
|
214
|
+
# DIFFERENCE: implemented in ArJdbc::Abstract::DatabaseStatements
|
|
215
|
+
#def execute(sql, name = nil) #:nodoc:
|
|
220
216
|
|
|
221
217
|
def begin_db_transaction #:nodoc:
|
|
222
|
-
log("begin transaction",
|
|
218
|
+
log("begin transaction", 'TRANSACTION') { @connection.transaction }
|
|
223
219
|
end
|
|
224
220
|
|
|
225
221
|
def commit_db_transaction #:nodoc:
|
|
226
|
-
log("commit transaction",
|
|
222
|
+
log("commit transaction", 'TRANSACTION') { @connection.commit }
|
|
227
223
|
end
|
|
228
224
|
|
|
229
225
|
def exec_rollback_db_transaction #:nodoc:
|
|
230
|
-
log("rollback transaction",
|
|
226
|
+
log("rollback transaction", 'TRANSACTION') { @connection.rollback }
|
|
231
227
|
end
|
|
232
228
|
|
|
233
229
|
# SCHEMA STATEMENTS ========================================
|
|
@@ -237,8 +233,11 @@ module ArJdbc
|
|
|
237
233
|
pks.sort_by { |f| f["pk"] }.map { |f| f["name"] }
|
|
238
234
|
end
|
|
239
235
|
|
|
240
|
-
|
|
241
|
-
|
|
236
|
+
def remove_index(table_name, column_name = nil, **options) # :nodoc:
|
|
237
|
+
return if options[:if_exists] && !index_exists?(table_name, column_name, **options)
|
|
238
|
+
|
|
239
|
+
index_name = index_name_for_remove(table_name, column_name, options)
|
|
240
|
+
|
|
242
241
|
exec_query "DROP INDEX #{quote_column_name(index_name)}"
|
|
243
242
|
end
|
|
244
243
|
|
|
@@ -247,30 +246,28 @@ module ArJdbc
|
|
|
247
246
|
# Example:
|
|
248
247
|
# rename_table('octopuses', 'octopi')
|
|
249
248
|
def rename_table(table_name, new_name)
|
|
249
|
+
schema_cache.clear_data_source_cache!(table_name.to_s)
|
|
250
|
+
schema_cache.clear_data_source_cache!(new_name.to_s)
|
|
250
251
|
exec_query "ALTER TABLE #{quote_table_name(table_name)} RENAME TO #{quote_table_name(new_name)}"
|
|
251
252
|
rename_table_indexes(table_name, new_name)
|
|
252
253
|
end
|
|
253
254
|
|
|
254
|
-
|
|
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
|
-
def add_column(table_name, column_name, type, options = {}) #:nodoc:
|
|
255
|
+
def add_column(table_name, column_name, type, **options) #:nodoc:
|
|
262
256
|
if invalid_alter_table_type?(type, options)
|
|
263
257
|
alter_table(table_name) do |definition|
|
|
264
|
-
definition.column(column_name, type, options)
|
|
258
|
+
definition.column(column_name, type, **options)
|
|
265
259
|
end
|
|
266
260
|
else
|
|
267
261
|
super
|
|
268
262
|
end
|
|
269
263
|
end
|
|
270
264
|
|
|
271
|
-
def remove_column(table_name, column_name, type = nil, options
|
|
265
|
+
def remove_column(table_name, column_name, type = nil, **options) #:nodoc:
|
|
272
266
|
alter_table(table_name) do |definition|
|
|
273
267
|
definition.remove_column column_name
|
|
268
|
+
definition.foreign_keys.delete_if do |_, fk_options|
|
|
269
|
+
fk_options[:column] == column_name.to_s
|
|
270
|
+
end
|
|
274
271
|
end
|
|
275
272
|
end
|
|
276
273
|
|
|
@@ -291,16 +288,11 @@ module ArJdbc
|
|
|
291
288
|
end
|
|
292
289
|
end
|
|
293
290
|
|
|
294
|
-
def change_column(table_name, column_name, type, options
|
|
291
|
+
def change_column(table_name, column_name, type, **options) #:nodoc:
|
|
295
292
|
alter_table(table_name) do |definition|
|
|
296
293
|
definition[column_name].instance_eval do
|
|
297
294
|
self.type = type
|
|
298
|
-
|
|
299
|
-
self.default = options[:default] if options.include?(:default)
|
|
300
|
-
self.null = options[:null] if options.include?(:null)
|
|
301
|
-
self.precision = options[:precision] if options.include?(:precision)
|
|
302
|
-
self.scale = options[:scale] if options.include?(:scale)
|
|
303
|
-
self.collation = options[:collation] if options.include?(:collation)
|
|
295
|
+
self.options.merge!(options)
|
|
304
296
|
end
|
|
305
297
|
end
|
|
306
298
|
end
|
|
@@ -330,14 +322,6 @@ module ArJdbc
|
|
|
330
322
|
end
|
|
331
323
|
end
|
|
332
324
|
|
|
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
325
|
def insert_fixtures_set(fixture_set, tables_to_delete = [])
|
|
342
326
|
disable_referential_integrity do
|
|
343
327
|
transaction(requires_new: true) do
|
|
@@ -349,11 +333,44 @@ module ArJdbc
|
|
|
349
333
|
end
|
|
350
334
|
end
|
|
351
335
|
end
|
|
352
|
-
|
|
336
|
+
|
|
337
|
+
def build_insert_sql(insert) # :nodoc:
|
|
338
|
+
sql = +"INSERT #{insert.into} #{insert.values_list}"
|
|
339
|
+
|
|
340
|
+
if insert.skip_duplicates?
|
|
341
|
+
sql << " ON CONFLICT #{insert.conflict_target} DO NOTHING"
|
|
342
|
+
elsif insert.update_duplicates?
|
|
343
|
+
sql << " ON CONFLICT #{insert.conflict_target} DO UPDATE SET "
|
|
344
|
+
sql << insert.touch_model_timestamps_unless { |column| "#{column} IS excluded.#{column}" }
|
|
345
|
+
sql << insert.updatable_columns.map { |column| "#{column}=excluded.#{column}" }.join(",")
|
|
346
|
+
end
|
|
347
|
+
|
|
348
|
+
sql
|
|
349
|
+
end
|
|
350
|
+
|
|
351
|
+
def shared_cache?
|
|
352
|
+
config[:properties] && config[:properties][:shared_cache] == true
|
|
353
|
+
end
|
|
354
|
+
|
|
355
|
+
def get_database_version # :nodoc:
|
|
356
|
+
SQLite3Adapter::Version.new(query_value("SELECT sqlite_version(*)"))
|
|
357
|
+
end
|
|
358
|
+
|
|
359
|
+
def build_truncate_statement(table_name)
|
|
360
|
+
"DELETE FROM #{quote_table_name(table_name)}"
|
|
361
|
+
end
|
|
362
|
+
|
|
363
|
+
def check_version
|
|
364
|
+
if database_version < "3.8.0"
|
|
365
|
+
raise "Your version of SQLite (#{database_version}) is too old. Active Record supports SQLite >= 3.8."
|
|
366
|
+
end
|
|
367
|
+
end
|
|
368
|
+
|
|
353
369
|
private
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
370
|
+
# See https://www.sqlite.org/limits.html,
|
|
371
|
+
# the default value is 999 when not configured.
|
|
372
|
+
def bind_params_length
|
|
373
|
+
999
|
|
357
374
|
end
|
|
358
375
|
|
|
359
376
|
def table_structure(table_name)
|
|
@@ -366,17 +383,40 @@ module ArJdbc
|
|
|
366
383
|
# See: https://www.sqlite.org/lang_altertable.html
|
|
367
384
|
# SQLite has an additional restriction on the ALTER TABLE statement
|
|
368
385
|
def invalid_alter_table_type?(type, options)
|
|
369
|
-
type.to_sym == :primary_key || options[:primary_key]
|
|
386
|
+
type.to_sym == :primary_key || options[:primary_key] ||
|
|
387
|
+
options[:null] == false && options[:default].nil?
|
|
370
388
|
end
|
|
371
389
|
|
|
372
|
-
def alter_table(
|
|
390
|
+
def alter_table(
|
|
391
|
+
table_name,
|
|
392
|
+
foreign_keys = foreign_keys(table_name),
|
|
393
|
+
check_constraints = check_constraints(table_name),
|
|
394
|
+
**options
|
|
395
|
+
)
|
|
373
396
|
altered_table_name = "a#{table_name}"
|
|
374
|
-
|
|
397
|
+
|
|
398
|
+
caller = lambda do |definition|
|
|
399
|
+
rename = options[:rename] || {}
|
|
400
|
+
foreign_keys.each do |fk|
|
|
401
|
+
if column = rename[fk.options[:column]]
|
|
402
|
+
fk.options[:column] = column
|
|
403
|
+
end
|
|
404
|
+
to_table = strip_table_name_prefix_and_suffix(fk.to_table)
|
|
405
|
+
definition.foreign_key(to_table, **fk.options)
|
|
406
|
+
end
|
|
407
|
+
|
|
408
|
+
check_constraints.each do |chk|
|
|
409
|
+
definition.check_constraint(chk.expression, **chk.options)
|
|
410
|
+
end
|
|
411
|
+
|
|
412
|
+
yield definition if block_given?
|
|
413
|
+
end
|
|
375
414
|
|
|
376
415
|
transaction do
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
416
|
+
disable_referential_integrity do
|
|
417
|
+
move_table(table_name, altered_table_name, options.merge(temporary: true))
|
|
418
|
+
move_table(altered_table_name, table_name, &caller)
|
|
419
|
+
end
|
|
380
420
|
end
|
|
381
421
|
end
|
|
382
422
|
|
|
@@ -388,30 +428,32 @@ module ArJdbc
|
|
|
388
428
|
def copy_table(from, to, options = {})
|
|
389
429
|
from_primary_key = primary_key(from)
|
|
390
430
|
options[:id] = false
|
|
391
|
-
create_table(to, options) do |definition|
|
|
431
|
+
create_table(to, **options) do |definition|
|
|
392
432
|
@definition = definition
|
|
393
433
|
if from_primary_key.is_a?(Array)
|
|
394
434
|
@definition.primary_keys from_primary_key
|
|
395
435
|
end
|
|
436
|
+
|
|
396
437
|
columns(from).each do |column|
|
|
397
438
|
column_name = options[:rename] ?
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
439
|
+
(options[:rename][column.name] ||
|
|
440
|
+
options[:rename][column.name.to_sym] ||
|
|
441
|
+
column.name) : column.name
|
|
401
442
|
|
|
402
443
|
@definition.column(column_name, column.type,
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
444
|
+
limit: column.limit, default: column.default,
|
|
445
|
+
precision: column.precision, scale: column.scale,
|
|
446
|
+
null: column.null, collation: column.collation,
|
|
447
|
+
primary_key: column_name == from_primary_key
|
|
407
448
|
)
|
|
408
449
|
end
|
|
450
|
+
|
|
409
451
|
yield @definition if block_given?
|
|
410
452
|
end
|
|
411
453
|
copy_table_indexes(from, to, options[:rename] || {})
|
|
412
454
|
copy_table_contents(from, to,
|
|
413
|
-
|
|
414
|
-
|
|
455
|
+
@definition.columns.map(&:name),
|
|
456
|
+
options[:rename] || {})
|
|
415
457
|
end
|
|
416
458
|
|
|
417
459
|
def copy_table_indexes(from, to, rename = {})
|
|
@@ -419,24 +461,27 @@ module ArJdbc
|
|
|
419
461
|
name = index.name
|
|
420
462
|
# indexes sqlite creates for internal use start with `sqlite_` and
|
|
421
463
|
# don't need to be copied
|
|
422
|
-
next if name.
|
|
464
|
+
next if name.start_with?("sqlite_")
|
|
423
465
|
if to == "a#{from}"
|
|
424
466
|
name = "t#{name}"
|
|
425
467
|
elsif from == "a#{to}"
|
|
426
468
|
name = name[1..-1]
|
|
427
469
|
end
|
|
428
470
|
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
to_column_names.
|
|
471
|
+
columns = index.columns
|
|
472
|
+
if columns.is_a?(Array)
|
|
473
|
+
to_column_names = columns(to).map(&:name)
|
|
474
|
+
columns = columns.map { |c| rename[c] || c }.select do |column|
|
|
475
|
+
to_column_names.include?(column)
|
|
476
|
+
end
|
|
432
477
|
end
|
|
433
478
|
|
|
434
479
|
unless columns.empty?
|
|
435
480
|
# index name can't be the same
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
add_index(to, columns,
|
|
481
|
+
options = { name: name.gsub(/(^|_)(#{from})_/, "\\1#{to}_"), internal: true }
|
|
482
|
+
options[:unique] = true if index.unique
|
|
483
|
+
options[:where] = index.where if index.where
|
|
484
|
+
add_index(to, columns, **options)
|
|
440
485
|
end
|
|
441
486
|
end
|
|
442
487
|
end
|
|
@@ -454,27 +499,23 @@ module ArJdbc
|
|
|
454
499
|
SELECT #{quoted_from_columns} FROM #{quote_table_name(from)}")
|
|
455
500
|
end
|
|
456
501
|
|
|
457
|
-
def
|
|
458
|
-
@sqlite_version ||= SQLite3Adapter::Version.new(select_value("select sqlite_version(*)"))
|
|
459
|
-
end
|
|
460
|
-
|
|
461
|
-
def translate_exception(exception, message)
|
|
502
|
+
def translate_exception(exception, message:, sql:, binds:)
|
|
462
503
|
case exception.message
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
504
|
+
# SQLite 3.8.2 returns a newly formatted error message:
|
|
505
|
+
# UNIQUE constraint failed: *table_name*.*column_name*
|
|
506
|
+
# Older versions of SQLite return:
|
|
507
|
+
# column *column_name* is not unique
|
|
508
|
+
when /column(s)? .* (is|are) not unique/, /UNIQUE constraint failed: .*/
|
|
509
|
+
# DIFFERENCE: FQN
|
|
510
|
+
::ActiveRecord::RecordNotUnique.new(message, sql: sql, binds: binds)
|
|
511
|
+
when /.* may not be NULL/, /NOT NULL constraint failed: .*/
|
|
512
|
+
# DIFFERENCE: FQN
|
|
513
|
+
::ActiveRecord::NotNullViolation.new(message, sql: sql, binds: binds)
|
|
514
|
+
when /FOREIGN KEY constraint failed/i
|
|
515
|
+
# DIFFERENCE: FQN
|
|
516
|
+
::ActiveRecord::InvalidForeignKey.new(message, sql: sql, binds: binds)
|
|
517
|
+
else
|
|
518
|
+
super
|
|
478
519
|
end
|
|
479
520
|
end
|
|
480
521
|
|
|
@@ -482,11 +523,11 @@ module ArJdbc
|
|
|
482
523
|
|
|
483
524
|
def table_structure_with_collation(table_name, basic_structure)
|
|
484
525
|
collation_hash = {}
|
|
485
|
-
sql =
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
526
|
+
sql = <<~SQL
|
|
527
|
+
SELECT sql FROM
|
|
528
|
+
(SELECT * FROM sqlite_master UNION ALL
|
|
529
|
+
SELECT * FROM sqlite_temp_master)
|
|
530
|
+
WHERE type = 'table' AND name = #{quote(table_name)}
|
|
490
531
|
SQL
|
|
491
532
|
|
|
492
533
|
# Result will have following sample string
|
|
@@ -495,9 +536,9 @@ module ArJdbc
|
|
|
495
536
|
result = exec_query(sql, "SCHEMA").first
|
|
496
537
|
|
|
497
538
|
if result
|
|
498
|
-
# Splitting with left parentheses and
|
|
539
|
+
# Splitting with left parentheses and discarding the first part will return all
|
|
499
540
|
# columns separated with comma(,).
|
|
500
|
-
columns_string = result["sql"].split("(").last
|
|
541
|
+
columns_string = result["sql"].split("(", 2).last
|
|
501
542
|
|
|
502
543
|
columns_string.split(",").each do |column_string|
|
|
503
544
|
# This regex will match the column name and collation type and will save
|
|
@@ -505,7 +546,7 @@ module ArJdbc
|
|
|
505
546
|
collation_hash[$1] = $2 if COLLATE_REGEX =~ column_string
|
|
506
547
|
end
|
|
507
548
|
|
|
508
|
-
basic_structure.map
|
|
549
|
+
basic_structure.map do |column|
|
|
509
550
|
column_name = column["name"]
|
|
510
551
|
|
|
511
552
|
if collation_hash.has_key? column_name
|
|
@@ -515,7 +556,7 @@ module ArJdbc
|
|
|
515
556
|
column
|
|
516
557
|
end
|
|
517
558
|
else
|
|
518
|
-
basic_structure.
|
|
559
|
+
basic_structure.to_a
|
|
519
560
|
end
|
|
520
561
|
end
|
|
521
562
|
|
|
@@ -527,18 +568,6 @@ module ArJdbc
|
|
|
527
568
|
execute("PRAGMA foreign_keys = ON", "SCHEMA")
|
|
528
569
|
end
|
|
529
570
|
|
|
530
|
-
# DIFFERENCE: FQN
|
|
531
|
-
class SQLite3Integer < ::ActiveRecord::Type::Integer # :nodoc:
|
|
532
|
-
private
|
|
533
|
-
def _limit
|
|
534
|
-
# INTEGER storage class can be stored 8 bytes value.
|
|
535
|
-
# See https://www.sqlite.org/datatype3.html#storage_classes_and_datatypes
|
|
536
|
-
limit || 8
|
|
537
|
-
end
|
|
538
|
-
end
|
|
539
|
-
|
|
540
|
-
# DIFFERENCE: FQN
|
|
541
|
-
::ActiveRecord::Type.register(:integer, SQLite3Integer, adapter: :sqlite3)
|
|
542
571
|
end
|
|
543
572
|
# DIFFERENCE: A registration here is moved down to concrete class so we are not registering part of an adapter.
|
|
544
573
|
end
|
|
@@ -597,24 +626,6 @@ module ActiveRecord::ConnectionAdapters
|
|
|
597
626
|
|
|
598
627
|
private
|
|
599
628
|
|
|
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
629
|
# @override {ActiveRecord::ConnectionAdapters::Column#extract_limit}
|
|
619
630
|
def extract_limit(sql_type)
|
|
620
631
|
return nil if sql_type =~ /^(real)\(\d+/i
|
|
@@ -646,37 +657,42 @@ module ActiveRecord::ConnectionAdapters
|
|
|
646
657
|
class SQLite3Adapter < AbstractAdapter
|
|
647
658
|
include ArJdbc::Abstract::Core
|
|
648
659
|
include ArJdbc::SQLite3
|
|
660
|
+
include ArJdbc::Abstract::ConnectionManagement
|
|
649
661
|
include ArJdbc::Abstract::DatabaseStatements
|
|
650
662
|
include ArJdbc::Abstract::StatementCache
|
|
651
663
|
include ArJdbc::Abstract::TransactionSupport
|
|
652
664
|
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
665
|
+
def self.represent_boolean_as_integer=(value) # :nodoc:
|
|
666
|
+
if value == false
|
|
667
|
+
raise "`.represent_boolean_as_integer=` is now always true, so make sure your application can work with it and remove this settings."
|
|
668
|
+
end
|
|
669
|
+
|
|
670
|
+
ActiveSupport::Deprecation.warn(
|
|
671
|
+
"`.represent_boolean_as_integer=` is now always true, so setting this is deprecated and will be removed in Rails 6.1."
|
|
672
|
+
)
|
|
673
|
+
end
|
|
674
|
+
|
|
675
|
+
def self.database_exists?(config)
|
|
676
|
+
config = config.symbolize_keys
|
|
677
|
+
if config[:database] == ":memory:"
|
|
678
|
+
return true
|
|
679
|
+
else
|
|
680
|
+
database_file = defined?(Rails.root) ? File.expand_path(config[:database], Rails.root) : config[:database]
|
|
681
|
+
File.exist?(database_file)
|
|
682
|
+
end
|
|
683
|
+
end
|
|
684
|
+
|
|
671
685
|
|
|
672
686
|
def supports_transaction_isolation?
|
|
673
687
|
false
|
|
674
688
|
end
|
|
675
689
|
|
|
676
690
|
def begin_isolated_db_transaction(isolation)
|
|
677
|
-
raise ActiveRecord::TransactionIsolationError,
|
|
691
|
+
raise ActiveRecord::TransactionIsolationError, "SQLite3 only supports the `read_uncommitted` transaction isolation level" if isolation != :read_uncommitted
|
|
692
|
+
raise StandardError, "You need to enable the shared-cache mode in SQLite mode before attempting to change the transaction isolation level" unless shared_cache?
|
|
693
|
+
super
|
|
678
694
|
end
|
|
679
|
-
|
|
695
|
+
|
|
680
696
|
# SQLite driver doesn't support all types of insert statements with executeUpdate so
|
|
681
697
|
# make it act like a regular query and the ids will be returned from #last_inserted_id
|
|
682
698
|
# example: INSERT INTO "aircraft" DEFAULT VALUES
|
|
@@ -699,5 +715,34 @@ module ActiveRecord::ConnectionAdapters
|
|
|
699
715
|
|
|
700
716
|
# 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
717
|
# ActiveSupport.run_load_hooks(:active_record_sqlite3adapter, SQLite3Adapter)
|
|
718
|
+
|
|
719
|
+
private
|
|
720
|
+
|
|
721
|
+
# because the JDBC driver doesn't like multiple SQL statements in one JDBC statement
|
|
722
|
+
def combine_multi_statements(total_sql)
|
|
723
|
+
if total_sql.length == 1
|
|
724
|
+
total_sql.first
|
|
725
|
+
else
|
|
726
|
+
total_sql
|
|
727
|
+
end
|
|
728
|
+
end
|
|
729
|
+
|
|
730
|
+
def initialize_type_map(m = type_map)
|
|
731
|
+
super
|
|
732
|
+
register_class_with_limit m, %r(int)i, SQLite3Integer
|
|
733
|
+
end
|
|
734
|
+
|
|
735
|
+
# DIFFERENCE: FQN
|
|
736
|
+
class SQLite3Integer < ::ActiveRecord::Type::Integer # :nodoc:
|
|
737
|
+
private
|
|
738
|
+
def _limit
|
|
739
|
+
# INTEGER storage class can be stored 8 bytes value.
|
|
740
|
+
# See https://www.sqlite.org/datatype3.html#storage_classes_and_datatypes
|
|
741
|
+
limit || 8
|
|
742
|
+
end
|
|
743
|
+
end
|
|
744
|
+
|
|
745
|
+
# DIFFERENCE: FQN
|
|
746
|
+
::ActiveRecord::Type.register(:integer, SQLite3Integer, adapter: :sqlite3)
|
|
702
747
|
end
|
|
703
748
|
end
|