* Fixed Master/Detail relation in SQLDB and fixed memory leak

git-svn-id: trunk@25055 -
This commit is contained in:
michael 2013-07-07 18:14:11 +00:00
parent 2cdb4adf39
commit 087b6b4a39
3 changed files with 78 additions and 48 deletions

View File

@ -355,6 +355,7 @@ end;
procedure TIBConnection.DoInternalDisconnect;
begin
Inherited;
FDialect := INVALID_DATA;
if not Connected then
begin

View File

@ -41,10 +41,12 @@ type
WhereStopPos : integer;
end;
type
TSQLConnection = class;
TSQLTransaction = class;
TCustomSQLQuery = class;
TCustomSQLStatement = Class;
TSQLQuery = class;
TSQLScript = class;
@ -106,7 +108,7 @@ type
FHostName : string;
FCharSet : string;
FRole : String;
FStatements : TFPList;
function GetPort: cardinal;
function GetStatementInfo(const ASQL: string; Full: Boolean; ASchema : TSchemaType): TSQLStatementInfo;
procedure SetPort(const AValue: cardinal);
@ -126,6 +128,8 @@ type
Function AllocateCursorHandle : TSQLCursor; virtual; abstract;
Procedure DeAllocateCursorHandle(var cursor : TSQLCursor); virtual; abstract;
Function AllocateTransactionHandle : TSQLHandle; virtual; abstract;
Procedure RegisterStatement(S : TCustomSQLStatement);
Procedure UnRegisterStatement(S : TCustomSQLStatement);
procedure PrepareStatement(cursor: TSQLCursor;ATransaction : TSQLTransaction;buf : string; AParams : TParams); virtual; abstract;
procedure Execute(cursor: TSQLCursor;atransaction:tSQLtransaction; AParams : TParams); virtual; abstract;
@ -145,6 +149,7 @@ type
function GetSchemaInfoSQL(SchemaType : TSchemaType; SchemaObjectName, SchemaPattern : string) : string; virtual;
procedure LoadBlobIntoBuffer(FieldDef: TFieldDef;ABlobBuf: PBufBlobField; cursor: TSQLCursor; ATransaction : TSQLTransaction); virtual; abstract;
function RowsAffected(cursor: TSQLCursor): TRowsCount; virtual;
Property Statements : TFPList Read FStatements;
property Port: cardinal read GetPort write SetPort;
public
property Handle: Pointer read GetHandle;
@ -224,17 +229,19 @@ type
FOrigSQL : String;
FServerSQL : String;
FTransaction: TSQLTransaction;
FDatasource : TDatasource;
FParseSQL: Boolean;
FDataLink : TDataLink;
procedure SetDatabase(AValue: TSQLConnection);
procedure SetParams(AValue: TParams);
procedure SetSQL(AValue: TStrings);
procedure SetTransaction(AValue: TSQLTransaction);
Function GetPrepared : Boolean;
Protected
Function CreateDataLink : TDataLink; virtual;
procedure OnChangeSQL(Sender : TObject); virtual;
function GetDataSource: TDatasource; Virtual;
procedure SetDataSource(AValue: TDatasource); virtual;
Procedure CopyParamsFromMaster(CopyBound : Boolean); virtual;
procedure AllocateCursor;
procedure DeAllocateCursor;
Function GetSchemaType : TSchemaType; virtual;
@ -285,7 +292,6 @@ type
private
// FCheckParams: Boolean;
// FCursor : TSQLCursor;
FParams: TParams;
FSchemaType: TSchemaType;
// FSQL: TStringlist;
FUpdateable : boolean;
@ -673,13 +679,18 @@ end;
procedure TCustomSQLStatement.SetDataSource(AValue: TDatasource);
begin
if FDatasource=AValue then Exit;
If Assigned(FDatasource) then
FDatasource.RemoveFreeNotification(Self);
FDatasource:=AValue;
If Assigned(FDatasource) then
FDatasource.FreeNotification(Self);
if GetDatasource=AValue then Exit;
if (FDataLink=Nil) then
FDataLink:=CreateDataLink;
FDataLink.DataSource:=AValue;
end;
procedure TCustomSQLStatement.CopyParamsFromMaster(CopyBound : Boolean);
begin
if Assigned(DataSource) and Assigned(DataSource.Dataset) then
FParams.CopyParamValuesFromDataset(DataSource.Dataset,CopyBound);
end;
procedure TCustomSQLStatement.SetParams(AValue: TParams);
@ -711,8 +722,8 @@ end;
procedure TCustomSQLStatement.DoExecute;
begin
If (FParams.Count>0) and Assigned(FDatasource) then
; // FMasterLink.CopyParamsFromMaster(False);
If (FParams.Count>0) and Assigned(Datasource) then
CopyParamsFromMaster(False);
If LogEvent(detExecute) then
Log(detExecute,FServerSQL);
Database.Execute(FCursor,Transaction, FParams);
@ -723,6 +734,11 @@ begin
Result := Assigned(FCursor) and FCursor.FPrepared;
end;
function TCustomSQLStatement.CreateDataLink: TDataLink;
begin
Result:=TDataLink.Create;
end;
function TCustomSQLStatement.CreateParams: TParams;
begin
Result:=TParams.Create(Nil);
@ -756,7 +772,10 @@ begin
If (AComponent=FTransaction) then
FTransaction:=Nil
else if (AComponent=FDatabase) then
begin
UnPrepare;
FDatabase:=Nil;
end;
end;
constructor TCustomSQLStatement.Create(AOwner: TComponent);
@ -774,6 +793,8 @@ begin
UnPrepare;
Transaction:=Nil;
Database:=Nil;
DataSource:=Nil;
FreeAndNil(FDataLink);
FreeAndNil(Fparams);
FreeAndNil(FSQL);
inherited Destroy;
@ -812,13 +833,20 @@ procedure TCustomSQLStatement.AllocateCursor;
begin
if not assigned(FCursor) then
begin
// Do this as late as possible.
FCursor:=Database.AllocateCursorHandle;
FDatabase.RegisterStatement(Self);
end;
end;
procedure TCustomSQLStatement.DeAllocateCursor;
begin
if Assigned(FCursor) and Assigned(Database) then
begin
DataBase.DeAllocateCursorHandle(FCursor);
Database.UnRegisterStatement(Self);
end;
end;
procedure TCustomSQLStatement.DoPrepare;
@ -861,7 +889,7 @@ begin
DoPrepare;
except
if assigned(FCursor) then
DataBase.DeAllocateCursorHandle(FCursor);
DeAllocateCursor;
Raise;
end;
end;
@ -887,7 +915,10 @@ end;
function TCustomSQLStatement.GetDataSource: TDatasource;
begin
Result:=FDatasource;
if Assigned(FDataLink) then
Result:=FDataLink.Datasource
else
Result:=Nil;
end;
procedure TCustomSQLStatement.Unprepare;
@ -950,11 +981,19 @@ begin
end;
procedure TSQLConnection.DoInternalDisconnect;
Var
I : integer;
begin
For I:=0 to FStatements.Count-1 do
TCustomSQLStatement(FStatements[i]).Unprepare;
end;
destructor TSQLConnection.Destroy;
begin
Connected:=False; // needed because we want to de-allocate statements
FreeAndNil(FStatements);
inherited Destroy;
end;
@ -974,13 +1013,14 @@ begin
Transaction.EndTransaction;
end;
Procedure TSQLConnection.ExecuteDirect(SQL: String);
procedure TSQLConnection.ExecuteDirect(SQL: String);
begin
ExecuteDirect(SQL,FTransaction);
end;
Procedure TSQLConnection.ExecuteDirect(SQL: String; ATransaction : TSQLTransaction);
procedure TSQLConnection.ExecuteDirect(SQL: String;
ATransaction: TSQLTransaction);
var Cursor : TSQLCursor;
@ -1059,6 +1099,7 @@ begin
inherited Create(AOwner);
FSQLFormatSettings:=DefaultSQLFormatSettings;
FFieldNameQuoteChars:=DoubleQuotes;
FStatements:=TFPList.Create;
end;
procedure TSQLConnection.GetTableNames(List: TStrings; SystemTables: Boolean);
@ -1162,6 +1203,17 @@ begin
end;
end;
procedure TSQLConnection.RegisterStatement(S: TCustomSQLStatement);
begin
if FStatements.IndexOf(S)=-1 then
FStatements.Add(S);
end;
procedure TSQLConnection.UnRegisterStatement(S: TCustomSQLStatement);
begin
FStatements.Remove(S);
end;
procedure TSQLConnection.FreeFldBuffers(cursor: TSQLCursor);
begin
// empty
@ -1631,7 +1683,8 @@ begin
end;
*)
Function TSQLConnection.GetStatementInfo(const ASQL : string; Full : Boolean; ASchema : TSchemaType) : TSQLStatementInfo;
function TSQLConnection.GetStatementInfo(const ASQL: string; Full: Boolean;
ASchema: TSchemaType): TSQLStatementInfo;
type TParsePart = (ppStart,ppWith,ppSelect,ppTableName,ppFrom,ppWhere,ppGroup,ppOrder,ppBogus);
@ -1903,39 +1956,20 @@ Type
TQuerySQLStatement = Class(TCustomSQLStatement)
protected
FMasterLink: TMasterParamsDataLink;
FQuery : TCustomSQLQuery;
function GetDataSource: TDatasource; override;
procedure SetDataSource(AValue: TDatasource); override;
Function CreateDataLink : TDataLink; override;
Function GetSchemaType : TSchemaType; override;
Function GetSchemaObjectName : String; override;
Function GetSchemaPattern: String; override;
procedure GetStatementInfo(Var ASQL: String; Full: Boolean; ASchema: TSchemaType; out Info: TSQLStatementInfo); override;
procedure OnChangeSQL(Sender : TObject); override;
Public
destructor Destroy; override;
end;
{ TQuerySQLStatement }
function TQuerySQLStatement.GetDataSource: TDatasource;
function TQuerySQLStatement.CreateDataLink: TDataLink;
begin
Result:=inherited GetDataSource;
end;
procedure TQuerySQLStatement.SetDataSource(AValue: TDatasource);
begin
inherited SetDataSource(AValue);
If Assigned(AValue) then
begin
AValue.FreeNotification(Self);
If (FMasterLink=Nil) then
FMasterLink:=TMasterParamsDataLink.Create(FQuery);
FMasterLink.Datasource:=AValue;
end
else
FreeAndNil(FMasterLink);
Result:=TMasterParamsDataLink.Create(FQuery);
end;
function TQuerySQLStatement.GetSchemaType: TSchemaType;
@ -1981,17 +2015,11 @@ procedure TQuerySQLStatement.OnChangeSQL(Sender: TObject);
begin
UnPrepare;
inherited OnChangeSQL(Sender);
If CheckParams and Assigned(FMasterLink) then
FMasterLink.RefreshParamNames;
If CheckParams and Assigned(FDataLink) then
(FDataLink as TMasterParamsDataLink).RefreshParamNames;
FQuery.ServerIndexDefs.Updated:=false;
end;
destructor TQuerySQLStatement.Destroy;
begin
FreeAndNil(FMasterLink);
inherited Destroy;
end;
constructor TCustomSQLQuery.Create(AOwner : TComponent);
Var
@ -1999,7 +2027,6 @@ Var
begin
inherited Create(AOwner);
FParams := TParams.create(self);
F:=TQuerySQLStatement.Create(Self);
F.FQuery:=Self;
FStatement:=F;
@ -2034,7 +2061,6 @@ begin
if Active then Close;
UnPrepare;
FreeAndNil(Fstatement);
FreeAndNil(FParams);
// FreeAndNil(FSQL);
FreeAndNil(FInsertSQL);
FreeAndNil(FDeleteSQL);

View File

@ -5,6 +5,9 @@ if [ $? != 0 ]; then
echo "Compilation failed";
exit
fi
echo "Generating test list"
./dbtestframework --list 2>/dev/null | sed /TestSuites/d | tr -d '[:blank:]' > test-list.txt
exit
for f in `cat test-list.txt`
do
echo -n "Doing test $f"