PageRenderTime 43ms CodeModel.GetById 20ms RepoModel.GetById 1ms app.codeStats 0ms

/Error.c

https://bitbucket.org/anthony_tuininga/ceodbc
C | 197 lines | 141 code | 23 blank | 33 comment | 26 complexity | b7d661ad92f4a59f391a606a2f1ad90c MD5 | raw file
  1. //-----------------------------------------------------------------------------
  2. // Error.c
  3. // Error handling.
  4. //-----------------------------------------------------------------------------
  5. #define CheckForError(obj, rc, context) \
  6. Error_CheckForError((udt_ObjectWithHandle*) obj, rc, context)
  7. #define ObjectWithHandle_HEAD \
  8. PyObject_HEAD \
  9. SQLSMALLINT handleType; \
  10. SQLHANDLE handle;
  11. typedef struct {
  12. ObjectWithHandle_HEAD
  13. } udt_ObjectWithHandle;
  14. //-----------------------------------------------------------------------------
  15. // structure for the Python type
  16. //-----------------------------------------------------------------------------
  17. typedef struct {
  18. PyObject_HEAD
  19. PyObject *message;
  20. const char *context;
  21. } udt_Error;
  22. //-----------------------------------------------------------------------------
  23. // forward declarations
  24. //-----------------------------------------------------------------------------
  25. static void Error_Free(udt_Error*);
  26. static PyObject *Error_Str(udt_Error*);
  27. //-----------------------------------------------------------------------------
  28. // declaration of members
  29. //-----------------------------------------------------------------------------
  30. static PyMemberDef g_ErrorMembers[] = {
  31. { "message", T_OBJECT, offsetof(udt_Error, message), READONLY },
  32. { "context", T_STRING, offsetof(udt_Error, context), READONLY },
  33. { NULL }
  34. };
  35. //-----------------------------------------------------------------------------
  36. // declaration of Python type
  37. //-----------------------------------------------------------------------------
  38. static PyTypeObject g_ErrorType = {
  39. PyVarObject_HEAD_INIT(NULL, 0)
  40. "ceODBC._Error", // tp_name
  41. sizeof(udt_Error), // tp_basicsize
  42. 0, // tp_itemsize
  43. (destructor) Error_Free, // tp_dealloc
  44. 0, // tp_print
  45. 0, // tp_getattr
  46. 0, // tp_setattr
  47. 0, // tp_compare
  48. 0, // tp_repr
  49. 0, // tp_as_number
  50. 0, // tp_as_sequence
  51. 0, // tp_as_mapping
  52. 0, // tp_hash
  53. 0, // tp_call
  54. (reprfunc) Error_Str, // tp_str
  55. 0, // tp_getattro
  56. 0, // tp_setattro
  57. 0, // tp_as_buffer
  58. Py_TPFLAGS_DEFAULT, // tp_flags
  59. 0, // tp_doc
  60. 0, // tp_traverse
  61. 0, // tp_clear
  62. 0, // tp_richcompare
  63. 0, // tp_weaklistoffset
  64. 0, // tp_iter
  65. 0, // tp_iternext
  66. 0, // tp_methods
  67. g_ErrorMembers, // tp_members
  68. 0 // tp_getset
  69. };
  70. //-----------------------------------------------------------------------------
  71. // Error_Free()
  72. // Deallocate the environment, disconnecting from the database if necessary.
  73. //-----------------------------------------------------------------------------
  74. static void Error_Free(
  75. udt_Error *self) // error object
  76. {
  77. Py_CLEAR(self->message);
  78. Py_TYPE(self)->tp_free((PyObject*) self);
  79. }
  80. //-----------------------------------------------------------------------------
  81. // Error_Str()
  82. // Return a string representation of the error variable.
  83. //-----------------------------------------------------------------------------
  84. static PyObject *Error_Str(
  85. udt_Error *self) // variable to return the string for
  86. {
  87. if (self->message) {
  88. Py_INCREF(self->message);
  89. return self->message;
  90. }
  91. return ceString_FromAscii("");
  92. }
  93. //-----------------------------------------------------------------------------
  94. // Error_CheckForError()
  95. // Check for an error in the last call and if an error has occurred, raise a
  96. // Python exception.
  97. //-----------------------------------------------------------------------------
  98. static int Error_CheckForError(
  99. udt_ObjectWithHandle *obj, // object to check for errors on
  100. SQLRETURN rcToCheck, // return code of last call
  101. const char *context) // context
  102. {
  103. PyObject *errorMessages, *temp, *separator;
  104. CEODBC_CHAR buffer[1024];
  105. SQLINTEGER numRecords;
  106. SQLSMALLINT length;
  107. udt_Error *error;
  108. SQLRETURN rc;
  109. int i;
  110. // handle simple cases
  111. if (rcToCheck == SQL_SUCCESS || rcToCheck == SQL_SUCCESS_WITH_INFO)
  112. return 0;
  113. if (rcToCheck == SQL_INVALID_HANDLE) {
  114. PyErr_SetString(g_DatabaseErrorException, "Invalid handle!");
  115. return -1;
  116. }
  117. // create new error object
  118. error = PyObject_NEW(udt_Error, &g_ErrorType);
  119. if (!error)
  120. return -1;
  121. error->context = context;
  122. // determine number of diagnostic records available
  123. rc = SQLGetDiagField(obj->handleType, obj->handle, 0, SQL_DIAG_NUMBER,
  124. &numRecords, SQL_IS_INTEGER, NULL);
  125. if (rc != SQL_SUCCESS && rc != SQL_SUCCESS_WITH_INFO) {
  126. error->message = ceString_FromAscii("cannot get number of " \
  127. "diagnostic records");
  128. // determine error text
  129. } else if (numRecords == 0) {
  130. error->message = ceString_FromAscii("no diagnostic message text " \
  131. "available");
  132. } else {
  133. error->message = NULL;
  134. errorMessages = PyList_New(numRecords);
  135. if (!errorMessages) {
  136. Py_DECREF(error);
  137. return -1;
  138. }
  139. for (i = 1; i <= numRecords; i++) {
  140. rc = SQLGetDiagField(obj->handleType, obj->handle, i,
  141. SQL_DIAG_MESSAGE_TEXT, buffer, sizeof(buffer), &length);
  142. if (rc != SQL_SUCCESS && rc != SQL_SUCCESS_WITH_INFO) {
  143. error->message = ceString_FromAscii("cannot get " \
  144. "diagnostic message text");
  145. break;
  146. }
  147. temp = ceString_FromStringAndSize( (char*) buffer, length);
  148. if (!temp) {
  149. Py_DECREF(error);
  150. Py_DECREF(errorMessages);
  151. return -1;
  152. }
  153. PyList_SET_ITEM(errorMessages, i - 1, temp);
  154. }
  155. if (!error->message) {
  156. separator = ceString_FromAscii("\n");
  157. if (!separator) {
  158. Py_DECREF(error);
  159. Py_DECREF(errorMessages);
  160. return -1;
  161. }
  162. error->message = ceString_Join(separator, errorMessages);
  163. Py_DECREF(separator);
  164. Py_DECREF(errorMessages);
  165. }
  166. }
  167. if (!error->message) {
  168. Py_DECREF(error);
  169. return -1;
  170. }
  171. PyErr_SetObject(g_DatabaseErrorException, (PyObject*) error);
  172. Py_DECREF(error);
  173. return -1;
  174. }