From f7859ca3acb8e0ad0efe4dc877db67f064ae335b Mon Sep 17 00:00:00 2001 From: Richard Weinhold Date: Fri, 22 Jul 2016 10:35:53 +0200 Subject: [PATCH] implements new MysqliDb::insertMulti() Method - MysqliDb::insertMulti() requires at least a table-name and two-dimensional array containing the data-sets - the third parameter $dataKeys can contain an array, setting|overriding the table column names in the data-sets - removes some unnecessary linebreaks and comments - fixes typo - adds insertMulti() to Readme - adds MysqliDB::insertMulti() insertion tests - removes whitespace changes --- MysqliDb.php | 42 ++++++++++++++++++++++++++++++++++++++ readme.md | 37 +++++++++++++++++++++++++++++++++ tests/mysqliDbTests.php | 45 +++++++++++++++++++++++++++++++++++++++-- 3 files changed, 122 insertions(+), 2 deletions(-) diff --git a/MysqliDb.php b/MysqliDb.php index b6fd491b..6631e3fc 100644 --- a/MysqliDb.php +++ b/MysqliDb.php @@ -679,6 +679,48 @@ public function insert($tableName, $insertData) return $this->_buildInsert($tableName, $insertData, 'INSERT'); } + /** + * Insert method to add several rows at once + * + * @param string $tableName The name of the table. + * @param array $multiInsertData Two-dimensinal Data-array containing information for inserting into the DB. + * @param array $dataKeys Optinal Table Key names, if not set in insertDataSet. + * + * @return bool|array Boolean indicating the insertion failed (false), else return id-array ([int]) + */ + public function insertMulti($tableName, array $multiInsertData, array $dataKeys = null) + { + // only auto-commit our inserts, if no transaction is currently running + $autoCommit = (isset($this->_transaction_in_progress) ? !$this->_transaction_in_progress : true); + $ids = []; + + if($autoCommit) { + $this->startTransaction(); + } + + foreach ($multiInsertData as $insertData) { + if($dataKeys !== null) { + // apply column-names if given, else assume they're already given in the data + $insertData = array_combine($dataKeys, $insertData); + } + + $id = $this->insert($tableName, $insertData); + if(!$id) { + if($autoCommit) { + $this->rollback(); + } + return false; + } + $ids[] = $id; + } + + if($autoCommit) { + $this->commit(); + } + + return $ids; + } + /** * Replace method to add new row * diff --git a/readme.md b/readme.md index 80c16c6c..d34b052e 100644 --- a/readme.md +++ b/readme.md @@ -144,6 +144,43 @@ $db->onDuplicate($updateColumns, $lastInsertId); $id = $db->insert ('users', $data); ``` +Insert multiple datasets at once +```php +$data = Array( + Array ("login" => "admin", + "firstName" => "John", + "lastName" => 'Doe' + ), + Array ("login" => "other", + "firstName" => "Another", + "lastName" => 'User', + "password" => "very_cool_hash" + ) +); +$ids = $db->insertMulti('users', $data); +if(!$ids) { + echo 'insert failed: ' . $db->getLastError(); +} else { + echo 'new users inserted with following id\'s: ' . implode(', ', $ids); +} +``` + +If all datasets only have the same keys, it can be simplified +```php +$data = Array( + Array ("admin", "John", "Doe"), + Array ("other", "Another", "User") +); +$keys = Array("login", "firstName", "lastName"); + +$ids = $db->insertMulti('users', $data, $keys); +if(!$ids) { + echo 'insert failed: ' . $db->getLastError(); +} else { + echo 'new users inserted with following id\'s: ' . implode(', ', $ids); +} +``` + ### Replace Query Replace() method implements same API as insert(); diff --git a/tests/mysqliDbTests.php b/tests/mysqliDbTests.php index 58b3fd22..bd35bc30 100644 --- a/tests/mysqliDbTests.php +++ b/tests/mysqliDbTests.php @@ -396,8 +396,8 @@ function createTable ($name, $data) { } unset ($cnt); -$data = $db->get('users'); -if (count($data) != 3) { +$users = $db->get('users'); +if (count($users) != 3) { echo "copy with subquery data count failed"; exit; } @@ -444,6 +444,47 @@ function createTable ($name, $data) { exit; } +$expectedIDs = [ + 'users' => [5, 6, 7], + 'products' => [6,7,8,9,10], +]; + +// multi-insert test with autoincrement +foreach ($data as $name => $datas) { + + // remove previous entries to ensure avoiding PRIMARY-KEY collisions here + $db->delete($name); + + // actual insertion test + $ids = $db->insertMulti($name, $datas); + + // check results + if(!$ids) { + echo "failed to multi-insert: ".$db->getLastQuery() ."\n". $db->getLastError(); + exit; + } elseif($ids !== $expectedIDs[$name]) { + pretty_print($ids); + echo "multi-insert succeeded, but unexpected id's: ".$db->getLastQuery() ."\n". $db->getLastError(); + exit; + } +} + +// skip last user here, since it has other keys than the others +unset($data['users'][2]); + +// multi-insert test with autoincrement and overriding column-names +foreach ($data as $name => $datas) { + + // remove previous entries to ensure avoiding PRIMARY-KEY collisions here + $db->delete($name); + + // actual insertion test + if(!$db->insertMulti($name, $datas, array_keys($datas[0]))) { + echo "failed to multi-insert: ".$db->getLastQuery() ."\n". $db->getLastError(); + exit; + } +} + /// //TODO: insert test $db->delete("users");