/////////////////////////////////////////////////////////////////////////////// // PXEngine.cpp // // // // Copyright (c) Jan Knepper, 1998. All Rights Reserved. // // Written by Jan Knepper // // // // Redistribution and use in source and binary forms, with or without // // modification, are permitted provided that the following conditions // // are met: // // 1. Redistributions of source code must retain the above copyright // // notice, this list of conditions and the following disclaimer. // // 2. Redistributions in binary form must reproduce the above copyright // // notice, this list of conditions and the following disclaimer in the // // documentation and/or other materials provided with the distribution. // // 3. The name of the author may not be used to endorse or promote products // // derived from this software without specific prior written permission. // // // // THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND // // ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE // // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR // // PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE // // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR // // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF // // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS // // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN // // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) // // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF // // THE POSSIBILITY OF SUCH DAMAGE. // /////////////////////////////////////////////////////////////////////////////// #include #include #include #include #include #include //#include typedef struct __TABLE { TABLEHANDLE handle; hDBICur cursor; int index; int used; } _TABLE; typedef struct __RECORD { RECORDHANDLE handle; phDBICur cursor; pBYTE buffer; int size; } _RECORD; typedef struct __DROPLIST { char *tablename; char *indexname; struct __DROPLIST *next; } _DROPLIST; static const char *THISFILE = __FILE__; static int table_size = 0; static _TABLE *table_list = NULL; static int record_size = 0; static _RECORD *record_list = NULL; static _DROPLIST *droplist = NULL; static hDBIDb hDB; static DBIResult _CreateTable4 ( const char *, TABLEHANDLE *, int, int ); static DBIResult _DeleteTable4 ( TABLEHANDLE ); static DBIResult _GetCursor4Table ( TABLEHANDLE, phDBICur * ); static RECORDHANDLE _CreateRecBuf4 ( TABLEHANDLE ); static void _DeleteRecBuf4 ( RECORDHANDLE ); static pBYTE _GetRecBuf4 ( RECORDHANDLE ); static int _GetRecBufSize4 ( RECORDHANDLE ); static DBIResult _GetCursor4Record ( RECORDHANDLE, phDBICur * ); //static DBIResult _SwitchToPrimaryIndex ( TABLEHANDLE ); static DBIResult _GetFLDDesc ( phDBICur /* TABLEHANDLE */, FIELDHANDLE, pFLDDesc ); static const char *_GetErrorMessage ( DBIResult ); static int _DropListAdd ( const char *, const char * ); static int _DropListDrop ( void ); static pBYTE _SavePosition ( phDBICur ); static void _RestorePosition ( phDBICur, pBYTE ); static DBIResult _CreateTable4 ( const char *name, TABLEHANDLE *tbl, int index, int saveAllChanges ) { DBIResult result; int handle = 0; if ( table_list == NULL ) { Message ( "Invalid call to PXTblOpen, PXSetDefaults should be called first!" ); return ( -1 ); } while ( ( ( table_list + handle ) -> handle != -1 ) && ( handle < table_size ) ) handle++; iLog ( THISFILE, __LINE__, "_CreateTable4 : handle:%d, table_size:%d", handle, table_size ); if ( handle < table_size ) { if ( ( result = DbiOpenTable ( hDB, ( pCHAR ) name, szPARADOX, NULL, NULL, index, dbiREADWRITE, dbiOPENSHARED, xltFIELD, TRUE, NULL, &( ( table_list + handle ) -> cursor ) ) ) == DBIERR_NONE ) { ( table_list + handle ) -> handle = handle; ( table_list + handle ) -> index = index; *tbl = handle; return ( result ); } else { iLog ( THISFILE, __LINE__, "DbiOpenTable (%d)", result ); return ( result ); } } return ( DBIERR_NOFILEHANDLES ); } static DBIResult _DeleteTable4 ( TABLEHANDLE handle ) { DBIResult result; if ( handle < 0 ) return ( DBIERR_INVALIDHNDL ); if ( handle >= table_size ) return ( DBIERR_INVALIDHNDL ); if ( ( table_list + handle ) -> handle == -1 ) return ( DBIERR_INVALIDHNDL ); iLog ( THISFILE, __LINE__, "_DeleteTable4 : handle:%d", handle ); result = DbiCloseCursor ( &( ( table_list + handle ) -> cursor ) ); ( table_list + handle ) -> cursor = -1; ( table_list + handle ) -> handle = -1; return ( result ); } static DBIResult _GetCursor4Table ( TABLEHANDLE handle, phDBICur *cursor ) { const char *format = "Call to _GetCursor4Table with invalid table handle %d\n"; if ( handle < 0 ) { Message ( format, handle ); return ( DBIERR_INVALIDHNDL ); } if ( handle >= table_size ) { Message ( format, handle ); return ( DBIERR_INVALIDHNDL ); } if ( ( table_list + handle ) -> handle != -1 ) { *cursor = &( ( table_list + handle ) -> cursor ); return ( DBIERR_NONE ); } Message ( format, handle ); return ( DBIERR_INVALIDHNDL ); } /* static DBIResult _SwitchToPrimaryIndex ( TABLEHANDLE handle ) { const char *format = "Call to _SwitchToPrimaryIndex with invalid table handle %d\n"; if ( handle < 0 ) { Message ( format, handle ); return ( DBIERR_INVALIDHNDL ); } if ( handle >= table_size ) { Message ( format, handle ); return ( DBIERR_INVALIDHNDL ); } if ( ( table_list + handle ) -> handle != -1 ) { // *cursor = ( table_list + handle ) -> cursor; DbiSwitchToIndex ( &( ( table_list + handle ) -> cursor ), 0, 0, 0, TRUE ); return ( DBIERR_NONE ); } Message ( format, handle ); return ( DBIERR_INVALIDHNDL ); } */ static RECORDHANDLE _CreateRecBuf4 ( TABLEHANDLE tbl ) { phDBICur cursor; CURProps curprops; int handle = 0; if ( record_list == NULL ) { Message ( "Invalid call to PXRecBufOpen, PXSetDefaults should be called first!" ); return ( -1 ); } if ( _GetCursor4Table ( tbl, &cursor ) != DBIERR_NONE ) { Message ( "Invalid call to PXRecBufOpen, table handle is invalid!" ); return ( -1 ); } while ( ( ( record_list + handle ) -> buffer != NULL ) && ( handle < record_size ) ) handle++; if ( handle < record_size ) { if ( DbiGetCursorProps ( *cursor, &curprops ) == DBIERR_NONE ) { ( record_list + handle ) -> handle = handle; ( record_list + handle ) -> cursor = cursor; ( record_list + handle ) -> buffer = ( pBYTE ) calloc ( curprops.iRecBufSize, sizeof ( BYTE ) ); ( record_list + handle ) -> size = curprops.iRecBufSize; DbiInitRecord ( *cursor, ( record_list + handle ) -> buffer ); return ( handle ); } } return ( -1 ); } static void _DeleteRecBuf4 ( RECORDHANDLE handle ) { if ( record_list == NULL ) { Message ( "Invalid call to PXRecBufClose" ); return; } if ( handle == -1 ) // Never associated a buffer. return; if ( ( handle < 0 ) || ( handle >= record_size ) ) { Message ( "Invalid call to PXRecBufClose %d [%d]", handle, record_size ); return; } if ( ( record_list + handle ) -> buffer != NULL ) { free ( ( record_list + handle ) -> buffer ); ( record_list + handle ) -> handle = -1; #pragma "JAK: check for .cursor member!" ( record_list + handle ) -> cursor = 0; // -1; ( record_list + handle ) -> buffer = NULL; ( record_list + handle ) -> size = 0; } else Message ( "Invalid call to PXRecBufClose, handle already freed" ); } static pBYTE _GetRecBuf4 ( RECORDHANDLE handle ) { if ( handle < 0 ) { iLog ( THISFILE, __LINE__, "handle < 0" ); return ( NULL ); } if ( handle >= record_size ) { iLog ( THISFILE, __LINE__, "handle >= record_size" ); return ( NULL ); } return ( ( record_list + handle ) -> buffer ); } static int _GetRecBufSize4 ( RECORDHANDLE handle ) { if ( handle < 0 ) return ( 0 ); if ( handle >= record_size ) return ( 0 ); return ( ( record_list + handle ) -> size ); } static DBIResult _GetCursor4Record ( RECORDHANDLE handle, phDBICur *cursor ) { if ( handle < 0 ) return ( DBIERR_INVALIDHNDL ); if ( handle >= record_size ) return ( DBIERR_INVALIDHNDL ); if ( ( record_list + handle ) -> handle != -1 ) { *cursor = ( record_list + handle ) -> cursor; return ( DBIERR_NONE ); } return ( DBIERR_INVALIDHNDL ); } static DBIResult _GetFLDDesc ( phDBICur cursor, FIELDHANDLE fld, pFLDDesc flddesc ) { DBIResult result; CURProps curprops; pFLDDesc fielddesc; pFLDDesc help; if ( ( result = DbiGetCursorProps ( *cursor, &curprops ) ) == DBIERR_NONE ) { fielddesc = ( FLDDesc * ) calloc ( curprops.iFields, sizeof ( FLDDesc ) ); if ( ( result = DbiGetFieldDescs ( *cursor, fielddesc ) ) == DBIERR_NONE ) { // now loop over the fields looking for the specified name help = ( fielddesc + fld - 1 ); // Get the right field. #ifdef V1-00 int i; // field no for ( i = 0 , help = fielddesc ; ( i < curprops.iFields ) && ( help -> iFldNum != fld ) ; ++i, ++help ) ; #endif if ( fld <= curprops.iFields ) // was != { // found = TRUE; result = DBIERR_NONE; // *flddesc = *help; memcpy ( flddesc, help, sizeof ( FLDDesc ) ); } else { result = DBIERR_INVALIDHNDL; iLog ( THISFILE, __LINE__, "_GetFLDDesc : fld > curprops.iFields" ); } } else iLog ( THISFILE, __LINE__, "_GetFLDDesc : DbiGetFieldDescs (%d)", result ); free ( fielddesc ); } else iLog ( THISFILE, __LINE__, "_GetFLDDesc : DbiGetCursorProps (%d)", result ); return ( result ); // return ( found ); } static const char *_GetErrorMessage ( DBIResult result ) { static char buff [ DBIMAXMSGLEN + 1 ]; DbiGetErrorString ( result, buff ); return ( buff ); } static int _DropListAdd ( const char *table, const char *index ) { _DROPLIST *ptr = droplist; _DROPLIST *tmp = NULL; _DROPLIST *add = NULL; while ( ptr != NULL ) { if ( ( strcmp ( ptr -> tablename, table ) == 0 ) && ( strcmp ( ptr -> indexname, index ) == 0 ) ) break; tmp = ptr; ptr = ptr -> next; } if ( ptr != NULL ) // Already in droplist! return ( FALSE ); add = ( _DROPLIST * ) calloc ( 1, sizeof ( _DROPLIST ) ); add -> tablename = strdup ( table ); add -> indexname = strdup ( index ); add -> next = NULL; if ( droplist == NULL ) // Add as the first. droplist = add; else tmp -> next = add; // Add at the end of the list. return ( TRUE ); } static int _DropListDrop () { DBIResult result; _DROPLIST *ptr = droplist; _DROPLIST *tmp = NULL; while ( ptr != NULL ) { if ( ( result = DbiDeleteIndex ( hDB, 0, ptr -> tablename, szPARADOX, ptr -> indexname, 0, 0 ) ) != DBIERR_NONE ) iLog ( __FILE__, __LINE__, "DbiDeleteIndex table:'%s', index:'%s' (%d)", ptr -> tablename, ptr -> indexname, result ); tmp = ptr; ptr = ptr -> next; free ( tmp -> tablename ); free ( tmp -> indexname ); free ( tmp ); } return ( TRUE ); } static pBYTE _SavePosition ( phDBICur cursor ) { DBIResult result; CURProps curprops; pBYTE bookmark; if ( ( result = DbiGetCursorProps ( *cursor, &curprops ) ) != DBIERR_NONE ) return ( NULL ); bookmark = ( BYTE * ) calloc ( curprops.iBookMarkSize, sizeof ( BYTE ) ); DbiGetBookMark ( *cursor, bookmark ); return ( bookmark ); } static void _RestorePosition ( phDBICur cursor, pBYTE bookmark ) { if ( bookmark != NULL ) DbiSetToBookMark ( *cursor, bookmark ); } DBIResult PXInit () { DBIResult result; // Message ( "PXInit" ); iLog ( THISFILE, __LINE__, "PXInit" ); if ( ( result = DbiInit ( NULL ) ) == DBIERR_NONE ) result = DbiOpenDatabase ( NULL, NULL, dbiREADWRITE, dbiOPENSHARED, NULL, 0, NULL, NULL, &hDB ); return ( result ); } DBIResult PXNetInit ( const char *netNamePath, int netType, const char *netUser ) { DBIResult result; DBIEnv env; // Message ( "PXNetInit" ); iLog ( THISFILE, __LINE__, "PXNetInit path:'%s', type:%d, user:'%s'", netNamePath, netType, netUser ); memset ( &env, 0, sizeof ( env ) ); strcpy ( env.szWorkDir , netNamePath ); strcpy ( env.szClientName, netUser ); if ( ( result = DbiInit ( &env ) ) == DBIERR_NONE ) result = DbiOpenDatabase ( NULL, NULL, dbiREADWRITE, dbiOPENSHARED, NULL, 0, NULL, NULL, &hDB ); return ( result ); } DBIResult PXExit () { DBIResult result; // Message ( "PXExit" ); iLog ( THISFILE, __LINE__, "PXExit" ); // _DropListDrop (); // Delete indexes created with PXKeyMap! if ( ( result = DbiCloseDatabase ( &hDB ) ) == DBIERR_NONE ) result = DbiExit (); return ( result ); } DBIResult PXSetDefaults ( int bufsize, int maxtables, int maxrecbufs, int maxlocks, int maxfiles, char *sortorder ) { int i; // Message ( "PXSetDefaults" ); table_size = maxtables + 4; table_list = ( _TABLE * ) calloc ( table_size , sizeof ( _TABLE ) ); for ( i = 0 ; i < table_size ; i++ ) { ( table_list + i ) -> handle = -1; ( table_list + i ) -> cursor = -1; ( table_list + i ) -> index = 0; } record_size = maxrecbufs + 8; record_list = ( _RECORD * ) calloc ( record_size, sizeof ( _RECORD ) ); for ( i = 0 ; i < record_size ; i++ ) // Clean it! { ( record_list + i ) -> handle = -1; ( record_list + i ) -> cursor = 0; // -1; ( record_list + i ) -> buffer = NULL; ( record_list + i ) -> size = 0; } #pragma message "JAK: PXSetDefault might need further implementation!" return ( DBIERR_NONE ); } DBIResult PXTblOpen ( const char *name, TABLEHANDLE *tbl, int index, int saveAllChanges ) { DBIResult result; // Message ( "PXTblOpen %s %d", name, index ); result = _CreateTable4 ( name, tbl, index, saveAllChanges ); iLog ( THISFILE, __LINE__, "PXTblOpen table:'%s', index:%d, (%d:%X:%s)", name, index, result, result, _GetErrorMessage ( result ) ); return ( result ); } DBIResult PXTblClose ( TABLEHANDLE tbl ) { // Message ( "PXTblClose" ); iLog ( THISFILE, __LINE__, "PXTblClose" ); return ( _DeleteTable4 ( tbl ) ); } #if 0 DBIResult PXTblCreate ( const char *tblname, int nfields, char **fields, char **types ) { Message ( "JAK: PXTblCreate not implemented yet!" ); iLog ( THISFILE, __LINE__, "PXTblCreate not implemented yet!" ); #pragma message "JAK: PXTblCreate not implemented yet" /* CRTblDesc tbldesc; FLDDesc *flddesc = new FLDDesc [ nfields ]; memset ( &tbddesc, 0, sizeof ( tbldesc ) ); strncpy ( tbldesc.szTblName, tblname , sizeof ( tbldesc, szTblName ) ); strncpy ( tbldesc.szTblType, szPARADOX, sizeof ( tbldesc, szTblType ) ); tbldesc.iFldCount = nfields; tbldesc.pFLDDesc = fields; DbiCreateTable ( hDB, TRUE, &tbldesc ); */ } #endif DBIResult PXTblEmpty ( const char *tblname ) { // Message ( "PXTblEmpty" ); iLog ( THISFILE, __LINE__, "PXTblEmpty table:'%s'", tblname ); return ( DbiEmptyTable ( hDB, 0, ( pCHAR ) tblname, szPARADOX ) ); } DBIResult PXRecAppend ( TABLEHANDLE tbl, RECORDHANDLE rec ) { DBIResult result; phDBICur cursor; pBYTE ptr = _GetRecBuf4 ( rec ); // Message ( "PXRecAppend" ); iLog ( THISFILE, __LINE__, "PXRecAppend tbl:%d, rec:%d", tbl, rec ); if ( ( result = _GetCursor4Table ( tbl, &cursor ) ) != DBIERR_NONE ) return ( result ); if ( ptr == NULL ) return ( DBIERR_INVALIDHNDL ); return ( DbiAppendRecord ( *cursor, ptr ) ); } DBIResult PXRecInsert ( TABLEHANDLE tbl, RECORDHANDLE rec ) { DBIResult result; phDBICur cursor; pBYTE ptr = _GetRecBuf4 ( rec ); // Message ( "PXRecInsert" ); iLog ( THISFILE, __LINE__, "PXRecInsert tbl:%d, rec:%d", tbl, rec ); if ( ( result = _GetCursor4Table ( tbl, &cursor ) ) != DBIERR_NONE ) return ( result ); if ( ptr == NULL ) return ( DBIERR_INVALIDHNDL ); return ( DbiInsertRecord ( *cursor, dbiNOLOCK, ptr ) ); } DBIResult PXRecUpdate ( TABLEHANDLE tbl, RECORDHANDLE rec ) { DBIResult result; phDBICur cursor; pBYTE ptr = _GetRecBuf4 ( rec ); // Message ( "PXRecUpdate" ); iLog ( THISFILE, __LINE__, "PXRecUpdate tbl:%d, rec:%d", tbl, rec ); if ( ( result = _GetCursor4Table ( tbl, &cursor ) ) != DBIERR_NONE ) return ( result ); if ( ptr == NULL ) return ( DBIERR_INVALIDHNDL ); return ( DbiModifyRecord ( *cursor, ptr, TRUE ) ); } DBIResult PXRecDelete ( TABLEHANDLE tbl ) { DBIResult result; phDBICur cursor; pBYTE bookmark; // Message ( "PXRecDelete" ); iLog ( THISFILE, __LINE__, "PXRecDelete tbl:%d", tbl ); if ( ( result = _GetCursor4Table ( tbl, &cursor ) ) != DBIERR_NONE ) return ( result ); bookmark = _SavePosition ( cursor ); if ( ( result = DbiDeleteRecord ( *cursor, NULL ) ) == DBIERR_NONE ) { iLog ( THISFILE, __LINE__, "PXRecDelete, record is deleted" ); if ( DbiGetNextRecord ( *cursor, dbiNOLOCK, NULL, NULL ) == DBIERR_EOF ) { _RestorePosition ( cursor, bookmark ); iLog ( THISFILE, __LINE__, "PXRecDelete, no next record!" ); if ( DbiGetPriorRecord ( *cursor, dbiNOLOCK, NULL, NULL ) != DBIERR_NONE ) iLog ( THISFILE, __LINE__, "PXRecDelete, no prior record!" ); } } if ( bookmark != NULL ) free ( bookmark ); // return ( DbiDeleteRecord ( cursor, NULL ) ); return ( result ); } DBIResult PXRecBufOpen ( TABLEHANDLE tbl, RECORDHANDLE *rec ) { // Message ( "PXRecBufOpen" ); *rec = _CreateRecBuf4 ( tbl ); // Message ( "PXRecBufOpen (return)" ); iLog ( THISFILE, __LINE__, "PXRecBufOpen tbl:%d, rec:%d", tbl, *rec ); return ( DBIERR_NONE ); } DBIResult PXRecBufClose ( RECORDHANDLE rec ) { // Message ( "PXRecBufClose" ); _DeleteRecBuf4 ( rec ); iLog ( THISFILE, __LINE__, "PXRecBufClose rec:%d", rec ); return ( DBIERR_NONE ); } DBIResult PXRecBufEmpty ( RECORDHANDLE rec ) { DBIResult result; phDBICur cursor; pBYTE ptr = _GetRecBuf4 ( rec ); // Message ( "PXRecBufEmpty" ); iLog ( THISFILE, __LINE__, "PXRecBufEmpty rec:%d", rec ); if ( ( result = _GetCursor4Record ( rec, &cursor ) ) != DBIERR_NONE ) return ( result ); if ( ptr == NULL ) return ( DBIERR_INVALIDHNDL ); return ( DbiInitRecord ( *cursor, ptr ) ); } DBIResult PXRecBufCopy ( RECORDHANDLE source, RECORDHANDLE destin ) { pBYTE p_source = _GetRecBuf4 ( source ); int s_source = _GetRecBufSize4 ( source ); pBYTE p_destin = _GetRecBuf4 ( destin ); int s_destin = _GetRecBufSize4 ( destin ); // Message ( "PXRecBufCopy" ); iLog ( THISFILE, __LINE__, "PXRecBufCopy source:%d, destin:%d", source, destin ); if ( p_source == NULL ) return ( DBIERR_INVALIDHNDL ); if ( p_destin == NULL ) return ( DBIERR_INVALIDHNDL ); // memcpy ( p_source, p_destin, min ( s_source, s_destin ) ); memcpy ( p_destin, p_source, min ( s_source, s_destin ) ); return ( DBIERR_NONE ); } DBIResult PXRecGet ( TABLEHANDLE tbl, RECORDHANDLE rec ) { DBIResult result; phDBICur cursor; pBYTE ptr = _GetRecBuf4 ( rec ); // Message ( "PXRecGet" ); iLog ( THISFILE, __LINE__, "PXRecGet tbl:%d, rec:%d", tbl, rec ); if ( ( result = _GetCursor4Table ( tbl, &cursor ) ) != DBIERR_NONE ) return ( result ); if ( ptr == NULL ) return ( DBIERR_INVALIDHNDL ); if ( ( result = DbiGetRecord ( *cursor, dbiNOLOCK, ptr, NULL ) ) != DBIERR_NONE ) iLog ( THISFILE, __LINE__, "PXRecGet tbl:%d, rec:%d, result:%d", tbl, rec, result ); return ( result ); } DBIResult PXPutShort ( RECORDHANDLE rec, FIELDHANDLE fld, short val ) { DBIResult result; phDBICur cursor; pBYTE ptr = _GetRecBuf4 ( rec ); iLog ( THISFILE, __LINE__, "PXPutShort rec:%d, fld:%d, val:%d", rec, fld, val ); if ( ( result = _GetCursor4Record ( rec, &cursor ) ) != DBIERR_NONE ) return ( result ); if ( ptr == NULL ) return ( DBIERR_INVALIDHNDL ); return ( DbiPutField ( *cursor, fld, ptr, ( pBYTE ) &val ) ); } DBIResult PXPutDoub ( RECORDHANDLE rec, FIELDHANDLE fld, double val ) { DBIResult result; phDBICur cursor; pBYTE ptr = _GetRecBuf4 ( rec ); iLog ( THISFILE, __LINE__, "PXPutDoub rec:%d, fld:%d, val:%f", rec, fld, val ); if ( ( result = _GetCursor4Record ( rec, &cursor ) ) != DBIERR_NONE ) return ( result ); if ( ptr == NULL ) return ( DBIERR_INVALIDHNDL ); return ( DbiPutField ( *cursor, fld, ptr, ( pBYTE ) &val ) ); } DBIResult PXPutAlpha ( RECORDHANDLE rec, FIELDHANDLE fld, const char *str ) { DBIResult result; phDBICur cursor; pBYTE ptr = _GetRecBuf4 ( rec ); iLog ( THISFILE, __LINE__, "PXPutAlpha rec:%d, fld:%d, val:'%s'", rec, fld, str ); if ( ( result = _GetCursor4Record ( rec, &cursor ) ) != DBIERR_NONE ) return ( result ); if ( ptr == NULL ) return ( DBIERR_INVALIDHNDL ); return ( DbiPutField ( *cursor, fld, ptr, ( pBYTE ) str ) ); } DBIResult PXPutDate ( RECORDHANDLE rec, FIELDHANDLE fld, TDATE val ) { DBIResult result; phDBICur cursor; pBYTE ptr = _GetRecBuf4 ( rec ); iLog ( THISFILE, __LINE__, "PXPutDate rec:%d, fld:%d", rec, fld ); if ( ( result = _GetCursor4Record ( rec, &cursor ) ) != DBIERR_NONE ) return ( result ); if ( ptr == NULL ) return ( DBIERR_INVALIDHNDL ); return ( DbiPutField ( *cursor, fld, ptr, ( pBYTE ) &val ) ); } DBIResult PXGetShort ( RECORDHANDLE rec, FIELDHANDLE fld, short *val ) { DBIResult result; phDBICur cursor; BOOL isblank; pBYTE ptr = _GetRecBuf4 ( rec ); if ( ptr == NULL ) return ( DBIERR_INVALIDHNDL ); if ( ( result = _GetCursor4Record ( rec, &cursor ) ) != DBIERR_NONE ) return ( result ); result = DbiGetField ( *cursor, fld, ptr, ( pBYTE ) val, &isblank ); iLog ( THISFILE, __LINE__, "PXGetShort rec:%d, fld:%d, val:%d", rec, fld, *val ); return ( result ); } DBIResult PXGetDoub ( RECORDHANDLE rec, FIELDHANDLE fld, double *val ) { DBIResult result; phDBICur cursor; BOOL isblank; pBYTE ptr = _GetRecBuf4 ( rec ); if ( ptr == NULL ) return ( DBIERR_INVALIDHNDL ); if ( ( result = _GetCursor4Record ( rec, &cursor ) ) != DBIERR_NONE ) return ( result ); result = DbiGetField ( *cursor, fld, ptr, ( pBYTE ) val, &isblank ); iLog ( THISFILE, __LINE__, "PXGetDoub rec:%d, fld:%d, val:%f", rec, fld, *val ); return ( result ); } DBIResult PXGetAlpha ( RECORDHANDLE rec, FIELDHANDLE fld, int size, char *str ) { DBIResult result; phDBICur cursor; BOOL isblank; pBYTE ptr = _GetRecBuf4 ( rec ); FLDDesc flddesc; if ( ptr == NULL ) return ( DBIERR_INVALIDHNDL ); if ( ( result = _GetCursor4Record ( rec, &cursor ) ) != DBIERR_NONE ) return ( result ); if ( ( result = _GetFLDDesc ( cursor, fld, &flddesc ) ) != DBIERR_NONE ) return ( result ); if ( flddesc.iLen > size ) { iLog ( THISFILE, __LINE__, "PXGetAlpha rec:%d, fld:%d, val:'%-.*s' %d > %d", rec, fld, size, ptr, flddesc.iLen, size ); return ( DBIERR_NOMEMORY ); } result = DbiGetField ( *cursor, fld, ptr, ( pBYTE ) str, &isblank ); iLog ( THISFILE, __LINE__, "PXGetAlpha rec:%d, fld:%d, val:'%-.*s'", rec, fld, size, ptr ); return ( result ); } DBIResult PXGetDate ( RECORDHANDLE rec, FIELDHANDLE fld, TDATE *date ) { DBIResult result; phDBICur cursor; BOOL isblank; pBYTE ptr = _GetRecBuf4 ( rec ); iLog ( THISFILE, __LINE__, "PXGetDate rec:%d, fld:%d", rec, fld ); if ( ptr == NULL ) return ( DBIERR_INVALIDHNDL ); if ( ( result = _GetCursor4Record ( rec, &cursor ) ) != DBIERR_NONE ) return ( result ); return ( DbiGetField ( *cursor, fld, ptr, ( pBYTE ) date, &isblank ) ); } DBIResult PXFldBlank ( RECORDHANDLE rec, FIELDHANDLE fld, int *flag ) { DBIResult result; phDBICur cursor; pBYTE ptr = _GetRecBuf4 ( rec ); iLog ( THISFILE, __LINE__, "PXFldBlank rec:%d, fld:%d", rec, fld ); if ( ptr == NULL ) return ( DBIERR_INVALIDHNDL ); if ( ( result = _GetCursor4Record ( rec, &cursor ) ) != DBIERR_NONE ) return ( result ); return ( DbiGetField ( *cursor, fld, ptr, ( pBYTE ) NULL, flag ) ); } DBIResult PXRecFirst ( TABLEHANDLE tbl ) { DBIResult result; phDBICur cursor; iLog ( THISFILE, __LINE__, "PXRecFirst tbl:%d", tbl ); if ( ( result = _GetCursor4Table ( tbl, &cursor ) ) != DBIERR_NONE ) return ( result ); if ( ( result = DbiSetToBegin ( *cursor ) ) == DBIERR_NONE ) return ( DbiGetNextRecord ( *cursor, dbiNOLOCK, NULL, NULL ) ); Message ( "PXRecFirst (%d:%s)", result, _GetErrorMessage ( result ) ); return ( result ); } DBIResult PXRecLast ( TABLEHANDLE tbl ) { DBIResult result; phDBICur cursor; iLog ( THISFILE, __LINE__, "PXRecLast tbl:%d", tbl ); if ( ( result = _GetCursor4Table ( tbl, &cursor ) ) != DBIERR_NONE ) return ( result ); if ( ( result = DbiSetToEnd ( *cursor ) ) == DBIERR_NONE ) return ( DbiGetPriorRecord ( *cursor, dbiNOLOCK, NULL, NULL ) ); return ( result ); } DBIResult PXRecNext ( TABLEHANDLE tbl ) { DBIResult result; phDBICur cursor; iLog ( THISFILE, __LINE__, "PXRecNext tbl:%d", tbl ); if ( ( result = _GetCursor4Table ( tbl, &cursor ) ) != DBIERR_NONE ) return ( result ); return ( DbiGetNextRecord ( *cursor, dbiNOLOCK, NULL, NULL ) ); } DBIResult PXRecPrev ( TABLEHANDLE tbl ) { DBIResult result; phDBICur cursor; iLog ( THISFILE, __LINE__, "PXRecPrev tbl:%d", tbl ); if ( ( result = _GetCursor4Table ( tbl, &cursor ) ) != DBIERR_NONE ) return ( result ); return ( DbiGetPriorRecord ( *cursor, dbiNOLOCK, NULL, NULL ) ); } DBIResult PXKeyAdd ( const char *tblname, int nfields, FIELDHANDLE *fields, int mode ) { #pragma "JAK: PXKeyAdd, not completely implemented yet!" DBIResult result; IDXDesc indexdesc; int i; Message ( "JAK: PXKeyAdd not completely implemented yet!" ); iLog ( THISFILE, __LINE__, "PXKeyAdd not completely implemented yet %s %d", tblname, nfields ); memset ( &indexdesc, 0, sizeof ( indexdesc ) ); if ( mode == PRIMARY ) indexdesc.bPrimary = TRUE; else indexdesc.bPrimary = FALSE; indexdesc.bUnique = TRUE; if ( mode == SECONDARY ) indexdesc.bMaintained = FALSE; else indexdesc.bMaintained = TRUE; indexdesc.iFldsInKey = nfields; // for ( i = 1 ; i <= nfields ; indexdesc.aiKeyFld [ i - 1 ] = i, ++i ) // ; for ( i = 0 ; i < nfields ; i++ ) indexdesc.aiKeyFld [ i ] = *( fields + i ); result = DbiAddIndex ( hDB, 0, ( pCHAR ) tblname, szPARADOX, &indexdesc, NULL ); return ( result ); } DBIResult PXKeyDrop ( const char *tablename, FIELDHANDLE fld ) { return ( DbiDeleteIndex ( hDB, 0, ( pCHAR ) tablename, szPARADOX, NULL, NULL, fld ) ); } static DBIResult _PXKeyMap ( const char *, int, FIELDHANDLE *, const char *, FIELDHANDLE * ); static DBIResult _PXKeyMap2 ( const char *, int, FIELDHANDLE *, const char *, FIELDHANDLE * ); DBIResult PXKeyMap ( const char *tablename, int nfields, FIELDHANDLE *fields, const char *fldName, int mode, FIELDHANDLE *indexId ) { DBIResult result; IDXDesc indexdesc; int i; int create = TRUE; // Expect that we have to create the index. iLog ( THISFILE, __LINE__, "PXKeyMap %s %d %s", tablename, nfields, fldName ); // switch ( _PXKeyMap ( tablename, nfields, fields, fldName, indexId ) ) switch ( _PXKeyMap2 ( tablename, nfields, fields, fldName, indexId ) ) { case DBIERR_INDEXEXISTS : // Index exists and is ready to use. iLog ( THISFILE, __LINE__, "PXKeyMap index exists, id = %d!", *indexId ); _DropListAdd ( tablename, fldName ); // Remember to drop this index! return ( DBIERR_NONE ); // JAK 19971101. Index might be out of date! case DBIERR_INDEXOUTOFDATE : // Index exists, but is out of date! return ( DbiRegenIndex ( hDB, 0, ( pCHAR ) tablename, szPARADOX, 0, 0, *indexId ) ); default : break; } memset ( &indexdesc, 0, sizeof ( indexdesc ) ); indexdesc.iIndexId = *indexId; // _PXKeyMap return the first next if this index // does not exists already. iLog ( THISFILE, __LINE__, "PXKeyMap indexId:%d", *indexId ); strcpy ( indexdesc.szName, fldName ); indexdesc.bPrimary = FALSE; // if ( mode == PRIMARY ) // indexdesc.bPrimary = TRUE; // else // indexdesc.bPrimary = FALSE; // indexdesc.bUnique = TRUE; indexdesc.bUnique = FALSE; // if ( mode == SECONDARY ) // indexdesc.bMaintained = FALSE; // else // indexdesc.bMaintained = TRUE; indexdesc.bMaintained = FALSE; indexdesc.iFldsInKey = nfields; if ( mode == 0 ) indexdesc.bCaseInsensitive = FALSE; else indexdesc.bCaseInsensitive = TRUE; // for ( i = 1 ; i <= nfields ; indexdesc.aiKeyFld [ i - 1 ] = i, ++i ) // ; for ( i = 0 ; i < nfields ; i++ ) indexdesc.aiKeyFld [ i ] = *( fields + i ); if ( ( result = DbiAddIndex ( hDB, 0, ( pCHAR ) tablename, szPARADOX, &indexdesc, ( pCHAR ) NULL ) ) != DBIERR_NONE ) { iLog ( THISFILE, __LINE__, "PXKeyMap DbiAddIndex (%d:%04X)", result, result ); return ( result ); } *indexId = indexdesc.iIndexId; iLog ( THISFILE, __LINE__, "PXKeyMap index created, id = %d!", *indexId ); _DropListAdd ( tablename, fldName ); // Remember to drop this index! return ( result ); #if 0 // Message ( "JAK: PXKeyMap not implemented yet!" ); iLog ( THISFILE, __LINE__, "PXKeyMap not implemented yet!" ); // The following just forces to use the first index of the table. // This is a trick and functional NOT working! // PXKeyMap probably has to be implemented by 'adding' a 'Key' to the table. // indexId = 1; // JAK 19970916. indexId = 0; // return ( DBIERR_NONE ); #pragma message "JAK: PXKeyMap not implemented yet!" return ( DBIERR_INVALIDHNDL ); #endif } static DBIResult _PXKeyMap ( const char *tablename, int nfields, FIELDHANDLE *fields, const char *fldname, FIELDHANDLE *id ) { // DBIResult result; hDBICur cursor; IDXDesc indexdesc; UINT iIndexId = 255; int exists = FALSE; // Expect that the index does NOT exist. int i; iLog ( THISFILE, __LINE__, "_PXKeyMap" ); memset ( &indexdesc, 0, sizeof ( indexdesc ) ); if ( DbiOpenIndexList ( hDB, ( pCHAR ) tablename, szPARADOX, &cursor ) == DBIERR_NONE ) { if ( DbiSetToBegin ( cursor ) == DBIERR_NONE ) { while ( DbiGetNextRecord ( cursor, dbiNOLOCK, ( pBYTE ) &indexdesc, NULL ) == DBIERR_NONE ) { if ( indexdesc.iIndexId > iIndexId ) iIndexId = indexdesc.iIndexId; if ( indexdesc.iFldsInKey == nfields ) { int check = TRUE; iLog ( THISFILE, __LINE__, "_PXKeyMap compare (0:nfields) : %d == %d", indexdesc.iFldsInKey, nfields ); for ( i = 0 ; i < nfields ; i++ ) { if ( indexdesc.aiKeyFld [ i ] != *( fields + i ) ) { check = FALSE; break; } iLog ( THISFILE, __LINE__, "_PXKeyMap compare (1:fields) : %d && %d", indexdesc.aiKeyFld [ i ], *( fields + i ) ); } if ( check ) iLog ( THISFILE, __LINE__, "_PXKeyMap compare (1:fields) : same" ); // Same so far, now check the name. if ( ( check ) && ( strcmp ( indexdesc.szName, fldname ) == 0 ) ) { iLog ( THISFILE, __LINE__, "_PXKeyMap compare (3:name) : '%s' == '%s'", indexdesc.szName, fldname ); exists = TRUE; // Don't have to create, already exsists. break; // Exit loop! } } } } DbiCloseCursor ( &cursor ); } // If the index (or key) already exists, return the number (or id) of this existing // index. // If the index (or key) does NOT exists, return the the highest number + 1. if ( exists ) { iLog ( THISFILE, __LINE__, "_PXKeyMap valid index found %d", indexdesc.iIndexId ); *id = indexdesc.iIndexId; if ( indexdesc.bOutofDate ) return ( DBIERR_INDEXOUTOFDATE ); else return ( DBIERR_INDEXEXISTS ); } else *id = iIndexId + 1; return ( DBIERR_NONE ); } static DBIResult _PXKeyMap2 ( const char *tablename, int nfields, FIELDHANDLE *fields, const char *fldname, FIELDHANDLE *id ) { // DBIResult result; hDBICur cursor; CURProps curprops; IDXDesc indexdesc; UINT iIndexId = 255; int exists = FALSE; // Expect that the index does NOT exist. iLog ( THISFILE, __LINE__, "_PXKeyMap2" ); memset ( &indexdesc, 0, sizeof ( indexdesc ) ); if ( DbiOpenTable ( hDB, ( pCHAR ) tablename, szPARADOX, NULL, NULL, 0, dbiREADWRITE, dbiOPENSHARED, xltFIELD, TRUE, NULL, &cursor ) == DBIERR_NONE ) { if ( DbiGetCursorProps ( cursor, &curprops ) == DBIERR_NONE ) { pIDXDesc desc = ( pIDXDesc ) calloc ( curprops.iIndexes, sizeof ( IDXDesc ) ); int i; if ( DbiGetIndexDescs ( cursor, desc ) == DBIERR_NONE ) { for ( i = 0 ; i < curprops.iIndexes ; i++ ) { if ( desc [ i ].iIndexId > iIndexId ) iIndexId = desc [ i ].iIndexId; if ( desc [ i ].iFldsInKey == nfields ) { int check = TRUE; int f; iLog ( THISFILE, __LINE__, "_PXKeyMap2 compare (0:nfields) : %d == %d", desc [ i ].iFldsInKey, nfields ); for ( f = 0 ; f < nfields ; f++ ) { if ( desc [ i ].aiKeyFld [ f ] != *( fields + f ) ) { check = FALSE; break; } iLog ( THISFILE, __LINE__, "_PXKeyMap2 compare (1:fields) : %d && %d", desc [ i ].aiKeyFld [ f ], *( fields + f ) ); } if ( check ) iLog ( THISFILE, __LINE__, "_PXKeyMap2 compare (1:fields) : same" ); // Same so far, now check the name. if ( ( check ) && ( strcmp ( desc [ i ].szName, fldname ) == 0 ) ) { iLog ( THISFILE, __LINE__, "_PXKeyMap2 compare (3:name) : '%s' == '%s'", desc [ i ].szName, fldname ); exists = TRUE; // Don't have to create, already exsists. indexdesc = desc [ i ]; break; // Exit loop! } } } } free ( desc ); } DbiCloseCursor ( &cursor ); } // If the index (or key) already exists, return the number (or id) of this existing // index. // If the index (or key) does NOT exists, return the the highest number + 1. if ( exists ) { iLog ( THISFILE, __LINE__, "_PXKeyMap2 valid index found %d", indexdesc.iIndexId ); *id = indexdesc.iIndexId; if ( indexdesc.bOutofDate ) return ( DBIERR_INDEXOUTOFDATE ); else return ( DBIERR_INDEXEXISTS ); } else *id = iIndexId + 1; return ( DBIERR_NONE ); } DBIResult PXDateDecode ( TDATE adata, pUINT16 month, pUINT16 day, pINT16 year ) { return ( DbiDateDecode ( adata, month, day, year ) ); } DBIResult PXDateEncode ( UINT16 month, UINT16 day, INT16 year, TDATE *adate ) { return ( DbiDateEncode ( month, day, year, adate ) ); } static DBIResult _SearchOnIndex ( phDBICur, pBYTE, int, int, INT16 * ); static DBIResult _SearchFieldOnIndex ( phDBICur, pBYTE, pIDXDesc, int, INT16 * ); static DBIResult _SearchFieldBruteForce ( phDBICur, pBYTE, FIELDHANDLE fld, int, INT16 * ); // PXSrchKey searches in the Primary index of the table. DBIResult PXSrchKey ( TABLEHANDLE tbl, RECORDHANDLE rec, int nFields, int mode ) { DBIResult result; phDBICur cursor; IDXDesc desc; pBYTE bookmark; pBYTE ptr = _GetRecBuf4 ( rec ); INT16 found; iLog ( THISFILE, __LINE__, "PXSrchKey tbl:%d, rec:%d, fields:%d, mode:%d", tbl, rec, nFields, mode ); if ( ptr == NULL ) return ( DBIERR_INVALIDHNDL ); if ( ( result = _GetCursor4Table ( tbl, &cursor ) ) != DBIERR_NONE ) return ( result ); bookmark = _SavePosition ( cursor ); // Save current position in current index. if ( ( result = DbiGetIndexDesc ( *cursor, 0, &desc ) ) == DBIERR_NONE ) { if ( ! desc.bPrimary ) // We have to switch to the primary index. { if ( ( result = DbiSwitchToIndex ( cursor, 0, 0, 0, TRUE ) ) != DBIERR_NONE ) { /* * Table might not be positioned at a certain record. In that case change again, * but do NOT save the current position, because there is no current position! */ if ( result == DBIERR_NOCURRREC ) result = DbiSwitchToIndex ( cursor, 0, 0, 0, FALSE ); if ( result != DBIERR_NONE ) return ( result ); } } } //#endif // JAK 19971216, disabled for test <= result = _SearchOnIndex ( cursor, ptr, nFields, mode, &found ); if ( found ) { // Return to previous index when necessary, but maintain current record position. if ( ! desc.bPrimary ) result = DbiSwitchToIndex ( cursor, 0, 0, desc.iIndexId, TRUE ); } else { // Return to previous index when necessary, forget about current record position. if ( ! desc.bPrimary ) result = DbiSwitchToIndex ( cursor, 0, 0, desc.iIndexId, FALSE ); // Restore previous record position. _RestorePosition ( cursor, bookmark ); } // if ( result != DBIERR_NONE ) // _RestorePosition ( cursor, bookmark ); free ( bookmark ); return ( result ); } DBIResult PXSrchFld ( TABLEHANDLE tbl, RECORDHANDLE rec, FIELDHANDLE fld, int mode ) { DBIResult result; phDBICur cursor; // CURProps curprops; pBYTE bookmark; pBYTE ptr = _GetRecBuf4 ( rec ); IDXDesc idxdesc; INT16 found = FALSE; if ( ptr == NULL ) return ( DBIERR_INVALIDHNDL ); if ( ( result = _GetCursor4Table ( tbl, &cursor ) ) != DBIERR_NONE ) return ( result ); iLog ( THISFILE, __LINE__, "PXSrchFld: tbl:%d, rec:%d, fld:%d, mode:%d", tbl, rec, fld, mode ); // If 'fld' is smaller than 255 we treat fld as a field handle. // If 'fld' is greater or equal to 255 we treat fld as a PXKeyMap index handle! if ( fld < 255 ) { // First of all, we need to see if we can use the secondary indexes // by seeing if there is a index on the field specified. bookmark = _SavePosition ( cursor ); // if ( GetIndexForField ( fld, &idxdesc ) && ( mode != SEARCHNEXT ) ) // if ( ( DbiGetIndexForField ( *cursor, fld, FALSE, &idxdesc ) == DBIERR_NONE ) && ( mode != SEARCHNEXT ) ) if ( ( mode != SEARCHNEXT ) && ( DbiGetIndexForField ( *cursor, fld, FALSE, &idxdesc ) == DBIERR_NONE ) ) result = _SearchFieldOnIndex ( cursor, ptr, &idxdesc, mode, &found ); else result = _SearchFieldBruteForce ( cursor, ptr, fld, mode, &found ); if ( ! found ) _RestorePosition ( cursor, bookmark ); free ( bookmark ); } else { UINT16 seqno; if ( ( ( result = DbiGetIndexSeqNo ( *cursor, 0, 0, fld, &seqno ) ) == DBIERR_NONE ) && ( ( result = DbiGetIndexDesc ( *cursor, seqno, &idxdesc ) ) == DBIERR_NONE ) ) { iLog ( THISFILE, __LINE__, "PXSrchField : DbiGetIndexDesc %d", fld ); if ( ( result = DbiSwitchToIndex ( cursor, 0, 0, fld, TRUE ) ) == DBIERR_NOCURRREC ) result = DbiSwitchToIndex ( cursor, 0, 0, fld, FALSE ); if ( result == DBIERR_NONE ) result = _SearchOnIndex ( cursor, ptr, idxdesc.iFldsInKey, mode, &found ); } else iLog ( THISFILE, __LINE__, "PXSrchFld : DbiGetIndexDesc fld:%d (%d)", fld, result ); } iLog ( THISFILE, __LINE__, "PXSrchFld (%d %X)", result, result ); return ( result ); } static DBIResult _SearchOnIndex ( phDBICur cursor, pBYTE ptr, int nfields, int mode, INT16 *found ) { DBIResult result; INT16 samekey; iLog ( THISFILE, __LINE__, "_SearchOnIndex : nfields:%d, mode:%d", nfields, mode ); switch ( mode ) { case SEARCHFIRST : // Move to the begin. if ( ( result = DbiSetToKey ( *cursor, keySEARCHEQ , FALSE, nfields, 0, ptr ) ) == DBIERR_NONE ) // if ( ( result = DbiSetToKey ( *cursor, keySEARCHGEQ, FALSE, nfields, 0, ptr ) ) == DBIERR_NONE ) result = DbiGetNextRecord ( *cursor, dbiNOLOCK, NULL, NULL ); *found = ( result == DBIERR_NONE ); break; case SEARCHNEXT : if ( ( result = DbiGetNextRecord ( *cursor, dbiNOLOCK, NULL, NULL ) ) == DBIERR_NONE ) { DbiCompareKeys ( *cursor, ptr, NULL, nfields, 0, &samekey ); result = ( ! samekey ) ? DBIERR_NONE : DBIERR_RECNOTFOUND; } *found = ( result == DBIERR_NONE ); break; default : if ( ( result = DbiSetToKey ( *cursor, keySEARCHGEQ, FALSE, nfields, 0, ptr ) ) == DBIERR_NONE ) { // force a move - and record its value - if not there move back one record // if not eof then fiddle the result to be rec not found ? if ( ( result = DbiGetNextRecord ( *cursor, dbiNOLOCK, NULL, NULL ) ) == DBIERR_EOF ) result = DbiGetPriorRecord ( *cursor, dbiNOLOCK, NULL, NULL ); if ( result == DBIERR_NONE ) { BYTE keybuf [ 256 ]; // Temporary key buffer. DbiExtractKey ( *cursor, ptr, keybuf ); DbiCompareKeys ( *cursor, keybuf, NULL, nfields, 0, &samekey ); result = ( ! samekey ) ? DBIERR_NONE : ( ( samekey < 0 ) ? DBIERR_RECNOTFOUND : DBIERR_EOF ); } else result = DBIERR_EOF; } *found = TRUE; break; } return ( result ); } static DBIResult _SearchFieldOnIndex ( phDBICur cursor, pBYTE ptr, pIDXDesc pidxdesc, int mode, INT16 *found ) { DBIResult result; IDXDesc idxdesc; // Used to store current index - if any. BOOL anyindex; // Is there a current index ? iLog ( THISFILE, __LINE__, "_SearchFieldOnIndex : ndx:%d, mode:%d", pidxdesc -> iIndexId, mode ); // Now need to save the current index and where we currently are. // if ( ( anyindex = GetCurrentIndex ( *cursor, &idxdesc ) ) ) if ( anyindex = ( DbiGetIndexDesc ( *cursor, 0, &idxdesc ) == DBIERR_NONE ) ) { // Now switch to the new index that we have been provided with. // result = _SwitchToIndex ( cursor, 0, 0, pidxdesc -> iIndexId, TRUE ); if ( ( result = DbiSwitchToIndex ( cursor, 0, 0, pidxdesc -> iIndexId, TRUE ) ) == DBIERR_NOCURRREC ) result = DbiSwitchToIndex ( cursor, 0, 0, pidxdesc -> iIndexId, FALSE ); } result = _SearchOnIndex ( cursor, ptr, 1, mode, found ); // And put us back. if ( anyindex ) { // _SwitchToIndex ( cursor, 0, 0, idxdesc.iIndexId, TRUE ); DbiSwitchToIndex ( cursor, 0, 0, idxdesc.iIndexId, TRUE ); } return ( result ); } static DBIResult _SearchFieldBruteForce ( phDBICur cursor, pBYTE ptr, FIELDHANDLE fld, int mode, INT16 *found ) { DBIResult result; CURProps curprops; pBYTE buff; pBYTE field_0; pBYTE field_1; int flag_0; int flag_1; FLDDesc flddesc; int match = 1; *found = FALSE; if ( ( result = DbiGetCursorProps ( *cursor, &curprops ) ) != DBIERR_NONE ) { iLog ( THISFILE, __LINE__, "PXSrchFld : DbiGetCursorProps (%d)", result ); return ( result ); } if ( ( result = _GetFLDDesc ( cursor, fld, &flddesc ) ) != DBIERR_NONE ) { iLog ( THISFILE, __LINE__, "PXSrchFld : _GetFLDDesc (%d)", result ); return ( result ); } buff = ( BYTE * ) calloc ( curprops.iRecBufSize , sizeof ( BYTE ) ); field_0 = ( BYTE * ) calloc ( flddesc.iLen , sizeof ( BYTE ) ); field_1 = ( BYTE * ) calloc ( flddesc.iLen , sizeof ( BYTE ) ); if ( mode != SEARCHNEXT ) { result = DbiSetToBegin ( *cursor ); iLog ( THISFILE, __LINE__, "PXSrchFld : DbiSetToBegin (%d)", result ); } if ( ( result = DbiGetField ( *cursor, fld, ptr, field_0, &flag_0 ) ) != DBIERR_NONE ) iLog ( THISFILE, __LINE__, "PXSrchFld : DbiGetField (%d)", result ); match = 1; while ( ( result = DbiGetNextRecord ( *cursor, dbiNOLOCK, buff, 0 ) ) == DBIERR_NONE ) { if ( DbiGetField ( *cursor, fld, buff, field_1, &flag_1 ) == DBIERR_NONE ) { if ( mode != CLOSESTRECORD ) { switch ( flddesc.iFldType ) { case fldZSTRING : if ( ( flag_0 && flag_1 ) || ( strncmp ( ( char * ) field_0, ( char * ) field_1, flddesc.iLen ) == 0 ) ) *found = TRUE; break; default : if ( ( flag_0 && flag_1 ) || ( memcmp ( field_0, field_1, flddesc.iLen ) == 0 ) ) *found = TRUE; break; } } else { switch ( flddesc.iFldType ) { case fldZSTRING : if ( flag_0 ) match = 1; else match = strncmpi ( ( char * ) field_1, ( char * ) field_0, flddesc.iLen ); break; default : if ( flag_0 ) match = 1; else match = memcmp ( field_1, field_0, flddesc.iLen ); break; } } if ( *found ) { iLog ( THISFILE, __LINE__, "PXSrchFld : '%-.*s' = '%-.*s'", flddesc.iLen, field_0, flddesc.iLen, field_1 ); break; } else { iLog ( THISFILE, __LINE__, "PXSrchFld : '%-.*s' <> '%-.*s'", flddesc.iLen, field_0, flddesc.iLen, field_1 ); if ( ( mode == CLOSESTRECORD ) && ( match > 1 ) ) break; } } else iLog ( THISFILE, __LINE__, "PXSrchFld : DbiGetField (%d)", result ); } if ( mode == CLOSESTRECORD ) { if ( result == DBIERR_EOF ) result = DbiGetPriorRecord ( *cursor, dbiNOLOCK, 0, 0 ); if ( result == DBIERR_NONE ) result = ( match == 0 ) ? DBIERR_NONE : ( ( match > 0 ) ? DBIERR_RECNOTFOUND : DBIERR_EOF ); else result = DBIERR_EOF; *found = TRUE; } free ( field_1 ); free ( field_0 ); free ( buff ); return ( result ); } /* DBIResult PXTblExist ( const char *tblname, int *exists ) { Message ( "JAK: PXTblExist not implemented yet!" ); // iLog ( THISFILE, __LINE__, "PXTblExist not implemented yet!" ); //#pragma message "JAK: PXTblExist not implemented yet!" return ( DBIERR_NONE ); } */ DBIResult PXTblName ( TABLEHANDLE tbl, int size, char *tblname ) { DBIResult result; phDBICur cursor; CURProps curprops; if ( ( result = _GetCursor4Table ( tbl, &cursor ) ) != DBIERR_NONE ) return ( result ); if ( ( result = DbiGetCursorProps ( *cursor, &curprops ) ) == DBIERR_NONE ) strncpy ( tblname, curprops.szName, size ); iLog ( THISFILE, __LINE__, "PXTblName %s", tblname ); return ( result ); } DBIResult PXRecNum ( TABLEHANDLE tbl, RECORDNUMBER *recnum ) { DBIResult result; phDBICur cursor; CURProps curprops; RECProps recprops; iLog ( THISFILE, __LINE__, "PXRecNum %u", *recnum ); if ( ( result = _GetCursor4Table ( tbl, &cursor ) ) != DBIERR_NONE ) return ( result ); if ( ( result = DbiGetCursorProps ( *cursor, &curprops ) ) != DBIERR_NONE ) return ( result ); if ( strcmp ( curprops.szTableType, szPARADOX ) == 0 ) return ( DbiGetSeqNo ( *cursor, recnum ) ); else if ( strcmp ( curprops.szTableType, szDBASE ) == 0 ) { if ( ( result = DbiGetRecord ( *cursor, dbiNOLOCK, NULL, &recprops ) ) != DBIERR_NONE ) return ( result ); *recnum = recprops.iPhyRecNum; return ( DBIERR_NONE ); } else return ( DBIERR_NOTSUPPORTED ); } DBIResult PXRecNFlds ( TABLEHANDLE tbl, int *numflds ) { DBIResult result; phDBICur cursor; CURProps curprops; if ( ( result = _GetCursor4Table ( tbl, &cursor ) ) != DBIERR_NONE ) return ( result ); if ( ( result = DbiGetCursorProps ( *cursor, &curprops ) ) == DBIERR_NONE ) *numflds = curprops.iFields; iLog ( THISFILE, __LINE__, "PXRecNFlds %d", *numflds ); return ( result ); } // PXKeyNFlds returns the number of fields in the Primary index. DBIResult PXKeyNFlds ( TABLEHANDLE tbl, int *numflds ) { DBIResult result; phDBICur cursor; IDXDesc idxdesc; UINT16 seqno; iLog ( THISFILE, __LINE__, "PXKeyNFlds ?" ); *numflds = 0; // JAK 19971216 if ( ( result = _GetCursor4Table ( tbl, &cursor ) ) != DBIERR_NONE ) return ( result ); //#if 0 // JAK 19971216 => if ( ( result = DbiGetIndexSeqNo ( *cursor, NULL, NULL, 0, &seqno ) ) != DBIERR_NONE ) return ( result ); if ( ( result = DbiGetIndexDesc ( *cursor, seqno, &idxdesc ) ) == DBIERR_NONE ) *numflds = idxdesc.iFldsInKey; else if ( result == DBIERR_NOSUCHINDEX ) result = DBIERR_NONE; //#endif // JAK 19971216 <= #if 0 if ( ( result = DbiGetIndexDesc ( *cursor, 0 , &idxdesc ) ) == DBIERR_NONE ) *numflds = idxdesc.iFldsInKey; else if ( result == DBIERR_NOSUCHINDEX ) result = DBIERR_NONE; #endif iLog ( THISFILE, __LINE__, "PXKeyNFlds %d", *numflds ); return ( result ); } DBIResult PXFldType ( TABLEHANDLE tbl, FIELDHANDLE fld, int size, char *type ) { DBIResult result; phDBICur cursor; FLDDesc flddesc; iLog ( THISFILE, __LINE__, "PXFldType : tbl:%d, fld:%d, size:%d", tbl, fld, size ); if ( ( result = _GetCursor4Table ( tbl, &cursor ) ) != DBIERR_NONE ) return ( result ); if ( ( result = _GetFLDDesc ( cursor, fld, &flddesc ) ) == DBIERR_NONE ) { // now based upon paradox type construct a PXENGINE type switch ( flddesc.iFldType ) { case fldZSTRING : sprintf ( type, "A%d", flddesc.iUnits1 ); break; case fldFLOAT : sprintf ( type, "N" ); break; case fldDATE : sprintf ( type, "D" ); break; case fldBLOB : if ( flddesc.iSubType == fldstMEMO ) { sprintf ( type, "M%d", flddesc.iUnits1 ); } break; default : break; } } iLog ( THISFILE, __LINE__, "PXFldType : tbl:%d, fld:%d, size:%d, type:'%s'", tbl, fld, size, type ); return ( result ); #if 0 // JAK DBIResult result; CURProps curprops; FLDDesc *flddesc; int i; const char *typelist [] = { "?" , "ALPHA" , // 0x101 // Alpha (string) "NUM" , // 0x102 // Numeric "MONEY" , // 0x103 // Money "DATE" , // 0x104 // Date "SHORT" , // 0x105 // Short "MEMO" , // 0x106 // Text Memo (blob) // "BINARYBLOB", // 0x107 // Binary data (blob) // JAK 19970915 "BINARY" , // JAK 19970915 "FMTMEMO" , // 0x108 // Formatted text (blob) "OLEBLOB" , // 0x109 // OLE object (blob) "GRAPHIC" , // 0x10A // Graphics object (blob) "LONG" , // 0x10B // Long "TIME" , // 0x10C // Time "DATETIME" , // 0x10D // Time Stamp "BOOL" , // 0x10E // Logical "AUTOINC" , // 0x10F // Auto increment (long) "BYTES" , // 0x110 // Fixed number of bytes "BCD" , // 0x111 // BCD (32 digits) "UNICHAR" , // 0x112 // not supported yet NULL }; iLog ( THISFILE, __LINE__, "PXFldType %d", fld ); if ( type == NULL ) return ( DBIERR_INVALIDPARAM ); memset ( type, 0, size ); if ( ( result = DbiGetCursorProps ( tbl, &curprops ) ) != DBIERR_NONE ) return ( result ); if ( ( flddesc = ( FLDDesc * ) calloc ( curprops.iFields, sizeof ( FLDDesc ) ) ) == NULL ) return ( DBIERR_NOMEMORY ); if ( ( result = DbiGetFieldDescs ( tbl, flddesc ) ) != DBIERR_NONE ) { free ( flddesc ); return ( result ); } if ( ( fld < 1 ) || ( fld > curprops.iFields ) ) return ( DBIERR_INVALIDHNDL ); for ( i = 0 ; i < curprops.iFields ; i++ ) { if ( flddesc [ i ].iFldNum == fld ) strncpy ( type, typelist [ flddesc [ i ].iFldType ], size ); } free ( flddesc ); iLog ( THISFILE, __LINE__, "PXFldType %d %s", fld, type ); return ( result ); #endif } DBIResult PXNetTblRefresh ( TABLEHANDLE tbl ) { DBIResult result; phDBICur cursor; if ( ( result = _GetCursor4Table ( tbl, &cursor ) ) != DBIERR_NONE ) return ( result ); return ( DbiForceReread ( *cursor ) ); } void Reindex ( const TCHAR *dir, void ( *callback ) ( void ) ) { TCHAR path [ FILENAME_MAX ]; TCHAR name [ FILENAME_MAX ]; HANDLE handle; BOOL result; WIN32_FIND_DATA finddata; if ( dir != 0 ) { _tcscpy ( path, dir ); _tcscat ( path, _T ( "\\" ) ); } else memset ( path, 0, sizeof ( path ) ); _tcscpy ( name, path ); _tcscat ( name, _T ( "*.DB" ) ); // handle = FindFirstFile ( "*.DB", &finddata ); handle = FindFirstFile ( name, &finddata ); // handle = FindFirstFile ( *( argv + i ), &finddata ); if ( handle != INVALID_HANDLE_VALUE ) { do { if ( finddata.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY ) ; else { // Reindex ( hdb, finddata.cFileName ); hDBICur cursor; _tcscpy ( name, path ); _tcscat ( name, finddata.cFileName ); if ( callback != 0 ) ( callback ) (); if ( DbiOpenTable ( hDB, name, szPARADOX, NULL, NULL, 0, dbiREADWRITE, dbiOPENEXCL , xltFIELD, TRUE, NULL, &cursor ) == DBIERR_NONE ) { // printf ( "'%s' is open!\n", file ); UINT32 count; DbiGetRecordCount ( cursor, &count ); // printf ( "Record Count %ld\n", count ); // printf ( "Regenerating indexes\n" ); DbiRegenIndexes ( cursor ); if ( callback != 0 ) ( callback ) (); DbiCloseCursor ( &cursor ); } } result = FindNextFile ( handle, &finddata ); } while ( result ); FindClose ( handle ); } }