mirror of
https://github.com/mariadb-corporation/mariadb-connector-python.git
synced 2025-08-04 08:04:45 +00:00
Fix for CONPY-106
Check error number instead of SQL code for determine exception type.
This commit is contained in:
@ -252,9 +252,9 @@ typedef struct {
|
||||
unsigned long prefetch_rows;
|
||||
unsigned long cursor_type;
|
||||
int64_t affected_rows;
|
||||
int64_t row_count;
|
||||
uint32_t field_count;
|
||||
uint64_t lastrowid;
|
||||
int64_t row_count;
|
||||
uint64_t lastrow_id;
|
||||
unsigned long row_number;
|
||||
enum enum_result_format result_format;
|
||||
uint8_t is_prepared;
|
||||
@ -319,7 +319,7 @@ int Mariadb_traverse(PyObject *self,
|
||||
void
|
||||
mariadb_throw_exception(void *handle,
|
||||
PyObject *execption_type,
|
||||
unsigned char is_statement,
|
||||
int8_t is_statement,
|
||||
const char *message,
|
||||
...);
|
||||
|
||||
|
@ -18,6 +18,7 @@
|
||||
*************************************************************************************/
|
||||
|
||||
#include <mariadb_python.h>
|
||||
#include <mysqld_error.h>
|
||||
|
||||
/* Exceptions */
|
||||
PyObject *Mariadb_InterfaceError;
|
||||
@ -37,77 +38,70 @@ struct st_error_map {
|
||||
uint8_t type;
|
||||
};
|
||||
|
||||
static PyObject *get_exception_type(const char *sqlstate)
|
||||
static PyObject *get_exception_type(int error_number)
|
||||
{
|
||||
if (!sqlstate || strlen(sqlstate) != 5)
|
||||
return NULL;
|
||||
|
||||
if (!strncmp(sqlstate, "21", 2) ||
|
||||
!strncmp(sqlstate, "22", 2) ||
|
||||
!strncmp(sqlstate, "02", 2))
|
||||
/* This list might be incomplete, special error values which are
|
||||
not handled yet will be returned as Internal or Operational errors.
|
||||
error codes are defined in errmsg.h (client errors) and mysqld_error.h
|
||||
(server errors) */
|
||||
switch (error_number) {
|
||||
/* InterfaceError */
|
||||
case 0:
|
||||
return Mariadb_InterfaceError;
|
||||
/* DataError: Exception raised for errors that are due to problems with the processed
|
||||
data like division by zero, numeric value out of range, etc */
|
||||
case ER_DATA_TOO_LONG:
|
||||
case ER_DATETIME_FUNCTION_OVERFLOW:
|
||||
case ER_DIVISION_BY_ZERO:
|
||||
case ER_NO_DEFAULT:
|
||||
case ER_PRIMARY_CANT_HAVE_NULL:
|
||||
case ER_WARN_DATA_OUT_OF_RANGE:
|
||||
case WARN_DATA_TRUNCATED:
|
||||
return Mariadb_DataError;
|
||||
|
||||
if (!strncmp(sqlstate, "07", 2) ||
|
||||
!strncmp(sqlstate, "2B", 2) ||
|
||||
!strncmp(sqlstate, "2D", 2) ||
|
||||
!strncmp(sqlstate, "33", 2) ||
|
||||
!strncmp(sqlstate, "HY", 2))
|
||||
return Mariadb_DatabaseError;
|
||||
|
||||
if (!strncmp(sqlstate, "23", 2) ||
|
||||
!strncmp(sqlstate, "XA", 2))
|
||||
return Mariadb_IntegrityError;
|
||||
|
||||
if (!strncmp(sqlstate, "0A", 2))
|
||||
return Mariadb_NotSupportedError;
|
||||
|
||||
if (!strncmp(sqlstate, "40", 2) ||
|
||||
!strncmp(sqlstate, "44", 2))
|
||||
return Mariadb_InternalError;
|
||||
|
||||
if (!strncmp(sqlstate, "0K", 2) ||
|
||||
!strncmp(sqlstate, "08", 2) ||
|
||||
!strncmp(sqlstate, "HZ", 2))
|
||||
return Mariadb_OperationalError;
|
||||
|
||||
if (!strncmp(sqlstate, "24", 2) ||
|
||||
!strncmp(sqlstate, "25", 2) ||
|
||||
!strncmp(sqlstate, "26", 2) ||
|
||||
!strncmp(sqlstate, "27", 2) ||
|
||||
!strncmp(sqlstate, "28", 2) ||
|
||||
!strncmp(sqlstate, "2A", 2) ||
|
||||
!strncmp(sqlstate, "2C", 2) ||
|
||||
!strncmp(sqlstate, "2F", 2) ||
|
||||
!strncmp(sqlstate, "34", 2) ||
|
||||
!strncmp(sqlstate, "35", 2) ||
|
||||
!strncmp(sqlstate, "3C", 2) ||
|
||||
!strncmp(sqlstate, "3D", 2) ||
|
||||
!strncmp(sqlstate, "3F", 2) ||
|
||||
!strncmp(sqlstate, "37", 2) ||
|
||||
!strncmp(sqlstate, "42", 2) ||
|
||||
!strncmp(sqlstate, "70", 2))
|
||||
/* ProgrammingError: Exception raised for programming errors, e.g. table not found or
|
||||
already exists, syntax error in the SQL statement, wrong number of parameters specified, etc. */
|
||||
case CR_COMMANDS_OUT_OF_SYNC:
|
||||
case ER_CANT_DO_THIS_DURING_AN_TRANSACTION:
|
||||
case ER_DB_CREATE_EXISTS:
|
||||
case ER_FIELD_SPECIFIED_TWICE:
|
||||
case ER_INVALID_GROUP_FUNC_USE:
|
||||
case ER_NO_SUCH_INDEX:
|
||||
case ER_NO_SUCH_KEY_VALUE:
|
||||
case ER_NO_SUCH_TABLE:
|
||||
case ER_NO_SUCH_USER:
|
||||
case ER_PARSE_ERROR:
|
||||
case ER_SYNTAX_ERROR:
|
||||
case ER_TABLE_MUST_HAVE_COLUMNS:
|
||||
case ER_UNSUPPORTED_EXTENSION:
|
||||
case ER_WRONG_DB_NAME:
|
||||
case ER_WRONG_TABLE_NAME:
|
||||
return Mariadb_ProgrammingError;
|
||||
|
||||
/* IntegrityError: Exception raised when the relational integrity of the database is affected,
|
||||
e.g. a foreign key check fails */
|
||||
case ER_CANNOT_ADD_FOREIGN:
|
||||
case ER_DUP_ENTRY:
|
||||
case ER_DUP_UNIQUE:
|
||||
case ER_NO_DEFAULT_FOR_FIELD:
|
||||
case ER_NO_REFERENCED_ROW:
|
||||
case ER_NO_REFERENCED_ROW_2:
|
||||
case ER_ROW_IS_REFERENCED:
|
||||
case ER_ROW_IS_REFERENCED_2:
|
||||
return Mariadb_IntegrityError;
|
||||
default:
|
||||
/* MariaDB Error */
|
||||
if (error_number >= 1000)
|
||||
return Mariadb_OperationalError;
|
||||
/* same behavior as in MySQLdb: we return an InternalError, in case of system errors */
|
||||
return Mariadb_InternalError;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
mariadb_throw_exception()
|
||||
@brief raises an exception
|
||||
|
||||
@param handle[in] a connection or statement handle
|
||||
@param exception_type[in] type of exception
|
||||
@param is_statement[in] 1 is handle is a MYSQL_STMT handle
|
||||
@param message[in] Error message. If message is NULL, the error
|
||||
message will be retrieved from specified handle.
|
||||
@param ... [in] message parameter
|
||||
|
||||
@return void
|
||||
|
||||
*/
|
||||
void mariadb_throw_exception(void *handle,
|
||||
PyObject *exception_type,
|
||||
unsigned char is_statement,
|
||||
void mariadb_exception_connection_gone(PyObject *exception_type,
|
||||
int error_no,
|
||||
const char *message,
|
||||
...)
|
||||
{
|
||||
@ -117,19 +111,69 @@ void mariadb_throw_exception(void *handle,
|
||||
PyObject *SqlState= 0;
|
||||
PyObject *Exception= 0;
|
||||
|
||||
//if (!exception_type)
|
||||
// exception_type= Mariadb_InterfaceError;
|
||||
|
||||
ErrorNo= PyLong_FromLong(CR_UNKNOWN_ERROR);
|
||||
SqlState= PyUnicode_FromString("HY000");
|
||||
va_start(ap, message);
|
||||
ErrorMsg= PyUnicode_FromFormatV(message, ap);
|
||||
va_end(ap);
|
||||
|
||||
if (!(Exception= PyObject_CallFunctionObjArgs(exception_type, ErrorMsg, NULL)))
|
||||
{
|
||||
PyErr_SetString(PyExc_RuntimeError,
|
||||
"Failed to create exception");
|
||||
return;
|
||||
}
|
||||
|
||||
PyObject_SetAttr(Exception, PyUnicode_FromString("sqlstate"), SqlState);
|
||||
PyObject_SetAttr(Exception, PyUnicode_FromString("errno"), ErrorNo);
|
||||
PyObject_SetAttr(Exception, PyUnicode_FromString("errmsg"), ErrorMsg);
|
||||
/* For MySQL Connector/Python compatibility */
|
||||
PyObject_SetAttr(Exception, PyUnicode_FromString("msg"), ErrorMsg);
|
||||
PyErr_SetObject(exception_type, Exception);
|
||||
Py_XDECREF(ErrorMsg);
|
||||
Py_XDECREF(ErrorNo);
|
||||
Py_XDECREF(SqlState);
|
||||
}
|
||||
|
||||
/**
|
||||
mariadb_throw_exception()
|
||||
@brief raises an exception
|
||||
|
||||
@param handle[in] a connection or statement handle
|
||||
@param exception_type[in] type of exception
|
||||
@param handle_type[in] -1 no handle (use error_no)
|
||||
0 MYSQL
|
||||
1 MYSQL_STMT
|
||||
@param message[in] Error message. If message is NULL, the error
|
||||
message will be retrieved from specified handle.
|
||||
@param ... [in] message parameter
|
||||
|
||||
@return void
|
||||
|
||||
*/
|
||||
void mariadb_throw_exception(void *handle,
|
||||
PyObject *exception_type,
|
||||
int8_t is_statement,
|
||||
const char *message,
|
||||
...)
|
||||
{
|
||||
va_list ap;
|
||||
PyObject *ErrorMsg= 0;
|
||||
PyObject *ErrorNo= 0;
|
||||
PyObject *SqlState= 0;
|
||||
PyObject *Exception= 0;
|
||||
|
||||
if (message)
|
||||
{
|
||||
ErrorNo= PyLong_FromLong(-1);
|
||||
ErrorNo= PyLong_FromLong(CR_UNKNOWN_ERROR);
|
||||
SqlState= PyUnicode_FromString("HY000");
|
||||
va_start(ap, message);
|
||||
ErrorMsg= PyUnicode_FromFormatV(message, ap);
|
||||
va_end(ap);
|
||||
} else
|
||||
{
|
||||
exception_type= get_exception_type(is_statement ? mysql_stmt_sqlstate((MYSQL_STMT*) handle) : mysql_sqlstate((MYSQL *)handle));
|
||||
exception_type= get_exception_type(is_statement ? mysql_stmt_errno((MYSQL_STMT*) handle) : mysql_errno((MYSQL *)handle));
|
||||
|
||||
if (!exception_type)
|
||||
exception_type= Mariadb_DatabaseError;
|
||||
|
Reference in New Issue
Block a user