Commit 1885d150 authored by Carsten  Rose's avatar Carsten Rose
Browse files

#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.
parent 45fc3b76
......@@ -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
......
......@@ -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';
......@@ -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);
}
/**
......
......@@ -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)
......
......@@ -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
*/
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment