⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 resultset.c

📁 ORACLE编程的好东西,纯C写的OCI封装.很好用,支持数据池.
💻 C
📖 第 1 页 / 共 4 页
字号:
/*
   +----------------------------------------------------------------------+   
   |                                                                      |
   |                     OCILIB - C Driver for Oracle                     |
   |                                                                      |
   |                      (C Wrapper for Oracle OCI)                      |
   |                                                                      |
   +----------------------------------------------------------------------+
   |                      Website : http://ocilib.net                     |
   +----------------------------------------------------------------------+
   |               Copyright (c) 2007-2008 Vincent ROGIER                 |
   +----------------------------------------------------------------------+
   | This library is free software; you can redistribute it and/or        |
   | modify it under the terms of the GNU Library General Public          |
   | License as published by the Free Software Foundation; either         |
   | version 2 of the License, or (at your option) any later version.     |
   |                                                                      |
   | This library is distributed in the hope that it will be useful,      |
   | but WITHOUT ANY WARRANTY; without even the implied warranty of       |
   | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU    |
   | Library General Public License for more details.                     |
   |                                                                      |
   | You should have received a copy of the GNU Library General Public    |
   | License along with this library; if not, write to the Free           |
   | Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.   |
   +----------------------------------------------------------------------+
   |          Author: Vincent ROGIER <vince.rogier@gmail.com>             |
   +----------------------------------------------------------------------+ 
*/

/* ------------------------------------------------------------------------ *
 * $Id: resultset.c, v 3.0.0 2008/10/09 09:54 Vince $
 * ------------------------------------------------------------------------ */

#include "ocilib_internal.h"

/* ************************************************************************ *
 *                             PRIVATE FUNCTIONS
 * ************************************************************************ */

/* ------------------------------------------------------------------------ *
 * OCI_ResultsetCreate
 * ------------------------------------------------------------------------ */

OCI_Resultset * OCI_ResultsetCreate(OCI_Statement *stmt, int size)
{
    OCI_Resultset* rs = NULL;
    boolean res       = TRUE;
    ub4 nb            = 0;
    ub4 i;
  
    /* allocate resulset structure */
    
    rs = (OCI_Resultset *) OCI_MemAlloc(OCI_IPC_RESULTSET, sizeof(*rs), 1, TRUE);

    res = (rs != NULL);

    /* set attributes */

    if (res == TRUE)
    {
        rs->stmt         = stmt;
        rs->bof          = TRUE;
        rs->eof          = FALSE;
        rs->fetch_size   = size;
        rs->fetch_status = OCI_SUCCESS;
        rs->row_count    = 0;
        rs->row_cur      = 0;
        rs->row_abs      = 0;

        /* is the resultset created from a SQL select statement ? */

        if (stmt->type == OCI_CST_SELECT)
        {
            OCI_CALL1
            (
                res, stmt->con, stmt,
                
                OCIAttrGet((void *) stmt->stmt, (ub4) OCI_HTYPE_STMT,
                           (void *) &nb, (ub4 *) NULL,
                           (ub4) OCI_ATTR_PARAM_COUNT, stmt->con->err)
            )
        }
        else
        {
            nb = stmt->nb_outbinds;
        }

        /* allocate columns array */

        if (res == TRUE)
        {
            rs->defs = (OCI_Define *) OCI_MemAlloc(OCI_IPC_DEFINE, sizeof(*rs->defs),
                                                   nb, TRUE);

            res = (rs->defs != NULL);
        }

        /* describe select list */

        if ((res == TRUE) && (stmt->type == OCI_CST_SELECT))
        {
            for (i=0; i < nb; i++)
            {
                OCI_Define *def  = &rs->defs[i];

                def->buf.count   = size;
                def->buf.sizelen = sizeof(ub2);
            
                def->rs = rs;

                rs->nb_defs++;

                /* get column description */

                if (res == TRUE)
                    res = OCI_ColumnDescribe(&def->col, rs->stmt->con, 
                                             rs->stmt, rs->stmt->stmt,
                                             rs->nb_defs, OCI_DESC_RESULTSET);

                /* mapping to OCILIB internal types */

                if (res == TRUE)
                    res = OCI_ColumnMap(&def->col, rs->stmt);

                /* allocation of internal buffers for resultset content */

                if (res == TRUE)
                    res = OCI_DefineAlloc(def);
                
                /* register OCILIB result buffers to OCI */

                if (res == TRUE)
                    res = OCI_DefineDef(def);
                
                if (res == FALSE) 
                    break;
            }
        }
        else
        {
            /* get info from input binds */

            for (i=0; i < stmt->nb_binds; i++)
            {
                OCI_Bind   *bnd  = stmt->binds[i];
                OCI_Define *def  = &rs->defs[bnd->dynpos];

                def->buf.count   = size;
                def->buf.sizelen = sizeof(ub4);

                def->rs = rs;

                if (bnd->mode == OCI_BIND_OUTPUT)
                {
                    rs->nb_defs++;

                    /* columns info */

                    def->col.ocode   = bnd->code;
                    def->col.name    = mtsdup(bnd->name);
                    def->col.size    = (ub2) bnd->size;
                    def->col.type    = bnd->type;
                    def->col.subtype = bnd->subtype;

                    /* check national attribute for nclobs */

                    if (bnd->type == OCI_CDT_LOB && bnd->subtype == OCI_NCLOB)
                        def->col.csfrm = SQLCS_NCHAR;

                    /* ajdust colum size from bind atrributes */

                    if (def->col.type == OCI_CDT_TEXT)
                        def->col.size = (ub2) (def->col.size / (sizeof(dtext)) - 1);

                    /* for integer types, set the bufsize here in order to 
                       retreive later the integer type (short, integer, big_int)
                       depending on the integer size */
                    
                    if (def->col.type == OCI_CDT_NUMERIC)
                        def->col.bufsize = def->col.size;

                    /* preset bufsize here to let OCI_ColumnMap() know we don't 
                       want the column to mapped to SQLT_ODT */

                    if (def->col.ocode == SQLT_DAT)
                        def->col.bufsize = def->col.size;

                    /* map column : failure means unsupported type */

                    if (res == TRUE)
                        res = OCI_ColumnMap(&def->col, rs->stmt);

                    /* allocation of internal buffers for resultset content */
                    
                    if (res == TRUE)
                        res = OCI_DefineAlloc(def);
                
                    if (res == FALSE) 
                        break;
               }
            }
        }
    }

    return rs;
}


/* ------------------------------------------------------------------------ *
 * OCI_FetchPieces
 * ------------------------------------------------------------------------ */

boolean OCI_FetchPieces(OCI_Resultset *rs)
{
    boolean res  = TRUE;

    ub4 type, iter, dx;
    ub1 in_out, piece;
    void *handle;
    ub4 i, j;

    OCI_CHECK(rs == NULL, FALSE);

    /* reset long objects */

    for (i = 0; i < rs->nb_defs; i++)
    {
        OCI_Define *def = &rs->defs[i];
         
        if (def->col.type == OCI_CDT_LONG)
        {
            for (j = 0; j < def->buf.count; j++)
            {
                OCI_LongInit(rs->stmt, (OCI_Long **) &def->buf.data[j],
                             def, def->col.subtype);
            }
        }
    }

    /* dynamic fetch */

    while ((res == TRUE) && (rs->fetch_status == OCI_NEED_DATA)) 
    {      
        piece  = OCI_NEXT_PIECE;
        iter   = 0;
        handle = NULL;

        /* get piece information */

        OCI_CALL1
        (
            res, rs->stmt->con, rs->stmt,
            
            OCIStmtGetPieceInfo(rs->stmt->stmt, rs->stmt->con->err,
                                &handle,  &type, &in_out, &iter, &dx, &piece)
        )

        /* search for the given column */

        for (i = 0; (res == TRUE) && (i < rs->nb_defs); i++)
        {
            OCI_Define *def = &(rs->defs[i]);
             
            if (def->col.type == OCI_CDT_LONG && def->buf.handle == handle)
            {
                /* get the long object for the given internal row */

                OCI_Long *lg = (OCI_Long *) def->buf.data[iter];

                /* setup up piece size */

                ub4 bufsize = rs->stmt->long_size;

                if (lg->type == OCI_CLONG)
                    bufsize += sizeof(dtext);

                /* check buffer */

                if (lg->buffer == NULL)
                {
                    lg->maxsize = bufsize;

                    lg->buffer  = (ub1 *) OCI_MemAlloc(OCI_IPC_LONG_BUFFER, 
                                                       lg->maxsize, 1, FALSE);

                    lg->buffer[0] = 0;
                }
                else if (lg->size >= lg->maxsize)
                {
                    lg->maxsize = lg->size + bufsize;

                    lg->buffer  = (ub1 *) OCI_MemRealloc(lg->buffer,
                                                         OCI_IPC_LONG_BUFFER, 
                                                         lg->maxsize, 1);
                }

                res = (lg->buffer != NULL);
            
                /* update piece infos */

                if (res == TRUE)
                {
                    lg->piecesize = bufsize;

                    OCI_CALL1
                    (
                        res, rs->stmt->con, rs->stmt,
                             
                        OCIStmtSetPieceInfo((dvoid *) handle,
                                            (ub4) OCI_HTYPE_DEFINE,
                                            lg->stmt->con->err,
                                            (dvoid *) (lg->buffer + lg->size),
                                            &lg->piecesize, piece, 
                                            lg->def->buf.inds, (ub2 *) NULL)
                     )  

                }
             
                break;
            }
        }
          
        /* fetch data */

#if defined(OCI_STMT_SCROLLABLE_READONLY)

        if (OCILib.use_scrollable_cursors == TRUE)
        {
            rs->fetch_status = OCIStmtFetch2(rs->stmt->stmt, rs->stmt->con->err, 
                                             rs->fetch_size, (ub2) OCI_FETCH_NEXT, 
                                             (sb4) 0, (ub4) OCI_DEFAULT);
        }
        else
#endif
        {
            rs->fetch_status = OCIStmtFetch(rs->stmt->stmt, rs->stmt->con->err, 
                                            rs->fetch_size, (ub2) OCI_FETCH_NEXT, 
                                            (ub4) OCI_DEFAULT);
        }

        if (rs->fetch_status == OCI_NO_DATA)
            rs->fetch_status = rs->fetch_status;

        /* check for return value of fetch call */

        if (rs->fetch_status == OCI_ERROR)
        {
              OCI_ExceptionOCI(rs->stmt->con->err, rs->stmt->con, rs->stmt);
              res = FALSE;
        }
        else
        {
            /* search for the given column */

            for (i = 0; i < rs->nb_defs; i++)
            {
                OCI_Define *def = &rs->defs[i];

                if (def->col.type == OCI_CDT_LONG && def->buf.handle == handle)
                {
                    /* get the long object for the given internal row */
              
                    OCI_Long *lg = (OCI_Long *) def->buf.data[iter];
                    
                    lg->size += lg->piecesize;

                    break;
                }
            }
        }
    }

    /* for LONG columns, set the zero terminal string */

    for (i = 0; i < rs->nb_defs; i++)
    {
        OCI_Define *def = &rs->defs[i];

        if (def->col.type == OCI_CDT_LONG && def->col.subtype == OCI_CLONG)
        {
            for (j = 0; j < def->buf.count; j++)
            {
                OCI_Long *lg = (OCI_Long *) def->buf.data[j];
                
                if (lg->buffer != NULL)
                    lg->buffer[lg->size] = 0;                    
            }
        }
    }

    return res;
}

