| program/include/rcube_mdb2.php |
| |
| This file is part of the RoundCube Webmail client |
- | Copyright (C) 2005-2008, RoundCube Dev. - Switzerland |
+ | Copyright (C) 2005-2009, RoundCube Dev. - Switzerland |
| Licensed under the GNU GPL |
| |
| PURPOSE: |
| Author: Lukas Kahwe Smith <smith@pooteeweet.org> |
+-----------------------------------------------------------------------+
- $Id: rcube_mdb2.php 1390 2008-05-15 11:15:58Z thomasb $
+ $Id: rcube_mdb2.php 2920 2009-09-04 13:07:48Z alec $
*/
}
- /**
- * PHP 4 object constructor
- *
- * @see rcube_mdb2::__construct
- */
- function rcube_db($db_dsnw,$db_dsnr='')
- {
- $this->__construct($db_dsnw,$db_dsnr);
- }
-
-
/**
* Connect to specific database
*
function dsn_connect($dsn)
{
// Use persistent connections if available
- $dbh = MDB2::connect($dsn, array(
+ $db_options = array(
'persistent' => $this->db_pconn,
'emulate_prepared' => $this->debug_mode,
'debug' => $this->debug_mode,
'debug_handler' => 'mdb2_debug_handler',
- 'portability' => MDB2_PORTABILITY_ALL ^ MDB2_PORTABILITY_EMPTY_TO_NULL));
+ 'portability' => MDB2_PORTABILITY_ALL ^ MDB2_PORTABILITY_EMPTY_TO_NULL);
+
+ if ($this->db_provider == 'pgsql') {
+ $db_options['disable_smart_seqname'] = true;
+ $db_options['seqname_format'] = '%s';
+ }
+
+ $dbh = MDB2::connect($dsn, $db_options);
if (MDB2::isError($dbh))
{
if (!filesize($dsn_array['database']) && !empty($this->sqlite_initials))
$this->_sqlite_create_database($dbh, $this->sqlite_initials);
}
- else
+ else if ($this->db_provider!='mssql')
$dbh->setCharset('utf8');
return $dbh;
}
+ /**
+ * Connection state checker
+ *
+ * @param boolean True if in connected state
+ */
+ function is_connected()
+ {
+ return PEAR::isError($this->db_handle) ? false : true;
+ }
+
+
/**
* Execute a SQL query
*
*/
function query()
{
+ if (!$this->is_connected())
+ return NULL;
+
$params = func_get_args();
$query = array_shift($params);
function _query($query, $offset, $numrows, $params)
{
// Read or write ?
- if (strtolower(trim(substr($query,0,6)))=='select')
+ if (strtolower(substr(trim($query),0,6))=='select')
$mode='r';
else
$mode='w';
$result = $this->db_handle->setLimit($numrows,$offset);
if (empty($params))
- $result = $this->db_handle->query($query);
+ $result = $mode=='r' ? $this->db_handle->query($query) : $this->db_handle->exec($query);
else
{
$params = (array)$params;
- $q = $this->db_handle->prepare($query);
+ $q = $this->db_handle->prepare($query, null, $mode=='w' ? MDB2_PREPARE_MANIP : null);
if ($this->db_handle->isError($q))
{
$this->db_error = TRUE;
/**
- * Get number of affected rows fort he last query
+ * Get number of affected rows for the last query
*
+ * @param number Optional query handle identifier
* @return mixed Number of rows or FALSE on failure
* @access public
*/
- function affected_rows($result = null)
+ function affected_rows($res_id = null)
{
if (!$this->db_handle)
return FALSE;
- return $this->_get_result($result);
+ return (int) $this->_get_result($res_id);
}
* Get last inserted record ID
* For Postgres databases, a sequence name is required
*
- * @param string Sequence name for increment
+ * @param string Table name (to find the incremented sequence)
* @return mixed ID or FALSE on failure
* @access public
*/
- function insert_id($sequence = '')
+ function insert_id($table = '')
{
if (!$this->db_handle || $this->db_mode=='r')
return FALSE;
- return $this->db_handle->lastInsertID($sequence);
+ // find sequence name
+ if ($table && $this->db_provider == 'pgsql')
+ $table = get_sequence_name($table);
+
+ $id = $this->db_handle->lastInsertID($table);
+
+ return $this->db_handle->isError($id) ? null : $id;
}
/**
- * Get co values for a result row
+ * Get col values for a result row
*
* @param object Query result handle
* @param number Fetch mode identifier
*/
function _fetch_row($result, $mode)
{
- if (PEAR::isError($result))
- {
- raise_error(array('code' => 500, 'type' => 'db', 'line' => __LINE__, 'file' => __FILE__,
- 'message' => $this->db_link->getMessage()), TRUE, FALSE);
+ if ($result === FALSE || PEAR::isError($result) || !$this->is_connected())
return FALSE;
- }
return $result->fetchRow($mode);
}
* @param string Value to quote
* @return string Quoted string for use in query
* @deprecated Replaced by rcube_MDB2::quote_identifier
- * @see rcube_MDB2::quote_identifier
+ * @see rcube_mdb2::quote_identifier
* @access public
*/
function quoteIdentifier($str)
- {
+ {
return $this->quote_identifier($str);
- }
+ }
/**
}
+ /**
+ * Return list of elements for use with SQL's IN clause
+ *
+ * @param string Input array
+ * @return string Elements list string
+ * @access public
+ */
+ function array2list($arr, $type=null)
+ {
+ if (!is_array($arr))
+ return $this->quote($arr, $type);
+
+ $res = array();
+ foreach ($arr as $item)
+ $res[] = $this->quote($item, $type);
+
+ return implode(',', $res);
+ }
+
+
/**
* Return SQL statement to convert a field value into a unix timestamp
*
break;
case 'mssql':
- return "datediff(s, '1970-01-01 00:00:00', $field)";
+ return "DATEDIFF(second, '19700101', $field) + DATEDIFF(second, GETDATE(), GETUTCDATE())";
default:
return "UNIX_TIMESTAMP($field)";
}
+ /**
+ * Return SQL statement for case insensitive LIKE
+ *
+ * @param string Field name
+ * @param string Search value
+ * @return string SQL statement to use in query
+ * @access public
+ */
+ function ilike($column, $value)
+ {
+ // TODO: use MDB2's matchPattern() function
+ switch($this->db_provider)
+ {
+ case 'pgsql':
+ return $this->quote_identifier($column).' ILIKE '.$this->quote($value);
+ default:
+ return $this->quote_identifier($column).' LIKE '.$this->quote($value);
+ }
+ }
+
+
+ /**
+ * Encodes non-UTF-8 characters in string/array/object (recursive)
+ *
+ * @param mixed Data to fix
+ * @return mixed Properly UTF-8 encoded data
+ * @access public
+ */
+ function encode($input)
+ {
+ if (is_object($input)) {
+ foreach (get_object_vars($input) as $idx => $value)
+ $input->$idx = $this->encode($value);
+ return $input;
+ }
+ else if (is_array($input)) {
+ foreach ($input as $idx => $value)
+ $input[$idx] = $this->encode($value);
+ return $input;
+ }
+
+ return utf8_encode($input);
+ }
+
+
+ /**
+ * Decodes encoded UTF-8 string/object/array (recursive)
+ *
+ * @param mixed Input data
+ * @return mixed Decoded data
+ * @access public
+ */
+ function decode($input)
+ {
+ if (is_object($input)) {
+ foreach (get_object_vars($input) as $idx => $value)
+ $input->$idx = $this->decode($value);
+ return $input;
+ }
+ else if (is_array($input)) {
+ foreach ($input as $idx => $value)
+ $input[$idx] = $this->decode($value);
+ return $input;
+ }
+
+ return utf8_decode($input);
+ }
+
+
/**
* Adds a query result and returns a handle ID
*
* @param object Query handle
- * @return mixed Handle ID or FALE on failure
+ * @return mixed Handle ID
* @access private
*/
function _add_result($res)
// sql error occured
if (PEAR::isError($res))
{
+ $this->db_error = TRUE;
+ $this->db_error_msg = $res->getMessage();
raise_error(array('code' => 500, 'type' => 'db', 'line' => __LINE__, 'file' => __FILE__,
- 'message' => $res->getMessage() . " Query: " . substr(preg_replace('/[\r\n]+\s*/', ' ', $res->userinfo), 0, 512)), TRUE, FALSE);
- return FALSE;
- }
- else
- {
- $res_id = sizeof($this->a_query_results);
- $this->a_query_results[$res_id] = $res;
- $this->last_res_id = $res_id;
- return $res_id;
+ 'message' => $res->getMessage() . " Query: "
+ . substr(preg_replace('/[\r\n]+\s*/', ' ', $res->userinfo), 0, 512)),
+ TRUE, FALSE);
}
+
+ $res_id = sizeof($this->a_query_results);
+ $this->last_res_id = $res_id;
+ $this->a_query_results[$res_id] = $res;
+ return $res_id;
}
/**
* Resolves a given handle ID and returns the according query handle
- * If no ID is specified, the last ressource handle will be returned
+ * If no ID is specified, the last resource handle will be returned
*
* @param number Handle ID
- * @return mixed Ressource handle or FALE on failure
+ * @return mixed Resource handle or FALSE on failure
* @access private
*/
function _get_result($res_id=NULL)
if ($res_id==NULL)
$res_id = $this->last_res_id;
- if ($res_id && isset($this->a_query_results[$res_id]))
- return $this->a_query_results[$res_id];
- else
- return FALSE;
+ if (isset($this->a_query_results[$res_id]))
+ if (!PEAR::isError($this->a_query_results[$res_id]))
+ return $this->a_query_results[$res_id];
+
+ return FALSE;
}
if (empty($file_name) || !is_string($file_name))
return;
- $data = '';
- if ($fd = fopen($file_name, 'r'))
- {
- $data = fread($fd, filesize($file_name));
- fclose($fd);
- }
+ $data = file_get_contents($file_name);
if (strlen($data))
- sqlite_exec($dbh->connection, $data);
+ if (!sqlite_exec($dbh->connection, $data, $error) || MDB2::isError($dbh))
+ raise_error(array('code' => 500, 'type' => 'db',
+ 'line' => __LINE__, 'file' => __FILE__, 'message' => $error), TRUE, FALSE);
}
{
$debug_output = $scope . '('.$db->db_index.'): ';
$debug_output .= $message . $db->getOption('log_line_break');
- write_log('sqllog', $debug_output);
+ write_log('sql', $debug_output);
}
}
-
-