pack paradox and DBase codeunit DDGTbls;interfaceuses DB, DBTables, BDE;type TdBaseTable = class(TTable) private FViewDeleted: Boolean; function GetIsDeleted: Boolean; function GetRecNum: Longint; procedure SetViewDeleted(Value: Boolean); protected function CreateHandle: HDBICur; override; public procedure Pack(RegenIndexes: Boolean); procedure UndeleteRecord; property IsDeleted: Boolean read GetIsDeleted; property RecNum: Longint read GetRecNum; property ViewDeleted: Boolean read FViewDeleted write SetViewDeleted; end; TParadoxTable = class(TTable) private protected function CreateHandle: HDBICur; override; function GetRecNum: Longint; public procedure Pack; property RecNum: Longint read GetRecNum; end;implementationuses SysUtils;{ TdBaseTable }function TdBaseTable.GetIsDeleted: Boolean; { Returns a boolean indicating whether or not the current record } { has been soft deleted. } var RP: RECProps; begin if not FViewDeleted then // don't bother if they aren't viewing Result := False // deleted records else begin UpdateCursorPos; // update BDE from Delphi { Get current record properties } Check(dbiGetRecord(Handle, dbiNOLOCK, Nil, @RP)); Result := RP.bDeleteFlag; // return flag from properties end; end;function TdBaseTable.GetRecNum: Longint; { Returns the physical record number of the current record. } var RP: RECProps; begin UpdateCursorPos; // update BDE from Delphi { Get current record properties } Check(dbiGetRecord(Handle, dbiNOLOCK, Nil, @RP)); Result := RP.iPhyRecNum; // return value from properties end;function TdBaseTable.CreateHandle: HDBICur; { Overridden from ancestor in order to perform a check to } { ensure that this is a dBASE table. } var CP: CURProps; begin Result := inherited CreateHandle; // do inherited if Result <> Nil then begin { Get cursor properties, and raise exception if the } { table isn't using the dBASE driver. } Check(dbiGetCursorProps(Result, CP)); if not (CP.szTableType = szdBASE) then raise EDatabaseError.Create('Not a dBASE table'); end; end;procedure TdBaseTable.Pack(RegenIndexes: Boolean); { Packs the table in order to removed soft deleted records } { from the file. } const SPackError = 'Table must be active and opened exclusively'; begin { Table must be active and opened exclusively } if not (Active and Exclusive) then raise EDatabaseError.Create(SPackError); try { Pack the table } Check(dbiPackTable(DBHandle, Handle, Nil, Nil, RegenIndexes)); finally { update Delphi from BDE } CursorPosChanged; Refresh; end; end;procedure TdBaseTable.SetViewDeleted(Value: Boolean); { Allows the user to toggle between viewing and not viewing } { deleted records. } begin { Table must be active } if Active and (FViewDeleted <> Value) then begin DisableControls; // avoid flicker try { Magic BDE call to toggle view of soft deleted records } Check(dbiSetProp(hdbiObj(Handle), curSOFTDELETEON, Longint(Value))); finally Refresh; // update Delphi EnableControls; // flicker avoidance complete end; FViewDeleted := Value end; end;procedure TdBaseTable.UndeleteRecord; begin if not IsDeleted then raise EDatabaseError.Create('Record is not deleted'); Check(dbiUndeleteRecord(Handle)); Refresh; end;function TParadoxTable.CreateHandle: HDBICur; { Overridden from ancestor in order to perform a check to } { ensure that this is a Paradox table. } var CP: CURProps; begin Result := inherited CreateHandle; // do inherited if Result <> Nil then begin { Get cursor properties, and raise exception if the } { table isn't using the Paradox driver. } Check(dbiGetCursorProps(Result, CP)); if not (CP.szTableType = szPARADOX) then raise EDatabaseError.Create('Not a Paradox table'); end; end;function TParadoxTable.GetRecNum: Longint; { Returns the sequence number of the current record. } begin UpdateCursorPos; // update BDE from Delphi { Get sequence number of current record into Result } Check(dbiGetSeqNo(Handle, Result)); end;procedure TParadoxTable.Pack; var TblDesc: CRTblDesc; TempDBHandle: HDBIDb; WasActive: Boolean; begin { Initialize TblDesc record } FillChar(TblDesc, SizeOf(TblDesc), 0); // fill with 0s with TblDesc do begin StrPCopy(szTblName, TableName); // set table name szTblType := szPARADOX; // set table type bPack := True; // set pack flag end; { Store table active state. Must close table to pack. } WasActive := Active; if WasActive then Close; try { Create a temporary database. Must be read-write/exclusive } Check(dbiOpenDatabase(PChar(DatabaseName), Nil, dbiREADWRITE, dbiOpenExcl, Nil, 0, Nil, Nil, TempDBHandle)); try { Pack the table } Check(dbiDoRestructure(TempDBHandle, 1, @TblDesc, Nil, Nil, Nil, False)); finally { Close the temporary database } dbiCloseDatabase(TempDBHandle); end; finally { Reset table active state } Active := WasActive; end; end;end.
用函数packtable就行啦procedure PackTable(Table: TTable); var Props: CURProps; hDb: hDBIDb; TableDesc: CRTblDesc;begin // Make sure the table is open exclusively so we can get the db handle... if Table.Active = False then raise EDatabaseError.Create('Table must be opened to pack'); if Table.Exclusive = False then raise EDatabaseError.Create('Table must be opened exclusively to pack'); // Get the table properties to determine table type... Check(DbiGetCursorProps(Table.Handle, Props)); // If the table is a Paradox table, you must call DbiDoRestructure... if Props.szTableType = szPARADOX then begin // Blank out the structure... FillChar(TableDesc, sizeof(TableDesc), 0); // Get the database handle from the table's cursor handle... Check(DbiGetObjFromObj(hDBIObj(Table.Handle), objDATABASE, hDBIObj(hDb))); // Put the table name in the table descriptor... StrPCopy(TableDesc.szTblName, Table.TableName); // Put the table type in the table descriptor... StrPCopy(TableDesc.szTblType, Props.szTableType); // Set the Pack option in the table descriptor to TRUE... TableDesc.bPack := True; // Close the table so the restructure can complete... Table.Close; // Call DbiDoRestructure... Check(DbiDoRestructure(hDb, 1, @TableDesc, nil, nil, nil, FALSE)); end else // If the table is a dBASE table, simply call DbiPackTable... if Props.szTableType = szDBASE then Check(DbiPackTable(Table.DBHandle, Table.Handle, nil, szDBASE, TRUE)) else // Pack only works on PAradox or dBASE; nothing else... raise EDatabaseError.Create('Table must be either of Paradox or dBASE ' + 'type to pack'); Table.Open; end;
TdBaseTable = class(TTable)
private
FViewDeleted: Boolean;
function GetIsDeleted: Boolean;
function GetRecNum: Longint;
procedure SetViewDeleted(Value: Boolean);
protected
function CreateHandle: HDBICur; override;
public
procedure Pack(RegenIndexes: Boolean);
procedure UndeleteRecord;
property IsDeleted: Boolean read GetIsDeleted;
property RecNum: Longint read GetRecNum;
property ViewDeleted: Boolean read FViewDeleted write SetViewDeleted;
end; TParadoxTable = class(TTable)
private
protected
function CreateHandle: HDBICur; override;
function GetRecNum: Longint;
public
procedure Pack;
property RecNum: Longint read GetRecNum;
end;implementationuses SysUtils;{ TdBaseTable }function TdBaseTable.GetIsDeleted: Boolean;
{ Returns a boolean indicating whether or not the current record }
{ has been soft deleted. }
var
RP: RECProps;
begin
if not FViewDeleted then // don't bother if they aren't viewing
Result := False // deleted records
else begin
UpdateCursorPos; // update BDE from Delphi
{ Get current record properties }
Check(dbiGetRecord(Handle, dbiNOLOCK, Nil, @RP));
Result := RP.bDeleteFlag; // return flag from properties
end;
end;function TdBaseTable.GetRecNum: Longint;
{ Returns the physical record number of the current record. }
var
RP: RECProps;
begin
UpdateCursorPos; // update BDE from Delphi
{ Get current record properties }
Check(dbiGetRecord(Handle, dbiNOLOCK, Nil, @RP));
Result := RP.iPhyRecNum; // return value from properties
end;function TdBaseTable.CreateHandle: HDBICur;
{ Overridden from ancestor in order to perform a check to }
{ ensure that this is a dBASE table. }
var
CP: CURProps;
begin
Result := inherited CreateHandle; // do inherited
if Result <> Nil then begin
{ Get cursor properties, and raise exception if the }
{ table isn't using the dBASE driver. }
Check(dbiGetCursorProps(Result, CP));
if not (CP.szTableType = szdBASE) then
raise EDatabaseError.Create('Not a dBASE table');
end;
end;procedure TdBaseTable.Pack(RegenIndexes: Boolean);
{ Packs the table in order to removed soft deleted records }
{ from the file. }
const
SPackError = 'Table must be active and opened exclusively';
begin
{ Table must be active and opened exclusively }
if not (Active and Exclusive) then
raise EDatabaseError.Create(SPackError);
try
{ Pack the table }
Check(dbiPackTable(DBHandle, Handle, Nil, Nil, RegenIndexes));
finally
{ update Delphi from BDE }
CursorPosChanged;
Refresh;
end;
end;procedure TdBaseTable.SetViewDeleted(Value: Boolean);
{ Allows the user to toggle between viewing and not viewing }
{ deleted records. }
begin
{ Table must be active }
if Active and (FViewDeleted <> Value) then begin
DisableControls; // avoid flicker
try
{ Magic BDE call to toggle view of soft deleted records }
Check(dbiSetProp(hdbiObj(Handle), curSOFTDELETEON, Longint(Value)));
finally
Refresh; // update Delphi
EnableControls; // flicker avoidance complete
end;
FViewDeleted := Value
end;
end;procedure TdBaseTable.UndeleteRecord;
begin
if not IsDeleted then
raise EDatabaseError.Create('Record is not deleted');
Check(dbiUndeleteRecord(Handle));
Refresh;
end;function TParadoxTable.CreateHandle: HDBICur;
{ Overridden from ancestor in order to perform a check to }
{ ensure that this is a Paradox table. }
var
CP: CURProps;
begin
Result := inherited CreateHandle; // do inherited
if Result <> Nil then begin
{ Get cursor properties, and raise exception if the }
{ table isn't using the Paradox driver. }
Check(dbiGetCursorProps(Result, CP));
if not (CP.szTableType = szPARADOX) then
raise EDatabaseError.Create('Not a Paradox table');
end;
end;function TParadoxTable.GetRecNum: Longint;
{ Returns the sequence number of the current record. }
begin
UpdateCursorPos; // update BDE from Delphi
{ Get sequence number of current record into Result }
Check(dbiGetSeqNo(Handle, Result));
end;procedure TParadoxTable.Pack;
var
TblDesc: CRTblDesc;
TempDBHandle: HDBIDb;
WasActive: Boolean;
begin
{ Initialize TblDesc record }
FillChar(TblDesc, SizeOf(TblDesc), 0); // fill with 0s
with TblDesc do begin
StrPCopy(szTblName, TableName); // set table name
szTblType := szPARADOX; // set table type
bPack := True; // set pack flag
end;
{ Store table active state. Must close table to pack. }
WasActive := Active;
if WasActive then Close;
try
{ Create a temporary database. Must be read-write/exclusive }
Check(dbiOpenDatabase(PChar(DatabaseName), Nil, dbiREADWRITE,
dbiOpenExcl, Nil, 0, Nil, Nil, TempDBHandle));
try
{ Pack the table }
Check(dbiDoRestructure(TempDBHandle, 1, @TblDesc, Nil, Nil, Nil,
False));
finally
{ Close the temporary database }
dbiCloseDatabase(TempDBHandle);
end;
finally
{ Reset table active state }
Active := WasActive;
end;
end;end.
这个方法能实现吗?我试了一下,好象不行。
我的思想与你的不同。
dbTable.pas中有描述。
var
Props: CURProps;
hDb: hDBIDb;
TableDesc: CRTblDesc;begin
// Make sure the table is open exclusively so we can get the db handle...
if Table.Active = False then
raise EDatabaseError.Create('Table must be opened to pack');
if Table.Exclusive = False then
raise EDatabaseError.Create('Table must be opened exclusively to pack'); // Get the table properties to determine table type...
Check(DbiGetCursorProps(Table.Handle, Props)); // If the table is a Paradox table, you must call DbiDoRestructure...
if Props.szTableType = szPARADOX then
begin
// Blank out the structure...
FillChar(TableDesc, sizeof(TableDesc), 0);
// Get the database handle from the table's cursor handle...
Check(DbiGetObjFromObj(hDBIObj(Table.Handle), objDATABASE, hDBIObj(hDb)));
// Put the table name in the table descriptor...
StrPCopy(TableDesc.szTblName, Table.TableName);
// Put the table type in the table descriptor...
StrPCopy(TableDesc.szTblType, Props.szTableType);
// Set the Pack option in the table descriptor to TRUE...
TableDesc.bPack := True;
// Close the table so the restructure can complete...
Table.Close;
// Call DbiDoRestructure...
Check(DbiDoRestructure(hDb, 1, @TableDesc, nil, nil, nil, FALSE));
end
else
// If the table is a dBASE table, simply call DbiPackTable...
if Props.szTableType = szDBASE then
Check(DbiPackTable(Table.DBHandle, Table.Handle, nil, szDBASE, TRUE))
else
// Pack only works on PAradox or dBASE; nothing else...
raise EDatabaseError.Create('Table must be either of Paradox or dBASE ' +
'type to pack'); Table.Open;
end;
DbiPackTable(用于DBase),DbiDoRestructure(用于Paradox)另Pack并不是真正意义上的压缩,它的作用只是清除被删除的记录,是“紧缩”而非“压缩”。
题目说的并不是很清楚,我只是照文字来回答一下。更确切的说是从tip中挖了一段。
不知Tense(何必)大侠的想法是什么?愿闻其详。我因为专业的原因,对数据库方面了解不多。