📄 dbf.cpp
字号:
/* lock the database */#ifdef XB_LOCKING_ON if( AutoLock ) { if(( rc = LockDatabase( F_SETLKW, F_WRLCK, CurRec )) != XB_NO_ERROR ) { return rc; } if(( rc = LockDatabase( F_SETLKW, F_WRLCK, 0L )) != XB_NO_ERROR ) { LockDatabase( F_SETLK, F_UNLCK, CurRec ); return rc; } if((rc = ReadHeader(1)) != XB_NO_ERROR) { if(AutoLock) { LockDatabase( F_SETLK, F_UNLCK, CurRec ); LockDatabase( F_SETLK, F_UNLCK, 0L ); } return rc; } }#endif/* lock the indexes */#if defined(XB_INDEX_ANY) && defined(XB_LOCKING_ON) && defined(XB_REAL_DELETE) i = NdxList; while( i && AutoLock ) { if(( rc = i->index->LockIndex( F_SETLKW, F_WRLCK )) != XB_NO_ERROR ) return rc; i = i->NextIx; }#endif/* remove keys from indexes */#if defined(XB_REAL_DELETE) && defined(XB_INDEX_ANY) if(RealDelete) { i = NdxList; while(i) { i->index->CreateKey(0, 0); /* load key buf */ if(i->index->GetCurDbfRec() == (xbLong)CurRec) { i->index->DeleteKey(CurRec); newCurRec = i->index->GetCurDbfRec(); } else i->index->DeleteKey(CurRec); i->index->TouchIndex(); i = i->NextIx; } }#endif RecBuf[0] = 0x2a; #ifdef XB_REAL_DELETE//fprintf(stderr, "DeleteRecord() -> RealDelete = %d\n", RealDelete); if(RealDelete) { xbase->PutULong(&RecBuf[1], FirstFreeRec); FirstFreeRec = CurRec; RealNumRecs--; WriteHeader(1); }#endif if(!RealDelete) { if( DbfStatus != XB_UPDATED ) { DbfStatus = XB_UPDATED; memcpy( RecBuf2, RecBuf, RecordLen ); } rc = PutRecord( CurRec ); } else { if(fseek( fp, (long) HeaderLen + ((CurRec - 1L) * RecordLen), 0)) xb_error(XB_SEEK_ERROR); if(fwrite( RecBuf, RecordLen, 1, fp ) != 1 ) xb_error(XB_WRITE_ERROR); // // Attempt to read in the record for the current location // in the active index. // CurRec = newCurRec; if(CurRec) rc = GetRecord(CurRec); else BlankRecord(); } #ifdef XB_LOCKING_ON if(AutoLock) { LockDatabase( F_SETLK, F_UNLCK, CurRec ); LockDatabase( F_SETLK, F_UNLCK, 0L ); }#if defined(XB_INDEX_ANY) && defined(XB_REAL_DELETE) i = NdxList; while( i && AutoLock ) { i->index->LockIndex( F_SETLK, F_UNLCK ); i = i->NextIx; }#endif /* XB_INDEX_ANY */#endif /* XB_LOCKING_ON */ return rc;}/************************************************************************///! Undelete the current record/*! Marks the currect record as not deleted (i.e. removes the flag indicating the record is deleted). This method may not be used (and will return an error code) if "real" deletes are on. \returns One of the following: \htmlonly <p> <table border=2><tr><th>Return Code</th><th>Description</th></tr> <tr><td>XB_NO_ERROR</td><td>No error</td></tr> <tr><td>XB_INVALID_RECORD</td><td>Invalid record number</td></tr> </table> \endhtmlonly \latexonly \\ \\ \begin{tabular}{|l|l|} \hline \textbf{Return Code} & \textbf{Description} \\ \hline \hline XB\_NO\_ERROR & No error \\ \hline XB\_INVALID\_RECORD & Invalid record number \\ \hline \end{tabular} \endlatexonly*/xbShort xbDbf::UndeleteRecord( void ){ xbShort rc; #ifdef XB_REAL_DELETE if(RealDelete) xb_error(XB_INVALID_RECORD);#endif if( RecBuf ) { if( DbfStatus != XB_UPDATED ) { DbfStatus = XB_UPDATED; memcpy( RecBuf2, RecBuf, RecordLen ); } RecBuf[0] = 0x20; if(( rc = PutRecord( CurRec )) != 0 ) return rc; } else xb_error(XB_INVALID_RECORD); return 0;}/************************************************************************///! Determine if current record is deleted/*! \returns TRUE (1) if the current record is marked as deleted or FALSE (0) if not.*/xbShort xbDbf::RecordDeleted( void ){ if( RecBuf && RecBuf[0] == 0x2a ) return 1; else return 0;} /************************************************************************///! Pack data file/*!*/xbShort xbDbf::PackDatafiles(void (*statusFunc)(xbLong itemNum, xbLong numItems)){ xbShort rc = 0, i, NameLen; FILE *t; xbLong l; char *target, *source; xbString TempDbfName; char * Buf = 0;#ifdef XB_MEMO_FIELDS char tbuf[4];#endif#ifdef XB_MEMO_FIELDS xbLong len, BufSize; xbString TempDbtName; xbShort MemoFields;#endif /* XB_MEMO_FIELDS */ xbDbf Temp( xbase ); if(( rc = xbase->DirectoryExistsInName( DatabaseName )) > 0 ) NameLen = rc + 13; else NameLen = 13; if (rc) { TempDbfName.assign(DatabaseName, 0, rc); TempDbfName += "TMPXBASE.DBF"; } else TempDbfName = "TMPXBASE.DBF"; if (( t = fopen( TempDbfName, "w+b" )) == NULL ) xb_open_error(TempDbfName); /* copy file header */ if(( rc = fseek( fp, 0, SEEK_SET )) != 0 ) xb_io_error(XB_SEEK_ERROR, TempDbfName); for( i = 0; i < HeaderLen; i++ ) fputc( fgetc( fp ), t ); fputc( 0x1a, t ); if( fclose( t ) != 0 ) xb_io_error(XB_CLOSE_ERROR, TempDbfName);#ifdef XB_MEMO_FIELDS if(( MemoFields = MemoFieldsPresent()) > 0 ) { TempDbtName = TempDbfName; TempDbtName.putAt(TempDbtName.len()-1, 'T'); if ((t = fopen( TempDbtName, "w+b" )) == NULL) xb_open_error(TempDbtName); l = 1L; memset( tbuf, 0x00, 4 ); xbase->PutLong( tbuf, l ); if ((fwrite(&tbuf, 4, 1, t)) != 1) xb_io_error(XB_WRITE_ERROR, TempDbfName); if( MemoHeader.Version == 0x03 ) { for( i = 0; i < 12; i++ ) fputc( 0x00, t ); fputc( 0x03, t ); for( i = 0; i < 495; i++ ) fputc( 0x00, t ); } else { for( i = 0; i < 4; i++ ) fputc( 0x00, t ); if ((fwrite(&MemoHeader.FileName, 8, 1, t)) != 1) xb_io_error(XB_WRITE_ERROR, TempDbfName); for( i = 0; i < 4; i++ ) fputc( 0x00, t ); memset( tbuf, 0x00, 2 ); xbase->PutShort( tbuf, MemoHeader.BlockSize ); if ((fwrite(&tbuf, 2, 1, t)) != 1) xb_io_error(XB_WRITE_ERROR, TempDbfName); for( i = 22; i < MemoHeader.BlockSize; i++ ) fputc( 0x00, t ); } if( fclose( t ) != 0 ) xb_io_error(XB_CLOSE_ERROR, TempDbfName); }#endif /* XB_MEMO_FIELDS */ /* reopen as database */ if(( rc = Temp.OpenDatabase( TempDbfName )) != XB_NO_ERROR ) return rc; Temp.ResetNoOfRecs(); Temp.WriteHeader(2); // flush NoOfRecs=0 to disk target = Temp.GetRecordBuf(); source = GetRecordBuf(); for( l = 1; l <= NoOfRecords(); l++ ) { if(statusFunc && (l == 1 || !(l % 100) || l == PhysicalNoOfRecords())) statusFunc(l, PhysicalNoOfRecords()); if(( rc = GetRecord( l )) != XB_NO_ERROR ) return rc; if( !RecordDeleted()) { strncpy( target, source, GetRecordLen());#ifdef XB_MEMO_FIELDS len = BufSize = 0L; Buf = NULL; for( i = 0; i < NoOfFields; i++ ) { if( GetFieldType( i ) == 'M' && MemoFieldExists( i )) { len = GetMemoFieldLen( i ); if( len > BufSize ) { if( BufSize ) free( Buf ); if ((Buf = (char *)malloc(len)) == NULL) xb_memory_error; BufSize = len; } GetMemoField( i, len, Buf, -1 ); Temp.UpdateMemoData( i, len, Buf, -1 ); } }#endif if(( rc = Temp.AppendRecord()) != XB_NO_ERROR ) { if(Buf) free(Buf); return rc; } } } if( Buf ) free( Buf ); Temp.CloseDatabase(); if (fclose(fp) != 0) xb_io_error(XB_CLOSE_ERROR, DatabaseName); if(remove(DatabaseName) != 0) xb_io_error(XB_WRITE_ERROR, DatabaseName); if(rename(TempDbfName, DatabaseName) != 0) xb_io_error(XB_WRITE_ERROR, TempDbfName);#ifdef XB_MEMO_FIELDS if( MemoFields ) { // len = DatabaseName.len(); // len--; // lb = DatabaseName[len]; int len = DatabaseName.len() - 1; char lb = DatabaseName[len]; if( lb == 'F' ) DatabaseName.putAt(len, 'T'); else DatabaseName.putAt(len, 't'); if(fclose(mfp) != 0) /* thanks Jourquin */ xb_io_error(XB_CLOSE_ERROR, TempDbtName); if (remove(DatabaseName) != 0) { DatabaseName.putAt(len, lb); xb_io_error(XB_WRITE_ERROR, DatabaseName); } if( rename( TempDbtName, DatabaseName ) != 0 ) { DatabaseName.putAt(len, lb); xb_io_error(XB_WRITE_ERROR, DatabaseName); } if(( mfp = fopen( DatabaseName, "r+b" )) == NULL ) xb_open_error(DatabaseName);#ifdef XB_LOCKING_ON /* no buffering in multi user mode */ setbuf( mfp, NULL );#endif DatabaseName.putAt(len, lb); }#endif /* XB_MEMO_FIELDS */ if(( fp = fopen( DatabaseName, "r+b" )) == NULL ) xb_open_error(DatabaseName);#ifdef XB_LOCKING_ON /* no buffering in multi user mode */ setbuf( fp, NULL );#endif return XB_NO_ERROR;}/************************************************************************///! Pack the database/*! This method removes all records marked for deletion from an Xbase (.DBF) file, reindexes any open index files, and also reorganizes any memo fields stored in a .DBT memo file. \param LockWaitOption One of the following: \htmlonly <p> <table border=2><tr><th>LockWaitOption</th><th>Description</th></tr> <tr><td>F_SETLK</td><td>Return immediately if the DBF file cannot be locked</td></tr> <tr><td>F_SETLKW</td><td>Wait for lock on DBF file to succeed</td></tr> </table> \endhtmlonly \latexonly \\ \\ \begin{tabular}{|l|l|} \hline \textbf{LockWaitOption} & \textbf{Description} \\ \hline \hline F\_SETLK & Return immediately if DBF file cannot be locked \\ \hline F\_SETLKW & Wait for lock on DBF file to succeed \\ \hline \end{tabular} \endlatexonly \returns One of the following return codes: \htmlonly <p> <table border=2><tr><th>Return Code</th><th>Description</th></tr> <tr><td>XB_NO_ERROR</td><td>No error</td></tr> <tr><td>XB_CLOSE_ERROR</td><td>Unable to close intermediate work file</td></tr> <tr><td>XB_OPEN_ERROR</td><td>Could not open file</td></tr> <tr><td>XB_NO_MEMORY</td><td>Memory allocation error</td></tr> <tr><td>XB_WRITE_ERROR</td><td>Couldn't write to disk</td></tr> <tr><td>XB_SEEK_ERROR</td><td>Error seeking file</td></tr> <tr><td>XB_LOCK_FAILED</td><td>Unable to lock file or index</td></tr> </table> \endhtmlonly \latexonly \\ \\ \begin{tabular}{|l|l|} \hline \textbf{Return Code} & \textbf{Description} \\ \hline \hline XB\_NO\_ERROR & No Error \\ \hline XB\_CLOSE\_ERROR & Unable to close intermediate work file \\ \hline XB\_OPEN\_ERROR & Couldn't open the file \\ \hline XB\_NO\_MEMORY & Memory allocation error \\ \hline XB\_WRITE\_ERROR & Couldn't write to disk \\ \hline XB\_SEEK\_ERROR & Error seeking file \\ \hline XB\_LOCK\_FAILED & Unable to lock file or index \\ \hline \end{tabular} \endlatexonly*/xbShort xbDbf::PackDatabase(xbShort LockWaitOption, void (*packStatusFunc)(xbLong itemNum, xbLong numItems), void (*indexStatusFunc)(xbLong itemNum, xbLong numItems)){ xbShort rc = 0; /* lock all open files and indexes */ if(( rc = ExclusiveLock( LockWaitOption )) != XB_NO_ERROR ) return rc; if(( rc = PackDatafiles(packStatusFunc)) != XB_NO_ERROR ) { ExclusiveUnlock(); return rc; } /* refresh file header */ if(( rc = ReadHeader(1)) != XB_NO_ERROR ) return rc; if(( rc = RebuildAllIndices(indexStatusFunc)) != XB_NO_ERROR ) return rc; ExclusiveUnlock(); return XB_NO_ERROR;}/************************************************************************///! Copy DBF structure/*!*/xbShort xbDbf::C
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -