C:/Users/vincent/Data/Perso/dev/ocilib/ocilib/src/typeinfo.c

00001 /*
00002    +----------------------------------------------------------------------+   
00003    |                                                                      |
00004    |                     OCILIB - C Driver for Oracle                     |
00005    |                                                                      |
00006    |                      (C Wrapper for Oracle OCI)                      |
00007    |                                                                      |
00008    +----------------------------------------------------------------------+
00009    |                      Website : http://www.ocilib.net                 |
00010    +----------------------------------------------------------------------+
00011    |               Copyright (c) 2007-2009 Vincent ROGIER                 |
00012    +----------------------------------------------------------------------+
00013    | This library is free software; you can redistribute it and/or        |
00014    | modify it under the terms of the GNU Lesser General Public           |
00015    | License as published by the Free Software Foundation; either         |
00016    | version 2 of the License, or (at your option) any later version.     |
00017    |                                                                      |
00018    | This library is distributed in the hope that it will be useful,      |
00019    | but WITHOUT ANY WARRANTY; without even the implied warranty of       |
00020    | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU    |
00021    | Lesser General Public License for more details.                      |
00022    |                                                                      |
00023    | You should have received a copy of the GNU Lesser General Public     |
00024    | License along with this library; if not, write to the Free           |
00025    | Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.   |
00026    +----------------------------------------------------------------------+
00027    |          Author: Vincent ROGIER <vince.rogier@gmail.com>             |
00028    +----------------------------------------------------------------------+ 
00029 */
00030 
00031 /* ------------------------------------------------------------------------ *
00032  * $Id: typeinfo.c, v 3.4.0 2009-07-30 17:40 Vince $
00033  * ------------------------------------------------------------------------ */
00034 
00035 #include "ocilib_internal.h"
00036 
00037 /* ************************************************************************ *
00038  *                             PRIVATE FUNCTIONS
00039  * ************************************************************************ */
00040 
00041 /* ------------------------------------------------------------------------ *
00042  * OCI_TypeInfoClose
00043  * ------------------------------------------------------------------------ */
00044 
00045 boolean OCI_TypeInfoClose(OCI_TypeInfo *typinf)
00046 {
00047     ub2 i;
00048 
00049     OCI_CHECK(typinf == NULL, FALSE);
00050 
00051     for (i=0; i < typinf->nb_cols; i++)
00052     {
00053         OCI_FREE(typinf->cols[i].name);
00054     }
00055 
00056     OCI_FREE(typinf->cols);
00057     OCI_FREE(typinf->name);
00058     OCI_FREE(typinf->schema);
00059 
00060     return TRUE;
00061 }
00062 
00063 /* ************************************************************************ *
00064  *                            PUBLIC FUNCTIONS
00065  * ************************************************************************ */
00066 
00067 /* ------------------------------------------------------------------------ *
00068  * OCI_TypeInfoGet
00069  * ------------------------------------------------------------------------ */
00070 
00071 OCI_TypeInfo * OCI_API OCI_TypeInfoGet(OCI_Connection *con, const mtext *name, 
00072                                        unsigned int type)
00073 {
00074     OCI_TypeInfo *typinf = NULL;
00075     OCI_Item     *item   = NULL;
00076     OCIDescribe *dschp   = NULL;
00077     OCIParam *parmh1     = NULL;
00078     OCIParam *parmh2     = NULL;
00079     mtext *str           = NULL;
00080     int etype            = OCI_DESC_COLUMN;
00081     int ptype            = 0;
00082     ub1 item_type        = 0;
00083     ub4 attr_type        = 0;
00084     ub4 num_type         = 0;
00085     boolean res          = TRUE;
00086     boolean found        = FALSE;
00087     ub2 i;
00088     
00089     mtext obj_schema[OCI_SIZE_OBJ_NAME+1];
00090     mtext obj_name[OCI_SIZE_OBJ_NAME+1];
00091 
00092     OCI_CHECK_INITIALIZED(NULL);
00093 
00094     OCI_CHECK_PTR(OCI_IPC_CONNECTION, con, NULL);
00095     OCI_CHECK_PTR(OCI_IPC_STRING, name, NULL);
00096 
00097     if (type == OCI_TIF_TABLE)
00098         item_type = OCI_PTYPE_TABLE;
00099     else if (type == OCI_TIF_VIEW)
00100         item_type = OCI_PTYPE_VIEW;
00101     else if (type == OCI_TIF_TYPE)
00102         item_type = OCI_PTYPE_TYPE;
00103     else
00104         return NULL;
00105 
00106     obj_schema[0] = 0;
00107     obj_name[0] = 0;
00108 
00109     /* is the schema provided in the object name ? */
00110 
00111     for (str = (mtext *) name; *str != 0; str++)
00112     {
00113         if (*str == MT('.'))
00114         {
00115             mtsncat(obj_schema, name, str-name);
00116             mtsncat(obj_name, ++str, OCI_SIZE_OBJ_NAME);
00117             break;
00118         }
00119     }
00120 
00121     /* if the schema is not provided, we just copy the object name */
00122 
00123     if (obj_name[0] == 0)
00124     {
00125         mtsncat(obj_name, name, OCI_SIZE_OBJ_NAME);
00126     }
00127 
00128     /* type name must be uppercase */
00129 
00130     for (str = obj_name; *str != 0; str++)
00131         *str = (mtext) mttoupper(*str);
00132 
00133     /* schema name must be uppercase */
00134 
00135     for (str = obj_schema; *str != 0; str++)
00136         *str = (mtext) mttoupper(*str);
00137 
00138     /* first try to find it in list */
00139 
00140     item = con->tinfs->head;
00141 
00142     /* walk along the list to find the type */
00143 
00144     while (item != NULL)
00145     {
00146         typinf = (OCI_TypeInfo *) item->data;
00147      
00148         if ((typinf != NULL) && (typinf->type == type))
00149         {
00150             if ((mtscasecmp(typinf->name,   obj_name  ) == 0) &&
00151                 (mtscasecmp(typinf->schema, obj_schema) == 0))
00152             {
00153                 found = TRUE;
00154                 break;
00155             }
00156         }
00157 
00158         item = item->next;
00159     } 
00160 
00161     /* Not found, so create type object */
00162 
00163     if (found == FALSE)
00164     {
00165         item = OCI_ListAppend(con->tinfs, sizeof(OCI_TypeInfo));
00166 
00167         res = (item != NULL);
00168 
00169         if (res == TRUE)
00170         {
00171             typinf = (OCI_TypeInfo *) item->data;
00172 
00173             typinf->type   = type;
00174             typinf->con    = con;
00175             typinf->name   = mtsdup(obj_name);
00176             typinf->schema = mtsdup(obj_schema);
00177 
00178             res = (OCI_SUCCESS == OCI_HandleAlloc(OCILib.env,
00179                                                   (dvoid **) (void *) &dschp, 
00180                                                   OCI_HTYPE_DESCRIBE, 0, 
00181                                                   (dvoid **) NULL));
00182         }
00183 
00184         if (res == TRUE)
00185         {
00186             if (type == OCI_TIF_TYPE)
00187             {            
00188                 void *ostr1 = NULL;
00189                 void *ostr2 = NULL;
00190                 int osize1  = -1;
00191                 int osize2  = -1;
00192                
00193                 attr_type = OCI_ATTR_LIST_TYPE_ATTRS;
00194                 num_type  = OCI_ATTR_NUM_TYPE_ATTRS;
00195                 ptype     = OCI_DESC_TYPE;
00196 
00197                 ostr1 = OCI_GetInputMetaString(typinf->schema, &osize1);
00198                 ostr2 = OCI_GetInputMetaString(typinf->name,   &osize2);
00199 
00200                 OCI_CALL2
00201                 (
00202                     res, con, 
00203                     
00204                     OCITypeByName(OCILib.env, con->err, con->cxt,
00205                                  (text *) ostr1, (ub4) osize1, 
00206                                  (text *) ostr2, (ub4) osize2, 
00207                                  (text *) NULL, (ub4) 0, 
00208                                  OCI_DURATION_SESSION, OCI_TYPEGET_ALL,
00209                                  &typinf->tdo)
00210                 )
00211 
00212                 OCI_CALL2
00213                 (
00214                     res, con, 
00215                     
00216                     OCIDescribeAny(con->cxt, con->err, (void *) typinf->tdo,
00217                                    0, OCI_OTYPE_PTR, OCI_DEFAULT, 
00218                                    OCI_PTYPE_TYPE, dschp)
00219                 )
00220                 
00221                 OCI_ReleaseMetaString(ostr1);
00222                 OCI_ReleaseMetaString(ostr2);
00223             }
00224             else
00225             {
00226                 mtext buffer[(OCI_SIZE_OBJ_NAME*2) + 2];
00227                 
00228                 size_t size = sizeof(buffer)/sizeof(mtext);
00229                 void *ostr1 = NULL;
00230                 int osize1  = -1;
00231 
00232                 attr_type = OCI_ATTR_LIST_COLUMNS;
00233                 num_type  = OCI_ATTR_NUM_COLS;
00234                 ptype     = OCI_DESC_TABLE;
00235                 str       = buffer;
00236 
00237                 str[0] = 0;                
00238 
00239                 if ((typinf->schema != NULL) && (typinf->schema[0] != 0))
00240                 {
00241                     str = mtsncat(buffer, typinf->schema, size);
00242                     size -= mtslen(typinf->schema);
00243                     str = mtsncat(str, MT("."), size);
00244                     size -= 1;
00245                 }
00246 
00247                 mtsncat(str, typinf->name, size);
00248 
00249                 ostr1 = OCI_GetInputMetaString(str, &osize1);
00250 
00251                 OCI_CALL2
00252                 (
00253                     res, con, 
00254                     
00255                     OCIDescribeAny(con->cxt, con->err, (dvoid *) ostr1, 
00256                                    (ub4) osize1, OCI_OTYPE_NAME, 
00257                                    OCI_DEFAULT, item_type, dschp)
00258                 )
00259 
00260                 OCI_ReleaseMetaString(ostr1);
00261             }
00262                   
00263             OCI_CALL2
00264             (
00265                 res, con, 
00266                 
00267                 OCIAttrGet(dschp, OCI_HTYPE_DESCRIBE, &parmh1, 
00268                            NULL, OCI_ATTR_PARAM, con->err)
00269             )
00270 
00271             /* do we need get more attributes for collections ? */
00272 
00273             if (type == OCI_TIF_TYPE)
00274             {
00275                 OCI_CALL2
00276                 (
00277                     res, con, 
00278                     
00279                     OCIAttrGet(parmh1, OCI_DTYPE_PARAM, &typinf->tcode, 
00280                                NULL, OCI_ATTR_TYPECODE, con->err)
00281                 )
00282 
00283             }
00284 
00285             if (typinf->tcode == SQLT_NCO)
00286             {      
00287                 typinf->nb_cols = 1;
00288                 
00289                 ptype  = OCI_DESC_COLLECTION;
00290                 etype  = OCI_DESC_TYPE;
00291                 parmh2 = parmh1;
00292 
00293                 OCI_CALL2
00294                 (
00295                     res, con, 
00296                     
00297                     OCIAttrGet(parmh1, OCI_DTYPE_PARAM, &typinf->ccode, 
00298                                NULL, OCI_ATTR_COLLECTION_TYPECODE, con->err)
00299                 )
00300             }
00301             else
00302             {
00303                 OCI_CALL2
00304                 (
00305                     res, con, 
00306                     
00307                     OCIAttrGet(parmh1, OCI_DTYPE_PARAM, &parmh2, 
00308                                NULL, attr_type, con->err)
00309                 )
00310 
00311                 OCI_CALL2
00312                 (
00313                     res, con, 
00314                     
00315                     OCIAttrGet(parmh1, OCI_DTYPE_PARAM, &typinf->nb_cols,
00316                                NULL, num_type, con->err)
00317                 )
00318             }
00319 
00320             /* allocates memory for children */
00321 
00322             if (typinf->nb_cols > 0)
00323             {
00324                 typinf->cols = (OCI_Column *) OCI_MemAlloc(OCI_IPC_COLUMN,
00325                                                            sizeof(*typinf->cols),
00326                                                            typinf->nb_cols,
00327                                                            TRUE);
00328 
00329                 /* describe children */
00330 
00331                 if (typinf->cols != NULL)
00332                 {
00333                     for (i = 0; i < typinf->nb_cols; i++)
00334                     {
00335                         res = res && OCI_ColumnDescribe(&typinf->cols[i], con, 
00336                                                         NULL, parmh2, i + 1, ptype);
00337                         
00338                         res = res && OCI_ColumnMap(&typinf->cols[i], NULL);
00339 
00340                         if (res == FALSE)
00341                             break;
00342                    }
00343                 }
00344                 else
00345                     res = FALSE;
00346             }
00347   
00348             /* free describe handle */
00349 
00350             if (dschp != NULL)
00351                 OCI_HandleFree(dschp, OCI_HTYPE_DESCRIBE);
00352         }
00353     }
00354 
00355    /* handle errors */
00356 
00357     if (res == FALSE)
00358     {
00359        OCI_TypeInfoFree(typinf);        
00360        typinf = NULL;
00361     }
00362 
00363     OCI_RESULT(res);
00364 
00365     /* increment type info reference counter on success */
00366 
00367     if (typinf != NULL)
00368         typinf->refcount++;
00369 
00370     return typinf; 
00371 }
00372 
00373 /* ------------------------------------------------------------------------ *
00374  * OCI_TypeInfoFree
00375  * ------------------------------------------------------------------------ */
00376 
00377 boolean OCI_API OCI_TypeInfoFree(OCI_TypeInfo *typinf)
00378 {
00379     boolean res = TRUE;
00380 
00381     OCI_CHECK_PTR(OCI_IPC_TYPE_INFO, typinf, FALSE);
00382 
00383     typinf->refcount--;
00384 
00385     if (typinf->refcount == 0)
00386     {
00387         OCI_ListRemove(typinf->con->tinfs, typinf);
00388 
00389         res = OCI_TypeInfoClose(typinf);
00390 
00391         OCI_FREE(typinf);
00392     }
00393 
00394     OCI_RESULT(res);
00395 
00396     return res;
00397 }
00398 
00399 /* ------------------------------------------------------------------------ *
00400  * OCI_TypeInfoGetType
00401  * ------------------------------------------------------------------------ */
00402 
00403 unsigned int OCI_API OCI_TypeInfoGetType(OCI_TypeInfo *typinf)
00404 {
00405     OCI_CHECK_PTR(OCI_IPC_TYPE_INFO, typinf, OCI_UNKNOWN);
00406 
00407     OCI_RESULT(TRUE);
00408 
00409     return typinf->type;
00410 }
00411 
00412 /* ------------------------------------------------------------------------ *
00413  * OCI_TypeInfoGetColumnCount
00414  * ------------------------------------------------------------------------ */
00415 
00416 unsigned int OCI_API OCI_TypeInfoGetColumnCount(OCI_TypeInfo *typinf)
00417 {
00418     OCI_CHECK_PTR(OCI_IPC_TYPE_INFO, typinf, 0);
00419   
00420     OCI_RESULT(TRUE);
00421 
00422     return typinf->nb_cols;
00423 }
00424 
00425 /* ------------------------------------------------------------------------ *
00426  * OCI_TypeInfoGetColumn
00427  * ------------------------------------------------------------------------ */
00428 
00429 OCI_Column * OCI_API OCI_TypeInfoGetColumn(OCI_TypeInfo *typinf, unsigned int index)
00430 {
00431     OCI_CHECK_PTR(OCI_IPC_TYPE_INFO, typinf, NULL);
00432     OCI_CHECK_BOUND(typinf->con, index, 1,  typinf->nb_cols, NULL);
00433 
00434     OCI_RESULT(TRUE);
00435 
00436     return &(typinf->cols[index-1]);
00437 }
00438 
00439 /* ------------------------------------------------------------------------ *
00440  * OCI_TypeInfoGetName
00441  * ------------------------------------------------------------------------ */
00442 
00443 const mtext * OCI_API OCI_TypeInfoGetName(OCI_TypeInfo *typinf)
00444 {
00445     OCI_CHECK_PTR(OCI_IPC_TYPE_INFO, typinf, NULL);
00446 
00447     OCI_RESULT(TRUE);
00448 
00449     return typinf->name;
00450 }

Generated on Thu Jul 30 17:41:53 2009 for OCILIB (C Driver for Oracle) by  doxygen 1.5.4