ViewVC Help
View File | Revision Log | Show Annotations | Download File | View Changeset | Root Listing
root/public/ibx/branches/journaling/fbintf/client/FBStatement.pas
(Generate patch)

Comparing:
ibx/trunk/fbintf/client/FBStatement.pas (file contents), Revision 209 by tony, Wed Mar 14 12:48:51 2018 UTC vs.
ibx/branches/journaling/fbintf/client/FBStatement.pas (file contents), Revision 363 by tony, Tue Dec 7 13:30:05 2021 UTC

# Line 44 | Line 44 | uses
44    Classes, SysUtils,  IB,  FBClientAPI, FBSQLData, FBOutputBlock, FBActivityMonitor,
45    FBTransaction;
46  
47 + const
48 +  DefaultBatchRowLimit = 1000;
49 +
50   type
51    TPerfStatistics = array[psCurrentMemory..psFetches] of Int64;
52  
53    { TFBStatement }
54  
55 <  TFBStatement = class(TActivityReporter)
55 >  TFBStatement = class(TActivityReporter,ITransactionUser)
56    private
57      FAttachmentIntf: IAttachment;
58 +    FFirebirdClientAPI: TFBClientAPI;
59    protected
60      FTransactionIntf: ITransaction;
61      FExecTransactionIntf: ITransaction;
62 +    FStaleReferenceChecks: boolean;
63      FSQLStatementType: TIBSQLStatementTypes;         { Select, update, delete, insert, create, alter, etc...}
64      FSQLDialect: integer;
65      FOpen: boolean;
# Line 72 | Line 77 | type
77      FStatisticsAvailable: boolean;
78      FBeforeStats: TPerfStatistics;
79      FAfterStats: TPerfStatistics;
80 +    FCaseSensitiveParams: boolean;
81 +    FBatchRowLimit: integer;
82 +    procedure CheckChangeBatchRowLimit; virtual;
83      procedure CheckHandle; virtual; abstract;
84      procedure CheckTransaction(aTransaction: ITransaction);
85 +    procedure DoJournaling;
86 +    function GetJournalIntf: IJournallingHook;
87 +    function GetStatementIntf: IStatement; virtual; abstract;
88      procedure GetDsqlInfo(info_request: byte; buffer: ISQLInfoResults); overload; virtual; abstract;
89 <    procedure InternalPrepare;  virtual; abstract;
90 <    function InternalExecute(aTransaction: ITransaction): IResults;  virtual; abstract;
91 <    function InternalOpenCursor(aTransaction: ITransaction): IResultSet;   virtual; abstract;
89 >    procedure InternalPrepare(CursorName: AnsiString='');  virtual; abstract;
90 >    function InternalExecute(Transaction: ITransaction): IResults;  virtual; abstract;
91 >    function InternalOpenCursor(aTransaction: ITransaction; Scrollable: boolean): IResultSet;   virtual; abstract;
92 >    procedure ProcessSQL(sql: AnsiString; GenerateParamNames: boolean; var processedSQL: AnsiString); virtual; abstract;
93      procedure FreeHandle;  virtual; abstract;
94      procedure InternalClose(Force: boolean); virtual; abstract;
95      function TimeStampToMSecs(const TimeStamp: TTimeStamp): Int64;
# Line 85 | Line 97 | type
97      constructor Create(Attachment: IAttachment; Transaction: ITransaction;
98        sql: AnsiString; SQLDialect: integer);
99      constructor CreateWithParameterNames(Attachment: IAttachment; Transaction: ITransaction;
100 <      sql: AnsiString;  SQLDialect: integer; GenerateParamNames: boolean =false);
100 >      sql: AnsiString;  SQLDialect: integer; GenerateParamNames: boolean =false;
101 >      CaseSensitiveParams: boolean = false);
102      destructor Destroy; override;
103      procedure Close;
104      procedure TransactionEnding(aTransaction: ITransaction; Force: boolean);
105      property SQLDialect: integer read FSQLDialect;
106 +    property FirebirdClientAPI: TFBClientAPI read FFirebirdClientAPI;
107  
108    public
109      function GetSQLParams: ISQLParams; virtual; abstract;
# Line 97 | Line 111 | type
111      function GetRowsAffected(var SelectCount, InsertCount, UpdateCount,
112        DeleteCount: integer): boolean;
113      function GetSQLStatementType: TIBSQLStatementTypes;
114 +    function GetSQLStatementTypeName: AnsiString;
115      function GetSQLText: AnsiString;
116 +    function GetProcessedSQLText: AnsiString;
117      function GetSQLDialect: integer;
118 +    function GetFlags: TStatementFlags; virtual;
119  
120      {GetDSQLInfo only supports isc_info_sql_stmt_type, isc_info_sql_get_plan, isc_info_sql_records}
121 <    procedure Prepare(aTransaction: ITransaction=nil); virtual;
121 >    procedure Prepare(aTransaction: ITransaction=nil);  overload;
122 >    procedure Prepare(CursorName: AnsiString; aTransaction: ITransaction=nil); overload; virtual;
123      function Execute(aTransaction: ITransaction=nil): IResults;
124 <    function OpenCursor(aTransaction: ITransaction=nil): IResultSet;
124 >    function OpenCursor(aTransaction: ITransaction=nil): IResultSet; overload;
125 >    function OpenCursor(Scrollable: boolean; aTransaction: ITransaction=nil): IResultSet; overload;
126      function CreateBlob(paramName: AnsiString): IBlob; overload;
127      function CreateBlob(index: integer): IBlob; overload;
128      function CreateBlob(column: TColumnMetaData): IBlob; overload; virtual; abstract;
# Line 116 | Line 135 | type
135      procedure SetRetainInterfaces(aValue: boolean); virtual;
136      procedure EnableStatistics(aValue: boolean);
137      function GetPerfStatistics(var stats: TPerfCounters): boolean;
138 +    function IsInBatchMode: boolean; virtual;
139 +    function HasBatchMode: boolean; virtual;
140 +  public
141 +    {IBatch support}
142 +    procedure AddToBatch; virtual;
143 +    function ExecuteBatch(aTransaction: ITransaction): IBatchCompletion; virtual;
144 +    procedure CancelBatch; virtual;
145 +    function GetBatchCompletion: IBatchCompletion; virtual;
146 +    function GetBatchRowLimit: integer;
147 +    procedure SetBatchRowLimit(aLimit: integer);
148 +    {Stale Reference Check}
149 +    procedure SetStaleReferenceChecks(Enable:boolean); {default true}
150 +    function GetStaleReferenceChecks: boolean;
151 +  public
152      property ChangeSeqNo: integer read FChangeSeqNo;
153      property SQLParams: ISQLParams read GetSQLParams;
154      property SQLStatementType: TIBSQLStatementTypes read GetSQLStatementType;
# Line 127 | Line 160 | uses FBMessages;
160  
161   { TFBStatement }
162  
163 + procedure TFBStatement.CheckChangeBatchRowLimit;
164 + begin
165 +  //Do Nothing
166 + end;
167 +
168   procedure TFBStatement.CheckTransaction(aTransaction: ITransaction);
169   begin
170    if (aTransaction = nil) then
# Line 136 | Line 174 | begin
174      IBError(ibxeNotInTransaction,[]);
175   end;
176  
177 + procedure TFBStatement.DoJournaling;
178 +  function doGetRowsAffected: integer;
179 +  var a,i,u,d: integer;
180 +  begin
181 +    GetRowsAffected(a,i,u,d);
182 +    Result := i + u + d;
183 +  end;
184 +
185 + var RowsAffected: integer;
186 + begin
187 +  RowsAffected := doGetRowsAffected;
188 +  with GetAttachment do
189 +    if JournalingActive and
190 +      (((joReadOnlyQueries in GetJournalOptions) and (RowsAffected = 0)) or
191 +      ((joModifyQueries in GetJournalOptions) and (RowsAffected > 0))) then
192 +      GetJournalIntf.ExecQuery(GetStatementIntf);
193 + end;
194 +
195 + function TFBStatement.GetJournalIntf: IJournallingHook;
196 + begin
197 +  GetAttachment.QueryInterface(IJournallingHook,Result)
198 + end;
199 +
200   function TFBStatement.TimeStampToMSecs(const TimeStamp: TTimeStamp): Int64;
201   begin
202    Result := TimeStamp.Time + Int64(timestamp.date)*msecsperday;
# Line 147 | Line 208 | begin
208    inherited Create(Transaction as TFBTransaction,2);
209    FAttachmentIntf := Attachment;
210    FTransactionIntf := Transaction;
211 +  FFirebirdClientAPI := Attachment.getFirebirdAPI as TFBClientAPI;
212    FSQLDialect := SQLDialect;
213    FSQL := sql;
214 +  FBatchRowLimit := DefaultBatchRowLimit;
215 +  FStaleReferenceChecks := true;
216   end;
217  
218   constructor TFBStatement.CreateWithParameterNames(Attachment: IAttachment;
219    Transaction: ITransaction; sql: AnsiString; SQLDialect: integer;
220 <  GenerateParamNames: boolean);
220 >  GenerateParamNames: boolean; CaseSensitiveParams: boolean);
221   begin
222    FHasParamNames := true;
223    FGenerateParamNames := GenerateParamNames;
224 +  FCaseSensitiveParams := CaseSensitiveParams;
225    Create(Attachment,Transaction,sql,SQLDialect);
226   end;
227  
# Line 175 | Line 240 | end;
240   procedure TFBStatement.TransactionEnding(aTransaction: ITransaction;
241    Force: boolean);
242   begin
243 <  if FOpen and (FExecTransactionIntf = aTransaction) then
243 >  if FOpen and ((FExecTransactionIntf as TObject) = (aTransaction as TObject)) then
244      InternalClose(Force);
245  
246    if FTransactionIntf = aTransaction then
# Line 223 | Line 288 | begin
288    Result := FSQLStatementType;
289   end;
290  
291 + function TFBStatement.GetSQLStatementTypeName: AnsiString;
292 + begin
293 +  case FSQLStatementType of
294 +  SQLUnknown: Result := 'SQL_Unknown';
295 +  SQLSelect: Result := 'SQL_Select';
296 +  SQLInsert: Result := 'SQL_Insert';
297 +  SQLUpdate: Result := 'SQL_Update';
298 +  SQLDelete: Result := 'SQL_Delete';
299 +  SQLDDL: Result := 'SQL_DDL';
300 +  SQLGetSegment: Result := 'SQL_GetSegment';
301 +  SQLPutSegment: Result := 'SQL_PutSegment';
302 +  SQLExecProcedure: Result := 'SQL_ExecProcedure';
303 +  SQLStartTransaction: Result := 'SQL_StartTransaction';
304 +  SQLCommit: Result := 'SQL_Commit';
305 +  SQLRollback: Result := 'SQL_Rollback';
306 +  SQLSelectForUpdate: Result := 'SQL_SelectForUpdate';
307 +  SQLSetGenerator: Result := 'SQL_SetGenerator';
308 +  SQLSavePoint: Result := 'SQL_SavePoint';
309 +  end;
310 + end;
311 +
312   function TFBStatement.GetSQLText: AnsiString;
313   begin
314    Result := FSQL;
315   end;
316  
317 + function TFBStatement.GetProcessedSQLText: AnsiString;
318 + begin
319 +  if not FHasParamNames then
320 +    Result := FSQL
321 +  else
322 +  begin
323 +    if FProcessedSQL = '' then
324 +      ProcessSQL(FSQL,FGenerateParamNames,FProcessedSQL);
325 +    Result := FProcessedSQL;
326 +  end;
327 + end;
328 +
329   function TFBStatement.GetSQLDialect: integer;
330   begin
331    Result := FSQLDialect;
332   end;
333  
334 + function TFBStatement.GetFlags: TStatementFlags;
335 + begin
336 +  Result := [];
337 + end;
338 +
339   procedure TFBStatement.Prepare(aTransaction: ITransaction);
340   begin
341 +  Prepare('',aTransaction);
342 + end;
343 +
344 + procedure TFBStatement.Prepare(CursorName: AnsiString;
345 +  aTransaction: ITransaction);
346 + begin
347    if FPrepared then FreeHandle;
348    if aTransaction <> nil then
349    begin
# Line 242 | Line 351 | begin
351      FTransactionIntf := aTransaction;
352      AddMonitor(FTransactionIntf as TFBTransaction);
353    end;
354 <  InternalPrepare;
354 >  InternalPrepare(CursorName);
355   end;
356  
357   function TFBStatement.Execute(aTransaction: ITransaction): IResults;
# Line 251 | Line 360 | begin
360      Result :=  InternalExecute(FTransactionIntf)
361    else
362      Result := InternalExecute(aTransaction);
363 +  DoJournaling;
364 + end;
365 +
366 + procedure TFBStatement.AddToBatch;
367 + begin
368 +  IBError(ibxeBatchModeNotSupported,[]);
369 + end;
370 +
371 + function TFBStatement.ExecuteBatch(aTransaction: ITransaction
372 +  ): IBatchCompletion;
373 + begin
374 +  IBError(ibxeBatchModeNotSupported,[]);
375 + end;
376 +
377 + procedure TFBStatement.CancelBatch;
378 + begin
379 +  IBError(ibxeBatchModeNotSupported,[]);
380 + end;
381 +
382 + function TFBStatement.GetBatchCompletion: IBatchCompletion;
383 + begin
384 +  IBError(ibxeBatchModeNotSupported,[]);
385 + end;
386 +
387 + function TFBStatement.GetBatchRowLimit: integer;
388 + begin
389 +  Result := FBatchRowLimit;
390 + end;
391 +
392 + procedure TFBStatement.SetBatchRowLimit(aLimit: integer);
393 + begin
394 +  CheckChangeBatchRowLimit;
395 +  FBatchRowLimit := aLimit;
396 + end;
397 +
398 + procedure TFBStatement.SetStaleReferenceChecks(Enable: boolean);
399 + begin
400 +  FStaleReferenceChecks := Enable;
401 + end;
402 +
403 + function TFBStatement.GetStaleReferenceChecks: boolean;
404 + begin
405 +  Result := FStaleReferenceChecks;
406   end;
407  
408   function TFBStatement.OpenCursor(aTransaction: ITransaction): IResultSet;
409   begin
410 +  Result := OpenCursor(false,aTransaction);
411 + end;
412 +
413 + function TFBStatement.OpenCursor(Scrollable: boolean; aTransaction: ITransaction
414 +  ): IResultSet;
415 + begin
416    Close;
417    if aTransaction = nil then
418 <    Result := InternalOpenCursor(FTransactionIntf)
418 >    Result := InternalOpenCursor(FTransactionIntf,Scrollable)
419    else
420 <    Result := InternalOpenCursor(aTransaction);
420 >    Result := InternalOpenCursor(aTransaction,Scrollable);
421 >  DoJournaling;
422   end;
423  
424   function TFBStatement.CreateBlob(paramName: AnsiString): IBlob;
# Line 306 | Line 465 | end;
465  
466   function TFBStatement.GetDSQLInfo(Request: byte): ISQLInfoResults;
467   begin
468 <  Result := TSQLInfoResultsBuffer.Create;
468 >  Result := TSQLInfoResultsBuffer.Create(FFirebirdClientAPI);
469    GetDsqlInfo(Request,Result);
470   end;
471  
# Line 341 | Line 500 | begin
500    end;
501   end;
502  
503 + function TFBStatement.IsInBatchMode: boolean;
504 + begin
505 +  Result := false;
506 + end;
507 +
508 + function TFBStatement.HasBatchMode: boolean;
509 + begin
510 +  Result := false;
511 + end;
512 +
513   end.
514  

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines