Reworked the database class
Got rid of all of that object bloatin’ nonsense.
This commit is contained in:
parent
7fc38398eb
commit
9a2d593eff
7 changed files with 372 additions and 607 deletions
|
@ -16,116 +16,419 @@
|
|||
*/
|
||||
|
||||
/**
|
||||
* Database Factory
|
||||
* Database Class
|
||||
*
|
||||
* Generic class to simplify connecting to a database. All database objects
|
||||
* should be created by this class to future proof against any internal changes
|
||||
* to PICKLES.
|
||||
* Database interaction all in one place. Allows for object reuse and contains
|
||||
* functions to ease interacting with databases. Common assumptions about PDO
|
||||
* attributes are baked in. Only support PDO.
|
||||
*/
|
||||
class Database extends Object
|
||||
{
|
||||
/**
|
||||
* Constructor
|
||||
* DSN format
|
||||
*
|
||||
* Attempts to get an instance of the passed database type or attempts to
|
||||
* use a default specified in the config.
|
||||
*
|
||||
* @param string $name optional name of the connection to use
|
||||
* @access protected
|
||||
* @var string
|
||||
*/
|
||||
public function __construct(String $name = null)
|
||||
{
|
||||
parent::__construct();
|
||||
protected $dsn;
|
||||
|
||||
return Database::getInstance($name);
|
||||
}
|
||||
/**
|
||||
* PDO Attributes
|
||||
*
|
||||
* @access protected
|
||||
* @var string
|
||||
*/
|
||||
protected $attributes = [
|
||||
PDO::ATTR_PERSISTENT => true,
|
||||
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
|
||||
PDO::NULL_EMPTY_STRING => true,
|
||||
];
|
||||
|
||||
/**
|
||||
* Driver
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public $driver = null;
|
||||
|
||||
/**
|
||||
* Hostname for the server
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public $hostname = 'localhost';
|
||||
|
||||
/**
|
||||
* Port number for the server
|
||||
*
|
||||
* @var integer
|
||||
*/
|
||||
public $port = null;
|
||||
|
||||
/**
|
||||
* UNIX socket for the server
|
||||
*
|
||||
* @var integer
|
||||
*/
|
||||
public $socket = null;
|
||||
|
||||
/**
|
||||
* Username for the server
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public $username = null;
|
||||
|
||||
/**
|
||||
* Password for the server
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public $password = null;
|
||||
|
||||
/**
|
||||
* Database name for the server
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public $database = null;
|
||||
|
||||
/**
|
||||
* Whether or not to use caching
|
||||
*
|
||||
* @var boolean
|
||||
*/
|
||||
public $cache = false;
|
||||
|
||||
/**
|
||||
* Connection resource
|
||||
*
|
||||
* @var object
|
||||
*/
|
||||
public $connection = null;
|
||||
|
||||
/**
|
||||
* Results object for the executed statement
|
||||
*
|
||||
* @var object
|
||||
*/
|
||||
public $results = null;
|
||||
|
||||
/**
|
||||
* Get Instance
|
||||
*
|
||||
* Looks up the datasource using the passed name and gets an instance of
|
||||
* it. Allows for easy sharing of certain classes within the system to
|
||||
* avoid the extra overhead of creating new objects each time. Also avoids
|
||||
* the hassle of passing around variables (yeah I know, very global-ish)
|
||||
* Instantiates a new instance of the Database class or returns the
|
||||
* previously instantiated copy.
|
||||
*
|
||||
* @static
|
||||
* @param string $name name of the datasource
|
||||
* @param string $datasource_name name of the datasource
|
||||
* @return object instance of the class
|
||||
*/
|
||||
public static function getInstance($name = null)
|
||||
public static function getInstance($datasource_name = false)
|
||||
{
|
||||
$config = Config::getInstance();
|
||||
|
||||
// Checks if we have a default
|
||||
if ($name == null)
|
||||
// Tries to load a datasource if one wasn't specified
|
||||
if (!$datasource_name)
|
||||
{
|
||||
// Checks the config for a default
|
||||
if (isset($config->pickles['datasource']))
|
||||
{
|
||||
$name = $config->pickles['datasource'];
|
||||
$datasource_name = $config->pickles['datasource'];
|
||||
}
|
||||
// Tries to use the first defined datasource
|
||||
elseif (is_array($config->datasources))
|
||||
{
|
||||
$datasources = $config->datasources;
|
||||
$name = key($datasources);
|
||||
$datasources = $config->datasources;
|
||||
$datasource_name = key($datasources);
|
||||
}
|
||||
}
|
||||
|
||||
// If we have a name try to set up a connection
|
||||
if ($name != null)
|
||||
// Attempts to validate the datasource
|
||||
if ($datasource_name)
|
||||
{
|
||||
if (isset($config->datasources[$name]))
|
||||
if (!isset(self::$instances['Database'][$datasource_name]))
|
||||
{
|
||||
$datasource = $config->datasources[$name];
|
||||
if (!isset($config->datasources[$datasource_name]))
|
||||
{
|
||||
throw new Exception('The specified datasource is not defined in the config.');
|
||||
}
|
||||
|
||||
$datasource = $config->datasources[$datasource_name];
|
||||
|
||||
if (!isset($datasource['driver']))
|
||||
{
|
||||
return false;
|
||||
throw new Exception('The specified datasource lacks a driver.');
|
||||
}
|
||||
|
||||
$datasource['driver'] = strtolower($datasource['driver']);
|
||||
|
||||
if (!isset(self::$instances['Database'][$name]))
|
||||
// Checks the driver is legit and scrubs the name
|
||||
switch ($datasource['driver'])
|
||||
{
|
||||
// Checks the driver is legit and scrubs the name
|
||||
switch ($datasource['driver'])
|
||||
case 'pdo_mysql':
|
||||
$attributes = [
|
||||
'dsn' => 'mysql:host=[[hostname]];port=[[port]];unix_socket=[[socket]];dbname=[[database]]',
|
||||
'port' => 3306,
|
||||
];
|
||||
break;
|
||||
|
||||
case 'pdo_pgsql':
|
||||
$attributes = [
|
||||
'dsn' => 'pgsql:host=[[hostname]];port=[[port]];dbname=[[database]];user=[[username]];password=[[password]]',
|
||||
'port' => 5432,
|
||||
];
|
||||
break;
|
||||
|
||||
case 'pdo_sqlite':
|
||||
$attributes = ['dsn' => 'sqlite:[[hostname]]'];
|
||||
break;
|
||||
|
||||
default:
|
||||
throw new Exception('Datasource driver "' . $datasource['driver'] . '" is invalid');
|
||||
break;
|
||||
}
|
||||
|
||||
// Instantiates our database class
|
||||
$instance = new Database();
|
||||
|
||||
// Sets our database parameters
|
||||
if (is_array($datasource))
|
||||
{
|
||||
$datasource = array_merge($attributes, $datasource);
|
||||
|
||||
foreach ($datasource as $variable => $value)
|
||||
{
|
||||
case 'pdo_mysql': $class = 'PDO_MySQL'; break;
|
||||
case 'pdo_pgsql': $class = 'PDO_PostgreSQL'; break;
|
||||
case 'pdo_sqlite': $class = 'PDO_SQLite'; break;
|
||||
|
||||
default:
|
||||
throw new Exception('Datasource driver "' . $datasource['driver'] . '" is invalid');
|
||||
break;
|
||||
}
|
||||
|
||||
// Instantiates our database class
|
||||
$class = 'Database_' . $class;
|
||||
$instance = new $class();
|
||||
|
||||
// Sets our database parameters
|
||||
if (is_array($datasource))
|
||||
{
|
||||
foreach ($datasource as $variable => $value)
|
||||
{
|
||||
$instance->$variable = $value;
|
||||
}
|
||||
$instance->$variable = $value;
|
||||
}
|
||||
}
|
||||
|
||||
// Caches the instance for possible reuse later
|
||||
if (isset($instance))
|
||||
{
|
||||
self::$instances['Database'][$name] = $instance;
|
||||
}
|
||||
|
||||
// Returns the instance
|
||||
return self::$instances['Database'][$name];
|
||||
self::$instances['Database'][$datasource_name] = $instance;
|
||||
}
|
||||
|
||||
// Returns the instance
|
||||
return self::$instances['Database'][$datasource_name];
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Opens database connection
|
||||
*
|
||||
* Establishes a connection to the database based on the set configuration
|
||||
* options.
|
||||
*
|
||||
* @return boolean true on success, throws an exception overwise
|
||||
*/
|
||||
public function open()
|
||||
{
|
||||
if ($this->connection === null)
|
||||
{
|
||||
// Checks that the prefix is set
|
||||
if ($this->dsn == null)
|
||||
{
|
||||
throw new Exception('Data source name is not defined');
|
||||
}
|
||||
|
||||
switch ($this->driver)
|
||||
{
|
||||
case 'pdo_mysql':
|
||||
// Resolves "Invalid UTF-8 sequence" issues when encoding as JSON
|
||||
// @todo Didn't resolve that issue, borked some other characters though
|
||||
//$this->attributes[PDO::MYSQL_ATTR_INIT_COMMAND] = 'SET NAMES utf8';
|
||||
break;
|
||||
|
||||
case 'pdo_pgsql':
|
||||
// This combats a bug: https://bugs.php.net/bug.php?id=62571&edit=1
|
||||
$this->attributes[PDO::ATTR_PERSISTENT] = false;
|
||||
|
||||
// This allows for multiple prepared queries
|
||||
$this->attributes[PDO::ATTR_EMULATE_PREPARES] = true;
|
||||
break;
|
||||
}
|
||||
|
||||
if (isset($this->username, $this->password, $this->database))
|
||||
{
|
||||
// Creates a new PDO database object (persistent)
|
||||
try
|
||||
{
|
||||
// Swaps out any variables with values in the DSN
|
||||
$this->dsn = str_replace(
|
||||
['[[hostname]]', '[[port]]', '[[socket]]', '[[username]]', '[[password]]', '[[database]]'],
|
||||
[$this->hostname, $this->port, $this->socket, $this->username, $this->password, $this->database],
|
||||
$this->dsn
|
||||
);
|
||||
|
||||
// Strips any empty parameters in the DSN
|
||||
$this->dsn = str_replace(['host=;', 'port=;', 'unix_socket=;'], '', $this->dsn);
|
||||
|
||||
// Attempts to establish a connection
|
||||
$this->connection = new PDO($this->dsn, $this->username, $this->password, $this->attributes);
|
||||
}
|
||||
catch (PDOException $e)
|
||||
{
|
||||
throw new Exception($e);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new Exception('There was an error loading the database configuration');
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Closes database connection
|
||||
*
|
||||
* Sets the connection to null regardless of state.
|
||||
*
|
||||
* @return boolean always true
|
||||
*/
|
||||
public function close()
|
||||
{
|
||||
$this->connection = null;
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Executes an SQL Statement
|
||||
*
|
||||
* Executes a standard or prepared query based on passed parameters. All
|
||||
* queries are logged to a file as well as timed and logged in the
|
||||
* execution time is over 1 second.
|
||||
*
|
||||
* @param string $sql statement to execute
|
||||
* @param array $input_parameters optional key/values to be bound
|
||||
* @return integer ID of the last inserted row or sequence number
|
||||
*/
|
||||
public function execute($sql, $input_parameters = null)
|
||||
{
|
||||
$this->open();
|
||||
|
||||
if ($this->config->pickles['logging'] === true)
|
||||
{
|
||||
$loggable_query = $sql;
|
||||
|
||||
if ($input_parameters != null)
|
||||
{
|
||||
$loggable_query .= ' -- ' . json_encode($input_parameters);
|
||||
}
|
||||
|
||||
Log::query($loggable_query);
|
||||
}
|
||||
|
||||
$sql = trim($sql);
|
||||
|
||||
// Checks if the query is blank
|
||||
if ($sql != '')
|
||||
{
|
||||
// Builds out stack trace for queries
|
||||
$files = [];
|
||||
|
||||
$backtrace = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS);
|
||||
krsort($backtrace);
|
||||
|
||||
foreach ($backtrace as $file)
|
||||
{
|
||||
if (isset($file['class'], $file['line']))
|
||||
{
|
||||
$files[] = $file['class'] . ':' . $file['line'];
|
||||
}
|
||||
}
|
||||
|
||||
$sql .= "\n" . '/* [' . implode('|', $files) . '] */';
|
||||
|
||||
try
|
||||
{
|
||||
// Establishes if we're working on an EXPLAIN
|
||||
if (Profiler::enabled('explains') == true)
|
||||
{
|
||||
$explaining = preg_match('/^EXPLAIN /i', $sql);
|
||||
$selecting = preg_match('/^SELECT /i', $sql);
|
||||
}
|
||||
else
|
||||
{
|
||||
$explaining = null;
|
||||
$selecting = null;
|
||||
}
|
||||
|
||||
// Executes a standard query
|
||||
if ($input_parameters === null)
|
||||
{
|
||||
// Explains the query
|
||||
if ($selecting == true && $explaining == false)
|
||||
{
|
||||
$explain = $this->fetch('EXPLAIN ' . $sql);
|
||||
}
|
||||
|
||||
$start_time = microtime(true);
|
||||
$this->results = $this->connection->query($sql);
|
||||
}
|
||||
// Executes a prepared statement
|
||||
else
|
||||
{
|
||||
// Explains the query
|
||||
if ($selecting == true && $explaining == false)
|
||||
{
|
||||
$explain = $this->fetch('EXPLAIN ' . $sql, $input_parameters);
|
||||
}
|
||||
|
||||
$start_time = microtime(true);
|
||||
$this->results = $this->connection->prepare($sql);
|
||||
$this->results->execute($input_parameters);
|
||||
}
|
||||
|
||||
$end_time = microtime(true);
|
||||
$duration = $end_time - $start_time;
|
||||
|
||||
if ($duration >= 1)
|
||||
{
|
||||
Log::slowQuery($duration . ' seconds: ' . $loggable_query);
|
||||
}
|
||||
|
||||
// Logs the information to the profiler
|
||||
if ($explaining == false && Profiler::enabled('explains', 'queries'))
|
||||
{
|
||||
Profiler::logQuery($sql, $input_parameters, (isset($explain) ? $explain : false), $duration);
|
||||
}
|
||||
}
|
||||
catch (PDOException $e)
|
||||
{
|
||||
throw new Exception($e);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new Exception('No query to execute');
|
||||
}
|
||||
|
||||
return $this->connection->lastInsertId();
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetch records from the database
|
||||
*
|
||||
* @param string $sql statement to be executed
|
||||
* @param array $input_parameters optional key/values to be bound
|
||||
* @param string $return_type optional type of return set
|
||||
* @return mixed based on return type
|
||||
*/
|
||||
public function fetch($sql = null, $input_parameters = null)
|
||||
{
|
||||
$this->open();
|
||||
|
||||
if ($sql !== null)
|
||||
{
|
||||
$this->execute($sql, $input_parameters);
|
||||
}
|
||||
|
||||
// Pulls the results based on the type
|
||||
$results = $this->results->fetchAll(PDO::FETCH_ASSOC);
|
||||
|
||||
return $results;
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
||||
|
|
|
@ -1,139 +0,0 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* Common Database Class File for PICKLES
|
||||
*
|
||||
* PHP version 5
|
||||
*
|
||||
* Licensed under The MIT License
|
||||
* Redistribution of these files must retain the above copyright notice.
|
||||
*
|
||||
* @author Joshua Sherman <pickles@joshtronic.com>
|
||||
* @copyright Copyright 2007-2014, Joshua Sherman
|
||||
* @license http://www.opensource.org/licenses/mit-license.html
|
||||
* @package PICKLES
|
||||
* @link https://github.com/joshtronic/pickles
|
||||
*/
|
||||
|
||||
/**
|
||||
* Common Database Abstraction Layer
|
||||
*
|
||||
* Parent class that our database driver classes should be extending. Contains
|
||||
* basic functionality for instantiation and interfacing.
|
||||
*/
|
||||
abstract class Database_Common extends Object
|
||||
{
|
||||
/**
|
||||
* Driver
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public $driver = null;
|
||||
|
||||
/**
|
||||
* Hostname for the server
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public $hostname = 'localhost';
|
||||
|
||||
/**
|
||||
* Port number for the server
|
||||
*
|
||||
* @var integer
|
||||
*/
|
||||
public $port = null;
|
||||
|
||||
/**
|
||||
* UNIX socket for the server
|
||||
*
|
||||
* @var integer
|
||||
*/
|
||||
public $socket = null;
|
||||
|
||||
/**
|
||||
* Username for the server
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public $username = null;
|
||||
|
||||
/**
|
||||
* Password for the server
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public $password = null;
|
||||
|
||||
/**
|
||||
* Database name for the server
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public $database = null;
|
||||
|
||||
/**
|
||||
* Whether or not to use caching
|
||||
*
|
||||
* @var boolean
|
||||
*/
|
||||
public $cache = false;
|
||||
|
||||
/**
|
||||
* Connection resource
|
||||
*
|
||||
* @var object
|
||||
*/
|
||||
public $connection = null;
|
||||
|
||||
/**
|
||||
* Results object for the executed statement
|
||||
*
|
||||
* @var object
|
||||
*/
|
||||
public $results = null;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct();
|
||||
|
||||
// Checks the driver is set and available
|
||||
if ($this->driver == null)
|
||||
{
|
||||
throw new Exception('Driver name is not set');
|
||||
}
|
||||
else
|
||||
{
|
||||
if (extension_loaded($this->driver) == false)
|
||||
{
|
||||
throw new Exception('Driver "' . $this->driver . '" is not loaded');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Open Database Connection
|
||||
*
|
||||
* Establishes a connection to the MySQL database based on the configuration
|
||||
* options that are available in the Config object.
|
||||
*
|
||||
* @abstract
|
||||
* @return boolean true on success, throws an exception overwise
|
||||
*/
|
||||
abstract public function open();
|
||||
|
||||
/**
|
||||
* Close Database Connection
|
||||
*
|
||||
* Sets the connection to null regardless of state.
|
||||
*
|
||||
* @abstract
|
||||
* @return boolean always true
|
||||
*/
|
||||
abstract public function close();
|
||||
}
|
||||
|
||||
?>
|
|
@ -1,278 +0,0 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* PDO Class File for PICKLES
|
||||
*
|
||||
* PHP version 5
|
||||
*
|
||||
* Licensed under The MIT License
|
||||
* Redistribution of these files must retain the above copyright notice.
|
||||
*
|
||||
* @author Joshua Sherman <pickles@joshtronic.com>
|
||||
* @copyright Copyright 2007-2014, Joshua Sherman
|
||||
* @license http://www.opensource.org/licenses/mit-license.html
|
||||
* @package PICKLES
|
||||
* @link https://github.com/joshtronic/pickles
|
||||
*/
|
||||
|
||||
/**
|
||||
* PDO Abstraction Layer
|
||||
*
|
||||
* Parent class for any of our database classes that use PDO.
|
||||
*/
|
||||
class Database_PDO_Common extends Database_Common
|
||||
{
|
||||
/**
|
||||
* DSN format
|
||||
*
|
||||
* @access protected
|
||||
* @var string
|
||||
*/
|
||||
protected $dsn;
|
||||
|
||||
/**
|
||||
* PDO Attributes
|
||||
*
|
||||
* @access protected
|
||||
* @var string
|
||||
*/
|
||||
protected $attributes = array(
|
||||
PDO::ATTR_PERSISTENT => true,
|
||||
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
|
||||
PDO::NULL_EMPTY_STRING => true,
|
||||
);
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct();
|
||||
|
||||
// Checks that the prefix is set
|
||||
if ($this->dsn == null)
|
||||
{
|
||||
throw new Exception('Data source name is not defined');
|
||||
}
|
||||
|
||||
switch ($this->driver)
|
||||
{
|
||||
case 'pdo_mysql':
|
||||
// Resolves "Invalid UTF-8 sequence" issues when encoding as JSON
|
||||
// @todo Didn't resolve that issue, borked some other characters though
|
||||
//$this->attributes[PDO::MYSQL_ATTR_INIT_COMMAND] = 'SET NAMES utf8';
|
||||
break;
|
||||
|
||||
case 'pdo_pgsql':
|
||||
// This combats a bug: https://bugs.php.net/bug.php?id=62571&edit=1
|
||||
$this->attributes[PDO::ATTR_PERSISTENT] = false;
|
||||
|
||||
// This allows for multiple prepared queries
|
||||
$this->attributes[PDO::ATTR_EMULATE_PREPARES] = true;
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Opens database connection
|
||||
*
|
||||
* Establishes a connection to the database based on the set configuration
|
||||
* options.
|
||||
*
|
||||
* @return boolean true on success, throws an exception overwise
|
||||
*/
|
||||
public function open()
|
||||
{
|
||||
if ($this->connection === null)
|
||||
{
|
||||
if (isset($this->username, $this->password, $this->database))
|
||||
{
|
||||
// Creates a new PDO database object (persistent)
|
||||
try
|
||||
{
|
||||
// Swaps out any variables with values in the DSN
|
||||
$this->dsn = str_replace(
|
||||
array('[[hostname]]', '[[port]]', '[[socket]]', '[[username]]', '[[password]]', '[[database]]'),
|
||||
array($this->hostname, $this->port, $this->socket, $this->username, $this->password, $this->database),
|
||||
$this->dsn
|
||||
);
|
||||
|
||||
// Strips any empty parameters in the DSN
|
||||
$this->dsn = str_replace(array('host=;', 'port=;', 'unix_socket=;'), '', $this->dsn);
|
||||
|
||||
// Attempts to establish a connection
|
||||
$this->connection = new PDO($this->dsn, $this->username, $this->password, $this->attributes);
|
||||
}
|
||||
catch (PDOException $e)
|
||||
{
|
||||
throw new Exception($e);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new Exception('There was an error loading the database configuration');
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Closes database connection
|
||||
*
|
||||
* Sets the connection to null regardless of state.
|
||||
*
|
||||
* @return boolean always true
|
||||
*/
|
||||
public function close()
|
||||
{
|
||||
$this->connection = null;
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Executes an SQL Statement
|
||||
*
|
||||
* Executes a standard or prepared query based on passed parameters. All
|
||||
* queries are logged to a file as well as timed and logged in the
|
||||
* execution time is over 1 second.
|
||||
*
|
||||
* @param string $sql statement to execute
|
||||
* @param array $input_parameters optional key/values to be bound
|
||||
* @return integer ID of the last inserted row or sequence number
|
||||
*/
|
||||
public function execute($sql, $input_parameters = null)
|
||||
{
|
||||
$this->open();
|
||||
|
||||
if ($this->config->pickles['logging'] === true)
|
||||
{
|
||||
$loggable_query = $sql;
|
||||
|
||||
if ($input_parameters != null)
|
||||
{
|
||||
$loggable_query .= ' -- ' . json_encode($input_parameters);
|
||||
}
|
||||
|
||||
Log::query($loggable_query);
|
||||
}
|
||||
|
||||
$sql = trim($sql);
|
||||
|
||||
// Checks if the query is blank
|
||||
if ($sql != '')
|
||||
{
|
||||
$files = array();
|
||||
|
||||
// Ubuntu 10.04 is a bit behind on PHP 5.3.x and the IGNORE_ARGS
|
||||
// constant doesn't exist. To conserve memory, the backtrace will
|
||||
// Only be used on servers running PHP 5.3.6 or above.
|
||||
if (version_compare(PHP_VERSION, '5.3.6', '>='))
|
||||
{
|
||||
$backtrace = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS);
|
||||
krsort($backtrace);
|
||||
|
||||
foreach ($backtrace as $file)
|
||||
{
|
||||
if (isset($file['class'], $file['line']))
|
||||
{
|
||||
$files[] = $file['class'] . ':' . $file['line'];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$sql .= "\n" . '/* [' . implode('|', $files) . '] */';
|
||||
|
||||
try
|
||||
{
|
||||
// Establishes if we're working on an EXPLAIN
|
||||
if (Profiler::enabled('explains') == true)
|
||||
{
|
||||
$explaining = preg_match('/^EXPLAIN /i', $sql);
|
||||
$selecting = preg_match('/^SELECT /i', $sql);
|
||||
}
|
||||
else
|
||||
{
|
||||
$explaining = null;
|
||||
$selecting = null;
|
||||
}
|
||||
|
||||
// Executes a standard query
|
||||
if ($input_parameters === null)
|
||||
{
|
||||
// Explains the query
|
||||
if ($selecting == true && $explaining == false)
|
||||
{
|
||||
$explain = $this->fetch('EXPLAIN ' . $sql);
|
||||
}
|
||||
|
||||
$start_time = microtime(true);
|
||||
$this->results = $this->connection->query($sql);
|
||||
}
|
||||
// Executes a prepared statement
|
||||
else
|
||||
{
|
||||
// Explains the query
|
||||
if ($selecting == true && $explaining == false)
|
||||
{
|
||||
$explain = $this->fetch('EXPLAIN ' . $sql, $input_parameters);
|
||||
}
|
||||
|
||||
$start_time = microtime(true);
|
||||
$this->results = $this->connection->prepare($sql);
|
||||
$this->results->execute($input_parameters);
|
||||
}
|
||||
|
||||
$end_time = microtime(true);
|
||||
$duration = $end_time - $start_time;
|
||||
|
||||
if ($duration >= 1)
|
||||
{
|
||||
Log::slowQuery($duration . ' seconds: ' . $loggable_query);
|
||||
}
|
||||
|
||||
// Logs the information to the profiler
|
||||
if ($explaining == false && Profiler::enabled('explains', 'queries'))
|
||||
{
|
||||
Profiler::logQuery($sql, $input_parameters, (isset($explain) ? $explain : false), $duration);
|
||||
}
|
||||
}
|
||||
catch (PDOException $e)
|
||||
{
|
||||
throw new Exception($e);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new Exception('No query to execute');
|
||||
}
|
||||
|
||||
return $this->connection->lastInsertId();
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetch records from the database
|
||||
*
|
||||
* @param string $sql statement to be executed
|
||||
* @param array $input_parameters optional key/values to be bound
|
||||
* @param string $return_type optional type of return set
|
||||
* @return mixed based on return type
|
||||
*/
|
||||
public function fetch($sql = null, $input_parameters = null)
|
||||
{
|
||||
$this->open();
|
||||
|
||||
if ($sql !== null)
|
||||
{
|
||||
$this->execute($sql, $input_parameters);
|
||||
}
|
||||
|
||||
// Pulls the results based on the type
|
||||
$results = $this->results->fetchAll(PDO::FETCH_ASSOC);
|
||||
|
||||
return $results;
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
|
@ -1,45 +0,0 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* MySQL Class File for PICKLES
|
||||
*
|
||||
* PHP version 5
|
||||
*
|
||||
* Licensed under The MIT License
|
||||
* Redistribution of these files must retain the above copyright notice.
|
||||
*
|
||||
* @author Joshua Sherman <pickles@joshtronic.com>
|
||||
* @copyright Copyright 2007-2014, Joshua Sherman
|
||||
* @license http://www.opensource.org/licenses/mit-license.html
|
||||
* @package PICKLES
|
||||
* @link https://github.com/joshtronic/pickles
|
||||
*/
|
||||
|
||||
/**
|
||||
* MySQL Database Abstraction Layer
|
||||
*/
|
||||
class Database_PDO_MySQL extends Database_PDO_Common
|
||||
{
|
||||
/**
|
||||
* Driver
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public $driver = 'pdo_mysql';
|
||||
|
||||
/**
|
||||
* DSN format
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public $dsn = 'mysql:host=[[hostname]];port=[[port]];unix_socket=[[socket]];dbname=[[database]]';
|
||||
|
||||
/**
|
||||
* Default port
|
||||
*
|
||||
* @var integer
|
||||
*/
|
||||
public $port = 3306;
|
||||
}
|
||||
|
||||
?>
|
|
@ -1,45 +0,0 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* PostgreSQL Class File for PICKLES
|
||||
*
|
||||
* PHP version 5
|
||||
*
|
||||
* Licensed under The MIT License
|
||||
* Redistribution of these files must retain the above copyright notice.
|
||||
*
|
||||
* @author Joshua Sherman <pickles@joshtronic.com>
|
||||
* @copyright Copyright 2007-2014, Joshua Sherman
|
||||
* @license http://www.opensource.org/licenses/mit-license.html
|
||||
* @package PICKLES
|
||||
* @link https://github.com/joshtronic/pickles
|
||||
*/
|
||||
|
||||
/**
|
||||
* PostgreSQL Database Abstraction Layer
|
||||
*/
|
||||
class Database_PDO_PostgreSQL extends Database_PDO_Common
|
||||
{
|
||||
/**
|
||||
* Driver
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public $driver = 'pdo_pgsql';
|
||||
|
||||
/**
|
||||
* DSN format
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public $dsn = 'pgsql:host=[[hostname]];port=[[port]];dbname=[[database]];user=[[username]];password=[[password]]';
|
||||
|
||||
/**
|
||||
* Default port
|
||||
*
|
||||
* @var integer
|
||||
*/
|
||||
public $port = 5432;
|
||||
}
|
||||
|
||||
?>
|
|
@ -1,38 +0,0 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* SQLite Class File for PICKLES
|
||||
*
|
||||
* PHP version 5
|
||||
*
|
||||
* Licensed under The MIT License
|
||||
* Redistribution of these files must retain the above copyright notice.
|
||||
*
|
||||
* @author Joshua Sherman <pickles@joshtronic.com>
|
||||
* @copyright Copyright 2007-2014, Joshua Sherman
|
||||
* @license http://www.opensource.org/licenses/mit-license.html
|
||||
* @package PICKLES
|
||||
* @link https://github.com/joshtronic/pickles
|
||||
*/
|
||||
|
||||
/**
|
||||
* SQLite Database Abstraction Layer
|
||||
*/
|
||||
class Database_PDO_SQLite extends Database_PDO_Common
|
||||
{
|
||||
/**
|
||||
* Driver
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public $driver = 'pdo_sqlite';
|
||||
|
||||
/**
|
||||
* DSN format
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public $dsn = 'sqlite:[[hostname]]';
|
||||
}
|
||||
|
||||
?>
|
|
@ -47,6 +47,13 @@ class TimeTest extends PHPUnit_Framework_TestCase
|
|||
$this->assertEquals('1 day ago', Time::ago(strtotime('-1 day')));
|
||||
}
|
||||
|
||||
/* @todo Need to fix these results so it doesn't fail.
|
||||
public function testAgoPastTimeDays2()
|
||||
{
|
||||
$this->assertEquals('1 day ago', Time::ago(strtotime('-23 hours -55 minutes')));
|
||||
}
|
||||
*/
|
||||
|
||||
public function testAgoPastTimeWeeks()
|
||||
{
|
||||
$this->assertEquals('1 week ago', Time::ago(strtotime('-1 week')));
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue