📄 abstempengine.pas
字号:
unit ABSTempEngine;
{$I ABSVer.inc}
interface
uses SysUtils, Classes,
// AbsoluteDatabase units
{$IFNDEF D5H}
ABSD4Routines,
{$ENDIF}
{$IFDEF DEBUG_LOG}
ABSDebug,
{$ENDIF}
ABSExcept,
ABSBase,
ABSPage,
ABSBaseEngine,
ABSMemory,
ABSCompression,
ABSSecurity,
ABSTypes,
ABSConst;
type
TABSTemporaryTableData = class;
////////////////////////////////////////////////////////////////////////////////
//
// TABSTemporaryRecordManager
//
////////////////////////////////////////////////////////////////////////////////
TABSTemporaryRecordManager = class (TABSBaseRecordManager)
private
FRecordsPerPage: Integer;
FPageSize: Integer;
FCachedRecordCount: Integer;
FCache: PChar;
FAllocatedRecordCount: Integer;
FTempPage: PChar;
FTempPageRecordCount: Integer;
FTempPageFile: TABSFileStream;
FMaxCachedRecordCount: Integer;
FAllocRecordsBy: Integer;
FDisableTempFiles: Boolean;
procedure SaveTempPage;
function ReadRecord(
var RecordBuffer: TABSRecordBuffer;
RecordID: TABSRecordNo
): Boolean;
// return result for attempt of getting record relatively to first position
// and set RecordID to new record ID
function GetRecordFromFirstPosition(
GetRecordMode: TABSGetRecordMode;
var RecordID: TABSRecordNo
): TABSGetRecordResult;
// return result for attempt of getting record relatively to last position
// and set RecordID to new record ID
function GetRecordFromLastPosition(
GetRecordMode: TABSGetRecordMode;
var RecordID: TABSRecordNo
): TABSGetRecordResult;
// return result for attempt of getting record relatively any position
// and set RecordID to new record ID
function GetRecordFromAnyPosition(
GetRecordMode: TABSGetRecordMode;
var RecordID: TABSRecordNo
): TABSGetRecordResult;
public
constructor Create(
RecordBufferSize: Integer;
RecordsPerPage: Integer;
AllocRecordsBy: Integer;
DisableTempFiles: Boolean
);
destructor Destroy; override;
procedure Empty(SessionID: TABSSessionID); override;
// add record and return its number
function AddRecord(
SessionID: TABSSessionID;
RecordBuffer: TABSRecordBuffer;
var RecordID: TABSRecordID
): Boolean; override;
// update record, return true if record was updated, false if record was deleted
function UpdateRecord(SessionID: TABSSessionID; RecordBuffer: TABSRecordBuffer; RecordID: TABSRecordID): Boolean; override;
// delete record, return true if record was deleted, false if record was deleted earlier
function DeleteRecord(SessionID: TABSSessionID; var RecordID: TABSRecordID): Boolean; override;
procedure GetRecordBuffer(SessionID: TABSSessionID; var NavigationInfo: TABSNavigationInfo); override;
// return 0,1, or -1 if (1 = 2), (1 > 2) or (1 < 2)
function CompareRecordID(RecordID1: TABSRecordID; RecordID2: TABSRecordID): Integer; override;
// return record no
function GetApproximateRecNo(SessionID: TABSSessionID; RecordID: TABSRecordID): TABSRecordNo; override;
end; // TABSTemporaryRecordManager
////////////////////////////////////////////////////////////////////////////////
//
// TABSTemporaryPageManager
//
////////////////////////////////////////////////////////////////////////////////
TABSTemporaryPageManager = class (TABSPageManager)
protected
FAllocatedPageMap: TABSBitsArray;
FAllocatedPageCount: TABSPageNo;
FTempPageFile: TABSFileStream;
FMaxMemoryPageCount: TABSPageNo;
FMemoryPageManager: TABSPageManager;
FDisableTempFiles: Boolean;
public
procedure InternalAddPage(aPage: TABSPage); override;
procedure InternalRemovePage(PageNo: TABSPageNo); override;
function InternalReadPage(aPage: TABSPage): Boolean; override;
procedure InternalWritePage(aPage: TABSPage); override;
constructor Create(DisableTempFiles: Boolean);
destructor Destroy; override;
end; // TABSMemoryPageManager
////////////////////////////////////////////////////////////////////////////////
//
// TABSTemporaryDatabaseData
//
////////////////////////////////////////////////////////////////////////////////
TABSTemporaryDatabaseData = class (TABSDatabaseData)
private
FLastObjectID: TABSLastObjectID;
public
constructor Create;
destructor Destroy; override;
// create table data
function CreateTableData(Cursor: TABSCursor): TABSTableData; override;
function GetNewObjectId: TABSObjectID; override;
end; // TABSTemporaryDatabaseData
////////////////////////////////////////////////////////////////////////////////
//
// TABSTemporaryTableData
//
////////////////////////////////////////////////////////////////////////////////
TABSTemporaryTableData = class (TABSTableData)
private
FBLOBFile: TABSStream;
FRecordsPerPage: Integer;
FAllocRecordsBy: Integer;
protected
procedure CreateRecordManager; override;
procedure CreateFieldManager(FieldDefs: TABSFieldDefs); override;
procedure CreateIndexManager(IndexDefs: TABSIndexDefs); override;
procedure CreateConstraintManager(ConstraintDefs: TABSConstraintDefs); override;
procedure CreateBLOBFile;
procedure DeleteBLOBFile;
// return filter bitmap rec count
function GetBitmapRecordCount(SessionID: TABSSessionID): TABSRecordNo; override;
// return filter bitmap rec no by record id
function GetBitmapRecNoByRecordID(RecordID: TABSRecordID): TABSRecordNo; override;
// return filter bitmap rec no by record id
function GetRecordIDByBitmapRecNo(RecordNo: TABSRecordNo): TABSRecordID; override;
public
constructor Create(
aDatabaseData: TABSDatabaseData;
RecordsPerPage: Integer = 10;
AllocRecordsBy: Integer = 1000
);
destructor Destroy; override;
procedure CreateTable(
Cursor: TABSCursor;
FieldDefs: TABSFieldDefs;
IndexDefs: TABSIndexDefs;
ConstraintDefs: TABSConstraintDefs
); override;
procedure DeleteTable(Cursor: TABSCursor; DesignMode: Boolean = False); override;
procedure EmptyTable(Cursor: TABSCursor); override;
procedure OpenTable(Cursor: TABSCursor); override;
procedure CloseTable(Cursor: TABSCursor); override;
procedure AddIndex(IndexDef: TABSIndexDef; Cursor: TABSCursor); override;
procedure DeleteIndex(IndexID: TABSObjectID; Cursor: TABSCursor); override;
function InsertRecord(var Cursor: TABSCursor): Boolean; override;
function DeleteRecord(Cursor: TABSCursor): Boolean; override;
function UpdateRecord(Cursor: TABSCursor): Boolean; override;
function InternalGetRecordCount(Cursor: TABSCursor): TABSRecordNo; override;
// move cursor to specified position and set current record id in cursor
procedure InternalSetRecNo(Cursor: TABSCursor; RecNo: TABSRecordNo); override;
// get current record position from cursor
function InternalGetRecNo(Cursor: TABSCursor): TABSRecordNo; override;
//---------------------------------------------------------------------------
// BLOB methods
//---------------------------------------------------------------------------
procedure WriteBLOBFieldToRecordBuffer(
Cursor: TABSCursor;
FieldNo: Integer;
BLOBStream: TABSStream
); override;
function InternalCreateBlobStream(
Cursor: TABSCursor;
ToInsert: Boolean;
FieldNo: Integer;
OpenMode: TABSBLOBOpenMode
): TABSStream; override;
procedure GetDirectBlobData(
Cursor: TABSCursor;
FieldNo: Integer;
RecordBuffer: TABSRecordBuffer;
var BLOBDescriptor: TABSPartialTemporaryBLOBDescriptor;
var pBlobData: PChar); override;
procedure SetDirectBlobData(
Cursor: TABSCursor;
FieldNo: Integer;
RecordBuffer: TABSRecordBuffer;
var BLOBDescriptor: TABSPartialTemporaryBLOBDescriptor;
var pBlobData: PChar); override;
procedure FreeDirectBlobData(
Cursor: TABSCursor;
FieldNo: Integer;
RecordBuffer: TABSRecordBuffer;
var BLOBDescriptor: TABSPartialTemporaryBLOBDescriptor;
var pBlobData: PChar); override;
end; // TABSTemporaryTableData
implementation
uses
// AbsoluteDatabase units
ABSLocalEngine,
ABSMemEngine;
////////////////////////////////////////////////////////////////////////////////
//
// TABSTemporaryRecordManager
//
////////////////////////////////////////////////////////////////////////////////
//------------------------------------------------------------------------------
// save temporary page
//------------------------------------------------------------------------------
procedure TABSTemporaryRecordManager.SaveTempPage;
var WriteBytes,WriteSize: Integer;
OldPos,NewPos: Int64;
begin
if (FTempPageRecordCount > 0) then
begin
if (FTempPageRecordCount > FRecordsPerPage) then
raise EABSException.Create(10126,ErrorLInvalidRecordCount,
[FTempPageRecordCount,FRecordsPerPage]);
OldPos := FTempPageFile.Position;
NewPos := Int64(FRecordCount - FMaxCachedRecordCount - FTempPageRecordCount) *
Int64(FRecordBufferSize);
FTempPageFile.Position := NewPos;
if (FTempPageFile.Position <> NewPos) then
raise EABSException.Create(10128,ErrorLCannotSetPosition,
[NewPos,OldPos,FTempPageFile.Size]);
OldPos := FTempPageFile.Position;
WriteSize := FTempPageRecordCount * FRecordBufferSize;
WriteBytes := FTempPageFile.Write(FTempPage^,WriteSize);
if (WriteBytes <> WriteSize) then
raise EABSException.Create(10125,ErrorLWriteToStream,
[OldPos,FTempPageFile.Size,WriteSize,WriteBytes]);
FTempPageRecordCount := 0;
end;
end; // SaveTempPage
//------------------------------------------------------------------------------
// read record
//------------------------------------------------------------------------------
function TABSTemporaryRecordManager.ReadRecord(
var RecordBuffer: TABSRecordBuffer;
RecordID: TABSRecordNo
): Boolean;
var ReadBytes: Integer;
OldPos,NewPos: Int64;
begin
if (FDisableTempFiles or (RecordID < FMaxCachedRecordCount)) then
begin
try
Move((FCache + RecordID * FRecordBufferSize)^,RecordBuffer^,
FRecordBufferSize);
except
raise EABSException.Create(10127,ErrorLRetreivingRecord);
end;
Result := True;
end
else
begin
SaveTempPage;
OldPos := FTempPageFile.Position;
NewPos := Int64(RecordID - FMaxCachedRecordCount) *
Int64(FRecordBufferSize);
FTempPageFile.Position := NewPos;
if (FTempPageFile.Position <> NewPos) then
raise EABSException.Create(10129,ErrorLCannotSetPosition,
[NewPos,OldPos,FTempPageFile.Size]);
OldPos := FTempPageFile.Position;
ReadBytes := FTempPageFile.Read(RecordBuffer^,FRecordBufferSize);
if (ReadBytes <> FRecordBufferSize) then
raise EABSException.Create(10130,ErrorLCannotReadFromStream,
[OldPos,FTempPageFile.Size,FRecordBufferSize,ReadBytes]);
Result := True;
end;
end; // ReadRecord
//------------------------------------------------------------------------------
// return result for attempt of getting record relatively to first position
// and set RecordID to new record ID
//------------------------------------------------------------------------------
function TABSTemporaryRecordManager.GetRecordFromFirstPosition(
GetRecordMode: TABSGetRecordMode;
var RecordID: TABSRecordNo
): TABSGetRecordResult;
begin
Result := grrError;
case GetRecordMode of
grmPrior:
begin
Result := grrBOF;
end;
grmCurrent:
begin
Result := grrError;
end;
grmNext:
begin
RecordID := 0;
Result := grrOK;
end;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -