summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAleksander Machniak <alec@alec.pl>2012-12-07 12:38:08 +0100
committerAleksander Machniak <alec@alec.pl>2012-12-07 12:38:08 +0100
commita3985963f0df4fffa1a6d272c777f781ebd86d50 (patch)
treeaddfff86d643012329ae38260afd0c37e3dd7cfb
parent996af3bfd9bfcac84396790a9a215d177b17c79e (diff)
Fix big memory consumption of DB layer (#1488856)
-rw-r--r--CHANGELOG1
-rw-r--r--program/lib/Roundcube/rcube_db.php100
2 files changed, 32 insertions, 69 deletions
diff --git a/CHANGELOG b/CHANGELOG
index 5a1b1acd5..79f19b904 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -1,6 +1,7 @@
CHANGELOG Roundcube Webmail
===========================
+- Fix big memory consumption of DB layer (#1488856)
- 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 broken message/part bodies when FETCH response contains more untagged lines (#1488836)
diff --git a/program/lib/Roundcube/rcube_db.php b/program/lib/Roundcube/rcube_db.php
index 5d8c4a534..2c471e74d 100644
--- a/program/lib/Roundcube/rcube_db.php
+++ b/program/lib/Roundcube/rcube_db.php
@@ -37,12 +37,11 @@ class rcube_db
protected $db_mode; // Connection mode
protected $dbh; // Connection handle
- protected $db_error = false;
- protected $db_error_msg = '';
- protected $conn_failure = false;
- protected $a_query_results = array('dummy');
- protected $last_res_id = 0;
- protected $db_index = 0;
+ protected $db_error = false;
+ protected $db_error_msg = '';
+ protected $conn_failure = false;
+ protected $db_index = 0;
+ protected $last_result;
protected $tables;
protected $variables;
@@ -267,14 +266,14 @@ class rcube_db
/**
* Getter for error state
*
- * @param int $res_id Optional query result identifier
+ * @param mixed $result Optional query result
*
* @return string Error message
*/
- public function is_error($res_id = null)
+ public function is_error($result = null)
{
- if ($res_id !== null) {
- return $this->_get_result($res_id) === false ? $this->db_error_msg : null;
+ if ($result !== null) {
+ return $result === false ? $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 mixed Values to be inserted in query
*
- * @return int Query handle identifier
+ * @return PDOStatement|bool Query handle or False on error
*/
public function limitquery()
{
@@ -363,7 +362,7 @@ class rcube_db
* @param int $numrows Number of rows for LIMIT statement
* @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)
{
@@ -374,7 +373,7 @@ class rcube_db
// check connection before proceeding
if (!$this->is_connected()) {
- return null;
+ return $this->last_result = false;
}
if ($numrows || $offset) {
@@ -417,20 +416,21 @@ class rcube_db
'message' => $this->db_error_msg), true, false);
}
- // add result, even if it's an error
- return $this->_add_result($query);
+ $this->last_result = $query;
+
+ return $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
*/
- 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();
}
@@ -464,13 +464,12 @@ class rcube_db
* Get an associative array for one row
* 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
*/
- 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);
}
@@ -478,31 +477,30 @@ class rcube_db
* Get an index array for one row
* 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
*/
- 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);
}
/**
* Get col values for a result row
*
- * @param PDOStatement $result Result handle
- * @param int $mode Fetch mode identifier
+ * @param mixed $result Optional query handle
+ * @param int $mode Fetch mode identifier
*
* @return mixed Array with col values or false on failure
*/
protected function _fetch_row($result, $mode)
{
- if (!is_object($result) || !$this->is_connected()) {
- return false;
+ if ($result || ($result === null && ($result = $this->last_result))) {
+ return $result->fetch($mode);
}
- return $result->fetch($mode);
+ return false;
}
/**
@@ -538,8 +536,8 @@ class rcube_db
if ($this->tables === null) {
$q = $this->query('SELECT TABLE_NAME FROM INFORMATION_SCHEMA.TABLES ORDER BY TABLE_NAME');
- if ($res = $this->_get_result($q)) {
- $this->tables = $res->fetchAll(PDO::FETCH_COLUMN, 0);
+ if ($q) {
+ $this->tables = $q->fetchAll(PDO::FETCH_COLUMN, 0);
}
else {
$this->tables = array();
@@ -561,8 +559,8 @@ class rcube_db
$q = $this->query('SELECT COLUMN_NAME FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = ?',
array($table));
- if ($res = $this->_get_result($q)) {
- return $res->fetchAll(PDO::FETCH_COLUMN, 0);
+ if ($q) {
+ return $q->fetchAll(PDO::FETCH_COLUMN, 0);
}
return array();
@@ -777,42 +775,6 @@ class rcube_db
}
/**
- * 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
*
* @param string $table Table name