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

Comparing ibx/trunk/fbintf/client/2.5/FB25Statement.pas (file contents):
Revision 47 by tony, Mon Jan 9 15:31:51 2017 UTC vs.
Revision 345 by tony, Mon Aug 23 14:22:29 2021 UTC

# Line 60 | Line 60
60   {                                                                        }
61   {************************************************************************}
62   unit FB25Statement;
63 + {$IFDEF MSWINDOWS}
64 + {$DEFINE WINDOWS}
65 + {$ENDIF}
66  
67   {$IFDEF FPC}
68 < {$mode objfpc}{$H+}
68 > {$mode delphi}
69   {$codepage UTF8}
70   {$interfaces COM}
71   {$ENDIF}
# Line 118 | Line 121 | type
121    TIBXSQLVAR = class(TSQLVarData)
122    private
123      FStatement: TFB25Statement;
124 +    FFirebird25ClientAPI: TFB25ClientAPI;
125      FBlob: IBlob;             {Cache references}
126      FArray: IArray;
127      FNullIndicator: short;
128      FOwnsSQLData: boolean;
129      FBlobMetaData: IBlobMetaData;
130      FArrayMetaData: IArrayMetaData;
131 +    FMetadataSize: short; {size of field from metadata}
132      FXSQLVAR: PXSQLVAR;       { Points to the PXSQLVAR in the owner object }
133    protected
134      function GetSQLType: cardinal; override;
135      function GetSubtype: integer; override;
136 <    function GetAliasName: string;  override;
137 <    function GetFieldName: string; override;
138 <    function GetOwnerName: string;  override;
139 <    function GetRelationName: string;  override;
136 >    function GetAliasName: AnsiString;  override;
137 >    function GetFieldName: AnsiString; override;
138 >    function GetOwnerName: AnsiString;  override;
139 >    function GetRelationName: AnsiString;  override;
140      function GetScale: integer; override;
141      function GetCharSetID: cardinal; override;
142      function GetCodePage: TSystemCodePage; override;
143 +    function GetCharSetWidth: integer; override;
144      function GetIsNull: Boolean;   override;
145      function GetIsNullable: boolean; override;
146 <    function GetSQLData: PChar;  override;
146 >    function GetSQLData: PByte;  override;
147      function GetDataLength: cardinal; override;
148 +    function GetSize: cardinal; override;
149 +    function GetAttachment: IAttachment; override;
150 +    function GetDefaultTextSQLType: cardinal; override;
151      procedure SetIsNull(Value: Boolean); override;
152      procedure SetIsNullable(Value: Boolean);  override;
153 <    procedure SetSQLData(AValue: PChar; len: cardinal); override;
153 >    procedure SetSQLData(AValue: PByte; len: cardinal); override;
154      procedure SetScale(aValue: integer); override;
155      procedure SetDataLength(len: cardinal); override;
156      procedure SetSQLType(aValue: cardinal); override;
# Line 158 | Line 167 | type
167      procedure Initialize; override;
168  
169      property Statement: TFB25Statement read FStatement;
170 +    property SQLType: cardinal read GetSQLType write SetSQLType;
171    end;
172  
173    TIBXINPUTSQLDA = class;
# Line 174 | Line 184 | type
184      function GetXSQLDA: PXSQLDA;
185    protected
186      FStatement: TFB25Statement;
187 +    FFirebird25ClientAPI: TFB25ClientAPI;
188      function GetTransactionSeqNo: integer; override;
189      procedure FreeXSQLDA;
190      function GetStatement: IStatement; override;
# Line 211 | Line 222 | type
222      procedure Bind;
223      function GetTransaction: TFB25Transaction; override;
224      procedure GetData(index: integer; var aIsNull: boolean; var len: short;
225 <      var data: PChar); override;
225 >      var data: PByte); override;
226      function IsInputDataArea: boolean; override;
227    end;
228  
# Line 226 | Line 237 | type
237      destructor Destroy; override;
238      {IResultSet}
239      function FetchNext: boolean;
240 <    function GetCursorName: string;
240 >    function GetCursorName: AnsiString;
241      function GetTransaction: ITransaction; override;
242      function IsEof: boolean;
243      procedure Close;
# Line 238 | Line 249 | type
249    private
250      FDBHandle: TISC_DB_HANDLE;
251      FHandle: TISC_STMT_HANDLE;
252 +    FFirebird25ClientAPI: TFB25ClientAPI;
253      FSQLParams: TIBXINPUTSQLDA;
254      FSQLRecord: TIBXOUTPUTSQLDA;
255 <    FCursor: String;               { Cursor name...}
255 >    FCursor: AnsiString;               { Cursor name...}
256      FCursorSeqNo: integer;
257      procedure GetPerfCounters(var counters: TPerfStatistics);
258    protected
# Line 249 | Line 261 | type
261      procedure InternalPrepare; override;
262      function InternalExecute(aTransaction: ITransaction): IResults; override;
263      function InternalOpenCursor(aTransaction: ITransaction): IResultSet; override;
264 +    procedure ProcessSQL(sql: AnsiString; GenerateParamNames: boolean; var processedSQL: AnsiString); override;
265      procedure FreeHandle; override;
266      procedure InternalClose(Force: boolean); override;
267    public
268      constructor Create(Attachment: TFB25Attachment; Transaction: ITransaction;
269 <      sql: string; aSQLDialect: integer);
269 >      sql: AnsiString; aSQLDialect: integer);
270      constructor CreateWithParameterNames(Attachment: TFB25Attachment;
271 <      Transaction: ITransaction; sql: string; aSQLDialect: integer; GenerateParamNames: boolean);
271 >      Transaction: ITransaction; sql: AnsiString; aSQLDialect: integer; GenerateParamNames: boolean;
272 >      CaseSensitiveParams: boolean=false);
273      destructor Destroy; override;
274      function FetchNext: boolean;
275  
# Line 263 | Line 277 | type
277      {IStatement}
278      function GetSQLParams: ISQLParams; override;
279      function GetMetaData: IMetaData; override;
280 <    function GetPlan: String;
280 >    function GetPlan: AnsiString;
281      function IsPrepared: boolean;
282      function CreateBlob(column: TColumnMetaData): IBlob; override;
283      function CreateArray(column: TColumnMetaData): IArray; override;
# Line 293 | Line 307 | begin
307      result := 0;
308   end;
309  
310 < function TIBXSQLVAR.GetAliasName: string;
310 > function TIBXSQLVAR.GetAliasName: AnsiString;
311   begin
312    result := strpas(FXSQLVAR^.aliasname);
313   end;
314  
315 < function TIBXSQLVAR.GetFieldName: string;
315 > function TIBXSQLVAR.GetFieldName: AnsiString;
316   begin
317    result := strpas(FXSQLVAR^.sqlname);
318   end;
319  
320 < function TIBXSQLVAR.GetOwnerName: string;
320 > function TIBXSQLVAR.GetOwnerName: AnsiString;
321   begin
322    result := strpas(FXSQLVAR^.ownname);
323   end;
324  
325 < function TIBXSQLVAR.GetRelationName: string;
325 > function TIBXSQLVAR.GetRelationName: AnsiString;
326   begin
327    result := strpas(FXSQLVAR^.relname);
328   end;
# Line 332 | Line 346 | begin
346    SQL_BLOB:
347      if (SQLSubType = 1)  then
348        {see http://firebirdsql.org/rlsnotesh/rlsnotes210.html}
349 <      result := FXSQLVAR^.sqlscale;
349 >      result := FXSQLVAR^.sqlscale and $FF;
350  
351    SQL_ARRAY:
352      if (GetRelationName <> '') and (GetFieldName <> '') then
# Line 343 | Line 357 | end;
357   function TIBXSQLVAR.GetCodePage: TSystemCodePage;
358   begin
359    result := CP_NONE;
360 <  with FirebirdClientAPI do
360 >  with Statement.GetAttachment do
361       CharSetID2CodePage(GetCharSetID,result);
362   end;
363  
364 + function TIBXSQLVAR.GetCharSetWidth: integer;
365 + begin
366 +  result := 1;
367 +  with Statement.GetAttachment DO
368 +    CharSetWidth(GetCharSetID,result);
369 + end;
370 +
371   function TIBXSQLVAR.GetIsNull: Boolean;
372   begin
373    result := IsNullable and (FNullIndicator = -1);
# Line 357 | Line 378 | begin
378    result := (FXSQLVAR^.sqltype and 1 = 1);
379   end;
380  
381 < function TIBXSQLVAR.GetSQLData: PChar;
381 > function TIBXSQLVAR.GetSQLData: PByte;
382   begin
383    Result := FXSQLVAR^.sqldata;
384   end;
# Line 367 | Line 388 | begin
388    Result := FXSQLVAR^.sqllen;
389   end;
390  
391 + function TIBXSQLVAR.GetSize: cardinal;
392 + begin
393 +  Result := FMetadataSize;
394 + end;
395 +
396 + function TIBXSQLVAR.GetAttachment: IAttachment;
397 + begin
398 +  Result := FStatement.GetAttachment;
399 + end;
400 +
401   function TIBXSQLVAR.GetArrayMetaData: IArrayMetaData;
402   begin
403    if GetSQLType <> SQL_ARRAY then
# Line 438 | Line 469 | procedure TIBXSQLVAR.Initialize;
469   begin
470    inherited Initialize;
471    FOwnsSQLData := true;
472 <  with FirebirdClientAPI, FXSQLVar^ do
472 >  with FFirebird25ClientAPI, FXSQLVar^ do
473    begin
474 +    FMetadataSize := sqllen;
475      case sqltype and (not 1) of
476        SQL_TEXT, SQL_TYPE_DATE, SQL_TYPE_TIME, SQL_TIMESTAMP,
477        SQL_BLOB, SQL_ARRAY, SQL_QUAD, SQL_SHORT, SQL_BOOLEAN,
# Line 499 | Line 531 | begin
531        FXSQLVAR^.sqlind := nil;
532      end;
533    end;
534 +  Changed;
535   end;
536  
537 < procedure TIBXSQLVAR.SetSQLData(AValue: PChar; len: cardinal);
537 > procedure TIBXSQLVAR.SetSQLData(AValue: PByte; len: cardinal);
538   begin
539    if FOwnsSQLData then
540      FreeMem(FXSQLVAR^.sqldata);
541    FXSQLVAR^.sqldata := AValue;
542    FXSQLVAR^.sqllen := len;
543    FOwnsSQLData := false;
544 +  Changed;
545   end;
546  
547   procedure TIBXSQLVAR.SetScale(aValue: integer);
548   begin
549    FXSQLVAR^.sqlscale := aValue;
550 +  Changed;
551   end;
552  
553   procedure TIBXSQLVAR.SetDataLength(len: cardinal);
# Line 520 | Line 555 | begin
555    if not FOwnsSQLData then
556      FXSQLVAR^.sqldata := nil;
557    FXSQLVAR^.sqllen := len;
558 <  with FirebirdClientAPI do
558 >  with FFirebird25ClientAPI do
559      IBAlloc(FXSQLVAR^.sqldata, 0, FXSQLVAR^.sqllen);
560    FOwnsSQLData := true;
561 +  Changed;
562   end;
563  
564   procedure TIBXSQLVAR.SetSQLType(aValue: cardinal);
565   begin
566    FXSQLVAR^.sqltype := aValue or (FXSQLVAR^.sqltype and 1);
567 +  Changed;
568   end;
569  
570   procedure TIBXSQLVAR.SetCharSetID(aValue: cardinal);
571   begin
572    if aValue <> GetCharSetID then
573 <  case SQLType of
574 <  SQL_VARYING, SQL_TEXT:
575 <      FXSQLVAR^.sqlsubtype := (aValue and $FF) or (FXSQLVAR^.sqlsubtype and not $FF);
576 <
577 <  SQL_BLOB,
578 <  SQL_ARRAY:
579 <    IBError(ibxeInvalidDataConversion,[nil]);
573 >  begin
574 >    case SQLType of
575 >    SQL_VARYING, SQL_TEXT:
576 >        FXSQLVAR^.sqlsubtype := (aValue and $FF) or (FXSQLVAR^.sqlsubtype and not $FF);
577 >
578 >    SQL_BLOB,
579 >    SQL_ARRAY:
580 >      IBError(ibxeInvalidDataConversion,[nil]);
581 >    end;
582 >  Changed;
583    end;
584   end;
585  
586 + function TIBXSQLVAR.GetDefaultTextSQLType: cardinal;
587 + begin
588 +  Result := SQL_TEXT;
589 + end;
590 +
591   constructor TIBXSQLVAR.Create(aParent: TIBXSQLDA; aIndex: integer);
592   begin
593    inherited Create(aParent,aIndex);
594    FStatement := aParent.Statement;
595 +  FFirebird25ClientAPI := aParent.FFirebird25ClientAPI;
596   end;
597  
598   procedure TIBXSQLVAR.FreeSQLData;
# Line 590 | Line 636 | begin
636        FResults.Column[i].RowChange;
637   end;
638  
639 < function TResultSet.GetCursorName: string;
639 > function TResultSet.GetCursorName: AnsiString;
640   begin
641    Result := FResults.FStatement.FCursor;
642   end;
# Line 617 | Line 663 | procedure TIBXINPUTSQLDA.Bind;
663   begin
664    if Count = 0 then
665      Count := 1;
666 <  with Firebird25ClientAPI do
666 >  with FFirebird25ClientAPI do
667    begin
668      if (FXSQLDA <> nil) then
669         if isc_dsql_describe_bind(StatusVector, @(FStatement.Handle), FStatement.SQLDialect,
# Line 649 | Line 695 | procedure TIBXOUTPUTSQLDA.Bind;
695   begin
696    { Allocate an initial output descriptor (with one column) }
697    Count := 1;
698 <  with Firebird25ClientAPI do
698 >  with FFirebird25ClientAPI do
699    begin
700      { Using isc_dsql_describe, get the right size for the columns... }
701      if isc_dsql_describe(StatusVector, @(FStatement.Handle), FStatement.SQLDialect, FXSQLDA) > 0 then
# Line 675 | Line 721 | begin
721   end;
722  
723   procedure TIBXOUTPUTSQLDA.GetData(index: integer; var aIsNull:boolean; var len: short;
724 <  var data: PChar);
724 >  var data: PByte);
725   begin
726    with TIBXSQLVAR(Column[index]), FXSQLVAR^ do
727    begin
# Line 684 | Line 730 | begin
730      len := sqllen;
731      if not IsNull and ((sqltype and (not 1)) = SQL_VARYING) then
732      begin
733 <      with FirebirdClientAPI do
733 >      with FFirebird25ClientAPI do
734          len := DecodeInteger(data,2);
735        Inc(data,2);
736      end;
# Line 701 | Line 747 | constructor TIBXSQLDA.Create(aStatement:
747   begin
748    inherited Create;
749    FStatement := aStatement;
750 +  FFirebird25ClientAPI := aStatement.FFirebird25ClientAPI;
751    FSize := 0;
752   //  writeln('Creating ',ClassName);
753   end;
# Line 787 | Line 834 | begin
834        OldSize := 0;
835      if Count > FSize then
836      begin
837 <      Firebird25ClientAPI.IBAlloc(FXSQLDA, OldSize, XSQLDA_LENGTH(Count));
837 >      FFirebird25ClientAPI.IBAlloc(FXSQLDA, OldSize, XSQLDA_LENGTH(Count));
838        SetLength(FColumnList, FCount);
839        FXSQLDA^.version := SQLDA_VERSION1;
840        p := @FXSQLDA^.sqlvar[0];
# Line 796 | Line 843 | begin
843          if i >= FSize then
844            FColumnList[i] := TIBXSQLVAR.Create(self,i);
845          TIBXSQLVAR(Column[i]).FXSQLVAR := p;
846 <        p := Pointer(PChar(p) + sizeof(FXSQLDA^.sqlvar));
846 >        p := Pointer(PAnsiChar(p) + sizeof(FXSQLDA^.sqlvar));
847        end;
848        FSize := inherited Count;
849      end;
# Line 850 | Line 897 | begin
897    {$ELSE}
898    counters[psUserTime] := 0;
899    {$ENDIF}
900 <  counters[psRealTime] := Int64(TimeStampToMSecs(DateTimeToTimeStamp(Now)));
900 >  counters[psRealTime] := TimeStampToMSecs(DateTimeToTimeStamp(Now));
901  
902    DBInfo := GetAttachment.GetDBInformation([isc_info_reads,isc_info_writes,
903           isc_info_fetches, isc_info_num_buffers, isc_info_current_memory,
# Line 885 | Line 932 | end;
932   procedure TFB25Statement.GetDsqlInfo(info_request: byte; buffer: ISQLInfoResults
933    );
934   begin
935 <  with Firebird25ClientAPI, buffer as TSQLInfoResultsBuffer do
935 >  with FFirebird25ClientAPI, buffer as TSQLInfoResultsBuffer do
936    if isc_dsql_sql_info(StatusVector, @(FHandle), 1, @info_request,
937                       GetBufSize, Buffer) > 0 then
938      IBDatabaseError;
# Line 902 | Line 949 | begin
949      IBError(ibxeEmptyQuery, [nil]);
950    try
951      CheckTransaction(FTransactionIntf);
952 <    with Firebird25ClientAPI do
952 >    with FFirebird25ClientAPI do
953      begin
954        Call(isc_dsql_alloc_statement2(StatusVector, @(FDBHandle),
955                                        @FHandle), True);
# Line 910 | Line 957 | begin
957        if FHasParamNames then
958        begin
959          if FProcessedSQL = '' then
960 <          FSQLParams.PreprocessSQL(FSQL,FGenerateParamNames,FProcessedSQL);
960 >          ProcessSQL(FSQL,FGenerateParamNames,FProcessedSQL);
961          Call(isc_dsql_prepare(StatusVector, @(TRHandle), @FHandle, 0,
962 <                 PChar(FProcessedSQL), FSQLDialect, nil), True);
962 >                 PAnsiChar(FProcessedSQL), FSQLDialect, nil), True);
963        end
964        else
965          Call(isc_dsql_prepare(StatusVector, @(TRHandle), @FHandle, 0,
966 <                 PChar(FSQL), FSQLDialect, nil), True);
966 >                 PAnsiChar(FSQL), FSQLDialect, nil), True);
967      end;
968      { After preparing the statement, query the stmt type and possibly
969        create a FSQLRecord "holder" }
# Line 954 | Line 1001 | begin
1001        if (FHandle <> nil) then
1002          FreeHandle;
1003        if E is EIBInterBaseError then
1004 <        raise EIBInterBaseError.Create(EIBInterBaseError(E).SQLCode,
1005 <                                       EIBInterBaseError(E).IBErrorCode,
959 <                                       EIBInterBaseError(E).Message +
960 <                                       sSQLErrorSeparator + FSQL)
961 <      else
962 <        raise;
1004 >        E.Message := E.Message + sSQLErrorSeparator + FSQL;
1005 >      raise;
1006      end;
1007    end;
1008    FPrepared := true;
# Line 996 | Line 1039 | begin
1039  
1040    try
1041      TRHandle := (aTransaction as TFB25Transaction).Handle;
1042 <    with Firebird25ClientAPI do
1042 >    with FFirebird25ClientAPI do
1043      begin
1044        if FCollectStatistics then
1045          GetPerfCounters(FBeforeStats);
# Line 1035 | Line 1078 | begin
1078         RemoveMonitor(aTransaction as TFB25Transaction);
1079    end;
1080    FExecTransactionIntf := aTransaction;
1081 +  FSQLRecord.FTransaction := aTransaction as TFB25Transaction;
1082 +  FSQLRecord.FTransactionSeqNo := FSQLRecord.FTransaction.TransactionSeqNo;
1083    Inc(FChangeSeqNo);
1084   end;
1085  
# Line 1055 | Line 1100 | begin
1100    if (FSQLParams.FTransactionSeqNo < (FTransactionIntf as TFB25transaction).TransactionSeqNo) then
1101      IBError(ibxeInterfaceOutofDate,[nil]);
1102  
1103 < with Firebird25ClientAPI do
1103 > with FFirebird25ClientAPI do
1104   begin
1105     if FCollectStatistics then
1106       GetPerfCounters(FBeforeStats);
# Line 1072 | Line 1117 | begin
1117       CreateGuid(GUID);
1118       FCursor := GUIDToString(GUID);
1119       Call(
1120 <       isc_dsql_set_cursor_name(StatusVector, @FHandle, PChar(FCursor), 0),
1120 >       isc_dsql_set_cursor_name(StatusVector, @FHandle, PAnsiChar(FCursor), 0),
1121         True);
1122     end;
1123  
# Line 1094 | Line 1139 | begin
1139   Inc(FChangeSeqNo);
1140   end;
1141  
1142 + procedure TFB25Statement.ProcessSQL(sql: AnsiString; GenerateParamNames: boolean;
1143 +  var processedSQL: AnsiString);
1144 + begin
1145 +  FSQLParams.PreprocessSQL(sql,GenerateParamNames, processedSQL);
1146 + end;
1147 +
1148   procedure TFB25Statement.FreeHandle;
1149   var
1150    isc_res: ISC_STATUS;
# Line 1102 | Line 1153 | begin
1153    ReleaseInterfaces;
1154    try
1155      if FHandle <> nil then
1156 <    with Firebird25ClientAPI do
1156 >    with FFirebird25ClientAPI do
1157      begin
1158        isc_res :=
1159          Call(isc_dsql_free_statement(StatusVector, @FHandle, DSQL_drop), False);
# Line 1122 | Line 1173 | var
1173   begin
1174    if (FHandle <> nil) and (SQLStatementType = SQLSelect) and FOpen then
1175    try
1176 <    with Firebird25ClientAPI do
1176 >    with FFirebird25ClientAPI do
1177      begin
1178        isc_res := Call(
1179                     isc_dsql_free_statement(StatusVector, @FHandle, DSQL_close),
# Line 1133 | Line 1184 | begin
1184          IBDatabaseError;
1185      end;
1186    finally
1187 <    if (FSQLRecord.FTransaction <> nil) and (FSQLRecord.FTransaction <> FTransactionIntf) then
1187 >    if (FSQLRecord.FTransaction <> nil) and (FSQLRecord.FTransaction <> (FTransactionIntf as TFB25Transaction)) then
1188        RemoveMonitor(FSQLRecord.FTransaction);
1189      FOpen := False;
1190      FExecTransactionIntf := nil;
# Line 1143 | Line 1194 | begin
1194   end;
1195  
1196   constructor TFB25Statement.Create(Attachment: TFB25Attachment;
1197 <  Transaction: ITransaction; sql: string; aSQLDialect: integer);
1197 >  Transaction: ITransaction; sql: AnsiString; aSQLDialect: integer);
1198   begin
1199    inherited Create(Attachment,Transaction,sql,aSQLDialect);
1200    FDBHandle := Attachment.Handle;
1201 +  FFirebird25ClientAPI := Attachment.Firebird25ClientAPI;
1202 +  OnDatabaseError := FFirebird25ClientAPI.IBDataBaseError;
1203    FSQLParams := TIBXINPUTSQLDA.Create(self);
1204    FSQLRecord := TIBXOUTPUTSQLDA.Create(self);
1205    InternalPrepare;
1206   end;
1207  
1208 < constructor TFB25Statement.CreateWithParameterNames(Attachment: TFB25Attachment;
1209 <  Transaction: ITransaction; sql: string; aSQLDialect: integer;
1210 <  GenerateParamNames: boolean);
1208 > constructor TFB25Statement.CreateWithParameterNames(
1209 >  Attachment: TFB25Attachment; Transaction: ITransaction; sql: AnsiString;
1210 >  aSQLDialect: integer; GenerateParamNames: boolean;
1211 >  CaseSensitiveParams: boolean);
1212   begin
1213    inherited CreateWithParameterNames(Attachment,Transaction,sql,aSQLDialect,GenerateParamNames);
1214    FDBHandle := Attachment.Handle;
1215 +  FFirebird25ClientAPI := Attachment.Firebird25ClientAPI;
1216 +  OnDatabaseError := FFirebird25ClientAPI.IBDataBaseError;
1217    FSQLParams := TIBXINPUTSQLDA.Create(self);
1218 +  FSQLParams.CaseSensitiveParams := CaseSensitiveParams;
1219    FSQLRecord := TIBXOUTPUTSQLDA.Create(self);
1220    InternalPrepare;
1221   end;
# Line 1180 | Line 1237 | begin
1237    if FEOF then
1238      IBError(ibxeEOF,[nil]);
1239  
1240 <  with Firebird25ClientAPI do
1240 >  with FFirebird25ClientAPI do
1241    begin
1242      { Go to the next record... }
1243      fetch_res :=
# Line 1206 | Line 1263 | begin
1263        FBOF := false;
1264        result := true;
1265      end;
1266 +    if FCollectStatistics then
1267 +    begin
1268 +      GetPerfCounters(FAfterStats);
1269 +      FStatisticsAvailable := true;
1270 +    end;
1271    end;
1272    FSQLRecord.RowChange;
1273    if FEOF then
# Line 1228 | Line 1290 | begin
1290    Result := TMetaData(GetInterface(1));
1291   end;
1292  
1293 < function TFB25Statement.GetPlan: String;
1293 > function TFB25Statement.GetPlan: AnsiString;
1294   var
1295      RB: ISQLInfoResults;
1296   begin
# Line 1238 | Line 1300 | begin
1300      result := ''
1301    else
1302    begin
1303 <    RB := TSQLInfoResultsBuffer.Create(4*4096);
1303 >    RB := TSQLInfoResultsBuffer.Create(FFirebird25ClientAPI,4*4096);
1304      GetDsqlInfo(isc_info_sql_get_plan,RB);
1305       if RB.Count > 0 then
1306       Result := RB[0].GetAsString;

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines