--- /dev/null
+/** Fetch query result
+
+ Copyright (C) 1995 by Ke Jin <kejin@empress.com>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program 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 General Public License for more details.
+**/
+
+#include <../iodbc/iodbc.h>
+
+#include <../iodbc/isql.h>
+#include <../iodbc/isqlext.h>
+
+#include <../iodbc/dlproc.h>
+
+#include <../iodbc/herr.h>
+#include <../iodbc/henv.h>
+#include <../iodbc/hdbc.h>
+#include <../iodbc/hstmt.h>
+
+#include <../iodbc/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) )
+
+#if 0
+ retcode = hproc( pstmt->dhstmt );
+#endif
+ /* 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 ) )
+
+#if 0
+ retcode = hproc(pstmt->dhstmt,
+ fFetchType,
+ irow,
+ pcrow,
+ rgfRowStatus );
+#endif
+
+ /* 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 ) )
+
+#if 0
+ retcode = hproc(pstmt->dhstmt,
+ icol,
+ fCType,
+ rgbValue,
+ cbValueMax,
+ pcbValue );
+#endif
+
+ /* 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) )
+
+#if 0
+ retcode = hproc( pstmt->dhstmt );
+#endif
+
+ /* 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 ) )
+#if 0
+ retcode = hproc(pstmt->dhstmt,
+ irow,
+ fOption,
+ fLock );
+#endif
+
+ /* 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;
+}