OCILIB (C Driver for Oracle) 3.12.1
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-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: define.c, 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 == NULL, NULL);
00129     OCI_CHECK(def->rs->row_cur < 1, NULL);
00130 
00131     switch (def->col.type)
00132     {
00133         case OCI_CDT_LONG:
00134         case OCI_CDT_CURSOR:
00135         case OCI_CDT_TIMESTAMP:
00136         case OCI_CDT_INTERVAL:
00137         case OCI_CDT_LOB:
00138         case OCI_CDT_FILE:
00139         case OCI_CDT_OBJECT:
00140         case OCI_CDT_COLLECTION:
00141         case OCI_CDT_REF:
00142         {
00143             /* handle based types */
00144 
00145             return def->buf.data[def->rs->row_cur-1];
00146         }
00147         default:
00148         {
00149             /* scalar types */
00150 
00151             return (((ub1 *) (def->buf.data)) + (size_t) (def->col.bufsize * (def->rs->row_cur-1)));
00152         }
00153     }
00154 }
00155 
00156 /* --------------------------------------------------------------------------------------------- *
00157  * OCI_DefineIsDataNotNull
00158  * --------------------------------------------------------------------------------------------- */
00159 
00160 boolean OCI_DefineIsDataNotNull
00161 (
00162     OCI_Define *def
00163 )
00164 {
00165     boolean res = FALSE;
00166     
00167     if ((def != NULL) && (def->rs->row_cur > 0))
00168     {
00169         OCIInd ind = OCI_IND_NULL;
00170 
00171         if (def->col.type == OCI_CDT_OBJECT)
00172         {
00173            ind =  * (OCIInd *) def->buf.obj_inds[def->rs->row_cur-1];
00174         }
00175         else
00176         {
00177             ind = ((OCIInd *) (def->buf.inds))[def->rs->row_cur-1];
00178 
00179         }
00180         
00181         res = (ind != OCI_IND_NULL);
00182     }
00183 
00184     return res;
00185 }
00186 
00187 
00188 /* --------------------------------------------------------------------------------------------- *
00189  * OCI_DefineGetNumber
00190  * --------------------------------------------------------------------------------------------- */
00191 
00192 boolean OCI_DefineGetNumber
00193 (
00194     OCI_Resultset *rs,
00195     unsigned int   index,
00196     void          *value,
00197     uword          type,
00198     uword          size
00199 )
00200 {
00201     OCI_Define *def = OCI_GetDefine(rs, index);
00202     boolean res     = FALSE;
00203 
00204     if (OCI_DefineIsDataNotNull(def) == TRUE)
00205     {
00206         void *data = OCI_DefineGetData(def);
00207 
00208         switch (def->col.type)
00209         {
00210             case OCI_CDT_NUMERIC:
00211             {
00212                 res = OCI_NumberGet(rs->stmt->con, data, size, type, def->col.icode, value);
00213                 break;
00214             }
00215             case OCI_CDT_TEXT:
00216             {
00217                 res = OCI_NumberFromString(rs->stmt->con, value, size, type, def->col.icode, (const dtext *) data, NULL);
00218                 break;
00219             }
00220         }
00221     }
00222 
00223     OCI_RESULT(res);
00224 
00225     return res;
00226 }
00227 
00228 /* --------------------------------------------------------------------------------------------- *
00229  * OCI_DefineAlloc
00230  * --------------------------------------------------------------------------------------------- */
00231 
00232 boolean OCI_DefineAlloc
00233 (
00234     OCI_Define *def
00235 )
00236 {
00237     boolean res = TRUE;
00238     ub4 indsize = 0;
00239     ub4 i;
00240 
00241     /* this function allocates internal buffers, handles, indicators, arrays, ...
00242        for the given output define handle */
00243 
00244     OCI_CHECK(def == NULL, FALSE);
00245 
00246     /* Allocate null indicators array */
00247 
00248     if (def->col.ocode == SQLT_NTY || def->col.ocode == SQLT_REF)
00249     {
00250         indsize = (ub4) sizeof(void*);
00251     }
00252     else
00253     {
00254         indsize = (ub4) sizeof(sb2);
00255     }
00256 
00257     if (res == TRUE)
00258     {
00259         def->buf.inds = (void *) OCI_MemAlloc(OCI_IPC_INDICATOR_ARRAY, (size_t) indsize,
00260                                               (size_t) def->buf.count, TRUE);
00261         res = (def->buf.inds != NULL);
00262     }
00263 
00264     if (def->col.type == OCI_CDT_OBJECT)
00265     {
00266         def->buf.obj_inds = (void *) OCI_MemAlloc(OCI_IPC_INDICATOR_ARRAY, sizeof(void *),
00267                                                   (size_t) def->buf.count, TRUE);
00268         res = (def->buf.obj_inds != NULL);
00269     }
00270 
00271     /* Allocate row data sizes array */
00272 
00273     if (res == TRUE)
00274     {
00275         def->buf.lens = (void *) OCI_MemAlloc(OCI_IPC_LEN_ARRAY, (size_t) def->buf.sizelen,
00276                                               (size_t) def->buf.count, TRUE);
00277         res = (def->buf.lens != NULL);
00278     }
00279 
00280     /* initialize length array with buffer default size.
00281        But, Oracle uses different sizes for static fetch and callback fetch....*/
00282 
00283     if (res == TRUE)
00284     {
00285        ub4 bufsize = 0;
00286 
00287        for (i=0; i < def->buf.count; i++)
00288         {
00289             if (def->buf.sizelen == (int) sizeof(ub2))
00290             {
00291                 *(ub2*)(((ub1 *)def->buf.lens) + (size_t) (def->buf.sizelen*i)) = (ub2) def->col.bufsize;
00292             }
00293             else if (def->buf.sizelen == (int) sizeof(ub4))
00294             {
00295                 *(ub4*)(((ub1 *)def->buf.lens) + (size_t) (def->buf.sizelen*i)) = (ub4) def->col.bufsize;
00296             }
00297         }
00298 
00299         /* Allocate buffer array */
00300 
00301         if (def->col.type == OCI_CDT_LONG)
00302         {
00303             bufsize = (ub4) sizeof(OCI_Long *);
00304         }
00305         else
00306         {
00307             bufsize = def->col.bufsize;
00308         }
00309 
00310         def->buf.data = (void *) OCI_MemAlloc(OCI_IPC_BUFF_ARRAY, (size_t) bufsize,
00311                                                 (size_t) def->buf.count, TRUE);
00312 
00313         res = (def->buf.data != NULL);
00314     }
00315 
00316     /* Allocate descriptor for cursor, lob and file, interval and timestamp */
00317 
00318     if (res == TRUE)
00319     {
00320         if (def->col.dtype != 0)
00321         {
00322             if (def->col.type == OCI_CDT_CURSOR)
00323             {
00324                 for (i = 0; (i < def->buf.count) && (res == TRUE); i++)
00325                 {
00326                     res = (OCI_SUCCESS == OCI_HandleAlloc((dvoid  *) def->rs->stmt->con->env,
00327                                                           (dvoid **) &(def->buf.data[i]),
00328                                                           (ub4) def->col.dtype,
00329                                                           (size_t) 0, (dvoid **) NULL));
00330                 }
00331             }
00332             else
00333             {
00334                 res = (OCI_SUCCESS == OCI_DescriptorArrayAlloc((dvoid  *) def->rs->stmt->con->env,
00335                                                                (dvoid **) def->buf.data,
00336                                                                (ub4) def->col.dtype,
00337                                                                (ub4) def->buf.count,
00338                                                                (size_t) 0, (dvoid **) NULL));
00339 
00340                 if ((res == TRUE) && (def->col.type == OCI_CDT_LOB))
00341                 {
00342                     ub4 empty = 0;
00343 
00344                     for (i = 0; (i < def->buf.count) && (res == TRUE); i++)
00345                     {
00346                         OCI_CALL1
00347                         (
00348                             res, def->rs->stmt->con, def->rs->stmt,
00349 
00350                             OCIAttrSet((dvoid *) def->buf.data[i],  (ub4) def->col.dtype,
00351                                        (void *) &empty, (ub4) sizeof(empty),
00352                                        (ub4) OCI_ATTR_LOBEMPTY, def->rs->stmt->con->err)
00353                         )
00354                     }
00355                 }
00356             }
00357         }
00358     }
00359 
00360     return res;
00361 }
00362 
00363 /* --------------------------------------------------------------------------------------------- *
00364  * OCI_DefineDef
00365  * --------------------------------------------------------------------------------------------- */
00366 
00367 boolean OCI_DefineDef
00368 (
00369     OCI_Define *def,
00370     ub4         position
00371 )
00372 {
00373     boolean res    = TRUE;
00374     ub2 fetch_mode = OCI_DEFAULT;
00375 
00376     OCI_CHECK(def == NULL, FALSE);
00377 
00378     /*check define mode for long columns */
00379 
00380     if (def->col.type == OCI_CDT_LONG)
00381     {
00382         fetch_mode = OCI_DYNAMIC_FETCH;
00383     }
00384 
00385     /* oracle defining */
00386 
00387     OCI_CALL1
00388     (
00389         res, def->rs->stmt->con, def->rs->stmt,
00390 
00391         OCIDefineByPos(def->rs->stmt->stmt,
00392                        (OCIDefine **) &def->buf.handle,
00393                        def->rs->stmt->con->err,
00394                        position,
00395                        (void *) def->buf.data,
00396                        (sb4   ) def->col.bufsize,
00397                        (ub2   ) def->col.icode,
00398                        (void *) def->buf.inds,
00399                        (ub2  *) def->buf.lens,
00400                        (ub2  *) NULL,
00401                        (ub4   ) fetch_mode)
00402     )
00403 
00404     if (def->col.ocode == SQLT_NTY || def->col.ocode == SQLT_REF)
00405     {
00406         OCI_CALL1
00407         (
00408             res, def->rs->stmt->con, def->rs->stmt,
00409 
00410             OCIDefineObject((OCIDefine *) def->buf.handle,
00411                             def->rs->stmt->con->err,
00412                             def->col.typinf->tdo,
00413                             (void **) def->buf.data,
00414                             (ub4   *) NULL,
00415                             (void **) def->buf.obj_inds,
00416                             (ub4   *) NULL)
00417         )
00418     }
00419 
00420     if(( def->col.type == OCI_CDT_TEXT)  ||
00421        ((def->col.type == OCI_CDT_LOB)   && (def->col.subtype != OCI_BLOB))  ||
00422        ((def->col.type == OCI_CDT_FILE)  && (def->col.subtype != OCI_BFILE)) ||
00423        ((def->col.type == OCI_CDT_LONG)  && (def->col.subtype != OCI_BLONG)))
00424     {
00425 
00426         if ((def->col.csfrm == SQLCS_NCHAR) || (OCILib.nls_utf8 == TRUE))
00427         {
00428             ub1 csfrm = SQLCS_NCHAR;
00429 
00430             OCI_CALL1
00431             (
00432                 res, def->rs->stmt->con, def->rs->stmt,
00433 
00434                 OCIAttrSet((dvoid *) def->buf.handle,
00435                            (ub4    ) OCI_HTYPE_DEFINE,
00436                            (dvoid *) &csfrm,
00437                            (ub4    ) sizeof(csfrm),
00438                            (ub4    ) OCI_ATTR_CHARSET_FORM,
00439                            def->rs->stmt->con->err)
00440             )
00441         }
00442 
00443     #ifdef OCI_CHARSET_MIXED
00444 
00445         /* setup Unicode mode for user data on mixed builds */
00446         {
00447             ub2 csid = OCI_UTF16ID;
00448 
00449             OCI_CALL1
00450             (
00451                 res, def->rs->stmt->con, def->rs->stmt,
00452 
00453                 OCIAttrSet((dvoid *) def->buf.handle,
00454                            (ub4    ) OCI_HTYPE_DEFINE,
00455                            (dvoid *) &csid,
00456                            (ub4    ) sizeof(csid),
00457                            (ub4    ) OCI_ATTR_CHARSET_ID,
00458                            def->rs->stmt->con->err)
00459             )
00460         }
00461 
00462     #endif
00463 
00464     }
00465 
00466     return res;
00467 }
00468 
00469 /* --------------------------------------------------------------------------------------------- *
00470  * OCI_DefineRequestBuffer
00471  * --------------------------------------------------------------------------------------------- */
00472 
00473 boolean OCI_DefineRequestBuffer
00474 (
00475     OCI_Define  *def,
00476     unsigned int size
00477 )
00478 {
00479     boolean res = TRUE;
00480 
00481     size++;
00482 
00483     if (OCILib.nls_utf8 == TRUE)
00484     {
00485         size *= UTF8_BYTES_PER_CHAR;
00486     }
00487     else
00488     {
00489         size *= sizeof(dtext);
00490     }
00491 
00492     if (def->buf.tmpbuf == NULL)
00493     {
00494         def->buf.tmpbuf = (dtext *) OCI_MemAlloc(OCI_IPC_STRING, (size_t) size, (size_t) 1, TRUE);
00495 
00496         if (def->buf.tmpbuf != NULL)
00497         {
00498             def->buf.tmpsize = size;
00499         }
00500         else
00501         {
00502             res = FALSE;
00503         }
00504 
00505     }
00506     else if (def->buf.tmpsize < size)
00507     {
00508         def->buf.tmpbuf = (dtext *) OCI_MemRealloc(def->buf.tmpbuf, OCI_IPC_STRING, (size_t) size, (size_t) 1);
00509 
00510         if (def->buf.tmpbuf != NULL)
00511         {
00512             def->buf.tmpsize = size;
00513         }
00514         else
00515         {
00516             res = FALSE;
00517         }
00518     }
00519 
00520     if (def->buf.tmpbuf != NULL)
00521     {
00522         def->buf.tmpbuf[0] = 0;
00523     }
00524 
00525     return res;
00526 }