OCILIB (C Driver for Oracle) 3.9.2
D:/Perso/dev/ocilib/ocilib/src/define.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: define.c, v 3.9.2 2011-07-13 00:00 Vincent Rogier $
00033  * --------------------------------------------------------------------------------------------- */
00034 
00035 #include "ocilib_internal.h"
00036 
00037 /* ********************************************************************************************* *
00038  *                             PRIVATE FUNCTIONS
00039  * ********************************************************************************************* */
00040 
00041 /* --------------------------------------------------------------------------------------------- *
00042  * OCI_GetDefine
00043  * --------------------------------------------------------------------------------------------- */
00044 
00045 OCI_Define * OCI_GetDefine
00046 (
00047     OCI_Resultset *rs,
00048     unsigned int   index
00049 )
00050 {
00051     OCI_Define * def = NULL;
00052 
00053     OCI_CHECK_PTR(OCI_IPC_RESULTSET, rs, NULL);
00054     OCI_CHECK_BOUND(rs->stmt->con, index,  1,  rs->nb_defs, NULL);
00055 
00056     if ((rs->stmt->exec_mode != OCI_DESCRIBE_ONLY) && (rs->stmt->exec_mode != OCI_PARSE_ONLY))
00057     {
00058         def =  &rs->defs[index-1];
00059     }
00060 
00061     return def;
00062 }
00063 
00064 /* --------------------------------------------------------------------------------------------- *
00065  * OCI_GetDefineIndex
00066  * --------------------------------------------------------------------------------------------- */
00067 
00068 int OCI_GetDefineIndex
00069 (
00070     OCI_Resultset *rs,
00071     const mtext   *name
00072 )
00073 {
00074     OCI_HashEntry *he = NULL;
00075     int index         = -1;
00076 
00077     OCI_CHECK_PTR(OCI_IPC_RESULTSET, rs, -1);
00078     OCI_CHECK_PTR(OCI_IPC_STRING, name, -1);
00079 
00080     if (rs->map == NULL)
00081     {
00082         /* create the map at the first call to OCI_Getxxxxx2() to save
00083            time and memory when it's not needed */
00084 
00085         rs->map = OCI_HashCreate(OCI_HASH_DEFAULT_SIZE, OCI_HASH_INTEGER);
00086 
00087         if (rs->map != NULL)
00088         {
00089             ub4 i;
00090 
00091             for (i = 0; i < rs->nb_defs; i++)
00092             {
00093                 OCI_HashAddInt(rs->map, rs->defs[i].col.name, (i+1));
00094             }
00095         }
00096     }
00097 
00098     /* check out we got our map object */
00099 
00100     OCI_CHECK(rs->map == NULL, -1);
00101 
00102     he = OCI_HashLookup(rs->map, name, FALSE);
00103 
00104     while (he != NULL)
00105     {
00106         /* no more entries or key matched => so we got it ! */
00107 
00108         if (he->next == NULL || mtscasecmp(he->key, name) == 0)
00109         {
00110             index = he->values->value.num;
00111             break;
00112         }
00113     }
00114 
00115     return index;
00116 }
00117 
00118 /* --------------------------------------------------------------------------------------------- *
00119  * OCI_DefineGetData
00120  * --------------------------------------------------------------------------------------------- */
00121 
00122 void * OCI_DefineGetData
00123 (
00124     OCI_Define *def
00125 )
00126 {
00127     OCI_CHECK(def == NULL, NULL);
00128     OCI_CHECK(def->rs->row_cur < 1, NULL);
00129 
00130     switch (def->col.type)
00131     {
00132         case OCI_CDT_LONG:
00133         case OCI_CDT_CURSOR:
00134         case OCI_CDT_TIMESTAMP:
00135         case OCI_CDT_INTERVAL:
00136         case OCI_CDT_LOB:
00137         case OCI_CDT_FILE:
00138         case OCI_CDT_OBJECT:
00139         case OCI_CDT_COLLECTION:
00140         case OCI_CDT_REF:
00141         {
00142             /* handle based types */
00143 
00144             return def->buf.data[def->rs->row_cur-1];
00145         }
00146         default:
00147         {
00148             /* scalar types */
00149 
00150             return (((ub1 *) (def->buf.data)) + (size_t) (def->col.bufsize * (def->rs->row_cur-1)));
00151         }
00152     }
00153 }
00154 
00155 /* --------------------------------------------------------------------------------------------- *
00156  * OCI_DefineIsDataNotNull
00157  * --------------------------------------------------------------------------------------------- */
00158 
00159 boolean OCI_DefineIsDataNotNull
00160 (
00161     OCI_Define *def
00162 )
00163 {
00164     boolean res = FALSE;
00165     
00166     if ((def != NULL) && (def->rs->row_cur > 0))
00167     {
00168         OCIInd ind = OCI_IND_NULL;
00169 
00170         if (def->col.type == OCI_CDT_OBJECT)
00171         {
00172            ind =  * (OCIInd *) def->buf.obj_inds[def->rs->row_cur-1];
00173         }
00174         else
00175         {
00176             ind = ((OCIInd *) (def->buf.inds))[def->rs->row_cur-1];
00177 
00178         }
00179         
00180         res = (ind != OCI_IND_NULL);
00181     }
00182 
00183     return res;
00184 }
00185 
00186 
00187 /* --------------------------------------------------------------------------------------------- *
00188  * OCI_DefineGetNumber
00189  * --------------------------------------------------------------------------------------------- */
00190 
00191 boolean OCI_DefineGetNumber
00192 (
00193     OCI_Resultset *rs,
00194     unsigned int   index,
00195     void          *value,
00196     uword          type,
00197     uword          size
00198 )
00199 {
00200     OCI_Define *def = OCI_GetDefine(rs, index);
00201     boolean res     = FALSE;
00202 
00203     if (OCI_DefineIsDataNotNull(def) == TRUE)
00204     {
00205         void *data = OCI_DefineGetData(def);
00206 
00207         switch (def->col.type)
00208         {
00209             case OCI_CDT_NUMERIC:
00210             {
00211                 res = OCI_NumberGet(rs->stmt->con, (OCINumber *) data, value, size, type);
00212                 break;
00213             }
00214             case OCI_CDT_TEXT:
00215             {
00216                 const mtext *fmt = OCI_GetDefaultFormatNumeric(rs->stmt->con);
00217                 ub4 fmt_size     = (ub4) mtslen(fmt);
00218 
00219                 res = OCI_NumberGetFromStr(rs->stmt->con, value, size, type, (dtext *) data,
00220                                            (int) dtslen((dtext *) data), fmt, fmt_size);
00221                 break;
00222             }
00223         }
00224     }
00225 
00226     OCI_RESULT(res);
00227 
00228     return res;
00229 }
00230 
00231 /* --------------------------------------------------------------------------------------------- *
00232  * OCI_DefineAlloc
00233  * --------------------------------------------------------------------------------------------- */
00234 
00235 boolean OCI_DefineAlloc
00236 (
00237     OCI_Define *def
00238 )
00239 {
00240     boolean res = TRUE;
00241     ub4 bufsize = 0;
00242     ub4 indsize = 0;
00243     ub4 i;
00244 
00245     /* this function allocates internal buffers, handles, indicators, arrays, ...
00246        for the given output define handle */
00247 
00248     OCI_CHECK(def == NULL, FALSE);
00249 
00250     /* Allocate null indicators array */
00251 
00252     if (def->col.ocode == SQLT_NTY || def->col.ocode == SQLT_REF)
00253     {
00254         indsize = (ub4) sizeof(void*);
00255     }
00256     else
00257     {
00258         indsize = (ub4) sizeof(sb2);
00259     }
00260 
00261     if (res == TRUE)
00262     {
00263         def->buf.inds = (void *) OCI_MemAlloc(OCI_IPC_INDICATOR_ARRAY, (size_t) indsize,
00264                                               (size_t) def->buf.count, TRUE);
00265         res = (def->buf.inds != NULL);
00266     }
00267 
00268     if (def->col.type == OCI_CDT_OBJECT)
00269     {
00270         def->buf.obj_inds = (void *) OCI_MemAlloc(OCI_IPC_INDICATOR_ARRAY, sizeof(void *),
00271                                                   (size_t) def->buf.count, TRUE);
00272         res = (def->buf.obj_inds != NULL);
00273     }
00274 
00275     /* Allocate row data sizes array */
00276 
00277     if (res == TRUE)
00278     {
00279         def->buf.lens = (void *) OCI_MemAlloc(OCI_IPC_LEN_ARRAY, (size_t) def->buf.sizelen,
00280                                               (size_t) def->buf.count, TRUE);
00281         res = (def->buf.lens != NULL);
00282     }
00283 
00284     /* initialize length array with buffer default size.
00285        But, Oracle uses different sizes for static fetch and callback fetch....*/
00286 
00287     if (res == TRUE)
00288     {
00289         for (i=0; i < def->buf.count; i++)
00290         {
00291             if (def->buf.sizelen == (int) sizeof(ub2))
00292             {
00293                 *(ub2*)(((ub1 *)def->buf.lens) + (size_t) (def->buf.sizelen*i)) = (ub2) def->col.bufsize;
00294             }
00295             else if (def->buf.sizelen == (int) sizeof(ub4))
00296             {
00297                 *(ub4*)(((ub1 *)def->buf.lens) + (size_t) (def->buf.sizelen*i)) = (ub4) def->col.bufsize;
00298             }
00299         }
00300     }
00301 
00302     /* Allocate buffer array */
00303 
00304     if (res == TRUE)
00305     {
00306         if (def->col.type == OCI_CDT_LONG)
00307         {
00308             bufsize = (ub4) sizeof(OCI_Long *);
00309         }
00310         else
00311         {
00312             bufsize = def->col.bufsize;
00313         }
00314 
00315         def->buf.data = (void *) OCI_MemAlloc(OCI_IPC_BUFF_ARRAY, (size_t) bufsize,
00316                                               (size_t) def->buf.count, TRUE);
00317 
00318         res = (def->buf.data != NULL);
00319     }
00320 
00321     /* Allocate descriptor for cursor, lob and file, interval and timestamp */
00322 
00323     if (res == TRUE)
00324     {
00325         if (def->col.dtype != 0)
00326         {
00327             if (def->col.type == OCI_CDT_CURSOR)
00328             {
00329                 for (i = 0; (i < def->buf.count) && (res == TRUE); i++)
00330                 {
00331                     res = (OCI_SUCCESS == OCI_HandleAlloc((dvoid  *) def->rs->stmt->con->env,
00332                                                           (dvoid **) &(def->buf.data[i]),
00333                                                           (ub4) def->col.dtype,
00334                                                           (size_t) 0, (dvoid **) NULL));
00335                 }
00336             }
00337             else
00338             {
00339                 res = (OCI_SUCCESS == OCI_DescriptorArrayAlloc((dvoid  *) def->rs->stmt->con->env,
00340                                                                (dvoid **) def->buf.data,
00341                                                                (ub4) def->col.dtype,
00342                                                                (ub4) def->buf.count,
00343                                                                (size_t) 0, (dvoid **) NULL));
00344 
00345                 if ((res == TRUE) && (def->col.type == OCI_CDT_LOB))
00346                 {
00347                     ub4 empty = 0;
00348 
00349                     for (i = 0; (i < def->buf.count) && (res == TRUE); i++)
00350                     {
00351                         OCI_CALL1
00352                         (
00353                             res, def->rs->stmt->con, def->rs->stmt,
00354 
00355                             OCIAttrSet((dvoid *) def->buf.data[i],  (ub4) def->col.dtype,
00356                                        (void *) &empty, (ub4) sizeof(empty),
00357                                        (ub4) OCI_ATTR_LOBEMPTY, def->rs->stmt->con->err)
00358                         )
00359                     }
00360                 }
00361             }
00362         }
00363     }
00364 
00365     return res;
00366 }
00367 
00368 /* --------------------------------------------------------------------------------------------- *
00369  * OCI_DefineDef
00370  * --------------------------------------------------------------------------------------------- */
00371 
00372 boolean OCI_DefineDef
00373 (
00374     OCI_Define *def
00375 )
00376 {
00377     boolean res    = TRUE;
00378     ub2 fetch_mode = OCI_DEFAULT;
00379 
00380     OCI_CHECK(def == NULL, FALSE);
00381 
00382     /*check define mode for long columns */
00383 
00384     if (def->col.type == OCI_CDT_LONG)
00385     {
00386         fetch_mode = OCI_DYNAMIC_FETCH;
00387     }
00388 
00389     /* oracle defining */
00390 
00391     OCI_CALL1
00392     (
00393         res, def->rs->stmt->con, def->rs->stmt,
00394 
00395         OCIDefineByPos(def->rs->stmt->stmt,
00396                        (OCIDefine **) &def->buf.handle,
00397                        def->rs->stmt->con->err,
00398                        def->rs->nb_defs,
00399                        (void *) def->buf.data,
00400                        (sb4   ) def->col.bufsize,
00401                        (ub2   ) def->col.icode,
00402                        (void *) def->buf.inds,
00403                        (ub2  *) def->buf.lens,
00404                        (ub2  *) NULL,
00405                        (ub4   ) fetch_mode)
00406     )
00407 
00408     if (def->col.ocode == SQLT_NTY || def->col.ocode == SQLT_REF)
00409     {
00410         OCI_CALL1
00411         (
00412             res, def->rs->stmt->con, def->rs->stmt,
00413 
00414             OCIDefineObject((OCIDefine *) def->buf.handle,
00415                             def->rs->stmt->con->err,
00416                             def->col.typinf->tdo,
00417                             (void **) def->buf.data,
00418                             (ub4   *) NULL,
00419                             (void **) def->buf.obj_inds,
00420                             (ub4   *) NULL)
00421         )
00422     }
00423 
00424     if(( def->col.type == OCI_CDT_TEXT)  ||
00425        ((def->col.type == OCI_CDT_LOB)   && (def->col.subtype != OCI_BLOB))  ||
00426        ((def->col.type == OCI_CDT_FILE)  && (def->col.subtype != OCI_BFILE)) ||
00427        ((def->col.type == OCI_CDT_LONG)  && (def->col.subtype != OCI_BLONG)))
00428     {
00429 
00430         if ((def->col.csfrm == SQLCS_NCHAR) || (OCILib.nls_utf8 == TRUE))
00431         {
00432             ub1 csfrm = SQLCS_NCHAR;
00433 
00434             OCI_CALL1
00435             (
00436                 res, def->rs->stmt->con, def->rs->stmt,
00437 
00438                 OCIAttrSet((dvoid *) def->buf.handle,
00439                            (ub4    ) OCI_HTYPE_DEFINE,
00440                            (dvoid *) &csfrm,
00441                            (ub4    ) sizeof(csfrm),
00442                            (ub4    ) OCI_ATTR_CHARSET_FORM,
00443                            def->rs->stmt->con->err)
00444             )
00445         }
00446 
00447     #ifdef OCI_CHARSET_MIXED
00448 
00449         /* setup Unicode mode for user data on mixed builds */
00450         {
00451             ub2 csid = OCI_UTF16ID;
00452 
00453             OCI_CALL1
00454             (
00455                 res, def->rs->stmt->con, def->rs->stmt,
00456 
00457                 OCIAttrSet((dvoid *) def->buf.handle,
00458                            (ub4    ) OCI_HTYPE_DEFINE,
00459                            (dvoid *) &csid,
00460                            (ub4    ) sizeof(csid),
00461                            (ub4    ) OCI_ATTR_CHARSET_ID,
00462                            def->rs->stmt->con->err)
00463             )
00464         }
00465 
00466     #endif
00467 
00468     }
00469 
00470     return res;
00471 }
00472 
00473 /* --------------------------------------------------------------------------------------------- *
00474  * OCI_DefineRequestBuffer
00475  * --------------------------------------------------------------------------------------------- */
00476 
00477 boolean OCI_DefineRequestBuffer
00478 (
00479     OCI_Define  *def,
00480     unsigned int size
00481 )
00482 {
00483     boolean res = TRUE;
00484 
00485     size++;
00486 
00487     if (OCILib.nls_utf8 == TRUE)
00488     {
00489         size *= UTF8_BYTES_PER_CHAR;
00490     }
00491     else
00492     {
00493         size *= sizeof(dtext);
00494     }
00495 
00496     if (def->buf.tmpbuf == NULL)
00497     {
00498         def->buf.tmpbuf = (dtext *) OCI_MemAlloc(OCI_IPC_STRING, (size_t) size, (size_t) 1, TRUE);
00499 
00500         if (def->buf.tmpbuf != NULL)
00501         {
00502             def->buf.tmpsize = size;
00503         }
00504         else
00505         {
00506             res = FALSE;
00507         }
00508 
00509     }
00510     else if (def->buf.tmpsize < size)
00511     {
00512         def->buf.tmpbuf = (dtext *) OCI_MemRealloc(def->buf.tmpbuf, OCI_IPC_STRING, (size_t) size, (size_t) 1);
00513 
00514         if (def->buf.tmpbuf != NULL)
00515         {
00516             def->buf.tmpsize = size;
00517         }
00518         else
00519         {
00520             res = FALSE;
00521         }
00522     }
00523 
00524     def->buf.tmpbuf[0] = 0;
00525 
00526     return res;
00527 }