Fix big memory consumption of DB layer (#1488856)

pull/51/head
Aleksander Machniak 12 years ago
parent 996af3bfd9
commit a3985963f0

@ -1,6 +1,7 @@
CHANGELOG Roundcube Webmail CHANGELOG Roundcube Webmail
=========================== ===========================
- Fix big memory consumption of DB layer (#1488856)
- Add workaround for IE<=8 bug where Content-Disposition:inline was ignored (#1488844) - Add workaround for IE<=8 bug where Content-Disposition:inline was ignored (#1488844)
- Fix XSS vulnerability in vbscript: and data:text links handling (#1488850) - Fix XSS vulnerability in vbscript: and data:text links handling (#1488850)
- Fix broken message/part bodies when FETCH response contains more untagged lines (#1488836) - Fix broken message/part bodies when FETCH response contains more untagged lines (#1488836)

@ -37,12 +37,11 @@ class rcube_db
protected $db_mode; // Connection mode protected $db_mode; // Connection mode
protected $dbh; // Connection handle protected $dbh; // Connection handle
protected $db_error = false; protected $db_error = false;
protected $db_error_msg = ''; protected $db_error_msg = '';
protected $conn_failure = false; protected $conn_failure = false;
protected $a_query_results = array('dummy'); protected $db_index = 0;
protected $last_res_id = 0; protected $last_result;
protected $db_index = 0;
protected $tables; protected $tables;
protected $variables; protected $variables;
@ -267,14 +266,14 @@ class rcube_db
/** /**
* Getter for error state * Getter for error state
* *
* @param int $res_id Optional query result identifier * @param mixed $result Optional query result
* *
* @return string Error message * @return string Error message
*/ */
public function is_error($res_id = null) public function is_error($result = null)
{ {
if ($res_id !== null) { if ($result !== null) {
return $this->_get_result($res_id) === false ? $this->db_error_msg : null; return $result === false ? $this->db_error_msg : null;
} }
return $this->db_error ? $this->db_error_msg : null; return $this->db_error ? $this->db_error_msg : null;
@ -343,7 +342,7 @@ class rcube_db
* @param int Number of rows for LIMIT statement * @param int Number of rows for LIMIT statement
* @param mixed Values to be inserted in query * @param mixed Values to be inserted in query
* *
* @return int Query handle identifier * @return PDOStatement|bool Query handle or False on error
*/ */
public function limitquery() public function limitquery()
{ {
@ -363,7 +362,7 @@ class rcube_db
* @param int $numrows Number of rows for LIMIT statement * @param int $numrows Number of rows for LIMIT statement
* @param array $params Values to be inserted in query * @param array $params Values to be inserted in query
* *
* @return int Query handle identifier * @return PDOStatement|bool Query handle or False on error
*/ */
protected function _query($query, $offset, $numrows, $params) protected function _query($query, $offset, $numrows, $params)
{ {
@ -374,7 +373,7 @@ class rcube_db
// check connection before proceeding // check connection before proceeding
if (!$this->is_connected()) { if (!$this->is_connected()) {
return null; return $this->last_result = false;
} }
if ($numrows || $offset) { if ($numrows || $offset) {
@ -417,20 +416,21 @@ class rcube_db
'message' => $this->db_error_msg), true, false); 'message' => $this->db_error_msg), true, false);
} }
// add result, even if it's an error $this->last_result = $query;
return $this->_add_result($query);
return $query;
} }
/** /**
* Get number of affected rows for the last query * Get number of affected rows for the last query
* *
* @param number $res_id Optional query handle identifier * @param mixed $result Optional query handle
* *
* @return int Number of rows or false on failure * @return int Number of rows or false on failure
*/ */
public function affected_rows($res_id = null) public function affected_rows($result = null)
{ {
if ($result = $this->_get_result($res_id)) { if ($result || ($result === null && ($result = $this->last_result))) {
return $result->rowCount(); return $result->rowCount();
} }
@ -464,13 +464,12 @@ class rcube_db
* Get an associative array for one row * Get an associative array for one row
* If no query handle is specified, the last query will be taken as reference * If no query handle is specified, the last query will be taken as reference
* *
* @param int $res_id Optional query handle identifier * @param mixed $result Optional query handle
* *
* @return mixed Array with col values or false on failure * @return mixed Array with col values or false on failure
*/ */
public function fetch_assoc($res_id = null) public function fetch_assoc($result = null)
{ {
$result = $this->_get_result($res_id);
return $this->_fetch_row($result, PDO::FETCH_ASSOC); return $this->_fetch_row($result, PDO::FETCH_ASSOC);
} }
@ -478,31 +477,30 @@ class rcube_db
* Get an index array for one row * Get an index array for one row
* If no query handle is specified, the last query will be taken as reference * If no query handle is specified, the last query will be taken as reference
* *
* @param int $res_id Optional query handle identifier * @param mixed $result Optional query handle
* *
* @return mixed Array with col values or false on failure * @return mixed Array with col values or false on failure
*/ */
public function fetch_array($res_id = null) public function fetch_array($result = null)
{ {
$result = $this->_get_result($res_id);
return $this->_fetch_row($result, PDO::FETCH_NUM); return $this->_fetch_row($result, PDO::FETCH_NUM);
} }
/** /**
* Get col values for a result row * Get col values for a result row
* *
* @param PDOStatement $result Result handle * @param mixed $result Optional query handle
* @param int $mode Fetch mode identifier * @param int $mode Fetch mode identifier
* *
* @return mixed Array with col values or false on failure * @return mixed Array with col values or false on failure
*/ */
protected function _fetch_row($result, $mode) protected function _fetch_row($result, $mode)
{ {
if (!is_object($result) || !$this->is_connected()) { if ($result || ($result === null && ($result = $this->last_result))) {
return false; return $result->fetch($mode);
} }
return $result->fetch($mode); return false;
} }
/** /**
@ -538,8 +536,8 @@ class rcube_db
if ($this->tables === null) { if ($this->tables === null) {
$q = $this->query('SELECT TABLE_NAME FROM INFORMATION_SCHEMA.TABLES ORDER BY TABLE_NAME'); $q = $this->query('SELECT TABLE_NAME FROM INFORMATION_SCHEMA.TABLES ORDER BY TABLE_NAME');
if ($res = $this->_get_result($q)) { if ($q) {
$this->tables = $res->fetchAll(PDO::FETCH_COLUMN, 0); $this->tables = $q->fetchAll(PDO::FETCH_COLUMN, 0);
} }
else { else {
$this->tables = array(); $this->tables = array();
@ -561,8 +559,8 @@ class rcube_db
$q = $this->query('SELECT COLUMN_NAME FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = ?', $q = $this->query('SELECT COLUMN_NAME FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = ?',
array($table)); array($table));
if ($res = $this->_get_result($q)) { if ($q) {
return $res->fetchAll(PDO::FETCH_COLUMN, 0); return $q->fetchAll(PDO::FETCH_COLUMN, 0);
} }
return array(); return array();
@ -776,42 +774,6 @@ class rcube_db
return utf8_decode($input); return utf8_decode($input);
} }
/**
* Adds a query result and returns a handle ID
*
* @param object $res Query handle
*
* @return int Handle ID
*/
protected function _add_result($res)
{
$this->last_res_id = sizeof($this->a_query_results);
$this->a_query_results[$this->last_res_id] = $res;
return $this->last_res_id;
}
/**
* Resolves a given handle ID and returns the according query handle
* If no ID is specified, the last resource handle will be returned
*
* @param int $res_id Handle ID
*
* @return mixed Resource handle or false on failure
*/
protected function _get_result($res_id = null)
{
if ($res_id == null) {
$res_id = $this->last_res_id;
}
if (!empty($this->a_query_results[$res_id])) {
return $this->a_query_results[$res_id];
}
return false;
}
/** /**
* Return correct name for a specific database table * Return correct name for a specific database table
* *

Loading…
Cancel
Save