OCILIB (C Driver for Oracle) 3.12.1
collection.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-2013 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: collection.c, Vincent Rogier $
00033  * --------------------------------------------------------------------------------------------- */
00034 
00035 #include "ocilib_internal.h"
00036 
00037 /* ********************************************************************************************* *
00038  *                             PRIVATE FUNCTIONS
00039  * ********************************************************************************************* */
00040 
00041 /* --------------------------------------------------------------------------------------------- *
00042  * OCI_CollInit
00043  * --------------------------------------------------------------------------------------------- */
00044 
00045 OCI_Coll * OCI_CollInit
00046 (
00047     OCI_Connection *con,
00048     OCI_Coll      **pcoll,
00049     void           *handle,
00050     OCI_TypeInfo   *typinf
00051 )
00052 {
00053     OCI_Coll *coll = NULL;
00054     boolean res    = TRUE;
00055 
00056     OCI_CHECK(pcoll == NULL, NULL);
00057 
00058     if (*pcoll == NULL)
00059     {
00060         *pcoll = (OCI_Coll *) OCI_MemAlloc(OCI_IPC_COLLECTION, sizeof(*coll), (size_t) 1, TRUE);
00061     }
00062 
00063     if (*pcoll != NULL)
00064     {
00065         coll = *pcoll;
00066 
00067         coll->con    = con;
00068         coll->handle = handle;
00069         coll->typinf = typinf;
00070 
00071         if ((coll->handle == NULL) || (coll->hstate == OCI_OBJECT_ALLOCATED_ARRAY))
00072         {
00073             /* allocates handle for non fetched collection */
00074 
00075             if (coll->hstate != OCI_OBJECT_ALLOCATED_ARRAY)
00076             {
00077                 coll->hstate = OCI_OBJECT_ALLOCATED;
00078             }
00079 
00080             OCI_CALL2
00081             (
00082                 res, con,
00083 
00084                 OCI_ObjectNew(coll->con->env, coll->con->err, coll->con->cxt,
00085                               typinf->ccode, typinf->tdo, (void *) NULL,
00086                               OCI_DURATION_SESSION, TRUE, (dvoid **) &coll->handle)
00087             )
00088         }
00089         else
00090         {
00091             coll->hstate = OCI_OBJECT_FETCHED_CLEAN;
00092         }
00093     }
00094     else
00095     {
00096         res = FALSE;
00097     }
00098 
00099     /* check for failure */
00100 
00101     if (res == FALSE)
00102     {
00103         OCI_CollFree(coll);
00104         coll = NULL;
00105     }
00106 
00107     return coll;
00108 }
00109 
00110 /* ********************************************************************************************* *
00111  *                             PUBLIC FUNCTIONS
00112  * ********************************************************************************************* */
00113 
00114 /* --------------------------------------------------------------------------------------------- *
00115  * OCI_CollCreate
00116  * --------------------------------------------------------------------------------------------- */
00117 
00118 OCI_Coll * OCI_API OCI_CollCreate
00119 (
00120     OCI_TypeInfo *typinf
00121 )
00122 {
00123     OCI_Coll *coll = NULL;
00124 
00125     OCI_CHECK_INITIALIZED(NULL);
00126 
00127     OCI_CHECK_PTR(OCI_IPC_TYPE_INFO, typinf, NULL);
00128     OCI_CHECK(typinf->ccode == OCI_UNKNOWN, NULL)
00129 
00130     coll = OCI_CollInit(typinf->con, &coll, (OCIColl *) NULL, typinf);
00131 
00132     OCI_RESULT(coll != NULL);
00133 
00134     return coll;
00135 }
00136 
00137 /* --------------------------------------------------------------------------------------------- *
00138  * OCI_CollFree
00139  * --------------------------------------------------------------------------------------------- */
00140 
00141 boolean OCI_API OCI_CollFree
00142 (
00143     OCI_Coll *coll
00144 )
00145 {
00146     OCI_CHECK_PTR(OCI_IPC_COLLECTION, coll, FALSE);
00147     OCI_CHECK_OBJECT_FETCHED(coll, FALSE);
00148 
00149     /* free data element accessor */
00150 
00151     if (coll->elem != NULL)
00152     {
00153         coll->elem->hstate = OCI_OBJECT_FETCHED_DIRTY;
00154         OCI_ElemFree(coll->elem);
00155         coll->elem = NULL;
00156     }
00157 
00158     /* free collection for local object */
00159 
00160     if ((coll->hstate == OCI_OBJECT_ALLOCATED      ) ||
00161         (coll->hstate == OCI_OBJECT_ALLOCATED_ARRAY))
00162     {
00163         OCI_OCIObjectFree(coll->con->env, coll->typinf->con->err, coll->handle, OCI_OBJECTFREE_NONULL);
00164     }
00165 
00166     if (coll->hstate != OCI_OBJECT_ALLOCATED_ARRAY)
00167     {
00168         OCI_FREE(coll);
00169     }
00170 
00171     OCI_RESULT(TRUE);
00172 
00173     return TRUE;
00174 }
00175 
00176 /* --------------------------------------------------------------------------------------------- *
00177  * OCI_CollArrayCreate
00178  * --------------------------------------------------------------------------------------------- */
00179 
00180 OCI_Coll ** OCI_API OCI_CollArrayCreate
00181 (
00182     OCI_Connection *con,
00183     OCI_TypeInfo   *typinf,
00184     unsigned int    nbelem
00185 )
00186 {
00187     OCI_Array *arr   = NULL;
00188     OCI_Coll **colls = NULL;
00189 
00190     arr = OCI_ArrayCreate(con, nbelem, OCI_CDT_COLLECTION, 0, sizeof(OCIColl *),
00191                           sizeof(OCI_Coll), 0, typinf);
00192 
00193     if (arr != NULL)
00194     {
00195         colls = (OCI_Coll **) arr->tab_obj;
00196     }
00197 
00198     return colls;
00199 }
00200 
00201 /* --------------------------------------------------------------------------------------------- *
00202  * OCI_CollArrayFree
00203  * --------------------------------------------------------------------------------------------- */
00204 
00205 boolean OCI_API OCI_CollArrayFree
00206 (
00207     OCI_Coll **colls
00208 )
00209 {
00210     return OCI_ArrayFreeFromHandles((void **) colls);
00211 }
00212 
00213 /* --------------------------------------------------------------------------------------------- *
00214  * OCI_CollAssign
00215  * --------------------------------------------------------------------------------------------- */
00216 
00217 boolean OCI_API OCI_CollAssign
00218 (
00219     OCI_Coll *coll,
00220     OCI_Coll *coll_src
00221 )
00222 {
00223     boolean res = TRUE;
00224 
00225     OCI_CHECK_PTR(OCI_IPC_COLLECTION, coll,     FALSE);
00226     OCI_CHECK_PTR(OCI_IPC_COLLECTION, coll_src, FALSE);
00227 
00228     OCI_CHECK_COMPAT(coll->con, coll->typinf->cols[0].icode == coll_src->typinf->cols[0].icode, FALSE);
00229 
00230     OCI_CALL2
00231     (
00232         res, coll->con,
00233 
00234         OCICollAssign(coll->con->env, coll->con->err, coll_src->handle, coll->handle)
00235     )
00236 
00237     OCI_RESULT(res);
00238 
00239     return res;
00240 }
00241 
00242 /* --------------------------------------------------------------------------------------------- *
00243  * OCI_CollGetType
00244  * --------------------------------------------------------------------------------------------- */
00245 
00246 unsigned int OCI_API OCI_CollGetType
00247 (
00248     OCI_Coll *coll
00249 )
00250 {
00251     unsigned int type = OCI_UNKNOWN;
00252 
00253     OCI_CHECK_PTR(OCI_IPC_COLLECTION, coll, OCI_UNKNOWN);
00254 
00255     if (coll->typinf->ccode == OCI_TYPECODE_TABLE)
00256     {
00257         type = OCI_COLL_NESTED_TABLE;
00258     }
00259     else if(coll->typinf->ccode == OCI_TYPECODE_VARRAY)
00260     {
00261         type = OCI_COLL_VARRAY;
00262     }
00263 
00264     OCI_RESULT(TRUE);
00265 
00266     return type;
00267 }
00268 
00269 /* --------------------------------------------------------------------------------------------- *
00270  * OCI_CollGetMax
00271  * --------------------------------------------------------------------------------------------- */
00272 
00273 unsigned int OCI_API OCI_CollGetMax
00274 (
00275     OCI_Coll *coll
00276 )
00277 {
00278     int max = 0;
00279 
00280     OCI_CHECK_PTR(OCI_IPC_COLLECTION, coll, 0);
00281 
00282     max = OCICollMax(coll->con->env, coll->handle);
00283 
00284     OCI_RESULT(TRUE);
00285 
00286     return (unsigned int) max;
00287 }
00288 
00289 /* --------------------------------------------------------------------------------------------- *
00290  * OCI_CollGetSize
00291  * --------------------------------------------------------------------------------------------- */
00292 
00293 unsigned int OCI_API OCI_CollGetSize
00294 (
00295     OCI_Coll *coll
00296 )
00297 {
00298     boolean res = TRUE;
00299     sb4 size    = 0;
00300 
00301     OCI_CHECK_PTR(OCI_IPC_COLLECTION, coll, 0);
00302 
00303     OCI_CALL2
00304     (
00305         res, coll->con,
00306 
00307         OCICollSize(coll->con->env, coll->con->err, coll->handle, &size)
00308     )
00309 
00310     OCI_RESULT(res);
00311 
00312     return (unsigned int) size;
00313 }
00314 
00315 /* --------------------------------------------------------------------------------------------- *
00316  * OCI_CollTrim
00317  * --------------------------------------------------------------------------------------------- */
00318 
00319 boolean OCI_API OCI_CollTrim
00320 (
00321     OCI_Coll     *coll,
00322     unsigned int  nb_elem
00323 )
00324 {
00325     boolean res = TRUE;
00326     unsigned int size = 0;
00327 
00328     OCI_CHECK_PTR(OCI_IPC_COLLECTION, coll, FALSE);
00329 
00330     size = OCI_CollGetSize(coll);
00331 
00332     OCI_CHECK_BOUND(coll->con, (sb4) nb_elem, (sb4) 0, (sb4) size, FALSE);
00333 
00334     OCI_CALL2
00335     (
00336         res, coll->con,
00337 
00338         OCICollTrim(coll->con->env, coll->con->err, (sb4) nb_elem, coll->handle)
00339     )
00340 
00341     OCI_RESULT(res);
00342 
00343     return res;
00344 }
00345 
00346 /* --------------------------------------------------------------------------------------------- *
00347  * OCI_CollGetAt
00348  * --------------------------------------------------------------------------------------------- */
00349 
00350 OCI_Elem * OCI_API OCI_CollGetAt
00351 (
00352     OCI_Coll    *coll,
00353     unsigned int index
00354 )
00355 {
00356     boolean res    = TRUE;
00357     boolean exists = FALSE;
00358     void *data     = NULL;
00359     OCIInd *p_ind  = NULL;
00360     OCI_Elem *elem = NULL;
00361 
00362     OCI_CHECK_PTR(OCI_IPC_COLLECTION, coll, NULL);
00363 
00364     OCI_CALL2
00365     (
00366         res, coll->con,
00367 
00368         OCICollGetElem(coll->con->env, coll->con->err, coll->handle, (sb4) index-1,
00369                        &exists, &data, (dvoid **) (dvoid *) &p_ind)
00370     )
00371 
00372     if (res == TRUE && exists == TRUE && data != NULL)
00373     {
00374         elem = coll->elem = OCI_ElemInit(coll->con, &coll->elem, data, p_ind, coll->typinf);
00375     }
00376 
00377     OCI_RESULT(res);
00378 
00379     return elem;
00380 }
00381 
00382 /* --------------------------------------------------------------------------------------------- *
00383  * OCI_CollGetAt2
00384  * --------------------------------------------------------------------------------------------- */
00385 
00386 boolean OCI_API OCI_CollGetAt2
00387 (
00388     OCI_Coll    *coll,
00389     unsigned int index,
00390     OCI_Elem    *elem
00391 )
00392 {
00393     boolean res    = TRUE;
00394     boolean exists = FALSE;
00395     void *data     = NULL;
00396     OCIInd *p_ind  = NULL;
00397 
00398     OCI_CHECK_PTR(OCI_IPC_COLLECTION, coll, FALSE);
00399     OCI_CHECK_PTR(OCI_IPC_ELEMENT, elem, FALSE);
00400 
00401     OCI_CHECK_COMPAT(coll->con, elem->typinf->cols[0].type == coll->typinf->cols[0].type, FALSE);
00402 
00403     OCI_CALL2
00404     (
00405         res, coll->con,
00406 
00407         OCICollGetElem(coll->con->env, coll->con->err, coll->handle, (sb4) index-1,
00408                        &exists, &data, (dvoid **) (dvoid *) &p_ind)
00409     )
00410 
00411     if (res == TRUE && exists == TRUE && data != NULL)
00412     {
00413         res = (OCI_ElemInit(coll->con, &elem, data, p_ind, coll->typinf) != NULL);
00414     }
00415     else
00416     {
00417         OCI_ElemSetNullIndicator(elem, OCI_IND_NULL);
00418     }
00419 
00420     OCI_RESULT(res);
00421 
00422     return res;
00423 }
00424 
00425 /* --------------------------------------------------------------------------------------------- *
00426  * OCI_CollSetAt
00427  * --------------------------------------------------------------------------------------------- */
00428 
00429 boolean OCI_API OCI_CollSetAt
00430 (
00431     OCI_Coll    *coll,
00432     unsigned int index,
00433     OCI_Elem    *elem
00434 )
00435 {
00436     boolean res = TRUE;
00437 
00438     OCI_CHECK_PTR(OCI_IPC_COLLECTION, coll, FALSE);
00439     OCI_CHECK_PTR(OCI_IPC_ELEMENT, elem, FALSE);
00440 
00441     OCI_CHECK_COMPAT(coll->con, elem->typinf->cols[0].type == coll->typinf->cols[0].type, FALSE);
00442 
00443     OCI_CALL2
00444     (
00445         res, coll->con,
00446 
00447         OCICollAssignElem(coll->con->env, coll->con->err, (sb4) index-1, elem->handle,
00448                           elem->pind, coll->handle)
00449     )
00450 
00451     OCI_RESULT(res);
00452 
00453     return res;
00454 }
00455 
00456 /* --------------------------------------------------------------------------------------------- *
00457  * OCI_CollAppend
00458  * --------------------------------------------------------------------------------------------- */
00459 
00460 boolean OCI_API OCI_CollAppend
00461 (
00462     OCI_Coll *coll,
00463     OCI_Elem *elem
00464 )
00465 {
00466     boolean res = TRUE;
00467 
00468     OCI_CHECK_PTR(OCI_IPC_COLLECTION, coll, FALSE);
00469     OCI_CHECK_PTR(OCI_IPC_ELEMENT, elem, FALSE);
00470 
00471     OCI_CHECK_COMPAT(coll->con, elem->typinf->cols[0].type == coll->typinf->cols[0].type, FALSE);
00472 
00473     OCI_CALL2
00474     (
00475         res, coll->con,
00476 
00477         OCICollAppend(coll->con->env, coll->con->err, elem->handle, elem->pind, coll->handle)
00478     )
00479 
00480     OCI_RESULT(res);
00481 
00482     return res;
00483 }
00484 
00485 /* --------------------------------------------------------------------------------------------- *
00486  * OCI_CollGetTypeInfo
00487  * --------------------------------------------------------------------------------------------- */
00488 
00489 OCI_TypeInfo * OCI_API OCI_CollGetTypeInfo
00490 (
00491     OCI_Coll *coll
00492 )
00493 {
00494     OCI_CHECK_PTR(OCI_IPC_COLLECTION, coll, NULL);
00495 
00496     OCI_RESULT(TRUE);
00497 
00498     return coll->typinf;
00499 }
00500 
00501 /* --------------------------------------------------------------------------------------------- *
00502  * OCI_CollClear
00503  * --------------------------------------------------------------------------------------------- */
00504 
00505 boolean OCI_API OCI_CollClear
00506 (
00507     OCI_Coll *coll
00508 )
00509 {
00510     boolean res = TRUE;
00511 
00512     unsigned int size = OCI_CollGetSize(coll);
00513 
00514     if (size > 0)
00515     {
00516         res = OCI_CollTrim(coll, size);
00517     }
00518 
00519     OCI_RESULT(res);
00520 
00521     return res;
00522 }
00523