1 | import struct |
---|
2 | |
---|
3 | from .constants import ER |
---|
4 | |
---|
5 | |
---|
6 | class MySQLError(Exception): |
---|
7 | """Exception related to operation with MySQL.""" |
---|
8 | |
---|
9 | |
---|
10 | class Warning(Warning, MySQLError): |
---|
11 | """Exception raised for important warnings like data truncations |
---|
12 | while inserting, etc.""" |
---|
13 | |
---|
14 | |
---|
15 | class Error(MySQLError): |
---|
16 | """Exception that is the base class of all other error exceptions |
---|
17 | (not Warning).""" |
---|
18 | |
---|
19 | |
---|
20 | class InterfaceError(Error): |
---|
21 | """Exception raised for errors that are related to the database |
---|
22 | interface rather than the database itself.""" |
---|
23 | |
---|
24 | |
---|
25 | class DatabaseError(Error): |
---|
26 | """Exception raised for errors that are related to the |
---|
27 | database.""" |
---|
28 | |
---|
29 | |
---|
30 | class DataError(DatabaseError): |
---|
31 | """Exception raised for errors that are due to problems with the |
---|
32 | processed data like division by zero, numeric value out of range, |
---|
33 | etc.""" |
---|
34 | |
---|
35 | |
---|
36 | class OperationalError(DatabaseError): |
---|
37 | """Exception raised for errors that are related to the database's |
---|
38 | operation and not necessarily under the control of the programmer, |
---|
39 | e.g. an unexpected disconnect occurs, the data source name is not |
---|
40 | found, a transaction could not be processed, a memory allocation |
---|
41 | error occurred during processing, etc.""" |
---|
42 | |
---|
43 | |
---|
44 | class IntegrityError(DatabaseError): |
---|
45 | """Exception raised when the relational integrity of the database |
---|
46 | is affected, e.g. a foreign key check fails, duplicate key, |
---|
47 | etc.""" |
---|
48 | |
---|
49 | |
---|
50 | class InternalError(DatabaseError): |
---|
51 | """Exception raised when the database encounters an internal |
---|
52 | error, e.g. the cursor is not valid anymore, the transaction is |
---|
53 | out of sync, etc.""" |
---|
54 | |
---|
55 | |
---|
56 | class ProgrammingError(DatabaseError): |
---|
57 | """Exception raised for programming errors, e.g. table not found |
---|
58 | or already exists, syntax error in the SQL statement, wrong number |
---|
59 | of parameters specified, etc.""" |
---|
60 | |
---|
61 | |
---|
62 | class NotSupportedError(DatabaseError): |
---|
63 | """Exception raised in case a method or database API was used |
---|
64 | which is not supported by the database, e.g. requesting a |
---|
65 | .rollback() on a connection that does not support transaction or |
---|
66 | has transactions turned off.""" |
---|
67 | |
---|
68 | |
---|
69 | error_map = {} |
---|
70 | |
---|
71 | |
---|
72 | def _map_error(exc, *errors): |
---|
73 | for error in errors: |
---|
74 | error_map[error] = exc |
---|
75 | |
---|
76 | |
---|
77 | _map_error(ProgrammingError, ER.DB_CREATE_EXISTS, ER.SYNTAX_ERROR, |
---|
78 | ER.PARSE_ERROR, ER.NO_SUCH_TABLE, ER.WRONG_DB_NAME, |
---|
79 | ER.WRONG_TABLE_NAME, ER.FIELD_SPECIFIED_TWICE, |
---|
80 | ER.INVALID_GROUP_FUNC_USE, ER.UNSUPPORTED_EXTENSION, |
---|
81 | ER.TABLE_MUST_HAVE_COLUMNS, ER.CANT_DO_THIS_DURING_AN_TRANSACTION) |
---|
82 | _map_error(DataError, ER.WARN_DATA_TRUNCATED, ER.WARN_NULL_TO_NOTNULL, |
---|
83 | ER.WARN_DATA_OUT_OF_RANGE, ER.NO_DEFAULT, ER.PRIMARY_CANT_HAVE_NULL, |
---|
84 | ER.DATA_TOO_LONG, ER.DATETIME_FUNCTION_OVERFLOW) |
---|
85 | _map_error(IntegrityError, ER.DUP_ENTRY, ER.NO_REFERENCED_ROW, |
---|
86 | ER.NO_REFERENCED_ROW_2, ER.ROW_IS_REFERENCED, ER.ROW_IS_REFERENCED_2, |
---|
87 | ER.CANNOT_ADD_FOREIGN, ER.BAD_NULL_ERROR) |
---|
88 | _map_error(NotSupportedError, ER.WARNING_NOT_COMPLETE_ROLLBACK, |
---|
89 | ER.NOT_SUPPORTED_YET, ER.FEATURE_DISABLED, ER.UNKNOWN_STORAGE_ENGINE) |
---|
90 | _map_error(OperationalError, ER.DBACCESS_DENIED_ERROR, ER.ACCESS_DENIED_ERROR, |
---|
91 | ER.CON_COUNT_ERROR, ER.TABLEACCESS_DENIED_ERROR, |
---|
92 | ER.COLUMNACCESS_DENIED_ERROR) |
---|
93 | |
---|
94 | |
---|
95 | del _map_error, ER |
---|
96 | |
---|
97 | |
---|
98 | def raise_mysql_exception(data): |
---|
99 | errno = struct.unpack('<h', data[1:3])[0] |
---|
100 | is_41 = data[3:4] == b"#" |
---|
101 | if is_41: |
---|
102 | # client protocol 4.1 |
---|
103 | errval = data[9:].decode('utf-8', 'replace') |
---|
104 | else: |
---|
105 | errval = data[3:].decode('utf-8', 'replace') |
---|
106 | errorclass = error_map.get(errno, InternalError) |
---|
107 | raise errorclass(errno, errval) |
---|