Subject | Problem with triggers, and master detail setup |
---|---|
Author | Adrian Wreyford |
Post date | 2010-07-04T06:33:35Z |
Hi, this one has had me baffled for days. I'm not sure if it is IBO or Firebird.
I will go through the steps that replicate the problem:
Create Master table .. lets call it Clients
Create Child table ... lets call it Vehicle
The Vehicle table has VehicleID, an autoincrement field set up using a simple trigger.
The Vehicle table has VehicleID as primary key field.
Here follows both tables metadata.
SET SQL DIALECT 3;
/***********************************/
/* Tables */
/***********************************/
CREATE TABLE CLIENTS (
CLIENTID Integer NOT NULL,
CLIENTCOMPANY Varchar(100) NOT NULL,
CONSTRAINT PK_CLIENTS PRIMARY KEY (CLIENTCOMPANY)
);
CREATE TABLE VEHICLE (
VEHICLEID Integer NOT NULL,
VEHICLECLIENTID Integer NOT NULL,
VEHICLEREGNR Varchar(15) NOT NULL,
CONSTRAINT PK_VEHICLE PRIMARY KEY (VEHICLEID)
);
/***********************************/
/* Generators */
/***********************************/
CREATE GENERATOR GEN_CLIENTS_ID;
CREATE GENERATOR GEN_VEHICLE_ID;
SET GENERATOR GEN_CLIENTS_ID TO 5;
SET GENERATOR GEN_VEHICLE_ID TO 46;
COMMIT WORK;
SET TERM ^ ;
/***********************************/
/* Triggers */
/***********************************/
CREATE TRIGGER TR_GEN_CLIENTS_ID FOR CLIENTS
ACTIVE BEFORE INSERT POSITION 0
AS
begin
IF (NEW.CLIENTID IS NULL) THEN
NEW.CLIENTID=GEN_ID(GEN_CLIENTS_ID,1);
end^
CREATE TRIGGER TR_GEN_VEHICLE_ID FOR VEHICLE
ACTIVE BEFORE INSERT POSITION 0
AS
begin
IF (NEW.VEHICLEID IS NULL) THEN
NEW.VEHICLEID=GEN_ID(GEN_VEHICLE_ID,1);
end^
COMMIT WORK^
SET TERM ; ^
/* Grant role for this database */
/* Grant permissions for this database */
COMMIT WORK;
//***************************************************************************************//
Now that we have the tables set up we need to create a small project in Delphi.
On a form set up two IB_Queries
IB_QueryClients
IB_QueryVehicle
IB_QueryVehicle.MasterSource := IB_DataSourceClients
IB_QueryVehicle.MasterLinks := 'VEHICLE.VEHICLECLIENTID = CLIENTS.CLIENTID'
IB_QueryVehicle.KeyLinksAutoDefine := True // PS setting this to false and KeyLink to Vehicle.VehicleID, doesn't change anything.
We set up the Column Attribute for ClientID, and VehicleID as COMPUTED on the server. //For the trigger to work.
We drop two IB_NavigationBars and two IB_Update bars on the form, and link to the respective datasources.
Drop a IB_Grid for the Client, and below this the IB_Vehicle's NAv and Update bar, with a IB_Grid linked to the IB_Vehicle below this.
NOW run the test:
Add a few clients. The ClientID is correctly calculated, and you don't fill this in
Now add a VEHICLE:
Only enter the VehicleRegNr, and then post the record.
The VehicleClientID correctly displays in the grid, with the regnr entered, but the VehicleID ramains blank.
Now put the vehicle dataset into edit mode, and edit the vehicle RegistrationNr, and post the changes.
You get an error: Record was not located to update.
If I browse the client DB forward and backward, then locate the vehicle record just entered, the VehicleID displays, and you can then edit it.
If you set up an IB_monitor, the update DML looks like this:
[ 2010/07/03 11:37:41 AM ]
EXECUTE STATEMENT
TR_HANDLE = 24
STMT_HANDLE = 27
PARAMS = [ Version 1 SQLd 45 SQLn 45
VEHICLE.VEHICLECLIENTID = 2
VEHICLE.VEHICLEREGNR = 'TESTING1231'
VEHICLE.VEHICLEID = <n> 0 ]
Notice the Vehicle.VehicleID = <n> 0 .. this is not correct.
If I make the VehicleRegNr the Primary key, and not the VehicleID, it works as expected.
Can anybody explain, and help me right here, or is this a bug?
Thanks.. I hope I have been clear enough.
Adrian Wreyford
[Non-text portions of this message have been removed]
I will go through the steps that replicate the problem:
Create Master table .. lets call it Clients
Create Child table ... lets call it Vehicle
The Vehicle table has VehicleID, an autoincrement field set up using a simple trigger.
The Vehicle table has VehicleID as primary key field.
Here follows both tables metadata.
SET SQL DIALECT 3;
/***********************************/
/* Tables */
/***********************************/
CREATE TABLE CLIENTS (
CLIENTID Integer NOT NULL,
CLIENTCOMPANY Varchar(100) NOT NULL,
CONSTRAINT PK_CLIENTS PRIMARY KEY (CLIENTCOMPANY)
);
CREATE TABLE VEHICLE (
VEHICLEID Integer NOT NULL,
VEHICLECLIENTID Integer NOT NULL,
VEHICLEREGNR Varchar(15) NOT NULL,
CONSTRAINT PK_VEHICLE PRIMARY KEY (VEHICLEID)
);
/***********************************/
/* Generators */
/***********************************/
CREATE GENERATOR GEN_CLIENTS_ID;
CREATE GENERATOR GEN_VEHICLE_ID;
SET GENERATOR GEN_CLIENTS_ID TO 5;
SET GENERATOR GEN_VEHICLE_ID TO 46;
COMMIT WORK;
SET TERM ^ ;
/***********************************/
/* Triggers */
/***********************************/
CREATE TRIGGER TR_GEN_CLIENTS_ID FOR CLIENTS
ACTIVE BEFORE INSERT POSITION 0
AS
begin
IF (NEW.CLIENTID IS NULL) THEN
NEW.CLIENTID=GEN_ID(GEN_CLIENTS_ID,1);
end^
CREATE TRIGGER TR_GEN_VEHICLE_ID FOR VEHICLE
ACTIVE BEFORE INSERT POSITION 0
AS
begin
IF (NEW.VEHICLEID IS NULL) THEN
NEW.VEHICLEID=GEN_ID(GEN_VEHICLE_ID,1);
end^
COMMIT WORK^
SET TERM ; ^
/* Grant role for this database */
/* Grant permissions for this database */
COMMIT WORK;
//***************************************************************************************//
Now that we have the tables set up we need to create a small project in Delphi.
On a form set up two IB_Queries
IB_QueryClients
IB_QueryVehicle
IB_QueryVehicle.MasterSource := IB_DataSourceClients
IB_QueryVehicle.MasterLinks := 'VEHICLE.VEHICLECLIENTID = CLIENTS.CLIENTID'
IB_QueryVehicle.KeyLinksAutoDefine := True // PS setting this to false and KeyLink to Vehicle.VehicleID, doesn't change anything.
We set up the Column Attribute for ClientID, and VehicleID as COMPUTED on the server. //For the trigger to work.
We drop two IB_NavigationBars and two IB_Update bars on the form, and link to the respective datasources.
Drop a IB_Grid for the Client, and below this the IB_Vehicle's NAv and Update bar, with a IB_Grid linked to the IB_Vehicle below this.
NOW run the test:
Add a few clients. The ClientID is correctly calculated, and you don't fill this in
Now add a VEHICLE:
Only enter the VehicleRegNr, and then post the record.
The VehicleClientID correctly displays in the grid, with the regnr entered, but the VehicleID ramains blank.
Now put the vehicle dataset into edit mode, and edit the vehicle RegistrationNr, and post the changes.
You get an error: Record was not located to update.
If I browse the client DB forward and backward, then locate the vehicle record just entered, the VehicleID displays, and you can then edit it.
If you set up an IB_monitor, the update DML looks like this:
[ 2010/07/03 11:37:41 AM ]
EXECUTE STATEMENT
TR_HANDLE = 24
STMT_HANDLE = 27
PARAMS = [ Version 1 SQLd 45 SQLn 45
VEHICLE.VEHICLECLIENTID = 2
VEHICLE.VEHICLEREGNR = 'TESTING1231'
VEHICLE.VEHICLEID = <n> 0 ]
Notice the Vehicle.VehicleID = <n> 0 .. this is not correct.
If I make the VehicleRegNr the Primary key, and not the VehicleID, it works as expected.
Can anybody explain, and help me right here, or is this a bug?
Thanks.. I hope I have been clear enough.
Adrian Wreyford
[Non-text portions of this message have been removed]