Skip to content

Commit ebea905

Browse files
authored
Merge pull request #992 from dr-itz/mysql-jndi-dev
MySQL JNDI fixes
2 parents ca69a84 + 8b0d767 commit ebea905

11 files changed

+97
-270
lines changed

.travis.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -52,8 +52,8 @@ env:
5252
- DB=postgresql PREPARED_STATEMENTS=true INSERT_RETURNING=true
5353
- DB=sqlite3 PREPARED_STATEMENTS=false
5454
- DB=sqlite3 PREPARED_STATEMENTS=true
55-
#- DB=jndi PREPARED_STATEMENTS=false
56-
#- DB=jndi PREPARED_STATEMENTS=true
55+
- DB=jndi PREPARED_STATEMENTS=false
56+
- DB=jndi PREPARED_STATEMENTS=true
5757
matrix:
5858
allow_failures:
5959
- rvm: jruby-head

lib/arjdbc/mysql/adapter.rb

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,15 @@ class Mysql2Adapter < AbstractMysqlAdapter
3232
include ArJdbc::MySQL
3333

3434
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+
3539
super
40+
41+
# set to nil to have it lazy-load the real value when required
42+
@version = nil if is_jndi
43+
3644
@prepared_statements = false unless config.key?(:prepared_statements)
3745
# configure_connection taken care of at ArJdbc::Abstract::Core
3846
end

src/java/arjdbc/jdbc/ConnectionFactory.java

Lines changed: 0 additions & 87 deletions
Original file line numberDiff line numberDiff line change
@@ -27,12 +27,6 @@
2727

2828
import java.sql.Connection;
2929
import java.sql.SQLException;
30-
import javax.sql.DataSource;
31-
32-
import org.jruby.RubyObject;
33-
import org.jruby.RubyString;
34-
import org.jruby.runtime.ThreadContext;
35-
import org.jruby.runtime.builtin.IRubyObject;
3630

3731
/**
3832
* Interface to be implemented in Ruby for retrieving a new connection.
@@ -49,84 +43,3 @@ public interface ConnectionFactory {
4943
Connection newConnection() throws SQLException;
5044

5145
}
52-
53-
class DataSourceConnectionFactoryImpl implements ConnectionFactory {
54-
55-
private final DataSource dataSource;
56-
final String username, password; // optional
57-
58-
public DataSourceConnectionFactoryImpl(final DataSource dataSource) {
59-
this.dataSource = dataSource;
60-
this.username = null; this.password = null;
61-
}
62-
63-
public DataSourceConnectionFactoryImpl(final DataSource dataSource,
64-
final String username, final String password) {
65-
this.dataSource = dataSource;
66-
this.username = username; this.password = password;
67-
}
68-
69-
@Override
70-
public Connection newConnection() throws SQLException {
71-
if ( username != null ) {
72-
dataSource.getConnection(username, password);
73-
}
74-
return dataSource.getConnection();
75-
}
76-
77-
DataSource getDataSource() { return dataSource; } /* for tests */
78-
79-
}
80-
81-
class DriverConnectionFactoryImpl implements ConnectionFactory {
82-
83-
private final DriverWrapper driverWrapper;
84-
final String url;
85-
final String username, password; // null allowed
86-
87-
public DriverConnectionFactoryImpl(final DriverWrapper driver, final String url) {
88-
this.driverWrapper = driver; this.url = url;
89-
this.username = null; this.password = null;
90-
}
91-
92-
public DriverConnectionFactoryImpl(final DriverWrapper driver, final String url,
93-
final String username, final String password) {
94-
this.driverWrapper = driver; this.url = url;
95-
this.username = username; this.password = password;
96-
}
97-
98-
@Override
99-
public Connection newConnection() throws SQLException {
100-
return driverWrapper.connect(url, username, password);
101-
}
102-
103-
DriverWrapper getDriverWrapper() { return driverWrapper; } /* for tests */
104-
105-
}
106-
107-
// @legacy ActiveRecord::ConnectionAdapters::JdbcDriver
108-
class RubyConnectionFactoryImpl implements ConnectionFactory {
109-
110-
private final IRubyObject driver;
111-
final RubyString url;
112-
final IRubyObject username, password; // null allowed
113-
114-
private final RubyObject contextProvider;
115-
116-
public RubyConnectionFactoryImpl(final IRubyObject driver, final RubyString url,
117-
final IRubyObject username, final IRubyObject password) {
118-
this.driver = driver; this.url = url;
119-
this.username = username; this.password = password;
120-
contextProvider = (RubyObject) driver;
121-
}
122-
123-
@Override
124-
public Connection newConnection() throws SQLException {
125-
final ThreadContext context = contextProvider.getRuntime().getCurrentContext();
126-
final IRubyObject connection = driver.callMethod(context, "connection", new IRubyObject[] { url, username, password });
127-
return (Connection) connection.toJava(Connection.class);
128-
}
129-
130-
IRubyObject getDriver() { return driver; } /* for tests */
131-
132-
}

src/java/arjdbc/jdbc/DataSourceConnectionFactory.java

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,6 @@ public void setPassword(final String password) {
6868

6969
@Override
7070
public Connection newConnection() throws SQLException {
71-
DataSource dataSource = this.dataSource;
7271
// in case DS failed previously look it up again from JNDI :
7372
if (dataSource == null) {
7473
lookupDataSource();
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
/***** BEGIN LICENSE BLOCK *****
2+
* Copyright (c) 2012-2014 Karol Bucek <self@kares.org>
3+
* Copyright (c) 2006-2010 Nick Sieger <nick@nicksieger.com>
4+
* Copyright (c) 2006-2007 Ola Bini <ola.bini@gmail.com>
5+
*
6+
* Permission is hereby granted, free of charge, to any person obtaining
7+
* a copy of this software and associated documentation files (the
8+
* "Software"), to deal in the Software without restriction, including
9+
* without limitation the rights to use, copy, modify, merge, publish,
10+
* distribute, sublicense, and/or sell copies of the Software, and to
11+
* permit persons to whom the Software is furnished to do so, subject to
12+
* the following conditions:
13+
*
14+
* The above copyright notice and this permission notice shall be
15+
* included in all copies or substantial portions of the Software.
16+
*
17+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
18+
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19+
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
20+
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
21+
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
22+
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
23+
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24+
***** END LICENSE BLOCK *****/
25+
26+
package arjdbc.jdbc;
27+
28+
import java.sql.Connection;
29+
import java.sql.SQLException;
30+
31+
import org.jruby.RubyObject;
32+
import org.jruby.RubyString;
33+
import org.jruby.runtime.ThreadContext;
34+
import org.jruby.runtime.builtin.IRubyObject;
35+
36+
// @legacy ActiveRecord::ConnectionAdapters::JdbcDriver
37+
class RubyConnectionFactory implements ConnectionFactory {
38+
39+
private final IRubyObject driver;
40+
final RubyString url;
41+
final IRubyObject username, password; // null allowed
42+
43+
private final RubyObject contextProvider;
44+
45+
public RubyConnectionFactory(final IRubyObject driver, final RubyString url,
46+
final IRubyObject username, final IRubyObject password) {
47+
this.driver = driver; this.url = url;
48+
this.username = username; this.password = password;
49+
contextProvider = (RubyObject) driver;
50+
}
51+
52+
@Override
53+
public Connection newConnection() throws SQLException {
54+
final ThreadContext context = contextProvider.getRuntime().getCurrentContext();
55+
final IRubyObject connection = driver.callMethod(context, "connection", new IRubyObject[] { url, username, password });
56+
return (Connection) connection.toJava(Connection.class);
57+
}
58+
59+
IRubyObject getDriver() { return driver; } /* for tests */
60+
61+
}

src/java/arjdbc/jdbc/RubyJdbcConnection.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1824,7 +1824,7 @@ private ConnectionFactory setDriverFactory(final ThreadContext context) {
18241824
return factory;
18251825
}
18261826
else {
1827-
setConnectionFactory(factory = new RubyConnectionFactoryImpl(
1827+
setConnectionFactory(factory = new RubyConnectionFactory(
18281828
driver_instance, context.runtime.newString(jdbcURL),
18291829
( username.isNil() ? username : username.asString() ),
18301830
( password.isNil() ? password : password.asString() )

test/db/jndi_mysql_config.rb

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,4 +19,11 @@
1919
data_source.user = MYSQL_CONFIG[:username] if MYSQL_CONFIG[:username]
2020
data_source.password = MYSQL_CONFIG[:password] if MYSQL_CONFIG[:password]
2121

22+
# must set these to match non-jndi setup
23+
data_source.cache_default_timezone = false
24+
data_source.server_timezone = java.util.TimeZone.getDefault.getID
25+
data_source.use_legacy_datetime_code = false
26+
data_source.zero_date_time_behavior = 'convertToNull'
27+
data_source.jdbc_compliant_truncation = false
28+
2229
javax.naming.InitialContext.new.bind JNDI_MYSQL_CONFIG[:jndi], data_source

test/jdbc_connection_test.rb

Lines changed: 1 addition & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -307,7 +307,7 @@ def newConnection; @real_factory.newConnection end
307307
def startup; clear_cached_jdbc_connection_factory end
308308

309309
def setup
310-
config = JDBC_CONFIG.merge :retry_count => 1, :configure_connection => false
310+
config = JDBC_CONFIG.merge :configure_connection => false
311311
ActiveRecord::Base.establish_connection config
312312

313313
@real_connection_factory = get_jdbc_connection_factory
@@ -323,33 +323,6 @@ def teardown
323323
self.class.clear_cached_jdbc_connection_factory
324324
end
325325

326-
test 'getConnection() works' do
327-
ActiveRecord::Base.connection.execute 'SELECT 42' # MySQL
328-
end
329-
330-
test 'getConnection() fails' do
331-
@connection_factory.stubs(:newConnection).
332-
raises( java.sql.SQLException.new('failing twice 1') ).then.
333-
raises( java.sql.SQLException.new('failing twice 2') ).then.
334-
returns( @real_connection_factory.newConnection )
335-
336-
begin
337-
ActiveRecord::Base.connection.execute 'SELECT 1'
338-
fail('connection unexpectedly retrieved')
339-
rescue ActiveRecord::JDBCError => e
340-
assert e.cause
341-
assert_match /failing twice/, e.sql_exception.message
342-
end
343-
end if ar_version('3.0') # NOTE: for some reason fails on 2.3
344-
345-
test 'getConnection() works due retry count' do
346-
@connection_factory.stubs(:newConnection).
347-
raises( java.sql.SQLException.new('failing once') ).then.
348-
returns( @real_connection_factory.newConnection )
349-
350-
ActiveRecord::Base.connection.execute 'SELECT 1'
351-
end
352-
353326
class ConnectionDelegate
354327
include java.sql.Connection
355328

0 commit comments

Comments
 (0)