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, 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
-
.insert?(sql) ⇒ Boolean
Whether the given SQL string is an 'INSERT' query.
-
.prepared_statements?(config) ⇒ Boolean
Allows changing the prepared statements setting for this connection.
-
.select?(sql) ⇒ Boolean
query (returning a result set).
-
.update?(sql) ⇒ Boolean
Whether the given SQL string is an 'UPDATE' (or 'DELETE') query.
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 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
#delete, #exec_insert, #exec_query, #exec_update, #insert, #select_all, #update
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 |
.insert?(sql) ⇒ Boolean
Returns whether the given SQL string is an 'INSERT' query.
448 449 450 |
# File 'lib/arjdbc/jdbc/adapter.rb', line 448 def self.insert?(sql) JdbcConnection::insert?(sql) end |
.prepared_statements?(config) ⇒ Boolean
Allows changing the prepared statements setting for this connection. def prepared_statements=(statements) @prepared_statements = statements end
423 424 425 426 427 |
# File 'lib/arjdbc/jdbc/adapter.rb', line 423 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 |
.select?(sql) ⇒ Boolean
query (returning a result set)
443 444 445 |
# File 'lib/arjdbc/jdbc/adapter.rb', line 443 def self.select?(sql) JdbcConnection::select?(sql) end |
.update?(sql) ⇒ Boolean
Returns whether the given SQL string is an 'UPDATE' (or 'DELETE') query.
453 454 455 |
# File 'lib/arjdbc/jdbc/adapter.rb', line 453 def self.update?(sql) ! select?(sql) && ! insert?(sql) 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
312 313 314 |
# File 'lib/arjdbc/jdbc/adapter.rb', line 312 def data_source_exists?(name) table_exists?(name) end |
#data_sources ⇒ Object
307 308 309 |
# File 'lib/arjdbc/jdbc/adapter.rb', line 307 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).
265 266 267 268 269 270 271 272 |
# File 'lib/arjdbc/jdbc/adapter.rb', line 265 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.
285 286 287 288 289 290 291 292 293 |
# File 'lib/arjdbc/jdbc/adapter.rb', line 285 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
332 333 334 |
# File 'lib/arjdbc/jdbc/adapter.rb', line 332 def foreign_keys(table_name) @connection.foreign_keys(table_name) end |
#indexes(table_name, name = nil, schema_name = nil) ⇒ Object
317 318 319 |
# File 'lib/arjdbc/jdbc/adapter.rb', line 317 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.
359 360 361 362 363 364 365 366 367 368 369 |
# File 'lib/arjdbc/jdbc/adapter.rb', line 359 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.
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
322 323 324 |
# File 'lib/arjdbc/jdbc/adapter.rb', line 322 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.
412 413 414 415 |
# File 'lib/arjdbc/jdbc/adapter.rb', line 412 def prepared_statements? return @prepared_statements unless (@prepared_statements ||= nil).nil? @prepared_statements = self.class.prepared_statements?(config) end |
#primary_keys(table) ⇒ Object
327 328 329 |
# File 'lib/arjdbc/jdbc/adapter.rb', line 327 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?
339 340 341 |
# File 'lib/arjdbc/jdbc/adapter.rb', line 339 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 :
372 |
# File 'lib/arjdbc/jdbc/adapter.rb', line 372 alias table_definition create_table_definition |
#table_exists?(name) ⇒ Boolean
301 302 303 304 |
# File 'lib/arjdbc/jdbc/adapter.rb', line 301 def table_exists?(name) return false unless name @connection.table_exists?(name) # schema_name = nil end |
#tables(name = nil) ⇒ Object
296 297 298 |
# File 'lib/arjdbc/jdbc/adapter.rb', line 296 def tables(name = nil) @connection.tables end |
#update_lob_value(record, column, value) ⇒ Object
351 352 353 |
# File 'lib/arjdbc/jdbc/adapter.rb', line 351 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.
344 345 346 |
# File 'lib/arjdbc/jdbc/adapter.rb', line 344 def write_large_object(*args) @connection.write_large_object(*args) end |