📄 absrelationalalgebra.pas
字号:
begin
FResultDataset.Close;
try
if (TABSTable(FResultDataset).Temporary) then
TABSTable(FResultDataset).DeleteTable;
except
end;
FResultDataset.Free;
end;
if (FResultFieldsOrder <> nil) then
FResultFieldsOrder.Free;
if (FLeftAO <> nil) then
FLeftAO.Free;
if (FRightAO <> nil) then
FRightAO.Free;
if (FFilterExpr <> nil) then
TABSExpression(FFilterExpr).Free;
FreeResultIndexLists;
FValue.Free;
inherited Destroy;
end; // Destroy
//------------------------------------------------------------------------------
// getting all result records
//------------------------------------------------------------------------------
procedure TABSAO.Execute(IsRootAO: Boolean; ParentQueryAO: TABSAO; ParentCursor: TABSCursor);
var
p: Pointer;
IsCreated: Boolean;
begin
FIsRootAO := IsRootAO;
// filter
if (not FIsAOTable) then
if (FFilterExpr <> nil) then
TABSExpression(FFilterExpr).AssignAO(Self, ParentQueryAO, ParentCursor);
if (FLeftAO <> nil) then
FLeftAO.Execute(False, ParentQueryAO, ParentCursor);
if (FRightAO <> nil) then
FRightAO.Execute(False, ParentQueryAO, ParentCursor);
// optimize join
if ((FLeftAO <> nil) and (FRightAO <> nil)) then
if (Self is TABSAOJoin) then
if (TABSAOJoin(Self).FJoinType in [ajtInner,ajtFullOuter]) then
// bug-fix: 4.84 - speed up join with filtered table when LeftAO has much more records than RightAO
// if (TABSTable(FLeftAO.ResultDataset).Handle.SQLFilterExpression = nil) and
// (TABSTable(FRightAO.ResultDataset).Handle.SQLFilterExpression = nil) then
if (FRightAO.ResultDataset.RecordCount < FLeftAO.ResultDataset.RecordCount) then
begin
p := FLeftAO;
FLeftAO := FRightAO;
FRightAO := p;
p := TABSAOJoin(Self).FFields1;
TABSAOJoin(Self).FFields1 := TABSAOJoin(Self).FFields2;
TABSAOJoin(Self).FFields2 := p;
end;
if (FIsAOGroupBy) then
if (not TABSAOGroupBy(Self).FAllFields) then
if (TABSAOGroupBy(Self).FTempDataset = nil) and (FLeftAO <> nil) then
begin
TABSAOGroupBy(Self).FTempDataset := TABSTable.Create(nil);
TABSTable(TABSAOGroupBy(Self).FTempDataset).DatabaseName :=
TABSTable(FLeftAO.FResultDataset).DatabaseName;
TABSTable(TABSAOGroupBy(Self).FTempDataset).SessionName :=
TABSTable(FLeftAO.FResultDataset).SessionName;
TABSTable(TABSAOGroupBy(Self).FTempDataset).TableName :=
TABSTable(FLeftAO.FResultDataset).TableName;
TABSTable(TABSAOGroupBy(Self).FTempDataset).InMemory :=
TABSTable(FLeftAO.FResultDataset).InMemory;
TABSTable(TABSAOGroupBy(Self).FTempDataset).Temporary :=
TABSTable(FLeftAO.FResultDataset).Temporary;
TABSTable(TABSAOGroupBy(Self).FTempDataset).ReadOnly := True;
try
TABSAOGroupBy(Self).FTempDataset.Open;
except
raise EABSException.Create(10304,ErrorLCannotOpenTable,
[TABSTable(TABSAOGroupBy(Self).FTempDataset).TableName,
Word(TABSTable(TABSAOGroupBy(Self).FTempDataset).InMemory)]);
end;
if (TABSTable(FLeftAO.FResultDataset).IsDistinctApplied) then
TABSTable(TABSAOGroupBy(Self).FTempDataset).ApplyDistinct(TABSTable(FLeftAO.FResultDataset))
else
TABSTable(TABSAOGroupBy(Self).FTempDataset).IndexName :=
TABSTable(FLeftAo.FResultDataset).IndexName;
end; // FIsAOGroupBy
if (FTopRowCount > 0) and (FResultIndexFieldsList <> nil) and (FLeftAO <> nil) then
begin
TABSTable(FLeftAo.FResultDataset).IndexName :=
TABSTable(FLeftAo.FResultDataset).FindOrCreateIndex(
FResultIndexFieldsList,FResultIndexAscDescFieldsList,FResultIndexCaseInsFieldsList,IsCreated)
end;
if ((FLeftAO <> nil) or (FRightAO <> nil)) then
DoMaterialize;
if (FResultIndexFieldsList <> nil) then
InternalSetIndex(True);
end;// Execute
//------------------------------------------------------------------------------
// LockTables
//------------------------------------------------------------------------------
function TABSAO.LockTables: Boolean;
begin
if (FIsAOTable) then
begin
if (ResultDataset.Active) then
Result := TABSTable(ResultDataset).Handle.LockTable(ltS,
SelectTrialTableLockRetries, SelectTrialTableLockDelay)
else
Result := False;
FIsLocked := Result;
end
else
begin
Result := True;
if (FLeftAO <> nil) then
Result := Result and FLeftAO.LockTables;
if (FRightAO <> nil) then
if (Result) then
Result := Result and FRightAO.LockTables;
end;
end;// LockTables
//------------------------------------------------------------------------------
// UnlockTables
//------------------------------------------------------------------------------
function TABSAO.UnlockTables: Boolean;
begin
if (FIsAOTable) then
begin
if (FIsLocked) then
if (ResultDataset.Active) then
begin
Result := TABSTable(ResultDataset).Handle.UnlockTable(ltS, True);
FIsLocked := not Result;
end
else
Result := False
else
Result := True;
end
else
begin
Result := True;
if (FLeftAO <> nil) then
Result := Result and FLeftAO.UnlockTables;
if (FRightAO <> nil) then
Result := Result and FRightAO.UnlockTables;
end;
end;// UnlockTables
//------------------------------------------------------------------------------
// OpenTables
//------------------------------------------------------------------------------
function TABSAO.OpenTables: Boolean;
begin
if (FIsAOTable) then
begin
try
ResultDataset.Open;
Result := True;
except
ResultDataset.Close;
Result := False;
end;
end
else
begin
Result := True;
if (FLeftAO <> nil) then
Result := Result and FLeftAO.OpenTables;
if (FRightAO <> nil) then
Result := Result and FRightAO.OpenTables;
end;
end;// OpenTables
//------------------------------------------------------------------------------
// CloseTables
//------------------------------------------------------------------------------
function TABSAO.CloseTables: Boolean;
begin
if (FIsAOTable) then
begin
try
ResultDataset.Close;
Result := True;
except
Result := False;
end;
end
else
begin
Result := True;
if (FLeftAO <> nil) then
Result := Result and FLeftAO.CloseTables;
if (FRightAO <> nil) then
Result := Result and FRightAO.CloseTables;
end;
end;// CloseTables
//------------------------------------------------------------------------------
// set filter
//------------------------------------------------------------------------------
procedure TABSAO.SetFilter(FilterExpr: TObject);
begin
if (FFilterExpr = nil) then
FFilterExpr := FilterExpr
else
begin
TABSExpression(FFilterExpr).AddAndMoveNodesFromExpression(TABSExpression(FilterExpr));
FilterExpr.Free;
end;
end; // SetFilter
//------------------------------------------------------------------------------
// for SELECT INTO optimization
//------------------------------------------------------------------------------
procedure TABSAO.SetResultTable(InMemory, Immediate: Boolean; TableName: String; DatabaseName: String);
begin
FResultInMemory := InMemory;
FResultImmediate := Immediate;
FResultTableName := TableName;
FResultDatabaseName := DatabaseName;
end; // SetResultTable
//------------------------------------------------------------------------------
// sets Top row count
//------------------------------------------------------------------------------
procedure TABSAO.SetTopRowCount(FirstRowNo, TopRowCount: integer);
begin
if (not FDistinctApplied) and
((FResultIndexFieldsList = nil) or
((FResultIndexFieldsList <> nil) and (FResultIndexFieldsList.Count = 0))) then
begin
FTopRowCount := TopRowCount;
if (FirstRowNo < 0) then
FFirstRowNo := 1
else
FFirstRowNo := FirstRowNo;
end;
end;// SetTopRowCount
//------------------------------------------------------------------------------
// applies distinct
//------------------------------------------------------------------------------
procedure TABSAO.ApplyDistinct(DistinctFields: String);
var
DistinctFieldList: TStringList;
procedure ApplyDistinctToChild(AO: TABSAO);
var
ChildDistinctFields: String;
i: integer;
begin
if not (AO is TABSAOTable) then
begin
ChildDistinctFields := '';
for i := 0 to FFieldCount-1 do
if (FFieldLinks[i].AO = AO) and (not FFieldLinks[i].IsHidden) then
begin
if (ChildDistinctFields <> '') then
ChildDistinctFields := ChildDistinctFields+';';
ChildDistinctFields := ChildDistinctFields +
TABSAO(FFieldLinks[i].AO).FFieldLinks[FFieldLinks[i].FieldNo].FieldName;
end;
if (ChildDistinctFields <> '') then
AO.ApplyDistinct(ChildDistinctFields);
end;
end;
procedure FillDistinctFieldsMap;
var
i,j: integer;
begin
SetLength(FDistinctFieldsMap, DistinctFieldList.Count);
for i := 0 to DistinctFieldList.Count-1 do
for j := 0 to FFieldCount-1 do
if (AnsiUpperCase(FFieldLinks[j].FieldName) = AnsiUpperCase(DistinctFieldList[i])) then
begin
FDistinctFieldsMap[i] := j;
break;
end;
end;
begin
DistinctFieldList := TStringList.Create;
try
FillFieldNames(DistinctFieldList,DistinctFields);
FDistinctApplied := (DistinctFieldList.Count > 0);
if (FDistinctApplied) then
begin
FDistinctFields := DistinctFields;
FDistinctFieldCount := DistinctFieldList.Count;
FillDistinctFieldsMap;
// bug-fix 4.85 - incorrect when condition on hidden join fields
if (FFilterExpr = nil) then
if (Self is TABSAOJoin) then
begin
if (FLeftAO <> nil) then
ApplyDistinctToChild(FLeftAO);
if (FRightAO <> nil) then
ApplyDistinctToChild(FRightAO);
end;
end;
finally
DistinctFieldList.Free;
end;
end; // ApplyDistinct
//------------------------------------------------------------------------------
// sets projection for other TABSAO
//------------------------------------------------------------------------------
procedure TABSAO.SetResultFields(var FieldRefs: array of TABSSelectListItem;
bDistinct: Boolean);
var i,j,k,x,res: integer;
fname,tname: string;
aDistinctFields: String;
begin
aDistinctFields := '';
j := Length(FieldRefs);
if (j <= 0) then
begin
FieldExists('*','',true,FResultFieldsOrder);
end
else
for i := 0 to j-1 do
begin
if (FieldRefs[i].AllFields) then
fname := '*'
else
fname := FieldRefs[i].FieldName;
tname := FieldRefs[i].TableName;
if (FieldRefs[i].IsExpression) then
if ((not TABSExpression(FieldRefs[i].ValueExpr).IsAggregated) or (FIsAOGroupBy)) then
begin
inc(FFieldCount);
SetLength(FFieldLinks,FFieldCount);
FFieldLinks[FFieldCount-1].Expr := FieldRefs[i].ValueExpr;
TABSExpression(FFieldLinks[FFieldCount-1].Expr).AssignAO(self, nil, nil);
// create new field for this expression
if (FieldRefs[i].Pseudonym <> '') then
// pseudonim specified
FFieldLinks[FFieldCount-1].FieldName := FieldRefs[i].Pseudonym
else
// random name
FFieldLinks[FFieldCount-1].FieldName := GetTemporaryName(ABSExpressionFieldName);
FFieldLinks[FFieldCount-1].DisplayName := FFieldLinks[FFieldCount-1].FieldName;
// get field type
FFieldLinks[FFieldCount-1].FieldType :=
TABSExpression(FieldRefs[i].ValueExpr).GetDataType;
// get field size
FFieldLinks[FFieldCount-1].FieldSize :=
TABSExpression(FieldRefs[i].ValueExpr).GetDataSize;
// get field precision
FFieldLinks[FFieldCount-1].FieldPrecision :=
TABSExpression(FieldRefs[i].ValueExpr).GetPrecision;
// AO
FFieldLinks[FFieldCount-1].AO := self;
FFieldLinks[FFieldCount-1].Dataset := nil;
FFieldLinks[FFieldCount-1].IsHidden := false;
FFieldLinks[FFieldCount-1].IsExpression := true;
FFieldLinks[FFieldCount-1].IsAggregate :=
TABSExpression(FieldRefs[i].ValueExpr).IsAggregated;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -