home *** CD-ROM | disk | FTP | other *** search
/ Chip 2001 December / Chip_2001-12_cd1.bin / zkuste / delphi / kompon / d23456 / BKQUERY.ZIP / uBkQuery.pas next >
Encoding:
Pascal/Delphi Source File  |  2001-10-02  |  16.6 KB  |  570 lines

  1. (*******************************************************************************
  2.     BkQuery - Backgroud Query
  3.     BkQuery:= EQuery + Backgroud Query = Wait Query + Parse Query + Backgroud Query
  4.  
  5.     Author: J. Tungli, T-SOFT (c) 2001  mailto:jan.tungli@seznam.cz
  6.  
  7.  *******************************************************************************
  8.  
  9.   BkCommands:   ( BkOpen, BkExecSQL, BkLocate, BkFindFirst, BkLast, ... )
  10.       if BkQueryTread is not created, BkCommand automatically create
  11.       new BkQueryThread. When a BkCommand is ready call OnBkReady event.
  12.  
  13.   OnBkReady event:
  14.       Procedure OnBkReady(Sender: TObject; Msg:String; AResult:integer) of object;
  15.       Msg    : result message text (coresponding with ReadyMsg property)
  16.       AResult: result executed result value (1=true 0=false,
  17.                     (coresponding with ReadyResult property)
  18.  
  19.   BkQueryThread:
  20.       create BkCommands front in thread : ... ->  BkCommand2 -> BkCommand1
  21.       and provide for first command must finish first
  22.  
  23.   BkStop command:
  24.       wait for BkCommands front finish and dispose BkQueryThread
  25.  
  26.   BkTerminate command:
  27.       dispose BkQueryThread immediatelly, dont wait for BkCommands front finish
  28.  
  29.   Example:
  30.       BkQuery1.Database_AliasName:='DBDEMOS';
  31.       BkQuery1.sql.text:='select * from Country';
  32.       BkQuery1.DisableControls;
  33.       BkQuery1.BkOpen;
  34.       BkQuery1.BkLocate('Name','Venez',[loPartialkey]);
  35.       ...
  36.       BkQuery1.BkStop;
  37.       BkQuery1.EnableControls;
  38.  
  39. ********************************************************************************)
  40.  
  41. unit uBkQuery;
  42.  
  43. interface
  44.  
  45. uses
  46.   Windows, Messages, SysUtils, Classes, DB, DBTables,Forms,Controls,stdctrls,Dialogs,uEQuery;
  47.  
  48. const
  49.    UM_BkReady=WM_User+191;
  50. type
  51.   TOnBkReady = procedure (Sender: TObject; Msg:String; AResult:integer) of object;
  52.  
  53.   TBkWC=class(TStaticText)
  54.   private
  55.     fMaster:TComponent;
  56.   protected
  57.     procedure UM_BkReady(var AMessage : TMessage); message UM_BkReady;
  58.     { Protected declarations }
  59.   public
  60.   published
  61.   end;
  62.  
  63.   TBkQuery = class(TEQuery)
  64.   private
  65.     fThreadRun:boolean;
  66.     fThread: TThread;
  67.     fIndex:integer;
  68.     fWC:TBkWC;
  69.     fRes:integer;
  70.     fMsg: string;
  71.     fSession:TSession;
  72.     fDatabase:TDatabase;
  73.     fDBParams:TStringList;
  74.     fDBAlias:string;
  75.     fDBDriver:string;
  76.     fOnBkReady:TOnBkReady;
  77.     procedure SetfIndex(A:integer);
  78.     procedure SetfRes(A:integer);
  79.     procedure SetfMsg(A:string);
  80.     procedure BkInit;
  81.      {Private declarations }
  82.   protected
  83.     { Protected declarations }
  84.   public
  85.     constructor Create(AOwner: TComponent);override;
  86.     destructor Destroy; override;
  87.       { Public declarations }
  88.   published
  89.      property BkExecuteIndex:integer read fIndex write SetfIndex; {read only}
  90.      property ReadyResult: integer read fRes write SetfRes; {read only 1=true 0=false}
  91.      property ReadyMsg:string read fMsg write SetfMsg; {read only}
  92.      property Database_AliasName:string read fDBAlias write fDBAlias;
  93.      property Database_DriverName:string read fDBDriver write fDBDriver;
  94.      property Database_Params:TStringList read fDBParams write fDBParams;
  95.      property OnBkReady : TOnBkReady read fOnBkReady write fOnBkReady;
  96.      procedure BkOpen;
  97.      procedure BkExecSQL(ATransaction:boolean=false; ARollBack:boolean=true);
  98.      procedure BkPost;
  99.      procedure BkApplyUpdates;
  100.      procedure BkMoveBy(AMove:integer);
  101.      procedure BkFirst;
  102.      procedure BkLast;
  103.      procedure BkNext;
  104.      procedure BkPrior;
  105.      procedure BkLocate(const AKeyFields: String; const AKeyValues: Variant; AOptions: TLocateOptions);
  106.      procedure BkFindFirst;
  107.      procedure BkFindLast;
  108.      procedure BkFindNext;
  109.      procedure BkFindPrior;
  110.      procedure BkGotoBookMark(ABookMark:TBookMark);
  111.      procedure BkFetchAll;
  112.      procedure BkCommitUpdates;
  113.      procedure BkRecordCount;
  114.      procedure BkDisableControls;
  115.      procedure BkEnableControls;
  116.      procedure BkStop;
  117.      procedure BkTerminate;
  118.     { Published declarations }
  119.   end;
  120.  
  121. procedure Register;
  122.  
  123. implementation
  124.  
  125. type
  126.   TQueryThread = class(TThread)
  127.   private
  128.     fExit       : boolean;
  129.     fMessageText: string;
  130.     fTrans,fRollBack : boolean;
  131.     fAction     : byte;
  132.     fKeyFields  : string;
  133.     fKeyValues  : variant;
  134.     fOptions    : TLocateOptions;
  135.     fMove       : integer;
  136.     fBookMark   : TBookMark;
  137.  
  138.     fBkQuery    : TBkQuery;
  139.     fResult     : integer;
  140.     //procedure QueryReady;
  141.     { Private declarations }
  142.   protected
  143.     procedure Execute; override;
  144.     procedure Start( ABkQuery:TBkQuery;AAction:byte;
  145.                      ATransaction,ARollBack:boolean;
  146.                      AKeyFields  : string;
  147.                      AKeyValues  : variant;
  148.                      AOptions    : TLocateOptions;
  149.                      AMove       : integer;
  150.                      ABookMark   : TBookMark);
  151.     procedure Stop(ABkQuery:TBkQuery);
  152.     { Protected declarations }
  153.   public
  154.     constructor Create;
  155.     destructor Destroy; override;
  156.       { Public declarations }
  157.   published
  158.     { Published declarations }
  159.   end;
  160.  
  161. var
  162.   gIndex:integer;
  163.  
  164. constructor TBkQuery.Create(AOwner: TComponent);
  165. begin
  166.   inherited Create(AOwner);
  167.   fWC:=nil;fSession:=nil; fDatabase:=nil;
  168.   fMsg:=''; fRes:=0; fThread:=nil;
  169.   fDBParams:=TStringList.Create;
  170. end;
  171.  
  172. destructor TBkQuery.Destroy;
  173. begin
  174.   fDBParams.Free;
  175.   if fSession<>nil then begin fSession.Close; fSession.Free; end;
  176.   if fDatabase<>nil then fDatabase.Free;
  177.   if fThread<>nil then begin
  178.     fThread.Terminate;
  179.     fThread.WaitFor;
  180.   end;
  181.   inherited Destroy;
  182. end;
  183.  
  184. procedure TQueryThread.Stop(ABkQuery:TBkQuery);
  185. begin
  186.   fBkQuery:=ABkQuery;
  187.   fBkQuery.fThreadRun:=true;
  188.   fExit:=true;
  189.   Resume;
  190. end;
  191.  
  192. procedure TQueryThread.Start( ABkQuery:TBkQuery;AAction:byte;
  193.                         ATransaction,ARollBack:boolean;
  194.                         AKeyFields  : string;
  195.                         AKeyValues  : variant;
  196.                         AOptions    : TLocateOptions;
  197.                         AMove       : integer;
  198.                         ABookMark   : TBookMark);
  199. begin
  200.   fExit:=false;
  201.   fBkQuery:=ABkQuery;
  202.   fRollBack:=ARollBack;
  203.   fTrans:=ATransaction;
  204.   fAction:=AAction;
  205.   fKeyFields:=AKeyFields;
  206.   fKeyValues:=AKeyValues;
  207.   fOptions:=AOptions;
  208.   fMove:=AMove;
  209.   fBookMark:=ABookMark;
  210.   Resume;
  211. end;
  212.  
  213. constructor TQueryThread.Create;
  214. begin
  215.   FreeOnTerminate := True;
  216.   inherited Create(true);
  217. end;
  218.  
  219. destructor TQueryThread.Destroy;
  220. begin
  221.   inherited Destroy;
  222. end;
  223.  
  224. const
  225.   cTransaction:boolean=false;
  226.   cRollBack:boolean=true;
  227.   cKeyFields:string='';
  228.   cOptions:TLocateOptions=[];
  229.   cMove: integer=0;
  230.   cBookMark:TBookMark=nil;
  231. var
  232.   Guard: Integer;
  233.   Numbers: Integer;
  234.   cKeyValues:Variant;
  235. { Thread safe increment of Numbers to guarantee the result is unique }
  236.  
  237. function GetUniqueNumber: Integer;
  238. asm
  239. @@1:    MOV     EDX,1
  240.         XCHG    Guard,EDX
  241.         OR      EDX,EDX
  242.         JNZ     @@2
  243.         MOV     EAX,Numbers
  244.         INC     EAX
  245.         MOV     Numbers,EAX
  246.         MOV     Guard,EDX
  247.         RET
  248.  
  249. @@2:    PUSH    0
  250.         CALL    Sleep
  251.         JMP     @@1
  252. end;
  253.  
  254. procedure TBkWC.UM_BkReady(var AMessage : TMessage);
  255. begin
  256.   if fMaster is TbkQuery then
  257.     with TBkQuery(fMaster) do begin
  258.       if Assigned(fOnBkReady) then fOnBkReady(TBkQuery(fMaster),fMsg,fRes);
  259.     end;
  260. end;
  261.  
  262. procedure TQueryThread.Execute;
  263.     procedure Posted;
  264.     begin
  265.       fBkQuery.fMsg:=fMessageText;
  266.       fBkQuery.fRes:=fResult;
  267.       //if fBkQuery.fIndex=gIndex then fBkQuery.EnableControls;
  268.       if fBkQuery.fWC<>nil then PostMessage(fBkQuery.fWC.Handle,UM_BkReady,0,0);
  269.       fBkQuery.fThreadRun:=false;
  270.       Suspend;
  271.     end;
  272.  
  273. //var UniqueNumber: Integer;
  274. begin
  275.   while not Terminated do begin
  276.     try
  277.       if fExit then begin fBkQuery.fThreadRun:=false; exit; end;
  278.       //UniqueNumber := GetUniqueNumber;
  279.       with fBkQuery do begin
  280.         if fSession=nil then fSession:=TSession.Create(nil) else begin
  281.           if fAction<=2 then fSession.close;
  282.         end;
  283.         if fDatabase=nil then fDatabase:=TDatabase.Create(nil) else begin
  284.           if fAction<=2 then fDatabase.Connected:=false;
  285.         end;
  286.         if fAction<=2 then begin
  287.           fSession.SessionName :='Session_'+fBkQuery.Name;
  288.           fDatabase.DatabaseName :='Database_'+fBkQuery.Name;
  289.           fDatabase.SessionName := fSession.SessionName;
  290.           fDatabase.LoginPrompt:=false;
  291.           fDataBase.DriverName:=fDBDriver;
  292.           fDatabase.AliasName:=fDBAlias;
  293.           fDatabase.Params.Text:=fDBParams.Text;
  294.           SessionName := fDatabase.SessionName;
  295.           DatabaseName := fDatabase.DatabaseName;
  296.           SessionName := fDatabase.SessionName;
  297.           DatabaseName := fDatabase.DatabaseName;
  298.         end;
  299.         fResult:=1;
  300.         case fAction of
  301.         1:Open;
  302.         2:if fTrans then begin
  303.             fDatabase.StartTransaction;
  304.             ExecSQL;
  305.             fMessageText := 'OK';
  306.             fDatabase.Commit;
  307.             Posted; //Synchronize(QueryReady);
  308.             continue;
  309.           end else begin
  310.             ExecSQL;
  311.           end;
  312.         3: Post;
  313.         4: ApplyUpdates;
  314.         5: fResult:=MoveBy(fMove);
  315.         6: First;
  316.         7: Last;
  317.         8: Next;
  318.         9: Prior;
  319.         10:if Active and Locate(fKeyFields,fKeyValues,fOptions) then fResult:=1 else begin fResult:=0; fMessageText:='Datset is closed'; end;
  320.         11:if Active and FindFirst then fResult:=1 else begin fResult:=0; fMessageText:='Datset is closed'; end;
  321.         12:if Active and FindLast then fResult:=1 else begin fResult:=0; fMessageText:='Datset is closed'; end;
  322.         13:if Active and FindNext then fResult:=1 else begin fResult:=0; fMessageText:='Datset is closed'; end;
  323.         14:if Active and FindPrior then fResult:=1 else begin fResult:=0; fMessageText:='Datset is closed'; end;
  324.         15:GotoBookMark(fBookMark);
  325.         16:FetchAll;
  326.         17:CommitUpdates;
  327.         18:fResult:=RecordCount;
  328.         19:DisableControls;
  329.         20:EnableControls;
  330.         end;
  331.         fMessageText := 'OK';
  332.         Posted;
  333.         continue;
  334.         //QueryReady;
  335.         //Synchronize(QueryReady);
  336.       end;
  337.     except
  338.       on E: Exception do
  339.       begin
  340.         fResult:=0;
  341.         { Display any error we receive on the status line }
  342.         fMessageText := Format('%s: %s.', [E.ClassName, E.Message]);
  343.         if fTrans then begin
  344.           if fRollBack then begin
  345.             fMessageText:=fMessageText+' -> Rollback';
  346.             fBkQuery.fDatabase.Rollback;
  347.           end else begin
  348.             try fBkQuery.fDatabase.Commit; except end;
  349.           end;
  350.         end;
  351.         Posted;//Synchronize(QueryReady);
  352.        end;
  353.     end;
  354.   end;
  355. end;
  356.  
  357. // -------------------------------
  358.  
  359. procedure TBkQuery.BkOpen;
  360. begin
  361.   BkInit;
  362.   if (trim(fDbAlias)='') and (DatabaseName<>'') then fDbAlias:=DatabaseName;
  363.   if Active then Close;
  364.   TQueryThread(fThread).Start(Self,1,cTransaction,cRollBack,
  365.                        cKeyFields,cKeyValues,cOptions,cMove,cBookMark);
  366. end;
  367.  
  368. procedure TbkQuery.BkExecSQL(ATransaction:boolean=false;ARollBack:boolean=true);
  369. begin
  370.   BkInit;
  371.   if (trim(fDbAlias)='') and (DatabaseName<>'') then fDbAlias:=DatabaseName;
  372.   if Active then Close;
  373.   TQueryThread(fThread).Start(Self,2,ATransaction,ARollBack,
  374.                        cKeyFields,cKeyValues,cOptions,cMove,cBookMark);
  375. end;
  376.  
  377. procedure TbkQuery.BkPost;
  378. begin
  379.   BkInit;
  380.   TQueryThread(fThread).Start(Self,3,cTransaction,cRollBack,
  381.                        cKeyFields,cKeyValues,cOptions,cMove,cBookMark);
  382. end;
  383.  
  384. procedure TbkQuery.BkApplyUpdates;
  385. begin
  386.   BkInit;
  387.   TQueryThread(fThread).Start(Self,4,cTransaction,cRollBack,
  388.                        cKeyFields,cKeyValues,cOptions,cMove,cBookMark);
  389. end;
  390.  
  391. procedure TbkQuery.BkMoveBy(AMove:integer);
  392. begin
  393.   BkInit;
  394.   TQueryThread(fThread).Start(Self,5,cTransaction,cRollBack,
  395.                        cKeyFields,cKeyValues,cOptions,AMove,cBookMark);
  396. end;
  397.  
  398. procedure TbkQuery.BkFirst;
  399. begin
  400.   BkInit;
  401.   TQueryThread(fThread).Start(Self,6,cTransaction,cRollBack,
  402.                        cKeyFields,cKeyValues,cOptions,cMove,cBookMark);
  403. end;
  404.  
  405. procedure TbkQuery.BkLast;
  406. begin
  407.   BkInit;
  408.   TQueryThread(fThread).Start(Self,7,cTransaction,cRollBack,
  409.                        cKeyFields,cKeyValues,cOptions,cMove,cBookMark);
  410. end;
  411.  
  412. procedure TbkQuery.BkNext;
  413. begin
  414.   BkInit;
  415.   TQueryThread(fThread).Start(Self,8,cTransaction,cRollBack,
  416.                        cKeyFields,cKeyValues,cOptions,cMove,cBookMark);
  417. end;
  418.  
  419. procedure TbkQuery.BkPrior;
  420. begin
  421.   BkInit;
  422.   TQueryThread(fThread).Start(Self,9,cTransaction,cRollBack,
  423.                        cKeyFields,cKeyValues,cOptions,cMove,cBookMark);
  424. end;
  425.  
  426. procedure TbkQuery.BkLocate(const AKeyFields: String; const AKeyValues: Variant; AOptions: TLocateOptions);
  427. begin
  428.   BkInit;
  429.   TQueryThread(fThread).Start(Self,10,cTransaction,cRollBack,
  430.                        AKeyFields,AKeyValues,AOptions,cMove,cBookMark);
  431. end;
  432.  
  433. procedure TbkQuery.BkFindFirst;
  434. begin
  435.   BkInit;
  436.   TQueryThread(fThread).Start(Self,11,cTransaction,cRollBack,
  437.                        cKeyFields,cKeyValues,cOptions,cMove,cBookMark);
  438. end;
  439.  
  440. procedure TbkQuery.BkFindLast;
  441. begin
  442.   BkInit;
  443.   TQueryThread(fThread).Start(Self,12,cTransaction,cRollBack,
  444.                        cKeyFields,cKeyValues,cOptions,cMove,cBookMark);
  445. end;
  446.  
  447. procedure TbkQuery.BkFindNext;
  448. begin
  449.   BkInit;
  450.   TQueryThread(fThread).Start(Self,13,cTransaction,cRollBack,
  451.                        cKeyFields,cKeyValues,cOptions,cMove,cBookMark);
  452. end;
  453.  
  454. procedure TbkQuery.BkFindPrior;
  455. begin
  456.   BkInit;
  457.   TQueryThread(fThread).Start(Self,14,cTransaction,cRollBack,
  458.                        cKeyFields,cKeyValues,cOptions,cMove,cBookMark);
  459. end;
  460.  
  461. procedure TbkQuery.BkGotoBookMark(ABookMark:TBookMark);
  462. begin
  463.   BkInit;
  464.   TQueryThread(fThread).Start(Self,15,cTransaction,cRollBack,
  465.                         cKeyFields,cKeyValues,cOptions,cMove,ABookMark);
  466. end;
  467.  
  468. procedure TbkQuery.BkFetchAll;
  469. begin
  470.   BkInit;
  471.   TQueryThread(fThread).Start(Self,3,cTransaction,cRollBack,
  472.                        cKeyFields,cKeyValues,cOptions,cMove,cBookMark);
  473. end;
  474.  
  475. procedure TbkQuery.BkCommitUpdates;
  476. begin
  477.   BkInit;
  478.   TQueryThread(fThread).Start(Self,17,cTransaction,cRollBack,
  479.                        cKeyFields,cKeyValues,cOptions,cMove,cBookMark);
  480. end;
  481.  
  482. procedure TbkQuery.BkRecordCount;
  483. begin
  484.   BkInit;
  485.   TQueryThread(fThread).Start(Self,18,cTransaction,cRollBack,
  486.                        cKeyFields,cKeyValues,cOptions,cMove,cBookMark);
  487. end;
  488.  
  489. procedure TbkQuery.BkDisableControls;
  490. begin
  491.   BkInit;
  492.   TQueryThread(fThread).Start(Self,19,cTransaction,cRollBack,
  493.                        cKeyFields,cKeyValues,cOptions,cMove,cBookMark);
  494. end;
  495.  
  496. procedure TbkQuery.BkEnableControls;
  497. begin
  498.   BkInit;
  499.   TQueryThread(fThread).Start(Self,20,cTransaction,cRollBack,
  500.                        cKeyFields,cKeyValues,cOptions,cMove,cBookMark);
  501. end;
  502.  
  503. procedure TbkQuery.BkStop;
  504. begin
  505.   while gIndex>fIndex do Application.ProcessMessages;
  506.   Application.ProcessMessages;
  507.   while fThreadRun do Application.ProcessMessages;
  508.   if fThread=nil then begin fIndex:=0; gIndex:=0; exit; end;
  509.   TQueryThread(fThread).Stop(Self);
  510.   while fThreadRun do Application.ProcessMessages;
  511.   fThread:=nil;
  512.   fIndex:=0; gIndex:=0;
  513. end;
  514.  
  515. procedure TbkQuery.BkTerminate;
  516. begin
  517.   if fThread=nil then exit;
  518.   TQueryThread(fThread).Stop(Self);
  519.   Application.ProcessMessages;
  520.   if fThread<>nil then TQueryThread(fThread).Terminate;
  521.   fThreadRun:=false;
  522.   fIndex:=0; gIndex:=0;
  523.   fThread:=nil;
  524. end;
  525.  
  526. procedure TBkQuery.BkInit;
  527. begin
  528.   gIndex:=fIndex+1;if gIndex=MaxInt then gIndex:=1;
  529.   Application.ProcessMessages;
  530.   while fThreadRun do Application.ProcessMessages;
  531.   if fThread=nil then fThread:=TQueryThread.Create;
  532.  
  533.   fThreadRun:=true;
  534.   inc(fIndex); if fIndex=MaxInt then fIndex:=1;
  535.   fMsg:=''; fRes:=0;
  536.   if (fWC=nil) then begin
  537.     fWC:=TBkWC.Create(Owner);
  538.     fWC.Width:=0; fWC.Height:=0;
  539.     fWC.Name:=Name+'_WC';
  540.     fWC.Caption:='';
  541.     if Owner is TForm then
  542.       fWC.Parent:=TWinControl(Owner)
  543.       else fWC.Parent:=Screen.ActiveForm;
  544.     fWC.fMaster:=Self;
  545.   end;
  546. end;
  547.  
  548. procedure TBkQuery.SetfIndex(A:integer);
  549. begin
  550.   if csDesigning in ComponentState then ShowMessage('property is read only');
  551. end;
  552.  
  553. procedure TBkQuery.SetfRes(A:integer);
  554. begin
  555.   if csDesigning in ComponentState then ShowMessage('property is read only');
  556. end;
  557.  
  558. procedure TBkQuery.SetfMsg(A:string);
  559. begin
  560.   if csDesigning in ComponentState then ShowMessage('property is read only');
  561. end;
  562.  
  563.  
  564. procedure Register;
  565. begin
  566.   RegisterComponents('Samples', [TBkQuery]);
  567. end;
  568.  
  569. end.
  570.