Search moodle.org's
Developer Documentation

See Release Notes

  • Bug fixes for general core bugs in 4.2.x will end 22 April 2024 (12 months).
  • Bug fixes for security issues in 4.2.x will end 7 October 2024 (18 months).
  • PHP version: minimum PHP 8.0.0 Note: minimum PHP version has increased since Moodle 4.1. PHP 8.1.x is supported too.
/lib/ -> dmllib.php (source)

Differences Between: [Versions 310 and 402] [Versions 311 and 402] [Versions 39 and 402] [Versions 400 and 402] [Versions 401 and 402]

   1  <?php
   2  
   3  // This file is part of Moodle - http://moodle.org/
   4  //
   5  // Moodle is free software: you can redistribute it and/or modify
   6  // it under the terms of the GNU General Public License as published by
   7  // the Free Software Foundation, either version 3 of the License, or
   8  // (at your option) any later version.
   9  //
  10  // Moodle is distributed in the hope that it will be useful,
  11  // but WITHOUT ANY WARRANTY; without even the implied warranty of
  12  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  13  // GNU General Public License for more details.
  14  //
  15  // You should have received a copy of the GNU General Public License
  16  // along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
  17  
  18  
  19  /**
  20   * This library contains all the Data Manipulation Language (DML) functions
  21   * used to interact with the DB
  22   *
  23   * This library contains all the Data Manipulation Language (DML) functions
  24   * used to interact with the DB. All the dunctions in this library must be
  25   * generic and work against the major number of RDBMS possible. This is the
  26   * list of currently supported and tested DBs: mysql, postresql, mssql, oracle
  27   *
  28   * This library is automatically included by Moodle core so you never need to
  29   * include it yourself.
  30   *
  31   * For more info about the functions available in this library, please visit:
  32   *     http://docs.moodle.org/en/DML_functions
  33   * (feel free to modify, improve and document such page, thanks!)
  34   *
  35   * @package    core
  36   * @category   dml
  37   * @subpackage dml
  38   * @copyright  2008 Petr Skoda (http://skodak.org)
  39   * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  40   */
  41  
  42  defined('MOODLE_INTERNAL') || die();
  43  
  44  // Require the essential
  45  require_once($CFG->libdir.'/dml/moodle_database.php');
  46  
  47  /** Return false if record not found, show debug warning if multiple records found */
  48  define('IGNORE_MISSING', 0);
  49  /** Similar to IGNORE_MISSING but does not show debug warning if multiple records found, not recommended to be used */
  50  define('IGNORE_MULTIPLE', 1);
  51  /** Indicates exactly one record must exist */
  52  define('MUST_EXIST', 2);
  53  
  54  /**
  55   * DML exception class, use instead of throw new \moodle_exception() in dml code.
  56   *
  57   * @package    core
  58   * @category   dml
  59   * @subpackage dml
  60   * @copyright  2008 Petr Skoda (http://skodak.org)
  61   * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  62   */
  63  class dml_exception extends moodle_exception {
  64      /**
  65       * @param string $errorcode The name of the string from error.php to print.
  66       * @param mixed  $a Extra words and phrases that might be required in the error string.
  67       * @param string $debuginfo Optional debugging information.
  68       */
  69      function __construct($errorcode, $a=NULL, $debuginfo=null) {
  70          parent::__construct($errorcode, '', '', $a, $debuginfo);
  71      }
  72  }
  73  
  74  /**
  75   * DML db connection exception - triggered if database not accessible.
  76   *
  77   * @package    core
  78   * @category   dml
  79   * @subpackage dml
  80   * @copyright  2008 Petr Skoda (http://skodak.org)
  81   * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  82   */
  83  class dml_connection_exception extends dml_exception {
  84      /**
  85       * Constructor
  86       * @param string $error Optional debugging information.
  87       */
  88      function __construct($error) {
  89          $errorinfo = $error;
  90          parent::__construct('dbconnectionfailed', NULL, $errorinfo);
  91      }
  92  }
  93  
  94  /**
  95   * DML db session wait exception - triggered when session lock request times out.
  96   *
  97   * @package    core
  98   * @category   dml
  99   * @subpackage dml
 100   * @copyright  2008 Petr Skoda (http://skodak.org)
 101   * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
 102   */
 103  class dml_sessionwait_exception extends dml_exception {
 104      /**
 105       * Constructor
 106       */
 107      function __construct() {
 108          parent::__construct('sessionwaiterr');
 109      }
 110  }
 111  
 112  /**
 113   * DML read exception - triggered by some SQL syntax errors, etc.
 114   *
 115   * @package    core
 116   * @category   dml
 117   * @subpackage dml
 118   * @copyright  2008 Petr Skoda (http://skodak.org)
 119   * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
 120   */
 121  class dml_read_exception extends dml_exception {
 122      /** @var string The name of the string from error.php to print.*/
 123      public $error;
 124      /** @var string The SQL that ran just before this read error.*/
 125      public $sql;
 126      /** @var array The SQL's related parameters.*/
 127      public $params;
 128  
 129      /**
 130       * Constructor
 131       * @param string $error The name of the string from error.php to print.
 132       * @param string $sql The SQL that ran just before this read error.
 133       * @param array $params The SQL's related parameters.(optional)
 134       */
 135      function __construct($error, $sql=null, array $params=null) {
 136          $this->error  = $error;
 137          $this->sql    = $sql;
 138          $this->params = $params;
 139          $errorinfo = $error."\n".$sql."\n[".var_export($params, true).']';
 140          parent::__construct('dmlreadexception', NULL, $errorinfo);
 141      }
 142  }
 143  
 144  /**
 145   * Caused by multiple records found in get_record() call.
 146   *
 147   * @package    core
 148   * @category   dml
 149   * @subpackage dml
 150   * @copyright  2008 Petr Skoda (http://skodak.org)
 151   * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
 152   */
 153  class dml_multiple_records_exception extends dml_exception {
 154      /** @var string The SQL that ran just before this read error.*/
 155      public $sql;
 156      /** @var array The SQL's related parameters.*/
 157      public $params;
 158  
 159      /**
 160       * Constructor
 161       * @param string $sql The SQL that ran just before this read error.
 162       * @param array $params The SQL's related parameters.(optional)
 163       */
 164      function __construct($sql='', array $params=null) {
 165          $errorinfo = $sql."\n[".var_export($params, true).']';
 166          parent::__construct('multiplerecordsfound', null, $errorinfo);
 167      }
 168  }
 169  
 170  /**
 171   * Caused by missing record that is required for normal operation.
 172   *
 173   * @package    core
 174   * @category   dml
 175   * @subpackage dml
 176   * @copyright  2008 Petr Skoda (http://skodak.org)
 177   * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
 178   */
 179  class dml_missing_record_exception extends dml_exception {
 180      /** @var string A table's name.*/
 181      public $tablename;
 182      /** @var string An SQL query.*/
 183      public $sql;
 184      /** @var array The SQL's parameters.*/
 185      public $params;
 186  
 187      /**
 188       * Constructor
 189       * @param string $tablename The table name if known, '' if unknown.
 190       * @param string $sql Optional SQL query.
 191       * @param array $params Optional SQL query's parameters.
 192       */
 193      function __construct($tablename, $sql='', array $params=null) {
 194          if (empty($tablename)) {
 195              $tablename = null;
 196          }
 197          $this->tablename = $tablename;
 198          $this->sql       = $sql;
 199          $this->params    = $params;
 200  
 201          switch ($tablename) {
 202              case null:
 203                  $errcode = 'invalidrecordunknown';
 204                  break;
 205              case 'course':
 206                  $errcode = empty($sql) ? 'invalidcourseid' : 'invalidrecord';
 207                  break;
 208              case 'course_modules':
 209                  $errcode = 'invalidcoursemodule';
 210                  break;
 211              case 'user':
 212                  $errcode = 'invaliduser';
 213                  break;
 214              default:
 215                  $errcode = 'invalidrecord';
 216                  break;
 217          }
 218          $errorinfo = $sql."\n[".var_export($params, true).']';
 219          parent::__construct($errcode, $tablename, $errorinfo);
 220      }
 221  }
 222  
 223  /**
 224   * DML write exception - triggered by some SQL syntax errors, etc.
 225   *
 226   * @package    core
 227   * @category   dml
 228   * @subpackage dml
 229   * @copyright  2008 Petr Skoda (http://skodak.org)
 230   * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
 231   */
 232  class dml_write_exception extends dml_exception {
 233      /** @var string The name of the string from error.php to print.*/
 234      public $error;
 235      /** @var string The SQL that ran just before this write error.*/
 236      public $sql;
 237      /** @var array The SQL's related parameters.*/
 238      public $params;
 239  
 240      /**
 241       * Constructor
 242       * @param string $error The name of the string from error.php to print.
 243       * @param string $sql The SQL that ran just before this write error.
 244       * @param array $params The SQL's related parameters.(optional)
 245       */
 246      function __construct($error, $sql=null, array $params=null) {
 247          $this->error  = $error;
 248          $this->sql    = $sql;
 249          $this->params = $params;
 250          $errorinfo = $error."\n".$sql."\n[".var_export($params, true).']';
 251          parent::__construct('dmlwriteexception', NULL, $errorinfo);
 252      }
 253  }
 254  
 255  /**
 256   * DML transaction exception - triggered by problems related to DB transactions.
 257   *
 258   * @todo MDL-20625 Use the info from $transaction for debugging purposes.
 259   *
 260   * @package    core
 261   * @category   dml
 262   * @subpackage dml
 263   * @copyright  2008 Petr Skoda (http://skodak.org)
 264   * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
 265   */
 266  class dml_transaction_exception extends dml_exception {
 267      /** @var moodle_transaction An instance of a transaction.*/
 268      public $transaction;
 269  
 270      /**
 271       * Constructor
 272       * @param array $debuginfo Optional debugging information.
 273       * @param moodle_transaction $transaction The instance of the transaction.(Optional)
 274       */
 275      function __construct($debuginfo=null, $transaction=null) {
 276          $this->transaction = $transaction; // TODO: MDL-20625 use the info from $transaction for debugging purposes
 277          parent::__construct('dmltransactionexception', NULL, $debuginfo);
 278      }
 279  }
 280  
 281  /**
 282   * Sets up global $DB moodle_database instance
 283   *
 284   * @global stdClass $CFG The global configuration instance.
 285   * @see config.php
 286   * @see config-dist.php
 287   * @global stdClass $DB The global moodle_database instance.
 288   * @return void|bool Returns true when finished setting up $DB. Returns void when $DB has already been set.
 289   */
 290  function setup_DB() {
 291      global $CFG, $DB;
 292  
 293      if (isset($DB)) {
 294          return;
 295      }
 296  
 297      if (!isset($CFG->dbuser)) {
 298          $CFG->dbuser = '';
 299      }
 300  
 301      if (!isset($CFG->dbpass)) {
 302          $CFG->dbpass = '';
 303      }
 304  
 305      if (!isset($CFG->dbname)) {
 306          $CFG->dbname = '';
 307      }
 308  
 309      if (!isset($CFG->dblibrary)) {
 310          $CFG->dblibrary = 'native';
 311          // use new drivers instead of the old adodb driver names
 312          switch ($CFG->dbtype) {
 313              case 'postgres7' :
 314                  $CFG->dbtype = 'pgsql';
 315                  break;
 316  
 317              case 'oci8po':
 318                  $CFG->dbtype = 'oci';
 319                  break;
 320  
 321              case 'mysql' :
 322                  $CFG->dbtype = 'mysqli';
 323                  break;
 324          }
 325      }
 326  
 327      if (!isset($CFG->dboptions)) {
 328          $CFG->dboptions = array();
 329      }
 330  
 331      if (isset($CFG->dbpersist)) {
 332          $CFG->dboptions['dbpersist'] = $CFG->dbpersist;
 333      }
 334  
 335      if (!$DB = moodle_database::get_driver_instance($CFG->dbtype, $CFG->dblibrary)) {
 336          throw new dml_exception('dbdriverproblem', "Unknown driver $CFG->dblibrary/$CFG->dbtype");
 337      }
 338  
 339      try {
 340          $DB->connect($CFG->dbhost, $CFG->dbuser, $CFG->dbpass, $CFG->dbname, $CFG->prefix, $CFG->dboptions);
 341      } catch (moodle_exception $e) {
 342          if (empty($CFG->noemailever) and !empty($CFG->emailconnectionerrorsto)) {
 343              $body = "Connection error: ".$CFG->wwwroot.
 344                  "\n\nInfo:".
 345                  "\n\tError code: ".$e->errorcode.
 346                  "\n\tDebug info: ".$e->debuginfo.
 347                  "\n\tServer: ".$_SERVER['SERVER_NAME']." (".$_SERVER['SERVER_ADDR'].")";
 348              if (file_exists($CFG->dataroot.'/emailcount')){
 349                  $fp = @fopen($CFG->dataroot.'/emailcount', 'r');
 350                  $content = @fread($fp, 24);
 351                  @fclose($fp);
 352                  if((time() - (int)$content) > 600){
 353                      //email directly rather than using messaging
 354                      @mail($CFG->emailconnectionerrorsto,
 355                          'WARNING: Database connection error: '.$CFG->wwwroot,
 356                          $body);
 357                      $fp = @fopen($CFG->dataroot.'/emailcount', 'w');
 358                      @fwrite($fp, time());
 359                  }
 360              } else {
 361                 //email directly rather than using messaging
 362                 @mail($CFG->emailconnectionerrorsto,
 363                      'WARNING: Database connection error: '.$CFG->wwwroot,
 364                      $body);
 365                 $fp = @fopen($CFG->dataroot.'/emailcount', 'w');
 366                 @fwrite($fp, time());
 367              }
 368          }
 369          // rethrow the exception
 370          throw $e;
 371      }
 372  
 373      $CFG->dbfamily = $DB->get_dbfamily(); // TODO: BC only for now
 374  
 375      return true;
 376  }