📄 absbtree.pas
字号:
property PagePrefixSize: Word read GetPagePrefixSize write SetPagePrefixSize;
// calculated
property EntrySize: Integer read GetEntrySize;
property ReferenceSize: Integer read GetReferenceSize;
property EntriesOffset: Integer read GetEntriesOffset;
property SuffixPtrSize: Integer read GetSuffixPtrSize;
property KeyRef: TABSBTreeKeyRef read LKeyRef write LKeyRef;
end;
////////////////////////////////////////////////////////////////////////////////
//
// TABSBTreePageController
//
////////////////////////////////////////////////////////////////////////////////
TABSBTreePageController = class(TObject)
protected
FPage: TABSBTreePage;
function GetKeyRef: TABSBTreeKeyRef;
function CanAddEntry: Boolean;
function IsOverflow: Boolean;
function CanUnderflow: Boolean;
function CanMergeWithPage(Page: TABSBTreePage): Boolean;
procedure EnlargePageBuffer;
function CompareKeys(MayUseFullKeys: Boolean;
SessionID: TABSSessionID;
Key1: PChar; Key2Index: Word): Integer;
function CompareReferences(Reference1: PChar; Reference2Index: Word): Integer;
function CompareEntries(MayUseFullKeys: Boolean;
SessionID: TABSSessionID;
Key1: PChar; Reference1: PChar;
Entry2Index: Word): Integer; virtual; abstract;
function GetKeyPosition(
MayUseFullKeys: Boolean;
SessionID: TABSSessionID;
Key: PChar;
Reference: PChar; // if finding entry
StartPosition: Integer = 0;
PositionType: PABSKeyPathPosition = nil;
SearchType: TABSKeySearchType = kstAny
): Word;
procedure InsertEntry(Key, Reference: PChar; Position: Integer);
procedure DeleteEntry(Position: Integer);
procedure RootSplit(SessionID: TABSSessionID; KeyPath: TABSKeyPath);
procedure NonRootSplit(SessionID: TABSSessionID; KeyPath: TABSKeyPath);
function TryMergeWithPage(
SessionID: TABSSessionID;
MergePageNo: TABSPageNo;
KeyPath: TABSKeyPath
): Boolean;
function TryMerge(SessionID: TABSSessionID; KeyPath: TABSKeyPath): Boolean;
procedure MergeWithLeftPage(
SessionID: TABSSessionID;
LeftPage: TABSBTreePage;
KeyPath: TABSKeyPath
);
procedure MergeWithRightPage(
SessionID: TABSSessionID;
RightPage: TABSBTreePage;
KeyPath: TABSKeyPath
);
public
constructor Create(aPage: TABSBTreePage);
procedure InsertLeafEntry(SessionID: TABSSessionID; Key, Reference: PChar; KeyPath: TABSKeyPath); virtual; abstract;
function DeleteLeafEntry(SessionID: TABSSessionID; Key, Reference: PChar; KeyPath: TABSKeyPath): Boolean; virtual; abstract;
procedure FreeAllPages(SessionID: TABSSessionID; KeepRootPage: Boolean); virtual; abstract;
procedure CheckIntegrity(SessionID: TABSSessionID; KeyPath: TABSKeyPath); virtual; abstract;
function FindEntry(
SessionID: TABSSessionID;
Key: PChar;
Reference: PChar;
Position: TABSKeyPath
): Boolean; virtual; abstract;
function GetFirstPosition(SessionID: TABSSessionID; Position: TABSKeyPath): Boolean; virtual; abstract;
function GetLastPosition(SessionID: TABSSessionID; Position: TABSKeyPath): Boolean; virtual; abstract;
function FindByCondition(
SessionID: TABSSessionID;
First: Boolean; // if False => Last
Key: PChar;
Operator: TABSSearchCondition;
Position: TABSKeyPath
): Boolean; virtual; abstract;
function GetPKey(KeyPosition: Integer): PChar;
function GetPReference(RefPosition: Integer): PChar;
procedure GetFirstKey(SessionID: TABSSessionID; Key: PChar); virtual; abstract;
procedure GetLastKey(SessionID: TABSSessionID; Key: PChar); virtual; abstract;
procedure GetFirstEntry(SessionID: TABSSessionID; Key, Reference: PChar); virtual; abstract;
procedure GetLastEntry(SessionID: TABSSessionID; Key, Reference: PChar); virtual; abstract;
procedure Split(SessionID: TABSSessionID; KeyPath: TABSKeyPath);
property KeyRef: TABSBTreeKeyRef read GetKeyRef;
end;// TABSBTreePageController
////////////////////////////////////////////////////////////////////////////////
//
// TABSBTreeLeafController
//
////////////////////////////////////////////////////////////////////////////////
TABSBTreeLeafController = class(TABSBTreePageController)
private
function FindEntryOnPage(SessionID: TABSSessionID;
Key, Reference: PChar; var EntryNo: Integer): Boolean;
function FindFirstByCondition(
SessionID: TABSSessionID;
Key: PChar;
Operator: TABSSearchCondition;
Position: TABSKeyPath
): Boolean;
function FindLastByCondition(
SessionID: TABSSessionID;
Key: PChar;
Operator: TABSSearchCondition;
Position: TABSKeyPath
): Boolean;
protected
function CompareEntries(MayUseFullKeys: Boolean;
SessionID: TABSSessionID;
Key1: PChar; Reference1: PChar;
Entry2Index: Word): Integer; override;
public
procedure InsertLeafEntry(SessionID: TABSSessionID; Key, Reference: PChar; KeyPath: TABSKeyPath); override;
function DeleteLeafEntry(SessionID: TABSSessionID; Key, Reference: PChar; KeyPath: TABSKeyPath): Boolean; override;
procedure GetFirstKey(SessionID: TABSSessionID; Key: PChar); override;
procedure GetLastKey(SessionID: TABSSessionID; Key: PChar); override;
procedure GetFirstEntry(SessionID: TABSSessionID; Key, Reference: PChar); override;
procedure GetLastEntry(SessionID: TABSSessionID; Key, Reference: PChar); override;
function FindEntry(
SessionID: TABSSessionID;
Key: PChar;
Reference: PChar;
Position: TABSKeyPath
): Boolean; override;
function GetFirstPosition(SessionID: TABSSessionID; Position: TABSKeyPath): Boolean; override;
function GetLastPosition(SessionID: TABSSessionID; Position: TABSKeyPath): Boolean; override;
function FindByCondition(
SessionID: TABSSessionID;
First: Boolean; // if False => Last
Key: PChar;
Operator: TABSSearchCondition;
Position: TABSKeyPath
): Boolean; override;
procedure FreeAllPages(SessionID: TABSSessionID; KeepRootPage: Boolean); override;
procedure CheckIntegrity(SessionID: TABSSessionID; KeyPath: TABSKeyPath); override;
end;// TABSBTreeLeafController
////////////////////////////////////////////////////////////////////////////////
//
// TABSBTreeNodeController
//
////////////////////////////////////////////////////////////////////////////////
TABSBTreeNodeController = class(TABSBTreePageController)
private
function FindByConditionOnOneOfPages(
SessionID: TABSSessionID;
First: Boolean; // if False => Last
StartEntryNo: Integer;
EndEntryNo: Integer;
Key: PChar;
Operator: TABSSearchCondition;
Position: TABSKeyPath
): Boolean;
function FindEntryOnOneOfPages(
SessionID: TABSSessionID;
StartEntryNo: Integer;
EndEntryNo: Integer;
Key: PChar;
Reference: PChar;
Position: TABSKeyPath
): Boolean;
procedure GetChildPagesToCheck(
SessionID: TABSSessionID;
Key: PChar;
SearchCondition: TABSSearchCondition;
var StartEntryNo: Integer;
var EndEntryNo: Integer
);
procedure DecreaseTreeDepth(SessionID: TABSSessionID);
protected
function CompareEntries(MayUseFullKeys: Boolean;
SessionID: TABSSessionID;
Key1: PChar; Reference1: PChar;
Entry2Index: Word): Integer; override;
public
procedure InsertLeafEntry(SessionID: TABSSessionID; Key, Reference: PChar; KeyPath: TABSKeyPath); override;
procedure InsertNodeEntry(SessionID: TABSSessionID; Key, Reference: PChar; KeyPath: TABSKeyPath);
function DeleteLeafEntry(SessionID: TABSSessionID; Key, Reference: PChar; KeyPath: TABSKeyPath): Boolean; override;
procedure DeleteNodeEntry(
SessionID: TABSSessionID;
KeyPath: TABSKeyPath;
MergeWithLeft: Boolean
);
procedure GetFirstKey(SessionID: TABSSessionID; Key: PChar); override;
procedure GetLastKey(SessionID: TABSSessionID; Key: PChar); override;
procedure GetFirstEntry(SessionID: TABSSessionID; Key, Reference: PChar); override;
procedure GetLastEntry(SessionID: TABSSessionID; Key, Reference: PChar); override;
function FindEntry(
SessionID: TABSSessionID;
Key: PChar;
Reference: PChar;
Position: TABSKeyPath
): Boolean; override;
function GetFirstPosition(SessionID: TABSSessionID; Position: TABSKeyPath): Boolean; override;
function GetLastPosition(SessionID: TABSSessionID; Position: TABSKeyPath): Boolean; override;
function FindByCondition(
SessionID: TABSSessionID;
First: Boolean; // if False => Last
Key: PChar;
Operator: TABSSearchCondition;
Position: TABSKeyPath
): Boolean; override;
procedure FreeAllPages(SessionID: TABSSessionID; KeepRootPage: Boolean); override;
procedure CheckIntegrity(SessionID: TABSSessionID; KeyPath: TABSKeyPath); override;
end;// TABSBTreeNodeController
////////////////////////////////////////////////////////////////////////////////
//
// TABSBTreeRecordIndex
//
////////////////////////////////////////////////////////////////////////////////
TABSBTreeSearchInfo = packed record
GoForward: Boolean;
IsFilled: Boolean;
EndKeyPath: TABSKeyPath;
CurrentKeyPath: TABSKeyPath;
end;
PABSBTreeSearchInfo = ^TABSBTreeSearchInfo;
TABSBTreeRecordIndex = class (TABSIndex)
private
FRootPage: TABSBTreePage;
FKeyRef: TABSRecordKeyRef;
function AddIndexPage(SessionID: TABSSessionID): TABSBTreePage;
function GetIndexPage(SessionID: TABSSessionID; PageNo: TABSPageNo): TABSBTreePage;
procedure PutIndexPage(Page: TABSBTreePage);
function GetRecordID(SessionID: TABSSessionID; Position: TABSKeyPath): TABSRecordID;
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; Restart, GoForward: Boolean; Position: TABSKeyPath): Boolean;
public
constructor Create(aIndexManager: TABSBaseIndexManager);
destructor Destroy; override;
procedure CreateIndex(Cursor: TABSCursor; aIndexDef: TABSIndexDef); override;
procedure DropIndex(SessionID: TABSSessionID); override;
procedure EmptyIndex(SessionID: TABSSessionID); override;
procedure OpenIndex(aIndexDef: TABSIndexDef); override;
procedure RebuildTemporaryIndex(Cursor: TABSCursor); override;
procedure GetRecordBuffer(
SessionID: TABSSessionID;
var NavigationInfo: TABSNavigationInfo;
IndexPositionCache: TABSIndexPositionCache;
TableState: Integer
); override;
procedure GetClosestRecordBuffer(
SessionID: TABSSessionID;
var NavigationInfo: TABSNavigationInfo;
IndexPositionCache: TABSIndexPositionCache;
TableState: Integer
); override;
function CreateIndexPosition: TABSIndexPosition; override;
procedure FreeIndexPosition(var IndexPosition: TABSIndexPosition); override;
function GetIndexPosition(
SessionID: TABSSessionID;
RecordID: TABSRecordID;
RecordBuffer: TABSRecordBuffer;
IndexPosition: TABSIndexPosition
): Boolean; override;
// return 0, 1, -1 if (Pos1 = Pos2), (Pos1 > Pos2), (Pos1 < Pos2)
function CompareRecordPositionsInIndex(
RecordPosition1: TABSIndexPosition;
RecordPosition2: TABSIndexPosition
): Integer; override;
function GetRecNoByRecordID(
SessionID: TABSSessionID;
RecordID: TABSRecordID;
RecordBuffer: TABSRecordBuffer
): TABSRecordNo; override;
function GetRecordIDByRecNo(
SessionID: TABSSessionID;
RecNo: TABSRecordNo
): TABSRecordID; override;
procedure ApplyDistinctToRecordBitmap(
SessionID: TABSSessionID;
Bitmap: TABSRecordBitmap;
DistinctFieldCount: Integer
); override;
function CreateSearchInfo: TABSSearchInfo; override;
procedure FreeSearchInfo(SearchInfo: TABSSearchInfo); override;
private
function GetCurrentPosition(
SessionID: TABSSessionID;
Restart: Boolean;
GoForward: Boolean;
StartScanCondition: TABSScanSearchCondition;
RecordBuffer: TABSRecordBuffer;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -