|
Moodle
2.2.1
http://www.collinsharper.com
|
00001 <?php 00002 00003 // This file is part of Moodle - http://moodle.org/ 00004 // 00005 // Moodle is free software: you can redistribute it and/or modify 00006 // it under the terms of the GNU General Public License as published by 00007 // the Free Software Foundation, either version 3 of the License, or 00008 // (at your option) any later version. 00009 // 00010 // Moodle is distributed in the hope that it will be useful, 00011 // but WITHOUT ANY WARRANTY; without even the implied warranty of 00012 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00013 // GNU General Public License for more details. 00014 // 00015 // You should have received a copy of the GNU General Public License 00016 // along with Moodle. If not, see <http://www.gnu.org/licenses/>. 00017 00025 defined('MOODLE_INTERNAL') || die(); 00026 00027 class dml_test extends UnitTestCase { 00028 private $tables = array(); 00030 private $tdb; 00031 private $data; 00032 public static $includecoverage = array('lib/dml'); 00033 public static $excludecoverage = array('lib/dml/simpletest'); 00034 00035 protected $olddebug; 00036 protected $olddisplay; 00037 00038 function setUp() { 00039 global $DB, $UNITTEST; 00040 00041 if (isset($UNITTEST->func_test_db)) { 00042 $this->tdb = $UNITTEST->func_test_db; 00043 } else { 00044 $this->tdb = $DB; 00045 } 00046 } 00047 00048 function tearDown() { 00049 $dbman = $this->tdb->get_manager(); 00050 00051 foreach ($this->tables as $tablename) { 00052 if ($dbman->table_exists($tablename)) { 00053 $table = new xmldb_table($tablename); 00054 $dbman->drop_table($table); 00055 } 00056 } 00057 $this->tables = array(); 00058 } 00059 00069 private function get_test_table($suffix = '') { 00070 $dbman = $this->tdb->get_manager(); 00071 00072 $tablename = "unit_table"; 00073 if ($suffix !== '') { 00074 $tablename .= $suffix; 00075 } 00076 00077 $table = new xmldb_table($tablename); 00078 if ($dbman->table_exists($table)) { 00079 $dbman->drop_table($table); 00080 } 00081 $table->setComment("This is a test'n drop table. You can drop it safely"); 00082 $this->tables[$tablename] = $tablename; 00083 return new xmldb_table($tablename); 00084 } 00085 00086 protected function enable_debugging() { 00087 global $CFG; 00088 00089 $this->olddebug = $CFG->debug; // Save current debug settings 00090 $this->olddisplay = $CFG->debugdisplay; 00091 $CFG->debug = DEBUG_DEVELOPER; 00092 $CFG->debugdisplay = true; 00093 ob_start(); // hide debug warning 00094 00095 } 00096 00097 protected function get_debugging() { 00098 global $CFG; 00099 00100 $debuginfo = ob_get_contents(); 00101 ob_end_clean(); 00102 $CFG->debug = $this->olddebug; // Restore original debug settings 00103 $CFG->debugdisplay = $this->olddisplay; 00104 00105 return $debuginfo; 00106 } 00107 00108 // NOTE: please keep order of test methods here matching the order of moodle_database class methods 00109 00110 function test_diagnose() { 00111 $DB = $this->tdb; 00112 $result = $DB->diagnose(); 00113 $this->assertNull($result, 'Database self diagnostics failed %s'); 00114 } 00115 00116 function test_get_server_info() { 00117 $DB = $this->tdb; 00118 $result = $DB->get_server_info(); 00119 $this->assertTrue(is_array($result)); 00120 $this->assertTrue(array_key_exists('description', $result)); 00121 $this->assertTrue(array_key_exists('version', $result)); 00122 } 00123 00124 public function test_get_in_or_equal() { 00125 $DB = $this->tdb; 00126 00127 // SQL_PARAMS_QM - IN or = 00128 00129 // Correct usage of multiple values 00130 $in_values = array('value1', 'value2', '3', 4, null, false, true); 00131 list($usql, $params) = $DB->get_in_or_equal($in_values); 00132 $this->assertEqual('IN ('.implode(',',array_fill(0, count($in_values), '?')).')', $usql); 00133 $this->assertEqual(count($in_values), count($params)); 00134 foreach ($params as $key => $value) { 00135 $this->assertIdentical($in_values[$key], $value); 00136 } 00137 00138 // Correct usage of single value (in an array) 00139 $in_values = array('value1'); 00140 list($usql, $params) = $DB->get_in_or_equal($in_values); 00141 $this->assertEqual("= ?", $usql); 00142 $this->assertEqual(1, count($params)); 00143 $this->assertEqual($in_values[0], $params[0]); 00144 00145 // Correct usage of single value 00146 $in_value = 'value1'; 00147 list($usql, $params) = $DB->get_in_or_equal($in_values); 00148 $this->assertEqual("= ?", $usql); 00149 $this->assertEqual(1, count($params)); 00150 $this->assertEqual($in_value, $params[0]); 00151 00152 // SQL_PARAMS_QM - NOT IN or <> 00153 00154 // Correct usage of multiple values 00155 $in_values = array('value1', 'value2', 'value3', 'value4'); 00156 list($usql, $params) = $DB->get_in_or_equal($in_values, SQL_PARAMS_QM, null, false); 00157 $this->assertEqual("NOT IN (?,?,?,?)", $usql); 00158 $this->assertEqual(4, count($params)); 00159 foreach ($params as $key => $value) { 00160 $this->assertEqual($in_values[$key], $value); 00161 } 00162 00163 // Correct usage of single value (in array() 00164 $in_values = array('value1'); 00165 list($usql, $params) = $DB->get_in_or_equal($in_values, SQL_PARAMS_QM, null, false); 00166 $this->assertEqual("<> ?", $usql); 00167 $this->assertEqual(1, count($params)); 00168 $this->assertEqual($in_values[0], $params[0]); 00169 00170 // Correct usage of single value 00171 $in_value = 'value1'; 00172 list($usql, $params) = $DB->get_in_or_equal($in_values, SQL_PARAMS_QM, null, false); 00173 $this->assertEqual("<> ?", $usql); 00174 $this->assertEqual(1, count($params)); 00175 $this->assertEqual($in_value, $params[0]); 00176 00177 // SQL_PARAMS_NAMED - IN or = 00178 00179 // Correct usage of multiple values 00180 $in_values = array('value1', 'value2', 'value3', 'value4'); 00181 list($usql, $params) = $DB->get_in_or_equal($in_values, SQL_PARAMS_NAMED, 'param', true); 00182 $this->assertEqual(4, count($params)); 00183 reset($in_values); 00184 $ps = array(); 00185 foreach ($params as $key => $value) { 00186 $this->assertEqual(current($in_values), $value); 00187 next($in_values); 00188 $ps[] = ':'.$key; 00189 } 00190 $this->assertEqual("IN (".implode(',', $ps).")", $usql); 00191 00192 // Correct usage of single values (in array) 00193 $in_values = array('value1'); 00194 list($usql, $params) = $DB->get_in_or_equal($in_values, SQL_PARAMS_NAMED, 'param', true); 00195 $this->assertEqual(1, count($params)); 00196 $value = reset($params); 00197 $key = key($params); 00198 $this->assertEqual("= :$key", $usql); 00199 $this->assertEqual($in_value, $value); 00200 00201 // Correct usage of single value 00202 $in_value = 'value1'; 00203 list($usql, $params) = $DB->get_in_or_equal($in_values, SQL_PARAMS_NAMED, 'param', true); 00204 $this->assertEqual(1, count($params)); 00205 $value = reset($params); 00206 $key = key($params); 00207 $this->assertEqual("= :$key", $usql); 00208 $this->assertEqual($in_value, $value); 00209 00210 // SQL_PARAMS_NAMED - NOT IN or <> 00211 00212 // Correct usage of multiple values 00213 $in_values = array('value1', 'value2', 'value3', 'value4'); 00214 list($usql, $params) = $DB->get_in_or_equal($in_values, SQL_PARAMS_NAMED, 'param', false); 00215 $this->assertEqual(4, count($params)); 00216 reset($in_values); 00217 $ps = array(); 00218 foreach ($params as $key => $value) { 00219 $this->assertEqual(current($in_values), $value); 00220 next($in_values); 00221 $ps[] = ':'.$key; 00222 } 00223 $this->assertEqual("NOT IN (".implode(',', $ps).")", $usql); 00224 00225 // Correct usage of single values (in array) 00226 $in_values = array('value1'); 00227 list($usql, $params) = $DB->get_in_or_equal($in_values, SQL_PARAMS_NAMED, 'param', false); 00228 $this->assertEqual(1, count($params)); 00229 $value = reset($params); 00230 $key = key($params); 00231 $this->assertEqual("<> :$key", $usql); 00232 $this->assertEqual($in_value, $value); 00233 00234 // Correct usage of single value 00235 $in_value = 'value1'; 00236 list($usql, $params) = $DB->get_in_or_equal($in_values, SQL_PARAMS_NAMED, 'param', false); 00237 $this->assertEqual(1, count($params)); 00238 $value = reset($params); 00239 $key = key($params); 00240 $this->assertEqual("<> :$key", $usql); 00241 $this->assertEqual($in_value, $value); 00242 00243 // make sure the param names are unique 00244 list($usql1, $params1) = $DB->get_in_or_equal(array(1,2,3), SQL_PARAMS_NAMED, 'param'); 00245 list($usql2, $params2) = $DB->get_in_or_equal(array(1,2,3), SQL_PARAMS_NAMED, 'param'); 00246 $params1 = array_keys($params1); 00247 $params2 = array_keys($params2); 00248 $common = array_intersect($params1, $params2); 00249 $this->assertEqual(count($common), 0); 00250 00251 // Some incorrect tests 00252 00253 // Incorrect usage passing not-allowed params type 00254 $in_values = array(1, 2, 3); 00255 try { 00256 list($usql, $params) = $DB->get_in_or_equal($in_values, SQL_PARAMS_DOLLAR, 'param', false); 00257 $this->fail('An Exception is missing, expected due to not supported SQL_PARAMS_DOLLAR'); 00258 } catch (exception $e) { 00259 $this->assertTrue($e instanceof dml_exception); 00260 $this->assertEqual($e->errorcode, 'typenotimplement'); 00261 } 00262 00263 // Incorrect usage passing empty array 00264 $in_values = array(); 00265 try { 00266 list($usql, $params) = $DB->get_in_or_equal($in_values, SQL_PARAMS_NAMED, 'param', false); 00267 $this->fail('An Exception is missing, expected due to empty array of items'); 00268 } catch (exception $e) { 00269 $this->assertTrue($e instanceof coding_exception); 00270 } 00271 00272 // Test using $onemptyitems 00273 00274 // Correct usage passing empty array and $onemptyitems = NULL (equal = true, QM) 00275 $in_values = array(); 00276 list($usql, $params) = $DB->get_in_or_equal($in_values, SQL_PARAMS_QM, 'param', true, NULL); 00277 $this->assertEqual(' IS NULL', $usql); 00278 $this->assertIdentical(array(), $params); 00279 00280 // Correct usage passing empty array and $onemptyitems = NULL (equal = false, NAMED) 00281 $in_values = array(); 00282 list($usql, $params) = $DB->get_in_or_equal($in_values, SQL_PARAMS_NAMED, 'param', false, NULL); 00283 $this->assertEqual(' IS NOT NULL', $usql); 00284 $this->assertIdentical(array(), $params); 00285 00286 // Correct usage passing empty array and $onemptyitems = true (equal = true, QM) 00287 $in_values = array(); 00288 list($usql, $params) = $DB->get_in_or_equal($in_values, SQL_PARAMS_QM, 'param', true, true); 00289 $this->assertEqual('= ?', $usql); 00290 $this->assertIdentical(array(true), $params); 00291 00292 // Correct usage passing empty array and $onemptyitems = true (equal = false, NAMED) 00293 $in_values = array(); 00294 list($usql, $params) = $DB->get_in_or_equal($in_values, SQL_PARAMS_NAMED, 'param', false, true); 00295 $this->assertEqual(1, count($params)); 00296 $value = reset($params); 00297 $key = key($params); 00298 $this->assertEqual('<> :'.$key, $usql); 00299 $this->assertIdentical($value, true); 00300 00301 // Correct usage passing empty array and $onemptyitems = -1 (equal = true, QM) 00302 $in_values = array(); 00303 list($usql, $params) = $DB->get_in_or_equal($in_values, SQL_PARAMS_QM, 'param', true, -1); 00304 $this->assertEqual('= ?', $usql); 00305 $this->assertIdentical(array(-1), $params); 00306 00307 // Correct usage passing empty array and $onemptyitems = -1 (equal = false, NAMED) 00308 $in_values = array(); 00309 list($usql, $params) = $DB->get_in_or_equal($in_values, SQL_PARAMS_NAMED, 'param', false, -1); 00310 $this->assertEqual(1, count($params)); 00311 $value = reset($params); 00312 $key = key($params); 00313 $this->assertEqual('<> :'.$key, $usql); 00314 $this->assertIdentical($value, -1); 00315 00316 // Correct usage passing empty array and $onemptyitems = 'onevalue' (equal = true, QM) 00317 $in_values = array(); 00318 list($usql, $params) = $DB->get_in_or_equal($in_values, SQL_PARAMS_QM, 'param', true, 'onevalue'); 00319 $this->assertEqual('= ?', $usql); 00320 $this->assertIdentical(array('onevalue'), $params); 00321 00322 // Correct usage passing empty array and $onemptyitems = 'onevalue' (equal = false, NAMED) 00323 $in_values = array(); 00324 list($usql, $params) = $DB->get_in_or_equal($in_values, SQL_PARAMS_NAMED, 'param', false, 'onevalue'); 00325 $this->assertEqual(1, count($params)); 00326 $value = reset($params); 00327 $key = key($params); 00328 $this->assertEqual('<> :'.$key, $usql); 00329 $this->assertIdentical($value, 'onevalue'); 00330 } 00331 00332 public function test_fix_table_names() { 00333 $DB = new moodle_database_for_testing(); 00334 $prefix = $DB->get_prefix(); 00335 00336 // Simple placeholder 00337 $placeholder = "{user_123}"; 00338 $this->assertIdentical($prefix."user_123", $DB->public_fix_table_names($placeholder)); 00339 00340 // wrong table name 00341 $placeholder = "{user-a}"; 00342 $this->assertIdentical($placeholder, $DB->public_fix_table_names($placeholder)); 00343 00344 // wrong table name 00345 $placeholder = "{123user}"; 00346 $this->assertIdentical($placeholder, $DB->public_fix_table_names($placeholder)); 00347 00348 // Full SQL 00349 $sql = "SELECT * FROM {user}, {funny_table_name}, {mdl_stupid_table} WHERE {user}.id = {funny_table_name}.userid"; 00350 $expected = "SELECT * FROM {$prefix}user, {$prefix}funny_table_name, {$prefix}mdl_stupid_table WHERE {$prefix}user.id = {$prefix}funny_table_name.userid"; 00351 $this->assertIdentical($expected, $DB->public_fix_table_names($sql)); 00352 } 00353 00354 function test_fix_sql_params() { 00355 $DB = $this->tdb; 00356 00357 $table = $this->get_test_table(); 00358 $tablename = $table->getName(); 00359 00360 // Correct table placeholder substitution 00361 $sql = "SELECT * FROM {{$tablename}}"; 00362 $sqlarray = $DB->fix_sql_params($sql); 00363 $this->assertEqual("SELECT * FROM {$DB->get_prefix()}".$tablename, $sqlarray[0]); 00364 00365 // Conversions of all param types 00366 $sql = array(); 00367 $sql[SQL_PARAMS_NAMED] = "SELECT * FROM {$DB->get_prefix()}testtable WHERE name = :param1, course = :param2"; 00368 $sql[SQL_PARAMS_QM] = "SELECT * FROM {$DB->get_prefix()}testtable WHERE name = ?, course = ?"; 00369 $sql[SQL_PARAMS_DOLLAR] = "SELECT * FROM {$DB->get_prefix()}testtable WHERE name = \$1, course = \$2"; 00370 00371 $params = array(); 00372 $params[SQL_PARAMS_NAMED] = array('param1'=>'first record', 'param2'=>1); 00373 $params[SQL_PARAMS_QM] = array('first record', 1); 00374 $params[SQL_PARAMS_DOLLAR] = array('first record', 1); 00375 00376 list($rsql, $rparams, $rtype) = $DB->fix_sql_params($sql[SQL_PARAMS_NAMED], $params[SQL_PARAMS_NAMED]); 00377 $this->assertIdentical($rsql, $sql[$rtype]); 00378 $this->assertIdentical($rparams, $params[$rtype]); 00379 00380 list($rsql, $rparams, $rtype) = $DB->fix_sql_params($sql[SQL_PARAMS_QM], $params[SQL_PARAMS_QM]); 00381 $this->assertIdentical($rsql, $sql[$rtype]); 00382 $this->assertIdentical($rparams, $params[$rtype]); 00383 00384 list($rsql, $rparams, $rtype) = $DB->fix_sql_params($sql[SQL_PARAMS_DOLLAR], $params[SQL_PARAMS_DOLLAR]); 00385 $this->assertIdentical($rsql, $sql[$rtype]); 00386 $this->assertIdentical($rparams, $params[$rtype]); 00387 00388 00389 // Malformed table placeholder 00390 $sql = "SELECT * FROM [testtable]"; 00391 $sqlarray = $DB->fix_sql_params($sql); 00392 $this->assertIdentical($sql, $sqlarray[0]); 00393 00394 00395 // Mixed param types (colon and dollar) 00396 $sql = "SELECT * FROM {{$tablename}} WHERE name = :param1, course = \$1"; 00397 $params = array('param1' => 'record1', 'param2' => 3); 00398 try { 00399 $DB->fix_sql_params($sql, $params); 00400 $this->fail("Expecting an exception, none occurred"); 00401 } catch (Exception $e) { 00402 $this->assertTrue($e instanceof dml_exception); 00403 } 00404 00405 // Mixed param types (question and dollar) 00406 $sql = "SELECT * FROM {{$tablename}} WHERE name = ?, course = \$1"; 00407 $params = array('param1' => 'record2', 'param2' => 5); 00408 try { 00409 $DB->fix_sql_params($sql, $params); 00410 $this->fail("Expecting an exception, none occurred"); 00411 } catch (Exception $e) { 00412 $this->assertTrue($e instanceof dml_exception); 00413 } 00414 00415 // Too few params in sql 00416 $sql = "SELECT * FROM {{$tablename}} WHERE name = ?, course = ?, id = ?"; 00417 $params = array('record2', 3); 00418 try { 00419 $DB->fix_sql_params($sql, $params); 00420 $this->fail("Expecting an exception, none occurred"); 00421 } catch (Exception $e) { 00422 $this->assertTrue($e instanceof dml_exception); 00423 } 00424 00425 // Too many params in array: no error, just use what is necessary 00426 $params[] = 1; 00427 $params[] = time(); 00428 try { 00429 $sqlarray = $DB->fix_sql_params($sql, $params); 00430 $this->assertTrue(is_array($sqlarray)); 00431 $this->assertEqual(count($sqlarray[1]), 3); 00432 } catch (Exception $e) { 00433 $this->fail("Unexpected ".get_class($e)." exception"); 00434 } 00435 00436 // Named params missing from array 00437 $sql = "SELECT * FROM {{$tablename}} WHERE name = :name, course = :course"; 00438 $params = array('wrongname' => 'record1', 'course' => 1); 00439 try { 00440 $DB->fix_sql_params($sql, $params); 00441 $this->fail("Expecting an exception, none occurred"); 00442 } catch (Exception $e) { 00443 $this->assertTrue($e instanceof dml_exception); 00444 } 00445 00446 // Duplicate named param in query - this is a very important feature!! 00447 // it helps with debugging of sloppy code 00448 $sql = "SELECT * FROM {{$tablename}} WHERE name = :name, course = :name"; 00449 $params = array('name' => 'record2', 'course' => 3); 00450 try { 00451 $DB->fix_sql_params($sql, $params); 00452 $this->fail("Expecting an exception, none occurred"); 00453 } catch (Exception $e) { 00454 $this->assertTrue($e instanceof dml_exception); 00455 } 00456 00457 // Extra named param is ignored 00458 $sql = "SELECT * FROM {{$tablename}} WHERE name = :name, course = :course"; 00459 $params = array('name' => 'record1', 'course' => 1, 'extrastuff'=>'haha'); 00460 try { 00461 $sqlarray = $DB->fix_sql_params($sql, $params); 00462 $this->assertTrue(is_array($sqlarray)); 00463 $this->assertEqual(count($sqlarray[1]), 2); 00464 } catch (Exception $e) { 00465 $this->fail("Unexpected ".get_class($e)." exception"); 00466 } 00467 00468 // Params exceeding 30 chars length 00469 $sql = "SELECT * FROM {{$tablename}} WHERE name = :long_placeholder_with_more_than_30"; 00470 $params = array('long_placeholder_with_more_than_30' => 'record1'); 00471 try { 00472 $DB->fix_sql_params($sql, $params); 00473 $this->fail("Expecting an exception, none occurred"); 00474 } catch (Exception $e) { 00475 $this->assertTrue($e instanceof coding_exception); 00476 } 00477 00478 // Booleans in NAMED params are casting to 1/0 int 00479 $sql = "SELECT * FROM {{$tablename}} WHERE course = ? OR course = ?"; 00480 $params = array(true, false); 00481 list($sql, $params) = $DB->fix_sql_params($sql, $params); 00482 $this->assertTrue(reset($params) === 1); 00483 $this->assertTrue(next($params) === 0); 00484 00485 // Booleans in QM params are casting to 1/0 int 00486 $sql = "SELECT * FROM {{$tablename}} WHERE course = :course1 OR course = :course2"; 00487 $params = array('course1' => true, 'course2' => false); 00488 list($sql, $params) = $DB->fix_sql_params($sql, $params); 00489 $this->assertTrue(reset($params) === 1); 00490 $this->assertTrue(next($params) === 0); 00491 00492 // Booleans in DOLLAR params are casting to 1/0 int 00493 $sql = "SELECT * FROM {{$tablename}} WHERE course = \$1 OR course = \$2"; 00494 $params = array(true, false); 00495 list($sql, $params) = $DB->fix_sql_params($sql, $params); 00496 $this->assertTrue(reset($params) === 1); 00497 $this->assertTrue(next($params) === 0); 00498 00499 // No data types are touched except bool 00500 $sql = "SELECT * FROM {{$tablename}} WHERE name IN (?,?,?,?,?,?)"; 00501 $inparams = array('abc', 'ABC', NULL, '1', 1, 1.4); 00502 list($sql, $params) = $DB->fix_sql_params($sql, $inparams); 00503 $this->assertIdentical(array_values($params), array_values($inparams)); 00504 } 00505 00506 public function test_strtok() { 00507 // strtok was previously used by bound emulation, make sure it is not used any more 00508 $DB = $this->tdb; 00509 $dbman = $this->tdb->get_manager(); 00510 00511 $table = $this->get_test_table(); 00512 $tablename = $table->getName(); 00513 00514 $table->add_field('id', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, XMLDB_SEQUENCE, null); 00515 $table->add_field('course', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '0'); 00516 $table->add_field('name', XMLDB_TYPE_CHAR, '255', null, null, null, 'lala'); 00517 $table->add_key('primary', XMLDB_KEY_PRIMARY, array('id')); 00518 $dbman->create_table($table); 00519 00520 $str = 'a?b?c?d'; 00521 $this->assertIdentical(strtok($str, '?'), 'a'); 00522 00523 $DB->get_records($tablename, array('id'=>1)); 00524 00525 $this->assertIdentical(strtok('?'), 'b'); 00526 } 00527 00528 public function test_tweak_param_names() { 00529 // Note the tweak_param_names() method is only available in the oracle driver, 00530 // hence we look for expected results indirectly, by testing various DML methods 00531 // with some "extreme" conditions causing the tweak to happen. 00532 $DB = $this->tdb; 00533 $dbman = $this->tdb->get_manager(); 00534 00535 $table = $this->get_test_table(); 00536 $tablename = $table->getName(); 00537 00538 $table->add_field('id', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, XMLDB_SEQUENCE, null); 00539 // Add some columns with 28 chars in the name 00540 $table->add_field('long_int_columnname_with_28c', XMLDB_TYPE_INTEGER, '10'); 00541 $table->add_field('long_dec_columnname_with_28c', XMLDB_TYPE_NUMBER, '10,2'); 00542 $table->add_field('long_str_columnname_with_28c', XMLDB_TYPE_CHAR, '100'); 00543 // Add some columns with 30 chars in the name 00544 $table->add_field('long_int_columnname_with_30cxx', XMLDB_TYPE_INTEGER, '10'); 00545 $table->add_field('long_dec_columnname_with_30cxx', XMLDB_TYPE_NUMBER, '10,2'); 00546 $table->add_field('long_str_columnname_with_30cxx', XMLDB_TYPE_CHAR, '100'); 00547 00548 $table->add_key('primary', XMLDB_KEY_PRIMARY, array('id')); 00549 00550 $dbman->create_table($table); 00551 00552 $this->assertTrue($dbman->table_exists($tablename)); 00553 00554 // Test insert record 00555 $rec1 = new stdClass(); 00556 $rec1->long_int_columnname_with_28c = 28; 00557 $rec1->long_dec_columnname_with_28c = 28.28; 00558 $rec1->long_str_columnname_with_28c = '28'; 00559 $rec1->long_int_columnname_with_30cxx = 30; 00560 $rec1->long_dec_columnname_with_30cxx = 30.30; 00561 $rec1->long_str_columnname_with_30cxx = '30'; 00562 00563 // insert_record() 00564 $rec1->id = $DB->insert_record($tablename, $rec1); 00565 $this->assertEqual($rec1, $DB->get_record($tablename, array('id' => $rec1->id))); 00566 00567 // update_record() 00568 $DB->update_record($tablename, $rec1); 00569 $this->assertEqual($rec1, $DB->get_record($tablename, array('id' => $rec1->id))); 00570 00571 // set_field() 00572 $rec1->long_int_columnname_with_28c = 280; 00573 $DB->set_field($tablename, 'long_int_columnname_with_28c', $rec1->long_int_columnname_with_28c, 00574 array('id' => $rec1->id, 'long_int_columnname_with_28c' => 28)); 00575 $rec1->long_dec_columnname_with_28c = 280.28; 00576 $DB->set_field($tablename, 'long_dec_columnname_with_28c', $rec1->long_dec_columnname_with_28c, 00577 array('id' => $rec1->id, 'long_dec_columnname_with_28c' => 28.28)); 00578 $rec1->long_str_columnname_with_28c = '280'; 00579 $DB->set_field($tablename, 'long_str_columnname_with_28c', $rec1->long_str_columnname_with_28c, 00580 array('id' => $rec1->id, 'long_str_columnname_with_28c' => '28')); 00581 $rec1->long_int_columnname_with_30cxx = 300; 00582 $DB->set_field($tablename, 'long_int_columnname_with_30cxx', $rec1->long_int_columnname_with_30cxx, 00583 array('id' => $rec1->id, 'long_int_columnname_with_30cxx' => 30)); 00584 $rec1->long_dec_columnname_with_30cxx = 300.30; 00585 $DB->set_field($tablename, 'long_dec_columnname_with_30cxx', $rec1->long_dec_columnname_with_30cxx, 00586 array('id' => $rec1->id, 'long_dec_columnname_with_30cxx' => 30.30)); 00587 $rec1->long_str_columnname_with_30cxx = '300'; 00588 $DB->set_field($tablename, 'long_str_columnname_with_30cxx', $rec1->long_str_columnname_with_30cxx, 00589 array('id' => $rec1->id, 'long_str_columnname_with_30cxx' => '30')); 00590 $this->assertEqual($rec1, $DB->get_record($tablename, array('id' => $rec1->id))); 00591 00592 // delete_records() 00593 $rec2 = $DB->get_record($tablename, array('id' => $rec1->id)); 00594 $rec2->id = $DB->insert_record($tablename, $rec2); 00595 $this->assertEqual(2, $DB->count_records($tablename)); 00596 $DB->delete_records($tablename, (array) $rec2); 00597 $this->assertEqual(1, $DB->count_records($tablename)); 00598 00599 // get_recordset() 00600 $rs = $DB->get_recordset($tablename, (array) $rec1); 00601 $iterations = 0; 00602 foreach ($rs as $rec2) { 00603 $iterations++; 00604 } 00605 $rs->close(); 00606 $this->assertEqual(1, $iterations); 00607 $this->assertEqual($rec1, $rec2); 00608 00609 // get_records() 00610 $recs = $DB->get_records($tablename, (array) $rec1); 00611 $this->assertEqual(1, count($recs)); 00612 $this->assertEqual($rec1, reset($recs)); 00613 00614 // get_fieldset_select() 00615 $select = 'id = :id AND 00616 long_int_columnname_with_28c = :long_int_columnname_with_28c AND 00617 long_dec_columnname_with_28c = :long_dec_columnname_with_28c AND 00618 long_str_columnname_with_28c = :long_str_columnname_with_28c AND 00619 long_int_columnname_with_30cxx = :long_int_columnname_with_30cxx AND 00620 long_dec_columnname_with_30cxx = :long_dec_columnname_with_30cxx AND 00621 long_str_columnname_with_30cxx = :long_str_columnname_with_30cxx'; 00622 $fields = $DB->get_fieldset_select($tablename, 'long_int_columnname_with_28c', $select, (array)$rec1); 00623 $this->assertEqual(1, count($fields)); 00624 $this->assertEqual($rec1->long_int_columnname_with_28c, reset($fields)); 00625 $fields = $DB->get_fieldset_select($tablename, 'long_dec_columnname_with_28c', $select, (array)$rec1); 00626 $this->assertEqual($rec1->long_dec_columnname_with_28c, reset($fields)); 00627 $fields = $DB->get_fieldset_select($tablename, 'long_str_columnname_with_28c', $select, (array)$rec1); 00628 $this->assertEqual($rec1->long_str_columnname_with_28c, reset($fields)); 00629 $fields = $DB->get_fieldset_select($tablename, 'long_int_columnname_with_30cxx', $select, (array)$rec1); 00630 $this->assertEqual($rec1->long_int_columnname_with_30cxx, reset($fields)); 00631 $fields = $DB->get_fieldset_select($tablename, 'long_dec_columnname_with_30cxx', $select, (array)$rec1); 00632 $this->assertEqual($rec1->long_dec_columnname_with_30cxx, reset($fields)); 00633 $fields = $DB->get_fieldset_select($tablename, 'long_str_columnname_with_30cxx', $select, (array)$rec1); 00634 $this->assertEqual($rec1->long_str_columnname_with_30cxx, reset($fields)); 00635 00636 // overlapping placeholders (progressive str_replace) 00637 $overlapselect = 'id = :p AND 00638 long_int_columnname_with_28c = :param1 AND 00639 long_dec_columnname_with_28c = :param2 AND 00640 long_str_columnname_with_28c = :param_with_29_characters_long AND 00641 long_int_columnname_with_30cxx = :param_with_30_characters_long_ AND 00642 long_dec_columnname_with_30cxx = :param_ AND 00643 long_str_columnname_with_30cxx = :param__'; 00644 $overlapparams = array( 00645 'p' => $rec1->id, 00646 'param1' => $rec1->long_int_columnname_with_28c, 00647 'param2' => $rec1->long_dec_columnname_with_28c, 00648 'param_with_29_characters_long' => $rec1->long_str_columnname_with_28c, 00649 'param_with_30_characters_long_' => $rec1->long_int_columnname_with_30cxx, 00650 'param_' => $rec1->long_dec_columnname_with_30cxx, 00651 'param__' => $rec1->long_str_columnname_with_30cxx); 00652 $recs = $DB->get_records_select($tablename, $overlapselect, $overlapparams); 00653 $this->assertEqual(1, count($recs)); 00654 $this->assertEqual($rec1, reset($recs)); 00655 00656 // execute() 00657 $DB->execute("DELETE FROM {{$tablename}} WHERE $select", (array)$rec1); 00658 $this->assertEqual(0, $DB->count_records($tablename)); 00659 } 00660 00661 public function test_get_tables() { 00662 $DB = $this->tdb; 00663 $dbman = $this->tdb->get_manager(); 00664 00665 // Need to test with multiple DBs 00666 $table = $this->get_test_table(); 00667 $tablename = $table->getName(); 00668 00669 $original_count = count($DB->get_tables()); 00670 00671 $table->add_field('id', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, XMLDB_SEQUENCE, null); 00672 $table->add_key('primary', XMLDB_KEY_PRIMARY, array('id')); 00673 00674 $dbman->create_table($table); 00675 $this->assertTrue(count($DB->get_tables()) == $original_count + 1); 00676 00677 $dbman->drop_table($table); 00678 $this->assertTrue(count($DB->get_tables()) == $original_count); 00679 } 00680 00681 public function test_get_indexes() { 00682 $DB = $this->tdb; 00683 $dbman = $this->tdb->get_manager(); 00684 00685 $table = $this->get_test_table(); 00686 $tablename = $table->getName(); 00687 00688 $table->add_field('id', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, XMLDB_SEQUENCE, null); 00689 $table->add_field('course', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '0'); 00690 $table->add_key('primary', XMLDB_KEY_PRIMARY, array('id')); 00691 $table->add_index('course', XMLDB_INDEX_NOTUNIQUE, array('course')); 00692 $table->add_index('course-id', XMLDB_INDEX_UNIQUE, array('course', 'id')); 00693 $dbman->create_table($table); 00694 00695 $indices = $DB->get_indexes($tablename); 00696 $this->assertTrue(is_array($indices)); 00697 $this->assertEqual(count($indices), 2); 00698 // we do not care about index names for now 00699 $first = array_shift($indices); 00700 $second = array_shift($indices); 00701 if (count($first['columns']) == 2) { 00702 $composed = $first; 00703 $single = $second; 00704 } else { 00705 $composed = $second; 00706 $single = $first; 00707 } 00708 $this->assertFalse($single['unique']); 00709 $this->assertTrue($composed['unique']); 00710 $this->assertEqual(1, count($single['columns'])); 00711 $this->assertEqual(2, count($composed['columns'])); 00712 $this->assertEqual('course', $single['columns'][0]); 00713 $this->assertEqual('course', $composed['columns'][0]); 00714 $this->assertEqual('id', $composed['columns'][1]); 00715 } 00716 00717 public function test_get_columns() { 00718 $DB = $this->tdb; 00719 $dbman = $this->tdb->get_manager(); 00720 00721 $table = $this->get_test_table(); 00722 $tablename = $table->getName(); 00723 00724 $table->add_field('id', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, XMLDB_SEQUENCE, null); 00725 $table->add_field('course', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '0'); 00726 $table->add_field('name', XMLDB_TYPE_CHAR, '255', null, null, null, 'lala'); 00727 $table->add_field('description', XMLDB_TYPE_TEXT, 'small', null, null, null, null); 00728 $table->add_field('enumfield', XMLDB_TYPE_CHAR, '255', null, XMLDB_NOTNULL, null, 'test2'); 00729 $table->add_field('onenum', XMLDB_TYPE_NUMBER, '10,2', null, null, null, 200); 00730 $table->add_field('onefloat', XMLDB_TYPE_FLOAT, '10,2', null, null, null, 300); 00731 $table->add_field('anotherfloat', XMLDB_TYPE_FLOAT, null, null, null, null, 400); 00732 $table->add_field('negativedfltint', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, '-1'); 00733 $table->add_field('negativedfltnumber', XMLDB_TYPE_NUMBER, '10', null, XMLDB_NOTNULL, null, '-2'); 00734 $table->add_field('negativedfltfloat', XMLDB_TYPE_FLOAT, '10', null, XMLDB_NOTNULL, null, '-3'); 00735 $table->add_key('primary', XMLDB_KEY_PRIMARY, array('id')); 00736 $dbman->create_table($table); 00737 00738 $columns = $DB->get_columns($tablename); 00739 $this->assertTrue(is_array($columns)); 00740 00741 $fields = $table->getFields(); 00742 $this->assertEqual(count($columns), count($fields)); 00743 00744 $field = $columns['id']; 00745 $this->assertEqual('R', $field->meta_type); 00746 $this->assertTrue($field->auto_increment); 00747 $this->assertTrue($field->unique); 00748 00749 $field = $columns['course']; 00750 $this->assertEqual('I', $field->meta_type); 00751 $this->assertFalse($field->auto_increment); 00752 $this->assertTrue($field->has_default); 00753 $this->assertEqual(0, $field->default_value); 00754 $this->assertTrue($field->not_null); 00755 00756 $field = $columns['name']; 00757 $this->assertEqual('C', $field->meta_type); 00758 $this->assertFalse($field->auto_increment); 00759 $this->assertEqual(255, $field->max_length); 00760 $this->assertTrue($field->has_default); 00761 $this->assertIdentical('lala', $field->default_value); 00762 $this->assertFalse($field->not_null); 00763 00764 $field = $columns['description']; 00765 $this->assertEqual('X', $field->meta_type); 00766 $this->assertFalse($field->auto_increment); 00767 $this->assertFalse($field->has_default); 00768 $this->assertIdentical(null, $field->default_value); 00769 $this->assertFalse($field->not_null); 00770 00771 $field = $columns['enumfield']; 00772 $this->assertEqual('C', $field->meta_type); 00773 $this->assertFalse($field->auto_increment); 00774 $this->assertIdentical('test2', $field->default_value); 00775 $this->assertTrue($field->not_null); 00776 00777 $field = $columns['onenum']; 00778 $this->assertEqual('N', $field->meta_type); 00779 $this->assertFalse($field->auto_increment); 00780 $this->assertEqual(10, $field->max_length); 00781 $this->assertEqual(2, $field->scale); 00782 $this->assertTrue($field->has_default); 00783 $this->assertEqual(200.0, $field->default_value); 00784 $this->assertFalse($field->not_null); 00785 00786 $field = $columns['onefloat']; 00787 $this->assertEqual('N', $field->meta_type); 00788 $this->assertFalse($field->auto_increment); 00789 $this->assertTrue($field->has_default); 00790 $this->assertEqual(300.0, $field->default_value); 00791 $this->assertFalse($field->not_null); 00792 00793 $field = $columns['anotherfloat']; 00794 $this->assertEqual('N', $field->meta_type); 00795 $this->assertFalse($field->auto_increment); 00796 $this->assertTrue($field->has_default); 00797 $this->assertEqual(400.0, $field->default_value); 00798 $this->assertFalse($field->not_null); 00799 00800 // Test negative defaults in numerical columns 00801 $field = $columns['negativedfltint']; 00802 $this->assertTrue($field->has_default); 00803 $this->assertEqual(-1, $field->default_value); 00804 00805 $field = $columns['negativedfltnumber']; 00806 $this->assertTrue($field->has_default); 00807 $this->assertEqual(-2, $field->default_value); 00808 00809 $field = $columns['negativedfltfloat']; 00810 $this->assertTrue($field->has_default); 00811 $this->assertEqual(-3, $field->default_value); 00812 00813 for ($i = 0; $i < count($columns); $i++) { 00814 if ($i == 0) { 00815 $next_column = reset($columns); 00816 $next_field = reset($fields); 00817 } else { 00818 $next_column = next($columns); 00819 $next_field = next($fields); 00820 } 00821 00822 $this->assertEqual($next_column->name, $next_field->name); 00823 } 00824 00825 // Test get_columns for non-existing table returns empty array. MDL-30147 00826 $columns = $DB->get_columns('xxxx'); 00827 $this->assertEqual(array(), $columns); 00828 } 00829 00830 public function test_get_manager() { 00831 $DB = $this->tdb; 00832 $dbman = $this->tdb->get_manager(); 00833 00834 $this->assertTrue($dbman instanceof database_manager); 00835 } 00836 00837 public function test_setup_is_unicodedb() { 00838 $DB = $this->tdb; 00839 $this->assertTrue($DB->setup_is_unicodedb()); 00840 } 00841 00842 public function test_set_debug() { //tests get_debug() too 00843 $DB = $this->tdb; 00844 $dbman = $this->tdb->get_manager(); 00845 00846 $table = $this->get_test_table(); 00847 $tablename = $table->getName(); 00848 00849 $table->add_field('id', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, XMLDB_SEQUENCE, null); 00850 $table->add_field('course', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '0'); 00851 $table->add_key('primary', XMLDB_KEY_PRIMARY, array('id')); 00852 $dbman->create_table($table); 00853 00854 $sql = "SELECT * FROM {{$tablename}}"; 00855 00856 $prevdebug = $DB->get_debug(); 00857 00858 ob_start(); 00859 $DB->set_debug(true); 00860 $this->assertTrue($DB->get_debug()); 00861 $DB->execute($sql); 00862 $DB->set_debug(false); 00863 $this->assertFalse($DB->get_debug()); 00864 $debuginfo = ob_get_contents(); 00865 ob_end_clean(); 00866 $this->assertFalse($debuginfo === ''); 00867 00868 ob_start(); 00869 $DB->execute($sql); 00870 $debuginfo = ob_get_contents(); 00871 ob_end_clean(); 00872 $this->assertTrue($debuginfo === ''); 00873 00874 $DB->set_debug($prevdebug); 00875 } 00876 00877 public function test_execute() { 00878 $DB = $this->tdb; 00879 $dbman = $this->tdb->get_manager(); 00880 00881 $table1 = $this->get_test_table('1'); 00882 $tablename1 = $table1->getName(); 00883 $table1->add_field('id', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, XMLDB_SEQUENCE, null); 00884 $table1->add_field('course', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '0'); 00885 $table1->add_field('name', XMLDB_TYPE_CHAR, '255', null, null, null, '0'); 00886 $table1->add_index('course', XMLDB_INDEX_NOTUNIQUE, array('course')); 00887 $table1->add_key('primary', XMLDB_KEY_PRIMARY, array('id')); 00888 $dbman->create_table($table1); 00889 00890 $table2 = $this->get_test_table('2'); 00891 $tablename2 = $table2->getName(); 00892 $table2->add_field('id', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, XMLDB_SEQUENCE, null); 00893 $table2->add_field('course', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '0'); 00894 $table2->add_key('primary', XMLDB_KEY_PRIMARY, array('id')); 00895 $dbman->create_table($table2); 00896 00897 $DB->insert_record($tablename1, array('course' => 3, 'name' => 'aaa')); 00898 $DB->insert_record($tablename1, array('course' => 1, 'name' => 'bbb')); 00899 $DB->insert_record($tablename1, array('course' => 7, 'name' => 'ccc')); 00900 $DB->insert_record($tablename1, array('course' => 3, 'name' => 'ddd')); 00901 00902 // select results are ignored 00903 $sql = "SELECT * FROM {{$tablename1}} WHERE course = :course"; 00904 $this->assertTrue($DB->execute($sql, array('course'=>3))); 00905 00906 // throw exception on error 00907 $sql = "XXUPDATE SET XSSD"; 00908 try { 00909 $DB->execute($sql); 00910 $this->fail("Expecting an exception, none occurred"); 00911 } catch (Exception $e) { 00912 $this->assertTrue($e instanceof dml_exception); 00913 } 00914 00915 // update records 00916 $sql = "UPDATE {{$tablename1}} 00917 SET course = 6 00918 WHERE course = ?"; 00919 $this->assertTrue($DB->execute($sql, array('3'))); 00920 $this->assertEqual($DB->count_records($tablename1, array('course' => 6)), 2); 00921 00922 // update records with subquery condition 00923 // confirm that the option not using table aliases is cross-db 00924 $sql = "UPDATE {{$tablename1}} 00925 SET course = 0 00926 WHERE NOT EXISTS ( 00927 SELECT course 00928 FROM {{$tablename2}} tbl2 00929 WHERE tbl2.course = {{$tablename1}}.course 00930 AND 1 = 0)"; // Really we don't update anything, but verify the syntax is allowed 00931 $this->assertTrue($DB->execute($sql)); 00932 00933 // insert from one into second table 00934 $sql = "INSERT INTO {{$tablename2}} (course) 00935 00936 SELECT course 00937 FROM {{$tablename1}}"; 00938 $this->assertTrue($DB->execute($sql)); 00939 $this->assertEqual($DB->count_records($tablename2), 4); 00940 } 00941 00942 public function test_get_recordset() { 00943 $DB = $this->tdb; 00944 $dbman = $DB->get_manager(); 00945 00946 $table = $this->get_test_table(); 00947 $tablename = $table->getName(); 00948 00949 $table->add_field('id', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, XMLDB_SEQUENCE, null); 00950 $table->add_field('course', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '0'); 00951 $table->add_field('name', XMLDB_TYPE_CHAR, '255', null, null, null, '0'); 00952 $table->add_field('onetext', XMLDB_TYPE_TEXT, 'big', null, null, null); 00953 $table->add_index('course', XMLDB_INDEX_NOTUNIQUE, array('course')); 00954 $table->add_key('primary', XMLDB_KEY_PRIMARY, array('id')); 00955 $dbman->create_table($table); 00956 00957 $data = array(array('id' => 1, 'course' => 3, 'name' => 'record1', 'onetext'=>'abc'), 00958 array('id' => 2, 'course' => 3, 'name' => 'record2', 'onetext'=>'abcd'), 00959 array('id' => 3, 'course' => 5, 'name' => 'record3', 'onetext'=>'abcde')); 00960 00961 foreach ($data as $record) { 00962 $DB->insert_record($tablename, $record); 00963 } 00964 00965 // standard recordset iteration 00966 $rs = $DB->get_recordset($tablename); 00967 $this->assertTrue($rs instanceof moodle_recordset); 00968 reset($data); 00969 foreach($rs as $record) { 00970 $data_record = current($data); 00971 foreach ($record as $k => $v) { 00972 $this->assertEqual($data_record[$k], $v); 00973 } 00974 next($data); 00975 } 00976 $rs->close(); 00977 00978 // iterator style usage 00979 $rs = $DB->get_recordset($tablename); 00980 $this->assertTrue($rs instanceof moodle_recordset); 00981 reset($data); 00982 while ($rs->valid()) { 00983 $record = $rs->current(); 00984 $data_record = current($data); 00985 foreach ($record as $k => $v) { 00986 $this->assertEqual($data_record[$k], $v); 00987 } 00988 next($data); 00989 $rs->next(); 00990 } 00991 $rs->close(); 00992 00993 // make sure rewind is ignored 00994 $rs = $DB->get_recordset($tablename); 00995 $this->assertTrue($rs instanceof moodle_recordset); 00996 reset($data); 00997 $i = 0; 00998 foreach($rs as $record) { 00999 $i++; 01000 $rs->rewind(); 01001 if ($i > 10) { 01002 $this->fail('revind not ignored in recordsets'); 01003 break; 01004 } 01005 $data_record = current($data); 01006 foreach ($record as $k => $v) { 01007 $this->assertEqual($data_record[$k], $v); 01008 } 01009 next($data); 01010 } 01011 $rs->close(); 01012 01013 // test for exception throwing on text conditions being compared. (MDL-24863, unwanted auto conversion of param to int) 01014 $conditions = array('onetext' => '1'); 01015 try { 01016 $rs = $DB->get_recordset($tablename, $conditions); 01017 if (debugging()) { 01018 // only in debug mode - hopefully all devs test code in debug mode... 01019 $this->fail('An Exception is missing, expected due to equating of text fields'); 01020 } 01021 } catch (exception $e) { 01022 $this->assertTrue($e instanceof dml_exception); 01023 $this->assertEqual($e->errorcode, 'textconditionsnotallowed'); 01024 } 01025 01026 // notes: 01027 // * limits are tested in test_get_recordset_sql() 01028 // * where_clause() is used internally and is tested in test_get_records() 01029 } 01030 01031 public function test_get_recordset_iterator_keys() { 01032 $DB = $this->tdb; 01033 $dbman = $DB->get_manager(); 01034 01035 $table = $this->get_test_table(); 01036 $tablename = $table->getName(); 01037 01038 $table->add_field('id', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, XMLDB_SEQUENCE, null); 01039 $table->add_field('course', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '0'); 01040 $table->add_field('name', XMLDB_TYPE_CHAR, '255', null, null, null, '0'); 01041 $table->add_index('course', XMLDB_INDEX_NOTUNIQUE, array('course')); 01042 $table->add_key('primary', XMLDB_KEY_PRIMARY, array('id')); 01043 $dbman->create_table($table); 01044 01045 $data = array(array('id'=> 1, 'course' => 3, 'name' => 'record1'), 01046 array('id'=> 2, 'course' => 3, 'name' => 'record2'), 01047 array('id'=> 3, 'course' => 5, 'name' => 'record3')); 01048 foreach ($data as $record) { 01049 $DB->insert_record($tablename, $record); 01050 } 01051 01052 // Test repeated numeric keys are returned ok 01053 $rs = $DB->get_recordset($tablename, NULL, NULL, 'course, name, id'); 01054 01055 reset($data); 01056 $count = 0; 01057 foreach($rs as $key => $record) { 01058 $data_record = current($data); 01059 $this->assertEqual($data_record['course'], $key); 01060 next($data); 01061 $count++; 01062 } 01063 $rs->close(); 01064 $this->assertEqual($count, 3); 01065 01066 // Test string keys are returned ok 01067 $rs = $DB->get_recordset($tablename, NULL, NULL, 'name, course, id'); 01068 01069 reset($data); 01070 $count = 0; 01071 foreach($rs as $key => $record) { 01072 $data_record = current($data); 01073 $this->assertEqual($data_record['name'], $key); 01074 next($data); 01075 $count++; 01076 } 01077 $rs->close(); 01078 $this->assertEqual($count, 3); 01079 01080 // Test numeric not starting in 1 keys are returned ok 01081 $rs = $DB->get_recordset($tablename, NULL, 'id DESC', 'id, course, name'); 01082 01083 $data = array_reverse($data); 01084 reset($data); 01085 $count = 0; 01086 foreach($rs as $key => $record) { 01087 $data_record = current($data); 01088 $this->assertEqual($data_record['id'], $key); 01089 next($data); 01090 $count++; 01091 } 01092 $rs->close(); 01093 $this->assertEqual($count, 3); 01094 } 01095 01096 public function test_get_recordset_list() { 01097 $DB = $this->tdb; 01098 $dbman = $DB->get_manager(); 01099 01100 $table = $this->get_test_table(); 01101 $tablename = $table->getName(); 01102 01103 $table->add_field('id', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, XMLDB_SEQUENCE, null); 01104 $table->add_field('course', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '0'); 01105 $table->add_index('course', XMLDB_INDEX_NOTUNIQUE, array('course')); 01106 $table->add_key('primary', XMLDB_KEY_PRIMARY, array('id')); 01107 $dbman->create_table($table); 01108 01109 $DB->insert_record($tablename, array('course' => 3)); 01110 $DB->insert_record($tablename, array('course' => 3)); 01111 $DB->insert_record($tablename, array('course' => 5)); 01112 $DB->insert_record($tablename, array('course' => 2)); 01113 01114 $rs = $DB->get_recordset_list($tablename, 'course', array(3, 2)); 01115 01116 $counter = 0; 01117 foreach ($rs as $record) { 01118 $counter++; 01119 } 01120 $this->assertEqual(3, $counter); 01121 $rs->close(); 01122 01123 $rs = $DB->get_recordset_list($tablename, 'course',array()); 01124 01125 $counter = 0; 01126 foreach ($rs as $record) { 01127 $counter++; 01128 } 01129 $rs->close(); 01130 $this->assertEqual(0, $counter); 01131 01132 // notes: 01133 // * limits are tested in test_get_recordset_sql() 01134 // * where_clause() is used internally and is tested in test_get_records() 01135 } 01136 01137 public function test_get_recordset_select() { 01138 $DB = $this->tdb; 01139 $dbman = $DB->get_manager(); 01140 01141 $table = $this->get_test_table(); 01142 $tablename = $table->getName(); 01143 01144 $table->add_field('id', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, XMLDB_SEQUENCE, null); 01145 $table->add_field('course', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '0'); 01146 $table->add_key('primary', XMLDB_KEY_PRIMARY, array('id')); 01147 $dbman->create_table($table); 01148 01149 $DB->insert_record($tablename, array('course' => 3)); 01150 $DB->insert_record($tablename, array('course' => 3)); 01151 $DB->insert_record($tablename, array('course' => 5)); 01152 $DB->insert_record($tablename, array('course' => 2)); 01153 01154 $rs = $DB->get_recordset_select($tablename, ''); 01155 $counter = 0; 01156 foreach ($rs as $record) { 01157 $counter++; 01158 } 01159 $rs->close(); 01160 $this->assertEqual(4, $counter); 01161 01162 $this->assertTrue($rs = $DB->get_recordset_select($tablename, 'course = 3')); 01163 $counter = 0; 01164 foreach ($rs as $record) { 01165 $counter++; 01166 } 01167 $rs->close(); 01168 $this->assertEqual(2, $counter); 01169 01170 // notes: 01171 // * limits are tested in test_get_recordset_sql() 01172 } 01173 01174 public function test_get_recordset_sql() { 01175 $DB = $this->tdb; 01176 $dbman = $DB->get_manager(); 01177 01178 $table = $this->get_test_table(); 01179 $tablename = $table->getName(); 01180 01181 $table->add_field('id', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, XMLDB_SEQUENCE, null); 01182 $table->add_field('course', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '0'); 01183 $table->add_key('primary', XMLDB_KEY_PRIMARY, array('id')); 01184 $dbman->create_table($table); 01185 01186 $inskey1 = $DB->insert_record($tablename, array('course' => 3)); 01187 $inskey2 = $DB->insert_record($tablename, array('course' => 5)); 01188 $inskey3 = $DB->insert_record($tablename, array('course' => 4)); 01189 $inskey4 = $DB->insert_record($tablename, array('course' => 3)); 01190 $inskey5 = $DB->insert_record($tablename, array('course' => 2)); 01191 $inskey6 = $DB->insert_record($tablename, array('course' => 1)); 01192 $inskey7 = $DB->insert_record($tablename, array('course' => 0)); 01193 01194 $rs = $DB->get_recordset_sql("SELECT * FROM {{$tablename}} WHERE course = ?", array(3)); 01195 $counter = 0; 01196 foreach ($rs as $record) { 01197 $counter++; 01198 } 01199 $rs->close(); 01200 $this->assertEqual(2, $counter); 01201 01202 // limits - only need to test this case, the rest have been tested by test_get_records_sql() 01203 // only limitfrom = skips that number of records 01204 $rs = $DB->get_recordset_sql("SELECT * FROM {{$tablename}} ORDER BY id", null, 2, 0); 01205 $records = array(); 01206 foreach($rs as $key => $record) { 01207 $records[$key] = $record; 01208 } 01209 $rs->close(); 01210 $this->assertEqual(5, count($records)); 01211 $this->assertEqual($inskey3, reset($records)->id); 01212 $this->assertEqual($inskey7, end($records)->id); 01213 01214 // note: fetching nulls, empties, LOBs already tested by test_insert_record() no needed here 01215 } 01216 01217 public function test_get_records() { 01218 $DB = $this->tdb; 01219 $dbman = $DB->get_manager(); 01220 01221 $table = $this->get_test_table(); 01222 $tablename = $table->getName(); 01223 01224 $table->add_field('id', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, XMLDB_SEQUENCE, null); 01225 $table->add_field('course', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '0'); 01226 $table->add_field('onetext', XMLDB_TYPE_TEXT, 'big', null, null, null); 01227 $table->add_key('primary', XMLDB_KEY_PRIMARY, array('id')); 01228 $dbman->create_table($table); 01229 01230 $DB->insert_record($tablename, array('course' => 3)); 01231 $DB->insert_record($tablename, array('course' => 3)); 01232 $DB->insert_record($tablename, array('course' => 5)); 01233 $DB->insert_record($tablename, array('course' => 2)); 01234 01235 // All records 01236 $records = $DB->get_records($tablename); 01237 $this->assertEqual(4, count($records)); 01238 $this->assertEqual(3, $records[1]->course); 01239 $this->assertEqual(3, $records[2]->course); 01240 $this->assertEqual(5, $records[3]->course); 01241 $this->assertEqual(2, $records[4]->course); 01242 01243 // Records matching certain conditions 01244 $records = $DB->get_records($tablename, array('course' => 3)); 01245 $this->assertEqual(2, count($records)); 01246 $this->assertEqual(3, $records[1]->course); 01247 $this->assertEqual(3, $records[2]->course); 01248 01249 // All records sorted by course 01250 $records = $DB->get_records($tablename, null, 'course'); 01251 $this->assertEqual(4, count($records)); 01252 $current_record = reset($records); 01253 $this->assertEqual(4, $current_record->id); 01254 $current_record = next($records); 01255 $this->assertEqual(1, $current_record->id); 01256 $current_record = next($records); 01257 $this->assertEqual(2, $current_record->id); 01258 $current_record = next($records); 01259 $this->assertEqual(3, $current_record->id); 01260 01261 // All records, but get only one field 01262 $records = $DB->get_records($tablename, null, '', 'id'); 01263 $this->assertFalse(isset($records[1]->course)); 01264 $this->assertTrue(isset($records[1]->id)); 01265 $this->assertEqual(4, count($records)); 01266 01267 // Booleans into params 01268 $records = $DB->get_records($tablename, array('course' => true)); 01269 $this->assertEqual(0, count($records)); 01270 $records = $DB->get_records($tablename, array('course' => false)); 01271 $this->assertEqual(0, count($records)); 01272 01273 // test for exception throwing on text conditions being compared. (MDL-24863, unwanted auto conversion of param to int) 01274 $conditions = array('onetext' => '1'); 01275 try { 01276 $records = $DB->get_records($tablename, $conditions); 01277 if (debugging()) { 01278 // only in debug mode - hopefully all devs test code in debug mode... 01279 $this->fail('An Exception is missing, expected due to equating of text fields'); 01280 } 01281 } catch (exception $e) { 01282 $this->assertTrue($e instanceof dml_exception); 01283 $this->assertEqual($e->errorcode, 'textconditionsnotallowed'); 01284 } 01285 01286 // test get_records passing non-existing table 01287 // with params 01288 try { 01289 $records = $DB->get_records('xxxx', array('id' => 0)); 01290 $this->fail('An Exception is missing, expected due to query against non-existing table'); 01291 } catch (exception $e) { 01292 $this->assertTrue($e instanceof dml_exception); 01293 if (debugging()) { 01294 // information for developers only, normal users get general error message 01295 $this->assertEqual($e->errorcode, 'ddltablenotexist'); 01296 } 01297 } 01298 // and without params 01299 try { 01300 $records = $DB->get_records('xxxx', array()); 01301 $this->fail('An Exception is missing, expected due to query against non-existing table'); 01302 } catch (exception $e) { 01303 $this->assertTrue($e instanceof dml_exception); 01304 if (debugging()) { 01305 // information for developers only, normal users get general error message 01306 $this->assertEqual($e->errorcode, 'ddltablenotexist'); 01307 } 01308 } 01309 01310 // test get_records passing non-existing column 01311 try { 01312 $records = $DB->get_records($tablename, array('xxxx' => 0)); 01313 $this->fail('An Exception is missing, expected due to query against non-existing column'); 01314 } catch (exception $e) { 01315 $this->assertTrue($e instanceof dml_exception); 01316 if (debugging()) { 01317 // information for developers only, normal users get general error message 01318 $this->assertEqual($e->errorcode, 'ddlfieldnotexist'); 01319 } 01320 } 01321 01322 // note: delegate limits testing to test_get_records_sql() 01323 } 01324 01325 public function test_get_records_list() { 01326 $DB = $this->tdb; 01327 $dbman = $DB->get_manager(); 01328 01329 $table = $this->get_test_table(); 01330 $tablename = $table->getName(); 01331 01332 $table->add_field('id', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, XMLDB_SEQUENCE, null); 01333 $table->add_field('course', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '0'); 01334 $table->add_key('primary', XMLDB_KEY_PRIMARY, array('id')); 01335 $dbman->create_table($table); 01336 01337 $DB->insert_record($tablename, array('course' => 3)); 01338 $DB->insert_record($tablename, array('course' => 3)); 01339 $DB->insert_record($tablename, array('course' => 5)); 01340 $DB->insert_record($tablename, array('course' => 2)); 01341 01342 $records = $DB->get_records_list($tablename, 'course', array(3, 2)); 01343 $this->assertTrue(is_array($records)); 01344 $this->assertEqual(3, count($records)); 01345 $this->assertEqual(1, reset($records)->id); 01346 $this->assertEqual(2, next($records)->id); 01347 $this->assertEqual(4, next($records)->id); 01348 01349 $this->assertIdentical(array(), $records = $DB->get_records_list($tablename, 'course', array())); 01350 $this->assertEqual(0, count($records)); 01351 01352 // note: delegate limits testing to test_get_records_sql() 01353 } 01354 01355 public function test_get_records_sql() { 01356 $DB = $this->tdb; 01357 $dbman = $DB->get_manager(); 01358 01359 $table = $this->get_test_table(); 01360 $tablename = $table->getName(); 01361 01362 $table->add_field('id', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, XMLDB_SEQUENCE, null); 01363 $table->add_field('course', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '0'); 01364 $table->add_key('primary', XMLDB_KEY_PRIMARY, array('id')); 01365 $dbman->create_table($table); 01366 01367 $inskey1 = $DB->insert_record($tablename, array('course' => 3)); 01368 $inskey2 = $DB->insert_record($tablename, array('course' => 5)); 01369 $inskey3 = $DB->insert_record($tablename, array('course' => 4)); 01370 $inskey4 = $DB->insert_record($tablename, array('course' => 3)); 01371 $inskey5 = $DB->insert_record($tablename, array('course' => 2)); 01372 $inskey6 = $DB->insert_record($tablename, array('course' => 1)); 01373 $inskey7 = $DB->insert_record($tablename, array('course' => 0)); 01374 01375 $table2 = $this->get_test_table("2"); 01376 $tablename2 = $table2->getName(); 01377 $table2->add_field('id', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, XMLDB_SEQUENCE, null); 01378 $table2->add_field('course', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '0'); 01379 $table2->add_field('nametext', XMLDB_TYPE_TEXT, 'small', null, null, null, null); 01380 $table2->add_key('primary', XMLDB_KEY_PRIMARY, array('id')); 01381 $dbman->create_table($table2); 01382 01383 $DB->insert_record($tablename2, array('course'=>3, 'nametext'=>'badabing')); 01384 $DB->insert_record($tablename2, array('course'=>4, 'nametext'=>'badabang')); 01385 $DB->insert_record($tablename2, array('course'=>5, 'nametext'=>'badabung')); 01386 $DB->insert_record($tablename2, array('course'=>6, 'nametext'=>'badabong')); 01387 01388 $records = $DB->get_records_sql("SELECT * FROM {{$tablename}} WHERE course = ?", array(3)); 01389 $this->assertEqual(2, count($records)); 01390 $this->assertEqual($inskey1, reset($records)->id); 01391 $this->assertEqual($inskey4, next($records)->id); 01392 01393 // Awful test, requires debug enabled and sent to browser. Let's do that and restore after test 01394 $this->enable_debugging(); 01395 $records = $DB->get_records_sql("SELECT course AS id, course AS course FROM {{$tablename}}", null); 01396 $this->assertFalse($this->get_debugging() === ''); 01397 $this->assertEqual(6, count($records)); 01398 01399 // negative limits = no limits 01400 $records = $DB->get_records_sql("SELECT * FROM {{$tablename}} ORDER BY id", null, -1, -1); 01401 $this->assertEqual(7, count($records)); 01402 01403 // zero limits = no limits 01404 $records = $DB->get_records_sql("SELECT * FROM {{$tablename}} ORDER BY id", null, 0, 0); 01405 $this->assertEqual(7, count($records)); 01406 01407 // only limitfrom = skips that number of records 01408 $records = $DB->get_records_sql("SELECT * FROM {{$tablename}} ORDER BY id", null, 2, 0); 01409 $this->assertEqual(5, count($records)); 01410 $this->assertEqual($inskey3, reset($records)->id); 01411 $this->assertEqual($inskey7, end($records)->id); 01412 01413 // only limitnum = fetches that number of records 01414 $records = $DB->get_records_sql("SELECT * FROM {{$tablename}} ORDER BY id", null, 0, 3); 01415 $this->assertEqual(3, count($records)); 01416 $this->assertEqual($inskey1, reset($records)->id); 01417 $this->assertEqual($inskey3, end($records)->id); 01418 01419 // both limitfrom and limitnum = skips limitfrom records and fetches limitnum ones 01420 $records = $DB->get_records_sql("SELECT * FROM {{$tablename}} ORDER BY id", null, 3, 2); 01421 $this->assertEqual(2, count($records)); 01422 $this->assertEqual($inskey4, reset($records)->id); 01423 $this->assertEqual($inskey5, end($records)->id); 01424 01425 // both limitfrom and limitnum in query having subqueris 01426 // note the subquery skips records with course = 0 and 3 01427 $sql = "SELECT * FROM {{$tablename}} 01428 WHERE course NOT IN ( 01429 SELECT course FROM {{$tablename}} 01430 WHERE course IN (0, 3)) 01431 ORDER BY course"; 01432 $records = $DB->get_records_sql($sql, null, 0, 2); // Skip 0, get 2 01433 $this->assertEqual(2, count($records)); 01434 $this->assertEqual($inskey6, reset($records)->id); 01435 $this->assertEqual($inskey5, end($records)->id); 01436 $records = $DB->get_records_sql($sql, null, 2, 2); // Skip 2, get 2 01437 $this->assertEqual(2, count($records)); 01438 $this->assertEqual($inskey3, reset($records)->id); 01439 $this->assertEqual($inskey2, end($records)->id); 01440 01441 // test 2 tables with aliases and limits with order bys 01442 $sql = "SELECT t1.id, t1.course AS cid, t2.nametext 01443 FROM {{$tablename}} t1, {{$tablename2}} t2 01444 WHERE t2.course=t1.course 01445 ORDER BY t1.course, ". $DB->sql_compare_text('t2.nametext'); 01446 $records = $DB->get_records_sql($sql, null, 2, 2); // Skip courses 3 and 6, get 4 and 5 01447 $this->assertEqual(2, count($records)); 01448 $this->assertEqual('5', end($records)->cid); 01449 $this->assertEqual('4', reset($records)->cid); 01450 01451 // test 2 tables with aliases and limits with the highest INT limit works 01452 $records = $DB->get_records_sql($sql, null, 2, PHP_INT_MAX); // Skip course {3,6}, get {4,5} 01453 $this->assertEqual(2, count($records)); 01454 $this->assertEqual('5', end($records)->cid); 01455 $this->assertEqual('4', reset($records)->cid); 01456 01457 // test 2 tables with aliases and limits with order bys (limit which is highest INT number) 01458 $records = $DB->get_records_sql($sql, null, PHP_INT_MAX, 2); // Skip all courses 01459 $this->assertEqual(0, count($records)); 01460 01461 // test 2 tables with aliases and limits with order bys (limit which s highest INT number) 01462 $records = $DB->get_records_sql($sql, null, PHP_INT_MAX, PHP_INT_MAX); // Skip all courses 01463 $this->assertEqual(0, count($records)); 01464 01465 // TODO: Test limits in queries having DISTINCT clauses 01466 01467 // note: fetching nulls, empties, LOBs already tested by test_update_record() no needed here 01468 } 01469 01470 public function test_get_records_menu() { 01471 $DB = $this->tdb; 01472 $dbman = $DB->get_manager(); 01473 01474 $table = $this->get_test_table(); 01475 $tablename = $table->getName(); 01476 01477 $table->add_field('id', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, XMLDB_SEQUENCE, null); 01478 $table->add_field('course', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '0'); 01479 $table->add_key('primary', XMLDB_KEY_PRIMARY, array('id')); 01480 $dbman->create_table($table); 01481 01482 $DB->insert_record($tablename, array('course' => 3)); 01483 $DB->insert_record($tablename, array('course' => 3)); 01484 $DB->insert_record($tablename, array('course' => 5)); 01485 $DB->insert_record($tablename, array('course' => 2)); 01486 01487 $records = $DB->get_records_menu($tablename, array('course' => 3)); 01488 $this->assertTrue(is_array($records)); 01489 $this->assertEqual(2, count($records)); 01490 $this->assertFalse(empty($records[1])); 01491 $this->assertFalse(empty($records[2])); 01492 $this->assertEqual(3, $records[1]); 01493 $this->assertEqual(3, $records[2]); 01494 01495 // note: delegate limits testing to test_get_records_sql() 01496 } 01497 01498 public function test_get_records_select_menu() { 01499 $DB = $this->tdb; 01500 $dbman = $DB->get_manager(); 01501 01502 $table = $this->get_test_table(); 01503 $tablename = $table->getName(); 01504 01505 $table->add_field('id', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, XMLDB_SEQUENCE, null); 01506 $table->add_field('course', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '0'); 01507 $table->add_key('primary', XMLDB_KEY_PRIMARY, array('id')); 01508 $dbman->create_table($table); 01509 01510 $DB->insert_record($tablename, array('course' => 3)); 01511 $DB->insert_record($tablename, array('course' => 2)); 01512 $DB->insert_record($tablename, array('course' => 3)); 01513 $DB->insert_record($tablename, array('course' => 5)); 01514 01515 $records = $DB->get_records_select_menu($tablename, "course > ?", array(2)); 01516 $this->assertTrue(is_array($records)); 01517 01518 $this->assertEqual(3, count($records)); 01519 $this->assertFalse(empty($records[1])); 01520 $this->assertTrue(empty($records[2])); 01521 $this->assertFalse(empty($records[3])); 01522 $this->assertFalse(empty($records[4])); 01523 $this->assertEqual(3, $records[1]); 01524 $this->assertEqual(3, $records[3]); 01525 $this->assertEqual(5, $records[4]); 01526 01527 // note: delegate limits testing to test_get_records_sql() 01528 } 01529 01530 public function test_get_records_sql_menu() { 01531 $DB = $this->tdb; 01532 $dbman = $DB->get_manager(); 01533 01534 $table = $this->get_test_table(); 01535 $tablename = $table->getName(); 01536 01537 $table->add_field('id', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, XMLDB_SEQUENCE, null); 01538 $table->add_field('course', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '0'); 01539 $table->add_key('primary', XMLDB_KEY_PRIMARY, array('id')); 01540 $dbman->create_table($table); 01541 01542 $DB->insert_record($tablename, array('course' => 3)); 01543 $DB->insert_record($tablename, array('course' => 2)); 01544 $DB->insert_record($tablename, array('course' => 3)); 01545 $DB->insert_record($tablename, array('course' => 5)); 01546 01547 $records = $DB->get_records_sql_menu("SELECT * FROM {{$tablename}} WHERE course > ?", array(2)); 01548 $this->assertTrue(is_array($records)); 01549 01550 $this->assertEqual(3, count($records)); 01551 $this->assertFalse(empty($records[1])); 01552 $this->assertTrue(empty($records[2])); 01553 $this->assertFalse(empty($records[3])); 01554 $this->assertFalse(empty($records[4])); 01555 $this->assertEqual(3, $records[1]); 01556 $this->assertEqual(3, $records[3]); 01557 $this->assertEqual(5, $records[4]); 01558 01559 // note: delegate limits testing to test_get_records_sql() 01560 } 01561 01562 public function test_get_record() { 01563 $DB = $this->tdb; 01564 $dbman = $DB->get_manager(); 01565 01566 $table = $this->get_test_table(); 01567 $tablename = $table->getName(); 01568 01569 $table->add_field('id', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, XMLDB_SEQUENCE, null); 01570 $table->add_field('course', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '0'); 01571 $table->add_key('primary', XMLDB_KEY_PRIMARY, array('id')); 01572 $dbman->create_table($table); 01573 01574 $DB->insert_record($tablename, array('course' => 3)); 01575 $DB->insert_record($tablename, array('course' => 2)); 01576 01577 $record = $DB->get_record($tablename, array('id' => 2)); 01578 $this->assertTrue($record instanceof stdClass); 01579 01580 $this->assertEqual(2, $record->course); 01581 $this->assertEqual(2, $record->id); 01582 } 01583 01584 01585 public function test_get_record_select() { 01586 $DB = $this->tdb; 01587 $dbman = $DB->get_manager(); 01588 01589 $table = $this->get_test_table(); 01590 $tablename = $table->getName(); 01591 01592 $table->add_field('id', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, XMLDB_SEQUENCE, null); 01593 $table->add_field('course', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '0'); 01594 $table->add_key('primary', XMLDB_KEY_PRIMARY, array('id')); 01595 $dbman->create_table($table); 01596 01597 $DB->insert_record($tablename, array('course' => 3)); 01598 $DB->insert_record($tablename, array('course' => 2)); 01599 01600 $record = $DB->get_record_select($tablename, "id = ?", array(2)); 01601 $this->assertTrue($record instanceof stdClass); 01602 01603 $this->assertEqual(2, $record->course); 01604 01605 // note: delegates limit testing to test_get_records_sql() 01606 } 01607 01608 public function test_get_record_sql() { 01609 $DB = $this->tdb; 01610 $dbman = $DB->get_manager(); 01611 01612 $table = $this->get_test_table(); 01613 $tablename = $table->getName(); 01614 01615 $table->add_field('id', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, XMLDB_SEQUENCE, null); 01616 $table->add_field('course', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '0'); 01617 $table->add_key('primary', XMLDB_KEY_PRIMARY, array('id')); 01618 $dbman->create_table($table); 01619 01620 $DB->insert_record($tablename, array('course' => 3)); 01621 $DB->insert_record($tablename, array('course' => 2)); 01622 01623 // standard use 01624 $record = $DB->get_record_sql("SELECT * FROM {{$tablename}} WHERE id = ?", array(2)); 01625 $this->assertTrue($record instanceof stdClass); 01626 $this->assertEqual(2, $record->course); 01627 $this->assertEqual(2, $record->id); 01628 01629 // backwards compatibility with $ignoremultiple 01630 $this->assertFalse(IGNORE_MISSING); 01631 $this->assertTrue(IGNORE_MULTIPLE); 01632 01633 // record not found - ignore 01634 $this->assertFalse($DB->get_record_sql("SELECT * FROM {{$tablename}} WHERE id = ?", array(666), IGNORE_MISSING)); 01635 $this->assertFalse($DB->get_record_sql("SELECT * FROM {{$tablename}} WHERE id = ?", array(666), IGNORE_MULTIPLE)); 01636 01637 // record not found error 01638 try { 01639 $DB->get_record_sql("SELECT * FROM {{$tablename}} WHERE id = ?", array(666), MUST_EXIST); 01640 $this->fail("Exception expected"); 01641 } catch (dml_missing_record_exception $e) { 01642 $this->assertTrue(true); 01643 } 01644 01645 $this->enable_debugging(); 01646 $this->assertTrue($DB->get_record_sql("SELECT * FROM {{$tablename}}", array(), IGNORE_MISSING)); 01647 $this->assertFalse($this->get_debugging() === ''); 01648 01649 // multiple matches ignored 01650 $this->assertTrue($DB->get_record_sql("SELECT * FROM {{$tablename}}", array(), IGNORE_MULTIPLE)); 01651 01652 // multiple found error 01653 try { 01654 $DB->get_record_sql("SELECT * FROM {{$tablename}}", array(), MUST_EXIST); 01655 $this->fail("Exception expected"); 01656 } catch (dml_multiple_records_exception $e) { 01657 $this->assertTrue(true); 01658 } 01659 } 01660 01661 public function test_get_field() { 01662 $DB = $this->tdb; 01663 $dbman = $DB->get_manager(); 01664 01665 $table = $this->get_test_table(); 01666 $tablename = $table->getName(); 01667 01668 $table->add_field('id', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, XMLDB_SEQUENCE, null); 01669 $table->add_field('course', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '0'); 01670 $table->add_field('onetext', XMLDB_TYPE_TEXT, 'big', null, null, null); 01671 $table->add_key('primary', XMLDB_KEY_PRIMARY, array('id')); 01672 $dbman->create_table($table); 01673 01674 $id1 = $DB->insert_record($tablename, array('course' => 3)); 01675 $DB->insert_record($tablename, array('course' => 5)); 01676 $DB->insert_record($tablename, array('course' => 5)); 01677 01678 $this->assertEqual(3, $DB->get_field($tablename, 'course', array('id' => $id1))); 01679 $this->assertEqual(3, $DB->get_field($tablename, 'course', array('course' => 3))); 01680 01681 $this->assertIdentical(false, $DB->get_field($tablename, 'course', array('course' => 11), IGNORE_MISSING)); 01682 try { 01683 $DB->get_field($tablename, 'course', array('course' => 4), MUST_EXIST); 01684 $this->assertFail('Exception expected due to missing record'); 01685 } catch (dml_exception $ex) { 01686 $this->assertTrue(true); 01687 } 01688 01689 $this->enable_debugging(); 01690 $this->assertEqual(5, $DB->get_field($tablename, 'course', array('course' => 5), IGNORE_MULTIPLE)); 01691 $this->assertIdentical($this->get_debugging(), ''); 01692 01693 $this->enable_debugging(); 01694 $this->assertEqual(5, $DB->get_field($tablename, 'course', array('course' => 5), IGNORE_MISSING)); 01695 $this->assertFalse($this->get_debugging() === ''); 01696 01697 // test for exception throwing on text conditions being compared. (MDL-24863, unwanted auto conversion of param to int) 01698 $conditions = array('onetext' => '1'); 01699 try { 01700 $DB->get_field($tablename, 'course', $conditions); 01701 if (debugging()) { 01702 // only in debug mode - hopefully all devs test code in debug mode... 01703 $this->fail('An Exception is missing, expected due to equating of text fields'); 01704 } 01705 } catch (exception $e) { 01706 $this->assertTrue($e instanceof dml_exception); 01707 $this->assertEqual($e->errorcode, 'textconditionsnotallowed'); 01708 } 01709 } 01710 01711 public function test_get_field_select() { 01712 $DB = $this->tdb; 01713 $dbman = $DB->get_manager(); 01714 01715 $table = $this->get_test_table(); 01716 $tablename = $table->getName(); 01717 01718 $table->add_field('id', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, XMLDB_SEQUENCE, null); 01719 $table->add_field('course', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '0'); 01720 $table->add_key('primary', XMLDB_KEY_PRIMARY, array('id')); 01721 $dbman->create_table($table); 01722 01723 $DB->insert_record($tablename, array('course' => 3)); 01724 01725 $this->assertEqual(3, $DB->get_field_select($tablename, 'course', "id = ?", array(1))); 01726 } 01727 01728 public function test_get_field_sql() { 01729 $DB = $this->tdb; 01730 $dbman = $DB->get_manager(); 01731 01732 $table = $this->get_test_table(); 01733 $tablename = $table->getName(); 01734 01735 $table->add_field('id', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, XMLDB_SEQUENCE, null); 01736 $table->add_field('course', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '0'); 01737 $table->add_key('primary', XMLDB_KEY_PRIMARY, array('id')); 01738 $dbman->create_table($table); 01739 01740 $DB->insert_record($tablename, array('course' => 3)); 01741 01742 $this->assertEqual(3, $DB->get_field_sql("SELECT course FROM {{$tablename}} WHERE id = ?", array(1))); 01743 } 01744 01745 public function test_get_fieldset_select() { 01746 $DB = $this->tdb; 01747 $dbman = $DB->get_manager(); 01748 01749 $table = $this->get_test_table(); 01750 $tablename = $table->getName(); 01751 01752 $table->add_field('id', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, XMLDB_SEQUENCE, null); 01753 $table->add_field('course', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '0'); 01754 $table->add_key('primary', XMLDB_KEY_PRIMARY, array('id')); 01755 $dbman->create_table($table); 01756 01757 $DB->insert_record($tablename, array('course' => 1)); 01758 $DB->insert_record($tablename, array('course' => 3)); 01759 $DB->insert_record($tablename, array('course' => 2)); 01760 $DB->insert_record($tablename, array('course' => 6)); 01761 01762 $fieldset = $DB->get_fieldset_select($tablename, 'course', "course > ?", array(1)); 01763 $this->assertTrue(is_array($fieldset)); 01764 01765 $this->assertEqual(3, count($fieldset)); 01766 $this->assertEqual(3, $fieldset[0]); 01767 $this->assertEqual(2, $fieldset[1]); 01768 $this->assertEqual(6, $fieldset[2]); 01769 } 01770 01771 public function test_get_fieldset_sql() { 01772 $DB = $this->tdb; 01773 $dbman = $DB->get_manager(); 01774 01775 $table = $this->get_test_table(); 01776 $tablename = $table->getName(); 01777 01778 $table->add_field('id', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, XMLDB_SEQUENCE, null); 01779 $table->add_field('course', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '0'); 01780 $table->add_key('primary', XMLDB_KEY_PRIMARY, array('id')); 01781 $dbman->create_table($table); 01782 01783 $DB->insert_record($tablename, array('course' => 1)); 01784 $DB->insert_record($tablename, array('course' => 3)); 01785 $DB->insert_record($tablename, array('course' => 2)); 01786 $DB->insert_record($tablename, array('course' => 6)); 01787 01788 $fieldset = $DB->get_fieldset_sql("SELECT * FROM {{$tablename}} WHERE course > ?", array(1)); 01789 $this->assertTrue(is_array($fieldset)); 01790 01791 $this->assertEqual(3, count($fieldset)); 01792 $this->assertEqual(2, $fieldset[0]); 01793 $this->assertEqual(3, $fieldset[1]); 01794 $this->assertEqual(4, $fieldset[2]); 01795 } 01796 01797 public function test_insert_record_raw() { 01798 $DB = $this->tdb; 01799 $dbman = $DB->get_manager(); 01800 01801 $table = $this->get_test_table(); 01802 $tablename = $table->getName(); 01803 01804 $table->add_field('id', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, XMLDB_SEQUENCE, null); 01805 $table->add_field('course', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '0'); 01806 $table->add_field('onechar', XMLDB_TYPE_CHAR, '100', null, null, null, 'onestring'); 01807 $table->add_key('primary', XMLDB_KEY_PRIMARY, array('id')); 01808 $dbman->create_table($table); 01809 01810 $record = (object)array('course' => 1, 'onechar' => 'xx'); 01811 $before = clone($record); 01812 $result = $DB->insert_record_raw($tablename, $record); 01813 $this->assertIdentical(1, $result); 01814 $this->assertIdentical($record, $before); 01815 01816 $record = $DB->get_record($tablename, array('course' => 1)); 01817 $this->assertTrue($record instanceof stdClass); 01818 $this->assertIdentical('xx', $record->onechar); 01819 01820 $result = $DB->insert_record_raw($tablename, array('course' => 2, 'onechar' => 'yy'), false); 01821 $this->assertIdentical(true, $result); 01822 01823 // note: bulk not implemented yet 01824 $DB->insert_record_raw($tablename, array('course' => 3, 'onechar' => 'zz'), true, true); 01825 $record = $DB->get_record($tablename, array('course' => 3)); 01826 $this->assertTrue($record instanceof stdClass); 01827 $this->assertIdentical('zz', $record->onechar); 01828 01829 // custom sequence (id) - returnid is ignored 01830 $result = $DB->insert_record_raw($tablename, array('id' => 10, 'course' => 3, 'onechar' => 'bb'), true, false, true); 01831 $this->assertIdentical(true, $result); 01832 $record = $DB->get_record($tablename, array('id' => 10)); 01833 $this->assertTrue($record instanceof stdClass); 01834 $this->assertIdentical('bb', $record->onechar); 01835 01836 // custom sequence - missing id error 01837 try { 01838 $DB->insert_record_raw($tablename, array('course' => 3, 'onechar' => 'bb'), true, false, true); 01839 $this->assertFail('Exception expected due to missing record'); 01840 } catch (coding_exception $ex) { 01841 $this->assertTrue(true); 01842 } 01843 01844 // wrong column error 01845 try { 01846 $DB->insert_record_raw($tablename, array('xxxxx' => 3, 'onechar' => 'bb')); 01847 $this->assertFail('Exception expected due to invalid column'); 01848 } catch (dml_exception $ex) { 01849 $this->assertTrue(true); 01850 } 01851 } 01852 01853 public function test_insert_record() { 01854 // All the information in this test is fetched from DB by get_recordset() so we 01855 // have such method properly tested against nulls, empties and friends... 01856 01857 $DB = $this->tdb; 01858 $dbman = $DB->get_manager(); 01859 01860 $table = $this->get_test_table(); 01861 $tablename = $table->getName(); 01862 01863 $table->add_field('id', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, XMLDB_SEQUENCE, null); 01864 $table->add_field('course', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '0'); 01865 $table->add_field('oneint', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, null, null, 100); 01866 $table->add_field('onenum', XMLDB_TYPE_NUMBER, '10,2', null, null, null, 200); 01867 $table->add_field('onechar', XMLDB_TYPE_CHAR, '100', null, null, null, 'onestring'); 01868 $table->add_field('onetext', XMLDB_TYPE_TEXT, 'big', null, null, null); 01869 $table->add_field('onebinary', XMLDB_TYPE_BINARY, 'big', null, null, null); 01870 $table->add_key('primary', XMLDB_KEY_PRIMARY, array('id')); 01871 $dbman->create_table($table); 01872 01873 $this->assertIdentical(1, $DB->insert_record($tablename, array('course' => 1), true)); 01874 $record = $DB->get_record($tablename, array('course' => 1)); 01875 $this->assertEqual(1, $record->id); 01876 $this->assertEqual(100, $record->oneint); // Just check column defaults have been applied 01877 $this->assertEqual(200, $record->onenum); 01878 $this->assertIdentical('onestring', $record->onechar); 01879 $this->assertNull($record->onetext); 01880 $this->assertNull($record->onebinary); 01881 01882 // without returning id, bulk not implemented 01883 $result = $this->assertIdentical(true, $DB->insert_record($tablename, array('course' => 99), false, true)); 01884 $record = $DB->get_record($tablename, array('course' => 99)); 01885 $this->assertEqual(2, $record->id); 01886 $this->assertEqual(99, $record->course); 01887 01888 // Check nulls are set properly for all types 01889 $record = new stdClass(); 01890 $record->oneint = null; 01891 $record->onenum = null; 01892 $record->onechar = null; 01893 $record->onetext = null; 01894 $record->onebinary = null; 01895 $recid = $DB->insert_record($tablename, $record); 01896 $record = $DB->get_record($tablename, array('id' => $recid)); 01897 $this->assertEqual(0, $record->course); 01898 $this->assertNull($record->oneint); 01899 $this->assertNull($record->onenum); 01900 $this->assertNull($record->onechar); 01901 $this->assertNull($record->onetext); 01902 $this->assertNull($record->onebinary); 01903 01904 // Check zeros are set properly for all types 01905 $record = new stdClass(); 01906 $record->oneint = 0; 01907 $record->onenum = 0; 01908 $recid = $DB->insert_record($tablename, $record); 01909 $record = $DB->get_record($tablename, array('id' => $recid)); 01910 $this->assertEqual(0, $record->oneint); 01911 $this->assertEqual(0, $record->onenum); 01912 01913 // Check booleans are set properly for all types 01914 $record = new stdClass(); 01915 $record->oneint = true; // trues 01916 $record->onenum = true; 01917 $record->onechar = true; 01918 $record->onetext = true; 01919 $recid = $DB->insert_record($tablename, $record); 01920 $record = $DB->get_record($tablename, array('id' => $recid)); 01921 $this->assertEqual(1, $record->oneint); 01922 $this->assertEqual(1, $record->onenum); 01923 $this->assertEqual(1, $record->onechar); 01924 $this->assertEqual(1, $record->onetext); 01925 01926 $record = new stdClass(); 01927 $record->oneint = false; // falses 01928 $record->onenum = false; 01929 $record->onechar = false; 01930 $record->onetext = false; 01931 $recid = $DB->insert_record($tablename, $record); 01932 $record = $DB->get_record($tablename, array('id' => $recid)); 01933 $this->assertEqual(0, $record->oneint); 01934 $this->assertEqual(0, $record->onenum); 01935 $this->assertEqual(0, $record->onechar); 01936 $this->assertEqual(0, $record->onetext); 01937 01938 // Check string data causes exception in numeric types 01939 $record = new stdClass(); 01940 $record->oneint = 'onestring'; 01941 $record->onenum = 0; 01942 try { 01943 $DB->insert_record($tablename, $record); 01944 $this->fail("Expecting an exception, none occurred"); 01945 } catch (exception $e) { 01946 $this->assertTrue($e instanceof dml_exception); 01947 } 01948 $record = new stdClass(); 01949 $record->oneint = 0; 01950 $record->onenum = 'onestring'; 01951 try { 01952 $DB->insert_record($tablename, $record); 01953 $this->fail("Expecting an exception, none occurred"); 01954 } catch (exception $e) { 01955 $this->assertTrue($e instanceof dml_exception); 01956 } 01957 01958 // Check empty string data is stored as 0 in numeric datatypes 01959 $record = new stdClass(); 01960 $record->oneint = ''; // empty string 01961 $record->onenum = 0; 01962 $recid = $DB->insert_record($tablename, $record); 01963 $record = $DB->get_record($tablename, array('id' => $recid)); 01964 $this->assertTrue(is_numeric($record->oneint) && $record->oneint == 0); 01965 01966 $record = new stdClass(); 01967 $record->oneint = 0; 01968 $record->onenum = ''; // empty string 01969 $recid = $DB->insert_record($tablename, $record); 01970 $record = $DB->get_record($tablename, array('id' => $recid)); 01971 $this->assertTrue(is_numeric($record->onenum) && $record->onenum == 0); 01972 01973 // Check empty strings are set properly in string types 01974 $record = new stdClass(); 01975 $record->oneint = 0; 01976 $record->onenum = 0; 01977 $record->onechar = ''; 01978 $record->onetext = ''; 01979 $recid = $DB->insert_record($tablename, $record); 01980 $record = $DB->get_record($tablename, array('id' => $recid)); 01981 $this->assertTrue($record->onechar === ''); 01982 $this->assertTrue($record->onetext === ''); 01983 01984 // Check operation ((210.10 + 39.92) - 150.02) against numeric types 01985 $record = new stdClass(); 01986 $record->oneint = ((210.10 + 39.92) - 150.02); 01987 $record->onenum = ((210.10 + 39.92) - 150.02); 01988 $recid = $DB->insert_record($tablename, $record); 01989 $record = $DB->get_record($tablename, array('id' => $recid)); 01990 $this->assertEqual(100, $record->oneint); 01991 $this->assertEqual(100, $record->onenum); 01992 01993 // Check various quotes/backslashes combinations in string types 01994 $teststrings = array( 01995 'backslashes and quotes alone (even): "" \'\' \\\\', 01996 'backslashes and quotes alone (odd): """ \'\'\' \\\\\\', 01997 'backslashes and quotes sequences (even): \\"\\" \\\'\\\'', 01998 'backslashes and quotes sequences (odd): \\"\\"\\" \\\'\\\'\\\''); 01999 foreach ($teststrings as $teststring) { 02000 $record = new stdClass(); 02001 $record->onechar = $teststring; 02002 $record->onetext = $teststring; 02003 $recid = $DB->insert_record($tablename, $record); 02004 $record = $DB->get_record($tablename, array('id' => $recid)); 02005 $this->assertEqual($teststring, $record->onechar); 02006 $this->assertEqual($teststring, $record->onetext); 02007 } 02008 02009 // Check LOBs in text/binary columns 02010 $clob = file_get_contents(dirname(__FILE__).'/fixtures/clob.txt'); 02011 $blob = file_get_contents(dirname(__FILE__).'/fixtures/randombinary'); 02012 $record = new stdClass(); 02013 $record->onetext = $clob; 02014 $record->onebinary = $blob; 02015 $recid = $DB->insert_record($tablename, $record); 02016 $rs = $DB->get_recordset($tablename, array('id' => $recid)); 02017 $record = $rs->current(); 02018 $rs->close(); 02019 $this->assertEqual($clob, $record->onetext, 'Test CLOB insert (full contents output disabled)'); 02020 $this->assertEqual($blob, $record->onebinary, 'Test BLOB insert (full contents output disabled)'); 02021 02022 // And "small" LOBs too, just in case 02023 $newclob = substr($clob, 0, 500); 02024 $newblob = substr($blob, 0, 250); 02025 $record = new stdClass(); 02026 $record->onetext = $newclob; 02027 $record->onebinary = $newblob; 02028 $recid = $DB->insert_record($tablename, $record); 02029 $rs = $DB->get_recordset($tablename, array('id' => $recid)); 02030 $record = $rs->current(); 02031 $rs->close(); 02032 $this->assertEqual($newclob, $record->onetext, 'Test "small" CLOB insert (full contents output disabled)'); 02033 $this->assertEqual($newblob, $record->onebinary, 'Test "small" BLOB insert (full contents output disabled)'); 02034 $this->assertEqual(false, $rs->key()); // Ensure recordset key() method to be working ok after closing 02035 02036 // And "diagnostic" LOBs too, just in case 02037 $newclob = '\'"\\;/ěščřžýáíé'; 02038 $newblob = '\'"\\;/ěščřžýáíé'; 02039 $record = new stdClass(); 02040 $record->onetext = $newclob; 02041 $record->onebinary = $newblob; 02042 $recid = $DB->insert_record($tablename, $record); 02043 $rs = $DB->get_recordset($tablename, array('id' => $recid)); 02044 $record = $rs->current(); 02045 $rs->close(); 02046 $this->assertIdentical($newclob, $record->onetext); 02047 $this->assertIdentical($newblob, $record->onebinary); 02048 $this->assertEqual(false, $rs->key()); // Ensure recordset key() method to be working ok after closing 02049 02050 // test data is not modified 02051 $record = new stdClass(); 02052 $record->id = -1; // has to be ignored 02053 $record->course = 3; 02054 $record->lalala = 'lalal'; // unused 02055 $before = clone($record); 02056 $DB->insert_record($tablename, $record); 02057 $this->assertEqual($record, $before); 02058 02059 // make sure the id is always increasing and never reuses the same id 02060 $id1 = $DB->insert_record($tablename, array('course' => 3)); 02061 $id2 = $DB->insert_record($tablename, array('course' => 3)); 02062 $this->assertTrue($id1 < $id2); 02063 $DB->delete_records($tablename, array('id'=>$id2)); 02064 $id3 = $DB->insert_record($tablename, array('course' => 3)); 02065 $this->assertTrue($id2 < $id3); 02066 $DB->delete_records($tablename, array()); 02067 $id4 = $DB->insert_record($tablename, array('course' => 3)); 02068 $this->assertTrue($id3 < $id4); 02069 02070 // Test saving a float in a CHAR column, and reading it back. 02071 $id = $DB->insert_record($tablename, array('onechar' => 1.0)); 02072 $this->assertEqual(1.0, $DB->get_field($tablename, 'onechar', array('id' => $id))); 02073 $id = $DB->insert_record($tablename, array('onechar' => 1e20)); 02074 $this->assertEqual(1e20, $DB->get_field($tablename, 'onechar', array('id' => $id))); 02075 $id = $DB->insert_record($tablename, array('onechar' => 1e-4)); 02076 $this->assertEqual(1e-4, $DB->get_field($tablename, 'onechar', array('id' => $id))); 02077 $id = $DB->insert_record($tablename, array('onechar' => 1e-5)); 02078 $this->assertEqual(1e-5, $DB->get_field($tablename, 'onechar', array('id' => $id))); 02079 $id = $DB->insert_record($tablename, array('onechar' => 1e-300)); 02080 $this->assertEqual(1e-300, $DB->get_field($tablename, 'onechar', array('id' => $id))); 02081 $id = $DB->insert_record($tablename, array('onechar' => 1e300)); 02082 $this->assertEqual(1e300, $DB->get_field($tablename, 'onechar', array('id' => $id))); 02083 02084 // Test saving a float in a TEXT column, and reading it back. 02085 $id = $DB->insert_record($tablename, array('onetext' => 1.0)); 02086 $this->assertEqual(1.0, $DB->get_field($tablename, 'onetext', array('id' => $id))); 02087 $id = $DB->insert_record($tablename, array('onetext' => 1e20)); 02088 $this->assertEqual(1e20, $DB->get_field($tablename, 'onetext', array('id' => $id))); 02089 $id = $DB->insert_record($tablename, array('onetext' => 1e-4)); 02090 $this->assertEqual(1e-4, $DB->get_field($tablename, 'onetext', array('id' => $id))); 02091 $id = $DB->insert_record($tablename, array('onetext' => 1e-5)); 02092 $this->assertEqual(1e-5, $DB->get_field($tablename, 'onetext', array('id' => $id))); 02093 $id = $DB->insert_record($tablename, array('onetext' => 1e-300)); 02094 $this->assertEqual(1e-300, $DB->get_field($tablename, 'onetext', array('id' => $id))); 02095 $id = $DB->insert_record($tablename, array('onetext' => 1e300)); 02096 $this->assertEqual(1e300, $DB->get_field($tablename, 'onetext', array('id' => $id))); 02097 } 02098 02099 public function test_import_record() { 02100 // All the information in this test is fetched from DB by get_recordset() so we 02101 // have such method properly tested against nulls, empties and friends... 02102 02103 $DB = $this->tdb; 02104 $dbman = $DB->get_manager(); 02105 02106 $table = $this->get_test_table(); 02107 $tablename = $table->getName(); 02108 02109 $table->add_field('id', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, XMLDB_SEQUENCE, null); 02110 $table->add_field('course', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '0'); 02111 $table->add_field('oneint', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, null, null, 100); 02112 $table->add_field('onenum', XMLDB_TYPE_NUMBER, '10,2', null, null, null, 200); 02113 $table->add_field('onechar', XMLDB_TYPE_CHAR, '100', null, null, null, 'onestring'); 02114 $table->add_field('onetext', XMLDB_TYPE_TEXT, 'big', null, null, null); 02115 $table->add_field('onebinary', XMLDB_TYPE_BINARY, 'big', null, null, null); 02116 $table->add_key('primary', XMLDB_KEY_PRIMARY, array('id')); 02117 $dbman->create_table($table); 02118 02119 $this->assertIdentical(1, $DB->insert_record($tablename, array('course' => 1), true)); 02120 $record = $DB->get_record($tablename, array('course' => 1)); 02121 $this->assertEqual(1, $record->id); 02122 $this->assertEqual(100, $record->oneint); // Just check column defaults have been applied 02123 $this->assertEqual(200, $record->onenum); 02124 $this->assertIdentical('onestring', $record->onechar); 02125 $this->assertNull($record->onetext); 02126 $this->assertNull($record->onebinary); 02127 02128 // ignore extra columns 02129 $record = (object)array('id'=>13, 'course'=>2, 'xxxx'=>788778); 02130 $before = clone($record); 02131 $this->assertIdentical(true, $DB->import_record($tablename, $record)); 02132 $this->assertIdentical($record, $before); 02133 $records = $DB->get_records($tablename); 02134 $this->assertEqual(2, $records[13]->course); 02135 02136 // Check nulls are set properly for all types 02137 $record = new stdClass(); 02138 $record->id = 20; 02139 $record->oneint = null; 02140 $record->onenum = null; 02141 $record->onechar = null; 02142 $record->onetext = null; 02143 $record->onebinary = null; 02144 $this->assertTrue($DB->import_record($tablename, $record)); 02145 $record = $DB->get_record($tablename, array('id' => 20)); 02146 $this->assertEqual(0, $record->course); 02147 $this->assertNull($record->oneint); 02148 $this->assertNull($record->onenum); 02149 $this->assertNull($record->onechar); 02150 $this->assertNull($record->onetext); 02151 $this->assertNull($record->onebinary); 02152 02153 // Check zeros are set properly for all types 02154 $record = new stdClass(); 02155 $record->id = 23; 02156 $record->oneint = 0; 02157 $record->onenum = 0; 02158 $this->assertTrue($DB->import_record($tablename, $record)); 02159 $record = $DB->get_record($tablename, array('id' => 23)); 02160 $this->assertEqual(0, $record->oneint); 02161 $this->assertEqual(0, $record->onenum); 02162 02163 // Check string data causes exception in numeric types 02164 $record = new stdClass(); 02165 $record->id = 32; 02166 $record->oneint = 'onestring'; 02167 $record->onenum = 0; 02168 try { 02169 $DB->import_record($tablename, $record); 02170 $this->fail("Expecting an exception, none occurred"); 02171 } catch (exception $e) { 02172 $this->assertTrue($e instanceof dml_exception); 02173 } 02174 $record = new stdClass(); 02175 $record->id = 35; 02176 $record->oneint = 0; 02177 $record->onenum = 'onestring'; 02178 try { 02179 $DB->import_record($tablename, $record); 02180 $this->fail("Expecting an exception, none occurred"); 02181 } catch (exception $e) { 02182 $this->assertTrue($e instanceof dml_exception); 02183 } 02184 02185 // Check empty strings are set properly in string types 02186 $record = new stdClass(); 02187 $record->id = 44; 02188 $record->oneint = 0; 02189 $record->onenum = 0; 02190 $record->onechar = ''; 02191 $record->onetext = ''; 02192 $this->assertTrue($DB->import_record($tablename, $record)); 02193 $record = $DB->get_record($tablename, array('id' => 44)); 02194 $this->assertTrue($record->onechar === ''); 02195 $this->assertTrue($record->onetext === ''); 02196 02197 // Check operation ((210.10 + 39.92) - 150.02) against numeric types 02198 $record = new stdClass(); 02199 $record->id = 47; 02200 $record->oneint = ((210.10 + 39.92) - 150.02); 02201 $record->onenum = ((210.10 + 39.92) - 150.02); 02202 $this->assertTrue($DB->import_record($tablename, $record)); 02203 $record = $DB->get_record($tablename, array('id' => 47)); 02204 $this->assertEqual(100, $record->oneint); 02205 $this->assertEqual(100, $record->onenum); 02206 02207 // Check various quotes/backslashes combinations in string types 02208 $i = 50; 02209 $teststrings = array( 02210 'backslashes and quotes alone (even): "" \'\' \\\\', 02211 'backslashes and quotes alone (odd): """ \'\'\' \\\\\\', 02212 'backslashes and quotes sequences (even): \\"\\" \\\'\\\'', 02213 'backslashes and quotes sequences (odd): \\"\\"\\" \\\'\\\'\\\''); 02214 foreach ($teststrings as $teststring) { 02215 $record = new stdClass(); 02216 $record->id = $i; 02217 $record->onechar = $teststring; 02218 $record->onetext = $teststring; 02219 $this->assertTrue($DB->import_record($tablename, $record)); 02220 $record = $DB->get_record($tablename, array('id' => $i)); 02221 $this->assertEqual($teststring, $record->onechar); 02222 $this->assertEqual($teststring, $record->onetext); 02223 $i = $i + 3; 02224 } 02225 02226 // Check LOBs in text/binary columns 02227 $clob = file_get_contents(dirname(__FILE__).'/fixtures/clob.txt'); 02228 $record = new stdClass(); 02229 $record->id = 70; 02230 $record->onetext = $clob; 02231 $record->onebinary = ''; 02232 $this->assertTrue($DB->import_record($tablename, $record)); 02233 $rs = $DB->get_recordset($tablename, array('id' => 70)); 02234 $record = $rs->current(); 02235 $rs->close(); 02236 $this->assertEqual($clob, $record->onetext, 'Test CLOB insert (full contents output disabled)'); 02237 02238 $blob = file_get_contents(dirname(__FILE__).'/fixtures/randombinary'); 02239 $record = new stdClass(); 02240 $record->id = 71; 02241 $record->onetext = ''; 02242 $record->onebinary = $blob; 02243 $this->assertTrue($DB->import_record($tablename, $record)); 02244 $rs = $DB->get_recordset($tablename, array('id' => 71)); 02245 $record = $rs->current(); 02246 $rs->close(); 02247 $this->assertEqual($blob, $record->onebinary, 'Test BLOB insert (full contents output disabled)'); 02248 02249 // And "small" LOBs too, just in case 02250 $newclob = substr($clob, 0, 500); 02251 $newblob = substr($blob, 0, 250); 02252 $record = new stdClass(); 02253 $record->id = 73; 02254 $record->onetext = $newclob; 02255 $record->onebinary = $newblob; 02256 $this->assertTrue($DB->import_record($tablename, $record)); 02257 $rs = $DB->get_recordset($tablename, array('id' => 73)); 02258 $record = $rs->current(); 02259 $rs->close(); 02260 $this->assertEqual($newclob, $record->onetext, 'Test "small" CLOB insert (full contents output disabled)'); 02261 $this->assertEqual($newblob, $record->onebinary, 'Test "small" BLOB insert (full contents output disabled)'); 02262 $this->assertEqual(false, $rs->key()); // Ensure recordset key() method to be working ok after closing 02263 } 02264 02265 public function test_update_record_raw() { 02266 $DB = $this->tdb; 02267 $dbman = $DB->get_manager(); 02268 02269 $table = $this->get_test_table(); 02270 $tablename = $table->getName(); 02271 02272 $table->add_field('id', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, XMLDB_SEQUENCE, null); 02273 $table->add_field('course', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '0'); 02274 $table->add_key('primary', XMLDB_KEY_PRIMARY, array('id')); 02275 $dbman->create_table($table); 02276 02277 $DB->insert_record($tablename, array('course' => 1)); 02278 $DB->insert_record($tablename, array('course' => 3)); 02279 02280 $record = $DB->get_record($tablename, array('course' => 1)); 02281 $record->course = 2; 02282 $this->assertTrue($DB->update_record_raw($tablename, $record)); 02283 $this->assertEqual(0, $DB->count_records($tablename, array('course' => 1))); 02284 $this->assertEqual(1, $DB->count_records($tablename, array('course' => 2))); 02285 $this->assertEqual(1, $DB->count_records($tablename, array('course' => 3))); 02286 02287 $record = $DB->get_record($tablename, array('course' => 1)); 02288 $record->xxxxx = 2; 02289 try { 02290 $DB->update_record_raw($tablename, $record); 02291 $this->fail("Expecting an exception, none occurred"); 02292 } catch (Exception $e) { 02293 $this->assertTrue($e instanceof coding_exception); 02294 } 02295 02296 $record = $DB->get_record($tablename, array('course' => 3)); 02297 unset($record->id); 02298 try { 02299 $DB->update_record_raw($tablename, $record); 02300 $this->fail("Expecting an exception, none occurred"); 02301 } catch (Exception $e) { 02302 $this->assertTrue($e instanceof coding_exception); 02303 } 02304 } 02305 02306 public function test_update_record() { 02307 02308 // All the information in this test is fetched from DB by get_record() so we 02309 // have such method properly tested against nulls, empties and friends... 02310 02311 $DB = $this->tdb; 02312 $dbman = $DB->get_manager(); 02313 02314 $table = $this->get_test_table(); 02315 $tablename = $table->getName(); 02316 02317 $table->add_field('id', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, XMLDB_SEQUENCE, null); 02318 $table->add_field('course', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '0'); 02319 $table->add_field('oneint', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, null, null, 100); 02320 $table->add_field('onenum', XMLDB_TYPE_NUMBER, '10,2', null, null, null, 200); 02321 $table->add_field('onechar', XMLDB_TYPE_CHAR, '100', null, null, null, 'onestring'); 02322 $table->add_field('onetext', XMLDB_TYPE_TEXT, 'big', null, null, null); 02323 $table->add_field('onebinary', XMLDB_TYPE_BINARY, 'big', null, null, null); 02324 $table->add_key('primary', XMLDB_KEY_PRIMARY, array('id')); 02325 $dbman->create_table($table); 02326 02327 $DB->insert_record($tablename, array('course' => 1)); 02328 $record = $DB->get_record($tablename, array('course' => 1)); 02329 $record->course = 2; 02330 02331 $this->assertTrue($DB->update_record($tablename, $record)); 02332 $this->assertFalse($record = $DB->get_record($tablename, array('course' => 1))); 02333 $this->assertTrue($record = $DB->get_record($tablename, array('course' => 2))); 02334 $this->assertEqual(100, $record->oneint); // Just check column defaults have been applied 02335 $this->assertEqual(200, $record->onenum); 02336 $this->assertEqual('onestring', $record->onechar); 02337 $this->assertNull($record->onetext); 02338 $this->assertNull($record->onebinary); 02339 02340 // Check nulls are set properly for all types 02341 $record->oneint = null; 02342 $record->onenum = null; 02343 $record->onechar = null; 02344 $record->onetext = null; 02345 $record->onebinary = null; 02346 $DB->update_record($tablename, $record); 02347 $record = $DB->get_record($tablename, array('course' => 2)); 02348 $this->assertNull($record->oneint); 02349 $this->assertNull($record->onenum); 02350 $this->assertNull($record->onechar); 02351 $this->assertNull($record->onetext); 02352 $this->assertNull($record->onebinary); 02353 02354 // Check zeros are set properly for all types 02355 $record->oneint = 0; 02356 $record->onenum = 0; 02357 $DB->update_record($tablename, $record); 02358 $record = $DB->get_record($tablename, array('course' => 2)); 02359 $this->assertEqual(0, $record->oneint); 02360 $this->assertEqual(0, $record->onenum); 02361 02362 // Check booleans are set properly for all types 02363 $record->oneint = true; // trues 02364 $record->onenum = true; 02365 $record->onechar = true; 02366 $record->onetext = true; 02367 $DB->update_record($tablename, $record); 02368 $record = $DB->get_record($tablename, array('course' => 2)); 02369 $this->assertEqual(1, $record->oneint); 02370 $this->assertEqual(1, $record->onenum); 02371 $this->assertEqual(1, $record->onechar); 02372 $this->assertEqual(1, $record->onetext); 02373 02374 $record->oneint = false; // falses 02375 $record->onenum = false; 02376 $record->onechar = false; 02377 $record->onetext = false; 02378 $DB->update_record($tablename, $record); 02379 $record = $DB->get_record($tablename, array('course' => 2)); 02380 $this->assertEqual(0, $record->oneint); 02381 $this->assertEqual(0, $record->onenum); 02382 $this->assertEqual(0, $record->onechar); 02383 $this->assertEqual(0, $record->onetext); 02384 02385 // Check string data causes exception in numeric types 02386 $record->oneint = 'onestring'; 02387 $record->onenum = 0; 02388 try { 02389 $DB->update_record($tablename, $record); 02390 $this->fail("Expecting an exception, none occurred"); 02391 } catch (exception $e) { 02392 $this->assertTrue($e instanceof dml_exception); 02393 } 02394 $record->oneint = 0; 02395 $record->onenum = 'onestring'; 02396 try { 02397 $DB->update_record($tablename, $record); 02398 $this->fail("Expecting an exception, none occurred"); 02399 } catch (exception $e) { 02400 $this->assertTrue($e instanceof dml_exception); 02401 } 02402 02403 // Check empty string data is stored as 0 in numeric datatypes 02404 $record->oneint = ''; // empty string 02405 $record->onenum = 0; 02406 $DB->update_record($tablename, $record); 02407 $record = $DB->get_record($tablename, array('course' => 2)); 02408 $this->assertTrue(is_numeric($record->oneint) && $record->oneint == 0); 02409 02410 $record->oneint = 0; 02411 $record->onenum = ''; // empty string 02412 $DB->update_record($tablename, $record); 02413 $record = $DB->get_record($tablename, array('course' => 2)); 02414 $this->assertTrue(is_numeric($record->onenum) && $record->onenum == 0); 02415 02416 // Check empty strings are set properly in string types 02417 $record->oneint = 0; 02418 $record->onenum = 0; 02419 $record->onechar = ''; 02420 $record->onetext = ''; 02421 $DB->update_record($tablename, $record); 02422 $record = $DB->get_record($tablename, array('course' => 2)); 02423 $this->assertTrue($record->onechar === ''); 02424 $this->assertTrue($record->onetext === ''); 02425 02426 // Check operation ((210.10 + 39.92) - 150.02) against numeric types 02427 $record->oneint = ((210.10 + 39.92) - 150.02); 02428 $record->onenum = ((210.10 + 39.92) - 150.02); 02429 $DB->update_record($tablename, $record); 02430 $record = $DB->get_record($tablename, array('course' => 2)); 02431 $this->assertEqual(100, $record->oneint); 02432 $this->assertEqual(100, $record->onenum); 02433 02434 // Check various quotes/backslashes combinations in string types 02435 $teststrings = array( 02436 'backslashes and quotes alone (even): "" \'\' \\\\', 02437 'backslashes and quotes alone (odd): """ \'\'\' \\\\\\', 02438 'backslashes and quotes sequences (even): \\"\\" \\\'\\\'', 02439 'backslashes and quotes sequences (odd): \\"\\"\\" \\\'\\\'\\\''); 02440 foreach ($teststrings as $teststring) { 02441 $record->onechar = $teststring; 02442 $record->onetext = $teststring; 02443 $DB->update_record($tablename, $record); 02444 $record = $DB->get_record($tablename, array('course' => 2)); 02445 $this->assertEqual($teststring, $record->onechar); 02446 $this->assertEqual($teststring, $record->onetext); 02447 } 02448 02449 // Check LOBs in text/binary columns 02450 $clob = file_get_contents(dirname(__FILE__).'/fixtures/clob.txt'); 02451 $blob = file_get_contents(dirname(__FILE__).'/fixtures/randombinary'); 02452 $record->onetext = $clob; 02453 $record->onebinary = $blob; 02454 $DB->update_record($tablename, $record); 02455 $record = $DB->get_record($tablename, array('course' => 2)); 02456 $this->assertEqual($clob, $record->onetext, 'Test CLOB update (full contents output disabled)'); 02457 $this->assertEqual($blob, $record->onebinary, 'Test BLOB update (full contents output disabled)'); 02458 02459 // And "small" LOBs too, just in case 02460 $newclob = substr($clob, 0, 500); 02461 $newblob = substr($blob, 0, 250); 02462 $record->onetext = $newclob; 02463 $record->onebinary = $newblob; 02464 $DB->update_record($tablename, $record); 02465 $record = $DB->get_record($tablename, array('course' => 2)); 02466 $this->assertEqual($newclob, $record->onetext, 'Test "small" CLOB update (full contents output disabled)'); 02467 $this->assertEqual($newblob, $record->onebinary, 'Test "small" BLOB update (full contents output disabled)'); 02468 02469 // Test saving a float in a CHAR column, and reading it back. 02470 $id = $DB->insert_record($tablename, array('onechar' => 'X')); 02471 $DB->update_record($tablename, array('id' => $id, 'onechar' => 1.0)); 02472 $this->assertEqual(1.0, $DB->get_field($tablename, 'onechar', array('id' => $id))); 02473 $DB->update_record($tablename, array('id' => $id, 'onechar' => 1e20)); 02474 $this->assertEqual(1e20, $DB->get_field($tablename, 'onechar', array('id' => $id))); 02475 $DB->update_record($tablename, array('id' => $id, 'onechar' => 1e-4)); 02476 $this->assertEqual(1e-4, $DB->get_field($tablename, 'onechar', array('id' => $id))); 02477 $DB->update_record($tablename, array('id' => $id, 'onechar' => 1e-5)); 02478 $this->assertEqual(1e-5, $DB->get_field($tablename, 'onechar', array('id' => $id))); 02479 $DB->update_record($tablename, array('id' => $id, 'onechar' => 1e-300)); 02480 $this->assertEqual(1e-300, $DB->get_field($tablename, 'onechar', array('id' => $id))); 02481 $DB->update_record($tablename, array('id' => $id, 'onechar' => 1e300)); 02482 $this->assertEqual(1e300, $DB->get_field($tablename, 'onechar', array('id' => $id))); 02483 02484 // Test saving a float in a TEXT column, and reading it back. 02485 $id = $DB->insert_record($tablename, array('onetext' => 'X')); 02486 $DB->update_record($tablename, array('id' => $id, 'onetext' => 1.0)); 02487 $this->assertEqual(1.0, $DB->get_field($tablename, 'onetext', array('id' => $id))); 02488 $DB->update_record($tablename, array('id' => $id, 'onetext' => 1e20)); 02489 $this->assertEqual(1e20, $DB->get_field($tablename, 'onetext', array('id' => $id))); 02490 $DB->update_record($tablename, array('id' => $id, 'onetext' => 1e-4)); 02491 $this->assertEqual(1e-4, $DB->get_field($tablename, 'onetext', array('id' => $id))); 02492 $DB->update_record($tablename, array('id' => $id, 'onetext' => 1e-5)); 02493 $this->assertEqual(1e-5, $DB->get_field($tablename, 'onetext', array('id' => $id))); 02494 $DB->update_record($tablename, array('id' => $id, 'onetext' => 1e-300)); 02495 $this->assertEqual(1e-300, $DB->get_field($tablename, 'onetext', array('id' => $id))); 02496 $DB->update_record($tablename, array('id' => $id, 'onetext' => 1e300)); 02497 $this->assertEqual(1e300, $DB->get_field($tablename, 'onetext', array('id' => $id))); 02498 } 02499 02500 public function test_set_field() { 02501 $DB = $this->tdb; 02502 $dbman = $DB->get_manager(); 02503 02504 $table = $this->get_test_table(); 02505 $tablename = $table->getName(); 02506 02507 $table->add_field('id', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, XMLDB_SEQUENCE, null); 02508 $table->add_field('course', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '0'); 02509 $table->add_field('onechar', XMLDB_TYPE_CHAR, '100', null, null, null); 02510 $table->add_field('onetext', XMLDB_TYPE_TEXT, 'big', null, null, null); 02511 $table->add_key('primary', XMLDB_KEY_PRIMARY, array('id')); 02512 $dbman->create_table($table); 02513 02514 // simple set_field 02515 $id1 = $DB->insert_record($tablename, array('course' => 1)); 02516 $id2 = $DB->insert_record($tablename, array('course' => 1)); 02517 $id3 = $DB->insert_record($tablename, array('course' => 3)); 02518 $this->assertTrue($DB->set_field($tablename, 'course', 2, array('id' => $id1))); 02519 $this->assertEqual(2, $DB->get_field($tablename, 'course', array('id' => $id1))); 02520 $this->assertEqual(1, $DB->get_field($tablename, 'course', array('id' => $id2))); 02521 $this->assertEqual(3, $DB->get_field($tablename, 'course', array('id' => $id3))); 02522 $DB->delete_records($tablename, array()); 02523 02524 // multiple fields affected 02525 $id1 = $DB->insert_record($tablename, array('course' => 1)); 02526 $id2 = $DB->insert_record($tablename, array('course' => 1)); 02527 $id3 = $DB->insert_record($tablename, array('course' => 3)); 02528 $DB->set_field($tablename, 'course', '5', array('course' => 1)); 02529 $this->assertEqual(5, $DB->get_field($tablename, 'course', array('id' => $id1))); 02530 $this->assertEqual(5, $DB->get_field($tablename, 'course', array('id' => $id2))); 02531 $this->assertEqual(3, $DB->get_field($tablename, 'course', array('id' => $id3))); 02532 $DB->delete_records($tablename, array()); 02533 02534 // no field affected 02535 $id1 = $DB->insert_record($tablename, array('course' => 1)); 02536 $id2 = $DB->insert_record($tablename, array('course' => 1)); 02537 $id3 = $DB->insert_record($tablename, array('course' => 3)); 02538 $DB->set_field($tablename, 'course', '5', array('course' => 0)); 02539 $this->assertEqual(1, $DB->get_field($tablename, 'course', array('id' => $id1))); 02540 $this->assertEqual(1, $DB->get_field($tablename, 'course', array('id' => $id2))); 02541 $this->assertEqual(3, $DB->get_field($tablename, 'course', array('id' => $id3))); 02542 $DB->delete_records($tablename, array()); 02543 02544 // all fields - no condition 02545 $id1 = $DB->insert_record($tablename, array('course' => 1)); 02546 $id2 = $DB->insert_record($tablename, array('course' => 1)); 02547 $id3 = $DB->insert_record($tablename, array('course' => 3)); 02548 $DB->set_field($tablename, 'course', 5, array()); 02549 $this->assertEqual(5, $DB->get_field($tablename, 'course', array('id' => $id1))); 02550 $this->assertEqual(5, $DB->get_field($tablename, 'course', array('id' => $id2))); 02551 $this->assertEqual(5, $DB->get_field($tablename, 'course', array('id' => $id3))); 02552 02553 // test for exception throwing on text conditions being compared. (MDL-24863, unwanted auto conversion of param to int) 02554 $conditions = array('onetext' => '1'); 02555 try { 02556 $DB->set_field($tablename, 'onechar', 'frog', $conditions); 02557 if (debugging()) { 02558 // only in debug mode - hopefully all devs test code in debug mode... 02559 $this->fail('An Exception is missing, expected due to equating of text fields'); 02560 } 02561 } catch (exception $e) { 02562 $this->assertTrue($e instanceof dml_exception); 02563 $this->assertEqual($e->errorcode, 'textconditionsnotallowed'); 02564 } 02565 02566 // Test saving a float in a CHAR column, and reading it back. 02567 $id = $DB->insert_record($tablename, array('onechar' => 'X')); 02568 $DB->set_field($tablename, 'onechar', 1.0, array('id' => $id)); 02569 $this->assertEqual(1.0, $DB->get_field($tablename, 'onechar', array('id' => $id))); 02570 $DB->set_field($tablename, 'onechar', 1e20, array('id' => $id)); 02571 $this->assertEqual(1e20, $DB->get_field($tablename, 'onechar', array('id' => $id))); 02572 $DB->set_field($tablename, 'onechar', 1e-4, array('id' => $id)); 02573 $this->assertEqual(1e-4, $DB->get_field($tablename, 'onechar', array('id' => $id))); 02574 $DB->set_field($tablename, 'onechar', 1e-5, array('id' => $id)); 02575 $this->assertEqual(1e-5, $DB->get_field($tablename, 'onechar', array('id' => $id))); 02576 $DB->set_field($tablename, 'onechar', 1e-300, array('id' => $id)); 02577 $this->assertEqual(1e-300, $DB->get_field($tablename, 'onechar', array('id' => $id))); 02578 $DB->set_field($tablename, 'onechar', 1e300, array('id' => $id)); 02579 $this->assertEqual(1e300, $DB->get_field($tablename, 'onechar', array('id' => $id))); 02580 02581 // Test saving a float in a TEXT column, and reading it back. 02582 $id = $DB->insert_record($tablename, array('onetext' => 'X')); 02583 $DB->set_field($tablename, 'onetext', 1.0, array('id' => $id)); 02584 $this->assertEqual(1.0, $DB->get_field($tablename, 'onetext', array('id' => $id))); 02585 $DB->set_field($tablename, 'onetext', 1e20, array('id' => $id)); 02586 $this->assertEqual(1e20, $DB->get_field($tablename, 'onetext', array('id' => $id))); 02587 $DB->set_field($tablename, 'onetext', 1e-4, array('id' => $id)); 02588 $this->assertEqual(1e-4, $DB->get_field($tablename, 'onetext', array('id' => $id))); 02589 $DB->set_field($tablename, 'onetext', 1e-5, array('id' => $id)); 02590 $this->assertEqual(1e-5, $DB->get_field($tablename, 'onetext', array('id' => $id))); 02591 $DB->set_field($tablename, 'onetext', 1e-300, array('id' => $id)); 02592 $this->assertEqual(1e-300, $DB->get_field($tablename, 'onetext', array('id' => $id))); 02593 $DB->set_field($tablename, 'onetext', 1e300, array('id' => $id)); 02594 $this->assertEqual(1e300, $DB->get_field($tablename, 'onetext', array('id' => $id))); 02595 02596 // Note: All the nulls, booleans, empties, quoted and backslashes tests 02597 // go to set_field_select() because set_field() is just one wrapper over it 02598 } 02599 02600 public function test_set_field_select() { 02601 02602 // All the information in this test is fetched from DB by get_field() so we 02603 // have such method properly tested against nulls, empties and friends... 02604 02605 $DB = $this->tdb; 02606 $dbman = $DB->get_manager(); 02607 02608 $table = $this->get_test_table(); 02609 $tablename = $table->getName(); 02610 02611 $table->add_field('id', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, XMLDB_SEQUENCE, null); 02612 $table->add_field('course', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '0'); 02613 $table->add_field('oneint', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, null, null); 02614 $table->add_field('onenum', XMLDB_TYPE_NUMBER, '10,2', null, null, null); 02615 $table->add_field('onechar', XMLDB_TYPE_CHAR, '100', null, null, null); 02616 $table->add_field('onetext', XMLDB_TYPE_TEXT, 'big', null, null, null); 02617 $table->add_field('onebinary', XMLDB_TYPE_BINARY, 'big', null, null, null); 02618 $table->add_key('primary', XMLDB_KEY_PRIMARY, array('id')); 02619 $dbman->create_table($table); 02620 02621 $DB->insert_record($tablename, array('course' => 1)); 02622 02623 $this->assertTrue($DB->set_field_select($tablename, 'course', 2, 'id = ?', array(1))); 02624 $this->assertEqual(2, $DB->get_field($tablename, 'course', array('id' => 1))); 02625 02626 // Check nulls are set properly for all types 02627 $DB->set_field_select($tablename, 'oneint', null, 'id = ?', array(1)); // trues 02628 $DB->set_field_select($tablename, 'onenum', null, 'id = ?', array(1)); 02629 $DB->set_field_select($tablename, 'onechar', null, 'id = ?', array(1)); 02630 $DB->set_field_select($tablename, 'onetext', null, 'id = ?', array(1)); 02631 $DB->set_field_select($tablename, 'onebinary', null, 'id = ?', array(1)); 02632 $this->assertNull($DB->get_field($tablename, 'oneint', array('id' => 1))); 02633 $this->assertNull($DB->get_field($tablename, 'onenum', array('id' => 1))); 02634 $this->assertNull($DB->get_field($tablename, 'onechar', array('id' => 1))); 02635 $this->assertNull($DB->get_field($tablename, 'onetext', array('id' => 1))); 02636 $this->assertNull($DB->get_field($tablename, 'onebinary', array('id' => 1))); 02637 02638 // Check zeros are set properly for all types 02639 $DB->set_field_select($tablename, 'oneint', 0, 'id = ?', array(1)); 02640 $DB->set_field_select($tablename, 'onenum', 0, 'id = ?', array(1)); 02641 $this->assertEqual(0, $DB->get_field($tablename, 'oneint', array('id' => 1))); 02642 $this->assertEqual(0, $DB->get_field($tablename, 'onenum', array('id' => 1))); 02643 02644 // Check booleans are set properly for all types 02645 $DB->set_field_select($tablename, 'oneint', true, 'id = ?', array(1)); // trues 02646 $DB->set_field_select($tablename, 'onenum', true, 'id = ?', array(1)); 02647 $DB->set_field_select($tablename, 'onechar', true, 'id = ?', array(1)); 02648 $DB->set_field_select($tablename, 'onetext', true, 'id = ?', array(1)); 02649 $this->assertEqual(1, $DB->get_field($tablename, 'oneint', array('id' => 1))); 02650 $this->assertEqual(1, $DB->get_field($tablename, 'onenum', array('id' => 1))); 02651 $this->assertEqual(1, $DB->get_field($tablename, 'onechar', array('id' => 1))); 02652 $this->assertEqual(1, $DB->get_field($tablename, 'onetext', array('id' => 1))); 02653 02654 $DB->set_field_select($tablename, 'oneint', false, 'id = ?', array(1)); // falses 02655 $DB->set_field_select($tablename, 'onenum', false, 'id = ?', array(1)); 02656 $DB->set_field_select($tablename, 'onechar', false, 'id = ?', array(1)); 02657 $DB->set_field_select($tablename, 'onetext', false, 'id = ?', array(1)); 02658 $this->assertEqual(0, $DB->get_field($tablename, 'oneint', array('id' => 1))); 02659 $this->assertEqual(0, $DB->get_field($tablename, 'onenum', array('id' => 1))); 02660 $this->assertEqual(0, $DB->get_field($tablename, 'onechar', array('id' => 1))); 02661 $this->assertEqual(0, $DB->get_field($tablename, 'onetext', array('id' => 1))); 02662 02663 // Check string data causes exception in numeric types 02664 try { 02665 $DB->set_field_select($tablename, 'oneint', 'onestring', 'id = ?', array(1)); 02666 $this->fail("Expecting an exception, none occurred"); 02667 } catch (exception $e) { 02668 $this->assertTrue($e instanceof dml_exception); 02669 } 02670 try { 02671 $DB->set_field_select($tablename, 'onenum', 'onestring', 'id = ?', array(1)); 02672 $this->fail("Expecting an exception, none occurred"); 02673 } catch (exception $e) { 02674 $this->assertTrue($e instanceof dml_exception); 02675 } 02676 02677 // Check empty string data is stored as 0 in numeric datatypes 02678 $DB->set_field_select($tablename, 'oneint', '', 'id = ?', array(1)); 02679 $field = $DB->get_field($tablename, 'oneint', array('id' => 1)); 02680 $this->assertTrue(is_numeric($field) && $field == 0); 02681 02682 $DB->set_field_select($tablename, 'onenum', '', 'id = ?', array(1)); 02683 $field = $DB->get_field($tablename, 'onenum', array('id' => 1)); 02684 $this->assertTrue(is_numeric($field) && $field == 0); 02685 02686 // Check empty strings are set properly in string types 02687 $DB->set_field_select($tablename, 'onechar', '', 'id = ?', array(1)); 02688 $DB->set_field_select($tablename, 'onetext', '', 'id = ?', array(1)); 02689 $this->assertTrue($DB->get_field($tablename, 'onechar', array('id' => 1)) === ''); 02690 $this->assertTrue($DB->get_field($tablename, 'onetext', array('id' => 1)) === ''); 02691 02692 // Check operation ((210.10 + 39.92) - 150.02) against numeric types 02693 $DB->set_field_select($tablename, 'oneint', ((210.10 + 39.92) - 150.02), 'id = ?', array(1)); 02694 $DB->set_field_select($tablename, 'onenum', ((210.10 + 39.92) - 150.02), 'id = ?', array(1)); 02695 $this->assertEqual(100, $DB->get_field($tablename, 'oneint', array('id' => 1))); 02696 $this->assertEqual(100, $DB->get_field($tablename, 'onenum', array('id' => 1))); 02697 02698 // Check various quotes/backslashes combinations in string types 02699 $teststrings = array( 02700 'backslashes and quotes alone (even): "" \'\' \\\\', 02701 'backslashes and quotes alone (odd): """ \'\'\' \\\\\\', 02702 'backslashes and quotes sequences (even): \\"\\" \\\'\\\'', 02703 'backslashes and quotes sequences (odd): \\"\\"\\" \\\'\\\'\\\''); 02704 foreach ($teststrings as $teststring) { 02705 $DB->set_field_select($tablename, 'onechar', $teststring, 'id = ?', array(1)); 02706 $DB->set_field_select($tablename, 'onetext', $teststring, 'id = ?', array(1)); 02707 $this->assertEqual($teststring, $DB->get_field($tablename, 'onechar', array('id' => 1))); 02708 $this->assertEqual($teststring, $DB->get_field($tablename, 'onetext', array('id' => 1))); 02709 } 02710 02711 // Check LOBs in text/binary columns 02712 $clob = file_get_contents(dirname(__FILE__).'/fixtures/clob.txt'); 02713 $blob = file_get_contents(dirname(__FILE__).'/fixtures/randombinary'); 02714 $DB->set_field_select($tablename, 'onetext', $clob, 'id = ?', array(1)); 02715 $DB->set_field_select($tablename, 'onebinary', $blob, 'id = ?', array(1)); 02716 $this->assertEqual($clob, $DB->get_field($tablename, 'onetext', array('id' => 1)), 'Test CLOB set_field (full contents output disabled)'); 02717 $this->assertEqual($blob, $DB->get_field($tablename, 'onebinary', array('id' => 1)), 'Test BLOB set_field (full contents output disabled)'); 02718 02719 // And "small" LOBs too, just in case 02720 $newclob = substr($clob, 0, 500); 02721 $newblob = substr($blob, 0, 250); 02722 $DB->set_field_select($tablename, 'onetext', $newclob, 'id = ?', array(1)); 02723 $DB->set_field_select($tablename, 'onebinary', $newblob, 'id = ?', array(1)); 02724 $this->assertEqual($newclob, $DB->get_field($tablename, 'onetext', array('id' => 1)), 'Test "small" CLOB set_field (full contents output disabled)'); 02725 $this->assertEqual($newblob, $DB->get_field($tablename, 'onebinary', array('id' => 1)), 'Test "small" BLOB set_field (full contents output disabled)'); 02726 02727 // This is the failure from MDL-24863. This was giving an error on MSSQL, 02728 // which converts the '1' to an integer, which cannot then be compared with 02729 // onetext cast to a varchar. This should be fixed and working now. 02730 $newchar = 'frog'; 02731 // test for exception throwing on text conditions being compared. (MDL-24863, unwanted auto conversion of param to int) 02732 $params = array('onetext' => '1'); 02733 try { 02734 $DB->set_field_select($tablename, 'onechar', $newchar, $DB->sql_compare_text('onetext') . ' = ?', $params); 02735 $this->assertTrue(true, 'No exceptions thrown with numerical text param comparison for text field.'); 02736 } catch (dml_exception $e) { 02737 $this->assertFalse(true, 'We have an unexpected exception.'); 02738 throw $e; 02739 } 02740 02741 02742 } 02743 02744 public function test_count_records() { 02745 $DB = $this->tdb; 02746 02747 $dbman = $DB->get_manager(); 02748 02749 $table = $this->get_test_table(); 02750 $tablename = $table->getName(); 02751 02752 $table->add_field('id', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, XMLDB_SEQUENCE, null); 02753 $table->add_field('course', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '0'); 02754 $table->add_field('onetext', XMLDB_TYPE_TEXT, 'big', null, null, null); 02755 $table->add_key('primary', XMLDB_KEY_PRIMARY, array('id')); 02756 $dbman->create_table($table); 02757 02758 $this->assertEqual(0, $DB->count_records($tablename)); 02759 02760 $DB->insert_record($tablename, array('course' => 3)); 02761 $DB->insert_record($tablename, array('course' => 4)); 02762 $DB->insert_record($tablename, array('course' => 5)); 02763 02764 $this->assertEqual(3, $DB->count_records($tablename)); 02765 02766 // test for exception throwing on text conditions being compared. (MDL-24863, unwanted auto conversion of param to int) 02767 $conditions = array('onetext' => '1'); 02768 try { 02769 $DB->count_records($tablename, $conditions); 02770 if (debugging()) { 02771 // only in debug mode - hopefully all devs test code in debug mode... 02772 $this->fail('An Exception is missing, expected due to equating of text fields'); 02773 } 02774 } catch (exception $e) { 02775 $this->assertTrue($e instanceof dml_exception); 02776 $this->assertEqual($e->errorcode, 'textconditionsnotallowed'); 02777 } 02778 } 02779 02780 public function test_count_records_select() { 02781 $DB = $this->tdb; 02782 02783 $dbman = $DB->get_manager(); 02784 02785 $table = $this->get_test_table(); 02786 $tablename = $table->getName(); 02787 02788 $table->add_field('id', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, XMLDB_SEQUENCE, null); 02789 $table->add_field('course', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '0'); 02790 $table->add_key('primary', XMLDB_KEY_PRIMARY, array('id')); 02791 $dbman->create_table($table); 02792 02793 $this->assertEqual(0, $DB->count_records($tablename)); 02794 02795 $DB->insert_record($tablename, array('course' => 3)); 02796 $DB->insert_record($tablename, array('course' => 4)); 02797 $DB->insert_record($tablename, array('course' => 5)); 02798 02799 $this->assertEqual(2, $DB->count_records_select($tablename, 'course > ?', array(3))); 02800 } 02801 02802 public function test_count_records_sql() { 02803 $DB = $this->tdb; 02804 $dbman = $DB->get_manager(); 02805 02806 $table = $this->get_test_table(); 02807 $tablename = $table->getName(); 02808 02809 $table->add_field('id', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, XMLDB_SEQUENCE, null); 02810 $table->add_field('course', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '0'); 02811 $table->add_key('primary', XMLDB_KEY_PRIMARY, array('id')); 02812 $dbman->create_table($table); 02813 02814 $this->assertEqual(0, $DB->count_records($tablename)); 02815 02816 $DB->insert_record($tablename, array('course' => 3)); 02817 $DB->insert_record($tablename, array('course' => 4)); 02818 $DB->insert_record($tablename, array('course' => 5)); 02819 02820 $this->assertEqual(2, $DB->count_records_sql("SELECT COUNT(*) FROM {{$tablename}} WHERE course > ?", array(3))); 02821 } 02822 02823 public function test_record_exists() { 02824 $DB = $this->tdb; 02825 $dbman = $DB->get_manager(); 02826 02827 $table = $this->get_test_table(); 02828 $tablename = $table->getName(); 02829 02830 $table->add_field('id', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, XMLDB_SEQUENCE, null); 02831 $table->add_field('course', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '0'); 02832 $table->add_field('onetext', XMLDB_TYPE_TEXT, 'big', null, null, null); 02833 $table->add_key('primary', XMLDB_KEY_PRIMARY, array('id')); 02834 $dbman->create_table($table); 02835 02836 $this->assertEqual(0, $DB->count_records($tablename)); 02837 02838 $this->assertFalse($DB->record_exists($tablename, array('course' => 3))); 02839 $DB->insert_record($tablename, array('course' => 3)); 02840 02841 $this->assertTrue($DB->record_exists($tablename, array('course' => 3))); 02842 02843 02844 // test for exception throwing on text conditions being compared. (MDL-24863, unwanted auto conversion of param to int) 02845 $conditions = array('onetext' => '1'); 02846 try { 02847 $DB->record_exists($tablename, $conditions); 02848 if (debugging()) { 02849 // only in debug mode - hopefully all devs test code in debug mode... 02850 $this->fail('An Exception is missing, expected due to equating of text fields'); 02851 } 02852 } catch (exception $e) { 02853 $this->assertTrue($e instanceof dml_exception); 02854 $this->assertEqual($e->errorcode, 'textconditionsnotallowed'); 02855 } 02856 } 02857 02858 public function test_record_exists_select() { 02859 $DB = $this->tdb; 02860 $dbman = $DB->get_manager(); 02861 02862 $table = $this->get_test_table(); 02863 $tablename = $table->getName(); 02864 02865 $table->add_field('id', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, XMLDB_SEQUENCE, null); 02866 $table->add_field('course', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '0'); 02867 $table->add_key('primary', XMLDB_KEY_PRIMARY, array('id')); 02868 $dbman->create_table($table); 02869 02870 $this->assertEqual(0, $DB->count_records($tablename)); 02871 02872 $this->assertFalse($DB->record_exists_select($tablename, "course = ?", array(3))); 02873 $DB->insert_record($tablename, array('course' => 3)); 02874 02875 $this->assertTrue($DB->record_exists_select($tablename, "course = ?", array(3))); 02876 } 02877 02878 public function test_record_exists_sql() { 02879 $DB = $this->tdb; 02880 $dbman = $DB->get_manager(); 02881 02882 $table = $this->get_test_table(); 02883 $tablename = $table->getName(); 02884 02885 $table->add_field('id', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, XMLDB_SEQUENCE, null); 02886 $table->add_field('course', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '0'); 02887 $table->add_key('primary', XMLDB_KEY_PRIMARY, array('id')); 02888 $dbman->create_table($table); 02889 02890 $this->assertEqual(0, $DB->count_records($tablename)); 02891 02892 $this->assertFalse($DB->record_exists_sql("SELECT * FROM {{$tablename}} WHERE course = ?", array(3))); 02893 $DB->insert_record($tablename, array('course' => 3)); 02894 02895 $this->assertTrue($DB->record_exists_sql("SELECT * FROM {{$tablename}} WHERE course = ?", array(3))); 02896 } 02897 02898 public function test_recordset_locks_delete() { 02899 $DB = $this->tdb; 02900 $dbman = $DB->get_manager(); 02901 02902 //Setup 02903 $table = $this->get_test_table(); 02904 $tablename = $table->getName(); 02905 02906 $table->add_field('id', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, XMLDB_SEQUENCE, null); 02907 $table->add_field('course', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '0'); 02908 $table->add_key('primary', XMLDB_KEY_PRIMARY, array('id')); 02909 $dbman->create_table($table); 02910 02911 $DB->insert_record($tablename, array('course' => 1)); 02912 $DB->insert_record($tablename, array('course' => 2)); 02913 $DB->insert_record($tablename, array('course' => 3)); 02914 $DB->insert_record($tablename, array('course' => 4)); 02915 $DB->insert_record($tablename, array('course' => 5)); 02916 $DB->insert_record($tablename, array('course' => 6)); 02917 02918 // Test against db write locking while on an open recordset 02919 $rs = $DB->get_recordset($tablename, array(), null, 'course', 2, 2); // get courses = {3,4} 02920 foreach ($rs as $record) { 02921 $cid = $record->course; 02922 $DB->delete_records($tablename, array('course' => $cid)); 02923 $this->assertFalse($DB->record_exists($tablename, array('course' => $cid))); 02924 } 02925 $rs->close(); 02926 02927 $this->assertEqual(4, $DB->count_records($tablename, array())); 02928 } 02929 02930 public function test_recordset_locks_update() { 02931 $DB = $this->tdb; 02932 $dbman = $DB->get_manager(); 02933 02934 //Setup 02935 $table = $this->get_test_table(); 02936 $tablename = $table->getName(); 02937 02938 $table->add_field('id', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, XMLDB_SEQUENCE, null); 02939 $table->add_field('course', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '0'); 02940 $table->add_key('primary', XMLDB_KEY_PRIMARY, array('id')); 02941 $dbman->create_table($table); 02942 02943 $DB->insert_record($tablename, array('course' => 1)); 02944 $DB->insert_record($tablename, array('course' => 2)); 02945 $DB->insert_record($tablename, array('course' => 3)); 02946 $DB->insert_record($tablename, array('course' => 4)); 02947 $DB->insert_record($tablename, array('course' => 5)); 02948 $DB->insert_record($tablename, array('course' => 6)); 02949 02950 // Test against db write locking while on an open recordset 02951 $rs = $DB->get_recordset($tablename, array(), null, 'course', 2, 2); // get courses = {3,4} 02952 foreach ($rs as $record) { 02953 $cid = $record->course; 02954 $DB->set_field($tablename, 'course', 10, array('course' => $cid)); 02955 $this->assertFalse($DB->record_exists($tablename, array('course' => $cid))); 02956 } 02957 $rs->close(); 02958 02959 $this->assertEqual(2, $DB->count_records($tablename, array('course' => 10))); 02960 } 02961 02962 public function test_delete_records() { 02963 $DB = $this->tdb; 02964 $dbman = $DB->get_manager(); 02965 02966 $table = $this->get_test_table(); 02967 $tablename = $table->getName(); 02968 02969 $table->add_field('id', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, XMLDB_SEQUENCE, null); 02970 $table->add_field('course', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '0'); 02971 $table->add_field('onetext', XMLDB_TYPE_TEXT, 'big', null, null, null); 02972 $table->add_key('primary', XMLDB_KEY_PRIMARY, array('id')); 02973 $dbman->create_table($table); 02974 02975 $DB->insert_record($tablename, array('course' => 3)); 02976 $DB->insert_record($tablename, array('course' => 2)); 02977 $DB->insert_record($tablename, array('course' => 2)); 02978 02979 // Delete all records 02980 $this->assertTrue($DB->delete_records($tablename)); 02981 $this->assertEqual(0, $DB->count_records($tablename)); 02982 02983 // Delete subset of records 02984 $DB->insert_record($tablename, array('course' => 3)); 02985 $DB->insert_record($tablename, array('course' => 2)); 02986 $DB->insert_record($tablename, array('course' => 2)); 02987 02988 $this->assertTrue($DB->delete_records($tablename, array('course' => 2))); 02989 $this->assertEqual(1, $DB->count_records($tablename)); 02990 02991 // delete all 02992 $this->assertTrue($DB->delete_records($tablename, array())); 02993 $this->assertEqual(0, $DB->count_records($tablename)); 02994 02995 // test for exception throwing on text conditions being compared. (MDL-24863, unwanted auto conversion of param to int) 02996 $conditions = array('onetext'=>'1'); 02997 try { 02998 $DB->delete_records($tablename, $conditions); 02999 if (debugging()) { 03000 // only in debug mode - hopefully all devs test code in debug mode... 03001 $this->fail('An Exception is missing, expected due to equating of text fields'); 03002 } 03003 } catch (exception $e) { 03004 $this->assertTrue($e instanceof dml_exception); 03005 $this->assertEqual($e->errorcode, 'textconditionsnotallowed'); 03006 } 03007 03008 // test for exception throwing on text conditions being compared. (MDL-24863, unwanted auto conversion of param to int) 03009 $conditions = array('onetext' => 1); 03010 try { 03011 $DB->delete_records($tablename, $conditions); 03012 if (debugging()) { 03013 // only in debug mode - hopefully all devs test code in debug mode... 03014 $this->fail('An Exception is missing, expected due to equating of text fields'); 03015 } 03016 } catch (exception $e) { 03017 $this->assertTrue($e instanceof dml_exception); 03018 $this->assertEqual($e->errorcode, 'textconditionsnotallowed'); 03019 } 03020 } 03021 03022 public function test_delete_records_select() { 03023 $DB = $this->tdb; 03024 $dbman = $DB->get_manager(); 03025 03026 $table = $this->get_test_table(); 03027 $tablename = $table->getName(); 03028 03029 $table->add_field('id', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, XMLDB_SEQUENCE, null); 03030 $table->add_field('course', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '0'); 03031 $table->add_key('primary', XMLDB_KEY_PRIMARY, array('id')); 03032 $dbman->create_table($table); 03033 03034 $DB->insert_record($tablename, array('course' => 3)); 03035 $DB->insert_record($tablename, array('course' => 2)); 03036 $DB->insert_record($tablename, array('course' => 2)); 03037 03038 $this->assertTrue($DB->delete_records_select($tablename, 'course = ?', array(2))); 03039 $this->assertEqual(1, $DB->count_records($tablename)); 03040 } 03041 03042 public function test_delete_records_list() { 03043 $DB = $this->tdb; 03044 $dbman = $DB->get_manager(); 03045 03046 $table = $this->get_test_table(); 03047 $tablename = $table->getName(); 03048 03049 $table->add_field('id', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, XMLDB_SEQUENCE, null); 03050 $table->add_field('course', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '0'); 03051 $table->add_key('primary', XMLDB_KEY_PRIMARY, array('id')); 03052 $dbman->create_table($table); 03053 03054 $DB->insert_record($tablename, array('course' => 1)); 03055 $DB->insert_record($tablename, array('course' => 2)); 03056 $DB->insert_record($tablename, array('course' => 3)); 03057 03058 $this->assertTrue($DB->delete_records_list($tablename, 'course', array(2, 3))); 03059 $this->assertEqual(1, $DB->count_records($tablename)); 03060 03061 $this->assertTrue($DB->delete_records_list($tablename, 'course', array())); 03062 $this->assertEqual(1, $DB->count_records($tablename)); 03063 } 03064 03065 function test_sql_null_from_clause() { 03066 $DB = $this->tdb; 03067 $sql = "SELECT 1 AS id ".$DB->sql_null_from_clause(); 03068 $this->assertEqual($DB->get_field_sql($sql), 1); 03069 } 03070 03071 function test_sql_bitand() { 03072 $DB = $this->tdb; 03073 $dbman = $DB->get_manager(); 03074 03075 $table = $this->get_test_table(); 03076 $tablename = $table->getName(); 03077 03078 $table->add_field('id', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, XMLDB_SEQUENCE, null); 03079 $table->add_field('col1', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '0'); 03080 $table->add_field('col2', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '0'); 03081 $table->add_key('primary', XMLDB_KEY_PRIMARY, array('id')); 03082 $dbman->create_table($table); 03083 03084 $DB->insert_record($tablename, array('col1' => 3, 'col2' => 10)); 03085 03086 $sql = "SELECT ".$DB->sql_bitand(10, 3)." AS res ".$DB->sql_null_from_clause(); 03087 $this->assertEqual($DB->get_field_sql($sql), 2); 03088 03089 $sql = "SELECT id, ".$DB->sql_bitand('col1', 'col2')." AS res FROM {{$tablename}}"; 03090 $result = $DB->get_records_sql($sql); 03091 $this->assertEqual(count($result), 1); 03092 $this->assertEqual(reset($result)->res, 2); 03093 03094 $sql = "SELECT id, ".$DB->sql_bitand('col1', '?')." AS res FROM {{$tablename}}"; 03095 $result = $DB->get_records_sql($sql, array(10)); 03096 $this->assertEqual(count($result), 1); 03097 $this->assertEqual(reset($result)->res, 2); 03098 } 03099 03100 function test_sql_bitnot() { 03101 $DB = $this->tdb; 03102 03103 $not = $DB->sql_bitnot(2); 03104 $notlimited = $DB->sql_bitand($not, 7); // might be positive or negative number which can not fit into PHP INT! 03105 03106 $sql = "SELECT $notlimited AS res ".$DB->sql_null_from_clause(); 03107 $this->assertEqual($DB->get_field_sql($sql), 5); 03108 } 03109 03110 function test_sql_bitor() { 03111 $DB = $this->tdb; 03112 $dbman = $DB->get_manager(); 03113 03114 $table = $this->get_test_table(); 03115 $tablename = $table->getName(); 03116 03117 $table->add_field('id', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, XMLDB_SEQUENCE, null); 03118 $table->add_field('col1', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '0'); 03119 $table->add_field('col2', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '0'); 03120 $table->add_key('primary', XMLDB_KEY_PRIMARY, array('id')); 03121 $dbman->create_table($table); 03122 03123 $DB->insert_record($tablename, array('col1' => 3, 'col2' => 10)); 03124 03125 $sql = "SELECT ".$DB->sql_bitor(10, 3)." AS res ".$DB->sql_null_from_clause(); 03126 $this->assertEqual($DB->get_field_sql($sql), 11); 03127 03128 $sql = "SELECT id, ".$DB->sql_bitor('col1', 'col2')." AS res FROM {{$tablename}}"; 03129 $result = $DB->get_records_sql($sql); 03130 $this->assertEqual(count($result), 1); 03131 $this->assertEqual(reset($result)->res, 11); 03132 03133 $sql = "SELECT id, ".$DB->sql_bitor('col1', '?')." AS res FROM {{$tablename}}"; 03134 $result = $DB->get_records_sql($sql, array(10)); 03135 $this->assertEqual(count($result), 1); 03136 $this->assertEqual(reset($result)->res, 11); 03137 } 03138 03139 function test_sql_bitxor() { 03140 $DB = $this->tdb; 03141 $dbman = $DB->get_manager(); 03142 03143 $table = $this->get_test_table(); 03144 $tablename = $table->getName(); 03145 03146 $table->add_field('id', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, XMLDB_SEQUENCE, null); 03147 $table->add_field('col1', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '0'); 03148 $table->add_field('col2', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '0'); 03149 $table->add_key('primary', XMLDB_KEY_PRIMARY, array('id')); 03150 $dbman->create_table($table); 03151 03152 $DB->insert_record($tablename, array('col1' => 3, 'col2' => 10)); 03153 03154 $sql = "SELECT ".$DB->sql_bitxor(10, 3)." AS res ".$DB->sql_null_from_clause(); 03155 $this->assertEqual($DB->get_field_sql($sql), 9); 03156 03157 $sql = "SELECT id, ".$DB->sql_bitxor('col1', 'col2')." AS res FROM {{$tablename}}"; 03158 $result = $DB->get_records_sql($sql); 03159 $this->assertEqual(count($result), 1); 03160 $this->assertEqual(reset($result)->res, 9); 03161 03162 $sql = "SELECT id, ".$DB->sql_bitxor('col1', '?')." AS res FROM {{$tablename}}"; 03163 $result = $DB->get_records_sql($sql, array(10)); 03164 $this->assertEqual(count($result), 1); 03165 $this->assertEqual(reset($result)->res, 9); 03166 } 03167 03168 function test_sql_modulo() { 03169 $DB = $this->tdb; 03170 $sql = "SELECT ".$DB->sql_modulo(10, 7)." AS res ".$DB->sql_null_from_clause(); 03171 $this->assertEqual($DB->get_field_sql($sql), 3); 03172 } 03173 03174 function test_sql_ceil() { 03175 $DB = $this->tdb; 03176 $sql = "SELECT ".$DB->sql_ceil(665.666)." AS res ".$DB->sql_null_from_clause(); 03177 $this->assertEqual($DB->get_field_sql($sql), 666); 03178 } 03179 03180 function test_cast_char2int() { 03181 $DB = $this->tdb; 03182 $dbman = $DB->get_manager(); 03183 03184 $table1 = $this->get_test_table("1"); 03185 $tablename1 = $table1->getName(); 03186 03187 $table1->add_field('id', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, XMLDB_SEQUENCE, null); 03188 $table1->add_field('name', XMLDB_TYPE_CHAR, '255', null, null, null, null); 03189 $table1->add_field('nametext', XMLDB_TYPE_TEXT, 'small', null, null, null, null); 03190 $table1->add_key('primary', XMLDB_KEY_PRIMARY, array('id')); 03191 $dbman->create_table($table1); 03192 03193 $DB->insert_record($tablename1, array('name'=>'0100', 'nametext'=>'0200')); 03194 $DB->insert_record($tablename1, array('name'=>'10', 'nametext'=>'20')); 03195 03196 $table2 = $this->get_test_table("2"); 03197 $tablename2 = $table2->getName(); 03198 $table2->add_field('id', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, XMLDB_SEQUENCE, null); 03199 $table2->add_field('res', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '0'); 03200 $table2->add_field('restext', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '0'); 03201 $table2->add_key('primary', XMLDB_KEY_PRIMARY, array('id')); 03202 $dbman->create_table($table2); 03203 03204 $DB->insert_record($tablename2, array('res'=>100, 'restext'=>200)); 03205 03206 // casting varchar field 03207 $sql = "SELECT * 03208 FROM {".$tablename1."} t1 03209 JOIN {".$tablename2."} t2 ON ".$DB->sql_cast_char2int("t1.name")." = t2.res "; 03210 $records = $DB->get_records_sql($sql); 03211 $this->assertEqual(count($records), 1); 03212 // also test them in order clauses 03213 $sql = "SELECT * FROM {{$tablename1}} ORDER BY ".$DB->sql_cast_char2int('name'); 03214 $records = $DB->get_records_sql($sql); 03215 $this->assertEqual(count($records), 2); 03216 $this->assertEqual(reset($records)->name, '10'); 03217 $this->assertEqual(next($records)->name, '0100'); 03218 03219 // casting text field 03220 $sql = "SELECT * 03221 FROM {".$tablename1."} t1 03222 JOIN {".$tablename2."} t2 ON ".$DB->sql_cast_char2int("t1.nametext", true)." = t2.restext "; 03223 $records = $DB->get_records_sql($sql); 03224 $this->assertEqual(count($records), 1); 03225 // also test them in order clauses 03226 $sql = "SELECT * FROM {{$tablename1}} ORDER BY ".$DB->sql_cast_char2int('nametext', true); 03227 $records = $DB->get_records_sql($sql); 03228 $this->assertEqual(count($records), 2); 03229 $this->assertEqual(reset($records)->nametext, '20'); 03230 $this->assertEqual(next($records)->nametext, '0200'); 03231 } 03232 03233 function test_cast_char2real() { 03234 $DB = $this->tdb; 03235 $dbman = $DB->get_manager(); 03236 03237 $table = $this->get_test_table(); 03238 $tablename = $table->getName(); 03239 03240 $table->add_field('id', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, XMLDB_SEQUENCE, null); 03241 $table->add_field('name', XMLDB_TYPE_CHAR, '255', null, null, null, null); 03242 $table->add_field('nametext', XMLDB_TYPE_TEXT, 'small', null, null, null, null); 03243 $table->add_field('res', XMLDB_TYPE_NUMBER, '12, 7', null, null, null, null); 03244 $table->add_key('primary', XMLDB_KEY_PRIMARY, array('id')); 03245 $dbman->create_table($table); 03246 03247 $DB->insert_record($tablename, array('name'=>'10.10', 'nametext'=>'10.10', 'res'=>5.1)); 03248 $DB->insert_record($tablename, array('name'=>'91.10', 'nametext'=>'91.10', 'res'=>666)); 03249 $DB->insert_record($tablename, array('name'=>'011.10','nametext'=>'011.10','res'=>10.1)); 03250 03251 // casting varchar field 03252 $sql = "SELECT * FROM {{$tablename}} WHERE ".$DB->sql_cast_char2real('name')." > res"; 03253 $records = $DB->get_records_sql($sql); 03254 $this->assertEqual(count($records), 2); 03255 // also test them in order clauses 03256 $sql = "SELECT * FROM {{$tablename}} ORDER BY ".$DB->sql_cast_char2real('name'); 03257 $records = $DB->get_records_sql($sql); 03258 $this->assertEqual(count($records), 3); 03259 $this->assertEqual(reset($records)->name, '10.10'); 03260 $this->assertEqual(next($records)->name, '011.10'); 03261 $this->assertEqual(next($records)->name, '91.10'); 03262 03263 // casting text field 03264 $sql = "SELECT * FROM {{$tablename}} WHERE ".$DB->sql_cast_char2real('nametext', true)." > res"; 03265 $records = $DB->get_records_sql($sql); 03266 $this->assertEqual(count($records), 2); 03267 // also test them in order clauses 03268 $sql = "SELECT * FROM {{$tablename}} ORDER BY ".$DB->sql_cast_char2real('nametext', true); 03269 $records = $DB->get_records_sql($sql); 03270 $this->assertEqual(count($records), 3); 03271 $this->assertEqual(reset($records)->nametext, '10.10'); 03272 $this->assertEqual(next($records)->nametext, '011.10'); 03273 $this->assertEqual(next($records)->nametext, '91.10'); 03274 } 03275 03276 function sql_compare_text() { 03277 $DB = $this->tdb; 03278 $dbman = $DB->get_manager(); 03279 03280 $table = $this->get_test_table(); 03281 $tablename = $table->getName(); 03282 03283 $table->add_field('id', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, XMLDB_SEQUENCE, null); 03284 $table->add_field('name', XMLDB_TYPE_CHAR, '255', null, null, null, null); 03285 $table->add_field('description', XMLDB_TYPE_TEXT, 'big', null, null, null, null); 03286 $table->add_key('primary', XMLDB_KEY_PRIMARY, array('id')); 03287 $dbman->create_table($table); 03288 03289 $DB->insert_record($tablename, array('name'=>'abcd', 'description'=>'abcd')); 03290 $DB->insert_record($tablename, array('name'=>'abcdef', 'description'=>'bbcdef')); 03291 $DB->insert_record($tablename, array('name'=>'aaaabb', 'description'=>'aaaacccccccccccccccccc')); 03292 03293 $sql = "SELECT * FROM {{$tablename}} WHERE name = ".$DB->sql_compare_text('description'); 03294 $records = $DB->get_records_sql($sql); 03295 $this->assertEqual(count($records), 1); 03296 03297 $sql = "SELECT * FROM {{$tablename}} WHERE name = ".$DB->sql_compare_text('description', 4); 03298 $records = $DB->get_records_sql($sql); 03299 $this->assertEqual(count($records), 2); 03300 } 03301 03302 function test_unique_index_collation_trouble() { 03303 // note: this is a work in progress, we should probably move this to ddl test 03304 03305 $DB = $this->tdb; 03306 $dbman = $DB->get_manager(); 03307 03308 $table = $this->get_test_table(); 03309 $tablename = $table->getName(); 03310 03311 $table->add_field('id', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, XMLDB_SEQUENCE, null); 03312 $table->add_field('name', XMLDB_TYPE_CHAR, '255', null, null, null, null); 03313 $table->add_key('primary', XMLDB_KEY_PRIMARY, array('id')); 03314 $table->add_index('name', XMLDB_INDEX_UNIQUE, array('name')); 03315 $dbman->create_table($table); 03316 03317 $DB->insert_record($tablename, array('name'=>'aaa')); 03318 03319 try { 03320 $DB->insert_record($tablename, array('name'=>'AAA')); 03321 } catch (Exception $e) { 03322 //TODO: ignore case insensitive uniqueness problems for now 03323 //$this->fail("Unique index is case sensitive - this may cause problems in some tables"); 03324 } 03325 03326 try { 03327 $DB->insert_record($tablename, array('name'=>'aäa')); 03328 $DB->insert_record($tablename, array('name'=>'aáa')); 03329 $this->assertTrue(true); 03330 } catch (Exception $e) { 03331 $family = $DB->get_dbfamily(); 03332 if ($family === 'mysql' or $family === 'mssql') { 03333 $this->fail("Unique index is accent insensitive, this may cause problems for non-ascii languages. This is usually caused by accent insensitive default collation."); 03334 } else { 03335 // this should not happen, PostgreSQL and Oracle do not support accent insensitive uniqueness. 03336 $this->fail("Unique index is accent insensitive, this may cause problems for non-ascii languages."); 03337 } 03338 throw($e); 03339 } 03340 } 03341 03342 function test_sql_binary_equal() { 03343 $DB = $this->tdb; 03344 $dbman = $DB->get_manager(); 03345 03346 $table = $this->get_test_table(); 03347 $tablename = $table->getName(); 03348 03349 $table->add_field('id', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, XMLDB_SEQUENCE, null); 03350 $table->add_field('name', XMLDB_TYPE_CHAR, '255', null, null, null, null); 03351 $table->add_key('primary', XMLDB_KEY_PRIMARY, array('id')); 03352 $dbman->create_table($table); 03353 03354 $DB->insert_record($tablename, array('name'=>'aaa')); 03355 $DB->insert_record($tablename, array('name'=>'aáa')); 03356 $DB->insert_record($tablename, array('name'=>'aäa')); 03357 $DB->insert_record($tablename, array('name'=>'bbb')); 03358 $DB->insert_record($tablename, array('name'=>'BBB')); 03359 03360 $records = $DB->get_records_sql("SELECT * FROM {{$tablename}} WHERE name = ?", array('aaa')); 03361 $this->assertEqual(count($records), 1, 'SQL operator "=" is expected to be accent sensitive'); 03362 03363 $records = $DB->get_records_sql("SELECT * FROM {{$tablename}} WHERE name = ?", array('bbb')); 03364 $this->assertEqual(count($records), 1, 'SQL operator "=" is expected to be case sensitive'); 03365 } 03366 03367 function test_sql_like() { 03368 $DB = $this->tdb; 03369 $dbman = $DB->get_manager(); 03370 03371 $table = $this->get_test_table(); 03372 $tablename = $table->getName(); 03373 03374 $table->add_field('id', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, XMLDB_SEQUENCE, null); 03375 $table->add_field('name', XMLDB_TYPE_CHAR, '255', null, null, null, null); 03376 $table->add_key('primary', XMLDB_KEY_PRIMARY, array('id')); 03377 $dbman->create_table($table); 03378 03379 $DB->insert_record($tablename, array('name'=>'SuperDuperRecord')); 03380 $DB->insert_record($tablename, array('name'=>'Nodupor')); 03381 $DB->insert_record($tablename, array('name'=>'ouch')); 03382 $DB->insert_record($tablename, array('name'=>'ouc_')); 03383 $DB->insert_record($tablename, array('name'=>'ouc%')); 03384 $DB->insert_record($tablename, array('name'=>'aui')); 03385 $DB->insert_record($tablename, array('name'=>'aüi')); 03386 $DB->insert_record($tablename, array('name'=>'aÜi')); 03387 03388 $sql = "SELECT * FROM {{$tablename}} WHERE ".$DB->sql_like('name', '?', false); 03389 $records = $DB->get_records_sql($sql, array("%dup_r%")); 03390 $this->assertEqual(count($records), 2); 03391 03392 $sql = "SELECT * FROM {{$tablename}} WHERE ".$DB->sql_like('name', '?', true); 03393 $records = $DB->get_records_sql($sql, array("%dup%")); 03394 $this->assertEqual(count($records), 1); 03395 03396 $sql = "SELECT * FROM {{$tablename}} WHERE ".$DB->sql_like('name', '?'); // defaults 03397 $records = $DB->get_records_sql($sql, array("%dup%")); 03398 $this->assertEqual(count($records), 1); 03399 03400 $sql = "SELECT * FROM {{$tablename}} WHERE ".$DB->sql_like('name', '?', true); 03401 $records = $DB->get_records_sql($sql, array("ouc\\_")); 03402 $this->assertEqual(count($records), 1); 03403 03404 $sql = "SELECT * FROM {{$tablename}} WHERE ".$DB->sql_like('name', '?', true, true, false, '|'); 03405 $records = $DB->get_records_sql($sql, array($DB->sql_like_escape("ouc%", '|'))); 03406 $this->assertEqual(count($records), 1); 03407 03408 $sql = "SELECT * FROM {{$tablename}} WHERE ".$DB->sql_like('name', '?', true, true); 03409 $records = $DB->get_records_sql($sql, array('aui')); 03410 $this->assertEqual(count($records), 1); 03411 03412 $sql = "SELECT * FROM {{$tablename}} WHERE ".$DB->sql_like('name', '?', true, true, true); // NOT LIKE 03413 $records = $DB->get_records_sql($sql, array("%o%")); 03414 $this->assertEqual(count($records), 3); 03415 03416 $sql = "SELECT * FROM {{$tablename}} WHERE ".$DB->sql_like('name', '?', false, true, true); // NOT ILIKE 03417 $records = $DB->get_records_sql($sql, array("%D%")); 03418 $this->assertEqual(count($records), 6); 03419 03420 // TODO: we do not require accent insensitivness yet, just make sure it does not throw errors 03421 $sql = "SELECT * FROM {{$tablename}} WHERE ".$DB->sql_like('name', '?', true, false); 03422 $records = $DB->get_records_sql($sql, array('aui')); 03423 //$this->assertEqual(count($records), 2, 'Accent insensitive LIKE searches may not be supported in all databases, this is not a problem.'); 03424 $sql = "SELECT * FROM {{$tablename}} WHERE ".$DB->sql_like('name', '?', false, false); 03425 $records = $DB->get_records_sql($sql, array('aui')); 03426 //$this->assertEqual(count($records), 3, 'Accent insensitive LIKE searches may not be supported in all databases, this is not a problem.'); 03427 } 03428 03429 function test_sql_ilike() { 03430 // note: this is deprecated, just make sure it does not throw error 03431 $DB = $this->tdb; 03432 $dbman = $DB->get_manager(); 03433 03434 $table = $this->get_test_table(); 03435 $tablename = $table->getName(); 03436 03437 $table->add_field('id', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, XMLDB_SEQUENCE, null); 03438 $table->add_field('name', XMLDB_TYPE_CHAR, '255', null, null, null, null); 03439 $table->add_key('primary', XMLDB_KEY_PRIMARY, array('id')); 03440 $dbman->create_table($table); 03441 03442 $DB->insert_record($tablename, array('name'=>'SuperDuperRecord')); 03443 $DB->insert_record($tablename, array('name'=>'NoDupor')); 03444 $DB->insert_record($tablename, array('name'=>'ouch')); 03445 03446 // make sure it prints debug message 03447 $this->enable_debugging(); 03448 $sql = "SELECT * FROM {{$tablename}} WHERE name ".$DB->sql_ilike()." ?"; 03449 $params = array("%dup_r%"); 03450 $this->assertFalse($this->get_debugging() === ''); 03451 03452 // following must not throw exception, we ignore result 03453 $DB->get_records_sql($sql, $params); 03454 } 03455 03456 function test_coalesce() { 03457 $DB = $this->tdb; 03458 03459 // Testing not-null ocurrences, return 1st 03460 $sql = "SELECT COALESCE('returnthis', 'orthis', 'orwhynotthis') AS test" . $DB->sql_null_from_clause(); 03461 $this->assertEqual('returnthis', $DB->get_field_sql($sql, array())); 03462 $sql = "SELECT COALESCE(:paramvalue, 'orthis', 'orwhynotthis') AS test" . $DB->sql_null_from_clause(); 03463 $this->assertEqual('returnthis', $DB->get_field_sql($sql, array('paramvalue' => 'returnthis'))); 03464 03465 // Testing null ocurrences, return 2nd 03466 $sql = "SELECT COALESCE(null, 'returnthis', 'orthis') AS test" . $DB->sql_null_from_clause(); 03467 $this->assertEqual('returnthis', $DB->get_field_sql($sql, array())); 03468 $sql = "SELECT COALESCE(:paramvalue, 'returnthis', 'orthis') AS test" . $DB->sql_null_from_clause(); 03469 $this->assertEqual('returnthis', $DB->get_field_sql($sql, array('paramvalue' => null))); 03470 $sql = "SELECT COALESCE(null, :paramvalue, 'orthis') AS test" . $DB->sql_null_from_clause(); 03471 $this->assertEqual('returnthis', $DB->get_field_sql($sql, array('paramvalue' => 'returnthis'))); 03472 03473 // Testing null ocurrences, return 3rd 03474 $sql = "SELECT COALESCE(null, null, 'returnthis') AS test" . $DB->sql_null_from_clause(); 03475 $this->assertEqual('returnthis', $DB->get_field_sql($sql, array())); 03476 $sql = "SELECT COALESCE(null, :paramvalue, 'returnthis') AS test" . $DB->sql_null_from_clause(); 03477 $this->assertEqual('returnthis', $DB->get_field_sql($sql, array('paramvalue' => null))); 03478 $sql = "SELECT COALESCE(null, null, :paramvalue) AS test" . $DB->sql_null_from_clause(); 03479 $this->assertEqual('returnthis', $DB->get_field_sql($sql, array('paramvalue' => 'returnthis'))); 03480 03481 // Testing all null ocurrences, return null 03482 // Note: under mssql, if all elements are nulls, at least one must be a "typed" null, hence 03483 // we cannot test this in a cross-db way easily, so next 2 tests are using 03484 // different queries depending of the DB family 03485 $customnull = $DB->get_dbfamily() == 'mssql' ? 'CAST(null AS varchar)' : 'null'; 03486 $sql = "SELECT COALESCE(null, null, " . $customnull . ") AS test" . $DB->sql_null_from_clause(); 03487 $this->assertNull($DB->get_field_sql($sql, array())); 03488 $sql = "SELECT COALESCE(null, :paramvalue, " . $customnull . ") AS test" . $DB->sql_null_from_clause(); 03489 $this->assertNull($DB->get_field_sql($sql, array('paramvalue' => null))); 03490 03491 // Check there are not problems with whitespace strings 03492 $sql = "SELECT COALESCE(null, '', null) AS test" . $DB->sql_null_from_clause(); 03493 $this->assertEqual('', $DB->get_field_sql($sql, array())); 03494 $sql = "SELECT COALESCE(null, :paramvalue, null) AS test" . $DB->sql_null_from_clause(); 03495 $this->assertEqual('', $DB->get_field_sql($sql, array('paramvalue' => ''))); 03496 } 03497 03498 function test_sql_concat() { 03499 $DB = $this->tdb; 03500 $dbman = $DB->get_manager(); 03501 03503 $sql = "SELECT ".$DB->sql_concat("?", "?", "?")." AS fullname ". $DB->sql_null_from_clause(); 03504 // string, some unicode chars 03505 $params = array('name', 'áéíóú', 'name3'); 03506 $this->assertEqual('nameáéíóúname3', $DB->get_field_sql($sql, $params)); 03507 // string, spaces and numbers 03508 $params = array('name', ' ', 12345); 03509 $this->assertEqual('name 12345', $DB->get_field_sql($sql, $params)); 03510 // float, empty and strings 03511 $params = array(123.45, '', 'test'); 03512 $this->assertEqual('123.45test', $DB->get_field_sql($sql, $params)); 03513 // only integers 03514 $params = array(12, 34, 56); 03515 $this->assertEqual('123456', $DB->get_field_sql($sql, $params)); 03516 // float, null and strings 03517 $params = array(123.45, null, 'test'); 03518 $this->assertNull($DB->get_field_sql($sql, $params), 'ANSI behaviour: Concatenating NULL must return NULL - But in Oracle :-(. [%s]'); // Concatenate NULL with anything result = NULL 03519 03521 $table = $this->get_test_table(); 03522 $tablename = $table->getName(); 03523 03524 $table->add_field('id', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, XMLDB_SEQUENCE, null); 03525 $table->add_field('description', XMLDB_TYPE_TEXT, 'big', null, null, null, null); 03526 $table->add_key('primary', XMLDB_KEY_PRIMARY, array('id')); 03527 $dbman->create_table($table); 03528 03529 $DB->insert_record($tablename, array('description'=>'áéíóú')); 03530 $DB->insert_record($tablename, array('description'=>'dxxx')); 03531 $DB->insert_record($tablename, array('description'=>'bcde')); 03532 03533 // fieldnames and values mixed 03534 $sql = 'SELECT id, ' . $DB->sql_concat('description', "'harcoded'", '?', '?') . ' AS result FROM {' . $tablename . '}'; 03535 $records = $DB->get_records_sql($sql, array(123.45, 'test')); 03536 $this->assertEqual(count($records), 3); 03537 $this->assertEqual($records[1]->result, 'áéíóúharcoded123.45test'); 03538 // integer fieldnames and values 03539 $sql = 'SELECT id, ' . $DB->sql_concat('id', "'harcoded'", '?', '?') . ' AS result FROM {' . $tablename . '}'; 03540 $records = $DB->get_records_sql($sql, array(123.45, 'test')); 03541 $this->assertEqual(count($records), 3); 03542 $this->assertEqual($records[1]->result, '1harcoded123.45test'); 03543 // all integer fieldnames 03544 $sql = 'SELECT id, ' . $DB->sql_concat('id', 'id', 'id') . ' AS result FROM {' . $tablename . '}'; 03545 $records = $DB->get_records_sql($sql, array()); 03546 $this->assertEqual(count($records), 3); 03547 $this->assertEqual($records[1]->result, '111'); 03548 03549 } 03550 03551 function test_concat_join() { 03552 $DB = $this->tdb; 03553 $sql = "SELECT ".$DB->sql_concat_join("' '", array("?", "?", "?"))." AS fullname ".$DB->sql_null_from_clause(); 03554 $params = array("name", "name2", "name3"); 03555 $result = $DB->get_field_sql($sql, $params); 03556 $this->assertEqual("name name2 name3", $result); 03557 } 03558 03559 function test_sql_fullname() { 03560 $DB = $this->tdb; 03561 $sql = "SELECT ".$DB->sql_fullname(':first', ':last')." AS fullname ".$DB->sql_null_from_clause(); 03562 $params = array('first'=>'Firstname', 'last'=>'Surname'); 03563 $this->assertEqual("Firstname Surname", $DB->get_field_sql($sql, $params)); 03564 } 03565 03566 function sql_sql_order_by_text() { 03567 $DB = $this->tdb; 03568 $dbman = $DB->get_manager(); 03569 03570 $table = $this->get_test_table(); 03571 $tablename = $table->getName(); 03572 03573 $table->add_field('id', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, XMLDB_SEQUENCE, null); 03574 $table->add_field('description', XMLDB_TYPE_TEXT, 'big', null, null, null, null); 03575 $table->add_key('primary', XMLDB_KEY_PRIMARY, array('id')); 03576 $dbman->create_table($table); 03577 03578 $DB->insert_record($tablename, array('description'=>'abcd')); 03579 $DB->insert_record($tablename, array('description'=>'dxxx')); 03580 $DB->insert_record($tablename, array('description'=>'bcde')); 03581 03582 $sql = "SELECT * FROM {{$tablename}} ORDER BY ".$DB->sql_order_by_text('description'); 03583 $records = $DB->get_records_sql($sql); 03584 $first = array_shift($records); 03585 $this->assertEqual(1, $first->id); 03586 $second = array_shift($records); 03587 $this->assertEqual(3, $second->id); 03588 $last = array_shift($records); 03589 $this->assertEqual(2, $last->id); 03590 } 03591 03592 function test_sql_substring() { 03593 $DB = $this->tdb; 03594 $dbman = $DB->get_manager(); 03595 03596 $table = $this->get_test_table(); 03597 $tablename = $table->getName(); 03598 03599 $table->add_field('id', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, XMLDB_SEQUENCE, null); 03600 $table->add_field('name', XMLDB_TYPE_CHAR, '255', null, null, null, null); 03601 $table->add_key('primary', XMLDB_KEY_PRIMARY, array('id')); 03602 $dbman->create_table($table); 03603 03604 $string = 'abcdefghij'; 03605 03606 $DB->insert_record($tablename, array('name'=>$string)); 03607 03608 $sql = "SELECT id, ".$DB->sql_substr("name", 5)." AS name FROM {{$tablename}}"; 03609 $record = $DB->get_record_sql($sql); 03610 $this->assertEqual(substr($string, 5-1), $record->name); 03611 03612 $sql = "SELECT id, ".$DB->sql_substr("name", 5, 2)." AS name FROM {{$tablename}}"; 03613 $record = $DB->get_record_sql($sql); 03614 $this->assertEqual(substr($string, 5-1, 2), $record->name); 03615 03616 try { 03617 // silence php warning ;-) 03618 @$DB->sql_substr("name"); 03619 $this->fail("Expecting an exception, none occurred"); 03620 } catch (Exception $e) { 03621 $this->assertTrue($e instanceof coding_exception); 03622 } 03623 } 03624 03625 function test_sql_length() { 03626 $DB = $this->tdb; 03627 $this->assertEqual($DB->get_field_sql( 03628 "SELECT ".$DB->sql_length("'aeiou'").$DB->sql_null_from_clause()), 5); 03629 $this->assertEqual($DB->get_field_sql( 03630 "SELECT ".$DB->sql_length("'áéíóú'").$DB->sql_null_from_clause()), 5); 03631 } 03632 03633 function test_sql_position() { 03634 $DB = $this->tdb; 03635 $this->assertEqual($DB->get_field_sql( 03636 "SELECT ".$DB->sql_position("'ood'", "'Moodle'").$DB->sql_null_from_clause()), 2); 03637 $this->assertEqual($DB->get_field_sql( 03638 "SELECT ".$DB->sql_position("'Oracle'", "'Moodle'").$DB->sql_null_from_clause()), 0); 03639 } 03640 03641 function test_sql_empty() { 03642 $DB = $this->tdb; 03643 $dbman = $DB->get_manager(); 03644 03645 $table = $this->get_test_table(); 03646 $tablename = $table->getName(); 03647 03648 $table->add_field('id', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, XMLDB_SEQUENCE, null); 03649 $table->add_field('name', XMLDB_TYPE_CHAR, '255', null, null, null, null); 03650 $table->add_field('namenotnull', XMLDB_TYPE_CHAR, '255', null, XMLDB_NOTNULL, null, 'default value'); 03651 $table->add_field('namenotnullnodeflt', XMLDB_TYPE_CHAR, '255', null, XMLDB_NOTNULL, null, null); 03652 $table->add_key('primary', XMLDB_KEY_PRIMARY, array('id')); 03653 $dbman->create_table($table); 03654 03655 $DB->insert_record($tablename, array('name'=>'', 'namenotnull'=>'')); 03656 $DB->insert_record($tablename, array('name'=>null)); 03657 $DB->insert_record($tablename, array('name'=>'lalala')); 03658 $DB->insert_record($tablename, array('name'=>0)); 03659 03660 $records = $DB->get_records_sql("SELECT * FROM {{$tablename}} WHERE name = '".$DB->sql_empty()."'"); 03661 $this->assertEqual(count($records), 1); 03662 $record = reset($records); 03663 $this->assertEqual($record->name, ''); 03664 03665 $records = $DB->get_records_sql("SELECT * FROM {{$tablename}} WHERE namenotnull = '".$DB->sql_empty()."'"); 03666 $this->assertEqual(count($records), 1); 03667 $record = reset($records); 03668 $this->assertEqual($record->namenotnull, ''); 03669 03670 $records = $DB->get_records_sql("SELECT * FROM {{$tablename}} WHERE namenotnullnodeflt = '".$DB->sql_empty()."'"); 03671 $this->assertEqual(count($records), 4); 03672 $record = reset($records); 03673 $this->assertEqual($record->namenotnullnodeflt, ''); 03674 } 03675 03676 function test_sql_isempty() { 03677 $DB = $this->tdb; 03678 $dbman = $DB->get_manager(); 03679 03680 $table = $this->get_test_table(); 03681 $tablename = $table->getName(); 03682 03683 $table->add_field('id', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, XMLDB_SEQUENCE, null); 03684 $table->add_field('name', XMLDB_TYPE_CHAR, '255', null, XMLDB_NOTNULL, null, null); 03685 $table->add_field('namenull', XMLDB_TYPE_CHAR, '255', null, null, null, null); 03686 $table->add_field('description', XMLDB_TYPE_TEXT, 'big', null, XMLDB_NOTNULL, null, null); 03687 $table->add_field('descriptionnull', XMLDB_TYPE_TEXT, 'big', null, null, null, null); 03688 $table->add_key('primary', XMLDB_KEY_PRIMARY, array('id')); 03689 $dbman->create_table($table); 03690 03691 $DB->insert_record($tablename, array('name'=>'', 'namenull'=>'', 'description'=>'', 'descriptionnull'=>'')); 03692 $DB->insert_record($tablename, array('name'=>'??', 'namenull'=>null, 'description'=>'??', 'descriptionnull'=>null)); 03693 $DB->insert_record($tablename, array('name'=>'la', 'namenull'=>'la', 'description'=>'la', 'descriptionnull'=>'lalala')); 03694 $DB->insert_record($tablename, array('name'=>0, 'namenull'=>0, 'description'=>0, 'descriptionnull'=>0)); 03695 03696 $records = $DB->get_records_sql("SELECT * FROM {{$tablename}} WHERE ".$DB->sql_isempty($tablename, 'name', false, false)); 03697 $this->assertEqual(count($records), 1); 03698 $record = reset($records); 03699 $this->assertEqual($record->name, ''); 03700 03701 $records = $DB->get_records_sql("SELECT * FROM {{$tablename}} WHERE ".$DB->sql_isempty($tablename, 'namenull', true, false)); 03702 $this->assertEqual(count($records), 1); 03703 $record = reset($records); 03704 $this->assertEqual($record->namenull, ''); 03705 03706 $records = $DB->get_records_sql("SELECT * FROM {{$tablename}} WHERE ".$DB->sql_isempty($tablename, 'description', false, true)); 03707 $this->assertEqual(count($records), 1); 03708 $record = reset($records); 03709 $this->assertEqual($record->description, ''); 03710 03711 $records = $DB->get_records_sql("SELECT * FROM {{$tablename}} WHERE ".$DB->sql_isempty($tablename, 'descriptionnull', true, true)); 03712 $this->assertEqual(count($records), 1); 03713 $record = reset($records); 03714 $this->assertEqual($record->descriptionnull, ''); 03715 } 03716 03717 function test_sql_isnotempty() { 03718 $DB = $this->tdb; 03719 $dbman = $DB->get_manager(); 03720 03721 $table = $this->get_test_table(); 03722 $tablename = $table->getName(); 03723 03724 $table->add_field('id', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, XMLDB_SEQUENCE, null); 03725 $table->add_field('name', XMLDB_TYPE_CHAR, '255', null, XMLDB_NOTNULL, null, null); 03726 $table->add_field('namenull', XMLDB_TYPE_CHAR, '255', null, null, null, null); 03727 $table->add_field('description', XMLDB_TYPE_TEXT, 'big', null, XMLDB_NOTNULL, null, null); 03728 $table->add_field('descriptionnull', XMLDB_TYPE_TEXT, 'big', null, null, null, null); 03729 $table->add_key('primary', XMLDB_KEY_PRIMARY, array('id')); 03730 $dbman->create_table($table); 03731 03732 $DB->insert_record($tablename, array('name'=>'', 'namenull'=>'', 'description'=>'', 'descriptionnull'=>'')); 03733 $DB->insert_record($tablename, array('name'=>'??', 'namenull'=>null, 'description'=>'??', 'descriptionnull'=>null)); 03734 $DB->insert_record($tablename, array('name'=>'la', 'namenull'=>'la', 'description'=>'la', 'descriptionnull'=>'lalala')); 03735 $DB->insert_record($tablename, array('name'=>0, 'namenull'=>0, 'description'=>0, 'descriptionnull'=>0)); 03736 03737 $records = $DB->get_records_sql("SELECT * FROM {{$tablename}} WHERE ".$DB->sql_isnotempty($tablename, 'name', false, false)); 03738 $this->assertEqual(count($records), 3); 03739 $record = reset($records); 03740 $this->assertEqual($record->name, '??'); 03741 03742 $records = $DB->get_records_sql("SELECT * FROM {{$tablename}} WHERE ".$DB->sql_isnotempty($tablename, 'namenull', true, false)); 03743 $this->assertEqual(count($records), 2); // nulls aren't comparable (so they aren't "not empty"). SQL expected behaviour 03744 $record = reset($records); 03745 $this->assertEqual($record->namenull, 'la'); // so 'la' is the first non-empty 'namenull' record 03746 03747 $records = $DB->get_records_sql("SELECT * FROM {{$tablename}} WHERE ".$DB->sql_isnotempty($tablename, 'description', false, true)); 03748 $this->assertEqual(count($records), 3); 03749 $record = reset($records); 03750 $this->assertEqual($record->description, '??'); 03751 03752 $records = $DB->get_records_sql("SELECT * FROM {{$tablename}} WHERE ".$DB->sql_isnotempty($tablename, 'descriptionnull', true, true)); 03753 $this->assertEqual(count($records), 2); // nulls aren't comparable (so they aren't "not empty"). SQL expected behaviour 03754 $record = reset($records); 03755 $this->assertEqual($record->descriptionnull, 'lalala'); // so 'lalala' is the first non-empty 'descriptionnull' record 03756 } 03757 03758 function test_sql_regex() { 03759 $DB = $this->tdb; 03760 $dbman = $DB->get_manager(); 03761 03762 $table = $this->get_test_table(); 03763 $tablename = $table->getName(); 03764 03765 $table->add_field('id', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, XMLDB_SEQUENCE, null); 03766 $table->add_field('name', XMLDB_TYPE_CHAR, '255', null, null, null, null); 03767 $table->add_key('primary', XMLDB_KEY_PRIMARY, array('id')); 03768 $dbman->create_table($table); 03769 03770 $DB->insert_record($tablename, array('name'=>'lalala')); 03771 $DB->insert_record($tablename, array('name'=>'holaaa')); 03772 $DB->insert_record($tablename, array('name'=>'aouch')); 03773 03774 $sql = "SELECT * FROM {{$tablename}} WHERE name ".$DB->sql_regex()." ?"; 03775 $params = array('a$'); 03776 if ($DB->sql_regex_supported()) { 03777 $records = $DB->get_records_sql($sql, $params); 03778 $this->assertEqual(count($records), 2); 03779 } else { 03780 $this->assertTrue(true, 'Regexp operations not supported. Test skipped'); 03781 } 03782 03783 $sql = "SELECT * FROM {{$tablename}} WHERE name ".$DB->sql_regex(false)." ?"; 03784 $params = array('.a'); 03785 if ($DB->sql_regex_supported()) { 03786 $records = $DB->get_records_sql($sql, $params); 03787 $this->assertEqual(count($records), 1); 03788 } else { 03789 $this->assertTrue(true, 'Regexp operations not supported. Test skipped'); 03790 } 03791 03792 } 03793 03798 public function test_get_records_sql_complicated() { 03799 $DB = $this->tdb; 03800 $dbman = $DB->get_manager(); 03801 03802 $table = $this->get_test_table(); 03803 $tablename = $table->getName(); 03804 03805 $table->add_field('id', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, XMLDB_SEQUENCE, null); 03806 $table->add_field('course', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '0'); 03807 $table->add_field('name', XMLDB_TYPE_CHAR, '255', null, null, null, null); 03808 $table->add_field('content', XMLDB_TYPE_TEXT, 'big', XMLDB_UNSIGNED, XMLDB_NOTNULL); 03809 $table->add_key('primary', XMLDB_KEY_PRIMARY, array('id')); 03810 $dbman->create_table($table); 03811 03812 $DB->insert_record($tablename, array('course' => 3, 'content' => 'hello', 'name'=>'xyz')); 03813 $DB->insert_record($tablename, array('course' => 3, 'content' => 'world', 'name'=>'abc')); 03814 $DB->insert_record($tablename, array('course' => 5, 'content' => 'hello', 'name'=>'def')); 03815 $DB->insert_record($tablename, array('course' => 2, 'content' => 'universe', 'name'=>'abc')); 03816 03817 // test grouping by expressions in the query. MDL-26819. Note that there are 4 ways: 03818 // - By column position (GROUP by 1) - Not supported by mssql & oracle 03819 // - By column name (GROUP by course) - Supported by all, but leading to wrong results 03820 // - By column alias (GROUP by casecol) - Not supported by mssql & oracle 03821 // - By complete expression (GROUP BY CASE ...) - 100% cross-db, this test checks it 03822 $sql = "SELECT (CASE WHEN course = 3 THEN 1 ELSE 0 END) AS casecol, 03823 COUNT(1) AS countrecs, 03824 MAX(name) AS maxname 03825 FROM {{$tablename}} 03826 GROUP BY CASE WHEN course = 3 THEN 1 ELSE 0 END 03827 ORDER BY casecol DESC"; 03828 $result = array( 03829 1 => (object)array('casecol' => 1, 'countrecs' => 2, 'maxname' => 'xyz'), 03830 0 => (object)array('casecol' => 0, 'countrecs' => 2, 'maxname' => 'def')); 03831 $records = $DB->get_records_sql($sql, null); 03832 $this->assertEqual($result, $records); 03833 03834 // another grouping by CASE expression just to ensure it works ok for multiple WHEN 03835 $sql = "SELECT CASE name 03836 WHEN 'xyz' THEN 'last' 03837 WHEN 'def' THEN 'mid' 03838 WHEN 'abc' THEN 'first' 03839 END AS casecol, 03840 COUNT(1) AS countrecs, 03841 MAX(name) AS maxname 03842 FROM {{$tablename}} 03843 GROUP BY CASE name 03844 WHEN 'xyz' THEN 'last' 03845 WHEN 'def' THEN 'mid' 03846 WHEN 'abc' THEN 'first' 03847 END 03848 ORDER BY casecol DESC"; 03849 $result = array( 03850 'mid' => (object)array('casecol' => 'mid', 'countrecs' => 1, 'maxname' => 'def'), 03851 'last' => (object)array('casecol' => 'last', 'countrecs' => 1, 'maxname' => 'xyz'), 03852 'first'=> (object)array('casecol' => 'first', 'countrecs' => 2, 'maxname' => 'abc')); 03853 $records = $DB->get_records_sql($sql, null); 03854 $this->assertEqual($result, $records); 03855 03856 // test limits in queries with DISTINCT/ALL clauses and multiple whitespace. MDL-25268 03857 $sql = "SELECT DISTINCT course 03858 FROM {{$tablename}} 03859 ORDER BY course"; 03860 // only limitfrom 03861 $records = $DB->get_records_sql($sql, null, 1); 03862 $this->assertEqual(2, count($records)); 03863 $this->assertEqual(3, reset($records)->course); 03864 $this->assertEqual(5, next($records)->course); 03865 // only limitnum 03866 $records = $DB->get_records_sql($sql, null, 0, 2); 03867 $this->assertEqual(2, count($records)); 03868 $this->assertEqual(2, reset($records)->course); 03869 $this->assertEqual(3, next($records)->course); 03870 // both limitfrom and limitnum 03871 $records = $DB->get_records_sql($sql, null, 2, 2); 03872 $this->assertEqual(1, count($records)); 03873 $this->assertEqual(5, reset($records)->course); 03874 03875 // we have sql like this in moodle, this syntax breaks on older versions of sqlite for example.. 03876 $sql = "SELECT a.id AS id, a.course AS course 03877 FROM {{$tablename}} a 03878 JOIN (SELECT * FROM {{$tablename}}) b ON a.id = b.id 03879 WHERE a.course = ?"; 03880 03881 $records = $DB->get_records_sql($sql, array(3)); 03882 $this->assertEqual(2, count($records)); 03883 $this->assertEqual(1, reset($records)->id); 03884 $this->assertEqual(2, next($records)->id); 03885 03886 // do NOT try embedding sql_xxxx() helper functions in conditions array of count_records(), they don't break params/binding! 03887 $count = $DB->count_records_select($tablename, "course = :course AND ".$DB->sql_compare_text('content')." = :content", array('course' => 3, 'content' => 'hello')); 03888 $this->assertEqual(1, $count); 03889 03890 // test int x string comparison 03891 $sql = "SELECT * 03892 FROM {{$tablename}} c 03893 WHERE name = ?"; 03894 $this->assertEqual(count($DB->get_records_sql($sql, array(10))), 0); 03895 $this->assertEqual(count($DB->get_records_sql($sql, array("10"))), 0); 03896 $DB->insert_record($tablename, array('course' => 7, 'content' => 'xx', 'name'=>'1')); 03897 $DB->insert_record($tablename, array('course' => 7, 'content' => 'yy', 'name'=>'2')); 03898 $this->assertEqual(count($DB->get_records_sql($sql, array(1))), 1); 03899 $this->assertEqual(count($DB->get_records_sql($sql, array("1"))), 1); 03900 $this->assertEqual(count($DB->get_records_sql($sql, array(10))), 0); 03901 $this->assertEqual(count($DB->get_records_sql($sql, array("10"))), 0); 03902 $DB->insert_record($tablename, array('course' => 7, 'content' => 'xx', 'name'=>'1abc')); 03903 $this->assertEqual(count($DB->get_records_sql($sql, array(1))), 1); 03904 $this->assertEqual(count($DB->get_records_sql($sql, array("1"))), 1); 03905 } 03906 03907 function test_onelevel_commit() { 03908 $DB = $this->tdb; 03909 $dbman = $DB->get_manager(); 03910 03911 $table = $this->get_test_table(); 03912 $tablename = $table->getName(); 03913 03914 $table->add_field('id', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, XMLDB_SEQUENCE, null); 03915 $table->add_field('course', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '0'); 03916 $table->add_key('primary', XMLDB_KEY_PRIMARY, array('id')); 03917 $dbman->create_table($table); 03918 03919 $transaction = $DB->start_delegated_transaction(); 03920 $data = (object)array('course'=>3); 03921 $this->assertEqual(0, $DB->count_records($tablename)); 03922 $DB->insert_record($tablename, $data); 03923 $this->assertEqual(1, $DB->count_records($tablename)); 03924 $transaction->allow_commit(); 03925 $this->assertEqual(1, $DB->count_records($tablename)); 03926 } 03927 03928 function test_onelevel_rollback() { 03929 $DB = $this->tdb; 03930 $dbman = $DB->get_manager(); 03931 03932 $table = $this->get_test_table(); 03933 $tablename = $table->getName(); 03934 03935 $table->add_field('id', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, XMLDB_SEQUENCE, null); 03936 $table->add_field('course', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '0'); 03937 $table->add_key('primary', XMLDB_KEY_PRIMARY, array('id')); 03938 $dbman->create_table($table); 03939 03940 // this might in fact encourage ppl to migrate from myisam to innodb 03941 03942 $transaction = $DB->start_delegated_transaction(); 03943 $data = (object)array('course'=>3); 03944 $this->assertEqual(0, $DB->count_records($tablename)); 03945 $DB->insert_record($tablename, $data); 03946 $this->assertEqual(1, $DB->count_records($tablename)); 03947 try { 03948 $transaction->rollback(new Exception('test')); 03949 $this->fail('transaction rollback must rethrow exception'); 03950 } catch (Exception $e) { 03951 } 03952 $this->assertEqual(0, $DB->count_records($tablename)); 03953 } 03954 03955 function test_nested_transactions() { 03956 $DB = $this->tdb; 03957 $dbman = $DB->get_manager(); 03958 03959 $table = $this->get_test_table(); 03960 $tablename = $table->getName(); 03961 03962 $table->add_field('id', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, XMLDB_SEQUENCE, null); 03963 $table->add_field('course', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '0'); 03964 $table->add_key('primary', XMLDB_KEY_PRIMARY, array('id')); 03965 $dbman->create_table($table); 03966 03967 // two level commit 03968 $this->assertFalse($DB->is_transaction_started()); 03969 $transaction1 = $DB->start_delegated_transaction(); 03970 $this->assertTrue($DB->is_transaction_started()); 03971 $data = (object)array('course'=>3); 03972 $DB->insert_record($tablename, $data); 03973 $transaction2 = $DB->start_delegated_transaction(); 03974 $data = (object)array('course'=>4); 03975 $DB->insert_record($tablename, $data); 03976 $transaction2->allow_commit(); 03977 $this->assertTrue($DB->is_transaction_started()); 03978 $transaction1->allow_commit(); 03979 $this->assertFalse($DB->is_transaction_started()); 03980 $this->assertEqual(2, $DB->count_records($tablename)); 03981 03982 $DB->delete_records($tablename); 03983 03984 // rollback from top level 03985 $transaction1 = $DB->start_delegated_transaction(); 03986 $data = (object)array('course'=>3); 03987 $DB->insert_record($tablename, $data); 03988 $transaction2 = $DB->start_delegated_transaction(); 03989 $data = (object)array('course'=>4); 03990 $DB->insert_record($tablename, $data); 03991 $transaction2->allow_commit(); 03992 try { 03993 $transaction1->rollback(new Exception('test')); 03994 $this->fail('transaction rollback must rethrow exception'); 03995 } catch (Exception $e) { 03996 $this->assertEqual(get_class($e), 'Exception'); 03997 } 03998 $this->assertEqual(0, $DB->count_records($tablename)); 03999 04000 $DB->delete_records($tablename); 04001 04002 // rollback from nested level 04003 $transaction1 = $DB->start_delegated_transaction(); 04004 $data = (object)array('course'=>3); 04005 $DB->insert_record($tablename, $data); 04006 $transaction2 = $DB->start_delegated_transaction(); 04007 $data = (object)array('course'=>4); 04008 $DB->insert_record($tablename, $data); 04009 try { 04010 $transaction2->rollback(new Exception('test')); 04011 $this->fail('transaction rollback must rethrow exception'); 04012 } catch (Exception $e) { 04013 $this->assertEqual(get_class($e), 'Exception'); 04014 } 04015 $this->assertEqual(2, $DB->count_records($tablename)); // not rolled back yet 04016 try { 04017 $transaction1->allow_commit(); 04018 } catch (Exception $e) { 04019 $this->assertEqual(get_class($e), 'dml_transaction_exception'); 04020 } 04021 $this->assertEqual(2, $DB->count_records($tablename)); // not rolled back yet 04022 // the forced rollback is done from the default_exception handler and similar places, 04023 // let's do it manually here 04024 $this->assertTrue($DB->is_transaction_started()); 04025 $DB->force_transaction_rollback(); 04026 $this->assertFalse($DB->is_transaction_started()); 04027 $this->assertEqual(0, $DB->count_records($tablename)); // finally rolled back 04028 04029 $DB->delete_records($tablename); 04030 } 04031 04032 function test_transactions_forbidden() { 04033 $DB = $this->tdb; 04034 $dbman = $DB->get_manager(); 04035 04036 $table = $this->get_test_table(); 04037 $tablename = $table->getName(); 04038 04039 $table->add_field('id', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, XMLDB_SEQUENCE, null); 04040 $table->add_field('course', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '0'); 04041 $table->add_key('primary', XMLDB_KEY_PRIMARY, array('id')); 04042 $dbman->create_table($table); 04043 04044 $DB->transactions_forbidden(); 04045 $transaction = $DB->start_delegated_transaction(); 04046 $data = (object)array('course'=>1); 04047 $DB->insert_record($tablename, $data); 04048 try { 04049 $DB->transactions_forbidden(); 04050 } catch (Exception $e) { 04051 $this->assertEqual(get_class($e), 'dml_transaction_exception'); 04052 } 04053 // the previous test does not force rollback 04054 $transaction->allow_commit(); 04055 $this->assertFalse($DB->is_transaction_started()); 04056 $this->assertEqual(1, $DB->count_records($tablename)); 04057 } 04058 04059 function test_wrong_transactions() { 04060 $DB = $this->tdb; 04061 $dbman = $DB->get_manager(); 04062 04063 $table = $this->get_test_table(); 04064 $tablename = $table->getName(); 04065 04066 $table->add_field('id', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, XMLDB_SEQUENCE, null); 04067 $table->add_field('course', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '0'); 04068 $table->add_key('primary', XMLDB_KEY_PRIMARY, array('id')); 04069 $dbman->create_table($table); 04070 04071 04072 // wrong order of nested commits 04073 $transaction1 = $DB->start_delegated_transaction(); 04074 $data = (object)array('course'=>3); 04075 $DB->insert_record($tablename, $data); 04076 $transaction2 = $DB->start_delegated_transaction(); 04077 $data = (object)array('course'=>4); 04078 $DB->insert_record($tablename, $data); 04079 try { 04080 $transaction1->allow_commit(); 04081 $this->fail('wrong order of commits must throw exception'); 04082 } catch (Exception $e) { 04083 $this->assertEqual(get_class($e), 'dml_transaction_exception'); 04084 } 04085 try { 04086 $transaction2->allow_commit(); 04087 $this->fail('first wrong commit forces rollback'); 04088 } catch (Exception $e) { 04089 $this->assertEqual(get_class($e), 'dml_transaction_exception'); 04090 } 04091 // this is done in default exception handler usually 04092 $this->assertTrue($DB->is_transaction_started()); 04093 $this->assertEqual(2, $DB->count_records($tablename)); // not rolled back yet 04094 $DB->force_transaction_rollback(); 04095 $this->assertEqual(0, $DB->count_records($tablename)); 04096 $DB->delete_records($tablename); 04097 04098 04099 // wrong order of nested rollbacks 04100 $transaction1 = $DB->start_delegated_transaction(); 04101 $data = (object)array('course'=>3); 04102 $DB->insert_record($tablename, $data); 04103 $transaction2 = $DB->start_delegated_transaction(); 04104 $data = (object)array('course'=>4); 04105 $DB->insert_record($tablename, $data); 04106 try { 04107 // this first rollback should prevent all other rollbacks 04108 $transaction1->rollback(new Exception('test')); 04109 } catch (Exception $e) { 04110 $this->assertEqual(get_class($e), 'Exception'); 04111 } 04112 try { 04113 $transaction2->rollback(new Exception('test')); 04114 } catch (Exception $e) { 04115 $this->assertEqual(get_class($e), 'Exception'); 04116 } 04117 try { 04118 $transaction1->rollback(new Exception('test')); 04119 } catch (Exception $e) { 04120 // the rollback was used already once, no way to use it again 04121 $this->assertEqual(get_class($e), 'dml_transaction_exception'); 04122 } 04123 // this is done in default exception handler usually 04124 $this->assertTrue($DB->is_transaction_started()); 04125 $DB->force_transaction_rollback(); 04126 $DB->delete_records($tablename); 04127 04128 04129 // unknown transaction object 04130 $transaction1 = $DB->start_delegated_transaction(); 04131 $data = (object)array('course'=>3); 04132 $DB->insert_record($tablename, $data); 04133 $transaction2 = new moodle_transaction($DB); 04134 try { 04135 $transaction2->allow_commit(); 04136 $this->fail('foreign transaction must fail'); 04137 } catch (Exception $e) { 04138 $this->assertEqual(get_class($e), 'dml_transaction_exception'); 04139 } 04140 try { 04141 $transaction1->allow_commit(); 04142 $this->fail('first wrong commit forces rollback'); 04143 } catch (Exception $e) { 04144 $this->assertEqual(get_class($e), 'dml_transaction_exception'); 04145 } 04146 $DB->force_transaction_rollback(); 04147 $DB->delete_records($tablename); 04148 } 04149 04150 function test_concurent_transactions() { 04151 // Notes about this test: 04152 // 1- MySQL needs to use one engine with transactions support (InnoDB). 04153 // 2- MSSQL needs to have enabled versioning for read committed 04154 // transactions (ALTER DATABASE xxx SET READ_COMMITTED_SNAPSHOT ON) 04155 $DB = $this->tdb; 04156 $dbman = $DB->get_manager(); 04157 04158 $table = $this->get_test_table(); 04159 $tablename = $table->getName(); 04160 04161 $table->add_field('id', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, XMLDB_SEQUENCE, null); 04162 $table->add_field('course', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '0'); 04163 $table->add_key('primary', XMLDB_KEY_PRIMARY, array('id')); 04164 $dbman->create_table($table); 04165 04166 $transaction = $DB->start_delegated_transaction(); 04167 $data = (object)array('course'=>1); 04168 $this->assertEqual(0, $DB->count_records($tablename)); 04169 $DB->insert_record($tablename, $data); 04170 $this->assertEqual(1, $DB->count_records($tablename)); 04171 04172 //open second connection 04173 $cfg = $DB->export_dbconfig(); 04174 if (!isset($cfg->dboptions)) { 04175 $cfg->dboptions = array(); 04176 } 04177 $DB2 = moodle_database::get_driver_instance($cfg->dbtype, $cfg->dblibrary); 04178 $DB2->connect($cfg->dbhost, $cfg->dbuser, $cfg->dbpass, $cfg->dbname, $cfg->prefix, $cfg->dboptions); 04179 04180 // second instance should not see pending inserts 04181 $this->assertEqual(0, $DB2->count_records($tablename)); 04182 $data = (object)array('course'=>2); 04183 $DB2->insert_record($tablename, $data); 04184 $this->assertEqual(1, $DB2->count_records($tablename)); 04185 04186 // first should see the changes done from second 04187 $this->assertEqual(2, $DB->count_records($tablename)); 04188 04189 // now commit and we should see it finally in second connections 04190 $transaction->allow_commit(); 04191 $this->assertEqual(2, $DB2->count_records($tablename)); 04192 04193 // let's try delete all is also working on (this checks MDL-29198) 04194 // initially both connections see all the records in the table (2) 04195 $this->assertEqual(2, $DB->count_records($tablename)); 04196 $this->assertEqual(2, $DB2->count_records($tablename)); 04197 $transaction = $DB->start_delegated_transaction(); 04198 04199 // delete all from within transaction 04200 $DB->delete_records($tablename); 04201 04202 // transactional $DB, sees 0 records now 04203 $this->assertEqual(0, $DB->count_records($tablename)); 04204 04205 // others ($DB2) get no changes yet 04206 $this->assertEqual(2, $DB2->count_records($tablename)); 04207 04208 // now commit and we should see changes 04209 $transaction->allow_commit(); 04210 $this->assertEqual(0, $DB2->count_records($tablename)); 04211 04212 $DB2->dispose(); 04213 } 04214 04215 public function test_session_locks() { 04216 $DB = $this->tdb; 04217 $dbman = $DB->get_manager(); 04218 04219 // Open second connection 04220 $cfg = $DB->export_dbconfig(); 04221 if (!isset($cfg->dboptions)) { 04222 $cfg->dboptions = array(); 04223 } 04224 $DB2 = moodle_database::get_driver_instance($cfg->dbtype, $cfg->dblibrary); 04225 $DB2->connect($cfg->dbhost, $cfg->dbuser, $cfg->dbpass, $cfg->dbname, $cfg->prefix, $cfg->dboptions); 04226 04227 // Testing that acquiring a lock efectively locks 04228 // Get a session lock on connection1 04229 $rowid = rand(100, 200); 04230 $timeout = 1; 04231 $DB->get_session_lock($rowid, $timeout); 04232 04233 // Try to get the same session lock on connection2 04234 try { 04235 $DB2->get_session_lock($rowid, $timeout); 04236 $DB2->release_session_lock($rowid); // Should not be excuted, but here for safety 04237 $this->fail('An Exception is missing, expected due to session lock acquired.'); 04238 } catch (exception $e) { 04239 $this->assertTrue($e instanceof dml_sessionwait_exception); 04240 $DB->release_session_lock($rowid); // Release lock on connection1 04241 } 04242 04243 // Testing that releasing a lock efectively frees 04244 // Get a session lock on connection1 04245 $rowid = rand(100, 200); 04246 $timeout = 1; 04247 $DB->get_session_lock($rowid, $timeout); 04248 // Release the lock on connection1 04249 $DB->release_session_lock($rowid); 04250 04251 // Get the just released lock on connection2 04252 $DB2->get_session_lock($rowid, $timeout); 04253 // Release the lock on connection2 04254 $DB2->release_session_lock($rowid); 04255 04256 $DB2->dispose(); 04257 } 04258 04259 public function test_bound_param_types() { 04260 $DB = $this->tdb; 04261 $dbman = $DB->get_manager(); 04262 04263 $table = $this->get_test_table(); 04264 $tablename = $table->getName(); 04265 04266 $table->add_field('id', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, XMLDB_SEQUENCE, null); 04267 $table->add_field('name', XMLDB_TYPE_CHAR, '255', null, null, null, null); 04268 $table->add_field('content', XMLDB_TYPE_TEXT, 'big', XMLDB_UNSIGNED, XMLDB_NOTNULL); 04269 $table->add_key('primary', XMLDB_KEY_PRIMARY, array('id')); 04270 $dbman->create_table($table); 04271 04272 $this->assertTrue($DB->insert_record($tablename, array('name' => '1', 'content'=>'xx'))); 04273 $this->assertTrue($DB->insert_record($tablename, array('name' => 2, 'content'=>'yy'))); 04274 $this->assertTrue($DB->insert_record($tablename, array('name' => 'somestring', 'content'=>'zz'))); 04275 $this->assertTrue($DB->insert_record($tablename, array('name' => 'aa', 'content'=>'1'))); 04276 $this->assertTrue($DB->insert_record($tablename, array('name' => 'bb', 'content'=>2))); 04277 $this->assertTrue($DB->insert_record($tablename, array('name' => 'cc', 'content'=>'sometext'))); 04278 04279 04280 // Conditions in CHAR columns 04281 $this->assertTrue($DB->record_exists($tablename, array('name'=>1))); 04282 $this->assertTrue($DB->record_exists($tablename, array('name'=>'1'))); 04283 $this->assertFalse($DB->record_exists($tablename, array('name'=>111))); 04284 $this->assertTrue($DB->get_record($tablename, array('name'=>1))); 04285 $this->assertTrue($DB->get_record($tablename, array('name'=>'1'))); 04286 $this->assertFalse($DB->get_record($tablename, array('name'=>111))); 04287 $sqlqm = "SELECT * 04288 FROM {{$tablename}} 04289 WHERE name = ?"; 04290 $this->assertTrue($records = $DB->get_records_sql($sqlqm, array(1))); 04291 $this->assertEqual(1, count($records)); 04292 $this->assertTrue($records = $DB->get_records_sql($sqlqm, array('1'))); 04293 $this->assertEqual(1, count($records)); 04294 $records = $DB->get_records_sql($sqlqm, array(222)); 04295 $this->assertEqual(0, count($records)); 04296 $sqlnamed = "SELECT * 04297 FROM {{$tablename}} 04298 WHERE name = :name"; 04299 $this->assertTrue($records = $DB->get_records_sql($sqlnamed, array('name' => 2))); 04300 $this->assertEqual(1, count($records)); 04301 $this->assertTrue($records = $DB->get_records_sql($sqlnamed, array('name' => '2'))); 04302 $this->assertEqual(1, count($records)); 04303 04304 // Conditions in TEXT columns always must be performed with the sql_compare_text 04305 // helper function on both sides of the condition 04306 $sqlqm = "SELECT * 04307 FROM {{$tablename}} 04308 WHERE " . $DB->sql_compare_text('content') . " = " . $DB->sql_compare_text('?'); 04309 $this->assertTrue($records = $DB->get_records_sql($sqlqm, array('1'))); 04310 $this->assertEqual(1, count($records)); 04311 $this->assertTrue($records = $DB->get_records_sql($sqlqm, array(1))); 04312 $this->assertEqual(1, count($records)); 04313 $sqlnamed = "SELECT * 04314 FROM {{$tablename}} 04315 WHERE " . $DB->sql_compare_text('content') . " = " . $DB->sql_compare_text(':content'); 04316 $this->assertTrue($records = $DB->get_records_sql($sqlnamed, array('content' => 2))); 04317 $this->assertEqual(1, count($records)); 04318 $this->assertTrue($records = $DB->get_records_sql($sqlnamed, array('content' => '2'))); 04319 $this->assertEqual(1, count($records)); 04320 } 04321 04322 public function test_bound_param_reserved() { 04323 $DB = $this->tdb; 04324 $dbman = $DB->get_manager(); 04325 04326 $table = $this->get_test_table(); 04327 $tablename = $table->getName(); 04328 04329 $table->add_field('id', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, XMLDB_SEQUENCE, null); 04330 $table->add_field('course', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '0'); 04331 $table->add_key('primary', XMLDB_KEY_PRIMARY, array('id')); 04332 $dbman->create_table($table); 04333 04334 $DB->insert_record($tablename, array('course' => '1')); 04335 04336 // make sure reserved words do not cause fatal problems in query parameters 04337 04338 $DB->execute("UPDATE {{$tablename}} SET course = 1 WHERE ID = :select", array('select'=>1)); 04339 $DB->get_records_sql("SELECT * FROM {{$tablename}} WHERE course = :select", array('select'=>1)); 04340 $rs = $DB->get_recordset_sql("SELECT * FROM {{$tablename}} WHERE course = :select", array('select'=>1)); 04341 $rs->close(); 04342 $DB->get_fieldset_sql("SELECT id FROM {{$tablename}} WHERE course = :select", array('select'=>1)); 04343 $DB->set_field_select($tablename, 'course', '1', "id = :select", array('select'=>1)); 04344 $DB->delete_records_select($tablename, "id = :select", array('select'=>1)); 04345 } 04346 04347 public function test_limits_and_offsets() { 04348 $DB = $this->tdb; 04349 $dbman = $DB->get_manager(); 04350 04351 if (false) $DB = new moodle_database (); 04352 04353 $table = $this->get_test_table(); 04354 $tablename = $table->getName(); 04355 04356 $table->add_field('id', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, XMLDB_SEQUENCE, null); 04357 $table->add_field('name', XMLDB_TYPE_CHAR, '255', null, null, null, null); 04358 $table->add_field('content', XMLDB_TYPE_TEXT, 'big', XMLDB_UNSIGNED, XMLDB_NOTNULL); 04359 $table->add_key('primary', XMLDB_KEY_PRIMARY, array('id')); 04360 $dbman->create_table($table); 04361 04362 $this->assertTrue($DB->insert_record($tablename, array('name' => 'a', 'content'=>'one'))); 04363 $this->assertTrue($DB->insert_record($tablename, array('name' => 'b', 'content'=>'two'))); 04364 $this->assertTrue($DB->insert_record($tablename, array('name' => 'c', 'content'=>'three'))); 04365 $this->assertTrue($DB->insert_record($tablename, array('name' => 'd', 'content'=>'four'))); 04366 $this->assertTrue($DB->insert_record($tablename, array('name' => 'e', 'content'=>'five'))); 04367 $this->assertTrue($DB->insert_record($tablename, array('name' => 'f', 'content'=>'six'))); 04368 04369 $sqlqm = "SELECT * 04370 FROM {{$tablename}}"; 04371 $this->assertTrue($records = $DB->get_records_sql($sqlqm, null, 4)); 04372 $this->assertEqual(2, count($records)); 04373 $this->assertEqual('e', reset($records)->name); 04374 $this->assertEqual('f', end($records)->name); 04375 04376 $sqlqm = "SELECT * 04377 FROM {{$tablename}}"; 04378 $this->assertFalse($records = $DB->get_records_sql($sqlqm, null, 8)); 04379 04380 $sqlqm = "SELECT * 04381 FROM {{$tablename}}"; 04382 $this->assertTrue($records = $DB->get_records_sql($sqlqm, null, 0, 4)); 04383 $this->assertEqual(4, count($records)); 04384 $this->assertEqual('a', reset($records)->name); 04385 $this->assertEqual('d', end($records)->name); 04386 04387 $sqlqm = "SELECT * 04388 FROM {{$tablename}}"; 04389 $this->assertTrue($records = $DB->get_records_sql($sqlqm, null, 0, 8)); 04390 $this->assertEqual(6, count($records)); 04391 $this->assertEqual('a', reset($records)->name); 04392 $this->assertEqual('f', end($records)->name); 04393 04394 $sqlqm = "SELECT * 04395 FROM {{$tablename}}"; 04396 $this->assertTrue($records = $DB->get_records_sql($sqlqm, null, 1, 4)); 04397 $this->assertEqual(4, count($records)); 04398 $this->assertEqual('b', reset($records)->name); 04399 $this->assertEqual('e', end($records)->name); 04400 04401 $sqlqm = "SELECT * 04402 FROM {{$tablename}}"; 04403 $this->assertTrue($records = $DB->get_records_sql($sqlqm, null, 4, 4)); 04404 $this->assertEqual(2, count($records)); 04405 $this->assertEqual('e', reset($records)->name); 04406 $this->assertEqual('f', end($records)->name); 04407 04408 $sqlqm = "SELECT t.*, t.name AS test 04409 FROM {{$tablename}} t 04410 ORDER BY t.id ASC"; 04411 $this->assertTrue($records = $DB->get_records_sql($sqlqm, null, 4, 4)); 04412 $this->assertEqual(2, count($records)); 04413 $this->assertEqual('e', reset($records)->name); 04414 $this->assertEqual('f', end($records)->name); 04415 04416 $sqlqm = "SELECT DISTINCT t.name, t.name AS test 04417 FROM {{$tablename}} t 04418 ORDER BY t.name DESC"; 04419 $this->assertTrue($records = $DB->get_records_sql($sqlqm, null, 4, 4)); 04420 $this->assertEqual(2, count($records)); 04421 $this->assertEqual('b', reset($records)->name); 04422 $this->assertEqual('a', end($records)->name); 04423 04424 $sqlqm = "SELECT 1 04425 FROM {{$tablename}} t 04426 WHERE t.name = 'a'"; 04427 $this->assertTrue($records = $DB->get_records_sql($sqlqm, null, 0, 1)); 04428 $this->assertEqual(1, count($records)); 04429 04430 $sqlqm = "SELECT 'constant' 04431 FROM {{$tablename}} t 04432 WHERE t.name = 'a'"; 04433 $this->assertTrue($records = $DB->get_records_sql($sqlqm, null, 0, 8)); 04434 $this->assertEqual(1, count($records)); 04435 04436 $this->assertTrue($DB->insert_record($tablename, array('name' => 'a', 'content'=>'one'))); 04437 $this->assertTrue($DB->insert_record($tablename, array('name' => 'b', 'content'=>'two'))); 04438 $this->assertTrue($DB->insert_record($tablename, array('name' => 'c', 'content'=>'three'))); 04439 04440 $sqlqm = "SELECT t.name, COUNT(DISTINCT t2.id) AS count, 'Test' AS teststring 04441 FROM {{$tablename}} t 04442 LEFT JOIN ( 04443 SELECT t.id, t.name 04444 FROM {{$tablename}} t 04445 ) t2 ON t2.name = t.name 04446 GROUP BY t.name 04447 ORDER BY t.name ASC"; 04448 $this->assertTrue($records = $DB->get_records_sql($sqlqm)); 04449 $this->assertEqual(6, count($records)); // a,b,c,d,e,f 04450 $this->assertEqual(2, reset($records)->count); // a has 2 records now 04451 $this->assertEqual(1, end($records)->count); // f has 1 record still 04452 04453 $this->assertTrue($records = $DB->get_records_sql($sqlqm, null, 0, 2)); 04454 $this->assertEqual(2, count($records)); 04455 $this->assertEqual(2, reset($records)->count); 04456 $this->assertEqual(2, end($records)->count); 04457 } 04458 } 04459 04465 class moodle_database_for_testing extends moodle_database { 04466 protected $prefix = 'mdl_'; 04467 04468 public function public_fix_table_names($sql) { 04469 return $this->fix_table_names($sql); 04470 } 04471 04472 public function driver_installed(){} 04473 public function get_dbfamily(){} 04474 protected function get_dbtype(){} 04475 protected function get_dblibrary(){} 04476 public function get_name(){} 04477 public function get_configuration_help(){} 04478 public function get_configuration_hints(){} 04479 public function connect($dbhost, $dbuser, $dbpass, $dbname, $prefix, array $dboptions=null){} 04480 public function get_server_info(){} 04481 protected function allowed_param_types(){} 04482 public function get_last_error(){} 04483 public function get_tables($usecache=true){} 04484 public function get_indexes($table){} 04485 public function get_columns($table, $usecache=true){} 04486 protected function normalise_value($column, $value){} 04487 public function set_debug($state){} 04488 public function get_debug(){} 04489 public function set_logging($state){} 04490 public function change_database_structure($sql){} 04491 public function execute($sql, array $params=null){} 04492 public function get_recordset_sql($sql, array $params=null, $limitfrom=0, $limitnum=0){} 04493 public function get_records_sql($sql, array $params=null, $limitfrom=0, $limitnum=0){} 04494 public function get_fieldset_sql($sql, array $params=null){} 04495 public function insert_record_raw($table, $params, $returnid=true, $bulk=false, $customsequence=false){} 04496 public function insert_record($table, $dataobject, $returnid=true, $bulk=false){} 04497 public function import_record($table, $dataobject){} 04498 public function update_record_raw($table, $params, $bulk=false){} 04499 public function update_record($table, $dataobject, $bulk=false){} 04500 public function set_field_select($table, $newfield, $newvalue, $select, array $params=null){} 04501 public function delete_records_select($table, $select, array $params=null){} 04502 public function sql_concat(){} 04503 public function sql_concat_join($separator="' '", $elements=array()){} 04504 public function sql_substr($expr, $start, $length=false){} 04505 public function begin_transaction() {} 04506 public function commit_transaction() {} 04507 public function rollback_transaction() {} 04508 }