• 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.1 2010-12-13 00:00 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             case OCI_CDT_CURSOR:
00194             case OCI_CDT_TIMESTAMP:
00195             case OCI_CDT_INTERVAL:
00196             case OCI_CDT_LOB:
00197             case OCI_CDT_FILE:
00198 
00199                 *bufpp = def->buf.data[index];
00200                 break;
00201 
00202             default:
00203 
00204                 *bufpp = (((ub1*)def->buf.data) + (size_t) (def->col.bufsize * index));
00205         }
00206 
00207         *alenp  = (ub4   *) (((ub1 *) def->buf.lens) + (size_t) ((ub4) def->buf.sizelen * index));
00208         *indp   = (dvoid *) (((ub1 *) def->buf.inds) + (size_t) ((ub4) sizeof(sb2)      * index));
00209         *piecep = (ub1    ) OCI_ONE_PIECE;
00210         *rcodep = (ub2   *) NULL;
00211     }
00212 
00213     return ((res == TRUE) ? OCI_CONTINUE : OCI_ERROR);
00214 }
00215 
00216 /* --------------------------------------------------------------------------------------------- *
00217  * OCI_ProcNotify
00218  * --------------------------------------------------------------------------------------------- */
00219 
00220 ub4 OCI_ProcNotify
00221 (
00222     void            *ctx,
00223     OCISubscription *subscrhp,
00224     void            *payload,
00225     ub4              paylen,
00226     void            *desc,
00227     ub4              mode
00228 )
00229 {
00230     OCI_Subscription *sub = (OCI_Subscription *) ctx;
00231     boolean res           = TRUE;
00232     void *ostr            = NULL;
00233     int osize             = 0;
00234     ub4 type              = 0;
00235 
00236     OCI_NOT_USED(paylen);
00237     OCI_NOT_USED(payload);
00238     OCI_NOT_USED(mode);
00239     OCI_NOT_USED(subscrhp);
00240 
00241     OCI_CHECK(sub == NULL, OCI_SUCCESS);
00242 
00243     OCI_EventReset(&sub->event);
00244 
00245     #if OCI_VERSION_COMPILE >= OCI_10_2
00246 
00247     /* get database that generated the notification */
00248 
00249     OCI_CALL3
00250     (
00251         res, sub->err,
00252 
00253         OCIAttrGet((dvoid *) desc, (ub4) OCI_DTYPE_CHDES,
00254                    (dvoid *) &ostr, (ub4 *) &osize,
00255                    (ub4) OCI_ATTR_CHDES_DBNAME,
00256                    sub->err)
00257     )
00258 
00259     if ((res == TRUE) && (osize > (int) sub->event.dbname_size))
00260     {
00261         /* buffer is ANSI  */
00262 
00263         sub->event.dbname =
00264 
00265             (dtext *) OCI_MemRealloc(sub->event.dbname,  OCI_IPC_STRING,
00266                                      sizeof(dtext), (size_t) (osize + 1));
00267 
00268         sub->event.dbname_size = osize;
00269     }
00270 
00271     OCI_CopyString(ostr, sub->event.dbname, &osize, sizeof(char), sizeof(dtext));
00272 
00273     /* get notification type */
00274 
00275     OCI_CALL3
00276     (
00277         res, sub->err,
00278 
00279         OCIAttrGet((dvoid *) desc, (ub4) OCI_DTYPE_CHDES,
00280                    (dvoid *) &type, (ub4 *) NULL,
00281                    (ub4) OCI_ATTR_CHDES_NFYTYPE, sub->err)
00282     )
00283 
00284     switch(type)
00285     {
00286         case OCI_EVENT_STARTUP:
00287         case OCI_EVENT_SHUTDOWN:
00288         case OCI_EVENT_SHUTDOWN_ANY:
00289         {
00290             if (sub->type & OCI_CNT_DATABASES)
00291             {
00292                 sub->event.type = type;
00293             }
00294 
00295             break;
00296         }
00297         case OCI_EVENT_DEREG:
00298         {
00299             sub->event.type = type;
00300             break;
00301         }
00302         case OCI_EVENT_OBJCHANGE:
00303         {
00304             if (sub->type & OCI_CNT_OBJECTS)
00305             {
00306                 sub->event.type = type;
00307             }
00308 
00309             break;
00310         }
00311         default:
00312         {
00313             break;
00314         }
00315     }
00316 
00317     /* for object, much work to do for retrieving data */
00318 
00319     if (sub->event.type == OCI_EVENT_OBJCHANGE)
00320     {
00321         OCIColl *tables = 0;
00322         sb4 nb_tables   = 0;
00323         sb4 i;
00324 
00325         /* get collection of modified tables */
00326 
00327         OCI_CALL3
00328         (
00329             res, sub->err,
00330 
00331             OCIAttrGet((dvoid *) desc, (ub4) OCI_DTYPE_CHDES,
00332                        (dvoid *) &tables, (ub4 *) NULL,
00333                        (ub4) OCI_ATTR_CHDES_TABLE_CHANGES,
00334                        sub->err)
00335         )
00336 
00337         if (tables != NULL)
00338         {
00339             dvoid **elem_tbl = NULL;
00340             dvoid *ind_tbl   = NULL;
00341             boolean exist    = FALSE;
00342             sb4 nb_rows      = 0;
00343 
00344             /* get number of tables in the collection */
00345 
00346             OCI_CALL3
00347             (
00348                 res, sub->err,
00349 
00350                 OCICollSize(OCILib.env, sub->err, tables, &nb_tables)
00351             )
00352 
00353             for(i = 0; i < nb_tables; i++)
00354             {
00355                 nb_rows = 0;
00356 
00357                 /* partial reset of the event object  */
00358 
00359                 if (sub->event.objname != NULL)
00360                     sub->event.objname[0] = 0;
00361 
00362                 if (sub->event.rowid != NULL)
00363                     sub->event.rowid[0] = 0;
00364 
00365                 /* get table element */
00366 
00367                 OCI_CALL3
00368                 (
00369                     res, sub->err,
00370 
00371                     OCICollGetElem(OCILib.env, sub->err,
00372                                    tables, i, &exist,
00373                                    (dvoid**) (dvoid*) &elem_tbl,
00374                                    (dvoid**) &ind_tbl)
00375                 )
00376 
00377                 /* get table name */
00378 
00379                 OCI_CALL3
00380                 (
00381                     res, sub->err,
00382 
00383                     OCIAttrGet((dvoid *) *elem_tbl,
00384                                (ub4) OCI_DTYPE_TABLE_CHDES,
00385                                (dvoid *) &ostr, (ub4 *) &osize,
00386                                (ub4) OCI_ATTR_CHDES_TABLE_NAME,
00387                                sub->err)
00388                 )
00389 
00390                 if(osize > (int) sub->event.objname_size)
00391                 {
00392                     /* buffer is ANSI  */
00393 
00394                     sub->event.objname =
00395 
00396                         (dtext *) OCI_MemRealloc(sub->event.objname,
00397                                                  OCI_IPC_STRING, sizeof(dtext),
00398                                                  (size_t) (osize + 1));
00399 
00400                     sub->event.objname_size = osize;
00401                 }
00402 
00403                 OCI_CopyString(ostr, sub->event.objname, &osize,
00404                                sizeof(char), sizeof(dtext));
00405 
00406                 /* get table modification type */
00407 
00408                 OCI_CALL3
00409                 (
00410                     res, sub->err,
00411 
00412                     OCIAttrGet((dvoid *) *elem_tbl, (ub4) OCI_DTYPE_TABLE_CHDES,
00413                                (dvoid *) &sub->event.op, (ub4*) NULL,
00414                                (ub4) OCI_ATTR_CHDES_TABLE_OPFLAGS,
00415                                sub->err)
00416                 )
00417 
00418                 sub->event.op = sub->event.op & (~OCI_OPCODE_ALLROWS);
00419                 sub->event.op = sub->event.op & (~OCI_OPCODE_ALLOPS);
00420 
00421                 /* if requested, get row details */
00422 
00423                 if (sub->type & OCI_CNT_ROWS)
00424                 {
00425                     OCIColl *rows = 0;
00426 
00427                     /* get collection of modified rows */
00428 
00429                     OCI_CALL3
00430                     (
00431                         res, sub->err,
00432 
00433                         OCIAttrGet((dvoid *) *elem_tbl,
00434                                    (ub4) OCI_DTYPE_TABLE_CHDES,
00435                                    (dvoid *) &rows, (ub4 *) NULL,
00436                                    (ub4) OCI_ATTR_CHDES_TABLE_ROW_CHANGES,
00437                                    sub->err)
00438                     )
00439 
00440                     if (rows != NULL)
00441                     {
00442                         dvoid **elem_row = NULL;
00443                         dvoid *ind_row   = NULL;
00444                         boolean exist    = FALSE;
00445                         sb4 j;
00446 
00447                         /* get number of rows */
00448 
00449                         OCI_CALL3
00450                         (
00451                             res, sub->err,
00452 
00453                             OCICollSize(OCILib.env, sub->err, rows, &nb_rows)
00454                         )
00455 
00456                         for (j = 0; j < nb_rows; j++)
00457                         {
00458                             /* partial reset of the event  */
00459 
00460                             if (sub->event.rowid != NULL)
00461                                 sub->event.rowid[0] = 0;
00462 
00463                             /* get row element */
00464 
00465                             OCI_CALL3
00466                             (
00467                                 res, sub->err,
00468 
00469                                 OCICollGetElem(OCILib.env, sub->err,
00470                                                rows, j, &exist,
00471                                                (dvoid**) (dvoid*) &elem_row,
00472                                                (dvoid**) &ind_row)
00473                             )
00474 
00475                             /* get rowid  */
00476 
00477                             OCI_CALL3
00478                             (
00479                                 res, sub->err,
00480 
00481                                 OCIAttrGet((dvoid *) *elem_row,
00482                                            (ub4) OCI_DTYPE_ROW_CHDES,
00483                                            (dvoid *) &ostr, (ub4 *) &osize,
00484                                            (ub4) OCI_ATTR_CHDES_ROW_ROWID,
00485                                            sub->err)
00486                             )
00487 
00488                             /* get opcode  */
00489 
00490                             OCI_CALL3
00491                             (
00492                                 res, sub->err,
00493 
00494                                 OCIAttrGet((dvoid *) *elem_row,
00495                                            (ub4) OCI_DTYPE_ROW_CHDES,
00496                                            &sub->event.op, (ub4*) NULL,
00497                                            (ub4) OCI_ATTR_CHDES_ROW_OPFLAGS,
00498                                            sub->err)
00499                             )
00500 
00501                             if(osize > (int) sub->event.rowid_size)
00502                             {
00503                                 /* buffer is ANSI  */
00504 
00505                                 sub->event.rowid =
00506 
00507                                     (dtext *) OCI_MemRealloc(sub->event.rowid,
00508                                                              OCI_IPC_STRING,
00509                                                              sizeof(dtext),
00510                                                              (size_t) (osize + 1));
00511 
00512                                 sub->event.rowid_size = osize;
00513                             }
00514 
00515                             OCI_CopyString(ostr, sub->event.rowid, &osize,
00516                                            sizeof(char), sizeof(dtext));
00517 
00518                             sub->handler(&sub->event);
00519                         }
00520                     }
00521                 }
00522 
00523                 if (nb_rows == 0)
00524                 {
00525                     sub->handler(&sub->event);
00526                 }
00527             }
00528         }
00529     }
00530     else if (sub->event.type > 0)
00531     {
00532         sub->handler(&sub->event);
00533     }
00534 
00535     #else
00536 
00537     OCI_NOT_USED(ctx);
00538     OCI_NOT_USED(desc);
00539     OCI_NOT_USED(subscrhp);
00540 
00541     OCI_NOT_USED(res);
00542     OCI_NOT_USED(type);
00543     OCI_NOT_USED(ostr);
00544     OCI_NOT_USED(osize);
00545 
00546     #endif
00547 
00548     return OCI_SUCCESS;
00549 }
00550 

Generated on Mon Dec 13 2010 22:32:01 for OCILIB (C Driver for Oracle) by  doxygen 1.7.2