Componentes.Terceros.SDAC/internal/4.10.0.10/1/Source/Design/DASQLGeneratorFrame.pas

629 lines
19 KiB
ObjectPascal
Raw Normal View History

//////////////////////////////////////////////////
// DB Access Components
// Copyright <20> 1998-2005 Core Lab. All right reserved.
// SQLGenerator Frame
//////////////////////////////////////////////////
{$IFNDEF CLR}
{$I Dac.inc}
unit DASQLGeneratorFrame;
{$ENDIF}
interface
uses
{$IFDEF MSWINDOWS}
Windows, Messages, Graphics, Controls, Forms,
Dialogs, StdCtrls, ExtCtrls, Buttons,
{$ENDIF}
{$IFDEF LINUX}
QStdCtrls, QExtCtrls, QButtons, QControls,
{$ENDIF}
Classes, SysUtils,
DBAccess, CRAccess,
CRFrame, CRTabEditor;
type
TDASQLGeneratorFrame = class(TCRFrame)
pnSQLGenerator: TPanel;
lbTableName: TLabel;
lbKeyFieldsLabel: TLabel;
lbUpdateFieldsLabel: TLabel;
cbTables: TComboBox;
btGenerate: TButton;
lbKeyFields: TListBox;
lbUpdateFields: TListBox;
btGetFields: TButton;
cbInsert: TCheckBox;
cbUpdate: TCheckBox;
cbDelete: TCheckBox;
cbRefresh: TCheckBox;
cbQuoteFields: TCheckBox;
procedure pnSQLGeneratorResize(Sender: TObject);
procedure btGetFieldsClick(Sender: TObject);
procedure cbTablesChange(Sender: TObject);
procedure cbIUDRClick(Sender: TObject);
procedure btGenerateClick(Sender: TObject);
procedure lbUpdateFieldsClick(Sender: TObject);
procedure cbTablesDropDown(Sender: TObject);
protected
FLocalDataSet: TCustomDADataSet;
FOnChange: TNotifyEvent;
FLockUpdateControlsState: boolean;
FLastGeneratedSQL,
FLastOriginSQL,
FOldSQL,
FOldFilterSQL: string;
FOldUpdatingTable: string;
Fcb: array[TStatementType] of TCheckBox;
FPromptlyServerRead,
FParseTableNames: boolean;
FActivated: boolean;
procedure GenerateSelectFromAllFields; virtual;
procedure SetFilterSQL(Value: string; Open: boolean = False);
function OpenDataSet(RaiseException: boolean = False): boolean;
procedure InitTables(DeleteBadTableNames: boolean = False);
procedure ClearFields;
procedure GetFields(Forced: boolean = False);
procedure UpdateControlsState; virtual;
function GetOriginLocalDataSet: TCustomDADataSet;
function GetLocalDataSet: TCustomDADataSet;
function GetTablesInfo: TCRTablesInfo; virtual;
function SelectedTableName: string; virtual;
function NormSelectedTableName: string; virtual;
function UnqSelectedTableName: string;
procedure SetControlEnabled(Control: TControl; Value: boolean);
function cbChecked(StatementType: TStatementType): boolean;
property LocalDataSet: TCustomDADataSet read GetLocalDataSet;
property OriginLocalDataSet: TCustomDADataSet read GetOriginLocalDataSet;
property TablesInfo: TCRTablesInfo read GetTablesInfo;
procedure DoActivate; override;
procedure DoFinish; override;
function GenerateSQLforUpdTable(TableInfo: TCRTableInfo;
const KeyAndDataFields: TKeyAndDataFields;
const StatementType: TStatementType;
const ModifiedFieldsOnly: boolean): string; virtual;
public
constructor Create(AOwner: TComponent); override;
function ActiveControl: TWinControl; override;
property OnChange: TNotifyEvent read FOnChange write FOnChange;
end;
implementation
{$IFDEF IDE}
{$R *.dfm}
{$ENDIF}
{$IFDEF MSWINDOWS}
{$R DASQLGeneratorFrame.dfm}
{$ENDIF}
{$IFDEF LINUX}
{$R *.xfm}
{$ENDIF}
uses
DB, DAQueryEditor, DAUpdateSQLEditor, DAUpdateSQLFrame, MemData;
constructor TDASQLGeneratorFrame.Create(AOwner: TComponent);
var
st: TStatementType;
begin
inherited;
for st := Low(TStatementType) to High(TStatementType) do
Fcb[st] := nil;
Fcb[stInsert] := cbInsert;
Fcb[stUpdate] := cbUpdate;
Fcb[stDelete] := cbDelete;
Fcb[stRefresh] := cbRefresh;
FPromptlyServerRead := True;
FParseTableNames := False;
FActivated := False;
end;
procedure TDASQLGeneratorFrame.SetControlEnabled(Control: TControl; Value: boolean);
begin
{$IFNDEF LINUX}
if not Value and (Editor.ActiveControl = Control) then
Editor.ActiveControl := Control.Parent;
{$ENDIF}
Control.Enabled := Value;
end;
function TDASQLGeneratorFrame.cbChecked(StatementType: TStatementType): boolean;
begin
Result := (Fcb[StatementType] <> nil) and Fcb[StatementType].Enabled
and Fcb[StatementType].Checked and Fcb[StatementType].Visible;
end;
function TDASQLGeneratorFrame.GetOriginLocalDataSet: TCustomDADataSet;
begin
Result := nil;
if FEditor is TDAQueryEditorForm then
Result := TDAQueryEditorForm(FEditor).LocalComponent as TCustomDADataSet
else
if FEditor is TDAUpdateSQLEditorForm then
Result := TDAUpdateSQLEditorForm(FEditor).LocalDataSet
else
Assert(False);
end;
function TDASQLGeneratorFrame.GetLocalDataSet: TCustomDADataSet;
begin
if FLocalDataSet = nil then begin
FLocalDataSet := TComponentClass(OriginLocalDataSet.ClassType).Create(nil) as TCustomDADataSet;
FLocalDataSet.Assign(OriginLocalDataSet);
TDBAccessUtils.SetDesigning(FLocalDataSet, csDesigning in OriginLocalDataSet.ComponentState);
end;
Result := FLocalDataSet;
end;
function TDASQLGeneratorFrame.GetTablesInfo: TCRTablesInfo;
begin
Result := TDBAccessUtils.GetTablesInfo(LocalDataSet);
end;
function TDASQLGeneratorFrame.SelectedTableName: string;
begin
Result := TablesInfo.TableInfoClass.NormalizeName(Trim(cbTables.Text), LocalDataSet.Options.QuoteNames);
end;
function TDASQLGeneratorFrame.NormSelectedTableName: string;
begin
Result := TablesInfo.TableInfoClass.NormalizeName(Trim(cbTables.Text)); // Without QuoteName!
end;
function TDASQLGeneratorFrame.UnqSelectedTableName: string;
begin
Result := TablesInfo.TableInfoClass.UnQuote(Trim(cbTables.Text));
end;
function TDASQLGeneratorFrame.ActiveControl: TWinControl;
begin
Result := cbTables;
end;
procedure TDASQLGeneratorFrame.GenerateSelectFromAllFields;
begin
LocalDataSet.SQL.Text := 'SELECT * FROM ' + SelectedTableName;
end;
procedure TDASQLGeneratorFrame.SetFilterSQL(Value: string; Open: boolean = False);
var
OldDebug: boolean;
begin
OldDebug := LocalDataSet.Debug;
try
LocalDataSet.Debug := False;
LocalDataSet.FilterSQL := Value;
if Open then
LocalDataSet.Open;
finally
LocalDataSet.Debug := OldDebug;
end;
end;
function TDASQLGeneratorFrame.OpenDataSet(RaiseException: boolean = False): boolean;
begin
Result := True;
try
Editor.CheckConnection(LocalDataSet);
SetFilterSQL('1=0', True);
except
Result := False;
if RaiseException then
raise;
end;
end;
procedure TDASQLGeneratorFrame.InitTables(DeleteBadTableNames: boolean = False);
var
i, n, ItemIndex: integer;
s: string;
begin
cbTables.Items.BeginUpdate;
try
{$IFDEF LINUX}
if (cbTables.Items.Count = 1) and (cbTables.Items[0] = '') then
cbTables.Items.Clear;
{$ENDIF}
if DeleteBadTableNames then begin
i := 0;
while i < cbTables.Items.Count do
if cbTables.Items.Objects[i] = nil then
cbTables.Items.Delete(i)
else
Inc(i);
end;
SetFilterSQL('1=0');
ItemIndex := -1;
if FParseTableNames or OpenDataSet then
for i := 0 to TablesInfo.Count - 1 do begin
s := Trim(TablesInfo[i].TableName);
n := cbTables.Items.IndexOf(s);
if n = -1 then
n := cbTables.Items.Add(s);
if i = 0 then
ItemIndex := n;
end;
if (Trim(cbTables.Text) = '') and (FOldUpdatingTable <> '') then
cbTables.Text := FOldUpdatingTable
else
if (ItemIndex <> -1) and (Trim(OriginLocalDataSet.SQL.Text) <> FLastOriginSQL)
and (cbTables.Items[ItemIndex] <> cbTables.Text) then begin
FLastOriginSQL := Trim(OriginLocalDataSet.SQL.Text);
ClearFields;
cbTables.ItemIndex := ItemIndex;
end;
finally
{$IFDEF LINUX}
if cbTables.Items.Count = 0 then
cbTables.Items.Add('');
{$ENDIF}
cbTables.Items.EndUpdate;
end;
end;
procedure TDASQLGeneratorFrame.ClearFields;
begin
lbKeyFields.Items.Clear;
lbUpdateFields.Items.Clear;
end;
procedure TDASQLGeneratorFrame.GetFields(Forced: boolean = False);
var
KeyAndDataFields: TKeyAndDataFields;
OriginKeyList,
OriginDataList: TStringList;
function EmptyLists: boolean;
begin
Result := (lbKeyFields.Items.Count = 0) and (lbUpdateFields.Items.Count = 0);
end;
procedure GetFieldNames;
var
j: integer;
Empty: boolean;
procedure AddFieldName(LB: TListBox; Name: string; const FieldList: TStringList; Selected: boolean);
begin
if LB.Items.IndexOf(Name) < 0 then begin
if Selected and (FieldList.Count <> 0) then
Selected := FieldList.IndexOf(Name) >= 0;
LB.Selected[LB.Items.Add(Name)] := Selected;
end;
end;
begin
try
Empty := EmptyLists;
for j := 0 to High(KeyAndDataFields.KeyFieldDescs) do begin
AddFieldName(lbKeyFields, KeyAndDataFields.KeyFieldDescs[j].ActualName, OriginKeyList, Empty);
end;
for j := 0 to High(KeyAndDataFields.DataFieldDescs) do begin
AddFieldName(lbKeyFields, KeyAndDataFields.DataFieldDescs[j].ActualName, OriginKeyList, False);
AddFieldName(lbUpdateFields, KeyAndDataFields.DataFieldDescs[j].ActualName, OriginDataList, Empty);
end;
except
ClearFields;
raise;
end;
end;
procedure InitFields(OriginFields: boolean);
var
i: integer;
begin
if OriginFields then begin
SetLength(KeyAndDataFields.KeyFieldDescs, 0);
SetLength(KeyAndDataFields.DataFieldDescs, 0);
end;
if not OpenDataSet(not OriginFields) or (OriginFields and not EmptyLists) then
Exit;
if TablesInfo.IndexByName(SelectedTableName) = -1 then begin
ClearFields;
Exit;
end;
TDBAccessUtils.SetUpdatingTable(LocalDataSet, SelectedTableName);
TDBAccessUtils.GetKeyAndDataFields(LocalDataSet, KeyAndDataFields, False);
if OriginFields then begin
for i := 0 to High(KeyAndDataFields.KeyFieldDescs) do
OriginKeyList.Add(KeyAndDataFields.KeyFieldDescs[i].ActualName);
for i := 0 to High(KeyAndDataFields.DataFieldDescs) do
OriginDataList.Add(KeyAndDataFields.DataFieldDescs[i].ActualName);
end
else
if not Forced then
try
GetFieldNames;
finally
UpdateControlsState;
end;
end;
var
i: integer;
begin
if not (EmptyLists or Forced) or (UnqSelectedTableName = '') then
Exit;
if (TDBAccessUtils.UsedConnection(LocalDataSet) <> nil) then
Editor.CheckConnection(LocalDataSet);
try
OriginKeyList := TStringList.Create;
OriginDataList := TStringList.Create;
if FOldSQL <> LocalDataSet.SQL.Text then
LocalDataSet.SQL.Text := FOldSQL;
InitFields(True);
if EmptyLists then begin
GenerateSelectFromAllFields;
FLastGeneratedSQL := LocalDataSet.SQL.Text;
end
else
LocalDataSet.SQL.Text := FLastGeneratedSQL;
InitFields(False);
i := cbTables.Items.IndexOf(SelectedTableName);
if i < 0 then
i := cbTables.Items.Add(SelectedTableName);
cbTables.Items.Objects[i] := Self; // Mark good table
finally
OriginKeyList.Free;
OriginDataList.Free;
end;
end;
procedure TDASQLGeneratorFrame.UpdateControlsState;
var
TableName: string;
sts: TStatementTypes;
st: TStatementType;
IsEnabled: boolean;
begin
if FLockUpdateControlsState then
Exit;
Assert(LocalDataSet <> nil);
sts := TDBAccessUtils.GetUpdateSQLStatementTypes(LocalDataSet);
TableName := SelectedTableName;
IsEnabled := TableName <> '';
SetControlEnabled(btGetFields, IsEnabled and (lbUpdateFields.Items.Count + lbUpdateFields.Items.Count = 0));
SetControlEnabled(cbInsert, IsEnabled and (lbUpdateFields.SelCount > 0));
SetControlEnabled(cbUpdate, IsEnabled and (lbKeyFields.SelCount > 0) and (lbUpdateFields.SelCount > 0));
SetControlEnabled(cbDelete, IsEnabled and (lbKeyFields.SelCount > 0));
SetControlEnabled(cbRefresh, IsEnabled and (lbKeyFields.SelCount > 0) and (lbUpdateFields.SelCount > 0) {and TableNameSelectedFromList});
if IsEnabled then
for st := Low(TStatementType) to High(TStatementType) do
if st in sts then begin
IsEnabled := cbChecked(st);
if IsEnabled then
Break;
end;
SetControlEnabled(btGenerate, IsEnabled);
SetControlEnabled(cbQuoteFields, IsEnabled);
end;
procedure TDASQLGeneratorFrame.pnSQLGeneratorResize(Sender: TObject);
begin
lbKeyFields.Width := (lbUpdateFields.Left + lbUpdateFields.Width - lbKeyFields.Left - 8) div 2;
lbUpdateFields.Left := lbUpdateFields.Left - (lbKeyFields.Width - lbUpdateFields.Width);
lbUpdateFields.Width := lbKeyFields.Width;
lbUpdateFieldsLabel.Left := lbUpdateFields.Left;
end;
procedure TDASQLGeneratorFrame.btGetFieldsClick(Sender: TObject);
begin
GetFields;
end;
procedure TDASQLGeneratorFrame.cbTablesChange(Sender: TObject);
begin
ClearFields;
if FPromptlyServerRead and (cbTables.Items.IndexOf(SelectedTableName) <> -1) then
GetFields;
UpdateControlsState;
end;
procedure TDASQLGeneratorFrame.DoActivate;
var
OldSQL: string;
begin
FOldUpdatingTable := TDBAccessUtils.GetUpdatingTable(LocalDataSet);
OldSQL := LocalDataSet.SQL.Text;
FOldFilterSQL := LocalDataSet.FilterSQL;
try
inherited;
if OriginLocalDataSet.SQL.Text <> LocalDataSet.SQL.Text then
LocalDataSet.SQL := OriginLocalDataSet.SQL;
if not FActivated then
cbQuoteFields.Checked := LocalDataSet.Options.QuoteNames;
if ((TDBAccessUtils.UsedConnection(LocalDataSet) <> nil) and
TDBAccessUtils.UsedConnection(LocalDataSet).Connected and
(FOldSQL <> LocalDataSet.SQL.Text) and
FPromptlyServerRead) or FParseTableNames then
InitTables(FParseTableNames);
FActivated := True;
finally
FOldSQL := OldSQL; // always call; see DoFinish for details
UpdateControlsState;
end;
if FPromptlyServerRead then
GetFields;
end;
procedure TDASQLGeneratorFrame.DoFinish;
begin
inherited;
LocalDataSet.Close;
if FOldSQL <> LocalDataSet.SQL.Text then
LocalDataSet.SQL.Text := FOldSQL;
if FOldFilterSQL <> LocalDataSet.FilterSQL then
SetFilterSQL(FOldFilterSQL);
if FOldUpdatingTable <> TDBAccessUtils.GetUpdatingTable(LocalDataSet) then
TDBAccessUtils.SetUpdatingTable(LocalDataSet, FOldUpdatingTable);
FLocalDataSet.Free;
FLocalDataSet := nil;
end;
procedure TDASQLGeneratorFrame.cbIUDRClick(Sender: TObject);
begin
inherited;
UpdateControlsState;
end;
function TDASQLGeneratorFrame.GenerateSQLforUpdTable(
TableInfo: TCRTableInfo; const KeyAndDataFields: TKeyAndDataFields;
const StatementType: TStatementType; const ModifiedFieldsOnly: boolean): string;
begin
Result := TDBAccessUtils.SQLGenerator(LocalDataSet).GenerateSQLforUpdTable(TableInfo, KeyAndDataFields, StatementType, ModifiedFieldsOnly, nil);
end;
procedure TDASQLGeneratorFrame.btGenerateClick(Sender: TObject);
var
i, j: integer;
KeyAndDataFields: TKeyAndDataFields;
TableInfo: TCRTableInfo;
UpdateSQLFrame: TDAUpdateSQLFrame;
OldSQL: string;
OldActive: boolean;
st: TStatementType;
sts: TStatementTypes;
stSQL: array[TStatementType] of string;
OldQuoteNames: boolean;
begin
GetFields(True);
OldSQL := LocalDataSet.SQL.Text;
OldActive := LocalDataSet.Active;
OldQuoteNames := LocalDataSet.Options.QuoteNames;
try
if LocalDataSet.SQL.Text <> FLastGeneratedSQL then
LocalDataSet.SQL.Text := FLastGeneratedSQL;
OpenDataSet(True);
TableInfo := TablesInfo.TableInfoClass.Create(nil);
try
TableInfo.IsView := False; // Use to generate only specified fields
TableInfo.TableName := NormSelectedTableName;
TableInfo.TableNameFull := TableInfo.TableName;
TableInfo.TableAlias := '';
SetLength(KeyAndDataFields.KeyFieldDescs, lbKeyFields.SelCount);
j := 0;
for i := 0 to lbKeyFields.Items.Count - 1 do
if lbKeyFields.Selected[i] then begin
KeyAndDataFields.KeyFieldDescs[j] := LocalDataSet.GetFieldDesc(lbKeyFields.Items[i]) as TCRFieldDesc;
Inc(j);
end;
SetLength(KeyAndDataFields.DataFieldDescs, lbUpdateFields.SelCount);
j := 0;
for i := 0 to lbUpdateFields.Items.Count - 1 do
if lbUpdateFields.Selected[i] then begin
KeyAndDataFields.DataFieldDescs[j] := LocalDataSet.GetFieldDesc(lbUpdateFields.Items[i]) as TCRFieldDesc;
Inc(j);
end;
LocalDataSet.Options.QuoteNames := cbQuoteFields.Checked;
sts := Editor.DADesignUtilsClass.GetStatementTypes;
try
for st := Low(TStatementType) to High(TStatementType) do
if (st in sts) and cbChecked(st) then begin
stSQL[st] := GenerateSQLforUpdTable(TableInfo, KeyAndDataFields, st, False);
Modified := True;
end;
// after setting SQL Fields[] may be destroyed
SetLength(KeyAndDataFields.KeyFieldDescs, 0); // Just in case
SetLength(KeyAndDataFields.DataFieldDescs, 0);
for st := Low(TStatementType) to High(TStatementType) do
if (st in sts) and cbChecked(st) then
Editor.DADesignUtilsClass.SetSQL(Editor.LocalComponent, stSQL[st], st);
finally
UpdateSQLFrame := nil;
if FEditor is TDAUpdateSQLEditorForm then
UpdateSQLFrame := TDAUpdateSQLEditorForm(FEditor).UpdateSQLFrame
else
if FEditor is TDAQueryEditorForm then
UpdateSQLFrame := TDAQueryEditorForm(FEditor).UpdateSQLFrame
else
Assert(False);
for st := Low(TStatementType) to High(TStatementType) do
if (st in sts) and cbChecked(st) then begin
UpdateSQLFrame.SetStatementType(st);
Break;
end;
if FEditor is TDAUpdateSQLEditorForm then
TDAUpdateSQLEditorForm(FEditor).ActivateFrame(UpdateSQLFrame)
else
TDAQueryEditorForm(FEditor).ActivateFrame(UpdateSQLFrame);
end;
finally
TableInfo.Free;
end;
finally
LocalDataSet.Options.QuoteNames := OldQuoteNames;
if not OldActive then
LocalDataSet.SQL.Text := OldSQL;
end;
end;
procedure TDASQLGeneratorFrame.lbUpdateFieldsClick(Sender: TObject);
begin
UpdateControlsState;
end;
procedure TDASQLGeneratorFrame.cbTablesDropDown(Sender: TObject);
begin
if FParseTableNames then
InitTables
else
if ((TDBAccessUtils.UsedConnection(LocalDataSet) <> nil) and
((cbTables.Items.Count = 0) {$IFDEF LINUX}or (cbTables.Items.Count = 1) and
(cbTables.Items[0] = ''){$ENDIF})) then begin
InitTables;
cbTablesChange(nil);
end;
end;
end.