I'm working on a plugin and have an activation hook that creates several tables using dbDelta. The tables all get created without any errors or issues. Several of the tables have foreign key constraints, which all also work fine.
However, if I deactivate and reactive the plugin, the last constraint on each table throws the following:
WordPress database error You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'CONSTRAINT `fk_fkName` FOREIGN KEY (`Sour' at line 1 for query ALTER TABLE wp_table ADD COLUMN CONSTRAINT `fk_fkName` FOREIGN KEY (`Source`) REFERENCES wp_other_table (`SourceID`) ON DELETE RESTRICT ON UPDATE RESTRICT The function that is called is:
public static function create_table() { $sql = "CREATE TABLE " . self::$tbl_table . " ( `CustomerID` int NOT NULL AUTO_INCREMENT, `CompanyName` varchar(50) DEFAULT NULL, `FirstName` varchar(50) NOT NULL, `LastName` varchar(50) NOT NULL, `AddressStreet` varchar(50) NOT NULL, `AddressSecond` varchar(50) DEFAULT NULL, `AddressCity` varchar(50) NOT NULL, `AddressZip` varchar(10) NOT NULL, `PhoneNumber` varchar(13) DEFAULT NULL, `EmailAddress` varchar(50) DEFAULT NULL, `Commercial` bit(1) NOT NULL DEFAULT b'0', `Source` int NOT NULL, `DoNotTake` bit(1) NOT NULL DEFAULT b'0', `Preferred` bit(1) NOT NULL DEFAULT b'0', `Notes` varchar(300) DEFAULT NULL, PRIMARY KEY (`CustomerID`), CONSTRAINT `fk_fkName` FOREIGN KEY (`Source`) REFERENCES " . self::$tbl_other_table . " (`SourceID`) ON DELETE RESTRICT ON UPDATE RESTRICT ) ENGINE=InnoDB;"; dbDelta($sql); } *table names are obfuscated out of habit
In that particular table, there's only the one constraint, and it throws the error. In other tables there are as few as two and as many as five. It's always an error on the last constraint, and only on activations after the table was first created.
Things I've tried:
- Adding and removing whitespace around SQL keywords
- Adding a comma after the last constraint (it was the only actual difference between constraints that complain and those that don't)
Here's another example with multiple fk constraints:
CONSTRAINT `fk_fk1` FOREIGN KEY (`Field1`) REFERENCES " . self::$tbl_t1 . " (`Field1`) ON DELETE RESTRICT ON UPDATE RESTRICT, CONSTRAINT `fk_fk2` FOREIGN KEY (`Field2`) REFERENCES " . self::$tbl_t2 . " (`Field2`) ON DELETE RESTRICT ON UPDATE RESTRICT, CONSTRAINT `fk_fk3` FOREIGN KEY (`Field3`) REFERENCES " . self::$tbl_t3 . " (`Field3`) ON DELETE RESTRICT ON UPDATE RESTRICT, CONSTRAINT `fk_fk4` FOREIGN KEY (`Field4`) REFERENCES " . self::$tbl_t4 . " (`Field4`) ON DELETE RESTRICT ON UPDATE RESTRICT, CONSTRAINT `fk_fk5` FOREIGN KEY (`Field5`) REFERENCES " . self::$tbl_t5 . " (`Field5`) ON DELETE RESTRICT ON UPDATE RESTRICT *again, table names and key names are obfuscated.
Just to reiterate, the tables all create fine on the initial activation with all constraints in place. In the first example, the single constraint throws the error for that table when activation/update occurs after the first time (deactivate/activate, update, anything that calls the activation hook). In the second example (and others), it's only the last constraint that throws the error, and again only after the table already exists and the activation hook is called later.
Since the constraint already exists, dbDelta should be ignoring it after comparing the table schema, but for some reason it's not.