Environment.c 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404
  1. //-----------------------------------------------------------------------------
  2. // Environment.c
  3. // Environment handling.
  4. //-----------------------------------------------------------------------------
  5. //-----------------------------------------------------------------------------
  6. // structure for the Python type
  7. //-----------------------------------------------------------------------------
  8. typedef struct {
  9. PyObject_HEAD
  10. OCIEnv *handle;
  11. OCIError *errorHandle;
  12. int maxBytesPerCharacter;
  13. int fixedWidth;
  14. char *encoding;
  15. char *nencoding;
  16. ub4 maxStringBytes;
  17. PyObject *cloneEnv;
  18. udt_Buffer numberToStringFormatBuffer;
  19. udt_Buffer numberFromStringFormatBuffer;
  20. udt_Buffer nlsNumericCharactersBuffer;
  21. } udt_Environment;
  22. //-----------------------------------------------------------------------------
  23. // maximum number of characters/bytes applicable to strings/binaries
  24. //-----------------------------------------------------------------------------
  25. #define MAX_STRING_CHARS 4000
  26. #define MAX_BINARY_BYTES 4000
  27. //-----------------------------------------------------------------------------
  28. // forward declarations
  29. //-----------------------------------------------------------------------------
  30. static void Environment_Free(udt_Environment*);
  31. static int Environment_CheckForError(udt_Environment*, sword, const char*);
  32. //-----------------------------------------------------------------------------
  33. // declaration of Python type
  34. //-----------------------------------------------------------------------------
  35. static PyTypeObject g_EnvironmentType = {
  36. PyVarObject_HEAD_INIT(NULL, 0)
  37. "OracleEnvironment", // tp_name
  38. sizeof(udt_Environment), // tp_basicsize
  39. 0, // tp_itemsize
  40. (destructor) Environment_Free, // tp_dealloc
  41. 0, // tp_print
  42. 0, // tp_getattr
  43. 0, // tp_setattr
  44. 0, // tp_compare
  45. 0, // tp_repr
  46. 0, // tp_as_number
  47. 0, // tp_as_sequence
  48. 0, // tp_as_mapping
  49. 0, // tp_hash
  50. 0, // tp_call
  51. 0, // tp_str
  52. 0, // tp_getattro
  53. 0, // tp_setattro
  54. 0, // tp_as_buffer
  55. Py_TPFLAGS_DEFAULT, // tp_flags
  56. 0 // tp_doc
  57. };
  58. #include "Error.c"
  59. //-----------------------------------------------------------------------------
  60. // Environment_New()
  61. // Create a new environment object.
  62. //-----------------------------------------------------------------------------
  63. static udt_Environment *Environment_New(
  64. OCIEnv *handle) // handle to use
  65. {
  66. udt_Environment *env;
  67. sword status;
  68. // create a new object for the Oracle environment
  69. env = (udt_Environment*) g_EnvironmentType.tp_alloc(&g_EnvironmentType, 0);
  70. if (!env)
  71. return NULL;
  72. env->handle = NULL;
  73. env->errorHandle = NULL;
  74. env->fixedWidth = 1;
  75. env->maxBytesPerCharacter = 1;
  76. env->maxStringBytes = MAX_STRING_CHARS;
  77. env->cloneEnv = NULL;
  78. cxBuffer_Init(&env->numberToStringFormatBuffer);
  79. cxBuffer_Init(&env->numberFromStringFormatBuffer);
  80. cxBuffer_Init(&env->nlsNumericCharactersBuffer);
  81. // create the error handle
  82. status = OCIHandleAlloc(handle, (dvoid**) &env->errorHandle,
  83. OCI_HTYPE_ERROR, 0, 0);
  84. if (Environment_CheckForError(env, status,
  85. "Environment_New(): create error handle") < 0) {
  86. Py_DECREF(env);
  87. return NULL;
  88. }
  89. env->handle = handle;
  90. return env;
  91. }
  92. //-----------------------------------------------------------------------------
  93. // Environment_GetCharacterSetName()
  94. // Retrieve and store the IANA character set name for the attribute.
  95. //-----------------------------------------------------------------------------
  96. static int Environment_GetCharacterSetName(
  97. udt_Environment *self, // environment object
  98. ub2 attribute, // attribute to fetch
  99. const char *overrideValue, // override value, if specified
  100. char **result) // place to store result
  101. {
  102. char charsetName[OCI_NLS_MAXBUFSZ], ianaCharsetName[OCI_NLS_MAXBUFSZ];
  103. ub2 charsetId;
  104. sword status;
  105. // if override value specified, use it
  106. if (overrideValue) {
  107. *result = PyMem_Malloc(strlen(overrideValue) + 1);
  108. if (!*result)
  109. return -1;
  110. strcpy(*result, overrideValue);
  111. return 0;
  112. }
  113. // get character set id
  114. status = OCIAttrGet(self->handle, OCI_HTYPE_ENV, &charsetId, NULL,
  115. attribute, self->errorHandle);
  116. if (Environment_CheckForError(self, status,
  117. "Environment_GetCharacterSetName(): get charset id") < 0)
  118. return -1;
  119. // get character set name
  120. status = OCINlsCharSetIdToName(self->handle, (text*) charsetName,
  121. OCI_NLS_MAXBUFSZ, charsetId);
  122. if (Environment_CheckForError(self, status,
  123. "Environment_GetCharacterSetName(): get Oracle charset name") < 0)
  124. return -1;
  125. // get IANA character set name
  126. status = OCINlsNameMap(self->handle, (oratext*) ianaCharsetName,
  127. OCI_NLS_MAXBUFSZ, (oratext*) charsetName, OCI_NLS_CS_ORA_TO_IANA);
  128. if (Environment_CheckForError(self, status,
  129. "Environment_GetCharacterSetName(): translate NLS charset") < 0)
  130. return -1;
  131. // store results
  132. *result = PyMem_Malloc(strlen(ianaCharsetName) + 1);
  133. if (!*result)
  134. return -1;
  135. strcpy(*result, ianaCharsetName);
  136. return 0;
  137. }
  138. //-----------------------------------------------------------------------------
  139. // Environment_SetBuffer()
  140. // Set the buffer in the environment from the specified string.
  141. //-----------------------------------------------------------------------------
  142. static int Environment_SetBuffer(
  143. udt_Buffer *buf, // buffer to set
  144. const char *value, // ASCII value to use
  145. const char *encoding) // encoding to use
  146. {
  147. PyObject *obj;
  148. obj = cxString_FromAscii(value);
  149. if (!obj)
  150. return -1;
  151. return cxBuffer_FromObject(buf, obj, encoding);
  152. }
  153. //-----------------------------------------------------------------------------
  154. // Environment_NewFromScratch()
  155. // Create a new environment object from scratch.
  156. //-----------------------------------------------------------------------------
  157. static udt_Environment *Environment_NewFromScratch(
  158. int threaded, // use threaded mode?
  159. int events, // use events mode?
  160. char *encoding, // override value for encoding
  161. char *nencoding) // override value for nencoding
  162. {
  163. udt_Environment *env;
  164. OCIEnv *handle;
  165. sword status;
  166. ub4 mode;
  167. // turn threading mode on, if desired
  168. mode = OCI_OBJECT;
  169. if (threaded)
  170. mode |= OCI_THREADED;
  171. #ifdef OCI_EVENTS
  172. if (events)
  173. mode |= OCI_EVENTS;
  174. #endif
  175. // create the new environment handle
  176. status = OCIEnvNlsCreate(&handle, mode, NULL, NULL, NULL, NULL, 0, NULL, 0,
  177. 0);
  178. if (!handle ||
  179. (status != OCI_SUCCESS && status != OCI_SUCCESS_WITH_INFO)) {
  180. PyErr_SetString(g_InterfaceErrorException,
  181. "Unable to acquire Oracle environment handle");
  182. return NULL;
  183. }
  184. // create the environment object
  185. env = Environment_New(handle);
  186. if (!env) {
  187. OCIHandleFree(handle, OCI_HTYPE_ENV);
  188. return NULL;
  189. }
  190. // acquire max bytes per character
  191. status = OCINlsNumericInfoGet(env->handle, env->errorHandle,
  192. &env->maxBytesPerCharacter, OCI_NLS_CHARSET_MAXBYTESZ);
  193. if (Environment_CheckForError(env, status,
  194. "Environment_New(): get max bytes per character") < 0) {
  195. Py_DECREF(env);
  196. return NULL;
  197. }
  198. env->maxStringBytes = MAX_STRING_CHARS * env->maxBytesPerCharacter;
  199. // acquire whether character set is fixed width
  200. status = OCINlsNumericInfoGet(env->handle, env->errorHandle,
  201. &env->fixedWidth, OCI_NLS_CHARSET_FIXEDWIDTH);
  202. if (Environment_CheckForError(env, status,
  203. "Environment_New(): determine if charset fixed width") < 0) {
  204. Py_DECREF(env);
  205. return NULL;
  206. }
  207. // determine encodings to use for Unicode values
  208. if (Environment_GetCharacterSetName(env, OCI_ATTR_ENV_CHARSET_ID,
  209. encoding, &env->encoding) < 0)
  210. return NULL;
  211. if (Environment_GetCharacterSetName(env, OCI_ATTR_ENV_NCHARSET_ID,
  212. nencoding, &env->nencoding) < 0)
  213. return NULL;
  214. // fill buffers for number formats
  215. if (Environment_SetBuffer(&env->numberToStringFormatBuffer, "TM9",
  216. env->encoding) < 0)
  217. return NULL;
  218. if (Environment_SetBuffer(&env->numberFromStringFormatBuffer,
  219. "999999999999999999999999999999999999999999999999999999999999999",
  220. env->encoding) < 0)
  221. return NULL;
  222. if (Environment_SetBuffer(&env->nlsNumericCharactersBuffer,
  223. "NLS_NUMERIC_CHARACTERS='.,'", env->encoding) < 0)
  224. return NULL;
  225. return env;
  226. }
  227. //-----------------------------------------------------------------------------
  228. // Environment_Clone()
  229. // Clone an existing environment which is used when acquiring a connection
  230. // from a session pool, for example.
  231. //-----------------------------------------------------------------------------
  232. static udt_Environment *Environment_Clone(
  233. udt_Environment *cloneEnv) // environment to clone
  234. {
  235. udt_Environment *env;
  236. env = Environment_New(cloneEnv->handle);
  237. if (!env)
  238. return NULL;
  239. env->maxBytesPerCharacter = cloneEnv->maxBytesPerCharacter;
  240. env->maxStringBytes = cloneEnv->maxStringBytes;
  241. env->fixedWidth = cloneEnv->fixedWidth;
  242. Py_INCREF(cloneEnv);
  243. env->cloneEnv = (PyObject*) cloneEnv;
  244. env->encoding = cloneEnv->encoding;
  245. env->nencoding = cloneEnv->nencoding;
  246. cxBuffer_Copy(&env->numberToStringFormatBuffer,
  247. &cloneEnv->numberToStringFormatBuffer);
  248. cxBuffer_Copy(&env->numberFromStringFormatBuffer,
  249. &cloneEnv->numberFromStringFormatBuffer);
  250. cxBuffer_Copy(&env->nlsNumericCharactersBuffer,
  251. &cloneEnv->nlsNumericCharactersBuffer);
  252. return env;
  253. }
  254. //-----------------------------------------------------------------------------
  255. // Environment_Free()
  256. // Deallocate the environment. Note that destroying the environment handle
  257. // will automatically destroy any child handles that were created.
  258. //-----------------------------------------------------------------------------
  259. static void Environment_Free(
  260. udt_Environment *self) // environment object
  261. {
  262. if (self->errorHandle)
  263. OCIHandleFree(self->errorHandle, OCI_HTYPE_ERROR);
  264. if (self->handle && !self->cloneEnv)
  265. OCIHandleFree(self->handle, OCI_HTYPE_ENV);
  266. if (!self->cloneEnv) {
  267. if (self->encoding)
  268. PyMem_Free(self->encoding);
  269. if (self->nencoding)
  270. PyMem_Free(self->nencoding);
  271. }
  272. cxBuffer_Clear(&self->numberToStringFormatBuffer);
  273. cxBuffer_Clear(&self->numberFromStringFormatBuffer);
  274. cxBuffer_Clear(&self->nlsNumericCharactersBuffer);
  275. Py_CLEAR(self->cloneEnv);
  276. Py_TYPE(self)->tp_free((PyObject*) self);
  277. }
  278. //-----------------------------------------------------------------------------
  279. // Environment_RaiseError()
  280. // Reads the error that was caused by the last Oracle statement and raise an
  281. // exception for Python. At this point it is assumed that the Oracle
  282. // environment is fully initialized.
  283. //-----------------------------------------------------------------------------
  284. static int Environment_RaiseError(
  285. udt_Environment *environment, // environment to raise error for
  286. const char *context) // context in which error occurred
  287. {
  288. PyObject *exceptionType;
  289. udt_Error *error;
  290. error = Error_New(environment, context, 1);
  291. if (error) {
  292. switch (error->code) {
  293. case 1:
  294. case 1400:
  295. case 2290:
  296. case 2291:
  297. case 2292:
  298. exceptionType = g_IntegrityErrorException;
  299. break;
  300. case 22:
  301. case 378:
  302. case 602:
  303. case 603:
  304. case 604:
  305. case 609:
  306. case 1012:
  307. case 1013:
  308. case 1033:
  309. case 1034:
  310. case 1041:
  311. case 1043:
  312. case 1089:
  313. case 1090:
  314. case 1092:
  315. case 3113:
  316. case 3114:
  317. case 3122:
  318. case 3135:
  319. case 12153:
  320. case 12203:
  321. case 12500:
  322. case 12571:
  323. case 27146:
  324. case 28511:
  325. exceptionType = g_OperationalErrorException;
  326. break;
  327. default:
  328. exceptionType = g_DatabaseErrorException;
  329. break;
  330. }
  331. PyErr_SetObject(exceptionType, (PyObject*) error);
  332. Py_DECREF(error);
  333. }
  334. return -1;
  335. }
  336. //-----------------------------------------------------------------------------
  337. // Environment_CheckForError()
  338. // Check for an error in the last call and if an error has occurred, raise a
  339. // Python exception.
  340. //-----------------------------------------------------------------------------
  341. static int Environment_CheckForError(
  342. udt_Environment *environment, // environment to raise error in
  343. sword status, // status of last call
  344. const char *context) // context
  345. {
  346. udt_Error *error;
  347. if (status != OCI_SUCCESS && status != OCI_SUCCESS_WITH_INFO) {
  348. if (status != OCI_INVALID_HANDLE)
  349. return Environment_RaiseError(environment, context);
  350. error = Error_New(environment, context, 0);
  351. if (!error)
  352. return -1;
  353. error->code = 0;
  354. error->message = cxString_FromAscii("Invalid handle!");
  355. if (!error->message)
  356. Py_DECREF(error);
  357. else PyErr_SetObject(g_DatabaseErrorException, (PyObject*) error);
  358. return -1;
  359. }
  360. return 0;
  361. }