📄 absbtree.pas
字号:
RecordID: TABSRecordID;
SearchInfo: TABSSearchInfo
): Boolean;
function GetEndPosition(
SessionID: TABSSessionID;
GoForward: Boolean;
StartScanCondition: TABSScanSearchCondition;
EndScanCondition: TABSScanSearchCondition;
SearchInfo: TABSSearchInfo
): Boolean;
public
function FindRecord(
SessionID: TABSSessionID;
Restart: Boolean;
GoForward: Boolean;
StartScanCondition: TABSScanSearchCondition;
EndScanCondition: TABSScanSearchCondition;
RecordBuffer: TABSRecordBuffer;
var RecordID: TABSRecordID;
SearchInfo: TABSSearchInfo
): Boolean; override;
// return 0 if record buffers are equal in this index
// return 1 if Buffer1 is higher than Buffer 2 (Pos1 > Pos2)
// return -1 if Buffer1 is lower than Buffer 2 (Pos1 < Pos2)
function CompareRecordBuffersByIndex(
Buffer1: TABSRecordBuffer;
Buffer2: TABSRecordBuffer;
IndexFieldCount: Integer
): Integer; override;
// return 0 if conditions are equal in this index
// return 1 if Condition1 is higher than Condition2
// return -1 if Condition1 is lower than Condition2
function CompareConditions(
Condition1: TABSScanSearchCondition;
Condition2: TABSScanSearchCondition
): Integer; override;
// approximate record count between range conditions
function GetApproxRangeRecordCount(
SessionID: TABSSessionID;
TableRecordCount: TABSRecordNo;
RangeCondition1: TABSScanSearchCondition;
RangeCondition2: TABSScanSearchCondition
): TABSRecordNo; override;
function CanInsertRecord(
SessionID: TABSSessionID;
RecordBuffer: TABSRecordBuffer
): Boolean; override;
function CanUpdateRecord(
SessionID: TABSSessionID;
OldRecordBuffer, NewRecordBuffer: TABSRecordBuffer
): Boolean; override;
procedure InsertRecord(Cursor: TABSCursor); override;
procedure UpdateRecord(Cursor: TABSCursor; BeforeNewRecordIsStored: Boolean); override;
procedure DeleteRecord(Cursor: TABSCursor); override;
function GetMaxEntriesPerPage: Integer; override;
procedure GetRecordIDByIndexPosition(SessionID: TABSSessionID; IndexPos: TABSIndexPosition; var RecordID: TABSRecordID); override;
property KeyRef: TABSRecordKeyRef read FKeyRef;
end; // TABSBTreeRecordIndex
////////////////////////////////////////////////////////////////////////////////
//
// TABSBTreePageIndex
//
////////////////////////////////////////////////////////////////////////////////
TABSBTreePageIndex = class (TObject)
protected
FRootPageNo: TABSPageNo;
FKeyRef: TABSPageKeyRef;
LPageManager: TABSPageManager;
FMaxRecordsOnPage: Integer;
function AddIndexPage(SessionID: TABSSessionID): TABSBTreePage;
function GetIndexPage(SessionID: TABSSessionID; PageNo: TABSPageNo): TABSBTreePage;
procedure PutIndexPage(Page: TABSBTreePage);
function GetFirstPosition(SessionID: TABSSessionID; Position: TABSKeyPath): Boolean;
function GetLastPosition(SessionID: TABSSessionID; Position: TABSKeyPath): Boolean;
function GetNextPosition(SessionID: TABSSessionID; Position: TABSKeyPath): Boolean;
function GetPriorPosition(SessionID: TABSSessionID; Position: TABSKeyPath): Boolean;
function GetPosition(SessionID: TABSSessionID; PageNo: TABSPageNo; Position: TABSKeyPath): Boolean;
function GetPageValue(SessionID: TABSSessionID; Position: TABSKeyPath): Word;
procedure SetPageValue(SessionID: TABSSessionID; Position: TABSKeyPath; Value: Word);
function GetPageNo(SessionID: TABSSessionID; Position: TABSKeyPath): TABSPageNo;
function CanAddNewItem(OldValue: Integer; NewItemSize: Integer): Boolean; virtual; abstract;
function FindPageForNewItem(SessionID: TABSSessionID; ItemSize: Integer; var PageNo: TABSPageNo): Boolean;
procedure AddPageItem(SessionID: TABSSessionID; ItemSize: Integer; PageNo: TABSPageNo);
procedure DeletePageItem(SessionID: TABSSessionID; ItemSize: Integer; PageNo: TABSPageNo; NewItemCount: Integer);
public
constructor Create(PageManager: TABSPageManager);
destructor Destroy; override;
procedure CreateIndex(SessionID: TABSSessionID);
procedure DropIndex(SessionID: TABSSessionID);
procedure EmptyIndex(SessionID: TABSSessionID);
procedure OpenIndex(RootPageNo: TABSPageNo);
property KeyRef: TABSPageKeyRef read FKeyRef;
property RootPageNo: TABSPageNo read FRootPageNo;
end; // TABSBTreePageIndex
////////////////////////////////////////////////////////////////////////////////
//
// TABSBTreeRecordPageIndex
//
////////////////////////////////////////////////////////////////////////////////
TABSBTreeRecordPageIndex = class (TABSBTreePageIndex)
private
FMaxRecordsOnPage: Integer;
function GetPageRecordCount(SessionID: TABSSessionID; Position: TABSKeyPath): Word;
protected
function CanAddNewItem(OldValue: Integer; NewItemSize: Integer): Boolean; override;
public
function FindPageForNewRecord(SessionID: TABSSessionID; var PageNo: TABSPageNo): Boolean;
procedure AddRecord(SessionID: TABSSessionID; PageNo: TABSPageNo; AddCount: Integer = 1);
procedure DeleteRecord(SessionID: TABSSessionID; PageNo: TABSPageNo; NewItemCount: Integer);
function GetFirstRecordPage(SessionID: TABSSessionID; var PageNo: TABSPageNo): Boolean;
function GetLastRecordPage(SessionID: TABSSessionID; var PageNo: TABSPageNo): Boolean;
function GetNextRecordPage(SessionID: TABSSessionID; CurrentPageNo: TABSPageNo; var NextPageNo: TABSPageNo): Boolean;
function GetPriorRecordPage(SessionID: TABSSessionID; CurrentPageNo: TABSPageNo; var PriorPageNo: TABSPageNo): Boolean;
procedure GetRecordByRecNo(SessionID: TABSSessionID; RecNo: TABSRecordNo; var PageNo: TABSPageNo; var RecNoOnPage: Integer);
procedure GetRecNoByRecord(SessionID: TABSSessionID; PageNo: TABSPageNo; RecNoOnPage: Integer; var RecNo: TABSRecordNo);
procedure Validate(SessionID: TABSSessionID; StoredRecordCount: Integer);
property MaxRecordsOnPage: Integer read FMaxRecordsOnPage write FMaxRecordsOnPage;
end; // TABSBTreeRecordPageIndex
////////////////////////////////////////////////////////////////////////////////
//
// TABSBTreeBlobPageIndex
//
////////////////////////////////////////////////////////////////////////////////
TABSBTreeBlobPageIndex = class (TABSBTreePageIndex)
protected
function CanAddNewItem(OldValue: Integer; NewItemSize: Integer): Boolean; override;
public
function FindPageForNewBlob(SessionID: TABSSessionID; BlobSize: Integer; var PageNo: TABSPageNo): Boolean;
procedure AddBlob(SessionID: TABSSessionID; BlobSize: Integer; PageNo: TABSPageNo);
procedure DeleteBlob(SessionID: TABSSessionID; BlobSize: Integer; PageNo: TABSPageNo);
function GetBlobPageAllocatedSpace(SessionID: TABSSessionID; PageNo: TABSPageNo): Integer;
end; // TABSBTreeBlobPageIndex
implementation
uses ABSLocalEngine;
////////////////////////////////////////////////////////////////////////////////
//
// TABSBTreeKeyPath
//
////////////////////////////////////////////////////////////////////////////////
//------------------------------------------------------------------------------
// constructor
//------------------------------------------------------------------------------
constructor TABSKeyPath.Create;
begin
Clear;
end;// Create
//------------------------------------------------------------------------------
// Clear
//------------------------------------------------------------------------------
procedure TABSKeyPath.Clear;
begin
Count := 0;
ItemNo := 0;
end;// Clear
//------------------------------------------------------------------------------
// Assign
//------------------------------------------------------------------------------
procedure TABSKeyPath.Assign(KeyPath: TABSKeyPath);
begin
Count := KeyPath.Count;
ItemNo := KeyPath.ItemNo;
PositionType := KeyPath.PositionType;
IndexState := KeyPath.IndexState;
Move(KeyPath.Items[0], Items[0], Count * sizeof(Items[0]));
end;// Assign
//------------------------------------------------------------------------------
// AddItem
//------------------------------------------------------------------------------
procedure TABSKeyPath.AddItem(aPageNo: TABSPageNo; aEntryNo, aEntryCount: Integer);
begin
Items[ItemNo].PageNo := aPageNo;
Items[ItemNo].EntryNo := aEntryNo;
Items[ItemNo].EntryCount := aEntryCount;
Inc(ItemNo);
Inc(Count);
end;// AddItem
//------------------------------------------------------------------------------
// DeleteLastItem
//------------------------------------------------------------------------------
procedure TABSKeyPath.DeleteLastItem;
begin
Dec(ItemNo);
Dec(Count);
end;// DeleteLastItem
//------------------------------------------------------------------------------
// IncLevel
//------------------------------------------------------------------------------
procedure TABSKeyPath.IncLevel;
begin
Inc(ItemNo);
end;// IncLevel
//------------------------------------------------------------------------------
// DecLevel
//------------------------------------------------------------------------------
procedure TABSKeyPath.DecLevel;
begin
Dec(ItemNo);
end;// DecLevel
//------------------------------------------------------------------------------
// GetCurrentPageNo
//------------------------------------------------------------------------------
function TABSKeyPath.GetCurrentPageNo: TABSPageNo;
begin
Result := Items[ItemNo].PageNo;
end;// GetCurrentPageNo
//------------------------------------------------------------------------------
// SetCurrentPageNo
//------------------------------------------------------------------------------
procedure TABSKeyPath.SetCurrentPageNo(Value: TABSPageNo);
begin
Items[ItemNo].PageNo := Value;
end;// SetCurrentPageNo
//------------------------------------------------------------------------------
// PageExists
//------------------------------------------------------------------------------
function TABSKeyPath.PageExists(aPageNo: TABSPageNo): Boolean;
var
i: Integer;
begin
Result := False;
for i := 0 to Count-1 do
if (Items[i].PageNo = aPageNo) then
begin
Result := True;
break;
end;
end;// PageExists
//------------------------------------------------------------------------------
// return 0, 1, -1 if (Self = aKeyPath), (Self > aKeyPath), (Self < aKeyPath)
//------------------------------------------------------------------------------
function TABSKeyPath.Compare(aKeyPath: TABSKeyPath): Integer;
var
i: Integer;
begin
if (Count <> aKeyPath.Count) then
raise EABSException.Create(20051, ErrorAInvalidIndexKeyPath);
Result := 0;
for i := 0 to Count-1 do
begin
if (Items[i].PageNo <> aKeyPath.Items[i].PageNo) then
raise EABSException.Create(20052, ErrorAInvalidIndexKeyPath);
if (Items[i].EntryNo < aKeyPath.Items[i].EntryNo) then
begin
Result := -1;
break;
end
else
if (Items[i].EntryNo > aKeyPath.Items[i].EntryNo) then
begin
Result := 1;
break;
end;
end;
end;// Compare
//------------------------------------------------------------------------------
// GetApproxRecNoInPercents
//------------------------------------------------------------------------------
function TABSKeyPath.GetApproxRecNoInPercents: double;
var
i: Integer;
ApproxRecNo: TABSRecordNo;
ApproxRecCount: TABSRecordNo;
begin
ApproxRecNo := 0;
ApproxRecCount := 1;
for i := Count-1 downto 0 do
begin
ApproxRecNo := Items[i].EntryNo * ApproxRecCount + ApproxRecNo;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -