Class: ActiveRecord::ConnectionAdapters::JdbcAdapter
- Inherits:
-
AbstractAdapter
- Object
- AbstractAdapter
- ActiveRecord::ConnectionAdapters::JdbcAdapter
- Includes:
- ActiveRecord::ConnectionAdapters::Jdbc::ConnectionPoolCallbacks, ArJdbc::Abstract::ConnectionManagement, ArJdbc::Abstract::Core, ArJdbc::Abstract::DatabaseStatements, ArJdbc::Abstract::TransactionSupport
- Defined in:
- lib/arjdbc/jdbc/adapter.rb
Overview
Built on top of ActiveRecord::ConnectionAdapters::AbstractAdapter
which
provides the abstract interface for database-specific functionality, this
class serves 2 purposes in AR-JDBC :
- as a base class for sub-classes
- usable standalone (or with a mixed in adapter spec module)
Historically this class is mostly been used standalone and that's still a
valid use-case esp. since (with it's arjdbc.jdbc.RubyJdbcConnectionClass
)
JDBC provides a unified interface for all databases in Java it tries to do
it's best implementing all ActiveRecord
functionality on top of that.
This might no be perfect that's why it checks for a config[:adapter_spec]
module (or tries to resolve one from the JDBC driver's meta-data) and if
the database has "extended" AR-JDBC support mixes in the given module for
each adapter instance.
This is sufficient for most database specific specs we support, but for
compatibility with native (MRI) adapters it's perfectly fine to sub-class
the adapter and override some of its API methods.
Direct Known Subclasses
FirebirdAdapter, H2Adapter, HsqldbAdapter, InformixAdapter, MSSQLAdapter, OracleAdapter
Constant Summary collapse
- ADAPTER_NAME =
'JDBC'.freeze
Constants included from ArJdbc::Abstract::DatabaseStatements
ArJdbc::Abstract::DatabaseStatements::NO_BINDS
Instance Attribute Summary collapse
-
#prepared_statements ⇒ Object
readonly
Returns the value of attribute prepared_statements.
Attributes included from ArJdbc::Abstract::Core
Class Method Summary collapse
-
.arel2_visitors(config) ⇒ Hash
deprecated
Deprecated.
re-implemented - no longer used
-
.configure_arel2_visitors(config) ⇒ Object
deprecated
Deprecated.
re-implemented - no longer used
-
.prepared_statements?(config) ⇒ Boolean
protected
Allows changing the prepared statements setting for this connection.
Instance Method Summary collapse
-
#adapter_name ⇒ String
The 'JDBC' adapter name.
-
#adapter_spec(config) ⇒ Module
Locate the specialized (database specific) adapter specification module if one exists based on provided configuration data.
- #columns(table_name, name = nil) ⇒ Object
- #data_source_exists?(name) ⇒ Boolean
- #data_sources ⇒ Object
-
#database_name ⇒ Object
Returns the underlying database name.
-
#exec_query_raw(sql, name = 'SQL', binds = []) {|v1, v2| ... } ⇒ Array
Similar to ArJdbc::Abstract::DatabaseStatements#exec_query except it returns "raw" results in an array where each rows is a hash with keys as columns (just like Rails used to do up until 3.0) instead of wrapping them in a #ActiveRecord#ActiveRecord::Result.
-
#execute(sql, name = nil, binds = nil) ⇒ Object
Executes the SQL statement in the context of this connection.
-
#execute_quietly(sql, name = 'SQL') ⇒ Object
Kind of
execute(sql) rescue nil
but logging failures at debug level only. - #foreign_keys(table_name) ⇒ Object
- #indexes(table_name, name = nil, schema_name = nil) ⇒ Object
-
#is_a?(klass) ⇒ Boolean
Will return true even when native adapter classes passed in e.g.
-
#jdbc_column_class ⇒ Object
Returns the (JDBC)
ActiveRecord
column class for this adapter. -
#jdbc_connection_class(spec) ⇒ Object
Returns the (JDBC) connection class to be used for this adapter.
-
#last_inserted_id(result) ⇒ Integer, NilClass
protected
Take an id from the result of an INSERT query.
-
#modify_types(types) ⇒ Object
Allows for modification of the detected native types.
-
#native_database_types ⇒ Hash
DB specific types are detected but adapter specs (or extenders) are expected to hand tune these types for concrete databases.
- #pk_and_sequence_for(table) ⇒ Object
-
#prepared_statements? ⇒ Boolean
protected
Whether
:prepared_statements
are to be used. - #primary_keys(table) ⇒ Object
-
#structure_dump ⇒ Object
Abstract adapter default implementation does nothing silently.
-
#supports_foreign_keys? ⇒ Boolean
Does our database (+ its JDBC driver) support foreign-keys?.
-
#supports_migrations? ⇒ true
JDBC adapters support migration.
- #supports_views? ⇒ Boolean
-
#table_definition ⇒ Object
protected
aliasing #create_table_definition as #table_definition :.
- #table_exists?(name) ⇒ Boolean
- #tables(name = nil) ⇒ Object
- #update_lob_value(record, column, value) ⇒ Object
- #valid_type?(type) ⇒ Boolean
-
#write_large_object(*args) ⇒ Object
deprecated
Deprecated.
Rather use #update_lob_value instead.
Methods included from ArJdbc::Abstract::TransactionSupport
#begin_db_transaction, #begin_isolated_db_transaction, #commit_db_transaction, #create_savepoint, #exec_rollback_db_transaction, #exec_rollback_to_savepoint, #release_savepoint, #supports_savepoints?, #supports_transaction_isolation?
Methods included from ArJdbc::Abstract::DatabaseStatements
#exec_insert, #exec_query, #exec_update, #select_all
Methods included from ArJdbc::Abstract::ConnectionManagement
#active?, #disconnect!, #reconnect!
Methods included from ArJdbc::Abstract::Core
#extract_raw_bind_values, #initialize, #jdbc_connection, #log, #translate_exception, #translate_exception_class
Methods included from ActiveRecord::ConnectionAdapters::Jdbc::ConnectionPoolCallbacks
Instance Attribute Details
#prepared_statements ⇒ Object (readonly)
Returns the value of attribute prepared_statements.
46 47 48 |
# File 'lib/arjdbc/jdbc/adapter.rb', line 46 def prepared_statements @prepared_statements end |
Class Method Details
.arel2_visitors(config) ⇒ Hash
re-implemented - no longer used
If there's a self.arel2_visitors(config)
method on the adapter
spec than it is preferred and will be used instead of this one.
125 126 127 |
# File 'lib/arjdbc/jdbc/adapter.rb', line 125 def self.arel2_visitors(config) { 'jdbc' => ::Arel::Visitors::ToSql } end |
.configure_arel2_visitors(config) ⇒ Object
re-implemented - no longer used
131 132 133 134 135 136 137 138 139 140 141 142 143 |
# File 'lib/arjdbc/jdbc/adapter.rb', line 131 def self.configure_arel2_visitors(config) visitors = ::Arel::Visitors::VISITORS klass = config[:adapter_spec] klass = self unless klass.respond_to?(:arel2_visitors) visitor = nil klass.arel2_visitors(config).each do |name, arel| visitors[name] = ( visitor = arel ) end if visitor && config[:adapter] =~ /^(jdbc|jndi)$/ visitors[ config[:adapter] ] = visitor end visitor end |
.prepared_statements?(config) ⇒ Boolean (protected)
Allows changing the prepared statements setting for this connection. def prepared_statements=(statements) @prepared_statements = statements end
425 426 427 428 429 |
# File 'lib/arjdbc/jdbc/adapter.rb', line 425 def self.prepared_statements?(config) config.key?(:prepared_statements) ? type_cast_config_to_boolean(config.fetch(:prepared_statements)) : false # off by default - NOTE: on AR 4.x it's on by default !? end |
Instance Method Details
#adapter_name ⇒ String
Returns the 'JDBC' adapter name.
100 101 102 |
# File 'lib/arjdbc/jdbc/adapter.rb', line 100 def adapter_name ADAPTER_NAME end |
#adapter_spec(config) ⇒ Module
Locate the specialized (database specific) adapter specification module
if one exists based on provided configuration data. This module will than
extend an instance of the adapter (unless an :adapter_class
provided).
This method is called during ArJdbc::Abstract::Core#initialize unless an explicit
config[:adapter_spec]
is set.
72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 |
# File 'lib/arjdbc/jdbc/adapter.rb', line 72 def adapter_spec(config) dialect = (config[:dialect] || config[:driver]).to_s ::ArJdbc.modules.each do |constant| # e.g. ArJdbc::MySQL if constant.respond_to?(:adapter_matcher) spec = constant.adapter_matcher(dialect, config) return spec if spec end end unless config.key?(:dialect) begin # does nothing unless config[:jndi] || config[:data_source] dialect = ::ArJdbc.(config) do || config[:dialect] = .getDatabaseProductName end return adapter_spec(config) if dialect # re-try matching with :dialect rescue => e ::ArJdbc.warn("failed to set :dialect from database meda-data: #{e.inspect}") else return adapter_spec(config) # re-try matching a spec with set config[:dialect] end end nil end |
#columns(table_name, name = nil) ⇒ Object
224 225 226 |
# File 'lib/arjdbc/jdbc/adapter.rb', line 224 def columns(table_name, name = nil) @connection.columns(table_name.to_s) end |
#data_source_exists?(name) ⇒ Boolean
318 319 320 |
# File 'lib/arjdbc/jdbc/adapter.rb', line 318 def data_source_exists?(name) table_exists?(name) end |
#data_sources ⇒ Object
313 314 315 |
# File 'lib/arjdbc/jdbc/adapter.rb', line 313 def data_sources tables end |
#database_name ⇒ Object
Returns the underlying database name.
184 185 186 |
# File 'lib/arjdbc/jdbc/adapter.rb', line 184 def database_name @connection.database_name end |
#exec_query_raw(sql, name = 'SQL', binds = []) {|v1, v2| ... } ⇒ Array
Similar to ArJdbc::Abstract::DatabaseStatements#exec_query except it returns "raw" results in an array where each rows is a hash with keys as columns (just like Rails used to do up until 3.0) instead of wrapping them in a ActiveRecord::ConnectionAdapters::JdbcAdapter#ActiveRecord#ActiveRecord::Result. In case a block is given it will yield each row from the result set instead of returning mapped query results in an array.
243 244 245 246 247 248 249 250 251 |
# File 'lib/arjdbc/jdbc/adapter.rb', line 243 def exec_query_raw(sql, name = 'SQL', binds = [], &block) sql = to_sql(sql, binds) if sql.respond_to?(:to_sql) if prepared_statements? log(sql, name, binds) { @connection.execute_query_raw(sql, binds, &block) } else log(sql, name) { @connection.execute_query_raw(sql, &block) } end end |
#execute(sql, name = nil, binds = nil) ⇒ Object
This method does not use prepared statements.
The method does not emulate various "native" execute
results on MRI.
Executes the SQL statement in the context of this connection.
The return value from this method depends on the SQL type (whether
it's a SELECT, INSERT etc.). For INSERTs a generated id might get
returned while for UPDATE statements the affected row count.
Please note that this method returns "raw" results (in an array) for
statements that return a result set, while ArJdbc::Abstract::DatabaseStatements#exec_query is expected to
return a ActiveRecord::Result
(since AR 3.1).
271 272 273 274 275 276 277 278 |
# File 'lib/arjdbc/jdbc/adapter.rb', line 271 def execute(sql, name = nil, binds = nil) sql = to_sql(sql, binds) if binds if name == :skip_logging _execute(sql, name) else log(sql, name) { _execute(sql, name) } end end |
#execute_quietly(sql, name = 'SQL') ⇒ Object
Kind of execute(sql) rescue nil
but logging failures at debug level only.
291 292 293 294 295 296 297 298 299 |
# File 'lib/arjdbc/jdbc/adapter.rb', line 291 def execute_quietly(sql, name = 'SQL') log(sql, name) do begin _execute(sql) rescue => e logger.debug("#{e.class}: #{e.}: #{sql}") end end end |
#foreign_keys(table_name) ⇒ Object
338 339 340 |
# File 'lib/arjdbc/jdbc/adapter.rb', line 338 def foreign_keys(table_name) @connection.foreign_keys(table_name) end |
#indexes(table_name, name = nil, schema_name = nil) ⇒ Object
323 324 325 |
# File 'lib/arjdbc/jdbc/adapter.rb', line 323 def indexes(table_name, name = nil, schema_name = nil) @connection.indexes(table_name, name, schema_name) end |
#is_a?(klass) ⇒ Boolean
Will return true even when native adapter classes passed in
e.g. jdbc_adapter.is_a? ConnectionAdapter::PostgresqlAdapter
This is only necessary (for built-in adapters) when
config[:adapter_class]
is forced to nil
and the :adapter_spec
module is used to extend the JdbcAdapter
, otherwise we replace the
class constants for built-in adapters (MySQL, PostgreSQL and SQLite3).
112 113 114 115 116 117 118 119 |
# File 'lib/arjdbc/jdbc/adapter.rb', line 112 def is_a?(klass) # This is to fake out current_adapter? conditional logic in AR tests if klass.is_a?(Class) && klass.name =~ /#{adapter_name}Adapter$/i true else super end end |
#jdbc_column_class ⇒ Object
Returns the (JDBC) ActiveRecord
column class for this adapter.
This is used by (database specific) spec modules to override the class.
60 61 62 |
# File 'lib/arjdbc/jdbc/adapter.rb', line 60 def jdbc_column_class ::ActiveRecord::ConnectionAdapters::JdbcColumn end |
#jdbc_connection_class(spec) ⇒ Object
Returns the (JDBC) connection class to be used for this adapter. This is used by (database specific) spec modules to override the class used assuming some of the available methods have been re-defined.
52 53 54 55 |
# File 'lib/arjdbc/jdbc/adapter.rb', line 52 def jdbc_connection_class(spec) connection_class = spec.jdbc_connection_class if spec && spec.respond_to?(:jdbc_connection_class) connection_class ? connection_class : ::ActiveRecord::ConnectionAdapters::JdbcConnection end |
#last_inserted_id(result) ⇒ Integer, NilClass (protected)
Take an id from the result of an INSERT query.
365 366 367 368 369 370 371 |
# File 'lib/arjdbc/jdbc/adapter.rb', line 365 def last_inserted_id(result) if result.is_a?(Hash) || result.is_a?(ActiveRecord::Result) result.first.first[1] # .first = { "id"=>1 } .first = [ "id", 1 ] else result end end |
#modify_types(types) ⇒ Object
Allows for modification of the detected native types.
165 166 167 |
# File 'lib/arjdbc/jdbc/adapter.rb', line 165 def modify_types(types) types end |
#native_database_types ⇒ Hash
DB specific types are detected but adapter specs (or extenders) are expected to hand tune these types for concrete databases.
149 150 151 152 153 154 155 |
# File 'lib/arjdbc/jdbc/adapter.rb', line 149 def native_database_types @native_database_types ||= begin types = @connection.native_database_types modify_types(types) types end end |
#pk_and_sequence_for(table) ⇒ Object
328 329 330 |
# File 'lib/arjdbc/jdbc/adapter.rb', line 328 def pk_and_sequence_for(table) ( key = primary_key(table) ) ? [ key, nil ] : nil end |
#prepared_statements? ⇒ Boolean (protected)
Returns whether :prepared_statements
are to be used.
414 415 416 417 |
# File 'lib/arjdbc/jdbc/adapter.rb', line 414 def prepared_statements? return @prepared_statements unless (@prepared_statements ||= nil).nil? @prepared_statements = self.class.prepared_statements?(config) end |
#primary_keys(table) ⇒ Object
333 334 335 |
# File 'lib/arjdbc/jdbc/adapter.rb', line 333 def primary_keys(table) @connection.primary_keys(table) end |
#structure_dump ⇒ Object
Abstract adapter default implementation does nothing silently.
171 172 173 |
# File 'lib/arjdbc/jdbc/adapter.rb', line 171 def structure_dump raise NotImplementedError, "structure_dump not supported" end |
#supports_foreign_keys? ⇒ Boolean
Does our database (+ its JDBC driver) support foreign-keys?
345 346 347 |
# File 'lib/arjdbc/jdbc/adapter.rb', line 345 def supports_foreign_keys? @connection.supports_foreign_keys? end |
#supports_migrations? ⇒ true
JDBC adapters support migration.
178 179 180 |
# File 'lib/arjdbc/jdbc/adapter.rb', line 178 def supports_migrations? true end |
#supports_views? ⇒ Boolean
229 230 231 |
# File 'lib/arjdbc/jdbc/adapter.rb', line 229 def supports_views? @connection.supports_views? end |
#table_definition ⇒ Object (protected)
aliasing #create_table_definition as #table_definition :
374 |
# File 'lib/arjdbc/jdbc/adapter.rb', line 374 alias table_definition create_table_definition |
#table_exists?(name) ⇒ Boolean
307 308 309 310 |
# File 'lib/arjdbc/jdbc/adapter.rb', line 307 def table_exists?(name) return false unless name @connection.table_exists?(name) # schema_name = nil end |
#tables(name = nil) ⇒ Object
302 303 304 |
# File 'lib/arjdbc/jdbc/adapter.rb', line 302 def tables(name = nil) @connection.tables end |
#update_lob_value(record, column, value) ⇒ Object
357 358 359 |
# File 'lib/arjdbc/jdbc/adapter.rb', line 357 def update_lob_value(record, column, value) @connection.update_lob_value(record, column, value) end |
#valid_type?(type) ⇒ Boolean
158 159 160 |
# File 'lib/arjdbc/jdbc/adapter.rb', line 158 def valid_type?(type) ! native_database_types[type].nil? end |
#write_large_object(*args) ⇒ Object
Rather use #update_lob_value instead.
350 351 352 |
# File 'lib/arjdbc/jdbc/adapter.rb', line 350 def write_large_object(*args) @connection.write_large_object(*args) end |