TeeBI supports powerful relational data structures through master-detail relationships. These relationships enable you to link columns together, creating foreign key constraints and efficiently navigating between related data sets.
TeeBI automatically creates an index for efficient lookups between master and detail records:
var Orders: TDataItem; OrderCustID: TDataItem;begin // After setting Master property... OrderCustID.Master := CustID; // Create the index for fast lookups OrderCustID.CreateMasterIndex; // The index is stored in IMaster.Index // IMaster.Index[0] contains the master row for detail row 0end;
function GetMasterRow(const DetailRow: Integer): Integer;begin if OrderCustID.IMaster.Index <> nil then Result := OrderCustID.IMaster.Index[DetailRow] else Result := -1;end;var DetailRow, MasterRow: Integer; CustomerName: String;begin DetailRow := 0; // First order MasterRow := GetMasterRow(DetailRow); if MasterRow >= 0 then begin CustomerName := Customers['Name'].TextData[MasterRow]; ShowMessage('Customer: ' + CustomerName); end;end;
Use the TMasterDetail.GetIndex method to find all detail rows for a master row:
var MasterRow: Integer; DetailRows: TNativeIntArray; I: Integer;begin MasterRow := 0; // First customer // Get all orders for this customer DetailRows := OrderCustID.IMaster.GetIndex(CustID, MasterRow); ShowMessage(Format('Customer has %d orders', [Length(DetailRows)])); for I := 0 to High(DetailRows) do begin ShowMessage( Format('Order %d: Amount = %f', [Orders['OrderID'].Int32Data[DetailRows[I]], Orders['Amount'].DoubleData[DetailRows[I]]] ) ); end;end;
function TDataItem.HasMaster: Boolean;begin Result := (IMaster.Data <> nil) or (IMaster.Origin <> '');end;// Usage:if OrderCustID.HasMaster then ShowMessage('This column has a master relationship');
TeeBI can automatically detect relationships based on matching column names and types:
// When loading from databases or files, TeeBI will automatically// create relationships if:// 1. Column names match (e.g., "CustomerID" in both tables)// 2. Data types are compatible// 3. Values in detail exist in master (referential integrity)
The TDetailData class provides a convenient way to work with detail records:
type TDetailData = class(TDataItem) public Detail: TDataItem; constructor Create(const ADetail: TDataItem; const AName: String); end;var CustomerOrders: TDetailData;begin // Create a detail data item for a specific relationship CustomerOrders := TDetailData.Create(Orders, 'CustomerOrders'); CustomerOrders.Detail := Orders;end;
When a detail row references a master value that doesn’t exist, the index contains -1:
var MasterRow: Integer;begin MasterRow := OrderCustID.IMaster.Index[DetailRow]; if MasterRow = -1 then ShowMessage('Orphan record: no matching master') else ShowMessage('Valid relationship');end;