/** Fetch query result Copyright (C) 1995 by Ke Jin 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; }