Skip to content

Commit

Permalink
redo binds passing - due some AR internals PS logging now shows values
Browse files Browse the repository at this point in the history
- translate_exception - do not set backtrace if exception did not change
- log has type_casted_binds default to nil and since/if we're not passing
  the log subscriber will on-demand generate those (only if log.debug?)
  win-win esp. since with JDBC we use whatever (raw) binds we get ...
  • Loading branch information
kares committed Dec 18, 2017
1 parent df0cdfd commit f3d76a3
Show file tree
Hide file tree
Showing 2 changed files with 37 additions and 15 deletions.
35 changes: 31 additions & 4 deletions lib/arjdbc/abstract/core.rb
Original file line number Diff line number Diff line change
Expand Up @@ -32,18 +32,45 @@ def jdbc_connection(unwrap = nil)
raw_connection.jdbc_connection(unwrap)
end

protected

def translate_exception_class(e, sql)
begin
message = "#{e.class.name}: #{e.message}: #{sql}"
rescue Encoding::CompatibilityError
message = "#{e.class.name}: #{e.message.force_encoding sql.encoding}: #{sql}"
end

exception = translate_exception(e, message)
exception.set_backtrace e.backtrace unless e.equal?(exception)
exception
end

def translate_exception(e, message)
# we shall not translate native "Java" exceptions as they might
# swallow an ArJdbc / driver bug into a AR::StatementInvalid ...
# swallow an ArJdbc / driver bug into an AR::StatementInvalid !
return e if e.is_a?(Java::JavaLang::Throwable)

case e
when ActiveModel::RangeError, TypeError, SystemExit, SignalException, NoMemoryError then e
# NOTE: wraps AR::JDBCError into AR::StatementInvalid, desired ?!
else super
when SystemExit, SignalException, NoMemoryError then e
when ActiveModel::RangeError, TypeError then e
else ActiveRecord::StatementInvalid.new(message)
end
end

def log(sql, name = "SQL", binds = [], type_casted_binds = nil, statement_name = nil)
@instrumenter.instrument(
"sql.active_record",
sql: sql,
name: name,
binds: binds,
type_casted_binds: type_casted_binds,
statement_name: statement_name,
connection_id: object_id) { yield }
rescue => e
raise translate_exception_class(e, sql)
end

end
end
end
17 changes: 6 additions & 11 deletions lib/arjdbc/abstract/database_statements.rb
Original file line number Diff line number Diff line change
@@ -1,17 +1,20 @@
# frozen_string_literal: true

module ArJdbc
module Abstract

# This provides the basic interface for interacting with the
# database for JDBC based adapters
module DatabaseStatements

NO_BINDS = [].freeze

# It appears that at this point (AR 5.0) "prepare" should only ever be true
# if prepared statements are enabled
def exec_query(sql, name = nil, binds = [], prepare: false)
def exec_query(sql, name = nil, binds = NO_BINDS, prepare: false)
if without_prepared_statement?(binds)
execute(sql, name)
else
binds = convert_legacy_binds_to_attributes(binds) if binds.first.is_a?(Array)
log(sql, name, binds) do
# It seems that #supports_statement_cache? is defined but isn't checked before setting "prepare" (AR 5.0)
cached_statement = fetch_cached_statement(sql) if prepare && supports_statement_cache?
Expand All @@ -20,7 +23,7 @@ def exec_query(sql, name = nil, binds = [], prepare: false)
end
end

def exec_update(sql, name = nil, binds = [])
def exec_update(sql, name = nil, binds = NO_BINDS)
if without_prepared_statement?(binds)
log(sql, name) { @connection.execute_update(sql, nil) }
else
Expand All @@ -33,14 +36,6 @@ def execute(sql, name = nil)
log(sql, name) { @connection.execute(sql) }
end

private

def convert_legacy_binds_to_attributes(binds)
binds.map do |column, value|
ActiveRecord::Relation::QueryAttribute.new(nil, type_cast(value, column), ActiveModel::Type::Value.new)
end
end

end
end
end

0 comments on commit f3d76a3

Please sign in to comment.