View Issue Details

IDProjectCategoryView StatusLast Update
363RackTablesdefaultpublic2011-01-08 19:27
Reporterinfrastation Assigned Toadoom42  
PrioritynormalSeverityminorReproducibilityalways
Status closedResolutionfixed 
Product Version0.18.4 
Target Version0.19.0Fixed in Version0.19.0 
Summary363: same port_id twice in Link table
DescriptionA flaw in DB schema design allows one port to be more, than once, for example:

mysql> SELECT porta, portb FROM Link WHERE 61358 IN(porta, portb);
+-------+-------+
| porta | portb |
+-------+-------+
| 55395 | 61358 |
| 61358 | 62126 |
+-------+-------+
2 rows in set (0.00 sec)

The matter is, port_id X can occur once in porta and once in portb (once porta<portb constraint is met).
TagsNo tags attached.

Activities

adoom42

adoom42

2010-12-10 21:37

administrator   ~0000203

There are at least two ways to prevent this from happening - perform validation in PHP code or in the database itself using triggers. I believe handling it on the DB level is safer, since it will prevent users from inserting invalid data via other means. Here's how to handle it with triggers:

CREATE TRIGGER `checkForDuplicateLinksBeforeInsert` BEFORE INSERT ON `Link`
  FOR EACH ROW
BEGIN
  DECLARE count INTEGER;

  IF NEW.porta = NEW.portb THEN
    SET NEW.porta = NULL;
  END IF;

  SELECT COUNT(*) INTO count FROM Link WHERE porta IN (NEW.porta,NEW.portb) OR portb IN (NEW.porta,NEW.portb);

  IF count > 0 THEN
    SET NEW.porta = NULL;
  END IF;
END;

CREATE TRIGGER `checkForDuplicateLinksBeforeUpdate` BEFORE UPDATE ON `Link`
  FOR EACH ROW
BEGIN
  DECLARE count INTEGER;

  IF NEW.porta = NEW.portb THEN
    SET NEW.porta = NULL;
  END IF;

  SELECT COUNT(*) INTO count FROM Link WHERE
  (NEW.porta IN (porta,portb) AND NEW.porta != porta) OR
  (NEW.portb IN (porta,portb) AND NEW.portb != portb);
 
  IF count > 0 THEN
    SET NEW.porta = NULL;
  END IF;
END;

MySQL does not allow you to raise an exception or return a valid error message by other means, so if the validation check fails, it sets porta to NULL which violates the NOT NULL column constraint. Triggers are supported in MySQL >= 5.0 (I doubt many people still use 4.x).

Note that adding these triggers to an existing DB would not affect invalid data that already exists. That must be cleaned up manually.

Let me know if you want this added to version 0.19, I'll be glad to do it.
infrastation

infrastation

2010-12-11 10:51

administrator   ~0000206

Yes, that would be great, if you could handle this issue.
adoom42

adoom42

2010-12-24 20:23

administrator   ~0000211

Fixed in 0.19.0 (SVN commit 4064).
adoom42

adoom42

2011-01-08 19:27

administrator   ~0000218

Many users run MySQL <5.1.6 which requires the SUPER privilege to use triggers. Triggers were replaced with a SELECT-before-INSERT validation scheme. Perhaps they will be reintroduced someday when most users are running >5.1.6.

Issue History

Date Modified Username Field Change
2010-08-30 13:32 infrastation New Issue
2010-12-10 21:37 adoom42 Note Added: 0000203
2010-12-11 10:51 infrastation Status new => assigned
2010-12-11 10:51 infrastation Assigned To => adoom42
2010-12-11 10:51 infrastation Note Added: 0000206
2010-12-24 20:23 adoom42 Note Added: 0000211
2010-12-24 20:25 adoom42 Status assigned => closed
2010-12-24 20:25 adoom42 Resolution open => fixed
2010-12-24 20:25 adoom42 Fixed in Version => 0.19.0
2010-12-25 09:03 infrastation Target Version => 0.19.0
2011-01-08 19:27 adoom42 Note Added: 0000218