ExternalObjectVar.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305
  1. //-----------------------------------------------------------------------------
  2. // ExternalObjectVar.c
  3. // Defines the routines for handling object variables external to this
  4. // module.
  5. //-----------------------------------------------------------------------------
  6. //-----------------------------------------------------------------------------
  7. // external Object type
  8. //-----------------------------------------------------------------------------
  9. typedef struct {
  10. PyObject_HEAD
  11. PyObject *referencedObject;
  12. udt_ObjectType *objectType;
  13. dvoid *instance;
  14. dvoid *indicator;
  15. int isIndependent;
  16. } udt_ExternalObjectVar;
  17. //-----------------------------------------------------------------------------
  18. // Declaration of external object variable functions.
  19. //-----------------------------------------------------------------------------
  20. static void ExternalObjectVar_Free(udt_ExternalObjectVar*);
  21. static PyObject *ExternalObjectVar_GetAttr(udt_ExternalObjectVar*, PyObject*);
  22. static PyObject *ExternalObjectVar_ConvertToPython(udt_Environment*,
  23. OCITypeCode, dvoid*, dvoid*, PyObject*, udt_ObjectType*);
  24. //-----------------------------------------------------------------------------
  25. // Declaration of external object variable members.
  26. //-----------------------------------------------------------------------------
  27. static PyMemberDef g_ExternalObjectVarMembers[] = {
  28. { "type", T_OBJECT, offsetof(udt_ExternalObjectVar, objectType),
  29. READONLY },
  30. { NULL }
  31. };
  32. //-----------------------------------------------------------------------------
  33. // Python type declaration
  34. //-----------------------------------------------------------------------------
  35. static PyTypeObject g_ExternalObjectVarType = {
  36. PyVarObject_HEAD_INIT(NULL, 0)
  37. "cx_Oracle.OBJECT", // tp_name
  38. sizeof(udt_ExternalObjectVar), // tp_basicsize
  39. 0, // tp_itemsize
  40. (destructor) ExternalObjectVar_Free,
  41. // tp_dealloc
  42. 0, // tp_print
  43. 0, // tp_getattr
  44. 0, // tp_setattr
  45. 0, // tp_compare
  46. 0, // tp_repr
  47. 0, // tp_as_number
  48. 0, // tp_as_sequence
  49. 0, // tp_as_mapping
  50. 0, // tp_hash
  51. 0, // tp_call
  52. 0, // tp_str
  53. (getattrofunc) ExternalObjectVar_GetAttr,
  54. // tp_getattro
  55. 0, // tp_setattro
  56. 0, // tp_as_buffer
  57. Py_TPFLAGS_DEFAULT, // tp_flags
  58. 0, // tp_doc
  59. 0, // tp_traverse
  60. 0, // tp_clear
  61. 0, // tp_richcompare
  62. 0, // tp_weaklistoffset
  63. 0, // tp_iter
  64. 0, // tp_iternext
  65. 0, // tp_methods
  66. g_ExternalObjectVarMembers // tp_members
  67. };
  68. //-----------------------------------------------------------------------------
  69. // ExternalObjectVar_New()
  70. // Create a new external LOB variable.
  71. //-----------------------------------------------------------------------------
  72. PyObject *ExternalObjectVar_New(
  73. PyObject *referencedObject, // referenced object
  74. udt_ObjectType *objectType, // type of object
  75. dvoid *instance, // object instance data
  76. dvoid *indicator, // indicator structure
  77. int isIndependent) // is object independent?
  78. {
  79. udt_ExternalObjectVar *self;
  80. self = (udt_ExternalObjectVar*)
  81. g_ExternalObjectVarType.tp_alloc(&g_ExternalObjectVarType, 0);
  82. if (!self)
  83. return NULL;
  84. Py_INCREF(referencedObject);
  85. self->referencedObject = referencedObject;
  86. Py_INCREF(objectType);
  87. self->objectType = objectType;
  88. self->instance = instance;
  89. self->indicator = indicator;
  90. self->isIndependent = isIndependent;
  91. return (PyObject*) self;
  92. }
  93. //-----------------------------------------------------------------------------
  94. // ExternalObjectVar_Free()
  95. // Free an external LOB variable.
  96. //-----------------------------------------------------------------------------
  97. static void ExternalObjectVar_Free(
  98. udt_ExternalObjectVar *self) // variable to free
  99. {
  100. if (self->isIndependent)
  101. OCIObjectFree(self->objectType->environment->handle,
  102. self->objectType->environment->errorHandle,
  103. self->instance, OCI_OBJECTFREE_FORCE);
  104. Py_CLEAR(self->objectType);
  105. Py_CLEAR(self->referencedObject);
  106. Py_TYPE(self)->tp_free((PyObject*) self);
  107. }
  108. //-----------------------------------------------------------------------------
  109. // ExternalObjectVar_ConvertCollectionElements()
  110. // Convert the collection elements to Python values.
  111. //-----------------------------------------------------------------------------
  112. static int ExternalObjectVar_ConvertCollectionElements(
  113. udt_Environment *environment, // environment to use
  114. OCIIter *iter, // iterator
  115. PyObject *list, // list result
  116. PyObject *referencedObject, // referenced object
  117. udt_ObjectType *objectType) // collection type information
  118. {
  119. dvoid *elementValue, *elementIndicator;
  120. PyObject *elementObject;
  121. boolean endOfCollection;
  122. sword status;
  123. while (list) {
  124. status = OCIIterNext(environment->handle, environment->errorHandle,
  125. iter, &elementValue, &elementIndicator, &endOfCollection);
  126. if (Environment_CheckForError(environment, status,
  127. "ExternalObjectVar_ConvertCollection(): get next") < 0)
  128. return -1;
  129. if (endOfCollection)
  130. break;
  131. elementObject = ExternalObjectVar_ConvertToPython(environment,
  132. objectType->elementTypeCode, elementValue, elementIndicator,
  133. referencedObject, (udt_ObjectType*) objectType->elementType);
  134. if (!elementObject)
  135. return -1;
  136. if (PyList_Append(list, elementObject) < 0) {
  137. Py_DECREF(elementObject);
  138. return -1;
  139. }
  140. Py_DECREF(elementObject);
  141. }
  142. return 0;
  143. }
  144. //-----------------------------------------------------------------------------
  145. // ExternalObjectVar_ConvertCollection()
  146. // Convert a collection to a Python list.
  147. //-----------------------------------------------------------------------------
  148. static PyObject *ExternalObjectVar_ConvertCollection(
  149. udt_Environment *environment, // environment to use
  150. OCIColl *collectionValue, // collection value
  151. PyObject *referencedObject, // referenced object
  152. udt_ObjectType *objectType) // collection type information
  153. {
  154. PyObject *list;
  155. OCIIter *iter;
  156. sword status;
  157. int result;
  158. // create the iterator
  159. status = OCIIterCreate(environment->handle, environment->errorHandle,
  160. collectionValue, &iter);
  161. if (Environment_CheckForError(environment, status,
  162. "ExternalObjectVar_ConvertCollection(): creating iterator") < 0)
  163. return NULL;
  164. // create the result list
  165. list = PyList_New(0);
  166. if (list) {
  167. result = ExternalObjectVar_ConvertCollectionElements(environment, iter,
  168. list, referencedObject, objectType);
  169. if (result < 0) {
  170. Py_DECREF(list);
  171. list = NULL;
  172. }
  173. }
  174. OCIIterDelete(environment->handle, environment->errorHandle, &iter);
  175. return list;
  176. }
  177. //-----------------------------------------------------------------------------
  178. // ExternalObjectVar_ConvertToPython()
  179. // Convert an Oracle value to a Python value.
  180. //-----------------------------------------------------------------------------
  181. static PyObject *ExternalObjectVar_ConvertToPython(
  182. udt_Environment *environment, // environment to use
  183. OCITypeCode typeCode, // type of Oracle data
  184. dvoid *value, // Oracle value
  185. dvoid *indicator, // null indicator
  186. PyObject *referencedObject, // referenced object (for sub objects)
  187. udt_ObjectType *subType) // sub type (for sub objects)
  188. {
  189. text *stringValue;
  190. ub4 stringSize;
  191. // null values returned as None
  192. if (* (OCIInd*) indicator == OCI_IND_NULL) {
  193. Py_INCREF(Py_None);
  194. return Py_None;
  195. }
  196. switch (typeCode) {
  197. case OCI_TYPECODE_CHAR:
  198. case OCI_TYPECODE_VARCHAR:
  199. case OCI_TYPECODE_VARCHAR2:
  200. stringValue = OCIStringPtr(environment->handle,
  201. * (OCIString**) value);
  202. stringSize = OCIStringSize(environment->handle,
  203. * (OCIString**) value);
  204. return cxString_FromEncodedString( (char*) stringValue,
  205. stringSize, environment->encoding);
  206. case OCI_TYPECODE_NUMBER:
  207. return OracleNumberToPythonFloat(environment, (OCINumber*) value);
  208. case OCI_TYPECODE_DATE:
  209. return OracleDateToPythonDate(&vt_DateTime, (OCIDate*) value);
  210. case OCI_TYPECODE_TIMESTAMP:
  211. return OracleTimestampToPythonDate(environment,
  212. * (OCIDateTime**) value);
  213. case OCI_TYPECODE_OBJECT:
  214. return ExternalObjectVar_New(referencedObject, subType, value,
  215. indicator, 0);
  216. case OCI_TYPECODE_NAMEDCOLLECTION:
  217. return ExternalObjectVar_ConvertCollection(environment,
  218. * (OCIColl**) value, referencedObject, subType);
  219. };
  220. return PyErr_Format(g_NotSupportedErrorException,
  221. "ExternalObjectVar_GetAttributeValue(): unhandled data type %d",
  222. typeCode);
  223. }
  224. //-----------------------------------------------------------------------------
  225. // ExternalObjectVar_GetAttributeValue()
  226. // Retrieve an attribute on the external LOB variable object.
  227. //-----------------------------------------------------------------------------
  228. static PyObject *ExternalObjectVar_GetAttributeValue(
  229. udt_ExternalObjectVar *self, // object
  230. udt_ObjectAttribute *attribute) // attribute to get
  231. {
  232. dvoid *valueIndicator, *value;
  233. OCIInd scalarValueIndicator;
  234. udt_Buffer buffer;
  235. sword status;
  236. OCIType *tdo;
  237. // get the value for the attribute
  238. if (cxBuffer_FromObject(&buffer, attribute->name,
  239. self->objectType->environment->encoding) < 0)
  240. return NULL;
  241. status = OCIObjectGetAttr(self->objectType->environment->handle,
  242. self->objectType->environment->errorHandle, self->instance,
  243. self->indicator, self->objectType->tdo,
  244. (const OraText**) &buffer.ptr, (ub4*) &buffer.size, 1, 0, 0,
  245. &scalarValueIndicator, &valueIndicator, &value, &tdo);
  246. cxBuffer_Clear(&buffer);
  247. if (Environment_CheckForError(self->objectType->environment, status,
  248. "ExternalObjectVar_GetAttributeValue(): getting value") < 0)
  249. return NULL;
  250. // determine the proper null indicator
  251. if (!valueIndicator)
  252. valueIndicator = &scalarValueIndicator;
  253. return ExternalObjectVar_ConvertToPython(self->objectType->environment,
  254. attribute->typeCode, value, valueIndicator, (PyObject*) self,
  255. attribute->subType);
  256. }
  257. //-----------------------------------------------------------------------------
  258. // ExternalObjectVar_GetAttr()
  259. // Retrieve an attribute on the external LOB variable object.
  260. //-----------------------------------------------------------------------------
  261. static PyObject *ExternalObjectVar_GetAttr(
  262. udt_ExternalObjectVar *self, // object
  263. PyObject *nameObject) // name of attribute
  264. {
  265. udt_ObjectAttribute *attribute;
  266. attribute = (udt_ObjectAttribute*)
  267. PyDict_GetItem(self->objectType->attributesByName, nameObject);
  268. if (attribute)
  269. return ExternalObjectVar_GetAttributeValue(self, attribute);
  270. return PyObject_GenericGetAttr( (PyObject*) self, nameObject);
  271. }