From 075e978367fd7154bd45571dcb8dbc03bb8bb671 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C3=ABl=20Van=20Canneyt?= Date: Mon, 16 Oct 2023 14:18:37 +0200 Subject: [PATCH] * Close dataset on SQL change. Fixes issue #39610 (manually merged) (cherry picked from commit a61d60664309bc3a49446bf78a319c96aac94229) --- packages/fcl-db/src/sqldb/sqldb.pp | 17 ++++++++++++++- packages/fcl-db/tests/testsqldb.pas | 34 +++++++++++++++++++++++++++++ 2 files changed, 50 insertions(+), 1 deletion(-) diff --git a/packages/fcl-db/src/sqldb/sqldb.pp b/packages/fcl-db/src/sqldb/sqldb.pp index 0c271c25dd..654381682b 100644 --- a/packages/fcl-db/src/sqldb/sqldb.pp +++ b/packages/fcl-db/src/sqldb/sqldb.pp @@ -365,6 +365,7 @@ type Private FCursor : TSQLCursor; FDatabase: TSQLConnection; + FOnSQLChanged: TNotifyEvent; FParamCheck: Boolean; FParams: TParams; FMacroCheck: Boolean; @@ -423,6 +424,8 @@ type Property ParseSQL : Boolean Read FParseSQL Write FParseSQL; Property ParamCheck : Boolean Read FParamCheck Write FParamCheck default true; Property MacroCheck : Boolean Read FMacroCheck Write SetMacroCheck default false; + Property InfoQuery : Boolean Read FInfoQuery Write FInfoQuery; + Property OnSQLChanged : TNotifyEvent Read FOnSQLChanged Write FOnSQLChanged; Public constructor Create(AOwner : TComponent); override; destructor Destroy; override; @@ -474,7 +477,7 @@ type { TCustomSQLQuery } - TSQLQueryOption = (sqoKeepOpenOnCommit, sqoAutoApplyUpdates, sqoAutoCommit, sqoCancelUpdatesOnRefresh, sqoRefreshUsingSelect); + TSQLQueryOption = (sqoKeepOpenOnCommit, sqoAutoApplyUpdates, sqoAutoCommit, sqoCancelUpdatesOnRefresh, sqoRefreshUsingSelect, sqoNoCloseOnSQLChange); TSQLQueryOptions = Set of TSQLQueryOption; TCustomSQLQuery = class (TCustomBufDataset) @@ -524,6 +527,7 @@ type function HasMacros: Boolean; Function HasParams : Boolean; Function NeedLastInsertID: TField; + procedure OnChangeSelectSQL(Sender: TObject); procedure SetMacroChar(AValue: Char); procedure SetOptions(AValue: TSQLQueryOptions); procedure SetParamCheck(AValue: Boolean); @@ -933,6 +937,8 @@ var NewParams: TSQLDBParams; begin + if Assigned(FOnSQLChanged) then + FOnSQLChanged(Self); UnPrepare; RecreateMacros; if not ParamCheck then @@ -2785,6 +2791,7 @@ begin If ParamCheck and Assigned(FDataLink) then (FDataLink as TMasterParamsDataLink).RefreshParamNames; FQuery.ServerIndexDefs.Updated:=false; + end; { TCustomSQLQuery } @@ -2801,6 +2808,7 @@ constructor TCustomSQLQuery.Create(AOwner : TComponent); begin inherited Create(AOwner); FStatement:=CreateSQLStatement(Self); + FStatement.OnSQLChanged:=@OnChangeSelectSQL; FInsertSQL := TStringList.Create; FInsertSQL.OnChange := @OnChangeModifySQL; @@ -3408,6 +3416,13 @@ begin end end; +procedure TCustomSQLQuery.OnChangeSelectSQL(Sender: TObject); +begin + if (sqoNoCloseOnSQLChange in Options) then + exit; + Close; +end; + procedure TCustomSQLQuery.SetMacroChar(AValue: Char); begin FStatement.MacroChar:=AValue; diff --git a/packages/fcl-db/tests/testsqldb.pas b/packages/fcl-db/tests/testsqldb.pas index d5e517733a..ac4c9c719a 100644 --- a/packages/fcl-db/tests/testsqldb.pas +++ b/packages/fcl-db/tests/testsqldb.pas @@ -61,6 +61,8 @@ type procedure TestMacros; Procedure TestPrepareCount; Procedure TestNullTypeParam; + procedure TestChangeSQLCloseUnprepare; + procedure TestChangeSQLCloseUnprepareDisabled; end; { TTestTSQLConnection } @@ -824,6 +826,38 @@ begin SQLDBConnector.Connection.OnLog:=Nil; end; end; +procedure TTestTSQLQuery.TestChangeSQLCloseUnprepare; +begin + with SQLDBConnector.GetNDataset(10) as TSQLQuery do + begin + Open; + AssertTrue('Prepared after open', Prepared); + SQL.Text := 'SELECT * FROM FPDEV WHERE ID<0'; + // statement must be unprepared when SQL is changed + AssertFalse('Prepared after SQL changed', Prepared); + // dataset remained active in FPC <= 3.2.2 + AssertFalse('Active after SQL changed', Active); + SQL.Text := 'UPDATE FPDEV SET NAME=''Test'' WHERE ID>100'; + ExecSQL; + end; +end; +procedure TTestTSQLQuery.TestChangeSQLCloseUnprepareDisabled; +begin + with SQLDBConnector.GetNDataset(10) as TSQLQuery do + begin + OPtions:=OPtions+[sqoNoCloseOnSQLChange]; + Open; + AssertTrue('Prepared after open', Prepared); + SQL.Text := 'SELECT * FROM FPDEV WHERE ID<0'; + // statement must be unprepared when SQL is changed + AssertFalse('Prepared after SQL changed', Prepared); + // dataset remained active in FPC <= 3.2.2 + AssertTrue('Active after SQL changed', Active); + Close; + SQL.Text := 'UPDATE FPDEV SET NAME=''Test'' WHERE ID>100'; + ExecSQL; + end; +end; { TTestTSQLConnection }