OCILIB (C Driver for Oracle) 3.12.1
array.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: array.c, Vincent Rogier $
00033  * --------------------------------------------------------------------------------------------- */
00034 
00035 #include "ocilib_internal.h"
00036 
00037 /* ********************************************************************************************* *
00038  *                            PRIVATE FUNCTIONS
00039  * ********************************************************************************************* */
00040 
00041 /* --------------------------------------------------------------------------------------------- *
00042  * OCI_ArrayInit
00043  * --------------------------------------------------------------------------------------------- */
00044 
00045 boolean OCI_ArrayInit
00046 (
00047     OCI_Array    *arr,
00048     OCI_TypeInfo *typinf
00049 )
00050 {
00051     unsigned int i;
00052 
00053     for (i = 0; i < arr->nb_elem; i++)
00054     {
00055         void *handle = NULL;
00056 
00057         if (arr->elem_type == OCI_CDT_DATETIME)
00058         {
00059             handle = &(((OCIDate *)(arr->mem_handle))[i]);
00060         }
00061         else
00062         {
00063             handle = ((void **)(arr->mem_handle))[i];
00064         }
00065 
00066         arr->tab_obj[i] = ((char *) arr->mem_struct) + (arr->struct_size * i);
00067 
00068         ((OCI_Datatype *) (arr->tab_obj[i]))->hstate = OCI_OBJECT_ALLOCATED_ARRAY;
00069 
00070         switch (arr->elem_type)
00071         {
00072             case OCI_CDT_DATETIME:
00073             {
00074                 OCI_DateInit(arr->con, (OCI_Date **) &arr->tab_obj[i],
00075                              (OCIDate *) handle, FALSE, FALSE);
00076 
00077                 break;
00078             }
00079             case OCI_CDT_LOB:
00080             {
00081                 OCI_LobInit(arr->con, (OCI_Lob **) &arr->tab_obj[i],
00082                             (OCILobLocator *) handle, arr->elem_subtype);
00083 
00084                 break;
00085             }
00086             case OCI_CDT_FILE:
00087             {
00088                 OCI_FileInit(arr->con, (OCI_File **) &arr->tab_obj[i],
00089                              (OCILobLocator *) handle, arr->elem_subtype);
00090                 break;
00091             }
00092             case OCI_CDT_TIMESTAMP:
00093             {
00094                 OCI_TimestampInit(arr->con, (OCI_Timestamp **) &arr->tab_obj[i],
00095                                   (OCIDateTime *) handle, arr->elem_subtype);
00096 
00097                 break;
00098             }
00099             case OCI_CDT_INTERVAL:
00100             {
00101                 OCI_IntervalInit(arr->con, (OCI_Interval **) &arr->tab_obj[i],
00102                                  (OCIInterval *) handle, arr->elem_subtype);
00103 
00104                 break;
00105             }
00106             case OCI_CDT_OBJECT:
00107             {
00108                 OCI_ObjectInit(arr->con, (OCI_Object **) &arr->tab_obj[i],
00109                                handle, typinf, NULL, -1, TRUE);
00110 
00111                 break;
00112             }
00113             case OCI_CDT_COLLECTION:
00114             {
00115                 OCI_CollInit(arr->con, (OCI_Coll **) &arr->tab_obj[i], handle, typinf);
00116 
00117                 break;
00118             }
00119             case OCI_CDT_REF:
00120             {
00121                 OCI_RefInit(arr->con, typinf, (OCI_Ref **) &arr->tab_obj[i], handle);
00122 
00123                 break;
00124             }
00125         }
00126     }
00127 
00128     return TRUE;
00129 }
00130 
00131 /* --------------------------------------------------------------------------------------------- *
00132  * OCI_ArrayClose
00133  * --------------------------------------------------------------------------------------------- */
00134 
00135 boolean OCI_ArrayClose
00136 (
00137     OCI_Array *arr
00138 )
00139 {
00140     unsigned int i;
00141 
00142     OCI_CHECK_PTR(OCI_IPC_ARRAY, arr, FALSE);
00143 
00144     /* Cleanup OCILIB Objects */
00145 
00146     for (i = 0; i < arr->nb_elem; i++)
00147     {
00148         switch (arr->elem_type)
00149         {
00150             case OCI_CDT_DATETIME:
00151             {
00152                 OCI_DateFree((OCI_Date *) arr->tab_obj[i]);
00153 
00154                 break;
00155             }
00156             case OCI_CDT_LOB:
00157             {
00158                 OCI_LobFree((OCI_Lob *) arr->tab_obj[i]);
00159 
00160                 break;
00161             }
00162             case OCI_CDT_FILE:
00163             {
00164                 OCI_FileFree((OCI_File *) arr->tab_obj[i]);
00165 
00166                 break;
00167             }
00168             case OCI_CDT_TIMESTAMP:
00169             {
00170                 OCI_TimestampFree((OCI_Timestamp *) arr->tab_obj[i]);
00171 
00172                 break;
00173             }
00174             case OCI_CDT_INTERVAL:
00175             {
00176                 OCI_IntervalFree((OCI_Interval *) arr->tab_obj[i]);
00177 
00178                 break;
00179             }
00180             case OCI_CDT_OBJECT:
00181             {
00182                 OCI_ObjectFree((OCI_Object *) arr->tab_obj[i]);
00183 
00184                 break;
00185             }
00186             case OCI_CDT_COLLECTION:
00187             {
00188                 OCI_CollFree((OCI_Coll *) arr->tab_obj[i]);
00189 
00190                 break;
00191             }
00192             case OCI_CDT_REF:
00193             {
00194                 OCI_RefFree((OCI_Ref *) arr->tab_obj[i]);
00195 
00196                 break;
00197             }
00198        }
00199     }
00200 
00201     /* free OCI descriptors */
00202 
00203     if (arr->handle_type != 0)
00204     {
00205         OCI_DescriptorArrayFree
00206         (
00207             (dvoid **) arr->mem_handle,
00208             (ub4     ) arr->handle_type,
00209             (ub4     ) arr->nb_elem
00210         );
00211     }
00212 
00213     OCI_FREE(arr->mem_handle);
00214     OCI_FREE(arr->mem_struct);
00215     OCI_FREE(arr->tab_obj);
00216 
00217     return TRUE;
00218 }
00219 
00220 /* --------------------------------------------------------------------------------------------- *
00221  * OCI_ArrayCreate
00222  * --------------------------------------------------------------------------------------------- */
00223 
00224 OCI_Array * OCI_ArrayCreate
00225 (
00226     OCI_Connection *con,
00227     unsigned int    nb_elem,
00228     unsigned int    elem_type,
00229     unsigned int    elem_subtype,
00230     unsigned int    elem_size,
00231     unsigned int    struct_size,
00232     unsigned int    handle_type,
00233     OCI_TypeInfo   *typinf
00234 )
00235 {
00236     boolean res    = TRUE;
00237     OCI_Array *arr = NULL;
00238     OCI_Item *item = NULL;
00239 
00240     OCI_CHECK_INITIALIZED(NULL);
00241     OCI_CHECK_PTR(OCI_IPC_CONNECTION, con, NULL);
00242 
00243     /* create array object */
00244 
00245     item = OCI_ListAppend(OCILib.arrs, sizeof(*arr));
00246 
00247     if (item != NULL)
00248     {
00249         arr = (OCI_Array *) item->data;
00250 
00251         arr->con          = con;
00252         arr->elem_type    = elem_type;
00253         arr->elem_subtype = elem_subtype;
00254         arr->elem_size    = elem_size;
00255         arr->nb_elem      = nb_elem;
00256         arr->struct_size  = struct_size;
00257         arr->handle_type  = handle_type;
00258 
00259         /* allocate OCILIB Object array */
00260 
00261         if (res == TRUE)
00262         {
00263             if ( (arr->elem_type != OCI_CDT_NUMERIC ) &&
00264                  (arr->elem_type != OCI_CDT_TEXT    ) && 
00265                  (arr->elem_type != OCI_CDT_RAW     ))
00266             {
00267                 arr->tab_obj = (void **) OCI_MemAlloc(OCI_IPC_VOID,  sizeof(void *), nb_elem, TRUE);
00268 
00269                 res = (arr->tab_obj != NULL) ;
00270             }
00271         }
00272 
00273         /* allocate OCI handle array */
00274 
00275         if (res == TRUE)
00276         {
00277             if (arr->elem_size > 0)
00278             {
00279                 arr->mem_handle = (void **) OCI_MemAlloc(OCI_IPC_VOID, elem_size, nb_elem, TRUE);
00280 
00281                 res = (arr->mem_handle != NULL) ;
00282             }
00283         }
00284 
00285         /* allocate OCILIB structure array */
00286 
00287         if (res == TRUE)
00288         {
00289             if (arr->struct_size > 0)
00290             {
00291                 arr->mem_struct = (void **) OCI_MemAlloc(OCI_IPC_VOID, struct_size, nb_elem, TRUE);
00292 
00293                 res = (arr->mem_struct != NULL) ;
00294             }
00295         }
00296 
00297         /* allocate OCI handle descriptors */
00298 
00299         if (res == TRUE)
00300         {
00301             if (handle_type != 0)
00302             {
00303                 res = (OCI_SUCCESS == OCI_DescriptorArrayAlloc
00304                        (
00305                            (dvoid  *) arr->con->env,
00306                            (dvoid **) arr->mem_handle,
00307                            (ub4     ) handle_type,
00308                            (ub4     ) nb_elem,
00309                            (size_t  ) 0,
00310                            (dvoid **) NULL
00311                        ));
00312             }
00313         }
00314 
00315         if ((res == TRUE) && (arr->tab_obj != NULL) && (arr->mem_handle != NULL))
00316         {
00317             res = OCI_ArrayInit(arr, typinf);
00318         }
00319     }
00320     else
00321     {
00322         res = FALSE;
00323     }
00324 
00325     /* check for failure */
00326 
00327     if (res == FALSE)
00328     {
00329         OCI_ArrayClose(arr);
00330         OCI_FREE(arr);
00331     }
00332 
00333     OCI_RESULT(res);
00334 
00335     return arr;
00336 }
00337 
00338 /* --------------------------------------------------------------------------------------------- *
00339  * OCI_ArrayFreeFromHandles
00340  * --------------------------------------------------------------------------------------------- */
00341 
00342 boolean OCI_ArrayFreeFromHandles
00343 (
00344     void **handles
00345 )
00346 {
00347     boolean res    = FALSE;
00348     OCI_List *list = OCILib.arrs;
00349     OCI_Item *item = NULL;
00350     OCI_Array *arr = NULL;
00351 
00352     OCI_CHECK_PTR(OCI_IPC_VOID, handles, FALSE);
00353 
00354     OCI_CHECK(list == NULL, FALSE);
00355 
00356     if (list->mutex != NULL)
00357     {
00358         OCI_MutexAcquire(list->mutex);
00359     }
00360 
00361     item = list->head;
00362 
00363     while (item != NULL)
00364     {
00365         OCI_Array * tmp_arr = (OCI_Array *) item->data;
00366 
00367         if ((tmp_arr != NULL) && (tmp_arr->tab_obj == handles))
00368         {
00369             arr = tmp_arr;
00370             break;
00371         }
00372 
00373         item = item->next;
00374     }
00375 
00376     if (list->mutex != NULL)
00377     {
00378         OCI_MutexRelease(list->mutex);
00379     }
00380 
00381     if (arr != NULL)
00382     {
00383         res = OCI_ListRemove(OCILib.arrs, arr);
00384         OCI_ArrayClose(arr);
00385         OCI_FREE(arr);
00386     }
00387 
00388     OCI_RESULT(res);
00389 
00390     return res;
00391 }
00392 
00393 /* --------------------------------------------------------------------------------------------- *
00394  * OCI_ArrayGetOCIHandlesFromHandles
00395  * --------------------------------------------------------------------------------------------- */
00396 
00397 void * OCI_ArrayGetOCIHandlesFromHandles
00398 (
00399     void **handles
00400 )
00401 {
00402     OCI_List *list = OCILib.arrs;
00403     void *ret      = NULL;
00404     OCI_Item *item = NULL;
00405     OCI_Array *arr = NULL;
00406 
00407     OCI_CHECK(list == NULL, NULL);
00408 
00409     if (list->mutex != NULL)
00410     {
00411         OCI_MutexAcquire(list->mutex);
00412     }
00413 
00414     item = list->head;
00415 
00416     while (item != NULL)
00417     {
00418         OCI_Array * tmp_arr = (OCI_Array *) item->data;
00419 
00420         if ((tmp_arr != NULL) && (tmp_arr->tab_obj == handles))
00421         {
00422             arr = tmp_arr;
00423             break;
00424         }
00425 
00426         item = item->next;
00427     }
00428 
00429     if (list->mutex != NULL)
00430     {
00431         OCI_MutexRelease(list->mutex);
00432     }
00433 
00434     if (arr != NULL)
00435     {
00436         ret = arr->mem_handle;
00437     }
00438 
00439     return ret;
00440 }