Repository URL to install this package:
|
Version:
3.2.0 ▾
|
unit SQLDBWebData;
{$mode objfpc}{$H+}
interface
uses
Classes, SysUtils, fphttp, fpwebdata, DB, SQLDB;
Type
{ TCustomSQLDBWebDataProvider }
TNewIDEvent = Procedure(Sender : TObject; Out AID : String) of object;
TGetParamTypeEvent = Procedure (Sender : TObject; Const ParamName,AValue : String; Var AType : TFieldtype) of object;
TGetParamValueEvent = Procedure (Sender : TObject; P : TParam; Var Handled : Boolean) of object;
TCustomSQLDBWebDataProvider = Class(TFPCustomWebDataProvider)
private
FIDFieldName: String;
FONGetDataset: TNotifyEvent;
FOnGetNewID: TNewIDEvent;
FOnGetParamValue: TGetParamValueEvent;
FParams: TParams;
FSQLS : Array[0..3] of TStringList;
FConnection: TSQLConnection;
FQuery : TSQLQuery;
FLastNewID : String;
FOnGetParamType : TGetParamTypeEvent;
function GetS(AIndex: integer): TStrings;
procedure RegenerateParams;
procedure SetConnection(const AValue: TSQLConnection);
procedure SetParams(const AValue: TParams);
procedure SetS(AIndex: integer; const AValue: TStrings);
Protected
function CheckDataset : Boolean; virtual;
function CreateQuery(AOwner: TComponent; ATransaction: TSQLTransaction; ASQL: Tstrings): TSQLQuery;
function GetParamType(P: TParam; const AValue: String): TFieldType; virtual;
procedure SetTypedParam(P: TParam; Const AValue: String); virtual;
procedure ExecuteSQL(ASQL: TStrings; Msg: String=''; DoNewID : Boolean = False); virtual;
procedure ApplySQLParams(AQuery: TSQLQuery; DoNewID : Boolean = False); virtual;
Procedure SQLChanged(Sender : TObject); virtual;
Procedure DoUpdate; override;
Procedure DoDelete; override;
Procedure DoInsert; override;
Procedure DoApplyParams; override;
Function SQLQuery : TSQLQuery;
Function GetDataset : TDataset; override;
Function DoGetNewID : String; virtual;
Function GetNewID : String;
Function IDFieldValue : String; override;
procedure Notification(AComponent: TComponent; Operation: TOperation); override;
Property SelectSQL : TStrings Index 0 Read GetS Write SetS;
Property UpdateSQL : TStrings Index 1 Read GetS Write SetS;
Property DeleteSQL : TStrings Index 2 Read GetS Write SetS;
Property InsertSQL : TStrings Index 3 Read GetS Write SetS;
Property Connection : TSQLConnection Read FConnection Write SetConnection;
Property OnGetNewID : TNewIDEvent Read FOnGetNewID Write FOnGetNewID;
property OnGetParameterType : TGetParamTypeEvent Read FOnGetParamType Write FOnGetParamType;
property OnGetParameterValue : TGetParamValueEvent Read FOnGetParamValue Write FOnGetParamValue;
Property OnGetDataset : TNotifyEvent Read FONGetDataset Write FOnGetDataset;
Property Params : TParams Read FParams Write SetParams;
Public
Constructor Create(AOwner : TComponent); override;
Destructor Destroy; override;
end;
TSQLDBWebDataProvider = Class(TCustomSQLDBWebDataProvider)
Published
Property SelectSQL;
Property UpdateSQL;
Property DeleteSQL;
Property InsertSQL;
Property Connection;
Property IDFieldName;
Property OnGetNewID;
property OnGetParameterType;
property OnGetParameterValue;
Property OnGetDataset;
Property Options;
Property Params;
end;
implementation
{ $define wmdebug}
{$ifdef wmdebug}
uses dbugintf;
{$endif}
resourcestring
SErrNoSelectSQL = '%s: No select SQL statement provided.';
SErrNoUpdateSQL = '%s: No update SQL statement provided.';
SErrNoInsertSQL = '%s: No insert SQL statement provided.';
SErrNoDeleteSQL = '%s: No delete SQL statement provided.';
SErrUpdating = '%s: An error occurred during the update operation: %s';
SErrDeleting = '%s: An error occurred during the delete operation: %s';
SErrInserting = '%s: An error occurred during the insert operation: %s';
SErrNoNewIDEvent = '%s : Cannot generate ID: No OnGetNewID event assigned.';
{ TCustomSQLDBWebDataProvider }
function TCustomSQLDBWebDataProvider.GetS(AIndex: integer): TStrings;
begin
Result:=FSQLS[AIndex];
end;
procedure TCustomSQLDBWebDataProvider.SetConnection(const AValue: TSQLConnection
);
begin
if (FConnection=AValue) then exit;
If Assigned(FConnection) then
FConnection.RemoveFreeNotification(Self);
FConnection:=AValue;
If Assigned(FConnection) then
FConnection.FreeNotification(Self);
end;
procedure TCustomSQLDBWebDataProvider.SetParams(const AValue: TParams);
begin
if FParams=AValue then exit;
FParams.Assign(AValue);
end;
procedure TCustomSQLDBWebDataProvider.SetS(AIndex: integer;
const AValue: TStrings);
begin
FSQLS[AIndex].Assign(AValue);
end;
procedure TCustomSQLDBWebDataProvider.SQLChanged(Sender: TObject);
begin
If (Sender=SelectSQL) then
begin
if Assigned(FQuery) then
begin
FQuery.Close;
FQuery.SQL.Assign(SelectSQL);
end;
If Not (csLoading in ComponentState) then
RegenerateParams;
end;
end;
procedure TCustomSQLDBWebDataProvider.RegenerateParams;
Var
S : String;
begin
S:=SelectSQL.Text;
Params.Clear;
Params.ParseSQL(S,True);
end;
procedure TCustomSQLDBWebDataProvider.ExecuteSQL(ASQL : TStrings; Msg : String = ''; DoNewID : Boolean = False);
Var
Q : TSQLQuery;
begin
{$ifdef wmdebug}SendDebug('Entering TCustomSQLDBWebDataProvider.ExecuteSQL');{$endif}
Q:=CreateQuery(Nil,Nil,ASQL);
try
Q.Transaction.Active:=True;
try
ApplySQLParams(Q,DoNewID);
Q.ExecSQL;
(Q.Transaction as TSQLTransaction).Commit;
except
On E : Exception do
begin
(Q.Transaction as TSQLTransaction).Rollback;
If (Msg<>'') then
E.Message:=Format(Msg,[Self.Name,E.Message]);
Raise;
end;
end
finally
Q.Free;
end;
{$ifdef wmdebug}SendDebug('Exiting TCustomSQLDBWebDataProvider.ExecuteSQL');{$endif}
end;
procedure TCustomSQLDBWebDataProvider.DoUpdate;
begin
{$ifdef wmdebug}SendDebug('Entering TCustomSQLDBWebDataProvider.DoUpdate');{$endif}
If (Trim(UpdateSQL.Text)='') then
Raise EFPHTTPError.CreateFmt(SErrNoUpdateSQL,[Self.Name]);
FLastNewID:='';
ExecuteSQL(UpdateSQL,SErrUpdating);
{$ifdef wmdebug}SendDebug('Exiting TCustomSQLDBWebDataProvider.DoUpdate');{$endif}
end;
procedure TCustomSQLDBWebDataProvider.DoDelete;
begin
{$ifdef wmdebug}SendDebug('Entering TCustomSQLDBWebDataProvider.DoDelete');{$endif}
If (Trim(DeleteSQL.Text)='') then
Raise EFPHTTPError.CreateFmt(SErrNoDeleteSQL,[Self.Name]);
FLastNewID:='';
ExecuteSQL(DeleteSQL,SErrDeleting);
{$ifdef wmdebug}SendDebug('Exiting TCustomSQLDBWebDataProvider.DoDelete');{$endif}
end;
procedure TCustomSQLDBWebDataProvider.DoInsert;
begin
{$ifdef wmdebug}SendDebug('Entering TCustomSQLDBWebDataProvider.DoInsert');{$endif}
If (Trim(InsertSQL.Text)='') then
Raise EFPHTTPError.CreateFmt(SErrNoInsertSQL,[Self.Name]);
FLastNewID:='';
ExecuteSQL(InsertSQL,SErrInserting,(IDFieldName<>''));
{$ifdef wmdebug}SendDebug('Exiting TCustomSQLDBWebDataProvider.DoInsert');{$endif}
end;
procedure TCustomSQLDBWebDataProvider.Notification(AComponent: TComponent;
Operation: TOperation);
begin
inherited;
If (Operation=opRemove) then
begin
If (AComponent=FQuery) then
FQuery:=Nil
else if (AComponent=FConnection) then
FConnection:=Nil;
end;
end;
Function TCustomSQLDBWebDataProvider.CreateQuery(AOwner : TComponent; ATransaction : TSQLTransaction; ASQL : Tstrings) : TSQLQuery;
begin
Result:=TSQLQuery.Create(AOwner);
If (AOwner<>Self) then
Result.FreeNotification(Self);
Result.DataBase:=Connection;
If ATransaction=Nil then
begin
ATransaction:=TSQLTransaction.Create(Result);
ATransaction.DataBase:=Connection;
end;
Result.Transaction:=ATransaction;
Result.SQL.Assign(ASQL);
end;
Function TCustomSQLDBWebDataProvider.CheckDataset : boolean;
begin
{$ifdef wmdebug}SendDebug('Entering CheckDataset');{$endif}
If (Trim(SelectSQL.Text)='') then
Raise EFPHTTPError.CreateFmt(SErrNoSelectSQL,[Self.Name]);
Result:=FQuery=Nil;
If (Result) then
FQuery:=CreateQuery(Nil,Nil,SelectSQL)
else if not FQuery.Active then
FQuery.SQL.Assign(SelectSQL);
{$ifdef wmdebug}SendDebug('Exiting CheckDataset');{$endif}
end;
Function TCustomSQLDBWebDataProvider.GetParamType(P : TParam; Const AValue : String) : TFieldType;
begin
Result:=ftunknown;
If Assigned(FOnGetParamType) then
FOnGetParamType(Self,P.Name,AValue,Result);
end;
procedure TCustomSQLDBWebDataProvider.SetTypedParam(P : TParam; Const AValue : String);
Var
I : Integer;
Q : Int64;
D : TDateTime;
ft : TFieldType;
F : Double;
B : Boolean;
C : Currency;
begin
ft:=GetParamtype(P,AValue);
If (AValue='') and (not (ft in [ftString,ftFixedChar,ftWideString,ftFixedWideChar])) then
begin
P.Clear;
exit;
end;
If (ft<>ftUnknown) then
begin
try
case ft of
ftInteger,
ftword,
ftsmallint : I:=StrToInt(AValue);
ftDate : D:=StrToDate(AValue);
ftDateTime,
ftTimestamp : D:=StrToDateTime(AValue);
ftBoolean : B:=StrToBool(AValue);
ftTime : D:=StrToTime(AValue);
ftLargeint : Q:=StrToInt64(AValue);
ftCurrency : C:=StrToCurr(Avalue);
else
ft:=ftString
end
except
ft:=ftUnknown
end;
end;
If (ft=ftUnknown) and (Length(AValue)<30) then
begin
if TryStrToInt(Avalue,I) then
ft:=ftInteger
else if TryStrToInt64(Avalue,Q) then
ft:=ftInteger
else if (Pos(DateSeparator,AValue)<>0) then
begin
if (Pos(TimeSeparator,AValue)<>0) and TryStrToDateTime(Avalue,D) then
ft:=ftDateTime
else if TryStrToDate(Avalue,D) then
ft:=ftDate
end
else If (Pos(TimeSeparator,AValue)<>0) and TryStrToTime(Avalue,D) then
ft:=ftTime
else if (Pos(DecimalSeparator,AValue)<>0) then
begin
if trystrtofloat(AValue,F) then
ft:=ftFloat
else if TryStrToCurr(Avalue,C) then
ft:=ftCurrency
end
else if TryStrToBool(Avalue,B) then
ft:=ftBoolean
end;
Case ft of
ftInteger,
ftword,
ftsmallint : P.AsInteger:=I;
ftBoolean : P.AsBoolean:=B;
ftLargeInt : P.AsLargeInt:=Q;
ftDate : P.AsDate:=D;
ftDateTime,
ftTimestamp : P.AsDateTime:=D;
ftTime : P.AsTime:=D;
ftFloat,
ftBCD,
ftFMTBCD : P.AsFloat:=F;
ftCurrency : P.AsCurrency:=F;
else
P.AsString:=AValue;
end;
end;
procedure TCustomSQLDBWebDataProvider.ApplySQLParams(AQuery : TSQLQuery; DoNewID : Boolean = False);
function TryAdaptor (const aName: string; P: TParam) : boolean;
var S : string;
begin
result := Adaptor.TryFieldValue(aName,S);
if not result then
result := Adaptor.TryParamValue(aName,S);
if result then
SetTypedParam(P,S);
end;
var
I: Integer;
P : TParam;
S : String;
B : Boolean;
begin
{$ifdef wmdebug}SendDebug('Entering ApplySQLPArams');{$endif}
For I:=0 to AQuery.Params.Count-1 do
begin
P:=AQuery.Params[i];
B:=Assigned(FOnGetParamValue);
if B then
FOnGetParamValue(Self,P,B);
if not B then
begin
If (P.Name=IDFieldName) then
begin
if DoNewID then
begin
GetNewID;
SetTypedParam(P,FLastNewID)
end
else
begin
if not TryAdaptor (P.Name, P) then
TryAdaptor('ID', P);
end;
end
else if not TryAdaptor (P.Name, P) then
P.Clear;
end;
end;
{$ifdef wmdebug}SendDebug('Exiting ApplySQLPArams');{$endif}
end;
procedure TCustomSQLDBWebDataProvider.DoApplyParams;
begin
CheckDataset;
ApplySQLParams(FQuery);
end;
function TCustomSQLDBWebDataProvider.SQLQuery: TSQLQuery;
begin
Result:=FQuery;
end;
function TCustomSQLDBWebDataProvider.GetDataset: TDataset;
begin
{$ifdef wmdebug}SendDebug('Get dataset: checking dataset');{$endif}
If Assigned(FonGetDataset) then
FOnGetDataset(Self);
CheckDataset;
FLastNewID:='';
Result:=FQuery;
{$ifdef wmdebug}SendDebug('Get dataset: activating transaction');{$endif}
If Not FQuery.Transaction.Active then
FQuery.Transaction.Active:=True;
{$ifdef wmdebug}SendDebug('Get dataset: done');{$endif}
end;
function TCustomSQLDBWebDataProvider.DoGetNewID: String;
begin
If Not Assigned(FOnGetNewID) then
Raise EFPHTTPError.CreateFmt(SErrNoNewIDEvent,[Self.Name]);
FOnGetNewID(Self,Result);
end;
function TCustomSQLDBWebDataProvider.GetNewID: String;
begin
Result:=DoGetNewID;
FLastNewID:=Result;
end;
function TCustomSQLDBWebDataProvider.IDFieldValue: String;
begin
{$ifdef wmdebug}SendDebug('Entering IDFieldValue');{$endif}
If (FLastNewID<>'') then
Result:=FLastNewID
else If (IDFieldName<>'') then
begin
If not Adaptor.TryParamValue(IDFieldName,Result) then
If not Adaptor.TryFieldValue(IDFieldName,Result) then
Result:=inherited IDFieldValue;
end
else
Result:=inherited IDFieldValue;
{$ifdef wmdebug}SendDebug('Exiting IDFieldValue : '+Result);{$endif}
end;
constructor TCustomSQLDBWebDataProvider.Create(AOwner: TComponent);
Var
I : Integer;
L : TStringList;
begin
inherited Create(AOwner);
For I:=0 to 3 do
begin
L:=TStringList.Create;
L.OnChange:=@SQLChanged;
FSQLS[i]:=L;
end;
FParams:=TParams.Create(TParam);
end;
destructor TCustomSQLDBWebDataProvider.Destroy;
Var
I: Integer;
begin
For I:=0 to 3 do
FreeAndNil(FSQLS[i]);
Connection:=Nil;
FreeAndNil(FQuery);
FreeAndNil(FParams);
inherited Destroy;
end;
end.