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 45 by tony, Tue Dec 6 10:33:46 2016 UTC vs.
Revision 359 by tony, Tue Dec 7 09:37:32 2021 UTC

# Line 28 | Line 28
28   *
29   *)
30   unit FBStatement;
31 + {$IFDEF MSWINDOWS}
32 + {$DEFINE WINDOWS}
33 + {$ENDIF}
34  
35   {$IFDEF FPC}
36 < {$mode objfpc}{$H+}
36 > {$mode delphi}
37   {$codepage UTF8}
38   {$interfaces COM}
39   {$ENDIF}
# Line 41 | 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;
66      FPrepared: boolean;
67      FPrepareSeqNo: integer; {used to check for out of date references from interfaces}
68 <    FSQL: string;
69 <    FProcessedSQL: string;
68 >    FSQL: AnsiString;
69 >    FProcessedSQL: AnsiString;
70      FHasParamNames: boolean;
71      FBOF: boolean;
72      FEOF: boolean;
73      FSingleResults: boolean;
74      FGenerateParamNames: boolean;
75      FChangeSeqNo: integer;
76 +    FCollectStatistics: boolean;
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 GetDsqlInfo(info_request: byte; buffer: ISQLInfoResults); overload; virtual; abstract;
86 <    procedure InternalPrepare;  virtual; abstract;
87 <    function InternalExecute(aTransaction: ITransaction): IResults;  virtual; abstract;
88 <    function InternalOpenCursor(aTransaction: ITransaction): IResultSet;   virtual; abstract;
86 >    procedure InternalPrepare(CursorName: AnsiString='');  virtual; abstract;
87 >    function InternalExecute(Transaction: ITransaction): IResults;  virtual; abstract;
88 >    function InternalOpenCursor(aTransaction: ITransaction; Scrollable: boolean): IResultSet;   virtual; abstract;
89 >    procedure ProcessSQL(sql: AnsiString; GenerateParamNames: boolean; var processedSQL: AnsiString); virtual; abstract;
90      procedure FreeHandle;  virtual; abstract;
91      procedure InternalClose(Force: boolean); virtual; abstract;
92 +    function TimeStampToMSecs(const TimeStamp: TTimeStamp): Int64;
93    public
94      constructor Create(Attachment: IAttachment; Transaction: ITransaction;
95 <      sql: string; SQLDialect: integer);
95 >      sql: AnsiString; SQLDialect: integer);
96      constructor CreateWithParameterNames(Attachment: IAttachment; Transaction: ITransaction;
97 <      sql: string;  SQLDialect: integer; GenerateParamNames: boolean =false);
97 >      sql: AnsiString;  SQLDialect: integer; GenerateParamNames: boolean =false;
98 >      CaseSensitiveParams: boolean = false);
99      destructor Destroy; override;
100      procedure Close;
101      procedure TransactionEnding(aTransaction: ITransaction; Force: boolean);
102      property SQLDialect: integer read FSQLDialect;
103 +    property FirebirdClientAPI: TFBClientAPI read FFirebirdClientAPI;
104  
105    public
106      function GetSQLParams: ISQLParams; virtual; abstract;
# Line 88 | Line 108 | type
108      function GetRowsAffected(var SelectCount, InsertCount, UpdateCount,
109        DeleteCount: integer): boolean;
110      function GetSQLStatementType: TIBSQLStatementTypes;
111 <    function GetSQLText: string;
111 >    function GetSQLStatementTypeName: AnsiString;
112 >    function GetSQLText: AnsiString;
113 >    function GetProcessedSQLText: AnsiString;
114      function GetSQLDialect: integer;
115 +    function GetFlags: TStatementFlags; virtual;
116  
117      {GetDSQLInfo only supports isc_info_sql_stmt_type, isc_info_sql_get_plan, isc_info_sql_records}
118 <    procedure Prepare(aTransaction: ITransaction=nil); virtual;
118 >    procedure Prepare(aTransaction: ITransaction=nil);  overload;
119 >    procedure Prepare(CursorName: AnsiString; aTransaction: ITransaction=nil); overload; virtual;
120      function Execute(aTransaction: ITransaction=nil): IResults;
121 <    function OpenCursor(aTransaction: ITransaction=nil): IResultSet;
122 <    function CreateBlob(paramName: string): IBlob; overload;
121 >    function OpenCursor(aTransaction: ITransaction=nil): IResultSet; overload;
122 >    function OpenCursor(Scrollable: boolean; aTransaction: ITransaction=nil): IResultSet; overload;
123 >    function CreateBlob(paramName: AnsiString): IBlob; overload;
124      function CreateBlob(index: integer): IBlob; overload;
125      function CreateBlob(column: TColumnMetaData): IBlob; overload; virtual; abstract;
126 <    function CreateArray(paramName: string): IArray; overload;
126 >    function CreateArray(paramName: AnsiString): IArray; overload;
127      function CreateArray(index: integer): IArray;  overload;
128      function CreateArray(column: TColumnMetaData): IArray; overload; virtual; abstract;
129      function GetAttachment: IAttachment;
130      function GetTransaction: ITransaction;
131      function GetDSQLInfo(Request: byte): ISQLInfoResults; overload;
132      procedure SetRetainInterfaces(aValue: boolean); virtual;
133 +    procedure EnableStatistics(aValue: boolean);
134 +    function GetPerfStatistics(var stats: TPerfCounters): boolean;
135 +    function IsInBatchMode: boolean; virtual;
136 +    function HasBatchMode: boolean; virtual;
137 +  public
138 +    {IBatch support}
139 +    procedure AddToBatch; virtual;
140 +    function ExecuteBatch(aTransaction: ITransaction): IBatchCompletion; virtual;
141 +    procedure CancelBatch; virtual;
142 +    function GetBatchCompletion: IBatchCompletion; virtual;
143 +    function GetBatchRowLimit: integer;
144 +    procedure SetBatchRowLimit(aLimit: integer);
145 +    {Stale Reference Check}
146 +    procedure SetStaleReferenceChecks(Enable:boolean); {default true}
147 +    function GetStaleReferenceChecks: boolean;
148 +  public
149      property ChangeSeqNo: integer read FChangeSeqNo;
150      property SQLParams: ISQLParams read GetSQLParams;
151      property SQLStatementType: TIBSQLStatementTypes read GetSQLStatementType;
# Line 116 | Line 157 | uses FBMessages;
157  
158   { TFBStatement }
159  
160 + procedure TFBStatement.CheckChangeBatchRowLimit;
161 + begin
162 +  //Do Nothing
163 + end;
164 +
165   procedure TFBStatement.CheckTransaction(aTransaction: ITransaction);
166   begin
167    if (aTransaction = nil) then
# Line 125 | Line 171 | begin
171      IBError(ibxeNotInTransaction,[]);
172   end;
173  
174 + function TFBStatement.TimeStampToMSecs(const TimeStamp: TTimeStamp): Int64;
175 + begin
176 +  Result := TimeStamp.Time + Int64(timestamp.date)*msecsperday;
177 + end;
178 +
179   constructor TFBStatement.Create(Attachment: IAttachment;
180 <  Transaction: ITransaction; sql: string; SQLDialect: integer);
180 >  Transaction: ITransaction; sql: AnsiString; SQLDialect: integer);
181   begin
182    inherited Create(Transaction as TFBTransaction,2);
183    FAttachmentIntf := Attachment;
184    FTransactionIntf := Transaction;
185 +  FFirebirdClientAPI := Attachment.getFirebirdAPI as TFBClientAPI;
186    FSQLDialect := SQLDialect;
187    FSQL := sql;
188 +  FBatchRowLimit := DefaultBatchRowLimit;
189 +  FStaleReferenceChecks := true;
190   end;
191  
192   constructor TFBStatement.CreateWithParameterNames(Attachment: IAttachment;
193 <  Transaction: ITransaction; sql: string; SQLDialect: integer;
194 <  GenerateParamNames: boolean);
193 >  Transaction: ITransaction; sql: AnsiString; SQLDialect: integer;
194 >  GenerateParamNames: boolean; CaseSensitiveParams: boolean);
195   begin
196    FHasParamNames := true;
197    FGenerateParamNames := GenerateParamNames;
198 +  FCaseSensitiveParams := CaseSensitiveParams;
199    Create(Attachment,Transaction,sql,SQLDialect);
200   end;
201  
# Line 159 | Line 214 | end;
214   procedure TFBStatement.TransactionEnding(aTransaction: ITransaction;
215    Force: boolean);
216   begin
217 <  if FOpen and (FExecTransactionIntf = aTransaction) then
217 >  if FOpen and ((FExecTransactionIntf as TObject) = (aTransaction as TObject)) then
218      InternalClose(Force);
219  
220    if FTransactionIntf = aTransaction then
# Line 207 | Line 262 | begin
262    Result := FSQLStatementType;
263   end;
264  
265 < function TFBStatement.GetSQLText: string;
265 > function TFBStatement.GetSQLStatementTypeName: AnsiString;
266 > begin
267 >  case FSQLStatementType of
268 >  SQLUnknown: Result := 'SQL_Unknown';
269 >  SQLSelect: Result := 'SQL_Select';
270 >  SQLInsert: Result := 'SQL_Insert';
271 >  SQLUpdate: Result := 'SQL_Update';
272 >  SQLDelete: Result := 'SQL_Delete';
273 >  SQLDDL: Result := 'SQL_DDL';
274 >  SQLGetSegment: Result := 'SQL_GetSegment';
275 >  SQLPutSegment: Result := 'SQL_PutSegment';
276 >  SQLExecProcedure: Result := 'SQL_ExecProcedure';
277 >  SQLStartTransaction: Result := 'SQL_StartTransaction';
278 >  SQLCommit: Result := 'SQL_Commit';
279 >  SQLRollback: Result := 'SQL_Rollback';
280 >  SQLSelectForUpdate: Result := 'SQL_SelectForUpdate';
281 >  SQLSetGenerator: Result := 'SQL_SetGenerator';
282 >  SQLSavePoint: Result := 'SQL_SavePoint';
283 >  end;
284 > end;
285 >
286 > function TFBStatement.GetSQLText: AnsiString;
287   begin
288    Result := FSQL;
289   end;
290  
291 + function TFBStatement.GetProcessedSQLText: AnsiString;
292 + begin
293 +  if not FHasParamNames then
294 +    Result := FSQL
295 +  else
296 +  begin
297 +    if FProcessedSQL = '' then
298 +      ProcessSQL(FSQL,FGenerateParamNames,FProcessedSQL);
299 +    Result := FProcessedSQL;
300 +  end;
301 + end;
302 +
303   function TFBStatement.GetSQLDialect: integer;
304   begin
305    Result := FSQLDialect;
306   end;
307  
308 + function TFBStatement.GetFlags: TStatementFlags;
309 + begin
310 +  Result := [];
311 + end;
312 +
313   procedure TFBStatement.Prepare(aTransaction: ITransaction);
314   begin
315 +  Prepare('',aTransaction);
316 + end;
317 +
318 + procedure TFBStatement.Prepare(CursorName: AnsiString;
319 +  aTransaction: ITransaction);
320 + begin
321    if FPrepared then FreeHandle;
322    if aTransaction <> nil then
323    begin
# Line 226 | Line 325 | begin
325      FTransactionIntf := aTransaction;
326      AddMonitor(FTransactionIntf as TFBTransaction);
327    end;
328 <  InternalPrepare;
328 >  InternalPrepare(CursorName);
329   end;
330  
331   function TFBStatement.Execute(aTransaction: ITransaction): IResults;
# Line 237 | Line 336 | begin
336      Result := InternalExecute(aTransaction);
337   end;
338  
339 + procedure TFBStatement.AddToBatch;
340 + begin
341 +  IBError(ibxeBatchModeNotSupported,[]);
342 + end;
343 +
344 + function TFBStatement.ExecuteBatch(aTransaction: ITransaction
345 +  ): IBatchCompletion;
346 + begin
347 +  IBError(ibxeBatchModeNotSupported,[]);
348 + end;
349 +
350 + procedure TFBStatement.CancelBatch;
351 + begin
352 +  IBError(ibxeBatchModeNotSupported,[]);
353 + end;
354 +
355 + function TFBStatement.GetBatchCompletion: IBatchCompletion;
356 + begin
357 +  IBError(ibxeBatchModeNotSupported,[]);
358 + end;
359 +
360 + function TFBStatement.GetBatchRowLimit: integer;
361 + begin
362 +  Result := FBatchRowLimit;
363 + end;
364 +
365 + procedure TFBStatement.SetBatchRowLimit(aLimit: integer);
366 + begin
367 +  CheckChangeBatchRowLimit;
368 +  FBatchRowLimit := aLimit;
369 + end;
370 +
371 + procedure TFBStatement.SetStaleReferenceChecks(Enable: boolean);
372 + begin
373 +  FStaleReferenceChecks := Enable;
374 + end;
375 +
376 + function TFBStatement.GetStaleReferenceChecks: boolean;
377 + begin
378 +  Result := FStaleReferenceChecks;
379 + end;
380 +
381   function TFBStatement.OpenCursor(aTransaction: ITransaction): IResultSet;
382   begin
383 +  Result := OpenCursor(false,aTransaction);
384 + end;
385 +
386 + function TFBStatement.OpenCursor(Scrollable: boolean; aTransaction: ITransaction
387 +  ): IResultSet;
388 + begin
389    Close;
390    if aTransaction = nil then
391 <    Result := InternalOpenCursor(FTransactionIntf)
391 >    Result := InternalOpenCursor(FTransactionIntf,Scrollable)
392    else
393 <    Result := InternalOpenCursor(aTransaction);
393 >    Result := InternalOpenCursor(aTransaction,Scrollable);
394   end;
395  
396 < function TFBStatement.CreateBlob(paramName: string): IBlob;
396 > function TFBStatement.CreateBlob(paramName: AnsiString): IBlob;
397   var column: TColumnMetaData;
398   begin
399    InternalPrepare;
# Line 262 | Line 409 | begin
409    Result := CreateBlob(SQLParams[index] as TSQLParam);
410   end;
411  
412 < function TFBStatement.CreateArray(paramName: string): IArray;
412 > function TFBStatement.CreateArray(paramName: AnsiString): IArray;
413   var column: TColumnMetaData;
414   begin
415    InternalPrepare;
# Line 290 | Line 437 | end;
437  
438   function TFBStatement.GetDSQLInfo(Request: byte): ISQLInfoResults;
439   begin
440 <  Result := TSQLInfoResultsBuffer.Create;
440 >  Result := TSQLInfoResultsBuffer.Create(FFirebirdClientAPI);
441    GetDsqlInfo(Request,Result);
442   end;
443  
# Line 299 | Line 446 | begin
446    RetainInterfaces := aValue;
447   end;
448  
449 + procedure TFBStatement.EnableStatistics(aValue: boolean);
450 + begin
451 +  if FCollectStatistics <> aValue then
452 +  begin
453 +    FCollectStatistics := aValue;
454 +    FStatisticsAvailable := false;
455 +  end;
456 + end;
457 +
458 + function TFBStatement.GetPerfStatistics(var stats: TPerfCounters): boolean;
459 + begin
460 +  Result := FStatisticsAvailable;
461 +  if Result then
462 +  begin
463 +    stats[psCurrentMemory] := FAfterStats[psCurrentMemory];
464 +    stats[psDeltaMemory] := FAfterStats[psCurrentMemory] - FBeforeStats[psCurrentMemory];
465 +    stats[psMaxMemory] := FAfterStats[psMaxMemory];
466 +    stats[psRealTime] :=  FAfterStats[psRealTime] - FBeforeStats[psRealTime];
467 +    stats[psUserTime] :=  FAfterStats[psUserTime] - FBeforeStats[psUserTime];
468 +    stats[psReads] := FAfterStats[psReads] - FBeforeStats[psReads];
469 +    stats[psWrites] := FAfterStats[psWrites] - FBeforeStats[psWrites];
470 +    stats[psFetches] := FAfterStats[psFetches] - FBeforeStats[psFetches];
471 +    stats[psBuffers] :=  FAfterStats[psBuffers];
472 +  end;
473 + end;
474 +
475 + function TFBStatement.IsInBatchMode: boolean;
476 + begin
477 +  Result := false;
478 + end;
479 +
480 + function TFBStatement.HasBatchMode: boolean;
481 + begin
482 +  Result := false;
483 + end;
484 +
485   end.
486  

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines