[pypy-svn] r69637 - in pypy/trunk/pypy/module/oracle: . test

afa at codespeak.net afa at codespeak.net
Wed Nov 25 17:12:35 CET 2009


Author: afa
Date: Wed Nov 25 17:12:33 2009
New Revision: 69637

Modified:
   pypy/trunk/pypy/module/oracle/interp_object.py
   pypy/trunk/pypy/module/oracle/roci.py
   pypy/trunk/pypy/module/oracle/test/test_objectvar.py
Log:
Add ability to describe OBJECT types.
(Still incomplete)


Modified: pypy/trunk/pypy/module/oracle/interp_object.py
==============================================================================
--- pypy/trunk/pypy/module/oracle/interp_object.py	(original)
+++ pypy/trunk/pypy/module/oracle/interp_object.py	Wed Nov 25 17:12:33 2009
@@ -1,5 +1,6 @@
 from pypy.interpreter.baseobjspace import Wrappable
-from pypy.interpreter.typedef import TypeDef, interp_attrproperty
+from pypy.interpreter.typedef import TypeDef, GetSetProperty
+from pypy.interpreter.typedef import interp_attrproperty
 from pypy.rpython.lltypesystem import rffi, lltype
 from pypy.module.oracle import roci
 
@@ -92,14 +93,188 @@
 
         # describe the type
         try:
-            pass
-            #self.describe(connection, describeHandle)
+            self.describe(connection, describeHandle)
         finally:
             roci.OCIHandleFree(describeHandle, roci.OCI_HTYPE_DESCRIBE)
+
+    def describe(self, connection, describeHandle):
+        "Describe the type and store information about it as needed"
+
+        # describe the type
+        status = roci.OCIDescribeAny(
+            connection.handle,
+            self.environment.errorHandle,
+            self.tdo, 0,
+            roci.OCI_OTYPE_PTR,
+            roci.OCI_DEFAULT,
+            roci.OCI_PTYPE_TYPE,
+            describeHandle)
+        self.environment.checkForError(
+            status, "ObjectType_Describe(): describe type")
+
+        # get top level parameter descriptor
+        paramptr = lltype.malloc(roci.Ptr(roci.OCIParam).TO,
+                                 1, flavor='raw')
+        try:
+            status = roci.OCIAttrGet(
+                describeHandle, roci.OCI_HTYPE_DESCRIBE,
+                rffi.cast(roci.dvoidp, paramptr),
+                lltype.nullptr(roci.Ptr(roci.ub4).TO),
+                roci.OCI_ATTR_PARAM,
+                self.environment.errorHandle)
+            self.environment.checkForError(
+                status,
+                "ObjectType_Describe(): get top level parameter descriptor")
+            toplevelParam = paramptr[0]
+        finally:
+            lltype.free(paramptr, flavor='raw')
+
+        # determine type of type
+        typecodeptr = lltype.malloc(roci.Ptr(roci.OCITypeCode).TO,
+                                    1, flavor='raw')
+        try:
+            status = roci.OCIAttrGet(
+                toplevelParam, roci.OCI_DTYPE_PARAM,
+                rffi.cast(roci.dvoidp, typecodeptr),
+                lltype.nullptr(roci.Ptr(roci.ub4).TO),
+                roci.OCI_ATTR_TYPECODE,
+                self.environment.errorHandle)
+            self.environment.checkForError(
+                status, "ObjectType_Describe(): get type code")
+            typeCode = typecodeptr[0]
+        finally:
+            lltype.free(typecodeptr, flavor='raw')
+
+        # if a collection, need to determine the sub type
+        if typeCode == roci.OCI_TYPECODE_NAMEDCOLLECTION:
+            self.isCollection = 1
+
+            # determine type of collection
+            XXX
+
+            # acquire collection parameter descriptor
+            XXX
+
+            # determine type of element
+            XXX
+
+            # if element type is an object type get its type
+            XXX
+
+        # determine the number of attributes
+        numptr = lltype.malloc(roci.Ptr(roci.ub2).TO,
+                               1, flavor='raw')
+        try:
+            status = roci.OCIAttrGet(
+                toplevelParam, roci.OCI_DTYPE_PARAM,
+                rffi.cast(roci.dvoidp, numptr),
+                lltype.nullptr(roci.Ptr(roci.ub4).TO),
+                roci.OCI_ATTR_NUM_TYPE_ATTRS,
+                self.environment.errorHandle)
+            self.environment.checkForError(
+                status, "ObjectType_Describe(): get number of attributes")
+            numAttributes = numptr[0]
+        finally:
+            lltype.free(numptr, flavor='raw')
+
+        # allocate the attribute list and dictionary
+        self.attributes = []
+        self.attributesByName = {}
+
+        # acquire the list parameter descriptor
+        listptr = lltype.malloc(roci.Ptr(roci.OCIParam).TO,
+                               1, flavor='raw')
+        try:
+            status = roci.OCIAttrGet(
+                toplevelParam, roci.OCI_DTYPE_PARAM,
+                rffi.cast(roci.dvoidp, listptr),
+                lltype.nullptr(roci.Ptr(roci.ub4).TO),
+                roci.OCI_ATTR_LIST_TYPE_ATTRS,
+                self.environment.errorHandle)
+            self.environment.checkForError(
+                status, "ObjectType_Describe(): get list parameter descriptor")
+            attributeListParam = listptr[0]
+        finally:
+            lltype.free(listptr, flavor='raw')
+
+        # create attribute information for each attribute
+        for i in range(numAttributes):
+            paramptr = lltype.malloc(roci.Ptr(roci.OCIParam).TO,
+                                    1, flavor='raw')
+            try:
+                status = roci.OCIParamGet(
+                    attributeListParam, roci.OCI_DTYPE_PARAM,
+                    self.environment.errorHandle,
+                    paramptr, i + 1)
+                self.environment.checkForError(
+                    status,
+                    "ObjectType_Describe(): get attribute param descriptor")
+                attribute = W_ObjectAttribute(connection, paramptr[0])
+            finally:
+                lltype.free(paramptr, flavor='raw')
+
+            self.attributes.append(attribute)
+            self.attributesByName[attribute.name] = attribute
+
+    def get_attributes(space, self):
+        return space.newlist([space.wrap(attr) for attr in self.attributes])
+
 W_ObjectType.typedef = TypeDef(
     'ObjectType',
     schema = interp_attrproperty('schema', W_ObjectType),
     name = interp_attrproperty('name', W_ObjectType),
+    attributes = GetSetProperty(W_ObjectType.get_attributes),
+    )
+
+class W_ObjectAttribute(Wrappable):
+    def __init__(self, connection, param):
+        self.initialize(connection, param)
+
+    def initialize(self, connection, param):
+        # determine the name of the attribute
+        nameptr = lltype.malloc(rffi.CArrayPtr(roci.oratext).TO, 1,
+                                flavor='raw')
+        lenptr = lltype.malloc(rffi.CArrayPtr(roci.ub4).TO, 1,
+                               flavor='raw')
+        try:
+            status = roci.OCIAttrGet(
+                param, roci.OCI_DTYPE_PARAM,
+                rffi.cast(roci.dvoidp, nameptr),
+                lenptr,
+                roci.OCI_ATTR_NAME,
+                connection.environment.errorHandle)
+            connection.environment.checkForError(
+                status,
+                "ObjectAttribute_Initialize(): get name")
+            self.name = rffi.charpsize2str(nameptr[0], lenptr[0])
+        finally:
+            lltype.free(nameptr, flavor='raw')
+            lltype.free(lenptr, flavor='raw')
+
+        # determine the type of the attribute
+        typecodeptr = lltype.malloc(roci.Ptr(roci.OCITypeCode).TO,
+                                    1, flavor='raw')
+        try:
+            status = roci.OCIAttrGet(
+                param, roci.OCI_DTYPE_PARAM,
+                rffi.cast(roci.dvoidp, typecodeptr),
+                lltype.nullptr(roci.Ptr(roci.ub4).TO),
+                roci.OCI_ATTR_TYPECODE,
+                connection.environment.errorHandle)
+            connection.environment.checkForError(
+                status, "ObjectType_Describe(): get type code")
+            self.typeCode = typecodeptr[0]
+        finally:
+            lltype.free(typecodeptr, flavor='raw')
+
+        # if the type of the attribute is object, recurse
+        if self.typeCode in (roci.OCI_TYPECODE_NAMEDCOLLECTION,
+                             roci.OCI_TYPECODE_OBJECT):
+            self.subType = W_ObjectType(connection, param)
+
+W_ObjectAttribute.typedef = TypeDef(
+    'ObjectAttribute',
+    name = interp_attrproperty('name', W_ObjectAttribute),
     )
 
 class W_ExternalObject(Wrappable):

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 17:12:33 2009
@@ -36,6 +36,7 @@
     OCIInd = platform.SimpleType('OCIInd', rffi.INT)
     OCIPinOpt = platform.SimpleType('OCIPinOpt', rffi.INT)
     OCILockOpt = platform.SimpleType('OCILockOpt', rffi.INT)
