Environment.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327
  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. PyObject *cloneEnv;
  17. udt_Buffer numberToStringFormatBuffer;
  18. udt_Buffer numberFromStringFormatBuffer;
  19. udt_Buffer nlsNumericCharactersBuffer;
  20. } udt_Environment;
  21. //-----------------------------------------------------------------------------
  22. // forward declarations
  23. //-----------------------------------------------------------------------------
  24. static void Environment_Free(udt_Environment*);
  25. static int Environment_CheckForError(udt_Environment*, sword, const char*);
  26. //-----------------------------------------------------------------------------
  27. // declaration of Python type
  28. //-----------------------------------------------------------------------------
  29. static PyTypeObject g_EnvironmentType = {
  30. PyVarObject_HEAD_INIT(NULL, 0)
  31. "OracleEnvironment", // tp_name
  32. sizeof(udt_Environment), // tp_basicsize
  33. 0, // tp_itemsize
  34. (destructor) Environment_Free, // tp_dealloc
  35. 0, // tp_print
  36. 0, // tp_getattr
  37. 0, // tp_setattr
  38. 0, // tp_compare
  39. 0, // tp_repr
  40. 0, // tp_as_number
  41. 0, // tp_as_sequence
  42. 0, // tp_as_mapping
  43. 0, // tp_hash
  44. 0, // tp_call
  45. 0, // tp_str
  46. 0, // tp_getattro
  47. 0, // tp_setattro
  48. 0, // tp_as_buffer
  49. Py_TPFLAGS_DEFAULT, // tp_flags
  50. 0 // tp_doc
  51. };
  52. #include "Error.c"
  53. //-----------------------------------------------------------------------------
  54. // Environment_New()
  55. // Create a new environment object.
  56. //-----------------------------------------------------------------------------
  57. static udt_Environment *Environment_New(
  58. OCIEnv *handle) // handle to use
  59. {
  60. udt_Environment *env;
  61. udt_Error *errorObj;
  62. sword status;
  63. // create a new object for the Oracle environment
  64. env = (udt_Environment*) g_EnvironmentType.tp_alloc(&g_EnvironmentType, 0);
  65. if (!env)
  66. return NULL;
  67. env->handle = NULL;
  68. env->errorHandle = NULL;
  69. env->fixedWidth = 1;
  70. env->maxBytesPerCharacter = 1;
  71. env->cloneEnv = NULL;
  72. cxBuffer_Init(&env->numberToStringFormatBuffer);
  73. cxBuffer_Init(&env->numberFromStringFormatBuffer);
  74. cxBuffer_Init(&env->nlsNumericCharactersBuffer);
  75. // create the error handle
  76. status = OCIHandleAlloc(handle, (dvoid**) &env->errorHandle,
  77. OCI_HTYPE_ERROR, 0, 0);
  78. if (status != OCI_SUCCESS) {
  79. errorObj = Error_New(env, "Environment_New(): create error handle",
  80. OCI_HTYPE_ENV, handle);
  81. if (!errorObj) {
  82. Py_DECREF(env);
  83. return NULL;
  84. }
  85. PyErr_SetObject(g_DatabaseErrorException, (PyObject*) errorObj);
  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. if (cxBuffer_FromObject(buf, obj, encoding)<0)
  152. return -1;
  153. Py_CLEAR(obj);
  154. return 0;
  155. }
  156. //-----------------------------------------------------------------------------
  157. // Environment_NewFromScratch()
  158. // Create a new environment object from scratch.
  159. //-----------------------------------------------------------------------------
  160. static udt_Environment *Environment_NewFromScratch(
  161. int threaded, // use threaded mode?
  162. int events, // use events mode?
  163. char *encoding, // override value for encoding
  164. char *nencoding) // override value for nencoding
  165. {
  166. udt_Environment *env;
  167. OCIEnv *handle;
  168. sword status;
  169. ub4 mode;
  170. // turn threading mode on, if desired
  171. mode = OCI_OBJECT;
  172. if (threaded)
  173. mode |= OCI_THREADED;
  174. if (events)
  175. mode |= OCI_EVENTS;
  176. // create the new environment handle
  177. status = OCIEnvNlsCreate(&handle, mode, NULL, NULL, NULL, NULL, 0, NULL, 0,
  178. 0);
  179. if (!handle ||
  180. (status != OCI_SUCCESS && status != OCI_SUCCESS_WITH_INFO)) {
  181. PyErr_SetString(g_InterfaceErrorException,
  182. "Unable to acquire Oracle environment handle");
  183. return NULL;
  184. }
  185. // create the environment object
  186. env = Environment_New(handle);
  187. if (!env) {
  188. OCIHandleFree(handle, OCI_HTYPE_ENV);
  189. return NULL;
  190. }
  191. // acquire max bytes per character
  192. status = OCINlsNumericInfoGet(env->handle, env->errorHandle,
  193. &env->maxBytesPerCharacter, OCI_NLS_CHARSET_MAXBYTESZ);
  194. if (Environment_CheckForError(env, status,
  195. "Environment_New(): get max bytes per character") < 0) {
  196. Py_DECREF(env);
  197. return NULL;
  198. }
  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->fixedWidth = cloneEnv->fixedWidth;
  241. Py_INCREF(cloneEnv);
  242. env->cloneEnv = (PyObject*) cloneEnv;
  243. env->encoding = cloneEnv->encoding;
  244. env->nencoding = cloneEnv->nencoding;
  245. cxBuffer_Copy(&env->numberToStringFormatBuffer,
  246. &cloneEnv->numberToStringFormatBuffer);
  247. cxBuffer_Copy(&env->numberFromStringFormatBuffer,
  248. &cloneEnv->numberFromStringFormatBuffer);
  249. cxBuffer_Copy(&env->nlsNumericCharactersBuffer,
  250. &cloneEnv->nlsNumericCharactersBuffer);
  251. return env;
  252. }
  253. //-----------------------------------------------------------------------------
  254. // Environment_Free()
  255. // Deallocate the environment. Note that destroying the environment handle
  256. // will automatically destroy any child handles that were created.
  257. //-----------------------------------------------------------------------------
  258. static void Environment_Free(
  259. udt_Environment *self) // environment object
  260. {
  261. if (self->errorHandle)
  262. OCIHandleFree(self->errorHandle, OCI_HTYPE_ERROR);
  263. if (self->handle && !self->cloneEnv)
  264. OCIHandleFree(self->handle, OCI_HTYPE_ENV);
  265. if (!self->cloneEnv) {
  266. if (self->encoding)
  267. PyMem_Free(self->encoding);
  268. if (self->nencoding)
  269. PyMem_Free(self->nencoding);
  270. }
  271. cxBuffer_Clear(&self->numberToStringFormatBuffer);
  272. cxBuffer_Clear(&self->numberFromStringFormatBuffer);
  273. cxBuffer_Clear(&self->nlsNumericCharactersBuffer);
  274. Py_CLEAR(self->cloneEnv);
  275. Py_TYPE(self)->tp_free((PyObject*) self);
  276. }
  277. //-----------------------------------------------------------------------------
  278. // Environment_CheckForError()
  279. // Check for an error in the last call and if an error has occurred, raise a
  280. // Python exception.
  281. //-----------------------------------------------------------------------------
  282. static int Environment_CheckForError(
  283. udt_Environment *environment, // environment to raise error in
  284. sword status, // status of last call
  285. const char *context) // context
  286. {
  287. return Error_Check(environment, status, context, environment->errorHandle);
  288. }