From ce1526061c645892f5f942072a77445e647a04d2 Mon Sep 17 00:00:00 2001 From: skodak Date: Sat, 22 Nov 2008 01:16:52 +0000 Subject: [PATCH] MDL-17317 DML: more exceptions - now in connect too --- lib/dml/adodb_moodle_database.php | 26 ++++++--- lib/dml/moodle_database.php | 3 +- lib/dml/mysqli_native_moodle_database.php | 16 +++++- lib/dml/pgsql_native_moodle_database.php | 23 +++++--- lib/dmllib.php | 66 ++++++++--------------- lib/setuplib.php | 2 +- lib/weblib.php | 14 +++-- 7 files changed, 87 insertions(+), 63 deletions(-) diff --git a/lib/dml/adodb_moodle_database.php b/lib/dml/adodb_moodle_database.php index cf0608be70..7d11b5cf8c 100644 --- a/lib/dml/adodb_moodle_database.php +++ b/lib/dml/adodb_moodle_database.php @@ -38,6 +38,14 @@ abstract class adodb_moodle_database extends moodle_database { public function connect($dbhost, $dbuser, $dbpass, $dbname, $prefix, array $dboptions=null) { global $CFG; + $driverstatus = $this->driver_installed(); + + if ($driverstatus !== true) { + throw new dml_exception('dbdriverproblem', $driverstatus); + } + + ob_start(); + $this->store_settings($dbhost, $dbuser, $dbpass, $dbname, $prefix, $dboptions); $this->preconfigure_dbconnection(); @@ -50,16 +58,22 @@ abstract class adodb_moodle_database extends moodle_database { // we probably want to change this value to ''. $this->adodb->null2null = 'A long random string that will never, ever match something we want to insert into the database, I hope. \''; + if (!empty($this->dboptions['dbpersist'])) { // Use persistent connection - if (!$this->adodb->PConnect($this->dbhost, $this->dbuser, $this->dbpass, $this->dbname)) { - return false; - } + $connected = $this->adodb->PConnect($this->dbhost, $this->dbuser, $this->dbpass, $this->dbname); } else { // Use single connection - if (!$this->adodb->Connect($this->dbhost, $this->dbuser, $this->dbpass, $this->dbname)) { - return false; - } + $connected = $this->adodb->Connect($this->dbhost, $this->dbuser, $this->dbpass, $this->dbname); + } + + $dberr = ob_get_contents(); + ob_end_clean(); + + if (!$connected) { + throw new dml_connection_exception($dberr); } + $this->configure_dbconnection(); + return true; } diff --git a/lib/dml/moodle_database.php b/lib/dml/moodle_database.php index 405a82655e..c395f47ce1 100644 --- a/lib/dml/moodle_database.php +++ b/lib/dml/moodle_database.php @@ -198,7 +198,8 @@ abstract class moodle_database { * @param string $dbname * @param mixed $prefix string means moodle db prefix, false used for external databases where prefix not used * @param array $dboptions driver specific options - * @return bool success + * @return bool true + * @throws dml_connection_exception if error */ public abstract function connect($dbhost, $dbuser, $dbpass, $dbname, $prefix, array $dboptions=null); diff --git a/lib/dml/mysqli_native_moodle_database.php b/lib/dml/mysqli_native_moodle_database.php index 03edbc3861..ba61a494d2 100644 --- a/lib/dml/mysqli_native_moodle_database.php +++ b/lib/dml/mysqli_native_moodle_database.php @@ -82,12 +82,24 @@ class mysqli_native_moodle_database extends moodle_database { public function connect($dbhost, $dbuser, $dbpass, $dbname, $prefix, array $dboptions=null) { global $CFG; + $driverstatus = $this->driver_installed(); + + if ($driverstatus !== true) { + throw new dml_exception('dbdriverproblem', $driverstatus); + } + $this->store_settings($dbhost, $dbuser, $dbpass, $dbname, $prefix, $dboptions); + ob_start(); $this->mysqli = new mysqli($dbhost, $dbuser, $dbpass, $dbname); - if ($this->mysqli->connect_error) { - return false; + $dberr = ob_get_contents(); + ob_end_clean(); + $errorno = @$this->mysqli->connect_errno; + + if ($errorno !== 0) { + throw new dml_connection_exception($dberr); } + $this->query_start("--set_charset()", null, SQL_QUERY_AUX); $this->mysqli->set_charset('utf8'); $this->query_end(true); diff --git a/lib/dml/pgsql_native_moodle_database.php b/lib/dml/pgsql_native_moodle_database.php index c6eb6b1e84..d110c74eb4 100644 --- a/lib/dml/pgsql_native_moodle_database.php +++ b/lib/dml/pgsql_native_moodle_database.php @@ -80,11 +80,18 @@ class pgsql_native_moodle_database extends moodle_database { * @param string $dbname * @param mixed $prefix string means moodle db prefix, false used for external databases where prefix not used * @param array $dboptions driver specific options - * @return bool success + * @return bool true + * @throws dml_connection_exception if error */ public function connect($dbhost, $dbuser, $dbpass, $dbname, $prefix, array $dboptions=null) { global $CFG; + $driverstatus = $this->driver_installed(); + + if ($driverstatus !== true) { + throw new dml_exception('dbdriverproblem', $driverstatus); + } + $this->store_settings($dbhost, $dbuser, $dbpass, $dbname, $prefix, $dboptions); $pass = addcslashes($this->dbpass, "'\\"); @@ -101,17 +108,20 @@ class pgsql_native_moodle_database extends moodle_database { $connection = "host='$this->dbhost' port='$port' user='$this->dbuser' password='$pass' dbname='$this->dbname'"; } + ob_start(); if (empty($this->dboptions['dbpersit'])) { $this->pgsql = pg_connect($connection, PGSQL_CONNECT_FORCE_NEW); } else { $this->pgsql = pg_pconnect($connection, PGSQL_CONNECT_FORCE_NEW); } - + $dberr = ob_get_contents(); + ob_end_clean(); + $status = pg_connection_status($this->pgsql); if ($status === false or $status === PGSQL_CONNECTION_BAD) { $this->pgsql = null; - return false; + throw new dml_connection_exception($dberr); } $this->query_start("--pg_set_client_encoding()", null, SQL_QUERY_AUX); @@ -123,13 +133,12 @@ class pgsql_native_moodle_database extends moodle_database { $this->query_start($sql, null, SQL_QUERY_AUX); $result = pg_query($this->pgsql, $sql); $this->query_end($result); - if ($result === false) { - return false; - } + $this->bytea_oid = pg_fetch_result($result, 0); pg_free_result($result); if ($this->bytea_oid === false) { - return false; + $this->pgsql = null; + throw new dml_connection_exception('Can not read bytea type.'); } return true; diff --git a/lib/dmllib.php b/lib/dmllib.php index a7f6a6a350..2d2ad5da61 100644 --- a/lib/dmllib.php +++ b/lib/dmllib.php @@ -46,6 +46,16 @@ class dml_exception extends moodle_exception { } } +/** + * DML db connection exception - triggered if database not accessible. + */ +class dml_connection_exception extends dml_exception { + function __construct($error) { + $errorinfo = ''.s($error).''; + parent::__construct('dbconnectionfailed', NULL, $errorinfo); + } +} + /** * DML read exception - triggered by SQL syntax errors, missing tables, etc. */ @@ -133,68 +143,38 @@ function setup_DB() { $CFG->dboptions['dbpersist'] = $CFG->dbpersist; } - if (!$DB = moodle_database::get_driver_instance($CFG->dbtype, $CFG->dblibrary)) { throw new dml_exception('dbdriverproblem', "Unknown driver $CFG->dblibrary/$CFG->dbtype"); } - $CFG->dbfamily = $DB->get_dbfamily(); // TODO: BC only for now - - $driverstatus = $DB->driver_installed(); - - if ($driverstatus !== true) { - throw new dml_exception('dbdriverproblem', $driverstatus); - } - - if (debugging('', DEBUG_ALL)) { - // catch errors - ob_start(); - } else { - $prevdebug = error_reporting(0); - } - - $connected = false; try { - $connected = $DB->connect($CFG->dbhost, $CFG->dbuser, $CFG->dbpass, $CFG->dbname, $CFG->prefix, $CFG->dboptions); - } Catch (Exception $e) { - $connected = false; - } - - if (!$connected) { - $dberr = ''; - if (debugging('', DEBUG_ALL)) { - if ($dberr = ob_get_contents()) { - $dberr = '

'.$dberr.'

'; - } - ob_end_clean(); - } + $DB->connect($CFG->dbhost, $CFG->dbuser, $CFG->dbpass, $CFG->dbname, $CFG->prefix, $CFG->dboptions); + } catch (moodle_exception $e) { if (empty($CFG->noemailever) and !empty($CFG->emailconnectionerrorsto)) { if (file_exists($CFG->dataroot.'/emailcount')){ - $fp = fopen($CFG->dataroot.'/emailcount', 'r'); - $content = fread($fp, 24); - fclose($fp); + $fp = @fopen($CFG->dataroot.'/emailcount', 'r'); + $content = @fread($fp, 24); + @fclose($fp); if((time() - (int)$content) > 600){ @mail($CFG->emailconnectionerrorsto, 'WARNING: Database connection error: '.$CFG->wwwroot, 'Connection error: '.$CFG->wwwroot); - $fp = fopen($CFG->dataroot.'/emailcount', 'w'); - fwrite($fp, time()); + $fp = @fopen($CFG->dataroot.'/emailcount', 'w'); + @fwrite($fp, time()); } } else { @mail($CFG->emailconnectionerrorsto, 'WARNING: Database connection error: '.$CFG->wwwroot, 'Connection error: '.$CFG->wwwroot); - $fp = fopen($CFG->dataroot.'/emailcount', 'w'); - fwrite($fp, time()); + $fp = @fopen($CFG->dataroot.'/emailcount', 'w'); + @fwrite($fp, time()); } } - throw new dml_exception('dbconnectionfailed', $dberr); - } - if (debugging('', DEBUG_ALL)) { - ob_end_clean(); - } else { - error_reporting($prevdebug); + // rethrow the exception + throw $e; } + $CFG->dbfamily = $DB->get_dbfamily(); // TODO: BC only for now + return true; } diff --git a/lib/setuplib.php b/lib/setuplib.php index 5323e6883a..e0c8dbfc05 100644 --- a/lib/setuplib.php +++ b/lib/setuplib.php @@ -71,7 +71,7 @@ function default_exception_handler($ex) { if ($ex instanceof moodle_exception) { if (!isset($CFG->theme) or !isset($CFG->stylesheets)) { - _print_early_error($ex->errorcode, $ex->module, $ex->a); + _print_early_error($ex->errorcode, $ex->module, $ex->a, $backtrace, $ex->debuginfo); } else { _print_normal_error($ex->errorcode, $ex->module, $ex->a, $ex->link, $backtrace, $ex->debuginfo); } diff --git a/lib/weblib.php b/lib/weblib.php index 2cdc303b8f..b443ef7b5e 100644 --- a/lib/weblib.php +++ b/lib/weblib.php @@ -5925,7 +5925,7 @@ function _print_normal_error($errorcode, $module, $a, $link, $backtrace, $debugi * Internal function - do not use directly!! * This function is used if fatal error occures before the themes are fully initialised (eg. in lib/setup.php) */ -function _print_early_error($errorcode, $module, $a) { +function _print_early_error($errorcode, $module, $a, $backtrace=null, $debuginfo=null) { $message = get_string($errorcode, $module, $a); if ($module === 'error' and strpos($message, '[[') === 0) { //search in moodle file if error specified - needed for backwards compatibility @@ -5958,8 +5958,16 @@ function _print_early_error($errorcode, $module, $a) { border-color:black; background-color:#ffffee; border-style:solid; border-radius: 20px; border-collapse: collapse; width: 80%; -moz-border-radius: 20px; padding: 15px"> '.$message.' - -'; +'; + if (debugging('', DEBUG_DEVELOPER)) { + if ($debuginfo) { + debugging($debuginfo, DEBUG_DEVELOPER, $backtrace); + } else { + notify('Stack trace:'.print_backtrace($backtrace, true), 'notifytiny'); + } + } + + echo ''; die; } -- 2.39.5