Skip to content

Commit ae7d7f5

Browse files
authored
Merge pull request #1047 from dr-itz/rails61-dev
Rails 6.1 fixes
2 parents 64c54c3 + 79ccf9b commit ae7d7f5

File tree

15 files changed

+98
-16
lines changed

15 files changed

+98
-16
lines changed

README.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,8 @@ Versions are targeted at certain versions of Rails and live on their own branche
2323
| 50.x | 5.0.x | 50-stable | 9.1.x | 7 |
2424
| 51.x | 5.1.x | 51-stable | 9.1.x | 7 |
2525
| 52.x | 5.2.x | 52-stable | 9.1.x | 7 |
26-
| 60.x | 6.0.x | master | 9.2.7 | 8 |
26+
| 60.x | 6.0.x | 60-stable | 9.2.7 | 8 |
27+
| 61.x | 6.1.x | master | 9.2.7 | 8 |
2728

2829
Note that JRuby 9.1.x is end-of-life. We recommend Java 8 at a minimum for all
2930
versions.

lib/arjdbc/mysql/adapter.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,7 @@ def supports_set_server_option?
8888

8989
# from MySQL::DatabaseStatements
9090
READ_QUERY = ActiveRecord::ConnectionAdapters::AbstractAdapter.build_read_query_regexp(
91-
:begin, :commit, :explain, :select, :set, :show, :release, :savepoint, :rollback, :describe, :desc
91+
:desc, :describe, :set, :show, :use
9292
) # :nodoc:
9393
private_constant :READ_QUERY
9494

lib/arjdbc/mysql/connection_methods.rb

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,8 @@ def mysql_connection(config)
102102
alias_method :mysql2_connection, :mysql_connection
103103

104104
def mariadb_connection(config)
105+
config = config.deep_dup
106+
105107
config[:adapter_spec] ||= ::ArJdbc::MySQL
106108
config[:adapter_class] = ActiveRecord::ConnectionAdapters::Mysql2Adapter unless config.key?(:adapter_class)
107109

lib/arjdbc/postgresql/adapter.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -394,7 +394,7 @@ def explain(arel, binds = [])
394394

395395
# from ActiveRecord::ConnectionAdapters::PostgreSQL::DatabaseStatements
396396
READ_QUERY = ActiveRecord::ConnectionAdapters::AbstractAdapter.build_read_query_regexp(
397-
:begin, :commit, :explain, :select, :set, :show, :release, :savepoint, :rollback, :with
397+
:close, :declare, :fetch, :move, :set, :show
398398
) # :nodoc:
399399
private_constant :READ_QUERY
400400

lib/arjdbc/sqlite3/adapter.rb

Lines changed: 41 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,33 @@
1616
require "active_record/connection_adapters/sqlite3/schema_statements"
1717
require "active_support/core_ext/class/attribute"
1818

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+
1946
module ArJdbc
2047
# All the code in this module is a copy of ConnectionAdapters::SQLite3Adapter from active_record 5.
2148
# The constants at the front of this file are to allow the rest of the file to remain with no modifications
@@ -69,6 +96,10 @@ def supports_savepoints?
6996
true
7097
end
7198

99+
def supports_transaction_isolation?
100+
true
101+
end
102+
72103
def supports_partial_index?
73104
database_version >= "3.9.0"
74105
end
@@ -159,7 +190,7 @@ def disable_referential_integrity # :nodoc:
159190
#++
160191

161192
READ_QUERY = ActiveRecord::ConnectionAdapters::AbstractAdapter.build_read_query_regexp(
162-
:begin, :commit, :explain, :select, :pragma, :release, :savepoint, :rollback, :with
193+
:pragma
163194
) # :nodoc:
164195
private_constant :READ_QUERY
165196

@@ -321,6 +352,10 @@ def build_insert_sql(insert) # :nodoc:
321352
sql
322353
end
323354

355+
def shared_cache?
356+
config[:properties] && config[:properties][:shared_cache] == true
357+
end
358+
324359
def get_database_version # :nodoc:
325360
SQLite3Adapter::Version.new(query_value("SELECT sqlite_version(*)"))
326361
end
@@ -357,7 +392,8 @@ def table_structure(table_name)
357392
# See: https://www.sqlite.org/lang_altertable.html
358393
# SQLite has an additional restriction on the ALTER TABLE statement
359394
def invalid_alter_table_type?(type, options)
360-
type.to_sym == :primary_key || options[:primary_key]
395+
type.to_sym == :primary_key || options[:primary_key] ||
396+
options[:null] == false && options[:default].nil?
361397
end
362398

363399
def alter_table(table_name, foreign_keys = foreign_keys(table_name), **options)
@@ -664,7 +700,9 @@ def supports_transaction_isolation?
664700
end
665701

666702
def begin_isolated_db_transaction(isolation)
667-
raise ActiveRecord::TransactionIsolationError, 'adapter does not support setting transaction isolation'
703+
raise ActiveRecord::TransactionIsolationError, "SQLite3 only supports the `read_uncommitted` transaction isolation level" if isolation != :read_uncommitted
704+
raise StandardError, "You need to enable the shared-cache mode in SQLite mode before attempting to change the transaction isolation level" unless shared_cache?
705+
super
668706
end
669707

670708
# SQLite driver doesn't support all types of insert statements with executeUpdate so