/* ------------------------------------------------------------------------ *
 * OCI_FetchData
 * ------------------------------------------------------------------------ */

boolean OCI_FetchData(OCI_Resultset *rs, int mode, int offset)
{
    boolean res  = TRUE;
    //OCI_CHECK(rs->fetch_status == OCI_NO_DATA, FALSE);

    /* internal fetch */

#if defined(OCI_STMT_SCROLLABLE_READONLY)

    if (OCILib.use_scrollable_cursors == TRUE)
    {
        rs->fetch_status = OCIStmtFetch2(rs->stmt->stmt, rs->stmt->con->err,
                                         rs->fetch_size, (ub2) mode, (sb4) offset,
                                         (ub4) OCI_DEFAULT);
    }
    else
#endif
    {
        rs->fetch_status = OCIStmtFetch(rs->stmt->stmt, rs->stmt->con->err, 
                                        rs->fetch_size, (ub2) OCI_FETCH_NEXT, 
                                        (ub4) OCI_DEFAULT);   
    }

    /* check failure */

    if (rs->fetch_status == OCI_ERROR)
    {
          OCI_ExceptionOCI(rs->stmt->con->err, rs->stmt->con, rs->stmt);
          res = FALSE;
    }

    /* do we need to do a piecewise fetch */

    if (rs->fetch_status == OCI_NEED_DATA)
        res = OCI_FetchPieces(rs);

    /* check string buffer for unicode builds that need buffer expansion */

#ifdef OCI_CHECK_DATASTRINGS 
 
    OCI_ResultsetExpandStrings(rs);

#endif

    /* check for success */

    res = ((res == TRUE) && ((rs->fetch_status == OCI_SUCCESS) ||
                             (rs->fetch_status == OCI_NO_DATA) ||
                             (rs->fetch_status == OCI_SUCCESS_WITH_INFO)));
 
    /* update internal fecth status and variables */

    if (res == TRUE)
    {
        ub4 row_count      = 0;
        ub4 row_fetched    = 0;

#if defined(OCI_STMT_SCROLLABLE_READONLY)

        if (rs->stmt->exec_mode  == OCI_SFM_SCROLLABLE)
        {
            OCI_CALL1
            (
                res, rs->stmt->con, rs->stmt,

                OCIAttrGet((dvoid *) rs->stmt->stmt, (ub4) OCI_HTYPE_STMT,
                           (dvoid *) &row_count, (ub4 *) NULL, 
                           (ub4) OCI_ATTR_CURRENT_POSITION, rs->stmt->con->err)
            )

            OCI_CALL1

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -