Unexpected outcome of the "before insert" triger with subquery and EXISTS predicate along with further PK violation

45 Views Asked by At

I am managing a legacy web-app which process data using Firebird 2.5-based DB (runs on Ubuntu 18.04 server). All was OK for years, but I got something very strange recently.

There is a table with combined keys:

/******************************************************************************/
/*                                   Tables                                   */
/******************************************************************************/
CREATE TABLE STAT_VALIDATION (
    DATAREPORTID  D$BIGINT NOT NULL /* D$BIGINT = BIGINT */,
    PARAMGROUPID  D$INTEGER NOT NULL /* D$INTEGER = INTEGER */,
    KINDID        D$BIGINT NOT NULL /* D$BIGINT = BIGINT */,
    VALIDATIONID  D$BIGINT NOT NULL /* D$BIGINT = BIGINT */,
    ARG1          U$VARCHAR500 NOT NULL /* U$VARCHAR500 = VARCHAR(500) */,
    ARG2          U$VARCHAR500 /* U$VARCHAR500 = VARCHAR(500) */,
    NOTE          U$TEXTBLOB NOT NULL /* U$TEXTBLOB = BLOB SUB_TYPE 1 SEGMENT SIZE 80 */
);
/******************************************************************************/
/*                                Primary keys                                */
/******************************************************************************/
ALTER TABLE STAT_VALIDATION ADD CONSTRAINT PK_STAT_VALIDATION PRIMARY KEY (DATAREPORTID, PARAMGROUPID, KINDID, VALIDATIONID);
/******************************************************************************/
/*                                Foreign keys                                */
/******************************************************************************/
ALTER TABLE STAT_VALIDATION ADD CONSTRAINT FK_STAT_VALIDATION_DATAREPORTID FOREIGN KEY (DATAREPORTID, PARAMGROUPID, KINDID) REFERENCES STAT_DATA (DATAREPORTID, PARAMGROUPID, KINDID) ON DELETE CASCADE ON UPDATE CASCADE;
ALTER TABLE STAT_VALIDATION ADD CONSTRAINT FK_STAT_VALIDATION_VALIDATIONID FOREIGN KEY (VALIDATIONID) REFERENCES CONTENTTREE (NODEID) ON UPDATE CASCADE;

It also has a "before insert" trigger

/* Trigger: STAT_VALIDATION_BI0 */
CREATE OR ALTER TRIGGER STAT_VALIDATION_BI0 FOR STAT_VALIDATION
ACTIVE BEFORE INSERT POSITION 0
as
declare variable PARAMS D$VARCHAR500;
begin
  if (exists (
    select *
    from STAT_VALIDATION SV
    where SV.DATAREPORTID = new.DATAREPORTID
    and SV.PARAMGROUPID = new.PARAMGROUPID
    and SV.KINDID = new.KINDID
    and SV.VALIDATIONID = new.VALIDATIONID
  )) then
  begin
    select list(VSPG.PARAMNAME || '=' || VSPG.PARAMVALUE, ';')
    from V_STAT_PARAMGROUPS VSPG
    where VSPG.PARAMGROUPID = new.PARAMGROUPID
    into :PARAMS;

    exception E_CUSTOM_EXCEPTION 'Validation already exists: '
      || 'DATAREPORTID=' || new.DATAREPORTID
      || '; PARAMGROUPID=' || new.PARAMGROUPID
      || '; KINDID=' || new.KINDID
      || '; VALIDATIONID=' || new.VALIDATIONID
      || '; PARAMS: ' || :PARAMS;
  end
end

Data in the table looks like this Table data sample, so values in each of DATAREPORTID, PARAMGROUPID, KINDID, VALIDATIONID repeats - and only their combination must be unique.

The problem

A NEW record going to be inserted with the following values DATAREPORTID=214746; PARAMGROUPID=45542; KINDID=48062; VALIDATIONID=99517 (ARGs also exist but those content are insignificant there) And I got the following error message

Firebird statement execute error : exception 1 E_CUSTOM_EXCEPTION Validation already exists: DATAREPORTID=214746; PARAMGROUPID=45542; KINDID=48062; VALIDATIONID=99517; PARAMS: STAT_PARAM_SPECIALITYID=454;STAT_PARAM_EDUFORMID=444;STAT_P ARAM_EDUBASISID=449;STAT_PARAM_COUNTRYID=545;STAT_PARAM_COURSE=740 At trigger 'STAT_VALIDATION_BI0' line: 19, col: 5

An attempt of investigation

For investigation, I have executed a select part of the query from trigger manually (using IB Expert remotely):

select *
    from STAT_VALIDATION SV
    where SV.DATAREPORTID = 214746
    and SV.PARAMGROUPID = 45542
    and SV.KINDID = 48062
    and SV.VALIDATIONID = 99517

As I expect, no records found:

Query results

Same way I have checked for only DATAREPORTID value:

select *
    from STAT_VALIDATION SV
    where SV.DATAREPORTID = 214746

Also - no records found (which is correct)

Some additional info: When I remove condition and run test query again:

select *
    from STAT_VALIDATION SV
    where SV.PARAMGROUPID = 45542
    and SV.KINDID = 48062
    and SV.VALIDATIONID = 99517
  • I am receiving existing record:
    existing record (previous)
  • which is expected by logic of this app. But in this record value of DATAREPORTID is different.

Almost in desperation I have deactivated trigger and tried to insert mentioned record again This time I got the following error

Firebird statement execute error : violation of PRIMARY or UNIQUE KEY constraint "PK_STAT_VALIDATION" on table "STAT_VALIDATION" Problematic key value is ("DATAREPORTID" = 214746, "PARAMGROUPID" = 45542, "KINDID" = 48062, "VALIDATIONID" = 99517)

Could somebody at least explain for: Why trigger has been fired? Why PK violation has happens? We have a composite PK based on 4 fields DATAREPORTID, PARAMGROUPID, KINDID, VALIDATIONID Within given new record:

  • value of DATAREPORTID not available in this DB table,
  • values of PARAMGROUPID, KINDID, VALIDATIONID - have been repeated in this DB table. As for me final combination must be unique and PK requiremets have to be fulfilled. But trigger has been fired / PC violation ossurs. How it is possible? Or do I miss (do not know) something important?

As I noted in post - I have tried to execute sub-query manually and got expected responses. But of the trigger and PK constraints is incorrect.

0

There are 0 best solutions below