diff --git a/MysqliDb.php b/MysqliDb.php index 42dc34a8..ff4832d3 100644 --- a/MysqliDb.php +++ b/MysqliDb.php @@ -112,6 +112,18 @@ class MysqliDb */ protected $isSubQuery = false; + /** + * Name of the auto increment column + * + */ + protected $_lastInsertId = null; + + /** + * Column names for update when using onDuplicate method + * + */ + protected $_updateColumns = null; + /** * Return type: 'Array' to return results as array, 'Object' as object * 'Json' as json string @@ -235,6 +247,8 @@ protected function reset() $this->returnType = 'Array'; $this->_nestJoin = false; $this->_tableName = ''; + $this->_lastInsertId = null; + $this->_updateColumns = null; } /** @@ -550,6 +564,19 @@ public function where($whereProp, $whereValue = 'DBNULL', $operator = '=', $cond return $this; } + /** + * This function store update column's name and column name of the + * autoincrement column + * + * @param Array Variable with values + * @param String Variable value + */ + public function onDuplicate($_updateColumns, $_lastInsertId = null) + { + $this->_lastInsertId = $_lastInsertId; + $this->_updateColumns = $_updateColumns; + } + /** * This method allows you to specify multiple (method chaining optional) OR WHERE statements for SQL queries. * @@ -779,6 +806,57 @@ private function _buildInsert ($tableName, $insertData, $operation) return true; } + /** + * Helper function to add variables into the query statement + * + * @param Array Variable with values + */ + protected function _buildDuplicate($tableData) + { + if (is_array($this->_updateColumns) && !empty($this->_updateColumns)) { + $this->_query .= " on duplicate key update "; + if ($this->_lastInsertId) { + $this->_lastQuery .= $this->_lastInsertId."=LAST_INSERT_ID(".$this->_lastInsertId."),"; + $this->_lastInsertId = null; + } + + foreach ($this->_updateColumns as $column) { + $this->_query .= "`" . $column . "` = "; + + // Simple value + if (!is_array ($tableData[$column])) { + $this->_bindParam($tableData[$column]); + $this->_query .= '?, '; + continue; + } + + // Function value + $arr = $tableData[$column]; + $key = key($arr); + $val = $arr[$key]; + switch ($key) { + case '[I]': + $this->_query .= $column . $val . ", "; + break; + case '[F]': + $this->_query .= $val[0] . ", "; + if (!empty ($val[1])) + $this->_bindParams ($val[1]); + break; + case '[N]': + if ($val == null) + $this->_query .= "!" . $column . ", "; + else + $this->_query .= "!" . $val . ", "; + break; + default: + die ("Wrong operation"); + } + } + $this->_query = rtrim($this->_query, ', '); + } + } + /** * Abstraction method that will compile the WHERE statement, * any passed update data, and the desired rows. @@ -798,6 +876,7 @@ protected function _buildQuery($numRows = null, $tableData = null) $this->_buildGroupBy(); $this->_buildOrderBy(); $this->_buildLimit ($numRows); + $this->_buildDuplicate($tableData); $this->_lastQuery = $this->replacePlaceHolders ($this->_query, $this->_bindParams); diff --git a/readme.md b/readme.md index dfd9a9de..299f2f3c 100644 --- a/readme.md +++ b/readme.md @@ -123,6 +123,20 @@ else echo 'insert failed: ' . $db->getLastError(); ``` +Insert with on duplicate key update +```php +$data = Array ("login" => "admin", + "firstName" => "John", + "lastName" => 'Doe', + "createdAt" => $db->now(), + "updatedAt" => $db->now(), +); +$updateColumns = Array ("updateAt"); +$lastInsertId = "id"; +$db->onDuplicate($updateColumns, $lastInsertId); +$id = $db->insert ('users', $data); +``` + ### Replace Query Replace() method implements same API as insert(); diff --git a/tests/mysqliDbTests.php b/tests/mysqliDbTests.php index 0cdcd34e..6a83b668 100644 --- a/tests/mysqliDbTests.php +++ b/tests/mysqliDbTests.php @@ -29,8 +29,10 @@ 'lastName' => 'char(10)', 'password' => 'text not null', 'createdAt' => 'datetime', + 'updatedAt' => 'datetime', 'expires' => 'datetime', - 'loginCount' => 'int(10) default 0' + 'loginCount' => 'int(10) default 0', + 'unique key' => 'login (login)' ), 'products' => Array ( 'customerId' => 'int(10) not null', @@ -46,6 +48,7 @@ 'lastName' => 'Doe', 'password' => $db->func('SHA1(?)',Array ("secretpassword+salt")), 'createdAt' => $db->now(), + 'updatedAt' => $db->now(), 'expires' => $db->now('+1Y'), 'loginCount' => $db->inc() ), @@ -55,6 +58,7 @@ 'lastName' => NULL, 'password' => $db->func('SHA1(?)',Array ("secretpassword2+salt")), 'createdAt' => $db->now(), + 'updatedAt' => $db->now(), 'expires' => $db->now('+1Y'), 'loginCount' => $db->inc(2) ), @@ -65,6 +69,7 @@ 'lastName' => 'D', 'password' => $db->func('SHA1(?)',Array ("secretpassword2+salt")), 'createdAt' => $db->now(), + 'updatedAt' => $db->now(), 'expires' => $db->now('+1Y'), 'loginCount' => $db->inc(3) ) @@ -136,6 +141,7 @@ function createTable ($name, $data) { 'lastName' => 'Doe', 'password' => 'test', 'createdAt' => $db->now(), + 'updatedAt' => $db->now(), 'expires' => $db->now('+1Y'), 'loginCount' => $db->inc() ); @@ -170,6 +176,23 @@ function createTable ($name, $data) { exit; } +// insert with on duplicate key update +$user = Array ('login' => 'user3', + 'active' => true, + 'customerId' => 11, + 'firstName' => 'Pete', + 'lastName' => 'D', + 'password' => $db->func('SHA1(?)',Array ("secretpassword2+salt")), + 'createdAt' => $db->now(), + 'updatedAt' => $db->now(), + 'expires' => $db->now('+1Y'), + 'loginCount' => $db->inc(3) + ); +$updateColumns = Array ("updatedAt"); +$insertLastId = "id"; +$db->onDuplicate($updateColumns, "id"); +$db->insert("users", $user); + // order by field $db->orderBy("login","asc", Array ("user3","user2","user1")); $login = $db->getValue ("users", "login");