{*******************************************************}
{                                                       }
{        Midas RemoteDataModule Pooler Demo             }
{                                                       }
{*******************************************************}

unit clntfrm;

interface

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
  DBClient, Db, Grids, DBGrids, StdCtrls, MConnect, Variants;

type
  TForm1 = class(TForm)
    Button1: TButton;
    Memo1: TMemo;
    DBGrid1: TDBGrid;
    ClientDataSet1: TClientDataSet;
    RemoteServer1: TDCOMConnection;
    DataSource1: TDataSource;
//    CDSClone: TClientDataSet;
    Button2: TButton;
    Button3: TButton;
    Edit1: TEdit;
    procedure Button1Click(Sender: TObject);
    procedure ClientDataSet1BeforeGetRecords(Sender: TObject;
      var OwnerData: OleVariant);
    procedure Button2Click(Sender: TObject);
    procedure Memo1Change(Sender: TObject);
    procedure CheckButtonActive(DataSet: TDataSet);
    procedure Button3Click(Sender: TObject);
    procedure RemoteServer1BeforeDisconnect(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

{
Build the group project to generate server.exe and client.exe.
Run the server first by selecting server.exe and Run Without
Debugging, or execute server.exe outside of Delphi.  Then run
client.exe.  Click "Run SQL" first, then "GetNextPacket".
}

// BeginExample: BeforeGetRecords
// Event: DBClient.TCustomClientDataSet.BeforeGetRecords
// Property: DBClient.TCustomClientDataSet.Active
// Property: DBClient.TCustomClientDataSet.FetchOnDemand
// Method: DBClient.TCustomClientDataSet.CloneCursor
// Method: DBClient.TCustomClientDataSet.GetNextPacket
// Property: DBClient.TCustomClientDataSet.PacketRecords
// Method: DB.TDataSet.Last

// BeginCode
{
This example shows how to use the BeforeGetRecords event
handler (a TRemoteEventType value) to send the provider
information it needs for incremental data fetching. Before
fetching the next data packet, the client dataset packages
up the key value of the last record so that the provider
knows where to begin the next data packet. It also sends
some application-specific information, which is stored in
Memo1.  This method is used to pass the sql statement and the
value of the first field for the last record to the server so
that the server can return the correct records. The complete
project using this code example is in
Demos/DelphiWin32/VCLWin32/MIDAS/Pooler.
}
procedure TForm1.ClientDataSet1BeforeGetRecords(Sender: TObject; var OwnerData: OleVariant);
var
  LastValue: OleVariant;
  CDSClone: TClientDataSet;
begin
  if ClientDataSet1.Active then
  begin
    CDSClone := TClientDataSet.Create(Form1);
    try
      CDSClone.CloneCursor(ClientDataSet1, True);
      { turn off FetchOnDemand so that the clone only fetches
        the last LOCAL record }
      CDSClone.FetchOnDemand := False;
      CDSClone.Last;
      LastValue := CDSClone.Fields[0].AsString;
      CDSClone.Close;
    finally
      CDSClone.Free;
    end;
  end else
    LastValue := NULL;
  OwnerData := VarArrayOf([Memo1.Lines.Text, LastValue]);
end;

procedure TForm1.Button2Click(Sender: TObject);
begin
  ClientDataSet1.PacketRecords := StrToInt(Edit1.Text);
  ClientDataSet1.GetNextPacket;
end;
// EndCode
// EndExample: BeforeGetRecords

// BeginExample: TCustomConnectionDataSets
// Property: DB.TCustomConnection.DataSets
// Property: DB.TCustomConnection.DataSetCount
// Method: DB.TDataSet.EnableControls
// Method: DB.TDataSet.DisableControls
// Property: DBClient.TCustomClientDataSet.Active
// Event: DB.TDataSet.AfterClose
// Event: DB.TDataSet.AfterOpen

// BeginCode
{
The following code fragment illustrates how DataSets and
DataSetCount can be used to ensure that an action is taken
for every open dataset.  Assign CheckButtonActive as the
AfterClose and AfterOpen event handlers for TClientDataSet1.
}
procedure TForm1.Button1Click(Sender: TObject);
var
  I: Integer;
begin
  if not RemoteServer1.Connected then
    RemoteServer1.Connected := True;
  ClientDataSet1.Close;
  with RemoteServer1 do
  begin
    for I := 0 to DataSetCount - 1 do
      DataSets[I].EnableControls;
  end;
  ClientDataSet1.Open;
end;

procedure TForm1.Button3Click(Sender: TObject);
var
  I: Integer;
begin
  ClientDataSet1.Close;
  RemoteServer1.Connected := False;
  with RemoteServer1 do
  begin
    for I := 0 to DataSetCount - 1 do
      DataSets[I].DisableControls;
  end;
end;

procedure TForm1.CheckButtonActive(DataSet: TDataSet);
begin
  Button1.Enabled := not ClientDataSet1.Active;
  Button2.Enabled := ClientDataSet1.Active;
  Button3.Enabled := ClientDataSet1.Active;
end;
// EndCode
// EndExample: TCustomConnectionDataSets

procedure TForm1.Memo1Change(Sender: TObject);
begin
  ClientDataSet1.Close;
end;

// BeginExample: BeforeDisconnect
// Event: DB.TCustomConnection.BeforeDisconnect
// Property: DBClient.TCustomClientDataSet.ChangeCount
// Method: DBClient.TCustomClientDataSet.ApplyUpdates

// BeginCode
{
This BeforeDisconnect event handler makes sure that the
client dataset has applied all its pending updates before
terminating the connection to the server.
}
procedure TForm1.RemoteServer1BeforeDisconnect(Sender: TObject);
begin
  if (ClientDataSet1.ChangeCount > 0) then 
    ClientDataSet1.ApplyUpdates(-1);
end;
// EndCode
// EndExample: BeforeDisconnect
end.
