3 // This file is part of Moodle - http://moodle.org/
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.
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.
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/>.
21 * @copyright 2008 Petr Skoda (http://skodak.org)
22 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
25 defined('MOODLE_INTERNAL') || die();
27 class dml_test extends UnitTestCase {
28 private $tables = array();
29 /** @var moodle_database */
32 public static $includecoverage = array('lib/dml');
33 public static $excludecoverage = array('lib/dml/simpletest');
36 protected $olddisplay;
39 global $DB, $UNITTEST;
41 if (isset($UNITTEST->func_test_db)) {
42 $this->tdb = $UNITTEST->func_test_db;
49 $dbman = $this->tdb->get_manager();
51 foreach ($this->tables as $tablename) {
52 if ($dbman->table_exists($tablename)) {
53 $table = new xmldb_table($tablename);
54 $dbman->drop_table($table);
57 $this->tables = array();
61 * Get a xmldb_table object for testing, deleting any existing table
62 * of the same name, for example if one was left over from a previous test
65 * @param database_manager $dbman the database_manager to use.
66 * @param string $suffix table name suffix, use if you need more test tables
67 * @return xmldb_table the table object.
69 private function get_test_table($suffix = '') {
70 $dbman = $this->tdb->get_manager();
72 $tablename = "unit_table";
74 $tablename .= $suffix;
77 $table = new xmldb_table($tablename);
78 if ($dbman->table_exists($table)) {
79 $dbman->drop_table($table);
81 $table->setComment("This is a test'n drop table. You can drop it safely");
82 $this->tables[$tablename] = $tablename;
83 return new xmldb_table($tablename);
86 protected function enable_debugging() {
89 $this->olddebug = $CFG->debug; // Save current debug settings
90 $this->olddisplay = $CFG->debugdisplay;
91 $CFG->debug = DEBUG_DEVELOPER;
92 $CFG->debugdisplay = true;
93 ob_start(); // hide debug warning
97 protected function get_debugging() {
100 $debuginfo = ob_get_contents();
102 $CFG->debug = $this->olddebug; // Restore original debug settings
103 $CFG->debugdisplay = $this->olddisplay;
108 // NOTE: please keep order of test methods here matching the order of moodle_database class methods
110 function test_diagnose() {
112 $result = $DB->diagnose();
113 $this->assertNull($result, 'Database self diagnostics failed %s');
116 function test_get_server_info() {
118 $result = $DB->get_server_info();
119 $this->assertTrue(is_array($result));
120 $this->assertTrue(array_key_exists('description', $result));
121 $this->assertTrue(array_key_exists('version', $result));
124 public function test_get_in_or_equal() {
127 // SQL_PARAMS_QM - IN or =
129 // Correct usage of multiple values
130 $in_values = array('value1', 'value2', '3', 4, null, false, true);
131 list($usql, $params) = $DB->get_in_or_equal($in_values);
132 $this->assertEqual('IN ('.implode(',',array_fill(0, count($in_values), '?')).')', $usql);
133 $this->assertEqual(count($in_values), count($params));
134 foreach ($params as $key => $value) {
135 $this->assertIdentical($in_values[$key], $value);
138 // Correct usage of single value (in an array)
139 $in_values = array('value1');
140 list($usql, $params) = $DB->get_in_or_equal($in_values);
141 $this->assertEqual("= ?", $usql);
142 $this->assertEqual(1, count($params));
143 $this->assertEqual($in_values[0], $params[0]);
145 // Correct usage of single value
146 $in_value = 'value1';
147 list($usql, $params) = $DB->get_in_or_equal($in_values);
148 $this->assertEqual("= ?", $usql);
149 $this->assertEqual(1, count($params));
150 $this->assertEqual($in_value, $params[0]);
152 // SQL_PARAMS_QM - NOT IN or <>
154 // Correct usage of multiple values
155 $in_values = array('value1', 'value2', 'value3', 'value4');
156 list($usql, $params) = $DB->get_in_or_equal($in_values, SQL_PARAMS_QM, null, false);
157 $this->assertEqual("NOT IN (?,?,?,?)", $usql);
158 $this->assertEqual(4, count($params));
159 foreach ($params as $key => $value) {
160 $this->assertEqual($in_values[$key], $value);
163 // Correct usage of single value (in array()
164 $in_values = array('value1');
165 list($usql, $params) = $DB->get_in_or_equal($in_values, SQL_PARAMS_QM, null, false);
166 $this->assertEqual("<> ?", $usql);
167 $this->assertEqual(1, count($params));
168 $this->assertEqual($in_values[0], $params[0]);
170 // Correct usage of single value
171 $in_value = 'value1';
172 list($usql, $params) = $DB->get_in_or_equal($in_values, SQL_PARAMS_QM, null, false);
173 $this->assertEqual("<> ?", $usql);
174 $this->assertEqual(1, count($params));
175 $this->assertEqual($in_value, $params[0]);
177 // SQL_PARAMS_NAMED - IN or =
179 // Correct usage of multiple values
180 $in_values = array('value1', 'value2', 'value3', 'value4');
181 list($usql, $params) = $DB->get_in_or_equal($in_values, SQL_PARAMS_NAMED, 'param', true);
182 $this->assertEqual(4, count($params));
185 foreach ($params as $key => $value) {
186 $this->assertEqual(current($in_values), $value);
190 $this->assertEqual("IN (".implode(',', $ps).")", $usql);
192 // Correct usage of single values (in array)
193 $in_values = array('value1');
194 list($usql, $params) = $DB->get_in_or_equal($in_values, SQL_PARAMS_NAMED, 'param', true);
195 $this->assertEqual(1, count($params));
196 $value = reset($params);
198 $this->assertEqual("= :$key", $usql);
199 $this->assertEqual($in_value, $value);
201 // Correct usage of single value
202 $in_value = 'value1';
203 list($usql, $params) = $DB->get_in_or_equal($in_values, SQL_PARAMS_NAMED, 'param', true);
204 $this->assertEqual(1, count($params));
205 $value = reset($params);
207 $this->assertEqual("= :$key", $usql);
208 $this->assertEqual($in_value, $value);
210 // SQL_PARAMS_NAMED - NOT IN or <>
212 // Correct usage of multiple values
213 $in_values = array('value1', 'value2', 'value3', 'value4');
214 list($usql, $params) = $DB->get_in_or_equal($in_values, SQL_PARAMS_NAMED, 'param', false);
215 $this->assertEqual(4, count($params));
218 foreach ($params as $key => $value) {
219 $this->assertEqual(current($in_values), $value);
223 $this->assertEqual("NOT IN (".implode(',', $ps).")", $usql);
225 // Correct usage of single values (in array)
226 $in_values = array('value1');
227 list($usql, $params) = $DB->get_in_or_equal($in_values, SQL_PARAMS_NAMED, 'param', false);
228 $this->assertEqual(1, count($params));
229 $value = reset($params);
231 $this->assertEqual("<> :$key", $usql);
232 $this->assertEqual($in_value, $value);
234 // Correct usage of single value
235 $in_value = 'value1';
236 list($usql, $params) = $DB->get_in_or_equal($in_values, SQL_PARAMS_NAMED, 'param', false);
237 $this->assertEqual(1, count($params));
238 $value = reset($params);
240 $this->assertEqual("<> :$key", $usql);
241 $this->assertEqual($in_value, $value);
243 // make sure the param names are unique
244 list($usql1, $params1) = $DB->get_in_or_equal(array(1,2,3), SQL_PARAMS_NAMED, 'param');
245 list($usql2, $params2) = $DB->get_in_or_equal(array(1,2,3), SQL_PARAMS_NAMED, 'param');
246 $params1 = array_keys($params1);
247 $params2 = array_keys($params2);
248 $common = array_intersect($params1, $params2);
249 $this->assertEqual(count($common), 0);
251 // Some incorrect tests
253 // Incorrect usage passing not-allowed params type
254 $in_values = array(1, 2, 3);
256 list($usql, $params) = $DB->get_in_or_equal($in_values, SQL_PARAMS_DOLLAR, 'param', false);
257 $this->fail('An Exception is missing, expected due to not supported SQL_PARAMS_DOLLAR');
258 } catch (exception $e) {
259 $this->assertTrue($e instanceof dml_exception);
260 $this->assertEqual($e->errorcode, 'typenotimplement');
263 // Incorrect usage passing empty array
264 $in_values = array();
266 list($usql, $params) = $DB->get_in_or_equal($in_values, SQL_PARAMS_NAMED, 'param', false);
267 $this->fail('An Exception is missing, expected due to empty array of items');
268 } catch (exception $e) {
269 $this->assertTrue($e instanceof coding_exception);
272 // Test using $onemptyitems
274 // Correct usage passing empty array and $onemptyitems = NULL (equal = true, QM)
275 $in_values = array();
276 list($usql, $params) = $DB->get_in_or_equal($in_values, SQL_PARAMS_QM, 'param', true, NULL);
277 $this->assertEqual(' IS NULL', $usql);
278 $this->assertIdentical(array(), $params);
280 // Correct usage passing empty array and $onemptyitems = NULL (equal = false, NAMED)
281 $in_values = array();
282 list($usql, $params) = $DB->get_in_or_equal($in_values, SQL_PARAMS_NAMED, 'param', false, NULL);
283 $this->assertEqual(' IS NOT NULL', $usql);
284 $this->assertIdentical(array(), $params);
286 // Correct usage passing empty array and $onemptyitems = true (equal = true, QM)
287 $in_values = array();
288 list($usql, $params) = $DB->get_in_or_equal($in_values, SQL_PARAMS_QM, 'param', true, true);
289 $this->assertEqual('= ?', $usql);
290 $this->assertIdentical(array(true), $params);
292 // Correct usage passing empty array and $onemptyitems = true (equal = false, NAMED)
293 $in_values = array();
294 list($usql, $params) = $DB->get_in_or_equal($in_values, SQL_PARAMS_NAMED, 'param', false, true);
295 $this->assertEqual(1, count($params));
296 $value = reset($params);
298 $this->assertEqual('<> :'.$key, $usql);
299 $this->assertIdentical($value, true);
301 // Correct usage passing empty array and $onemptyitems = -1 (equal = true, QM)
302 $in_values = array();
303 list($usql, $params) = $DB->get_in_or_equal($in_values, SQL_PARAMS_QM, 'param', true, -1);
304 $this->assertEqual('= ?', $usql);
305 $this->assertIdentical(array(-1), $params);
307 // Correct usage passing empty array and $onemptyitems = -1 (equal = false, NAMED)
308 $in_values = array();
309 list($usql, $params) = $DB->get_in_or_equal($in_values, SQL_PARAMS_NAMED, 'param', false, -1);
310 $this->assertEqual(1, count($params));
311 $value = reset($params);
313 $this->assertEqual('<> :'.$key, $usql);
314 $this->assertIdentical($value, -1);
316 // Correct usage passing empty array and $onemptyitems = 'onevalue' (equal = true, QM)
317 $in_values = array();
318 list($usql, $params) = $DB->get_in_or_equal($in_values, SQL_PARAMS_QM, 'param', true, 'onevalue');
319 $this->assertEqual('= ?', $usql);
320 $this->assertIdentical(array('onevalue'), $params);
322 // Correct usage passing empty array and $onemptyitems = 'onevalue' (equal = false, NAMED)
323 $in_values = array();
324 list($usql, $params) = $DB->get_in_or_equal($in_values, SQL_PARAMS_NAMED, 'param', false, 'onevalue');
325 $this->assertEqual(1, count($params));
326 $value = reset($params);
328 $this->assertEqual('<> :'.$key, $usql);
329 $this->assertIdentical($value, 'onevalue');
332 public function test_fix_table_names() {
333 $DB = new moodle_database_for_testing();
334 $prefix = $DB->get_prefix();
336 // Simple placeholder
337 $placeholder = "{user_123}";
338 $this->assertIdentical($prefix."user_123", $DB->public_fix_table_names($placeholder));
341 $placeholder = "{user-a}";
342 $this->assertIdentical($placeholder, $DB->public_fix_table_names($placeholder));
345 $placeholder = "{123user}";
346 $this->assertIdentical($placeholder, $DB->public_fix_table_names($placeholder));
349 $sql = "SELECT * FROM {user}, {funny_table_name}, {mdl_stupid_table} WHERE {user}.id = {funny_table_name}.userid";
350 $expected = "SELECT * FROM {$prefix}user, {$prefix}funny_table_name, {$prefix}mdl_stupid_table WHERE {$prefix}user.id = {$prefix}funny_table_name.userid";
351 $this->assertIdentical($expected, $DB->public_fix_table_names($sql));
354 function test_fix_sql_params() {
357 $table = $this->get_test_table();
358 $tablename = $table->getName();
360 // Correct table placeholder substitution
361 $sql = "SELECT * FROM {{$tablename}}";
362 $sqlarray = $DB->fix_sql_params($sql);
363 $this->assertEqual("SELECT * FROM {$DB->get_prefix()}".$tablename, $sqlarray[0]);
365 // Conversions of all param types
367 $sql[SQL_PARAMS_NAMED] = "SELECT * FROM {$DB->get_prefix()}testtable WHERE name = :param1, course = :param2";
368 $sql[SQL_PARAMS_QM] = "SELECT * FROM {$DB->get_prefix()}testtable WHERE name = ?, course = ?";
369 $sql[SQL_PARAMS_DOLLAR] = "SELECT * FROM {$DB->get_prefix()}testtable WHERE name = \$1, course = \$2";
372 $params[SQL_PARAMS_NAMED] = array('param1'=>'first record', 'param2'=>1);
373 $params[SQL_PARAMS_QM] = array('first record', 1);
374 $params[SQL_PARAMS_DOLLAR] = array('first record', 1);
376 list($rsql, $rparams, $rtype) = $DB->fix_sql_params($sql[SQL_PARAMS_NAMED], $params[SQL_PARAMS_NAMED]);
377 $this->assertIdentical($rsql, $sql[$rtype]);
378 $this->assertIdentical($rparams, $params[$rtype]);
380 list($rsql, $rparams, $rtype) = $DB->fix_sql_params($sql[SQL_PARAMS_QM], $params[SQL_PARAMS_QM]);
381 $this->assertIdentical($rsql, $sql[$rtype]);
382 $this->assertIdentical($rparams, $params[$rtype]);
384 list($rsql, $rparams, $rtype) = $DB->fix_sql_params($sql[SQL_PARAMS_DOLLAR], $params[SQL_PARAMS_DOLLAR]);
385 $this->assertIdentical($rsql, $sql[$rtype]);
386 $this->assertIdentical($rparams, $params[$rtype]);
389 // Malformed table placeholder
390 $sql = "SELECT * FROM [testtable]";
391 $sqlarray = $DB->fix_sql_params($sql);
392 $this->assertIdentical($sql, $sqlarray[0]);
395 // Mixed param types (colon and dollar)
396 $sql = "SELECT * FROM {{$tablename}} WHERE name = :param1, course = \$1";
397 $params = array('param1' => 'record1', 'param2' => 3);
399 $DB->fix_sql_params($sql, $params);
400 $this->fail("Expecting an exception, none occurred");
401 } catch (Exception $e) {
402 $this->assertTrue($e instanceof dml_exception);
405 // Mixed param types (question and dollar)
406 $sql = "SELECT * FROM {{$tablename}} WHERE name = ?, course = \$1";
407 $params = array('param1' => 'record2', 'param2' => 5);
409 $DB->fix_sql_params($sql, $params);
410 $this->fail("Expecting an exception, none occurred");
411 } catch (Exception $e) {
412 $this->assertTrue($e instanceof dml_exception);
415 // Too few params in sql
416 $sql = "SELECT * FROM {{$tablename}} WHERE name = ?, course = ?, id = ?";
417 $params = array('record2', 3);
419 $DB->fix_sql_params($sql, $params);
420 $this->fail("Expecting an exception, none occurred");
421 } catch (Exception $e) {
422 $this->assertTrue($e instanceof dml_exception);
425 // Too many params in array: no error, just use what is necessary
429 $sqlarray = $DB->fix_sql_params($sql, $params);
430 $this->assertTrue(is_array($sqlarray));
431 $this->assertEqual(count($sqlarray[1]), 3);
432 } catch (Exception $e) {
433 $this->fail("Unexpected ".get_class($e)." exception");
436 // Named params missing from array
437 $sql = "SELECT * FROM {{$tablename}} WHERE name = :name, course = :course";
438 $params = array('wrongname' => 'record1', 'course' => 1);
440 $DB->fix_sql_params($sql, $params);
441 $this->fail("Expecting an exception, none occurred");
442 } catch (Exception $e) {
443 $this->assertTrue($e instanceof dml_exception);
446 // Duplicate named param in query - this is a very important feature!!
447 // it helps with debugging of sloppy code
448 $sql = "SELECT * FROM {{$tablename}} WHERE name = :name, course = :name";
449 $params = array('name' => 'record2', 'course' => 3);
451 $DB->fix_sql_params($sql, $params);
452 $this->fail("Expecting an exception, none occurred");
453 } catch (Exception $e) {
454 $this->assertTrue($e instanceof dml_exception);
457 // Extra named param is ignored
458 $sql = "SELECT * FROM {{$tablename}} WHERE name = :name, course = :course";
459 $params = array('name' => 'record1', 'course' => 1, 'extrastuff'=>'haha');
461 $sqlarray = $DB->fix_sql_params($sql, $params);
462 $this->assertTrue(is_array($sqlarray));
463 $this->assertEqual(count($sqlarray[1]), 2);
464 } catch (Exception $e) {
465 $this->fail("Unexpected ".get_class($e)." exception");
468 // Params exceeding 30 chars length
469 $sql = "SELECT * FROM {{$tablename}} WHERE name = :long_placeholder_with_more_than_30";
470 $params = array('long_placeholder_with_more_than_30' => 'record1');
472 $DB->fix_sql_params($sql, $params);
473 $this->fail("Expecting an exception, none occurred");
474 } catch (Exception $e) {
475 $this->assertTrue($e instanceof coding_exception);
478 // Booleans in NAMED params are casting to 1/0 int
479 $sql = "SELECT * FROM {{$tablename}} WHERE course = ? OR course = ?";
480 $params = array(true, false);
481 list($sql, $params) = $DB->fix_sql_params($sql, $params);
482 $this->assertTrue(reset($params) === 1);
483 $this->assertTrue(next($params) === 0);
485 // Booleans in QM params are casting to 1/0 int
486 $sql = "SELECT * FROM {{$tablename}} WHERE course = :course1 OR course = :course2";
487 $params = array('course1' => true, 'course2' => false);
488 list($sql, $params) = $DB->fix_sql_params($sql, $params);
489 $this->assertTrue(reset($params) === 1);
490 $this->assertTrue(next($params) === 0);
492 // Booleans in DOLLAR params are casting to 1/0 int
493 $sql = "SELECT * FROM {{$tablename}} WHERE course = \$1 OR course = \$2";
494 $params = array(true, false);
495 list($sql, $params) = $DB->fix_sql_params($sql, $params);
496 $this->assertTrue(reset($params) === 1);
497 $this->assertTrue(next($params) === 0);
499 // No data types are touched except bool
500 $sql = "SELECT * FROM {{$tablename}} WHERE name IN (?,?,?,?,?,?)";
501 $inparams = array('abc', 'ABC', NULL, '1', 1, 1.4);
502 list($sql, $params) = $DB->fix_sql_params($sql, $inparams);
503 $this->assertIdentical(array_values($params), array_values($inparams));
506 public function test_tweak_param_names() {
507 // Note the tweak_param_names() method is only available in the oracle driver,
508 // hence we look for expected results indirectly, by testing various DML methods
509 // with some "extreme" conditions causing the tweak to happen.
511 $dbman = $this->tdb->get_manager();
513 $table = $this->get_test_table();
514 $tablename = $table->getName();
516 $table->add_field('id', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, XMLDB_SEQUENCE, null);
517 // Add some columns with 28 chars in the name
518 $table->add_field('long_int_columnname_with_28c', XMLDB_TYPE_INTEGER, '10');
519 $table->add_field('long_dec_columnname_with_28c', XMLDB_TYPE_NUMBER, '10,2');
520 $table->add_field('long_str_columnname_with_28c', XMLDB_TYPE_CHAR, '100');
521 // Add some columns with 30 chars in the name
522 $table->add_field('long_int_columnname_with_30cxx', XMLDB_TYPE_INTEGER, '10');
523 $table->add_field('long_dec_columnname_with_30cxx', XMLDB_TYPE_NUMBER, '10,2');
524 $table->add_field('long_str_columnname_with_30cxx', XMLDB_TYPE_CHAR, '100');
526 $table->add_key('primary', XMLDB_KEY_PRIMARY, array('id'));
528 $dbman->create_table($table);
530 $this->assertTrue($dbman->table_exists($tablename));
532 // Test insert record
533 $rec1 = new stdClass();
534 $rec1->long_int_columnname_with_28c = 28;
535 $rec1->long_dec_columnname_with_28c = 28.28;
536 $rec1->long_str_columnname_with_28c = '28';
537 $rec1->long_int_columnname_with_30cxx = 30;
538 $rec1->long_dec_columnname_with_30cxx = 30.30;
539 $rec1->long_str_columnname_with_30cxx = '30';
542 $rec1->id = $DB->insert_record($tablename, $rec1);
543 $this->assertEqual($rec1, $DB->get_record($tablename, array('id' => $rec1->id)));
546 $DB->update_record($tablename, $rec1);
547 $this->assertEqual($rec1, $DB->get_record($tablename, array('id' => $rec1->id)));
550 $rec1->long_int_columnname_with_28c = 280;
551 $DB->set_field($tablename, 'long_int_columnname_with_28c', $rec1->long_int_columnname_with_28c,
552 array('id' => $rec1->id, 'long_int_columnname_with_28c' => 28));
553 $rec1->long_dec_columnname_with_28c = 280.28;
554 $DB->set_field($tablename, 'long_dec_columnname_with_28c', $rec1->long_dec_columnname_with_28c,
555 array('id' => $rec1->id, 'long_dec_columnname_with_28c' => 28.28));
556 $rec1->long_str_columnname_with_28c = '280';
557 $DB->set_field($tablename, 'long_str_columnname_with_28c', $rec1->long_str_columnname_with_28c,
558 array('id' => $rec1->id, 'long_str_columnname_with_28c' => '28'));
559 $rec1->long_int_columnname_with_30cxx = 300;
560 $DB->set_field($tablename, 'long_int_columnname_with_30cxx', $rec1->long_int_columnname_with_30cxx,
561 array('id' => $rec1->id, 'long_int_columnname_with_30cxx' => 30));
562 $rec1->long_dec_columnname_with_30cxx = 300.30;
563 $DB->set_field($tablename, 'long_dec_columnname_with_30cxx', $rec1->long_dec_columnname_with_30cxx,
564 array('id' => $rec1->id, 'long_dec_columnname_with_30cxx' => 30.30));
565 $rec1->long_str_columnname_with_30cxx = '300';
566 $DB->set_field($tablename, 'long_str_columnname_with_30cxx', $rec1->long_str_columnname_with_30cxx,
567 array('id' => $rec1->id, 'long_str_columnname_with_30cxx' => '30'));
568 $this->assertEqual($rec1, $DB->get_record($tablename, array('id' => $rec1->id)));
571 $rec2 = $DB->get_record($tablename, array('id' => $rec1->id));
572 $rec2->id = $DB->insert_record($tablename, $rec2);
573 $this->assertEqual(2, $DB->count_records($tablename));
574 $DB->delete_records($tablename, (array) $rec2);
575 $this->assertEqual(1, $DB->count_records($tablename));
578 $rs = $DB->get_recordset($tablename, (array) $rec1);
580 foreach ($rs as $rec2) {
584 $this->assertEqual(1, $iterations);
585 $this->assertEqual($rec1, $rec2);
588 $recs = $DB->get_records($tablename, (array) $rec1);
589 $this->assertEqual(1, count($recs));
590 $this->assertEqual($rec1, reset($recs));
592 // get_fieldset_select()
593 $select = 'id = :id AND
594 long_int_columnname_with_28c = :long_int_columnname_with_28c AND
595 long_dec_columnname_with_28c = :long_dec_columnname_with_28c AND
596 long_str_columnname_with_28c = :long_str_columnname_with_28c AND
597 long_int_columnname_with_30cxx = :long_int_columnname_with_30cxx AND
598 long_dec_columnname_with_30cxx = :long_dec_columnname_with_30cxx AND
599 long_str_columnname_with_30cxx = :long_str_columnname_with_30cxx';
600 $fields = $DB->get_fieldset_select($tablename, 'long_int_columnname_with_28c', $select, (array)$rec1);
601 $this->assertEqual(1, count($fields));
602 $this->assertEqual($rec1->long_int_columnname_with_28c, reset($fields));
603 $fields = $DB->get_fieldset_select($tablename, 'long_dec_columnname_with_28c', $select, (array)$rec1);
604 $this->assertEqual($rec1->long_dec_columnname_with_28c, reset($fields));
605 $fields = $DB->get_fieldset_select($tablename, 'long_str_columnname_with_28c', $select, (array)$rec1);
606 $this->assertEqual($rec1->long_str_columnname_with_28c, reset($fields));
607 $fields = $DB->get_fieldset_select($tablename, 'long_int_columnname_with_30cxx', $select, (array)$rec1);
608 $this->assertEqual($rec1->long_int_columnname_with_30cxx, reset($fields));
609 $fields = $DB->get_fieldset_select($tablename, 'long_dec_columnname_with_30cxx', $select, (array)$rec1);
610 $this->assertEqual($rec1->long_dec_columnname_with_30cxx, reset($fields));
611 $fields = $DB->get_fieldset_select($tablename, 'long_str_columnname_with_30cxx', $select, (array)$rec1);
612 $this->assertEqual($rec1->long_str_columnname_with_30cxx, reset($fields));
614 // overlapping placeholders (progressive str_replace)
615 $overlapselect = 'id = :p AND
616 long_int_columnname_with_28c = :param1 AND
617 long_dec_columnname_with_28c = :param2 AND
618 long_str_columnname_with_28c = :param_with_29_characters_long AND
619 long_int_columnname_with_30cxx = :param_with_30_characters_long_ AND
620 long_dec_columnname_with_30cxx = :param_ AND
621 long_str_columnname_with_30cxx = :param__';
622 $overlapparams = array(
624 'param1' => $rec1->long_int_columnname_with_28c,
625 'param2' => $rec1->long_dec_columnname_with_28c,
626 'param_with_29_characters_long' => $rec1->long_str_columnname_with_28c,
627 'param_with_30_characters_long_' => $rec1->long_int_columnname_with_30cxx,
628 'param_' => $rec1->long_dec_columnname_with_30cxx,
629 'param__' => $rec1->long_str_columnname_with_30cxx);
630 $recs = $DB->get_records_select($tablename, $overlapselect, $overlapparams);
631 $this->assertEqual(1, count($recs));
632 $this->assertEqual($rec1, reset($recs));
635 $DB->execute("DELETE FROM {{$tablename}} WHERE $select", (array)$rec1);
636 $this->assertEqual(0, $DB->count_records($tablename));
639 public function test_get_tables() {
641 $dbman = $this->tdb->get_manager();
643 // Need to test with multiple DBs
644 $table = $this->get_test_table();
645 $tablename = $table->getName();
647 $original_count = count($DB->get_tables());
649 $table->add_field('id', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, XMLDB_SEQUENCE, null);
650 $table->add_key('primary', XMLDB_KEY_PRIMARY, array('id'));
652 $dbman->create_table($table);
653 $this->assertTrue(count($DB->get_tables()) == $original_count + 1);
655 $dbman->drop_table($table);
656 $this->assertTrue(count($DB->get_tables()) == $original_count);
659 public function test_get_indexes() {
661 $dbman = $this->tdb->get_manager();
663 $table = $this->get_test_table();
664 $tablename = $table->getName();
666 $table->add_field('id', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, XMLDB_SEQUENCE, null);
667 $table->add_field('course', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '0');
668 $table->add_key('primary', XMLDB_KEY_PRIMARY, array('id'));
669 $table->add_index('course', XMLDB_INDEX_NOTUNIQUE, array('course'));
670 $table->add_index('course-id', XMLDB_INDEX_UNIQUE, array('course', 'id'));
671 $dbman->create_table($table);
673 $indices = $DB->get_indexes($tablename);
674 $this->assertTrue(is_array($indices));
675 $this->assertEqual(count($indices), 2);
676 // we do not care about index names for now
677 $first = array_shift($indices);
678 $second = array_shift($indices);
679 if (count($first['columns']) == 2) {
686 $this->assertFalse($single['unique']);
687 $this->assertTrue($composed['unique']);
688 $this->assertEqual(1, count($single['columns']));
689 $this->assertEqual(2, count($composed['columns']));
690 $this->assertEqual('course', $single['columns'][0]);
691 $this->assertEqual('course', $composed['columns'][0]);
692 $this->assertEqual('id', $composed['columns'][1]);
695 public function test_get_columns() {
697 $dbman = $this->tdb->get_manager();
699 $table = $this->get_test_table();
700 $tablename = $table->getName();
702 $table->add_field('id', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, XMLDB_SEQUENCE, null);
703 $table->add_field('course', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '0');
704 $table->add_field('name', XMLDB_TYPE_CHAR, '255', null, null, null, 'lala');
705 $table->add_field('description', XMLDB_TYPE_TEXT, 'small', null, null, null, null);
706 $table->add_field('enumfield', XMLDB_TYPE_CHAR, '255', null, XMLDB_NOTNULL, null, 'test2');
707 $table->add_field('onenum', XMLDB_TYPE_NUMBER, '10,2', null, null, null, 200);
708 $table->add_key('primary', XMLDB_KEY_PRIMARY, array('id'));
709 $dbman->create_table($table);
711 $columns = $DB->get_columns($tablename);
712 $this->assertTrue(is_array($columns));
714 $fields = $table->getFields();
715 $this->assertEqual(count($columns), count($fields));
717 $field = $columns['id'];
718 $this->assertEqual('R', $field->meta_type);
719 $this->assertTrue($field->auto_increment);
720 $this->assertTrue($field->unique);
722 $field = $columns['course'];
723 $this->assertEqual('I', $field->meta_type);
724 $this->assertFalse($field->auto_increment);
725 $this->assertTrue($field->has_default);
726 $this->assertEqual(0, $field->default_value);
727 $this->assertTrue($field->not_null);
729 $field = $columns['name'];
730 $this->assertEqual('C', $field->meta_type);
731 $this->assertFalse($field->auto_increment);
732 $this->assertTrue($field->has_default);
733 $this->assertIdentical('lala', $field->default_value);
734 $this->assertFalse($field->not_null);
736 $field = $columns['description'];
737 $this->assertEqual('X', $field->meta_type);
738 $this->assertFalse($field->auto_increment);
739 $this->assertFalse($field->has_default);
740 $this->assertIdentical(null, $field->default_value);
741 $this->assertFalse($field->not_null);
743 $field = $columns['enumfield'];
744 $this->assertEqual('C', $field->meta_type);
745 $this->assertFalse($field->auto_increment);
746 $this->assertIdentical('test2', $field->default_value);
747 $this->assertTrue($field->not_null);
749 $field = $columns['onenum'];
750 $this->assertEqual('N', $field->meta_type);
751 $this->assertFalse($field->auto_increment);
752 $this->assertTrue($field->has_default);
753 $this->assertEqual(200.0, $field->default_value);
754 $this->assertFalse($field->not_null);
756 for ($i = 0; $i < count($columns); $i++) {
758 $next_column = reset($columns);
759 $next_field = reset($fields);
761 $next_column = next($columns);
762 $next_field = next($fields);
765 $this->assertEqual($next_column->name, $next_field->name);
769 public function test_get_manager() {
771 $dbman = $this->tdb->get_manager();
773 $this->assertTrue($dbman instanceof database_manager);
776 public function test_setup_is_unicodedb() {
778 $this->assertTrue($DB->setup_is_unicodedb());
781 public function test_set_debug() { //tests get_debug() too
783 $dbman = $this->tdb->get_manager();
785 $table = $this->get_test_table();
786 $tablename = $table->getName();
788 $table->add_field('id', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, XMLDB_SEQUENCE, null);
789 $table->add_field('course', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '0');
790 $table->add_key('primary', XMLDB_KEY_PRIMARY, array('id'));
791 $dbman->create_table($table);
793 $sql = "SELECT * FROM {{$tablename}}";
795 $prevdebug = $DB->get_debug();
798 $DB->set_debug(true);
799 $this->assertTrue($DB->get_debug());
801 $DB->set_debug(false);
802 $this->assertFalse($DB->get_debug());
803 $debuginfo = ob_get_contents();
805 $this->assertFalse($debuginfo === '');
809 $debuginfo = ob_get_contents();
811 $this->assertTrue($debuginfo === '');
813 $DB->set_debug($prevdebug);
816 public function test_execute() {
818 $dbman = $this->tdb->get_manager();
820 $table1 = $this->get_test_table('1');
821 $tablename1 = $table1->getName();
822 $table1->add_field('id', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, XMLDB_SEQUENCE, null);
823 $table1->add_field('course', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '0');
824 $table1->add_field('name', XMLDB_TYPE_CHAR, '255', null, null, null, '0');
825 $table1->add_index('course', XMLDB_INDEX_NOTUNIQUE, array('course'));
826 $table1->add_key('primary', XMLDB_KEY_PRIMARY, array('id'));
827 $dbman->create_table($table1);
829 $table2 = $this->get_test_table('2');
830 $tablename2 = $table2->getName();
831 $table2->add_field('id', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, XMLDB_SEQUENCE, null);
832 $table2->add_field('course', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '0');
833 $table2->add_key('primary', XMLDB_KEY_PRIMARY, array('id'));
834 $dbman->create_table($table2);
836 $DB->insert_record($tablename1, array('course' => 3, 'name' => 'aaa'));
837 $DB->insert_record($tablename1, array('course' => 1, 'name' => 'bbb'));
838 $DB->insert_record($tablename1, array('course' => 7, 'name' => 'ccc'));
839 $DB->insert_record($tablename1, array('course' => 3, 'name' => 'ddd'));
841 // select results are ignored
842 $sql = "SELECT * FROM {{$tablename1}} WHERE course = :course";
843 $this->assertTrue($DB->execute($sql, array('course'=>3)));
845 // throw exception on error
846 $sql = "XXUPDATE SET XSSD";
849 $this->fail("Expecting an exception, none occurred");
850 } catch (Exception $e) {
851 $this->assertTrue($e instanceof dml_write_exception);
855 $sql = "UPDATE {{$tablename1}}
858 $this->assertTrue($DB->execute($sql, array('3')));
859 $this->assertEqual($DB->count_records($tablename1, array('course' => 6)), 2);
861 // insert from one into second table
862 $sql = "INSERT INTO {{$tablename2}} (course)
865 FROM {{$tablename1}}";
866 $this->assertTrue($DB->execute($sql));
867 $this->assertEqual($DB->count_records($tablename2), 4);
870 public function test_get_recordset() {
872 $dbman = $DB->get_manager();
874 $table = $this->get_test_table();
875 $tablename = $table->getName();
877 $table->add_field('id', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, XMLDB_SEQUENCE, null);
878 $table->add_field('course', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '0');
879 $table->add_field('name', XMLDB_TYPE_CHAR, '255', null, null, null, '0');
880 $table->add_field('onetext', XMLDB_TYPE_TEXT, 'big', null, null, null);
881 $table->add_index('course', XMLDB_INDEX_NOTUNIQUE, array('course'));
882 $table->add_key('primary', XMLDB_KEY_PRIMARY, array('id'));
883 $dbman->create_table($table);
885 $data = array(array('id' => 1, 'course' => 3, 'name' => 'record1', 'onetext'=>'abc'),
886 array('id' => 2, 'course' => 3, 'name' => 'record2', 'onetext'=>'abcd'),
887 array('id' => 3, 'course' => 5, 'name' => 'record3', 'onetext'=>'abcde'));
889 foreach ($data as $record) {
890 $DB->insert_record($tablename, $record);
893 // standard recordset iteration
894 $rs = $DB->get_recordset($tablename);
895 $this->assertTrue($rs instanceof moodle_recordset);
897 foreach($rs as $record) {
898 $data_record = current($data);
899 foreach ($record as $k => $v) {
900 $this->assertEqual($data_record[$k], $v);
906 // iterator style usage
907 $rs = $DB->get_recordset($tablename);
908 $this->assertTrue($rs instanceof moodle_recordset);
910 while ($rs->valid()) {
911 $record = $rs->current();
912 $data_record = current($data);
913 foreach ($record as $k => $v) {
914 $this->assertEqual($data_record[$k], $v);
921 // make sure rewind is ignored
922 $rs = $DB->get_recordset($tablename);
923 $this->assertTrue($rs instanceof moodle_recordset);
926 foreach($rs as $record) {
930 $this->fail('revind not ignored in recordsets');
933 $data_record = current($data);
934 foreach ($record as $k => $v) {
935 $this->assertEqual($data_record[$k], $v);
941 // test for exception throwing on text conditions being compared. (MDL-24863, unwanted auto conversion of param to int)
942 $conditions = array('onetext' => '1');
944 $rs = $DB->get_recordset($tablename, $conditions);
945 $this->fail('An Exception is missing, expected due to equating of text fields');
946 } catch (exception $e) {
947 $this->assertTrue($e instanceof dml_exception);
948 $this->assertEqual($e->errorcode, 'textconditionsnotallowed');
952 // * limits are tested in test_get_recordset_sql()
953 // * where_clause() is used internally and is tested in test_get_records()
956 public function test_get_recordset_iterator_keys() {
958 $dbman = $DB->get_manager();
960 $table = $this->get_test_table();
961 $tablename = $table->getName();
963 $table->add_field('id', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, XMLDB_SEQUENCE, null);
964 $table->add_field('course', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '0');
965 $table->add_field('name', XMLDB_TYPE_CHAR, '255', null, null, null, '0');
966 $table->add_index('course', XMLDB_INDEX_NOTUNIQUE, array('course'));
967 $table->add_key('primary', XMLDB_KEY_PRIMARY, array('id'));
968 $dbman->create_table($table);
970 $data = array(array('id'=> 1, 'course' => 3, 'name' => 'record1'),
971 array('id'=> 2, 'course' => 3, 'name' => 'record2'),
972 array('id'=> 3, 'course' => 5, 'name' => 'record3'));
973 foreach ($data as $record) {
974 $DB->insert_record($tablename, $record);
977 // Test repeated numeric keys are returned ok
978 $rs = $DB->get_recordset($tablename, NULL, NULL, 'course, name, id');
982 foreach($rs as $key => $record) {
983 $data_record = current($data);
984 $this->assertEqual($data_record['course'], $key);
989 $this->assertEqual($count, 3);
991 // Test string keys are returned ok
992 $rs = $DB->get_recordset($tablename, NULL, NULL, 'name, course, id');
996 foreach($rs as $key => $record) {
997 $data_record = current($data);
998 $this->assertEqual($data_record['name'], $key);
1003 $this->assertEqual($count, 3);
1005 // Test numeric not starting in 1 keys are returned ok
1006 $rs = $DB->get_recordset($tablename, NULL, 'id DESC', 'id, course, name');
1008 $data = array_reverse($data);
1011 foreach($rs as $key => $record) {
1012 $data_record = current($data);
1013 $this->assertEqual($data_record['id'], $key);
1018 $this->assertEqual($count, 3);
1021 public function test_get_recordset_list() {
1023 $dbman = $DB->get_manager();
1025 $table = $this->get_test_table();
1026 $tablename = $table->getName();
1028 $table->add_field('id', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, XMLDB_SEQUENCE, null);
1029 $table->add_field('course', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '0');
1030 $table->add_index('course', XMLDB_INDEX_NOTUNIQUE, array('course'));
1031 $table->add_key('primary', XMLDB_KEY_PRIMARY, array('id'));
1032 $dbman->create_table($table);
1034 $DB->insert_record($tablename, array('course' => 3));
1035 $DB->insert_record($tablename, array('course' => 3));
1036 $DB->insert_record($tablename, array('course' => 5));
1037 $DB->insert_record($tablename, array('course' => 2));
1039 $rs = $DB->get_recordset_list($tablename, 'course', array(3, 2));
1042 foreach ($rs as $record) {
1045 $this->assertEqual(3, $counter);
1048 $rs = $DB->get_recordset_list($tablename, 'course',array()); /// Must return 0 rows without conditions. MDL-17645
1051 foreach ($rs as $record) {
1055 $this->assertEqual(0, $counter);
1058 // * limits are tested in test_get_recordset_sql()
1059 // * where_clause() is used internally and is tested in test_get_records()
1062 public function test_get_recordset_select() {
1064 $dbman = $DB->get_manager();
1066 $table = $this->get_test_table();
1067 $tablename = $table->getName();
1069 $table->add_field('id', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, XMLDB_SEQUENCE, null);
1070 $table->add_field('course', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '0');
1071 $table->add_key('primary', XMLDB_KEY_PRIMARY, array('id'));
1072 $dbman->create_table($table);
1074 $DB->insert_record($tablename, array('course' => 3));
1075 $DB->insert_record($tablename, array('course' => 3));
1076 $DB->insert_record($tablename, array('course' => 5));
1077 $DB->insert_record($tablename, array('course' => 2));
1079 $rs = $DB->get_recordset_select($tablename, '');
1081 foreach ($rs as $record) {
1085 $this->assertEqual(4, $counter);
1087 $this->assertTrue($rs = $DB->get_recordset_select($tablename, 'course = 3'));
1089 foreach ($rs as $record) {
1093 $this->assertEqual(2, $counter);
1096 // * limits are tested in test_get_recordset_sql()
1099 public function test_get_recordset_sql() {
1101 $dbman = $DB->get_manager();
1103 $table = $this->get_test_table();
1104 $tablename = $table->getName();
1106 $table->add_field('id', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, XMLDB_SEQUENCE, null);
1107 $table->add_field('course', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '0');
1108 $table->add_key('primary', XMLDB_KEY_PRIMARY, array('id'));
1109 $dbman->create_table($table);
1111 $inskey1 = $DB->insert_record($tablename, array('course' => 3));
1112 $inskey2 = $DB->insert_record($tablename, array('course' => 5));
1113 $inskey3 = $DB->insert_record($tablename, array('course' => 4));
1114 $inskey4 = $DB->insert_record($tablename, array('course' => 3));
1115 $inskey5 = $DB->insert_record($tablename, array('course' => 2));
1116 $inskey6 = $DB->insert_record($tablename, array('course' => 1));
1117 $inskey7 = $DB->insert_record($tablename, array('course' => 0));
1119 $rs = $DB->get_recordset_sql("SELECT * FROM {{$tablename}} WHERE course = ?", array(3));
1121 foreach ($rs as $record) {
1125 $this->assertEqual(2, $counter);
1127 // limits - only need to test this case, the rest have been tested by test_get_records_sql()
1128 // only limitfrom = skips that number of records
1129 $rs = $DB->get_recordset_sql("SELECT * FROM {{$tablename}} ORDER BY id", null, 2, 0);
1131 foreach($rs as $key => $record) {
1132 $records[$key] = $record;
1135 $this->assertEqual(5, count($records));
1136 $this->assertEqual($inskey3, reset($records)->id);
1137 $this->assertEqual($inskey7, end($records)->id);
1139 // note: fetching nulls, empties, LOBs already tested by test_insert_record() no needed here
1142 public function test_get_records() {
1144 $dbman = $DB->get_manager();
1146 $table = $this->get_test_table();
1147 $tablename = $table->getName();
1149 $table->add_field('id', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, XMLDB_SEQUENCE, null);
1150 $table->add_field('course', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '0');
1151 $table->add_field('onetext', XMLDB_TYPE_TEXT, 'big', null, null, null);
1152 $table->add_key('primary', XMLDB_KEY_PRIMARY, array('id'));
1153 $dbman->create_table($table);
1155 $DB->insert_record($tablename, array('course' => 3));
1156 $DB->insert_record($tablename, array('course' => 3));
1157 $DB->insert_record($tablename, array('course' => 5));
1158 $DB->insert_record($tablename, array('course' => 2));
1161 $records = $DB->get_records($tablename);
1162 $this->assertEqual(4, count($records));
1163 $this->assertEqual(3, $records[1]->course);
1164 $this->assertEqual(3, $records[2]->course);
1165 $this->assertEqual(5, $records[3]->course);
1166 $this->assertEqual(2, $records[4]->course);
1168 // Records matching certain conditions
1169 $records = $DB->get_records($tablename, array('course' => 3));
1170 $this->assertEqual(2, count($records));
1171 $this->assertEqual(3, $records[1]->course);
1172 $this->assertEqual(3, $records[2]->course);
1174 // All records sorted by course
1175 $records = $DB->get_records($tablename, null, 'course');
1176 $this->assertEqual(4, count($records));
1177 $current_record = reset($records);
1178 $this->assertEqual(4, $current_record->id);
1179 $current_record = next($records);
1180 $this->assertEqual(1, $current_record->id);
1181 $current_record = next($records);
1182 $this->assertEqual(2, $current_record->id);
1183 $current_record = next($records);
1184 $this->assertEqual(3, $current_record->id);
1186 // All records, but get only one field
1187 $records = $DB->get_records($tablename, null, '', 'id');
1188 $this->assertFalse(isset($records[1]->course));
1189 $this->assertTrue(isset($records[1]->id));
1190 $this->assertEqual(4, count($records));
1192 // Booleans into params
1193 $records = $DB->get_records($tablename, array('course' => true));
1194 $this->assertEqual(0, count($records));
1195 $records = $DB->get_records($tablename, array('course' => false));
1196 $this->assertEqual(0, count($records));
1198 // test for exception throwing on text conditions being compared. (MDL-24863, unwanted auto conversion of param to int)
1199 $conditions = array('onetext' => '1');
1201 $records = $DB->get_records($tablename, $conditions);
1202 $this->fail('An Exception is missing, expected due to equating of text fields');
1203 } catch (exception $e) {
1204 $this->assertTrue($e instanceof dml_exception);
1205 $this->assertEqual($e->errorcode, 'textconditionsnotallowed');
1208 // note: delegate limits testing to test_get_records_sql()
1211 public function test_get_records_list() {
1213 $dbman = $DB->get_manager();
1215 $table = $this->get_test_table();
1216 $tablename = $table->getName();
1218 $table->add_field('id', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, XMLDB_SEQUENCE, null);
1219 $table->add_field('course', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '0');
1220 $table->add_key('primary', XMLDB_KEY_PRIMARY, array('id'));
1221 $dbman->create_table($table);
1223 $DB->insert_record($tablename, array('course' => 3));
1224 $DB->insert_record($tablename, array('course' => 3));
1225 $DB->insert_record($tablename, array('course' => 5));
1226 $DB->insert_record($tablename, array('course' => 2));
1228 $records = $DB->get_records_list($tablename, 'course', array(3, 2));
1229 $this->assertTrue(is_array($records));
1230 $this->assertEqual(3, count($records));
1231 $this->assertEqual(1, reset($records)->id);
1232 $this->assertEqual(2, next($records)->id);
1233 $this->assertEqual(4, next($records)->id);
1235 $this->assertIdentical(array(), $records = $DB->get_records_list($tablename, 'course', array())); /// Must return 0 rows without conditions. MDL-17645
1236 $this->assertEqual(0, count($records));
1238 // note: delegate limits testing to test_get_records_sql()
1241 public function test_get_records_sql() {
1243 $dbman = $DB->get_manager();
1245 $table = $this->get_test_table();
1246 $tablename = $table->getName();
1248 $table->add_field('id', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, XMLDB_SEQUENCE, null);
1249 $table->add_field('course', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '0');
1250 $table->add_key('primary', XMLDB_KEY_PRIMARY, array('id'));
1251 $dbman->create_table($table);
1253 $inskey1 = $DB->insert_record($tablename, array('course' => 3));
1254 $inskey2 = $DB->insert_record($tablename, array('course' => 5));
1255 $inskey3 = $DB->insert_record($tablename, array('course' => 4));
1256 $inskey4 = $DB->insert_record($tablename, array('course' => 3));
1257 $inskey5 = $DB->insert_record($tablename, array('course' => 2));
1258 $inskey6 = $DB->insert_record($tablename, array('course' => 1));
1259 $inskey7 = $DB->insert_record($tablename, array('course' => 0));
1261 $table2 = $this->get_test_table("2");
1262 $tablename2 = $table2->getName();
1263 $table2->add_field('id', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, XMLDB_SEQUENCE, null);
1264 $table2->add_field('course', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '0');
1265 $table2->add_field('nametext', XMLDB_TYPE_TEXT, 'small', null, null, null, null);
1266 $table2->add_key('primary', XMLDB_KEY_PRIMARY, array('id'));
1267 $dbman->create_table($table2);
1269 $DB->insert_record($tablename2, array('course'=>3, 'nametext'=>'badabing'));
1270 $DB->insert_record($tablename2, array('course'=>4, 'nametext'=>'badabang'));
1271 $DB->insert_record($tablename2, array('course'=>5, 'nametext'=>'badabung'));
1272 $DB->insert_record($tablename2, array('course'=>6, 'nametext'=>'badabong'));
1274 $records = $DB->get_records_sql("SELECT * FROM {{$tablename}} WHERE course = ?", array(3));
1275 $this->assertEqual(2, count($records));
1276 $this->assertEqual($inskey1, reset($records)->id);
1277 $this->assertEqual($inskey4, next($records)->id);
1279 // Awful test, requires debug enabled and sent to browser. Let's do that and restore after test
1280 $this->enable_debugging();
1281 $records = $DB->get_records_sql("SELECT course AS id, course AS course FROM {{$tablename}}", null);
1282 $this->assertFalse($this->get_debugging() === '');
1283 $this->assertEqual(6, count($records));
1285 // negative limits = no limits
1286 $records = $DB->get_records_sql("SELECT * FROM {{$tablename}} ORDER BY id", null, -1, -1);
1287 $this->assertEqual(7, count($records));
1289 // zero limits = no limits
1290 $records = $DB->get_records_sql("SELECT * FROM {{$tablename}} ORDER BY id", null, 0, 0);
1291 $this->assertEqual(7, count($records));
1293 // only limitfrom = skips that number of records
1294 $records = $DB->get_records_sql("SELECT * FROM {{$tablename}} ORDER BY id", null, 2, 0);
1295 $this->assertEqual(5, count($records));
1296 $this->assertEqual($inskey3, reset($records)->id);
1297 $this->assertEqual($inskey7, end($records)->id);
1299 // only limitnum = fetches that number of records
1300 $records = $DB->get_records_sql("SELECT * FROM {{$tablename}} ORDER BY id", null, 0, 3);
1301 $this->assertEqual(3, count($records));
1302 $this->assertEqual($inskey1, reset($records)->id);
1303 $this->assertEqual($inskey3, end($records)->id);
1305 // both limitfrom and limitnum = skips limitfrom records and fetches limitnum ones
1306 $records = $DB->get_records_sql("SELECT * FROM {{$tablename}} ORDER BY id", null, 3, 2);
1307 $this->assertEqual(2, count($records));
1308 $this->assertEqual($inskey4, reset($records)->id);
1309 $this->assertEqual($inskey5, end($records)->id);
1311 // both limitfrom and limitnum in query having subqueris
1312 // note the subquery skips records with course = 0 and 3
1313 $sql = "SELECT * FROM {{$tablename}}
1314 WHERE course NOT IN (
1315 SELECT course FROM {{$tablename}}
1316 WHERE course IN (0, 3))
1318 $records = $DB->get_records_sql($sql, null, 0, 2); // Skip 0, get 2
1319 $this->assertEqual(2, count($records));
1320 $this->assertEqual($inskey6, reset($records)->id);
1321 $this->assertEqual($inskey5, end($records)->id);
1322 $records = $DB->get_records_sql($sql, null, 2, 2); // Skip 2, get 2
1323 $this->assertEqual(2, count($records));
1324 $this->assertEqual($inskey3, reset($records)->id);
1325 $this->assertEqual($inskey2, end($records)->id);
1327 // test 2 tables with aliases and limits with order bys
1328 $sql = "SELECT t1.id, t1.course AS cid, t2.nametext
1329 FROM {{$tablename}} t1, {{$tablename2}} t2
1330 WHERE t2.course=t1.course
1331 ORDER BY t1.course, ". $DB->sql_compare_text('t2.nametext');
1332 $records = $DB->get_records_sql($sql, null, 2, 2); // Skip courses 3 and 6, get 4 and 5
1333 $this->assertEqual(2, count($records));
1334 $this->assertEqual('5', end($records)->cid);
1335 $this->assertEqual('4', reset($records)->cid);
1337 // test 2 tables with aliases and limits with the highest INT limit works
1338 $records = $DB->get_records_sql($sql, null, 2, PHP_INT_MAX); // Skip course {3,6}, get {4,5}
1339 $this->assertEqual(2, count($records));
1340 $this->assertEqual('5', end($records)->cid);
1341 $this->assertEqual('4', reset($records)->cid);
1343 // test 2 tables with aliases and limits with order bys (limit which is highest INT number)
1344 $records = $DB->get_records_sql($sql, null, PHP_INT_MAX, 2); // Skip all courses
1345 $this->assertEqual(0, count($records));
1347 // test 2 tables with aliases and limits with order bys (limit which s highest INT number)
1348 $records = $DB->get_records_sql($sql, null, PHP_INT_MAX, PHP_INT_MAX); // Skip all courses
1349 $this->assertEqual(0, count($records));
1351 // TODO: Test limits in queries having DISTINCT clauses
1353 // note: fetching nulls, empties, LOBs already tested by test_update_record() no needed here
1356 public function test_get_records_menu() {
1358 $dbman = $DB->get_manager();
1360 $table = $this->get_test_table();
1361 $tablename = $table->getName();
1363 $table->add_field('id', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, XMLDB_SEQUENCE, null);
1364 $table->add_field('course', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '0');
1365 $table->add_key('primary', XMLDB_KEY_PRIMARY, array('id'));
1366 $dbman->create_table($table);
1368 $DB->insert_record($tablename, array('course' => 3));
1369 $DB->insert_record($tablename, array('course' => 3));
1370 $DB->insert_record($tablename, array('course' => 5));
1371 $DB->insert_record($tablename, array('course' => 2));
1373 $records = $DB->get_records_menu($tablename, array('course' => 3));
1374 $this->assertTrue(is_array($records));
1375 $this->assertEqual(2, count($records));
1376 $this->assertFalse(empty($records[1]));
1377 $this->assertFalse(empty($records[2]));
1378 $this->assertEqual(3, $records[1]);
1379 $this->assertEqual(3, $records[2]);
1381 // note: delegate limits testing to test_get_records_sql()
1384 public function test_get_records_select_menu() {
1386 $dbman = $DB->get_manager();
1388 $table = $this->get_test_table();
1389 $tablename = $table->getName();
1391 $table->add_field('id', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, XMLDB_SEQUENCE, null);
1392 $table->add_field('course', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '0');
1393 $table->add_key('primary', XMLDB_KEY_PRIMARY, array('id'));
1394 $dbman->create_table($table);
1396 $DB->insert_record($tablename, array('course' => 3));
1397 $DB->insert_record($tablename, array('course' => 2));
1398 $DB->insert_record($tablename, array('course' => 3));
1399 $DB->insert_record($tablename, array('course' => 5));
1401 $records = $DB->get_records_select_menu($tablename, "course > ?", array(2));
1402 $this->assertTrue(is_array($records));
1404 $this->assertEqual(3, count($records));
1405 $this->assertFalse(empty($records[1]));
1406 $this->assertTrue(empty($records[2]));
1407 $this->assertFalse(empty($records[3]));
1408 $this->assertFalse(empty($records[4]));
1409 $this->assertEqual(3, $records[1]);
1410 $this->assertEqual(3, $records[3]);
1411 $this->assertEqual(5, $records[4]);
1413 // note: delegate limits testing to test_get_records_sql()
1416 public function test_get_records_sql_menu() {
1418 $dbman = $DB->get_manager();
1420 $table = $this->get_test_table();
1421 $tablename = $table->getName();
1423 $table->add_field('id', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, XMLDB_SEQUENCE, null);
1424 $table->add_field('course', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '0');
1425 $table->add_key('primary', XMLDB_KEY_PRIMARY, array('id'));
1426 $dbman->create_table($table);
1428 $DB->insert_record($tablename, array('course' => 3));
1429 $DB->insert_record($tablename, array('course' => 2));
1430 $DB->insert_record($tablename, array('course' => 3));
1431 $DB->insert_record($tablename, array('course' => 5));
1433 $records = $DB->get_records_sql_menu("SELECT * FROM {{$tablename}} WHERE course > ?", array(2));
1434 $this->assertTrue(is_array($records));
1436 $this->assertEqual(3, count($records));
1437 $this->assertFalse(empty($records[1]));
1438 $this->assertTrue(empty($records[2]));
1439 $this->assertFalse(empty($records[3]));
1440 $this->assertFalse(empty($records[4]));
1441 $this->assertEqual(3, $records[1]);
1442 $this->assertEqual(3, $records[3]);
1443 $this->assertEqual(5, $records[4]);
1445 // note: delegate limits testing to test_get_records_sql()
1448 public function test_get_record() {
1450 $dbman = $DB->get_manager();
1452 $table = $this->get_test_table();
1453 $tablename = $table->getName();
1455 $table->add_field('id', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, XMLDB_SEQUENCE, null);
1456 $table->add_field('course', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '0');
1457 $table->add_key('primary', XMLDB_KEY_PRIMARY, array('id'));
1458 $dbman->create_table($table);
1460 $DB->insert_record($tablename, array('course' => 3));
1461 $DB->insert_record($tablename, array('course' => 2));
1463 $record = $DB->get_record($tablename, array('id' => 2));
1464 $this->assertTrue($record instanceof stdClass);
1466 $this->assertEqual(2, $record->course);
1467 $this->assertEqual(2, $record->id);
1471 public function test_get_record_select() {
1473 $dbman = $DB->get_manager();
1475 $table = $this->get_test_table();
1476 $tablename = $table->getName();
1478 $table->add_field('id', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, XMLDB_SEQUENCE, null);
1479 $table->add_field('course', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '0');
1480 $table->add_key('primary', XMLDB_KEY_PRIMARY, array('id'));
1481 $dbman->create_table($table);
1483 $DB->insert_record($tablename, array('course' => 3));
1484 $DB->insert_record($tablename, array('course' => 2));
1486 $record = $DB->get_record_select($tablename, "id = ?", array(2));
1487 $this->assertTrue($record instanceof stdClass);
1489 $this->assertEqual(2, $record->course);
1491 // note: delegates limit testing to test_get_records_sql()
1494 public function test_get_record_sql() {
1496 $dbman = $DB->get_manager();
1498 $table = $this->get_test_table();
1499 $tablename = $table->getName();
1501 $table->add_field('id', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, XMLDB_SEQUENCE, null);
1502 $table->add_field('course', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '0');
1503 $table->add_key('primary', XMLDB_KEY_PRIMARY, array('id'));
1504 $dbman->create_table($table);
1506 $DB->insert_record($tablename, array('course' => 3));
1507 $DB->insert_record($tablename, array('course' => 2));
1510 $record = $DB->get_record_sql("SELECT * FROM {{$tablename}} WHERE id = ?", array(2));
1511 $this->assertTrue($record instanceof stdClass);
1512 $this->assertEqual(2, $record->course);
1513 $this->assertEqual(2, $record->id);
1515 // backwards compatibility with $ignoremultiple
1516 $this->assertFalse(IGNORE_MISSING);
1517 $this->assertTrue(IGNORE_MULTIPLE);
1519 // record not found - ignore
1520 $this->assertFalse($DB->get_record_sql("SELECT * FROM {{$tablename}} WHERE id = ?", array(666), IGNORE_MISSING));
1521 $this->assertFalse($DB->get_record_sql("SELECT * FROM {{$tablename}} WHERE id = ?", array(666), IGNORE_MULTIPLE));
1523 // record not found error
1525 $DB->get_record_sql("SELECT * FROM {{$tablename}} WHERE id = ?", array(666), MUST_EXIST);
1526 $this->fail("Exception expected");
1527 } catch (dml_missing_record_exception $e) {
1528 $this->assertTrue(true);
1531 $this->enable_debugging();
1532 $this->assertTrue($DB->get_record_sql("SELECT * FROM {{$tablename}}", array(), IGNORE_MISSING));
1533 $this->assertFalse($this->get_debugging() === '');
1535 // multiple matches ignored
1536 $this->assertTrue($DB->get_record_sql("SELECT * FROM {{$tablename}}", array(), IGNORE_MULTIPLE));
1538 // multiple found error
1540 $DB->get_record_sql("SELECT * FROM {{$tablename}}", array(), MUST_EXIST);
1541 $this->fail("Exception expected");
1542 } catch (dml_multiple_records_exception $e) {
1543 $this->assertTrue(true);
1547 public function test_get_field() {
1549 $dbman = $DB->get_manager();
1551 $table = $this->get_test_table();
1552 $tablename = $table->getName();
1554 $table->add_field('id', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, XMLDB_SEQUENCE, null);
1555 $table->add_field('course', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '0');
1556 $table->add_field('onetext', XMLDB_TYPE_TEXT, 'big', null, null, null);
1557 $table->add_key('primary', XMLDB_KEY_PRIMARY, array('id'));
1558 $dbman->create_table($table);
1560 $id1 = $DB->insert_record($tablename, array('course' => 3));
1561 $DB->insert_record($tablename, array('course' => 5));
1562 $DB->insert_record($tablename, array('course' => 5));
1564 $this->assertEqual(3, $DB->get_field($tablename, 'course', array('id' => $id1)));
1565 $this->assertEqual(3, $DB->get_field($tablename, 'course', array('course' => 3)));
1567 $this->assertIdentical(false, $DB->get_field($tablename, 'course', array('course' => 11), IGNORE_MISSING));
1569 $DB->get_field($tablename, 'course', array('course' => 4), MUST_EXIST);
1570 $this->assertFail('Exception expected due to missing record');
1571 } catch (dml_exception $ex) {
1572 $this->assertTrue(true);
1575 $this->enable_debugging();
1576 $this->assertEqual(5, $DB->get_field($tablename, 'course', array('course' => 5), IGNORE_MULTIPLE));
1577 $this->assertIdentical($this->get_debugging(), '');
1579 $this->enable_debugging();
1580 $this->assertEqual(5, $DB->get_field($tablename, 'course', array('course' => 5), IGNORE_MISSING));
1581 $this->assertFalse($this->get_debugging() === '');
1583 // test for exception throwing on text conditions being compared. (MDL-24863, unwanted auto conversion of param to int)
1584 $conditions = array('onetext' => '1');
1586 $DB->get_field($tablename, 'course', $conditions);
1587 $this->fail('An Exception is missing, expected due to equating of text fields');
1588 } catch (exception $e) {
1589 $this->assertTrue($e instanceof dml_exception);
1590 $this->assertEqual($e->errorcode, 'textconditionsnotallowed');
1594 public function test_get_field_select() {
1596 $dbman = $DB->get_manager();
1598 $table = $this->get_test_table();
1599 $tablename = $table->getName();
1601 $table->add_field('id', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, XMLDB_SEQUENCE, null);
1602 $table->add_field('course', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '0');
1603 $table->add_key('primary', XMLDB_KEY_PRIMARY, array('id'));
1604 $dbman->create_table($table);
1606 $DB->insert_record($tablename, array('course' => 3));
1608 $this->assertEqual(3, $DB->get_field_select($tablename, 'course', "id = ?", array(1)));
1611 public function test_get_field_sql() {
1613 $dbman = $DB->get_manager();
1615 $table = $this->get_test_table();
1616 $tablename = $table->getName();
1618 $table->add_field('id', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, XMLDB_SEQUENCE, null);
1619 $table->add_field('course', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '0');
1620 $table->add_key('primary', XMLDB_KEY_PRIMARY, array('id'));
1621 $dbman->create_table($table);
1623 $DB->insert_record($tablename, array('course' => 3));
1625 $this->assertEqual(3, $DB->get_field_sql("SELECT course FROM {{$tablename}} WHERE id = ?", array(1)));
1628 public function test_get_fieldset_select() {
1630 $dbman = $DB->get_manager();
1632 $table = $this->get_test_table();
1633 $tablename = $table->getName();
1635 $table->add_field('id', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, XMLDB_SEQUENCE, null);
1636 $table->add_field('course', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '0');
1637 $table->add_key('primary', XMLDB_KEY_PRIMARY, array('id'));
1638 $dbman->create_table($table);
1640 $DB->insert_record($tablename, array('course' => 1));
1641 $DB->insert_record($tablename, array('course' => 3));
1642 $DB->insert_record($tablename, array('course' => 2));
1643 $DB->insert_record($tablename, array('course' => 6));
1645 $fieldset = $DB->get_fieldset_select($tablename, 'course', "course > ?", array(1));
1646 $this->assertTrue(is_array($fieldset));
1648 $this->assertEqual(3, count($fieldset));
1649 $this->assertEqual(3, $fieldset[0]);
1650 $this->assertEqual(2, $fieldset[1]);
1651 $this->assertEqual(6, $fieldset[2]);
1654 public function test_get_fieldset_sql() {
1656 $dbman = $DB->get_manager();
1658 $table = $this->get_test_table();
1659 $tablename = $table->getName();
1661 $table->add_field('id', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, XMLDB_SEQUENCE, null);
1662 $table->add_field('course', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '0');
1663 $table->add_key('primary', XMLDB_KEY_PRIMARY, array('id'));
1664 $dbman->create_table($table);
1666 $DB->insert_record($tablename, array('course' => 1));
1667 $DB->insert_record($tablename, array('course' => 3));
1668 $DB->insert_record($tablename, array('course' => 2));
1669 $DB->insert_record($tablename, array('course' => 6));
1671 $fieldset = $DB->get_fieldset_sql("SELECT * FROM {{$tablename}} WHERE course > ?", array(1));
1672 $this->assertTrue(is_array($fieldset));
1674 $this->assertEqual(3, count($fieldset));
1675 $this->assertEqual(2, $fieldset[0]);
1676 $this->assertEqual(3, $fieldset[1]);
1677 $this->assertEqual(4, $fieldset[2]);
1680 public function test_insert_record_raw() {
1682 $dbman = $DB->get_manager();
1684 $table = $this->get_test_table();
1685 $tablename = $table->getName();
1687 $table->add_field('id', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, XMLDB_SEQUENCE, null);
1688 $table->add_field('course', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '0');
1689 $table->add_field('onechar', XMLDB_TYPE_CHAR, '100', null, null, null, 'onestring');
1690 $table->add_key('primary', XMLDB_KEY_PRIMARY, array('id'));
1691 $dbman->create_table($table);
1693 $record = (object)array('course' => 1, 'onechar' => 'xx');
1694 $before = clone($record);
1695 $result = $DB->insert_record_raw($tablename, $record);
1696 $this->assertIdentical(1, $result);
1697 $this->assertIdentical($record, $before);
1699 $record = $DB->get_record($tablename, array('course' => 1));
1700 $this->assertTrue($record instanceof stdClass);
1701 $this->assertIdentical('xx', $record->onechar);
1703 $result = $DB->insert_record_raw($tablename, array('course' => 2, 'onechar' => 'yy'), false);
1704 $this->assertIdentical(true, $result);
1706 // note: bulk not implemented yet
1707 $DB->insert_record_raw($tablename, array('course' => 3, 'onechar' => 'zz'), true, true);
1708 $record = $DB->get_record($tablename, array('course' => 3));
1709 $this->assertTrue($record instanceof stdClass);
1710 $this->assertIdentical('zz', $record->onechar);
1712 // custom sequence (id) - returnid is ignored
1713 $result = $DB->insert_record_raw($tablename, array('id' => 10, 'course' => 3, 'onechar' => 'bb'), true, false, true);
1714 $this->assertIdentical(true, $result);
1715 $record = $DB->get_record($tablename, array('id' => 10));
1716 $this->assertTrue($record instanceof stdClass);
1717 $this->assertIdentical('bb', $record->onechar);
1719 // custom sequence - missing id error
1721 $DB->insert_record_raw($tablename, array('course' => 3, 'onechar' => 'bb'), true, false, true);
1722 $this->assertFail('Exception expected due to missing record');
1723 } catch (coding_exception $ex) {
1724 $this->assertTrue(true);
1727 // wrong column error
1729 $DB->insert_record_raw($tablename, array('xxxxx' => 3, 'onechar' => 'bb'));
1730 $this->assertFail('Exception expected due to invalid column');
1731 } catch (dml_write_exception $ex) {
1732 $this->assertTrue(true);
1736 public function test_insert_record() {
1737 // All the information in this test is fetched from DB by get_recordset() so we
1738 // have such method properly tested against nulls, empties and friends...
1741 $dbman = $DB->get_manager();
1743 $table = $this->get_test_table();
1744 $tablename = $table->getName();
1746 $table->add_field('id', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, XMLDB_SEQUENCE, null);
1747 $table->add_field('course', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '0');
1748 $table->add_field('oneint', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, null, null, 100);
1749 $table->add_field('onenum', XMLDB_TYPE_NUMBER, '10,2', null, null, null, 200);
1750 $table->add_field('onechar', XMLDB_TYPE_CHAR, '100', null, null, null, 'onestring');
1751 $table->add_field('onetext', XMLDB_TYPE_TEXT, 'big', null, null, null);
1752 $table->add_field('onebinary', XMLDB_TYPE_BINARY, 'big', null, null, null);
1753 $table->add_key('primary', XMLDB_KEY_PRIMARY, array('id'));
1754 $dbman->create_table($table);
1756 $this->assertIdentical(1, $DB->insert_record($tablename, array('course' => 1), true));
1757 $record = $DB->get_record($tablename, array('course' => 1));
1758 $this->assertEqual(1, $record->id);
1759 $this->assertEqual(100, $record->oneint); // Just check column defaults have been applied
1760 $this->assertEqual(200, $record->onenum);
1761 $this->assertIdentical('onestring', $record->onechar);
1762 $this->assertNull($record->onetext);
1763 $this->assertNull($record->onebinary);
1765 // without returning id, bulk not implemented
1766 $result = $this->assertIdentical(true, $DB->insert_record($tablename, array('course' => 99), false, true));
1767 $record = $DB->get_record($tablename, array('course' => 99));
1768 $this->assertEqual(2, $record->id);
1769 $this->assertEqual(99, $record->course);
1771 // Check nulls are set properly for all types
1772 $record = new stdClass();
1773 $record->oneint = null;
1774 $record->onenum = null;
1775 $record->onechar = null;
1776 $record->onetext = null;
1777 $record->onebinary = null;
1778 $recid = $DB->insert_record($tablename, $record);
1779 $record = $DB->get_record($tablename, array('id' => $recid));
1780 $this->assertEqual(0, $record->course);
1781 $this->assertNull($record->oneint);
1782 $this->assertNull($record->onenum);
1783 $this->assertNull($record->onechar);
1784 $this->assertNull($record->onetext);
1785 $this->assertNull($record->onebinary);
1787 // Check zeros are set properly for all types
1788 $record = new stdClass();
1789 $record->oneint = 0;
1790 $record->onenum = 0;
1791 $recid = $DB->insert_record($tablename, $record);
1792 $record = $DB->get_record($tablename, array('id' => $recid));
1793 $this->assertEqual(0, $record->oneint);
1794 $this->assertEqual(0, $record->onenum);
1796 // Check booleans are set properly for all types
1797 $record = new stdClass();
1798 $record->oneint = true; // trues
1799 $record->onenum = true;
1800 $record->onechar = true;
1801 $record->onetext = true;
1802 $recid = $DB->insert_record($tablename, $record);
1803 $record = $DB->get_record($tablename, array('id' => $recid));
1804 $this->assertEqual(1, $record->oneint);
1805 $this->assertEqual(1, $record->onenum);
1806 $this->assertEqual(1, $record->onechar);
1807 $this->assertEqual(1, $record->onetext);
1809 $record = new stdClass();
1810 $record->oneint = false; // falses
1811 $record->onenum = false;
1812 $record->onechar = false;
1813 $record->onetext = false;
1814 $recid = $DB->insert_record($tablename, $record);
1815 $record = $DB->get_record($tablename, array('id' => $recid));
1816 $this->assertEqual(0, $record->oneint);
1817 $this->assertEqual(0, $record->onenum);
1818 $this->assertEqual(0, $record->onechar);
1819 $this->assertEqual(0, $record->onetext);
1821 // Check string data causes exception in numeric types
1822 $record = new stdClass();
1823 $record->oneint = 'onestring';
1824 $record->onenum = 0;
1826 $DB->insert_record($tablename, $record);
1827 $this->fail("Expecting an exception, none occurred");
1828 } catch (exception $e) {
1829 $this->assertTrue($e instanceof dml_exception);
1831 $record = new stdClass();
1832 $record->oneint = 0;
1833 $record->onenum = 'onestring';
1835 $DB->insert_record($tablename, $record);
1836 $this->fail("Expecting an exception, none occurred");
1837 } catch (exception $e) {
1838 $this->assertTrue($e instanceof dml_exception);
1841 // Check empty string data is stored as 0 in numeric datatypes
1842 $record = new stdClass();
1843 $record->oneint = ''; // empty string
1844 $record->onenum = 0;
1845 $recid = $DB->insert_record($tablename, $record);
1846 $record = $DB->get_record($tablename, array('id' => $recid));
1847 $this->assertTrue(is_numeric($record->oneint) && $record->oneint == 0);
1849 $record = new stdClass();
1850 $record->oneint = 0;
1851 $record->onenum = ''; // empty string
1852 $recid = $DB->insert_record($tablename, $record);
1853 $record = $DB->get_record($tablename, array('id' => $recid));
1854 $this->assertTrue(is_numeric($record->onenum) && $record->onenum == 0);
1856 // Check empty strings are set properly in string types
1857 $record = new stdClass();
1858 $record->oneint = 0;
1859 $record->onenum = 0;
1860 $record->onechar = '';
1861 $record->onetext = '';
1862 $recid = $DB->insert_record($tablename, $record);
1863 $record = $DB->get_record($tablename, array('id' => $recid));
1864 $this->assertTrue($record->onechar === '');
1865 $this->assertTrue($record->onetext === '');
1867 // Check operation ((210.10 + 39.92) - 150.02) against numeric types
1868 $record = new stdClass();
1869 $record->oneint = ((210.10 + 39.92) - 150.02);
1870 $record->onenum = ((210.10 + 39.92) - 150.02);
1871 $recid = $DB->insert_record($tablename, $record);
1872 $record = $DB->get_record($tablename, array('id' => $recid));
1873 $this->assertEqual(100, $record->oneint);
1874 $this->assertEqual(100, $record->onenum);
1876 // Check various quotes/backslashes combinations in string types
1877 $teststrings = array(
1878 'backslashes and quotes alone (even): "" \'\' \\\\',
1879 'backslashes and quotes alone (odd): """ \'\'\' \\\\\\',
1880 'backslashes and quotes sequences (even): \\"\\" \\\'\\\'',
1881 'backslashes and quotes sequences (odd): \\"\\"\\" \\\'\\\'\\\'');
1882 foreach ($teststrings as $teststring) {
1883 $record = new stdClass();
1884 $record->onechar = $teststring;
1885 $record->onetext = $teststring;
1886 $recid = $DB->insert_record($tablename, $record);
1887 $record = $DB->get_record($tablename, array('id' => $recid));
1888 $this->assertEqual($teststring, $record->onechar);
1889 $this->assertEqual($teststring, $record->onetext);
1892 // Check LOBs in text/binary columns
1893 $clob = file_get_contents(dirname(__FILE__).'/fixtures/clob.txt');
1894 $blob = file_get_contents(dirname(__FILE__).'/fixtures/randombinary');
1895 $record = new stdClass();
1896 $record->onetext = $clob;
1897 $record->onebinary = $blob;
1898 $recid = $DB->insert_record($tablename, $record);
1899 $rs = $DB->get_recordset($tablename, array('id' => $recid));
1900 $record = $rs->current();
1902 $this->assertEqual($clob, $record->onetext, 'Test CLOB insert (full contents output disabled)');
1903 $this->assertEqual($blob, $record->onebinary, 'Test BLOB insert (full contents output disabled)');
1905 // And "small" LOBs too, just in case
1906 $newclob = substr($clob, 0, 500);
1907 $newblob = substr($blob, 0, 250);
1908 $record = new stdClass();
1909 $record->onetext = $newclob;
1910 $record->onebinary = $newblob;
1911 $recid = $DB->insert_record($tablename, $record);
1912 $rs = $DB->get_recordset($tablename, array('id' => $recid));
1913 $record = $rs->current();
1915 $this->assertEqual($newclob, $record->onetext, 'Test "small" CLOB insert (full contents output disabled)');
1916 $this->assertEqual($newblob, $record->onebinary, 'Test "small" BLOB insert (full contents output disabled)');
1917 $this->assertEqual(false, $rs->key()); // Ensure recordset key() method to be working ok after closing
1919 // And "diagnostic" LOBs too, just in case
1920 $newclob = '\'"\\;/ěščřžýáíé';
1921 $newblob = '\'"\\;/ěščřžýáíé';
1922 $record = new stdClass();
1923 $record->onetext = $newclob;
1924 $record->onebinary = $newblob;
1925 $recid = $DB->insert_record($tablename, $record);
1926 $rs = $DB->get_recordset($tablename, array('id' => $recid));
1927 $record = $rs->current();
1929 $this->assertIdentical($newclob, $record->onetext);
1930 $this->assertIdentical($newblob, $record->onebinary);
1931 $this->assertEqual(false, $rs->key()); // Ensure recordset key() method to be working ok after closing
1933 // test data is not modified
1934 $record = new stdClass();
1935 $record->id = -1; // has to be ignored
1936 $record->course = 3;
1937 $record->lalala = 'lalal'; // unused
1938 $before = clone($record);
1939 $DB->insert_record($tablename, $record);
1940 $this->assertEqual($record, $before);
1942 // make sure the id is always increasing and never reuses the same id
1943 $id1 = $DB->insert_record($tablename, array('course' => 3));
1944 $id2 = $DB->insert_record($tablename, array('course' => 3));
1945 $this->assertTrue($id1 < $id2);
1946 $DB->delete_records($tablename, array('id'=>$id2));
1947 $id3 = $DB->insert_record($tablename, array('course' => 3));
1948 $this->assertTrue($id2 < $id3);
1949 $DB->delete_records($tablename, array());
1950 $id4 = $DB->insert_record($tablename, array('course' => 3));
1951 $this->assertTrue($id3 < $id4);
1953 // Test saving a float in a CHAR column, and reading it back.
1954 $id = $DB->insert_record($tablename, array('onechar' => 1.0));
1955 $this->assertEqual(1.0, $DB->get_field($tablename, 'onechar', array('id' => $id)));
1956 $id = $DB->insert_record($tablename, array('onechar' => 1e20));
1957 $this->assertEqual(1e20, $DB->get_field($tablename, 'onechar', array('id' => $id)));
1958 $id = $DB->insert_record($tablename, array('onechar' => 1e-4));
1959 $this->assertEqual(1e-4, $DB->get_field($tablename, 'onechar', array('id' => $id)));
1960 $id = $DB->insert_record($tablename, array('onechar' => 1e-5));
1961 $this->assertEqual(1e-5, $DB->get_field($tablename, 'onechar', array('id' => $id)));
1962 $id = $DB->insert_record($tablename, array('onechar' => 1e-300));
1963 $this->assertEqual(1e-300, $DB->get_field($tablename, 'onechar', array('id' => $id)));
1964 $id = $DB->insert_record($tablename, array('onechar' => 1e300));
1965 $this->assertEqual(1e300, $DB->get_field($tablename, 'onechar', array('id' => $id)));
1967 // Test saving a float in a TEXT column, and reading it back.
1968 $id = $DB->insert_record($tablename, array('onetext' => 1.0));
1969 $this->assertEqual(1.0, $DB->get_field($tablename, 'onetext', array('id' => $id)));
1970 $id = $DB->insert_record($tablename, array('onetext' => 1e20));
1971 $this->assertEqual(1e20, $DB->get_field($tablename, 'onetext', array('id' => $id)));
1972 $id = $DB->insert_record($tablename, array('onetext' => 1e-4));
1973 $this->assertEqual(1e-4, $DB->get_field($tablename, 'onetext', array('id' => $id)));
1974 $id = $DB->insert_record($tablename, array('onetext' => 1e-5));
1975 $this->assertEqual(1e-5, $DB->get_field($tablename, 'onetext', array('id' => $id)));
1976 $id = $DB->insert_record($tablename, array('onetext' => 1e-300));
1977 $this->assertEqual(1e-300, $DB->get_field($tablename, 'onetext', array('id' => $id)));
1978 $id = $DB->insert_record($tablename, array('onetext' => 1e300));
1979 $this->assertEqual(1e300, $DB->get_field($tablename, 'onetext', array('id' => $id)));
1982 public function test_import_record() {
1983 // All the information in this test is fetched from DB by get_recordset() so we
1984 // have such method properly tested against nulls, empties and friends...
1987 $dbman = $DB->get_manager();
1989 $table = $this->get_test_table();
1990 $tablename = $table->getName();
1992 $table->add_field('id', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, XMLDB_SEQUENCE, null);
1993 $table->add_field('course', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '0');
1994 $table->add_field('oneint', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, null, null, 100);
1995 $table->add_field('onenum', XMLDB_TYPE_NUMBER, '10,2', null, null, null, 200);
1996 $table->add_field('onechar', XMLDB_TYPE_CHAR, '100', null, null, null, 'onestring');
1997 $table->add_field('onetext', XMLDB_TYPE_TEXT, 'big', null, null, null);
1998 $table->add_field('onebinary', XMLDB_TYPE_BINARY, 'big', null, null, null);
1999 $table->add_key('primary', XMLDB_KEY_PRIMARY, array('id'));
2000 $dbman->create_table($table);
2002 $this->assertIdentical(1, $DB->insert_record($tablename, array('course' => 1), true));
2003 $record = $DB->get_record($tablename, array('course' => 1));
2004 $this->assertEqual(1, $record->id);
2005 $this->assertEqual(100, $record->oneint); // Just check column defaults have been applied
2006 $this->assertEqual(200, $record->onenum);
2007 $this->assertIdentical('onestring', $record->onechar);
2008 $this->assertNull($record->onetext);
2009 $this->assertNull($record->onebinary);
2011 // ignore extra columns
2012 $record = (object)array('id'=>13, 'course'=>2, 'xxxx'=>788778);
2013 $before = clone($record);
2014 $this->assertIdentical(true, $DB->import_record($tablename, $record));
2015 $this->assertIdentical($record, $before);
2016 $records = $DB->get_records($tablename);
2017 $this->assertEqual(2, $records[13]->course);
2019 // Check nulls are set properly for all types
2020 $record = new stdClass();
2022 $record->oneint = null;
2023 $record->onenum = null;
2024 $record->onechar = null;
2025 $record->onetext = null;
2026 $record->onebinary = null;
2027 $this->assertTrue($DB->import_record($tablename, $record));
2028 $record = $DB->get_record($tablename, array('id' => 20));
2029 $this->assertEqual(0, $record->course);
2030 $this->assertNull($record->oneint);
2031 $this->assertNull($record->onenum);
2032 $this->assertNull($record->onechar);
2033 $this->assertNull($record->onetext);
2034 $this->assertNull($record->onebinary);
2036 // Check zeros are set properly for all types
2037 $record = new stdClass();
2039 $record->oneint = 0;
2040 $record->onenum = 0;
2041 $this->assertTrue($DB->import_record($tablename, $record));
2042 $record = $DB->get_record($tablename, array('id' => 23));
2043 $this->assertEqual(0, $record->oneint);
2044 $this->assertEqual(0, $record->onenum);
2046 // Check string data causes exception in numeric types
2047 $record = new stdClass();
2049 $record->oneint = 'onestring';
2050 $record->onenum = 0;
2052 $DB->import_record($tablename, $record);
2053 $this->fail("Expecting an exception, none occurred");
2054 } catch (exception $e) {
2055 $this->assertTrue($e instanceof dml_exception);
2057 $record = new stdClass();
2059 $record->oneint = 0;
2060 $record->onenum = 'onestring';
2062 $DB->import_record($tablename, $record);
2063 $this->fail("Expecting an exception, none occurred");
2064 } catch (exception $e) {
2065 $this->assertTrue($e instanceof dml_exception);
2068 // Check empty strings are set properly in string types
2069 $record = new stdClass();
2071 $record->oneint = 0;
2072 $record->onenum = 0;
2073 $record->onechar = '';
2074 $record->onetext = '';
2075 $this->assertTrue($DB->import_record($tablename, $record));
2076 $record = $DB->get_record($tablename, array('id' => 44));
2077 $this->assertTrue($record->onechar === '');
2078 $this->assertTrue($record->onetext === '');
2080 // Check operation ((210.10 + 39.92) - 150.02) against numeric types
2081 $record = new stdClass();
2083 $record->oneint = ((210.10 + 39.92) - 150.02);
2084 $record->onenum = ((210.10 + 39.92) - 150.02);
2085 $this->assertTrue($DB->import_record($tablename, $record));
2086 $record = $DB->get_record($tablename, array('id' => 47));
2087 $this->assertEqual(100, $record->oneint);
2088 $this->assertEqual(100, $record->onenum);
2090 // Check various quotes/backslashes combinations in string types
2092 $teststrings = array(
2093 'backslashes and quotes alone (even): "" \'\' \\\\',
2094 'backslashes and quotes alone (odd): """ \'\'\' \\\\\\',
2095 'backslashes and quotes sequences (even): \\"\\" \\\'\\\'',
2096 'backslashes and quotes sequences (odd): \\"\\"\\" \\\'\\\'\\\'');
2097 foreach ($teststrings as $teststring) {
2098 $record = new stdClass();
2100 $record->onechar = $teststring;
2101 $record->onetext = $teststring;
2102 $this->assertTrue($DB->import_record($tablename, $record));
2103 $record = $DB->get_record($tablename, array('id' => $i));
2104 $this->assertEqual($teststring, $record->onechar);
2105 $this->assertEqual($teststring, $record->onetext);
2109 // Check LOBs in text/binary columns
2110 $clob = file_get_contents(dirname(__FILE__).'/fixtures/clob.txt');
2111 $record = new stdClass();
2113 $record->onetext = $clob;
2114 $record->onebinary = '';
2115 $this->assertTrue($DB->import_record($tablename, $record));
2116 $rs = $DB->get_recordset($tablename, array('id' => 70));
2117 $record = $rs->current();
2119 $this->assertEqual($clob, $record->onetext, 'Test CLOB insert (full contents output disabled)');
2121 $blob = file_get_contents(dirname(__FILE__).'/fixtures/randombinary');
2122 $record = new stdClass();
2124 $record->onetext = '';
2125 $record->onebinary = $blob;
2126 $this->assertTrue($DB->import_record($tablename, $record));
2127 $rs = $DB->get_recordset($tablename, array('id' => 71));
2128 $record = $rs->current();
2130 $this->assertEqual($blob, $record->onebinary, 'Test BLOB insert (full contents output disabled)');
2132 // And "small" LOBs too, just in case
2133 $newclob = substr($clob, 0, 500);
2134 $newblob = substr($blob, 0, 250);
2135 $record = new stdClass();
2137 $record->onetext = $newclob;
2138 $record->onebinary = $newblob;
2139 $this->assertTrue($DB->import_record($tablename, $record));
2140 $rs = $DB->get_recordset($tablename, array('id' => 73));
2141 $record = $rs->current();
2143 $this->assertEqual($newclob, $record->onetext, 'Test "small" CLOB insert (full contents output disabled)');
2144 $this->assertEqual($newblob, $record->onebinary, 'Test "small" BLOB insert (full contents output disabled)');
2145 $this->assertEqual(false, $rs->key()); // Ensure recordset key() method to be working ok after closing
2148 public function test_update_record_raw() {
2150 $dbman = $DB->get_manager();
2152 $table = $this->get_test_table();
2153 $tablename = $table->getName();
2155 $table->add_field('id', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, XMLDB_SEQUENCE, null);
2156 $table->add_field('course', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '0');
2157 $table->add_key('primary', XMLDB_KEY_PRIMARY, array('id'));
2158 $dbman->create_table($table);
2160 $DB->insert_record($tablename, array('course' => 1));
2161 $DB->insert_record($tablename, array('course' => 3));
2163 $record = $DB->get_record($tablename, array('course' => 1));
2164 $record->course = 2;
2165 $this->assertTrue($DB->update_record_raw($tablename, $record));
2166 $this->assertEqual(0, $DB->count_records($tablename, array('course' => 1)));
2167 $this->assertEqual(1, $DB->count_records($tablename, array('course' => 2)));
2168 $this->assertEqual(1, $DB->count_records($tablename, array('course' => 3)));
2170 $record = $DB->get_record($tablename, array('course' => 1));
2173 $DB->update_record_raw($tablename, $record);
2174 $this->fail("Expecting an exception, none occurred");
2175 } catch (Exception $e) {
2176 $this->assertTrue($e instanceof coding_exception);
2179 $record = $DB->get_record($tablename, array('course' => 3));
2182 $DB->update_record_raw($tablename, $record);
2183 $this->fail("Expecting an exception, none occurred");
2184 } catch (Exception $e) {
2185 $this->assertTrue($e instanceof coding_exception);
2189 public function test_update_record() {
2191 // All the information in this test is fetched from DB by get_record() so we
2192 // have such method properly tested against nulls, empties and friends...
2195 $dbman = $DB->get_manager();
2197 $table = $this->get_test_table();
2198 $tablename = $table->getName();
2200 $table->add_field('id', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, XMLDB_SEQUENCE, null);
2201 $table->add_field('course', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '0');
2202 $table->add_field('oneint', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, null, null, 100);
2203 $table->add_field('onenum', XMLDB_TYPE_NUMBER, '10,2', null, null, null, 200);
2204 $table->add_field('onechar', XMLDB_TYPE_CHAR, '100', null, null, null, 'onestring');
2205 $table->add_field('onetext', XMLDB_TYPE_TEXT, 'big', null, null, null);
2206 $table->add_field('onebinary', XMLDB_TYPE_BINARY, 'big', null, null, null);
2207 $table->add_key('primary', XMLDB_KEY_PRIMARY, array('id'));
2208 $dbman->create_table($table);
2210 $DB->insert_record($tablename, array('course' => 1));
2211 $record = $DB->get_record($tablename, array('course' => 1));
2212 $record->course = 2;
2214 $this->assertTrue($DB->update_record($tablename, $record));
2215 $this->assertFalse($record = $DB->get_record($tablename, array('course' => 1)));
2216 $this->assertTrue($record = $DB->get_record($tablename, array('course' => 2)));
2217 $this->assertEqual(100, $record->oneint); // Just check column defaults have been applied
2218 $this->assertEqual(200, $record->onenum);
2219 $this->assertEqual('onestring', $record->onechar);
2220 $this->assertNull($record->onetext);
2221 $this->assertNull($record->onebinary);
2223 // Check nulls are set properly for all types
2224 $record->oneint = null;
2225 $record->onenum = null;
2226 $record->onechar = null;
2227 $record->onetext = null;
2228 $record->onebinary = null;
2229 $DB->update_record($tablename, $record);
2230 $record = $DB->get_record($tablename, array('course' => 2));
2231 $this->assertNull($record->oneint);
2232 $this->assertNull($record->onenum);
2233 $this->assertNull($record->onechar);
2234 $this->assertNull($record->onetext);
2235 $this->assertNull($record->onebinary);
2237 // Check zeros are set properly for all types
2238 $record->oneint = 0;
2239 $record->onenum = 0;
2240 $DB->update_record($tablename, $record);
2241 $record = $DB->get_record($tablename, array('course' => 2));
2242 $this->assertEqual(0, $record->oneint);
2243 $this->assertEqual(0, $record->onenum);
2245 // Check booleans are set properly for all types
2246 $record->oneint = true; // trues
2247 $record->onenum = true;
2248 $record->onechar = true;
2249 $record->onetext = true;
2250 $DB->update_record($tablename, $record);
2251 $record = $DB->get_record($tablename, array('course' => 2));
2252 $this->assertEqual(1, $record->oneint);
2253 $this->assertEqual(1, $record->onenum);
2254 $this->assertEqual(1, $record->onechar);
2255 $this->assertEqual(1, $record->onetext);
2257 $record->oneint = false; // falses
2258 $record->onenum = false;
2259 $record->onechar = false;
2260 $record->onetext = false;
2261 $DB->update_record($tablename, $record);
2262 $record = $DB->get_record($tablename, array('course' => 2));
2263 $this->assertEqual(0, $record->oneint);
2264 $this->assertEqual(0, $record->onenum);
2265 $this->assertEqual(0, $record->onechar);
2266 $this->assertEqual(0, $record->onetext);
2268 // Check string data causes exception in numeric types
2269 $record->oneint = 'onestring';
2270 $record->onenum = 0;
2272 $DB->update_record($tablename, $record);
2273 $this->fail("Expecting an exception, none occurred");
2274 } catch (exception $e) {
2275 $this->assertTrue($e instanceof dml_exception);
2277 $record->oneint = 0;
2278 $record->onenum = 'onestring';
2280 $DB->update_record($tablename, $record);
2281 $this->fail("Expecting an exception, none occurred");
2282 } catch (exception $e) {
2283 $this->assertTrue($e instanceof dml_exception);
2286 // Check empty string data is stored as 0 in numeric datatypes
2287 $record->oneint = ''; // empty string
2288 $record->onenum = 0;
2289 $DB->update_record($tablename, $record);
2290 $record = $DB->get_record($tablename, array('course' => 2));
2291 $this->assertTrue(is_numeric($record->oneint) && $record->oneint == 0);
2293 $record->oneint = 0;
2294 $record->onenum = ''; // empty string
2295 $DB->update_record($tablename, $record);
2296 $record = $DB->get_record($tablename, array('course' => 2));
2297 $this->assertTrue(is_numeric($record->onenum) && $record->onenum == 0);
2299 // Check empty strings are set properly in string types
2300 $record->oneint = 0;
2301 $record->onenum = 0;
2302 $record->onechar = '';
2303 $record->onetext = '';
2304 $DB->update_record($tablename, $record);
2305 $record = $DB->get_record($tablename, array('course' => 2));
2306 $this->assertTrue($record->onechar === '');
2307 $this->assertTrue($record->onetext === '');
2309 // Check operation ((210.10 + 39.92) - 150.02) against numeric types
2310 $record->oneint = ((210.10 + 39.92) - 150.02);
2311 $record->onenum = ((210.10 + 39.92) - 150.02);
2312 $DB->update_record($tablename, $record);
2313 $record = $DB->get_record($tablename, array('course' => 2));
2314 $this->assertEqual(100, $record->oneint);
2315 $this->assertEqual(100, $record->onenum);
2317 // Check various quotes/backslashes combinations in string types
2318 $teststrings = array(
2319 'backslashes and quotes alone (even): "" \'\' \\\\',
2320 'backslashes and quotes alone (odd): """ \'\'\' \\\\\\',
2321 'backslashes and quotes sequences (even): \\"\\" \\\'\\\'',
2322 'backslashes and quotes sequences (odd): \\"\\"\\" \\\'\\\'\\\'');
2323 foreach ($teststrings as $teststring) {
2324 $record->onechar = $teststring;
2325 $record->onetext = $teststring;
2326 $DB->update_record($tablename, $record);
2327 $record = $DB->get_record($tablename, array('course' => 2));
2328 $this->assertEqual($teststring, $record->onechar);
2329 $this->assertEqual($teststring, $record->onetext);
2332 // Check LOBs in text/binary columns
2333 $clob = file_get_contents(dirname(__FILE__).'/fixtures/clob.txt');
2334 $blob = file_get_contents(dirname(__FILE__).'/fixtures/randombinary');
2335 $record->onetext = $clob;
2336 $record->onebinary = $blob;
2337 $DB->update_record($tablename, $record);
2338 $record = $DB->get_record($tablename, array('course' => 2));
2339 $this->assertEqual($clob, $record->onetext, 'Test CLOB update (full contents output disabled)');
2340 $this->assertEqual($blob, $record->onebinary, 'Test BLOB update (full contents output disabled)');
2342 // And "small" LOBs too, just in case
2343 $newclob = substr($clob, 0, 500);
2344 $newblob = substr($blob, 0, 250);
2345 $record->onetext = $newclob;
2346 $record->onebinary = $newblob;
2347 $DB->update_record($tablename, $record);
2348 $record = $DB->get_record($tablename, array('course' => 2));
2349 $this->assertEqual($newclob, $record->onetext, 'Test "small" CLOB update (full contents output disabled)');
2350 $this->assertEqual($newblob, $record->onebinary, 'Test "small" BLOB update (full contents output disabled)');
2352 // Test saving a float in a CHAR column, and reading it back.
2353 $id = $DB->insert_record($tablename, array('onechar' => 'X'));
2354 $DB->update_record($tablename, array('id' => $id, 'onechar' => 1.0));
2355 $this->assertEqual(1.0, $DB->get_field($tablename, 'onechar', array('id' => $id)));
2356 $DB->update_record($tablename, array('id' => $id, 'onechar' => 1e20));
2357 $this->assertEqual(1e20, $DB->get_field($tablename, 'onechar', array('id' => $id)));
2358 $DB->update_record($tablename, array('id' => $id, 'onechar' => 1e-4));
2359 $this->assertEqual(1e-4, $DB->get_field($tablename, 'onechar', array('id' => $id)));
2360 $DB->update_record($tablename, array('id' => $id, 'onechar' => 1e-5));
2361 $this->assertEqual(1e-5, $DB->get_field($tablename, 'onechar', array('id' => $id)));
2362 $DB->update_record($tablename, array('id' => $id, 'onechar' => 1e-300));
2363 $this->assertEqual(1e-300, $DB->get_field($tablename, 'onechar', array('id' => $id)));
2364 $DB->update_record($tablename, array('id' => $id, 'onechar' => 1e300));
2365 $this->assertEqual(1e300, $DB->get_field($tablename, 'onechar', array('id' => $id)));
2367 // Test saving a float in a TEXT column, and reading it back.
2368 $id = $DB->insert_record($tablename, array('onetext' => 'X'));
2369 $DB->update_record($tablename, array('id' => $id, 'onetext' => 1.0));
2370 $this->assertEqual(1.0, $DB->get_field($tablename, 'onetext', array('id' => $id)));
2371 $DB->update_record($tablename, array('id' => $id, 'onetext' => 1e20));
2372 $this->assertEqual(1e20, $DB->get_field($tablename, 'onetext', array('id' => $id)));
2373 $DB->update_record($tablename, array('id' => $id, 'onetext' => 1e-4));
2374 $this->assertEqual(1e-4, $DB->get_field($tablename, 'onetext', array('id' => $id)));
2375 $DB->update_record($tablename, array('id' => $id, 'onetext' => 1e-5));
2376 $this->assertEqual(1e-5, $DB->get_field($tablename, 'onetext', array('id' => $id)));
2377 $DB->update_record($tablename, array('id' => $id, 'onetext' => 1e-300));
2378 $this->assertEqual(1e-300, $DB->get_field($tablename, 'onetext', array('id' => $id)));
2379 $DB->update_record($tablename, array('id' => $id, 'onetext' => 1e300));
2380 $this->assertEqual(1e300, $DB->get_field($tablename, 'onetext', array('id' => $id)));
2383 public function test_set_field() {
2385 $dbman = $DB->get_manager();
2387 $table = $this->get_test_table();
2388 $tablename = $table->getName();
2390 $table->add_field('id', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, XMLDB_SEQUENCE, null);
2391 $table->add_field('course', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '0');
2392 $table->add_field('onechar', XMLDB_TYPE_CHAR, '100', null, null, null);
2393 $table->add_field('onetext', XMLDB_TYPE_TEXT, 'big', null, null, null);
2394 $table->add_key('primary', XMLDB_KEY_PRIMARY, array('id'));
2395 $dbman->create_table($table);
2398 $id1 = $DB->insert_record($tablename, array('course' => 1));
2399 $id2 = $DB->insert_record($tablename, array('course' => 1));
2400 $id3 = $DB->insert_record($tablename, array('course' => 3));
2401 $this->assertTrue($DB->set_field($tablename, 'course', 2, array('id' => $id1)));
2402 $this->assertEqual(2, $DB->get_field($tablename, 'course', array('id' => $id1)));
2403 $this->assertEqual(1, $DB->get_field($tablename, 'course', array('id' => $id2)));
2404 $this->assertEqual(3, $DB->get_field($tablename, 'course', array('id' => $id3)));
2405 $DB->delete_records($tablename, array());
2407 // multiple fields affected
2408 $id1 = $DB->insert_record($tablename, array('course' => 1));
2409 $id2 = $DB->insert_record($tablename, array('course' => 1));
2410 $id3 = $DB->insert_record($tablename, array('course' => 3));
2411 $DB->set_field($tablename, 'course', '5', array('course' => 1));
2412 $this->assertEqual(5, $DB->get_field($tablename, 'course', array('id' => $id1)));
2413 $this->assertEqual(5, $DB->get_field($tablename, 'course', array('id' => $id2)));
2414 $this->assertEqual(3, $DB->get_field($tablename, 'course', array('id' => $id3)));
2415 $DB->delete_records($tablename, array());
2417 // no field affected
2418 $id1 = $DB->insert_record($tablename, array('course' => 1));
2419 $id2 = $DB->insert_record($tablename, array('course' => 1));
2420 $id3 = $DB->insert_record($tablename, array('course' => 3));
2421 $DB->set_field($tablename, 'course', '5', array('course' => 0));
2422 $this->assertEqual(1, $DB->get_field($tablename, 'course', array('id' => $id1)));
2423 $this->assertEqual(1, $DB->get_field($tablename, 'course', array('id' => $id2)));
2424 $this->assertEqual(3, $DB->get_field($tablename, 'course', array('id' => $id3)));
2425 $DB->delete_records($tablename, array());
2427 // all fields - no condition
2428 $id1 = $DB->insert_record($tablename, array('course' => 1));
2429 $id2 = $DB->insert_record($tablename, array('course' => 1));
2430 $id3 = $DB->insert_record($tablename, array('course' => 3));
2431 $DB->set_field($tablename, 'course', 5, array());
2432 $this->assertEqual(5, $DB->get_field($tablename, 'course', array('id' => $id1)));
2433 $this->assertEqual(5, $DB->get_field($tablename, 'course', array('id' => $id2)));
2434 $this->assertEqual(5, $DB->get_field($tablename, 'course', array('id' => $id3)));
2436 // test for exception throwing on text conditions being compared. (MDL-24863, unwanted auto conversion of param to int)
2437 $conditions = array('onetext' => '1');
2439 $DB->set_field($tablename, 'onechar', 'frog', $conditions);
2440 $this->fail('An Exception is missing, expected due to equating of text fields');
2441 } catch (exception $e) {
2442 $this->assertTrue($e instanceof dml_exception);
2443 $this->assertEqual($e->errorcode, 'textconditionsnotallowed');
2446 // Test saving a float in a CHAR column, and reading it back.
2447 $id = $DB->insert_record($tablename, array('onechar' => 'X'));
2448 $DB->set_field($tablename, 'onechar', 1.0, array('id' => $id));
2449 $this->assertEqual(1.0, $DB->get_field($tablename, 'onechar', array('id' => $id)));
2450 $DB->set_field($tablename, 'onechar', 1e20, array('id' => $id));
2451 $this->assertEqual(1e20, $DB->get_field($tablename, 'onechar', array('id' => $id)));
2452 $DB->set_field($tablename, 'onechar', 1e-4, array('id' => $id));
2453 $this->assertEqual(1e-4, $DB->get_field($tablename, 'onechar', array('id' => $id)));
2454 $DB->set_field($tablename, 'onechar', 1e-5, array('id' => $id));
2455 $this->assertEqual(1e-5, $DB->get_field($tablename, 'onechar', array('id' => $id)));
2456 $DB->set_field($tablename, 'onechar', 1e-300, array('id' => $id));
2457 $this->assertEqual(1e-300, $DB->get_field($tablename, 'onechar', array('id' => $id)));
2458 $DB->set_field($tablename, 'onechar', 1e300, array('id' => $id));
2459 $this->assertEqual(1e300, $DB->get_field($tablename, 'onechar', array('id' => $id)));
2461 // Test saving a float in a TEXT column, and reading it back.
2462 $id = $DB->insert_record($tablename, array('onetext' => 'X'));
2463 $DB->set_field($tablename, 'onetext', 1.0, array('id' => $id));
2464 $this->assertEqual(1.0, $DB->get_field($tablename, 'onetext', array('id' => $id)));
2465 $DB->set_field($tablename, 'onetext', 1e20, array('id' => $id));
2466 $this->assertEqual(1e20, $DB->get_field($tablename, 'onetext', array('id' => $id)));
2467 $DB->set_field($tablename, 'onetext', 1e-4, array('id' => $id));
2468 $this->assertEqual(1e-4, $DB->get_field($tablename, 'onetext', array('id' => $id)));
2469 $DB->set_field($tablename, 'onetext', 1e-5, array('id' => $id));
2470 $this->assertEqual(1e-5, $DB->get_field($tablename, 'onetext', array('id' => $id)));
2471 $DB->set_field($tablename, 'onetext', 1e-300, array('id' => $id));
2472 $this->assertEqual(1e-300, $DB->get_field($tablename, 'onetext', array('id' => $id)));
2473 $DB->set_field($tablename, 'onetext', 1e300, array('id' => $id));
2474 $this->assertEqual(1e300, $DB->get_field($tablename, 'onetext', array('id' => $id)));
2476 // Note: All the nulls, booleans, empties, quoted and backslashes tests
2477 // go to set_field_select() because set_field() is just one wrapper over it
2480 public function test_set_field_select() {
2482 // All the information in this test is fetched from DB by get_field() so we
2483 // have such method properly tested against nulls, empties and friends...
2486 $dbman = $DB->get_manager();
2488 $table = $this->get_test_table();
2489 $tablename = $table->getName();
2491 $table->add_field('id', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, XMLDB_SEQUENCE, null);
2492 $table->add_field('course', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '0');
2493 $table->add_field('oneint', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, null, null);
2494 $table->add_field('onenum', XMLDB_TYPE_NUMBER, '10,2', null, null, null);
2495 $table->add_field('onechar', XMLDB_TYPE_CHAR, '100', null, null, null);
2496 $table->add_field('onetext', XMLDB_TYPE_TEXT, 'big', null, null, null);
2497 $table->add_field('onebinary', XMLDB_TYPE_BINARY, 'big', null, null, null);
2498 $table->add_key('primary', XMLDB_KEY_PRIMARY, array('id'));
2499 $dbman->create_table($table);
2501 $DB->insert_record($tablename, array('course' => 1));
2503 $this->assertTrue($DB->set_field_select($tablename, 'course', 2, 'id = ?', array(1)));
2504 $this->assertEqual(2, $DB->get_field($tablename, 'course', array('id' => 1)));
2506 // Check nulls are set properly for all types
2507 $DB->set_field_select($tablename, 'oneint', null, 'id = ?', array(1)); // trues
2508 $DB->set_field_select($tablename, 'onenum', null, 'id = ?', array(1));
2509 $DB->set_field_select($tablename, 'onechar', null, 'id = ?', array(1));
2510 $DB->set_field_select($tablename, 'onetext', null, 'id = ?', array(1));
2511 $DB->set_field_select($tablename, 'onebinary', null, 'id = ?', array(1));
2512 $this->assertNull($DB->get_field($tablename, 'oneint', array('id' => 1)));
2513 $this->assertNull($DB->get_field($tablename, 'onenum', array('id' => 1)));
2514 $this->assertNull($DB->get_field($tablename, 'onechar', array('id' => 1)));
2515 $this->assertNull($DB->get_field($tablename, 'onetext', array('id' => 1)));
2516 $this->assertNull($DB->get_field($tablename, 'onebinary', array('id' => 1)));
2518 // Check zeros are set properly for all types
2519 $DB->set_field_select($tablename, 'oneint', 0, 'id = ?', array(1));
2520 $DB->set_field_select($tablename, 'onenum', 0, 'id = ?', array(1));
2521 $this->assertEqual(0, $DB->get_field($tablename, 'oneint', array('id' => 1)));
2522 $this->assertEqual(0, $DB->get_field($tablename, 'onenum', array('id' => 1)));
2524 // Check booleans are set properly for all types
2525 $DB->set_field_select($tablename, 'oneint', true, 'id = ?', array(1)); // trues
2526 $DB->set_field_select($tablename, 'onenum', true, 'id = ?', array(1));
2527 $DB->set_field_select($tablename, 'onechar', true, 'id = ?', array(1));
2528 $DB->set_field_select($tablename, 'onetext', true, 'id = ?', array(1));
2529 $this->assertEqual(1, $DB->get_field($tablename, 'oneint', array('id' => 1)));
2530 $this->assertEqual(1, $DB->get_field($tablename, 'onenum', array('id' => 1)));
2531 $this->assertEqual(1, $DB->get_field($tablename, 'onechar', array('id' => 1)));
2532 $this->assertEqual(1, $DB->get_field($tablename, 'onetext', array('id' => 1)));
2534 $DB->set_field_select($tablename, 'oneint', false, 'id = ?', array(1)); // falses
2535 $DB->set_field_select($tablename, 'onenum', false, 'id = ?', array(1));
2536 $DB->set_field_select($tablename, 'onechar', false, 'id = ?', array(1));
2537 $DB->set_field_select($tablename, 'onetext', false, 'id = ?', array(1));
2538 $this->assertEqual(0, $DB->get_field($tablename, 'oneint', array('id' => 1)));
2539 $this->assertEqual(0, $DB->get_field($tablename, 'onenum', array('id' => 1)));
2540 $this->assertEqual(0, $DB->get_field($tablename, 'onechar', array('id' => 1)));
2541 $this->assertEqual(0, $DB->get_field($tablename, 'onetext', array('id' => 1)));
2543 // Check string data causes exception in numeric types
2545 $DB->set_field_select($tablename, 'oneint', 'onestring', 'id = ?', array(1));
2546 $this->fail("Expecting an exception, none occurred");
2547 } catch (exception $e) {
2548 $this->assertTrue($e instanceof dml_exception);
2551 $DB->set_field_select($tablename, 'onenum', 'onestring', 'id = ?', array(1));
2552 $this->fail("Expecting an exception, none occurred");
2553 } catch (exception $e) {
2554 $this->assertTrue($e instanceof dml_exception);
2557 // Check empty string data is stored as 0 in numeric datatypes
2558 $DB->set_field_select($tablename, 'oneint', '', 'id = ?', array(1));
2559 $field = $DB->get_field($tablename, 'oneint', array('id' => 1));
2560 $this->assertTrue(is_numeric($field) && $field == 0);
2562 $DB->set_field_select($tablename, 'onenum', '', 'id = ?', array(1));
2563 $field = $DB->get_field($tablename, 'onenum', array('id' => 1));
2564 $this->assertTrue(is_numeric($field) && $field == 0);
2566 // Check empty strings are set properly in string types
2567 $DB->set_field_select($tablename, 'onechar', '', 'id = ?', array(1));
2568 $DB->set_field_select($tablename, 'onetext', '', 'id = ?', array(1));
2569 $this->assertTrue($DB->get_field($tablename, 'onechar', array('id' => 1)) === '');
2570 $this->assertTrue($DB->get_field($tablename, 'onetext', array('id' => 1)) === '');
2572 // Check operation ((210.10 + 39.92) - 150.02) against numeric types
2573 $DB->set_field_select($tablename, 'oneint', ((210.10 + 39.92) - 150.02), 'id = ?', array(1));
2574 $DB->set_field_select($tablename, 'onenum', ((210.10 + 39.92) - 150.02), 'id = ?', array(1));
2575 $this->assertEqual(100, $DB->get_field($tablename, 'oneint', array('id' => 1)));
2576 $this->assertEqual(100, $DB->get_field($tablename, 'onenum', array('id' => 1)));
2578 // Check various quotes/backslashes combinations in string types
2579 $teststrings = array(
2580 'backslashes and quotes alone (even): "" \'\' \\\\',
2581 'backslashes and quotes alone (odd): """ \'\'\' \\\\\\',
2582 'backslashes and quotes sequences (even): \\"\\" \\\'\\\'',
2583 'backslashes and quotes sequences (odd): \\"\\"\\" \\\'\\\'\\\'');
2584 foreach ($teststrings as $teststring) {
2585 $DB->set_field_select($tablename, 'onechar', $teststring, 'id = ?', array(1));
2586 $DB->set_field_select($tablename, 'onetext', $teststring, 'id = ?', array(1));
2587 $this->assertEqual($teststring, $DB->get_field($tablename, 'onechar', array('id' => 1)));
2588 $this->assertEqual($teststring, $DB->get_field($tablename, 'onetext', array('id' => 1)));
2591 // Check LOBs in text/binary columns
2592 $clob = file_get_contents(dirname(__FILE__).'/fixtures/clob.txt');
2593 $blob = file_get_contents(dirname(__FILE__).'/fixtures/randombinary');
2594 $DB->set_field_select($tablename, 'onetext', $clob, 'id = ?', array(1));
2595 $DB->set_field_select($tablename, 'onebinary', $blob, 'id = ?', array(1));
2596 $this->assertEqual($clob, $DB->get_field($tablename, 'onetext', array('id' => 1)), 'Test CLOB set_field (full contents output disabled)');
2597 $this->assertEqual($blob, $DB->get_field($tablename, 'onebinary', array('id' => 1)), 'Test BLOB set_field (full contents output disabled)');
2599 // And "small" LOBs too, just in case
2600 $newclob = substr($clob, 0, 500);
2601 $newblob = substr($blob, 0, 250);
2602 $DB->set_field_select($tablename, 'onetext', $newclob, 'id = ?', array(1));
2603 $DB->set_field_select($tablename, 'onebinary', $newblob, 'id = ?', array(1));
2604 $this->assertEqual($newclob, $DB->get_field($tablename, 'onetext', array('id' => 1)), 'Test "small" CLOB set_field (full contents output disabled)');
2605 $this->assertEqual($newblob, $DB->get_field($tablename, 'onebinary', array('id' => 1)), 'Test "small" BLOB set_field (full contents output disabled)');
2607 // This is the failure from MDL-24863. This was giving an error on MSSQL,
2608 // which converts the '1' to an integer, which cannot then be compared with
2609 // onetext cast to a varchar. This should be fixed and working now.
2611 // test for exception throwing on text conditions being compared. (MDL-24863, unwanted auto conversion of param to int)
2612 $params = array('onetext' => '1');
2614 $DB->set_field_select($tablename, 'onechar', $newchar, $DB->sql_compare_text('onetext') . ' = ?', $params);
2615 $this->assertTrue(true, 'No exceptions thrown with numerical text param comparison for text field.');
2616 } catch (dml_exception $e) {
2617 $this->assertFalse(true, 'We have an unexpected exception.');
2624 public function test_count_records() {
2627 $dbman = $DB->get_manager();
2629 $table = $this->get_test_table();
2630 $tablename = $table->getName();
2632 $table->add_field('id', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, XMLDB_SEQUENCE, null);
2633 $table->add_field('course', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '0');
2634 $table->add_field('onetext', XMLDB_TYPE_TEXT, 'big', null, null, null);
2635 $table->add_key('primary', XMLDB_KEY_PRIMARY, array('id'));
2636 $dbman->create_table($table);
2638 $this->assertEqual(0, $DB->count_records($tablename));
2640 $DB->insert_record($tablename, array('course' => 3));
2641 $DB->insert_record($tablename, array('course' => 4));
2642 $DB->insert_record($tablename, array('course' => 5));
2644 $this->assertEqual(3, $DB->count_records($tablename));
2646 // test for exception throwing on text conditions being compared. (MDL-24863, unwanted auto conversion of param to int)
2647 $conditions = array('onetext' => '1');
2649 $DB->count_records($tablename, $conditions);
2650 $this->fail('An Exception is missing, expected due to equating of text fields');
2651 } catch (exception $e) {
2652 $this->assertTrue($e instanceof dml_exception);
2653 $this->assertEqual($e->errorcode, 'textconditionsnotallowed');
2657 public function test_count_records_select() {
2660 $dbman = $DB->get_manager();
2662 $table = $this->get_test_table();
2663 $tablename = $table->getName();
2665 $table->add_field('id', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, XMLDB_SEQUENCE, null);
2666 $table->add_field('course', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '0');
2667 $table->add_key('primary', XMLDB_KEY_PRIMARY, array('id'));
2668 $dbman->create_table($table);
2670 $this->assertEqual(0, $DB->count_records($tablename));
2672 $DB->insert_record($tablename, array('course' => 3));
2673 $DB->insert_record($tablename, array('course' => 4));
2674 $DB->insert_record($tablename, array('course' => 5));
2676 $this->assertEqual(2, $DB->count_records_select($tablename, 'course > ?', array(3)));
2679 public function test_count_records_sql() {
2681 $dbman = $DB->get_manager();
2683 $table = $this->get_test_table();
2684 $tablename = $table->getName();
2686 $table->add_field('id', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, XMLDB_SEQUENCE, null);
2687 $table->add_field('course', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '0');
2688 $table->add_key('primary', XMLDB_KEY_PRIMARY, array('id'));
2689 $dbman->create_table($table);
2691 $this->assertEqual(0, $DB->count_records($tablename));
2693 $DB->insert_record($tablename, array('course' => 3));
2694 $DB->insert_record($tablename, array('course' => 4));
2695 $DB->insert_record($tablename, array('course' => 5));
2697 $this->assertEqual(2, $DB->count_records_sql("SELECT COUNT(*) FROM {{$tablename}} WHERE course > ?", array(3)));
2700 public function test_record_exists() {
2702 $dbman = $DB->get_manager();
2704 $table = $this->get_test_table();
2705 $tablename = $table->getName();
2707 $table->add_field('id', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, XMLDB_SEQUENCE, null);
2708 $table->add_field('course', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '0');
2709 $table->add_field('onetext', XMLDB_TYPE_TEXT, 'big', null, null, null);
2710 $table->add_key('primary', XMLDB_KEY_PRIMARY, array('id'));
2711 $dbman->create_table($table);
2713 $this->assertEqual(0, $DB->count_records($tablename));
2715 $this->assertFalse($DB->record_exists($tablename, array('course' => 3)));
2716 $DB->insert_record($tablename, array('course' => 3));
2718 $this->assertTrue($DB->record_exists($tablename, array('course' => 3)));
2721 // test for exception throwing on text conditions being compared. (MDL-24863, unwanted auto conversion of param to int)
2722 $conditions = array('onetext' => '1');
2724 $DB->record_exists($tablename, $conditions);
2725 $this->fail('An Exception is missing, expected due to equating of text fields');
2726 } catch (exception $e) {
2727 $this->assertTrue($e instanceof dml_exception);
2728 $this->assertEqual($e->errorcode, 'textconditionsnotallowed');
2732 public function test_record_exists_select() {
2734 $dbman = $DB->get_manager();
2736 $table = $this->get_test_table();
2737 $tablename = $table->getName();
2739 $table->add_field('id', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, XMLDB_SEQUENCE, null);
2740 $table->add_field('course', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '0');
2741 $table->add_key('primary', XMLDB_KEY_PRIMARY, array('id'));
2742 $dbman->create_table($table);
2744 $this->assertEqual(0, $DB->count_records($tablename));
2746 $this->assertFalse($DB->record_exists_select($tablename, "course = ?", array(3)));
2747 $DB->insert_record($tablename, array('course' => 3));
2749 $this->assertTrue($DB->record_exists_select($tablename, "course = ?", array(3)));
2752 public function test_record_exists_sql() {
2754 $dbman = $DB->get_manager();
2756 $table = $this->get_test_table();
2757 $tablename = $table->getName();
2759 $table->add_field('id', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, XMLDB_SEQUENCE, null);
2760 $table->add_field('course', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '0');
2761 $table->add_key('primary', XMLDB_KEY_PRIMARY, array('id'));
2762 $dbman->create_table($table);
2764 $this->assertEqual(0, $DB->count_records($tablename));
2766 $this->assertFalse($DB->record_exists_sql("SELECT * FROM {{$tablename}} WHERE course = ?", array(3)));
2767 $DB->insert_record($tablename, array('course' => 3));
2769 $this->assertTrue($DB->record_exists_sql("SELECT * FROM {{$tablename}} WHERE course = ?", array(3)));
2772 public function test_recordset_locks_delete() {
2774 $dbman = $DB->get_manager();
2777 $table = $this->get_test_table();
2778 $tablename = $table->getName();
2780 $table->add_field('id', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, XMLDB_SEQUENCE, null);
2781 $table->add_field('course', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '0');
2782 $table->add_key('primary', XMLDB_KEY_PRIMARY, array('id'));
2783 $dbman->create_table($table);
2785 $DB->insert_record($tablename, array('course' => 1));
2786 $DB->insert_record($tablename, array('course' => 2));
2787 $DB->insert_record($tablename, array('course' => 3));
2788 $DB->insert_record($tablename, array('course' => 4));
2789 $DB->insert_record($tablename, array('course' => 5));
2790 $DB->insert_record($tablename, array('course' => 6));
2792 // Test against db write locking while on an open recordset
2793 $rs = $DB->get_recordset($tablename, array(), null, 'course', 2, 2); // get courses = {3,4}
2794 foreach ($rs as $record) {
2795 $cid = $record->course;
2796 $DB->delete_records($tablename, array('course' => $cid));
2797 $this->assertFalse($DB->record_exists($tablename, array('course' => $cid)));
2801 $this->assertEqual(4, $DB->count_records($tablename, array()));
2804 public function test_recordset_locks_update() {
2806 $dbman = $DB->get_manager();
2809 $table = $this->get_test_table();
2810 $tablename = $table->getName();
2812 $table->add_field('id', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, XMLDB_SEQUENCE, null);
2813 $table->add_field('course', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '0');
2814 $table->add_key('primary', XMLDB_KEY_PRIMARY, array('id'));
2815 $dbman->create_table($table);
2817 $DB->insert_record($tablename, array('course' => 1));
2818 $DB->insert_record($tablename, array('course' => 2));
2819 $DB->insert_record($tablename, array('course' => 3));
2820 $DB->insert_record($tablename, array('course' => 4));
2821 $DB->insert_record($tablename, array('course' => 5));
2822 $DB->insert_record($tablename, array('course' => 6));
2824 // Test against db write locking while on an open recordset
2825 $rs = $DB->get_recordset($tablename, array(), null, 'course', 2, 2); // get courses = {3,4}
2826 foreach ($rs as $record) {
2827 $cid = $record->course;
2828 $DB->set_field($tablename, 'course', 10, array('course' => $cid));
2829 $this->assertFalse($DB->record_exists($tablename, array('course' => $cid)));
2833 $this->assertEqual(2, $DB->count_records($tablename, array('course' => 10)));
2836 public function test_delete_records() {
2838 $dbman = $DB->get_manager();
2840 $table = $this->get_test_table();
2841 $tablename = $table->getName();
2843 $table->add_field('id', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, XMLDB_SEQUENCE, null);
2844 $table->add_field('course', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '0');
2845 $table->add_field('onetext', XMLDB_TYPE_TEXT, 'big', null, null, null);
2846 $table->add_key('primary', XMLDB_KEY_PRIMARY, array('id'));
2847 $dbman->create_table($table);
2849 $DB->insert_record($tablename, array('course' => 3));
2850 $DB->insert_record($tablename, array('course' => 2));
2851 $DB->insert_record($tablename, array('course' => 2));
2853 // Delete all records
2854 $this->assertTrue($DB->delete_records($tablename));
2855 $this->assertEqual(0, $DB->count_records($tablename));
2857 // Delete subset of records
2858 $DB->insert_record($tablename, array('course' => 3));
2859 $DB->insert_record($tablename, array('course' => 2));
2860 $DB->insert_record($tablename, array('course' => 2));
2862 $this->assertTrue($DB->delete_records($tablename, array('course' => 2)));
2863 $this->assertEqual(1, $DB->count_records($tablename));
2866 $this->assertTrue($DB->delete_records($tablename, array()));
2867 $this->assertEqual(0, $DB->count_records($tablename));
2869 // test for exception throwing on text conditions being compared. (MDL-24863, unwanted auto conversion of param to int)
2870 $conditions = array('onetext'=>'1');
2872 $DB->delete_records($tablename, $conditions);
2873 $this->fail('An Exception is missing, expected due to equating of text fields');
2874 } catch (exception $e) {
2875 $this->assertTrue($e instanceof dml_exception);
2876 $this->assertEqual($e->errorcode, 'textconditionsnotallowed');
2879 // test for exception throwing on text conditions being compared. (MDL-24863, unwanted auto conversion of param to int)
2880 $conditions = array('onetext' => 1);
2882 $DB->delete_records($tablename, $conditions);
2883 $this->fail('An Exception is missing, expected due to equating of text fields');
2884 } catch (exception $e) {
2885 $this->assertTrue($e instanceof dml_exception);
2886 $this->assertEqual($e->errorcode, 'textconditionsnotallowed');
2890 public function test_delete_records_select() {
2892 $dbman = $DB->get_manager();
2894 $table = $this->get_test_table();
2895 $tablename = $table->getName();
2897 $table->add_field('id', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, XMLDB_SEQUENCE, null);
2898 $table->add_field('course', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '0');
2899 $table->add_key('primary', XMLDB_KEY_PRIMARY, array('id'));
2900 $dbman->create_table($table);
2902 $DB->insert_record($tablename, array('course' => 3));
2903 $DB->insert_record($tablename, array('course' => 2));
2904 $DB->insert_record($tablename, array('course' => 2));
2906 $this->assertTrue($DB->delete_records_select($tablename, 'course = ?', array(2)));
2907 $this->assertEqual(1, $DB->count_records($tablename));
2910 public function test_delete_records_list() {
2912 $dbman = $DB->get_manager();
2914 $table = $this->get_test_table();
2915 $tablename = $table->getName();
2917 $table->add_field('id', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, XMLDB_SEQUENCE, null);
2918 $table->add_field('course', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '0');
2919 $table->add_key('primary', XMLDB_KEY_PRIMARY, array('id'));
2920 $dbman->create_table($table);
2922 $DB->insert_record($tablename, array('course' => 1));
2923 $DB->insert_record($tablename, array('course' => 2));
2924 $DB->insert_record($tablename, array('course' => 3));
2926 $this->assertTrue($DB->delete_records_list($tablename, 'course', array(2, 3)));
2927 $this->assertEqual(1, $DB->count_records($tablename));
2929 $this->assertTrue($DB->delete_records_list($tablename, 'course', array())); /// Must delete 0 rows without conditions. MDL-17645
2930 $this->assertEqual(1, $DB->count_records($tablename));
2933 function test_sql_null_from_clause() {
2935 $sql = "SELECT 1 AS id ".$DB->sql_null_from_clause();
2936 $this->assertEqual($DB->get_field_sql($sql), 1);
2939 function test_sql_bitand() {
2941 $dbman = $DB->get_manager();
2943 $table = $this->get_test_table();
2944 $tablename = $table->getName();
2946 $table->add_field('id', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, XMLDB_SEQUENCE, null);
2947 $table->add_field('col1', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '0');
2948 $table->add_field('col2', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '0');
2949 $table->add_key('primary', XMLDB_KEY_PRIMARY, array('id'));
2950 $dbman->create_table($table);
2952 $DB->insert_record($tablename, array('col1' => 3, 'col2' => 10));
2954 $sql = "SELECT ".$DB->sql_bitand(10, 3)." AS res ".$DB->sql_null_from_clause();
2955 $this->assertEqual($DB->get_field_sql($sql), 2);
2957 $sql = "SELECT id, ".$DB->sql_bitand('col1', 'col2')." AS res FROM {{$tablename}}";
2958 $result = $DB->get_records_sql($sql);
2959 $this->assertEqual(count($result), 1);
2960 $this->assertEqual(reset($result)->res, 2);
2962 $sql = "SELECT id, ".$DB->sql_bitand('col1', '?')." AS res FROM {{$tablename}}";
2963 $result = $DB->get_records_sql($sql, array(10));
2964 $this->assertEqual(count($result), 1);
2965 $this->assertEqual(reset($result)->res, 2);
2968 function test_sql_bitnot() {
2971 $not = $DB->sql_bitnot(2);
2972 $notlimited = $DB->sql_bitand($not, 7); // might be positive or negative number which can not fit into PHP INT!
2974 $sql = "SELECT $notlimited AS res ".$DB->sql_null_from_clause();
2975 $this->assertEqual($DB->get_field_sql($sql), 5);
2978 function test_sql_bitor() {
2980 $dbman = $DB->get_manager();
2982 $table = $this->get_test_table();
2983 $tablename = $table->getName();
2985 $table->add_field('id', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, XMLDB_SEQUENCE, null);
2986 $table->add_field('col1', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '0');
2987 $table->add_field('col2', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '0');
2988 $table->add_key('primary', XMLDB_KEY_PRIMARY, array('id'));
2989 $dbman->create_table($table);
2991 $DB->insert_record($tablename, array('col1' => 3, 'col2' => 10));
2993 $sql = "SELECT ".$DB->sql_bitor(10, 3)." AS res ".$DB->sql_null_from_clause();
2994 $this->assertEqual($DB->get_field_sql($sql), 11);
2996 $sql = "SELECT id, ".$DB->sql_bitor('col1', 'col2')." AS res FROM {{$tablename}}";
2997 $result = $DB->get_records_sql($sql);
2998 $this->assertEqual(count($result), 1);
2999 $this->assertEqual(reset($result)->res, 11);
3001 $sql = "SELECT id, ".$DB->sql_bitor('col1', '?')." AS res FROM {{$tablename}}";
3002 $result = $DB->get_records_sql($sql, array(10));
3003 $this->assertEqual(count($result), 1);
3004 $this->assertEqual(reset($result)->res, 11);
3007 function test_sql_bitxor() {
3009 $dbman = $DB->get_manager();
3011 $table = $this->get_test_table();
3012 $tablename = $table->getName();
3014 $table->add_field('id', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, XMLDB_SEQUENCE, null);
3015 $table->add_field('col1', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '0');
3016 $table->add_field('col2', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '0');
3017 $table->add_key('primary', XMLDB_KEY_PRIMARY, array('id'));
3018 $dbman->create_table($table);
3020 $DB->insert_record($tablename, array('col1' => 3, 'col2' => 10));
3022 $sql = "SELECT ".$DB->sql_bitxor(10, 3)." AS res ".$DB->sql_null_from_clause();
3023 $this->assertEqual($DB->get_field_sql($sql), 9);
3025 $sql = "SELECT id, ".$DB->sql_bitxor('col1', 'col2')." AS res FROM {{$tablename}}";
3026 $result = $DB->get_records_sql($sql);
3027 $this->assertEqual(count($result), 1);
3028 $this->assertEqual(reset($result)->res, 9);
3030 $sql = "SELECT id, ".$DB->sql_bitxor('col1', '?')." AS res FROM {{$tablename}}";
3031 $result = $DB->get_records_sql($sql, array(10));
3032 $this->assertEqual(count($result), 1);
3033 $this->assertEqual(reset($result)->res, 9);
3036 function test_sql_modulo() {
3038 $sql = "SELECT ".$DB->sql_modulo(10, 7)." AS res ".$DB->sql_null_from_clause();
3039 $this->assertEqual($DB->get_field_sql($sql), 3);
3042 function test_sql_ceil() {
3044 $sql = "SELECT ".$DB->sql_ceil(665.666)." AS res ".$DB->sql_null_from_clause();
3045 $this->assertEqual($DB->get_field_sql($sql), 666);
3048 function test_cast_char2int() {
3050 $dbman = $DB->get_manager();
3052 $table1 = $this->get_test_table("1");
3053 $tablename1 = $table1->getName();
3055 $table1->add_field('id', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, XMLDB_SEQUENCE, null);
3056 $table1->add_field('name', XMLDB_TYPE_CHAR, '255', null, null, null, null);
3057 $table1->add_field('nametext', XMLDB_TYPE_TEXT, 'small', null, null, null, null);
3058 $table1->add_key('primary', XMLDB_KEY_PRIMARY, array('id'));
3059 $dbman->create_table($table1);
3061 $DB->insert_record($tablename1, array('name'=>'0100', 'nametext'=>'0200'));
3062 $DB->insert_record($tablename1, array('name'=>'10', 'nametext'=>'20'));
3064 $table2 = $this->get_test_table("2");
3065 $tablename2 = $table2->getName();
3066 $table2->add_field('id', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, XMLDB_SEQUENCE, null);
3067 $table2->add_field('res', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '0');
3068 $table2->add_field('restext', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '0');
3069 $table2->add_key('primary', XMLDB_KEY_PRIMARY, array('id'));
3070 $dbman->create_table($table2);
3072 $DB->insert_record($tablename2, array('res'=>100, 'restext'=>200));
3074 // casting varchar field
3076 FROM {".$tablename1."} t1
3077 JOIN {".$tablename2."} t2 ON ".$DB->sql_cast_char2int("t1.name")." = t2.res ";
3078 $records = $DB->get_records_sql($sql);
3079 $this->assertEqual(count($records), 1);
3080 // also test them in order clauses
3081 $sql = "SELECT * FROM {{$tablename1}} ORDER BY ".$DB->sql_cast_char2int('name');
3082 $records = $DB->get_records_sql($sql);
3083 $this->assertEqual(count($records), 2);
3084 $this->assertEqual(reset($records)->name, '10');
3085 $this->assertEqual(next($records)->name, '0100');
3087 // casting text field
3089 FROM {".$tablename1."} t1
3090 JOIN {".$tablename2."} t2 ON ".$DB->sql_cast_char2int("t1.nametext", true)." = t2.restext ";
3091 $records = $DB->get_records_sql($sql);
3092 $this->assertEqual(count($records), 1);
3093 // also test them in order clauses
3094 $sql = "SELECT * FROM {{$tablename1}} ORDER BY ".$DB->sql_cast_char2int('nametext', true);
3095 $records = $DB->get_records_sql($sql);
3096 $this->assertEqual(count($records), 2);
3097 $this->assertEqual(reset($records)->nametext, '20');
3098 $this->assertEqual(next($records)->nametext, '0200');
3101 function test_cast_char2real() {
3103 $dbman = $DB->get_manager();
3105 $table = $this->get_test_table();
3106 $tablename = $table->getName();
3108 $table->add_field('id', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, XMLDB_SEQUENCE, null);
3109 $table->add_field('name', XMLDB_TYPE_CHAR, '255', null, null, null, null);
3110 $table->add_field('nametext', XMLDB_TYPE_TEXT, 'small', null, null, null, null);
3111 $table->add_field('res', XMLDB_TYPE_NUMBER, '12, 7', null, null, null, null);
3112 $table->add_key('primary', XMLDB_KEY_PRIMARY, array('id'));
3113 $dbman->create_table($table);
3115 $DB->insert_record($tablename, array('name'=>'10.10', 'nametext'=>'10.10', 'res'=>5.1));
3116 $DB->insert_record($tablename, array('name'=>'91.10', 'nametext'=>'91.10', 'res'=>666));
3117 $DB->insert_record($tablename, array('name'=>'011.10','nametext'=>'011.10','res'=>10.1));
3119 // casting varchar field
3120 $sql = "SELECT * FROM {{$tablename}} WHERE ".$DB->sql_cast_char2real('name')." > res";
3121 $records = $DB->get_records_sql($sql);
3122 $this->assertEqual(count($records), 2);
3123 // also test them in order clauses
3124 $sql = "SELECT * FROM {{$tablename}} ORDER BY ".$DB->sql_cast_char2real('name');
3125 $records = $DB->get_records_sql($sql);
3126 $this->assertEqual(count($records), 3);
3127 $this->assertEqual(reset($records)->name, '10.10');
3128 $this->assertEqual(next($records)->name, '011.10');
3129 $this->assertEqual(next($records)->name, '91.10');
3131 // casting text field
3132 $sql = "SELECT * FROM {{$tablename}} WHERE ".$DB->sql_cast_char2real('nametext', true)." > res";
3133 $records = $DB->get_records_sql($sql);
3134 $this->assertEqual(count($records), 2);
3135 // also test them in order clauses
3136 $sql = "SELECT * FROM {{$tablename}} ORDER BY ".$DB->sql_cast_char2real('nametext', true);
3137 $records = $DB->get_records_sql($sql);
3138 $this->assertEqual(count($records), 3);
3139 $this->assertEqual(reset($records)->nametext, '10.10');
3140 $this->assertEqual(next($records)->nametext, '011.10');
3141 $this->assertEqual(next($records)->nametext, '91.10');
3144 function sql_compare_text() {
3146 $dbman = $DB->get_manager();
3148 $table = $this->get_test_table();
3149 $tablename = $table->getName();
3151 $table->add_field('id', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, XMLDB_SEQUENCE, null);
3152 $table->add_field('name', XMLDB_TYPE_CHAR, '255', null, null, null, null);
3153 $table->add_field('description', XMLDB_TYPE_TEXT, 'big', null, null, null, null);
3154 $table->add_key('primary', XMLDB_KEY_PRIMARY, array('id'));
3155 $dbman->create_table($table);
3157 $DB->insert_record($tablename, array('name'=>'abcd', 'description'=>'abcd'));
3158 $DB->insert_record($tablename, array('name'=>'abcdef', 'description'=>'bbcdef'));
3159 $DB->insert_record($tablename, array('name'=>'aaaabb', 'description'=>'aaaacccccccccccccccccc'));
3161 $sql = "SELECT * FROM {{$tablename}} WHERE name = ".$DB->sql_compare_text('description');
3162 $records = $DB->get_records_sql($sql);
3163 $this->assertEqual(count($records), 1);
3165 $sql = "SELECT * FROM {{$tablename}} WHERE name = ".$DB->sql_compare_text('description', 4);
3166 $records = $DB->get_records_sql($sql);
3167 $this->assertEqual(count($records), 2);
3170 function test_unique_index_collation_trouble() {
3171 // note: this is a work in progress, we should probably move this to ddl test
3174 $dbman = $DB->get_manager();
3176 $table = $this->get_test_table();
3177 $tablename = $table->getName();
3179 $table->add_field('id', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, XMLDB_SEQUENCE, null);
3180 $table->add_field('name', XMLDB_TYPE_CHAR, '255', null, null, null, null);
3181 $table->add_key('primary', XMLDB_KEY_PRIMARY, array('id'));
3182 $table->add_index('name', XMLDB_INDEX_UNIQUE, array('name'));
3183 $dbman->create_table($table);
3185 $DB->insert_record($tablename, array('name'=>'aaa'));
3188 $DB->insert_record($tablename, array('name'=>'AAA'));
3189 } catch (Exception $e) {
3190 //TODO: ignore case insensitive uniqueness problems for now
3191 //$this->fail("Unique index is case sensitive - this may cause problems in some tables");
3195 $DB->insert_record($tablename, array('name'=>'aäa'));
3196 $DB->insert_record($tablename, array('name'=>'aáa'));
3197 $this->assertTrue(true);
3198 } catch (Exception $e) {
3199 $family = $DB->get_dbfamily();
3200 if ($family === 'mysql' or $family === 'mssql') {
3201 $this->fail("Unique index is accent insensitive, this may cause problems for non-ascii languages. This is usually caused by accent insensitive default collation.");
3203 // this should not happen, PostgreSQL and Oracle do not support accent insensitive uniqueness.
3204 $this->fail("Unique index is accent insensitive, this may cause problems for non-ascii languages.");
3210 function test_sql_binary_equal() {
3212 $dbman = $DB->get_manager();
3214 $table = $this->get_test_table();
3215 $tablename = $table->getName();
3217 $table->add_field('id', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, XMLDB_SEQUENCE, null);
3218 $table->add_field('name', XMLDB_TYPE_CHAR, '255', null, null, null, null);
3219 $table->add_key('primary', XMLDB_KEY_PRIMARY, array('id'));
3220 $dbman->create_table($table);
3222 $DB->insert_record($tablename, array('name'=>'aaa'));
3223 $DB->insert_record($tablename, array('name'=>'aáa'));
3224 $DB->insert_record($tablename, array('name'=>'aäa'));
3225 $DB->insert_record($tablename, array('name'=>'bbb'));
3226 $DB->insert_record($tablename, array('name'=>'BBB'));
3228 $records = $DB->get_records_sql("SELECT * FROM {{$tablename}} WHERE name = ?", array('aaa'));
3229 $this->assertEqual(count($records), 1, 'SQL operator "=" is expected to be accent sensitive');
3231 $records = $DB->get_records_sql("SELECT * FROM {{$tablename}} WHERE name = ?", array('bbb'));
3232 $this->assertEqual(count($records), 1, 'SQL operator "=" is expected to be case sensitive');
3235 function test_sql_like() {
3237 $dbman = $DB->get_manager();
3239 $table = $this->get_test_table();
3240 $tablename = $table->getName();
3242 $table->add_field('id', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, XMLDB_SEQUENCE, null);
3243 $table->add_field('name', XMLDB_TYPE_CHAR, '255', null, null, null, null);
3244 $table->add_key('primary', XMLDB_KEY_PRIMARY, array('id'));
3245 $dbman->create_table($table);
3247 $DB->insert_record($tablename, array('name'=>'SuperDuperRecord'));
3248 $DB->insert_record($tablename, array('name'=>'Nodupor'));
3249 $DB->insert_record($tablename, array('name'=>'ouch'));
3250 $DB->insert_record($tablename, array('name'=>'ouc_'));
3251 $DB->insert_record($tablename, array('name'=>'ouc%'));
3252 $DB->insert_record($tablename, array('name'=>'aui'));
3253 $DB->insert_record($tablename, array('name'=>'aüi'));
3254 $DB->insert_record($tablename, array('name'=>'aÜi'));
3256 $sql = "SELECT * FROM {{$tablename}} WHERE ".$DB->sql_like('name', '?', false);
3257 $records = $DB->get_records_sql($sql, array("%dup_r%"));
3258 $this->assertEqual(count($records), 2);
3260 $sql = "SELECT * FROM {{$tablename}} WHERE ".$DB->sql_like('name', '?', true);
3261 $records = $DB->get_records_sql($sql, array("%dup%"));
3262 $this->assertEqual(count($records), 1);
3264 $sql = "SELECT * FROM {{$tablename}} WHERE ".$DB->sql_like('name', '?'); // defaults
3265 $records = $DB->get_records_sql($sql, array("%dup%"));
3266 $this->assertEqual(count($records), 1);
3268 $sql = "SELECT * FROM {{$tablename}} WHERE ".$DB->sql_like('name', '?', true);
3269 $records = $DB->get_records_sql($sql, array("ouc\\_"));
3270 $this->assertEqual(count($records), 1);
3272 $sql = "SELECT * FROM {{$tablename}} WHERE ".$DB->sql_like('name', '?', true, true, false, '|');
3273 $records = $DB->get_records_sql($sql, array($DB->sql_like_escape("ouc%", '|')));
3274 $this->assertEqual(count($records), 1);
3276 $sql = "SELECT * FROM {{$tablename}} WHERE ".$DB->sql_like('name', '?', true, true);
3277 $records = $DB->get_records_sql($sql, array('aui'));
3278 $this->assertEqual(count($records), 1);
3280 $sql = "SELECT * FROM {{$tablename}} WHERE ".$DB->sql_like('name', '?', true, true, true); // NOT LIKE
3281 $records = $DB->get_records_sql($sql, array("%o%"));
3282 $this->assertEqual(count($records), 3);
3284 $sql = "SELECT * FROM {{$tablename}} WHERE ".$DB->sql_like('name', '?', false, true, true); // NOT ILIKE
3285 $records = $DB->get_records_sql($sql, array("%D%"));
3286 $this->assertEqual(count($records), 6);
3288 // TODO: we do not require accent insensitivness yet, just make sure it does not throw errors
3289 $sql = "SELECT * FROM {{$tablename}} WHERE ".$DB->sql_like('name', '?', true, false);
3290 $records = $DB->get_records_sql($sql, array('aui'));
3291 //$this->assertEqual(count($records), 2, 'Accent insensitive LIKE searches may not be supported in all databases, this is not a problem.');
3292 $sql = "SELECT * FROM {{$tablename}} WHERE ".$DB->sql_like('name', '?', false, false);
3293 $records = $DB->get_records_sql($sql, array('aui'));
3294 //$this->assertEqual(count($records), 3, 'Accent insensitive LIKE searches may not be supported in all databases, this is not a problem.');
3297 function test_sql_ilike() {
3298 // note: this is deprecated, just make sure it does not throw error
3300 $dbman = $DB->get_manager();
3302 $table = $this->get_test_table();
3303 $tablename = $table->getName();
3305 $table->add_field('id', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, XMLDB_SEQUENCE, null);
3306 $table->add_field('name', XMLDB_TYPE_CHAR, '255', null, null, null, null);
3307 $table->add_key('primary', XMLDB_KEY_PRIMARY, array('id'));
3308 $dbman->create_table($table);
3310 $DB->insert_record($tablename, array('name'=>'SuperDuperRecord'));
3311 $DB->insert_record($tablename, array('name'=>'NoDupor'));
3312 $DB->insert_record($tablename, array('name'=>'ouch'));
3314 // make sure it prints debug message
3315 $this->enable_debugging();
3316 $sql = "SELECT * FROM {{$tablename}} WHERE name ".$DB->sql_ilike()." ?";
3317 $params = array("%dup_r%");
3318 $this->assertFalse($this->get_debugging() === '');
3320 // following must not throw exception, we ignore result
3321 $DB->get_records_sql($sql, $params);
3324 function test_sql_concat() {
3326 $dbman = $DB->get_manager();
3328 /// Testing all sort of values
3329 $sql = "SELECT ".$DB->sql_concat("?", "?", "?")." AS fullname ". $DB->sql_null_from_clause();
3330 // string, some unicode chars
3331 $params = array('name', 'áéíóú', 'name3');
3332 $this->assertEqual('nameáéíóúname3', $DB->get_field_sql($sql, $params));
3333 // string, spaces and numbers
3334 $params = array('name', ' ', 12345);
3335 $this->assertEqual('name 12345', $DB->get_field_sql($sql, $params));
3336 // float, empty and strings
3337 $params = array(123.45, '', 'test');
3338 $this->assertEqual('123.45test', $DB->get_field_sql($sql, $params));
3340 $params = array(12, 34, 56);
3341 $this->assertEqual('123456', $DB->get_field_sql($sql, $params));
3342 // float, null and strings
3343 $params = array(123.45, null, 'test');
3344 $this->assertNull($DB->get_field_sql($sql, $params), 'ANSI behaviour: Concatenating NULL must return NULL - But in Oracle :-(. [%s]'); // Concatenate NULL with anything result = NULL
3346 /// Testing fieldnames + values and also integer fieldnames
3347 $table = $this->get_test_table();
3348 $tablename = $table->getName();
3350 $table->add_field('id', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, XMLDB_SEQUENCE, null);
3351 $table->add_field('description', XMLDB_TYPE_TEXT, 'big', null, null, null, null);
3352 $table->add_key('primary', XMLDB_KEY_PRIMARY, array('id'));
3353 $dbman->create_table($table);
3355 $DB->insert_record($tablename, array('description'=>'áéíóú'));
3356 $DB->insert_record($tablename, array('description'=>'dxxx'));
3357 $DB->insert_record($tablename, array('description'=>'bcde'));
3359 // fieldnames and values mixed
3360 $sql = 'SELECT id, ' . $DB->sql_concat('description', "'harcoded'", '?', '?') . ' AS result FROM {' . $tablename . '}';
3361 $records = $DB->get_records_sql($sql, array(123.45, 'test'));
3362 $this->assertEqual(count($records), 3);
3363 $this->assertEqual($records[1]->result, 'áéíóúharcoded123.45test');
3364 // integer fieldnames and values
3365 $sql = 'SELECT id, ' . $DB->sql_concat('id', "'harcoded'", '?', '?') . ' AS result FROM {' . $tablename . '}';
3366 $records = $DB->get_records_sql($sql, array(123.45, 'test'));
3367 $this->assertEqual(count($records), 3);
3368 $this->assertEqual($records[1]->result, '1harcoded123.45test');
3369 // all integer fieldnames
3370 $sql = 'SELECT id, ' . $DB->sql_concat('id', 'id', 'id') . ' AS result FROM {' . $tablename . '}';
3371 $records = $DB->get_records_sql($sql, array());
3372 $this->assertEqual(count($records), 3);
3373 $this->assertEqual($records[1]->result, '111');
3377 function test_concat_join() {
3379 $sql = "SELECT ".$DB->sql_concat_join("' '", array("?", "?", "?"))." AS fullname ".$DB->sql_null_from_clause();
3380 $params = array("name", "name2", "name3");
3381 $result = $DB->get_field_sql($sql, $params);
3382 $this->assertEqual("name name2 name3", $result);
3385 function test_sql_fullname() {
3387 $sql = "SELECT ".$DB->sql_fullname(':first', ':last')." AS fullname ".$DB->sql_null_from_clause();
3388 $params = array('first'=>'Firstname', 'last'=>'Surname');
3389 $this->assertEqual("Firstname Surname", $DB->get_field_sql($sql, $params));
3392 function sql_sql_order_by_text() {
3394 $dbman = $DB->get_manager();
3396 $table = $this->get_test_table();
3397 $tablename = $table->getName();
3399 $table->add_field('id', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, XMLDB_SEQUENCE, null);
3400 $table->add_field('description', XMLDB_TYPE_TEXT, 'big', null, null, null, null);
3401 $table->add_key('primary', XMLDB_KEY_PRIMARY, array('id'));
3402 $dbman->create_table($table);
3404 $DB->insert_record($tablename, array('description'=>'abcd'));
3405 $DB->insert_record($tablename, array('description'=>'dxxx'));
3406 $DB->insert_record($tablename, array('description'=>'bcde'));
3408 $sql = "SELECT * FROM {{$tablename}} ORDER BY ".$DB->sql_order_by_text('description');
3409 $records = $DB->get_records_sql($sql);
3410 $first = array_shift($records);
3411 $this->assertEqual(1, $first->id);
3412 $second = array_shift($records);
3413 $this->assertEqual(3, $second->id);
3414 $last = array_shift($records);
3415 $this->assertEqual(2, $last->id);
3418 function test_sql_substring() {
3420 $dbman = $DB->get_manager();
3422 $table = $this->get_test_table();
3423 $tablename = $table->getName();
3425 $table->add_field('id', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, XMLDB_SEQUENCE, null);
3426 $table->add_field('name', XMLDB_TYPE_CHAR, '255', null, null, null, null);
3427 $table->add_key('primary', XMLDB_KEY_PRIMARY, array('id'));
3428 $dbman->create_table($table);
3430 $string = 'abcdefghij';
3432 $DB->insert_record($tablename, array('name'=>$string));
3434 $sql = "SELECT id, ".$DB->sql_substr("name", 5)." AS name FROM {{$tablename}}";
3435 $record = $DB->get_record_sql($sql);
3436 $this->assertEqual(substr($string, 5-1), $record->name);
3438 $sql = "SELECT id, ".$DB->sql_substr("name", 5, 2)." AS name FROM {{$tablename}}";
3439 $record = $DB->get_record_sql($sql);
3440 $this->assertEqual(substr($string, 5-1, 2), $record->name);
3443 // silence php warning ;-)
3444 @$DB->sql_substr("name");
3445 $this->fail("Expecting an exception, none occurred");
3446 } catch (Exception $e) {
3447 $this->assertTrue($e instanceof coding_exception);
3451 function test_sql_length() {
3453 $this->assertEqual($DB->get_field_sql(
3454 "SELECT ".$DB->sql_length("'aeiou'").$DB->sql_null_from_clause()), 5);
3455 $this->assertEqual($DB->get_field_sql(
3456 "SELECT ".$DB->sql_length("'áéíóú'").$DB->sql_null_from_clause()), 5);
3459 function test_sql_position() {
3461 $this->assertEqual($DB->get_field_sql(
3462 "SELECT ".$DB->sql_position("'ood'", "'Moodle'").$DB->sql_null_from_clause()), 2);
3463 $this->assertEqual($DB->get_field_sql(
3464 "SELECT ".$DB->sql_position("'Oracle'", "'Moodle'").$DB->sql_null_from_clause()), 0);
3467 function test_sql_empty() {
3469 $dbman = $DB->get_manager();
3471 $table = $this->get_test_table();
3472 $tablename = $table->getName();
3474 $table->add_field('id', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, XMLDB_SEQUENCE, null);
3475 $table->add_field('name', XMLDB_TYPE_CHAR, '255', null, null, null, null);
3476 $table->add_field('namenotnull', XMLDB_TYPE_CHAR, '255', null, XMLDB_NOTNULL, null, 'default value');
3477 $table->add_field('namenotnullnodeflt', XMLDB_TYPE_CHAR, '255', null, XMLDB_NOTNULL, null, null);
3478 $table->add_key('primary', XMLDB_KEY_PRIMARY, array('id'));
3479 $dbman->create_table($table);
3481 $DB->insert_record($tablename, array('name'=>'', 'namenotnull'=>''));
3482 $DB->insert_record($tablename, array('name'=>null));
3483 $DB->insert_record($tablename, array('name'=>'lalala'));
3484 $DB->insert_record($tablename, array('name'=>0));
3486 $records = $DB->get_records_sql("SELECT * FROM {{$tablename}} WHERE name = '".$DB->sql_empty()."'");
3487 $this->assertEqual(count($records), 1);
3488 $record = reset($records);
3489 $this->assertEqual($record->name, '');
3491 $records = $DB->get_records_sql("SELECT * FROM {{$tablename}} WHERE namenotnull = '".$DB->sql_empty()."'");
3492 $this->assertEqual(count($records), 1);
3493 $record = reset($records);
3494 $this->assertEqual($record->namenotnull, '');
3496 $records = $DB->get_records_sql("SELECT * FROM {{$tablename}} WHERE namenotnullnodeflt = '".$DB->sql_empty()."'");
3497 $this->assertEqual(count($records), 4);
3498 $record = reset($records);
3499 $this->assertEqual($record->namenotnullnodeflt, '');
3502 function test_sql_isempty() {
3504 $dbman = $DB->get_manager();
3506 $table = $this->get_test_table();
3507 $tablename = $table->getName();
3509 $table->add_field('id', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, XMLDB_SEQUENCE, null);
3510 $table->add_field('name', XMLDB_TYPE_CHAR, '255', null, XMLDB_NOTNULL, null, null);
3511 $table->add_field('namenull', XMLDB_TYPE_CHAR, '255', null, null, null, null);
3512 $table->add_field('description', XMLDB_TYPE_TEXT, 'big', null, XMLDB_NOTNULL, null, null);
3513 $table->add_field('descriptionnull', XMLDB_TYPE_TEXT, 'big', null, null, null, null);
3514 $table->add_key('primary', XMLDB_KEY_PRIMARY, array('id'));
3515 $dbman->create_table($table);
3517 $DB->insert_record($tablename, array('name'=>'', 'namenull'=>'', 'description'=>'', 'descriptionnull'=>''));
3518 $DB->insert_record($tablename, array('name'=>'??', 'namenull'=>null, 'description'=>'??', 'descriptionnull'=>null));
3519 $DB->insert_record($tablename, array('name'=>'la', 'namenull'=>'la', 'description'=>'la', 'descriptionnull'=>'lalala'));
3520 $DB->insert_record($tablename, array('name'=>0, 'namenull'=>0, 'description'=>0, 'descriptionnull'=>0));
3522 $records = $DB->get_records_sql("SELECT * FROM {{$tablename}} WHERE ".$DB->sql_isempty($tablename, 'name', false, false));
3523 $this->assertEqual(count($records), 1);
3524 $record = reset($records);
3525 $this->assertEqual($record->name, '');
3527 $records = $DB->get_records_sql("SELECT * FROM {{$tablename}} WHERE ".$DB->sql_isempty($tablename, 'namenull', true, false));
3528 $this->assertEqual(count($records), 1);
3529 $record = reset($records);
3530 $this->assertEqual($record->namenull, '');
3532 $records = $DB->get_records_sql("SELECT * FROM {{$tablename}} WHERE ".$DB->sql_isempty($tablename, 'description', false, true));
3533 $this->assertEqual(count($records), 1);
3534 $record = reset($records);
3535 $this->assertEqual($record->description, '');
3537 $records = $DB->get_records_sql("SELECT * FROM {{$tablename}} WHERE ".$DB->sql_isempty($tablename, 'descriptionnull', true, true));
3538 $this->assertEqual(count($records), 1);
3539 $record = reset($records);
3540 $this->assertEqual($record->descriptionnull, '');
3543 function test_sql_isnotempty() {
3545 $dbman = $DB->get_manager();
3547 $table = $this->get_test_table();
3548 $tablename = $table->getName();
3550 $table->add_field('id', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, XMLDB_SEQUENCE, null);
3551 $table->add_field('name', XMLDB_TYPE_CHAR, '255', null, XMLDB_NOTNULL, null, null);
3552 $table->add_field('namenull', XMLDB_TYPE_CHAR, '255', null, null, null, null);
3553 $table->add_field('description', XMLDB_TYPE_TEXT, 'big', null, XMLDB_NOTNULL, null, null);
3554 $table->add_field('descriptionnull', XMLDB_TYPE_TEXT, 'big', null, null, null, null);
3555 $table->add_key('primary', XMLDB_KEY_PRIMARY, array('id'));
3556 $dbman->create_table($table);
3558 $DB->insert_record($tablename, array('name'=>'', 'namenull'=>'', 'description'=>'', 'descriptionnull'=>''));
3559 $DB->insert_record($tablename, array('name'=>'??', 'namenull'=>null, 'description'=>'??', 'descriptionnull'=>null));
3560 $DB->insert_record($tablename, array('name'=>'la', 'namenull'=>'la', 'description'=>'la', 'descriptionnull'=>'lalala'));
3561 $DB->insert_record($tablename, array('name'=>0, 'namenull'=>0, 'description'=>0, 'descriptionnull'=>0));
3563 $records = $DB->get_records_sql("SELECT * FROM {{$tablename}} WHERE ".$DB->sql_isnotempty($tablename, 'name', false, false));
3564 $this->assertEqual(count($records), 3);
3565 $record = reset($records);
3566 $this->assertEqual($record->name, '??');
3568 $records = $DB->get_records_sql("SELECT * FROM {{$tablename}} WHERE ".$DB->sql_isnotempty($tablename, 'namenull', true, false));
3569 $this->assertEqual(count($records), 2); // nulls aren't comparable (so they aren't "not empty"). SQL expected behaviour
3570 $record = reset($records);
3571 $this->assertEqual($record->namenull, 'la'); // so 'la' is the first non-empty 'namenull' record
3573 $records = $DB->get_records_sql("SELECT * FROM {{$tablename}} WHERE ".$DB->sql_isnotempty($tablename, 'description', false, true));
3574 $this->assertEqual(count($records), 3);
3575 $record = reset($records);
3576 $this->assertEqual($record->description, '??');
3578 $records = $DB->get_records_sql("SELECT * FROM {{$tablename}} WHERE ".$DB->sql_isnotempty($tablename, 'descriptionnull', true, true));
3579 $this->assertEqual(count($records), 2); // nulls aren't comparable (so they aren't "not empty"). SQL expected behaviour
3580 $record = reset($records);
3581 $this->assertEqual($record->descriptionnull, 'lalala'); // so 'lalala' is the first non-empty 'descriptionnull' record
3584 function test_sql_regex() {
3586 $dbman = $DB->get_manager();
3588 $table = $this->get_test_table();
3589 $tablename = $table->getName();
3591 $table->add_field('id', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, XMLDB_SEQUENCE, null);
3592 $table->add_field('name', XMLDB_TYPE_CHAR, '255', null, null, null, null);
3593 $table->add_key('primary', XMLDB_KEY_PRIMARY, array('id'));
3594 $dbman->create_table($table);
3596 $DB->insert_record($tablename, array('name'=>'lalala'));
3597 $DB->insert_record($tablename, array('name'=>'holaaa'));
3598 $DB->insert_record($tablename, array('name'=>'aouch'));
3600 $sql = "SELECT * FROM {{$tablename}} WHERE name ".$DB->sql_regex()." ?";
3601 $params = array('a$');
3602 if ($DB->sql_regex_supported()) {
3603 $records = $DB->get_records_sql($sql, $params);
3604 $this->assertEqual(count($records), 2);
3606 $this->assertTrue(true, 'Regexp operations not supported. Test skipped');
3609 $sql = "SELECT * FROM {{$tablename}} WHERE name ".$DB->sql_regex(false)." ?";
3610 $params = array('.a');
3611 if ($DB->sql_regex_supported()) {
3612 $records = $DB->get_records_sql($sql, $params);
3613 $this->assertEqual(count($records), 1);
3615 $this->assertTrue(true, 'Regexp operations not supported. Test skipped');
3621 * Test some more complex SQL syntax which moodle uses and depends on to work
3622 * useful to determine if new database libraries can be supported.
3624 public function test_get_records_sql_complicated() {
3626 $dbman = $DB->get_manager();
3628 $table = $this->get_test_table();
3629 $tablename = $table->getName();
3631 $table->add_field('id', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, XMLDB_SEQUENCE, null);
3632 $table->add_field('course', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '0');
3633 $table->add_field('name', XMLDB_TYPE_CHAR, '255', null, null, null, null);
3634 $table->add_field('content', XMLDB_TYPE_TEXT, 'big', XMLDB_UNSIGNED, XMLDB_NOTNULL);
3635 $table->add_key('primary', XMLDB_KEY_PRIMARY, array('id'));
3636 $dbman->create_table($table);
3638 $DB->insert_record($tablename, array('course' => 3, 'content' => 'hello', 'name'=>'xyz'));
3639 $DB->insert_record($tablename, array('course' => 3, 'content' => 'world', 'name'=>'abc'));
3640 $DB->insert_record($tablename, array('course' => 5, 'content' => 'hello', 'name'=>'def'));
3641 $DB->insert_record($tablename, array('course' => 2, 'content' => 'universe', 'name'=>'abc'));
3643 // test grouping by expressions in the query. MDL-26819. Note that there are 4 ways:
3644 // - By column position (GROUP by 1) - Not supported by mssql & oracle
3645 // - By column name (GROUP by course) - Supported by all, but leading to wrong results
3646 // - By column alias (GROUP by casecol) - Not supported by mssql & oracle
3647 // - By complete expression (GROUP BY CASE ...) - 100% cross-db, this test checks it
3648 $sql = "SELECT (CASE WHEN course = 3 THEN 1 ELSE 0 END) AS casecol,
3649 COUNT(1) AS countrecs,
3650 MAX(name) AS maxname
3652 GROUP BY CASE WHEN course = 3 THEN 1 ELSE 0 END
3653 ORDER BY casecol DESC";
3655 1 => (object)array('casecol' => 1, 'countrecs' => 2, 'maxname' => 'xyz'),
3656 0 => (object)array('casecol' => 0, 'countrecs' => 2, 'maxname' => 'def'));
3657 $records = $DB->get_records_sql($sql, null);
3658 $this->assertEqual($result, $records);
3660 // test limits in queries with DISTINCT/ALL clauses and multiple whitespace. MDL-25268
3661 $sql = "SELECT DISTINCT course
3665 $records = $DB->get_records_sql($sql, null, 1);
3666 $this->assertEqual(2, count($records));
3667 $this->assertEqual(3, reset($records)->course);
3668 $this->assertEqual(5, next($records)->course);
3670 $records = $DB->get_records_sql($sql, null, 0, 2);
3671 $this->assertEqual(2, count($records));
3672 $this->assertEqual(2, reset($records)->course);
3673 $this->assertEqual(3, next($records)->course);
3674 // both limitfrom and limitnum
3675 $records = $DB->get_records_sql($sql, null, 2, 2);
3676 $this->assertEqual(1, count($records));
3677 $this->assertEqual(5, reset($records)->course);
3679 // we have sql like this in moodle, this syntax breaks on older versions of sqlite for example..
3680 $sql = "SELECT a.id AS id, a.course AS course
3681 FROM {{$tablename}} a
3682 JOIN (SELECT * FROM {{$tablename}}) b ON a.id = b.id
3683 WHERE a.course = ?";
3685 $records = $DB->get_records_sql($sql, array(3));
3686 $this->assertEqual(2, count($records));
3687 $this->assertEqual(1, reset($records)->id);
3688 $this->assertEqual(2, next($records)->id);
3690 // do NOT try embedding sql_xxxx() helper functions in conditions array of count_records(), they don't break params/binding!
3691 $count = $DB->count_records_select($tablename, "course = :course AND ".$DB->sql_compare_text('content')." = :content", array('course' => 3, 'content' => 'hello'));
3692 $this->assertEqual(1, $count);
3694 // test int x string comparison
3696 FROM {{$tablename}} c
3698 $this->assertEqual(count($DB->get_records_sql($sql, array(10))), 0);
3699 $this->assertEqual(count($DB->get_records_sql($sql, array("10"))), 0);
3700 $DB->insert_record($tablename, array('course' => 7, 'content' => 'xx', 'name'=>'1'));
3701 $DB->insert_record($tablename, array('course' => 7, 'content' => 'yy', 'name'=>'2'));
3702 $this->assertEqual(count($DB->get_records_sql($sql, array(1))), 1);
3703 $this->assertEqual(count($DB->get_records_sql($sql, array("1"))), 1);
3704 $this->assertEqual(count($DB->get_records_sql($sql, array(10))), 0);
3705 $this->assertEqual(count($DB->get_records_sql($sql, array("10"))), 0);
3706 $DB->insert_record($tablename, array('course' => 7, 'content' => 'xx', 'name'=>'1abc'));
3707 $this->assertEqual(count($DB->get_records_sql($sql, array(1))), 1);
3708 $this->assertEqual(count($DB->get_records_sql($sql, array("1"))), 1);
3711 function test_onelevel_commit() {
3713 $dbman = $DB->get_manager();
3715 $table = $this->get_test_table();
3716 $tablename = $table->getName();
3718 $table->add_field('id', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, XMLDB_SEQUENCE, null);
3719 $table->add_field('course', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '0');
3720 $table->add_key('primary', XMLDB_KEY_PRIMARY, array('id'));
3721 $dbman->create_table($table);
3723 $transaction = $DB->start_delegated_transaction();
3724 $data = (object)array('course'=>3);
3725 $this->assertEqual(0, $DB->count_records($tablename));
3726 $DB->insert_record($tablename, $data);
3727 $this->assertEqual(1, $DB->count_records($tablename));
3728 $transaction->allow_commit();
3729 $this->assertEqual(1, $DB->count_records($tablename));
3732 function test_onelevel_rollback() {
3734 $dbman = $DB->get_manager();
3736 $table = $this->get_test_table();
3737 $tablename = $table->getName();
3739 $table->add_field('id', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, XMLDB_SEQUENCE, null);
3740 $table->add_field('course', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '0');
3741 $table->add_key('primary', XMLDB_KEY_PRIMARY, array('id'));
3742 $dbman->create_table($table);
3744 // this might in fact encourage ppl to migrate from myisam to innodb
3746 $transaction = $DB->start_delegated_transaction();
3747 $data = (object)array('course'=>3);
3748 $this->assertEqual(0, $DB->count_records($tablename));
3749 $DB->insert_record($tablename, $data);
3750 $this->assertEqual(1, $DB->count_records($tablename));
3752 $transaction->rollback(new Exception('test'));
3753 $this->fail('transaction rollback must rethrow exception');
3754 } catch (Exception $e) {
3756 $this->assertEqual(0, $DB->count_records($tablename));
3759 function test_nested_transactions() {
3761 $dbman = $DB->get_manager();
3763 $table = $this->get_test_table();
3764 $tablename = $table->getName();
3766 $table->add_field('id', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, XMLDB_SEQUENCE, null);
3767 $table->add_field('course', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '0');
3768 $table->add_key('primary', XMLDB_KEY_PRIMARY, array('id'));
3769 $dbman->create_table($table);
3772 $this->assertFalse($DB->is_transaction_started());
3773 $transaction1 = $DB->start_delegated_transaction();
3774 $this->assertTrue($DB->is_transaction_started());
3775 $data = (object)array('course'=>3);
3776 $DB->insert_record($tablename, $data);
3777 $transaction2 = $DB->start_delegated_transaction();
3778 $data = (object)array('course'=>4);