PageRenderTime 49ms CodeModel.GetById 10ms RepoModel.GetById 0ms app.codeStats 1ms

/pypy/module/oracle/interp_variable.py

https://bitbucket.org/dac_io/pypy
Python | 1561 lines | 1439 code | 81 blank | 41 comment | 74 complexity | e82adcd54aa2416548ba131794d4ad97 MD5 | raw file

Large files files are truncated, but you can click here to view the full file

  1. from pypy.interpreter.baseobjspace import Wrappable
  2. from pypy.interpreter.typedef import TypeDef
  3. from pypy.interpreter.typedef import interp_attrproperty
  4. from pypy.interpreter.gateway import interp2app, unwrap_spec
  5. from pypy.interpreter.error import OperationError
  6. from pypy.rpython.lltypesystem import rffi, lltype
  7. from pypy.rlib.rarithmetic import ovfcheck
  8. import sys
  9. from pypy.module.oracle import roci, config, transform
  10. from pypy.module.oracle import interp_lob, interp_object
  11. from pypy.module.oracle.interp_error import W_Error, get
  12. from pypy.module.oracle.config import string_w, StringBuffer
  13. def define(cursor, position, numElements):
  14. paramptr = lltype.malloc(roci.Ptr(roci.OCIParam).TO, 1, flavor='raw')
  15. try:
  16. status = roci.OCIParamGet(
  17. cursor.handle, roci.OCI_HTYPE_STMT,
  18. cursor.environment.errorHandle,
  19. paramptr, position)
  20. cursor.environment.checkForError(
  21. status,
  22. "Variable_Define(): parameter")
  23. param = paramptr[0]
  24. finally:
  25. lltype.free(paramptr, flavor='raw')
  26. # call the helper to do the actual work
  27. var = _defineHelper(cursor, param, position, numElements)
  28. roci.OCIDescriptorFree(param, roci.OCI_DTYPE_PARAM)
  29. return var
  30. def _defineHelper(cursor, param, position, numElements):
  31. # determine data type
  32. varType = typeByOracleDescriptor(param, cursor.environment)
  33. if cursor.numbersAsStrings and varType is VT_Float:
  34. varType = VT_NumberAsString
  35. # retrieve size of the parameter
  36. size = varType.size
  37. if varType.isVariableLength:
  38. # determine the maximum length from Oracle
  39. attrptr = lltype.malloc(rffi.CArrayPtr(roci.ub2).TO, 1, flavor='raw')
  40. try:
  41. status = roci.OCIAttrGet(
  42. param, roci.OCI_HTYPE_DESCRIBE,
  43. rffi.cast(roci.dvoidp, attrptr),
  44. lltype.nullptr(roci.Ptr(roci.ub4).TO),
  45. roci.OCI_ATTR_DATA_SIZE,
  46. cursor.environment.errorHandle)
  47. cursor.environment.checkForError(
  48. status, "Variable_Define(): data size")
  49. sizeFromOracle = rffi.cast(lltype.Signed, attrptr[0])
  50. finally:
  51. lltype.free(attrptr, flavor='raw')
  52. # use the length from Oracle directly if available
  53. if sizeFromOracle:
  54. size = rffi.cast(lltype.Signed, sizeFromOracle)
  55. # otherwise, use the value set with the setoutputsize() parameter
  56. elif cursor.outputSize >= 0:
  57. if (cursor.outputSizeColumn < 0 or
  58. position == cursor.outputSizeColumn):
  59. size = cursor.outputSize
  60. # call the procedure to set values prior to define
  61. varType2 = varType.preDefine(varType, param, cursor.environment)
  62. # create a variable of the correct type
  63. if 0 and cursor.w_outputTypeHandler: # XXX
  64. var = newByOutputTypeHandler(
  65. cursor, param,
  66. cursor.w_outputTypeHandler,
  67. varType2, size, numElements)
  68. elif 0 and cursor.connection.w_outputTypeHandler: # XXX
  69. var = newByOutputTypeHandler(
  70. cursor, param,
  71. cursor.connection.w_outputTypeHandler,
  72. varType2, size, numElements)
  73. else:
  74. var = varType2(cursor, numElements, size)
  75. assert isinstance(var, W_Variable)
  76. # perform the define
  77. handleptr = lltype.malloc(roci.Ptr(roci.OCIDefine).TO, 1, flavor='raw')
  78. try:
  79. status = roci.OCIDefineByPos(
  80. cursor.handle,
  81. handleptr,
  82. var.environment.errorHandle,
  83. position,
  84. var.data, var.bufferSize,
  85. var.oracleType,
  86. rffi.cast(roci.dvoidp, var.indicator),
  87. var.actualLength,
  88. var.returnCode,
  89. roci.OCI_DEFAULT)
  90. var.environment.checkForError(
  91. status,
  92. "Variable_Define(): define")
  93. var.defineHandle = handleptr[0]
  94. finally:
  95. lltype.free(handleptr, flavor='raw')
  96. # call the procedure to set values after define
  97. var.postDefine(param)
  98. return var
  99. class W_Variable(Wrappable):
  100. charsetForm = roci.SQLCS_IMPLICIT
  101. isVariableLength = False
  102. canBeInArray = True
  103. def __init__(self, cursor, numElements, size=0):
  104. self.environment = cursor.environment
  105. self.boundCursorHandle = lltype.nullptr(roci.OCIStmt.TO)
  106. self.boundName = None
  107. self.boundPos = 0
  108. self.isArray = False
  109. self.actualElementsPtr = lltype.malloc(roci.Ptr(roci.ub4).TO, 1,
  110. zero=True, flavor='raw')
  111. if numElements < 1:
  112. self.allocatedElements = 1
  113. else:
  114. self.allocatedElements = numElements
  115. self.internalFetchNum = 0
  116. self.actualLength = lltype.nullptr(rffi.CArrayPtr(roci.ub2).TO)
  117. self.returnCode = lltype.nullptr(rffi.CArrayPtr(roci.ub2).TO)
  118. # set the maximum length of the variable, ensure that a minimum of
  119. # 2 bytes is allocated to ensure that the array size check works
  120. if self.isVariableLength:
  121. size = max(size, rffi.sizeof(roci.ub2))
  122. if self.size != size:
  123. self.size = size
  124. # allocate the data for the variable
  125. self.allocateData(self.environment.space)
  126. # allocate the indicator for the variable
  127. self.indicator = lltype.malloc(rffi.CArrayPtr(roci.sb2).TO,
  128. self.allocatedElements,
  129. flavor='raw', zero=True)
  130. # ensure that all variable values start out NULL
  131. for i in range(self.allocatedElements):
  132. self.indicator[i] = rffi.cast(roci.sb2, roci.OCI_IND_NULL)
  133. # for variable length data, also allocate the return code
  134. if self.isVariableLength:
  135. self.returnCode = lltype.malloc(rffi.CArrayPtr(roci.ub2).TO,
  136. self.allocatedElements,
  137. flavor='raw', zero=True)
  138. # perform extended initialization
  139. self.initialize(self.environment.space, cursor)
  140. def __del__(self):
  141. self.enqueue_for_destruction(self.environment.space,
  142. W_Variable.destructor,
  143. '__del__ method of ')
  144. def destructor(self):
  145. assert isinstance(self, W_Variable)
  146. self.finalize()
  147. lltype.free(self.actualElementsPtr, flavor='raw')
  148. if self.actualLength:
  149. lltype.free(self.actualLength, flavor='raw')
  150. if self.data:
  151. lltype.free(self.data, flavor='raw')
  152. if self.returnCode:
  153. lltype.free(self.returnCode, flavor='raw')
  154. if self.indicator:
  155. lltype.free(self.indicator, flavor='raw')
  156. def getBufferSize(self):
  157. return self.size
  158. def allocateData(self, space):
  159. # set the buffer size for the variable
  160. self.bufferSize = self.getBufferSize()
  161. # allocate the data as long as it is small enough
  162. try:
  163. dataLength = ovfcheck(self.allocatedElements * self.bufferSize)
  164. except OverflowError:
  165. too_large = True
  166. else:
  167. too_large = False
  168. if too_large or dataLength >= roci.INT_MAX:
  169. raise OperationError(
  170. space.w_ValueError,
  171. space.wrap("array size too large"))
  172. self.data = lltype.malloc(rffi.CCHARP.TO, int(dataLength),
  173. flavor='raw', zero=True)
  174. def resize(self, space, size):
  175. # allocate the data for the new array
  176. orig_data = self.data
  177. orig_size = self.bufferSize
  178. self.size = size
  179. self.allocateData(space)
  180. # copy the data from the original array to the new array
  181. for i in range(self.allocatedElements):
  182. for j in range(orig_size):
  183. self.data[self.bufferSize * i + j] = \
  184. orig_data[orig_size * i + j]
  185. lltype.free(orig_data, flavor='raw')
  186. # force rebinding
  187. if self.boundName or self.boundPos:
  188. self._internalBind(space)
  189. def makeArray(self, space):
  190. if not self.canBeInArray:
  191. raise OperationError(
  192. get(space).w_NotSupportedError,
  193. space.wrap(
  194. "Variable_MakeArray(): type does not support arrays"))
  195. self.isArray = True
  196. def initialize(self, space, cursor):
  197. pass
  198. def finalize(self):
  199. pass
  200. @staticmethod
  201. def preDefine(cls, param, environment):
  202. return cls
  203. def postDefine(self, param):
  204. pass
  205. def bind(self, space, cursor, w_name, pos):
  206. # nothing to do if already bound
  207. if (cursor.handle == self.boundCursorHandle and
  208. w_name == self.w_boundName and pos == self.boundPos):
  209. return
  210. # set the instance variables specific for binding
  211. self.boundCursorHandle = cursor.handle
  212. self.boundPos = pos
  213. self.w_boundName = w_name
  214. # perform the bind
  215. self._internalBind(space)
  216. def _internalBind(self, space):
  217. bindHandlePtr = lltype.malloc(roci.Ptr(roci.OCIBind).TO, 1,
  218. flavor='raw')
  219. if self.isArray:
  220. allocatedElements = self.allocatedElements
  221. actualElementsPtr = self.actualElementsPtr
  222. else:
  223. allocatedElements = 0
  224. actualElementsPtr = lltype.nullptr(roci.Ptr(roci.ub4).TO)
  225. try:
  226. if self.w_boundName:
  227. nameBuffer = config.StringBuffer()
  228. nameBuffer.fill(space, self.w_boundName)
  229. status = roci.OCIBindByName(
  230. self.boundCursorHandle, bindHandlePtr,
  231. self.environment.errorHandle,
  232. nameBuffer.ptr, nameBuffer.size,
  233. self.data, self.bufferSize,
  234. self.oracleType,
  235. rffi.cast(roci.dvoidp, self.indicator),
  236. self.actualLength, self.returnCode,
  237. allocatedElements, actualElementsPtr,
  238. roci.OCI_DEFAULT)
  239. nameBuffer.clear()
  240. else:
  241. status = roci.OCIBindByPos(
  242. self.boundCursorHandle, bindHandlePtr,
  243. self.environment.errorHandle,
  244. self.boundPos,
  245. self.data, self.bufferSize,
  246. self.oracleType,
  247. rffi.cast(roci.dvoidp, self.indicator),
  248. self.actualLength, self.returnCode,
  249. allocatedElements, actualElementsPtr,
  250. roci.OCI_DEFAULT)
  251. self.environment.checkForError(
  252. status, "NumberVar_InternalBind()")
  253. self.bindHandle = bindHandlePtr[0]
  254. finally:
  255. lltype.free(bindHandlePtr, flavor='raw')
  256. # set the charset form and id if applicable
  257. if self.charsetForm != roci.SQLCS_IMPLICIT:
  258. charsetformptr = lltype.malloc(roci.Ptr(roci.ub1).TO, 1,
  259. zero=True, flavor='raw')
  260. charsetformptr[0] = rffi.cast(roci.ub1, self.charsetForm)
  261. try:
  262. status = roci.OCIAttrSet(
  263. self.bindHandle, roci.OCI_HTYPE_BIND,
  264. rffi.cast(roci.dvoidp, charsetformptr), 0,
  265. roci.OCI_ATTR_CHARSET_FORM,
  266. self.environment.errorHandle)
  267. self.environment.checkForError(
  268. status, "NumberVar_InternalBind(): set charset form")
  269. finally:
  270. lltype.free(charsetformptr, flavor='raw')
  271. charsetidptr = lltype.malloc(roci.Ptr(roci.ub2).TO, 1,
  272. zero=True, flavor='raw')
  273. charsetidptr[0] = rffi.cast(roci.ub2, roci.OCI_UTF16ID)
  274. try:
  275. status = roci.OCIAttrSet(
  276. self.bindHandle, roci.OCI_HTYPE_BIND,
  277. rffi.cast(roci.dvoidp, charsetidptr), 0,
  278. roci.OCI_ATTR_CHARSET_ID,
  279. self.environment.errorHandle)
  280. self.environment.checkForError(
  281. status, "NumberVar_InternalBind(): set charset Id")
  282. finally:
  283. lltype.free(charsetidptr, flavor='raw')
  284. # set the max data size for strings
  285. buffersizeptr = lltype.malloc(roci.Ptr(roci.ub4).TO, 1,
  286. zero=True, flavor='raw')
  287. buffersizeptr[0] = rffi.cast(roci.ub4, self.size)
  288. try:
  289. status = roci.OCIAttrSet(
  290. self.bindHandle, roci.OCI_HTYPE_BIND,
  291. rffi.cast(roci.dvoidp, buffersizeptr), 0,
  292. roci.OCI_ATTR_MAXDATA_SIZE,
  293. self.environment.errorHandle)
  294. self.environment.checkForError(
  295. status, "NumberVar_InternalBind(): set max data size")
  296. finally:
  297. lltype.free(buffersizeptr, flavor='raw')
  298. def isNull(self, pos):
  299. return (rffi.cast(lltype.Signed, self.indicator[pos])
  300. ==
  301. rffi.cast(lltype.Signed, roci.OCI_IND_NULL))
  302. def verifyFetch(self, space, pos):
  303. # Verifies that truncation or other problems did not take place on
  304. # retrieve.
  305. if self.isVariableLength:
  306. error_code = rffi.cast(lltype.Signed, self.returnCode[pos])
  307. if error_code != 0:
  308. error = W_Error(space, self.environment,
  309. "Variable_VerifyFetch()", 0)
  310. error.code = error_code
  311. error.message = space.wrap(
  312. "column at array pos %d fetched with error: %d" %
  313. (pos, error_code))
  314. w_error = get(space).w_DatabaseError
  315. raise OperationError(get(space).w_DatabaseError,
  316. space.wrap(error))
  317. def getSingleValue(self, space, pos):
  318. # ensure we do not exceed the number of allocated elements
  319. if pos >= self.allocatedElements:
  320. raise OperationError(
  321. space.w_IndexError,
  322. space.wrap("Variable_GetSingleValue: array size exceeded"))
  323. # check for a NULL value
  324. if self.isNull(pos):
  325. return space.wrap(None)
  326. # check for truncation or other problems on retrieve
  327. self.verifyFetch(space, pos)
  328. # calculate value to return
  329. value = self.getValueProc(space, pos)
  330. # XXX outConverter
  331. return value
  332. def getArrayValue(self, space, numElements):
  333. return space.newlist(
  334. [self.getSingleValue(space, i)
  335. for i in range(numElements)])
  336. @unwrap_spec(pos=int)
  337. def getValue(self, space, pos=0):
  338. if self.isArray:
  339. return self.getArrayValue(space, self.actualElementsPtr[0])
  340. return self.getSingleValue(space, pos)
  341. def setSingleValue(self, space, pos, w_value):
  342. # ensure we do not exceed the number of allocated elements
  343. if pos >= self.allocatedElements:
  344. raise OperationError(
  345. space.w_IndexError,
  346. space.wrap("Variable_SetSingleValue: array size exceeded"))
  347. # convert value, if necessary
  348. # XXX inConverter
  349. # check for a NULL value
  350. if space.is_w(w_value, space.w_None):
  351. self.indicator[pos] = roci.OCI_IND_NULL
  352. return
  353. self.indicator[pos] = roci.OCI_IND_NOTNULL
  354. if self.isVariableLength:
  355. self.returnCode[pos] = rffi.cast(roci.ub2, 0)
  356. self.setValueProc(space, pos, w_value)
  357. def setArrayValue(self, space, w_value):
  358. # ensure we have an array to set
  359. if not space.is_true(space.isinstance(w_value, space.w_list)):
  360. raise OperationError(
  361. space.w_TypeError,
  362. space.wrap("expecting array data"))
  363. elements_w = space.listview(w_value)
  364. # ensure we haven't exceeded the number of allocated elements
  365. if len(elements_w) > self.allocatedElements:
  366. raise OperationError(
  367. space.w_IndexError,
  368. space.wrap("Variable_SetArrayValue: array size exceeded"))
  369. # set all of the values
  370. self.actualElementsPtr[0] = rffi.cast(roci.ub4, len(elements_w))
  371. for i in range(len(elements_w)):
  372. self.setSingleValue(space, i, elements_w[i])
  373. @unwrap_spec(pos=int)
  374. def setValue(self, space, pos, w_value):
  375. if self.isArray:
  376. self.setArrayValue(space, w_value)
  377. else:
  378. self.setSingleValue(space, pos, w_value)
  379. W_Variable.typedef = TypeDef(
  380. 'Variable',
  381. getvalue = interp2app(W_Variable.getValue),
  382. setvalue = interp2app(W_Variable.setValue),
  383. maxlength = interp_attrproperty('bufferSize', W_Variable),
  384. bufferSize = interp_attrproperty('bufferSize', W_Variable),
  385. size = interp_attrproperty('size', W_Variable),
  386. )
  387. class VT_String(W_Variable):
  388. oracleType = roci.SQLT_CHR
  389. size = config.MAX_STRING_CHARS
  390. isVariableLength = True
  391. def getBufferSize(self):
  392. if config.WITH_UNICODE:
  393. return self.size * BYTES_PER_CHAR
  394. else:
  395. if self.charsetForm == roci.SQLCS_IMPLICIT:
  396. return self.size * self.environment.maxBytesPerCharacter
  397. else:
  398. return self.size * 2
  399. def initialize(self, space, cursor):
  400. self.actualLength = lltype.malloc(rffi.CArrayPtr(roci.ub2).TO,
  401. self.allocatedElements,
  402. zero=True, flavor='raw')
  403. def getValueProc(self, space, pos):
  404. offset = pos * self.bufferSize
  405. dataptr = rffi.ptradd(self.data, offset)
  406. length = rffi.cast(lltype.Signed, self.actualLength[pos])
  407. i = 0
  408. if config.WITH_UNICODE:
  409. if isinstance(self, VT_Binary):
  410. return space.wrap(rffi.charpsize2str(dataptr, length))
  411. else:
  412. l = []
  413. while i < length:
  414. l.append(unichr((ord(dataptr[i + 1]) << 8) +
  415. ord(dataptr[i])))
  416. i += 2
  417. return space.wrap(u''.join(l))
  418. else:
  419. if self.charsetForm == roci.SQLCS_IMPLICIT:
  420. return space.wrap(rffi.charpsize2str(dataptr, length))
  421. else:
  422. l = []
  423. while i < length:
  424. l.append(unichr((ord(dataptr[i + 1]) << 8) +
  425. ord(dataptr[i])))
  426. i += 2
  427. return space.wrap(u''.join(l))
  428. def setValueProc(self, space, pos, w_value):
  429. if config.WITH_UNICODE:
  430. wantBytes = not self.isCharacterData
  431. else:
  432. wantBytes = self.charsetForm == roci.SQLCS_IMPLICIT
  433. if wantBytes:
  434. if space.is_true(space.isinstance(w_value, space.w_str)):
  435. buf = config.StringBuffer()
  436. buf.fill(space, w_value)
  437. size = buf.size
  438. else:
  439. raise OperationError(
  440. space.w_TypeError,
  441. space.wrap("expecting string or buffer data"))
  442. else:
  443. if space.is_true(space.isinstance(w_value, space.w_unicode)):
  444. buf = config.StringBuffer()
  445. buf.fill_with_unicode(space, w_value)
  446. size = buf.size
  447. else:
  448. raise OperationError(
  449. space.w_TypeError,
  450. space.wrap("expecting unicode data"))
  451. try:
  452. if wantBytes:
  453. if buf.size > self.environment.maxStringBytes:
  454. raise OperationError(
  455. space.w_ValueError,
  456. space.wrap("string data too large"))
  457. else:
  458. if buf.size > config.MAX_STRING_CHARS * 2:
  459. raise OperationError(
  460. space.w_ValueError,
  461. space.wrap("unicode data too large"))
  462. # ensure that the buffer is large enough
  463. if buf.size > self.bufferSize:
  464. self.resize(space, size)
  465. # keep a copy of the string
  466. self.actualLength[pos] = rffi.cast(roci.ub2, buf.size)
  467. offset = pos * self.bufferSize
  468. for index in range(buf.size):
  469. self.data[offset + index] = buf.ptr[index]
  470. finally:
  471. buf.clear()
  472. class VT_FixedChar(VT_String):
  473. oracleType = roci.SQLT_AFC
  474. size = 2000
  475. class VT_NationalCharString(VT_String):
  476. charsetForm = roci.SQLCS_NCHAR
  477. def postDefine(self, param):
  478. charsetformptr = lltype.malloc(roci.Ptr(roci.ub1).TO, 1,
  479. zero=True, flavor='raw')
  480. charsetformptr[0] = rffi.cast(roci.ub1, self.charsetForm)
  481. try:
  482. status = roci.OCIAttrSet(
  483. self.defineHandle, roci.OCI_HTYPE_DEFINE,
  484. rffi.cast(roci.dvoidp, charsetformptr), 0,
  485. roci.OCI_ATTR_CHARSET_FORM,
  486. self.environment.errorHandle)
  487. self.environment.checkForError(
  488. status, "StringVar_PostDefine(): set charset form")
  489. finally:
  490. lltype.free(charsetformptr, flavor='raw')
  491. charsetidptr = lltype.malloc(roci.Ptr(roci.ub2).TO, 1,
  492. zero=True, flavor='raw')
  493. charsetidptr[0] = rffi.cast(roci.ub2, roci.OCI_UTF16ID)
  494. try:
  495. status = roci.OCIAttrSet(
  496. self.defineHandle, roci.OCI_HTYPE_DEFINE,
  497. rffi.cast(roci.dvoidp, charsetidptr), 0,
  498. roci.OCI_ATTR_CHARSET_ID,
  499. self.environment.errorHandle)
  500. self.environment.checkForError(
  501. status, "StringVar_PostDefine(): set charset Id")
  502. finally:
  503. lltype.free(charsetidptr, flavor='raw')
  504. class VT_FixedNationalChar(VT_NationalCharString):
  505. oracleType = roci.SQLT_AFC
  506. size = 2000
  507. class VT_LongString(W_Variable):
  508. oracleType = roci.SQLT_LVC
  509. isVariableLength = True
  510. size = 128 * 1024
  511. def getBufferSize(self):
  512. return self.size + rffi.sizeof(roci.ub4)
  513. def getValueProc(self, space, pos):
  514. ptr = rffi.ptradd(self.data, pos * self.bufferSize)
  515. length = rffi.cast(roci.Ptr(roci.ub4), ptr)[0]
  516. length = rffi.cast(lltype.Signed, length)
  517. ptr = rffi.ptradd(ptr, rffi.sizeof(roci.ub4))
  518. return space.wrap(rffi.charpsize2str(ptr, length))
  519. def setValueProc(self, space, pos, w_value):
  520. buf = config.StringBuffer()
  521. buf.fill(space, w_value)
  522. try:
  523. # ensure that the buffer is large enough
  524. if buf.size + rffi.sizeof(roci.ub4) > self.bufferSize:
  525. self.resize(space, buf.size + rffi.sizeof(roci.ub4))
  526. # copy the string to the Oracle buffer
  527. ptr = rffi.ptradd(self.data, pos * self.bufferSize)
  528. rffi.cast(roci.Ptr(roci.ub4), ptr)[0] = rffi.cast(roci.ub4, buf.size)
  529. for index in range(buf.size):
  530. ptr[index + rffi.sizeof(roci.ub4)] = buf.ptr[index]
  531. finally:
  532. buf.clear()
  533. class VT_Rowid(VT_String):
  534. oracleType = roci.SQLT_CHR
  535. size = 18
  536. isVariableLength = False
  537. class VT_Binary(VT_String):
  538. oracleType = roci.SQLT_BIN
  539. size = config.MAX_BINARY_BYTES
  540. class VT_LongBinary(VT_LongString):
  541. oracleType = roci.SQLT_LVB
  542. class VT_NativeFloat(W_Variable):
  543. pass
  544. class VT_Float(W_Variable):
  545. oracleType = roci.SQLT_VNU
  546. size = rffi.sizeof(roci.OCINumber)
  547. @staticmethod
  548. def preDefine(cls, param, environment):
  549. # if the return type has not already been specified, check to
  550. # see if the number can fit inside an integer by looking at
  551. # the precision and scale
  552. if cls is VT_Float:
  553. attrptr = lltype.malloc(rffi.CArrayPtr(roci.sb1).TO, 1,
  554. flavor='raw')
  555. try:
  556. status = roci.OCIAttrGet(
  557. param, roci.OCI_HTYPE_DESCRIBE,
  558. rffi.cast(roci.dvoidp, attrptr),
  559. lltype.nullptr(roci.Ptr(roci.ub4).TO),
  560. roci.OCI_ATTR_SCALE,
  561. environment.errorHandle)
  562. environment.checkForError(
  563. status,
  564. "NumberVar_PreDefine(): scale")
  565. scale = rffi.cast(lltype.Signed, attrptr[0])
  566. finally:
  567. lltype.free(attrptr, flavor='raw')
  568. attrptr = lltype.malloc(rffi.CArrayPtr(roci.ub2).TO, 1,
  569. flavor='raw')
  570. try:
  571. status = roci.OCIAttrGet(
  572. param, roci.OCI_HTYPE_DESCRIBE,
  573. rffi.cast(roci.dvoidp, attrptr),
  574. lltype.nullptr(roci.Ptr(roci.ub4).TO),
  575. roci.OCI_ATTR_PRECISION,
  576. environment.errorHandle)
  577. environment.checkForError(
  578. status,
  579. "NumberVar_PreDefine(): precision")
  580. precision = rffi.cast(lltype.Signed, attrptr[0])
  581. finally:
  582. lltype.free(attrptr, flavor='raw')
  583. if scale == 0 or (scale == -127 and precision == 0):
  584. if precision > 0 and precision < 10:
  585. return VT_Integer
  586. else:
  587. return VT_LongInteger
  588. return cls
  589. def getValueProc(self, space, pos):
  590. dataptr = rffi.ptradd(
  591. rffi.cast(roci.Ptr(roci.OCINumber), self.data),
  592. pos)
  593. if isinstance(self, VT_Integer):
  594. integerValuePtr = lltype.malloc(roci.Ptr(lltype.Signed).TO, 1,
  595. flavor='raw')
  596. try:
  597. status = roci.OCINumberToInt(
  598. self.environment.errorHandle,
  599. dataptr,
  600. rffi.sizeof(rffi.LONG),
  601. roci.OCI_NUMBER_SIGNED,
  602. rffi.cast(roci.dvoidp, integerValuePtr))
  603. self.environment.checkForError(
  604. status, "NumberVar_GetValue(): as integer")
  605. if isinstance(self, VT_Boolean):
  606. return space.newbool(bool(integerValuePtr[0]))
  607. else:
  608. return space.wrap(integerValuePtr[0])
  609. finally:
  610. lltype.free(integerValuePtr, flavor='raw')
  611. elif isinstance(self, VT_NumberAsString) or isinstance(self, VT_LongInteger):
  612. format_buf = config.StringBuffer()
  613. format_buf.fill(space, space.wrap("TM9"))
  614. sizeptr = lltype.malloc(rffi.CArray(roci.ub4), 1, flavor='raw')
  615. BUFSIZE = 200
  616. sizeptr[0] = rffi.cast(roci.ub4, BUFSIZE)
  617. textbuf, text = rffi.alloc_buffer(BUFSIZE)
  618. try:
  619. status = roci.OCINumberToText(
  620. self.environment.errorHandle,
  621. dataptr,
  622. format_buf.ptr, format_buf.size,
  623. None, 0,
  624. sizeptr, textbuf);
  625. self.environment.checkForError(
  626. status, "NumberVar_GetValue(): as string")
  627. w_strvalue = space.wrap(
  628. rffi.str_from_buffer(textbuf, text,
  629. BUFSIZE,
  630. rffi.cast(lltype.Signed, sizeptr[0])))
  631. finally:
  632. rffi.keep_buffer_alive_until_here(textbuf, text)
  633. lltype.free(sizeptr, flavor='raw')
  634. format_buf.clear()
  635. if isinstance(self, VT_NumberAsString):
  636. return w_strvalue
  637. try:
  638. return space.call_function(space.w_int, w_strvalue)
  639. except OperationError, e:
  640. if e.match(space, space.w_ValueError):
  641. return space.call_function(space.w_float, w_strvalue)
  642. raise
  643. else:
  644. return transform.OracleNumberToPythonFloat(
  645. self.environment, dataptr)
  646. def setValueProc(self, space, pos, w_value):
  647. dataptr = rffi.ptradd(
  648. rffi.cast(roci.Ptr(roci.OCINumber), self.data),
  649. pos)
  650. if space.is_true(space.isinstance(w_value, space.w_int)):
  651. integerValuePtr = lltype.malloc(roci.Ptr(lltype.Signed).TO, 1,
  652. flavor='raw')
  653. try:
  654. integerValuePtr[0] = space.int_w(w_value)
  655. status = roci.OCINumberFromInt(
  656. self.environment.errorHandle,
  657. rffi.cast(roci.dvoidp, integerValuePtr),
  658. rffi.sizeof(lltype.Signed),
  659. roci.OCI_NUMBER_SIGNED,
  660. dataptr)
  661. self.environment.checkForError(
  662. status, "NumberVar_SetValue(): from integer")
  663. finally:
  664. lltype.free(integerValuePtr, flavor='raw')
  665. return
  666. elif space.is_true(space.isinstance(w_value, space.w_long)):
  667. text_buf = config.StringBuffer()
  668. text_buf.fill(space, space.str(w_value))
  669. format_buf = config.StringBuffer()
  670. format_buf.fill(space, space.wrap("9" * 63))
  671. status = roci.OCINumberFromText(
  672. self.environment.errorHandle,
  673. text_buf.ptr, text_buf.size,
  674. format_buf.ptr, format_buf.size,
  675. None, 0,
  676. dataptr)
  677. text_buf.clear()
  678. format_buf.clear()
  679. self.environment.checkForError(
  680. status, "NumberVar_SetValue(): from long")
  681. return
  682. # XXX The bool case was already processed above
  683. elif space.is_true(space.isinstance(w_value, space.w_float)):
  684. doubleValuePtr = lltype.malloc(roci.Ptr(lltype.Float).TO, 1,
  685. flavor='raw')
  686. try:
  687. doubleValuePtr[0] = space.float_w(w_value)
  688. status = roci.OCINumberFromReal(
  689. self.environment.errorHandle,
  690. rffi.cast(roci.dvoidp, doubleValuePtr),
  691. rffi.sizeof(lltype.Float),
  692. dataptr)
  693. self.environment.checkForError(
  694. status, "NumberVar_SetValue(): from float")
  695. finally:
  696. lltype.free(doubleValuePtr, flavor='raw')
  697. return
  698. elif space.is_true(space.isinstance(w_value, get(space).w_DecimalType)):
  699. w_text, w_format = transform.DecimalToFormatAndText(self.environment, w_value)
  700. text_buf = config.StringBuffer()
  701. text_buf.fill(space, w_text)
  702. format_buf = config.StringBuffer()
  703. format_buf.fill(space, w_format)
  704. nls_params = "NLS_NUMERIC_CHARACTERS='.,'"
  705. status = roci.OCINumberFromText(
  706. self.environment.errorHandle,
  707. text_buf.ptr, text_buf.size,
  708. format_buf.ptr, format_buf.size,
  709. nls_params, len(nls_params),
  710. dataptr)
  711. text_buf.clear()
  712. format_buf.clear()
  713. self.environment.checkForError(
  714. status, "NumberVar_SetValue(): from decimal")
  715. return
  716. raise OperationError(
  717. space.w_TypeError,
  718. space.wrap("expecting numeric data"))
  719. class VT_Integer(VT_Float):
  720. pass
  721. class VT_Boolean(VT_Integer):
  722. pass
  723. class VT_NumberAsString(VT_Float):
  724. pass
  725. class VT_LongInteger(VT_Float):
  726. pass
  727. class VT_DateTime(W_Variable):
  728. oracleType = roci.SQLT_ODT
  729. size = rffi.sizeof(roci.OCIDate)
  730. def getValueProc(self, space, pos):
  731. dataptr = rffi.ptradd(
  732. rffi.cast(roci.Ptr(roci.OCIDate), self.data),
  733. pos)
  734. return transform.OracleDateToPythonDateTime(self.environment, dataptr)
  735. def setValueProc(self, space, pos, w_value):
  736. dataptr = rffi.ptradd(
  737. rffi.cast(roci.Ptr(roci.OCIDate), self.data),
  738. pos)
  739. if space.is_true(space.isinstance(w_value, get(space).w_DateTimeType)):
  740. year = space.int_w(space.getattr(w_value, space.wrap('year')))
  741. month = space.int_w(space.getattr(w_value, space.wrap('month')))
  742. day = space.int_w(space.getattr(w_value, space.wrap('day')))
  743. hour = space.int_w(space.getattr(w_value, space.wrap('hour')))
  744. minute = space.int_w(space.getattr(w_value, space.wrap('minute')))
  745. second = space.int_w(space.getattr(w_value, space.wrap('second')))
  746. elif space.is_true(space.isinstance(w_value, get(space).w_DateType)):
  747. year = space.int_w(space.getattr(w_value, space.wrap('year')))
  748. month = space.int_w(space.getattr(w_value, space.wrap('month')))
  749. day = space.int_w(space.getattr(w_value, space.wrap('day')))
  750. hour = minute = second = 0
  751. else:
  752. raise OperationError(
  753. space.w_TypeError,
  754. space.wrap("expecting date data"))
  755. # store a copy of the value
  756. value = dataptr[0]
  757. timePart = value.c_OCIDateTime
  758. rffi.setintfield(timePart, 'c_OCITimeHH', hour)
  759. rffi.setintfield(timePart, 'c_OCITimeMI', minute)
  760. rffi.setintfield(timePart, 'c_OCITimeSS', second)
  761. rffi.setintfield(dataptr[0], 'c_OCIDateYYYY', year)
  762. rffi.setintfield(dataptr[0], 'c_OCIDateMM', month)
  763. rffi.setintfield(dataptr[0], 'c_OCIDateDD', day)
  764. class VT_Date(VT_DateTime):
  765. oracleType = roci.SQLT_ODT
  766. size = rffi.sizeof(roci.OCIDate)
  767. def getValueProc(self, space, pos):
  768. dataptr = rffi.ptradd(
  769. rffi.cast(roci.Ptr(roci.OCIDate), self.data),
  770. pos)
  771. return transform.OracleDateToPythonDate(self.environment, dataptr)
  772. class W_VariableWithDescriptor(W_Variable):
  773. size = rffi.sizeof(roci.dvoidp)
  774. def initialize(self, space, cursor):
  775. # initialize the descriptors
  776. for i in range(self.allocatedElements):
  777. dataptr = rffi.ptradd(
  778. rffi.cast(roci.Ptr(roci.dvoidp), self.data),
  779. i)
  780. status = roci.OCIDescriptorAlloc(
  781. self.environment.handle,
  782. dataptr,
  783. self.descriptorType,
  784. 0, None)
  785. self.environment.checkForError(
  786. status, self.descriptionText + "_Initialize()")
  787. def finalize(self):
  788. dataptr = rffi.cast(roci.Ptr(roci.dvoidp), self.data)
  789. for i in range(self.allocatedElements):
  790. if dataptr[i]:
  791. roci.OCIDescriptorFree(
  792. dataptr[i], self.descriptorType)
  793. def getDataptr(self, pos):
  794. return rffi.ptradd(
  795. rffi.cast(roci.Ptr(roci.dvoidp), self.data),
  796. pos)
  797. class VT_Timestamp(W_VariableWithDescriptor):
  798. oracleType = roci.SQLT_TIMESTAMP
  799. descriptorType = roci.OCI_DTYPE_TIMESTAMP
  800. descriptionText = "TimestampVar"
  801. def getValueProc(self, space, pos):
  802. return transform.OracleTimestampToPythonDate(
  803. self.environment, self.getDataptr(pos))
  804. def setValueProc(self, space, pos, w_value):
  805. # make sure a timestamp is being bound
  806. if not space.is_true(space.isinstance(w_value, get(space).w_DateTimeType)):
  807. raise OperationError(
  808. space.w_TypeError,
  809. space.wrap("expecting timestamp data"))
  810. year = space.int_w(space.getattr(w_value, space.wrap('year')))
  811. month = space.int_w(space.getattr(w_value, space.wrap('month')))
  812. day = space.int_w(space.getattr(w_value, space.wrap('day')))
  813. hour = space.int_w(space.getattr(w_value, space.wrap('hour')))
  814. minute = space.int_w(space.getattr(w_value, space.wrap('minute')))
  815. second = space.int_w(space.getattr(w_value, space.wrap('second')))
  816. microsecond = space.int_w(space.getattr(w_value, space.wrap('microsecond')))
  817. status = roci.OCIDateTimeConstruct(
  818. self.environment.handle,
  819. self.environment.errorHandle,
  820. self.getDataptr(pos)[0],
  821. year, month, day, hour, minute, second, microsecond * 1000,
  822. None, 0)
  823. self.environment.checkForError(
  824. status, "TimestampVar_SetValue(): create structure")
  825. validptr = lltype.malloc(rffi.CArrayPtr(roci.ub4).TO, 1, flavor='raw')
  826. try:
  827. status = roci.OCIDateTimeCheck(
  828. self.environment.handle,
  829. self.environment.errorHandle,
  830. self.getDataptr(pos)[0],
  831. validptr);
  832. self.environment.checkForError(
  833. status,
  834. "TimestampVar_SetValue()")
  835. valid = rffi.cast(lltype.Signed, validptr[0])
  836. finally:
  837. lltype.free(validptr, flavor='raw')
  838. if valid != 0:
  839. raise OperationError(
  840. get(space).w_DataError,
  841. space.wrap("invalid date"))
  842. class VT_Interval(W_VariableWithDescriptor):
  843. oracleType = roci.SQLT_INTERVAL_DS
  844. descriptorType = roci.OCI_DTYPE_INTERVAL_DS
  845. descriptionText = "TimestampVar"
  846. def getValueProc(self, space, pos):
  847. return transform.OracleIntervalToPythonDelta(
  848. self.environment, self.getDataptr(pos))
  849. def setValueProc(self, space, pos, w_value):
  850. if not space.is_true(space.isinstance(w_value,
  851. get(space).w_TimedeltaType)):
  852. raise OperationError(
  853. space.w_TypeError,
  854. space.wrap("expecting timedelta data"))
  855. days = space.int_w(space.getattr(w_value, space.wrap('days')))
  856. seconds = space.int_w(space.getattr(w_value, space.wrap('seconds')))
  857. hours = seconds / 3600
  858. seconds -= hours * 3600
  859. minutes = seconds / 60
  860. seconds -= minutes * 60
  861. microseconds = space.int_w(
  862. space.getattr(w_value, space.wrap('microseconds')))
  863. status = roci.OCIIntervalSetDaySecond(
  864. self.environment.handle,
  865. self.environment.errorHandle,
  866. days, hours, minutes, seconds, microseconds,
  867. self.getDataptr(pos)[0])
  868. self.environment.checkForError(
  869. status, "IntervalVar_SetValue()")
  870. class W_LobVariable(W_VariableWithDescriptor):
  871. descriptorType = roci.OCI_DTYPE_LOB
  872. descriptionText = "LobVar"
  873. temporaryLobType = roci.OCI_TEMP_CLOB
  874. def initialize(self, space, cursor):
  875. W_VariableWithDescriptor.initialize(self, space, cursor)
  876. self.connection = cursor.connection
  877. def ensureTemporary(self, space, pos):
  878. # make sure we have a temporary LOB set up
  879. temporaryptr = lltype.malloc(rffi.CArrayPtr(roci.boolean).TO, 1, flavor='raw')
  880. try:
  881. status = roci.OCILobIsTemporary(
  882. self.environment.handle,
  883. self.environment.errorHandle,
  884. self.getDataptr(pos)[0],
  885. temporaryptr);
  886. self.environment.checkForError(
  887. status,
  888. "LobVar_SetValue(): check temporary")
  889. temporary = rffi.cast(lltype.Signed, temporaryptr[0])
  890. finally:
  891. lltype.free(temporaryptr, flavor='raw')
  892. if temporary:
  893. return
  894. status = roci.OCILobCreateTemporary(
  895. self.connection.handle,
  896. self.environment.errorHandle,
  897. self.getDataptr(pos)[0],
  898. roci.OCI_DEFAULT,
  899. roci.OCI_DEFAULT,
  900. self.temporaryLobType,
  901. False,
  902. roci.OCI_DURATION_SESSION)
  903. self.environment.checkForError(
  904. status,
  905. "LobVar_SetValue(): create temporary")
  906. def setValueProc(self, space, pos, w_value):
  907. self.ensureTemporary(space, pos)
  908. self.trim(space, pos, 0)
  909. self.write(space, pos, w_value, 1)
  910. def getLength(self, space, pos):
  911. "Return the size of the LOB variable for internal comsumption."
  912. lengthptr = lltype.malloc(rffi.CArrayPtr(roci.ub4).TO, 1, flavor='raw')
  913. try:
  914. status = roci.OCILobGetLength(
  915. self.connection.handle,
  916. self.environment.errorHandle,
  917. self.getDataptr(pos)[0],
  918. lengthptr)
  919. self.environment.checkForError(
  920. status,
  921. "LobVar_GetLength()")
  922. return rffi.cast(lltype.Signed,
  923. lengthptr[0]) # XXX test overflow
  924. finally:
  925. lltype.free(lengthptr, flavor='raw')
  926. def trim(self, space, pos, newSize):
  927. status = roci.OCILobTrim(
  928. self.connection.handle,
  929. self.environment.errorHandle,
  930. self.getDataptr(pos)[0],
  931. newSize)
  932. self.environment.checkForError(
  933. status,
  934. "LobVar_Trim()")
  935. def read(self, space, pos, offset, amount):
  936. # modify the arguments
  937. if offset <= 0:
  938. offset = 1
  939. if amount < 0:
  940. amount = self.getLength(space, pos) - offset + 1
  941. if amount <= 0:
  942. amount = 1
  943. bufferSize = amount
  944. raw_buffer, gc_buffer = rffi.alloc_buffer(bufferSize)
  945. amountptr = lltype.malloc(rffi.CArrayPtr(roci.ub4).TO, 1, flavor='raw')
  946. amountptr[0] = rffi.cast(roci.ub4, amount)
  947. try:
  948. status = roci.OCILobRead(
  949. self.connection.handle,
  950. self.environment.errorHandle,
  951. self.getDataptr(pos)[0],
  952. amountptr, offset,
  953. raw_buffer, bufferSize,
  954. None, None,
  955. config.CHARSETID, self.charsetForm)
  956. self.environment.checkForError(
  957. status,
  958. "LobVar_Read()")
  959. amount = rffi.cast(lltype.Signed,
  960. amountptr[0]) # XXX test overflow
  961. value = rffi.str_from_buffer(raw_buffer, gc_buffer, bufferSize, amount)
  962. return space.wrap(value)
  963. finally:
  964. lltype.free(amountptr, flavor='raw')
  965. rffi.keep_buffer_alive_until_here(raw_buffer, gc_buffer)
  966. def write(self, space, pos, w_value, offset):
  967. databuf = config.StringBuffer()
  968. databuf.fill(space, w_value)
  969. amountptr = lltype.malloc(rffi.CArrayPtr(roci.ub4).TO, 1, flavor='raw')
  970. amountptr[0] = rffi.cast(roci.ub4, databuf.size)
  971. try:
  972. # nothing to do if no data to write
  973. if databuf.size == 0:
  974. return 0
  975. status = roci.OCILobWrite(
  976. self.connection.handle,
  977. self.environment.errorHandle,
  978. self.getDataptr(pos)[0],
  979. amountptr, offset,
  980. databuf.ptr, databuf.size,
  981. roci.OCI_ONE_PIECE,
  982. None, None,
  983. config.CHARSETID, self.charsetForm)
  984. self.environment.checkForError(
  985. status,
  986. "LobVar_Write()")
  987. amount = amountptr[0]
  988. finally:
  989. lltype.free(amountptr, flavor='raw')
  990. databuf.clear()
  991. return amount
  992. def getValueProc(self, space, pos):
  993. return space.wrap(interp_lob.W_ExternalLob(self, pos))
  994. class VT_CLOB(W_LobVariable):
  995. oracleType = roci.SQLT_CLOB
  996. class VT_NCLOB(W_LobVariable):
  997. oracleType = roci.SQLT_CLOB
  998. class VT_BLOB(W_LobVariable):
  999. oracleType = roci.SQLT_BLOB
  1000. temporaryLobType = roci.OCI_TEMP_BLOB
  1001. class VT_BFILE(W_LobVariable):
  1002. oracleType = roci.SQLT_BFILE
  1003. def write(self, space, pos, w_value, offset):
  1004. raise OperationError(
  1005. space.w_TypeError,
  1006. space.wrap("BFILEs are read only"))
  1007. def read(self, space, pos, offset, amount):
  1008. self.openFile()
  1009. try:
  1010. return W_LobVariable.read(self, space, pos, offset, amount)
  1011. finally:
  1012. self.closeFile()
  1013. def openFile(self):
  1014. pass # XXX
  1015. def closeFile(self):
  1016. pass # XXX
  1017. class VT_Cursor(W_Variable):
  1018. oracleType = roci.SQLT_RSET
  1019. size = rffi.sizeof(roci.OCIStmt)
  1020. canBeInArray = False
  1021. def initialize(self, space, cursor):
  1022. from pypy.module.oracle import interp_cursor
  1023. self.connection = cursor.connection
  1024. self.cursors_w = [None] * self.allocatedElements
  1025. for i in range(self.allocatedElements):
  1026. tempCursor = interp_cursor.W_Cursor(space, self.connection)
  1027. tempCursor.allocateHandle()
  1028. self.cursors_w[i] = space.wrap(tempCursor)
  1029. dataptr = rffi.ptradd(
  1030. rffi.cast(roci.Ptr(roci.OCIStmt), self.data),
  1031. i)
  1032. dataptr[0] = tempCursor.handle
  1033. def getValueProc(self, space, pos):
  1034. from pypy.module.oracle import interp_cursor
  1035. w_cursor = self.cursors_w[pos]
  1036. space.interp_w(interp_cursor.W_Cursor, w_cursor).statementType = -1
  1037. return w_cursor
  1038. def setValueProc(self, space, pos, w_value):
  1039. from pypy.module.oracle import interp_cursor
  1040. w_CursorType = space.gettypeobject(interp_cursor.W_Cursor.typedef)
  1041. if not space.is_true(space.isinstance(w_value, w_CursorType)):
  1042. raise OperationError(
  1043. space.w_TypeError,
  1044. space.wrap("expecting cursor"))
  1045. self.cursors_w[pos] = w_value
  1046. cursor = space.interp_w(interp_cursor.W_Cursor, w_value)
  1047. if not cursor.isOwned:
  1048. cursor.freeHandle(space, raiseError=True)
  1049. cursor.isOwned = True
  1050. cursor.allocateHandle()
  1051. dataptr = rffi.ptradd(
  1052. rffi.cast(roci.Ptr(roci.OCIStmt), self.data),
  1053. pos)
  1054. dataptr[0] = cursor.handle
  1055. cursor.statementType = -1
  1056. class VT_Object(W_Variable):
  1057. oracleType = roci.SQLT_NTY
  1058. size = rffi.sizeof(roci.dvoidp)
  1059. canBeInArray = False
  1060. objectIndicator = lltype.nullptr(rffi.CArrayPtr(roci.dvoidp).TO)
  1061. def initialize(self, space, cursor):
  1062. self.connection = cursor.connection
  1063. self.objectType = None
  1064. self.objectIndicator = lltype.malloc(
  1065. rffi.CArrayPtr(roci.dvoidp).TO,
  1066. self.allocatedElements,
  1067. flavor='raw', zero=True)
  1068. def finalize(self):
  1069. for i in range(self.allocatedElements):
  1070. data = rffi.cast(roci.Ptr(roci.dvoidp), self.data)
  1071. roci.OCIObjectFree(
  1072. self.environment.handle,
  1073. self.environment.errorHandle,
  1074. data[i],
  1075. roci.OCI_OBJECTFREE_FORCE)
  1076. if self.objectIndicator:
  1077. lltype.free(self.objectIndicator, flavor='raw')
  1078. def postDefine(self, param):
  1079. # XXX this used to be in preDefine
  1080. self.objectType = interp_object.W_ObjectType(self.connection, param)
  1081. data = rffi.cast(roci.Ptr(roci.dvoidp), self.data)
  1082. status = roci.OCIDefineObject(
  1083. self.defineHandle,
  1084. self.environment.errorHandle,
  1085. self.objectType.tdo,
  1086. data,
  1087. 0,
  1088. self.objectIndicator,
  1089. 0)
  1090. self.environment.checkForError(
  1091. status,
  1092. "ObjectVar_PostDefine(): define object")
  1093. def isNull(self, pos):
  1094. # look at our own indicator array
  1095. if not self.objectIndicator[pos]:
  1096. return True
  1097. return (rffi.cast(lltype.Signed,
  1098. rffi.cast(roci.Ptr(roci.OCIInd),
  1099. self.objectIndicator[pos])[0])
  1100. ==
  1101. rffi.cast(lltype.Signed, roci.OCI_IND_NULL))
  1102. def getValueProc(self, space, pos):
  1103. data = rffi.cast(roci.Ptr(roci.dvoidp), self.data)
  1104. # only allowed to get the value once (for now)
  1105. if not data[pos]:
  1106. raise OperationError(
  1107. get(space).w_ProgrammingError,
  1108. space.wrap("variable value can only be acquired once"))
  1109. # for collections, return the list rather than the object
  1110. if self.objectType.isCollection:
  1111. return interp_object.convertCollection(
  1112. space, self.environment, data[pos], self, self.objectType)
  1113. # for objects, return a representation of the object
  1114. var = interp_object.W_ExternalObject(
  1115. self, self.objectType, data[pos], self.objectIndicator[pos])
  1116. data[pos] = lltype.nullptr(roci.dvoidp.TO)
  1117. self.objectIndicator[pos] = lltype.nullptr(roci.dvoidp.TO)
  1118. return space.wrap(var)
  1119. all_variable_types = []
  1120. for name, cls in globals().items():
  1121. if not name.startswith('VT_') or not isinstance(cls, type):
  1122. continue
  1123. def register_variable_class(cls):
  1124. def clone(self, cursor, numElements, size):
  1125. return cls(cursor, numElements, size)
  1126. cls.clone = clone
  1127. cls.typedef = TypeDef(
  1128. cls.__name__, W_Variable.typedef,
  1129. )
  1130. all_variable_types.append(cls)
  1131. register_variable_class(cls)
  1132. def typeByOracleDescriptor(param, environment):
  1133. # retrieve datatype of the parameter
  1134. attrptr = lltype.malloc(rffi.CArrayPtr(roci.ub2).TO, 1, flavor='raw')
  1135. try:
  1136. status = roci.OCIAttrGet(
  1137. param, roci.OCI_HTYPE_DESCRIBE,
  1138. rffi.cast(roci.dvoidp, attrptr),
  1139. lltype.nullptr(roci.Ptr(roci.ub4).TO),
  1140. roci.OCI_ATTR_DATA_TYPE,
  1141. environment.errorHandle)
  1142. environment.checkForError(
  1143. status,
  1144. "Variable_TypeByOracleDescriptor(): data type")
  1145. dataType = rffi.cast(lltype.Signed, attrptr[0])
  1146. finally:
  1147. lltype.free(attrptr, flavor='raw')
  1148. # retrieve character set form of the parameter
  1149. if dataType not in (roci.SQLT_CHR, roci.SQLT_AFC,

Large files files are truncated, but you can click here to view the full file