]> git.saurik.com Git - wxWidgets.git/blobdiff - src/iodbc/fetch.c
added ODBC support
[wxWidgets.git] / src / iodbc / fetch.c
diff --git a/src/iodbc/fetch.c b/src/iodbc/fetch.c
new file mode 100644 (file)
index 0000000..85bd13e
--- /dev/null
@@ -0,0 +1,675 @@
+/** 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;
+}