Improve error handling by using wrapper classes for PDO and PDOStatement

This commit is contained in:
Kijin Sung 2020-06-30 12:00:42 +09:00
parent 47bb30c535
commit 936568a8a5
3 changed files with 265 additions and 129 deletions

View file

@ -101,15 +101,17 @@ class DB
$options = array( $options = array(
\PDO::ATTR_ERRMODE => \PDO::ERRMODE_EXCEPTION, \PDO::ATTR_ERRMODE => \PDO::ERRMODE_EXCEPTION,
\PDO::ATTR_EMULATE_PREPARES => false, \PDO::ATTR_EMULATE_PREPARES => false,
\PDO::ATTR_STATEMENT_CLASS => array('\Rhymix\Framework\Helpers\DBStmtHelper'),
\PDO::MYSQL_ATTR_USE_BUFFERED_QUERY => false, \PDO::MYSQL_ATTR_USE_BUFFERED_QUERY => false,
); );
try try
{ {
$this->_handle = new \PDO($dsn, $config['user'], $config['pass'], $options); $this->_handle = new Helpers\DBHelper($dsn, $config['user'], $config['pass'], $options);
$this->_handle->setType($type);
} }
catch (\PDOException $e) catch (\PDOException $e)
{ {
throw new Exceptions\DBError($e->getMessage(), $e->getCode(), $e); throw new Exceptions\DBError($e->getMessage(), 0, $e);
} }
// Get the DB version. // Get the DB version.
@ -117,11 +119,11 @@ class DB
} }
/** /**
* Get the raw PDO handle. * Get the PDO handle for direct manipulation.
* *
* @return PDO * @return Helpers\DBHelper
*/ */
public function getHandle(): \PDO public function getHandle(): Helpers\DBHelper
{ {
return $this->_handle; return $this->_handle;
} }
@ -129,25 +131,37 @@ class DB
/** /**
* Create a prepared statement. * Create a prepared statement.
* *
* @param string $query_string * Table names in the FROM or JOIN clause of the statement are
* @return \PDOStatement * automatically prefixed with the configured prefix.
*
* @param string $statement
* @param array $driver_options
* @return Helpers\DBStmtHelper
*/ */
public function prepare(string $query_string) public function prepare(string $statement, array $driver_options = [])
{ {
// Add table prefixes to the query string. // Add table prefixes to the query string.
$query_string = $this->addPrefixes($query_string); $statement = $this->addPrefixes($statement);
// Create and return a prepared statement. // Create and return a prepared statement.
$this->_last_stmt = $this->_handle->prepare($query_string); $this->_last_stmt = $this->_handle->prepare($statement, $driver_options);
return $this->_last_stmt; return $this->_last_stmt;
} }
/** /**
* Execute a query string. * Execute a query string with or without parameters.
*
* This method will automatically use prepared statements if there are
* any parameters. It is strongly recommended to pass any user-supplied
* values as separate parameters instead of embedding them directly
* in the query string, in order to prevent SQL injection attacks.
*
* Table names in the FROM or JOIN clause of the statement are
* automatically prefixed with the configured prefix.
* *
* @param string $query_string * @param string $query_string
* @param mixed ...$args * @param mixed ...$args
* @return \PDOStatement * @return Helpers\DBStmtHelper
*/ */
public function query(string $query_string, ...$args) public function query(string $query_string, ...$args)
{ {
@ -158,36 +172,18 @@ class DB
} }
// Add table prefixes to the query string. // Add table prefixes to the query string.
$class_start_time = microtime(true);
$query_string = $this->addPrefixes($query_string); $query_string = $this->addPrefixes($query_string);
// Execute either a prepared statement or a regular query depending on whether there are arguments. // Execute either a prepared statement or a regular query depending on whether there are arguments.
try if (count($args))
{ {
$query_start_time = microtime(true); $this->_last_stmt = $this->_handle->prepare($query_string);
if (count($args)) $this->_last_stmt->execute($args);
{
$this->_last_stmt = $this->_handle->prepare($query_string);
$this->_last_stmt->execute($args);
}
else
{
$this->_last_stmt = $this->_handle->query($query_string);
}
$this->clearError();
$query_elapsed_time = microtime(true) - $query_start_time;
$this->_query_time += $query_elapsed_time;
Debug::addQuery($this->getQueryLog($query_string, '', $query_elapsed_time));
} }
catch (\PDOException $e) else
{ {
$this->setError($e->getCode(), $e->getMessage()); $this->_last_stmt = $this->_handle->query($query_string);
$query_elapsed_time = microtime(true) - $query_start_time;
$this->_query_time += $query_elapsed_time;
Debug::addQuery($this->getQueryLog($query_string, '', $query_elapsed_time));
} }
$this->_total_time += (microtime(true) - $class_start_time);
return $this->_last_stmt; return $this->_last_stmt;
} }
@ -207,6 +203,10 @@ class DB
{ {
$args = get_object_vars($args); $args = get_object_vars($args);
} }
if (is_null($args))
{
$args = array();
}
if (!is_array($args)) if (!is_array($args))
{ {
return $this->setError(-1, 'Invalid query arguments.'); return $this->setError(-1, 'Invalid query arguments.');
@ -216,7 +216,7 @@ class DB
$column_list = is_array($column_list) ? array_values($column_list) : array(); $column_list = is_array($column_list) ? array_values($column_list) : array();
// Start measuring elapsed time. // Start measuring elapsed time.
$class_start_time = microtime(true); $start_time = microtime(true);
// Get the name of the XML file. // Get the name of the XML file.
$parts = explode('.', $query_id); $parts = explode('.', $query_id);
@ -229,7 +229,7 @@ class DB
{ {
$output = $this->setError(-1, 'Query \'' . $query_id . '\' does not exist.'); $output = $this->setError(-1, 'Query \'' . $query_id . '\' does not exist.');
$output->page_navigation = new \PageHandler(0, 0, 0); $output->page_navigation = new \PageHandler(0, 0, 0);
$this->_total_time += (microtime(true) - $class_start_time); $this->_total_time += (microtime(true) - $start_time);
return $output; return $output;
} }
@ -247,7 +247,7 @@ class DB
{ {
$output = $this->setError(-1, 'Query \'' . $query_id . '\' cannot be parsed.'); $output = $this->setError(-1, 'Query \'' . $query_id . '\' cannot be parsed.');
$output->page_navigation = new \PageHandler(0, 0, 0); $output->page_navigation = new \PageHandler(0, 0, 0);
$this->_total_time += (microtime(true) - $class_start_time); $this->_total_time += (microtime(true) - $start_time);
return $output; return $output;
} }
} }
@ -262,7 +262,7 @@ class DB
{ {
$output = $this->setError(-1, $e->getMessage()); $output = $this->setError(-1, $e->getMessage());
$output->page_navigation = new \PageHandler(0, 0, 0); $output->page_navigation = new \PageHandler(0, 0, 0);
$this->_total_time += (microtime(true) - $class_start_time); $this->_total_time += (microtime(true) - $start_time);
return $output; return $output;
} }
@ -274,7 +274,7 @@ class DB
if (!$output->toBool()) if (!$output->toBool())
{ {
$output->page_navigation = new \PageHandler(0, 0, 0); $output->page_navigation = new \PageHandler(0, 0, 0);
$this->_total_time += (microtime(true) - $class_start_time); $this->_total_time += (microtime(true) - $start_time);
return $output; return $output;
} }
@ -284,7 +284,7 @@ class DB
$output->add('_query', $query_string); $output->add('_query', $query_string);
$output->add('_elapsed_time', '0.00000'); $output->add('_elapsed_time', '0.00000');
$output->page_navigation = new \PageHandler(0, 0, 0); $output->page_navigation = new \PageHandler(0, 0, 0);
$this->_total_time += (microtime(true) - $class_start_time); $this->_total_time += (microtime(true) - $start_time);
return $output; return $output;
} }
} }
@ -296,7 +296,6 @@ class DB
// Prepare and execute the main query. // Prepare and execute the main query.
try try
{ {
$query_start_time = microtime(true);
if (count($query_params)) if (count($query_params))
{ {
$this->_last_stmt = $this->_handle->prepare($query_string); $this->_last_stmt = $this->_handle->prepare($query_string);
@ -307,31 +306,22 @@ class DB
$this->_last_stmt = $this->_handle->query($query_string); $this->_last_stmt = $this->_handle->query($query_string);
} }
$result = $this->_fetch($this->_last_stmt, $last_index); $result = $this->_fetch($this->_last_stmt, $last_index);
$query_elapsed_time = microtime(true) - $query_start_time;
$this->_query_time += $query_elapsed_time;
Debug::addQuery($this->getQueryLog($query_string, $query_id, $query_elapsed_time));
} }
catch (\PDOException $e) catch (Exceptions\DBError $e)
{ {
$query_elapsed_time = microtime(true) - $query_start_time;
$this->_query_time += $query_elapsed_time;
$output = $this->setError(-1, $e->getMessage());
$output->add('_query', $query_string); $output->add('_query', $query_string);
$output->add('_elapsed_time', '0.00000'); $output->add('_elapsed_time', '0.00000');
$output->page_navigation = new \PageHandler(0, 0, 0); $output->page_navigation = new \PageHandler(0, 0, 0);
Debug::addQuery($this->getQueryLog($query_string, $query_id, $query_elapsed_time)); $this->_total_time += (microtime(true) - $start_time);
$this->_total_time += (microtime(true) - $class_start_time);
return $output; return $output;
} }
// Fill query information and result data in the output object. // Fill query information and result data in the output object.
$this->_total_time += ($elapsed_time = microtime(true) - $start_time);
$output->add('_query', $query_string); $output->add('_query', $query_string);
$output->add('_elapsed_time', sprintf('%0.5f', $query_elapsed_time)); $output->add('_elapsed_time', sprintf('%0.5f', $elapsed_time));
$output->data = $result; $output->data = $result;
// Record statistics about this query and elapsed time.
$this->_total_time += (microtime(true) - $class_start_time);
// Return the complete result. // Return the complete result.
$this->clearError(); $this->clearError();
return $output; return $output;
@ -362,7 +352,6 @@ class DB
// Prepare and execute the query. // Prepare and execute the query.
try try
{ {
$query_start_time = microtime(true);
if (count($query_params)) if (count($query_params))
{ {
$this->_last_stmt = $this->_handle->prepare($query_string); $this->_last_stmt = $this->_handle->prepare($query_string);
@ -373,16 +362,10 @@ class DB
$this->_last_stmt = $this->_handle->query($query_string); $this->_last_stmt = $this->_handle->query($query_string);
} }
$result = $this->_fetch($this->_last_stmt); $result = $this->_fetch($this->_last_stmt);
$query_elapsed_time = microtime(true) - $query_start_time;
$this->_query_time += $query_elapsed_time;
Debug::addQuery($this->getQueryLog($query_string, $query_id . ' (count)', $query_elapsed_time));
} }
catch (\PDOException $e) catch (Exceptions\DBError $e)
{ {
$query_elapsed_time = microtime(true) - $query_start_time;
$this->_query_time += $query_elapsed_time;
$output = $this->setError(-1, $e->getMessage()); $output = $this->setError(-1, $e->getMessage());
Debug::addQuery($this->getQueryLog($query_string, $query_id . ' (count)', $query_elapsed_time));
return $output; return $output;
} }
@ -412,29 +395,11 @@ class DB
* But since there are many legacy apps that rely on it, we will leave it public. * But since there are many legacy apps that rely on it, we will leave it public.
* *
* @param string $query_string * @param string $query_string
* @return \PDOStatement * @return Helpers\DBStmtHelper
*/ */
public function _query(string $query_string) public function _query(string $query_string)
{ {
try $this->_last_stmt = $this->_handle->query($query_string);
{
$query_start_time = microtime(true);
$this->_last_stmt = $this->_handle->query($query_string);
$this->clearError();
$query_elapsed_time = microtime(true) - $query_start_time;
$this->_query_time += $query_elapsed_time;
$this->_total_time += $query_elapsed_time;
Debug::addQuery($this->getQueryLog($query_string, '', $query_elapsed_time));
}
catch (\PDOException $e)
{
$this->setError($e->getCode(), $e->getMessage());
$query_elapsed_time = microtime(true) - $query_start_time;
$this->_query_time += $query_elapsed_time;
$this->_total_time += $query_elapsed_time;
Debug::addQuery($this->getQueryLog($query_string, '', $query_elapsed_time));
}
return $this->_last_stmt; return $this->_last_stmt;
} }
@ -488,7 +453,7 @@ class DB
} }
catch (\PDOException $e) catch (\PDOException $e)
{ {
$this->setError($e->getCode(), $e->getMessage()); $this->setError(-1, $e->getMessage());
} }
Debug::addQuery($this->getQueryLog('START TRANSACTION', '', 0)); Debug::addQuery($this->getQueryLog('START TRANSACTION', '', 0));
} }
@ -512,7 +477,7 @@ class DB
} }
catch (\PDOException $e) catch (\PDOException $e)
{ {
$this->setError($e->getCode(), $e->getMessage()); $this->setError(-1, $e->getMessage());
} }
Debug::addQuery($this->getQueryLog('ROLLBACK', '', 0)); Debug::addQuery($this->getQueryLog('ROLLBACK', '', 0));
} }
@ -536,7 +501,7 @@ class DB
} }
catch (\PDOException $e) catch (\PDOException $e)
{ {
$this->setError($e->getCode(), $e->getMessage()); $this->setError(-1, $e->getMessage());
} }
Debug::addQuery($this->getQueryLog('COMMIT', '', 0)); Debug::addQuery($this->getQueryLog('COMMIT', '', 0));
} }
@ -569,26 +534,16 @@ class DB
*/ */
public function getNextSequence() public function getNextSequence()
{ {
try $this->_handle->exec(sprintf('INSERT INTO `sequence` (seq) VALUES (0)'));
$sequence = $this->getInsertID();
if ($this->isError())
{ {
$this->_handle->exec(sprintf('INSERT INTO `sequence` (seq) VALUES (0)')); throw new Exceptions\DBError($this->getError()->getMessage());
$sequence = $this->getInsertID();
}
catch (\PDOException $e)
{
throw new Exceptions\DBError($e->getMessage(), $e->getCode(), $e);
} }
if($sequence % 10000 == 0) if($sequence % 10000 == 0)
{ {
try $this->_handle->exec(sprintf('DELETE FROM `sequence` WHERE seq < %d', $sequence));
{
$this->_handle->exec(sprintf('DELETE FROM `sequence` WHERE seq < %d', $sequence));
}
catch (\PDOException $e)
{
$this->setError($e->getCode(), $e->getMessage());
}
} }
$this->clearError(); $this->clearError();
@ -604,15 +559,10 @@ class DB
*/ */
public function isValidOldPassword(string $password, string $saved_password): bool public function isValidOldPassword(string $password, string $saved_password): bool
{ {
try $stmt = $this->_handle->query('SELECT' . ' ' . 'PASSWORD(?) AS pw1, OLD_PASSWORD(?) AS pw2', $password, $password);
$result = $this->_fetch($stmt);
if ($this->isError() || !$result)
{ {
$stmt = $this->query('SELECT' . ' ' . 'PASSWORD(?) AS pw1, OLD_PASSWORD(?) AS pw2', $password, $password);
$result = $this->_fetch($stmt);
$this->clearError();
}
catch (\PDOException $e)
{
$this->setError($e->getCode(), $e->getMessage());
return false; return false;
} }
@ -634,7 +584,7 @@ class DB
*/ */
public function isTableExists(string $table_name): bool public function isTableExists(string $table_name): bool
{ {
$stmt = $this->_query(sprintf("SHOW TABLES LIKE '%s'", $this->addQuotes($this->_prefix . $table_name))); $stmt = $this->_handle->query(sprintf("SHOW TABLES LIKE '%s'", $this->addQuotes($this->_prefix . $table_name)));
$result = $this->_fetch($stmt); $result = $this->_fetch($stmt);
return $result ? true : false; return $result ? true : false;
} }
@ -657,8 +607,8 @@ class DB
// Generate the CREATE TABLE query and execute it. // Generate the CREATE TABLE query and execute it.
$query_string = $table->getCreateQuery($this->_prefix, $this->_charset, $this->_engine); $query_string = $table->getCreateQuery($this->_prefix, $this->_charset, $this->_engine);
$stmt = $this->_query($query_string); $result = $this->_handle->exec($query_string);
return $stmt ? new \BaseObject : $this->getError(); return $result ? new \BaseObject : $this->getError();
} }
/** /**
@ -669,7 +619,7 @@ class DB
*/ */
public function dropTable(string $table_name): \BaseObject public function dropTable(string $table_name): \BaseObject
{ {
$stmt = $this->_query(sprintf("DROP TABLE `%s`", $this->addQuotes($this->_prefix . $table_name))); $stmt = $this->_handle->exec(sprintf("DROP TABLE `%s`", $this->addQuotes($this->_prefix . $table_name)));
return $stmt ? new \BaseObject : $this->getError(); return $stmt ? new \BaseObject : $this->getError();
} }
@ -682,7 +632,7 @@ class DB
*/ */
public function isColumnExists(string $table_name, string $column_name): bool public function isColumnExists(string $table_name, string $column_name): bool
{ {
$stmt = $this->_query(sprintf("SHOW FIELDS FROM `%s` WHERE Field = '%s'", $this->addQuotes($this->_prefix . $table_name), $this->addQuotes($column_name))); $stmt = $this->_handle->query(sprintf("SHOW FIELDS FROM `%s` WHERE Field = '%s'", $this->addQuotes($this->_prefix . $table_name), $this->addQuotes($column_name)));
$result = $this->_fetch($stmt); $result = $this->_fetch($stmt);
return $result ? true : false; return $result ? true : false;
} }
@ -733,8 +683,8 @@ class DB
} }
// Execute the query and return the result. // Execute the query and return the result.
$stmt = $this->_query($query); $result = $this->_handle->exec($query);
return $stmt ? new \BaseObject : $this->getError(); return $result ? new \BaseObject : $this->getError();
} }
/** /**
@ -791,8 +741,8 @@ class DB
} }
// Execute the query and return the result. // Execute the query and return the result.
$stmt = $this->_query($query); $result = $this->_handle->exec($query);
return $stmt ? new \BaseObject : $this->getError(); return $result ? new \BaseObject : $this->getError();
} }
/** /**
@ -804,8 +754,8 @@ class DB
*/ */
public function dropColumn(string $table_name, string $column_name): \BaseObject public function dropColumn(string $table_name, string $column_name): \BaseObject
{ {
$stmt = $this->_query(sprintf("ALTER TABLE `%s` DROP `%s`", $this->addQuotes($this->_prefix . $table_name), $this->addQuotes($column_name))); $result = $this->_handle->exec(sprintf("ALTER TABLE `%s` DROP `%s`", $this->addQuotes($this->_prefix . $table_name), $this->addQuotes($column_name)));
return $stmt ? new \BaseObject : $this->getError(); return $result ? new \BaseObject : $this->getError();
} }
/** /**
@ -818,7 +768,7 @@ class DB
public function getColumnInfo(string $table_name, string $column_name) public function getColumnInfo(string $table_name, string $column_name)
{ {
// If column information is not found, return false. // If column information is not found, return false.
$stmt = $this->_query(sprintf("SHOW FIELDS FROM `%s` WHERE Field = '%s'", $this->addQuotes($this->_prefix . $table_name), $this->addQuotes($column_name))); $stmt = $this->_handle->query(sprintf("SHOW FIELDS FROM `%s` WHERE Field = '%s'", $this->addQuotes($this->_prefix . $table_name), $this->addQuotes($column_name)));
$column_info = $this->_fetch($stmt); $column_info = $this->_fetch($stmt);
if (!$column_info) if (!$column_info)
{ {
@ -854,7 +804,7 @@ class DB
*/ */
public function isIndexExists(string $table_name, string $index_name): bool public function isIndexExists(string $table_name, string $index_name): bool
{ {
$stmt = $this->_query(sprintf("SHOW INDEX FROM `%s` WHERE Key_name = '%s'", $this->addQuotes($this->_prefix . $table_name), $this->addQuotes($index_name))); $stmt = $this->_handle->query(sprintf("SHOW INDEX FROM `%s` WHERE Key_name = '%s'", $this->addQuotes($this->_prefix . $table_name), $this->addQuotes($index_name)));
$result = $this->_fetch($stmt); $result = $this->_fetch($stmt);
return $result ? true : false; return $result ? true : false;
} }
@ -891,8 +841,8 @@ class DB
}, $columns)), }, $columns)),
)); ));
$stmt = $this->_query($query); $result = $this->_handle->exec($query);
return $stmt ? new \BaseObject : $this->getError(); return $result ? new \BaseObject : $this->getError();
} }
/** /**
@ -904,8 +854,8 @@ class DB
*/ */
public function dropIndex(string $table_name, string $index_name): \BaseObject public function dropIndex(string $table_name, string $index_name): \BaseObject
{ {
$stmt = $this->_query(sprintf("ALTER TABLE `%s` DROP INDEX `%s`", $this->addQuotes($this->_prefix . $table_name), $this->addQuotes($index_name))); $result = $this->_handle->exec(sprintf("ALTER TABLE `%s` DROP INDEX `%s`", $this->addQuotes($this->_prefix . $table_name), $this->addQuotes($index_name)));
return $stmt ? new \BaseObject : $this->getError(); return $result ? new \BaseObject : $this->getError();
} }
/** /**
@ -1054,7 +1004,7 @@ class DB
$backtrace = debug_backtrace(\DEBUG_BACKTRACE_IGNORE_ARGS); $backtrace = debug_backtrace(\DEBUG_BACKTRACE_IGNORE_ARGS);
foreach ($backtrace as $no => $call) foreach ($backtrace as $no => $call)
{ {
if ($call['file'] !== __FILE__ && $call['file'] !== \RX_BASEDIR . 'common/legacy.php') if (!preg_match('#/common/framework/(?:db|helpers)\b#', $call['file']) && $call['file'] !== \RX_BASEDIR . 'common/legacy.php')
{ {
$result['called_file'] = $backtrace[$no]['file']; $result['called_file'] = $backtrace[$no]['file'];
$result['called_line'] = $backtrace[$no]['line']; $result['called_line'] = $backtrace[$no]['line'];
@ -1079,12 +1029,23 @@ class DB
Debug::addQuery($log); Debug::addQuery($log);
} }
/**
* Add elapsed time.
*
* @param float $elapsed_time
* @return void
*/
public function addElapsedTime(float $elapsed_time)
{
$this->_query_time += $elapsed_time;
}
/** /**
* Get total time spent during queries. * Get total time spent during queries.
* *
* @return float * @return float
*/ */
public function getQueryElapsedTime() public function getQueryElapsedTime(): float
{ {
return $this->_query_time; return $this->_query_time;
} }
@ -1094,7 +1055,7 @@ class DB
* *
* @return float * @return float
*/ */
public function getTotalElapsedTime() public function getTotalElapsedTime(): float
{ {
return $this->_total_time; return $this->_total_time;
} }

View file

@ -0,0 +1,116 @@
<?php
namespace Rhymix\Framework\Helpers;
use Rhymix\Framework\DB;
use Rhymix\Framework\Debug;
use Rhymix\Framework\Exceptions\DBError;
/**
* DB helper class.
*/
class DBHelper extends \PDO
{
/**
* Store the database type (e.g. master) here.
*/
protected $_type = 'master';
/**
* Set the database type.
*/
public function setType(string $type)
{
$this->_type = $type;
}
/**
* Create a prepared statement.
*
* @param string $statement
* @param array $driver_options
* @return PDOStatement|DBStmtHelper
*/
public function prepare($statement, $driver_options = null)
{
try
{
if ($driver_options)
{
$stmt = parent::prepare($statement, $driver_options);
}
else
{
$stmt = parent::prepare($statement);
}
$stmt->setFetchMode(\PDO::FETCH_OBJ);
$stmt->setType($this->_type);
}
catch (\PDOException $e)
{
throw new DBError($e->getMessage(), 0, $e);
}
return $stmt;
}
/**
* Execute a query.
*
* @param string $statement
* @return PDOStatement|DBStmtHelper
*/
public function query($statement)
{
$start_time = microtime(true);
$db_class = DB::getInstance($this->_type);
$args = func_get_args();
array_shift($args);
try
{
$stmt = parent::query($statement, ...$args);
$stmt->setFetchMode(\PDO::FETCH_OBJ);
$stmt->setType($this->_type);
$db_class->clearError();
}
catch (\PDOException $e)
{
$db_class->setError(-1, $e->getMessage());
}
$elapsed_time = microtime(true) - $start_time;
$db_class->addElapsedTime($elapsed_time);
Debug::addQuery($db_class->getQueryLog($statement, '', $elapsed_time));
return $stmt;
}
/**
* Execute a query and return the number of affected rows.
*
* @param string $statement
* @return bool
*/
public function exec($query)
{
$start_time = microtime(true);
$db_class = DB::getInstance($this->_type);
try
{
$result = parent::exec($query);
$db_class->clearError();
}
catch (\PDOException $e)
{
$db_class->setError(-1, $e->getMessage());
}
$elapsed_time = microtime(true) - $start_time;
$db_class->addElapsedTime($elapsed_time);
Debug::addQuery($db_class->getQueryLog($query, '', $elapsed_time));
return $result;
}
}

