Permalink
Browse files

Raise Sequel::DatabaseError instead of generic Sequel::Error for data…

…base errors, don't swallow tracebacks

This commit adds a new exception class, Sequel::DatabaseError.  This
exception class should be used for all errors that come from the
database, such as invalid syntax in a query or database access rights
violation.

This commit adds a couple private Database methods, raise_error and
transaction_error.  raise_error converts the exception to a
DatabaseError, keeping the previous exception message (prepended
with the previous exception class) as well as the traceback.  If
an optional :classes option is passed, it only converts the exception
if it is one of those classes.  transaction_error calls raise_error
with the :classes options set to the array of passed classes, unless
the error is an Error::Rollback.  These DRY up some code in the
adapters.

This commit also removes the convert_pgerror method for the postgres
adapter, since it is no longer necessary.

This is a backwards incompatible change for SQLite users, since the
SQLite adapter previously raised Error::InvalidStatement instead of
just Error.
  • Loading branch information...
1 parent 80c2c9e commit 6acb504cd1ae8842b7b65270cecb73cad2fb31c4 @jeremyevans committed Aug 27, 2008
View
@@ -1,5 +1,7 @@
=== HEAD
+* Raise Sequel::DatabaseError instead of generic Sequel::Error for database errors, don't swallow tracebacks (jeremyevans)
+
* Use INSERT ... RETURNING ... with PostgreSQL 8.2 and higher (jeremyevans)
* Make insert_sql, delete_sql, and update_sql respect the :sql option (jeremyevans)
@@ -69,7 +69,7 @@ def check_error(rc, msg)
when SQL_SUCCESS, SQL_SUCCESS_WITH_INFO
nil
else
- raise Error, msg
+ raise DatabaseError, msg
end
end
end
@@ -126,7 +126,7 @@ def execute(sql, opts={}, &block)
end
end
rescue NativeException, JavaSQL::SQLException => e
- raise Error, e.message
+ raise_error(e)
ensure
stmt.close
end
@@ -232,7 +232,7 @@ def execute_prepared_statement(name, opts={})
end
end
rescue NativeException, JavaSQL::SQLException => e
- raise Error, e.message
+ raise_error(e)
ensure
cps.close unless name
end
@@ -21,7 +21,7 @@ def execute(sql, args=nil)
rows = stmt.send(method, sql)
yield(rows) if block_given?
rescue NativeException => e
- raise Error, e.message
+ raise_error(e)
ensure
stmt.close
end
@@ -137,7 +137,7 @@ def execute(sql, opts={}, &block)
begin
synchronize(opts[:server]){|conn| _execute(conn, sql, opts, &block)}
rescue Mysql::Error => e
- raise Error.new(e.message)
+ raise_error(e)
end
end
@@ -163,7 +163,7 @@ def transaction(server=nil)
rescue ::Exception => e
log_info(SQL_ROLLBACK)
conn.query(SQL_ROLLBACK)
- raise (Mysql::Error === e ? Error.new(e.message) : e) unless Error::Rollback === e
+ transaction_error(e, Mysql::Error)
ensure
unless e
log_info(SQL_COMMIT)
@@ -209,7 +209,7 @@ def execute(sql, opts={}, &block)
synchronize(opts[:server]){|conn| conn.execute(sql, opts[:arguments], &block)}
rescue => e
log_info(e.message)
- raise convert_pgerror(e)
+ raise_error(e, :classes=>CONVERTED_EXCEPTIONS)
end
end
@@ -225,7 +225,7 @@ def execute_insert(sql, opts={})
end
rescue => e
log_info(e.message)
- raise convert_pgerror(e)
+ raise_error(e, :classes=>CONVERTED_EXCEPTIONS)
end
end
@@ -196,7 +196,7 @@ def transaction(server=nil)
log_info(SQL_ROLLBACK)
conn.execute(SQL_ROLLBACK) rescue nil
end
- raise convert_pgerror(e) unless Error::Rollback === e
+ transaction_error(e, *CONVERTED_EXCEPTIONS)
ensure
unless e
begin
@@ -209,7 +209,7 @@ def transaction(server=nil)
end
rescue => e
log_info(e.message)
- raise convert_pgerror(e)
+ raise_error(e, :classes=>CONVERTED_EXCEPTIONS)
end
end
conn.transaction_depth -= 1
@@ -219,11 +219,6 @@ def transaction(server=nil)
private
- # Convert the exception to a Sequel::Error if it is in CONVERTED_EXCEPTIONS.
- def convert_pgerror(e)
- e.is_one_of?(*CONVERTED_EXCEPTIONS) ? Error.new(e.message) : e
- end
-
# The result of the insert for the given table and values. If values
# is an array, assume the first column is the primary key and return
# that. If values is a hash, lookup the primary key for the table. If
@@ -242,7 +237,7 @@ def insert_result(conn, table, values)
conn.last_insert_id(seq)
end
rescue Exception => e
- raise convert_pgerror(e) unless RE_CURRVAL_ERROR.match(e.message)
+ raise_error(e, :classes=>CONVERTED_EXCEPTIONS) unless RE_CURRVAL_ERROR.match(e.message)
end
end
when Array
@@ -78,7 +78,7 @@ def transaction(server=nil, &block)
conn.transaction{result = yield(conn)}
result
rescue ::Exception => e
- raise (SQLite3::Exception === e ? Error.new(e.message) : e) unless Error::Rollback === e
+ transaction_error(e, SQLite3::Exception)
end
end
end
@@ -92,7 +92,7 @@ def _execute(sql, opts)
log_info(sql, opts[:arguments])
synchronize(opts[:server]){|conn| yield conn}
rescue SQLite3::Exception => e
- raise Error::InvalidStatement, "#{sql}\r\n#{e.message}"
+ raise_error(e)
end
end
@@ -371,7 +371,7 @@ def transaction(server=nil)
rescue Exception => e
log_info(SQL_ROLLBACK)
conn.execute(SQL_ROLLBACK)
- raise e unless Error::Rollback === e
+ transaction_error(e)
ensure
unless e
log_info(SQL_COMMIT)
@@ -495,6 +495,23 @@ def server_opts(server)
def connection_pool_default_options
{}
end
+
+ # Convert the given exception to a DatabaseError, keeping message
+ # and traceback.
+ def raise_error(exception, opts={})
+ if !opts[:classes] || exception.is_one_of?(*opts[:classes])
+ e = DatabaseError.new("#{exception.class} #{exception.message}")
+ e.set_backtrace(exception.backtrace)
+ raise e
+ else
+ raise
+ end
+ end
+
+ # Raise a database error unless the exception is an Error::Rollback.
+ def transaction_error(e, *classes)
+ raise_error(e, :classes=>classes) unless Error::Rollback === e
+ end
end
end
@@ -27,4 +27,8 @@ class PoolTimeoutError < Error ; end
# A transaction block will catch this error and won't pass further up the stack.
class Rollback < Error ; end
end
+
+ # Generic error raised by the database adapters, indicating a
+ # problem originating from the database server.
+ class DatabaseError < Error; end
end

0 comments on commit 6acb504

Please sign in to comment.