LobVar.c 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429
  1. //-----------------------------------------------------------------------------
  2. // LobVar.c
  3. // Defines the routines for handling LOB variables.
  4. //-----------------------------------------------------------------------------
  5. //-----------------------------------------------------------------------------
  6. // LOB type
  7. //-----------------------------------------------------------------------------
  8. typedef struct {
  9. Variable_HEAD
  10. OCILobLocator **data;
  11. udt_Connection *connection;
  12. int isFile;
  13. } udt_LobVar;
  14. //-----------------------------------------------------------------------------
  15. // Declaration of LOB variable functions.
  16. //-----------------------------------------------------------------------------
  17. static int LobVar_Initialize(udt_LobVar*, udt_Cursor*);
  18. static int LobVar_PreFetch(udt_LobVar*);
  19. static void LobVar_Finalize(udt_LobVar*);
  20. static PyObject *LobVar_GetValue(udt_LobVar*, unsigned);
  21. static int LobVar_SetValue(udt_LobVar*, unsigned, PyObject*);
  22. static int LobVar_Write(udt_LobVar*, unsigned, PyObject*, oraub8, oraub8*);
  23. //-----------------------------------------------------------------------------
  24. // Python type declarations
  25. //-----------------------------------------------------------------------------
  26. static PyTypeObject g_CLOBVarType = {
  27. PyVarObject_HEAD_INIT(NULL, 0)
  28. "cx_Oracle.CLOB", // tp_name
  29. sizeof(udt_LobVar), // tp_basicsize
  30. 0, // tp_itemsize
  31. 0, // tp_dealloc
  32. 0, // tp_print
  33. 0, // tp_getattr
  34. 0, // tp_setattr
  35. 0, // tp_compare
  36. 0, // tp_repr
  37. 0, // tp_as_number
  38. 0, // tp_as_sequence
  39. 0, // tp_as_mapping
  40. 0, // tp_hash
  41. 0, // tp_call
  42. 0, // tp_str
  43. 0, // tp_getattro
  44. 0, // tp_setattro
  45. 0, // tp_as_buffer
  46. Py_TPFLAGS_DEFAULT, // tp_flags
  47. 0 // tp_doc
  48. };
  49. static PyTypeObject g_NCLOBVarType = {
  50. PyVarObject_HEAD_INIT(NULL, 0)
  51. "cx_Oracle.NCLOB", // tp_name
  52. sizeof(udt_LobVar), // tp_basicsize
  53. 0, // tp_itemsize
  54. 0, // tp_dealloc
  55. 0, // tp_print
  56. 0, // tp_getattr
  57. 0, // tp_setattr
  58. 0, // tp_compare
  59. 0, // tp_repr
  60. 0, // tp_as_number
  61. 0, // tp_as_sequence
  62. 0, // tp_as_mapping
  63. 0, // tp_hash
  64. 0, // tp_call
  65. 0, // tp_str
  66. 0, // tp_getattro
  67. 0, // tp_setattro
  68. 0, // tp_as_buffer
  69. Py_TPFLAGS_DEFAULT, // tp_flags
  70. 0 // tp_doc
  71. };
  72. static PyTypeObject g_BLOBVarType = {
  73. PyVarObject_HEAD_INIT(NULL, 0)
  74. "cx_Oracle.BLOB", // tp_name
  75. sizeof(udt_LobVar), // tp_basicsize
  76. 0, // tp_itemsize
  77. 0, // tp_dealloc
  78. 0, // tp_print
  79. 0, // tp_getattr
  80. 0, // tp_setattr
  81. 0, // tp_compare
  82. 0, // tp_repr
  83. 0, // tp_as_number
  84. 0, // tp_as_sequence
  85. 0, // tp_as_mapping
  86. 0, // tp_hash
  87. 0, // tp_call
  88. 0, // tp_str
  89. 0, // tp_getattro
  90. 0, // tp_setattro
  91. 0, // tp_as_buffer
  92. Py_TPFLAGS_DEFAULT, // tp_flags
  93. 0 // tp_doc
  94. };
  95. static PyTypeObject g_BFILEVarType = {
  96. PyVarObject_HEAD_INIT(NULL, 0)
  97. "cx_Oracle.BFILE", // tp_name
  98. sizeof(udt_LobVar), // tp_basicsize
  99. 0, // tp_itemsize
  100. 0, // tp_dealloc
  101. 0, // tp_print
  102. 0, // tp_getattr
  103. 0, // tp_setattr
  104. 0, // tp_compare
  105. 0, // tp_repr
  106. 0, // tp_as_number
  107. 0, // tp_as_sequence
  108. 0, // tp_as_mapping
  109. 0, // tp_hash
  110. 0, // tp_call
  111. 0, // tp_str
  112. 0, // tp_getattro
  113. 0, // tp_setattro
  114. 0, // tp_as_buffer
  115. Py_TPFLAGS_DEFAULT, // tp_flags
  116. 0 // tp_doc
  117. };
  118. //-----------------------------------------------------------------------------
  119. // variable type declarations
  120. //-----------------------------------------------------------------------------
  121. static udt_VariableType vt_CLOB = {
  122. (InitializeProc) LobVar_Initialize,
  123. (FinalizeProc) LobVar_Finalize,
  124. (PreDefineProc) NULL,
  125. (PostDefineProc) NULL,
  126. (PreFetchProc) LobVar_PreFetch,
  127. (IsNullProc) NULL,
  128. (SetValueProc) LobVar_SetValue,
  129. (GetValueProc) LobVar_GetValue,
  130. (GetBufferSizeProc) NULL,
  131. &g_CLOBVarType, // Python type
  132. SQLT_CLOB, // Oracle type
  133. SQLCS_IMPLICIT, // charset form
  134. sizeof(OCILobLocator*), // element length
  135. 1, // is character data
  136. 0, // is variable length
  137. 0, // can be copied
  138. 0 // can be in array
  139. };
  140. static udt_VariableType vt_NCLOB = {
  141. (InitializeProc) LobVar_Initialize,
  142. (FinalizeProc) LobVar_Finalize,
  143. (PreDefineProc) NULL,
  144. (PostDefineProc) NULL,
  145. (PreFetchProc) LobVar_PreFetch,
  146. (IsNullProc) NULL,
  147. (SetValueProc) LobVar_SetValue,
  148. (GetValueProc) LobVar_GetValue,
  149. (GetBufferSizeProc) NULL,
  150. &g_NCLOBVarType, // Python type
  151. SQLT_CLOB, // Oracle type
  152. SQLCS_NCHAR, // charset form
  153. sizeof(OCILobLocator*), // element length
  154. 1, // is character data
  155. 0, // is variable length
  156. 0, // can be copied
  157. 0 // can be in array
  158. };
  159. static udt_VariableType vt_BLOB = {
  160. (InitializeProc) LobVar_Initialize,
  161. (FinalizeProc) LobVar_Finalize,
  162. (PreDefineProc) NULL,
  163. (PostDefineProc) NULL,
  164. (PreFetchProc) LobVar_PreFetch,
  165. (IsNullProc) NULL,
  166. (SetValueProc) LobVar_SetValue,
  167. (GetValueProc) LobVar_GetValue,
  168. (GetBufferSizeProc) NULL,
  169. &g_BLOBVarType, // Python type
  170. SQLT_BLOB, // Oracle type
  171. SQLCS_IMPLICIT, // charset form
  172. sizeof(OCILobLocator*), // element length
  173. 0, // is character data
  174. 0, // is variable length
  175. 0, // can be copied
  176. 0 // can be in array
  177. };
  178. static udt_VariableType vt_BFILE = {
  179. (InitializeProc) LobVar_Initialize,
  180. (FinalizeProc) LobVar_Finalize,
  181. (PreDefineProc) NULL,
  182. (PostDefineProc) NULL,
  183. (PreFetchProc) LobVar_PreFetch,
  184. (IsNullProc) NULL,
  185. (SetValueProc) LobVar_SetValue,
  186. (GetValueProc) LobVar_GetValue,
  187. (GetBufferSizeProc) NULL,
  188. &g_BFILEVarType, // Python type
  189. SQLT_BFILE, // Oracle type
  190. SQLCS_IMPLICIT, // charset form
  191. sizeof(OCILobLocator*), // element length
  192. 0, // is character data
  193. 0, // is variable length
  194. 0, // can be copied
  195. 0 // can be in array
  196. };
  197. #include "ExternalLobVar.c"
  198. //-----------------------------------------------------------------------------
  199. // LobVar_Initialize()
  200. // Initialize the variable.
  201. //-----------------------------------------------------------------------------
  202. static int LobVar_Initialize(
  203. udt_LobVar *var, // variable to initialize
  204. udt_Cursor *cursor) // cursor created by
  205. {
  206. sword status;
  207. ub4 i;
  208. // initialize members
  209. Py_INCREF(cursor->connection);
  210. var->connection = cursor->connection;
  211. var->isFile = (var->type == &vt_BFILE);
  212. // initialize the LOB locators
  213. for (i = 0; i < var->allocatedElements; i++) {
  214. status = OCIDescriptorAlloc(var->environment->handle,
  215. (dvoid**) &var->data[i], OCI_DTYPE_LOB, 0, 0);
  216. if (Environment_CheckForError(var->environment, status,
  217. "LobVar_Initialize()") < 0)
  218. return -1;
  219. }
  220. return 0;
  221. }
  222. //-----------------------------------------------------------------------------
  223. // LobVar_PreFetch()
  224. // Free temporary LOBs prior to fetch.
  225. //-----------------------------------------------------------------------------
  226. static int LobVar_PreFetch(
  227. udt_LobVar *var) // variable to free
  228. {
  229. boolean isTemporary;
  230. sword status;
  231. ub4 i;
  232. for (i = 0; i < var->allocatedElements; i++) {
  233. if (var->data[i]) {
  234. status = OCILobIsTemporary(var->environment->handle,
  235. var->environment->errorHandle, var->data[i], &isTemporary);
  236. if (Environment_CheckForError(var->environment, status,
  237. "LobVar_PreFetch(): is temporary LOB?") < 0)
  238. return -1;
  239. if (isTemporary) {
  240. Py_BEGIN_ALLOW_THREADS
  241. status = OCILobFreeTemporary(var->connection->handle,
  242. var->environment->errorHandle, var->data[i]);
  243. Py_END_ALLOW_THREADS
  244. if (Environment_CheckForError(var->environment, status,
  245. "LobVar_PreFetch(): free temporary LOB") < 0)
  246. return -1;
  247. }
  248. }
  249. }
  250. return 0;
  251. }
  252. //-----------------------------------------------------------------------------
  253. // LobVar_Finalize()
  254. // Prepare for variable destruction.
  255. //-----------------------------------------------------------------------------
  256. static void LobVar_Finalize(
  257. udt_LobVar *var) // variable to free
  258. {
  259. boolean isTemporary;
  260. ub4 i;
  261. for (i = 0; i < var->allocatedElements; i++) {
  262. if (var->data[i]) {
  263. OCILobIsTemporary(var->environment->handle,
  264. var->environment->errorHandle, var->data[i], &isTemporary);
  265. if (isTemporary) {
  266. Py_BEGIN_ALLOW_THREADS
  267. OCILobFreeTemporary(var->connection->handle,
  268. var->environment->errorHandle, var->data[i]);
  269. Py_END_ALLOW_THREADS
  270. }
  271. OCIDescriptorFree(var->data[i], OCI_DTYPE_LOB);
  272. }
  273. }
  274. Py_DECREF(var->connection);
  275. }
  276. //-----------------------------------------------------------------------------
  277. // LobVar_Write()
  278. // Write data to the LOB variable.
  279. //-----------------------------------------------------------------------------
  280. static int LobVar_Write(
  281. udt_LobVar *var, // variable to perform write against
  282. unsigned position, // position to perform write against
  283. PyObject *dataObj, // data object to write into LOB
  284. oraub8 offset, // offset into variable
  285. oraub8 *amount) // amount to write
  286. {
  287. udt_Buffer buffer;
  288. sword status;
  289. // verify the data type
  290. if (var->type == &vt_BFILE) {
  291. PyErr_SetString(PyExc_TypeError, "BFILEs are read only");
  292. return -1;
  293. } else if (var->type == &vt_BLOB) {
  294. if (cxBuffer_FromObject(&buffer, dataObj,
  295. var->environment->encoding) < 0)
  296. return -1;
  297. *amount = buffer.size;
  298. #if PY_MAJOR_VERSION < 3
  299. } else if (var->type == &vt_NCLOB) {
  300. if (cxBuffer_FromObject(&buffer, dataObj,
  301. var->environment->nencoding) < 0)
  302. return -1;
  303. *amount = buffer.size;
  304. #endif
  305. } else {
  306. if (cxBuffer_FromObject(&buffer, dataObj,
  307. var->environment->encoding) < 0)
  308. return -1;
  309. if (var->environment->fixedWidth
  310. && var->environment->maxBytesPerCharacter > 1)
  311. *amount = buffer.size / var->environment->maxBytesPerCharacter;
  312. else *amount = buffer.size;
  313. }
  314. // nothing to do if no data to write
  315. if (*amount == 0) {
  316. cxBuffer_Clear(&buffer);
  317. return 0;
  318. }
  319. Py_BEGIN_ALLOW_THREADS
  320. status = OCILobWrite2(var->connection->handle,
  321. var->environment->errorHandle, var->data[position], amount, 0,
  322. offset, (void*) buffer.ptr, buffer.size, OCI_ONE_PIECE, NULL, NULL,
  323. 0, var->type->charsetForm);
  324. Py_END_ALLOW_THREADS
  325. cxBuffer_Clear(&buffer);
  326. if (Environment_CheckForError(var->environment, status,
  327. "LobVar_Write()") < 0)
  328. return -1;
  329. return 0;
  330. }
  331. //-----------------------------------------------------------------------------
  332. // LobVar_GetValue()
  333. // Returns the value stored at the given array position.
  334. //-----------------------------------------------------------------------------
  335. static PyObject *LobVar_GetValue(
  336. udt_LobVar *var, // variable to determine value for
  337. unsigned pos) // array position
  338. {
  339. return ExternalLobVar_New(var, pos);
  340. }
  341. //-----------------------------------------------------------------------------
  342. // LobVar_SetValue()
  343. // Sets the value stored at the given array position.
  344. //-----------------------------------------------------------------------------
  345. static int LobVar_SetValue(
  346. udt_LobVar *var, // variable to determine value for
  347. unsigned position, // array position
  348. PyObject *value) // value to set
  349. {
  350. boolean isTemporary;
  351. oraub8 amount;
  352. sword status;
  353. ub1 lobType;
  354. // make sure have temporary LOBs set up
  355. status = OCILobIsTemporary(var->environment->handle,
  356. var->environment->errorHandle, var->data[position], &isTemporary);
  357. if (Environment_CheckForError(var->environment, status,
  358. "LobVar_SetValue(): is temporary?") < 0)
  359. return -1;
  360. if (!isTemporary) {
  361. if (var->type->oracleType == SQLT_BLOB)
  362. lobType = OCI_TEMP_BLOB;
  363. else lobType = OCI_TEMP_CLOB;
  364. Py_BEGIN_ALLOW_THREADS
  365. status = OCILobCreateTemporary(var->connection->handle,
  366. var->environment->errorHandle, var->data[position],
  367. OCI_DEFAULT, var->type->charsetForm, lobType, FALSE,
  368. OCI_DURATION_SESSION);
  369. Py_END_ALLOW_THREADS
  370. if (Environment_CheckForError(var->environment, status,
  371. "LobVar_SetValue(): create temporary") < 0)
  372. return -1;
  373. }
  374. // trim the current value
  375. Py_BEGIN_ALLOW_THREADS
  376. status = OCILobTrim(var->connection->handle,
  377. var->environment->errorHandle, var->data[position], 0);
  378. Py_END_ALLOW_THREADS
  379. if (Environment_CheckForError(var->environment, status,
  380. "LobVar_SetValue(): trim") < 0)
  381. return -1;
  382. // set the current value
  383. return LobVar_Write(var, position, value, 1, &amount);
  384. }