From 1885d1505095c5b86e7249e01dd056d9e222c29b Mon Sep 17 00:00:00 2001 From: Carsten Rose <carsten.rose@math.uzh.ch> Date: Thu, 28 Apr 2016 22:29:07 +0200 Subject: [PATCH] #1925: Report: <level>.line.total sollte bei INSERT affected_rows enthalten Report.php, Database.php: triggerReport() supports stat[] with num_rows, affected_rows and insert_id. rowTotal does not contain anymore inserId (last_insert_id) from fired INSERT queries. Instead num_rows or affected_rows are choosen. New: <level>.line.inserId contains the insertId. --- extension/Documentation/UsersManual/Index.rst | 12 ++++---- extension/qfq/qfq/Constants.php | 8 ++++- extension/qfq/qfq/Database.php | 29 ++++++++++++------- extension/qfq/qfq/report/Report.php | 11 ++++--- extension/qfq/tests/phpunit/DatabaseTest.php | 23 ++++++++++----- 5 files changed, 55 insertions(+), 28 deletions(-) diff --git a/extension/Documentation/UsersManual/Index.rst b/extension/Documentation/UsersManual/Index.rst index 73c922fe9..0dbf8b674 100644 --- a/extension/Documentation/UsersManual/Index.rst +++ b/extension/Documentation/UsersManual/Index.rst @@ -989,16 +989,16 @@ Syntax Variables from specific stores: {{<name>[:<store/s>[:<sanitize class>]]}} - Row index and total rows: {{<level>.line.count}} or {{<level>.line.total}} + Current row index: {{<level>.line.count}} - 'last_insert_id' and 'affected_rows': {{<level>.line.total}} (*total* may have a different meaning, depending on the type of the SQL command) + Total rows (num_rows for SELECT and SHOW, affected_rows for UPDATE and INSERT): {{<level>.line.total}} - See :ref:`variables` for a full list of all available variables. + Last insert id for INSERT: {{<level>.line.insertId}} - Be aware of the following restrictions to {{<level>.line.count}} or {{<level>.line.total}}: + See :ref:`variables` for a full list of all available variables. - line.count / line.total have to be known when the query is fired. E.g. `10.sql = SELECT {{10.line.count}}, ... WHERE {{10.line.count}} = ...` - won't work as expected. `{{10.line.count}}` can't be replaced before the query is fired, but will be replaced during processing the result! + Be aware that line.count / line.total have to be known before the query is fired. E.g. `10.sql = SELECT {{10.line.count}}, ... WHERE {{10.line.count}} = ...` + won't work as expected. `{{10.line.count}}` can't be replaced before the query is fired, but will be replaced during processing the result! Different types of SQL queries are possible: SELECT, INSERT, UPDATE, DELETE, SHOW diff --git a/extension/qfq/qfq/Constants.php b/extension/qfq/qfq/Constants.php index 443a62aec..3e356854b 100644 --- a/extension/qfq/qfq/Constants.php +++ b/extension/qfq/qfq/Constants.php @@ -405,4 +405,10 @@ const FILES_FLAG_DELETE = 'flagDelete'; const UPLOAD_CACHED = '.cached'; const FILE_ACTION = 'action'; const FILE_ACTION_UPLOAD = 'upload'; -const FILE_ACTION_DELETE = 'delete'; \ No newline at end of file +const FILE_ACTION_DELETE = 'delete'; + +// DATABASE +const DB_NUM_ROWS = 'numRows'; +const DB_AFFECTED_ROWS = 'affectedRows'; +const DB_INSERT_ID = 'insertId'; + diff --git a/extension/qfq/qfq/Database.php b/extension/qfq/qfq/Database.php index 326245503..9d2fb57f3 100644 --- a/extension/qfq/qfq/Database.php +++ b/extension/qfq/qfq/Database.php @@ -208,7 +208,7 @@ class Database { * @throws \qfq\CodeException * @throws \qfq\DbException */ - public function sql($sql, $mode = ROW_REGULAR, array $parameterArray = array(), $specificMessage = '', array &$keys = array()) { + public function sql($sql, $mode = ROW_REGULAR, array $parameterArray = array(), $specificMessage = '', array &$keys = array(), array &$stat = array()) { $queryType = ''; $result = array(); $this->closeMysqliStmt(); @@ -221,7 +221,8 @@ class Database { if ($specificMessage) $specificMessage .= " "; - $count = $this->prepareExecute($sql, $parameterArray, $queryType); + $count = $this->prepareExecute($sql, $parameterArray, $queryType, $stat); + if ($count === false) { throw new DbException($specificMessage . "No idea why this error happens - please take some time and check this: $sql", ERROR_DB_GENERIC_CHECK); } @@ -297,18 +298,20 @@ class Database { /** * Execute a prepared SQL statement like SELECT, INSERT, UPDATE, DELETE, SHOW, ... * - * Returns the number of selected rows (SELECT, SHOW, ..) or the affected rows (UPDATE) or the last insert id (INSERT) + * Returns the number of selected rows (SELECT, SHOW, ..) or the affected rows (UPDATE, INSERT). $stat contains appropriate num_rows, insert_id or rows_affected. * * @param string $sql SQL statement with prepared statement variable. * @param array $parameterArray parameter array for prepared statement execution. * @param string $queryType returns QUERY_TYPE_SELECT | QUERY_TYPE_UPDATE | QUERY_TYPE_INSERT, depending on the query. + * @param array $stat * @return int|mixed * @throws \qfq\CodeException * @throws \qfq\DbException * @throws \qfq\UserFormException */ - private function prepareExecute($sql, array $parameterArray = array(), &$queryType = '') { + private function prepareExecute($sql, array $parameterArray = array(), &$queryType, array &$stat) { $result = 0; + $stat = array(); $this->store->setVar(SYSTEM_SQL_FINAL, $sql, STORE_SYSTEM); $this->store->setVar(SYSTEM_SQL_PARAM_ARRAY, $parameterArray, STORE_SYSTEM); @@ -343,19 +346,23 @@ class Database { } $queryType = QUERY_TYPE_SELECT; $this->mysqli_result = $result; - $count = $this->mysqli_result->num_rows; - $msg = 'Read rows: ' . $count; + $stat[DB_NUM_ROWS] = $this->mysqli_result->num_rows; + $count = $stat[DB_NUM_ROWS]; + $msg = 'Read rows: ' . $stat[DB_NUM_ROWS]; break; case 'INSERT': $queryType = QUERY_TYPE_INSERT; - $count = $this->mysqli->insert_id; + $stat[DB_INSERT_ID] = $this->mysqli->insert_id; + $stat[DB_AFFECTED_ROWS] = $this->mysqli->affected_rows; + $count = $stat[DB_AFFECTED_ROWS]; $msg = 'ID: ' . $count; break; case 'UPDATE': case 'REPLACE': case 'DELETE': $queryType = QUERY_TYPE_UPDATE; - $count = $this->mysqli->affected_rows; + $stat[DB_AFFECTED_ROWS] = $this->mysqli->affected_rows; + $count = $stat[DB_AFFECTED_ROWS]; $msg = 'Affected rows: ' . $count; break; default: @@ -508,12 +515,14 @@ class Database { * * @param $sql * @param array $keys + * @param array $stat * @return array|bool + * @throws \qfq\CodeException * @throws \qfq\DbException */ - public function sqlKeys($sql, array &$keys) { + public function sqlKeys($sql, array &$keys, array &$stat = array()) { - return $this->sql($sql, ROW_KEYS, array(), '', $keys); + return $this->sql($sql, ROW_KEYS, array(), '', $keys, $stat); } /** diff --git a/extension/qfq/qfq/report/Report.php b/extension/qfq/qfq/report/Report.php index c98235783..4f73ad1d2 100644 --- a/extension/qfq/qfq/report/Report.php +++ b/extension/qfq/qfq/report/Report.php @@ -316,6 +316,7 @@ class Report { private function triggerReport($cur_level = 1, array $super_level_array = array(), $counter = 0) { $keys = array(); + $stat = array(); $lineDebug = 0; $content = ""; @@ -370,15 +371,17 @@ class Report { //Execute SQL. All errors have been already catched. unset($result); - $result = $this->db->sqlKeys($sql, $keys); + $result = $this->db->sqlKeys($sql, $keys, $stat); // If an array is returned, $sql was a query, otherwise an 'insert', 'update', 'delete', ... // Query: total nummber of rows - // insert: last_insert_id - // delete, update: number of affected rows - $rowTotal = is_array($result) ? count($result) : $result; + // insert, delete, update: number of affected rows + $rowTotal = isset($stat[DB_NUM_ROWS]) ? $stat[DB_NUM_ROWS] : $stat[DB_AFFECTED_ROWS]; $this->variables->resultArray[$full_level . ".line."]["total"] = $rowTotal; + if (isset($stat[DB_INSERT_ID])) { + $this->variables->resultArray[$full_level . ".line."]["insertId"] = $stat[DB_INSERT_ID]; + } // HEAD: If there is at least one record, do 'head'. if ($rowTotal > 0) diff --git a/extension/qfq/tests/phpunit/DatabaseTest.php b/extension/qfq/tests/phpunit/DatabaseTest.php index f0594a275..ef5b36bcf 100644 --- a/extension/qfq/tests/phpunit/DatabaseTest.php +++ b/extension/qfq/tests/phpunit/DatabaseTest.php @@ -137,6 +137,9 @@ class DatabaseTest extends AbstractDatabaseTest { * @throws \qfq\DbException */ public function testQuerySimpleParameter() { + $stat = array(); + $dummy = array(); + // Parameter Susbstitution by '?' $dataArray = $this->db->sql('SELECT * FROM Person WHERE name LIKE ? ORDER BY id', ROW_REGULAR, ['Smith']); // Check count @@ -145,11 +148,13 @@ class DatabaseTest extends AbstractDatabaseTest { $dataArray = $this->db->sql('UPDATE Person SET groups = ?', ROW_REGULAR, ['a,b,c']); $this->assertEquals(2, $this->store->getVar(SYSTEM_SQL_COUNT, STORE_SYSTEM)); - $dataArray = $this->db->sql('INSERT INTO Person (`name`, `firstname`, `groups`) VALUES ( ?, ? ,? )', ROW_REGULAR, ['Meier', 'John', 'a']); - $this->assertEquals(3, $this->store->getVar(SYSTEM_SQL_COUNT, STORE_SYSTEM)); + $dataArray = $this->db->sql('INSERT INTO Person (`name`, `firstname`, `groups`) VALUES ( ?, ? ,? )', ROW_REGULAR, ['Meier', 'John', 'a'], 'fake', $dummy, $stat); + $this->assertEquals(1, $this->store->getVar(SYSTEM_SQL_COUNT, STORE_SYSTEM)); + $this->assertEquals(3, $stat[DB_INSERT_ID]); - $dataArray = $this->db->sql('INSERT INTO Person (`name`, `firstname`, `groups`) VALUES ( ?, ? ,? )', ROW_REGULAR, ['Meier', 'Jan', 'b']); - $this->assertEquals(4, $this->store->getVar(SYSTEM_SQL_COUNT, STORE_SYSTEM)); + $dataArray = $this->db->sql('INSERT INTO Person (`name`, `firstname`, `groups`) VALUES ( ?, ? ,? )', ROW_REGULAR, ['Meier', 'Jan', 'b'], 'fake', $dummy, $stat); + $this->assertEquals(1, $this->store->getVar(SYSTEM_SQL_COUNT, STORE_SYSTEM)); + $this->assertEquals(4, $stat[DB_INSERT_ID]); $dataArray = $this->db->sql('DELETE FROM Person WHERE name = ?', ROW_REGULAR, ['Meier']); $this->assertEquals(2, $this->store->getVar(SYSTEM_SQL_COUNT, STORE_SYSTEM)); @@ -224,11 +229,13 @@ class DatabaseTest extends AbstractDatabaseTest { * @throws \qfq\DbException */ public function testGetLastInsertId() { + $dummy = array(); + $stat = array(); $sql = "INSERT INTO Person (id, name, firstname, gender, groups) VALUES (NULL, 'Doe', 'Jonni', 'male','')"; - $this->db->sql($sql); - $this->assertEquals(3, $this->store->getVar(SYSTEM_SQL_COUNT, STORE_SYSTEM)); + $this->db->sql($sql, ROW_REGULAR, $dummy, 'fake', $dummy, $stat); + $this->assertEquals(3, $stat[DB_INSERT_ID]); } /** @@ -255,7 +262,8 @@ class DatabaseTest extends AbstractDatabaseTest { ['0' => '2', '1' => 'Smith', '2' => '0'], ]; // Same as above, but specify 'ROW_REGULAR' - $dataArray = $this->db->sqlKeys('SELECT id AS "id", name, "0" AS "id" FROM Person ORDER BY id LIMIT 3', $keys); + $stat = array(); + $dataArray = $this->db->sqlKeys('SELECT id AS "id", name, "0" AS "id" FROM Person ORDER BY id LIMIT 3', $keys, $stat); // Check rows $this->assertEquals($expected, $dataArray); @@ -263,6 +271,7 @@ class DatabaseTest extends AbstractDatabaseTest { // Check keys $this->assertEquals(['id', 'name', 'id'], $keys); } + /** * @throws Exception */ -- GitLab