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