home *** CD-ROM | disk | FTP | other *** search
/ Chip 1997 April / Chip_1997-04_cd.bin / prezent / cb / data.z / BTSCLASS.PAS < prev    next >
Pascal/Delphi Source File  |  1997-01-16  |  19KB  |  742 lines

  1.  
  2. {*******************************************************}
  3. {                                                       }
  4. {       Borland Bug Tracking System                     }
  5. {       Misc. Support Classes                           }
  6. {                                                       }
  7. {       Copyright (C) 1993,96 Borland International     }
  8. {                                                       }
  9. {*******************************************************}
  10.  
  11. unit BtsClass;
  12.  
  13. interface
  14.  
  15. uses Windows, SysUtils, Classes, MIFiles, DB, DBTables, BtsConst, BDE;
  16.  
  17. const
  18.   fldnoNetName    = 3;  { USER table, Network Name field }
  19.  
  20. type
  21.  
  22. { Exceptions }
  23.  
  24.   EBts = class(Exception);
  25.   ENoRecords = class(EBts);
  26.   ESystemDown = class(EBts);
  27.   EInvalidField = class(EBts)
  28.   public
  29.     Field: TField;
  30.     constructor Create(AField: TField; const Msg: string);
  31.   end;
  32.   EMissingAttach = class(EInvalidField);
  33.  
  34. { Notifications }
  35.  
  36.   EDisplayOutline = class(Exception)
  37.   public
  38.     ItemCode: Double;
  39.     constructor Create(ACode: Double);
  40.   end;
  41.  
  42. { TLookupList }
  43.  
  44.   PStrItem = ^TStrItem;
  45.   TStrItem = record
  46.     FObject: TObject;
  47.     FCode: Integer;
  48.     FDesc: PChar;
  49.     FValue: string;
  50.     FString: string;
  51.   end;
  52.  
  53.   TLookupList = class(TStrings)
  54.   private
  55.     List: TList;
  56.     FCoded: Boolean;
  57.     FUseDesc: Boolean;
  58.     FTableName: string;
  59.   protected
  60.     CodeSep: string;
  61.     DescSep: string;
  62.     function NewStrItem(const S: string): PStrItem;
  63.     procedure DisposeStrItem(P: PStrItem);
  64.     function Get(Index: Integer): string; override;
  65.     function GetCount: Integer; override;
  66.     function GetObject(Index: Integer): TObject; override;
  67.     procedure Put(Index: Integer; const S: string); override;
  68.     procedure PutObject(Index: Integer; AObject: TObject); override;
  69.     function GetValue(Index: Integer): string;
  70.     function GetDesc(Index: Integer): string;
  71.     function GetCode(Index: Integer): Integer;
  72.     function GetItem(Index: Integer): string;
  73.   public
  74.     constructor Create;
  75.     destructor Destroy; override;
  76.     procedure Delete(Index: Integer); override;
  77.     procedure Insert(Index: Integer; const S: string); override;
  78.     procedure Clear; override;
  79.     function IndexOfValue(const S: string): Integer;
  80.     function IndexOfDesc(const S: string): Integer;
  81.     function IndexOfCode(ACode: Integer): Integer;
  82.     function IndexOfItem(const S: string): Integer;
  83.     function CodeToValue(ACode: Integer): string;
  84.     function ValueToCode(const AValue: string): Integer;
  85.     property Value[Index: Integer]: string read GetValue;
  86.     property Desc[Index: Integer]: string read GetDesc;
  87.     property Code[Index: Integer]: Integer read GetCode;
  88.     property Item[Index: Integer]: string read GetItem;
  89.     property UseDesc: Boolean read FUseDesc write FUseDesc;
  90.     property TableName: string read FTableName write FTableName;
  91.     property Coded: Boolean read FCoded;
  92.   end;
  93.  
  94. { TBtsUser }
  95.  
  96.   TBtsUser = class
  97.   private
  98.     FNetName: string;
  99.     FUserName: string;
  100.     FGroup: string;
  101.     FRights: TUserRights;
  102.     FRegistered: Boolean;
  103.   public
  104.     constructor Create(UserTab: TTable; GroupLook: TLookupList;
  105.       const DefRights: string);
  106.     procedure CheckRights(Value: TUserRights);
  107.     property Group: string read FGroup;
  108.     property NetName: string read FNetName;
  109.     property Rights: TUserRights read FRights;
  110.     property UserName: string read FUserName;
  111.     property Registered: Boolean read FRegistered write FRegistered;
  112.   end;
  113.  
  114. { TFieldMap }
  115.  
  116.   TFieldMap = class(TStringList)
  117.   private
  118.     function GetStatusValue(ResValue: Integer): Integer;
  119.   public
  120.     constructor Create(StatIni: TMemIniFile; const CfgSect: string);
  121.     property StatusValue[ResValue: Integer]: Integer read GetStatusValue;
  122.   end;
  123.  
  124. { TCloneDataset }
  125.  
  126.   TCloneDataset = class(TDBDataset)
  127.   private
  128.     FSourceHandle: HDBICur;
  129.     procedure SetSourceHandle(ASourceHandle: HDBICur);
  130.   protected
  131.     function CreateHandle: HDBICur; override;
  132.   public
  133.     property SourceHandle: HDBICur read FSourceHandle write SetSourceHandle;
  134.   end;
  135.  
  136. { TCloneTable }
  137.  
  138.   TCloneTable = class(TTable)
  139.   private
  140.     FSourceHandle: HDBICur;
  141.     procedure SetSourceHandle(ASourceHandle: HDBICur);
  142.   protected
  143.     function CreateHandle: HDBICur; override;
  144.   public
  145.     constructor CreateFromTable(AOwner: TComponent; Reset: Boolean);
  146.     procedure InitFromTable(SourceTable: TTable; Reset: Boolean);
  147.   end;
  148.  
  149. { TQueryField }
  150.  
  151.   TQueryField = class
  152.   protected
  153.     FQDType: TQueryDataType;
  154.     FFldNo: Integer;
  155.     FQRow: Integer;
  156.     FQText: string;
  157.     FFldName: string;
  158.     FLookupTableName: string;
  159.   public
  160.     LookupData: array[1..2] of TQueryField;
  161.     constructor Create(AQDType: TQueryDataType; AFldNo: Integer; AQText: string);
  162.     destructor Destroy; override;
  163.     procedure InitLookupData(LookupList: TLookupList;
  164.      const Example, CodeFldName, DescFldName: string; ARow, ACol: Integer);
  165.     property FldNo: Integer read FFldNo;
  166.     property FldName: string read FFldName write FFldName;
  167.     property QText: string read FQText write FQText;
  168.     property QRow: Integer read FQRow write FQRow;
  169.     property QDType: TQueryDataType read FQDType;
  170.     property LookupTableName: string read FLookupTableName write FLookupTableName;
  171.   end;
  172.  
  173. { TQueryData }
  174.  
  175.   TQueryData = class(TList)
  176.   private
  177.     function Get(Index: Integer): TQueryField;
  178.   public
  179.     procedure Empty;
  180.     destructor Destroy; override;
  181.     property Items[Index: Integer]: TQueryField read Get; default;
  182.   end;
  183.  
  184. { TQBEQuery }
  185.  
  186.   TCheckType = (ctNone, ctCheck, ctCheckPlus, ctCheckDesc, ctCheckGroup);
  187.  
  188.   TQBEQuery = class(TQuery)
  189.   private
  190.     hQry: hDBIQry;
  191.   protected
  192.     function CreateHandle: HDBICur; override;
  193.   public
  194.     constructor Create(AOwner: TComponent); override;
  195.     procedure AddExpr(const TabName, FldName: string; Row: Integer;
  196.       CheckType: TCheckType; Expr: string);
  197.   end;
  198.  
  199. { TOtlData }
  200.  
  201.   TOtlData = class(TObject)
  202.   public
  203.     ProgName: PChar;
  204.     Tester: PChar;
  205.     HasChildren: Boolean;
  206.     constructor Create(PName, TName: PChar; ChildFlag: Boolean);
  207.     destructor Destroy; override;
  208.   end;
  209.  
  210. implementation
  211.  
  212. uses DBConsts;
  213.  
  214. { EInvalidField }
  215.  
  216. constructor EInvalidField.Create(AField: TField; const Msg: string);
  217. begin
  218.   Field := AField;
  219.   inherited Create(Msg);
  220. end;
  221.  
  222. { TDisplayOutline }
  223.  
  224. constructor EDisplayOutline.Create(ACode: Double);
  225. begin
  226.   ItemCode := ACode;
  227. end;
  228.  
  229. { TLookupList }
  230.  
  231. constructor TLookupList.Create;
  232. const
  233.   SCodeSep = '|';
  234.   SDescSep = ' - ';
  235. begin
  236.   inherited Create;
  237.   List := TList.Create;
  238.   CodeSep := SCodeSep;
  239.   DescSep := SDescSep;
  240. end;
  241.  
  242. destructor TLookupList.Destroy;
  243. begin
  244.   if List <> nil then
  245.   begin
  246.     Clear;
  247.     List.Destroy;
  248.   end;
  249.   inherited Destroy;
  250. end;
  251.  
  252. function TLookupList.NewStrItem(const S: string): PStrItem;
  253. var
  254.   CodeSepPos: Integer;
  255.   ValLen: Integer;
  256. begin
  257.   CodeSepPos := Pos(CodeSep, S);
  258.   FCoded := CodeSepPos > 0;
  259.   ValLen := Pos(DescSep, S) - 1;
  260.   if (ValLen > 0) and (CodeSepPos > 0) then
  261.     Dec(ValLen, CodeSepPos - 1 + Length(CodeSep));
  262.   Result := New(PStrItem);
  263.   if FCoded then
  264.   begin
  265.     Result^.FString := Copy(S, CodeSepPos + Length(CodeSep), Length(S));
  266.     Result^.FCode := StrToInt(Copy(S, 1, CodeSepPos - 1));
  267.   end else
  268.   begin
  269.     Result^.FString := S;
  270.     Result^.FCode := -1;
  271.   end;
  272.   with Result^ do
  273.   begin
  274.     FObject := nil;
  275.     if ValLen > 0 then
  276.     begin
  277.       { Make a copy of the value part, so we can access it easily }
  278.       FValue := Copy(FString, 1 , ValLen);
  279.       { And a pointer to only the description }
  280.       FDesc := @FString[ValLen + Length(DescSep) + 1];
  281.     end else
  282.     begin
  283.       FValue := FString;
  284.       FDesc := nil;
  285.     end;
  286.   end;
  287. end;
  288.  
  289. procedure TLookupList.DisposeStrItem(P: PStrItem);
  290. begin
  291.   P.FObject.Free;
  292.   Dispose(P);
  293. end;
  294.  
  295. function TLookupList.Get(Index: Integer): string;
  296. begin
  297.   Result := PStrItem(List[Index]).FString;
  298. end;
  299.  
  300. function TLookupList.GetObject(Index: Integer): TObject;
  301. begin
  302.   Result := PStrItem(List[Index]).FObject;
  303. end;
  304.  
  305. function TLookupList.GetCount: Integer;
  306. begin
  307.   Result := List.Count;
  308. end;
  309.  
  310. procedure TLookupList.Put(Index: Integer; const S: string);
  311. var
  312.   P: PStrItem;
  313. begin
  314.   P := List[Index];
  315.   List[Index] := NewStrItem(S);
  316.   DisposeStrItem(P);
  317. end;
  318.  
  319. procedure TLookupList.PutObject(Index: Integer; AObject: TObject);
  320. begin
  321.   PStrItem(List[Index]).FObject := AObject;
  322. end;
  323.  
  324. procedure TLookupList.Insert(Index: Integer; const S: string);
  325. begin
  326.   List.Expand.Insert(Index, NewStrItem(S));
  327. end;
  328.  
  329. procedure TLookupList.Delete(Index: Integer);
  330. begin
  331.   DisposeStrItem(List[Index]);
  332.   List.Delete(Index);
  333. end;
  334.  
  335. procedure TLookupList.Clear;
  336. var
  337.   I: Integer;
  338. begin
  339.   for I := 0 to List.Count - 1 do DisposeStrItem(List[I]);
  340.   List.Clear;
  341. end;
  342.  
  343. function TLookupList.GetValue(Index: Integer): string;
  344. begin
  345.   if Index >= 0 then
  346.     with PStrItem(List[Index])^ do
  347.       Result := FValue
  348.   else
  349.       Result := '';
  350. end;
  351.  
  352. function TLookupList.GetDesc(Index: Integer): string;
  353. begin
  354.   with PStrItem(List[Index])^ do
  355.     if Assigned(FDesc) then
  356.       Result := FDesc else
  357.       Result := '';
  358. end;
  359.  
  360. function TLookupList.GetCode(Index: Integer): Integer;
  361. begin
  362.   with PStrItem(List[Index])^ do
  363.     Result := FCode;
  364. end;
  365.  
  366. function TLookupList.GetItem(Index: Integer): string;
  367. begin
  368.   if UseDesc then
  369.     Result := GetDesc(Index) else
  370.     Result := GetValue(Index);
  371. end;
  372.  
  373. function TLookupList.IndexOfValue(const S: string): Integer;
  374. begin
  375.   for Result := 0 to GetCount - 1 do
  376.     if CompareText(GetValue(Result), S) = 0 then Exit;
  377.   Result := -1;
  378. end;
  379.  
  380. function TLookupList.IndexOfDesc(const S: string): Integer;
  381. begin
  382.   for Result := 0 to GetCount - 1 do
  383.     if CompareText(GetDesc(Result), S) = 0 then Exit;
  384.   Result := -1;
  385. end;
  386.  
  387. function TLookupList.IndexOfCode(ACode: Integer): Integer;
  388. begin
  389.   for Result := 0 to GetCount - 1 do
  390.     if ACode = GetCode(Result) then Exit;
  391.   Result := -1;
  392. end;
  393.  
  394. function TLookupList.IndexOfItem(const S: string): Integer;
  395. begin
  396.   if UseDesc then
  397.     Result := IndexOfDesc(S) else
  398.     Result := IndexOfValue(S);
  399. end;
  400.  
  401. function TLookupList.CodeToValue(ACode: Integer): string;
  402. var
  403.   Index: Integer;
  404. begin
  405.   Index := IndexOfCode(ACode);
  406.   if Index >= 0 then
  407.     Result := Item[Index] else
  408.     Result := EmptyStr;
  409. end;
  410.  
  411. function TLookupList.ValueToCode(const AValue: string): Integer;
  412. begin
  413.   Result := IndexOfItem(AValue);
  414.   if Result > -1 then Result := Code[Result];
  415. end;
  416.  
  417.  
  418. { TBtsUser }
  419.  
  420. constructor TBtsUser.Create(UserTab: TTable; GroupLook: TLookupList;
  421.   const DefRights: string);
  422. var
  423.   RightsStr: string;
  424.   NameBuf: array[0..255] of Char;
  425.  
  426.   procedure Str2Rights;
  427.   var
  428.     X: Byte;
  429.     I: Integer;
  430.   begin
  431.     FRights := [];
  432.     for I := 1 to Length(RightsStr) do
  433.     begin
  434.       X := Pos(RightsStr[I], sRightsChars);
  435.       if X > 0 then
  436.         Include(FRights, TUserRightsElement(X-1));
  437.     end;
  438.     if urDirectEntry in FRights then Include(FRights, urEntry);
  439.   end;
  440.  
  441. begin
  442.   if (DbiGetNetUserName(NameBuf) = 0) and (NameBuf[0] <> #0) then
  443.     SetString(FNetName, NameBuf, StrLen(NameBuf)) else
  444.     raise EBts.Create(SUnknownUser);
  445.  
  446.   with UserTab do
  447.   try
  448.     Open;
  449.     try
  450.       IndexName := 'NetName';
  451.     except
  452.       Close;
  453.       Exclusive := True;
  454.       Open;
  455.       AddIndex('NetName', Fields[fldnoNetName].FieldName, [ixCaseInsensitive]);
  456.       IndexName := 'NetName';
  457.     end;
  458.     if FindKey([NetName]) then
  459.     begin
  460.       FUserName := FieldByName('User Name').AsString;
  461.       FGroup := GroupLook.CodeToValue(FieldByName('Group').AsInteger);
  462.       RightsStr := FieldByName('Rights').AsString;
  463.     end else
  464.     begin
  465.       FUserName := NetName;
  466.       RightsStr := DefRights;
  467.       FGroup := 'User';
  468.     end;
  469.     Str2Rights;
  470.   finally
  471.     Close
  472.   end;
  473. end;
  474.  
  475. procedure TBtsUser.CheckRights(Value: TUserRights);
  476. var
  477.   S: string;
  478.   X: TUserRightsElement;
  479. begin
  480.   if not (Value <= Rights)  then
  481.   begin
  482.     S := SRights1;
  483.     for X := Low(X) to High(X) do
  484.       if (X in Value) and not (X in Rights) then
  485.         S := Format('%s%s, ', [S, SRights[X]]);
  486.     SetLength(S, Length(S) - 1); { remove last ", " }
  487.     S := S + SRights2;
  488.     raise EBts.Create(S);
  489.   end;
  490. end;
  491.  
  492. { TFieldMap }
  493.  
  494. constructor TFieldMap.Create(StatIni: TMemIniFile; const CfgSect: string);
  495. var
  496.   I, Count, BarPos: Integer;
  497.   S: string;
  498. begin
  499.   Count := StatIni.ReadInteger(CfgSect, ckCount, 0);
  500.   for I := 1 to Count do
  501.   begin
  502.     S := StatIni.ReadString(CfgSect, IntToStr(I), '');
  503.     BarPos := Pos('|', S);
  504.     if BarPos > 0 then
  505.       AddObject(Copy(S, 1, BarPos-1), TObject(StrToInt(Copy(S, BarPos+1, 5))));
  506.   end;
  507. end;
  508.  
  509. function TFieldMap.GetStatusValue(ResValue: Integer): Integer;
  510. begin
  511.   Result := IndexOf(IntToStr(ResValue));
  512.   if Result <> -1 then
  513.     Result := Integer(Objects[Result]);
  514. end;
  515.  
  516. { TCloneDataset }
  517.  
  518. procedure TCloneDataset.SetSourceHandle(ASourceHandle: HDBICur);
  519. begin
  520.   if ASourceHandle <> FSourceHandle then
  521.   begin
  522.     Close;
  523.     FSourceHandle := ASourceHandle;
  524.     if FSourceHandle <> nil then Open;
  525.   end;
  526. end;
  527.  
  528. function TCloneDataset.CreateHandle: HDBICur;
  529. begin
  530.    Check(DbiCloneCursor(FSourceHandle, False, False, Result));
  531. end;
  532.  
  533. { TCloneTable }
  534.  
  535. constructor TCloneTable.CreateFromTable(AOwner: TComponent; Reset: Boolean);
  536. begin
  537.   inherited Create(AOwner);
  538.   InitFromTable(TTable(AOwner), Reset);
  539. end;
  540.  
  541. procedure TCloneTable.InitFromTable(SourceTable: TTable; Reset: Boolean);
  542. begin
  543.   with SourceTable do
  544.   begin
  545.     Self.TableName := TableName;
  546.     Self.DatabaseName := DatabaseName;
  547.     if IndexName <> '' then
  548.       Self.IndexName := IndexName
  549.     else if IndexFieldNames <> '' then
  550.       Self.IndexFieldNames := IndexFieldNames;
  551.     SetSourceHandle(Handle);
  552.     Self.Filter := Filter;
  553.     Self.OnFilterRecord := OnFilterRecord;
  554.     Self.Filtered := Filtered;
  555.   end;
  556.   if Reset then
  557.   begin
  558.     Filtered := False;
  559.     DbiResetRange(Handle);
  560.     IndexName := '';
  561.     First;
  562.   end;
  563. end;
  564.  
  565. procedure TCloneTable.SetSourceHandle(ASourceHandle: HDBICur);
  566. begin
  567.   if ASourceHandle <> FSourceHandle then
  568.   begin
  569.     Close;
  570.     FSourceHandle := ASourceHandle;
  571.     if FSourceHandle <> nil then Open;
  572.   end;
  573. end;
  574.  
  575. function TCloneTable.CreateHandle: HDBICur;
  576. begin
  577.    Check(DbiCloneCursor(FSourceHandle, False, False, Result));
  578. end;
  579.  
  580. { TQueryField }
  581.  
  582. constructor TQueryField.Create(AQDType: TQueryDataType; AFldNo: Integer;
  583.   AQText: string);
  584. begin
  585.   FQDType := AQDType;
  586.   FFldNo := AFldNo;
  587.   FQText := AQText;
  588.   FQRow := 1;
  589. end;
  590.  
  591. destructor TQueryField.Destroy;
  592. begin
  593.   LookupData[1].Free;
  594.   LookupData[2].Free;
  595. end;
  596.  
  597. procedure TQueryField.InitLookupData(LookupList: TLookupList;
  598.   const Example, CodeFldName, DescFldName: string; ARow, ACol: Integer);
  599. var
  600.   Code: Integer;
  601. begin
  602.   Code := LookupList.ValueToCode(QText);
  603.   if Code <> -1 then
  604.     QText := IntToStr(Code)
  605.   else if (CompareText(QText, 'BADLINK') = 0) then
  606.   begin
  607.     LookupData[1] := TQueryField.Create(qdLookup, 1, Example + ',count=0');
  608.     LookupData[1].FldName := CodeFldName;
  609.     LookupData[1].LookupTableName := LookupList.TableName;
  610.     LookupData[1].QRow := ARow;
  611.     QText := Example + #33',not blank'; {#33 = Exclamation point}
  612.   end
  613.   else if not (CompareText(QText, SBLANK) = 0) or
  614.               (CompareText(QText, SNOTBLANK) = 0) then
  615.   begin
  616.     LookupData[1] := TQueryField.Create(qdLookup, 1, Example);
  617.     LookupData[1].FldName := CodeFldName;
  618.     LookupData[1].LookupTableName := LookupList.TableName;
  619.     LookupData[1].QRow := ARow;
  620.     LookupData[2] := TQueryField.Create(qdLookup, ACol, QText);
  621.     LookupData[2].LookupTableName := LookupList.TableName;
  622.     LookupData[2].FldName := DescFldName;
  623.     LookupData[2].QRow := ARow;
  624.     QText := Example;
  625.   end;
  626. end;
  627.  
  628. { TQueryData }
  629.  
  630. procedure TQueryData.Empty;
  631. var
  632.   I: Integer;
  633. begin
  634.   for I := 0 to Count - 1 do TQueryField(Items[I]).Free;
  635.   Count := 0;
  636. end;
  637.  
  638. destructor TQueryData.Destroy;
  639. begin
  640.   Empty;
  641.   inherited Destroy;
  642. end;
  643.  
  644. function TQueryData.Get(Index: Integer): TQueryField;
  645. begin
  646.   Result := inherited Items[Index];
  647. end;
  648.  
  649. { TQBEQuery }
  650.  
  651. type
  652.   TDbiQryFree = function(var hQry: hDBIQry): DbiResult; stdcall;
  653.  
  654.   TDbiQLowStart = function (hDb: hDbiDb; pszQryName: PChar;
  655.     eQryType: DbiQryType; var hQry: hDbiQry): DbiResult;  stdcall;
  656.  
  657.   TDbiQLowBuild = function(hQry: hDbiQry; pszTableName: PChar;
  658.     pszTableType: PChar; pszFieldName: PChar; iRowNum: Word;
  659.     eCheck: TCheckType; pszExpr: PChar): DbiResult; stdcall;
  660.  
  661.   TDbiQLowPrepare = function(hQry: hDbiQry;
  662.     TableBits: PWord): DbiResult; stdcall;
  663.  
  664.   TDbiQryOpen = function(hQry: hDBIQry; bUniDirec: Bool;
  665.     var hCur: hDBICur): DbiResult; stdcall;
  666.  
  667. var
  668.   DbiQLowStart: TDbiQLowStart;
  669.   DbiQLowBuild: TDbiQLowBuild;
  670.   DbiQLowPrepare: TDbiQLowPrepare;
  671.   DbiQryFree: TDbiQryFree;
  672.   DbiQryOpen: TDbiQryOpen;
  673.  
  674. procedure InitializeQBEProcedures;
  675. var
  676.   HModule: THandle;
  677. begin
  678.   if not Assigned(DbiQLowStart) then
  679.   begin
  680.     HModule := LoadLibrary('IDAPI32.DLL');
  681.     if HModule <= 32 then SysUtils.Abort;
  682.     DbiQLowStart := GetProcAddress(HModule, 'DbiQLowStart');
  683.     DbiQLowBuild := GetProcAddress(HModule, 'DbiQLowBuild');
  684.     DbiQLowPrepare := GetProcAddress(HModule, 'DbiQLowPrepare');
  685.     DbiQryOpen := GetProcAddress(HModule, 'DbiQryOpen');
  686.     DbiQryFree := GetProcAddress(HModule, 'DbiQryFree');
  687.     FreeLibrary(HModule);
  688.   end;
  689. end;
  690.  
  691. constructor TQBEQuery.Create(AOwner: TComponent);
  692. begin
  693.   inherited Create(AOwner);
  694.   InitializeQBEProcedures;
  695. end;
  696.  
  697. procedure TQBEQuery.AddExpr(const TabName, FldName: string; Row: Integer;
  698.   CheckType: TCheckType; Expr: string);
  699. begin
  700.   CheckInactive;
  701.   SetDBFlag(dbfOpened, True);
  702.   if hQry = nil then
  703.     Check(DbiQLowStart(DBHandle, nil, dbiqryDIRTY, hQry));
  704.   UniqueString(Expr);
  705.   try
  706.     Check(DbiQLowBuild(hQry, PChar(TabName), nil, PChar(FldName),
  707.       Row, CheckType, PChar(Expr)));
  708.   except
  709.     DbiQryFree(hQry);
  710.     raise;
  711.   end;
  712. end;
  713.  
  714. function TQBEQuery.CreateHandle: HDBICur;
  715. begin
  716.   try
  717.     Check(DbiQLowPrepare(hQry, nil));
  718.     Check(DbiQryOpen(hQry, True, Result));
  719.   finally
  720.     DbiQryFree(hQry);
  721.   end;
  722. end;
  723.  
  724. { TOtlData }
  725.  
  726. constructor TOtlData.Create(PName, TName: PChar; ChildFlag: Boolean);
  727. begin
  728.   inherited Create;
  729.   ProgName := StrNew(PName);
  730.   Tester := StrNew(TName);
  731.   HasChildren := ChildFlag;
  732. end;
  733.  
  734. destructor TOtlData.Destroy;
  735. begin
  736.   StrDispose(ProgName);
  737.   StrDispose(Tester);
  738.   inherited Destroy;
  739. end;
  740.  
  741. end.
  742.