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_strtok() {
507 // strtok was previously used by bound emulation, make sure it is not used any more
509 $dbman = $this->tdb->get_manager();
511 $table = $this->get_test_table();
512 $tablename = $table->getName();
514 $table->add_field('id', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, XMLDB_SEQUENCE, null);
515 $table->add_field('course', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '0');
516 $table->add_field('name', XMLDB_TYPE_CHAR, '255', null, null, null, 'lala');
517 $table->add_key('primary', XMLDB_KEY_PRIMARY, array('id'));
518 $dbman->create_table($table);
521 $this->assertIdentical(strtok($str, '?'), 'a');
523 $DB->get_records($tablename, array('id'=>1));
525 $this->assertIdentical(strtok('?'), 'b');
528 public function test_tweak_param_names() {
529 // Note the tweak_param_names() method is only available in the oracle driver,
530 // hence we look for expected results indirectly, by testing various DML methods
531 // with some "extreme" conditions causing the tweak to happen.
533 $dbman = $this->tdb->get_manager();
535 $table = $this->get_test_table();
536 $tablename = $table->getName();
538 $table->add_field('id', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, XMLDB_SEQUENCE, null);
539 // Add some columns with 28 chars in the name
540 $table->add_field('long_int_columnname_with_28c', XMLDB_TYPE_INTEGER, '10');
541 $table->add_field('long_dec_columnname_with_28c', XMLDB_TYPE_NUMBER, '10,2');
542 $table->add_field('long_str_columnname_with_28c', XMLDB_TYPE_CHAR, '100');
543 // Add some columns with 30 chars in the name
544 $table->add_field('long_int_columnname_with_30cxx', XMLDB_TYPE_INTEGER, '10');
545 $table->add_field('long_dec_columnname_with_30cxx', XMLDB_TYPE_NUMBER, '10,2');
546 $table->add_field('long_str_columnname_with_30cxx', XMLDB_TYPE_CHAR, '100');
548 $table->add_key('primary', XMLDB_KEY_PRIMARY, array('id'));
550 $dbman->create_table($table);
552 $this->assertTrue($dbman->table_exists($tablename));
554 // Test insert record
555 $rec1 = new stdClass();
556 $rec1->long_int_columnname_with_28c = 28;
557 $rec1->long_dec_columnname_with_28c = 28.28;
558 $rec1->long_str_columnname_with_28c = '28';
559 $rec1->long_int_columnname_with_30cxx = 30;
560 $rec1->long_dec_columnname_with_30cxx = 30.30;
561 $rec1->long_str_columnname_with_30cxx = '30';
564 $rec1->id = $DB->insert_record($tablename, $rec1);
565 $this->assertEqual($rec1, $DB->get_record($tablename, array('id' => $rec1->id)));
568 $DB->update_record($tablename, $rec1);
569 $this->assertEqual($rec1, $DB->get_record($tablename, array('id' => $rec1->id)));
572 $rec1->long_int_columnname_with_28c = 280;
573 $DB->set_field($tablename, 'long_int_columnname_with_28c', $rec1->long_int_columnname_with_28c,
574 array('id' => $rec1->id, 'long_int_columnname_with_28c' => 28));
575 $rec1->long_dec_columnname_with_28c = 280.28;
576 $DB->set_field($tablename, 'long_dec_columnname_with_28c', $rec1->long_dec_columnname_with_28c,
577 array('id' => $rec1->id, 'long_dec_columnname_with_28c' => 28.28));
578 $rec1->long_str_columnname_with_28c = '280';
579 $DB->set_field($tablename, 'long_str_columnname_with_28c', $rec1->long_str_columnname_with_28c,
580 array('id' => $rec1->id, 'long_str_columnname_with_28c' => '28'));
581 $rec1->long_int_columnname_with_30cxx = 300;
582 $DB->set_field($tablename, 'long_int_columnname_with_30cxx', $rec1->long_int_columnname_with_30cxx,
583 array('id' => $rec1->id, 'long_int_columnname_with_30cxx' => 30));
584 $rec1->long_dec_columnname_with_30cxx = 300.30;
585 $DB->set_field($tablename, 'long_dec_columnname_with_30cxx', $rec1->long_dec_columnname_with_30cxx,
586 array('id' => $rec1->id, 'long_dec_columnname_with_30cxx' => 30.30));
587 $rec1->long_str_columnname_with_30cxx = '300';
588 $DB->set_field($tablename, 'long_str_columnname_with_30cxx', $rec1->long_str_columnname_with_30cxx,
589 array('id' => $rec1->id, 'long_str_columnname_with_30cxx' => '30'));
590 $this->assertEqual($rec1, $DB->get_record($tablename, array('id' => $rec1->id)));
593 $rec2 = $DB->get_record($tablename, array('id' => $rec1->id));
594 $rec2->id = $DB->insert_record($tablename, $rec2);
595 $this->assertEqual(2, $DB->count_records($tablename));
596 $DB->delete_records($tablename, (array) $rec2);
597 $this->assertEqual(1, $DB->count_records($tablename));
600 $rs = $DB->get_recordset($tablename, (array) $rec1);
602 foreach ($rs as $rec2) {
606 $this->assertEqual(1, $iterations);
607 $this->assertEqual($rec1, $rec2);
610 $recs = $DB->get_records($tablename, (array) $rec1);
611 $this->assertEqual(1, count($recs));
612 $this->assertEqual($rec1, reset($recs));
614 // get_fieldset_select()
615 $select = 'id = :id AND
616 long_int_columnname_with_28c = :long_int_columnname_with_28c AND
617 long_dec_columnname_with_28c = :long_dec_columnname_with_28c AND
618 long_str_columnname_with_28c = :long_str_columnname_with_28c AND
619 long_int_columnname_with_30cxx = :long_int_columnname_with_30cxx AND
620 long_dec_columnname_with_30cxx = :long_dec_columnname_with_30cxx AND
621 long_str_columnname_with_30cxx = :long_str_columnname_with_30cxx';
622 $fields = $DB->get_fieldset_select($tablename, 'long_int_columnname_with_28c', $select, (array)$rec1);
623 $this->assertEqual(1, count($fields));
624 $this->assertEqual($rec1->long_int_columnname_with_28c, reset($fields));
625 $fields = $DB->get_fieldset_select($tablename, 'long_dec_columnname_with_28c', $select, (array)$rec1);
626 $this->assertEqual($rec1->long_dec_columnname_with_28c, reset($fields));
627 $fields = $DB->get_fieldset_select($tablename, 'long_str_columnname_with_28c', $select, (array)$rec1);
628 $this->assertEqual($rec1->long_str_columnname_with_28c, reset($fields));
629 $fields = $DB->get_fieldset_select($tablename, 'long_int_columnname_with_30cxx', $select, (array)$rec1);
630 $this->assertEqual($rec1->long_int_columnname_with_30cxx, reset($fields));
631 $fields = $DB->get_fieldset_select($tablename, 'long_dec_columnname_with_30cxx', $select, (array)$rec1);
632 $this->assertEqual($rec1->long_dec_columnname_with_30cxx, reset($fields));
633 $fields = $DB->get_fieldset_select($tablename, 'long_str_columnname_with_30cxx', $select, (array)$rec1);
634 $this->assertEqual($rec1->long_str_columnname_with_30cxx, reset($fields));
636 // overlapping placeholders (progressive str_replace)
637 $overlapselect = 'id = :p AND
638 long_int_columnname_with_28c = :param1 AND
639 long_dec_columnname_with_28c = :param2 AND
640 long_str_columnname_with_28c = :param_with_29_characters_long AND
641 long_int_columnname_with_30cxx = :param_with_30_characters_long_ AND
642 long_dec_columnname_with_30cxx = :param_ AND
643 long_str_columnname_with_30cxx = :param__';
644 $overlapparams = array(
646 'param1' => $rec1->long_int_columnname_with_28c,
647 'param2' => $rec1->long_dec_columnname_with_28c,
648 'param_with_29_characters_long' => $rec1->long_str_columnname_with_28c,
649 'param_with_30_characters_long_' => $rec1->long_int_columnname_with_30cxx,
650 'param_' => $rec1->long_dec_columnname_with_30cxx,
651 'param__' => $rec1->long_str_columnname_with_30cxx);
652 $recs = $DB->get_records_select($tablename, $overlapselect, $overlapparams);
653 $this->assertEqual(1, count($recs));
654 $this->assertEqual($rec1, reset($recs));
657 $DB->execute("DELETE FROM {{$tablename}} WHERE $select", (array)$rec1);
658 $this->assertEqual(0, $DB->count_records($tablename));
661 public function test_get_tables() {
663 $dbman = $this->tdb->get_manager();
665 // Need to test with multiple DBs
666 $table = $this->get_test_table();
667 $tablename = $table->getName();
669 $original_count = count($DB->get_tables());
671 $table->add_field('id', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, XMLDB_SEQUENCE, null);
672 $table->add_key('primary', XMLDB_KEY_PRIMARY, array('id'));
674 $dbman->create_table($table);
675 $this->assertTrue(count($DB->get_tables()) == $original_count + 1);
677 $dbman->drop_table($table);
678 $this->assertTrue(count($DB->get_tables()) == $original_count);
681 public function test_get_indexes() {
683 $dbman = $this->tdb->get_manager();
685 $table = $this->get_test_table();
686 $tablename = $table->getName();
688 $table->add_field('id', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, XMLDB_SEQUENCE, null);
689 $table->add_field('course', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '0');
690 $table->add_key('primary', XMLDB_KEY_PRIMARY, array('id'));
691 $table->add_index('course', XMLDB_INDEX_NOTUNIQUE, array('course'));
692 $table->add_index('course-id', XMLDB_INDEX_UNIQUE, array('course', 'id'));
693 $dbman->create_table($table);
695 $indices = $DB->get_indexes($tablename);
696 $this->assertTrue(is_array($indices));
697 $this->assertEqual(count($indices), 2);
698 // we do not care about index names for now
699 $first = array_shift($indices);
700 $second = array_shift($indices);
701 if (count($first['columns']) == 2) {
708 $this->assertFalse($single['unique']);
709 $this->assertTrue($composed['unique']);
710 $this->assertEqual(1, count($single['columns']));
711 $this->assertEqual(2, count($composed['columns']));
712 $this->assertEqual('course', $single['columns'][0]);
713 $this->assertEqual('course', $composed['columns'][0]);
714 $this->assertEqual('id', $composed['columns'][1]);
717 public function test_get_columns() {
719 $dbman = $this->tdb->get_manager();
721 $table = $this->get_test_table();
722 $tablename = $table->getName();
724 $table->add_field('id', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, XMLDB_SEQUENCE, null);
725 $table->add_field('course', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '0');
726 $table->add_field('name', XMLDB_TYPE_CHAR, '255', null, null, null, 'lala');
727 $table->add_field('description', XMLDB_TYPE_TEXT, 'small', null, null, null, null);
728 $table->add_field('enumfield', XMLDB_TYPE_CHAR, '255', null, XMLDB_NOTNULL, null, 'test2');
729 $table->add_field('onenum', XMLDB_TYPE_NUMBER, '10,2', null, null, null, 200);
730 $table->add_key('primary', XMLDB_KEY_PRIMARY, array('id'));
731 $dbman->create_table($table);
733 $columns = $DB->get_columns($tablename);
734 $this->assertTrue(is_array($columns));
736 $fields = $table->getFields();
737 $this->assertEqual(count($columns), count($fields));
739 $field = $columns['id'];
740 $this->assertEqual('R', $field->meta_type);
741 $this->assertTrue($field->auto_increment);
742 $this->assertTrue($field->unique);
744 $field = $columns['course'];
745 $this->assertEqual('I', $field->meta_type);
746 $this->assertFalse($field->auto_increment);
747 $this->assertTrue($field->has_default);
748 $this->assertEqual(0, $field->default_value);
749 $this->assertTrue($field->not_null);
751 $field = $columns['name'];
752 $this->assertEqual('C', $field->meta_type);
753 $this->assertFalse($field->auto_increment);
754 $this->assertEqual(255, $field->max_length);
755 $this->assertTrue($field->has_default);
756 $this->assertIdentical('lala', $field->default_value);
757 $this->assertFalse($field->not_null);
759 $field = $columns['description'];
760 $this->assertEqual('X', $field->meta_type);
761 $this->assertFalse($field->auto_increment);
762 $this->assertFalse($field->has_default);
763 $this->assertIdentical(null, $field->default_value);
764 $this->assertFalse($field->not_null);
766 $field = $columns['enumfield'];
767 $this->assertEqual('C', $field->meta_type);
768 $this->assertFalse($field->auto_increment);
769 $this->assertIdentical('test2', $field->default_value);
770 $this->assertTrue($field->not_null);
772 $field = $columns['onenum'];
773 $this->assertEqual('N', $field->meta_type);
774 $this->assertFalse($field->auto_increment);
775 $this->assertTrue($field->has_default);
776 $this->assertEqual(200.0, $field->default_value);
777 $this->assertFalse($field->not_null);
779 for ($i = 0; $i < count($columns); $i++) {
781 $next_column = reset($columns);
782 $next_field = reset($fields);
784 $next_column = next($columns);
785 $next_field = next($fields);
788 $this->assertEqual($next_column->name, $next_field->name);
792 public function test_get_manager() {
794 $dbman = $this->tdb->get_manager();
796 $this->assertTrue($dbman instanceof database_manager);
799 public function test_setup_is_unicodedb() {
801 $this->assertTrue($DB->setup_is_unicodedb());
804 public function test_set_debug() { //tests get_debug() too
806 $dbman = $this->tdb->get_manager();
808 $table = $this->get_test_table();
809 $tablename = $table->getName();
811 $table->add_field('id', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, XMLDB_SEQUENCE, null);
812 $table->add_field('course', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '0');
813 $table->add_key('primary', XMLDB_KEY_PRIMARY, array('id'));
814 $dbman->create_table($table);
816 $sql = "SELECT * FROM {{$tablename}}";
818 $prevdebug = $DB->get_debug();
821 $DB->set_debug(true);
822 $this->assertTrue($DB->get_debug());
824 $DB->set_debug(false);
825 $this->assertFalse($DB->get_debug());
826 $debuginfo = ob_get_contents();
828 $this->assertFalse($debuginfo === '');
832 $debuginfo = ob_get_contents();
834 $this->assertTrue($debuginfo === '');
836 $DB->set_debug($prevdebug);
839 public function test_execute() {
841 $dbman = $this->tdb->get_manager();
843 $table1 = $this->get_test_table('1');
844 $tablename1 = $table1->getName();
845 $table1->add_field('id', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, XMLDB_SEQUENCE, null);
846 $table1->add_field('course', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '0');
847 $table1->add_field('name', XMLDB_TYPE_CHAR, '255', null, null, null, '0');
848 $table1->add_index('course', XMLDB_INDEX_NOTUNIQUE, array('course'));
849 $table1->add_key('primary', XMLDB_KEY_PRIMARY, array('id'));
850 $dbman->create_table($table1);
852 $table2 = $this->get_test_table('2');
853 $tablename2 = $table2->getName();
854 $table2->add_field('id', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, XMLDB_SEQUENCE, null);
855 $table2->add_field('course', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '0');
856 $table2->add_key('primary', XMLDB_KEY_PRIMARY, array('id'));
857 $dbman->create_table($table2);
859 $DB->insert_record($tablename1, array('course' => 3, 'name' => 'aaa'));
860 $DB->insert_record($tablename1, array('course' => 1, 'name' => 'bbb'));
861 $DB->insert_record($tablename1, array('course' => 7, 'name' => 'ccc'));
862 $DB->insert_record($tablename1, array('course' => 3, 'name' => 'ddd'));
864 // select results are ignored
865 $sql = "SELECT * FROM {{$tablename1}} WHERE course = :course";
866 $this->assertTrue($DB->execute($sql, array('course'=>3)));
868 // throw exception on error
869 $sql = "XXUPDATE SET XSSD";
872 $this->fail("Expecting an exception, none occurred");
873 } catch (Exception $e) {
874 $this->assertTrue($e instanceof dml_write_exception);
878 $sql = "UPDATE {{$tablename1}}
881 $this->assertTrue($DB->execute($sql, array('3')));
882 $this->assertEqual($DB->count_records($tablename1, array('course' => 6)), 2);
884 // insert from one into second table
885 $sql = "INSERT INTO {{$tablename2}} (course)
888 FROM {{$tablename1}}";
889 $this->assertTrue($DB->execute($sql));
890 $this->assertEqual($DB->count_records($tablename2), 4);
893 public function test_get_recordset() {
895 $dbman = $DB->get_manager();
897 $table = $this->get_test_table();
898 $tablename = $table->getName();
900 $table->add_field('id', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, XMLDB_SEQUENCE, null);
901 $table->add_field('course', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '0');
902 $table->add_field('name', XMLDB_TYPE_CHAR, '255', null, null, null, '0');
903 $table->add_field('onetext', XMLDB_TYPE_TEXT, 'big', null, null, null);
904 $table->add_index('course', XMLDB_INDEX_NOTUNIQUE, array('course'));
905 $table->add_key('primary', XMLDB_KEY_PRIMARY, array('id'));
906 $dbman->create_table($table);
908 $data = array(array('id' => 1, 'course' => 3, 'name' => 'record1', 'onetext'=>'abc'),
909 array('id' => 2, 'course' => 3, 'name' => 'record2', 'onetext'=>'abcd'),
910 array('id' => 3, 'course' => 5, 'name' => 'record3', 'onetext'=>'abcde'));
912 foreach ($data as $record) {
913 $DB->insert_record($tablename, $record);
916 // standard recordset iteration
917 $rs = $DB->get_recordset($tablename);
918 $this->assertTrue($rs instanceof moodle_recordset);
920 foreach($rs as $record) {
921 $data_record = current($data);
922 foreach ($record as $k => $v) {
923 $this->assertEqual($data_record[$k], $v);
929 // iterator style usage
930 $rs = $DB->get_recordset($tablename);
931 $this->assertTrue($rs instanceof moodle_recordset);
933 while ($rs->valid()) {
934 $record = $rs->current();
935 $data_record = current($data);
936 foreach ($record as $k => $v) {
937 $this->assertEqual($data_record[$k], $v);
944 // make sure rewind is ignored
945 $rs = $DB->get_recordset($tablename);
946 $this->assertTrue($rs instanceof moodle_recordset);
949 foreach($rs as $record) {
953 $this->fail('revind not ignored in recordsets');
956 $data_record = current($data);
957 foreach ($record as $k => $v) {
958 $this->assertEqual($data_record[$k], $v);
964 // test for exception throwing on text conditions being compared. (MDL-24863, unwanted auto conversion of param to int)
965 $conditions = array('onetext' => '1');
967 $rs = $DB->get_recordset($tablename, $conditions);
968 $this->fail('An Exception is missing, expected due to equating of text fields');
969 } catch (exception $e) {
970 $this->assertTrue($e instanceof dml_exception);
971 $this->assertEqual($e->errorcode, 'textconditionsnotallowed');
975 // * limits are tested in test_get_recordset_sql()
976 // * where_clause() is used internally and is tested in test_get_records()
979 public function test_get_recordset_iterator_keys() {
981 $dbman = $DB->get_manager();
983 $table = $this->get_test_table();
984 $tablename = $table->getName();
986 $table->add_field('id', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, XMLDB_SEQUENCE, null);
987 $table->add_field('course', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '0');
988 $table->add_field('name', XMLDB_TYPE_CHAR, '255', null, null, null, '0');
989 $table->add_index('course', XMLDB_INDEX_NOTUNIQUE, array('course'));
990 $table->add_key('primary', XMLDB_KEY_PRIMARY, array('id'));
991 $dbman->create_table($table);
993 $data = array(array('id'=> 1, 'course' => 3, 'name' => 'record1'),
994 array('id'=> 2, 'course' => 3, 'name' => 'record2'),
995 array('id'=> 3, 'course' => 5, 'name' => 'record3'));
996 foreach ($data as $record) {
997 $DB->insert_record($tablename, $record);
1000 // Test repeated numeric keys are returned ok
1001 $rs = $DB->get_recordset($tablename, NULL, NULL, 'course, name, id');
1005 foreach($rs as $key => $record) {
1006 $data_record = current($data);
1007 $this->assertEqual($data_record['course'], $key);
1012 $this->assertEqual($count, 3);
1014 // Test string keys are returned ok
1015 $rs = $DB->get_recordset($tablename, NULL, NULL, 'name, course, id');
1019 foreach($rs as $key => $record) {
1020 $data_record = current($data);
1021 $this->assertEqual($data_record['name'], $key);
1026 $this->assertEqual($count, 3);
1028 // Test numeric not starting in 1 keys are returned ok
1029 $rs = $DB->get_recordset($tablename, NULL, 'id DESC', 'id, course, name');
1031 $data = array_reverse($data);
1034 foreach($rs as $key => $record) {
1035 $data_record = current($data);
1036 $this->assertEqual($data_record['id'], $key);
1041 $this->assertEqual($count, 3);
1044 public function test_get_recordset_list() {
1046 $dbman = $DB->get_manager();
1048 $table = $this->get_test_table();
1049 $tablename = $table->getName();
1051 $table->add_field('id', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, XMLDB_SEQUENCE, null);
1052 $table->add_field('course', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '0');
1053 $table->add_index('course', XMLDB_INDEX_NOTUNIQUE, array('course'));
1054 $table->add_key('primary', XMLDB_KEY_PRIMARY, array('id'));
1055 $dbman->create_table($table);
1057 $DB->insert_record($tablename, array('course' => 3));
1058 $DB->insert_record($tablename, array('course' => 3));
1059 $DB->insert_record($tablename, array('course' => 5));
1060 $DB->insert_record($tablename, array('course' => 2));
1062 $rs = $DB->get_recordset_list($tablename, 'course', array(3, 2));
1065 foreach ($rs as $record) {
1068 $this->assertEqual(3, $counter);
1071 $rs = $DB->get_recordset_list($tablename, 'course',array()); /// Must return 0 rows without conditions. MDL-17645
1074 foreach ($rs as $record) {
1078 $this->assertEqual(0, $counter);
1081 // * limits are tested in test_get_recordset_sql()
1082 // * where_clause() is used internally and is tested in test_get_records()
1085 public function test_get_recordset_select() {
1087 $dbman = $DB->get_manager();
1089 $table = $this->get_test_table();
1090 $tablename = $table->getName();
1092 $table->add_field('id', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, XMLDB_SEQUENCE, null);
1093 $table->add_field('course', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '0');
1094 $table->add_key('primary', XMLDB_KEY_PRIMARY, array('id'));
1095 $dbman->create_table($table);
1097 $DB->insert_record($tablename, array('course' => 3));
1098 $DB->insert_record($tablename, array('course' => 3));
1099 $DB->insert_record($tablename, array('course' => 5));
1100 $DB->insert_record($tablename, array('course' => 2));
1102 $rs = $DB->get_recordset_select($tablename, '');
1104 foreach ($rs as $record) {
1108 $this->assertEqual(4, $counter);
1110 $this->assertTrue($rs = $DB->get_recordset_select($tablename, 'course = 3'));
1112 foreach ($rs as $record) {
1116 $this->assertEqual(2, $counter);
1119 // * limits are tested in test_get_recordset_sql()
1122 public function test_get_recordset_sql() {
1124 $dbman = $DB->get_manager();
1126 $table = $this->get_test_table();
1127 $tablename = $table->getName();
1129 $table->add_field('id', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, XMLDB_SEQUENCE, null);
1130 $table->add_field('course', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '0');
1131 $table->add_key('primary', XMLDB_KEY_PRIMARY, array('id'));
1132 $dbman->create_table($table);
1134 $inskey1 = $DB->insert_record($tablename, array('course' => 3));
1135 $inskey2 = $DB->insert_record($tablename, array('course' => 5));
1136 $inskey3 = $DB->insert_record($tablename, array('course' => 4));
1137 $inskey4 = $DB->insert_record($tablename, array('course' => 3));
1138 $inskey5 = $DB->insert_record($tablename, array('course' => 2));
1139 $inskey6 = $DB->insert_record($tablename, array('course' => 1));
1140 $inskey7 = $DB->insert_record($tablename, array('course' => 0));
1142 $rs = $DB->get_recordset_sql("SELECT * FROM {{$tablename}} WHERE course = ?", array(3));
1144 foreach ($rs as $record) {
1148 $this->assertEqual(2, $counter);
1150 // limits - only need to test this case, the rest have been tested by test_get_records_sql()
1151 // only limitfrom = skips that number of records
1152 $rs = $DB->get_recordset_sql("SELECT * FROM {{$tablename}} ORDER BY id", null, 2, 0);
1154 foreach($rs as $key => $record) {
1155 $records[$key] = $record;
1158 $this->assertEqual(5, count($records));
1159 $this->assertEqual($inskey3, reset($records)->id);
1160 $this->assertEqual($inskey7, end($records)->id);
1162 // note: fetching nulls, empties, LOBs already tested by test_insert_record() no needed here
1165 public function test_get_records() {
1167 $dbman = $DB->get_manager();
1169 $table = $this->get_test_table();
1170 $tablename = $table->getName();
1172 $table->add_field('id', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, XMLDB_SEQUENCE, null);
1173 $table->add_field('course', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '0');
1174 $table->add_field('onetext', XMLDB_TYPE_TEXT, 'big', null, null, null);
1175 $table->add_key('primary', XMLDB_KEY_PRIMARY, array('id'));
1176 $dbman->create_table($table);
1178 $DB->insert_record($tablename, array('course' => 3));
1179 $DB->insert_record($tablename, array('course' => 3));
1180 $DB->insert_record($tablename, array('course' => 5));
1181 $DB->insert_record($tablename, array('course' => 2));
1184 $records = $DB->get_records($tablename);
1185 $this->assertEqual(4, count($records));
1186 $this->assertEqual(3, $records[1]->course);
1187 $this->assertEqual(3, $records[2]->course);
1188 $this->assertEqual(5, $records[3]->course);
1189 $this->assertEqual(2, $records[4]->course);
1191 // Records matching certain conditions
1192 $records = $DB->get_records($tablename, array('course' => 3));
1193 $this->assertEqual(2, count($records));
1194 $this->assertEqual(3, $records[1]->course);
1195 $this->assertEqual(3, $records[2]->course);
1197 // All records sorted by course
1198 $records = $DB->get_records($tablename, null, 'course');
1199 $this->assertEqual(4, count($records));
1200 $current_record = reset($records);
1201 $this->assertEqual(4, $current_record->id);
1202 $current_record = next($records);
1203 $this->assertEqual(1, $current_record->id);
1204 $current_record = next($records);
1205 $this->assertEqual(2, $current_record->id);
1206 $current_record = next($records);
1207 $this->assertEqual(3, $current_record->id);
1209 // All records, but get only one field
1210 $records = $DB->get_records($tablename, null, '', 'id');
1211 $this->assertFalse(isset($records[1]->course));
1212 $this->assertTrue(isset($records[1]->id));
1213 $this->assertEqual(4, count($records));
1215 // Booleans into params
1216 $records = $DB->get_records($tablename, array('course' => true));
1217 $this->assertEqual(0, count($records));
1218 $records = $DB->get_records($tablename, array('course' => false));
1219 $this->assertEqual(0, count($records));
1221 // test for exception throwing on text conditions being compared. (MDL-24863, unwanted auto conversion of param to int)
1222 $conditions = array('onetext' => '1');
1224 $records = $DB->get_records($tablename, $conditions);
1225 $this->fail('An Exception is missing, expected due to equating of text fields');
1226 } catch (exception $e) {
1227 $this->assertTrue($e instanceof dml_exception);
1228 $this->assertEqual($e->errorcode, 'textconditionsnotallowed');
1231 // note: delegate limits testing to test_get_records_sql()
1234 public function test_get_records_list() {
1236 $dbman = $DB->get_manager();
1238 $table = $this->get_test_table();
1239 $tablename = $table->getName();
1241 $table->add_field('id', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, XMLDB_SEQUENCE, null);
1242 $table->add_field('course', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '0');
1243 $table->add_key('primary', XMLDB_KEY_PRIMARY, array('id'));
1244 $dbman->create_table($table);
1246 $DB->insert_record($tablename, array('course' => 3));
1247 $DB->insert_record($tablename, array('course' => 3));
1248 $DB->insert_record($tablename, array('course' => 5));
1249 $DB->insert_record($tablename, array('course' => 2));
1251 $records = $DB->get_records_list($tablename, 'course', array(3, 2));
1252 $this->assertTrue(is_array($records));
1253 $this->assertEqual(3, count($records));
1254 $this->assertEqual(1, reset($records)->id);
1255 $this->assertEqual(2, next($records)->id);
1256 $this->assertEqual(4, next($records)->id);
1258 $this->assertIdentical(array(), $records = $DB->get_records_list($tablename, 'course', array())); /// Must return 0 rows without conditions. MDL-17645
1259 $this->assertEqual(0, count($records));
1261 // note: delegate limits testing to test_get_records_sql()
1264 public function test_get_records_sql() {
1266 $dbman = $DB->get_manager();
1268 $table = $this->get_test_table();
1269 $tablename = $table->getName();
1271 $table->add_field('id', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, XMLDB_SEQUENCE, null);
1272 $table->add_field('course', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '0');
1273 $table->add_key('primary', XMLDB_KEY_PRIMARY, array('id'));
1274 $dbman->create_table($table);
1276 $inskey1 = $DB->insert_record($tablename, array('course' => 3));
1277 $inskey2 = $DB->insert_record($tablename, array('course' => 5));
1278 $inskey3 = $DB->insert_record($tablename, array('course' => 4));
1279 $inskey4 = $DB->insert_record($tablename, array('course' => 3));
1280 $inskey5 = $DB->insert_record($tablename, array('course' => 2));
1281 $inskey6 = $DB->insert_record($tablename, array('course' => 1));
1282 $inskey7 = $DB->insert_record($tablename, array('course' => 0));
1284 $table2 = $this->get_test_table("2");
1285 $tablename2 = $table2->getName();
1286 $table2->add_field('id', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, XMLDB_SEQUENCE, null);
1287 $table2->add_field('course', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '0');
1288 $table2->add_field('nametext', XMLDB_TYPE_TEXT, 'small', null, null, null, null);
1289 $table2->add_key('primary', XMLDB_KEY_PRIMARY, array('id'));
1290 $dbman->create_table($table2);
1292 $DB->insert_record($tablename2, array('course'=>3, 'nametext'=>'badabing'));
1293 $DB->insert_record($tablename2, array('course'=>4, 'nametext'=>'badabang'));
1294 $DB->insert_record($tablename2, array('course'=>5, 'nametext'=>'badabung'));
1295 $DB->insert_record($tablename2, array('course'=>6, 'nametext'=>'badabong'));
1297 $records = $DB->get_records_sql("SELECT * FROM {{$tablename}} WHERE course = ?", array(3));
1298 $this->assertEqual(2, count($records));
1299 $this->assertEqual($inskey1, reset($records)->id);
1300 $this->assertEqual($inskey4, next($records)->id);
1302 // Awful test, requires debug enabled and sent to browser. Let's do that and restore after test
1303 $this->enable_debugging();
1304 $records = $DB->get_records_sql("SELECT course AS id, course AS course FROM {{$tablename}}", null);
1305 $this->assertFalse($this->get_debugging() === '');
1306 $this->assertEqual(6, count($records));
1308 // negative limits = no limits
1309 $records = $DB->get_records_sql("SELECT * FROM {{$tablename}} ORDER BY id", null, -1, -1);
1310 $this->assertEqual(7, count($records));
1312 // zero limits = no limits
1313 $records = $DB->get_records_sql("SELECT * FROM {{$tablename}} ORDER BY id", null, 0, 0);
1314 $this->assertEqual(7, count($records));
1316 // only limitfrom = skips that number of records
1317 $records = $DB->get_records_sql("SELECT * FROM {{$tablename}} ORDER BY id", null, 2, 0);
1318 $this->assertEqual(5, count($records));
1319 $this->assertEqual($inskey3, reset($records)->id);
1320 $this->assertEqual($inskey7, end($records)->id);
1322 // only limitnum = fetches that number of records
1323 $records = $DB->get_records_sql("SELECT * FROM {{$tablename}} ORDER BY id", null, 0, 3);
1324 $this->assertEqual(3, count($records));
1325 $this->assertEqual($inskey1, reset($records)->id);
1326 $this->assertEqual($inskey3, end($records)->id);
1328 // both limitfrom and limitnum = skips limitfrom records and fetches limitnum ones
1329 $records = $DB->get_records_sql("SELECT * FROM {{$tablename}} ORDER BY id", null, 3, 2);
1330 $this->assertEqual(2, count($records));
1331 $this->assertEqual($inskey4, reset($records)->id);
1332 $this->assertEqual($inskey5, end($records)->id);
1334 // both limitfrom and limitnum in query having subqueris
1335 // note the subquery skips records with course = 0 and 3
1336 $sql = "SELECT * FROM {{$tablename}}
1337 WHERE course NOT IN (
1338 SELECT course FROM {{$tablename}}
1339 WHERE course IN (0, 3))
1341 $records = $DB->get_records_sql($sql, null, 0, 2); // Skip 0, get 2
1342 $this->assertEqual(2, count($records));
1343 $this->assertEqual($inskey6, reset($records)->id);
1344 $this->assertEqual($inskey5, end($records)->id);
1345 $records = $DB->get_records_sql($sql, null, 2, 2); // Skip 2, get 2
1346 $this->assertEqual(2, count($records));
1347 $this->assertEqual($inskey3, reset($records)->id);
1348 $this->assertEqual($inskey2, end($records)->id);
1350 // test 2 tables with aliases and limits with order bys
1351 $sql = "SELECT t1.id, t1.course AS cid, t2.nametext
1352 FROM {{$tablename}} t1, {{$tablename2}} t2
1353 WHERE t2.course=t1.course
1354 ORDER BY t1.course, ". $DB->sql_compare_text('t2.nametext');
1355 $records = $DB->get_records_sql($sql, null, 2, 2); // Skip courses 3 and 6, get 4 and 5
1356 $this->assertEqual(2, count($records));
1357 $this->assertEqual('5', end($records)->cid);
1358 $this->assertEqual('4', reset($records)->cid);
1360 // test 2 tables with aliases and limits with the highest INT limit works
1361 $records = $DB->get_records_sql($sql, null, 2, PHP_INT_MAX); // Skip course {3,6}, get {4,5}
1362 $this->assertEqual(2, count($records));
1363 $this->assertEqual('5', end($records)->cid);
1364 $this->assertEqual('4', reset($records)->cid);
1366 // test 2 tables with aliases and limits with order bys (limit which is highest INT number)
1367 $records = $DB->get_records_sql($sql, null, PHP_INT_MAX, 2); // Skip all courses
1368 $this->assertEqual(0, count($records));
1370 // test 2 tables with aliases and limits with order bys (limit which s highest INT number)
1371 $records = $DB->get_records_sql($sql, null, PHP_INT_MAX, PHP_INT_MAX); // Skip all courses
1372 $this->assertEqual(0, count($records));
1374 // TODO: Test limits in queries having DISTINCT clauses
1376 // note: fetching nulls, empties, LOBs already tested by test_update_record() no needed here
1379 public function test_get_records_menu() {
1381 $dbman = $DB->get_manager();
1383 $table = $this->get_test_table();
1384 $tablename = $table->getName();
1386 $table->add_field('id', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, XMLDB_SEQUENCE, null);
1387 $table->add_field('course', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '0');
1388 $table->add_key('primary', XMLDB_KEY_PRIMARY, array('id'));
1389 $dbman->create_table($table);
1391 $DB->insert_record($tablename, array('course' => 3));
1392 $DB->insert_record($tablename, array('course' => 3));
1393 $DB->insert_record($tablename, array('course' => 5));
1394 $DB->insert_record($tablename, array('course' => 2));
1396 $records = $DB->get_records_menu($tablename, array('course' => 3));
1397 $this->assertTrue(is_array($records));
1398 $this->assertEqual(2, count($records));
1399 $this->assertFalse(empty($records[1]));
1400 $this->assertFalse(empty($records[2]));
1401 $this->assertEqual(3, $records[1]);
1402 $this->assertEqual(3, $records[2]);
1404 // note: delegate limits testing to test_get_records_sql()
1407 public function test_get_records_select_menu() {
1409 $dbman = $DB->get_manager();
1411 $table = $this->get_test_table();
1412 $tablename = $table->getName();
1414 $table->add_field('id', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, XMLDB_SEQUENCE, null);
1415 $table->add_field('course', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '0');
1416 $table->add_key('primary', XMLDB_KEY_PRIMARY, array('id'));
1417 $dbman->create_table($table);
1419 $DB->insert_record($tablename, array('course' => 3));
1420 $DB->insert_record($tablename, array('course' => 2));
1421 $DB->insert_record($tablename, array('course' => 3));
1422 $DB->insert_record($tablename, array('course' => 5));
1424 $records = $DB->get_records_select_menu($tablename, "course > ?", array(2));
1425 $this->assertTrue(is_array($records));
1427 $this->assertEqual(3, count($records));
1428 $this->assertFalse(empty($records[1]));
1429 $this->assertTrue(empty($records[2]));
1430 $this->assertFalse(empty($records[3]));
1431 $this->assertFalse(empty($records[4]));
1432 $this->assertEqual(3, $records[1]);
1433 $this->assertEqual(3, $records[3]);
1434 $this->assertEqual(5, $records[4]);
1436 // note: delegate limits testing to test_get_records_sql()
1439 public function test_get_records_sql_menu() {
1441 $dbman = $DB->get_manager();
1443 $table = $this->get_test_table();
1444 $tablename = $table->getName();
1446 $table->add_field('id', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, XMLDB_SEQUENCE, null);
1447 $table->add_field('course', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '0');
1448 $table->add_key('primary', XMLDB_KEY_PRIMARY, array('id'));
1449 $dbman->create_table($table);
1451 $DB->insert_record($tablename, array('course' => 3));
1452 $DB->insert_record($tablename, array('course' => 2));
1453 $DB->insert_record($tablename, array('course' => 3));
1454 $DB->insert_record($tablename, array('course' => 5));
1456 $records = $DB->get_records_sql_menu("SELECT * FROM {{$tablename}} WHERE course > ?", array(2));
1457 $this->assertTrue(is_array($records));
1459 $this->assertEqual(3, count($records));
1460 $this->assertFalse(empty($records[1]));
1461 $this->assertTrue(empty($records[2]));
1462 $this->assertFalse(empty($records[3]));
1463 $this->assertFalse(empty($records[4]));
1464 $this->assertEqual(3, $records[1]);
1465 $this->assertEqual(3, $records[3]);
1466 $this->assertEqual(5, $records[4]);
1468 // note: delegate limits testing to test_get_records_sql()
1471 public function test_get_record() {
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($tablename, array('id' => 2));
1487 $this->assertTrue($record instanceof stdClass);
1489 $this->assertEqual(2, $record->course);
1490 $this->assertEqual(2, $record->id);
1494 public function test_get_record_select() {
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));
1509 $record = $DB->get_record_select($tablename, "id = ?", array(2));
1510 $this->assertTrue($record instanceof stdClass);
1512 $this->assertEqual(2, $record->course);
1514 // note: delegates limit testing to test_get_records_sql()
1517 public function test_get_record_sql() {
1519 $dbman = $DB->get_manager();
1521 $table = $this->get_test_table();
1522 $tablename = $table->getName();
1524 $table->add_field('id', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, XMLDB_SEQUENCE, null);
1525 $table->add_field('course', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '0');
1526 $table->add_key('primary', XMLDB_KEY_PRIMARY, array('id'));
1527 $dbman->create_table($table);
1529 $DB->insert_record($tablename, array('course' => 3));
1530 $DB->insert_record($tablename, array('course' => 2));
1533 $record = $DB->get_record_sql("SELECT * FROM {{$tablename}} WHERE id = ?", array(2));
1534 $this->assertTrue($record instanceof stdClass);
1535 $this->assertEqual(2, $record->course);
1536 $this->assertEqual(2, $record->id);
1538 // backwards compatibility with $ignoremultiple
1539 $this->assertFalse(IGNORE_MISSING);
1540 $this->assertTrue(IGNORE_MULTIPLE);
1542 // record not found - ignore
1543 $this->assertFalse($DB->get_record_sql("SELECT * FROM {{$tablename}} WHERE id = ?", array(666), IGNORE_MISSING));
1544 $this->assertFalse($DB->get_record_sql("SELECT * FROM {{$tablename}} WHERE id = ?", array(666), IGNORE_MULTIPLE));
1546 // record not found error
1548 $DB->get_record_sql("SELECT * FROM {{$tablename}} WHERE id = ?", array(666), MUST_EXIST);
1549 $this->fail("Exception expected");
1550 } catch (dml_missing_record_exception $e) {
1551 $this->assertTrue(true);
1554 $this->enable_debugging();
1555 $this->assertTrue($DB->get_record_sql("SELECT * FROM {{$tablename}}", array(), IGNORE_MISSING));
1556 $this->assertFalse($this->get_debugging() === '');
1558 // multiple matches ignored
1559 $this->assertTrue($DB->get_record_sql("SELECT * FROM {{$tablename}}", array(), IGNORE_MULTIPLE));
1561 // multiple found error
1563 $DB->get_record_sql("SELECT * FROM {{$tablename}}", array(), MUST_EXIST);
1564 $this->fail("Exception expected");
1565 } catch (dml_multiple_records_exception $e) {
1566 $this->assertTrue(true);
1570 public function test_get_field() {
1572 $dbman = $DB->get_manager();
1574 $table = $this->get_test_table();
1575 $tablename = $table->getName();
1577 $table->add_field('id', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, XMLDB_SEQUENCE, null);
1578 $table->add_field('course', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '0');
1579 $table->add_field('onetext', XMLDB_TYPE_TEXT, 'big', null, null, null);
1580 $table->add_key('primary', XMLDB_KEY_PRIMARY, array('id'));
1581 $dbman->create_table($table);
1583 $id1 = $DB->insert_record($tablename, array('course' => 3));
1584 $DB->insert_record($tablename, array('course' => 5));
1585 $DB->insert_record($tablename, array('course' => 5));
1587 $this->assertEqual(3, $DB->get_field($tablename, 'course', array('id' => $id1)));
1588 $this->assertEqual(3, $DB->get_field($tablename, 'course', array('course' => 3)));
1590 $this->assertIdentical(false, $DB->get_field($tablename, 'course', array('course' => 11), IGNORE_MISSING));
1592 $DB->get_field($tablename, 'course', array('course' => 4), MUST_EXIST);
1593 $this->assertFail('Exception expected due to missing record');
1594 } catch (dml_exception $ex) {
1595 $this->assertTrue(true);
1598 $this->enable_debugging();
1599 $this->assertEqual(5, $DB->get_field($tablename, 'course', array('course' => 5), IGNORE_MULTIPLE));
1600 $this->assertIdentical($this->get_debugging(), '');
1602 $this->enable_debugging();
1603 $this->assertEqual(5, $DB->get_field($tablename, 'course', array('course' => 5), IGNORE_MISSING));
1604 $this->assertFalse($this->get_debugging() === '');
1606 // test for exception throwing on text conditions being compared. (MDL-24863, unwanted auto conversion of param to int)
1607 $conditions = array('onetext' => '1');
1609 $DB->get_field($tablename, 'course', $conditions);
1610 $this->fail('An Exception is missing, expected due to equating of text fields');
1611 } catch (exception $e) {
1612 $this->assertTrue($e instanceof dml_exception);
1613 $this->assertEqual($e->errorcode, 'textconditionsnotallowed');
1617 public function test_get_field_select() {
1619 $dbman = $DB->get_manager();
1621 $table = $this->get_test_table();
1622 $tablename = $table->getName();
1624 $table->add_field('id', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, XMLDB_SEQUENCE, null);
1625 $table->add_field('course', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '0');
1626 $table->add_key('primary', XMLDB_KEY_PRIMARY, array('id'));
1627 $dbman->create_table($table);
1629 $DB->insert_record($tablename, array('course' => 3));
1631 $this->assertEqual(3, $DB->get_field_select($tablename, 'course', "id = ?", array(1)));
1634 public function test_get_field_sql() {
1636 $dbman = $DB->get_manager();
1638 $table = $this->get_test_table();
1639 $tablename = $table->getName();
1641 $table->add_field('id', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, XMLDB_SEQUENCE, null);
1642 $table->add_field('course', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '0');
1643 $table->add_key('primary', XMLDB_KEY_PRIMARY, array('id'));
1644 $dbman->create_table($table);
1646 $DB->insert_record($tablename, array('course' => 3));
1648 $this->assertEqual(3, $DB->get_field_sql("SELECT course FROM {{$tablename}} WHERE id = ?", array(1)));
1651 public function test_get_fieldset_select() {
1653 $dbman = $DB->get_manager();
1655 $table = $this->get_test_table();
1656 $tablename = $table->getName();
1658 $table->add_field('id', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, XMLDB_SEQUENCE, null);
1659 $table->add_field('course', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '0');
1660 $table->add_key('primary', XMLDB_KEY_PRIMARY, array('id'));
1661 $dbman->create_table($table);
1663 $DB->insert_record($tablename, array('course' => 1));
1664 $DB->insert_record($tablename, array('course' => 3));
1665 $DB->insert_record($tablename, array('course' => 2));
1666 $DB->insert_record($tablename, array('course' => 6));
1668 $fieldset = $DB->get_fieldset_select($tablename, 'course', "course > ?", array(1));
1669 $this->assertTrue(is_array($fieldset));
1671 $this->assertEqual(3, count($fieldset));
1672 $this->assertEqual(3, $fieldset[0]);
1673 $this->assertEqual(2, $fieldset[1]);
1674 $this->assertEqual(6, $fieldset[2]);
1677 public function test_get_fieldset_sql() {
1679 $dbman = $DB->get_manager();
1681 $table = $this->get_test_table();
1682 $tablename = $table->getName();
1684 $table->add_field('id', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, XMLDB_SEQUENCE, null);
1685 $table->add_field('course', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '0');
1686 $table->add_key('primary', XMLDB_KEY_PRIMARY, array('id'));
1687 $dbman->create_table($table);
1689 $DB->insert_record($tablename, array('course' => 1));
1690 $DB->insert_record($tablename, array('course' => 3));
1691 $DB->insert_record($tablename, array('course' => 2));
1692 $DB->insert_record($tablename, array('course' => 6));
1694 $fieldset = $DB->get_fieldset_sql("SELECT * FROM {{$tablename}} WHERE course > ?", array(1));
1695 $this->assertTrue(is_array($fieldset));
1697 $this->assertEqual(3, count($fieldset));
1698 $this->assertEqual(2, $fieldset[0]);
1699 $this->assertEqual(3, $fieldset[1]);
1700 $this->assertEqual(4, $fieldset[2]);
1703 public function test_insert_record_raw() {
1705 $dbman = $DB->get_manager();
1707 $table = $this->get_test_table();
1708 $tablename = $table->getName();
1710 $table->add_field('id', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, XMLDB_SEQUENCE, null);
1711 $table->add_field('course', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '0');
1712 $table->add_field('onechar', XMLDB_TYPE_CHAR, '100', null, null, null, 'onestring');
1713 $table->add_key('primary', XMLDB_KEY_PRIMARY, array('id'));
1714 $dbman->create_table($table);
1716 $record = (object)array('course' => 1, 'onechar' => 'xx');
1717 $before = clone($record);
1718 $result = $DB->insert_record_raw($tablename, $record);
1719 $this->assertIdentical(1, $result);
1720 $this->assertIdentical($record, $before);
1722 $record = $DB->get_record($tablename, array('course' => 1));
1723 $this->assertTrue($record instanceof stdClass);
1724 $this->assertIdentical('xx', $record->onechar);
1726 $result = $DB->insert_record_raw($tablename, array('course' => 2, 'onechar' => 'yy'), false);
1727 $this->assertIdentical(true, $result);
1729 // note: bulk not implemented yet
1730 $DB->insert_record_raw($tablename, array('course' => 3, 'onechar' => 'zz'), true, true);
1731 $record = $DB->get_record($tablename, array('course' => 3));
1732 $this->assertTrue($record instanceof stdClass);
1733 $this->assertIdentical('zz', $record->onechar);
1735 // custom sequence (id) - returnid is ignored
1736 $result = $DB->insert_record_raw($tablename, array('id' => 10, 'course' => 3, 'onechar' => 'bb'), true, false, true);
1737 $this->assertIdentical(true, $result);
1738 $record = $DB->get_record($tablename, array('id' => 10));
1739 $this->assertTrue($record instanceof stdClass);
1740 $this->assertIdentical('bb', $record->onechar);
1742 // custom sequence - missing id error
1744 $DB->insert_record_raw($tablename, array('course' => 3, 'onechar' => 'bb'), true, false, true);
1745 $this->assertFail('Exception expected due to missing record');
1746 } catch (coding_exception $ex) {
1747 $this->assertTrue(true);
1750 // wrong column error
1752 $DB->insert_record_raw($tablename, array('xxxxx' => 3, 'onechar' => 'bb'));
1753 $this->assertFail('Exception expected due to invalid column');
1754 } catch (dml_write_exception $ex) {
1755 $this->assertTrue(true);
1759 public function test_insert_record() {
1760 // All the information in this test is fetched from DB by get_recordset() so we
1761 // have such method properly tested against nulls, empties and friends...
1764 $dbman = $DB->get_manager();
1766 $table = $this->get_test_table();
1767 $tablename = $table->getName();
1769 $table->add_field('id', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, XMLDB_SEQUENCE, null);
1770 $table->add_field('course', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '0');
1771 $table->add_field('oneint', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, null, null, 100);
1772 $table->add_field('onenum', XMLDB_TYPE_NUMBER, '10,2', null, null, null, 200);
1773 $table->add_field('onechar', XMLDB_TYPE_CHAR, '100', null, null, null, 'onestring');
1774 $table->add_field('onetext', XMLDB_TYPE_TEXT, 'big', null, null, null);
1775 $table->add_field('onebinary', XMLDB_TYPE_BINARY, 'big', null, null, null);
1776 $table->add_key('primary', XMLDB_KEY_PRIMARY, array('id'));
1777 $dbman->create_table($table);
1779 $this->assertIdentical(1, $DB->insert_record($tablename, array('course' => 1), true));
1780 $record = $DB->get_record($tablename, array('course' => 1));
1781 $this->assertEqual(1, $record->id);
1782 $this->assertEqual(100, $record->oneint); // Just check column defaults have been applied
1783 $this->assertEqual(200, $record->onenum);
1784 $this->assertIdentical('onestring', $record->onechar);
1785 $this->assertNull($record->onetext);
1786 $this->assertNull($record->onebinary);
1788 // without returning id, bulk not implemented
1789 $result = $this->assertIdentical(true, $DB->insert_record($tablename, array('course' => 99), false, true));
1790 $record = $DB->get_record($tablename, array('course' => 99));
1791 $this->assertEqual(2, $record->id);
1792 $this->assertEqual(99, $record->course);
1794 // Check nulls are set properly for all types
1795 $record = new stdClass();
1796 $record->oneint = null;
1797 $record->onenum = null;
1798 $record->onechar = null;
1799 $record->onetext = null;
1800 $record->onebinary = null;
1801 $recid = $DB->insert_record($tablename, $record);
1802 $record = $DB->get_record($tablename, array('id' => $recid));
1803 $this->assertEqual(0, $record->course);
1804 $this->assertNull($record->oneint);
1805 $this->assertNull($record->onenum);
1806 $this->assertNull($record->onechar);
1807 $this->assertNull($record->onetext);
1808 $this->assertNull($record->onebinary);
1810 // Check zeros are set properly for all types
1811 $record = new stdClass();
1812 $record->oneint = 0;
1813 $record->onenum = 0;
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);
1819 // Check booleans are set properly for all types
1820 $record = new stdClass();
1821 $record->oneint = true; // trues
1822 $record->onenum = true;
1823 $record->onechar = true;
1824 $record->onetext = true;
1825 $recid = $DB->insert_record($tablename, $record);
1826 $record = $DB->get_record($tablename, array('id' => $recid));
1827 $this->assertEqual(1, $record->oneint);
1828 $this->assertEqual(1, $record->onenum);
1829 $this->assertEqual(1, $record->onechar);
1830 $this->assertEqual(1, $record->onetext);
1832 $record = new stdClass();
1833 $record->oneint = false; // falses
1834 $record->onenum = false;
1835 $record->onechar = false;
1836 $record->onetext = false;
1837 $recid = $DB->insert_record($tablename, $record);
1838 $record = $DB->get_record($tablename, array('id' => $recid));
1839 $this->assertEqual(0, $record->oneint);
1840 $this->assertEqual(0, $record->onenum);
1841 $this->assertEqual(0, $record->onechar);
1842 $this->assertEqual(0, $record->onetext);
1844 // Check string data causes exception in numeric types
1845 $record = new stdClass();
1846 $record->oneint = 'onestring';
1847 $record->onenum = 0;
1849 $DB->insert_record($tablename, $record);
1850 $this->fail("Expecting an exception, none occurred");
1851 } catch (exception $e) {
1852 $this->assertTrue($e instanceof dml_exception);
1854 $record = new stdClass();
1855 $record->oneint = 0;
1856 $record->onenum = 'onestring';
1858 $DB->insert_record($tablename, $record);
1859 $this->fail("Expecting an exception, none occurred");
1860 } catch (exception $e) {
1861 $this->assertTrue($e instanceof dml_exception);
1864 // Check empty string data is stored as 0 in numeric datatypes
1865 $record = new stdClass();
1866 $record->oneint = ''; // empty string
1867 $record->onenum = 0;
1868 $recid = $DB->insert_record($tablename, $record);
1869 $record = $DB->get_record($tablename, array('id' => $recid));
1870 $this->assertTrue(is_numeric($record->oneint) && $record->oneint == 0);
1872 $record = new stdClass();
1873 $record->oneint = 0;
1874 $record->onenum = ''; // empty string
1875 $recid = $DB->insert_record($tablename, $record);
1876 $record = $DB->get_record($tablename, array('id' => $recid));
1877 $this->assertTrue(is_numeric($record->onenum) && $record->onenum == 0);
1879 // Check empty strings are set properly in string types
1880 $record = new stdClass();
1881 $record->oneint = 0;
1882 $record->onenum = 0;
1883 $record->onechar = '';
1884 $record->onetext = '';
1885 $recid = $DB->insert_record($tablename, $record);
1886 $record = $DB->get_record($tablename, array('id' => $recid));
1887 $this->assertTrue($record->onechar === '');
1888 $this->assertTrue($record->onetext === '');
1890 // Check operation ((210.10 + 39.92) - 150.02) against numeric types
1891 $record = new stdClass();
1892 $record->oneint = ((210.10 + 39.92) - 150.02);
1893 $record->onenum = ((210.10 + 39.92) - 150.02);
1894 $recid = $DB->insert_record($tablename, $record);
1895 $record = $DB->get_record($tablename, array('id' => $recid));
1896 $this->assertEqual(100, $record->oneint);
1897 $this->assertEqual(100, $record->onenum);
1899 // Check various quotes/backslashes combinations in string types
1900 $teststrings = array(
1901 'backslashes and quotes alone (even): "" \'\' \\\\',
1902 'backslashes and quotes alone (odd): """ \'\'\' \\\\\\',
1903 'backslashes and quotes sequences (even): \\"\\" \\\'\\\'',
1904 'backslashes and quotes sequences (odd): \\"\\"\\" \\\'\\\'\\\'');
1905 foreach ($teststrings as $teststring) {
1906 $record = new stdClass();
1907 $record->onechar = $teststring;
1908 $record->onetext = $teststring;
1909 $recid = $DB->insert_record($tablename, $record);
1910 $record = $DB->get_record($tablename, array('id' => $recid));
1911 $this->assertEqual($teststring, $record->onechar);
1912 $this->assertEqual($teststring, $record->onetext);
1915 // Check LOBs in text/binary columns
1916 $clob = file_get_contents(dirname(__FILE__).'/fixtures/clob.txt');
1917 $blob = file_get_contents(dirname(__FILE__).'/fixtures/randombinary');
1918 $record = new stdClass();
1919 $record->onetext = $clob;
1920 $record->onebinary = $blob;
1921 $recid = $DB->insert_record($tablename, $record);
1922 $rs = $DB->get_recordset($tablename, array('id' => $recid));
1923 $record = $rs->current();
1925 $this->assertEqual($clob, $record->onetext, 'Test CLOB insert (full contents output disabled)');
1926 $this->assertEqual($blob, $record->onebinary, 'Test BLOB insert (full contents output disabled)');
1928 // And "small" LOBs too, just in case
1929 $newclob = substr($clob, 0, 500);
1930 $newblob = substr($blob, 0, 250);
1931 $record = new stdClass();
1932 $record->onetext = $newclob;
1933 $record->onebinary = $newblob;
1934 $recid = $DB->insert_record($tablename, $record);
1935 $rs = $DB->get_recordset($tablename, array('id' => $recid));
1936 $record = $rs->current();
1938 $this->assertEqual($newclob, $record->onetext, 'Test "small" CLOB insert (full contents output disabled)');
1939 $this->assertEqual($newblob, $record->onebinary, 'Test "small" BLOB insert (full contents output disabled)');
1940 $this->assertEqual(false, $rs->key()); // Ensure recordset key() method to be working ok after closing
1942 // And "diagnostic" LOBs too, just in case
1943 $newclob = '\'"\\;/ěščřžýáíé';
1944 $newblob = '\'"\\;/ěščřžýáíé';
1945 $record = new stdClass();
1946 $record->onetext = $newclob;
1947 $record->onebinary = $newblob;
1948 $recid = $DB->insert_record($tablename, $record);
1949 $rs = $DB->get_recordset($tablename, array('id' => $recid));
1950 $record = $rs->current();
1952 $this->assertIdentical($newclob, $record->onetext);
1953 $this->assertIdentical($newblob, $record->onebinary);
1954 $this->assertEqual(false, $rs->key()); // Ensure recordset key() method to be working ok after closing
1956 // test data is not modified
1957 $record = new stdClass();
1958 $record->id = -1; // has to be ignored
1959 $record->course = 3;
1960 $record->lalala = 'lalal'; // unused
1961 $before = clone($record);
1962 $DB->insert_record($tablename, $record);
1963 $this->assertEqual($record, $before);
1965 // make sure the id is always increasing and never reuses the same id
1966 $id1 = $DB->insert_record($tablename, array('course' => 3));
1967 $id2 = $DB->insert_record($tablename, array('course' => 3));
1968 $this->assertTrue($id1 < $id2);
1969 $DB->delete_records($tablename, array('id'=>$id2));
1970 $id3 = $DB->insert_record($tablename, array('course' => 3));
1971 $this->assertTrue($id2 < $id3);
1972 $DB->delete_records($tablename, array());
1973 $id4 = $DB->insert_record($tablename, array('course' => 3));
1974 $this->assertTrue($id3 < $id4);
1976 // Test saving a float in a CHAR column, and reading it back.
1977 $id = $DB->insert_record($tablename, array('onechar' => 1.0));
1978 $this->assertEqual(1.0, $DB->get_field($tablename, 'onechar', array('id' => $id)));
1979 $id = $DB->insert_record($tablename, array('onechar' => 1e20));
1980 $this->assertEqual(1e20, $DB->get_field($tablename, 'onechar', array('id' => $id)));
1981 $id = $DB->insert_record($tablename, array('onechar' => 1e-4));
1982 $this->assertEqual(1e-4, $DB->get_field($tablename, 'onechar', array('id' => $id)));
1983 $id = $DB->insert_record($tablename, array('onechar' => 1e-5));
1984 $this->assertEqual(1e-5, $DB->get_field($tablename, 'onechar', array('id' => $id)));
1985 $id = $DB->insert_record($tablename, array('onechar' => 1e-300));
1986 $this->assertEqual(1e-300, $DB->get_field($tablename, 'onechar', array('id' => $id)));
1987 $id = $DB->insert_record($tablename, array('onechar' => 1e300));
1988 $this->assertEqual(1e300, $DB->get_field($tablename, 'onechar', array('id' => $id)));
1990 // Test saving a float in a TEXT column, and reading it back.
1991 $id = $DB->insert_record($tablename, array('onetext' => 1.0));
1992 $this->assertEqual(1.0, $DB->get_field($tablename, 'onetext', array('id' => $id)));
1993 $id = $DB->insert_record($tablename, array('onetext' => 1e20));
1994 $this->assertEqual(1e20, $DB->get_field($tablename, 'onetext', array('id' => $id)));
1995 $id = $DB->insert_record($tablename, array('onetext' => 1e-4));
1996 $this->assertEqual(1e-4, $DB->get_field($tablename, 'onetext', array('id' => $id)));
1997 $id = $DB->insert_record($tablename, array('onetext' => 1e-5));
1998 $this->assertEqual(1e-5, $DB->get_field($tablename, 'onetext', array('id' => $id)));
1999 $id = $DB->insert_record($tablename, array('onetext' => 1e-300));
2000 $this->assertEqual(1e-300, $DB->get_field($tablename, 'onetext', array('id' => $id)));
2001 $id = $DB->insert_record($tablename, array('onetext' => 1e300));
2002 $this->assertEqual(1e300, $DB->get_field($tablename, 'onetext', array('id' => $id)));
2005 public function test_import_record() {
2006 // All the information in this test is fetched from DB by get_recordset() so we
2007 // have such method properly tested against nulls, empties and friends...
2010 $dbman = $DB->get_manager();
2012 $table = $this->get_test_table();
2013 $tablename = $table->getName();
2015 $table->add_field('id', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, XMLDB_SEQUENCE, null);
2016 $table->add_field('course', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '0');
2017 $table->add_field('oneint', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, null, null, 100);
2018 $table->add_field('onenum', XMLDB_TYPE_NUMBER, '10,2', null, null, null, 200);
2019 $table->add_field('onechar', XMLDB_TYPE_CHAR, '100', null, null, null, 'onestring');
2020 $table->add_field('onetext', XMLDB_TYPE_TEXT, 'big', null, null, null);
2021 $table->add_field('onebinary', XMLDB_TYPE_BINARY, 'big', null, null, null);
2022 $table->add_key('primary', XMLDB_KEY_PRIMARY, array('id'));
2023 $dbman->create_table($table);
2025 $this->assertIdentical(1, $DB->insert_record($tablename, array('course' => 1), true));
2026 $record = $DB->get_record($tablename, array('course' => 1));
2027 $this->assertEqual(1, $record->id);
2028 $this->assertEqual(100, $record->oneint); // Just check column defaults have been applied
2029 $this->assertEqual(200, $record->onenum);
2030 $this->assertIdentical('onestring', $record->onechar);
2031 $this->assertNull($record->onetext);
2032 $this->assertNull($record->onebinary);
2034 // ignore extra columns
2035 $record = (object)array('id'=>13, 'course'=>2, 'xxxx'=>788778);
2036 $before = clone($record);
2037 $this->assertIdentical(true, $DB->import_record($tablename, $record));
2038 $this->assertIdentical($record, $before);
2039 $records = $DB->get_records($tablename);
2040 $this->assertEqual(2, $records[13]->course);
2042 // Check nulls are set properly for all types
2043 $record = new stdClass();
2045 $record->oneint = null;
2046 $record->onenum = null;
2047 $record->onechar = null;
2048 $record->onetext = null;
2049 $record->onebinary = null;
2050 $this->assertTrue($DB->import_record($tablename, $record));
2051 $record = $DB->get_record($tablename, array('id' => 20));
2052 $this->assertEqual(0, $record->course);
2053 $this->assertNull($record->oneint);
2054 $this->assertNull($record->onenum);
2055 $this->assertNull($record->onechar);
2056 $this->assertNull($record->onetext);
2057 $this->assertNull($record->onebinary);
2059 // Check zeros are set properly for all types
2060 $record = new stdClass();
2062 $record->oneint = 0;
2063 $record->onenum = 0;
2064 $this->assertTrue($DB->import_record($tablename, $record));
2065 $record = $DB->get_record($tablename, array('id' => 23));
2066 $this->assertEqual(0, $record->oneint);
2067 $this->assertEqual(0, $record->onenum);
2069 // Check string data causes exception in numeric types
2070 $record = new stdClass();
2072 $record->oneint = 'onestring';
2073 $record->onenum = 0;
2075 $DB->import_record($tablename, $record);
2076 $this->fail("Expecting an exception, none occurred");
2077 } catch (exception $e) {
2078 $this->assertTrue($e instanceof dml_exception);
2080 $record = new stdClass();
2082 $record->oneint = 0;
2083 $record->onenum = 'onestring';
2085 $DB->import_record($tablename, $record);
2086 $this->fail("Expecting an exception, none occurred");
2087 } catch (exception $e) {
2088 $this->assertTrue($e instanceof dml_exception);
2091 // Check empty strings are set properly in string types
2092 $record = new stdClass();
2094 $record->oneint = 0;
2095 $record->onenum = 0;
2096 $record->onechar = '';
2097 $record->onetext = '';
2098 $this->assertTrue($DB->import_record($tablename, $record));
2099 $record = $DB->get_record($tablename, array('id' => 44));
2100 $this->assertTrue($record->onechar === '');
2101 $this->assertTrue($record->onetext === '');
2103 // Check operation ((210.10 + 39.92) - 150.02) against numeric types
2104 $record = new stdClass();
2106 $record->oneint = ((210.10 + 39.92) - 150.02);
2107 $record->onenum = ((210.10 + 39.92) - 150.02);
2108 $this->assertTrue($DB->import_record($tablename, $record));
2109 $record = $DB->get_record($tablename, array('id' => 47));
2110 $this->assertEqual(100, $record->oneint);
2111 $this->assertEqual(100, $record->onenum);
2113 // Check various quotes/backslashes combinations in string types
2115 $teststrings = array(
2116 'backslashes and quotes alone (even): "" \'\' \\\\',
2117 'backslashes and quotes alone (odd): """ \'\'\' \\\\\\',
2118 'backslashes and quotes sequences (even): \\"\\" \\\'\\\'',
2119 'backslashes and quotes sequences (odd): \\"\\"\\" \\\'\\\'\\\'');
2120 foreach ($teststrings as $teststring) {
2121 $record = new stdClass();
2123 $record->onechar = $teststring;
2124 $record->onetext = $teststring;
2125 $this->assertTrue($DB->import_record($tablename, $record));
2126 $record = $DB->get_record($tablename, array('id' => $i));
2127 $this->assertEqual($teststring, $record->onechar);
2128 $this->assertEqual($teststring, $record->onetext);
2132 // Check LOBs in text/binary columns
2133 $clob = file_get_contents(dirname(__FILE__).'/fixtures/clob.txt');
2134 $record = new stdClass();
2136 $record->onetext = $clob;
2137 $record->onebinary = '';
2138 $this->assertTrue($DB->import_record($tablename, $record));
2139 $rs = $DB->get_recordset($tablename, array('id' => 70));
2140 $record = $rs->current();
2142 $this->assertEqual($clob, $record->onetext, 'Test CLOB insert (full contents output disabled)');
2144 $blob = file_get_contents(dirname(__FILE__).'/fixtures/randombinary');
2145 $record = new stdClass();
2147 $record->onetext = '';
2148 $record->onebinary = $blob;
2149 $this->assertTrue($DB->import_record($tablename, $record));
2150 $rs = $DB->get_recordset($tablename, array('id' => 71));
2151 $record = $rs->current();
2153 $this->assertEqual($blob, $record->onebinary, 'Test BLOB insert (full contents output disabled)');
2155 // And "small" LOBs too, just in case
2156 $newclob = substr($clob, 0, 500);
2157 $newblob = substr($blob, 0, 250);
2158 $record = new stdClass();
2160 $record->onetext = $newclob;
2161 $record->onebinary = $newblob;
2162 $this->assertTrue($DB->import_record($tablename, $record));
2163 $rs = $DB->get_recordset($tablename, array('id' => 73));
2164 $record = $rs->current();
2166 $this->assertEqual($newclob, $record->onetext, 'Test "small" CLOB insert (full contents output disabled)');
2167 $this->assertEqual($newblob, $record->onebinary, 'Test "small" BLOB insert (full contents output disabled)');
2168 $this->assertEqual(false, $rs->key()); // Ensure recordset key() method to be working ok after closing
2171 public function test_update_record_raw() {
2173 $dbman = $DB->get_manager();
2175 $table = $this->get_test_table();
2176 $tablename = $table->getName();
2178 $table->add_field('id', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, XMLDB_SEQUENCE, null);
2179 $table->add_field('course', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '0');
2180 $table->add_key('primary', XMLDB_KEY_PRIMARY, array('id'));
2181 $dbman->create_table($table);
2183 $DB->insert_record($tablename, array('course' => 1));
2184 $DB->insert_record($tablename, array('course' => 3));
2186 $record = $DB->get_record($tablename, array('course' => 1));
2187 $record->course = 2;
2188 $this->assertTrue($DB->update_record_raw($tablename, $record));
2189 $this->assertEqual(0, $DB->count_records($tablename, array('course' => 1)));
2190 $this->assertEqual(1, $DB->count_records($tablename, array('course' => 2)));
2191 $this->assertEqual(1, $DB->count_records($tablename, array('course' => 3)));
2193 $record = $DB->get_record($tablename, array('course' => 1));
2196 $DB->update_record_raw($tablename, $record);
2197 $this->fail("Expecting an exception, none occurred");
2198 } catch (Exception $e) {
2199 $this->assertTrue($e instanceof coding_exception);
2202 $record = $DB->get_record($tablename, array('course' => 3));
2205 $DB->update_record_raw($tablename, $record);
2206 $this->fail("Expecting an exception, none occurred");
2207 } catch (Exception $e) {
2208 $this->assertTrue($e instanceof coding_exception);
2212 public function test_update_record() {
2214 // All the information in this test is fetched from DB by get_record() so we
2215 // have such method properly tested against nulls, empties and friends...
2218 $dbman = $DB->get_manager();
2220 $table = $this->get_test_table();
2221 $tablename = $table->getName();
2223 $table->add_field('id', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, XMLDB_SEQUENCE, null);
2224 $table->add_field('course', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '0');
2225 $table->add_field('oneint', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, null, null, 100);
2226 $table->add_field('onenum', XMLDB_TYPE_NUMBER, '10,2', null, null, null, 200);
2227 $table->add_field('onechar', XMLDB_TYPE_CHAR, '100', null, null, null, 'onestring');
2228 $table->add_field('onetext', XMLDB_TYPE_TEXT, 'big', null, null, null);
2229 $table->add_field('onebinary', XMLDB_TYPE_BINARY, 'big', null, null, null);
2230 $table->add_key('primary', XMLDB_KEY_PRIMARY, array('id'));
2231 $dbman->create_table($table);
2233 $DB->insert_record($tablename, array('course' => 1));
2234 $record = $DB->get_record($tablename, array('course' => 1));
2235 $record->course = 2;
2237 $this->assertTrue($DB->update_record($tablename, $record));
2238 $this->assertFalse($record = $DB->get_record($tablename, array('course' => 1)));
2239 $this->assertTrue($record = $DB->get_record($tablename, array('course' => 2)));
2240 $this->assertEqual(100, $record->oneint); // Just check column defaults have been applied
2241 $this->assertEqual(200, $record->onenum);
2242 $this->assertEqual('onestring', $record->onechar);
2243 $this->assertNull($record->onetext);
2244 $this->assertNull($record->onebinary);
2246 // Check nulls are set properly for all types
2247 $record->oneint = null;
2248 $record->onenum = null;
2249 $record->onechar = null;
2250 $record->onetext = null;
2251 $record->onebinary = null;
2252 $DB->update_record($tablename, $record);
2253 $record = $DB->get_record($tablename, array('course' => 2));
2254 $this->assertNull($record->oneint);
2255 $this->assertNull($record->onenum);
2256 $this->assertNull($record->onechar);
2257 $this->assertNull($record->onetext);
2258 $this->assertNull($record->onebinary);
2260 // Check zeros are set properly for all types
2261 $record->oneint = 0;
2262 $record->onenum = 0;
2263 $DB->update_record($tablename, $record);
2264 $record = $DB->get_record($tablename, array('course' => 2));
2265 $this->assertEqual(0, $record->oneint);
2266 $this->assertEqual(0, $record->onenum);
2268 // Check booleans are set properly for all types
2269 $record->oneint = true; // trues
2270 $record->onenum = true;
2271 $record->onechar = true;
2272 $record->onetext = true;
2273 $DB->update_record($tablename, $record);
2274 $record = $DB->get_record($tablename, array('course' => 2));
2275 $this->assertEqual(1, $record->oneint);
2276 $this->assertEqual(1, $record->onenum);
2277 $this->assertEqual(1, $record->onechar);
2278 $this->assertEqual(1, $record->onetext);
2280 $record->oneint = false; // falses
2281 $record->onenum = false;
2282 $record->onechar = false;
2283 $record->onetext = false;
2284 $DB->update_record($tablename, $record);
2285 $record = $DB->get_record($tablename, array('course' => 2));
2286 $this->assertEqual(0, $record->oneint);
2287 $this->assertEqual(0, $record->onenum);
2288 $this->assertEqual(0, $record->onechar);
2289 $this->assertEqual(0, $record->onetext);
2291 // Check string data causes exception in numeric types
2292 $record->oneint = 'onestring';
2293 $record->onenum = 0;
2295 $DB->update_record($tablename, $record);
2296 $this->fail("Expecting an exception, none occurred");
2297 } catch (exception $e) {
2298 $this->assertTrue($e instanceof dml_exception);
2300 $record->oneint = 0;
2301 $record->onenum = 'onestring';
2303 $DB->update_record($tablename, $record);
2304 $this->fail("Expecting an exception, none occurred");
2305 } catch (exception $e) {
2306 $this->assertTrue($e instanceof dml_exception);
2309 // Check empty string data is stored as 0 in numeric datatypes
2310 $record->oneint = ''; // empty string
2311 $record->onenum = 0;
2312 $DB->update_record($tablename, $record);
2313 $record = $DB->get_record($tablename, array('course' => 2));
2314 $this->assertTrue(is_numeric($record->oneint) && $record->oneint == 0);
2316 $record->oneint = 0;
2317 $record->onenum = ''; // empty string
2318 $DB->update_record($tablename, $record);
2319 $record = $DB->get_record($tablename, array('course' => 2));
2320 $this->assertTrue(is_numeric($record->onenum) && $record->onenum == 0);
2322 // Check empty strings are set properly in string types
2323 $record->oneint = 0;
2324 $record->onenum = 0;
2325 $record->onechar = '';
2326 $record->onetext = '';
2327 $DB->update_record($tablename, $record);
2328 $record = $DB->get_record($tablename, array('course' => 2));
2329 $this->assertTrue($record->onechar === '');
2330 $this->assertTrue($record->onetext === '');
2332 // Check operation ((210.10 + 39.92) - 150.02) against numeric types
2333 $record->oneint = ((210.10 + 39.92) - 150.02);
2334 $record->onenum = ((210.10 + 39.92) - 150.02);
2335 $DB->update_record($tablename, $record);
2336 $record = $DB->get_record($tablename, array('course' => 2));
2337 $this->assertEqual(100, $record->oneint);
2338 $this->assertEqual(100, $record->onenum);
2340 // Check various quotes/backslashes combinations in string types
2341 $teststrings = array(
2342 'backslashes and quotes alone (even): "" \'\' \\\\',
2343 'backslashes and quotes alone (odd): """ \'\'\' \\\\\\',
2344 'backslashes and quotes sequences (even): \\"\\" \\\'\\\'',
2345 'backslashes and quotes sequences (odd): \\"\\"\\" \\\'\\\'\\\'');
2346 foreach ($teststrings as $teststring) {
2347 $record->onechar = $teststring;
2348 $record->onetext = $teststring;
2349 $DB->update_record($tablename, $record);
2350 $record = $DB->get_record($tablename, array('course' => 2));
2351 $this->assertEqual($teststring, $record->onechar);
2352 $this->assertEqual($teststring, $record->onetext);
2355 // Check LOBs in text/binary columns
2356 $clob = file_get_contents(dirname(__FILE__).'/fixtures/clob.txt');
2357 $blob = file_get_contents(dirname(__FILE__).'/fixtures/randombinary');
2358 $record->onetext = $clob;
2359 $record->onebinary = $blob;
2360 $DB->update_record($tablename, $record);
2361 $record = $DB->get_record($tablename, array('course' => 2));
2362 $this->assertEqual($clob, $record->onetext, 'Test CLOB update (full contents output disabled)');
2363 $this->assertEqual($blob, $record->onebinary, 'Test BLOB update (full contents output disabled)');
2365 // And "small" LOBs too, just in case
2366 $newclob = substr($clob, 0, 500);
2367 $newblob = substr($blob, 0, 250);
2368 $record->onetext = $newclob;
2369 $record->onebinary = $newblob;
2370 $DB->update_record($tablename, $record);
2371 $record = $DB->get_record($tablename, array('course' => 2));
2372 $this->assertEqual($newclob, $record->onetext, 'Test "small" CLOB update (full contents output disabled)');
2373 $this->assertEqual($newblob, $record->onebinary, 'Test "small" BLOB update (full contents output disabled)');
2375 // Test saving a float in a CHAR column, and reading it back.
2376 $id = $DB->insert_record($tablename, array('onechar' => 'X'));
2377 $DB->update_record($tablename, array('id' => $id, 'onechar' => 1.0));
2378 $this->assertEqual(1.0, $DB->get_field($tablename, 'onechar', array('id' => $id)));
2379 $DB->update_record($tablename, array('id' => $id, 'onechar' => 1e20));
2380 $this->assertEqual(1e20, $DB->get_field($tablename, 'onechar', array('id' => $id)));
2381 $DB->update_record($tablename, array('id' => $id, 'onechar' => 1e-4));
2382 $this->assertEqual(1e-4, $DB->get_field($tablename, 'onechar', array('id' => $id)));
2383 $DB->update_record($tablename, array('id' => $id, 'onechar' => 1e-5));
2384 $this->assertEqual(1e-5, $DB->get_field($tablename, 'onechar', array('id' => $id)));
2385 $DB->update_record($tablename, array('id' => $id, 'onechar' => 1e-300));
2386 $this->assertEqual(1e-300, $DB->get_field($tablename, 'onechar', array('id' => $id)));
2387 $DB->update_record($tablename, array('id' => $id, 'onechar' => 1e300));
2388 $this->assertEqual(1e300, $DB->get_field($tablename, 'onechar', array('id' => $id)));
2390 // Test saving a float in a TEXT column, and reading it back.
2391 $id = $DB->insert_record($tablename, array('onetext' => 'X'));
2392 $DB->update_record($tablename, array('id' => $id, 'onetext' => 1.0));
2393 $this->assertEqual(1.0, $DB->get_field($tablename, 'onetext', array('id' => $id)));
2394 $DB->update_record($tablename, array('id' => $id, 'onetext' => 1e20));
2395 $this->assertEqual(1e20, $DB->get_field($tablename, 'onetext', array('id' => $id)));
2396 $DB->update_record($tablename, array('id' => $id, 'onetext' => 1e-4));
2397 $this->assertEqual(1e-4, $DB->get_field($tablename, 'onetext', array('id' => $id)));
2398 $DB->update_record($tablename, array('id' => $id, 'onetext' => 1e-5));
2399 $this->assertEqual(1e-5, $DB->get_field($tablename, 'onetext', array('id' => $id)));
2400 $DB->update_record($tablename, array('id' => $id, 'onetext' => 1e-300));
2401 $this->assertEqual(1e-300, $DB->get_field($tablename, 'onetext', array('id' => $id)));
2402 $DB->update_record($tablename, array('id' => $id, 'onetext' => 1e300));
2403 $this->assertEqual(1e300, $DB->get_field($tablename, 'onetext', array('id' => $id)));
2406 public function test_set_field() {
2408 $dbman = $DB->get_manager();
2410 $table = $this->get_test_table();
2411 $tablename = $table->getName();
2413 $table->add_field('id', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, XMLDB_SEQUENCE, null);
2414 $table->add_field('course', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '0');
2415 $table->add_field('onechar', XMLDB_TYPE_CHAR, '100', null, null, null);
2416 $table->add_field('onetext', XMLDB_TYPE_TEXT, 'big', null, null, null);
2417 $table->add_key('primary', XMLDB_KEY_PRIMARY, array('id'));
2418 $dbman->create_table($table);
2421 $id1 = $DB->insert_record($tablename, array('course' => 1));
2422 $id2 = $DB->insert_record($tablename, array('course' => 1));
2423 $id3 = $DB->insert_record($tablename, array('course' => 3));
2424 $this->assertTrue($DB->set_field($tablename, 'course', 2, array('id' => $id1)));
2425 $this->assertEqual(2, $DB->get_field($tablename, 'course', array('id' => $id1)));
2426 $this->assertEqual(1, $DB->get_field($tablename, 'course', array('id' => $id2)));
2427 $this->assertEqual(3, $DB->get_field($tablename, 'course', array('id' => $id3)));
2428 $DB->delete_records($tablename, array());
2430 // multiple fields affected
2431 $id1 = $DB->insert_record($tablename, array('course' => 1));
2432 $id2 = $DB->insert_record($tablename, array('course' => 1));
2433 $id3 = $DB->insert_record($tablename, array('course' => 3));
2434 $DB->set_field($tablename, 'course', '5', array('course' => 1));
2435 $this->assertEqual(5, $DB->get_field($tablename, 'course', array('id' => $id1)));
2436 $this->assertEqual(5, $DB->get_field($tablename, 'course', array('id' => $id2)));
2437 $this->assertEqual(3, $DB->get_field($tablename, 'course', array('id' => $id3)));
2438 $DB->delete_records($tablename, array());
2440 // no field affected
2441 $id1 = $DB->insert_record($tablename, array('course' => 1));
2442 $id2 = $DB->insert_record($tablename, array('course' => 1));
2443 $id3 = $DB->insert_record($tablename, array('course' => 3));
2444 $DB->set_field($tablename, 'course', '5', array('course' => 0));
2445 $this->assertEqual(1, $DB->get_field($tablename, 'course', array('id' => $id1)));
2446 $this->assertEqual(1, $DB->get_field($tablename, 'course', array('id' => $id2)));
2447 $this->assertEqual(3, $DB->get_field($tablename, 'course', array('id' => $id3)));
2448 $DB->delete_records($tablename, array());
2450 // all fields - no condition
2451 $id1 = $DB->insert_record($tablename, array('course' => 1));
2452 $id2 = $DB->insert_record($tablename, array('course' => 1));
2453 $id3 = $DB->insert_record($tablename, array('course' => 3));
2454 $DB->set_field($tablename, 'course', 5, array());
2455 $this->assertEqual(5, $DB->get_field($tablename, 'course', array('id' => $id1)));
2456 $this->assertEqual(5, $DB->get_field($tablename, 'course', array('id' => $id2)));
2457 $this->assertEqual(5, $DB->get_field($tablename, 'course', array('id' => $id3)));
2459 // test for exception throwing on text conditions being compared. (MDL-24863, unwanted auto conversion of param to int)
2460 $conditions = array('onetext' => '1');
2462 $DB->set_field($tablename, 'onechar', 'frog', $conditions);
2463 $this->fail('An Exception is missing, expected due to equating of text fields');
2464 } catch (exception $e) {
2465 $this->assertTrue($e instanceof dml_exception);
2466 $this->assertEqual($e->errorcode, 'textconditionsnotallowed');
2469 // Test saving a float in a CHAR column, and reading it back.
2470 $id = $DB->insert_record($tablename, array('onechar' => 'X'));
2471 $DB->set_field($tablename, 'onechar', 1.0, array('id' => $id));
2472 $this->assertEqual(1.0, $DB->get_field($tablename, 'onechar', array('id' => $id)));
2473 $DB->set_field($tablename, 'onechar', 1e20, array('id' => $id));
2474 $this->assertEqual(1e20, $DB->get_field($tablename, 'onechar', array('id' => $id)));
2475 $DB->set_field($tablename, 'onechar', 1e-4, array('id' => $id));
2476 $this->assertEqual(1e-4, $DB->get_field($tablename, 'onechar', array('id' => $id)));
2477 $DB->set_field($tablename, 'onechar', 1e-5, array('id' => $id));
2478 $this->assertEqual(1e-5, $DB->get_field($tablename, 'onechar', array('id' => $id)));
2479 $DB->set_field($tablename, 'onechar', 1e-300, array('id' => $id));
2480 $this->assertEqual(1e-300, $DB->get_field($tablename, 'onechar', array('id' => $id)));
2481 $DB->set_field($tablename, 'onechar', 1e300, array('id' => $id));
2482 $this->assertEqual(1e300, $DB->get_field($tablename, 'onechar', array('id' => $id)));
2484 // Test saving a float in a TEXT column, and reading it back.
2485 $id = $DB->insert_record($tablename, array('onetext' => 'X'));
2486 $DB->set_field($tablename, 'onetext', 1.0, array('id' => $id));
2487 $this->assertEqual(1.0, $DB->get_field($tablename, 'onetext', array('id' => $id)));
2488 $DB->set_field($tablename, 'onetext', 1e20, array('id' => $id));
2489 $this->assertEqual(1e20, $DB->get_field($tablename, 'onetext', array('id' => $id)));
2490 $DB->set_field($tablename, 'onetext', 1e-4, array('id' => $id));
2491 $this->assertEqual(1e-4, $DB->get_field($tablename, 'onetext', array('id' => $id)));
2492 $DB->set_field($tablename, 'onetext', 1e-5, array('id' => $id));
2493 $this->assertEqual(1e-5, $DB->get_field($tablename, 'onetext', array('id' => $id)));
2494 $DB->set_field($tablename, 'onetext', 1e-300, array('id' => $id));
2495 $this->assertEqual(1e-300, $DB->get_field($tablename, 'onetext', array('id' => $id)));
2496 $DB->set_field($tablename, 'onetext', 1e300, array('id' => $id));
2497 $this->assertEqual(1e300, $DB->get_field($tablename, 'onetext', array('id' => $id)));
2499 // Note: All the nulls, booleans, empties, quoted and backslashes tests
2500 // go to set_field_select() because set_field() is just one wrapper over it
2503 public function test_set_field_select() {
2505 // All the information in this test is fetched from DB by get_field() so we
2506 // have such method properly tested against nulls, empties and friends...
2509 $dbman = $DB->get_manager();
2511 $table = $this->get_test_table();
2512 $tablename = $table->getName();
2514 $table->add_field('id', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, XMLDB_SEQUENCE, null);
2515 $table->add_field('course', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '0');
2516 $table->add_field('oneint', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, null, null);
2517 $table->add_field('onenum', XMLDB_TYPE_NUMBER, '10,2', null, null, null);
2518 $table->add_field('onechar', XMLDB_TYPE_CHAR, '100', null, null, null);
2519 $table->add_field('onetext', XMLDB_TYPE_TEXT, 'big', null, null, null);
2520 $table->add_field('onebinary', XMLDB_TYPE_BINARY, 'big', null, null, null);
2521 $table->add_key('primary', XMLDB_KEY_PRIMARY, array('id'));
2522 $dbman->create_table($table);
2524 $DB->insert_record($tablename, array('course' => 1));
2526 $this->assertTrue($DB->set_field_select($tablename, 'course', 2, 'id = ?', array(1)));
2527 $this->assertEqual(2, $DB->get_field($tablename, 'course', array('id' => 1)));
2529 // Check nulls are set properly for all types
2530 $DB->set_field_select($tablename, 'oneint', null, 'id = ?', array(1)); // trues
2531 $DB->set_field_select($tablename, 'onenum', null, 'id = ?', array(1));
2532 $DB->set_field_select($tablename, 'onechar', null, 'id = ?', array(1));
2533 $DB->set_field_select($tablename, 'onetext', null, 'id = ?', array(1));
2534 $DB->set_field_select($tablename, 'onebinary', null, 'id = ?', array(1));
2535 $this->assertNull($DB->get_field($tablename, 'oneint', array('id' => 1)));
2536 $this->assertNull($DB->get_field($tablename, 'onenum', array('id' => 1)));
2537 $this->assertNull($DB->get_field($tablename, 'onechar', array('id' => 1)));
2538 $this->assertNull($DB->get_field($tablename, 'onetext', array('id' => 1)));
2539 $this->assertNull($DB->get_field($tablename, 'onebinary', array('id' => 1)));
2541 // Check zeros are set properly for all types
2542 $DB->set_field_select($tablename, 'oneint', 0, 'id = ?', array(1));
2543 $DB->set_field_select($tablename, 'onenum', 0, 'id = ?', array(1));
2544 $this->assertEqual(0, $DB->get_field($tablename, 'oneint', array('id' => 1)));
2545 $this->assertEqual(0, $DB->get_field($tablename, 'onenum', array('id' => 1)));
2547 // Check booleans are set properly for all types
2548 $DB->set_field_select($tablename, 'oneint', true, 'id = ?', array(1)); // trues
2549 $DB->set_field_select($tablename, 'onenum', true, 'id = ?', array(1));
2550 $DB->set_field_select($tablename, 'onechar', true, 'id = ?', array(1));
2551 $DB->set_field_select($tablename, 'onetext', true, 'id = ?', array(1));
2552 $this->assertEqual(1, $DB->get_field($tablename, 'oneint', array('id' => 1)));
2553 $this->assertEqual(1, $DB->get_field($tablename, 'onenum', array('id' => 1)));
2554 $this->assertEqual(1, $DB->get_field($tablename, 'onechar', array('id' => 1)));
2555 $this->assertEqual(1, $DB->get_field($tablename, 'onetext', array('id' => 1)));
2557 $DB->set_field_select($tablename, 'oneint', false, 'id = ?', array(1)); // falses
2558 $DB->set_field_select($tablename, 'onenum', false, 'id = ?', array(1));
2559 $DB->set_field_select($tablename, 'onechar', false, 'id = ?', array(1));
2560 $DB->set_field_select($tablename, 'onetext', false, 'id = ?', array(1));
2561 $this->assertEqual(0, $DB->get_field($tablename, 'oneint', array('id' => 1)));
2562 $this->assertEqual(0, $DB->get_field($tablename, 'onenum', array('id' => 1)));
2563 $this->assertEqual(0, $DB->get_field($tablename, 'onechar', array('id' => 1)));
2564 $this->assertEqual(0, $DB->get_field($tablename, 'onetext', array('id' => 1)));
2566 // Check string data causes exception in numeric types
2568 $DB->set_field_select($tablename, 'oneint', 'onestring', 'id = ?', array(1));
2569 $this->fail("Expecting an exception, none occurred");
2570 } catch (exception $e) {
2571 $this->assertTrue($e instanceof dml_exception);
2574 $DB->set_field_select($tablename, 'onenum', 'onestring', 'id = ?', array(1));
2575 $this->fail("Expecting an exception, none occurred");
2576 } catch (exception $e) {
2577 $this->assertTrue($e instanceof dml_exception);
2580 // Check empty string data is stored as 0 in numeric datatypes
2581 $DB->set_field_select($tablename, 'oneint', '', 'id = ?', array(1));
2582 $field = $DB->get_field($tablename, 'oneint', array('id' => 1));
2583 $this->assertTrue(is_numeric($field) && $field == 0);
2585 $DB->set_field_select($tablename, 'onenum', '', 'id = ?', array(1));
2586 $field = $DB->get_field($tablename, 'onenum', array('id' => 1));
2587 $this->assertTrue(is_numeric($field) && $field == 0);
2589 // Check empty strings are set properly in string types
2590 $DB->set_field_select($tablename, 'onechar', '', 'id = ?', array(1));
2591 $DB->set_field_select($tablename, 'onetext', '', 'id = ?', array(1));
2592 $this->assertTrue($DB->get_field($tablename, 'onechar', array('id' => 1)) === '');
2593 $this->assertTrue($DB->get_field($tablename, 'onetext', array('id' => 1)) === '');
2595 // Check operation ((210.10 + 39.92) - 150.02) against numeric types
2596 $DB->set_field_select($tablename, 'oneint', ((210.10 + 39.92) - 150.02), 'id = ?', array(1));
2597 $DB->set_field_select($tablename, 'onenum', ((210.10 + 39.92) - 150.02), 'id = ?', array(1));
2598 $this->assertEqual(100, $DB->get_field($tablename, 'oneint', array('id' => 1)));
2599 $this->assertEqual(100, $DB->get_field($tablename, 'onenum', array('id' => 1)));
2601 // Check various quotes/backslashes combinations in string types
2602 $teststrings = array(
2603 'backslashes and quotes alone (even): "" \'\' \\\\',
2604 'backslashes and quotes alone (odd): """ \'\'\' \\\\\\',
2605 'backslashes and quotes sequences (even): \\"\\" \\\'\\\'',
2606 'backslashes and quotes sequences (odd): \\"\\"\\" \\\'\\\'\\\'');
2607 foreach ($teststrings as $teststring) {
2608 $DB->set_field_select($tablename, 'onechar', $teststring, 'id = ?', array(1));
2609 $DB->set_field_select($tablename, 'onetext', $teststring, 'id = ?', array(1));
2610 $this->assertEqual($teststring, $DB->get_field($tablename, 'onechar', array('id' => 1)));
2611 $this->assertEqual($teststring, $DB->get_field($tablename, 'onetext', array('id' => 1)));
2614 // Check LOBs in text/binary columns
2615 $clob = file_get_contents(dirname(__FILE__).'/fixtures/clob.txt');
2616 $blob = file_get_contents(dirname(__FILE__).'/fixtures/randombinary');
2617 $DB->set_field_select($tablename, 'onetext', $clob, 'id = ?', array(1));
2618 $DB->set_field_select($tablename, 'onebinary', $blob, 'id = ?', array(1));
2619 $this->assertEqual($clob, $DB->get_field($tablename, 'onetext', array('id' => 1)), 'Test CLOB set_field (full contents output disabled)');
2620 $this->assertEqual($blob, $DB->get_field($tablename, 'onebinary', array('id' => 1)), 'Test BLOB set_field (full contents output disabled)');
2622 // And "small" LOBs too, just in case
2623 $newclob = substr($clob, 0, 500);
2624 $newblob = substr($blob, 0, 250);
2625 $DB->set_field_select($tablename, 'onetext', $newclob, 'id = ?', array(1));
2626 $DB->set_field_select($tablename, 'onebinary', $newblob, 'id = ?', array(1));
2627 $this->assertEqual($newclob, $DB->get_field($tablename, 'onetext', array('id' => 1)), 'Test "small" CLOB set_field (full contents output disabled)');
2628 $this->assertEqual($newblob, $DB->get_field($tablename, 'onebinary', array('id' => 1)), 'Test "small" BLOB set_field (full contents output disabled)');
2630 // This is the failure from MDL-24863. This was giving an error on MSSQL,
2631 // which converts the '1' to an integer, which cannot then be compared with
2632 // onetext cast to a varchar. This should be fixed and working now.
2634 // test for exception throwing on text conditions being compared. (MDL-24863, unwanted auto conversion of param to int)
2635 $params = array('onetext' => '1');
2637 $DB->set_field_select($tablename, 'onechar', $newchar, $DB->sql_compare_text('onetext') . ' = ?', $params);
2638 $this->assertTrue(true, 'No exceptions thrown with numerical text param comparison for text field.');
2639 } catch (dml_exception $e) {
2640 $this->assertFalse(true, 'We have an unexpected exception.');
2647 public function test_count_records() {
2650 $dbman = $DB->get_manager();
2652 $table = $this->get_test_table();
2653 $tablename = $table->getName();
2655 $table->add_field('id', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, XMLDB_SEQUENCE, null);
2656 $table->add_field('course', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '0');
2657 $table->add_field('onetext', XMLDB_TYPE_TEXT, 'big', null, null, null);
2658 $table->add_key('primary', XMLDB_KEY_PRIMARY, array('id'));
2659 $dbman->create_table($table);
2661 $this->assertEqual(0, $DB->count_records($tablename));
2663 $DB->insert_record($tablename, array('course' => 3));
2664 $DB->insert_record($tablename, array('course' => 4));
2665 $DB->insert_record($tablename, array('course' => 5));
2667 $this->assertEqual(3, $DB->count_records($tablename));
2669 // test for exception throwing on text conditions being compared. (MDL-24863, unwanted auto conversion of param to int)
2670 $conditions = array('onetext' => '1');
2672 $DB->count_records($tablename, $conditions);
2673 $this->fail('An Exception is missing, expected due to equating of text fields');
2674 } catch (exception $e) {
2675 $this->assertTrue($e instanceof dml_exception);
2676 $this->assertEqual($e->errorcode, 'textconditionsnotallowed');
2680 public function test_count_records_select() {
2683 $dbman = $DB->get_manager();
2685 $table = $this->get_test_table();
2686 $tablename = $table->getName();
2688 $table->add_field('id', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, XMLDB_SEQUENCE, null);
2689 $table->add_field('course', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '0');
2690 $table->add_key('primary', XMLDB_KEY_PRIMARY, array('id'));
2691 $dbman->create_table($table);
2693 $this->assertEqual(0, $DB->count_records($tablename));
2695 $DB->insert_record($tablename, array('course' => 3));
2696 $DB->insert_record($tablename, array('course' => 4));
2697 $DB->insert_record($tablename, array('course' => 5));
2699 $this->assertEqual(2, $DB->count_records_select($tablename, 'course > ?', array(3)));
2702 public function test_count_records_sql() {
2704 $dbman = $DB->get_manager();
2706 $table = $this->get_test_table();
2707 $tablename = $table->getName();
2709 $table->add_field('id', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, XMLDB_SEQUENCE, null);
2710 $table->add_field('course', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '0');
2711 $table->add_key('primary', XMLDB_KEY_PRIMARY, array('id'));
2712 $dbman->create_table($table);
2714 $this->assertEqual(0, $DB->count_records($tablename));
2716 $DB->insert_record($tablename, array('course' => 3));
2717 $DB->insert_record($tablename, array('course' => 4));
2718 $DB->insert_record($tablename, array('course' => 5));
2720 $this->assertEqual(2, $DB->count_records_sql("SELECT COUNT(*) FROM {{$tablename}} WHERE course > ?", array(3)));
2723 public function test_record_exists() {
2725 $dbman = $DB->get_manager();
2727 $table = $this->get_test_table();
2728 $tablename = $table->getName();
2730 $table->add_field('id', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, XMLDB_SEQUENCE, null);
2731 $table->add_field('course', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '0');
2732 $table->add_field('onetext', XMLDB_TYPE_TEXT, 'big', null, null, null);
2733 $table->add_key('primary', XMLDB_KEY_PRIMARY, array('id'));
2734 $dbman->create_table($table);
2736 $this->assertEqual(0, $DB->count_records($tablename));
2738 $this->assertFalse($DB->record_exists($tablename, array('course' => 3)));
2739 $DB->insert_record($tablename, array('course' => 3));
2741 $this->assertTrue($DB->record_exists($tablename, array('course' => 3)));
2744 // test for exception throwing on text conditions being compared. (MDL-24863, unwanted auto conversion of param to int)
2745 $conditions = array('onetext' => '1');
2747 $DB->record_exists($tablename, $conditions);
2748 $this->fail('An Exception is missing, expected due to equating of text fields');
2749 } catch (exception $e) {
2750 $this->assertTrue($e instanceof dml_exception);
2751 $this->assertEqual($e->errorcode, 'textconditionsnotallowed');
2755 public function test_record_exists_select() {
2757 $dbman = $DB->get_manager();
2759 $table = $this->get_test_table();
2760 $tablename = $table->getName();
2762 $table->add_field('id', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, XMLDB_SEQUENCE, null);
2763 $table->add_field('course', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '0');
2764 $table->add_key('primary', XMLDB_KEY_PRIMARY, array('id'));
2765 $dbman->create_table($table);
2767 $this->assertEqual(0, $DB->count_records($tablename));
2769 $this->assertFalse($DB->record_exists_select($tablename, "course = ?", array(3)));
2770 $DB->insert_record($tablename, array('course' => 3));
2772 $this->assertTrue($DB->record_exists_select($tablename, "course = ?", array(3)));
2775 public function test_record_exists_sql() {
2777 $dbman = $DB->get_manager();
2779 $table = $this->get_test_table();
2780 $tablename = $table->getName();
2782 $table->add_field('id', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, XMLDB_SEQUENCE, null);
2783 $table->add_field('course', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '0');
2784 $table->add_key('primary', XMLDB_KEY_PRIMARY, array('id'));
2785 $dbman->create_table($table);
2787 $this->assertEqual(0, $DB->count_records($tablename));
2789 $this->assertFalse($DB->record_exists_sql("SELECT * FROM {{$tablename}} WHERE course = ?", array(3)));
2790 $DB->insert_record($tablename, array('course' => 3));
2792 $this->assertTrue($DB->record_exists_sql("SELECT * FROM {{$tablename}} WHERE course = ?", array(3)));
2795 public function test_recordset_locks_delete() {
2797 $dbman = $DB->get_manager();
2800 $table = $this->get_test_table();
2801 $tablename = $table->getName();
2803 $table->add_field('id', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, XMLDB_SEQUENCE, null);
2804 $table->add_field('course', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '0');
2805 $table->add_key('primary', XMLDB_KEY_PRIMARY, array('id'));
2806 $dbman->create_table($table);
2808 $DB->insert_record($tablename, array('course' => 1));
2809 $DB->insert_record($tablename, array('course' => 2));
2810 $DB->insert_record($tablename, array('course' => 3));
2811 $DB->insert_record($tablename, array('course' => 4));
2812 $DB->insert_record($tablename, array('course' => 5));
2813 $DB->insert_record($tablename, array('course' => 6));
2815 // Test against db write locking while on an open recordset
2816 $rs = $DB->get_recordset($tablename, array(), null, 'course', 2, 2); // get courses = {3,4}
2817 foreach ($rs as $record) {
2818 $cid = $record->course;
2819 $DB->delete_records($tablename, array('course' => $cid));
2820 $this->assertFalse($DB->record_exists($tablename, array('course' => $cid)));
2824 $this->assertEqual(4, $DB->count_records($tablename, array()));
2827 public function test_recordset_locks_update() {
2829 $dbman = $DB->get_manager();
2832 $table = $this->get_test_table();
2833 $tablename = $table->getName();
2835 $table->add_field('id', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, XMLDB_SEQUENCE, null);
2836 $table->add_field('course', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '0');
2837 $table->add_key('primary', XMLDB_KEY_PRIMARY, array('id'));
2838 $dbman->create_table($table);
2840 $DB->insert_record($tablename, array('course' => 1));
2841 $DB->insert_record($tablename, array('course' => 2));
2842 $DB->insert_record($tablename, array('course' => 3));
2843 $DB->insert_record($tablename, array('course' => 4));
2844 $DB->insert_record($tablename, array('course' => 5));
2845 $DB->insert_record($tablename, array('course' => 6));
2847 // Test against db write locking while on an open recordset
2848 $rs = $DB->get_recordset($tablename, array(), null, 'course', 2, 2); // get courses = {3,4}
2849 foreach ($rs as $record) {
2850 $cid = $record->course;
2851 $DB->set_field($tablename, 'course', 10, array('course' => $cid));
2852 $this->assertFalse($DB->record_exists($tablename, array('course' => $cid)));
2856 $this->assertEqual(2, $DB->count_records($tablename, array('course' => 10)));
2859 public function test_delete_records() {
2861 $dbman = $DB->get_manager();
2863 $table = $this->get_test_table();
2864 $tablename = $table->getName();
2866 $table->add_field('id', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, XMLDB_SEQUENCE, null);
2867 $table->add_field('course', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '0');
2868 $table->add_field('onetext', XMLDB_TYPE_TEXT, 'big', null, null, null);
2869 $table->add_key('primary', XMLDB_KEY_PRIMARY, array('id'));
2870 $dbman->create_table($table);
2872 $DB->insert_record($tablename, array('course' => 3));
2873 $DB->insert_record($tablename, array('course' => 2));
2874 $DB->insert_record($tablename, array('course' => 2));
2876 // Delete all records
2877 $this->assertTrue($DB->delete_records($tablename));
2878 $this->assertEqual(0, $DB->count_records($tablename));
2880 // Delete subset of records
2881 $DB->insert_record($tablename, array('course' => 3));
2882 $DB->insert_record($tablename, array('course' => 2));
2883 $DB->insert_record($tablename, array('course' => 2));
2885 $this->assertTrue($DB->delete_records($tablename, array('course' => 2)));
2886 $this->assertEqual(1, $DB->count_records($tablename));
2889 $this->assertTrue($DB->delete_records($tablename, array()));
2890 $this->assertEqual(0, $DB->count_records($tablename));
2892 // test for exception throwing on text conditions being compared. (MDL-24863, unwanted auto conversion of param to int)
2893 $conditions = array('onetext'=>'1');
2895 $DB->delete_records($tablename, $conditions);
2896 $this->fail('An Exception is missing, expected due to equating of text fields');
2897 } catch (exception $e) {
2898 $this->assertTrue($e instanceof dml_exception);
2899 $this->assertEqual($e->errorcode, 'textconditionsnotallowed');
2902 // test for exception throwing on text conditions being compared. (MDL-24863, unwanted auto conversion of param to int)
2903 $conditions = array('onetext' => 1);
2905 $DB->delete_records($tablename, $conditions);
2906 $this->fail('An Exception is missing, expected due to equating of text fields');
2907 } catch (exception $e) {
2908 $this->assertTrue($e instanceof dml_exception);
2909 $this->assertEqual($e->errorcode, 'textconditionsnotallowed');
2913 public function test_delete_records_select() {
2915 $dbman = $DB->get_manager();
2917 $table = $this->get_test_table();
2918 $tablename = $table->getName();
2920 $table->add_field('id', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, XMLDB_SEQUENCE, null);
2921 $table->add_field('course', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '0');
2922 $table->add_key('primary', XMLDB_KEY_PRIMARY, array('id'));
2923 $dbman->create_table($table);
2925 $DB->insert_record($tablename, array('course' => 3));
2926 $DB->insert_record($tablename, array('course' => 2));
2927 $DB->insert_record($tablename, array('course' => 2));
2929 $this->assertTrue($DB->delete_records_select($tablename, 'course = ?', array(2)));
2930 $this->assertEqual(1, $DB->count_records($tablename));
2933 public function test_delete_records_list() {
2935 $dbman = $DB->get_manager();
2937 $table = $this->get_test_table();
2938 $tablename = $table->getName();
2940 $table->add_field('id', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, XMLDB_SEQUENCE, null);
2941 $table->add_field('course', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '0');
2942 $table->add_key('primary', XMLDB_KEY_PRIMARY, array('id'));
2943 $dbman->create_table($table);
2945 $DB->insert_record($tablename, array('course' => 1));
2946 $DB->insert_record($tablename, array('course' => 2));
2947 $DB->insert_record($tablename, array('course' => 3));
2949 $this->assertTrue($DB->delete_records_list($tablename, 'course', array(2, 3)));
2950 $this->assertEqual(1, $DB->count_records($tablename));
2952 $this->assertTrue($DB->delete_records_list($tablename, 'course', array())); /// Must delete 0 rows without conditions. MDL-17645
2953 $this->assertEqual(1, $DB->count_records($tablename));
2956 function test_sql_null_from_clause() {
2958 $sql = "SELECT 1 AS id ".$DB->sql_null_from_clause();
2959 $this->assertEqual($DB->get_field_sql($sql), 1);
2962 function test_sql_bitand() {
2964 $dbman = $DB->get_manager();
2966 $table = $this->get_test_table();
2967 $tablename = $table->getName();
2969 $table->add_field('id', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, XMLDB_SEQUENCE, null);
2970 $table->add_field('col1', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '0');
2971 $table->add_field('col2', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '0');
2972 $table->add_key('primary', XMLDB_KEY_PRIMARY, array('id'));
2973 $dbman->create_table($table);
2975 $DB->insert_record($tablename, array('col1' => 3, 'col2' => 10));
2977 $sql = "SELECT ".$DB->sql_bitand(10, 3)." AS res ".$DB->sql_null_from_clause();
2978 $this->assertEqual($DB->get_field_sql($sql), 2);
2980 $sql = "SELECT id, ".$DB->sql_bitand('col1', 'col2')." AS res FROM {{$tablename}}";
2981 $result = $DB->get_records_sql($sql);
2982 $this->assertEqual(count($result), 1);
2983 $this->assertEqual(reset($result)->res, 2);
2985 $sql = "SELECT id, ".$DB->sql_bitand('col1', '?')." AS res FROM {{$tablename}}";
2986 $result = $DB->get_records_sql($sql, array(10));
2987 $this->assertEqual(count($result), 1);
2988 $this->assertEqual(reset($result)->res, 2);
2991 function test_sql_bitnot() {
2994 $not = $DB->sql_bitnot(2);
2995 $notlimited = $DB->sql_bitand($not, 7); // might be positive or negative number which can not fit into PHP INT!
2997 $sql = "SELECT $notlimited AS res ".$DB->sql_null_from_clause();
2998 $this->assertEqual($DB->get_field_sql($sql), 5);
3001 function test_sql_bitor() {
3003 $dbman = $DB->get_manager();
3005 $table = $this->get_test_table();
3006 $tablename = $table->getName();
3008 $table->add_field('id', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, XMLDB_SEQUENCE, null);
3009 $table->add_field('col1', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '0');
3010 $table->add_field('col2', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '0');
3011 $table->add_key('primary', XMLDB_KEY_PRIMARY, array('id'));
3012 $dbman->create_table($table);
3014 $DB->insert_record($tablename, array('col1' => 3, 'col2' => 10));
3016 $sql = "SELECT ".$DB->sql_bitor(10, 3)." AS res ".$DB->sql_null_from_clause();
3017 $this->assertEqual($DB->get_field_sql($sql), 11);
3019 $sql = "SELECT id, ".$DB->sql_bitor('col1', 'col2')." AS res FROM {{$tablename}}";
3020 $result = $DB->get_records_sql($sql);
3021 $this->assertEqual(count($result), 1);
3022 $this->assertEqual(reset($result)->res, 11);
3024 $sql = "SELECT id, ".$DB->sql_bitor('col1', '?')." AS res FROM {{$tablename}}";
3025 $result = $DB->get_records_sql($sql, array(10));
3026 $this->assertEqual(count($result), 1);
3027 $this->assertEqual(reset($result)->res, 11);
3030 function test_sql_bitxor() {
3032 $dbman = $DB->get_manager();
3034 $table = $this->get_test_table();
3035 $tablename = $table->getName();
3037 $table->add_field('id', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, XMLDB_SEQUENCE, null);
3038 $table->add_field('col1', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '0');
3039 $table->add_field('col2', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '0');
3040 $table->add_key('primary', XMLDB_KEY_PRIMARY, array('id'));
3041 $dbman->create_table($table);
3043 $DB->insert_record($tablename, array('col1' => 3, 'col2' => 10));
3045 $sql = "SELECT ".$DB->sql_bitxor(10, 3)." AS res ".$DB->sql_null_from_clause();
3046 $this->assertEqual($DB->get_field_sql($sql), 9);
3048 $sql = "SELECT id, ".$DB->sql_bitxor('col1', 'col2')." AS res FROM {{$tablename}}";
3049 $result = $DB->get_records_sql($sql);
3050 $this->assertEqual(count($result), 1);
3051 $this->assertEqual(reset($result)->res, 9);
3053 $sql = "SELECT id, ".$DB->sql_bitxor('col1', '?')." AS res FROM {{$tablename}}";
3054 $result = $DB->get_records_sql($sql, array(10));
3055 $this->assertEqual(count($result), 1);
3056 $this->assertEqual(reset($result)->res, 9);
3059 function test_sql_modulo() {
3061 $sql = "SELECT ".$DB->sql_modulo(10, 7)." AS res ".$DB->sql_null_from_clause();
3062 $this->assertEqual($DB->get_field_sql($sql), 3);
3065 function test_sql_ceil() {
3067 $sql = "SELECT ".$DB->sql_ceil(665.666)." AS res ".$DB->sql_null_from_clause();
3068 $this->assertEqual($DB->get_field_sql($sql), 666);
3071 function test_cast_char2int() {
3073 $dbman = $DB->get_manager();
3075 $table1 = $this->get_test_table("1");
3076 $tablename1 = $table1->getName();
3078 $table1->add_field('id', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, XMLDB_SEQUENCE, null);
3079 $table1->add_field('name', XMLDB_TYPE_CHAR, '255', null, null, null, null);
3080 $table1->add_field('nametext', XMLDB_TYPE_TEXT, 'small', null, null, null, null);
3081 $table1->add_key('primary', XMLDB_KEY_PRIMARY, array('id'));
3082 $dbman->create_table($table1);
3084 $DB->insert_record($tablename1, array('name'=>'0100', 'nametext'=>'0200'));
3085 $DB->insert_record($tablename1, array('name'=>'10', 'nametext'=>'20'));
3087 $table2 = $this->get_test_table("2");
3088 $tablename2 = $table2->getName();
3089 $table2->add_field('id', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, XMLDB_SEQUENCE, null);
3090 $table2->add_field('res', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '0');
3091 $table2->add_field('restext', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '0');
3092 $table2->add_key('primary', XMLDB_KEY_PRIMARY, array('id'));
3093 $dbman->create_table($table2);
3095 $DB->insert_record($tablename2, array('res'=>100, 'restext'=>200));
3097 // casting varchar field
3099 FROM {".$tablename1."} t1
3100 JOIN {".$tablename2."} t2 ON ".$DB->sql_cast_char2int("t1.name")." = t2.res ";
3101 $records = $DB->get_records_sql($sql);
3102 $this->assertEqual(count($records), 1);
3103 // also test them in order clauses
3104 $sql = "SELECT * FROM {{$tablename1}} ORDER BY ".$DB->sql_cast_char2int('name');
3105 $records = $DB->get_records_sql($sql);
3106 $this->assertEqual(count($records), 2);
3107 $this->assertEqual(reset($records)->name, '10');
3108 $this->assertEqual(next($records)->name, '0100');
3110 // casting text field
3112 FROM {".$tablename1."} t1
3113 JOIN {".$tablename2."} t2 ON ".$DB->sql_cast_char2int("t1.nametext", true)." = t2.restext ";
3114 $records = $DB->get_records_sql($sql);
3115 $this->assertEqual(count($records), 1);
3116 // also test them in order clauses
3117 $sql = "SELECT * FROM {{$tablename1}} ORDER BY ".$DB->sql_cast_char2int('nametext', true);
3118 $records = $DB->get_records_sql($sql);
3119 $this->assertEqual(count($records), 2);
3120 $this->assertEqual(reset($records)->nametext, '20');
3121 $this->assertEqual(next($records)->nametext, '0200');
3124 function test_cast_char2real() {
3126 $dbman = $DB->get_manager();
3128 $table = $this->get_test_table();
3129 $tablename = $table->getName();
3131 $table->add_field('id', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, XMLDB_SEQUENCE, null);
3132 $table->add_field('name', XMLDB_TYPE_CHAR, '255', null, null, null, null);
3133 $table->add_field('nametext', XMLDB_TYPE_TEXT, 'small', null, null, null, null);
3134 $table->add_field('res', XMLDB_TYPE_NUMBER, '12, 7', null, null, null, null);
3135 $table->add_key('primary', XMLDB_KEY_PRIMARY, array('id'));
3136 $dbman->create_table($table);
3138 $DB->insert_record($tablename, array('name'=>'10.10', 'nametext'=>'10.10', 'res'=>5.1));
3139 $DB->insert_record($tablename, array('name'=>'91.10', 'nametext'=>'91.10', 'res'=>666));
3140 $DB->insert_record($tablename, array('name'=>'011.10','nametext'=>'011.10','res'=>10.1));
3142 // casting varchar field
3143 $sql = "SELECT * FROM {{$tablename}} WHERE ".$DB->sql_cast_char2real('name')." > res";
3144 $records = $DB->get_records_sql($sql);
3145 $this->assertEqual(count($records), 2);
3146 // also test them in order clauses
3147 $sql = "SELECT * FROM {{$tablename}} ORDER BY ".$DB->sql_cast_char2real('name');
3148 $records = $DB->get_records_sql($sql);
3149 $this->assertEqual(count($records), 3);
3150 $this->assertEqual(reset($records)->name, '10.10');
3151 $this->assertEqual(next($records)->name, '011.10');
3152 $this->assertEqual(next($records)->name, '91.10');
3154 // casting text field
3155 $sql = "SELECT * FROM {{$tablename}} WHERE ".$DB->sql_cast_char2real('nametext', true)." > res";
3156 $records = $DB->get_records_sql($sql);
3157 $this->assertEqual(count($records), 2);
3158 // also test them in order clauses
3159 $sql = "SELECT * FROM {{$tablename}} ORDER BY ".$DB->sql_cast_char2real('nametext', true);
3160 $records = $DB->get_records_sql($sql);
3161 $this->assertEqual(count($records), 3);
3162 $this->assertEqual(reset($records)->nametext, '10.10');
3163 $this->assertEqual(next($records)->nametext, '011.10');
3164 $this->assertEqual(next($records)->nametext, '91.10');
3167 function sql_compare_text() {
3169 $dbman = $DB->get_manager();
3171 $table = $this->get_test_table();
3172 $tablename = $table->getName();
3174 $table->add_field('id', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, XMLDB_SEQUENCE, null);
3175 $table->add_field('name', XMLDB_TYPE_CHAR, '255', null, null, null, null);
3176 $table->add_field('description', XMLDB_TYPE_TEXT, 'big', null, null, null, null);
3177 $table->add_key('primary', XMLDB_KEY_PRIMARY, array('id'));
3178 $dbman->create_table($table);
3180 $DB->insert_record($tablename, array('name'=>'abcd', 'description'=>'abcd'));
3181 $DB->insert_record($tablename, array('name'=>'abcdef', 'description'=>'bbcdef'));
3182 $DB->insert_record($tablename, array('name'=>'aaaabb', 'description'=>'aaaacccccccccccccccccc'));
3184 $sql = "SELECT * FROM {{$tablename}} WHERE name = ".$DB->sql_compare_text('description');
3185 $records = $DB->get_records_sql($sql);
3186 $this->assertEqual(count($records), 1);
3188 $sql = "SELECT * FROM {{$tablename}} WHERE name = ".$DB->sql_compare_text('description', 4);
3189 $records = $DB->get_records_sql($sql);
3190 $this->assertEqual(count($records), 2);
3193 function test_unique_index_collation_trouble() {
3194 // note: this is a work in progress, we should probably move this to ddl test
3197 $dbman = $DB->get_manager();
3199 $table = $this->get_test_table();
3200 $tablename = $table->getName();
3202 $table->add_field('id', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, XMLDB_SEQUENCE, null);
3203 $table->add_field('name', XMLDB_TYPE_CHAR, '255', null, null, null, null);
3204 $table->add_key('primary', XMLDB_KEY_PRIMARY, array('id'));
3205 $table->add_index('name', XMLDB_INDEX_UNIQUE, array('name'));
3206 $dbman->create_table($table);
3208 $DB->insert_record($tablename, array('name'=>'aaa'));
3211 $DB->insert_record($tablename, array('name'=>'AAA'));
3212 } catch (Exception $e) {
3213 //TODO: ignore case insensitive uniqueness problems for now
3214 //$this->fail("Unique index is case sensitive - this may cause problems in some tables");
3218 $DB->insert_record($tablename, array('name'=>'aäa'));
3219 $DB->insert_record($tablename, array('name'=>'aáa'));
3220 $this->assertTrue(true);
3221 } catch (Exception $e) {
3222 $family = $DB->get_dbfamily();
3223 if ($family === 'mysql' or $family === 'mssql') {
3224 $this->fail("Unique index is accent insensitive, this may cause problems for non-ascii languages. This is usually caused by accent insensitive default collation.");
3226 // this should not happen, PostgreSQL and Oracle do not support accent insensitive uniqueness.
3227 $this->fail("Unique index is accent insensitive, this may cause problems for non-ascii languages.");
3233 function test_sql_binary_equal() {
3235 $dbman = $DB->get_manager();
3237 $table = $this->get_test_table();
3238 $tablename = $table->getName();
3240 $table->add_field('id', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, XMLDB_SEQUENCE, null);
3241 $table->add_field('name', XMLDB_TYPE_CHAR, '255', null, null, null, null);
3242 $table->add_key('primary', XMLDB_KEY_PRIMARY, array('id'));
3243 $dbman->create_table($table);
3245 $DB->insert_record($tablename, array('name'=>'aaa'));
3246 $DB->insert_record($tablename, array('name'=>'aáa'));
3247 $DB->insert_record($tablename, array('name'=>'aäa'));
3248 $DB->insert_record($tablename, array('name'=>'bbb'));
3249 $DB->insert_record($tablename, array('name'=>'BBB'));
3251 $records = $DB->get_records_sql("SELECT * FROM {{$tablename}} WHERE name = ?", array('aaa'));
3252 $this->assertEqual(count($records), 1, 'SQL operator "=" is expected to be accent sensitive');
3254 $records = $DB->get_records_sql("SELECT * FROM {{$tablename}} WHERE name = ?", array('bbb'));
3255 $this->assertEqual(count($records), 1, 'SQL operator "=" is expected to be case sensitive');
3258 function test_sql_like() {
3260 $dbman = $DB->get_manager();
3262 $table = $this->get_test_table();
3263 $tablename = $table->getName();
3265 $table->add_field('id', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, XMLDB_SEQUENCE, null);
3266 $table->add_field('name', XMLDB_TYPE_CHAR, '255', null, null, null, null);
3267 $table->add_key('primary', XMLDB_KEY_PRIMARY, array('id'));
3268 $dbman->create_table($table);