Subject | Re: [IBO] Syncronizing transactions |
---|---|
Author | hans@hoogstraat.ca |
Post date | 2002-05-25T20:28:13Z |
Hope the following is of some use to someone ...
This little data synchronization setup is easily maintained
and expanded. Due to it's on demand nature, it has a minimum
impact on the server and client software. DML caching has
many more options, but this is all I needed for an Airport
Arrival/Departure time like test.
Best Regards
Hans
================================
Add a little Table to the server
================================
CREATE TABLE TABLES_UPDATE (
RELATION_NAME CHAR( 31 ) NOT NULL
, DATETIME_UPDATED TIMESTAMP
, COUNT_UPDATED DECIMAL ( 18, 0 )
, PRIMARY KEY (RELATION_NAME)
)
====================================================
Add a little server procedure to maintain this table
====================================================
CREATE PROCEDURE TABLE_UPDATE( RELATION_NAME CHAR( 31 ) )
AS
BEGIN
/* Check if Table entry Present */
IF (NOT EXISTS (SELECT COUNT_UPDATED FROM TABLES_UPDATE
WHERE RELATION_NAME = :RELATION_NAME)) THEN
/* Not present, Create first Entry */
INSERT INTO TABLES_UPDATE
(RELATION_NAME,DATETIME_UPDATED,COUNT_UPDATED)
VALUES
(:RELATION_NAME,CURRENT_TIMESTAMP,1);
ELSE
/* Update Entry for Sync Requests */
BEGIN
UPDATE TABLES_UPDATE SET DATETIME_UPDATED = CURRENT_TIMESTAMP,
COUNT_UPDATED = COUNT_UPDATED+1
WHERE RELATION_NAME = :RELATION_NAME;
END
END
=====================================================
Now, for each Table to be part of the synchronization
add the EXECUTE PROCEDURE TABLE_UPDATE ('TABLE1');
statement to it's 'After Insert', 'After Update'
and 'After Delete' triger, like :
=====================================================
CREATE TRIGGER TABLE1_AFTER_INSERT FOR TABLE1
AFTER INSERT ... AFTER UPDATE ... AFTER DELETE
AS
BEGIN
... your statements ..
EXECUTE PROCEDURE TABLE_UPDATE ('TABLE1');
END
==========================
Add the Delphi client site
==========================
var
ResyncSecs : Double; // No of Secs to Resync when Idle
ResyncTime : TDateTime;
Application.OnIdle := MyIdleHandler;
=======================================================
When the Client is in Idle state for x No of secs, the
Idle handler will check and refresh Tables of interest.
This little example just checks for 'TABLE1' only
=======================================================
// Idle Handler ===========================================
procedure TFNotesMain.MyIdleHandler(Sender: TObject; var Done: Boolean);
var
IdleBookMark : String;
begin
// about every ResyncSecs secs
with DM do
if Now - ResyncTime > ResyncSecs / (24.0*3600.0) then
begin
ResyncTime := Now;
// Make sure Table is in Browse mode
if IBTable1.Active and (IBTable1.State = dsBrowse) then
begin
// Get latest update count for this table via an IBOQuery or
IB_Query
IBTables_Update.Close;
IBTables_Update.SQL.Text := 'SELECT COUNT_UPDATED FROM TABLES_UPDATE
WHERE RELATION_NAME=TABLE1';
IBTables_Update.Prepare;
IBTables_Update.Open;
// Check if it macthes our update count held in our Tag
if not IBTables_Update.IsEmpty then
if IBTable1.Tag <> IBTables_UpdateCount_Updated.value then
begin
// Update took place, Refresh
IBTable1.Tag := IBTables_UpdateCount_Updated.value;
try
IdleBookMark := IBTable1.BookMark; // Hold our location
IBTable1.Refresh; // if this Table is
IBTable1.BookMark := IdleBookMark; // used in a Grid
except
end;
end;
end;
end;
end;
This little data synchronization setup is easily maintained
and expanded. Due to it's on demand nature, it has a minimum
impact on the server and client software. DML caching has
many more options, but this is all I needed for an Airport
Arrival/Departure time like test.
Best Regards
Hans
================================
Add a little Table to the server
================================
CREATE TABLE TABLES_UPDATE (
RELATION_NAME CHAR( 31 ) NOT NULL
, DATETIME_UPDATED TIMESTAMP
, COUNT_UPDATED DECIMAL ( 18, 0 )
, PRIMARY KEY (RELATION_NAME)
)
====================================================
Add a little server procedure to maintain this table
====================================================
CREATE PROCEDURE TABLE_UPDATE( RELATION_NAME CHAR( 31 ) )
AS
BEGIN
/* Check if Table entry Present */
IF (NOT EXISTS (SELECT COUNT_UPDATED FROM TABLES_UPDATE
WHERE RELATION_NAME = :RELATION_NAME)) THEN
/* Not present, Create first Entry */
INSERT INTO TABLES_UPDATE
(RELATION_NAME,DATETIME_UPDATED,COUNT_UPDATED)
VALUES
(:RELATION_NAME,CURRENT_TIMESTAMP,1);
ELSE
/* Update Entry for Sync Requests */
BEGIN
UPDATE TABLES_UPDATE SET DATETIME_UPDATED = CURRENT_TIMESTAMP,
COUNT_UPDATED = COUNT_UPDATED+1
WHERE RELATION_NAME = :RELATION_NAME;
END
END
=====================================================
Now, for each Table to be part of the synchronization
add the EXECUTE PROCEDURE TABLE_UPDATE ('TABLE1');
statement to it's 'After Insert', 'After Update'
and 'After Delete' triger, like :
=====================================================
CREATE TRIGGER TABLE1_AFTER_INSERT FOR TABLE1
AFTER INSERT ... AFTER UPDATE ... AFTER DELETE
AS
BEGIN
... your statements ..
EXECUTE PROCEDURE TABLE_UPDATE ('TABLE1');
END
==========================
Add the Delphi client site
==========================
var
ResyncSecs : Double; // No of Secs to Resync when Idle
ResyncTime : TDateTime;
Application.OnIdle := MyIdleHandler;
=======================================================
When the Client is in Idle state for x No of secs, the
Idle handler will check and refresh Tables of interest.
This little example just checks for 'TABLE1' only
=======================================================
// Idle Handler ===========================================
procedure TFNotesMain.MyIdleHandler(Sender: TObject; var Done: Boolean);
var
IdleBookMark : String;
begin
// about every ResyncSecs secs
with DM do
if Now - ResyncTime > ResyncSecs / (24.0*3600.0) then
begin
ResyncTime := Now;
// Make sure Table is in Browse mode
if IBTable1.Active and (IBTable1.State = dsBrowse) then
begin
// Get latest update count for this table via an IBOQuery or
IB_Query
IBTables_Update.Close;
IBTables_Update.SQL.Text := 'SELECT COUNT_UPDATED FROM TABLES_UPDATE
WHERE RELATION_NAME=TABLE1';
IBTables_Update.Prepare;
IBTables_Update.Open;
// Check if it macthes our update count held in our Tag
if not IBTables_Update.IsEmpty then
if IBTable1.Tag <> IBTables_UpdateCount_Updated.value then
begin
// Update took place, Refresh
IBTable1.Tag := IBTables_UpdateCount_Updated.value;
try
IdleBookMark := IBTable1.BookMark; // Hold our location
IBTable1.Refresh; // if this Table is
IBTable1.BookMark := IdleBookMark; // used in a Grid
except
end;
end;
end;
end;
end;