From c5efa9a13ecf67a0d9000a99c5b6788b3a35b55b Mon Sep 17 00:00:00 2001 From: swaibar Date: Mon, 14 Jun 2021 09:40:03 +0100 Subject: [PATCH] Add "replace" option with ON DUPLICATE KEY UPDATE Using the primary key(s) allow replace duplicate records --- src/Ifsnop/Mysqldump/Mysqldump.php | 53 +++++++++++++++++++++++++++--- 1 file changed, 48 insertions(+), 5 deletions(-) diff --git a/src/Ifsnop/Mysqldump/Mysqldump.php b/src/Ifsnop/Mysqldump/Mysqldump.php index 8d1e4e37..f09e2d74 100644 --- a/src/Ifsnop/Mysqldump/Mysqldump.php +++ b/src/Ifsnop/Mysqldump/Mysqldump.php @@ -158,6 +158,7 @@ public function __construct( 'no-autocommit' => true, 'no-create-info' => false, 'lock-tables' => true, + 'replace' => false, 'routines' => false, 'single-transaction' => true, 'skip-triggers' => false, @@ -804,7 +805,8 @@ private function getTableColumnTypes($tableName) 'is_blob' => $types['is_blob'], 'type' => $types['type'], 'type_sql' => $col['Type'], - 'is_virtual' => $types['is_virtual'] + 'is_virtual' => $types['is_virtual'], + 'key_sql' => $col['Key'], ); } @@ -1117,13 +1119,17 @@ private function listValues($tableName) $resultSet = $this->dbHandler->query($stmt); $resultSet->setFetchMode(PDO::FETCH_ASSOC); - $ignore = $this->dumpSettings['insert-ignore'] ? ' IGNORE' : ''; + $replace = $this->dumpSettings['replace'] && $this->getHasPrimaryKey($tableName); + $strUpdates = $replace ? $this->getUpdateColumnsOnDuplicate($tableName) : ''; + $extendedInsert = $this->dumpSettings['extended-insert'] && !$replace; + $ignore = $this->dumpSettings['insert-ignore'] && !$replace ? ' IGNORE' : ''; + $count = 0; foreach ($resultSet as $row) { $count++; $vals = $this->prepareColumnValues($tableName, $row); - if ($onlyOnce || !$this->dumpSettings['extended-insert']) { + if ($onlyOnce || !$extendedInsert) { if ($this->dumpSettings['complete-insert']) { $lineSize += $this->compressManager->write( "INSERT$ignore INTO `$tableName` (". @@ -1135,12 +1141,14 @@ private function listValues($tableName) "INSERT$ignore INTO `$tableName` VALUES (".implode(",", $vals).")" ); } + if ($replace) { + $lineSize += $this->compressManager->write(" ON DUPLICATE KEY UPDATE {$strUpdates}"); + } $onlyOnce = false; } else { $lineSize += $this->compressManager->write(",(".implode(",", $vals).")"); } - if (($lineSize > $this->dumpSettings['net_buffer_length']) || - !$this->dumpSettings['extended-insert']) { + if (($lineSize > $this->dumpSettings['net_buffer_length']) || !$extendedInsert) { $onlyOnce = true; $lineSize = $this->compressManager->write(";".PHP_EOL); } @@ -1158,6 +1166,41 @@ private function listValues($tableName) } } + /** + * Does the table have a primary key + * + * @param string $tableName Name of table + * + * @return bool + */ + public function getHasPrimaryKey($tableName) + { + foreach ($this->tableColumnTypes[$tableName] as $colName => $colType) { + if ($colType['key_sql'] == 'PRI') { + return true; + } + } + return false; + } + + /** + * Build SQL List of all non-primary key columns on current table which will be used for update on duplicate key + * + * @param string $tableName Name of table to get columns + * + * @return string update columns for sql sentence where update on duplicate key + */ + public function getUpdateColumnsOnDuplicate($tableName) + { + $colUpdates = array(); + foreach ($this->tableColumnTypes[$tableName] as $colName => $colType) { + if ($colType['key_sql'] != 'PRI') { + $colUpdates[] = "`${colName}`=`${colName}`"; + } + } + return implode(',',$colUpdates); + } + /** * Table rows extractor, append information prior to dump *