Gem rescue 为什么不处理 SQLite3::SQLException 异常

tablecell · 2021年09月07日 · 最后由 tablecell 回复于 2021年09月09日 · 426 次阅读
require "sqlite3"
require "sequel"
DB = Sequel.sqlite  # memroy

if true
  DB.create_table :posts do
    primary_key :id
    String :email, null: false
  end
end
Post = DB[:posts]

begin
  row = Post.insert(mail: "[email protected]")
rescue SQLite3::SQLException => e
  puts e
end


执行会输出异常栈,SQLite3::SQLException: table posts has no column named mail 但不执行 rescue 代码块

rescue StandardError => e
  puts e.class # Sequel::DatabaseError
end
e.inspect # #<Sequel::DatabaseError: SQLite3::SQLException: table posts has no column named mail>
xinyifly 回复

为什么命令行运行报 SQLite3::SQLException 在代码里捕获是 Sequel::DatabaseError

看代码

  • Sequel::DatabaseError < Sequel::Error < ::StandardError
  • SQLite3::SQLException < SQLite3::Exception < ::StandardError

这两个有什么不同吗?为什么一个行,另一个不行

看样子是 Sequel 捕获了 SQLite3 的异常,包裹在 Sequel::DatabaseError 里面再抛出,到用户代码这里能捕获的是 Sequel::DatabaseError。

tablecell 回复

这段代码抛的异常是 Sequel::DatabaseErrorSQLite3::SQLException 不是 Sequel::DatabaseError 的父类,自然捕获不到。

xinyifly 回复

直接运行 Post.insert(mail: "[email protected]") 为什么不报 Sequel::DatabaseError 而是 SQLite3::SQLException

tablecell 回复

你应该把异常的 message 和类搞混了,终端看到的 SQLite3::SQLException 是 message 的一部分。

可以把完整错误栈信息贴上来看看。

Rei 回复
$ ruby  test.rb
Traceback (most recent call last):
        13: from test.rb:14:in `<main>'
        12: from Ruby25-x64/lib/ruby/gems/2.5.0/gems/sequel-5.48.0/lib/sequel/dataset/actions.rb:401:in `insert'
        11: from Ruby25-x64/lib/ruby/gems/2.5.0/gems/sequel-5.48.0/lib/sequel/dataset/actions.rb:1109:in `execute_insert'
        10: from Ruby25-x64/lib/ruby/gems/2.5.0/gems/sequel-5.48.0/lib/sequel/adapters/sqlite.rb:159:in `execute_insert'
         9: from Ruby25-x64/lib/ruby/gems/2.5.0/gems/sequel-5.48.0/lib/sequel/adapters/sqlite.rb:193:in `_execute'
         8: from Ruby25-x64/lib/ruby/gems/2.5.0/gems/sequel-5.48.0/lib/sequel/database/connecting.rb:269:in `synchronize'
         7: from Ruby25-x64/lib/ruby/gems/2.5.0/gems/sequel-5.48.0/lib/sequel/connection_pool/threaded.rb:92:in `hold'
         6: from Ruby25-x64/lib/ruby/gems/2.5.0/gems/sequel-5.48.0/lib/sequel/adapters/sqlite.rb:202:in `block in _execute'
         5: from Ruby25-x64/lib/ruby/gems/2.5.0/gems/sequel-5.48.0/lib/sequel/database/logging.rb:38:in `log_connection_yield'
         4: from Ruby25-x64/lib/ruby/gems/2.5.0/gems/sequel-5.48.0/lib/sequel/adapters/sqlite.rb:202:in `block (2 levels) in _execute'
         3: from Ruby25-x64/lib/ruby/gems/2.5.0/gems/sqlite3-1.4.2.mspgreg-x64-mingw32/lib/sqlite3/database.rb:194:in `execute'
         2: from Ruby25-x64/lib/ruby/gems/2.5.0/gems/sqlite3-1.4.2.mspgreg-x64-mingw32/lib/sqlite3/database.rb:148:in `prepare'
         1: from Ruby25-x64/lib/ruby/gems/2.5.0/gems/sqlite3-1.4.2.mspgreg-x64-mingw32/lib/sqlite3/database.rb:148:in `new'
Ruby25-x64/lib/ruby/gems/2.5.0/gems/sqlite3-1.4.2.mspgreg-x64-mingw32/lib/sqlite3/database.rb:148:in `initialize': SQLite3::SQLException: table posts has no column named mail (Sequel::DatabaseError)

tablecell 回复

你看最后一个括号,那才是异常的类

Rei 回复

封装的太深了

需要 登录 后方可回复, 如果你还没有账号请 注册新账号