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
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.
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 #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 nilbut 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)
ActiveRecordcolumn 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_statementsare 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_update, #internal_exec_query, #select_all
Methods included from ArJdbc::Abstract::ConnectionManagement
#active?, #disconnect!, #really_valid?
Methods included from ArJdbc::Abstract::Core
Methods included from ActiveRecord::ConnectionAdapters::Jdbc::ConnectionPoolCallbacks
Instance Attribute Details
#prepared_statements ⇒ Object (readonly)
Returns the value of attribute prepared_statements.
47 48 49 |
# File 'lib/arjdbc/jdbc/adapter.rb', line 47 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.
126 127 128 |
# File 'lib/arjdbc/jdbc/adapter.rb', line 126 def self.arel2_visitors(config) { 'jdbc' => ::Arel::Visitors::ToSql } end |
.configure_arel2_visitors(config) ⇒ Object
re-implemented - no longer used
132 133 134 135 136 137 138 139 140 141 142 143 144 |
# File 'lib/arjdbc/jdbc/adapter.rb', line 132 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
424 425 426 427 428 |
# File 'lib/arjdbc/jdbc/adapter.rb', line 424 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
101 102 103 |
# File 'lib/arjdbc/jdbc/adapter.rb', line 101 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.
73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 |
# File 'lib/arjdbc/jdbc/adapter.rb', line 73 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
225 226 227 |
# File 'lib/arjdbc/jdbc/adapter.rb', line 225 def columns(table_name, name = nil) @connection.columns(table_name.to_s) end |
#data_source_exists?(name) ⇒ Boolean
313 314 315 |
# File 'lib/arjdbc/jdbc/adapter.rb', line 313 def data_source_exists?(name) table_exists?(name) end |
#data_sources ⇒ Object
308 309 310 |
# File 'lib/arjdbc/jdbc/adapter.rb', line 308 def data_sources tables end |
#database_name ⇒ Object
Returns the underlying database name.
185 186 187 |
# File 'lib/arjdbc/jdbc/adapter.rb', line 185 def database_name @connection.database_name end |
#exec_query_raw(sql, name = 'SQL', binds = []) {|v1, v2| ... } ⇒ Array
Similar to #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.
244 245 246 247 248 249 250 251 252 |
# File 'lib/arjdbc/jdbc/adapter.rb', line 244 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 #exec_query is expected to
return a ActiveRecord::Result (since AR 3.1).
266 267 268 269 270 271 272 273 |
# File 'lib/arjdbc/jdbc/adapter.rb', line 266 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.
286 287 288 289 290 291 292 293 294 |
# File 'lib/arjdbc/jdbc/adapter.rb', line 286 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
333 334 335 |
# File 'lib/arjdbc/jdbc/adapter.rb', line 333 def foreign_keys(table_name) @connection.foreign_keys(table_name) end |
#indexes(table_name, name = nil, schema_name = nil) ⇒ Object
318 319 320 |
# File 'lib/arjdbc/jdbc/adapter.rb', line 318 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).
113 114 115 116 117 118 119 120 |
# File 'lib/arjdbc/jdbc/adapter.rb', line 113 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.
61 62 63 |
# File 'lib/arjdbc/jdbc/adapter.rb', line 61 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.
53 54 55 56 |
# File 'lib/arjdbc/jdbc/adapter.rb', line 53 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.
360 361 362 363 364 365 366 367 368 369 370 |
# File 'lib/arjdbc/jdbc/adapter.rb', line 360 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.
166 167 168 |
# File 'lib/arjdbc/jdbc/adapter.rb', line 166 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.
150 151 152 153 154 155 156 |
# File 'lib/arjdbc/jdbc/adapter.rb', line 150 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
323 324 325 |
# File 'lib/arjdbc/jdbc/adapter.rb', line 323 def pk_and_sequence_for(table) ( key = primary_key(table) ) ? [ key, nil ] : nil end |
#prepared_statements? ⇒ Boolean (protected)
413 414 415 416 |
# File 'lib/arjdbc/jdbc/adapter.rb', line 413 def prepared_statements? return @prepared_statements unless (@prepared_statements ||= nil).nil? @prepared_statements = self.class.prepared_statements?(config) end |
#primary_keys(table) ⇒ Object
328 329 330 |
# File 'lib/arjdbc/jdbc/adapter.rb', line 328 def primary_keys(table) @connection.primary_keys(table) end |
#structure_dump ⇒ Object
Abstract adapter default implementation does nothing silently.
172 173 174 |
# File 'lib/arjdbc/jdbc/adapter.rb', line 172 def structure_dump raise NotImplementedError, "structure_dump not supported" end |
#supports_foreign_keys? ⇒ Boolean
Does our database (+ its JDBC driver) support foreign-keys?
340 341 342 |
# File 'lib/arjdbc/jdbc/adapter.rb', line 340 def supports_foreign_keys? @connection.supports_foreign_keys? end |
#supports_migrations? ⇒ true
JDBC adapters support migration.
179 180 181 |
# File 'lib/arjdbc/jdbc/adapter.rb', line 179 def supports_migrations? true end |
#supports_views? ⇒ Boolean
230 231 232 |
# File 'lib/arjdbc/jdbc/adapter.rb', line 230 def supports_views? @connection.supports_views? end |
#table_definition ⇒ Object (protected)
aliasing #create_table_definition as #table_definition :
373 |
# File 'lib/arjdbc/jdbc/adapter.rb', line 373 alias table_definition create_table_definition |
#table_exists?(name) ⇒ Boolean
302 303 304 305 |
# File 'lib/arjdbc/jdbc/adapter.rb', line 302 def table_exists?(name) return false unless name @connection.table_exists?(name) # schema_name = nil end |
#tables(name = nil) ⇒ Object
297 298 299 |
# File 'lib/arjdbc/jdbc/adapter.rb', line 297 def tables(name = nil) @connection.tables end |
#update_lob_value(record, column, value) ⇒ Object
352 353 354 |
# File 'lib/arjdbc/jdbc/adapter.rb', line 352 def update_lob_value(record, column, value) @connection.update_lob_value(record, column, value) end |
#valid_type?(type) ⇒ Boolean
159 160 161 |
# File 'lib/arjdbc/jdbc/adapter.rb', line 159 def valid_type?(type) ! native_database_types[type].nil? end |
#write_large_object(*args) ⇒ Object
Rather use #update_lob_value instead.
345 346 347 |
# File 'lib/arjdbc/jdbc/adapter.rb', line 345 def write_large_object(*args) @connection.write_large_object(*args) end |