+    OCITypeCode = platform.SimpleType('OCITypeCode', rffi.UINT)
 
     OCINumber = platform.Struct('OCINumber', [])
     OCITime   = platform.Struct('OCITime',
@@ -58,16 +59,18 @@
     OCI_DTYPE_PARAM OCI_DTYPE_TIMESTAMP OCI_DTYPE_INTERVAL_DS OCI_DTYPE_LOB
     OCI_CRED_RDBMS OCI_CRED_EXT OCI_SPOOL_ATTRVAL_NOWAIT
     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_STMT_TYPE OCI_ATTR_PARAM 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_REF_TDO
-    OCI_ATTR_SCHEMA_NAME OCI_ATTR_TYPE_NAME
+    OCI_ATTR_SCHEMA_NAME OCI_ATTR_TYPE_NAME OCI_ATTR_TYPECODE
+    OCI_ATTR_NUM_TYPE_ATTRS OCI_ATTR_LIST_TYPE_ATTRS
     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_OTYPE_PTR OCI_PTYPE_TYPE
     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
@@ -78,6 +81,7 @@
     SQLCS_IMPLICIT SQLCS_NCHAR
     OCI_TEMP_CLOB OCI_TEMP_BLOB OCI_DURATION_SESSION OCI_ONE_PIECE
     OCI_NUMBER_SIGNED
+    OCI_TYPECODE_NAMEDCOLLECTION OCI_TYPECODE_OBJECT
     OCI_NLS_MAXBUFSZ OCI_NLS_CS_ORA_TO_IANA
     '''.split()
 
@@ -283,6 +287,18 @@
      ub4],           # indszp
     sword)
 
+OCIDescribeAny = external(
+    'OCIDescribeAny',
+    [OCISvcCtx,      # svchp
+     OCIError,       # errhp
+     dvoidp,         # objptr
+     ub4,            # objptr_len
+     ub1,            # objptr_typ
+     ub1,            # info_level
+     ub1,            # objtyp
+     OCIDescribe],   # dschp
+    sword)
+
 OCIStmtGetBindInfo = external(
     'OCIStmtGetBindInfo',
     [OCIStmt,        # stmtp

Modified: pypy/trunk/pypy/module/oracle/test/test_objectvar.py
==============================================================================
--- pypy/trunk/pypy/module/oracle/test/test_objectvar.py	(original)
+++ pypy/trunk/pypy/module/oracle/test/test_objectvar.py	Wed Nov 25 17:12:33 2009
@@ -31,4 +31,4 @@
         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"
+        assert objValue.type.attributes[0].name == "NUMBERCOL"



More information about the Pypy-commit mailing list