OCILIB (C Driver for Oracle) 3.12.1
lob.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: lob.c, Vincent Rogier $
00033  * --------------------------------------------------------------------------------------------- */
00034 
00035 #include "ocilib_internal.h"
00036 
00037 /* ********************************************************************************************* *
00038  *                             PRIVATE FUNCTIONS
00039  * ********************************************************************************************* */
00040 
00041 /* --------------------------------------------------------------------------------------------- *
00042  * OCI_LobInit
00043  * --------------------------------------------------------------------------------------------- */
00044 
00045 OCI_Lob * OCI_LobInit
00046 (
00047     OCI_Connection *con,
00048     OCI_Lob       **plob,
00049     OCILobLocator  *handle,
00050     ub4             type
00051 )
00052 {
00053     OCI_Lob * lob = NULL;
00054     boolean res   = TRUE;
00055 
00056     OCI_CHECK(plob == NULL, NULL);
00057 
00058     if (*plob == NULL)
00059     {
00060         *plob = (OCI_Lob *) OCI_MemAlloc(OCI_IPC_LOB, sizeof(*lob), (size_t) 1, TRUE);
00061     }
00062 
00063     if (*plob != NULL)
00064     {
00065         lob = *plob;
00066 
00067         lob->type   = type;
00068         lob->con    = con;
00069         lob->handle = handle;
00070         lob->offset = 1;
00071 
00072         if ((lob->handle == NULL) || (lob->hstate == OCI_OBJECT_ALLOCATED_ARRAY))
00073         {
00074             ub2 csid    = OCI_DEFAULT;
00075             ub1 csfrm   = OCI_DEFAULT;
00076             ub1 lobtype = 0;
00077             ub4 empty   = 0;
00078 
00079             if (lob->type == OCI_NCLOB)
00080             {
00081                 csfrm   = SQLCS_NCHAR;
00082                 lobtype = OCI_TEMP_CLOB;
00083             }
00084             else if (lob->type == OCI_CLOB)
00085             {
00086                 csfrm   = SQLCS_IMPLICIT;
00087                 lobtype = OCI_TEMP_CLOB;
00088             }
00089             else
00090             {
00091                 lobtype = OCI_TEMP_BLOB;
00092             }
00093 
00094             /* allocate handle for non fetched lob (temporary lob) */
00095 
00096             if (lob->hstate != OCI_OBJECT_ALLOCATED_ARRAY)
00097             {
00098                 lob->hstate = OCI_OBJECT_ALLOCATED;
00099 
00100                 res = (OCI_SUCCESS == OCI_DescriptorAlloc((dvoid  *) lob->con->env,
00101                                                           (dvoid **) (void *) &lob->handle,
00102                                                           (ub4) OCI_DTYPE_LOB,
00103                                                           (size_t) 0, (dvoid **) NULL));
00104             }
00105 
00106             OCI_CALL2
00107             (
00108                 res, lob->con,
00109 
00110                 OCIAttrSet((dvoid *) lob->handle, (ub4) OCI_DTYPE_LOB,
00111                            (dvoid *) &empty, (ub4) sizeof(empty),
00112                            (ub4) OCI_ATTR_LOBEMPTY, lob->con->err)
00113             )
00114 
00115             OCI_CALL2
00116             (
00117                 res, lob->con,
00118 
00119                 OCILobCreateTemporary(lob->con->cxt, lob->con->err,
00120                                       lob->handle, csid, csfrm, lobtype,
00121                                       FALSE, OCI_DURATION_SESSION)
00122             )
00123 
00124         }
00125         else
00126         {
00127             lob->hstate = OCI_OBJECT_FETCHED_CLEAN;
00128         }
00129     }
00130     else
00131     {
00132         res = FALSE;
00133     }
00134 
00135     /* check for failure */
00136 
00137     if (res == FALSE)
00138     {
00139         OCI_LobFree(lob);
00140         lob = NULL;
00141     }
00142 
00143     return lob;
00144 }
00145 
00146 /* ********************************************************************************************* *
00147  *                            PUBLIC FUNCTIONS
00148  * ********************************************************************************************* */
00149 
00150 /* --------------------------------------------------------------------------------------------- *
00151  * OCI_LobCreate
00152  * --------------------------------------------------------------------------------------------- */
00153 
00154 OCI_Lob * OCI_API OCI_LobCreate
00155 (
00156     OCI_Connection *con,
00157     unsigned int    type
00158 )
00159 {
00160     OCI_Lob *lob = NULL;
00161 
00162     OCI_CHECK_PTR(OCI_IPC_CONNECTION, con, NULL);
00163 
00164     lob = OCI_LobInit(con, &lob, NULL, type);
00165 
00166     OCI_RESULT(lob != NULL);
00167 
00168     return lob;
00169 }
00170 
00171 /* --------------------------------------------------------------------------------------------- *
00172  * OCI_LobFree
00173  * --------------------------------------------------------------------------------------------- */
00174 
00175 boolean OCI_API OCI_LobFree
00176 (
00177     OCI_Lob *lob
00178 )
00179 {
00180     boolean res = TRUE;
00181 
00182     OCI_CHECK_PTR(OCI_IPC_LOB, lob, FALSE);
00183 
00184     OCI_CHECK_OBJECT_FETCHED(lob, FALSE);
00185 
00186     if (OCI_LobIsTemporary(lob) == TRUE)
00187     {
00188         OCI_CALL2
00189         (
00190             res, lob->con,
00191 
00192             OCILobFreeTemporary(lob->con->cxt, lob->con->err, lob->handle)
00193         )
00194     }
00195 
00196     if (lob->hstate == OCI_OBJECT_ALLOCATED)
00197     {
00198         OCI_DescriptorFree((dvoid *) lob->handle, (ub4) OCI_DTYPE_LOB);
00199     }
00200 
00201     if (lob->hstate != OCI_OBJECT_ALLOCATED_ARRAY)
00202     {
00203         OCI_FREE(lob);
00204     }
00205 
00206     OCI_RESULT(res);
00207 
00208     return res;
00209 }
00210 
00211 /* --------------------------------------------------------------------------------------------- *
00212  * OCI_LobArrayCreate
00213  * --------------------------------------------------------------------------------------------- */
00214 
00215 OCI_Lob ** OCI_API OCI_LobArrayCreate
00216 (
00217     OCI_Connection *con,
00218     unsigned int    type,
00219     unsigned int    nbelem
00220 )
00221 {
00222     OCI_Array *arr = NULL;
00223     OCI_Lob **lobs = NULL;
00224 
00225     arr = OCI_ArrayCreate(con, nbelem, OCI_CDT_LOB, type, sizeof(OCILobLocator *),
00226                           sizeof(OCI_Lob), OCI_DTYPE_LOB, NULL);
00227 
00228     if (arr != NULL)
00229     {
00230         lobs = (OCI_Lob **) arr->tab_obj;
00231     }
00232 
00233     return lobs;
00234 }
00235 
00236 /* --------------------------------------------------------------------------------------------- *
00237  * OCI_LobArrayFree
00238  * --------------------------------------------------------------------------------------------- */
00239 
00240 boolean OCI_API OCI_LobArrayFree
00241 (
00242     OCI_Lob **lobs
00243 )
00244 {
00245     return OCI_ArrayFreeFromHandles((void **) lobs);
00246 }
00247 
00248 /* --------------------------------------------------------------------------------------------- *
00249  * OCI_LobGetType
00250  * --------------------------------------------------------------------------------------------- */
00251 
00252 unsigned int OCI_API OCI_LobGetType
00253 (
00254     OCI_Lob *lob
00255 )
00256 {
00257     OCI_CHECK_PTR(OCI_IPC_LOB, lob, OCI_UNKNOWN);
00258 
00259     OCI_RESULT(TRUE);
00260 
00261     return lob->type;
00262 }
00263 
00264 /* --------------------------------------------------------------------------------------------- *
00265  * OCI_LobSeek
00266  * --------------------------------------------------------------------------------------------- */
00267 
00268 boolean OCI_API OCI_LobSeek
00269 (
00270     OCI_Lob     *lob,
00271     big_uint     offset,
00272     unsigned int mode
00273 )
00274 {
00275     boolean res   = TRUE;
00276     big_uint size = 0;
00277 
00278     OCI_CHECK_PTR(OCI_IPC_LOB, lob, FALSE);
00279 
00280     size = OCI_LobGetLength(lob);
00281 
00282     if ((mode == OCI_SEEK_CUR && (offset + lob->offset-1) > size))
00283     {
00284         res = FALSE;
00285     }
00286     else if (mode == OCI_SEEK_SET)
00287     {
00288         lob->offset = offset + 1;
00289     }
00290     else if (mode == OCI_SEEK_END)
00291     {
00292         lob->offset = size-offset + 1;
00293     }
00294     else if (mode == OCI_SEEK_CUR)
00295     {
00296         lob->offset += offset;
00297     }
00298     else
00299     {
00300         res = FALSE;
00301     }
00302 
00303     OCI_RESULT(res);
00304 
00305     return res;
00306 }
00307 
00308 /* --------------------------------------------------------------------------------------------- *
00309  * OCI_LobGetOffset
00310  * --------------------------------------------------------------------------------------------- */
00311 
00312 big_uint OCI_API OCI_LobGetOffset
00313 (
00314     OCI_Lob *lob
00315 )
00316 {
00317     OCI_CHECK_PTR(OCI_IPC_LOB, lob, 0);
00318 
00319     OCI_RESULT(TRUE);
00320 
00321     return lob->offset - 1;
00322 }
00323 
00324 /* --------------------------------------------------------------------------------------------- *
00325  * OCI_LobRead2
00326  * --------------------------------------------------------------------------------------------- */
00327 
00328 boolean OCI_API OCI_LobRead2
00329 (
00330     OCI_Lob      *lob,
00331     void         *buffer,
00332     unsigned int *char_count,
00333     unsigned int *byte_count
00334 )
00335 {
00336     boolean res = TRUE;
00337     ub1 csfrm   = 0;
00338     ub2 csid    = 0;
00339 
00340     OCI_CHECK_PTR(OCI_IPC_LOB, lob, FALSE);
00341     OCI_CHECK_PTR(OCI_IPC_LOB, char_count, FALSE);
00342     OCI_CHECK_PTR(OCI_IPC_LOB, byte_count, FALSE);
00343 
00344     if (lob->type != OCI_BLOB)
00345     {
00346 
00347     #ifdef OCI_USERDATA_WIDE
00348 
00349         csid = OCI_UTF16ID;
00350 
00351     #endif
00352 
00353         if (((*byte_count) == 0) && ((*char_count) > 0))
00354         {
00355             if (OCILib.nls_utf8 == TRUE)
00356             {
00357                 (*byte_count) = (*char_count) * (ub4) UTF8_BYTES_PER_CHAR;
00358             }
00359             else
00360             {
00361                 (*byte_count) = (*char_count) * (ub4) sizeof(odtext);
00362             }
00363         }
00364     }
00365 
00366     if (lob->type == OCI_NCLOB)
00367     {
00368         csfrm = SQLCS_NCHAR;
00369     }
00370     else
00371     {
00372         csfrm = SQLCS_IMPLICIT;
00373     }
00374 
00375     OCI_CHECK_MIN(lob->con, NULL, (*byte_count), 1, FALSE);
00376 
00377 #ifdef OCI_LOB2_API_ENABLED
00378 
00379     if (OCILib.use_lob_ub8)
00380     {        
00381         ub8 size_in_out_char = (ub8) (*char_count);
00382         ub8 size_in_out_byte = (ub8) (*byte_count);
00383 
00384         OCI_CALL2
00385         (
00386             res, lob->con,
00387 
00388             OCILobRead2(lob->con->cxt, lob->con->err, lob->handle,
00389                         &size_in_out_byte, &size_in_out_char,
00390                         (ub8) lob->offset, buffer,(ub8) (*byte_count),
00391                         (ub1) OCI_ONE_PIECE, (void *) NULL,
00392                         NULL, csid, csfrm)
00393         )
00394 
00395         (*char_count) = (ub4) size_in_out_char;
00396         (*byte_count) = (ub4) size_in_out_byte;
00397     }
00398 
00399     else
00400 
00401 #endif
00402 
00403     {
00404         ub4 size_in_out_char_byte = 0;
00405 
00406         if (lob->type == OCI_BLOB)
00407         {
00408             size_in_out_char_byte = (*byte_count);
00409         }
00410         else
00411         {
00412             size_in_out_char_byte = (*char_count);
00413         }
00414 
00415         OCI_CALL2
00416         (
00417             res, lob->con,
00418 
00419             OCILobRead(lob->con->cxt, lob->con->err, lob->handle,
00420                        &size_in_out_char_byte, (ub4) lob->offset,
00421                        buffer, (ub4) (*byte_count), (void *) NULL,
00422                        NULL, csid, csfrm)
00423         )
00424 
00425         (*char_count) = (ub4) size_in_out_char_byte;
00426         (*byte_count) = (ub4) size_in_out_char_byte;
00427     }
00428 
00429     if (lob->type != OCI_BLOB)
00430     {
00431         ub4 ora_byte_count = (ub4) *byte_count;
00432 
00433         if (OCILib.nls_utf8 == FALSE)
00434         {
00435             ora_byte_count *= sizeof(odtext);
00436         }
00437 
00438         memset(((char *) buffer) + ora_byte_count, 0, sizeof(odtext));
00439 
00440     #ifndef OCI_LOB2_API_ENABLED
00441 
00442         if (OCILib.nls_utf8 == TRUE)
00443         {
00444             (*char_count) = OCI_StringUTF8Length((const char *) buffer);
00445         }
00446 
00447     #endif
00448 
00449     }
00450 
00451     if (res == TRUE)
00452     {
00453         if (lob->type == OCI_BLOB)
00454         {
00455             lob->offset += (big_uint) (*byte_count);
00456         }
00457         else
00458         {
00459             lob->offset += (big_uint) (*char_count);
00460 
00461             if (OCILib.nls_utf8 == FALSE)
00462             {
00463                 OCI_ConvertString(buffer, (int) (*char_count), sizeof(odtext), sizeof(dtext));
00464 
00465                 (*byte_count) = (ub4) (*char_count) * (ub4) sizeof(dtext);
00466             }
00467         }
00468     }
00469 
00470     OCI_RESULT(res);
00471 
00472     return res;
00473 }
00474 
00475 /* --------------------------------------------------------------------------------------------- *
00476  * OCI_LobRead
00477  * --------------------------------------------------------------------------------------------- */
00478 
00479 unsigned int OCI_API OCI_LobRead
00480 (
00481     OCI_Lob     *lob,
00482     void        *buffer,
00483     unsigned int len
00484 )
00485 {
00486     unsigned int char_count = 0;
00487     unsigned int byte_count = 0;
00488     unsigned int *ptr_count = NULL;
00489 
00490     if (lob != NULL)
00491     {
00492         if(lob->type == OCI_BLOB)
00493         {
00494             byte_count = len;
00495             ptr_count  = &byte_count;
00496         }
00497         else
00498         {
00499             char_count = len;
00500             ptr_count  = &char_count;
00501         }
00502     }
00503 
00504     OCI_LobRead2(lob, buffer, &char_count, &byte_count);
00505 
00506     return (ptr_count != NULL ? *ptr_count : 0);
00507 }
00508 
00509 /* --------------------------------------------------------------------------------------------- *
00510  * OCI_LobWrite
00511  * --------------------------------------------------------------------------------------------- */
00512 
00513 boolean OCI_API OCI_LobWrite2
00514 (
00515     OCI_Lob      *lob,
00516     void         *buffer,
00517     unsigned int *char_count,
00518     unsigned int *byte_count
00519 )
00520 {
00521     boolean res   = TRUE;
00522     ub1     csfrm = 0;
00523     ub2     csid  = 0;
00524     void   *obuf  = NULL;
00525 
00526     OCI_CHECK_PTR(OCI_IPC_LOB, char_count, FALSE);
00527     OCI_CHECK_PTR(OCI_IPC_LOB, byte_count, FALSE);
00528 
00529     if (lob->type != OCI_BLOB)
00530     {
00531 
00532     #ifdef OCI_USERDATA_WIDE
00533 
00534         csid = OCI_UTF16ID;
00535 
00536     #endif
00537 
00538         if (((*byte_count) == 0) && ((*char_count) > 0))
00539         {
00540             if (OCILib.nls_utf8 == TRUE)
00541             {
00542                 (*byte_count) = (unsigned int) strlen(buffer);
00543             }
00544             else
00545             {
00546                 (*byte_count) = (*char_count) * (ub4) sizeof(dtext);
00547             }
00548         }
00549 
00550         if (((*char_count) == 0) && ((*byte_count) > 0))
00551         {
00552             if (OCILib.nls_utf8 == TRUE)
00553             {
00554 
00555         #ifndef OCI_LOB2_API_ENABLED
00556 
00557                 (*char_count) = OCI_StringUTF8Length((const char *) buffer);
00558 
00559         #endif
00560 
00561             }
00562             else
00563             {
00564                 (*char_count) = (*byte_count) / (ub4) sizeof(dtext);
00565             }
00566         }
00567 
00568         obuf = OCI_GetInputDataString(buffer, (int *) byte_count);
00569     }
00570     else
00571     {
00572         obuf = buffer;
00573     }
00574 
00575     if (lob->type == OCI_NCLOB)
00576     {
00577         csfrm = SQLCS_NCHAR;
00578     }
00579     else
00580     {
00581         csfrm = SQLCS_IMPLICIT;
00582     }
00583 
00584     OCI_CHECK_MIN(lob->con, NULL, (*byte_count), 1, FALSE);
00585 
00586 #ifdef OCI_LOB2_API_ENABLED
00587 
00588     if (OCILib.use_lob_ub8)
00589     {
00590         ub8 size_in_out_char = (ub8) (*char_count);
00591         ub8 size_in_out_byte = (ub8) (*byte_count);
00592 
00593         OCI_CALL2
00594         (
00595             res, lob->con,
00596 
00597             OCILobWrite2(lob->con->cxt, lob->con->err, lob->handle,
00598                          &size_in_out_byte, &size_in_out_char,
00599                          (ub8) lob->offset, obuf, (ub8) (*byte_count),
00600                          (ub1) OCI_ONE_PIECE, (void *) NULL,
00601                          NULL, csid, csfrm)
00602         )
00603 
00604         (*char_count) = (ub4) size_in_out_char;
00605         (*byte_count) = (ub4) size_in_out_byte;
00606     }
00607 
00608     else
00609 
00610 #endif
00611 
00612     {
00613         ub4 size_in_out_char_byte = 0;
00614 
00615         if ((lob->type == OCI_BLOB) || (OCILib.nls_utf8 == TRUE))
00616         {
00617             size_in_out_char_byte = (*byte_count);
00618         }
00619         else
00620         {
00621             size_in_out_char_byte = (*char_count);
00622         }
00623 
00624         OCI_CALL2
00625         (
00626             res, lob->con,
00627 
00628             OCILobWrite(lob->con->cxt, lob->con->err, lob->handle,
00629                         &size_in_out_char_byte, (ub4) lob->offset,
00630                         obuf, (ub4) (*byte_count), (ub1) OCI_ONE_PIECE,
00631                         (void *) NULL, NULL, csid, csfrm)
00632         )
00633 
00634         if (lob->type == OCI_BLOB)
00635         {
00636             (*char_count) = (ub4) size_in_out_char_byte;
00637             (*byte_count) = (ub4) size_in_out_char_byte;
00638         }
00639         else
00640         {
00641             (*char_count) = (ub4) size_in_out_char_byte;
00642             (*byte_count) = (ub4) size_in_out_char_byte;
00643 
00644             if (OCILib.nls_utf8 == FALSE)
00645             {
00646                 (*byte_count) *= (ub4) sizeof(dtext);
00647             }
00648         }
00649     }
00650 
00651     if (res == TRUE)
00652     {
00653         if (lob->type == OCI_BLOB)
00654         {
00655             lob->offset += (big_uint) (*byte_count);
00656         }
00657         else
00658         {
00659             lob->offset += (big_uint) (*char_count);
00660 
00661             if (OCILib.nls_utf8 == FALSE)
00662             {
00663                 OCI_ReleaseDataString(obuf);
00664             }
00665         }
00666     }
00667 
00668     OCI_RESULT(res);
00669 
00670     return res;
00671 }
00672 
00673 /* --------------------------------------------------------------------------------------------- *
00674  * OCI_LobWrite
00675  * --------------------------------------------------------------------------------------------- */
00676 
00677 unsigned int OCI_API OCI_LobWrite
00678 (
00679     OCI_Lob     *lob,
00680     void        *buffer,
00681     unsigned int len
00682 )
00683 {
00684     unsigned int char_count = 0;
00685     unsigned int byte_count = 0;
00686     unsigned int *ptr_count = NULL;
00687 
00688     if (lob != NULL)
00689     {
00690         if(lob->type == OCI_BLOB)
00691         {
00692             byte_count = len;
00693             ptr_count  = &byte_count;
00694         }
00695         else
00696         {
00697             char_count = len;
00698             ptr_count  = &char_count;
00699         }
00700     }
00701 
00702     OCI_LobWrite2(lob, buffer, &char_count, &byte_count);
00703 
00704     return (ptr_count  != NULL ? *ptr_count : 0);
00705 }
00706 
00707 /* --------------------------------------------------------------------------------------------- *
00708  * OCI_LobTruncate
00709  * --------------------------------------------------------------------------------------------- */
00710 
00711 boolean OCI_API OCI_LobTruncate
00712 (
00713     OCI_Lob *lob,
00714     big_uint size
00715 )
00716 {
00717     boolean res = TRUE;
00718 
00719     OCI_CHECK_PTR(OCI_IPC_LOB, lob, FALSE);
00720 
00721 #ifdef OCI_LOB2_API_ENABLED
00722 
00723     if (OCILib.use_lob_ub8)
00724     {
00725         OCI_CALL2
00726         (
00727             res, lob->con,
00728 
00729             OCILobTrim2(lob->con->cxt, lob->con->err, lob->handle, (ub8) size)
00730         )
00731     }
00732     else
00733 
00734 #endif
00735 
00736     {
00737         OCI_CALL2
00738         (
00739             res, lob->con,
00740 
00741             OCILobTrim(lob->con->cxt, lob->con->err, lob->handle, (ub4) size)
00742         )
00743     }
00744 
00745     OCI_RESULT(res);
00746 
00747     return res;
00748 }
00749 
00750 /* --------------------------------------------------------------------------------------------- *
00751  * OCI_LobErase
00752  * --------------------------------------------------------------------------------------------- */
00753 
00754 big_uint OCI_API OCI_LobErase
00755 (
00756     OCI_Lob *lob,
00757     big_uint offset,
00758     big_uint size
00759 )
00760 {
00761     boolean res = TRUE;
00762 
00763     OCI_CHECK_PTR(OCI_IPC_LOB, lob, 0);
00764     OCI_CHECK_MIN(lob->con, NULL, size, 1, 0);
00765 
00766 #ifdef OCI_LOB2_API_ENABLED
00767 
00768     if (OCILib.use_lob_ub8)
00769     {
00770         ub8 lob_size = (ub8) size;
00771 
00772         OCI_CALL2
00773         (
00774             res, lob->con,
00775 
00776             OCILobErase2(lob->con->cxt, lob->con->err, lob->handle, (ub8 *) &lob_size, (ub8) (offset + 1))
00777         )
00778 
00779         size = (big_uint) lob_size;
00780     }
00781     else
00782 
00783 #endif
00784 
00785     {
00786         ub4 lob_size = (ub4) size;
00787 
00788         OCI_CALL2
00789         (
00790             res, lob->con,
00791 
00792             OCILobErase(lob->con->cxt, lob->con->err, lob->handle,  &lob_size, (ub4) offset + 1)
00793         )
00794 
00795         size = (big_uint) lob_size;
00796     }
00797 
00798     OCI_RESULT(res);
00799 
00800     return size;
00801 }
00802 
00803 /* --------------------------------------------------------------------------------------------- *
00804  * OCI_LobGetLength
00805  * --------------------------------------------------------------------------------------------- */
00806 
00807 big_uint OCI_API OCI_LobGetLength
00808 (
00809     OCI_Lob *lob
00810 )
00811 {
00812     boolean res   = TRUE;
00813     big_uint size = 0;
00814 
00815     OCI_CHECK_PTR(OCI_IPC_LOB, lob, 0);
00816 
00817 #ifdef OCI_LOB2_API_ENABLED
00818 
00819     if (OCILib.use_lob_ub8)
00820     {
00821         ub8 lob_size = 0;
00822 
00823         OCI_CALL2
00824         (
00825             res, lob->con,
00826 
00827             OCILobGetLength2(lob->con->cxt, lob->con->err, lob->handle, (ub8 *) &lob_size)
00828         )
00829 
00830         size = (big_uint) lob_size;
00831     }
00832     else
00833 
00834 #endif
00835 
00836     {
00837         ub4 lob_size = 0;
00838 
00839         OCI_CALL2
00840         (
00841             res, lob->con,
00842 
00843             OCILobGetLength(lob->con->cxt, lob->con->err, lob->handle, &lob_size)
00844         )
00845 
00846         size = (big_uint) lob_size;
00847     }
00848 
00849     OCI_RESULT(res);
00850 
00851     return size;
00852 }
00853 
00854 /* --------------------------------------------------------------------------------------------- *
00855  * OCI_LobGetChunkSize
00856  * --------------------------------------------------------------------------------------------- */
00857 
00858 unsigned int OCI_API OCI_LobGetChunkSize
00859 (
00860     OCI_Lob *lob
00861 )
00862 {
00863     boolean res = TRUE;
00864     ub4 size    = 0;
00865 
00866     OCI_CHECK_PTR(OCI_IPC_LOB, lob, 0);
00867 
00868     OCI_CALL2
00869     (
00870         res, lob->con,
00871 
00872         OCILobGetChunkSize(lob->con->cxt, lob->con->err, lob->handle, &size)
00873     )
00874 
00875     OCI_RESULT(res);
00876 
00877     return (unsigned int) size;
00878 }
00879 
00880 /* --------------------------------------------------------------------------------------------- *
00881  * OCI_LobCopy
00882  * --------------------------------------------------------------------------------------------- */
00883 
00884 boolean OCI_API OCI_LobCopy
00885 (
00886     OCI_Lob *lob,
00887     OCI_Lob *lob_src,
00888     big_uint offset_dst,
00889     big_uint offset_src,
00890     big_uint count
00891 )
00892 {
00893     boolean res = TRUE;
00894 
00895     OCI_CHECK_PTR(OCI_IPC_LOB, lob,     FALSE);
00896     OCI_CHECK_PTR(OCI_IPC_LOB, lob_src, FALSE);
00897 
00898 #ifdef OCI_LOB2_API_ENABLED
00899 
00900     if (OCILib.use_lob_ub8)
00901     {
00902 
00903         OCI_CALL2
00904         (
00905             res, lob->con,
00906 
00907             OCILobCopy2(lob->con->cxt, lob->con->err, lob->handle,
00908                         lob_src->handle, (ub8) count,
00909                         (ub8) (offset_dst + 1),
00910                         (ub8) (offset_src + 1))
00911         )
00912     }
00913     else
00914 
00915 #endif
00916 
00917 {
00918         OCI_CALL2
00919         (
00920             res, lob->con,
00921 
00922             OCILobCopy(lob->con->cxt, lob->con->err, lob->handle,
00923                        lob_src->handle, (ub4) count,
00924                        (ub4) (offset_dst + 1),
00925                        (ub4) (offset_src + 1))
00926         )
00927     }
00928 
00929     OCI_RESULT(res);
00930 
00931     return res;
00932 }
00933 
00934 /* --------------------------------------------------------------------------------------------- *
00935  * OCI_LobCopyFromFile
00936  * --------------------------------------------------------------------------------------------- */
00937 
00938 boolean OCI_API OCI_LobCopyFromFile
00939 (
00940     OCI_Lob  *lob,
00941     OCI_File *file,
00942     big_uint  offset_dst,
00943     big_uint  offset_src,
00944     big_uint  count
00945 )
00946 {
00947     boolean res = TRUE;
00948 
00949     OCI_CHECK_PTR(OCI_IPC_LOB, lob,   FALSE);
00950     OCI_CHECK_PTR(OCI_IPC_FILE, file, FALSE);
00951 
00952 #ifdef OCI_LOB2_API_ENABLED
00953 
00954     if (OCILib.use_lob_ub8)
00955     {
00956         OCI_CALL2
00957         (
00958             res, lob->con,
00959 
00960             OCILobLoadFromFile2(lob->con->cxt, lob->con->err,
00961                                 lob->handle, file->handle,
00962                                 (ub8) count,
00963                                 (ub8) (offset_dst + 1),
00964                                 (ub8) (offset_src + 1))
00965         )
00966     }
00967     else
00968 
00969 #endif
00970 
00971     {
00972         OCI_CALL2
00973         (
00974             res, lob->con,
00975 
00976             OCILobLoadFromFile(lob->con->cxt, lob->con->err,
00977                                lob->handle, file->handle,
00978                                (ub4) count,
00979                                (ub4) (offset_dst + 1),
00980                                (ub4) (offset_src + 1))
00981         )
00982     }
00983 
00984     OCI_RESULT(res);
00985 
00986     return res;
00987 }
00988 
00989 /* --------------------------------------------------------------------------------------------- *
00990  * OCI_LobAppend2
00991  * --------------------------------------------------------------------------------------------- */
00992 
00993 boolean OCI_API OCI_LobAppend2
00994 (
00995     OCI_Lob      *lob,
00996     void         *buffer,
00997     unsigned int *char_count,
00998     unsigned int *byte_count
00999 )
01000 {
01001     boolean res   = TRUE;
01002     ub1     csfrm = 0;
01003     ub2     csid  = 0;
01004     void   *obuf  = NULL;
01005 
01006     OCI_CHECK_PTR(OCI_IPC_LOB, char_count, FALSE);
01007     OCI_CHECK_PTR(OCI_IPC_LOB, byte_count, FALSE);
01008 
01009     /* OCILobWriteAppend() seems to cause problems on Oracle client 8.1 and 9.0
01010        It's an Oracle known bug #886191
01011        So we use OCI_LobSeek() + OCI_LobWrite() instead */
01012 
01013     if (OCILib.version_runtime < OCI_10_1)
01014     {
01015         return OCI_LobSeek(lob, OCI_LobGetLength(lob), OCI_SEEK_SET) &&
01016                OCI_LobWrite2(lob, buffer, char_count, byte_count);
01017     }
01018 
01019     if (lob->type != OCI_BLOB)
01020     {
01021     #ifdef OCI_USERDATA_WIDE
01022 
01023         csid = OCI_UTF16ID;
01024 
01025     #endif
01026 
01027         if (((*byte_count) == 0) && ((*char_count) > 0))
01028         {
01029             if (OCILib.nls_utf8 == TRUE)
01030             {
01031                 (*byte_count) = (unsigned int) strlen(buffer);
01032             }
01033             else
01034             {
01035                 (*byte_count) = (*char_count) * (ub4) sizeof(dtext);
01036             }
01037         }
01038 
01039         if (((*char_count) == 0) && ((*byte_count) > 0))
01040         {
01041             if (OCILib.nls_utf8 == TRUE)
01042             {
01043 
01044             #ifndef OCI_LOB2_API_ENABLED
01045 
01046                 (*char_count) = OCI_StringUTF8Length((const char *) buffer);
01047 
01048             #endif
01049 
01050             }
01051             else
01052             {
01053                 (*char_count) = (*byte_count) / (ub4) sizeof(dtext);
01054             }
01055         }
01056 
01057         obuf = OCI_GetInputDataString(buffer, (int *) byte_count);
01058     }
01059     else
01060     {
01061         obuf = buffer;
01062     }
01063 
01064     if (lob->type == OCI_NCLOB)
01065     {
01066         csfrm = SQLCS_NCHAR;
01067     }
01068     else
01069     {
01070         csfrm = SQLCS_IMPLICIT;
01071     }
01072 
01073     OCI_CHECK_MIN(lob->con, NULL, (*byte_count), 1, FALSE);
01074 
01075 #ifdef OCI_LOB2_API_ENABLED
01076 
01077     if (OCILib.use_lob_ub8)
01078     {
01079         ub8 size_in_out_char = (ub8) (*char_count);
01080         ub8 size_in_out_byte = (ub8) (*byte_count);
01081 
01082         OCI_CALL2
01083         (
01084             res, lob->con,
01085 
01086             OCILobWriteAppend2(lob->con->cxt, lob->con->err, lob->handle,
01087                                &size_in_out_byte, &size_in_out_char,
01088                                obuf, (ub8)  (*byte_count), (ub1) OCI_ONE_PIECE,
01089                                (dvoid *) NULL, NULL, csid, csfrm)
01090         )
01091 
01092         (*char_count) = (ub4) size_in_out_char;
01093         (*byte_count) = (ub4) size_in_out_byte;
01094     }
01095 
01096     else
01097 
01098 #endif
01099 
01100     {
01101         ub4 size_in_out_char_byte = 0;
01102 
01103         if ((lob->type == OCI_BLOB) || (OCILib.nls_utf8 == TRUE))
01104         {
01105             size_in_out_char_byte = (*byte_count);
01106         }
01107         else
01108         {
01109             size_in_out_char_byte = (*char_count);
01110         }
01111 
01112         OCI_CALL2
01113         (
01114             res, lob->con,
01115 
01116             OCILobWriteAppend(lob->con->cxt, lob->con->err, lob->handle,
01117                               &size_in_out_char_byte, obuf,  (*byte_count),
01118                               (ub1) OCI_ONE_PIECE, (dvoid *) NULL, NULL, csid, csfrm)
01119         )
01120 
01121         if (lob->type == OCI_BLOB)
01122         {
01123             (*char_count) = (ub4) size_in_out_char_byte;
01124             (*byte_count) = (ub4) size_in_out_char_byte;
01125         }
01126         else
01127         {
01128             (*char_count) = (ub4) size_in_out_char_byte;
01129             (*byte_count) = (ub4) size_in_out_char_byte;
01130 
01131             if (OCILib.nls_utf8 == FALSE)
01132             {
01133                 (*byte_count) *= (ub4) sizeof(dtext);
01134             }
01135         }
01136     }
01137 
01138     if (res == TRUE)
01139     {
01140         if (lob->type == OCI_BLOB)
01141         {
01142             lob->offset += (big_uint) (*byte_count);
01143         }
01144         else
01145         {
01146             lob->offset += (big_uint) (*char_count);
01147 
01148             if (OCILib.nls_utf8 == FALSE)
01149             {
01150                 OCI_ReleaseDataString(obuf);
01151             }
01152         }
01153     }
01154 
01155     OCI_RESULT(res);
01156 
01157     return res;
01158 }
01159 
01160 /* --------------------------------------------------------------------------------------------- *
01161  * OCI_LobAppend
01162  * --------------------------------------------------------------------------------------------- */
01163 
01164 unsigned int OCI_API OCI_LobAppend
01165 (
01166     OCI_Lob     *lob,
01167     void        *buffer,
01168     unsigned int len
01169 )
01170 {
01171     unsigned int char_count = 0;
01172     unsigned int byte_count = 0;
01173     unsigned int *ptr_count = NULL;
01174 
01175     if (lob != NULL)
01176     {
01177         if(lob->type == OCI_BLOB)
01178         {
01179             byte_count = len;
01180             ptr_count  = &byte_count;
01181         }
01182         else
01183         {
01184             char_count = len;
01185             ptr_count  = &char_count;
01186         }
01187     }
01188 
01189     OCI_LobAppend2(lob, buffer, &char_count, &byte_count);
01190 
01191     return (ptr_count != NULL ? *ptr_count : 0);
01192 }
01193 
01194 /* --------------------------------------------------------------------------------------------- *
01195  * OCI_LobAppendLob
01196  * --------------------------------------------------------------------------------------------- */
01197 
01198 boolean OCI_API OCI_LobAppendLob
01199 (
01200     OCI_Lob *lob,
01201     OCI_Lob *lob_src
01202 )
01203 {
01204     boolean res     = TRUE;
01205 
01206     OCI_CHECK_PTR(OCI_IPC_LOB, lob,     FALSE);
01207     OCI_CHECK_PTR(OCI_IPC_LOB, lob_src, FALSE);
01208 
01209     /*
01210        this might cause an ORA-24805 on Oracle 8.1.x only !
01211        I couldn’t find a bug ID on Metalink, but Oracle 9i had many fixes for
01212        lobs !
01213     */
01214 
01215     OCI_CALL2
01216     (
01217         res, lob->con,
01218 
01219         OCILobAppend(lob->con->cxt, lob->con->err, lob->handle, lob_src->handle)
01220     )
01221 
01222     if (res == TRUE)
01223     {
01224         lob->offset += OCI_LobGetLength(lob);
01225     }
01226 
01227     OCI_RESULT(res);
01228 
01229     return res;
01230 }
01231 
01232 /* --------------------------------------------------------------------------------------------- *
01233  * OCI_LobIsTemporary
01234  * --------------------------------------------------------------------------------------------- */
01235 
01236 boolean OCI_API OCI_LobIsTemporary
01237 (
01238     OCI_Lob *lob
01239 )
01240 {
01241     boolean value = FALSE;
01242     boolean res   = TRUE;
01243 
01244     OCI_CHECK_PTR(OCI_IPC_LOB, lob, FALSE);
01245 
01246     OCI_CALL2
01247     (
01248         res, lob->con,
01249 
01250         OCILobIsTemporary(lob->con->env, lob->con->err, lob->handle, &value)
01251     )
01252 
01253     OCI_RESULT(res);
01254 
01255     return value;
01256 }
01257 
01258 /* --------------------------------------------------------------------------------------------- *
01259  * OCI_LobOpen
01260  * --------------------------------------------------------------------------------------------- */
01261 
01262 boolean OCI_API OCI_LobOpen
01263 (
01264     OCI_Lob     *lob,
01265     unsigned int mode
01266 )
01267 {
01268     boolean res = TRUE;
01269 
01270     OCI_CHECK_PTR(OCI_IPC_LOB, lob, FALSE);
01271 
01272     OCI_CALL2
01273     (
01274         res, lob->con,
01275 
01276         OCILobOpen(lob->con->cxt, lob->con->err, lob->handle, (ub1) mode)
01277     )
01278 
01279     OCI_RESULT(res);
01280 
01281     return res;
01282 }
01283 
01284 /* --------------------------------------------------------------------------------------------- *
01285  * OCI_LobClose
01286  * --------------------------------------------------------------------------------------------- */
01287 
01288 boolean OCI_API OCI_LobClose
01289 (
01290     OCI_Lob *lob
01291 )
01292 {
01293     boolean res = TRUE;
01294 
01295     OCI_CHECK_PTR(OCI_IPC_LOB, lob, FALSE);
01296 
01297     OCI_CALL2
01298     (
01299         res, lob->con,
01300 
01301         OCILobClose(lob->con->cxt, lob->con->err, lob->handle)
01302     )
01303 
01304     OCI_RESULT(res);
01305 
01306     return res;
01307 }
01308 
01309 /* --------------------------------------------------------------------------------------------- *
01310  * OCI_LobIsEqual
01311  * --------------------------------------------------------------------------------------------- */
01312 
01313 boolean OCI_API OCI_LobIsEqual
01314 (
01315     OCI_Lob *lob,
01316     OCI_Lob *lob2
01317 )
01318 {
01319     boolean value = FALSE;
01320     boolean res   = TRUE;
01321 
01322     OCI_CHECK_PTR(OCI_IPC_LOB, lob,FALSE);
01323     OCI_CHECK_PTR(OCI_IPC_LOB, lob2, FALSE);
01324 
01325     OCI_CALL2
01326     (
01327         res, lob->con,
01328 
01329         OCILobIsEqual(lob->con->env, lob->handle, lob2->handle, &value)
01330     )
01331 
01332     OCI_RESULT(res);
01333 
01334     return value;
01335 }
01336 
01337 /* --------------------------------------------------------------------------------------------- *
01338  * OCI_LobAssign
01339  * --------------------------------------------------------------------------------------------- */
01340 
01341 boolean OCI_API OCI_LobAssign
01342 (
01343     OCI_Lob *lob,
01344     OCI_Lob *lob_src
01345 )
01346 {
01347     boolean res = TRUE;
01348 
01349     OCI_CHECK_PTR(OCI_IPC_LOB, lob,     FALSE);
01350     OCI_CHECK_PTR(OCI_IPC_LOB, lob_src, FALSE);
01351 
01352     if ((lob->hstate == OCI_OBJECT_ALLOCATED) || (lob->hstate == OCI_OBJECT_ALLOCATED_ARRAY))
01353     {
01354         OCI_CALL2
01355         (
01356             res, lob->con,
01357 
01358             OCILobLocatorAssign(lob->con->cxt, lob->con->err, lob_src->handle, &lob->handle)
01359         )
01360     }
01361     else
01362     {
01363         OCI_CALL2
01364         (
01365             res, lob->con,
01366 
01367             OCILobAssign(lob->con->env, lob->con->err, lob_src->handle, &lob->handle)
01368         )
01369     }
01370 
01371     OCI_RESULT(res);
01372 
01373     return res;
01374 }
01375 
01376 /* --------------------------------------------------------------------------------------------- *
01377  * OCI_LobGetMaxSize
01378  * --------------------------------------------------------------------------------------------- */
01379 
01380 big_uint OCI_API OCI_LobGetMaxSize
01381 (
01382     OCI_Lob *lob
01383 )
01384 {
01385     boolean res   = TRUE;
01386     big_uint size = 0;
01387 
01388     OCI_CHECK_PTR(OCI_IPC_LOB, lob, 0);
01389 
01390 #ifdef OCI_LOB2_API_ENABLED
01391 
01392     if (OCILib.use_lob_ub8)
01393     {
01394         OCI_CALL2
01395         (
01396             res, lob->con,
01397 
01398             OCILobGetStorageLimit(lob->con->cxt, lob->con->err, lob->handle, (ub8 *) &size)
01399         )
01400     }
01401 
01402 #endif
01403 
01404     OCI_RESULT(res);
01405 
01406     return size;
01407 }
01408 
01409 /* --------------------------------------------------------------------------------------------- *
01410  * OCI_LobFlush
01411  * --------------------------------------------------------------------------------------------- */
01412 
01413 boolean OCI_API OCI_LobFlush
01414 (
01415     OCI_Lob *lob
01416 )
01417 {
01418     boolean res = TRUE;
01419 
01420     OCI_CHECK_PTR(OCI_IPC_LOB, lob, FALSE);
01421 
01422     OCI_CALL2
01423     (
01424         res, lob->con,
01425 
01426         OCILobFlushBuffer(lob->con->cxt, lob->con->err, lob->handle, (ub4) OCI_DEFAULT)
01427     )
01428 
01429     OCI_RESULT(res);
01430 
01431     return res;
01432 }
01433 
01434 /* --------------------------------------------------------------------------------------------- *
01435  * OCI_LobEnableBuffering
01436  * --------------------------------------------------------------------------------------------- */
01437 
01438 boolean OCI_API OCI_LobEnableBuffering
01439 (
01440     OCI_Lob *lob,
01441     boolean  value
01442 )
01443 {
01444     boolean res = TRUE;
01445 
01446     OCI_CHECK_PTR(OCI_IPC_LOB, lob, FALSE);
01447 
01448     if (value == TRUE)
01449     {
01450         OCI_CALL2
01451         (
01452             res, lob->con,
01453 
01454             OCILobEnableBuffering(lob->con->cxt, lob->con->err, lob->handle)
01455         )
01456     }
01457     else
01458     {
01459         OCI_CALL2
01460         (
01461             res, lob->con,
01462 
01463             OCILobDisableBuffering(lob->con->cxt, lob->con->err, lob->handle)
01464         )
01465     }
01466 
01467     OCI_RESULT(res);
01468 
01469     return res;
01470 }
01471