NumberVar.c 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608
  1. //-----------------------------------------------------------------------------
  2. // NumberVar.c
  3. // Defines the routines for handling numeric variables.
  4. //-----------------------------------------------------------------------------
  5. //-----------------------------------------------------------------------------
  6. // Number types
  7. //-----------------------------------------------------------------------------
  8. typedef struct {
  9. Variable_HEAD
  10. OCINumber *data;
  11. } udt_NumberVar;
  12. #ifdef SQLT_BFLOAT
  13. typedef struct {
  14. Variable_HEAD
  15. double *data;
  16. } udt_NativeFloatVar;
  17. #endif
  18. //-----------------------------------------------------------------------------
  19. // Declaration of number variable functions.
  20. //-----------------------------------------------------------------------------
  21. static int NumberVar_PreDefine(udt_NumberVar*, OCIParam*);
  22. static int NumberVar_SetValue(udt_NumberVar*, unsigned, PyObject*);
  23. static PyObject *NumberVar_GetValue(udt_NumberVar*, unsigned);
  24. #ifdef SQLT_BFLOAT
  25. static int NativeFloatVar_SetValue(udt_NativeFloatVar*, unsigned, PyObject*);
  26. static PyObject *NativeFloatVar_GetValue(udt_NativeFloatVar*, unsigned);
  27. #endif
  28. //-----------------------------------------------------------------------------
  29. // Python type declaration
  30. //-----------------------------------------------------------------------------
  31. static PyTypeObject g_NumberVarType = {
  32. PyVarObject_HEAD_INIT(NULL, 0)
  33. "cx_Oracle.NUMBER", // tp_name
  34. sizeof(udt_NumberVar), // tp_basicsize
  35. 0, // tp_itemsize
  36. 0, // tp_dealloc
  37. 0, // tp_print
  38. 0, // tp_getattr
  39. 0, // tp_setattr
  40. 0, // tp_compare
  41. 0, // tp_repr
  42. 0, // tp_as_number
  43. 0, // tp_as_sequence
  44. 0, // tp_as_mapping
  45. 0, // tp_hash
  46. 0, // tp_call
  47. 0, // tp_str
  48. 0, // tp_getattro
  49. 0, // tp_setattro
  50. 0, // tp_as_buffer
  51. Py_TPFLAGS_DEFAULT, // tp_flags
  52. 0 // tp_doc
  53. };
  54. #ifdef SQLT_BFLOAT
  55. static PyTypeObject g_NativeFloatVarType = {
  56. PyVarObject_HEAD_INIT(NULL, 0)
  57. "cx_Oracle.NATIVE_FLOAT", // tp_name
  58. sizeof(udt_NativeFloatVar), // tp_basicsize
  59. 0, // tp_itemsize
  60. 0, // tp_dealloc
  61. 0, // tp_print
  62. 0, // tp_getattr
  63. 0, // tp_setattr
  64. 0, // tp_compare
  65. 0, // tp_repr
  66. 0, // tp_as_number
  67. 0, // tp_as_sequence
  68. 0, // tp_as_mapping
  69. 0, // tp_hash
  70. 0, // tp_call
  71. 0, // tp_str
  72. 0, // tp_getattro
  73. 0, // tp_setattro
  74. 0, // tp_as_buffer
  75. Py_TPFLAGS_DEFAULT, // tp_flags
  76. 0 // tp_doc
  77. };
  78. #endif
  79. //-----------------------------------------------------------------------------
  80. // variable type declarations
  81. //-----------------------------------------------------------------------------
  82. static udt_VariableType vt_Float = {
  83. (InitializeProc) NULL,
  84. (FinalizeProc) NULL,
  85. (PreDefineProc) NumberVar_PreDefine,
  86. (PostDefineProc) NULL,
  87. (PreFetchProc) NULL,
  88. (IsNullProc) NULL,
  89. (SetValueProc) NumberVar_SetValue,
  90. (GetValueProc) NumberVar_GetValue,
  91. (GetBufferSizeProc) NULL,
  92. &g_NumberVarType, // Python type
  93. SQLT_VNU, // Oracle type
  94. SQLCS_IMPLICIT, // charset form
  95. sizeof(OCINumber), // element length
  96. 0, // is character data
  97. 0, // is variable length
  98. 1, // can be copied
  99. 1 // can be in array
  100. };
  101. #ifdef SQLT_BFLOAT
  102. static udt_VariableType vt_NativeFloat = {
  103. (InitializeProc) NULL,
  104. (FinalizeProc) NULL,
  105. (PreDefineProc) NULL,
  106. (PostDefineProc) NULL,
  107. (PreFetchProc) NULL,
  108. (IsNullProc) NULL,
  109. (SetValueProc) NativeFloatVar_SetValue,
  110. (GetValueProc) NativeFloatVar_GetValue,
  111. (GetBufferSizeProc) NULL,
  112. &g_NativeFloatVarType, // Python type
  113. SQLT_BDOUBLE, // Oracle type
  114. SQLCS_IMPLICIT, // charset form
  115. sizeof(double), // element length
  116. 0, // is character data
  117. 0, // is variable length
  118. 1, // can be copied
  119. 1 // can be in array
  120. };
  121. #endif
  122. #if PY_MAJOR_VERSION < 3
  123. static udt_VariableType vt_Integer = {
  124. (InitializeProc) NULL,
  125. (FinalizeProc) NULL,
  126. (PreDefineProc) NumberVar_PreDefine,
  127. (PostDefineProc) NULL,
  128. (PreFetchProc) NULL,
  129. (IsNullProc) NULL,
  130. (SetValueProc) NumberVar_SetValue,
  131. (GetValueProc) NumberVar_GetValue,
  132. (GetBufferSizeProc) NULL,
  133. &g_NumberVarType, // Python type
  134. SQLT_VNU, // Oracle type
  135. SQLCS_IMPLICIT, // charset form
  136. sizeof(OCINumber), // element length
  137. 0, // is character data
  138. 0, // is variable length
  139. 1, // can be copied
  140. 1 // can be in array
  141. };
  142. #endif
  143. static udt_VariableType vt_LongInteger = {
  144. (InitializeProc) NULL,
  145. (FinalizeProc) NULL,
  146. (PreDefineProc) NumberVar_PreDefine,
  147. (PostDefineProc) NULL,
  148. (PreFetchProc) NULL,
  149. (IsNullProc) NULL,
  150. (SetValueProc) NumberVar_SetValue,
  151. (GetValueProc) NumberVar_GetValue,
  152. (GetBufferSizeProc) NULL,
  153. &g_NumberVarType, // Python type
  154. SQLT_VNU, // Oracle type
  155. SQLCS_IMPLICIT, // charset form
  156. sizeof(OCINumber), // element length
  157. 0, // is character data
  158. 0, // is variable length
  159. 1, // can be copied
  160. 1 // can be in array
  161. };
  162. static udt_VariableType vt_NumberAsString = {
  163. (InitializeProc) NULL,
  164. (FinalizeProc) NULL,
  165. (PreDefineProc) NumberVar_PreDefine,
  166. (PostDefineProc) NULL,
  167. (PreFetchProc) NULL,
  168. (IsNullProc) NULL,
  169. (SetValueProc) NumberVar_SetValue,
  170. (GetValueProc) NumberVar_GetValue,
  171. (GetBufferSizeProc) NULL,
  172. &g_NumberVarType, // Python type
  173. SQLT_VNU, // Oracle type
  174. SQLCS_IMPLICIT, // charset form
  175. sizeof(OCINumber), // element length
  176. 0, // is character data
  177. 0, // is variable length
  178. 1, // can be copied
  179. 1 // can be in array
  180. };
  181. static udt_VariableType vt_Boolean = {
  182. (InitializeProc) NULL,
  183. (FinalizeProc) NULL,
  184. (PreDefineProc) NumberVar_PreDefine,
  185. (PostDefineProc) NULL,
  186. (PreFetchProc) NULL,
  187. (IsNullProc) NULL,
  188. (SetValueProc) NumberVar_SetValue,
  189. (GetValueProc) NumberVar_GetValue,
  190. (GetBufferSizeProc) NULL,
  191. &g_NumberVarType, // Python type
  192. SQLT_VNU, // Oracle type
  193. SQLCS_IMPLICIT, // charset form
  194. sizeof(OCINumber), // element length
  195. 0, // is character data
  196. 0, // is variable length
  197. 1, // can be copied
  198. 1 // can be in array
  199. };
  200. //-----------------------------------------------------------------------------
  201. // NumberVar_PreDefine()
  202. // Set the type of value (integer, float or string) that will be returned
  203. // when values are fetched from this variable.
  204. //-----------------------------------------------------------------------------
  205. static int NumberVar_PreDefine(
  206. udt_NumberVar *var, // variable to initialize
  207. OCIParam *param) // parameter handle
  208. {
  209. sb2 precision;
  210. sword status;
  211. sb1 scale;
  212. // if the return type has not already been specified, check to see if the
  213. // number can fit inside an integer by looking at the precision and scale
  214. if (var->type == &vt_Float) {
  215. scale = 0;
  216. precision = 0;
  217. status = OCIAttrGet(param, OCI_HTYPE_DESCRIBE, (dvoid*) &scale, 0,
  218. OCI_ATTR_SCALE, var->environment->errorHandle);
  219. if (Environment_CheckForError(var->environment, status,
  220. "NumberVar_PreDefine(): scale") < 0)
  221. return -1;
  222. status = OCIAttrGet(param, OCI_HTYPE_DESCRIBE, (dvoid*) &precision, 0,
  223. OCI_ATTR_PRECISION, var->environment->errorHandle);
  224. if (Environment_CheckForError(var->environment, status,
  225. "NumberVar_PreDefine(): precision") < 0)
  226. return -1;
  227. if (scale == 0 || (scale == -127 && precision == 0)) {
  228. var->type = &vt_LongInteger;
  229. #if PY_MAJOR_VERSION < 3
  230. if (precision > 0 && precision < 10)
  231. var->type = &vt_Integer;
  232. #endif
  233. }
  234. }
  235. return 0;
  236. }
  237. //-----------------------------------------------------------------------------
  238. // NumberVar_SetValueFromBoolean()
  239. // Set the value of the variable from a Python boolean.
  240. //-----------------------------------------------------------------------------
  241. static int NumberVar_SetValueFromBoolean(
  242. udt_NumberVar *var, // variable to set value for
  243. unsigned pos, // array position to set
  244. PyObject *value) // value to set
  245. {
  246. long integerValue;
  247. sword status;
  248. integerValue = (value == Py_True);
  249. status = OCINumberFromInt(var->environment->errorHandle, &integerValue,
  250. sizeof(long), OCI_NUMBER_SIGNED, &var->data[pos]);
  251. return Environment_CheckForError(var->environment, status,
  252. "NumberVar_SetValueFromBoolean()");
  253. }
  254. #if PY_MAJOR_VERSION < 3
  255. //-----------------------------------------------------------------------------
  256. // NumberVar_SetValueFromInteger()
  257. // Set the value of the variable from a Python integer.
  258. //-----------------------------------------------------------------------------
  259. static int NumberVar_SetValueFromInteger(
  260. udt_NumberVar *var, // variable to set value for
  261. unsigned pos, // array position to set
  262. PyObject *value) // value to set
  263. {
  264. long integerValue;
  265. sword status;
  266. integerValue = PyInt_AS_LONG(value);
  267. status = OCINumberFromInt(var->environment->errorHandle, &integerValue,
  268. sizeof(long), OCI_NUMBER_SIGNED, &var->data[pos]);
  269. return Environment_CheckForError(var->environment, status,
  270. "NumberVar_SetValueFromInteger()");
  271. }
  272. #endif
  273. //-----------------------------------------------------------------------------
  274. // NumberVar_SetValueFromFloat()
  275. // Set the value of the variable from a Python float.
  276. //-----------------------------------------------------------------------------
  277. static int NumberVar_SetValueFromFloat(
  278. udt_NumberVar *var, // variable to set value for
  279. unsigned pos, // array position to set
  280. PyObject *value) // value to set
  281. {
  282. double doubleValue;
  283. sword status;
  284. doubleValue = PyFloat_AS_DOUBLE(value);
  285. status = OCINumberFromReal(var->environment->errorHandle, &doubleValue,
  286. sizeof(double), &var->data[pos]);
  287. return Environment_CheckForError(var->environment, status,
  288. "NumberVar_SetValueFromFloat()");
  289. }
  290. //-----------------------------------------------------------------------------
  291. // NumberVar_SetValueFromLong()
  292. // Set the value of the variable from a Python long.
  293. //-----------------------------------------------------------------------------
  294. static int NumberVar_SetValueFromLong(
  295. udt_NumberVar *var, // variable to set value for
  296. unsigned pos, // array position to set
  297. PyObject *value) // value to set
  298. {
  299. udt_Buffer textBuffer;
  300. PyObject *textValue;
  301. sword status;
  302. textValue = PyObject_Str(value);
  303. if (!textValue)
  304. return -1;
  305. if (cxBuffer_FromObject(&textBuffer, textValue,
  306. var->environment->encoding) < 0)
  307. return -1;
  308. status = OCINumberFromText(var->environment->errorHandle,
  309. (text*) textBuffer.ptr, textBuffer.size,
  310. (text*) var->environment->numberFromStringFormatBuffer.ptr,
  311. var->environment->numberFromStringFormatBuffer.size, NULL, 0,
  312. &var->data[pos]);
  313. cxBuffer_Clear(&textBuffer);
  314. Py_DECREF(textValue);
  315. return Environment_CheckForError(var->environment, status,
  316. "NumberVar_SetValueFromLong()");
  317. }
  318. //-----------------------------------------------------------------------------
  319. // NumberVar_GetFormatAndTextFromDecimal()
  320. // Return the number format and text to use for the Decimal object.
  321. //-----------------------------------------------------------------------------
  322. static int NumberVar_GetFormatAndTextFromDecimal(
  323. PyObject *tupleValue, // decimal as_tuple() value
  324. PyObject **textObj, // text string for conversion
  325. PyObject **formatObj) // format for conversion
  326. {
  327. long numDigits, scale, i, sign, length, digit;
  328. char *textValue, *format, *textPtr, *formatPtr;
  329. PyObject *digits;
  330. // acquire basic information from the value tuple
  331. sign = PyInt_AsLong(PyTuple_GET_ITEM(tupleValue, 0));
  332. if (PyErr_Occurred())
  333. return -1;
  334. digits = PyTuple_GET_ITEM(tupleValue, 1);
  335. scale = PyInt_AsLong(PyTuple_GET_ITEM(tupleValue, 2));
  336. if (PyErr_Occurred())
  337. return -1;
  338. numDigits = PyTuple_GET_SIZE(digits);
  339. // allocate memory for the string and format to use in conversion
  340. length = numDigits + abs(scale) + 3;
  341. textValue = textPtr = PyMem_Malloc(length);
  342. if (!textValue) {
  343. PyErr_NoMemory();
  344. return -1;
  345. }
  346. format = formatPtr = PyMem_Malloc(length);
  347. if (!format) {
  348. PyMem_Free(textValue);
  349. PyErr_NoMemory();
  350. return -1;
  351. }
  352. // populate the string and format
  353. if (sign)
  354. *textPtr++ = '-';
  355. for (i = 0; i < numDigits + scale; i++) {
  356. *formatPtr++ = '9';
  357. if (i < numDigits) {
  358. digit = PyInt_AsLong(PyTuple_GetItem(digits, i));
  359. if (PyErr_Occurred()) {
  360. PyMem_Free(textValue);
  361. return -1;
  362. }
  363. }
  364. else digit = 0;
  365. *textPtr++ = '0' + (char) digit;
  366. }
  367. if (scale < 0) {
  368. *formatPtr++ = 'D';
  369. *textPtr++ = '.';
  370. for (i = scale; i < 0; i++) {
  371. *formatPtr++ = '9';
  372. if (numDigits + i < 0)
  373. digit = 0;
  374. else {
  375. digit = PyInt_AsLong(PyTuple_GetItem(digits, numDigits + i));
  376. if (PyErr_Occurred()) {
  377. PyMem_Free(textValue);
  378. return -1;
  379. }
  380. }
  381. *textPtr++ = '0' + (char) digit;
  382. }
  383. }
  384. *formatPtr = '\0';
  385. *textPtr = '\0';
  386. *textObj = cxString_FromAscii(textValue);
  387. PyMem_Free(textValue);
  388. if (!*textObj) {
  389. PyMem_Free(format);
  390. return -1;
  391. }
  392. *formatObj = cxString_FromAscii(format);
  393. PyMem_Free(format);
  394. if (!*formatObj) {
  395. Py_DECREF(*textObj);
  396. return -1;
  397. }
  398. return 0;
  399. }
  400. //-----------------------------------------------------------------------------
  401. // NumberVar_SetValueFromDecimal()
  402. // Set the value of the variable from a Python decimal.Decimal object.
  403. //-----------------------------------------------------------------------------
  404. static int NumberVar_SetValueFromDecimal(
  405. udt_NumberVar *var, // variable to set value for
  406. unsigned pos, // array position to set
  407. PyObject *value) // value to set
  408. {
  409. PyObject *textValue, *format, *tupleValue;
  410. udt_Buffer textBuffer, formatBuffer;
  411. sword status;
  412. tupleValue = PyObject_CallMethod(value, "as_tuple", NULL);
  413. if (!tupleValue)
  414. return -1;
  415. if (NumberVar_GetFormatAndTextFromDecimal(tupleValue, &textValue,
  416. &format) < 0) {
  417. Py_DECREF(tupleValue);
  418. return -1;
  419. }
  420. Py_DECREF(tupleValue);
  421. if (cxBuffer_FromObject(&textBuffer, textValue,
  422. var->environment->encoding) < 0)
  423. return -1;
  424. if (cxBuffer_FromObject(&formatBuffer, format,
  425. var->environment->encoding) < 0) {
  426. cxBuffer_Clear(&textBuffer);
  427. return -1;
  428. }
  429. status = OCINumberFromText(var->environment->errorHandle,
  430. (text*) textBuffer.ptr, textBuffer.size, (text*) formatBuffer.ptr,
  431. formatBuffer.size,
  432. var->environment->nlsNumericCharactersBuffer.ptr,
  433. var->environment->nlsNumericCharactersBuffer.size,
  434. &var->data[pos]);
  435. cxBuffer_Clear(&textBuffer);
  436. cxBuffer_Clear(&formatBuffer);
  437. Py_DECREF(textValue);
  438. Py_DECREF(format);
  439. return Environment_CheckForError(var->environment, status,
  440. "NumberVar_SetValueFromDecimal()");
  441. }
  442. //-----------------------------------------------------------------------------
  443. // NumberVar_SetValue()
  444. // Set the value of the variable.
  445. //-----------------------------------------------------------------------------
  446. static int NumberVar_SetValue(
  447. udt_NumberVar *var, // variable to set value for
  448. unsigned pos, // array position to set
  449. PyObject *value) // value to set
  450. {
  451. #if PY_MAJOR_VERSION < 3
  452. if (PyInt_Check(value))
  453. return NumberVar_SetValueFromInteger(var, pos, value);
  454. #endif
  455. if (PyLong_Check(value))
  456. return NumberVar_SetValueFromLong(var, pos, value);
  457. if (PyBool_Check(value))
  458. return NumberVar_SetValueFromBoolean(var, pos, value);
  459. if (PyFloat_Check(value))
  460. return NumberVar_SetValueFromFloat(var, pos, value);
  461. if (Py_TYPE(value) == g_DecimalType)
  462. return NumberVar_SetValueFromDecimal(var, pos, value);
  463. PyErr_SetString(PyExc_TypeError, "expecting numeric data");
  464. return -1;
  465. }
  466. //-----------------------------------------------------------------------------
  467. // NumberVar_GetValue()
  468. // Returns the value stored at the given array position.
  469. //-----------------------------------------------------------------------------
  470. static PyObject *NumberVar_GetValue(
  471. udt_NumberVar *var, // variable to determine value for
  472. unsigned pos) // array position
  473. {
  474. PyObject *result, *stringObj;
  475. char stringValue[200];
  476. long integerValue;
  477. ub4 stringLength;
  478. sword status;
  479. #if PY_MAJOR_VERSION < 3
  480. if (var->type == &vt_Integer || var->type == &vt_Boolean) {
  481. #else
  482. if (var->type == &vt_Boolean) {
  483. #endif
  484. status = OCINumberToInt(var->environment->errorHandle, &var->data[pos],
  485. sizeof(long), OCI_NUMBER_SIGNED, (dvoid*) &integerValue);
  486. if (Environment_CheckForError(var->environment, status,
  487. "NumberVar_GetValue(): as integer") < 0)
  488. return NULL;
  489. #if PY_MAJOR_VERSION < 3
  490. if (var->type == &vt_Integer)
  491. return PyInt_FromLong(integerValue);
  492. #endif
  493. return PyBool_FromLong(integerValue);
  494. }
  495. if (var->type == &vt_NumberAsString || var->type == &vt_LongInteger) {
  496. stringLength = sizeof(stringValue);
  497. status = OCINumberToText(var->environment->errorHandle,
  498. &var->data[pos],
  499. (text*) var->environment->numberToStringFormatBuffer.ptr,
  500. var->environment->numberToStringFormatBuffer.size, NULL, 0,
  501. &stringLength, (unsigned char*) stringValue);
  502. if (Environment_CheckForError(var->environment, status,
  503. "NumberVar_GetValue(): as string") < 0)
  504. return NULL;
  505. stringObj = cxString_FromEncodedString(stringValue, stringLength,
  506. var->environment->encoding);
  507. if (!stringObj)
  508. return NULL;
  509. if (var->type == &vt_NumberAsString)
  510. return stringObj;
  511. #if PY_MAJOR_VERSION >= 3
  512. result = PyNumber_Long(stringObj);
  513. #else
  514. result = PyNumber_Int(stringObj);
  515. #endif
  516. Py_DECREF(stringObj);
  517. if (result || !PyErr_ExceptionMatches(PyExc_ValueError))
  518. return result;
  519. PyErr_Clear();
  520. }
  521. return OracleNumberToPythonFloat(var->environment, &var->data[pos]);
  522. }
  523. #ifdef SQLT_BFLOAT
  524. //-----------------------------------------------------------------------------
  525. // NativeFloatVar_GetValue()
  526. // Returns the value stored at the given array position as a float.
  527. //-----------------------------------------------------------------------------
  528. static PyObject *NativeFloatVar_GetValue(
  529. udt_NativeFloatVar *var, // variable to determine value for
  530. unsigned pos) // array position
  531. {
  532. return PyFloat_FromDouble(var->data[pos]);
  533. }
  534. //-----------------------------------------------------------------------------
  535. // NativeFloatVar_SetValue()
  536. // Set the value of the variable which should be a native double.
  537. //-----------------------------------------------------------------------------
  538. static int NativeFloatVar_SetValue(
  539. udt_NativeFloatVar *var, // variable to set value for
  540. unsigned pos, // array position to set
  541. PyObject *value) // value to set
  542. {
  543. if (!PyFloat_Check(value)) {
  544. PyErr_SetString(PyExc_TypeError, "expecting float");
  545. return -1;
  546. }
  547. var->data[pos] = PyFloat_AS_DOUBLE(value);
  548. return 0;
  549. }
  550. #endif