diff --git a/harbour/ChangeLog b/harbour/ChangeLog index a27eba1fd9..e282f20d4d 100644 --- a/harbour/ChangeLog +++ b/harbour/ChangeLog @@ -1,3 +1,16 @@ +19991020-22:58 GMT+3 Alexander Kresin + * source/pp/hbpp.c + * Fixed bugs, reported by Antonio Linares, Victor Szel and Guy Roussin + - contrib/odbc/bld32exe.bat + - contrib/odbc/hb32.bat + + contrib/odbc/bld_b32.bat + + contrib/odbc/odbccall.prg + + contrib/odbc/odbcdemo.prg + * contrib/odbc/odbc.c + * contrib/odbc/harbour.mdb + * These files I got from Felipe Coury + + 19991020-20:23 GMT+1 Victor Szel * source/rtl/alert.prg source/rtl/browdb.prg @@ -6,29 +19,29 @@ + include/hbsetup.ch include/hbsetup.h include/Makefile - + New header file added to setup things which are common to both - .PRG and .C source files, currently HARBOUR_STRICT_CLIPPER_COMPATIBILITY + + New header file added to setup things which are common to both + .PRG and .C source files, currently HARBOUR_STRICT_CLIPPER_COMPATIBILITY was moved from hbsetup.h + HB_COMPAT_C53 - HB_COMPAT_XPP + HB_COMPAT_XPP HB_COMPAT_VO - #defines added to be able to toggle inclusion of the new features + #defines added to be able to toggle inclusion of the new features of these compilers. All these are turned on by default. * source/rtl/browdb.prg - + dbSkipper() function added, it's now guarded with - HARBOUR_COMPAT_XPP, so there is a possibility to switch to the + + dbSkipper() function added, it's now guarded with + HARBOUR_COMPAT_XPP, so there is a possibility to switch to the fully Clipper compliant, or the XBase++ compliant method. + NOTE added about dbSkipper. * source/rtl/filesys.c + source/rtl/binnum.c (added) - * BIN2W(), BIN2I(), BIN2L(), I2BIN(), L2BIN() functions moved to + * BIN2W(), BIN2I(), BIN2L(), I2BIN(), L2BIN() functions moved to a separate source file. Since these were not FileSys APi functions. WARNING ! Please update non-GNU make systems. - include/caundoc.api renamed to + include/hbundoc.api include/Makefile tests/extend2.c - * Include file name standardized, now the HBUNDOC.API file should + * Include file name standardized, now the HBUNDOC.API file should contain all undocumented API calls (not only for CA-Cl*pper). - include/harbour.ch renamed to + include/hbclip.ch @@ -67,7 +80,7 @@ modules and standard OS makefiles. MAX() -> HB_MAX_() MIN() -> HB_MIN_() - (the additional underscore is need to avoid name collisions with + (the additional underscore is need to avoid name collisions with Harbour functions HB_MIN() and HB_MAX()) LOBYTE() -> HB_LOBYTE() HIBYTE() -> HB_HIBYTE() @@ -90,7 +103,7 @@ include/hbextern.ch source/runner/stdalone/external.prg + Public dbSkipper() function made STATIC, renamed to Skipped() to be - Clipper compatible. Clipper doesn't have any public dbSkipper(), + Clipper compatible. Clipper doesn't have any public dbSkipper(), _dbSkipper() or Skipped() functions. - Non-Clipper compatible function _dbSkipper() removed. * Formatted. diff --git a/harbour/contrib/odbc/bld32exe.bat b/harbour/contrib/odbc/bld32exe.bat deleted file mode 100644 index db228d15fb..0000000000 --- a/harbour/contrib/odbc/bld32exe.bat +++ /dev/null @@ -1,28 +0,0 @@ -@echo off - -IF A%1 == A GOTO :SINTAX -IF A%2 == A GOTO :NOOUTPUT - -echo -O2 -e%2.exe -I..\..\include ..\..\source\vm\hvm.c %1.c > b32.bc -echo ..\..\libs\b32\harbour.lib ..\..\libs\b32\terminal.lib >> b32.bc -echo ..\..\libs\b32\hbgt.lib ..\..\libs\b32\hbpp.lib >> b32.bc -echo ..\..\libs\b32\hbodbc.lib ..\..\libs\b32\odbc32.lib >> b32.bc -bcc32 @b32.bc -del b32.bc -GOTO :END - -:NOOUTPUT -echo -O2 -e%1.exe -I..\..\include ..\..\source\vm\hvm.c %1.c > b32.bc -echo ..\..\libs\b32\harbour.lib ..\..\libs\b32\terminal.lib >> b32.bc -echo ..\..\libs\b32\hbgt.lib ..\..\libs\b32\hbpp.lib >> b32.bc -echo ..\..\libs\b32\hbodbc.lib ..\..\libs\b32\odbc32.lib >> b32.bc -bcc32 @b32.bc -del b32.bc -GOTO :END - -:SINTAX -ECHO syntax: BuildExe Harbour_Output_Filename [Exe_Output_Filename] -ECHO Use Harbour_Output_Filename and Exe_Output_Filename without extensions -ECHO\ - -:END diff --git a/harbour/contrib/odbc/bld_b32.bat b/harbour/contrib/odbc/bld_b32.bat new file mode 100644 index 0000000000..56a496ce1a --- /dev/null +++ b/harbour/contrib/odbc/bld_b32.bat @@ -0,0 +1,8 @@ +@echo off +rem +rem $Id$ +rem + +..\..\bin\harbour %1 /n /i..\include %2 +bcc32 -e%1.exe -O2 -I..\..\include -L..\..\lib\b32 -v harbour.lib terminal.lib hbpp.lib hbgt.lib rdd.lib hbodbc.lib odbc32.lib %1.c +rem del %1.c diff --git a/harbour/contrib/odbc/bldodbc.bat b/harbour/contrib/odbc/bldodbc.bat index f9a8a738d1..10a0bacd4f 100644 --- a/harbour/contrib/odbc/bldodbc.bat +++ b/harbour/contrib/odbc/bldodbc.bat @@ -1,3 +1,3 @@ @echo off make -fhbodbc.b32 -implib ..\..\libs\b32\odbc32.lib odbc32.def +implib ..\..\lib\b32\odbc32.lib odbc32.def diff --git a/harbour/contrib/odbc/harbour.mdb b/harbour/contrib/odbc/harbour.mdb index 3095cf0b28..f50d9470df 100644 Binary files a/harbour/contrib/odbc/harbour.mdb and b/harbour/contrib/odbc/harbour.mdb differ diff --git a/harbour/contrib/odbc/hb32.bat b/harbour/contrib/odbc/hb32.bat deleted file mode 100644 index ec1d5ea826..0000000000 --- a/harbour/contrib/odbc/hb32.bat +++ /dev/null @@ -1,10 +0,0 @@ -@echo off - -REM From .PRG to .C = Harbour -..\..\bin\harbour %1.prg /n /i..\..\include -if errorlevel 1 goto end - -REM From .C to .EXE = BuildExe -call BLD32EXE %1 %2 - -:end diff --git a/harbour/contrib/odbc/hbodbc.b32 b/harbour/contrib/odbc/hbodbc.b32 index 8c30e31859..aa8560101e 100644 --- a/harbour/contrib/odbc/hbodbc.b32 +++ b/harbour/contrib/odbc/hbodbc.b32 @@ -1,15 +1,20 @@ # makefile for Borland C/C++ 32 bits -# ODBC Harbor Library and Import Library makefile +# ODBC Harbour Library and Import Library makefile .path.c = . -.path.h = .;include -.path.lib = ..\..\libs\b32 -.path.obj = obj +.path.h = .\;..\..\include;..\..\source\pp +.path.lib = ..\..\lib\b32 +.path.obj = ..\..\obj -libs\b32\hbodbc.lib : odbc.obj -odbc.obj : odbc.c +lib\b32\hbodbc.lib : odbc.obj todbc.obj +odbc.obj : odbc.c +todbc.obj : todbc.c +todbc.c : todbc.prg .c.obj : - bcc32 -c -O2 -I..\..\include;..\..\source\hbpp -o$@ $< - tlib ..\..\libs\b32\hbodbc.lib -+$@,, - implib ..\..\libs\b32\odbc32.lib odbc32.def + bcc32 -c -O2 -I.\;..\..\include;..\..\source\pp -o$@ $< + tlib ..\..\lib\b32\hbodbc.lib -+$@,, + implib ..\..\lib\b32\odbc32.lib odbc32.def + +.prg.c : + ..\bin\harbour $< /n /i..\..\include diff --git a/harbour/contrib/odbc/odbc.c b/harbour/contrib/odbc/odbc.c index 484c344737..0d2a604c5b 100644 --- a/harbour/contrib/odbc/odbc.c +++ b/harbour/contrib/odbc/odbc.c @@ -31,8 +31,23 @@ along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA (or visit their web site at http://www.gnu.org/). + + */ +/* + * The following parts are Copyright of the individual authors. + * www - http://www.harbour-project.org + * + * Copyright 1999 Felipe G. Coury + * HB_SQLNUMRES() + * HB_SQLDESCRIB() + * HB_SQLEXTENDE() + * + * See doc/license.txt for licensing terms. + * + */ + #include #include #include @@ -41,9 +56,10 @@ #include #include "extend.h" #include "itemapi.h" -#include "harb.h" +#include "hbdefs.h" #include #include +#include HARBOUR HB_SQLALLOCEN( void ) /* HB_SQLALLOCENV( @hEnv ) --> nRetCode */ { @@ -128,3 +144,88 @@ HARBOUR HB_SQLGETDATA( void ) /* HB_SQLGETDATA( hStmt, nField, nType, nLen, @cBu hb_xfree( ( PTR ) bBuffer ); hb_retni( wResult ); } + +/* HB_NUMRESULTCOLS( hStmt, @nColCount ) */ +HARBOUR HB_SQLNUMRES( void ) +{ + SQLSMALLINT nCols; + WORD wResult = SQLNumResultCols( ( HSTMT ) hb_parnl( 1 ), &nCols ); + + if( wResult == SQL_SUCCESS || wResult == SQL_SUCCESS_WITH_INFO ) + hb_stornl( ( LONG ) nCols, 2 ); + + hb_retni( wResult ); +} + +/* HB_SQLDESCRIBECOL( hStmt, nCol, @cName, nLen, @nBufferLen, @nDataType, @nColSize, @nDec, @nNull ) --> nRetCode */ +HARBOUR HB_SQLDESCRIB( void ) +{ + SDWORD lLen = ( SDWORD ) hb_parnl( 4 ); + PTR bBuffer = hb_xgrab( lLen ); + SQLSMALLINT wBufLen = hb_parni( 5 ); + SQLSMALLINT wDataType = hb_parni( 6 ); + SQLUINTEGER wColSize = hb_parni( 7 ); + SQLSMALLINT wDecimals = hb_parni( 8 ); + SQLSMALLINT wNullable = hb_parni( 9 ); + WORD wResult = SQLDescribeCol( ( HSTMT ) hb_parnl( 1 ), hb_parni( 2 ), + ( PTR ) bBuffer, hb_parni( 4 ), &wBufLen, + &wDataType, &wColSize, &wDecimals, + &wNullable ); + + if( wResult == SQL_SUCCESS || wResult == SQL_SUCCESS_WITH_INFO ) + { + hb_storclen( ( LPSTR ) bBuffer, + ( WORD ) wBufLen, 3 ); + hb_stornl( ( LONG ) wBufLen, 5 ); + hb_stornl( ( LONG ) wDataType, 6 ); + hb_stornl( ( LONG ) wColSize, 7 ); + hb_stornl( ( LONG ) wDecimals, 8 ); + hb_stornl( ( LONG ) wNullable, 9 ); + } + + hb_xfree( ( PTR ) bBuffer ); + hb_retni( wResult ); +} + +/* HB_SQLEXTENDEDFETCH( hStmt, nOrientation, nOffset, @nRows, @nRowStatus ) */ +HARBOUR HB_SQLEXTENDE( void ) +{ + SQLUINTEGER uiRowCountPtr = hb_parni( 4 ); + SQLUSMALLINT siRowStatus = hb_parni( 5 ); + WORD wResult = SQLExtendedFetch( ( HSTMT ) hb_parnl( 1 ), + hb_parnl( 2 ), + hb_parnl( 3 ), + &uiRowCountPtr, + &siRowStatus ); + + if( wResult == SQL_SUCCESS || wResult == SQL_SUCCESS_WITH_INFO ) + { + hb_stornl( ( LONG ) uiRowCountPtr, 4 ); + hb_stornl( ( LONG ) siRowStatus, 5 ); + } + + hb_retni( wResult ); +} + +HARBOUR HB_SQLFETCHSC( void ) +{ + hb_retni( SQLFetchScroll( ( HSTMT ) hb_parnl( 1 ), + hb_parnl( 2 ), hb_parnl( 3 ) ) ); +} + +HARBOUR HB_SQLERROR() // hEnv, hDbc, hStmt, @ cErrorClass, @ nType, @ cErrorMsg +{ + BYTE bBuffer1[ 256 ], szErrorMsg[ 256 ]; + UDWORD lError; + SWORD wLen; + + hb_retni( SQLError( ( HENV ) hb_parnl( 1 ), ( HDBC ) hb_parnl( 2 ), + ( HSTMT ) hb_parnl( 3 ), bBuffer1, &lError, + szErrorMsg, 256, &wLen ) ); + + hb_storc( bBuffer1, 4 ); + hb_stornl( lError, 5 ); + hb_storc( szErrorMsg, 6 ); +} + + diff --git a/harbour/contrib/odbc/odbccall.prg b/harbour/contrib/odbc/odbccall.prg new file mode 100644 index 0000000000..98c5c5b5bf --- /dev/null +++ b/harbour/contrib/odbc/odbccall.prg @@ -0,0 +1,36 @@ +#xcommand WITH DO => Self := +#xcommand ENDWITH => Self := NIL + +FUNCTION Main() + + LOCAL cExePath := substr( __argv(0), 1, rat( "\", __argv(0) ) - 1 ) + LOCAL cConStr := ; + "DBQ=" + cExePath + "\harbour.mdb;" + ; + "Driver={Microsoft Access Driver (*.mdb)}" + + LOCAL dsFunctions := TODBC():New( "xx" ) // cConStr ) + + WITH dsFunctions DO + + ::SetSQL( "SELECT * FROM Functions" ) + ::Open() + ? ::FieldByName( "Code" ):Value + ? ::Skip() + ? ::FieldByName( "Code" ):Value + ? ::GoTo( 1 ) + ? ::FieldByName( "Code" ):Value + ? ::Prior() + ? ::FieldByName( "Code" ):Value + ? ::First() + ? ::FieldByName( "Code" ):Value + ? ::Last() + ? ::FieldByName( "Code" ):Value + ? ::Close() + + ENDWITH + + dsFunctions:Destroy() + + RETURN( NIL ) + + diff --git a/harbour/contrib/odbc/odbcdemo.prg b/harbour/contrib/odbc/odbcdemo.prg new file mode 100644 index 0000000000..cff9ca3840 --- /dev/null +++ b/harbour/contrib/odbc/odbcdemo.prg @@ -0,0 +1,85 @@ + +*+-------------------------------------------------------------------- +*+ +*+ Function Main() +*+ +*+-------------------------------------------------------------------- +*+ +FUNCTION Main() + + LOCAL aOrders + LOCAL nOp + LOCAL dsFunctions + +// LOCAL cExePath := substr( cargv(), 1, rat( "\", cargv() ) - 1 ) + LOCAL cConStr := ; + "DBQ=" + "harbour.mdb;" + ; + "Driver={Microsoft Access Driver (*.mdb)}" + + dsFunctions := TODBC():New( cConStr ) + + set COLOR TO "W+/B" + CLS + + WHILE .T. + + @ 00, 00 SAY padc( "þ TODBC Demonstration þ", 80 ) COLOR "B/W" + + dsFunctions:SetSQL( "SELECT * FROM Functions" ) + dsFunctions:Open() + + @ 03, 24 TO len( dsFunctions:Fields ) + 4, 55 + + aOrders := {} + FOR i := 1 TO len( dsFunctions:Fields ) + + aadd( aOrders, dsFunctions:Fields[ i ] :FieldName ) + @ i + 3, 25 PROMPT padc( "ORDER BY " + aOrders[ i ], 30 ) + + NEXT + + MENU TO nOp + + IF nOp == 0 + EXIT + ENDIF + + dsFunctions:Close() + + dsFunctions:SetSQL( "SELECT * FROM Functions ORDER BY " + aOrders[ nOp ] ) + dsFunctions:Open() + + FOR i := 11 TO 24 + @ i, 00 SAY REPL( " ", 80 ) + NEXT + + @ 10, 00 TO 10, 79 + @ 24, 00 TO 24, 79 + @ 12, 00 TO 12, 79 + @ 11, 00 SAY "" + + @ 11, 02 SAY "Statement:" COLOR "GR+/B" + @ 11, col() + 1 SAY dsFunctions:cSQL + + @ 14, 05 SAY " " + padr( dsFunctions:FieldByName( "Code" ) :FieldName, 3 ) + " " + ; + padr( dsFunctions:FieldByName( "Function" ) :FieldName, 15 ) + " " + ; + padr( dsFunctions:FieldByName( "State" ) :FieldName, 2 ) + " " + ; + padr( dsFunctions:FieldByName( "Comments" ) :FieldName, 40 ) ; + COLOR "B/W" + + WHILE !dsFunctions:Eof() + ? " " + padr( dsFunctions:FieldByName( "Code" ) :Value, 3 ), "³", ; + padr( dsFunctions:FieldByName( "Function" ) :Value, 15 ), "³", ; + padr( dsFunctions:FieldByName( "State" ) :Value, 2 ), "³", ; + padr( dsFunctions:FieldByName( "Comments" ) :Value, 40 ) + dsFunctions:Skip() + ENDDO + + dsFunctions:Close() + + ENDDO + dsFunctions:Destroy() + +RETURN ( NIL ) + +*+ EOF: ODBCDEMO.PRG diff --git a/harbour/contrib/odbc/sql.ch b/harbour/contrib/odbc/sql.ch index c59aade160..ace9509908 100644 --- a/harbour/contrib/odbc/sql.ch +++ b/harbour/contrib/odbc/sql.ch @@ -92,4 +92,11 @@ nullablity of a column in a table. */ #define SQL_NULL_HDBC 0 #define SQL_NULL_HSTMT 0 +#define SQL_FETCH_NEXT 1 +#define SQL_FETCH_FIRST 2 +#define SQL_FETCH_LAST 3 +#define SQL_FETCH_PRIOR 4 +#define SQL_FETCH_ABSOLUTE 5 +#define SQL_FETCH_RELATIVE 6 +#define SQL_FETCH_BOOKMARK 8 diff --git a/harbour/contrib/odbc/sql.h b/harbour/contrib/odbc/sql.h index 6aa49d658b..b4c53b404e 100644 --- a/harbour/contrib/odbc/sql.h +++ b/harbour/contrib/odbc/sql.h @@ -1250,6 +1250,11 @@ SQLRETURN SQL_API SQLSetScrollOptions( /* Use SQLSetStmtOptions */ SQLINTEGER crowKeyset, SQLUSMALLINT crowRowset); +SQLRETURN SQL_API SQLFetchScroll( + SQLHSTMT hstmt, + SQLSMALLINT fOrientation, + SQLINTEGER fOffset); + #endif /* RC_INVOKED */ #ifdef __cplusplus diff --git a/harbour/source/pp/hbpp.c b/harbour/source/pp/hbpp.c index 5f9e7854e7..3d4a747829 100644 --- a/harbour/source/pp/hbpp.c +++ b/harbour/source/pp/hbpp.c @@ -65,7 +65,7 @@ int WorkCommand ( char*, char*, COMMANDS* ); int WorkTranslate ( char*, char*, COMMANDS*, int* ); int CommandStuff ( char *, char *, char *, int*, int, int ); int RemoveSlash( char * ); -int WorkMarkers( char**, char**, char*, int* ); +int WorkMarkers( char**, char**, char*, int*, int ); int getExpReal ( char *, char **, int, int ); int isExpres ( char* ); int TestOptional( char*, char* ); @@ -88,7 +88,7 @@ int strocpy (char*, char* ); int stroncpy (char*, char*, int); int strincpy (char*, char*); int truncmp (char**, char**, int); -int strincmp (char*, char**); +int strincmp (char*, char**, int); int strolen ( char* ); void stroupper ( char* ); int strotrim ( char* ); @@ -865,7 +865,7 @@ int CommandStuff ( char *ptrmp, char *inputLine, char * ptro, int *lenres, int c aIsRepeate[ Repeate ] = 0; lastopti[Repeate++] = ptrmp; ptrmp++; - if( !CheckOptional( ptrmp, ptri, ptro, lenres, com_or_xcom, com_or_xcom ) ) + if( !CheckOptional( ptrmp, ptri, ptro, lenres, com_or_tra, com_or_xcom ) ) SkipOptional( &ptrmp ); break; case ']': @@ -914,7 +914,7 @@ int CommandStuff ( char *ptrmp, char *inputLine, char * ptro, int *lenres, int c break; case '\1': /* Match marker */ if( !numBrackets ) strtopti = NULL; - if ( !WorkMarkers( &ptrmp, &ptri, ptro, lenres ) ) + if ( !WorkMarkers( &ptrmp, &ptri, ptro, lenres, com_or_xcom ) ) { if ( numBrackets ) { @@ -1016,7 +1016,7 @@ int RemoveSlash( char *stroka ) return lenres; } -int WorkMarkers( char **ptrmp, char **ptri, char *ptro, int *lenres ) +int WorkMarkers( char **ptrmp, char **ptri, char *ptro, int *lenres, int com_or_xcom ) { char expreal[MAX_NAME], exppatt[MAX_NAME]; int lenreal = 0, maxlenreal = STR_SIZE, lenpatt; @@ -1123,7 +1123,7 @@ int WorkMarkers( char **ptrmp, char **ptri, char *ptro, int *lenres ) SKIPTABSPACES( ptr ); /* Comparing real parameter and restriction value */ ptrtemp = ptr; - if ( !strincmp ( *ptri, &ptr ) ) + if ( !strincmp ( *ptri, &ptr, !com_or_xcom ) ) { lenreal = stroncpy( expreal, *ptri, (ptr-ptrtemp) ); *ptri += lenreal; @@ -1355,7 +1355,7 @@ int CheckOptional( char* ptrmp, char* ptri, char* ptro, int* lenres, int com_or_ } break; case '\1': /* Match marker */ - if ( !WorkMarkers( &ptrmp, &ptri, ptro, lenres ) ) + if ( !WorkMarkers( &ptrmp, &ptri, ptro, lenres, com_or_xcom ) ) { if ( numBrackets - save_numBr > 0 ) { @@ -1382,10 +1382,30 @@ int CheckOptional( char* ptrmp, char* ptri, char* ptro, int* lenres, int com_or_ } SKIPTABSPACES( ptri ); }; + if ( *ptri == '\0' ) + { + do + { + SKIPTABSPACES( ptrmp ); + if( *ptrmp == '[' ) + { + ptrmp++; + SkipOptional( &ptrmp ); + } + else if( *ptrmp == ']' ) + break; + else + { + result = 0; + break; + } + } + while ( 1 ); + } Repeate = save_Repeate; numBrackets = save_numBr; lReplacePat = TRUE; - return result; + return result ; } void SkipOptional( char** ptri ) @@ -1930,9 +1950,9 @@ int truncmp (char** ptro, char** ptri, int lTrunc ) } return 1; } -int strincmp (char* ptro, char** ptri ) +int strincmp (char* ptro, char** ptri, int lTrunc ) { - char co, ci; + char *ptrb = ptro, co, ci; for ( ; **ptri != ',' && **ptri != '[' && **ptri != ']' && **ptri != '\1' && **ptri != '\0' && toupper(**ptri)==toupper(*ptro); @@ -1944,6 +1964,11 @@ int strincmp (char* ptro, char** ptri ) ( ( !ISNAME(*ptro) && ISNAME(co) ) || ( !ISNAME(co) ) ) ) ) return 0; + else if ( lTrunc && ptro-ptrb >= 4 && ISNAME(ci) && !ISNAME(*ptro) && ISNAME(co) ) + { +// while( ISNAME(**ptri) ) (*ptri)++; + return 0; + } return 1; }