C:/Users/vincent/Data/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    +----------------------------------------------------------------------+
00009    |                      Website : http://www.ocilib.net                 |
00010    +----------------------------------------------------------------------+
00011    |               Copyright (c) 2007-2009 Vincent ROGIER                 |
00012    +----------------------------------------------------------------------+
00013    | This library is free software; you can redistribute it and/or        |
00014    | modify it under the terms of the GNU Lesser General Public           |
00015    | License as published by the Free Software Foundation; either         |
00016    | version 2 of the License, or (at your option) any later version.     |
00017    |                                                                      |
00018    | This library is distributed in the hope that it will be useful,      |
00019    | but WITHOUT ANY WARRANTY; without even the implied warranty of       |
00020    | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU    |
00021    | Lesser General Public License for more details.                      |
00022    |                                                                      |
00023    | You should have received a copy of the GNU Lesser General Public     |
00024    | License along with this library; if not, write to the Free           |
00025    | Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.   |
00026    +----------------------------------------------------------------------+
00027    |          Author: Vincent ROGIER <vince.rogier@gmail.com>             |
00028    +----------------------------------------------------------------------+
00029 */
00030 
00031 /* ------------------------------------------------------------------------ *
00032  * $Id: define.c, v 3.4.0 2009-07-30 17:40 Vince $
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(OCI_Resultset *rs, unsigned int index)
00046 {
00047     OCI_CHECK_PTR(OCI_IPC_RESULTSET, rs, NULL);
00048     OCI_CHECK_BOUND(rs->stmt->con, index,  1,  rs->nb_defs, NULL);
00049 
00050     return &rs->defs[index-1];
00051 }
00052 
00053 /* ------------------------------------------------------------------------ *
00054  * OCI_GetDefineIndex
00055  * ------------------------------------------------------------------------ */
00056 
00057 int OCI_GetDefineIndex(OCI_Resultset *rs, const mtext *name)
00058 {
00059     OCI_HashEntry *he = NULL;
00060     int index         = -1;
00061 
00062     OCI_CHECK_PTR(OCI_IPC_RESULTSET, rs, -1);
00063     OCI_CHECK_PTR(OCI_IPC_STRING, name, -1);
00064 
00065     if (rs->map == NULL)
00066     {
00067         /* create the map at the first call to OCI_Getxxxxx2() to save
00068            time and memory when it's not needed */
00069 
00070         rs->map = OCI_HashCreate(OCI_HASH_DEFAULT_SIZE, OCI_HASH_INTEGER);
00071 
00072         if (rs->map != NULL)
00073         {
00074             ub4 i;
00075 
00076             for (i = 0; i < rs->nb_defs; i++)
00077             {
00078                OCI_HashAddInt(rs->map, rs->defs[i].col.name, (i+1));
00079             }
00080         }
00081     }
00082 
00083     /* check out we got our map object */
00084 
00085     OCI_CHECK(rs->map == NULL, -1);
00086 
00087     he = OCI_HashLookup(rs->map, name, FALSE);
00088 
00089     while (he != NULL)
00090     {
00091         /* no more entries or key matched => so we got it ! */
00092 
00093         if (he->next == NULL || mtscasecmp(he->key, name) == 0)
00094         {
00095             index = he->values->value.num;
00096             break;
00097         }
00098     }
00099 
00100     return index;
00101 }
00102 
00103 /* ------------------------------------------------------------------------ *
00104  * OCI_DefineGetData
00105  * ------------------------------------------------------------------------ */
00106 
00107 void * OCI_DefineGetData(OCI_Define *def)
00108 {
00109     OCI_CHECK(def == NULL, NULL);
00110     OCI_CHECK(def->rs->row_cur < 1, NULL);
00111 
00112     switch (def->col.type)
00113     {
00114         case OCI_CDT_LONG:
00115         case OCI_CDT_CURSOR:
00116         case OCI_CDT_TIMESTAMP:
00117         case OCI_CDT_INTERVAL:
00118         case OCI_CDT_LOB:
00119         case OCI_CDT_FILE:
00120         case OCI_CDT_OBJECT:
00121         case OCI_CDT_COLLECTION:
00122         case OCI_CDT_REF:
00123 
00124             /* handle based types */
00125 
00126             return def->buf.data[def->rs->row_cur-1];
00127 
00128         default:
00129 
00130             /* scalar types */
00131 
00132             return (((ub1*)def->buf.data) + (def->col.bufsize  * (def->rs->row_cur-1)));
00133     }
00134 }
00135 
00136 /* ------------------------------------------------------------------------ *
00137  * OCI_DefineGetNumber
00138  * ------------------------------------------------------------------------ */
00139 
00140 boolean OCI_DefineGetNumber(OCI_Resultset *rs, unsigned int index, void *value,
00141                             uword type, uword size)
00142 {
00143     OCI_Define *def = OCI_GetDefine(rs, index);
00144     boolean res     = FALSE;
00145 
00146     if (OCI_NOT_NULL(def) == TRUE)
00147     {
00148         void *data = OCI_DefineGetData(def);
00149 
00150         switch (def->col.type)
00151         {
00152             case OCI_CDT_NUMERIC:
00153             {
00154                 res = OCI_NumberGet(rs->stmt->con, (OCINumber *) data, value,
00155                                     size, type);
00156                 break;
00157             }
00158             case OCI_CDT_TEXT:
00159             {
00160                 const mtext *fmt = OCI_GetDefaultFormatNumeric(rs->stmt->con);
00161                 ub4 fmt_size     = (ub4) mtslen(fmt);
00162 
00163                 res = OCI_NumberGetFromStr(rs->stmt->con, value, size, type,
00164                                            (dtext *) data,
00165                                            (int) dtslen((dtext *) data),
00166                                            fmt, fmt_size);
00167                 break;
00168             }
00169         }
00170     }
00171 
00172     OCI_RESULT(res);
00173 
00174     return res;
00175 }
00176 
00177 /* ------------------------------------------------------------------------ *
00178  * OCI_DefineAlloc
00179  * ------------------------------------------------------------------------ */
00180 
00181 boolean OCI_DefineAlloc(OCI_Define *def)
00182 {
00183     boolean res = TRUE;
00184     ub4 bufsize = 0;
00185     ub4 indsize = 0;
00186     ub4 i;
00187 
00188     /* this function allocates internal buffers, handles, indicators, arrays, ...
00189        for the given output define handle */
00190 
00191     OCI_CHECK(def == NULL, FALSE);
00192 
00193     /* Allocate null indicators array */
00194 
00195     if (def->col.ocode == SQLT_NTY || def->col.ocode == SQLT_REF)
00196         indsize = (ub4) sizeof(void*);
00197     else
00198         indsize = (ub4) sizeof(sb2);
00199 
00200     if (res == TRUE)
00201     {
00202         def->buf.inds = (void *) OCI_MemAlloc(OCI_IPC_INDICATOR_ARRAY,
00203                                               (int) indsize, def->buf.count, TRUE);
00204         res = (def->buf.inds != NULL);
00205     }
00206 
00207     /* Allocate row data sizes array */
00208 
00209     if (res == TRUE)
00210     {
00211         def->buf.lens = (void *) OCI_MemAlloc(OCI_IPC_LEN_ARRAY, def->buf.sizelen,
00212                                               def->buf.count, TRUE);
00213 
00214         res = (def->buf.lens != NULL);
00215     }
00216 
00217     /* initialize length array with buffer default size.
00218        But, Oracle uses different sizes for static fetch and callback fetch....*/
00219 
00220     if (res == TRUE)
00221     {
00222         for (i=0; i < def->buf.count; i++)
00223         {
00224             if (def->buf.sizelen == sizeof(ub2))
00225                 *(ub2*)(((ub1 *)def->buf.lens) + def->buf.sizelen*(i)) = (ub2) def->col.bufsize;
00226             else if (def->buf.sizelen == sizeof(ub4))
00227                 *(ub4*)(((ub1 *)def->buf.lens) + def->buf.sizelen*(i)) = (ub4) def->col.bufsize;
00228        }
00229     }
00230 
00231     /* Allocate buffer array */
00232 
00233     if (res == TRUE)
00234     {
00235         if (def->col.type == OCI_CDT_LONG)
00236             bufsize = (ub4) sizeof(OCI_Long *);
00237         else
00238             bufsize = def->col.bufsize;
00239 
00240         def->buf.data = (void *) OCI_MemAlloc(OCI_IPC_BUFF_ARRAY, (int) bufsize,
00241                                               def->buf.count, TRUE);
00242 
00243         res = (def->buf.data != NULL);
00244     }
00245 
00246     /* Allocate descriptor for cursor, lob and file, interval and timestamp */
00247 
00248     if (res == TRUE)
00249     {
00250         if (def->col.dtype != 0)
00251         {
00252             for (i = 0; i < def->buf.count; i++)
00253             {
00254                 if (def->col.type == OCI_CDT_CURSOR)
00255                 {
00256                     res = (OCI_SUCCESS == OCI_HandleAlloc((dvoid  *) OCILib.env,
00257                                                           (dvoid **) &(def->buf.data[i]),
00258                                                           (ub4) def->col.dtype,
00259                                                           (size_t) 0, (dvoid **) NULL));
00260                 }
00261                 else
00262                 {
00263                     res = (OCI_SUCCESS == OCI_DescriptorAlloc((dvoid  *) OCILib.env,
00264                                                               (dvoid **) &(def->buf.data[i]),
00265                                                               (ub4) def->col.dtype,
00266                                                               (size_t) 0, (dvoid **) NULL));
00267 
00268                     if ((res == TRUE) && (def->col.type == OCI_CDT_LOB))
00269                     {
00270                         ub4 empty = 0;
00271 
00272                         OCI_CALL1
00273                         (
00274                             res, def->rs->stmt->con, def->rs->stmt,
00275 
00276                             OCIAttrSet((dvoid *) def->buf.data[i],
00277                                        (ub4) def->col.dtype,
00278                                        (void *) &empty, (ub4) sizeof(empty),
00279                                        (ub4) OCI_ATTR_LOBEMPTY,
00280                                        def->rs->stmt->con->err)
00281                         )
00282                     }
00283                 }
00284 
00285                 if (res == FALSE)
00286                     break;
00287             }
00288         }
00289     }
00290 
00291     return res;
00292 }
00293 
00294 /* ------------------------------------------------------------------------ *
00295  * OCI_DefineDef
00296  * ------------------------------------------------------------------------ */
00297 
00298 boolean OCI_DefineDef(OCI_Define *def)
00299 {
00300     boolean res    = TRUE;
00301     ub2 fetch_mode = 0;
00302 
00303     OCI_CHECK(def == NULL, FALSE);
00304 
00305     /*check define mode for long columns */
00306 
00307     if (def->col.type == OCI_CDT_LONG)
00308         fetch_mode = OCI_DYNAMIC_FETCH;
00309     else
00310         fetch_mode = OCI_DEFAULT;
00311 
00312     /* oracle defining */
00313 
00314     OCI_CALL1
00315     (
00316         res, def->rs->stmt->con, def->rs->stmt,
00317 
00318         OCIDefineByPos(def->rs->stmt->stmt,
00319                        (OCIDefine **) &def->buf.handle,
00320                        def->rs->stmt->con->err,
00321                        def->rs->nb_defs,
00322                        (void *) def->buf.data,
00323                        (sb4   ) def->col.bufsize,
00324                        (ub2   ) def->col.icode,
00325                        (void *) def->buf.inds,
00326                        (ub2  *) def->buf.lens,
00327                        (ub2  *) NULL,
00328                        (ub4   ) fetch_mode)
00329     )
00330 
00331     if (def->col.ocode == SQLT_NTY || def->col.ocode == SQLT_REF)
00332     {
00333         OCI_CALL1
00334         (
00335             res, def->rs->stmt->con, def->rs->stmt,
00336 
00337             OCIDefineObject((OCIDefine *) def->buf.handle,
00338                             def->rs->stmt->con->err,
00339                             def->col.typinf->tdo,
00340                             (void **) def->buf.data,
00341                             (ub4   *) NULL,
00342                            (void **) def->buf.inds,
00343                             (ub4   *) NULL)
00344         )
00345     }
00346 
00347     if (def->col.csfrm == SQLCS_NCHAR
00348 #ifdef OCI_USERDATA_UNICODE
00349         || (def->col.type == OCI_CDT_TEXT && OCILib.version_runtime >= OCI_9_0)
00350 #endif
00351         )
00352     {
00353         ub1 csfrm = SQLCS_NCHAR;
00354 
00355         OCI_CALL1
00356         (
00357             res, def->rs->stmt->con, def->rs->stmt,
00358 
00359             OCIAttrSet((dvoid *) def->buf.handle,
00360                        (ub4    ) OCI_HTYPE_DEFINE,
00361                        (dvoid *) &csfrm,
00362                        (ub4    ) sizeof(csfrm),
00363                        (ub4    ) OCI_ATTR_CHARSET_FORM,
00364                        def->rs->stmt->con->err)
00365         )
00366     }
00367 
00368 #ifdef OCI_CHARSET_MIXED
00369 
00370     /* setup Unicode mode for user data on mixed builds */
00371     {
00372         ub2 csid = OCI_UTF16ID;
00373 
00374         OCI_CALL1
00375         (
00376             res, def->rs->stmt->con, def->rs->stmt,
00377 
00378             OCIAttrSet((dvoid *) def->buf.handle,
00379                        (ub4    ) OCI_HTYPE_DEFINE,
00380                        (dvoid *) &csid,
00381                        (ub4    ) sizeof(csid),
00382                        (ub4    ) OCI_ATTR_CHARSET_ID,
00383                        def->rs->stmt->con->err)
00384         )
00385     }
00386 
00387 #endif
00388 
00389     return res;
00390 }

Generated on Thu Jul 30 17:41:52 2009 for OCILIB (C Driver for Oracle) by  doxygen 1.5.4