lazarus/components/lazreport/source/addons/SqlDB/lr_sqlquery.pas
2014-09-04 19:28:33 +00:00

578 lines
15 KiB
ObjectPascal

unit lr_SQLQuery;
{$mode objfpc}{$H+}
interface
uses
Classes, SysUtils, Graphics, LR_Class, LR_DBComponent, sqldb, DB, contnrs;
type
TQueryParam = class
ParamType:TFieldType;
ParamName:string;
ParamValue:string;
end;
{ TQueryParamList }
TQueryParamList = class(TFPObjectList)
function ParamByName(AParamName:string):TQueryParam;
function Add(AParamType:TFieldType; const AParamName, AParamValue:string):TQueryParam;
end;
{ TLRSQLQuery }
TLRSQLQuery = class(TLRDataSetControl)
private
FDatabase: string;
FParams: TQueryParamList;
procedure SetDatabase(AValue: string);
procedure DoMakeParams;
procedure DoEditParams;
procedure SQLQueryBeforeOpen(ADataSet: TDataSet);
protected
function GetSQL: string;
procedure SetSQL(AValue:string);
procedure SetDataSource(AValue: string); override;
procedure AfterLoad;override;
public
constructor Create(AOwnerPage:TfrPage); override;
destructor Destroy; override;
procedure LoadFromXML(XML: TLrXMLConfig; const Path: String); override;
procedure SaveToXML(XML: TLrXMLConfig; const Path: String); override;
published
property SQL:string read GetSQL write SetSQL;
property Database:string read FDatabase write SetDatabase;
property Params:TQueryParamList read FParams write FParams;
end;
{ TLRSQLConnection }
TLRSQLConnection = class(TfrNonVisualControl)
private
FConnected:boolean;
function GetCharSet: string;
function GetConnected: Boolean;
function GetDatabase: string;
function GetHostName: string;
function GetLoginPrompt: Boolean;
function GetPassword: string;
function GetUserName: string;
procedure SetCharSet(AValue: string);
procedure SetConnected(AValue: Boolean);
procedure SetDatabase(AValue: string);
procedure SetHostName(AValue: string);
procedure SetLoginPrompt(AValue: Boolean);
procedure SetPassword(AValue: string);
procedure SetUserName(AValue: string);
protected
FConnection: TSQLConnection;
FSQLTransaction:TSQLTransaction;
procedure SetName(const AValue: string); override;
procedure AfterLoad;override;
public
constructor Create(AOwnerPage:TfrPage); override;
destructor Destroy; override;
procedure LoadFromXML(XML: TLrXMLConfig; const Path: String); override;
procedure SaveToXML(XML: TLrXMLConfig; const Path: String); override;
published
property CharSet: string read GetCharSet write SetCharSet;
property Connected: Boolean read GetConnected write SetConnected;
property LoginPrompt: Boolean read GetLoginPrompt write SetLoginPrompt;
property HostName: string read GetHostName write SetHostName;
property DatabaseName: string read GetDatabase write SetDatabase;
property UserName: string read GetUserName write SetUserName;
property Password: string read GetPassword write SetPassword;
end;
implementation
{$R lrsqldb_img.res}
uses LR_Utils, DBPropEdits, PropEdits, Controls, Forms,
lr_EditSQLDBParamsUnit;
var
lrBMP_SQLQuery:TBitmap = nil;
procedure InitLRComp;
begin
if not assigned(lrBMP_SQLQuery) then
begin
lrBMP_SQLQuery := TbitMap.Create;
lrBMP_SQLQuery.LoadFromResourceName(HInstance, 'TLRSQLQuery');
frRegisterObject(TLRSQLQuery, lrBMP_SQLQuery, 'TLRSQLQuery', nil, otlUIControl, nil);
end;
end;
{ TQueryParamList }
function TQueryParamList.ParamByName(AParamName: string): TQueryParam;
var
i:integer;
begin
Result:=nil;
AParamName:=UpperCase(AParamName);
for i:=0 to Count - 1 do
begin
if UpperCase(TQueryParam(Items[i]).ParamName) = AParamName then
begin
Result:=TQueryParam(Items[i]);
exit;
end;
end;
end;
function TQueryParamList.Add(AParamType: TFieldType; const AParamName,
AParamValue: string): TQueryParam;
begin
Result:=TQueryParam.Create;
inherited Add(Result);
Result.ParamType:=AParamType;
Result.ParamName:=AParamName;
Result.ParamValue:=AParamValue;
end;
{ TLRSQLConnection }
function TLRSQLConnection.GetCharSet: string;
begin
Result:=FConnection.CharSet;
end;
function TLRSQLConnection.GetConnected: Boolean;
begin
Result:=FConnection.Connected;
end;
function TLRSQLConnection.GetDatabase: string;
begin
Result:=FConnection.DatabaseName;
end;
function TLRSQLConnection.GetHostName: string;
begin
Result:=FConnection.HostName;
end;
function TLRSQLConnection.GetLoginPrompt: Boolean;
begin
Result:=FConnection.LoginPrompt;
end;
function TLRSQLConnection.GetPassword: string;
begin
Result:=FConnection.Password;
end;
function TLRSQLConnection.GetUserName: string;
begin
Result:=FConnection.UserName;
end;
procedure TLRSQLConnection.SetCharSet(AValue: string);
begin
FConnection.CharSet:=AValue;
end;
procedure TLRSQLConnection.SetConnected(AValue: Boolean);
begin
FConnection.Connected:=AValue;
end;
procedure TLRSQLConnection.SetDatabase(AValue: string);
begin
FConnection.DatabaseName:=AValue;
end;
procedure TLRSQLConnection.SetHostName(AValue: string);
begin
FConnection.HostName:=AValue;
end;
procedure TLRSQLConnection.SetLoginPrompt(AValue: Boolean);
begin
FConnection.LoginPrompt:=AValue;
end;
procedure TLRSQLConnection.SetPassword(AValue: string);
begin
FConnection.Password:=AValue;
end;
procedure TLRSQLConnection.SetUserName(AValue: string);
begin
FConnection.UserName:=AValue;
end;
procedure TLRSQLConnection.SetName(const AValue: string);
begin
inherited SetName(AValue);
FConnection.Name:=Name;
end;
procedure TLRSQLConnection.AfterLoad;
begin
inherited AfterLoad;
FConnection.Connected:=FConnected;
end;
constructor TLRSQLConnection.Create(AOwnerPage: TfrPage);
begin
inherited Create(AOwnerPage);
FSQLTransaction:=TSQLTransaction.Create(OwnerForm);
end;
destructor TLRSQLConnection.Destroy;
begin
if not (Assigned(OwnerPage) and (OwnerPage is TfrPageDialog)) then
begin
FreeAndNil(FSQLTransaction);
FreeAndNil(FConnection);
end;
inherited Destroy;
end;
procedure TLRSQLConnection.LoadFromXML(XML: TLrXMLConfig; const Path: String);
begin
inherited LoadFromXML(XML, Path);
FConnection.LoginPrompt:=XML.GetValue(Path + 'LoginPrompt/Value'{%H-}, false);
FConnection.CharSet:=XML.GetValue(Path + 'CharSet/Value'{%H-}, '');
FConnection.HostName:=XML.GetValue(Path + 'HostName/Value'{%H-}, '');
FConnection.DatabaseName:=XML.GetValue(Path + 'Database/Value'{%H-}, '');
FConnection.UserName:=XML.GetValue(Path + 'User/Value'{%H-}, '');
FConnection.Password:=XML.GetValue(Path + 'Password/Value'{%H-}, '');
FConnected:=XML.GetValue(Path + 'Connected/Value'{%H-}, false);
end;
procedure TLRSQLConnection.SaveToXML(XML: TLrXMLConfig; const Path: String);
begin
inherited SaveToXML(XML, Path);
XML.SetValue(Path + 'LoginPrompt/Value'{%H-}, FConnection.LoginPrompt);
XML.SetValue(Path + 'CharSet/Value'{%H-}, FConnection.CharSet);
XML.SetValue(Path + 'HostName/Value'{%H-}, FConnection.HostName);
XML.SetValue(Path + 'Database/Value'{%H-}, FConnection.DatabaseName);
XML.SetValue(Path + 'User/Value'{%H-}, FConnection.UserName);
XML.SetValue(Path + 'Password/Value'{%H-}, FConnection.Password);
XML.SetValue(Path + 'Connected/Value'{%H-}, FConnection.Connected);
end;
{ TLRSQLQuery }
procedure TLRSQLQuery.SetDatabase(AValue: string);
var
D:TComponent;
begin
if FDatabase=AValue then Exit;
FDatabase:=AValue;
DataSet.Active:=false;
D:=frFindComponent(TSQLQuery(DataSet).Owner, FDatabase);
if Assigned(D) and (D is TSQLConnection)then
TSQLQuery(DataSet).DataBase:=TSQLConnection(D);
end;
procedure TLRSQLQuery.DoMakeParams;
var
Q:TSQLQuery;
i:integer;
begin
Q:=TSQLQuery(DataSet);
if Q.Params.Count > 0 then
begin
//Add new params...
for i:=0 to Q.Params.Count-1 do
begin
if not Assigned(FParams.ParamByName(Q.Params[i].Name)) then
FParams.Add(ftUnknown, Q.Params[i].Name, '');
end;
//Delete not exists params
for i:=FParams.Count-1 downto 0 do
begin
if not Assigned(Q.Params.FindParam(TQueryParam(FParams[i]).ParamName)) then
FParams.Delete(i);
end;
end
else
FParams.Clear;
end;
procedure TLRSQLQuery.DoEditParams;
var
lrEditParamsForm: Tlr_EditSQLDBParamsForm;
begin
lrEditParamsForm:=Tlr_EditSQLDBParamsForm.Create(Application);
lrEditParamsForm.LoadParamList(FParams);
if lrEditParamsForm.ShowModal = mrOk then
begin
lrEditParamsForm.SaveParamList(FParams);
if Assigned(frDesigner) then
frDesigner.Modified:=true;
end;
lrEditParamsForm.Free;
end;
procedure TLRSQLQuery.SQLQueryBeforeOpen(ADataSet: TDataSet);
var
i: Integer;
s: String;
SaveView: TfrView;
SavePage: TfrPage;
SaveBand: TfrBand;
Q:TSQLQuery;
P:TQueryParam;
begin
Q:=TSQLQuery(DataSet);
SaveView := CurView;
SavePage := CurPage;
SaveBand := CurBand;
CurView := Self;
CurPage := OwnerPage;
CurBand := nil;
for i := 0 to Q.Params.Count - 1 do
begin
S:=Q.Params[i].Name;
P:=FParams.ParamByName(S);
if Assigned(P) and (P.ParamValue <> '') and (DocMode = dmPrinting) then
begin
case P.ParamType of
ftDate,
ftDateTime:Q.Params[i].AsDateTime := frParser.Calc(P.ParamValue);
ftInteger:Q.Params[i].AsInteger := frParser.Calc(P.ParamValue);
ftFloat:Q.Params[i].AsFloat := frParser.Calc(P.ParamValue);
ftString:Q.Params[i].AsString := frParser.Calc(P.ParamValue);
else
Q.Params[i].Value := frParser.Calc(P.ParamValue);
end;
end;
end;
if Assigned(Q.DataBase) then
if not Q.DataBase.Connected then Q.DataBase.Connected:=true;
CurView := SaveView;
CurPage := SavePage;
CurBand := SaveBand;
end;
function TLRSQLQuery.GetSQL: string;
begin
Result:=TSQLQuery(DataSet).SQL.Text;
end;
procedure TLRSQLQuery.SetSQL(AValue: string);
begin
DataSet.Active:=false;
TSQLQuery(DataSet).SQL.Text:=AValue;
DoMakeParams;
if Assigned(frDesigner) then
frDesigner.Modified:=true;
end;
procedure TLRSQLQuery.SetDataSource(AValue: string);
var
D:TComponent;
begin
inherited SetDataSource(AValue);
D:=frFindComponent(OwnerForm, AValue);
if Assigned(D) and (D is TDataSource)then
TSQLQuery(DataSet).DataSource:=TDataSource(D);
end;
procedure TLRSQLQuery.AfterLoad;
var
D:TComponent;
begin
D:=frFindComponent(OwnerForm, DataSource);
if Assigned(D) and (D is TDataSource)then
TSQLQuery(DataSet).DataSource:=TDataSource(D);
D:=frFindComponent(DataSet.Owner, FDatabase);
if Assigned(D) and (D is TSQLConnection)then
begin
TSQLQuery(DataSet).DataBase:=TSQLConnection(D);
DataSet.Active:=FActive;
end;
end;
constructor TLRSQLQuery.Create(AOwnerPage: TfrPage);
begin
inherited Create(AOwnerPage);
BaseName := 'lrSQLQuery';
DataSet:=TSQLQuery.Create(OwnerForm);
DataSet.BeforeOpen:=@SQLQueryBeforeOpen;
FParams:=TQueryParamList.Create;
end;
destructor TLRSQLQuery.Destroy;
begin
FreeAndNil(FParams);
inherited Destroy;
end;
function StrToFieldType(AStrTypeName:string):TFieldType;
var
i:TFieldType;
begin
Result:=ftUnknown;
AStrTypeName:=UpperCase(AStrTypeName);
for i in TFieldType do
begin
if UpperCase(Fieldtypenames[i]) = AStrTypeName then
begin
Result:=i;
exit;
end;
end;
end;
procedure TLRSQLQuery.LoadFromXML(XML: TLrXMLConfig; const Path: String);
var
C: Integer;
i: Integer;
begin
inherited LoadFromXML(XML, Path);
TSQLQuery(DataSet).SQL.Text := XML.GetValue(Path+'SQL/Value'{%H-}, '');
FDatabase:= XML.GetValue(Path+'Database/Value'{%H-}, '');
C:=XML.GetValue(Path+'Params/Count/Value', 0);
for i:=0 to C-1 do
FParams.Add(
StrToFieldType(XML.GetValue(Path+'Params/Item'+IntToStr(i)+'/ParamType', '')),
XML.GetValue(Path+'Params/Item'+IntToStr(i)+'/Name', ''),
XML.GetValue(Path+'Params/Item'+IntToStr(i)+'/Value', '')
);
end;
procedure TLRSQLQuery.SaveToXML(XML: TLrXMLConfig; const Path: String);
var
i: Integer;
P: TQueryParam;
begin
inherited SaveToXML(XML, Path);
XML.SetValue(Path+'SQL/Value', TSQLQuery(DataSet).SQL.Text);
XML.SetValue(Path+'Database/Value', FDatabase);
XML.SetValue(Path+'Params/Count/Value', FParams.Count);
for i:=0 to FParams.Count-1 do
begin
P:=TQueryParam(FParams[i]);
XML.SetValue(Path+'Params/Item'+IntToStr(i)+'/Name', P.ParamName);
XML.SetValue(Path+'Params/Item'+IntToStr(i)+'/Value', P.ParamValue);
XML.SetValue(Path+'Params/Item'+IntToStr(i)+'/ParamType', Fieldtypenames[P.ParamType]);
end;
end;
type
{ TLRSQLQueryParamsProperty }
TLRSQLQueryParamsProperty = class(TPropertyEditor)
public
function GetAttributes: TPropertyAttributes; override;
function GetValue: ansistring; override;
procedure Edit; override;
end;
TLRSQLConnectionProtocolProperty = class(TFieldProperty)
public
procedure FillValues(const Values: TStringList); override;
end;
{ TLRSQLQuerySQLProperty }
TLRSQLQuerySQLProperty = class(TStringPropertyEditor)
public
function GetAttributes: TPropertyAttributes; override;
function GetValue: ansistring; override;
procedure Edit; override;
end;
{ TLRSQLQueryParamsProperty }
function TLRSQLQueryParamsProperty.GetAttributes: TPropertyAttributes;
begin
Result:=[paDialog, paReadOnly];
end;
function TLRSQLQueryParamsProperty.GetValue: ansistring;
begin
Result:='(Params)';
end;
procedure TLRSQLQueryParamsProperty.Edit;
begin
if (GetComponent(0) is TLRSQLQuery) then
TLRSQLQuery(GetComponent(0)).DoEditParams;
end;
{ TLRSQLQuerySQLProperty }
function TLRSQLQuerySQLProperty.GetAttributes: TPropertyAttributes;
begin
Result:=[paDialog, paReadOnly];
end;
function TLRSQLQuerySQLProperty.GetValue: ansistring;
begin
Result:='(SQL)';
end;
procedure TLRSQLQuerySQLProperty.Edit;
var
TheDialog : TStringsPropEditorDlg;
AString : string;
begin
AString := GetStrValue;
TheDialog := TStringsPropEditorDlg.Create(nil);
try
TheDialog.Editor := Self;
TheDialog.Memo.Text := AString;
TheDialog.MemoChange(nil);
if (TheDialog.ShowModal = mrOK) then
begin
AString := TheDialog.Memo.Text;
//erase the last lineending if any
if Copy(AString, length(AString) - length(LineEnding) + 1, length(LineEnding)) = LineEnding then
Delete(AString, length(AString) - length(LineEnding) + 1, length(LineEnding));
SetStrValue(AString);
end;
finally
TheDialog.Free;
end;
end;
{ TLRZConnectionProtocolProperty }
procedure TLRSQLConnectionProtocolProperty.FillValues(const Values: TStringList);
begin
if (GetComponent(0) is TLRSQLQuery) then
frGetComponents(nil, TSQLConnection, Values, nil);
end;
initialization
InitLRComp;
RegisterPropertyEditor(TypeInfo(string), TLRSQLQuery, 'Database', TLRSQLConnectionProtocolProperty);
RegisterPropertyEditor(TypeInfo(string), TLRSQLQuery, 'SQL', TLRSQLQuerySQLProperty);
RegisterPropertyEditor(TypeInfo(TQueryParamList), TLRSQLQuery, 'Params', TLRSQLQueryParamsProperty);
finalization
if Assigned(lrBMP_SQLQuery) then
FreeAndNil(lrBMP_SQLQuery);
end.