git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@2613 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
650 lines
12 KiB
C
650 lines
12 KiB
C
/*
|
|
* fetch.c
|
|
*
|
|
* $Id$
|
|
*
|
|
* Fetch query result
|
|
*
|
|
* The iODBC driver manager.
|
|
*
|
|
* Copyright (C) 1995 by Ke Jin <kejin@empress.com>
|
|
*
|
|
* 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.
|
|
*/
|
|
|
|
#include "config.h"
|
|
|
|
#include "isql.h"
|
|
#include "isqlext.h"
|
|
|
|
#include "dlproc.h"
|
|
|
|
#include "herr.h"
|
|
#include "henv.h"
|
|
#include "hdbc.h"
|
|
#include "hstmt.h"
|
|
|
|
#include "itrace.h"
|
|
|
|
RETCODE SQL_API
|
|
SQLFetch (HSTMT hstmt)
|
|
{
|
|
STMT_t FAR *pstmt = (STMT_t FAR *) hstmt;
|
|
HPROC hproc = SQL_NULL_HPROC;
|
|
RETCODE retcode;
|
|
|
|
if (hstmt == SQL_NULL_HSTMT || pstmt->hdbc == SQL_NULL_HDBC)
|
|
{
|
|
return SQL_INVALID_HANDLE;
|
|
}
|
|
|
|
/* check state */
|
|
if (pstmt->asyn_on == en_NullProc)
|
|
{
|
|
switch (pstmt->state)
|
|
{
|
|
case en_stmt_allocated:
|
|
case en_stmt_prepared:
|
|
case en_stmt_xfetched:
|
|
case en_stmt_needdata:
|
|
case en_stmt_mustput:
|
|
case en_stmt_canput:
|
|
PUSHSQLERR (pstmt->herr, en_S1010);
|
|
return SQL_ERROR;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
else if (pstmt->asyn_on != en_Fetch)
|
|
{
|
|
PUSHSQLERR (pstmt->herr, en_S1010);
|
|
return SQL_ERROR;
|
|
}
|
|
|
|
hproc = _iodbcdm_getproc (pstmt->hdbc, en_Fetch);
|
|
|
|
if (hproc == SQL_NULL_HPROC)
|
|
{
|
|
PUSHSQLERR (pstmt->herr, en_IM001);
|
|
|
|
return SQL_ERROR;
|
|
}
|
|
|
|
CALL_DRIVER (pstmt->hdbc, retcode, hproc, en_Fetch,
|
|
(pstmt->dhstmt))
|
|
|
|
/* state transition */
|
|
if (pstmt->asyn_on == en_Fetch)
|
|
{
|
|
switch (retcode)
|
|
{
|
|
case SQL_SUCCESS:
|
|
case SQL_SUCCESS_WITH_INFO:
|
|
case SQL_NO_DATA_FOUND:
|
|
case SQL_ERROR:
|
|
pstmt->asyn_on = en_NullProc;
|
|
break;
|
|
|
|
case SQL_STILL_EXECUTING:
|
|
default:
|
|
return retcode;
|
|
}
|
|
}
|
|
|
|
switch (pstmt->state)
|
|
{
|
|
case en_stmt_cursoropen:
|
|
case en_stmt_fetched:
|
|
switch (retcode)
|
|
{
|
|
case SQL_SUCCESS:
|
|
case SQL_SUCCESS_WITH_INFO:
|
|
pstmt->state = en_stmt_fetched;
|
|
pstmt->cursor_state = en_stmt_cursor_fetched;
|
|
break;
|
|
|
|
case SQL_NO_DATA_FOUND:
|
|
if (pstmt->prep_state)
|
|
{
|
|
pstmt->state = en_stmt_prepared;
|
|
}
|
|
else
|
|
{
|
|
|
|
pstmt->state = en_stmt_allocated;
|
|
}
|
|
pstmt->cursor_state = en_stmt_cursor_no;
|
|
break;
|
|
|
|
case SQL_STILL_EXECUTING:
|
|
pstmt->asyn_on = en_Fetch;
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
|
|
return retcode;
|
|
}
|
|
|
|
|
|
RETCODE SQL_API
|
|
SQLExtendedFetch (
|
|
HSTMT hstmt,
|
|
UWORD fFetchType,
|
|
SDWORD irow,
|
|
UDWORD FAR * pcrow,
|
|
UWORD FAR * rgfRowStatus)
|
|
{
|
|
STMT_t FAR *pstmt = (STMT_t FAR *) hstmt;
|
|
HPROC hproc = SQL_NULL_HPROC;
|
|
RETCODE retcode;
|
|
|
|
if (hstmt == SQL_NULL_HSTMT || pstmt->hdbc == SQL_NULL_HDBC)
|
|
{
|
|
return SQL_INVALID_HANDLE;
|
|
}
|
|
|
|
/* check fetch type */
|
|
if (fFetchType < SQL_FETCH_NEXT || fFetchType > SQL_FETCH_BOOKMARK)
|
|
{
|
|
/* Unlike MS driver manager(i.e. DM),
|
|
* we don't check driver's ODBC version
|
|
* against SQL_FETCH_RESUME (only 1.0)
|
|
* and SQL_FETCH_BOOKMARK (only 2.0).
|
|
*/
|
|
PUSHSQLERR (pstmt->herr, en_S1106);
|
|
|
|
return SQL_ERROR;
|
|
}
|
|
|
|
/* check state */
|
|
if (pstmt->asyn_on == en_NullProc)
|
|
{
|
|
switch (pstmt->state)
|
|
{
|
|
case en_stmt_allocated:
|
|
case en_stmt_prepared:
|
|
case en_stmt_fetched:
|
|
case en_stmt_needdata:
|
|
case en_stmt_mustput:
|
|
case en_stmt_canput:
|
|
PUSHSQLERR (pstmt->herr, en_S1010);
|
|
return SQL_ERROR;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
else if (pstmt->asyn_on != en_ExtendedFetch)
|
|
{
|
|
PUSHSQLERR (pstmt->herr, en_S1010);
|
|
return SQL_ERROR;
|
|
}
|
|
|
|
hproc = _iodbcdm_getproc (pstmt->hdbc, en_ExtendedFetch);
|
|
|
|
if (hproc == SQL_NULL_HPROC)
|
|
{
|
|
PUSHSQLERR (pstmt->herr, en_IM001);
|
|
|
|
return SQL_ERROR;
|
|
}
|
|
|
|
CALL_DRIVER (pstmt->hdbc, retcode, hproc, en_ExtendedFetch,
|
|
(pstmt->dhstmt, fFetchType, irow, pcrow, rgfRowStatus))
|
|
|
|
/* state transition */
|
|
if (pstmt->asyn_on == en_ExtendedFetch)
|
|
{
|
|
switch (retcode)
|
|
{
|
|
case SQL_SUCCESS:
|
|
case SQL_SUCCESS_WITH_INFO:
|
|
case SQL_NO_DATA_FOUND:
|
|
case SQL_ERROR:
|
|
pstmt->asyn_on = en_NullProc;
|
|
break;
|
|
|
|
case SQL_STILL_EXECUTING:
|
|
default:
|
|
return retcode;
|
|
}
|
|
}
|
|
|
|
switch (pstmt->state)
|
|
{
|
|
case en_stmt_cursoropen:
|
|
case en_stmt_xfetched:
|
|
switch (retcode)
|
|
{
|
|
case SQL_SUCCESS:
|
|
case SQL_SUCCESS_WITH_INFO:
|
|
case SQL_NO_DATA_FOUND:
|
|
pstmt->state = en_stmt_xfetched;
|
|
pstmt->cursor_state = en_stmt_cursor_xfetched;
|
|
break;
|
|
|
|
case SQL_STILL_EXECUTING:
|
|
pstmt->asyn_on = en_ExtendedFetch;
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
|
|
return retcode;
|
|
}
|
|
|
|
|
|
RETCODE SQL_API
|
|
SQLGetData (
|
|
HSTMT hstmt,
|
|
UWORD icol,
|
|
SWORD fCType,
|
|
PTR rgbValue,
|
|
SDWORD cbValueMax,
|
|
SDWORD FAR * pcbValue)
|
|
{
|
|
STMT_t FAR *pstmt = (STMT_t FAR *) hstmt;
|
|
HPROC hproc;
|
|
RETCODE retcode;
|
|
int sqlstat = en_00000;
|
|
|
|
if (hstmt == SQL_NULL_HSTMT || pstmt->hdbc == SQL_NULL_HDBC)
|
|
{
|
|
return SQL_INVALID_HANDLE;
|
|
}
|
|
|
|
/* check argument */
|
|
if (rgbValue == NULL)
|
|
{
|
|
sqlstat = en_S1009;
|
|
}
|
|
else if (cbValueMax < 0)
|
|
{
|
|
sqlstat = en_S1090;
|
|
}
|
|
else
|
|
{
|
|
switch (fCType)
|
|
{
|
|
case SQL_C_DEFAULT:
|
|
case SQL_C_CHAR:
|
|
case SQL_C_BINARY:
|
|
case SQL_C_BIT:
|
|
case SQL_C_TINYINT:
|
|
case SQL_C_STINYINT:
|
|
case SQL_C_UTINYINT:
|
|
case SQL_C_SHORT:
|
|
case SQL_C_SSHORT:
|
|
case SQL_C_USHORT:
|
|
case SQL_C_LONG:
|
|
case SQL_C_SLONG:
|
|
case SQL_C_ULONG:
|
|
case SQL_C_FLOAT:
|
|
case SQL_C_DOUBLE:
|
|
case SQL_C_DATE:
|
|
case SQL_C_TIME:
|
|
case SQL_C_TIMESTAMP:
|
|
break;
|
|
|
|
default:
|
|
sqlstat = en_S1003;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (sqlstat != en_00000)
|
|
{
|
|
PUSHSQLERR (pstmt->herr, sqlstat);
|
|
|
|
return SQL_ERROR;
|
|
}
|
|
|
|
/* check state */
|
|
if (pstmt->asyn_on == en_NullProc)
|
|
{
|
|
switch (pstmt->state)
|
|
{
|
|
case en_stmt_allocated:
|
|
case en_stmt_prepared:
|
|
case en_stmt_needdata:
|
|
case en_stmt_mustput:
|
|
case en_stmt_canput:
|
|
sqlstat = en_S1010;
|
|
break;
|
|
|
|
case en_stmt_executed:
|
|
case en_stmt_cursoropen:
|
|
sqlstat = en_24000;
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
else if (pstmt->asyn_on != en_GetData)
|
|
{
|
|
sqlstat = en_S1010;
|
|
}
|
|
|
|
if (sqlstat != en_00000)
|
|
{
|
|
PUSHSQLERR (pstmt->herr, sqlstat);
|
|
|
|
return SQL_ERROR;
|
|
}
|
|
|
|
/* call driver */
|
|
hproc = _iodbcdm_getproc (pstmt->hdbc, en_GetData);
|
|
|
|
if (hproc == SQL_NULL_HPROC)
|
|
{
|
|
PUSHSQLERR (pstmt->herr, en_IM001);
|
|
|
|
return SQL_ERROR;
|
|
}
|
|
|
|
CALL_DRIVER (pstmt->hdbc, retcode, hproc, en_GetData,
|
|
(pstmt->dhstmt, icol, fCType, rgbValue, cbValueMax, pcbValue))
|
|
|
|
/* state transition */
|
|
if (pstmt->asyn_on == en_GetData)
|
|
{
|
|
switch (retcode)
|
|
{
|
|
case SQL_SUCCESS:
|
|
case SQL_SUCCESS_WITH_INFO:
|
|
case SQL_NO_DATA_FOUND:
|
|
case SQL_ERROR:
|
|
pstmt->asyn_on = en_NullProc;
|
|
break;
|
|
|
|
case SQL_STILL_EXECUTING:
|
|
default:
|
|
return retcode;
|
|
}
|
|
}
|
|
|
|
switch (pstmt->state)
|
|
{
|
|
case en_stmt_fetched:
|
|
case en_stmt_xfetched:
|
|
if (retcode == SQL_STILL_EXECUTING)
|
|
{
|
|
pstmt->asyn_on = en_GetData;
|
|
break;
|
|
}
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
|
|
return retcode;
|
|
}
|
|
|
|
|
|
RETCODE SQL_API
|
|
SQLMoreResults (HSTMT hstmt)
|
|
{
|
|
STMT_t FAR *pstmt = (STMT_t FAR *) hstmt;
|
|
HPROC hproc;
|
|
RETCODE retcode;
|
|
|
|
if (hstmt == SQL_NULL_HSTMT
|
|
|| pstmt->hdbc == SQL_NULL_HDBC)
|
|
{
|
|
return SQL_INVALID_HANDLE;
|
|
}
|
|
|
|
/* check state */
|
|
if (pstmt->asyn_on == en_NullProc)
|
|
{
|
|
switch (pstmt->state)
|
|
{
|
|
case en_stmt_allocated:
|
|
case en_stmt_prepared:
|
|
return SQL_NO_DATA_FOUND;
|
|
|
|
case en_stmt_needdata:
|
|
case en_stmt_mustput:
|
|
case en_stmt_canput:
|
|
PUSHSQLERR (pstmt->herr, en_S1010);
|
|
return SQL_ERROR;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
else if (pstmt->asyn_on != en_MoreResults)
|
|
{
|
|
PUSHSQLERR (pstmt->herr, en_S1010);
|
|
|
|
return SQL_ERROR;
|
|
}
|
|
|
|
/* call driver */
|
|
hproc = _iodbcdm_getproc (pstmt->hdbc, en_MoreResults);
|
|
|
|
if (hproc == SQL_NULL_HPROC)
|
|
{
|
|
PUSHSQLERR (pstmt->herr, en_IM001);
|
|
|
|
return SQL_ERROR;
|
|
}
|
|
|
|
CALL_DRIVER (pstmt->hdbc, retcode, hproc, en_MoreResults,
|
|
(pstmt->dhstmt))
|
|
|
|
/* state transition */
|
|
if (pstmt->asyn_on == en_MoreResults)
|
|
{
|
|
switch (retcode)
|
|
{
|
|
case SQL_SUCCESS:
|
|
case SQL_SUCCESS_WITH_INFO:
|
|
case SQL_NO_DATA_FOUND:
|
|
case SQL_ERROR:
|
|
pstmt->asyn_on = en_NullProc;
|
|
break;
|
|
|
|
case SQL_STILL_EXECUTING:
|
|
default:
|
|
return retcode;
|
|
}
|
|
}
|
|
|
|
switch (pstmt->state)
|
|
{
|
|
case en_stmt_allocated:
|
|
case en_stmt_prepared:
|
|
/* driver should return SQL_NO_DATA_FOUND */
|
|
break;
|
|
|
|
case en_stmt_executed:
|
|
if (retcode == SQL_NO_DATA_FOUND)
|
|
{
|
|
if (pstmt->prep_state)
|
|
{
|
|
pstmt->state = en_stmt_prepared;
|
|
}
|
|
else
|
|
{
|
|
pstmt->state = en_stmt_allocated;
|
|
}
|
|
}
|
|
else if (retcode == SQL_STILL_EXECUTING)
|
|
{
|
|
pstmt->asyn_on = en_MoreResults;
|
|
}
|
|
break;
|
|
|
|
case en_stmt_cursoropen:
|
|
case en_stmt_fetched:
|
|
case en_stmt_xfetched:
|
|
if (retcode == SQL_SUCCESS)
|
|
{
|
|
break;
|
|
}
|
|
else if (retcode == SQL_NO_DATA_FOUND)
|
|
{
|
|
if (pstmt->prep_state)
|
|
{
|
|
pstmt->state = en_stmt_prepared;
|
|
}
|
|
else
|
|
{
|
|
pstmt->state = en_stmt_allocated;
|
|
}
|
|
}
|
|
else if (retcode == SQL_STILL_EXECUTING)
|
|
{
|
|
pstmt->asyn_on = en_MoreResults;
|
|
}
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
|
|
return retcode;
|
|
}
|
|
|
|
|
|
RETCODE SQL_API
|
|
SQLSetPos (
|
|
HSTMT hstmt,
|
|
UWORD irow,
|
|
UWORD fOption,
|
|
UWORD fLock)
|
|
{
|
|
STMT_t FAR *pstmt = (STMT_t FAR *) hstmt;
|
|
HPROC hproc;
|
|
RETCODE retcode;
|
|
int sqlstat = en_00000;
|
|
|
|
if (hstmt == SQL_NULL_HSTMT || pstmt->hdbc == SQL_NULL_HDBC)
|
|
{
|
|
return SQL_INVALID_HANDLE;
|
|
}
|
|
|
|
/* check argument value */
|
|
if (fOption > SQL_ADD || fLock > SQL_LOCK_UNLOCK)
|
|
{
|
|
PUSHSQLERR (pstmt->herr, en_S1009);
|
|
}
|
|
|
|
/* check state */
|
|
if (pstmt->asyn_on == en_NullProc)
|
|
{
|
|
switch (pstmt->state)
|
|
{
|
|
case en_stmt_allocated:
|
|
case en_stmt_prepared:
|
|
case en_stmt_fetched:
|
|
case en_stmt_needdata:
|
|
case en_stmt_mustput:
|
|
case en_stmt_canput:
|
|
sqlstat = en_S1010;
|
|
break;
|
|
|
|
case en_stmt_executed:
|
|
case en_stmt_cursoropen:
|
|
sqlstat = en_24000;
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
else if (pstmt->asyn_on != en_SetPos)
|
|
{
|
|
sqlstat = en_S1010;
|
|
}
|
|
|
|
if (sqlstat != en_00000)
|
|
{
|
|
PUSHSQLERR (pstmt->herr, sqlstat);
|
|
|
|
return SQL_ERROR;
|
|
}
|
|
|
|
/* call driver */
|
|
hproc = _iodbcdm_getproc (pstmt->hdbc, en_SetPos);
|
|
|
|
if (hproc == SQL_NULL_HPROC)
|
|
{
|
|
PUSHSQLERR (pstmt->herr, en_IM001);
|
|
|
|
return SQL_ERROR;
|
|
}
|
|
|
|
CALL_DRIVER (pstmt->hdbc, retcode, hproc, en_SetPos,
|
|
(pstmt->dhstmt, irow, fOption, fLock))
|
|
|
|
/* state transition */
|
|
if (pstmt->asyn_on == en_SetPos)
|
|
{
|
|
switch (retcode)
|
|
{
|
|
case SQL_SUCCESS:
|
|
case SQL_SUCCESS_WITH_INFO:
|
|
case SQL_NEED_DATA:
|
|
case SQL_ERROR:
|
|
pstmt->asyn_on = en_NullProc;
|
|
break;
|
|
|
|
case SQL_STILL_EXECUTING:
|
|
default:
|
|
return retcode;
|
|
}
|
|
}
|
|
|
|
/* now, the only possible init state is 'xfetched' */
|
|
switch (retcode)
|
|
{
|
|
case SQL_SUCCESS:
|
|
case SQL_SUCCESS_WITH_INFO:
|
|
break;
|
|
|
|
case SQL_NEED_DATA:
|
|
pstmt->state = en_stmt_needdata;
|
|
pstmt->need_on = en_SetPos;
|
|
break;
|
|
|
|
case SQL_STILL_EXECUTING:
|
|
pstmt->asyn_on = en_SetPos;
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
|
|
return retcode;
|
|
}
|