home *** CD-ROM | disk | FTP | other *** search
/ Delphi Anthology / aDELPHI.iso / Runimage / Delphi50 / Source / Vcl / ibquery.pas < prev    next >
Pascal/Delphi Source File  |  1999-08-11  |  11KB  |  454 lines

  1. {********************************************************}
  2. {                                                        }
  3. {       Borland Delphi Visual Component Library          }
  4. {       InterBase Express core components                }
  5. {                                                        }
  6. {       Copyright (c) 1998-1999 Inprise Corporation      }
  7. {                                                        }
  8. {    InterBase Express is based in part on the product   }
  9. {    Free IB Components, written by Gregory H. Deatz for }
  10. {    Hoagland, Longo, Moran, Dunst & Doukas Company.     }
  11. {    Free IB Components is used under license.           }
  12. {                                                        }
  13. {********************************************************}
  14.  
  15. unit IBQuery;
  16.  
  17. interface
  18.  
  19. uses Windows, SysUtils, Graphics, Classes, Controls, Db, StdVCL,
  20.      IBHeader, IB, IBCustomDataSet, IBSQL;
  21.  
  22. type
  23.  
  24. { TIBQuery }
  25.  
  26.   TIBQuery = class(TIBCustomDataSet)
  27.   private
  28.     FSQL: TStrings;
  29.     FPrepared: Boolean;
  30.     FParams: TParams;
  31.     FText: string;
  32.     FRowsAffected: Integer;
  33.     FCheckRowsAffected: Boolean;
  34.     FGenerateParamNames: Boolean;
  35.     function GetRowsAffected: Integer;
  36.     procedure PrepareSQL(Value: PChar);
  37.     procedure QueryChanged(Sender: TObject);
  38.     procedure ReadParamData(Reader: TReader);
  39.     procedure SetQuery(Value: TStrings);
  40.     procedure SetParamsList(Value: TParams);
  41.     procedure SetParams;
  42.     procedure SetParamsFromCursor;
  43.     procedure SetPrepared(Value: Boolean);
  44.     procedure SetPrepare(Value: Boolean);
  45.     procedure WriteParamData(Writer: TWriter);
  46.     function GetStmtHandle: TISC_STMT_HANDLE;
  47.   protected
  48.     { IProviderSupport }
  49.     procedure PSExecute; override;
  50.     function PSGetParams: TParams; override;
  51.     function PSGetTableName: string; override;
  52.     procedure PSSetCommandText(const CommandText: string); override;
  53.     procedure PSSetParams(AParams: TParams); override;
  54.  
  55.     procedure DefineProperties(Filer: TFiler); override;
  56.     procedure InitFieldDefs; override;
  57.     procedure InternalOpen; override;
  58.     procedure Disconnect; override;
  59.     function GetParamsCount: Word;
  60.     function GenerateQueryForLiveUpdate : Boolean;
  61.     procedure SetFiltered(Value: Boolean); override;
  62.  
  63.   public
  64.     constructor Create(AOwner: TComponent); override;
  65.     destructor Destroy; override;
  66.     procedure BatchInput(InputObject: TIBBatchInput);
  67.     procedure BatchOutput(OutputObject: TIBBatchOutput);
  68.     procedure ExecSQL;
  69.     procedure GetDetailLinkFields(MasterFields, DetailFields: TList); override;
  70.     function ParamByName(const Value: string): TParam;
  71.     procedure Prepare;
  72.     procedure UnPrepare;
  73.     property Prepared: Boolean read FPrepared write SetPrepare;
  74.     property ParamCount: Word read GetParamsCount;
  75.     property StmtHandle: TISC_STMT_HANDLE read GetStmtHandle;
  76.     property Text: string read FText;
  77.     property RowsAffected: Integer read GetRowsAffected;
  78.     property GenerateParamNames: Boolean read FGenerateParamNames write FGenerateParamNames;
  79.   published
  80.     property CachedUpdates;
  81.     property DataSource read GetDataSource write SetDataSource;
  82.     property Constraints stored ConstraintsStored;
  83.     property ParamCheck;
  84.     property SQL: TStrings read FSQL write SetQuery;
  85.     property Params: TParams read FParams write SetParamsList stored False;
  86.     property UniDirectional default False;
  87.     property UpdateObject;
  88. end;
  89.  
  90. implementation
  91.  
  92. { TIBQuery }
  93.  
  94. constructor TIBQuery.Create(AOwner: TComponent);
  95. begin
  96.   inherited Create(AOwner);
  97.   FSQL := TStringList.Create;
  98.   TStringList(SQL).OnChange := QueryChanged;
  99.   FParams := TParams.Create(Self);
  100.   ParamCheck := True;
  101.   FGenerateParamNames := False;
  102.   FRowsAffected := -1;
  103. end;
  104.  
  105. destructor TIBQuery.Destroy;
  106. begin
  107.   Destroying;
  108.   Disconnect;
  109.   SQL.Free;
  110.   FParams.Free;
  111.   inherited Destroy;
  112. end;
  113.  
  114. procedure TIBQuery.InitFieldDefs;
  115. begin
  116.   if not Active then
  117.     SelectSQL.Assign(SQL);
  118.   inherited;
  119. end;
  120.  
  121. procedure TIBQuery.InternalOpen;
  122. begin
  123.   ActivateConnection();
  124.   ActivateTransaction;
  125.   QSelect.GenerateParamNames := FGenerateParamNames;
  126.   SelectSQL.Assign(SQL);
  127.   SetPrepared(True);
  128.   if DataSource <> nil then SetParamsFromCursor;
  129.   SetParams;
  130.   inherited InternalOpen;
  131. end;
  132.  
  133. procedure TIBQuery.Disconnect;
  134. begin
  135.   Close;
  136.   UnPrepare;
  137. end;
  138.  
  139. procedure TIBQuery.SetPrepare(Value: Boolean);
  140. begin
  141.   if Value then Prepare
  142.   else UnPrepare;
  143. end;
  144.  
  145. procedure TIBQuery.Prepare;
  146. begin
  147.   SetPrepared(True);
  148. end;
  149.  
  150. procedure TIBQuery.UnPrepare;
  151. begin
  152.   SetPrepared(False);
  153. end;
  154.  
  155. procedure TIBQuery.SetQuery(Value: TStrings);
  156. begin
  157.   if SQL.Text <> Value.Text then
  158.   begin
  159.     Disconnect;
  160.     SQL.BeginUpdate;
  161.     try
  162.       SQL.Assign(Value);
  163.     finally
  164.       SQL.EndUpdate;
  165.     end;
  166.   end;
  167. end;
  168.  
  169. procedure TIBQuery.QueryChanged(Sender: TObject);
  170. var
  171.   List: TParams;
  172. begin
  173.   if not (csReading in ComponentState) then
  174.   begin
  175.     Disconnect;
  176.     if ParamCheck or (csDesigning in ComponentState) then
  177.     begin
  178.       List := TParams.Create(Self);
  179.       try
  180.         FText := List.ParseSQL(SQL.Text, True);
  181.         List.AssignValues(FParams);
  182.         FParams.Clear;
  183.         FParams.Assign(List);
  184.       finally
  185.         List.Free;
  186.       end;
  187.     end else
  188.       FText := SQL.Text;
  189.     DataEvent(dePropertyChange, 0);
  190.   end else
  191.     FText := FParams.ParseSQL(SQL.Text, False);
  192. end;
  193.  
  194. procedure TIBQuery.SetParamsList(Value: TParams);
  195. begin
  196.   FParams.AssignValues(Value);
  197. end;
  198.  
  199. function TIBQuery.GetParamsCount: Word;
  200. begin
  201.   Result := FParams.Count;
  202. end;
  203.  
  204. procedure TIBQuery.DefineProperties(Filer: TFiler);
  205.  
  206.   function WriteData: Boolean;
  207.   begin
  208.     if Filer.Ancestor <> nil then
  209.       Result := not FParams.IsEqual(TIBQuery(Filer.Ancestor).FParams) else
  210.       Result := FParams.Count > 0;
  211.   end;
  212.  
  213. begin
  214.   inherited DefineProperties(Filer);
  215.   Filer.DefineProperty('ParamData', ReadParamData, WriteParamData, WriteData); {do not localize}
  216. end;
  217.  
  218. procedure TIBQuery.ReadParamData(Reader: TReader);
  219. begin
  220.   Reader.ReadValue;
  221.   Reader.ReadCollection(FParams);
  222. end;
  223.  
  224. procedure TIBQuery.WriteParamData(Writer: TWriter);
  225. begin
  226.   Writer.WriteCollection(Params);
  227. end;
  228.  
  229. procedure TIBQuery.SetPrepared(Value: Boolean);
  230. begin
  231.   CheckDatasetClosed;
  232.   if Value <> Prepared then
  233.   begin
  234.     if Value then
  235.     begin
  236.       FRowsAffected := -1;
  237.       FCheckRowsAffected := True;
  238.       if Length(Text) > 1 then PrepareSQL(PChar(Text))
  239.       else IBError(ibxeEmptySQLStatement, [nil]);
  240.     end
  241.     else
  242.     begin
  243.       if FCheckRowsAffected then
  244.         FRowsAffected := RowsAffected;
  245.       InternalUnPrepare;
  246.     end;
  247.     FPrepared := Value;
  248.   end;
  249. end;
  250.  
  251. procedure TIBQuery.SetParamsFromCursor;
  252. var
  253.   I: Integer;
  254.   DataSet: TDataSet;
  255.  
  256.   procedure CheckRequiredParams;
  257.   var
  258.     I: Integer;
  259.   begin
  260.     for I := 0 to FParams.Count - 1 do
  261.     with FParams[I] do
  262.       if not Bound then
  263.         IBError(ibxeRequiredParamNotSet, [nil]);
  264.   end;
  265.  
  266. begin
  267.   if DataSource <> nil then
  268.   begin
  269.     DataSet := DataSource.DataSet;
  270.     if DataSet <> nil then
  271.     begin
  272.       DataSet.FieldDefs.Update;
  273.       for I := 0 to FParams.Count - 1 do
  274.         with FParams[I] do
  275.           if not Bound then
  276.           begin
  277.             AssignField(DataSet.FieldByName(Name));
  278.             Bound := False;
  279.           end;
  280.     end
  281.     else
  282.       CheckRequiredParams;
  283.   end
  284.   else
  285.     CheckRequiredParams;
  286. end;
  287.  
  288.  
  289. function TIBQuery.ParamByName(const Value: string): TParam;
  290. begin
  291.   Result := FParams.ParamByName(Value);
  292. end;
  293.  
  294. procedure TIBQuery.BatchInput(InputObject: TIBBatchInput);
  295. begin
  296.   InternalBatchInput(InputObject);
  297. end;
  298.  
  299. procedure TIBQuery.BatchOutput(OutputObject: TIBBatchOutput);
  300. begin
  301.   InternalBatchOutput(OutputObject);
  302. end;
  303.  
  304. procedure TIBQuery.ExecSQL;
  305. var
  306.   DidActivate: Boolean;
  307. begin
  308.   CheckInActive;
  309.   if SQL.Count <= 0 then
  310.   begin
  311.     FCheckRowsAffected := False;
  312.     IBError(ibxeEmptySQLStatement, [nil]);
  313.   end;
  314.   ActivateConnection();
  315.   DidActivate := ActivateTransaction;
  316.   try
  317.     SetPrepared(True);
  318.     if DataSource <> nil then SetParamsFromCursor;
  319.     if FParams.Count > 0 then SetParams;
  320.     InternalExecQuery;
  321.   finally
  322.     if DidActivate then
  323.       DeactivateTransaction;
  324.     FCheckRowsAffected := True;
  325.   end;
  326. end;
  327.  
  328. procedure TIBQuery.SetParams;
  329. var
  330. i : integer;
  331. begin
  332.   for I := 0 to FParams.Count - 1 do
  333.   begin
  334.     if Params[i].IsNull then
  335.       SQLParams[i].IsNull := True
  336.     else begin
  337.       SQLParams[i].IsNull := False;
  338.       case Params[i].DataType of
  339.         ftString:
  340.           SQLParams[i].AsString := Params[i].AsString;
  341.         ftBoolean, ftSmallint, ftWord:
  342.           SQLParams[i].AsShort := Params[i].AsSmallInt;
  343.         ftInteger:
  344.           SQLParams[i].AsLong := Params[i].AsInteger;
  345. {        ftLargeInt:
  346.           SQLParams[i].AsInt64 := Params[i].AsLargeInt; }
  347.         ftFloat, ftCurrency:
  348.          SQLParams[i].AsDouble := Params[i].AsFloat;
  349.         ftBCD:
  350.           SQLParams[i].AsCurrency := Params[i].AsCurrency;
  351.         ftDate:
  352.           SQLParams[i].AsDate := Params[i].AsDateTime;
  353.         ftTime:
  354.           SQLParams[i].AsTime := Params[i].AsDateTime;
  355.         ftDateTime:
  356.           SQLParams[i].AsDateTime := Params[i].AsDateTime;
  357.         ftBlob, ftMemo:
  358.           SQLParams[i].AsString := Params[i].AsString;
  359.         else
  360.           IBError(ibxeNotSupported, [nil]);
  361.       end;
  362.     end;
  363.   end;
  364. end;
  365.  
  366. procedure TIBQuery.PrepareSQL(Value: PChar);
  367. begin
  368.   QSelect.GenerateParamNames := FGenerateParamNames;
  369.   SelectSQL := SQL;
  370.   InternalPrepare;
  371. end;
  372.  
  373.  
  374. function TIBQuery.GetRowsAffected: Integer;
  375. begin
  376.   Result := -1;
  377.   if Prepared then
  378.    Result := QSelect.RowsAffected
  379. end;
  380.  
  381.  
  382. procedure TIBQuery.GetDetailLinkFields(MasterFields, DetailFields: TList);
  383.  
  384.   function AddFieldToList(const FieldName: string; DataSet: TDataSet;
  385.     List: TList): Boolean;
  386.   var
  387.     Field: TField;
  388.   begin
  389.     Field := DataSet.FindField(FieldName);
  390.     if (Field <> nil) then
  391.       List.Add(Field);
  392.     Result := Field <> nil;
  393.   end;
  394.  
  395. var
  396.   i: Integer;
  397. begin
  398.   MasterFields.Clear;
  399.   DetailFields.Clear;
  400.   if (DataSource <> nil) and (DataSource.DataSet <> nil) then
  401.     for i := 0 to Params.Count - 1 do
  402.       if AddFieldToList(Params[i].Name, DataSource.DataSet, MasterFields) then
  403.         AddFieldToList(Params[i].Name, Self, DetailFields);
  404. end;
  405.  
  406. function TIBQuery.GetStmtHandle: TISC_STMT_HANDLE;
  407. begin
  408.   Result := SelectStmtHandle;
  409. end;
  410.  
  411. function TIBQuery.GenerateQueryForLiveUpdate : Boolean;
  412. begin
  413.   Result := False;
  414. end;
  415.  
  416. procedure TIBQuery.SetFiltered(Value: Boolean);
  417. begin
  418.   if Value <> False then
  419.     IBError(ibxeNotSupported, [nil]);
  420. end;
  421.  
  422. { TIBQuery IProviderSupport }
  423.  
  424. function TIBQuery.PSGetParams: TParams;
  425. begin
  426.   Result := Params;
  427. end;
  428.  
  429. procedure TIBQuery.PSSetParams(AParams: TParams);
  430. begin
  431.   if AParams.Count <> 0 then
  432.     Params.Assign(AParams);
  433.   Close;
  434. end;
  435.  
  436. function TIBQuery.PSGetTableName: string;
  437. begin
  438.   Result := QSelect.UniqueRelationName;
  439. end;
  440.  
  441. procedure TIBQuery.PSExecute;
  442. begin
  443.   ExecSQL;
  444. end;
  445.  
  446. procedure TIBQuery.PSSetCommandText(const CommandText: string);
  447. begin
  448.   if CommandText <> '' then
  449.     SQL.Text := CommandText;
  450. end;
  451.  
  452. end.
  453.  
  454.