blob: 37090cb5d4abcc1fc7dc4c88e1bd5749c881ef6a [file] [log] [blame]
<?php
/**
* CodeIgniter
*
* An open source application development framework for PHP 5.2.4 or newer
*
* NOTICE OF LICENSE
*
* Licensed under the Open Software License version 3.0
*
* This source file is subject to the Open Software License (OSL 3.0) that is
* bundled with this package in the files license.txt / license.rst. It is
* also available through the world wide web at this URL:
* http://opensource.org/licenses/OSL-3.0
* If you did not receive a copy of the license and are unable to obtain it
* through the world wide web, please send an email to
* licensing@ellislab.com so we can send you a copy immediately.
*
* @package CodeIgniter
* @author EllisLab Dev Team
* @copyright Copyright (c) 2008 - 2013, EllisLab, Inc. (http://ellislab.com/)
* @license http://opensource.org/licenses/OSL-3.0 Open Software License (OSL 3.0)
* @link http://codeigniter.com
* @since Version 2.1.0
* @filesource
*/
defined('BASEPATH') OR exit('No direct script access allowed');
/**
* PDO Database Adapter Class
*
* Note: _DB is an extender class that the app controller
* creates dynamically based on whether the query builder
* class is being used or not.
*
* @package CodeIgniter
* @subpackage Drivers
* @category Database
* @author EllisLab Dev Team
* @link http://codeigniter.com/user_guide/database/
*/
class CI_DB_pdo_driver extends CI_DB {
/**
* Database driver
*
* @var string
*/
public $dbdriver = 'pdo';
/**
* Transaction enabled flag
*
* @var bool
*/
public $trans_enabled = FALSE;
/**
* PDO Options
*
* @var array
*/
public $options = array();
// --------------------------------------------------------------------
/**
* Class constructor
*
* Validates the DSN string and/or detects the subdriver.
*
* @param array $params
* @return void
*/
public function __construct($params)
{
parent::__construct($params);
if (preg_match('/([^;]+):/', $this->dsn, $match) && count($match) === 2)
{
// If there is a minimum valid dsn string pattern found, we're done
// This is for general PDO users, who tend to have a full DSN string.
$this->subdriver = $match[1];
return;
}
// Legacy support for DSN specified in the hostname field
elseif (preg_match('/([^;]+):/', $this->hostname, $match) && count($match) === 2)
{
$this->dsn = $this->hostname;
$this->hostname = NULL;
$this->subdriver = $match[1];
return;
}
elseif (in_array($this->subdriver, array('mssql', 'sybase'), TRUE))
{
$this->subdriver = 'dblib';
}
elseif ($this->subdriver === '4D')
{
$this->subdriver = '4d';
}
elseif ( ! in_array($this->subdriver, array('4d', 'cubrid', 'dblib', 'firebird', 'ibm', 'informix', 'mysql', 'oci', 'odbc', 'sqlite', 'sqlsrv'), TRUE))
{
log_message('error', 'PDO: Invalid or non-existent subdriver');
if ($this->db_debug)
{
show_error('Invalid or non-existent PDO subdriver');
}
}
$this->dsn = NULL;
}
// --------------------------------------------------------------------
/**
* Database connection
*
* @param bool $persistent
* @return object
*/
public function db_connect($persistent = FALSE)
{
$this->options[PDO::ATTR_PERSISTENT] = $persistent;
// Connecting...
try
{
return @new PDO($this->dsn, $this->username, $this->password, $this->options);
}
catch (PDOException $e)
{
if ($this->db_debug && empty($this->failover))
{
$this->display_error($e->getMessage(), '', TRUE);
}
return FALSE;
}
}
// --------------------------------------------------------------------
/**
* Persistent database connection
*
* @return object
*/
public function db_pconnect()
{
return $this->db_connect(TRUE);
}
// --------------------------------------------------------------------
/**
* Database version number
*
* @return string
*/
public function version()
{
if (isset($this->data_cache['version']))
{
return $this->data_cache['version'];
}
elseif ( ! $this->conn_id)
{
$this->initialize();
}
// Not all subdrivers support the getAttribute() method
try
{
return $this->data_cache['version'] = $this->conn_id->getAttribute(PDO::ATTR_SERVER_VERSION);
}
catch (PDOException $e)
{
return parent::version();
}
}
// --------------------------------------------------------------------
/**
* Execute the query
*
* @param string $sql SQL query
* @return mixed
*/
protected function _execute($sql)
{
return $this->conn_id->query($sql);
}
// --------------------------------------------------------------------
/**
* Begin Transaction
*
* @param bool $test_mode
* @return bool
*/
public function trans_begin($test_mode = FALSE)
{
// When transactions are nested we only begin/commit/rollback the outermost ones
if ( ! $this->trans_enabled OR $this->_trans_depth > 0)
{
return TRUE;
}
// Reset the transaction failure flag.
// If the $test_mode flag is set to TRUE transactions will be rolled back
// even if the queries produce a successful result.
$this->_trans_failure = ($test_mode === TRUE);
return $this->conn_id->beginTransaction();
}
// --------------------------------------------------------------------
/**
* Commit Transaction
*
* @return bool
*/
public function trans_commit()
{
// When transactions are nested we only begin/commit/rollback the outermost ones
if ( ! $this->trans_enabled OR $this->_trans_depth > 0)
{
return TRUE;
}
return $this->conn_id->commit();
}
// --------------------------------------------------------------------
/**
* Rollback Transaction
*
* @return bool
*/
public function trans_rollback()
{
// When transactions are nested we only begin/commit/rollback the outermost ones
if ( ! $this->trans_enabled OR $this->_trans_depth > 0)
{
return TRUE;
}
return $this->conn_id->rollBack();
}
// --------------------------------------------------------------------
/**
* Escape String
*
* @param string $str
* @param bool $like Whether or not the string will be used in a LIKE condition
* @return string
*/
public function escape_str($str, $like = FALSE)
{
if (is_array($str))
{
foreach ($str as $key => $val)
{
$str[$key] = $this->escape_str($val, $like);
}
return $str;
}
// Escape the string
$str = $this->conn_id->quote($str);
// If there are duplicated quotes, trim them away
if ($str[0] === "'")
{
$str = substr($str, 1, -1);
}
// escape LIKE condition wildcards
if ($like === TRUE)
{
return str_replace(array($this->_like_escape_chr, '%', '_'),
array($this->_like_escape_chr.$this->_like_escape_chr, $this->_like_escape_chr.'%', $this->_like_escape_chr.'_'),
$str);
}
return $str;
}
// --------------------------------------------------------------------
/**
* Affected Rows
*
* @return int
*/
public function affected_rows()
{
return is_object($this->result_id) ? $this->result_id->rowCount() : 0;
}
// --------------------------------------------------------------------
/**
* Insert ID
*
* @param string $name
* @return int
*/
public function insert_id($name = NULL)
{
return $this->conn_id->lastInsertId($name);
}
// --------------------------------------------------------------------
/**
* Field data query
*
* Generates a platform-specific query so that the column data can be retrieved
*
* @param string $table
* @return string
*/
protected function _field_data($table)
{
return 'SELECT TOP 1 * FROM '.$this->protect_identifiers($table);
}
// --------------------------------------------------------------------
/**
* Error
*
* Returns an array containing code and message of the last
* database error that has occured.
*
* @return array
*/
public function error()
{
$error = array('code' => '00000', 'message' => '');
$pdo_error = $this->conn_id->errorInfo();
if (empty($pdo_error[0]))
{
return $error;
}
$error['code'] = isset($pdo_error[1]) ? $pdo_error[0].'/'.$pdo_error[1] : $pdo_error[0];
if (isset($pdo_error[2]))
{
$error['message'] = $pdo_error[2];
}
return $error;
}
// --------------------------------------------------------------------
/**
* Update_Batch statement
*
* Generates a platform-specific batch update string from the supplied data
*
* @param string $table Table name
* @param array $values Update data
* @param string $index WHERE key
* @return string
*/
protected function _update_batch($table, $values, $index)
{
$ids = array();
foreach ($values as $key => $val)
{
$ids[] = $val[$index];
foreach (array_keys($val) as $field)
{
if ($field !== $index)
{
$final[$field][] = 'WHEN '.$index.' = '.$val[$index].' THEN '.$val[$field];
}
}
}
$cases = '';
foreach ($final as $k => $v)
{
$cases .= $k.' = CASE '."\n";
foreach ($v as $row)
{
$cases .= $row."\n";
}
$cases .= 'ELSE '.$k.' END, ';
}
$this->where($index.' IN('.implode(',', $ids).')', NULL, FALSE);
return 'UPDATE '.$table.' SET '.substr($cases, 0, -2).$this->_compile_wh('qb_where');
}
// --------------------------------------------------------------------
/**
* Truncate statement
*
* Generates a platform-specific truncate string from the supplied data
*
* If the database does not support the TRUNCATE statement,
* then this method maps to 'DELETE FROM table'
*
* @param string $table
* @return string
*/
protected function _truncate($table)
{
return 'TRUNCATE TABLE '.$table;
}
}
/* End of file pdo_driver.php */
/* Location: ./system/database/drivers/pdo/pdo_driver.php */