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
DB2Adapter, FirebirdAdapter, H2Adapter, HsqldbAdapter, InformixAdapter, OracleAdapter
Constant Summary collapse
- ADAPTER_NAME =
'JDBC'
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!, #really_valid?, #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.
48 49 50 |
# File 'lib/arjdbc/jdbc/adapter.rb', line 48 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.
127 128 129 |
# File 'lib/arjdbc/jdbc/adapter.rb', line 127 def self.arel2_visitors(config) { 'jdbc' => ::Arel::Visitors::ToSql } end |
.configure_arel2_visitors(config) ⇒ Object
re-implemented - no longer used
133 134 135 136 137 138 139 140 141 142 143 144 145 |
# File 'lib/arjdbc/jdbc/adapter.rb', line 133 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.
102 103 104 |
# File 'lib/arjdbc/jdbc/adapter.rb', line 102 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.
74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 |
# File 'lib/arjdbc/jdbc/adapter.rb', line 74 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
226 227 228 |
# File 'lib/arjdbc/jdbc/adapter.rb', line 226 def columns(table_name, name = nil) @connection.columns(table_name.to_s) end |
#data_source_exists?(name) ⇒ Boolean
314 315 316 |
# File 'lib/arjdbc/jdbc/adapter.rb', line 314 def data_source_exists?(name) table_exists?(name) end |
#data_sources ⇒ Object
309 310 311 |
# File 'lib/arjdbc/jdbc/adapter.rb', line 309 def data_sources tables end |
#database_name ⇒ Object
Returns the underlying database name.
186 187 188 |
# File 'lib/arjdbc/jdbc/adapter.rb', line 186 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.
245 246 247 248 249 250 251 252 253 |
# File 'lib/arjdbc/jdbc/adapter.rb', line 245 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).
267 268 269 270 271 272 273 274 |
# File 'lib/arjdbc/jdbc/adapter.rb', line 267 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.
287 288 289 290 291 292 293 294 295 |
# File 'lib/arjdbc/jdbc/adapter.rb', line 287 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
334 335 336 |
# File 'lib/arjdbc/jdbc/adapter.rb', line 334 def foreign_keys(table_name) @connection.foreign_keys(table_name) end |
#indexes(table_name, name = nil, schema_name = nil) ⇒ Object
319 320 321 |
# File 'lib/arjdbc/jdbc/adapter.rb', line 319 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).
114 115 116 117 118 119 120 121 |
# File 'lib/arjdbc/jdbc/adapter.rb', line 114 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.
62 63 64 |
# File 'lib/arjdbc/jdbc/adapter.rb', line 62 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.
54 55 56 57 |
# File 'lib/arjdbc/jdbc/adapter.rb', line 54 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.
361 362 363 364 365 366 367 368 369 370 371 |
# File 'lib/arjdbc/jdbc/adapter.rb', line 361 def last_inserted_id(result) if result.is_a?(Hash) || result.is_a?(ActiveRecord::Result) # If table does not have primary key defined return nil if result.first.blank? 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.
167 168 169 |
# File 'lib/arjdbc/jdbc/adapter.rb', line 167 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.
151 152 153 154 155 156 157 |
# File 'lib/arjdbc/jdbc/adapter.rb', line 151 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
324 325 326 |
# File 'lib/arjdbc/jdbc/adapter.rb', line 324 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
329 330 331 |
# File 'lib/arjdbc/jdbc/adapter.rb', line 329 def primary_keys(table) @connection.primary_keys(table) end |
#structure_dump ⇒ Object
Abstract adapter default implementation does nothing silently.
173 174 175 |
# File 'lib/arjdbc/jdbc/adapter.rb', line 173 def structure_dump raise NotImplementedError, "structure_dump not supported" end |
#supports_foreign_keys? ⇒ Boolean
Does our database (+ its JDBC driver) support foreign-keys?
341 342 343 |
# File 'lib/arjdbc/jdbc/adapter.rb', line 341 def supports_foreign_keys? @connection.supports_foreign_keys? end |
#supports_migrations? ⇒ true
JDBC adapters support migration.
180 181 182 |
# File 'lib/arjdbc/jdbc/adapter.rb', line 180 def supports_migrations? true end |
#supports_views? ⇒ Boolean
231 232 233 |
# File 'lib/arjdbc/jdbc/adapter.rb', line 231 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
303 304 305 306 |
# File 'lib/arjdbc/jdbc/adapter.rb', line 303 def table_exists?(name) return false unless name @connection.table_exists?(name) # schema_name = nil end |
#tables(name = nil) ⇒ Object
298 299 300 |
# File 'lib/arjdbc/jdbc/adapter.rb', line 298 def tables(name = nil) @connection.tables end |
#update_lob_value(record, column, value) ⇒ Object
353 354 355 |
# File 'lib/arjdbc/jdbc/adapter.rb', line 353 def update_lob_value(record, column, value) @connection.update_lob_value(record, column, value) end |
#valid_type?(type) ⇒ Boolean
160 161 162 |
# File 'lib/arjdbc/jdbc/adapter.rb', line 160 def valid_type?(type) ! native_database_types[type].nil? end |
#write_large_object(*args) ⇒ Object
Rather use #update_lob_value instead.
346 347 348 |
# File 'lib/arjdbc/jdbc/adapter.rb', line 346 def write_large_object(*args) @connection.write_large_object(*args) end |