/* d4skip.c (c)Copyright Sequiter Software Inc., 1988-1996. All rights reserved. */ #include "d4all.h" #ifndef S4UNIX #ifdef __TURBOC__ #pragma hdrstop #endif #endif #ifdef S4SERVER /* -2 means eof, -3 means bof */ long d4skipRecno( DATA4 *data, long n ) { #ifndef S4OFF_INDEX TAG4 *tag ; TAG4FILE *tagFile ; #endif long startRec, newRec ; #ifndef S4OFF_INDEX unsigned char *keyValue ; int rc ; long recno, nSkipped ; #endif CODE4 *c4 ; #ifdef S4VBASIC if ( c4parm_check( data, 2, E94801 ) ) return -1 ; #endif #ifdef E4PARM_LOW if ( data == 0 ) return error4( 0, e4parm_null, E94801 ) ; #endif c4 = data->codeBase ; if ( c4 == 0 ) return e4info ; if ( error4code( c4 ) < 0 ) return error4code( c4 ) ; if ( data->recNum < 1L ) { #ifndef S4SERVER if ( c4->errSkip ) return error4( c4, e4info, E84801 ) ; #endif return e4info ; } #ifndef S4OFF_INDEX tag = data->tagSelected ; /* avoid function call */ if ( tag == 0 ) { #endif if ( n != 0L ) if ( d4recCountLessEq( data, 1L ) == 0 ) /* count == 0 */ return -4L ; data->bofFlag = 0 ; startRec = data->recNum ; newRec = startRec + n ; if ( newRec > 0L ) { if ( d4recCountLessEq( data, newRec ) == 0 ) return -2L ; return newRec ; } else return -3L ; #ifndef S4OFF_INDEX } else { tagFile = tag->tagFile ; if ( data->eofFlag ) { if ( n >= 0L ) return -2L ; rc = d4bottom( data ) ; if ( rc && rc != r4eof ) return rc ; if ( rc == r4eof ) return -2L ; n++ ; data->recNum = tfile4recNo( tagFile ) ; } data->bofFlag = 0 ; #ifndef S4OFF_WRITE if ( data->recordChanged ) { rc = d4updateRecord( data, 0 ) ; /* was 1 */ if ( rc < 0 ) return rc ; } #endif t4versionCheck( tag, 1, 0 ) ; if ( n == 0 ) return data->recNum ; if ( tfile4recNo( tagFile ) != data->recNum ) { if ( d4lockTest( data, data->recNum ) == 0 ) /* ensure latest from disk */ { rc = d4go( data, data->recNum ) ; if ( rc < 0 ) return rc ; } expr4context( tagFile->expr, data ) ; tfile4exprKey( tagFile, &keyValue ) ; rc = tfile4go( tagFile, keyValue, data->recNum, 0 ) ; if ( rc < 0 ) return rc ; if ( tfile4empty( tagFile ) ) return -4L ; if ( tfile4eof( tagFile ) && n >= 0L ) return -2L ; #ifdef S4HAS_DESCENDING if ( tagFile->header.descending ) { if ( (rc > 0) && (n < 0) ) n-- ; } else if ( (rc > 0) && (n > 0) ) n-- ; #else if ( (rc > 0) && (n > 0) ) n-- ; #endif } else { if ( tfile4eof( tagFile ) ) return -2L ; } nSkipped = tfile4dskip( tagFile, n ) ; if ( n > 0 && nSkipped != n ) return -2L ; if ( n < 0 && nSkipped != n ) return -3L ; if ( tfile4eof( tagFile ) ) return -2L ; recno = tfile4recNo( tagFile ) ; if ( recno < 0 ) return recno ; return recno ; } #endif } #endif /* S4SERVER */ /* flush the current record to disk, and update the data pointer to point to a valid tag location (in case the current record has been filtered out */ /* direction is -1 if line up backwards, or 1 if line up forwards */ #ifdef P4ARGS_USED #pragma argsused #endif int S4FUNCTION d4tagSync( DATA4 *data, TAG4 * const tag ) { #ifdef S4OFF_INDEX return 0 ; #else CODE4 *c4 ; #ifdef S4CLIENT int rc, saveRc ; CONNECTION4 *connection ; CONNECTION4TAG_SYNCH_INFO_IN info ; CONNECTION4TAG_SYNCH_INFO_OUT *out ; #ifndef S4OFF_MEMO int i ; #endif #endif #ifdef S4VBASIC if ( c4parm_check( data, 2, E94803 ) ) return -1 ; #endif #ifdef E4PARM_HIGH if ( data == 0 ) return error4( 0, e4parm_null, E94803 ) ; #endif if ( tag == 0 ) return 0 ; c4 = data->codeBase ; if ( error4code( c4 ) < 0 ) return error4code( c4 ) ; #ifdef S4CLIENT if ( data->recNum <= 0 || d4eof( data ) ) { #ifndef S4OFF_MEMO for ( i = 0; i < data->dataFile->nFieldsMemo; i++ ) f4memoReset( data->fieldsMemo[i].field ) ; #endif data->recordChanged = 0 ; return 0 ; } if ( data->recordChanged == 0 ) return 0 ; connection = data->dataFile->connection ; if ( connection == 0 ) return error4stack( data->codeBase, e4connection, E94803 ) ; connection4assign( connection, CON4TAG_SYNCH, data4clientId( data ), data4serverId( data ) ) ; memcpy( info.tagName, tag->tagFile->alias, LEN4TAG_ALIAS ) ; info.tagName[LEN4TAG_ALIAS] = 0 ; info.recno = d4recNo( data ) ; connection4addData( connection, &info, sizeof( CONNECTION4TAG_SYNCH_INFO_IN ), 0 ) ; saveRc = connection4repeat( connection, -2, -1, -1, data ) ; if ( saveRc == r4eof || saveRc == r4noRecords ) { data->bofFlag = 0 ; rc = d4goEof( data ) ; if ( rc == 0 ) rc = r4eof ; if ( saveRc == r4noRecords ) data->bofFlag = 1 ; return rc ; } if ( saveRc == r4bof ) { data->eofFlag = 0 ; rc = d4goBof( data ) ; data->bofFlag = 1 ; if ( rc == 0 ) rc = r4bof ; return rc ; } if ( saveRc != 0 ) { if ( saveRc < 0 ) return connection4errorDescribe( connection, c4, saveRc, E94803, tag->tagFile->alias, 0, 0 ) ; return saveRc ; } if ( connection4len( connection ) != sizeof( CONNECTION4TAG_SYNCH_INFO_OUT ) ) return error4( c4, e4packetLen, E94803 ) ; out = (CONNECTION4TAG_SYNCH_INFO_OUT *)connection4data( connection ) ; if ( out->recNo != 0 && out->recNo != d4recNo( data ) ) { rc = d4go( data, out->recNo ) ; if ( rc < 0 ) return rc ; } return saveRc ; #else return d4tagSyncDo( data, tag, 1 ) ; #endif #endif /* S4OFF_INDEX */ } #ifndef S4OFF_INDEX #ifndef S4CLIENT int d4tagSyncDo( DATA4 *data, TAG4 * const tag, int direction ) { int rc ; CODE4 *c4 ; unsigned char *keyValue ; #ifndef S4OFF_MULTI int done, verifyReccount ; #ifndef S4OFF_TRAN int nSkipped ; #endif #endif TAG4 *oldSelected ; TAG4FILE *tagFile ; long recno ; c4 = data->codeBase ; tagFile = tag->tagFile ; expr4context( tagFile->expr, data ) ; tfile4exprKey( tagFile, &keyValue ) ; recno = tfile4recNo( tagFile ) ; if ( recno != data->recNum ) { rc = tfile4go( tagFile, keyValue, data->recNum, 0 ) ; if ( rc ) return rc ; } oldSelected = data->tagSelected ; d4tagSelect( data, tag ) ; #ifndef S4OFF_WRITE if ( data->recordChanged ) { rc = d4updateRecord( data, 0 ) ; if ( rc ) { d4tagSelect( data, oldSelected ) ; return rc ; } } #endif if ( data->eofFlag ) { d4tagSelect( data, oldSelected ) ; /* if forward skip not true, not eof, here is */ return d4goEof( data ) ; } else { t4versionCheck( tag, 1, 0 ) ; if ( tfile4eof( tagFile ) ) return d4goEof( data ) ; recno = tfile4recNo( tagFile ) ; if ( recno != data->recNum ) rc = d4go( data, recno ) ; else rc = 0 ; } #ifndef S4OFF_MULTI for( verifyReccount = 1, done = 0 ; done == 0 ; ) { #ifndef S4OFF_TRAN if ( code4transEnabled( c4 ) ) if ( t4unique( tag ) != 0 ) if ( code4tranStatus( c4 ) == r4active ) if ( d4lockTest( data, recno ) ) { /* if within a transaction, and record is locked, it may mean that the record contents have changed. If the current tag key does not match, it must be an old entry (if a unique tag), and thus skip over */ for ( ;; ) { if ( recno > data->dataFile->minCount ) /* ensure correct sequencing for multi-user */ break ; /* just let the code below take care of this case */ verifyReccount = 1 ; expr4context( tagFile->expr, data ) ; if ( recno != d4recNo( data ) ) /* need to reposition data4 first */ d4go( data, recno ) ; tfile4exprKey( tagFile, &keyValue ) ; if ( memcmp( tfile4key( tagFile ), keyValue, tagFile->header.keyLen ) != 0 ) /* different, so skip */ nSkipped = (int)tfile4skip( tagFile, direction ) ; else /* done */ break ; if ( direction > 0 && nSkipped != 1 ) { rc = d4goEof( data ) ; done = 1 ; break ; } if ( tfile4eof( tagFile ) ) { data->bofFlag = 1 ; rc = d4goEof( data ) ; done = 1 ; break ; } if ( tfile4recNo( tagFile ) != recno ) /* ok, may continue */ { recno = tfile4recNo( tagFile ) ; d4go( data, recno ) ; break ; } } } #endif /* S4OFF_TRAN */ if ( done == 1 ) break ; if ( verifyReccount == 1 ) { verifyReccount = 0 ; if ( recno > data->dataFile->minCount ) /* ensure correct sequencing for multi-user */ { if ( d4recCountLessEq( data, recno ) == 0 ) { rc = (int)tfile4skip( tagFile, direction ) ; if ( rc < 0 ) done = 1 ; else { if ( rc == 0 ) { data->bofFlag = 1 ; done = 1 ; rc = d4goEof( data ) ; } else { recno = tfile4recNo( tagFile ) ; if ( recno <= 0 || recno > data->dataFile->minCount ) { done = 1 ; rc = -1 ; } if ( tfile4recNo( tagFile ) != recno ) /* ok, may continue */ { recno = tfile4recNo( tagFile ) ; d4go( data, recno ) ; break ; } } } } } else done = 1 ; } else done = 1 ; } #endif /* S4OFF_MULTI */ d4tagSelect( data, oldSelected ) ; return rc ; } #endif /* S4CLIENT */ #endif /* S4OFF_INDEX */ int S4FUNCTION d4skip( DATA4 *data, const long nSkip ) { int rc ; CODE4 *c4 ; #ifdef S4CLIENT int saveRc ; CONNECTION4 *connection ; CONNECTION4GO_INFO_OUT *out ; CONNECTION4SKIP_INFO_IN info ; #else #ifndef S4OFF_INDEX unsigned char *keyValue ; long nSkipped, recno ; TAG4FILE *tagFile ; #endif long n ; #ifndef S4SERVER int saveFlag ; #endif long startRec, newRec ; int oldEofFlag, c1 ; #endif #ifndef S4OFF_INDEX TAG4 *tag ; #endif #ifdef S4VBASIC if ( c4parm_check( data, 2, E94802 ) ) return -1 ; #endif #ifdef E4PARM_HIGH if ( data == 0 ) return error4( 0, e4parm_null, E94802 ) ; #endif c4 = data->codeBase ; if ( error4code( c4 ) < 0 ) return error4code( c4 ) ; if ( data->recNum < 1L ) { #ifndef S4SERVER if ( c4->errSkip ) error4( c4, e4info, E84801 ) ; #endif return e4info ; } #ifdef S4CLIENT rc = d4updateRecord( data, 0 ) ; /* returns -1 if error4code( codeBase ) < 0 */ if ( rc ) return rc ; connection = data->dataFile->connection ; if ( connection == 0 ) return error4stack( data->codeBase, e4connection, E94802 ) ; connection4assign( connection, CON4SKIP, data4clientId( data ), data4serverId( data ) ) ; info.startPos = data->recNum ; info.numSkip = nSkip ; #ifdef S4OFF_INDEX info.usesTag = 0 ; #else tag = data->tagSelected ; if ( tag == 0 ) info.usesTag = 0 ; else { info.usesTag = 1 ; memcpy( info.tagName, tag->tagFile->alias, LEN4TAG_ALIAS ) ; info.tagName[LEN4TAG_ALIAS] = 0 ; } #endif connection4addData( connection, &info, sizeof( CONNECTION4SKIP_INFO_IN ), 0 ) ; rc = connection4repeat( connection, -2, -1, -1, data ) ; if ( rc == r4locked ) return r4locked ; if ( (long)connection4len( connection ) < (long)sizeof( CONNECTION4GO_INFO_OUT ) ) return error4( c4, e4packetLen, E94802 ) ; out = (CONNECTION4GO_INFO_OUT *)connection4data( connection ) ; saveRc = out->skipRc ; if ( saveRc < 0 ) { if ( tag == 0 ) return connection4error( connection, c4, saveRc, E94802 ) ; else return connection4errorDescribe( connection, c4, saveRc, E94802, tag->tagFile->alias, 0, 0 ) ; } if ( saveRc == r4eof || saveRc == r4noRecords ) { data->bofFlag = 0 ; rc = d4goEof( data ) ; if ( rc == 0 ) rc = r4eof ; if ( saveRc == r4noRecords ) data->bofFlag = 1 ; return rc ; } if ( saveRc == r4bof ) { data->eofFlag = 0 ; rc = d4goBof( data ) ; data->bofFlag = 1 ; if ( rc == 0 ) rc = r4bof ; return rc ; } if ( saveRc != 0 ) { if ( saveRc < 0 ) return error4( c4, saveRc, E94802 ) ; return saveRc ; } rc = connection4status( connection ) ; if ( out->recNo != 0 ) { if ( (long)connection4len( connection ) != (long)sizeof( CONNECTION4GO_INFO_OUT ) + (long)dfile4recWidth( data->dataFile ) ) return error4( c4, e4packetLen, E94802 ) ; return d4goVirtual( data, out->recNo, rc, out, connection ) ; /* maybe r4locked, or whatever */ } return rc ; #else n = nSkip ; #ifndef S4OFF_INDEX tag = data->tagSelected ; if ( tag == 0 ) { #endif data->bofFlag = 0 ; startRec = data->recNum ; newRec = startRec + n ; if ( newRec > 0L ) { #ifndef S4SERVER saveFlag = c4->errGo ; c4->errGo = 0 ; #endif #ifndef S4OFF_OPTIMIZE data->dataFile->hiPrio = -1 ; /* indicate d4skip - data level */ #endif rc = d4go( data, newRec ) ; #ifndef S4OFF_OPTIMIZE data->dataFile->hiPrio = 0 ; #endif #ifndef S4SERVER c4->errGo = saveFlag ; #endif if ( rc >= 0 && rc != r4entry ) return rc ; } c1 = d4recCountLessEq( data, 1L ) ; if ( c1 < 0 ) return c1 ; if ( ( c1 == 0 ) || ( d4recCountLessEq( data, newRec ) == 0 ) ) { if ( c1 == 0L ) { rc = d4goEof( data ) ; if ( rc != r4eof ) return rc ; data->bofFlag = 1 ; } if ( n < 0 ) { data->bofFlag = 1 ; return r4bof ; } else return d4goEof( data ) ; } if ( newRec < 1L ) { oldEofFlag = data->eofFlag ; rc = d4go( data, 1L ) ; if ( rc ) return rc ; data->bofFlag = 1 ; data->eofFlag = oldEofFlag ; return r4bof ; } return d4go( data, newRec ) ; #ifndef S4OFF_INDEX } else { tagFile = tag->tagFile ; if ( data->eofFlag ) { if ( n >= 0 ) return d4goEof( data ) ; rc = d4bottom( data ) ; if ( rc && rc != r4eof ) return rc ; if ( rc == r4eof ) { rc = d4goEof( data ) ; if ( rc != r4eof ) return rc ; return r4bof ; } n++ ; data->recNum = tfile4recNo( tagFile ) ; } data->bofFlag = 0 ; #ifndef S4OFF_WRITE if ( data->recordChanged ) { rc = d4updateRecord( data, 0 ) ; /* was 1 */ if ( rc < 0 ) return rc ; } #endif t4versionCheck( tag, 1, 0 ) ; if ( n == 0 ) return 0 ; if ( tfile4recNo( tagFile ) != data->recNum ) { rc = d4go( data, data->recNum ) ; if ( rc ) return rc ; expr4context( tagFile->expr, data ) ; tfile4exprKey( tagFile, &keyValue ) ; rc = tfile4go( tagFile, keyValue, data->recNum, 0 ) ; if ( rc < 0 ) return rc ; #ifdef S4HAS_DESCENDING if ( tagFile->header.descending ) { if ( (rc > 0) && (n < 0) ) n-- ; } else if ( (rc > 0) && (n > 0) ) n-- ; #else if ( (rc > 0) && (n > 0) ) n-- ; #endif } nSkipped = tfile4dskip( tagFile, n ) ; if ( n > 0 && nSkipped != n ) return d4goEof( data ) ; if ( tfile4eof( tagFile ) ) { data->bofFlag = 1 ; return d4goEof( data ) ; } recno = tfile4recNo( tagFile ) ; if ( recno < 0 ) return (int)recno ; rc = d4go( data, recno ) ; if ( rc ) return rc ; #ifndef S4OFF_MULTI rc = d4tagSyncDo( data, tag, n > 0 ? 1 : -1 ) ; if ( rc != 0 ) return rc ; #endif if ( n == nSkipped ) return 0 ; #ifdef S4HAS_DESCENDING if ( ( n < 0 && !tagFile->header.descending ) || ( n < 0 && tagFile->header.descending ) ) #else if ( n < 0 ) #endif { data->bofFlag = 1 ; return r4bof ; } } return 0 ; #endif #endif }