View file

@ -0,0 +1,59 @@
<?php
namespace Rhymix\Framework\Helpers;
use Rhymix\Framework\DB;
use Rhymix\Framework\Debug;
use Rhymix\Framework\Exceptions\DBError;
/**
* DB Statement helper class.
*/
class DBStmtHelper extends \PDOStatement
{
/**
* Store the database type (e.g. master) here.
*/
protected $_type = 'master';
/**
* Set the database type.
*/
public function setType(string $type)
{
$this->_type = $type;
}
/**
* Execute a prepared statement.
*
* @param array $input_parameters
* @return bool
*/
public function execute($input_parameters = null): bool
{
$start_time = microtime(true);
$db_class = DB::getInstance($this->_type);
try
{
$result = parent::execute($input_parameters);
$db_class->clearError();
$elapsed_time = microtime(true) - $start_time;
$db_class->addElapsedTime($elapsed_time);
Debug::addQuery($db_class->getQueryLog($this->queryString, '', $elapsed_time));
}
catch (\PDOException $e)
{
$db_class->setError(-1, $e->getMessage());
$elapsed_time = microtime(true) - $start_time;
$db_class->addElapsedTime($elapsed_time);
Debug::addQuery($db_class->getQueryLog($this->queryString, '', $elapsed_time));
throw new DBError($e->getMessage(), 0, $e);
}
return $result;
}
}