Callback.c 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303
  1. //-----------------------------------------------------------------------------
  2. // Callback.c
  3. // Definition of OCI callback functions.
  4. //-----------------------------------------------------------------------------
  5. //-----------------------------------------------------------------------------
  6. // Callback_NewVariable()
  7. // Return a new variable from a callback.
  8. //-----------------------------------------------------------------------------
  9. static udt_Variable *Callback_NewVariable(
  10. udt_Connection *connection, // connection to use
  11. ub2 oracleType, // Oracle type of data
  12. ub4 bufferSize, // maximum length of elements
  13. void *data, // data pointer
  14. void *indicator, // indicator pointer
  15. ub2 *returnCode, // return code pointer
  16. ACTUAL_LENGTH_TYPE *actualLength) // actual length pointer
  17. {
  18. udt_VariableType *type;
  19. udt_Variable *var;
  20. // determine the type to use
  21. type = Variable_TypeByOracleDataType(oracleType, SQLCS_IMPLICIT);
  22. if (!type)
  23. return NULL;
  24. // attempt to allocate the object
  25. var = (udt_Variable*) type->pythonType->tp_alloc(type->pythonType, 0);
  26. if (!var)
  27. return NULL;
  28. // perform basic initialization
  29. // note that the number of allocated elements is set arbitrarily high
  30. // because the OCI doesn't give information about how many elements are
  31. // actually allocated; that has to be implied by the number of rows
  32. // passed to OCIStmtFetch and OCIStmtExecute
  33. Py_INCREF(connection->environment);
  34. var->environment = connection->environment;
  35. var->boundCursorHandle = NULL;
  36. var->bindHandle = NULL;
  37. var->defineHandle = NULL;
  38. var->boundName = NULL;
  39. var->allocatedElements = 2147483647;
  40. var->actualElements = 0;
  41. var->isArray = 0;
  42. var->isAllocatedInternally = 0;
  43. var->type = type;
  44. var->indicator = indicator;
  45. var->data = data;
  46. var->actualLength = actualLength;
  47. var->returnCode = returnCode;
  48. var->size = type->size;
  49. var->bufferSize = type->size;
  50. if (type->isVariableLength)
  51. var->bufferSize = bufferSize;
  52. return var;
  53. }
  54. //-----------------------------------------------------------------------------
  55. // Callback_BindByNameArgs()
  56. // Return the arguments to be passed when OCIBindByName is called.
  57. //-----------------------------------------------------------------------------
  58. static PyObject *Callback_BindByNameArgs(
  59. udt_Connection *connection, // connection to use
  60. va_list args) // arguments to OCI function
  61. {
  62. ub4 nameLength, allocatedElements, *actualElements;
  63. ACTUAL_LENGTH_TYPE *actualLength;
  64. ub2 dataType, *returnCode;
  65. dvoid *indicator, *value;
  66. udt_Variable *var;
  67. PyObject *result;
  68. sb4 valueLength;
  69. OCIStmt *handle;
  70. text *name;
  71. handle = va_arg(args, OCIStmt*);
  72. va_arg(args, OCIBind**);
  73. va_arg(args, OCIError*);
  74. name = va_arg(args, text*);
  75. nameLength = va_arg(args, ub4);
  76. value = va_arg(args, dvoid*);
  77. valueLength = va_arg(args, sb4);
  78. dataType = va_arg(args, int);
  79. indicator = va_arg(args, dvoid*);
  80. actualLength = va_arg(args, ACTUAL_LENGTH_TYPE*);
  81. returnCode = va_arg(args, ub2*);
  82. allocatedElements = va_arg(args, ub4);
  83. actualElements = va_arg(args, ub4*);
  84. var = Callback_NewVariable(connection, dataType, valueLength, value,
  85. indicator, returnCode, actualLength);
  86. if (!var)
  87. return NULL;
  88. if (allocatedElements > 0) {
  89. var->isArray = 1;
  90. var->actualElements = *actualElements;
  91. }
  92. result = Py_BuildValue("ls#O", handle, name, nameLength, var);
  93. Py_DECREF(var);
  94. return result;
  95. }
  96. //-----------------------------------------------------------------------------
  97. // Callback_DefineByPosArgs()
  98. // Return the arguments to be passed when OCIDefineByPos is called.
  99. //-----------------------------------------------------------------------------
  100. static PyObject *Callback_DefineByPosArgs(
  101. udt_Connection *connection, // connection to use
  102. va_list args) // arguments to OCI function
  103. {
  104. ACTUAL_LENGTH_TYPE *actualLength;
  105. ub2 dataType, *returnCode;
  106. dvoid *indicator, *value;
  107. udt_Variable *var;
  108. PyObject *result;
  109. OCIStmt *handle;
  110. sb4 valueLength;
  111. ub4 position;
  112. handle = va_arg(args, OCIStmt*);
  113. va_arg(args, OCIDefine**);
  114. va_arg(args, OCIError*);
  115. position = va_arg(args, ub4);
  116. value = va_arg(args, dvoid*);
  117. valueLength = va_arg(args, sb4);
  118. dataType = va_arg(args, int);
  119. indicator = va_arg(args, dvoid*);
  120. actualLength = va_arg(args, ACTUAL_LENGTH_TYPE*);
  121. returnCode = va_arg(args, ub2*);
  122. // create a variable
  123. var = Callback_NewVariable(connection, dataType, valueLength, value,
  124. indicator, returnCode, actualLength);
  125. if (!var)
  126. return NULL;
  127. result = Py_BuildValue("liO", handle, position, var);
  128. Py_DECREF(var);
  129. return result;
  130. }
  131. //-----------------------------------------------------------------------------
  132. // Callback_ExecuteArgs()
  133. // Return the arguments to be passed when OCIStmtExecute is called.
  134. //-----------------------------------------------------------------------------
  135. static PyObject *Callback_ExecuteArgs(
  136. va_list args) // arguments to OCI function
  137. {
  138. ub4 iters, rowoff;
  139. OCIStmt *handle;
  140. va_arg(args, OCISvcCtx*);
  141. handle = va_arg(args, OCIStmt*);
  142. va_arg(args, OCIError*);
  143. iters = va_arg(args, ub4);
  144. rowoff = va_arg(args, ub4);
  145. return Py_BuildValue("lii", handle, iters, rowoff);
  146. }
  147. //-----------------------------------------------------------------------------
  148. // Callback_FetchArgs()
  149. // Return the arguments to be passed when OCIStmtFetch is called.
  150. //-----------------------------------------------------------------------------
  151. static PyObject *Callback_FetchArgs(
  152. udt_Connection *connection, // connection to use
  153. va_list args) // arguments to OCI function
  154. {
  155. ub4 numRows, rowCount;
  156. OCIStmt *handle;
  157. sword status;
  158. handle = va_arg(args, OCIStmt*);
  159. va_arg(args, OCIError*);
  160. numRows = va_arg(args, ub4);
  161. status = OCIAttrGet(handle, OCI_HTYPE_STMT, &rowCount, 0,
  162. OCI_ATTR_ROW_COUNT, connection->environment->errorHandle);
  163. if (Environment_CheckForError(connection->environment, status,
  164. "Callback_FetchArgs()") < 0)
  165. return NULL;
  166. return Py_BuildValue("lii", handle, numRows, rowCount);
  167. }
  168. //-----------------------------------------------------------------------------
  169. // Callback_PrepareArgs()
  170. // Return the arguments to be passed when OCIStmtPrepare is called.
  171. //-----------------------------------------------------------------------------
  172. static PyObject *Callback_PrepareArgs(
  173. va_list args) // arguments to OCI function
  174. {
  175. ub4 statementLength;
  176. OCIStmt *handle;
  177. text *statement;
  178. handle = va_arg(args, OCIStmt*);
  179. va_arg(args, OCIError*);
  180. statement = va_arg(args, text *);
  181. statementLength = va_arg(args, ub4);
  182. return Py_BuildValue("ls#", handle, statement, statementLength);
  183. }
  184. //-----------------------------------------------------------------------------
  185. // Callback_GetArgs()
  186. // Return the arguments to be passed to the Python callback method.
  187. //-----------------------------------------------------------------------------
  188. static PyObject *Callback_GetArgs(
  189. udt_Connection *connection, // connection to use
  190. ub4 functionCode, // function code
  191. va_list args) // OCI function arguments
  192. {
  193. switch (functionCode) {
  194. case OCI_FNCODE_BINDBYNAME:
  195. return Callback_BindByNameArgs(connection, args);
  196. case OCI_FNCODE_DEFINEBYPOS:
  197. return Callback_DefineByPosArgs(connection, args);
  198. case OCI_FNCODE_STMTEXECUTE:
  199. return Callback_ExecuteArgs(args);
  200. case OCI_FNCODE_STMTFETCH:
  201. return Callback_FetchArgs(connection, args);
  202. case OCI_FNCODE_STMTPREPARE:
  203. return Callback_PrepareArgs(args);
  204. }
  205. return PyTuple_New(0);
  206. }
  207. //-----------------------------------------------------------------------------
  208. // Callback_Call()
  209. // Actually make the call to the Python function.
  210. //-----------------------------------------------------------------------------
  211. static sword Callback_Call(
  212. PyObject *tuple, // tuple containing connection/callback
  213. ub4 functionCode, // function code
  214. va_list args) // arguments
  215. {
  216. PyObject *callback, *callbackArgs, *result;
  217. udt_Connection *connection;
  218. // determine the connection and callback
  219. connection = (udt_Connection*) PyTuple_GET_ITEM(tuple, 0);
  220. callback = PyTuple_GET_ITEM(tuple, 1);
  221. // determine the arguments to pass to the function
  222. callbackArgs = Callback_GetArgs(connection, functionCode, args);
  223. if (!callbackArgs)
  224. return OCI_ERROR;
  225. // actually make the call to the method
  226. result = PyEval_CallObject(callback, callbackArgs);
  227. Py_DECREF(callbackArgs);
  228. if (!result)
  229. return OCI_ERROR;
  230. Py_DECREF(result);
  231. return OCI_SUCCESS;
  232. }
  233. //-----------------------------------------------------------------------------
  234. // Callback_Handler()
  235. // Callback handler for calling Python code within an OCI callback.
  236. //-----------------------------------------------------------------------------
  237. static sword Callback_Handler(
  238. PyObject *tuple, // tuple containing connection/callback
  239. dvoid *handle, // pointer to handle
  240. ub4 handleType, // handle type
  241. ub4 functionCode, // function code
  242. ub1 when, // when being called
  243. sword returnCode, // return code
  244. ub4 *errorCode, // error code (IN/OUT)
  245. va_list args) // arguments
  246. {
  247. #ifdef WITH_THREAD
  248. PyGILState_STATE gstate = PyGILState_Ensure();
  249. #endif
  250. sword result;
  251. // perform the call
  252. result = Callback_Call(tuple, functionCode, args);
  253. if (result != OCI_CONTINUE)
  254. PyErr_Print();
  255. // restore thread state, if necessary
  256. #ifdef WITH_THREAD
  257. PyGILState_Release(gstate);
  258. #endif
  259. return result;
  260. }