[pypy-svn] r69636 - in pypy/trunk/pypy/module/oracle: . test
afa at codespeak.net
afa at codespeak.net
Wed Nov 25 16:03:54 CET 2009
Author: afa
Date: Wed Nov 25 16:03:53 2009
New Revision: 69636
Added:
pypy/trunk/pypy/module/oracle/interp_object.py
pypy/trunk/pypy/module/oracle/test/test_objectvar.py
Modified:
pypy/trunk/pypy/module/oracle/interp_variable.py
pypy/trunk/pypy/module/oracle/roci.py
Log:
Start to implment the OBJECT datatype.
The Oracle API is really a complex beast.
Added: pypy/trunk/pypy/module/oracle/interp_object.py
==============================================================================
--- (empty file)
+++ pypy/trunk/pypy/module/oracle/interp_object.py Wed Nov 25 16:03:53 2009
@@ -0,0 +1,115 @@
+from pypy.interpreter.baseobjspace import Wrappable
+from pypy.interpreter.typedef import TypeDef, interp_attrproperty
+from pypy.rpython.lltypesystem import rffi, lltype
+from pypy.module.oracle import roci
+
+class W_ObjectType(Wrappable):
+ def __init__(self, connection, param):
+ self.environment = connection.environment
+ self.isCollection = False
+ self.initialize(connection, param)
+
+ def initialize(self, connection, param):
+ nameptr = lltype.malloc(rffi.CArrayPtr(roci.oratext).TO, 1,
+ flavor='raw')
+ lenptr = lltype.malloc(rffi.CArrayPtr(roci.ub4).TO, 1,
+ flavor='raw')
+ try:
+ # determine the schema of the type
+ status = roci.OCIAttrGet(
+ param, roci.OCI_HTYPE_DESCRIBE,
+ rffi.cast(roci.dvoidp, nameptr),
+ lenptr,
+ roci.OCI_ATTR_SCHEMA_NAME,
+ self.environment.errorHandle)
+ self.environment.checkForError(
+ status,
+ "ObjectType_Initialize(): get schema name")
+ self.schema = rffi.charpsize2str(nameptr[0], lenptr[0])
+
+ # determine the name of the type
+ status = roci.OCIAttrGet(
+ param, roci.OCI_HTYPE_DESCRIBE,
+ rffi.cast(roci.dvoidp, nameptr),
+ lenptr,
+ roci.OCI_ATTR_TYPE_NAME,
+ self.environment.errorHandle)
+ self.environment.checkForError(
+ status,
+ "ObjectType_Initialize(): get schema name")
+ self.name = rffi.charpsize2str(nameptr[0], lenptr[0])
+ finally:
+ lltype.free(nameptr, flavor='raw')
+ lltype.free(lenptr, flavor='raw')
+
+ # retrieve TDO (type descriptor object) of the parameter
+ tdorefptr = lltype.malloc(rffi.CArrayPtr(roci.OCIRef).TO, 1,
+ flavor='raw')
+ try:
+ status = roci.OCIAttrGet(
+ param, roci.OCI_HTYPE_DESCRIBE,
+ rffi.cast(roci.dvoidp, tdorefptr),
+ lltype.nullptr(roci.Ptr(roci.ub4).TO),
+ roci.OCI_ATTR_REF_TDO,
+ self.environment.errorHandle)
+ self.environment.checkForError(
+ status,
+ "ObjectType_Initialize(): get TDO reference")
+ tdoref = tdorefptr[0]
+ finally:
+ lltype.free(tdorefptr, flavor='raw')
+
+ tdoptr = lltype.malloc(rffi.CArrayPtr(roci.dvoidp).TO, 1,
+ flavor='raw')
+ try:
+ status = roci.OCIObjectPin(
+ self.environment.handle,
+ self.environment.errorHandle,
+ tdoref,
+ None, roci.OCI_PIN_ANY,
+ roci.OCI_DURATION_SESSION, roci.OCI_LOCK_NONE,
+ tdoptr)
+ self.environment.checkForError(
+ status,
+ "ObjectType_Initialize(): pin TDO reference")
+ self.tdo = tdoptr[0]
+ finally:
+ lltype.free(tdoptr, flavor='raw')
+
+ # acquire a describe handle
+ handleptr = lltype.malloc(rffi.CArrayPtr(roci.OCIDescribe).TO,
+ 1, flavor='raw')
+ try:
+ status = roci.OCIHandleAlloc(
+ self.environment.handle,
+ handleptr, roci.OCI_HTYPE_DESCRIBE, 0,
+ lltype.nullptr(rffi.CArray(roci.dvoidp)))
+ self.environment.checkForError(
+ status, "ObjectType_Initialize(): allocate describe handle")
+ describeHandle = handleptr[0]
+ finally:
+ lltype.free(handleptr, flavor='raw')
+
+ # describe the type
+ try:
+ pass
+ #self.describe(connection, describeHandle)
+ finally:
+ roci.OCIHandleFree(describeHandle, roci.OCI_HTYPE_DESCRIBE)
+W_ObjectType.typedef = TypeDef(
+ 'ObjectType',
+ schema = interp_attrproperty('schema', W_ObjectType),
+ name = interp_attrproperty('name', W_ObjectType),
+ )
+
+class W_ExternalObject(Wrappable):
+ def __init__(self, ref, type, instance, indicator, isIndependent=True):
+ self.ref = ref
+ self.type = type
+ self.instance = instance
+ self.indicator = indicator
+ self.isIndependent = isIndependent
+W_ExternalObject.typedef = TypeDef(
+ 'ExternalObject',
+ type = interp_attrproperty('type', W_ExternalObject),
+ )
Modified: pypy/trunk/pypy/module/oracle/interp_variable.py
==============================================================================
--- pypy/trunk/pypy/module/oracle/interp_variable.py (original)
+++ pypy/trunk/pypy/module/oracle/interp_variable.py Wed Nov 25 16:03:53 2009
@@ -8,7 +8,8 @@
from pypy.rlib.rarithmetic import ovfcheck
import sys
-from pypy.module.oracle import roci, config, transform, interp_lob
+from pypy.module.oracle import roci, config, transform
+from pypy.module.oracle import interp_lob, interp_object
from pypy.module.oracle.interp_error import W_Error, get
from pypy.module.oracle.config import string_w, StringBuffer
@@ -111,7 +112,7 @@
lltype.free(handleptr, flavor='raw')
# call the procedure to set values after define
- var.postDefine()
+ var.postDefine(param)
return var
@@ -233,7 +234,7 @@
def preDefine(cls, param, environment):
return cls
- def postDefine(self):
+ def postDefine(self, param):
pass
def bind(self, space, cursor, w_name, pos):
@@ -1126,8 +1127,79 @@
class VT_Object(W_Variable):
+ oracleType = roci.SQLT_NTY
+ size = rffi.sizeof(roci.dvoidp)
canBeInArray = False
+ objectIndicator = None
+
+ def initialize(self, space, cursor):
+ self.connection = cursor.connection
+ self.objectType = None
+ self.objectIndicator = lltype.malloc(
+ rffi.CArrayPtr(roci.dvoidp).TO,
+ self.allocatedElements,
+ flavor='raw', zero=True)
+
+ def finalize(self):
+ for i in range(self.allocatedElements):
+ data = rffi.cast(roci.Ptr(roci.dvoidp), self.data)
+ roci.OCIObjectFree(
+ self.environment.handle,
+ self.environment.errorHandle,
+ data[i],
+ roci.OCI_OBJECTFREE_FORCE)
+ if self.objectIndicator:
+ lltype.free(self.objectIndicator, flavor='raw')
+
+ def postDefine(self, param):
+ # XXX this used to be in preDefine
+ self.objectType = interp_object.W_ObjectType(self.connection, param)
+
+ data = rffi.cast(roci.Ptr(roci.dvoidp), self.data)
+
+ status = roci.OCIDefineObject(
+ self.defineHandle,
+ self.environment.errorHandle,
+ self.objectType.tdo,
+ data,
+ 0,
+ self.objectIndicator,
+ 0)
+ self.environment.checkForError(
+ status,
+ "ObjectVar_PostDefine(): define object")
+
+ def isNull(self, pos):
+ # look at our own indicator array
+ if not self.objectIndicator[pos]:
+ return True
+ return (rffi.cast(roci.Ptr(roci.OCIInd), self.objectIndicator[pos])[0]
+ ==
+ rffi.cast(lltype.Signed, roci.OCI_IND_NULL))
+
+ def getValueProc(self, space, pos):
+ data = rffi.cast(roci.Ptr(roci.dvoidp), self.data)
+ # only allowed to get the value once (for now)
+ if not data[pos]:
+ raise OperationError(
+ get(space).w_ProgrammingError,
+ space.wrap("variable value can only be acquired once"))
+
+
+ # for collections, return the list rather than the object
+ if self.objectType.isCollection:
+ return interp_object.convertCollection(
+ self.environment, data[pos], self, self.objectType)
+
+ # for objects, return a representation of the object
+ var = interp_object.W_ExternalObject(
+ self, self.objectType, data[pos], self.objectIndicator[pos])
+
+ data[pos] = lltype.nullptr(roci.dvoidp.TO)
+ self.objectIndicator[pos] = lltype.nullptr(roci.dvoidp.TO)
+ return space.wrap(var)
+
all_variable_types = []
for name, cls in globals().items():
if not name.startswith('VT_') or not isinstance(cls, type):
Modified: pypy/trunk/pypy/module/oracle/roci.py
==============================================================================
--- pypy/trunk/pypy/module/oracle/roci.py (original)
+++ pypy/trunk/pypy/module/oracle/roci.py Wed Nov 25 16:03:53 2009
@@ -33,6 +33,9 @@
uword = platform.SimpleType('uword', rffi.UINT)
boolean = platform.SimpleType('boolean', rffi.UINT)
OCIDuration = platform.SimpleType('OCIDuration', rffi.UINT)
+ OCIInd = platform.SimpleType('OCIInd', rffi.INT)
+ OCIPinOpt = platform.SimpleType('OCIPinOpt', rffi.INT)
+ OCILockOpt = platform.SimpleType('OCILockOpt', rffi.INT)
OCINumber = platform.Struct('OCINumber', [])
OCITime = platform.Struct('OCITime',
@@ -57,12 +60,14 @@
OCI_ATTR_SERVER OCI_ATTR_SESSION OCI_ATTR_USERNAME OCI_ATTR_PASSWORD
OCI_ATTR_STMT_TYPE OCI_ATTR_PARAM_COUNT OCI_ATTR_ROW_COUNT
OCI_ATTR_NAME OCI_ATTR_SCALE OCI_ATTR_PRECISION OCI_ATTR_IS_NULL
- OCI_ATTR_DATA_SIZE OCI_ATTR_DATA_TYPE OCI_ATTR_CHARSET_FORM
- OCI_ATTR_ENV_CHARSET_ID
+ OCI_ATTR_DATA_SIZE OCI_ATTR_DATA_TYPE OCI_ATTR_REF_TDO
+ OCI_ATTR_SCHEMA_NAME OCI_ATTR_TYPE_NAME
+ OCI_ATTR_CHARSET_FORM OCI_ATTR_ENV_CHARSET_ID
OCI_ATTR_PARSE_ERROR_OFFSET
OCI_NTV_SYNTAX OCI_COMMIT_ON_SUCCESS
OCI_FETCH_NEXT
OCI_IND_NULL OCI_IND_NOTNULL
+ OCI_PIN_ANY OCI_LOCK_NONE
OCI_STMT_SELECT OCI_STMT_CREATE OCI_STMT_DROP OCI_STMT_ALTER
OCI_STMT_INSERT OCI_STMT_DELETE OCI_STMT_UPDATE
SQLT_CHR SQLT_LNG SQLT_AFC SQLT_RDD SQLT_BIN SQLT_LBI SQLT_LVC SQLT_LVB
@@ -84,6 +89,7 @@
OCI_IND_NOTNULL = rffi.cast(rffi.SHORT, OCI_IND_NOTNULL)
OCI_IND_NULL = rffi.cast(rffi.SHORT, OCI_IND_NULL)
+# Various pointers to incomplete structures
OCISvcCtx = rffi.VOIDP
OCIEnv = rffi.VOIDP
OCIError = rffi.VOIDP
@@ -93,10 +99,14 @@
OCIParam = rffi.VOIDP
OCIBind = rffi.VOIDP
OCIDefine = rffi.VOIDP
+OCIDescribe = rffi.VOIDP
OCISnapshot = rffi.VOIDP
OCIDateTime = rffi.VOIDP
OCIInterval = rffi.VOIDP
OCILobLocator = rffi.VOIDP
+OCIRef = rffi.VOIDP
+OCIType = rffi.VOIDP
+OCIComplexObject = rffi.VOIDP
Ptr = rffi.CArrayPtr
void = lltype.Void
@@ -262,6 +272,17 @@
ub4], # mode
sword)
+OCIDefineObject = external(
+ 'OCIDefineObject',
+ [OCIDefine, # defnp
+ OCIError, # errhp
+ OCIType, # type
+ dvoidpp, # pgvpp
+ ub4, # pvszsp
+ dvoidpp, # indpp
+ ub4], # indszp
+ sword)
+
OCIStmtGetBindInfo = external(
'OCIStmtGetBindInfo',
[OCIStmt, # stmtp
@@ -422,6 +443,20 @@
ub4], # type
sword)
+# OCI Object Pin, Unpin, and Free Functions
+
+OCIObjectPin = external(
+ 'OCIObjectPin',
+ [OCIEnv, # env,
+ OCIError, # err
+ OCIRef, # object_ref
+ OCIComplexObject, # corhdl
+ OCIPinOpt, # pin_option
+ OCIDuration, # pin_duration
+ OCILockOpt, # lock_option
+ dvoidpp], # object
+ sword)
+
# OCI Date, Datetime, and Interval Functions
OCIDateTimeCheck = external(
Added: pypy/trunk/pypy/module/oracle/test/test_objectvar.py
==============================================================================
--- (empty file)
+++ pypy/trunk/pypy/module/oracle/test/test_objectvar.py Wed Nov 25 16:03:53 2009
@@ -0,0 +1,34 @@
+from pypy.module.oracle.test.test_connect import OracleTestBase
+
+class AppTestObjectVar(OracleTestBase):
+ def test_fetch(self):
+ cur = self.cnx.cursor()
+ try:
+ cur.execute("drop table pypy_test_objtable")
+ except oracle.DatabaseError:
+ pass
+ try:
+ cur.execute("drop type pypy_test_objtype")
+ except oracle.DatabaseError:
+ pass
+ cur.execute("""\
+ create type pypy_test_objtype as object (
+ numbercol number,
+ stringcol varchar2(60),
+ datecol date);
+ """)
+ cur.execute("""\
+ create table pypy_test_objtable (
+ objcol pypy_test_objtype)
+ """)
+ cur.execute("""\
+ insert into pypy_test_objtable values (
+ pypy_test_objtype(1, 'someText',
+ to_date(20070306, 'YYYYMMDD')))
+ """)
+
+ cur.execute("select objcol from pypy_test_objtable")
+ objValue, = cur.fetchone()
+ assert objValue.type.schema == self.cnx.username.upper()
+ assert objValue.type.name == "PYPY_TEST_OBJTYPE"
+ #assert objValue.type.attributes[0].name == "NUMBERVALUE"
More information about the Pypy-commit
mailing list