From b79cc545ec020f7dd4bd83dcd06af3cf2b1fcaff Mon Sep 17 00:00:00 2001
From: Aleksander Machniak <alec@alec.pl>
Date: Tue, 28 Aug 2012 05:20:20 -0400
Subject: [PATCH] Improvements/fixes for Larry skin
---
program/include/rcube_db.php | 316 ++++++++++++++++++++++++++++------------------------
1 files changed, 171 insertions(+), 145 deletions(-)
diff --git a/program/include/rcube_db.php b/program/include/rcube_db.php
index 64db6d5..f97d70a 100644
--- a/program/include/rcube_db.php
+++ b/program/include/rcube_db.php
@@ -1,6 +1,6 @@
<?php
-/*
+/**
+-----------------------------------------------------------------------+
| program/include/rcube_db.php |
| |
@@ -25,8 +25,8 @@
*
* This is a wrapper for the PHP PDO
*
- * @package Database
- * @version 1.0
+ * @package Database
+ * @version 1.0
*/
class rcube_db
{
@@ -36,13 +36,14 @@
protected $db_mode; // Connection mode
protected $dbh; // Connection handle
- protected $db_error = false;
- protected $db_error_msg = '';
- protected $conn_failure = false;
+ protected $db_error = false;
+ protected $db_error_msg = '';
+ protected $conn_failure = false;
protected $a_query_results = array('dummy');
- protected $last_res_id = 0;
+ protected $last_res_id = 0;
+ protected $db_index = 0;
protected $tables;
- protected $db_index = 0;
+ protected $variables;
protected $options = array(
// column/table quotes
@@ -54,11 +55,11 @@
/**
* Factory, returns driver-specific instance of the class
*
- * @param string $db_dsnw DSN for read/write operations
- * @param string $db_dsnr Optional DSN for read only operations
- * @param bool $pconn Enables persistent connections
+ * @param string $db_dsnw DSN for read/write operations
+ * @param string $db_dsnr Optional DSN for read only operations
+ * @param bool $pconn Enables persistent connections
*
- * @return rcube_db Object instance
+ * @return rcube_db Object instance
*/
public static function factory($db_dsnw, $db_dsnr = '', $pconn = false)
{
@@ -67,6 +68,7 @@
'sqlite2' => 'sqlite',
'sybase' => 'mssql',
'dblib' => 'mssql',
+ 'mysqli' => 'mysql',
);
$driver = isset($driver_map[$driver]) ? $driver_map[$driver] : $driver;
@@ -82,13 +84,12 @@
return new $class($db_dsnw, $db_dsnr, $pconn);
}
-
/**
* Object constructor
*
- * @param string $db_dsnw DSN for read/write operations
- * @param string $db_dsnr Optional DSN for read only operations
- * @param bool $pconn Enables persistent connections
+ * @param string $db_dsnw DSN for read/write operations
+ * @param string $db_dsnr Optional DSN for read only operations
+ * @param bool $pconn Enables persistent connections
*/
public function __construct($db_dsnw, $db_dsnr = '', $pconn = false)
{
@@ -107,7 +108,9 @@
$this->init();
}
-
+ /**
+ * Initialization of the object with driver specific code
+ */
protected function init()
{
// To be used by driver classes
@@ -116,7 +119,7 @@
/**
* Connect to specific database
*
- * @param array $dsn DSN for DB connections
+ * @param array $dsn DSN for DB connections
*
* @return PDO database handle
*/
@@ -135,6 +138,11 @@
// Connect
try {
+ // with this check we skip fatal error on PDO object creation
+ if (!class_exists('PDO', false)) {
+ throw new Exception('PDO extension not loaded. See http://php.net/manual/en/intro.pdo.php');
+ }
+
$this->conn_prepare($dsn);
$dbh = new PDO($dsn_string, $dsn['username'], $dsn['password'], $dsn_options);
@@ -142,7 +150,7 @@
// don't throw exceptions or warnings
$dbh->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_SILENT);
}
- catch (PDOException $e) {
+ catch (Exception $e) {
$this->db_error = true;
$this->db_error_msg = $e->getMessage();
@@ -158,20 +166,39 @@
return $dbh;
}
-
+ /**
+ * Driver-specific preparation of database connection
+ *
+ * @param array $dsn DSN for DB connections
+ */
protected function conn_prepare($dsn)
{
}
+ /**
+ * Driver-specific configuration of database connection
+ *
+ * @param array $dsn DSN for DB connections
+ * @param PDO $dbh Connection handler
+ */
protected function conn_configure($dsn, $dbh)
{
}
+ /**
+ * Driver-specific database character set setting
+ *
+ * @param string $charset Character set name
+ */
+ protected function set_charset($charset)
+ {
+ $this->query("SET NAMES 'utf8'");
+ }
/**
- * Connect to appropiate database depending on the operation
+ * Connect to appropriate database depending on the operation
*
- * @param string $mode Connection mode (r|w)
+ * @param string $mode Connection mode (r|w)
*/
public function db_connect($mode)
{
@@ -214,7 +241,6 @@
}
}
-
/**
* Activate/deactivate debug mode
*
@@ -225,50 +251,73 @@
$this->options['debug_mode'] = $dbg;
}
-
- protected function set_charset($charset)
+ /**
+ * Writes debug information/query to 'sql' log file
+ *
+ * @param string $query SQL query
+ */
+ protected function debug($query)
{
- $this->query("SET NAMES 'utf8'");
+ if ($this->options['debug_mode']) {
+ rcube::write_log('sql', '[' . (++$this->db_index) . '] ' . $query . ';');
+ }
}
-
/**
* Getter for error state
*
- * @param boolean True on error
+ * @param int $res_id Optional query result identifier
+ *
+ * @return string Error message
*/
- public function is_error()
+ public function is_error($res_id = null)
{
- return $this->db_error ? $this->db_error_msg : false;
- }
+ if ($res_id !== null) {
+ return $this->_get_result($res_id) === false ? $this->db_error_msg : null;
+ }
+ return $this->db_error ? $this->db_error_msg : null;
+ }
/**
* Connection state checker
*
- * @param boolean True if in connected state
+ * @return boolean True if in connected state
*/
public function is_connected()
{
return !is_object($this->dbh) ? false : $this->db_connected;
}
-
/**
* Is database replication configured?
- * This returns true if dsnw != dsnr
+ *
+ * @return bool Returns true if dsnw != dsnr
*/
public function is_replicated()
{
return !empty($this->db_dsnr) && $this->db_dsnw != $this->db_dsnr;
}
+ /**
+ * Get database runtime variables
+ *
+ * @param string $varname Variable name
+ * @param mixed $default Default value if variable is not set
+ *
+ * @return mixed Variable value or default
+ */
+ public function get_variable($varname, $default = null)
+ {
+ // to be implemented by driver class
+ return $default;
+ }
/**
* Execute a SQL query
*
- * @param string SQL query to execute
- * @param mixed Values to be inserted in query
+ * @param string SQL query to execute
+ * @param mixed Values to be inserted in query
*
* @return number Query handle identifier
*/
@@ -285,16 +334,15 @@
return $this->_query($query, 0, 0, $params);
}
-
/**
* Execute a SQL query with limits
*
- * @param string SQL query to execute
- * @param number Offset for LIMIT statement
- * @param number Number of rows for LIMIT statement
- * @param mixed Values to be inserted in query
+ * @param string SQL query to execute
+ * @param int Offset for LIMIT statement
+ * @param int Number of rows for LIMIT statement
+ * @param mixed Values to be inserted in query
*
- * @return number Query handle identifier
+ * @return int Query handle identifier
*/
public function limitquery()
{
@@ -306,20 +354,20 @@
return $this->_query($query, $offset, $numrows, $params);
}
-
/**
* Execute a SQL query with limits
*
- * @param string $query SQL query to execute
- * @param number $offset Offset for LIMIT statement
- * @param number $numrows Number of rows for LIMIT statement
- * @param array $params Values to be inserted in query
- * @return number Query handle identifier
+ * @param string $query SQL query to execute
+ * @param int $offset Offset for LIMIT statement
+ * @param int $numrows Number of rows for LIMIT statement
+ * @param array $params Values to be inserted in query
+ *
+ * @return int Query handle identifier
*/
protected function _query($query, $offset, $numrows, $params)
{
// Read or write ?
- $mode = preg_match('/^select/i', ltrim($query)) ? 'r' : 'w';
+ $mode = preg_match('/^(select|show)/i', ltrim($query)) ? 'r' : 'w';
$this->db_connect($mode);
@@ -348,9 +396,7 @@
$query = rtrim($query, ';');
- if ($this->options['debug_mode']) {
- rcube::write_log('sql', '[' . (++$this->db_index) . '] ' . $query . ';');
- }
+ $this->debug($query);
$query = $this->dbh->query($query);
@@ -368,12 +414,12 @@
return $this->_add_result($query);
}
-
/**
* Get number of affected rows for the last query
*
* @param number $res_id Optional query handle identifier
- * @return mixed Number of rows or false on failure
+ *
+ * @return int Number of rows or false on failure
*/
public function affected_rows($res_id = null)
{
@@ -384,14 +430,12 @@
return 0;
}
-
/**
* Get last inserted record ID
- * For Postgres databases, a sequence name is required
*
- * @param string $table Table name (to find the incremented sequence)
+ * @param string $table Table name (to find the incremented sequence)
*
- * @return mixed ID or false on failure
+ * @return mixed ID or false on failure
*/
public function insert_id($table = '')
{
@@ -409,14 +453,13 @@
return $id;
}
-
/**
* Get an associative array for one row
* If no query handle is specified, the last query will be taken as reference
*
- * @param number $res_id Optional query handle identifier
+ * @param int $res_id Optional query handle identifier
*
- * @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)
{
@@ -424,14 +467,13 @@
return $this->_fetch_row($result, PDO::FETCH_ASSOC);
}
-
/**
* Get an index array for one row
* If no query handle is specified, the last query will be taken as reference
*
- * @param number $res_id Optional query handle identifier
+ * @param int $res_id Optional query handle identifier
*
- * @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)
{
@@ -439,14 +481,13 @@
return $this->_fetch_row($result, PDO::FETCH_NUM);
}
-
/**
* Get col values for a result row
*
- * @param PDOStatement $result Result handle
- * @param number $mode Fetch mode identifier
+ * @param PDOStatement $result Result handle
+ * @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)
{
@@ -457,10 +498,14 @@
return $result->fetch($mode);
}
-
/**
* Adds LIMIT,OFFSET clauses to the query
*
+ * @param string $query SQL query
+ * @param int $limit Number of rows
+ * @param int $offset Offset
+ *
+ * @return string SQL query
*/
protected function set_limit($query, $limit = 0, $offset = 0)
{
@@ -474,7 +519,6 @@
return $query;
}
-
/**
* Returns list of tables in a database
@@ -498,11 +542,10 @@
return $this->tables;
}
-
/**
* Returns list of columns in database table
*
- * @param string Table name
+ * @param string $table Table name
*
* @return array List of table cols
*/
@@ -518,20 +561,23 @@
return array();
}
-
/**
* Formats input so it can be safely used in a query
*
- * @param mixed $input Value to quote
- * @param string $type Type of data
+ * @param mixed $input Value to quote
+ * @param string $type Type of data
*
- * @return string Quoted/converted string for use in query
+ * @return string Quoted/converted string for use in query
*/
public function quote($input, $type = null)
{
// handle int directly for better performance
if ($type == 'integer' || $type == 'int') {
return intval($input);
+ }
+
+ if (is_null($input)) {
+ return 'NULL';
}
// create DB handle if not available
@@ -551,28 +597,26 @@
return 'NULL';
}
-
/**
* Quotes a string so it can be safely used as a table or column name
*
- * @param string $str Value to quote
+ * @param string $str Value to quote
*
- * @return string Quoted string for use in query
- * @deprecated Replaced by rcube_db::quote_identifier
- * @see rcube_db::quote_identifier
+ * @return string Quoted string for use in query
+ * @deprecated Replaced by rcube_db::quote_identifier
+ * @see rcube_db::quote_identifier
*/
public function quoteIdentifier($str)
{
return $this->quote_identifier($str);
}
-
/**
* Quotes a string so it can be safely used as a table or column name
*
- * @param string $str Value to quote
+ * @param string $str Value to quote
*
- * @return string Quoted string for use in query
+ * @return string Quoted string for use in query
*/
public function quote_identifier($str)
{
@@ -588,7 +632,6 @@
return implode($name, '.');
}
-
/**
* Return SQL function for current time and date
*
@@ -599,12 +642,11 @@
return "now()";
}
-
/**
* Return list of elements for use with SQL's IN clause
*
- * @param array $arr Input array
- * @param string $type Type of data
+ * @param array $arr Input array
+ * @param string $type Type of data
*
* @return string Comma-separated list of quoted values for use in query
*/
@@ -621,14 +663,13 @@
return implode(',', $arr);
}
-
/**
* Return SQL statement to convert a field value into a unix timestamp
*
* This method is deprecated and should not be used anymore due to limitations
* of timestamp functions in Mysql (year 2038 problem)
*
- * @param string $field Field name
+ * @param string $field Field name
*
* @return string SQL statement to use in query
* @deprecated
@@ -638,33 +679,30 @@
return "UNIX_TIMESTAMP($field)";
}
-
/**
* Return SQL statement to convert from a unix timestamp
*
- * @param string $timestamp Field name
+ * @param int $timestamp Unix timestamp
*
- * @return string SQL statement to use in query
+ * @return string Date string in db-specific format
*/
public function fromunixtime($timestamp)
{
return date("'Y-m-d H:i:s'", $timestamp);
}
-
/**
* Return SQL statement for case insensitive LIKE
*
- * @param string $column Field name
- * @param string $value Search value
+ * @param string $column Field name
+ * @param string $value Search value
*
- * @return string SQL statement to use in query
+ * @return string SQL statement to use in query
*/
public function ilike($column, $value)
{
return $this->quote_identifier($column).' LIKE '.$this->quote($value);
}
-
/**
* Abstract SQL statement for value concatenation
@@ -681,13 +719,12 @@
return '(' . join(' || ', $args) . ')';
}
-
/**
* Encodes non-UTF-8 characters in string/array/object (recursive)
*
- * @param mixed $input Data to fix
+ * @param mixed $input Data to fix
*
- * @return mixed Properly UTF-8 encoded data
+ * @return mixed Properly UTF-8 encoded data
*/
public static function encode($input)
{
@@ -707,13 +744,12 @@
return utf8_encode($input);
}
-
/**
* Decodes encoded UTF-8 string/object/array (recursive)
*
- * @param mixed $input Input data
+ * @param mixed $input Input data
*
- * @return mixed Decoded data
+ * @return mixed Decoded data
*/
public static function decode($input)
{
@@ -733,31 +769,28 @@
return utf8_decode($input);
}
-
/**
* Adds a query result and returns a handle ID
*
- * @param object $res Query handle
+ * @param object $res Query handle
*
- * @return mixed Handle ID
+ * @return int Handle ID
*/
protected function _add_result($res)
{
- $res_id = sizeof($this->a_query_results);
- $this->last_res_id = $res_id;
- $this->a_query_results[$res_id] = $res;
+ $this->last_res_id = sizeof($this->a_query_results);
+ $this->a_query_results[$this->last_res_id] = $res;
- return $res_id;
+ 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 number $res_id Handle ID
+ * @param int $res_id Handle ID
*
- * @return mixed Resource handle or false on failure
+ * @return mixed Resource handle or false on failure
*/
protected function _get_result($res_id = null)
{
@@ -771,7 +804,6 @@
return false;
}
-
/**
* Return correct name for a specific database table
@@ -794,32 +826,12 @@
return $table;
}
-
/**
- * Return correct name for a specific database sequence
- * (used for Postgres only)
+ * MDB2 DSN string parser
*
* @param string $sequence Secuence name
*
- * @return string Translated sequence name
- */
- public function sequence_name($sequence)
- {
- $rcube = rcube::get_instance();
-
- // return sequence name if configured
- $config_key = 'db_sequence_'.$sequence;
-
- if ($name = $rcube->config->get($config_key)) {
- return $name;
- }
-
- return $sequence;
- }
-
-
- /**
- * MDB2 DSN string parser
+ * @return array DSN parameters
*/
public static function parse_dsn($dsn)
{
@@ -831,7 +843,8 @@
if (($pos = strpos($dsn, '://')) !== false) {
$str = substr($dsn, 0, $pos);
$dsn = substr($dsn, $pos + 3);
- } else {
+ }
+ else {
$str = $dsn;
$dsn = null;
}
@@ -841,7 +854,8 @@
if (preg_match('|^(.+?)\((.*?)\)$|', $str, $arr)) {
$parsed['phptype'] = $arr[1];
$parsed['dbsyntax'] = !$arr[2] ? $arr[1] : $arr[2];
- } else {
+ }
+ else {
$parsed['phptype'] = $str;
$parsed['dbsyntax'] = $str;
}
@@ -858,7 +872,8 @@
if (($pos = strpos($str, ':')) !== false) {
$parsed['username'] = rawurldecode(substr($str, 0, $pos));
$parsed['password'] = rawurldecode(substr($str, $pos + 1));
- } else {
+ }
+ else {
$parsed['username'] = rawurldecode($str);
}
}
@@ -887,9 +902,11 @@
$pos = strrpos($proto_opts, '/');
$dsn = substr($proto_opts, $pos + 1);
$proto_opts = substr($proto_opts, 0, $pos);
- } elseif (strpos($dsn, '/') !== false) {
+ }
+ else if (strpos($dsn, '/') !== false) {
list($proto_opts, $dsn) = explode('/', $dsn, 2);
- } else {
+ }
+ else {
$proto_opts = $dsn;
$dsn = null;
}
@@ -921,7 +938,8 @@
$dsn = substr($dsn, $pos + 1);
if (strpos($dsn, '&') !== false) {
$opts = explode('&', $dsn);
- } else { // database?param1=value1
+ }
+ else { // database?param1=value1
$opts = array($dsn);
}
foreach ($opts as $opt) {
@@ -938,7 +956,11 @@
}
/**
- * Returns PDO DSN string from DSN array (parse_dsn() result)
+ * Returns PDO DSN string from DSN array
+ *
+ * @param array $dsn DSN parameters
+ *
+ * @return string DSN string
*/
protected function dsn_string($dsn)
{
@@ -965,7 +987,11 @@
}
/**
- * Returns PDO driver options array from DSN array (parse_dsn() result)
+ * Returns driver-specific connection options
+ *
+ * @param array $dsn DSN parameters
+ *
+ * @return array Connection options
*/
protected function dsn_options($dsn)
{
--
Gitblit v1.9.1