exc.py 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388
  1. # sqlalchemy/exc.py
  2. # Copyright (C) 2005-2017 the SQLAlchemy authors and contributors
  3. # <see AUTHORS file>
  4. #
  5. # This module is part of SQLAlchemy and is released under
  6. # the MIT License: http://www.opensource.org/licenses/mit-license.php
  7. """Exceptions used with SQLAlchemy.
  8. The base exception class is :exc:`.SQLAlchemyError`. Exceptions which are
  9. raised as a result of DBAPI exceptions are all subclasses of
  10. :exc:`.DBAPIError`.
  11. """
  12. class SQLAlchemyError(Exception):
  13. """Generic error class."""
  14. class ArgumentError(SQLAlchemyError):
  15. """Raised when an invalid or conflicting function argument is supplied.
  16. This error generally corresponds to construction time state errors.
  17. """
  18. class ObjectNotExecutableError(ArgumentError):
  19. """Raised when an object is passed to .execute() that can't be
  20. executed as SQL.
  21. .. versionadded:: 1.1
  22. """
  23. def __init__(self, target):
  24. super(ObjectNotExecutableError, self).__init__(
  25. "Not an executable object: %r" % target
  26. )
  27. class NoSuchModuleError(ArgumentError):
  28. """Raised when a dynamically-loaded module (usually a database dialect)
  29. of a particular name cannot be located."""
  30. class NoForeignKeysError(ArgumentError):
  31. """Raised when no foreign keys can be located between two selectables
  32. during a join."""
  33. class AmbiguousForeignKeysError(ArgumentError):
  34. """Raised when more than one foreign key matching can be located
  35. between two selectables during a join."""
  36. class CircularDependencyError(SQLAlchemyError):
  37. """Raised by topological sorts when a circular dependency is detected.
  38. There are two scenarios where this error occurs:
  39. * In a Session flush operation, if two objects are mutually dependent
  40. on each other, they can not be inserted or deleted via INSERT or
  41. DELETE statements alone; an UPDATE will be needed to post-associate
  42. or pre-deassociate one of the foreign key constrained values.
  43. The ``post_update`` flag described at :ref:`post_update` can resolve
  44. this cycle.
  45. * In a :attr:`.MetaData.sorted_tables` operation, two :class:`.ForeignKey`
  46. or :class:`.ForeignKeyConstraint` objects mutually refer to each
  47. other. Apply the ``use_alter=True`` flag to one or both,
  48. see :ref:`use_alter`.
  49. """
  50. def __init__(self, message, cycles, edges, msg=None):
  51. if msg is None:
  52. message += " (%s)" % ", ".join(repr(s) for s in cycles)
  53. else:
  54. message = msg
  55. SQLAlchemyError.__init__(self, message)
  56. self.cycles = cycles
  57. self.edges = edges
  58. def __reduce__(self):
  59. return self.__class__, (None, self.cycles,
  60. self.edges, self.args[0])
  61. class CompileError(SQLAlchemyError):
  62. """Raised when an error occurs during SQL compilation"""
  63. class UnsupportedCompilationError(CompileError):
  64. """Raised when an operation is not supported by the given compiler.
  65. .. versionadded:: 0.8.3
  66. """
  67. def __init__(self, compiler, element_type):
  68. super(UnsupportedCompilationError, self).__init__(
  69. "Compiler %r can't render element of type %s" %
  70. (compiler, element_type))
  71. class IdentifierError(SQLAlchemyError):
  72. """Raised when a schema name is beyond the max character limit"""
  73. class DisconnectionError(SQLAlchemyError):
  74. """A disconnect is detected on a raw DB-API connection.
  75. This error is raised and consumed internally by a connection pool. It can
  76. be raised by the :meth:`.PoolEvents.checkout` event so that the host pool
  77. forces a retry; the exception will be caught three times in a row before
  78. the pool gives up and raises :class:`~sqlalchemy.exc.InvalidRequestError`
  79. regarding the connection attempt.
  80. """
  81. class TimeoutError(SQLAlchemyError):
  82. """Raised when a connection pool times out on getting a connection."""
  83. class InvalidRequestError(SQLAlchemyError):
  84. """SQLAlchemy was asked to do something it can't do.
  85. This error generally corresponds to runtime state errors.
  86. """
  87. class NoInspectionAvailable(InvalidRequestError):
  88. """A subject passed to :func:`sqlalchemy.inspection.inspect` produced
  89. no context for inspection."""
  90. class ResourceClosedError(InvalidRequestError):
  91. """An operation was requested from a connection, cursor, or other
  92. object that's in a closed state."""
  93. class NoSuchColumnError(KeyError, InvalidRequestError):
  94. """A nonexistent column is requested from a ``RowProxy``."""
  95. class NoReferenceError(InvalidRequestError):
  96. """Raised by ``ForeignKey`` to indicate a reference cannot be resolved."""
  97. class NoReferencedTableError(NoReferenceError):
  98. """Raised by ``ForeignKey`` when the referred ``Table`` cannot be
  99. located.
  100. """
  101. def __init__(self, message, tname):
  102. NoReferenceError.__init__(self, message)
  103. self.table_name = tname
  104. def __reduce__(self):
  105. return self.__class__, (self.args[0], self.table_name)
  106. class NoReferencedColumnError(NoReferenceError):
  107. """Raised by ``ForeignKey`` when the referred ``Column`` cannot be
  108. located.
  109. """
  110. def __init__(self, message, tname, cname):
  111. NoReferenceError.__init__(self, message)
  112. self.table_name = tname
  113. self.column_name = cname
  114. def __reduce__(self):
  115. return self.__class__, (self.args[0], self.table_name,
  116. self.column_name)
  117. class NoSuchTableError(InvalidRequestError):
  118. """Table does not exist or is not visible to a connection."""
  119. class UnboundExecutionError(InvalidRequestError):
  120. """SQL was attempted without a database connection to execute it on."""
  121. class DontWrapMixin(object):
  122. """A mixin class which, when applied to a user-defined Exception class,
  123. will not be wrapped inside of :exc:`.StatementError` if the error is
  124. emitted within the process of executing a statement.
  125. E.g.::
  126. from sqlalchemy.exc import DontWrapMixin
  127. class MyCustomException(Exception, DontWrapMixin):
  128. pass
  129. class MySpecialType(TypeDecorator):
  130. impl = String
  131. def process_bind_param(self, value, dialect):
  132. if value == 'invalid':
  133. raise MyCustomException("invalid!")
  134. """
  135. # Moved to orm.exc; compatibility definition installed by orm import until 0.6
  136. UnmappedColumnError = None
  137. class StatementError(SQLAlchemyError):
  138. """An error occurred during execution of a SQL statement.
  139. :class:`StatementError` wraps the exception raised
  140. during execution, and features :attr:`.statement`
  141. and :attr:`.params` attributes which supply context regarding
  142. the specifics of the statement which had an issue.
  143. The wrapped exception object is available in
  144. the :attr:`.orig` attribute.
  145. """
  146. statement = None
  147. """The string SQL statement being invoked when this exception occurred."""
  148. params = None
  149. """The parameter list being used when this exception occurred."""
  150. orig = None
  151. """The DBAPI exception object."""
  152. def __init__(self, message, statement, params, orig):
  153. SQLAlchemyError.__init__(self, message)
  154. self.statement = statement
  155. self.params = params
  156. self.orig = orig
  157. self.detail = []
  158. def add_detail(self, msg):
  159. self.detail.append(msg)
  160. def __reduce__(self):
  161. return self.__class__, (self.args[0], self.statement,
  162. self.params, self.orig)
  163. def __str__(self):
  164. from sqlalchemy.sql import util
  165. details = [SQLAlchemyError.__str__(self)]
  166. if self.statement:
  167. details.append("[SQL: %r]" % self.statement)
  168. if self.params:
  169. params_repr = util._repr_params(self.params, 10)
  170. details.append("[parameters: %r]" % params_repr)
  171. return ' '.join([
  172. "(%s)" % det for det in self.detail
  173. ] + details)
  174. def __unicode__(self):
  175. return self.__str__()
  176. class DBAPIError(StatementError):
  177. """Raised when the execution of a database operation fails.
  178. Wraps exceptions raised by the DB-API underlying the
  179. database operation. Driver-specific implementations of the standard
  180. DB-API exception types are wrapped by matching sub-types of SQLAlchemy's
  181. :class:`DBAPIError` when possible. DB-API's ``Error`` type maps to
  182. :class:`DBAPIError` in SQLAlchemy, otherwise the names are identical. Note
  183. that there is no guarantee that different DB-API implementations will
  184. raise the same exception type for any given error condition.
  185. :class:`DBAPIError` features :attr:`~.StatementError.statement`
  186. and :attr:`~.StatementError.params` attributes which supply context
  187. regarding the specifics of the statement which had an issue, for the
  188. typical case when the error was raised within the context of
  189. emitting a SQL statement.
  190. The wrapped exception object is available in the
  191. :attr:`~.StatementError.orig` attribute. Its type and properties are
  192. DB-API implementation specific.
  193. """
  194. @classmethod
  195. def instance(cls, statement, params,
  196. orig, dbapi_base_err,
  197. connection_invalidated=False,
  198. dialect=None):
  199. # Don't ever wrap these, just return them directly as if
  200. # DBAPIError didn't exist.
  201. if (isinstance(orig, BaseException) and
  202. not isinstance(orig, Exception)) or \
  203. isinstance(orig, DontWrapMixin):
  204. return orig
  205. if orig is not None:
  206. # not a DBAPI error, statement is present.
  207. # raise a StatementError
  208. if not isinstance(orig, dbapi_base_err) and statement:
  209. return StatementError(
  210. "(%s.%s) %s" %
  211. (orig.__class__.__module__, orig.__class__.__name__,
  212. orig),
  213. statement, params, orig
  214. )
  215. glob = globals()
  216. for super_ in orig.__class__.__mro__:
  217. name = super_.__name__
  218. if dialect:
  219. name = dialect.dbapi_exception_translation_map.get(
  220. name, name)
  221. if name in glob and issubclass(glob[name], DBAPIError):
  222. cls = glob[name]
  223. break
  224. return cls(statement, params, orig, connection_invalidated)
  225. def __reduce__(self):
  226. return self.__class__, (self.statement, self.params,
  227. self.orig, self.connection_invalidated)
  228. def __init__(self, statement, params, orig, connection_invalidated=False):
  229. try:
  230. text = str(orig)
  231. except Exception as e:
  232. text = 'Error in str() of DB-API-generated exception: ' + str(e)
  233. StatementError.__init__(
  234. self,
  235. '(%s.%s) %s' % (
  236. orig.__class__.__module__, orig.__class__.__name__, text, ),
  237. statement,
  238. params,
  239. orig
  240. )
  241. self.connection_invalidated = connection_invalidated
  242. class InterfaceError(DBAPIError):
  243. """Wraps a DB-API InterfaceError."""
  244. class DatabaseError(DBAPIError):
  245. """Wraps a DB-API DatabaseError."""
  246. class DataError(DatabaseError):
  247. """Wraps a DB-API DataError."""
  248. class OperationalError(DatabaseError):
  249. """Wraps a DB-API OperationalError."""
  250. class IntegrityError(DatabaseError):
  251. """Wraps a DB-API IntegrityError."""
  252. class InternalError(DatabaseError):
  253. """Wraps a DB-API InternalError."""
  254. class ProgrammingError(DatabaseError):
  255. """Wraps a DB-API ProgrammingError."""
  256. class NotSupportedError(DatabaseError):
  257. """Wraps a DB-API NotSupportedError."""
  258. # Warnings
  259. class SADeprecationWarning(DeprecationWarning):
  260. """Issued once per usage of a deprecated API."""
  261. class SAPendingDeprecationWarning(PendingDeprecationWarning):
  262. """Issued once per usage of a deprecated API."""
  263. class SAWarning(RuntimeWarning):
  264. """Issued at runtime."""