• Main Page
  • Modules
  • Data Structures
  • Files
  • File List

D:/Perso/dev/ocilib/ocilib/src/callback.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-2010 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: callback.c, v 3.8.0 2010-10-24 21:53 Vincent Rogier $
00033  * --------------------------------------------------------------------------------------------- */
00034 
00035 #include "ocilib_internal.h"
00036 
00037 /* ********************************************************************************************* *
00038  *                             PRIVATE FUNCTIONS
00039  * ********************************************************************************************* */
00040 
00041 /* --------------------------------------------------------------------------------------------- *
00042  * OCI_ProcInBind
00043  * --------------------------------------------------------------------------------------------- */
00044 
00045 sb4 OCI_ProcInBind
00046 (
00047     dvoid   *ictxp,
00048     OCIBind *bindp,
00049     ub4      iter,
00050     ub4      index,
00051     dvoid  **bufpp,
00052     ub4     *alenp,
00053     ub1     *piecep,
00054     dvoid  **indp
00055 )
00056 {
00057     OCI_Bind * bnd = (OCI_Bind *) ictxp;
00058     sb2 *ind       = (sb2 *) bnd->buf.inds;
00059     ub4 i          = 0;
00060 
00061     /* those checks may be not necessary but they keep away compilers warning
00062        away if the warning level is set to maximum !
00063     */
00064 
00065     OCI_NOT_USED(index);
00066     OCI_NOT_USED(bindp);
00067 
00068     /* check objects and bounds */
00069 
00070     OCI_CHECK(bnd  == NULL, OCI_ERROR);
00071     OCI_CHECK(iter >= bnd->buf.count, OCI_ERROR);
00072 
00073     /* indicators must be set to -1 depending on datatype,
00074        so let's do it for all */
00075 
00076     for (i = 0; i < bnd->buf.count; i++, ind++)
00077         *ind = -1;
00078 
00079     /* setup bind index because OCI_RegisterXXX() might not have been called
00080        in the same order than the variables in the returning clause */
00081 
00082     if (iter == 0)
00083         bnd->dynpos = bnd->stmt->dynidx++;
00084 
00085     /* we do not need to do anything here except setting indicators */
00086 
00087     *bufpp  = (dvoid *) 0;
00088     *alenp  = (ub4    ) 0;
00089     *indp   = (dvoid *) bnd->buf.inds;
00090     *piecep = (ub1    ) OCI_ONE_PIECE;
00091 
00092     return OCI_CONTINUE;
00093 }
00094 
00095 /* --------------------------------------------------------------------------------------------- *
00096  * OCI_ProcOutBind
00097  * --------------------------------------------------------------------------------------------- */
00098 
00099 sb4 OCI_ProcOutBind
00100 (
00101     dvoid   *octxp,
00102     OCIBind *bindp,
00103     ub4      iter,
00104     ub4      index,
00105     dvoid  **bufpp,
00106     ub4    **alenp,
00107     ub1     *piecep,
00108     dvoid  **indp,
00109     ub2    **rcodep
00110 )
00111 {
00112     OCI_Bind * bnd    = (OCI_Bind *) octxp;
00113     OCI_Define *def   = NULL;
00114     OCI_Resultset *rs = NULL;
00115     boolean res       = TRUE;
00116     ub4 rows          = 0;
00117 
00118     /* those checks may be not necessary but they keep away compilers warning
00119        away if the warning level is set to maximum !
00120     */
00121 
00122     OCI_NOT_USED(bindp);
00123 
00124     /* check objects and bounds */
00125 
00126     OCI_CHECK(bnd  == NULL, OCI_ERROR);
00127     OCI_CHECK(iter >= bnd->buf.count, OCI_ERROR);
00128 
00129     /* update statmement status */
00130 
00131     bnd->stmt->status = OCI_STMT_EXECUTED;
00132 
00133     /* create resultset on the first row processed for each iteration */
00134 
00135     if (index == 0)
00136     {
00137         bnd->stmt->nb_rs  = bnd->stmt->nb_iters;
00138         bnd->stmt->cur_rs = 0;
00139 
00140         /* allocate resultset handles array */
00141 
00142         if (bnd->stmt->rsts == NULL)
00143         {
00144             bnd->stmt->rsts =
00145 
00146                 (OCI_Resultset **) OCI_MemAlloc(OCI_IPC_RESULTSET_ARRAY,
00147                                                 sizeof(*bnd->stmt->rsts),
00148                                                 (size_t) bnd->stmt->nb_rs, TRUE);
00149 
00150             if (bnd->stmt->rsts == NULL)
00151                 res = FALSE;
00152         }
00153 
00154         /* create resultset as needed */
00155 
00156         if (bnd->stmt->rsts[iter] == NULL)
00157         {
00158             OCI_CALL1
00159             (
00160                 res, bnd->stmt->con, bnd->stmt,
00161 
00162                 OCIAttrGet(bnd->buf.handle, (ub4) OCI_HTYPE_BIND, (void *) &rows,
00163                            (ub4 *) NULL, (ub4) OCI_ATTR_ROWS_RETURNED,
00164                            bnd->stmt->con->err)
00165             )
00166 
00167             if (res == TRUE)
00168             {
00169                 bnd->stmt->rsts[iter] = OCI_ResultsetCreate(bnd->stmt, rows);
00170 
00171                 if (bnd->stmt->rsts[iter] != NULL)
00172                     bnd->stmt->rsts[iter]->row_count = rows;
00173             }
00174         }
00175     }
00176 
00177     OCI_CHECK(bnd->stmt->rsts == NULL, OCI_ERROR);
00178 
00179     rs = bnd->stmt->rsts[iter];
00180 
00181     OCI_CHECK(rs == NULL, OCI_ERROR);
00182 
00183     /* ok.. let's Oracle update its buffers */
00184 
00185     if (res == TRUE)
00186     {
00187         /* update pointers contents */
00188 
00189         def = &rs->defs[bnd->dynpos];
00190 
00191         switch (def->col.type)
00192         {
00193 
00194         case OCI_CDT_CURSOR:
00195         case OCI_CDT_TIMESTAMP:
00196         case OCI_CDT_INTERVAL:
00197         case OCI_CDT_LOB:
00198         case OCI_CDT_FILE:
00199 
00200             *bufpp = def->buf.data[index];
00201             break;
00202 
00203         default:
00204 
00205             *bufpp = (((ub1*)def->buf.data) + (size_t) (def->col.bufsize * index));
00206         }
00207 
00208         *alenp  = (ub4   *) (((ub1 *) def->buf.lens) + (size_t) ((ub4) def->buf.sizelen * index));
00209         *indp   = (dvoid *) (((ub1 *) def->buf.inds) + (size_t) ((ub4) sizeof(sb2)      * index));
00210         *piecep = (ub1    ) OCI_ONE_PIECE;
00211         *rcodep = (ub2   *) NULL;
00212     }
00213 
00214     return ((res == TRUE) ? OCI_CONTINUE : OCI_ERROR);
00215 }
00216 
00217 /* --------------------------------------------------------------------------------------------- *
00218  * OCI_ProcNotify
00219  * --------------------------------------------------------------------------------------------- */
00220 
00221 ub4 OCI_ProcNotify
00222 (
00223     void            *ctx,
00224     OCISubscription *subscrhp,
00225     void            *payload,
00226     ub4              paylen,
00227     void            *desc,
00228     ub4              mode
00229 )
00230 {
00231     OCI_Subscription *sub = (OCI_Subscription *) ctx;
00232     boolean res           = TRUE;
00233     void *ostr            = NULL;
00234     int osize             = 0;
00235     ub4 type              = 0;
00236 
00237     OCI_NOT_USED(paylen);
00238     OCI_NOT_USED(payload);
00239     OCI_NOT_USED(mode);
00240     OCI_NOT_USED(subscrhp);
00241 
00242     OCI_CHECK(sub == NULL, OCI_SUCCESS);
00243 
00244     OCI_EventReset(&sub->event);
00245 
00246     #if OCI_VERSION_COMPILE >= OCI_10_2
00247 
00248     /* get database that generated the notification */
00249 
00250     OCI_CALL3
00251     (
00252         res, sub->err,
00253 
00254         OCIAttrGet((dvoid *) desc, (ub4) OCI_DTYPE_CHDES,
00255                    (dvoid *) &ostr, (ub4 *) &osize,
00256                    (ub4) OCI_ATTR_CHDES_DBNAME,
00257                    sub->err)
00258     )
00259 
00260     if ((res == TRUE) && (osize > (int) sub->event.dbname_size))
00261     {
00262         /* buffer is ANSI  */
00263 
00264         sub->event.dbname =
00265 
00266             (dtext *) OCI_MemRealloc(sub->event.dbname,  OCI_IPC_STRING,
00267                                      sizeof(dtext), (size_t) (osize + 1));
00268 
00269         sub->event.dbname_size = osize;
00270     }
00271 
00272     OCI_CopyString(ostr, sub->event.dbname, &osize, sizeof(char), sizeof(dtext));
00273 
00274     /* get notification type */
00275 
00276     OCI_CALL3
00277     (
00278         res, sub->err,
00279 
00280         OCIAttrGet((dvoid *) desc, (ub4) OCI_DTYPE_CHDES,
00281                    (dvoid *) &type, (ub4 *) NULL,
00282                    (ub4) OCI_ATTR_CHDES_NFYTYPE, sub->err)
00283     )
00284 
00285     switch(type)
00286     {
00287     case OCI_EVENT_STARTUP:
00288     case OCI_EVENT_SHUTDOWN:
00289     case OCI_EVENT_SHUTDOWN_ANY:
00290     {
00291         if (sub->type & OCI_CNT_DATABASES)
00292         {
00293             sub->event.type = type;
00294         }
00295 
00296         break;
00297     }
00298     case OCI_EVENT_DEREG:
00299     {
00300         sub->event.type = type;
00301         break;
00302     }
00303     case OCI_EVENT_OBJCHANGE:
00304     {
00305         if (sub->type & OCI_CNT_OBJECTS)
00306         {
00307             sub->event.type = type;
00308         }
00309 
00310         break;
00311     }
00312     default:
00313     {
00314         break;
00315     }
00316     }
00317 
00318     /* for object, much work to do for retrieving data */
00319 
00320     if (sub->event.type == OCI_EVENT_OBJCHANGE)
00321     {
00322         OCIColl *tables = 0;
00323         sb4 nb_tables   = 0;
00324         sb4 i;
00325 
00326         /* get collection of modified tables */
00327 
00328         OCI_CALL3
00329         (
00330             res, sub->err,
00331 
00332             OCIAttrGet((dvoid *) desc, (ub4) OCI_DTYPE_CHDES,
00333                        (dvoid *) &tables, (ub4 *) NULL,
00334                        (ub4) OCI_ATTR_CHDES_TABLE_CHANGES,
00335                        sub->err)
00336         )
00337 
00338         if (tables != NULL)
00339         {
00340             dvoid **elem_tbl = NULL;
00341             dvoid *ind_tbl   = NULL;
00342             boolean exist    = FALSE;
00343             sb4 nb_rows      = 0;
00344 
00345             /* get number of tables in the collection */
00346 
00347             OCI_CALL3
00348             (
00349                 res, sub->err,
00350 
00351                 OCICollSize(OCILib.env, sub->err, tables, &nb_tables)
00352             )
00353 
00354             for(i = 0; i < nb_tables; i++)
00355             {
00356                 nb_rows = 0;
00357 
00358                 /* partial reset of the event object  */
00359 
00360                 if (sub->event.objname != NULL)
00361                     sub->event.objname[0] = 0;
00362 
00363                 if (sub->event.rowid != NULL)
00364                     sub->event.rowid[0] = 0;
00365 
00366                 /* get table element */
00367 
00368                 OCI_CALL3
00369                 (
00370                     res, sub->err,
00371 
00372                     OCICollGetElem(OCILib.env, sub->err,
00373                                    tables, i, &exist,
00374                                    (dvoid**) (dvoid*) &elem_tbl,
00375                                    (dvoid**) &ind_tbl)
00376                 )
00377 
00378                 /* get table name */
00379 
00380                 OCI_CALL3
00381                 (
00382                     res, sub->err,
00383 
00384                     OCIAttrGet((dvoid *) *elem_tbl,
00385                                (ub4) OCI_DTYPE_TABLE_CHDES,
00386                                (dvoid *) &ostr, (ub4 *) &osize,
00387                                (ub4) OCI_ATTR_CHDES_TABLE_NAME,
00388                                sub->err)
00389                 )
00390 
00391                 if(osize > (int) sub->event.objname_size)
00392                 {
00393                     /* buffer is ANSI  */
00394 
00395                     sub->event.objname =
00396 
00397                         (dtext *) OCI_MemRealloc(sub->event.objname,
00398                                                  OCI_IPC_STRING, sizeof(dtext),
00399                                                  (size_t) (osize + 1));
00400 
00401                     sub->event.objname_size = osize;
00402                 }
00403 
00404                 OCI_CopyString(ostr, sub->event.objname, &osize,
00405                                sizeof(char), sizeof(dtext));
00406 
00407                 /* get table modification type */
00408 
00409                 OCI_CALL3
00410                 (
00411                     res, sub->err,
00412 
00413                     OCIAttrGet((dvoid *) *elem_tbl, (ub4) OCI_DTYPE_TABLE_CHDES,
00414                                (dvoid *) &sub->event.op, (ub4*) NULL,
00415                                (ub4) OCI_ATTR_CHDES_TABLE_OPFLAGS,
00416                                sub->err)
00417                 )
00418 
00419                 sub->event.op = sub->event.op & (~OCI_OPCODE_ALLROWS);
00420                 sub->event.op = sub->event.op & (~OCI_OPCODE_ALLOPS);
00421 
00422                 /* if requested, get row details */
00423 
00424                 if (sub->type & OCI_CNT_ROWS)
00425                 {
00426                     OCIColl *rows = 0;
00427 
00428                     /* get collection of modified rows */
00429 
00430                     OCI_CALL3
00431                     (
00432                         res, sub->err,
00433 
00434                         OCIAttrGet((dvoid *) *elem_tbl,
00435                                    (ub4) OCI_DTYPE_TABLE_CHDES,
00436                                    (dvoid *) &rows, (ub4 *) NULL,
00437                                    (ub4) OCI_ATTR_CHDES_TABLE_ROW_CHANGES,
00438                                    sub->err)
00439                     )
00440 
00441                     if (rows != NULL)
00442                     {
00443                         dvoid **elem_row = NULL;
00444                         dvoid *ind_row   = NULL;
00445                         boolean exist    = FALSE;
00446                         sb4 j;
00447 
00448                         /* get number of rows */
00449 
00450                         OCI_CALL3
00451                         (
00452                             res, sub->err,
00453 
00454                             OCICollSize(OCILib.env, sub->err, rows, &nb_rows)
00455                         )
00456 
00457                         for (j = 0; j < nb_rows; j++)
00458                         {
00459                             /* partial reset of the event  */
00460 
00461                             if (sub->event.rowid != NULL)
00462                                 sub->event.rowid[0] = 0;
00463 
00464                             /* get row element */
00465 
00466                             OCI_CALL3
00467                             (
00468                                 res, sub->err,
00469 
00470                                 OCICollGetElem(OCILib.env, sub->err,
00471                                                rows, j, &exist,
00472                                                (dvoid**) (dvoid*) &elem_row,
00473                                                (dvoid**) &ind_row)
00474                             )
00475 
00476                             /* get rowid  */
00477 
00478                             OCI_CALL3
00479                             (
00480                                 res, sub->err,
00481 
00482                                 OCIAttrGet((dvoid *) *elem_row,
00483                                            (ub4) OCI_DTYPE_ROW_CHDES,
00484                                            (dvoid *) &ostr, (ub4 *) &osize,
00485                                            (ub4) OCI_ATTR_CHDES_ROW_ROWID,
00486                                            sub->err)
00487                             )
00488 
00489                             /* get opcode  */
00490 
00491                             OCI_CALL3
00492                             (
00493                                 res, sub->err,
00494 
00495                                 OCIAttrGet((dvoid *) *elem_row,
00496                                            (ub4) OCI_DTYPE_ROW_CHDES,
00497                                            &sub->event.op, (ub4*) NULL,
00498                                            (ub4) OCI_ATTR_CHDES_ROW_OPFLAGS,
00499                                            sub->err)
00500                             )
00501 
00502                             if(osize > (int) sub->event.rowid_size)
00503                             {
00504                                 /* buffer is ANSI  */
00505 
00506                                 sub->event.rowid =
00507 
00508                                     (dtext *) OCI_MemRealloc(sub->event.rowid,
00509                                                              OCI_IPC_STRING,
00510                                                              sizeof(dtext),
00511                                                              (size_t) (osize + 1));
00512 
00513                                 sub->event.rowid_size = osize;
00514                             }
00515 
00516                             OCI_CopyString(ostr, sub->event.rowid, &osize,
00517                                            sizeof(char), sizeof(dtext));
00518 
00519                             sub->handler(&sub->event);
00520                         }
00521                     }
00522                 }
00523 
00524                 if (nb_rows == 0)
00525                 {
00526                     sub->handler(&sub->event);
00527                 }
00528             }
00529         }
00530     }
00531     else if (sub->event.type > 0)
00532     {
00533         sub->handler(&sub->event);
00534     }
00535 
00536     #else
00537 
00538     OCI_NOT_USED(ctx);
00539     OCI_NOT_USED(desc);
00540     OCI_NOT_USED(subscrhp);
00541 
00542     OCI_NOT_USED(res);
00543     OCI_NOT_USED(type);
00544     OCI_NOT_USED(ostr);
00545     OCI_NOT_USED(osize);
00546 
00547     #endif
00548 
00549     return OCI_SUCCESS;
00550 }
00551 

Generated on Sun Oct 24 2010 22:02:54 for OCILIB (C Driver for Oracle) by  doxygen 1.7.1