private function AppendOnDuplicateKeyUpdate(QueryBuilder $QueryBuilder, $TableName, array $Columns, array $PrimaryKeyIdentifiers)
{
$QueryBuilder->Append(' ON DUPLICATE KEY UPDATE ');
$FirstPrimaryKey = true;
foreach ($QueryBuilder->Delimit($Columns, ',') as $ColumName => $Column) {
$ColumnIdentifier = [$TableName, $ColumName];
if ($FirstPrimaryKey && $Column->IsPrimaryKey()) {
/*
* Ugly fix/hack to prevent mysql from updating primary key when encountering
* a duplicate value on a seperate unique constraint. Sadly Mysql does not support
* the more robust 'MERGE' operation. Furthermore there is no clean way to throw a
* conditional runtime error in Mysql reliably.
*
* Example: Persisting a account entity with a unique username, if the user changes
* their username and and a duplicate username exists, mysql could attempt to update
* the other duplicate row with the new values/primary key. This should not be an
* issue as then it will fail with a duplicate primary key but could lead to some
* wacky edge cases that I want no part in.
*/
$QueryBuilder->AppendIdentifier('# = IF(', $ColumnIdentifier);
foreach ($QueryBuilder->Delimit($PrimaryKeyIdentifiers, ' AND ') as $PrimaryKeyIdentifier) {
$QueryBuilder->AppendIdentifier('# = VALUES(#)', $PrimaryKeyIdentifier);
}
$QueryBuilder->Append(',');
$QueryBuilder->AppendIdentifier('VALUES(#)', $ColumnIdentifier);
$QueryBuilder->Append(',');
$QueryBuilder->Append('(SELECT 1 UNION ALL SELECT 1))');
$FirstPrimaryKey = false;
} else {
$QueryBuilder->AppendIdentifier('# = VALUES(#)', $ColumnIdentifier);
}
}
}