📄 resultset.c
字号:
/*
+----------------------------------------------------------------------+
| |
| 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 + -