Skip to content

Commit faf2e96

Browse files
committed
Fix statement caching
Using config[:prepared_statements] is not reliable because of different defaults. Use the proper method instead. Move the "prepare_statement" call to Java to ensure proper exception wrapping. Also, while at it, align the method name "cached_statement_key" with Rails to make PG test actually work.
1 parent ebea905 commit faf2e96

File tree

4 files changed

+23
-7
lines changed

4 files changed

+23
-7
lines changed

lib/arjdbc/abstract/database_statements.rb

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,8 +26,8 @@ def exec_query(sql, name = nil, binds = NO_BINDS, prepare: false)
2626
log(sql, name) { @connection.execute_query(sql) }
2727
else
2828
log(sql, name, binds) do
29-
# It seems that #supports_statement_cache? is defined but isn't checked before setting "prepare" (AR 5.0)
30-
cached_statement = fetch_cached_statement(sql) if prepare && supports_statement_cache?
29+
# this is different from normal AR that always caches
30+
cached_statement = fetch_cached_statement(sql) if prepare && @jdbc_statement_cache_enabled
3131
@connection.execute_prepared_query(sql, binds, cached_statement)
3232
end
3333
end

lib/arjdbc/abstract/statement_cache.rb

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ def initialize(*args) # (connection, logger, config)
2323
# Only say we support the statement cache if we are using prepared statements
2424
# and have a max number of statements defined
2525
statement_limit = self.class.type_cast_config_to_integer(config[:statement_limit])
26-
@jdbc_statement_cache_enabled = config[:prepared_statements] && (statement_limit.nil? || statement_limit > 0)
26+
@jdbc_statement_cache_enabled = prepared_statements && (statement_limit.nil? || statement_limit > 0)
2727

2828
@statements = StatementPool.new(statement_limit) # AR (5.0) expects this to be stored as @statements
2929
end
@@ -34,11 +34,11 @@ def clear_cache!
3434
end
3535

3636
def delete_cached_statement(sql)
37-
@statements.delete(cached_statement_key(sql))
37+
@statements.delete(sql_key(sql))
3838
end
3939

4040
def fetch_cached_statement(sql)
41-
@statements[cached_statement_key(sql)] ||= @connection.connection.prepare_statement(sql)
41+
@statements[sql_key(sql)] ||= @connection.prepare_statement(sql)
4242
end
4343

4444
def supports_statement_cache?
@@ -49,7 +49,7 @@ def supports_statement_cache?
4949

5050
# This should be overridden by the adapter if the sql itself
5151
# is not enough to make the key unique
52-
def cached_statement_key(sql)
52+
def sql_key(sql)
5353
sql
5454
end
5555

lib/arjdbc/postgresql/adapter.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -736,7 +736,7 @@ def jdbc_connection_class(spec)
736736

737737
# Prepared statements aren't schema aware so we need to make sure we
738738
# store different PreparedStatement objects for different schemas
739-
def cached_statement_key(sql)
739+
def sql_key(sql)
740740
"#{schema_search_path}-#{sql}"
741741
end
742742

src/java/arjdbc/jdbc/RubyJdbcConnection.java

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1112,6 +1112,22 @@ public IRubyObject call(final Connection connection) throws SQLException {
11121112
});
11131113
}
11141114

1115+
/**
1116+
* Prepares a query, returns a wrapped PreparedStatement. This takes care of exception wrapping
1117+
* @param context which context this method is executing on.
1118+
* @param sql the query to prepare-
1119+
* @return a Ruby <code>PreparedStatement</code>
1120+
*/
1121+
@JRubyMethod(required = 1)
1122+
public IRubyObject prepare_statement(final ThreadContext context, final IRubyObject sql) {
1123+
return withConnection(context, new Callable<IRubyObject>() {
1124+
public IRubyObject call(Connection connection) throws SQLException {
1125+
final String query = sql.convertToString().getUnicodeValue();
1126+
return JavaUtil.convertJavaToRuby(context.runtime, connection.prepareStatement(query));
1127+
}
1128+
});
1129+
}
1130+
11151131
// Called from exec_query in abstract/database_statements
11161132
/**
11171133
* Executes a query and returns the (AR) result. There are three parameters:

0 commit comments

Comments
 (0)