PageRenderTime 64ms CodeModel.GetById 24ms RepoModel.GetById 0ms app.codeStats 1ms

/lib/dmllib.php

https://bitbucket.org/ceu/moodle_demo
PHP | 2905 lines | 1378 code | 339 blank | 1188 comment | 415 complexity | 03aadfda35e4e1c88134f3388d93e371 MD5 | raw file
Possible License(s): BSD-3-Clause, LGPL-2.0, LGPL-2.1

Large files files are truncated, but you can click here to view the full file

  1. <?php // $Id: dmllib.php,v 1.116.2.38 2011/12/01 12:25:16 moodlerobot Exp $
  2. ///////////////////////////////////////////////////////////////////////////
  3. // //
  4. // NOTICE OF COPYRIGHT //
  5. // //
  6. // Moodle - Modular Object-Oriented Dynamic Learning Environment //
  7. // http://moodle.com //
  8. // //
  9. // Copyright (C) 1999 onwards Martin Dougiamas http://dougiamas.com //
  10. // //
  11. // This program is free software; you can redistribute it and/or modify //
  12. // it under the terms of the GNU General Public License as published by //
  13. // the Free Software Foundation; either version 2 of the License, or //
  14. // (at your option) any later version. //
  15. // //
  16. // This program is distributed in the hope that it will be useful, //
  17. // but WITHOUT ANY WARRANTY; without even the implied warranty of //
  18. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the //
  19. // GNU General Public License for more details: //
  20. // //
  21. // http://www.gnu.org/copyleft/gpl.html //
  22. // //
  23. ///////////////////////////////////////////////////////////////////////////
  24. /// This library contains all the Data Manipulation Language (DML) functions
  25. /// used to interact with the DB. All the dunctions in this library must be
  26. /// generic and work against the major number of RDBMS possible. This is the
  27. /// list of currently supported and tested DBs: mysql, postresql, mssql, oracle
  28. /// This library is automatically included by Moodle core so you never need to
  29. /// include it yourself.
  30. /// For more info about the functions available in this library, please visit:
  31. /// http://docs.moodle.org/19/en/DML_functions
  32. /// (feel free to modify, improve and document such page, thanks!)
  33. /// GLOBAL CONSTANTS /////////////////////////////////////////////////////////
  34. $empty_rs_cache = array(); // Keeps copies of the recordsets used in one invocation
  35. $metadata_cache = array(); // Kereeps copies of the MetaColumns() for each table used in one invocations
  36. $rcache = new StdClass; // Cache simple get_record results
  37. $rcache->data = array();
  38. $rcache->hits = 0;
  39. $rcache->misses = 0;
  40. /// FUNCTIONS FOR DATABASE HANDLING ////////////////////////////////
  41. /**
  42. * Execute a given sql command string
  43. *
  44. * Completely general function - it just runs some SQL and reports success.
  45. *
  46. * @uses $db
  47. * @param string $command The sql string you wish to be executed.
  48. * @param bool $feedback Set this argument to true if the results generated should be printed. Default is true.
  49. * @return bool success
  50. */
  51. function execute_sql($command, $feedback=true) {
  52. /// Completely general function - it just runs some SQL and reports success.
  53. global $db, $CFG;
  54. $olddebug = $db->debug;
  55. if (!$feedback) {
  56. $db->debug = false;
  57. }
  58. if ($CFG->version >= 2006101007) { //Look for trailing ; from Moodle 1.7.0
  59. $command = trim($command);
  60. /// If the trailing ; is there, fix and warn!
  61. if (substr($command, strlen($command)-1, 1) == ';') {
  62. /// One noticeable exception, Oracle PL/SQL blocks require ending in ";"
  63. if ($CFG->dbfamily == 'oracle' && substr($command, -4) == 'END;') {
  64. /// Nothing to fix/warn. The command is one PL/SQL block, so it's ok.
  65. } else {
  66. $command = trim($command, ';');
  67. debugging('Warning. Avoid to end your SQL commands with a trailing ";".', DEBUG_DEVELOPER);
  68. }
  69. }
  70. }
  71. $empty_rs_cache = array(); // Clear out the cache, just in case changes were made to table structures
  72. if (defined('MDL_PERFDB')) { global $PERF ; $PERF->dbqueries++; };
  73. $rs = $db->Execute($command);
  74. $db->debug = $olddebug;
  75. if ($rs) {
  76. if ($feedback) {
  77. notify(get_string('success'), 'notifysuccess');
  78. }
  79. return true;
  80. } else {
  81. if ($feedback) {
  82. notify('<strong>' . get_string('error') . '</strong>');
  83. }
  84. // these two may go to difference places
  85. debugging($db->ErrorMsg() .'<br /><br />'. s($command));
  86. if (!empty($CFG->dblogerror)) {
  87. $debug=array_shift(debug_backtrace());
  88. error_log("SQL ".$db->ErrorMsg()." in {$debug['file']} on line {$debug['line']}. STATEMENT: $command");
  89. }
  90. return false;
  91. }
  92. }
  93. /**
  94. * on DBs that support it, switch to transaction mode and begin a transaction
  95. * you'll need to ensure you call commit_sql() or your changes *will* be lost.
  96. *
  97. * Now using ADOdb standard transactions. Some day, we should switch to
  98. * Smart Transactions (http://phplens.com/adodb/tutorial.smart.transactions.html)
  99. * as they autodetect errors and are nestable and easier to write
  100. *
  101. * this is _very_ useful for massive updates
  102. */
  103. function begin_sql() {
  104. global $db;
  105. $db->BeginTrans();
  106. return true;
  107. }
  108. /**
  109. * on DBs that support it, commit the transaction
  110. *
  111. * Now using ADOdb standard transactions. Some day, we should switch to
  112. * Smart Transactions (http://phplens.com/adodb/tutorial.smart.transactions.html)
  113. * as they autodetect errors and are nestable and easier to write
  114. */
  115. function commit_sql() {
  116. global $db;
  117. $db->CommitTrans();
  118. return true;
  119. }
  120. /**
  121. * on DBs that support it, rollback the transaction
  122. *
  123. * Now using ADOdb standard transactions. Some day, we should switch to
  124. * Smart Transactions (http://phplens.com/adodb/tutorial.smart.transactions.html)
  125. * as they autodetect errors and are nestable and easier to write
  126. */
  127. function rollback_sql() {
  128. global $db;
  129. $db->RollbackTrans();
  130. return true;
  131. }
  132. /**
  133. * returns db specific uppercase function
  134. * @deprecated Moodle 1.7 because all the RDBMS use upper()
  135. */
  136. function db_uppercase() {
  137. return "upper";
  138. }
  139. /**
  140. * returns db specific lowercase function
  141. * @deprecated Moodle 1.7 because all the RDBMS use lower()
  142. */
  143. function db_lowercase() {
  144. return "lower";
  145. }
  146. /**
  147. * Run an arbitrary sequence of semicolon-delimited SQL commands
  148. *
  149. * Assumes that the input text (file or string) consists of
  150. * a number of SQL statements ENDING WITH SEMICOLONS. The
  151. * semicolons MUST be the last character in a line.
  152. * Lines that are blank or that start with "#" or "--" (postgres) are ignored.
  153. * Only tested with mysql dump files (mysqldump -p -d moodle)
  154. *
  155. * @uses $CFG
  156. *
  157. * @deprecated Moodle 1.7 use the new XMLDB stuff in lib/ddllib.php
  158. *
  159. * @param string $sqlfile The path where a file with sql commands can be found on the server.
  160. * @param string $sqlstring If no path is supplied then a string with semicolon delimited sql
  161. * commands can be supplied in this argument.
  162. * @return bool Returns true if databse was modified successfully.
  163. */
  164. function modify_database($sqlfile='', $sqlstring='') {
  165. global $CFG;
  166. if ($CFG->version > 2006101007) {
  167. debugging('Function modify_database() is deprecated. Replace it with the new XMLDB stuff.', DEBUG_DEVELOPER);
  168. }
  169. $success = true; // Let's be optimistic
  170. if (!empty($sqlfile)) {
  171. if (!is_readable($sqlfile)) {
  172. $success = false;
  173. echo '<p>Tried to modify database, but "'. $sqlfile .'" doesn\'t exist!</p>';
  174. return $success;
  175. } else {
  176. $lines = file($sqlfile);
  177. }
  178. } else {
  179. $sqlstring = trim($sqlstring);
  180. if ($sqlstring{strlen($sqlstring)-1} != ";") {
  181. $sqlstring .= ";"; // add it in if it's not there.
  182. }
  183. $lines[] = $sqlstring;
  184. }
  185. $command = '';
  186. foreach ($lines as $line) {
  187. $line = rtrim($line);
  188. $length = strlen($line);
  189. if ($length and $line[0] <> '#' and $line[0].$line[1] <> '--') {
  190. if (substr($line, $length-1, 1) == ';') {
  191. $line = substr($line, 0, $length-1); // strip ;
  192. $command .= $line;
  193. $command = str_replace('prefix_', $CFG->prefix, $command); // Table prefixes
  194. if (! execute_sql($command)) {
  195. $success = false;
  196. }
  197. $command = '';
  198. } else {
  199. $command .= $line;
  200. }
  201. }
  202. }
  203. return $success;
  204. }
  205. /// GENERIC FUNCTIONS TO CHECK AND COUNT RECORDS ////////////////////////////////////////
  206. /**
  207. * Test whether a record exists in a table where all the given fields match the given values.
  208. *
  209. * The record to test is specified by giving up to three fields that must
  210. * equal the corresponding values.
  211. *
  212. * @uses $CFG
  213. * @param string $table The table to check.
  214. * @param string $field1 the first field to check (optional).
  215. * @param string $value1 the value field1 must have (requred if field1 is given, else optional).
  216. * @param string $field2 the second field to check (optional).
  217. * @param string $value2 the value field2 must have (requred if field2 is given, else optional).
  218. * @param string $field3 the third field to check (optional).
  219. * @param string $value3 the value field3 must have (requred if field3 is given, else optional).
  220. * @return bool true if a matching record exists, else false.
  221. */
  222. function record_exists($table, $field1='', $value1='', $field2='', $value2='', $field3='', $value3='') {
  223. global $CFG;
  224. $select = where_clause($field1, $value1, $field2, $value2, $field3, $value3);
  225. return record_exists_sql('SELECT * FROM '. $CFG->prefix . $table .' '. $select);
  226. }
  227. /**
  228. * Test whether any records exists in a table which match a particular WHERE clause.
  229. *
  230. * @uses $CFG
  231. * @param string $table The database table to be checked against.
  232. * @param string $select A fragment of SQL to be used in a WHERE clause in the SQL call.
  233. * @return bool true if a matching record exists, else false.
  234. */
  235. function record_exists_select($table, $select='') {
  236. global $CFG;
  237. if ($select) {
  238. $select = 'WHERE '.$select;
  239. }
  240. return record_exists_sql('SELECT * FROM '. $CFG->prefix . $table . ' ' . $select);
  241. }
  242. /**
  243. * Test whether a SQL SELECT statement returns any records.
  244. *
  245. * This function returns true if the SQL statement executes
  246. * without any errors and returns at least one record.
  247. *
  248. * @param string $sql The SQL statement to execute.
  249. * @return bool true if the SQL executes without errors and returns at least one record.
  250. */
  251. function record_exists_sql($sql) {
  252. $limitfrom = 0; /// Number of records to skip
  253. $limitnum = 1; /// Number of records to retrieve
  254. if (!$rs = get_recordset_sql($sql, $limitfrom, $limitnum)) {
  255. return false;
  256. }
  257. if (rs_EOF($rs)) {
  258. $result = false;
  259. } else {
  260. $result = true;
  261. }
  262. rs_close($rs);
  263. return $result;
  264. }
  265. /**
  266. * Count the records in a table where all the given fields match the given values.
  267. *
  268. * @uses $CFG
  269. * @param string $table The table to query.
  270. * @param string $field1 the first field to check (optional).
  271. * @param string $value1 the value field1 must have (requred if field1 is given, else optional).
  272. * @param string $field2 the second field to check (optional).
  273. * @param string $value2 the value field2 must have (requred if field2 is given, else optional).
  274. * @param string $field3 the third field to check (optional).
  275. * @param string $value3 the value field3 must have (requred if field3 is given, else optional).
  276. * @return int The count of records returned from the specified criteria.
  277. */
  278. function count_records($table, $field1='', $value1='', $field2='', $value2='', $field3='', $value3='') {
  279. global $CFG;
  280. $select = where_clause($field1, $value1, $field2, $value2, $field3, $value3);
  281. return count_records_sql('SELECT COUNT(*) FROM '. $CFG->prefix . $table .' '. $select);
  282. }
  283. /**
  284. * Count the records in a table which match a particular WHERE clause.
  285. *
  286. * @uses $CFG
  287. * @param string $table The database table to be checked against.
  288. * @param string $select A fragment of SQL to be used in a WHERE clause in the SQL call.
  289. * @param string $countitem The count string to be used in the SQL call. Default is COUNT(*).
  290. * @return int The count of records returned from the specified criteria.
  291. */
  292. function count_records_select($table, $select='', $countitem='COUNT(*)') {
  293. global $CFG;
  294. if ($select) {
  295. $select = 'WHERE '.$select;
  296. }
  297. return count_records_sql('SELECT '. $countitem .' FROM '. $CFG->prefix . $table .' '. $select);
  298. }
  299. /**
  300. * Get the result of a SQL SELECT COUNT(...) query.
  301. *
  302. * Given a query that counts rows, return that count. (In fact,
  303. * given any query, return the first field of the first record
  304. * returned. However, this method should only be used for the
  305. * intended purpose.) If an error occurrs, 0 is returned.
  306. *
  307. * @uses $CFG
  308. * @uses $db
  309. * @param string $sql The SQL string you wish to be executed.
  310. * @return int the count. If an error occurrs, 0 is returned.
  311. */
  312. function count_records_sql($sql) {
  313. $rs = get_recordset_sql($sql);
  314. if (is_object($rs) and is_array($rs->fields)) {
  315. return reset($rs->fields);
  316. } else {
  317. return 0;
  318. }
  319. }
  320. /// GENERIC FUNCTIONS TO GET, INSERT, OR UPDATE DATA ///////////////////////////////////
  321. /**
  322. * Get a single record as an object
  323. *
  324. * @uses $CFG
  325. * @param string $table The table to select from.
  326. * @param string $field1 the first field to check (optional).
  327. * @param string $value1 the value field1 must have (requred if field1 is given, else optional).
  328. * @param string $field2 the second field to check (optional).
  329. * @param string $value2 the value field2 must have (requred if field2 is given, else optional).
  330. * @param string $field3 the third field to check (optional).
  331. * @param string $value3 the value field3 must have (requred if field3 is given, else optional).
  332. * @return mixed a fieldset object containing the first mathcing record, or false if none found.
  333. */
  334. function get_record($table, $field1, $value1, $field2='', $value2='', $field3='', $value3='', $fields='*') {
  335. global $CFG;
  336. // Check to see whether this record is eligible for caching (fields=*, only condition is id)
  337. $docache = false;
  338. if (!empty($CFG->rcache) && $CFG->rcache === true && $field1=='id' && !$field2 && !$field3 && $fields=='*') {
  339. $docache = true;
  340. // If it's in the cache, return it
  341. $cached = rcache_getforfill($table, $value1);
  342. if (!empty($cached)) {
  343. return $cached;
  344. }
  345. }
  346. $select = where_clause($field1, $value1, $field2, $value2, $field3, $value3);
  347. $record = get_record_sql('SELECT '.$fields.' FROM '. $CFG->prefix . $table .' '. $select);
  348. // If we're caching records, store this one
  349. // (supposing we got something - we don't cache failures)
  350. if ($docache) {
  351. if ($record !== false) {
  352. rcache_set($table, $value1, $record);
  353. } else {
  354. rcache_releaseforfill($table, $value1);
  355. }
  356. }
  357. return $record;
  358. }
  359. /**
  360. * Get a single record as an object using an SQL statement
  361. *
  362. * The SQL statement should normally only return one record. In debug mode
  363. * you will get a warning if more record is returned (unless you
  364. * set $expectmultiple to true). In non-debug mode, it just returns
  365. * the first record.
  366. *
  367. * @uses $CFG
  368. * @uses $db
  369. * @param string $sql The SQL string you wish to be executed, should normally only return one record.
  370. * @param bool $expectmultiple If the SQL cannot be written to conveniently return just one record,
  371. * set this to true to hide the debug message.
  372. * @param bool $nolimit sometimes appending ' LIMIT 1' to the SQL causes an error. Set this to true
  373. * to stop your SQL being modified. This argument should probably be deprecated.
  374. * @return Found record as object. False if not found or error
  375. */
  376. function get_record_sql($sql, $expectmultiple=false, $nolimit=false) {
  377. global $CFG;
  378. /// Default situation
  379. $limitfrom = 0; /// Number of records to skip
  380. $limitnum = 1; /// Number of records to retrieve
  381. /// Only a few uses of the 2nd and 3rd parameter have been found
  382. /// I think that we should avoid to use them completely, one
  383. /// record is one record, and everything else should return error.
  384. /// So the proposal is to change all the uses, (4-5 inside Moodle
  385. /// Core), drop them from the definition and delete the next two
  386. /// "if" sentences. (eloy, 2006-08-19)
  387. if ($nolimit) {
  388. $limitfrom = 0;
  389. $limitnum = 0;
  390. } else if ($expectmultiple) {
  391. $limitfrom = 0;
  392. $limitnum = 1;
  393. } else if (debugging('', DEBUG_DEVELOPER)) {
  394. // Debugging mode - don't use a limit of 1, but do change the SQL, because sometimes that
  395. // causes errors, and in non-debug mode you don't see the error message and it is
  396. // impossible to know what's wrong.
  397. $limitfrom = 0;
  398. $limitnum = 100;
  399. }
  400. if (!$rs = get_recordset_sql($sql, $limitfrom, $limitnum)) {
  401. return false;
  402. }
  403. $recordcount = $rs->RecordCount();
  404. if ($recordcount == 0) { // Found no records
  405. return false;
  406. } else if ($recordcount == 1) { // Found one record
  407. /// DIRTY HACK to retrieve all the ' ' (1 space) fields converted back
  408. /// to '' (empty string) for Oracle. It's the only way to work with
  409. /// all those NOT NULL DEFAULT '' fields until we definitively delete them
  410. if ($CFG->dbfamily == 'oracle') {
  411. array_walk($rs->fields, 'onespace2empty');
  412. }
  413. /// End of DIRTY HACK
  414. return (object)$rs->fields;
  415. } else { // Error: found more than one record
  416. notify('Error: Turn off debugging to hide this error.');
  417. notify($sql . '(with limits ' . $limitfrom . ', ' . $limitnum . ')');
  418. if ($records = $rs->GetAssoc(true)) {
  419. notify('Found more than one record in get_record_sql !');
  420. print_object($records);
  421. } else {
  422. notify('Very strange error in get_record_sql !');
  423. print_object($rs);
  424. }
  425. print_continue("$CFG->wwwroot/$CFG->admin/config.php");
  426. }
  427. }
  428. /**
  429. * Gets one record from a table, as an object
  430. *
  431. * @uses $CFG
  432. * @param string $table The database table to be checked against.
  433. * @param string $select A fragment of SQL to be used in a where clause in the SQL call.
  434. * @param string $fields A comma separated list of fields to be returned from the chosen table.
  435. * @return object|false Returns an array of found records (as objects) or false if no records or error occured.
  436. */
  437. function get_record_select($table, $select='', $fields='*') {
  438. global $CFG;
  439. if ($select) {
  440. $select = 'WHERE '. $select;
  441. }
  442. return get_record_sql('SELECT '. $fields .' FROM '. $CFG->prefix . $table .' '. $select);
  443. }
  444. /**
  445. * Get a number of records as an ADODB RecordSet.
  446. *
  447. * Selects records from the table $table.
  448. *
  449. * If specified, only records where the field $field has value $value are retured.
  450. *
  451. * If specified, the results will be sorted as specified by $sort. This
  452. * is added to the SQL as "ORDER BY $sort". Example values of $sort
  453. * mightbe "time ASC" or "time DESC".
  454. *
  455. * If $fields is specified, only those fields are returned.
  456. *
  457. * Since this method is a little less readable, use of it should be restricted to
  458. * code where it's possible there might be large datasets being returned. For known
  459. * small datasets use get_records - it leads to simpler code.
  460. *
  461. * If you only want some of the records, specify $limitfrom and $limitnum.
  462. * The query will skip the first $limitfrom records (according to the sort
  463. * order) and then return the next $limitnum records. If either of $limitfrom
  464. * or $limitnum is specified, both must be present.
  465. *
  466. * The return value is an ADODB RecordSet object
  467. * @link http://phplens.com/adodb/reference.functions.adorecordset.html
  468. * if the query succeeds. If an error occurrs, false is returned.
  469. *
  470. * @param string $table the table to query.
  471. * @param string $field a field to check (optional).
  472. * @param string $value the value the field must have (requred if field1 is given, else optional).
  473. * @param string $sort an order to sort the results in (optional, a valid SQL ORDER BY parameter).
  474. * @param string $fields a comma separated list of fields to return (optional, by default all fields are returned).
  475. * @param int $limitfrom return a subset of records, starting at this point (optional, required if $limitnum is set).
  476. * @param int $limitnum return a subset comprising this many records (optional, required if $limitfrom is set).
  477. * @return mixed an ADODB RecordSet object, or false if an error occured.
  478. */
  479. function get_recordset($table, $field='', $value='', $sort='', $fields='*', $limitfrom='', $limitnum='') {
  480. if ($field) {
  481. $value = sql_magic_quotes_hack($value);
  482. $select = "$field = '$value'";
  483. } else {
  484. $select = '';
  485. }
  486. return get_recordset_select($table, $select, $sort, $fields, $limitfrom, $limitnum);
  487. }
  488. /**
  489. * Get a number of records as an ADODB RecordSet.
  490. *
  491. * If given, $select is used as the SELECT parameter in the SQL query,
  492. * otherwise all records from the table are returned.
  493. *
  494. * Other arguments and the return type as for @see function get_recordset.
  495. *
  496. * @uses $CFG
  497. * @param string $table the table to query.
  498. * @param string $select A fragment of SQL to be used in a where clause in the SQL call.
  499. * @param string $sort an order to sort the results in (optional, a valid SQL ORDER BY parameter).
  500. * @param string $fields a comma separated list of fields to return (optional, by default all fields are returned).
  501. * @param int $limitfrom return a subset of records, starting at this point (optional, required if $limitnum is set).
  502. * @param int $limitnum return a subset comprising this many records (optional, required if $limitfrom is set).
  503. * @return mixed an ADODB RecordSet object, or false if an error occured.
  504. */
  505. function get_recordset_select($table, $select='', $sort='', $fields='*', $limitfrom='', $limitnum='') {
  506. global $CFG;
  507. if ($select) {
  508. $select = ' WHERE '. $select;
  509. }
  510. if ($sort) {
  511. $sort = ' ORDER BY '. $sort;
  512. }
  513. return get_recordset_sql('SELECT '. $fields .' FROM '. $CFG->prefix . $table . $select . $sort, $limitfrom, $limitnum);
  514. }
  515. /**
  516. * Get a number of records as an ADODB RecordSet.
  517. *
  518. * Only records where $field takes one of the values $values are returned.
  519. * $values should be a comma-separated list of values, for example "4,5,6,10"
  520. * or "'foo','bar','baz'".
  521. *
  522. * Other arguments and the return type as for @see function get_recordset.
  523. *
  524. * @param string $table the table to query.
  525. * @param string $field a field to check (optional).
  526. * @param string $values comma separated list of values the field must have (requred if field is given, else optional).
  527. * @param string $sort an order to sort the results in (optional, a valid SQL ORDER BY parameter).
  528. * @param string $fields a comma separated list of fields to return (optional, by default all fields are returned).
  529. * @param int $limitfrom return a subset of records, starting at this point (optional, required if $limitnum is set).
  530. * @param int $limitnum return a subset comprising this many records (optional, required if $limitfrom is set).
  531. * @return mixed an ADODB RecordSet object, or false if an error occured.
  532. */
  533. function get_recordset_list($table, $field='', $values='', $sort='', $fields='*', $limitfrom='', $limitnum='') {
  534. if ($field) {
  535. $select = "$field IN ($values)";
  536. } else {
  537. $select = '';
  538. }
  539. return get_recordset_select($table, $select, $sort, $fields, $limitfrom, $limitnum);
  540. }
  541. /**
  542. * Get a number of records as an ADODB RecordSet. $sql must be a complete SQL query.
  543. * Since this method is a little less readable, use of it should be restricted to
  544. * code where it's possible there might be large datasets being returned. For known
  545. * small datasets use get_records_sql - it leads to simpler code.
  546. *
  547. * The return type is as for @see function get_recordset.
  548. *
  549. * @uses $CFG
  550. * @uses $db
  551. * @param string $sql the SQL select query to execute.
  552. * @param int $limitfrom return a subset of records, starting at this point (optional, required if $limitnum is set).
  553. * @param int $limitnum return a subset comprising this many records (optional, required if $limitfrom is set).
  554. * @return mixed an ADODB RecordSet object, or false if an error occured.
  555. */
  556. function get_recordset_sql($sql, $limitfrom=null, $limitnum=null) {
  557. global $CFG, $db;
  558. if (empty($db)) {
  559. return false;
  560. }
  561. /// Temporary hack as part of phasing out all access to obsolete user tables XXX
  562. if (!empty($CFG->rolesactive)) {
  563. if (strpos($sql, ' '.$CFG->prefix.'user_students ') ||
  564. strpos($sql, ' '.$CFG->prefix.'user_teachers ') ||
  565. strpos($sql, ' '.$CFG->prefix.'user_coursecreators ') ||
  566. strpos($sql, ' '.$CFG->prefix.'user_admins ')) {
  567. if (debugging()) { var_dump(debug_backtrace()); }
  568. error('This SQL relies on obsolete tables! Your code must be fixed by a developer.');
  569. }
  570. }
  571. if (defined('MDL_PERFDB')) { global $PERF ; $PERF->dbqueries++; };
  572. if ($limitfrom || $limitnum) {
  573. ///Special case, 0 must be -1 for ADOdb
  574. $limitfrom = empty($limitfrom) ? -1 : $limitfrom;
  575. $limitnum = empty($limitnum) ? -1 : $limitnum;
  576. $rs = $db->SelectLimit($sql, $limitnum, $limitfrom);
  577. } else {
  578. $rs = $db->Execute($sql);
  579. }
  580. if (!$rs) {
  581. debugging($db->ErrorMsg() .'<br /><br />'. s($sql));
  582. if (!empty($CFG->dblogerror)) {
  583. $debug=array_shift(debug_backtrace());
  584. error_log("SQL ".$db->ErrorMsg()." in {$debug['file']} on line {$debug['line']}. STATEMENT: $sql with limits ($limitfrom, $limitnum)");
  585. }
  586. return false;
  587. }
  588. return $rs;
  589. }
  590. /**
  591. * Utility function used by the following 4 methods. Note that for this to work, the first column
  592. * in the recordset must contain unique values, as it is used as the key to the associative array.
  593. *
  594. * @param object an ADODB RecordSet object.
  595. * @return mixed mixed an array of objects, or false if an error occured or the RecordSet was empty.
  596. */
  597. function recordset_to_array($rs) {
  598. global $CFG;
  599. $debugging = debugging('', DEBUG_DEVELOPER);
  600. if ($rs && !rs_EOF($rs)) {
  601. $objects = array();
  602. /// First of all, we are going to get the name of the first column
  603. /// to introduce it back after transforming the recordset to assoc array
  604. /// See http://docs.moodle.org/19/en/XMLDB_Problems, fetch mode problem.
  605. $firstcolumn = $rs->FetchField(0);
  606. /// Get the whole associative array
  607. if ($records = $rs->GetAssoc(true)) {
  608. foreach ($records as $key => $record) {
  609. /// Really DIRTY HACK for Oracle, but it's the only way to make it work
  610. /// until we got all those NOT NULL DEFAULT '' out from Moodle
  611. if ($CFG->dbfamily == 'oracle') {
  612. array_walk($record, 'onespace2empty');
  613. }
  614. /// End of DIRTY HACK
  615. $record[$firstcolumn->name] = $key;/// Re-add the assoc field
  616. if ($debugging && array_key_exists($key, $objects)) {
  617. debugging("Did you remember to make the first column something unique in your call to get_records? Duplicate value '$key' found in column '".$firstcolumn->name."'.", DEBUG_DEVELOPER);
  618. }
  619. $objects[$key] = (object) $record; /// To object
  620. }
  621. return $objects;
  622. /// Fallback in case we only have 1 field in the recordset. MDL-5877
  623. } else if ($rs->_numOfFields == 1 && $records = $rs->GetRows()) {
  624. foreach ($records as $key => $record) {
  625. /// Really DIRTY HACK for Oracle, but it's the only way to make it work
  626. /// until we got all those NOT NULL DEFAULT '' out from Moodle
  627. if ($CFG->dbfamily == 'oracle') {
  628. array_walk($record, 'onespace2empty');
  629. }
  630. /// End of DIRTY HACK
  631. if ($debugging && array_key_exists($record[$firstcolumn->name], $objects)) {
  632. debugging("Did you remember to make the first column something unique in your call to get_records? Duplicate value '".$record[$firstcolumn->name]."' found in column '".$firstcolumn->name."'.", DEBUG_DEVELOPER);
  633. }
  634. $objects[$record[$firstcolumn->name]] = (object) $record; /// The key is the first column value (like Assoc)
  635. }
  636. return $objects;
  637. } else {
  638. return false;
  639. }
  640. } else {
  641. return false;
  642. }
  643. }
  644. /**
  645. * This function is used to get the current record from the recordset. It
  646. * doesn't advance the recordset position. You'll need to do that by
  647. * using the rs_next_record($recordset) function.
  648. * @param ADORecordSet the recordset to fetch current record from
  649. * @return ADOFetchObj the object containing the fetched information
  650. */
  651. function rs_fetch_record(&$rs) {
  652. global $CFG;
  653. if (!$rs) {
  654. debugging('Incorrect $rs used!', DEBUG_DEVELOPER);
  655. return false;
  656. }
  657. $rec = $rs->FetchObj(); //Retrieve record as object without advance the pointer
  658. if ($rs->EOF) { //FetchObj requires manual checking of EOF to detect if it's the last record
  659. $rec = false;
  660. } else {
  661. /// DIRTY HACK to retrieve all the ' ' (1 space) fields converted back
  662. /// to '' (empty string) for Oracle. It's the only way to work with
  663. /// all those NOT NULL DEFAULT '' fields until we definetively delete them
  664. if ($CFG->dbfamily == 'oracle') {
  665. $recarr = (array)$rec; /// Cast to array
  666. array_walk($recarr, 'onespace2empty');
  667. $rec = (object)$recarr;/// Cast back to object
  668. }
  669. /// End DIRTY HACK
  670. }
  671. return $rec;
  672. }
  673. /**
  674. * This function is used to advance the pointer of the recordset
  675. * to its next position/record.
  676. * @param ADORecordSet the recordset to be moved to the next record
  677. * @return boolean true if the movement was successful and false if not (end of recordset)
  678. */
  679. function rs_next_record(&$rs) {
  680. if (!$rs) {
  681. debugging('Incorrect $rs used!', DEBUG_DEVELOPER);
  682. return false;
  683. }
  684. return $rs->MoveNext(); //Move the pointer to the next record
  685. }
  686. /**
  687. * This function is used to get the current record from the recordset. It
  688. * does advance the recordset position.
  689. * This is the prefered way to iterate over recordsets with code blocks like this:
  690. *
  691. * $rs = get_recordset('SELECT .....');
  692. * while ($rec = rs_fetch_next_record($rs)) {
  693. * /// Perform actions with the $rec record here
  694. * }
  695. * rs_close($rs); /// Close the recordset if not used anymore. Saves memory (optional but recommended).
  696. *
  697. * @param ADORecordSet the recordset to fetch current record from
  698. * @return mixed ADOFetchObj the object containing the fetched information or boolean false if no record (end of recordset)
  699. */
  700. function rs_fetch_next_record(&$rs) {
  701. global $CFG;
  702. if (!$rs) {
  703. debugging('Incorrect $rs used!', DEBUG_DEVELOPER);
  704. return false;
  705. }
  706. $rec = false;
  707. $recarr = $rs->FetchRow(); //Retrieve record as object without advance the pointer. It's quicker that FetchNextObj()
  708. if ($recarr) {
  709. /// DIRTY HACK to retrieve all the ' ' (1 space) fields converted back
  710. /// to '' (empty string) for Oracle. It's the only way to work with
  711. /// all those NOT NULL DEFAULT '' fields until we definetively delete them
  712. if ($CFG->dbfamily == 'oracle') {
  713. array_walk($recarr, 'onespace2empty');
  714. }
  715. /// End DIRTY HACK
  716. /// Cast array to object
  717. $rec = (object)$recarr;
  718. }
  719. return $rec;
  720. }
  721. /**
  722. * Returns true if no more records found
  723. * @param ADORecordSet the recordset
  724. * @return bool
  725. */
  726. function rs_EOF($rs) {
  727. if (!$rs) {
  728. debugging('Incorrect $rs used!', DEBUG_DEVELOPER);
  729. return true;
  730. }
  731. return $rs->EOF;
  732. }
  733. /**
  734. * This function closes the recordset, freeing all the memory and associated resources.
  735. * Note that, once closed, the recordset must not be used anymore along the request.
  736. * Saves memory (optional but recommended).
  737. * @param ADORecordSet the recordset to be closed
  738. * @return void
  739. */
  740. function rs_close(&$rs) {
  741. if (!$rs) {
  742. debugging('Incorrect $rs used!', DEBUG_DEVELOPER);
  743. return;
  744. }
  745. $rs->Close();
  746. }
  747. /**
  748. * This function is used to convert all the Oracle 1-space defaults to the empty string
  749. * like a really DIRTY HACK to allow it to work better until all those NOT NULL DEFAULT ''
  750. * fields will be out from Moodle.
  751. * @param string the string to be converted to '' (empty string) if it's ' ' (one space)
  752. * @param mixed the key of the array in case we are using this function from array_walk,
  753. * defaults to null for other (direct) uses
  754. * @return boolean always true (the converted variable is returned by reference)
  755. */
  756. function onespace2empty(&$item, $key=null) {
  757. $item = $item == ' ' ? '' : $item;
  758. return true;
  759. }
  760. ///End DIRTY HACK
  761. /**
  762. * Get a number of records as an array of objects.
  763. *
  764. * If the query succeeds and returns at least one record, the
  765. * return value is an array of objects, one object for each
  766. * record found. The array key is the value from the first
  767. * column of the result set. The object associated with that key
  768. * has a member variable for each column of the results.
  769. *
  770. * @param string $table the table to query.
  771. * @param string $field a field to check (optional).
  772. * @param string $value the value the field must have (requred if field1 is given, else optional).
  773. * @param string $sort an order to sort the results in (optional, a valid SQL ORDER BY parameter).
  774. * @param string $fields a comma separated list of fields to return (optional, by default
  775. * all fields are returned). The first field will be used as key for the
  776. * array so must be a unique field such as 'id'.
  777. * @param int $limitfrom return a subset of records, starting at this point (optional, required if $limitnum is set).
  778. * @param int $limitnum return a subset comprising this many records (optional, required if $limitfrom is set).
  779. * @return mixed an array of objects, or false if no records were found or an error occured.
  780. */
  781. function get_records($table, $field='', $value='', $sort='', $fields='*', $limitfrom='', $limitnum='') {
  782. $rs = get_recordset($table, $field, $value, $sort, $fields, $limitfrom, $limitnum);
  783. return recordset_to_array($rs);
  784. }
  785. /**
  786. * Get a number of records as an array of objects.
  787. *
  788. * Return value as for @see function get_records.
  789. *
  790. * @param string $table the table to query.
  791. * @param string $select A fragment of SQL to be used in a where clause in the SQL call.
  792. * @param string $sort an order to sort the results in (optional, a valid SQL ORDER BY parameter).
  793. * @param string $fields a comma separated list of fields to return
  794. * (optional, by default all fields are returned). The first field will be used as key for the
  795. * array so must be a unique field such as 'id'.
  796. * @param int $limitfrom return a subset of records, starting at this point (optional, required if $limitnum is set).
  797. * @param int $limitnum return a subset comprising this many records (optional, required if $limitfrom is set).
  798. * @return mixed an array of objects, or false if no records were found or an error occured.
  799. */
  800. function get_records_select($table, $select='', $sort='', $fields='*', $limitfrom='', $limitnum='') {
  801. $rs = get_recordset_select($table, $select, $sort, $fields, $limitfrom, $limitnum);
  802. return recordset_to_array($rs);
  803. }
  804. /**
  805. * Get a number of records as an array of objects.
  806. *
  807. * Return value as for @see function get_records.
  808. *
  809. * @param string $table The database table to be checked against.
  810. * @param string $field The field to search
  811. * @param string $values Comma separated list of possible value
  812. * @param string $sort Sort order (as valid SQL sort parameter)
  813. * @param string $fields A comma separated list of fields to be returned from the chosen table. If specified,
  814. * the first field should be a unique one such as 'id' since it will be used as a key in the associative
  815. * array.
  816. * @return mixed an array of objects, or false if no records were found or an error occured.
  817. */
  818. function get_records_list($table, $field='', $values='', $sort='', $fields='*', $limitfrom='', $limitnum='') {
  819. $rs = get_recordset_list($table, $field, $values, $sort, $fields, $limitfrom, $limitnum);
  820. return recordset_to_array($rs);
  821. }
  822. /**
  823. * Get a number of records as an array of objects.
  824. *
  825. * Return value as for @see function get_records.
  826. *
  827. * @param string $sql the SQL select query to execute. The first column of this SELECT statement
  828. * must be a unique value (usually the 'id' field), as it will be used as the key of the
  829. * returned array.
  830. * @param int $limitfrom return a subset of records, starting at this point (optional, required if $limitnum is set).
  831. * @param int $limitnum return a subset comprising this many records (optional, required if $limitfrom is set).
  832. * @return mixed an array of objects, or false if no records were found or an error occured.
  833. */
  834. function get_records_sql($sql, $limitfrom='', $limitnum='') {
  835. $rs = get_recordset_sql($sql, $limitfrom, $limitnum);
  836. return recordset_to_array($rs);
  837. }
  838. /**
  839. * Utility function used by the following 3 methods.
  840. *
  841. * @param object an ADODB RecordSet object with two columns.
  842. * @return mixed an associative array, or false if an error occured or the RecordSet was empty.
  843. */
  844. function recordset_to_menu($rs) {
  845. global $CFG;
  846. $menu = array();
  847. if ($rs && !rs_EOF($rs)) {
  848. $keys = array_keys($rs->fields);
  849. $key0=$keys[0];
  850. $key1=$keys[1];
  851. while (!$rs->EOF) {
  852. $menu[$rs->fields[$key0]] = $rs->fields[$key1];
  853. $rs->MoveNext();
  854. }
  855. /// Really DIRTY HACK for Oracle, but it's the only way to make it work
  856. /// until we got all those NOT NULL DEFAULT '' out from Moodle
  857. if ($CFG->dbfamily == 'oracle') {
  858. array_walk($menu, 'onespace2empty');
  859. }
  860. /// End of DIRTY HACK
  861. return $menu;
  862. } else {
  863. return false;
  864. }
  865. }
  866. /**
  867. * Utility function
  868. * Similar to recordset_to_menu
  869. *
  870. * field1, field2 is needed because the order from get_records_sql is not reliable
  871. * @param records - records from get_records_sql() or get_records()
  872. * @param field1 - field to be used as menu index
  873. * @param field2 - feild to be used as coresponding menu value
  874. * @return mixed an associative array, or false if an error occured or the RecordSet was empty.
  875. */
  876. function records_to_menu($records, $field1, $field2) {
  877. $menu = array();
  878. foreach ($records as $record) {
  879. $menu[$record->$field1] = $record->$field2;
  880. }
  881. if (!empty($menu)) {
  882. return $menu;
  883. } else {
  884. return false;
  885. }
  886. }
  887. /**
  888. * Get the first two columns from a number of records as an associative array.
  889. *
  890. * Arguments as for @see function get_recordset.
  891. *
  892. * If no errors occur, and at least one records is found, the return value
  893. * is an associative whose keys come from the first field of each record,
  894. * and whose values are the corresponding second fields. If no records are found,
  895. * or an error occurs, false is returned.
  896. *
  897. * @param string $table the table to query.
  898. * @param string $field a field to check (optional).
  899. * @param string $value the value the field must have (requred if field1 is given, else optional).
  900. * @param string $sort an order to sort the results in (optional, a valid SQL ORDER BY parameter).
  901. * @param string $fields a comma separated list of fields to return (optional, by default all fields are returned).
  902. * @param int $limitfrom return a subset of records, starting at this point (optional, required if $limitnum is set).
  903. * @param int $limitnum return a subset comprising this many records (optional, required if $limitfrom is set).
  904. * @return mixed an associative array, or false if no records were found or an error occured.
  905. */
  906. function get_records_menu($table, $field='', $value='', $sort='', $fields='*', $limitfrom='', $limitnum='') {
  907. $rs = get_recordset($table, $field, $value, $sort, $fields, $limitfrom, $limitnum);
  908. return recordset_to_menu($rs);
  909. }
  910. /**
  911. * Get the first two columns from a number of records as an associative array.
  912. *
  913. * Arguments as for @see function get_recordset_select.
  914. * Return value as for @see function get_records_menu.
  915. *
  916. * @param string $table The database table to be checked against.
  917. * @param string $select A fragment of SQL to be used in a where clause in the SQL call.
  918. * @param string $sort Sort order (optional) - a valid SQL order parameter
  919. * @param string $fields A comma separated list of fields to be returned from the chosen table.
  920. * @param int $limitfrom return a subset of records, starting at this point (optional, required if $limitnum is set).
  921. * @param int $limitnum return a subset comprising this many records (optional, required if $limitfrom is set).
  922. * @return mixed an associative array, or false if no records were found or an error occured.
  923. */
  924. function get_records_select_menu($table, $select='', $sort='', $fields='*', $limitfrom='', $limitnum='') {
  925. $rs = get_recordset_select($table, $select, $sort, $fields, $limitfrom, $limitnum);
  926. return recordset_to_menu($rs);
  927. }
  928. /**
  929. * Get the first two columns from a number of records as an associative array.
  930. *
  931. * Arguments as for @see function get_recordset_sql.
  932. * Return value as for @see function get_records_menu.
  933. *
  934. * @param string $sql The SQL string you wish to be executed.
  935. * @param int $limitfrom return a subset of records, starting at this point (optional, required if $limitnum is set).
  936. * @param int $limitnum return a subset comprising this many records (optional, required if $limitfrom is set).
  937. * @return mixed an associative array, or false if no records were found or an error occured.
  938. */
  939. function get_records_sql_menu($sql, $limitfrom='', $limitnum='') {
  940. $rs = get_recordset_sql($sql, $limitfrom, $limitnum);
  941. return recordset_to_menu($rs);
  942. }
  943. /**
  944. * Get a single value from a table row where all the given fields match the given values.
  945. *
  946. * @param string $table the table to query.
  947. * @param string $return the field to return the value of.
  948. * @param string $field1 the first field to check (optional).
  949. * @param string $value1 the value field1 must have (requred if field1 is given, else optional).
  950. * @param string $field2 the second field to check (optional).
  951. * @param string $value2 the value field2 must have (requred if field2 is given, else optional).
  952. * @param string $field3 the third field to check (optional).
  953. * @param string $value3 the value field3 must have (requred if field3 is given, else optional).
  954. * @return mixed the specified value, or false if an error occured.
  955. */
  956. function get_field($table, $return, $field1, $value1, $field2='', $value2='', $field3='', $value3='') {
  957. global $CFG;
  958. $select = where_clause($field1, $value1, $field2, $value2, $field3, $value3);
  959. return get_field_sql('SELECT ' . $return . ' FROM ' . $CFG->prefix . $table . ' ' . $select);
  960. }
  961. /**
  962. * Get a single value from a table row where a particular select clause is true.
  963. *
  964. * @uses $CFG
  965. * @param string $table the table to query.
  966. * @param string $return the field to return the value of.
  967. * @param string $select A fragment of SQL to be used in a where clause in the SQL call.
  968. * @return mixed the specified value, or false if an error occured.
  969. */
  970. function get_field_select($table, $return, $select) {
  971. global $CFG;
  972. if ($select) {
  973. $select = 'WHERE '. $select;
  974. }
  975. return get_field_sql('SELECT ' . $return . ' FROM ' . $CFG->prefix . $table . ' ' . $select);
  976. }
  977. /**
  978. * Get a single value from a table.
  979. *
  980. * @param string $sql an SQL statement expected to return a single value.
  981. * @return mixed the specified value, or false if an error occured.
  982. */
  983. function get_field_sql($sql) {
  984. global $CFG;
  985. /// Strip potential LIMIT uses arriving here, debugging them (MDL-7173)
  986. $newsql = preg_replace('/ LIMIT [0-9, ]+$/is', '', $sql);
  987. if ($newsql != $sql) {
  988. debugging('Incorrect use of LIMIT clause (not cross-db) in call to get_field_sql(): ' . s($sql), DEBUG_DEVELOPER);
  989. $sql = $newsql;
  990. }
  991. $rs = get_recordset_sql($sql, 0, 1);
  992. if ($rs && $rs->RecordCount() == 1) {
  993. /// DIRTY HACK to retrieve all the ' ' (1 space) fields converted back
  994. /// to '' (empty string) for Oracle. It's the only way to work with
  995. /// all those NOT NULL DEFAULT '' fields until we definetively delete them
  996. if ($CFG->dbfamily == 'oracle') {
  997. $value = reset($rs->fields);
  998. onespace2empty($value);
  999. return $value;
  1000. }
  1001. /// End of DIRTY HACK
  1002. return reset($rs->fields);
  1003. } else {
  1004. return false;
  1005. }
  1006. }
  1007. /**
  1008. * Get a single value from a table row where a particular select clause is true.
  1009. *
  1010. * @uses $CFG
  1011. * @param string $table the table to query.
  1012. * @param string $return the field to return the value of.
  1013. * @param string $select A fragment of SQL to be used in a where clause in the SQL call.
  1014. * @return mixed|false Returns the value return from the SQL statment or false if an error occured.
  1015. */
  1016. function get_fieldset_select($table, $return, $select) {
  1017. global $CFG;
  1018. if ($select) {
  1019. $select = ' WHERE '. $select;
  1020. }
  1021. return get_fieldset_sql('SELECT ' . $return . ' FROM ' . $CFG->prefix . $table . $select);
  1022. }
  1023. /**
  1024. * Get an array of data from one or more fields from a database
  1025. * use to get a column, or a series of distinct values
  1026. *
  1027. * @uses $CFG
  1028. * @uses $db
  1029. * @param string $sql The SQL string you wish to be executed.
  1030. * @return mixed|false Returns the value return from the SQL statment or false if an error occured.
  1031. * @todo Finish documenting this function
  1032. */
  1033. function get_fieldset_sql($sql) {
  1034. global $db, $CFG;
  1035. if (defined('MDL_PERFDB')) { global $PERF ; $PERF->dbqueries++; };
  1036. $rs = $db->Execute($sql);
  1037. if (!$rs) {
  1038. debugging($db->ErrorMsg() .'<br /><br />'. s($sql));
  1039. if (!empty($CFG->dblogerror)) {
  1040. $debug=array_shift(debug_backtrace());
  1041. error_log("SQL ".$db->ErrorMsg()." in {$debug['file']} on line {$debug['line']}. STATEMENT: $sql");
  1042. }
  1043. return false;
  1044. }
  1045. if ( !rs_EOF($rs) ) {
  1046. $keys = array_keys($rs->fields);
  1047. $key0 = $keys[0];
  1048. $results = array();
  1049. while (!$rs->EOF) {
  1050. array_push($results, $rs->fields[$key0]);
  1051. $rs->MoveNext();
  1052. }
  1053. /// DIRTY HACK to retrieve all the ' ' (1 space) fields converted back
  1054. /// to '' (empty string) for Oracle. It's the only way to work with
  1055. /// all those NOT NULL DEFAULT '' fields until we definetively delete them
  1056. if ($CFG->dbfamily == 'oracle') {
  1057. array_walk($results, 'onespace2empty');
  1058. }
  1059. /// End of DIRTY HACK
  1060. rs_close($rs);
  1061. return $results;
  1062. } else {
  1063. rs_close($rs);
  1064. return false;
  1065. }
  1066. }
  1067. /**
  1068. * Set a single field in every table row where all the given fields match the given values.
  1069. *
  1070. * @uses $CFG
  1071. * @uses $db
  1072. * @param string $table The database table to be checked against.
  1073. * @param string $newfield the field to set.
  1074. * @param string $newvalue the value to set the field to.
  1075. * @param string $field1 the first field to check (optional).
  1076. * @param string $value1 the value field1 must have (requred if field1 is given, else optional).
  1077. * @param string $field2 the second field to check (optional).
  1078. * @param string $value2 the value field2 must have (requred if field2 is given, else optional).
  1079. * @param string $field3 the third field to check (optional).
  1080. * @param string $value3 the value field3 must have (requred if field3 is given, else optional).
  1081. * @return mixed An ADODB RecordSet object with the results from the SQL call or false.
  1082. */
  1083. function set_field($table, $newfield, $newvalue, $field1, $value1, $field2='', $value2='', $field3='', $value3='') {
  1084. global $CFG;
  1085. // Clear record_cache based on the parameters passed
  1086. // (individual record or whole table)

Large files files are truncated, but you can click here to view the full file