lib/arjdbc/sqlite3/connection_methods.rb

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,17 @@ def sqlite3_connection(config)
3535
# * http://sqlite.org/c3ref/open.html
3636
# * http://sqlite.org/c3ref/c_open_autoproxy.html
3737
# => 0x01 = readonly, 0x40 = uri (default in JDBC)
38-
config[:properties][:open_mode] = 0x01 | 0x40
38+
config[:properties][:open_mode] = ::SQLite3::Constants::Open::READONLY | ::SQLite3::Constants::Open::URI
39+
end
40+
41+
if config[:flags]
42+
config[:properties][:open_mode] ||= 0
43+
config[:properties][:open_mode] |= config[:flags]
44+
45+
# JDBC driver has an extra flag for it
46+
if config[:flags] & ::SQLite3::Constants::Open::SHAREDCACHE != 0
47+
config[:properties][:shared_cache] = true
48+
end
3949
end
4050

4151
timeout = config[:timeout]

lib/arjdbc/tasks/databases.rake

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,10 @@ module ActiveRecord::Tasks
3636
private
3737

3838
def adapt_jdbc_config(db_config)
39-
db_config.configuration_hash[:adapter] = db_config.adapter.sub(/^jdbc/, '') if db_config.adapter
39+
if db_config.adapter.start_with? 'jdbc'
40+
config = db_config.configuration_hash.merge(adapter: db_config.adapter.sub(/^jdbc/, ''))
41+
db_config = ActiveRecord::DatabaseConfigurations::HashConfig.new(db_config.env_name, db_config.spec_name, config)
42+
end
4043
db_config
4144
end
4245

src/java/arjdbc/jdbc/RubyJdbcConnection.java

Lines changed: 25 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -359,7 +359,7 @@ public IRubyObject commit(final ThreadContext context) {
359359
if ( ! connection.getAutoCommit() ) {
360360
try {
361361
connection.commit();
362-
resetSavepoints(context); // if any
362+
resetSavepoints(context, connection); // if any
363363
return context.runtime.newBoolean(true);
364364
}
365365
finally {
@@ -380,7 +380,7 @@ public IRubyObject rollback(final ThreadContext context) {
380380
if ( ! connection.getAutoCommit() ) {
381381
try {
382382
connection.rollback();
383-
resetSavepoints(context); // if any
383+
resetSavepoints(context, connection); // if any
384384
return context.tru;
385385
} finally {
386386
connection.setAutoCommit(true);
@@ -516,7 +516,7 @@ private Map<IRubyObject, Savepoint> getSavepoints(final boolean init) {
516516
return null;
517517
}
518518

519-
protected boolean resetSavepoints(final ThreadContext context) {
519+
protected boolean resetSavepoints(final ThreadContext context, final Connection connection) throws SQLException {
520520
if ( hasInternalVariable("savepoints") ) {
521521
removeInternalVariable("savepoints");
522522
return true;
@@ -1098,6 +1098,28 @@ public IRubyObject execute_query(final ThreadContext context, final IRubyObject
10981098
});
10991099
}
11001100

1101+
@JRubyMethod(required = 1)
1102+
public IRubyObject get_first_value(final ThreadContext context, final IRubyObject sql) {
1103+
return withConnection(context, connection -> {
1104+
Statement statement = null;
1105+
final String query = sqlString(sql);
1106+
try {
1107+
statement = createStatement(context, connection);
1108+
statement.execute(query);
1109+
ResultSet rs = statement.getResultSet();
1110+
if (rs == null || !rs.next()) return context.nil;
1111+
1112+
return jdbcToRuby(context, context.getRuntime(), 1, rs.getMetaData().getColumnType(1), rs);
1113+
1114+
} catch (final SQLException e) {
1115+
debugErrorSQL(context, query);
1116+
throw e;
1117+
} finally {
1118+
close(statement);
1119+
}
1120+
});
1121+
}
1122+
11011123
/**
11021124
* Prepares a query, returns a wrapped PreparedStatement. This takes care of exception wrapping
11031125
* @param context which context this method is executing on.

src/java/arjdbc/sqlite3/SQLite3RubyJdbcConnection.java

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -370,10 +370,9 @@ private static boolean useSavepointAPI(final ThreadContext context) {
370370
}
371371

372372
@Override
373-
public IRubyObject begin(ThreadContext context, IRubyObject level) {
374-
throw context.runtime.newRaiseException(getTransactionIsolationError(context.runtime),
375-
"SQLite3 does not support isolation levels"
376-
);
373+
protected boolean resetSavepoints(final ThreadContext context, final Connection connection) throws SQLException {
374+
connection.setTransactionIsolation(Connection.TRANSACTION_SERIALIZABLE);
375+
return super.resetSavepoints(context, connection);
377376
}
378377

379378
@Override
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
11
exclude :test_doesnt_error_when_a_set_query_is_called_while_preventing_writes, 'different return value for execute() in ARJCBC'
2+
exclude :test_doesnt_error_when_a_use_query_is_called_while_preventing_writes, 'different return value for execute() in ARJCBC'
23
exclude :test_statement_timeout_error_codes, 'test stubs #query and expects #execute to call it, but arjdbc has its own implementation'
34
exclude :test_read_timeout_exception, 'uses "read_timeout" option, unknown to JDBC driver'

0 commit comments

Comments
 (0)