_type = $type; } /** * Create a prepared statement. * * @param string $statement * @param array $options * @return DBStmtHelper */ #[\ReturnTypeWillChange] public function prepare($statement, $options = null): DBStmtHelper { $start_time = microtime(true); $db_class = DB::getInstance($this->_type); try { /** * $stmt will be an instance of DBStmtHelper. * This allows it to track the parent database's type * and send query logs to the appropriate place. */ $stmt = $options ? parent::prepare($statement, $options) : parent::prepare($statement); $stmt->setFetchMode(\PDO::FETCH_OBJ); $stmt->setType($this->_type); $db_class->clearError(); } catch (\PDOException $e) { /** * We only measure the time when the prepared statement fails. * If the statement is successfully prepared, time will be measured * when the statement is executed in DBStmtHelper. */ $elapsed_time = microtime(true) - $start_time; $db_class->addElapsedTime($elapsed_time); $db_class->setError(-1, $e->getMessage()); if (Debug::isEnabledForCurrentUser()) { Debug::addQuery($db_class->getQueryLog($statement, $elapsed_time)); } /** * This is a new feature in Rhymix 2.0 so we don't have to mess * with status objects. We just throw an exception. Catch it! */ throw new DBError($e->getMessage(), 0, $e); } return $stmt; } /** * Execute a query. * * This method accepts additional parameters, but they are not for creating * prepared statements. They exist because PDO's own query() method accepts * various kinds of additional parameters, and we don't want to touch them. * * @param string $statement * @param int $fetch_mode * @return DBStmtHelper|false */ #[\ReturnTypeWillChange] public function query($statement, $fetch_mode = \PDO::FETCH_OBJ, ...$fetch_mode_args) { $start_time = microtime(true); $db_class = DB::getInstance($this->_type); $args = func_get_args(); array_shift($args); try { /** * $stmt will be an instance of DBStmtHelper. * This allows it to track the parent database's type * and send query logs to the appropriate place. */ $stmt = parent::query($statement, ...$args); $stmt->setFetchMode($fetch_mode); $stmt->setType($this->_type); $db_class->clearError(); } catch (\PDOException $e) { $stmt = false; $db_class->setError(-1, $e->getMessage()); } finally { $elapsed_time = microtime(true) - $start_time; $db_class->addElapsedTime($elapsed_time); if (Debug::isEnabledForCurrentUser()) { Debug::addQuery($db_class->getQueryLog($statement, $elapsed_time)); } } return $stmt; } /** * Execute a query and return the number of affected rows. * * @param string $statement * @return int|false */ #[\ReturnTypeWillChange] public function exec($statement) { $start_time = microtime(true); $db_class = DB::getInstance($this->_type); try { $result = parent::exec($statement); $db_class->clearError(); } catch (\PDOException $e) { $db_class->setError(-1, $e->getMessage()); } finally { $elapsed_time = microtime(true) - $start_time; $db_class->addElapsedTime($elapsed_time); if (Debug::isEnabledForCurrentUser()) { Debug::addQuery($db_class->getQueryLog($statement, $elapsed_time)); } } return $result; } }