Rails 1.2.3でOracleでConnectionNotEstablishedが発生する場合は?

# rak ConnectionNotEstablished /opt/local/lib/ruby/gems/1.8/gems/activerecord-1.15.3/lib/
  19|  class ConnectionNotEstablished < ActiveRecordError #:nodoc:
 251|  # * +ConnectionNotEstablished+ -- no connection has been established. Use <tt>establish_connection</tt> before querying.

/opt/local/lib/ruby/gems/1.8/gems/activerecord-1.15.3/lib/active_record/connection_adapters/abstract/connection_specification.rb
 235|      conn or raise ConnectionNotEstablished
 264|        raise ConnectionNotEstablished

/opt/local/lib/ruby/gems/1.8/gems/activerecord-1.15.3/lib/active_record/connection_adapters/firebird_adapter.rb
  97|            raise ConnectionNotEstablished, "No Firebird connections established."

ConnectionNotEstablishedが発生する箇所は二カ所

  • ActiveRecord::Base::ConnectionSpecification.retrieve_connection
  • ActiveRecord::Base::ConnectionSpecification.connection=

connection=は初回にDB接続するとき
retrieve_connectionは初回接続以後DBコネクションを取得するとき
それぞれ呼ばれる

connection=

connection=でConnectionNotEstablishedが発生するのは
接続設定がnilだったとき

このコードは通らないと思う・・
呼び先(retrieve_connection)でnilだったらこのメソッド呼ばれないし

retrieve_connection

DBコネクションオブジェクト(ConnectionAdapters::OracleAdapter)がnilになってたらConnectionNotEstablishedが発生する
nilになるのはremove_connectionされてた場合かなあ

    def self.remove_connection(klass=self)
     spec = @@defined_connections[klass.name]
     konn = active_connections[klass.name]
     @@defined_connections.delete_if { |key, value| value == spec }
     active_connections.delete_if { |key, value| value == konn }
     konn.disconnect! if konn
     spec.config if spec
    end 

テスト

/opt/local/lib/ruby/gems/1.8/gems/activerecord-1.15.3/test/unconnected_test.rb
にConnectionNotEstablishedのテストがある
setupでremove_connectionしてる

ConnectionNotEstablishedを起こす

無理栗に起こそうとしたらこんなんだけど(RailsのバージョンもDBも違うけどremove_connectionの動きは同じ)こんなんアプリのコードで書かないやん

# ruby script/console 
Loading development environment (Rails 2.2.2)
>> ActiveRecord::Base.remove_connection
=> {:timeout=>5000, :adapter=>"sqlite3", :pool=>5, :database=>"/Users/sogo/code/rails/jpmobile-demo/db/development.sqlite3"}
>> Post.find :first
ActiveRecord::ConnectionNotEstablished: ActiveRecord::ConnectionNotEstablished
from /opt/local/lib/ruby/gems/1.8/gems/activerecord-2.2.2/lib/active_record/connection_adapters/abstract/connection_pool.rb:326:in `retrieve_connection'
from /opt/local/lib/ruby/gems/1.8/gems/activerecord-2.2.2/lib/active_record/connection_adapters/abstract/connection_specification.rb:121:in `retrieve_connection'
from /opt/local/lib/ruby/gems/1.8/gems/activerecord-2.2.2/lib/active_record/connection_adapters/abstract/connection_specification.rb:113:in `connection'
from /opt/local/lib/ruby/gems/1.8/gems/activerecord-2.2.2/lib/active_record/base.rb:2934:in `quoted_table_name'
from /opt/local/lib/ruby/gems/1.8/gems/activerecord-2.2.2/lib/active_record/base.rb:1626:in `construct_finder_sql'
from /opt/local/lib/ruby/gems/1.8/gems/activerecord-2.2.2/lib/active_record/base.rb:1490:in `find_every'
from /opt/local/lib/ruby/gems/1.8/gems/activerecord-2.2.2/lib/active_record/base.rb:1452:in `find_initial'
from /opt/local/lib/ruby/gems/1.8/gems/activerecord-2.2.2/lib/active_record/base.rb:587:in `find'
from (irb):4
>> 


ちなみにalter system kill sessionしてかららDB接続するとRuntimeErrorが発生するはず
OCI8AutoRecoverの@@auto_retry?はfalseでshould_retryもfalseなので

# ORA-00028: your session has been killed
# ORA-01012: not logged on
# ORA-03113: end-of-file on communication channel
# ORA-03114: not connected to ORACLE
LOST_CONNECTION_ERROR_CODES = [ 28, 1012, 3113, 3114 ]

# Adds auto-recovery functionality.
# 
# See: http://www.jiubao.org/ruby-oci8/api.en.html#label-11
def exec(sql, *bindvars, &block)
should_retry = self.class.auto_retry? && autocommit?

begin
@connection.exec(sql, *bindvars, &block)
rescue OCIException => e
raise unless LOST_CONNECTION_ERROR_CODES.include?(e.code)
@active = false
raise unless should_retry
should_retry = false
reset! rescue nil 
retry
end 
end 

end