Skip to content

Commit 7bf64f2

Browse files
committed
Merge branch '52-stable' into 60-stable
2 parents 0521eae + 1739e4b commit 7bf64f2

File tree

10 files changed

+129
-43
lines changed

10 files changed

+129
-43
lines changed

.gitignore

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
*.tgz
33
*~
44
*.log
5+
/log/
56
patches*
67
*#
78
TAGS
@@ -30,4 +31,4 @@ Gemfile.lock
3031
.idea
3132
.settings
3233
activerecord-jdbc.iml
33-
lib/arjdbc/jdbc/adapter_java.jar
34+
lib/arjdbc/jdbc/adapter_java.jar

lib/arjdbc/abstract/database_statements.rb

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,10 +19,10 @@ def exec_insert(sql, name = nil, binds = NO_BINDS, pk = nil, sequence_name = nil
1919
binds = convert_legacy_binds_to_attributes(binds) if binds.first.is_a?(Array)
2020

2121
if without_prepared_statement?(binds)
22-
log(sql, name) { @connection.execute_insert(sql) }
22+
log(sql, name) { @connection.execute_insert_pk(sql, pk) }
2323
else
2424
log(sql, name, binds) do
25-
@connection.execute_insert(sql, binds)
25+
@connection.execute_insert_pk(sql, binds, pk)
2626
end
2727
end
2828
end

lib/arjdbc/mysql/connection_methods.rb

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
# frozen_string_literal: true
22
ArJdbc::ConnectionMethods.module_eval do
33
def mysql_connection(config)
4+
config = config.deep_dup
45
# NOTE: this isn't "really" necessary but Rails (in tests) assumes being able to :
56
# ActiveRecord::Base.mysql2_connection ActiveRecord::Base.configurations['arunit'].merge(database: ...)
67
config = symbolize_keys_if_necessary(config)

lib/arjdbc/postgresql/connection_methods.rb

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
# frozen_string_literal: true
22
ArJdbc::ConnectionMethods.module_eval do
33
def postgresql_connection(config)
4+
config = config.deep_dup
45
# NOTE: this isn't "really" necessary but Rails (in tests) assumes being able to :
56
# ActiveRecord::Base.postgresql_connection ActiveRecord::Base.configurations['arunit'].merge(:insert_returning => false)
67
# ... while using symbols by default but than configurations returning string keys ;(

lib/arjdbc/sqlite3/connection_methods.rb

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
# frozen_string_literal: true
22
ArJdbc::ConnectionMethods.module_eval do
33
def sqlite3_connection(config)
4+
config = config.deep_dup
45
config[:adapter_spec] ||= ::ArJdbc::SQLite3
56
config[:adapter_class] = ActiveRecord::ConnectionAdapters::SQLite3Adapter unless config.key?(:adapter_class)
67

rakelib/rails.rake

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ namespace :rails do
5151
ruby_opts_string += " -C \"#{ar_path}\""
5252
ruby_opts_string += " -rbundler/setup"
5353
ruby_opts_string += " -rminitest -rminitest/excludes" unless ENV['NO_EXCLUDES'].eql?('true')
54-
file_list = ENV["TEST"] ? FileList[ ENV["TEST"] ] : test_files_finder.call
54+
file_list = ENV["TEST"] ? FileList[ ENV["TEST"].split(',') ] : test_files_finder.call
5555
file_list_string = file_list.map { |fn| "\"#{fn}\"" }.join(' ')
5656
# test_loader_code = "-e \"ARGV.each{|f| require f}\"" # :direct
5757
option_list = ( ENV["TESTOPTS"] || ENV["TESTOPT"] || ENV["TEST_OPTS"] || '' )

src/java/arjdbc/jdbc/RubyJdbcConnection.java

Lines changed: 76 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -676,7 +676,10 @@ public synchronized IRubyObject reconnect(final ThreadContext context) {
676676

677677
private void connectImpl(final boolean forceConnection) throws SQLException {
678678
setConnection( forceConnection ? newConnection() : null );
679-
if ( forceConnection ) configureConnection();
679+
if (forceConnection) {
680+
if (getConnectionImpl() == null) throw new SQLException("Didn't get a connection. Wrong URL?");
681+
configureConnection();
682+
}
680683
}
681684

682685
@JRubyMethod(name = "read_only?")
@@ -832,62 +835,104 @@ protected IRubyObject mapExecuteResult(final ThreadContext context,
832835
return mapQueryResult(context, connection, resultSet);
833836
}
834837

838+
private static String[] createStatementPk(IRubyObject pk) {
839+
String[] statementPk;
840+
if (pk instanceof RubyArray) {
841+
RubyArray ary = (RubyArray) pk;
842+
int size = ary.size();
843+
statementPk = new String[size];
844+
for (int i = 0; i < size; i++) {
845+
statementPk[i] = sqlString(ary.eltInternal(i));
846+
}
847+
} else {
848+
statementPk = new String[] { sqlString(pk) };
849+
}
850+
return statementPk;
851+
}
852+
835853
/**
836854
* Executes an INSERT SQL statement
837855
* @param context
838856
* @param sql
857+
* @param pk Rails PK
839858
* @return ActiveRecord::Result
840859
* @throws SQLException
841860
*/
842-
@JRubyMethod(name = "execute_insert", required = 1)
843-
public IRubyObject execute_insert(final ThreadContext context, final IRubyObject sql) {
844-
return withConnection(context, connection -> {
845-
Statement statement = null;
846-
final String query = sqlString(sql);
847-
try {
861+
@JRubyMethod(name = "execute_insert_pk", required = 2)
862+
public IRubyObject execute_insert_pk(final ThreadContext context, final IRubyObject sql, final IRubyObject pk) {
863+
return withConnection(context, new Callable<IRubyObject>() {
864+
public IRubyObject call(final Connection connection) throws SQLException {
865+
Statement statement = null;
866+
final String query = sqlString(sql);
867+
try {
848868

849-
statement = createStatement(context, connection);
850-
statement.executeUpdate(query, Statement.RETURN_GENERATED_KEYS);
851-
return mapGeneratedKeys(context, connection, statement);
869+
statement = createStatement(context, connection);
852870

853-
} catch (final SQLException e) {
854-
debugErrorSQL(context, query);
855-
throw e;
856-
} finally {
857-
close(statement);
871+
if (pk == context.nil || pk == context.fals || !supportsGeneratedKeys(connection)) {
872+
statement.executeUpdate(query, Statement.RETURN_GENERATED_KEYS);
873+
} else {
874+
statement.executeUpdate(query, createStatementPk(pk));
875+
}
876+
877+
return mapGeneratedKeys(context, connection, statement);
878+
} catch (final SQLException e) {
879+
debugErrorSQL(context, query);
880+
throw e;
881+
} finally {
882+
close(statement);
883+
}
858884
}
859885
});
860886
}
861887

888+
@Deprecated
889+
@JRubyMethod(name = "execute_insert", required = 1)
890+
public IRubyObject execute_insert(final ThreadContext context, final IRubyObject sql) {
891+
return execute_insert_pk(context, sql, context.nil);
892+
}
893+
862894
/**
863895
* Executes an INSERT SQL statement using a prepared statement
864896
* @param context
865897
* @param sql
866898
* @param binds RubyArray of values to be bound to the query
899+
* @param pk Rails PK
867900
* @return ActiveRecord::Result
868901
* @throws SQLException
869902
*/
870-
@JRubyMethod(name = "execute_insert", required = 2)
871-
public IRubyObject execute_insert(final ThreadContext context, final IRubyObject sql, final IRubyObject binds) {
872-
return withConnection(context, connection -> {
873-
PreparedStatement statement = null;
874-
final String query = sqlString(sql);
875-
try {
876-
877-
statement = connection.prepareStatement(query, Statement.RETURN_GENERATED_KEYS);
878-
setStatementParameters(context, connection, statement, (RubyArray) binds);
879-
statement.executeUpdate();
880-
return mapGeneratedKeys(context, connection, statement);
903+
@JRubyMethod(name = "execute_insert_pk", required = 3)
904+
public IRubyObject execute_insert_pk(final ThreadContext context, final IRubyObject sql, final IRubyObject binds,
905+
final IRubyObject pk) {
906+
return withConnection(context, new Callable<IRubyObject>() {
907+
public IRubyObject call(final Connection connection) throws SQLException {
908+
PreparedStatement statement = null;
909+
final String query = sqlString(sql);
910+
try {
911+
if (pk == context.nil || pk == context.fals || !supportsGeneratedKeys(connection)) {
912+
statement = connection.prepareStatement(query, Statement.RETURN_GENERATED_KEYS);
913+
} else {
914+
statement = connection.prepareStatement(query, createStatementPk(pk));
915+
}
881916

882-
} catch (final SQLException e) {
883-
debugErrorSQL(context, query);
884-
throw e;
885-
} finally {
886-
close(statement);
917+
setStatementParameters(context, connection, statement, (RubyArray) binds);
918+
statement.executeUpdate();
919+
return mapGeneratedKeys(context, connection, statement);
920+
} catch (final SQLException e) {
921+
debugErrorSQL(context, query);
922+
throw e;
923+
} finally {
924+
close(statement);
925+
}
887926
}
888927
});
889928
}
890929

930+
@Deprecated
931+
@JRubyMethod(name = "execute_insert", required = 2)
932+
public IRubyObject execute_insert(final ThreadContext context, final IRubyObject binds, final IRubyObject sql) {
933+
return execute_insert_pk(context, sql, binds, context.nil);
934+
}
935+
891936
/**
892937
* Executes an UPDATE (DELETE) SQL statement
893938
* @param context

test/db/mysql/unit_test.rb

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,7 @@ def initialize; end
9696
connection_handler = connection_handler_stub
9797

9898
config = { :jndi => 'jdbc/TestDS' }
99-
connection_handler.expects(:jndi_connection)
99+
connection_handler.expects(:jndi_connection).with() { |c| config = c }
100100
connection_handler.mysql_connection config
101101

102102
# we do not complete username/database etc :
@@ -126,7 +126,7 @@ def initialize; end
126126
connection_handler = connection_handler_stub
127127

128128
config = { database: 'MyDB' }
129-
connection_handler.expects(:jdbc_connection)
129+
connection_handler.expects(:jdbc_connection).with() { |c| config = c }
130130
::Jdbc::MySQL.expects(:driver_name).returns('com.mysql.CustomDriver')
131131
connection_handler.mysql_connection config
132132
assert_equal 'com.mysql.CustomDriver', config[:driver]
@@ -138,7 +138,7 @@ def initialize; end
138138
connection_handler = connection_handler_stub
139139

140140
config = { database: 'MyDB' }
141-
connection_handler.expects(:jdbc_connection)
141+
connection_handler.expects(:jdbc_connection).with() { |c| config = c }
142142
::Jdbc::MySQL.expects(:driver_name).returns('com.mysql.cj.jdbc.Driver')
143143
connection_handler.mysql_connection config
144144
assert_equal 'com.mysql.cj.jdbc.Driver', config[:driver]
@@ -174,7 +174,7 @@ def teardown
174174
connection_handler = connection_handler_stub
175175

176176
config = { host: '127.0.0.1', database: 'MyDB' }
177-
connection_handler.expects(:jdbc_connection)
177+
connection_handler.expects(:jdbc_connection).with() { |c| config = c }
178178
connection_handler.mysql_connection config
179179

180180
# we do not complete username/database etc :
@@ -201,7 +201,7 @@ def teardown
201201
connection_handler = connection_handler_stub
202202

203203
config = { database: 'MyDB', driver: false }
204-
connection_handler.expects(:jdbc_connection)
204+
connection_handler.expects(:jdbc_connection).with() { |c| config = c }
205205
connection_handler.expects(:require).never
206206
connection_handler.mysql_connection config
207207
assert_not config[:driver] # allow Java's service discovery mechanism (with connector/j 8.0)
@@ -211,7 +211,7 @@ def teardown
211211
connection_handler = connection_handler_stub
212212

213213
config = { database: 'MyDB', driver: 'org.mariadb.jdbc.Driver' }
214-
connection_handler.expects(:jdbc_connection)
214+
connection_handler.expects(:jdbc_connection).with() { |c| config = c }
215215
connection_handler.mysql_connection config
216216

217217
# we do not complete username/database etc :
@@ -224,4 +224,4 @@ def teardown
224224

225225
end
226226

227-
end if defined? JRUBY_VERSION
227+
end if defined? JRUBY_VERSION
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
require 'test_helper'
2+
require 'db/postgres'
3+
4+
class PrimaryKeyIsNotTheFirstColumnTest < Test::Unit::TestCase
5+
6+
class CreateEmployees < ActiveRecord::Migration[4.2]
7+
def self.up
8+
create_table 'employees', :id => false do |t|
9+
t.string :full_name, :null => false
10+
t.primary_key :id, :serial
11+
end
12+
end
13+
def self.down
14+
drop_table 'employees'
15+
end
16+
end
17+
18+
def setup
19+
CreateEmployees.up
20+
end
21+
22+
def teardown
23+
CreateEmployees.down
24+
end
25+
26+
class Employee < ActiveRecord::Base
27+
end
28+
29+
def test_returning_when_primary_key_is_not_the_first_column
30+
e = Employee.new
31+
e.full_name = 'Slartibartfast'
32+
e.save!
33+
e.reload
34+
assert_equal 1, e.id
35+
end
36+
37+
end

test/db/postgresql/unit_test.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ class PostgresUnitTest < Test::Unit::TestCase
88
connection_handler = connection_handler_stub
99

1010
config = { :jndi => 'jdbc/TestDS' }
11-
connection_handler.expects(:jndi_connection)
11+
connection_handler.expects(:jndi_connection).with() { |c| config = c }
1212
connection_handler.postgresql_connection config
1313

1414
# we do not complete username/database etc :

0 commit comments

Comments
 (0)