home *** CD-ROM | disk | FTP | other *** search
/ Chip 2001 September / Chip_2001-09_cd1.bin / zkuste / delphi / kolekce / d6 / RX275D6.ZIP / Units / DBQBE.PAS < prev    next >
Pascal/Delphi Source File  |  1999-10-12  |  18KB  |  690 lines

  1. {*******************************************************}
  2. {                                                       }
  3. {         Delphi VCL Extensions (RX)                    }
  4. {                                                       }
  5. {         Copyright (c) 1995, 1996 AO ROSNO             }
  6. {         Copyright (c) 1997, 1998 Master-Bank          }
  7. {                                                       }
  8. {*******************************************************}
  9.  
  10. unit DBQBE;
  11.  
  12. {*************************************************************************}
  13. { The Delphi TQBEQuery component.                                         }
  14. { This component derives from TDBDataSet and is much like TQuery except   }
  15. { the language used for Query is QBE (Query by example).                  }
  16. { You can create the QBE queries from Paradox or DatabaseDesktop and then }
  17. { load or paste the query strings in the QBE property of TQBEQuery.       }
  18. {*************************************************************************}
  19.  
  20. {$I RX.INC}
  21. {$N+,P+,S-}
  22.  
  23. interface
  24.  
  25. uses SysUtils, {$IFDEF WIN32} Windows, Bde, {$ELSE} WinTypes, WinProcs,
  26.   DbiErrs, DbiTypes, DbiProcs, {$ENDIF} Classes, Controls, DB, DBTables;
  27.  
  28. const
  29.   DefQBEStartParam = '#';
  30.  
  31. type
  32.   TCheckType = (ctNone, ctCheck, ctCheckPlus, ctCheckDesc, ctCheckGroup);
  33.  
  34. { TQBEQuery }
  35.  
  36.   TQBEQuery = class(TDBDataSet)
  37.   private
  38.     FStmtHandle: HDBIStmt;
  39.     FQBE: TStrings;
  40.     FPrepared: Boolean;
  41.     FParams: TParams;
  42.     FStartParam: Char;
  43.     FAuxiliaryTables: Boolean;
  44. {$IFDEF WIN32}
  45.     FText: string;
  46.     FRowsAffected: Integer;
  47. {$ELSE}
  48.     FText: PChar;
  49. {$ENDIF}
  50. {$IFDEF RX_D3}
  51.     FConstrained: Boolean;
  52. {$ENDIF}
  53.     FLocal: Boolean;
  54.     FRequestLive: Boolean;
  55.     FBlankAsZero: Boolean;
  56.     FParamCheck: Boolean;
  57.     function CreateCursor(GenHandle: Boolean): HDBICur;
  58.     procedure ReplaceParams(QBEText: TStrings);
  59.     procedure CreateParams(List: TParams; const Value: PChar);
  60.     procedure FreeStatement;
  61.     function GetQueryCursor(GenHandle: Boolean): HDBICur;
  62.     procedure GetStatementHandle(QBEText: PChar);
  63.     procedure PrepareQBE(Value: PChar);
  64.     procedure QueryChanged(Sender: TObject);
  65.     procedure SetQuery(Value: TStrings);
  66.     procedure SetParamsList(Value: TParams);
  67.     procedure SetPrepared(Value: Boolean);
  68.     procedure SetPrepare(Value: Boolean);
  69.     procedure SetStartParam(Value: Char);
  70. {$IFDEF RX_D4}
  71.     procedure ReadParamData(Reader: TReader);
  72.     procedure WriteParamData(Writer: TWriter);
  73. {$ENDIF}
  74. {$IFDEF WIN32}
  75.     function GetRowsAffected: Integer;
  76. {$ENDIF}
  77. {$IFDEF RX_D5}
  78.   protected
  79.     { IProviderSupport }
  80.     procedure PSExecute; override;
  81.     function PSGetParams: TParams; override;
  82.     procedure PSSetCommandText(const CommandText: string); override;
  83.     procedure PSSetParams(AParams: TParams); override;
  84. {$ENDIF}
  85.   protected
  86.     function CreateHandle: HDBICur; override;
  87.     procedure Disconnect; override;
  88.     function GetParamsCount: Word;
  89. {$IFDEF RX_D4}
  90.     procedure DefineProperties(Filer: TFiler); override;
  91. {$ENDIF}
  92. {$IFDEF RX_V110}
  93.     function SetDBFlag(Flag: Integer; Value: Boolean): Boolean; override;
  94. {$ELSE}
  95.     procedure SetDBFlag(Flag: Integer; Value: Boolean); override;
  96. {$ENDIF}
  97.   public
  98.     constructor Create(AOwner: TComponent); override;
  99.     destructor Destroy; override;
  100.     function GetQBEText: PChar;
  101.     procedure ExecQBE;
  102.     function ParamByName(const Value: string): TParam;
  103.     procedure Prepare;
  104.     procedure RefreshQuery;
  105.     procedure UnPrepare;
  106. {$IFNDEF RX_D3}
  107.     function IsEmpty: Boolean;
  108. {$ENDIF}
  109.     property Local: Boolean read FLocal;
  110.     property ParamCount: Word read GetParamsCount;
  111.     property Prepared: Boolean read FPrepared write SetPrepare;
  112.     property StmtHandle: HDBIStmt read FStmtHandle;
  113. {$IFDEF WIN32}
  114.     property Text: string read FText;
  115.     property RowsAffected: Integer read GetRowsAffected;
  116. {$ELSE}
  117.     property Text: PChar read FText;
  118. {$ENDIF}
  119.   published
  120. {$IFDEF RX_D5}
  121.     property AutoRefresh;
  122. {$ENDIF}
  123.     property AuxiliaryTables: Boolean read FAuxiliaryTables write FAuxiliaryTables default True;
  124.     property ParamCheck: Boolean read FParamCheck write FParamCheck default True;
  125.     property StartParam: Char read FStartParam write SetStartParam default DefQBEStartParam;
  126.     { Ensure StartParam is declared before QBE }
  127.     property QBE: TStrings read FQBE write SetQuery;
  128.     { Ensure QBE is declared before Params }
  129.     property BlankAsZero: Boolean read FBlankAsZero write FBlankAsZero default False;
  130.     property Params: TParams read FParams write SetParamsList {$IFDEF RX_D4} stored False {$ENDIF};
  131.     property RequestLive: Boolean read FRequestLive write FRequestLive default False;
  132.     property UpdateMode;
  133. {$IFDEF WIN32}
  134.     property UpdateObject;
  135.   {$IFDEF RX_D3}
  136.     property Constrained: Boolean read FConstrained write FConstrained default False;
  137.     property Constraints stored ConstraintsStored;
  138.   {$ENDIF}
  139. {$ENDIF}
  140.   end;
  141.  
  142. implementation
  143.  
  144. uses DBConsts, {$IFDEF RX_D3} BDEConst, {$ENDIF} DBUtils, BdeUtils;
  145.  
  146. function NameDelimiter(C: Char): Boolean;
  147. begin
  148.   Result := C in [' ', ',', ';', ')', '.', #13, #10];
  149. end;
  150.  
  151. function IsLiteral(C: Char): Boolean;
  152. begin
  153.   Result := C in ['''', '"'];
  154. end;
  155.  
  156. { TQBEQuery }
  157.  
  158. constructor TQBEQuery.Create(AOwner: TComponent);
  159. begin
  160.   inherited Create(AOwner);
  161.   FQBE := TStringList.Create;
  162.   TStringList(QBE).OnChange := QueryChanged;
  163.   FParams := TParams.Create{$IFDEF RX_D4}(Self){$ENDIF};
  164.   FStartParam := DefQBEStartParam;
  165.   FParamCheck := True;
  166.   FAuxiliaryTables:= True;
  167. {$IFNDEF WIN32}
  168.   FText := nil;
  169. {$ELSE}
  170.   FRowsAffected := -1;
  171. {$ENDIF}
  172.   FRequestLive := False;
  173. end;
  174.  
  175. destructor TQBEQuery.Destroy;
  176. begin
  177.   Destroying;
  178.   Disconnect;
  179.   QBE.Free;
  180. {$IFNDEF WIN32}
  181.   StrDispose(FText);
  182. {$ENDIF}
  183.   FParams.Free;
  184.   inherited Destroy;
  185. end;
  186.  
  187. procedure TQBEQuery.Disconnect;
  188. begin
  189.   Close;
  190.   UnPrepare;
  191. end;
  192.  
  193. procedure TQBEQuery.RefreshQuery;
  194. var
  195.   Bookmark: TBookmark;
  196. begin
  197.   DisableControls;
  198.   Bookmark := GetBookmark;
  199.   try
  200.     Close;
  201.     Open;
  202.     try
  203.       GotoBookmark(Bookmark);
  204.     except
  205.       { ignore exceptions }
  206.     end;
  207.   finally
  208.     FreeBookmark(Bookmark);
  209.     EnableControls;
  210.   end;
  211. end;
  212.  
  213. procedure TQBEQuery.SetPrepare(Value: Boolean);
  214. begin
  215.   if Value then Prepare
  216.   else UnPrepare;
  217. end;
  218.  
  219. procedure TQBEQuery.Prepare;
  220. begin
  221.   SetDBFlag(dbfPrepared, True);
  222.   SetPrepared(True);
  223. end;
  224.  
  225. procedure TQBEQuery.UnPrepare;
  226. begin
  227.   SetPrepared(False);
  228.   SetDBFlag(dbfPrepared, False);
  229. end;
  230.  
  231. procedure TQBEQuery.SetStartParam(Value: Char);
  232. begin
  233.   if Value <> FStartParam then begin
  234.     FStartParam := Value;
  235.     QueryChanged(nil);
  236.   end;
  237. end;
  238.  
  239. procedure TQBEQuery.SetQuery(Value: TStrings);
  240. begin
  241. {$IFDEF WIN32}
  242.   if QBE.Text <> Value.Text then begin
  243. {$ENDIF}
  244.     Disconnect;
  245.     TStringList(QBE).OnChange := nil;
  246.     QBE.Assign(Value);
  247.     TStringList(QBE).OnChange := QueryChanged;
  248.     QueryChanged(nil);
  249. {$IFDEF WIN32}
  250.   end;
  251. {$ENDIF}
  252. end;
  253.  
  254. procedure TQBEQuery.QueryChanged(Sender: TObject);
  255. var
  256.   List: TParams;
  257. begin
  258. {$IFDEF RX_D4}
  259.   if not (csReading in ComponentState) then begin
  260. {$ENDIF RX_D4}
  261.     Disconnect;
  262.   {$IFDEF WIN32}
  263.     FText := QBE.Text;
  264.   {$ELSE}
  265.     StrDispose(FText);
  266.     FText := QBE.GetText;
  267.   {$ENDIF WIN32}
  268.     if ParamCheck or (csDesigning in ComponentState) then begin
  269.       List := TParams.Create{$IFDEF RX_D4}(Self){$ENDIF};
  270.       try
  271.         CreateParams(List, PChar(Text));
  272.         List.AssignValues(FParams);
  273.     {$IFDEF RX_D4}
  274.         FParams.Clear;
  275.         FParams.Assign(List);
  276.       finally
  277.     {$ELSE}
  278.         FParams.Free;
  279.         FParams := List;
  280.       except
  281.     {$ENDIF RX_D4}
  282.         List.Free;
  283.       end;
  284.     end;
  285. {$IFDEF RX_D4}
  286.     DataEvent(dePropertyChange, 0);
  287.   end
  288.   else begin
  289.     FText := QBE.Text;
  290.     FParams.Clear;
  291.     CreateParams(FParams, PChar(Text));
  292.   end;
  293. {$ENDIF RX_D4}
  294. end;
  295.  
  296. procedure TQBEQuery.SetParamsList(Value: TParams);
  297. begin
  298.   FParams.AssignValues(Value);
  299. end;
  300.  
  301. {$IFDEF RX_D4}
  302. procedure TQBEQuery.DefineProperties(Filer: TFiler);
  303. begin
  304.   inherited DefineProperties(Filer);
  305.   Filer.DefineProperty('ParamData', ReadParamData, WriteParamData, True);
  306. end;
  307.  
  308. procedure TQBEQuery.ReadParamData(Reader: TReader);
  309. begin
  310.   Reader.ReadValue;
  311.   Reader.ReadCollection(FParams);
  312. end;
  313.  
  314. procedure TQBEQuery.WriteParamData(Writer: TWriter);
  315. begin
  316.   Writer.WriteCollection(Params);
  317. end;
  318. {$ENDIF}
  319.  
  320. function TQBEQuery.GetParamsCount: Word;
  321. begin
  322.   Result := FParams.Count;
  323. end;
  324.  
  325. procedure TQBEQuery.ReplaceParams(QBEText: TStrings);
  326.  
  327.   function ReplaceString(const S: string): string;
  328.   var
  329.     I, J, P, LiteralChars: Integer;
  330.     Param: TParam;
  331.     Temp: string;
  332.     Found: Boolean;
  333.   begin
  334.     Result := S;
  335.     for I := Params.Count - 1 downto 0 do begin
  336.       Param := Params[I];
  337.       if Param.DataType = ftUnknown then
  338.         Continue; { ignore undefined params }
  339.       repeat
  340.         P := Pos(StartParam + Param.Name, Result);
  341.         Found := (P > 0) and ((Length(Result) = P + Length(Param.Name)) or
  342.           NameDelimiter(Result[P + Length(Param.Name) + 1]));
  343.         if Found then begin
  344.           LiteralChars := 0;
  345.           for J := 1 to P - 1 do
  346.             if IsLiteral(Result[J]) then Inc(LiteralChars);
  347.           Found := LiteralChars mod 2 = 0;
  348.           if Found then begin
  349.             Temp := Param.Text;
  350.             if Temp = '' then begin
  351.               if (Param.DataType = ftString) and not Param.IsNull then
  352.                 Temp := '""'
  353.               else Temp := 'BLANK'; { special QBE operator }
  354.             end;
  355.             Result := Copy(Result, 1, P - 1) + Temp + Copy(Result,
  356.               P + Length(Param.Name) + 1, MaxInt);
  357.           end;
  358.         end;
  359.       until not Found;
  360.     end;
  361.   end;
  362.  
  363. var
  364.   I: Integer;
  365. begin
  366.   for I := 0 to QBEText.Count - 1 do
  367.     QBEText[I] := ReplaceString(QBEText[I]);
  368. end;
  369.  
  370. procedure TQBEQuery.SetPrepared(Value: Boolean);
  371. var
  372.   TempQBE: TStrings;
  373.   AText: PChar;
  374. begin
  375.   if Handle <> nil then _DBError(SDataSetOpen);
  376.   if (Value <> Prepared) or (ParamCount > 0) then begin
  377.     if Value then begin
  378. {$IFDEF WIN32}
  379.       FRowsAffected := -1;
  380. {$ENDIF}
  381.       if ParamCount > 0 then begin
  382.         TempQBE := TStringList.Create;
  383.         try
  384.           TempQBE.Assign(QBE);
  385.           ReplaceParams(TempQBE);
  386. {$IFDEF WIN32}
  387.           AText := PChar(TempQBE.Text);
  388. {$ELSE}
  389.           AText := TempQBE.GetText;
  390. {$ENDIF}
  391.           try
  392.             FreeStatement;
  393.             if StrLen(AText) > 1 then PrepareQBE(AText)
  394.             else _DBError(SEmptySQLStatement);
  395.           finally
  396. {$IFNDEF WIN32}
  397.             StrDispose(AText);
  398. {$ENDIF}
  399.           end;
  400.         finally
  401.           TempQBE.Free;
  402.         end;
  403.       end
  404.       else begin
  405.         if StrLen(PChar(Text)) > 1 then PrepareQBE(PChar(Text))
  406.         else _DBError(SEmptySQLStatement);
  407.       end;
  408.     end
  409.     else begin
  410. {$IFDEF WIN32}
  411.       FRowsAffected := RowsAffected;
  412. {$ENDIF}
  413.       FreeStatement;
  414.     end;
  415.     FPrepared := Value;
  416.   end;
  417. end;
  418.  
  419. procedure TQBEQuery.FreeStatement;
  420. begin
  421.   if StmtHandle <> nil then begin
  422.     DbiQFree(FStmtHandle);
  423.     FStmtHandle := nil;
  424.   end;
  425. end;
  426.  
  427. function TQBEQuery.ParamByName(const Value: string): TParam;
  428. begin
  429.   Result := FParams.ParamByName(Value);
  430. end;
  431.  
  432. procedure TQBEQuery.CreateParams(List: TParams; const Value: PChar);
  433. var
  434.   CurPos, StartPos: PChar;
  435.   CurChar: Char;
  436.   Literal: Boolean;
  437.   EmbeddedLiteral: Boolean;
  438.   Name: string;
  439.  
  440.   function StripLiterals(Buffer: PChar): string;
  441.   var
  442.     Len: Word;
  443.     TempBuf: PChar;
  444.  
  445.     procedure StripChar(Value: Char);
  446.     begin
  447.       if TempBuf^ = Value then
  448.         StrMove(TempBuf, TempBuf + 1, Len - 1);
  449.       if TempBuf[StrLen(TempBuf) - 1] = Value then
  450.         TempBuf[StrLen(TempBuf) - 1] := #0;
  451.     end;
  452.  
  453.   begin
  454.     Len := StrLen(Buffer) + 1;
  455.     TempBuf := AllocMem(Len);
  456.     Result := '';
  457.     try
  458.       StrCopy(TempBuf, Buffer);
  459.       StripChar('''');
  460.       StripChar('"');
  461.       Result := StrPas(TempBuf);
  462.     finally
  463.       FreeMem(TempBuf, Len);
  464.     end;
  465.   end;
  466.  
  467. begin
  468.   CurPos := Value;
  469.   Literal := False;
  470.   EmbeddedLiteral := False;
  471.   repeat
  472.     CurChar := CurPos^;
  473.     if (CurChar = FStartParam) and not Literal and
  474.       ((CurPos + 1)^ <> FStartParam) then
  475.     begin
  476.       StartPos := CurPos;
  477.       while (CurChar <> #0) and (Literal or not NameDelimiter(CurChar)) do
  478.       begin
  479.         Inc(CurPos);
  480.         CurChar := CurPos^;
  481.         if IsLiteral(CurChar) then begin
  482.           Literal := Literal xor True;
  483.           if CurPos = StartPos + 1 then EmbeddedLiteral := True;
  484.         end;
  485.       end;
  486.       CurPos^ := #0;
  487.       if EmbeddedLiteral then begin
  488.         Name := StripLiterals(StartPos + 1);
  489.         EmbeddedLiteral := False;
  490.       end
  491.       else Name := StrPas(StartPos + 1);
  492. {$IFDEF RX_D4}
  493.       if List.FindParam(Name) = nil then
  494. {$ENDIF}
  495.         List.CreateParam(ftUnknown, Name, ptUnknown);
  496.       CurPos^ := CurChar;
  497.       StartPos^ := '?';
  498.       Inc(StartPos);
  499.       StrMove(StartPos, CurPos, StrLen(CurPos) + 1);
  500.       CurPos := StartPos;
  501.     end
  502.     else if (CurChar = FStartParam) and not Literal
  503.       and ((CurPos + 1)^ = FStartParam) then
  504.       StrMove(CurPos, CurPos + 1, StrLen(CurPos) + 1)
  505.     else if IsLiteral(CurChar) then Literal := Literal xor True;
  506.     Inc(CurPos);
  507.   until CurChar = #0;
  508. end;
  509.  
  510. {$IFNDEF RX_D3}
  511. function TQBEQuery.IsEmpty: Boolean;
  512. begin
  513.   Result := IsDataSetEmpty(Self);
  514. end;
  515. {$ENDIF}
  516.  
  517. function TQBEQuery.CreateCursor(GenHandle: Boolean): HDBICur;
  518. begin
  519.   if QBE.Count > 0 then begin
  520.     SetPrepared(True);
  521.     Result := GetQueryCursor(GenHandle);
  522.   end
  523.   else Result := nil;
  524. end;
  525.  
  526. function TQBEQuery.CreateHandle: HDBICur;
  527. begin
  528.   Result := CreateCursor(True)
  529. end;
  530.  
  531. procedure TQBEQuery.ExecQBE;
  532. begin
  533.   CheckInActive;
  534.   SetDBFlag(dbfExecSQL, True);
  535.   try
  536.     CreateCursor(False);
  537.   finally
  538.     SetDBFlag(dbfExecSQL, False);
  539.   end;
  540. end;
  541.  
  542. function TQBEQuery.GetQueryCursor(GenHandle: Boolean): HDBICur;
  543. var
  544.   PCursor: phDBICur;
  545. begin
  546.   Result := nil;
  547.   if GenHandle then PCursor := @Result
  548.   else PCursor := nil;
  549.   Check(DbiQExec(StmtHandle, PCursor));
  550. end;
  551.  
  552. {$IFDEF RX_V110}
  553. function TQBEQuery.SetDBFlag(Flag: Integer; Value: Boolean): Boolean;
  554. {$ELSE}
  555. procedure TQBEQuery.SetDBFlag(Flag: Integer; Value: Boolean);
  556. {$ENDIF}
  557. var
  558.   NewConnection: Boolean;
  559. begin
  560.   if Value then begin
  561.     NewConnection := DBFlags = [];
  562. {$IFDEF RX_V110}
  563.     Result := inherited SetDBFlag(Flag, Value);
  564. {$ELSE}
  565.     inherited SetDBFlag(Flag, Value);
  566. {$ENDIF}
  567.     if not (csReading in ComponentState) and NewConnection then
  568.       FLocal := not Database.IsSQLBased;
  569.   end
  570.   else begin
  571.     if DBFlags - [Flag] = [] then SetPrepared(False);
  572. {$IFDEF RX_V110}
  573.     Result := inherited SetDBFlag(Flag, Value);
  574. {$ELSE}
  575.     inherited SetDBFlag(Flag, Value);
  576. {$ENDIF}
  577.   end;
  578. end;
  579.  
  580. procedure TQBEQuery.PrepareQBE(Value: PChar);
  581. begin
  582.   GetStatementHandle(Value);
  583. end;
  584.  
  585. procedure TQBEQuery.GetStatementHandle(QBEText: PChar);
  586. const
  587.   DataType: array[Boolean] of LongInt = (Ord(wantCanned), Ord(wantLive));
  588. begin
  589. {$IFDEF WIN32}
  590.   Check(DbiQAlloc(DBHandle, qrylangQBE, FStmtHandle));
  591.   try
  592.     Check(DBiSetProp(hDbiObj(StmtHandle), stmtLIVENESS,
  593.       DataType[RequestLive and not ForceUpdateCallback]));
  594.     Check(DBiSetProp(hDbiObj(StmtHandle), stmtAUXTBLS, Longint(FAuxiliaryTables)));
  595. {$IFDEF RX_D3}
  596.     if Local and RequestLive and Constrained then
  597.       Check(DBiSetProp(hDbiObj(StmtHandle), stmtCONSTRAINED, LongInt(True)));
  598. {$ENDIF}
  599.     if FBlankAsZero then
  600.       Check(DbiSetProp(hDbiObj(StmtHandle), stmtBLANKS, Longint(True)));
  601.     while not CheckOpen(DbiQPrepare(FStmtHandle, QBEText)) do {Retry};
  602.   except
  603.     DbiQFree(FStmtHandle);
  604.     FStmtHandle := nil;
  605.     raise;
  606.   end;
  607. {$ELSE}
  608.   if Local then begin
  609.     while not CheckOpen(DbiQPrepare(DBHandle, qrylangQBE, QBEText,
  610.       FStmtHandle)) do {Retry};
  611.     Check(DBiSetProp(hDbiObj(StmtHandle), stmtLIVENESS, DataType[RequestLive]));
  612.   end
  613.   else begin
  614.     if RequestLive then
  615.       Check(DbiQPrepareExt(DBHandle, qrylangQBE, QBEText, qprepFORUPDATE, FStmtHandle))
  616.     else Check(DbiQPrepare(DBHandle, qrylangQBE, QBEText, FStmtHandle));
  617.   end;
  618.   Check(DBiSetProp(hDbiObj(StmtHandle), stmtAUXTBLS, Longint(FAuxiliaryTables)));
  619.   if FBlankAsZero then
  620.     Check(DbiSetProp(hDbiObj(StmtHandle), stmtBLANKS, LongInt(True)));
  621. {$ENDIF}
  622. end;
  623.  
  624. function TQBEQuery.GetQBEText: PChar;
  625. var
  626.   BufLen: Word;
  627.   I: Integer;
  628.   StrEnd: PChar;
  629.   StrBuf: array[0..255] of Char;
  630. begin
  631.   BufLen := 1;
  632.   for I := 0 to QBE.Count - 1 do
  633.     Inc(BufLen, Length(QBE.Strings[I]) + 1);
  634.   Result := StrAlloc(BufLen);
  635.   try
  636.     StrEnd := Result;
  637.     for I := 0 to QBE.Count - 1 do begin
  638.       StrPCopy(StrBuf, QBE.Strings[I]);
  639.       StrEnd := StrECopy(StrEnd, StrBuf);
  640.       StrEnd := StrECopy(StrEnd, ' ');
  641.     end;
  642.   except
  643.     StrDispose(Result);
  644.     raise;
  645.   end;
  646. end;
  647.  
  648. {$IFDEF WIN32}
  649. function TQBEQuery.GetRowsAffected: Integer;
  650. var
  651.   Length: Word;
  652. begin
  653.   if Prepared then
  654.     if DbiGetProp(hDBIObj(StmtHandle), stmtROWCOUNT, @Result, SizeOf(Result),
  655.       Length) <> 0 then Result := -1
  656.     else
  657.   else Result := FRowsAffected;
  658. end;
  659. {$ENDIF}
  660.  
  661. {$IFDEF RX_D5}
  662.  
  663. { TQBEQuery.IProviderSupport }
  664.  
  665. function TQBEQuery.PSGetParams: TParams;
  666. begin
  667.   Result := Params;
  668. end;
  669.  
  670. procedure TQBEQuery.PSSetParams(AParams: TParams);
  671. begin
  672.   if AParams.Count <> 0 then
  673.     Params.Assign(AParams);
  674.   Close;
  675. end;
  676.  
  677. procedure TQBEQuery.PSExecute;
  678. begin
  679.   ExecQBE;
  680. end;
  681.  
  682. procedure TQBEQuery.PSSetCommandText(const CommandText: string);
  683. begin
  684.   if CommandText <> '' then
  685.     QBE.Text := CommandText;
  686. end;
  687.  
  688. {$ENDIF RX_D5}
  689.  
  690. end.