[ Index ] |
PHP Cross Reference of moodle-2.8 |
[Summary view] [Print] [Text view]
1 <?php 2 // This file is part of Moodle - http://moodle.org/ 3 // 4 // Moodle is free software: you can redistribute it and/or modify 5 // it under the terms of the GNU General Public License as published by 6 // the Free Software Foundation, either version 3 of the License, or 7 // (at your option) any later version. 8 // 9 // Moodle is distributed in the hope that it will be useful, 10 // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 // GNU General Public License for more details. 13 // 14 // You should have received a copy of the GNU General Public License 15 // along with Moodle. If not, see <http://www.gnu.org/licenses/>. 16 17 /** 18 * DDL layer tests. 19 * 20 * @package core_ddl 21 * @category phpunit 22 * @copyright 2008 Nicolas Connault 23 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 24 */ 25 26 defined('MOODLE_INTERNAL') || die(); 27 28 class core_ddl_testcase extends database_driver_testcase { 29 private $tables = array(); 30 private $records= array(); 31 32 protected function setUp() { 33 parent::setUp(); 34 $dbman = $this->tdb->get_manager(); // Loads DDL libs. 35 36 $table = new xmldb_table('test_table0'); 37 $table->add_field('id', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, XMLDB_SEQUENCE, null); 38 $table->add_field('course', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, '0'); 39 $table->add_field('type', XMLDB_TYPE_CHAR, '20', null, XMLDB_NOTNULL, null, 'general'); 40 $table->add_field('name', XMLDB_TYPE_CHAR, '255', null, XMLDB_NOTNULL, null); 41 $table->add_field('intro', XMLDB_TYPE_TEXT, 'small', null, XMLDB_NOTNULL, null, null); 42 $table->add_field('logo', XMLDB_TYPE_BINARY, 'big', null, null, null); 43 $table->add_field('assessed', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, '0'); 44 $table->add_field('assesstimestart', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, '0'); 45 $table->add_field('assesstimefinish', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, '0'); 46 $table->add_field('scale', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, '0'); 47 $table->add_field('maxbytes', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, '0'); 48 $table->add_field('forcesubscribe', XMLDB_TYPE_INTEGER, '1', null, XMLDB_NOTNULL, null, '0'); 49 $table->add_field('trackingtype', XMLDB_TYPE_INTEGER, '2', null, XMLDB_NOTNULL, null, '1'); 50 $table->add_field('rsstype', XMLDB_TYPE_INTEGER, '2', null, XMLDB_NOTNULL, null, '0'); 51 $table->add_field('rssarticles', XMLDB_TYPE_INTEGER, '2', null, XMLDB_NOTNULL, null, '0'); 52 $table->add_field('timemodified', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, '0'); 53 $table->add_field('grade', XMLDB_TYPE_NUMBER, '20,0', null, null, null, null); 54 $table->add_field('percent', XMLDB_TYPE_NUMBER, '5,2', null, null, null, 66.6); 55 $table->add_field('warnafter', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, '0'); 56 $table->add_field('blockafter', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, '0'); 57 $table->add_field('blockperiod', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, '0'); 58 $table->add_key('primary', XMLDB_KEY_PRIMARY, array('id')); 59 $table->add_key('course', XMLDB_KEY_UNIQUE, array('course')); 60 $table->add_index('type-name', XMLDB_INDEX_UNIQUE, array('type', 'name')); 61 $table->add_index('rsstype', XMLDB_INDEX_NOTUNIQUE, array('rsstype')); 62 $table->setComment("This is a test'n drop table. You can drop it safely"); 63 64 $this->tables[$table->getName()] = $table; 65 66 // Define 2 initial records for this table. 67 $this->records[$table->getName()] = array( 68 (object)array( 69 'course' => '1', 70 'type' => 'general', 71 'name' => 'record', 72 'intro' => 'first record'), 73 (object)array( 74 'course' => '2', 75 'type' => 'social', 76 'name' => 'record', 77 'intro' => 'second record')); 78 79 // Second, smaller table. 80 $table = new xmldb_table ('test_table1'); 81 $table->add_field('id', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, XMLDB_SEQUENCE, null); 82 $table->add_field('course', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, '0'); 83 $table->add_field('name', XMLDB_TYPE_CHAR, '30', null, null, null, 'Moodle'); 84 $table->add_field('secondname', XMLDB_TYPE_CHAR, '30', null, XMLDB_NOTNULL, null, null); 85 $table->add_field('thirdname', XMLDB_TYPE_CHAR, '30', null, null, null, ''); // Nullable column with empty default. 86 $table->add_field('intro', XMLDB_TYPE_TEXT, 'medium', null, XMLDB_NOTNULL, null, null); 87 $table->add_field('avatar', XMLDB_TYPE_BINARY, 'medium', null, null, null, null); 88 $table->add_field('grade', XMLDB_TYPE_NUMBER, '20,10', null, null, null); 89 $table->add_field('gradefloat', XMLDB_TYPE_FLOAT, '20,0', null, null, null, null); 90 $table->add_field('percentfloat', XMLDB_TYPE_FLOAT, '5,2', null, null, null, 99.9); 91 $table->add_field('userid', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, '0'); 92 $table->add_key('primary', XMLDB_KEY_PRIMARY, array('id')); 93 $table->add_key('course', XMLDB_KEY_FOREIGN_UNIQUE, array('course'), 'test_table0', array('course')); 94 $table->setComment("This is a test'n drop table. You can drop it safely"); 95 96 $this->tables[$table->getName()] = $table; 97 98 // Define 2 initial records for this table. 99 $this->records[$table->getName()] = array( 100 (object)array( 101 'course' => '1', 102 'secondname' => 'first record', // Less than 10 cc, please don't modify. Some tests below depend of this. 103 'intro' => 'first record'), 104 (object)array( 105 'course' => '2', 106 'secondname' => 'second record', // More than 10 cc, please don't modify. Some tests below depend of this. 107 'intro' => 'second record')); 108 } 109 110 private function create_deftable($tablename) { 111 $dbman = $this->tdb->get_manager(); 112 113 if (!isset($this->tables[$tablename])) { 114 return null; 115 } 116 117 $table = $this->tables[$tablename]; 118 119 if ($dbman->table_exists($table)) { 120 $dbman->drop_table($table); 121 } 122 $dbman->create_table($table); 123 124 return $table; 125 } 126 127 /** 128 * Fill the given test table with some records, as far as 129 * DDL behaviour must be tested both with real data and 130 * with empty tables 131 * @param string $tablename 132 * @return int count of records 133 */ 134 private function fill_deftable($tablename) { 135 $DB = $this->tdb; // Do not use global $DB! 136 $dbman = $this->tdb->get_manager(); 137 138 if (!isset($this->records[$tablename])) { 139 return null; 140 } 141 142 if ($dbman->table_exists($tablename)) { 143 foreach ($this->records[$tablename] as $row) { 144 $DB->insert_record($tablename, $row); 145 } 146 } else { 147 return null; 148 } 149 150 return count($this->records[$tablename]); 151 } 152 153 /** 154 * Test behaviour of table_exists() 155 */ 156 public function test_table_exists() { 157 $DB = $this->tdb; // Do not use global $DB! 158 $dbman = $this->tdb->get_manager(); 159 160 // First make sure it returns false if table does not exist. 161 $table = $this->tables['test_table0']; 162 163 try { 164 $result = $DB->get_records('test_table0'); 165 } catch (dml_exception $e) { 166 $result = false; 167 } 168 $this->resetDebugging(); 169 170 $this->assertFalse($result); 171 172 $this->assertFalse($dbman->table_exists('test_table0')); // By name.. 173 $this->assertFalse($dbman->table_exists($table)); // By xmldb_table.. 174 175 // Create table and test again. 176 $dbman->create_table($table); 177 178 $this->assertSame(array(), $DB->get_records('test_table0')); 179 $this->assertTrue($dbman->table_exists('test_table0')); // By name. 180 $this->assertTrue($dbman->table_exists($table)); // By xmldb_table. 181 182 // Drop table and test again. 183 $dbman->drop_table($table); 184 185 try { 186 $result = $DB->get_records('test_table0'); 187 } catch (dml_exception $e) { 188 $result = false; 189 } 190 $this->resetDebugging(); 191 192 $this->assertFalse($result); 193 194 $this->assertFalse($dbman->table_exists('test_table0')); // By name. 195 $this->assertFalse($dbman->table_exists($table)); // By xmldb_table. 196 } 197 198 /** 199 * Test behaviour of create_table() 200 */ 201 public function test_create_table() { 202 $DB = $this->tdb; // Do not use global $DB! 203 $dbman = $this->tdb->get_manager(); 204 205 // Create table. 206 $table = $this->tables['test_table1']; 207 208 $dbman->create_table($table); 209 $this->assertTrue($dbman->table_exists($table)); 210 211 // Basic get_tables() test. 212 $tables = $DB->get_tables(); 213 $this->assertArrayHasKey('test_table1', $tables); 214 215 // Basic get_columns() tests. 216 $columns = $DB->get_columns('test_table1'); 217 $this->assertSame('R', $columns['id']->meta_type); 218 $this->assertSame('I', $columns['course']->meta_type); 219 $this->assertSame('C', $columns['name']->meta_type); 220 $this->assertSame('C', $columns['secondname']->meta_type); 221 $this->assertSame('C', $columns['thirdname']->meta_type); 222 $this->assertSame('X', $columns['intro']->meta_type); 223 $this->assertSame('B', $columns['avatar']->meta_type); 224 $this->assertSame('N', $columns['grade']->meta_type); 225 $this->assertSame('N', $columns['percentfloat']->meta_type); 226 $this->assertSame('I', $columns['userid']->meta_type); 227 // Some defaults. 228 $this->assertTrue($columns['course']->has_default); 229 $this->assertEquals(0, $columns['course']->default_value); 230 $this->assertTrue($columns['name']->has_default); 231 $this->assertSame('Moodle', $columns['name']->default_value); 232 $this->assertTrue($columns['secondname']->has_default); 233 $this->assertSame('', $columns['secondname']->default_value); 234 $this->assertTrue($columns['thirdname']->has_default); 235 $this->assertSame('', $columns['thirdname']->default_value); 236 $this->assertTrue($columns['percentfloat']->has_default); 237 $this->assertEquals(99.9, $columns['percentfloat']->default_value); 238 $this->assertTrue($columns['userid']->has_default); 239 $this->assertEquals(0, $columns['userid']->default_value); 240 241 // Basic get_indexes() test. 242 $indexes = $DB->get_indexes('test_table1'); 243 $courseindex = reset($indexes); 244 $this->assertEquals(1, $courseindex['unique']); 245 $this->assertSame('course', $courseindex['columns'][0]); 246 247 // Check sequence returns 1 for first insert. 248 $rec = (object)array( 249 'course' => 10, 250 'secondname' => 'not important', 251 'intro' => 'not important'); 252 $this->assertSame(1, $DB->insert_record('test_table1', $rec)); 253 254 // Check defined defaults are working ok. 255 $dbrec = $DB->get_record('test_table1', array('id' => 1)); 256 $this->assertSame('Moodle', $dbrec->name); 257 $this->assertSame('', $dbrec->thirdname); 258 259 // Check exceptions if multiple R columns. 260 $table = new xmldb_table ('test_table2'); 261 $table->add_field('id', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, XMLDB_SEQUENCE, null); 262 $table->add_field('rid', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, XMLDB_SEQUENCE, null); 263 $table->add_field('course', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, '0'); 264 $table->add_key('primary', XMLDB_KEY_PRIMARY, array('id')); 265 $table->add_key('primaryx', XMLDB_KEY_PRIMARY, array('id')); 266 $table->setComment("This is a test'n drop table. You can drop it safely"); 267 268 $this->tables[$table->getName()] = $table; 269 270 try { 271 $dbman->create_table($table); 272 $this->fail('Exception expected'); 273 } catch (moodle_exception $e) { 274 $this->assertInstanceOf('ddl_exception', $e); 275 } 276 277 // Check exceptions missing primary key on R column. 278 $table = new xmldb_table ('test_table2'); 279 $table->add_field('id', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, XMLDB_SEQUENCE, null); 280 $table->add_field('course', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, '0'); 281 $table->setComment("This is a test'n drop table. You can drop it safely"); 282 283 $this->tables[$table->getName()] = $table; 284 285 try { 286 $dbman->create_table($table); 287 $this->fail('Exception expected'); 288 } catch (moodle_exception $e) { 289 $this->assertInstanceOf('ddl_exception', $e); 290 } 291 292 // Long table name names - the largest allowed. 293 $table = new xmldb_table('test_table0123456789_____xyz'); 294 $table->add_field('id', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, XMLDB_SEQUENCE, null); 295 $table->add_field('course', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, '2'); 296 $table->add_key('primary', XMLDB_KEY_PRIMARY, array('id')); 297 $table->setComment("This is a test'n drop table. You can drop it safely"); 298 299 $this->tables[$table->getName()] = $table; 300 301 $dbman->create_table($table); 302 $this->assertTrue($dbman->table_exists($table)); 303 $dbman->drop_table($table); 304 305 // Table name is too long. 306 $table = new xmldb_table('test_table0123456789_____xyz9'); 307 $table->add_field('id', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, XMLDB_SEQUENCE, null); 308 $table->add_field('course', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, '2'); 309 $table->add_key('primary', XMLDB_KEY_PRIMARY, array('id')); 310 $table->setComment("This is a test'n drop table. You can drop it safely"); 311 312 $this->tables[$table->getName()] = $table; 313 314 try { 315 $dbman->create_table($table); 316 $this->fail('Exception expected'); 317 } catch (moodle_exception $e) { 318 $this->assertInstanceOf('coding_exception', $e); 319 } 320 321 // Invalid table name. 322 $table = new xmldb_table('test_tableCD'); 323 $table->add_field('id', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, XMLDB_SEQUENCE, null); 324 $table->add_field('course', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, '2'); 325 $table->add_key('primary', XMLDB_KEY_PRIMARY, array('id')); 326 $table->setComment("This is a test'n drop table. You can drop it safely"); 327 328 $this->tables[$table->getName()] = $table; 329 330 try { 331 $dbman->create_table($table); 332 $this->fail('Exception expected'); 333 } catch (moodle_exception $e) { 334 $this->assertInstanceOf('coding_exception', $e); 335 } 336 337 // Weird column names - the largest allowed. 338 $table = new xmldb_table('test_table3'); 339 $table->add_field('id', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, XMLDB_SEQUENCE, null); 340 $table->add_field('abcdef____0123456789_______xyz', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, '2'); 341 $table->add_key('primary', XMLDB_KEY_PRIMARY, array('id')); 342 $table->setComment("This is a test'n drop table. You can drop it safely"); 343 344 $this->tables[$table->getName()] = $table; 345 346 $dbman->create_table($table); 347 $this->assertTrue($dbman->table_exists($table)); 348 $dbman->drop_table($table); 349 350 // Too long field name - max 30. 351 $table = new xmldb_table('test_table4'); 352 $table->add_field('id', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, XMLDB_SEQUENCE, null); 353 $table->add_field('abcdeabcdeabcdeabcdeabcdeabcdez', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, '2'); 354 $table->add_key('primary', XMLDB_KEY_PRIMARY, array('id')); 355 $table->setComment("This is a test'n drop table. You can drop it safely"); 356 357 $this->tables[$table->getName()] = $table; 358 359 try { 360 $dbman->create_table($table); 361 $this->fail('Exception expected'); 362 } catch (moodle_exception $e) { 363 $this->assertInstanceOf('coding_exception', $e); 364 } 365 366 // Invalid field name. 367 $table = new xmldb_table('test_table4'); 368 $table->add_field('id', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, XMLDB_SEQUENCE, null); 369 $table->add_field('abCD', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, '2'); 370 $table->add_key('primary', XMLDB_KEY_PRIMARY, array('id')); 371 $table->setComment("This is a test'n drop table. You can drop it safely"); 372 373 $this->tables[$table->getName()] = $table; 374 375 try { 376 $dbman->create_table($table); 377 $this->fail('Exception expected'); 378 } catch (moodle_exception $e) { 379 $this->assertInstanceOf('coding_exception', $e); 380 } 381 382 // Invalid integer length. 383 $table = new xmldb_table('test_table4'); 384 $table->add_field('id', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, XMLDB_SEQUENCE, null); 385 $table->add_field('course', XMLDB_TYPE_INTEGER, '21', null, XMLDB_NOTNULL, null, '2'); 386 $table->add_key('primary', XMLDB_KEY_PRIMARY, array('id')); 387 $table->setComment("This is a test'n drop table. You can drop it safely"); 388 389 $this->tables[$table->getName()] = $table; 390 391 try { 392 $dbman->create_table($table); 393 $this->fail('Exception expected'); 394 } catch (moodle_exception $e) { 395 $this->assertInstanceOf('coding_exception', $e); 396 } 397 398 // Invalid integer default. 399 $table = new xmldb_table('test_table4'); 400 $table->add_field('id', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, XMLDB_SEQUENCE, null); 401 $table->add_field('course', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, 'x'); 402 $table->add_key('primary', XMLDB_KEY_PRIMARY, array('id')); 403 $table->setComment("This is a test'n drop table. You can drop it safely"); 404 405 $this->tables[$table->getName()] = $table; 406 407 try { 408 $dbman->create_table($table); 409 $this->fail('Exception expected'); 410 } catch (moodle_exception $e) { 411 $this->assertInstanceOf('coding_exception', $e); 412 } 413 414 // Invalid decimal length. 415 $table = new xmldb_table('test_table4'); 416 $table->add_field('id', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, XMLDB_SEQUENCE, null); 417 $table->add_field('num', XMLDB_TYPE_NUMBER, '21,10', null, XMLDB_NOTNULL, null, null); 418 $table->add_key('primary', XMLDB_KEY_PRIMARY, array('id')); 419 $table->setComment("This is a test'n drop table. You can drop it safely"); 420 421 $this->tables[$table->getName()] = $table; 422 423 try { 424 $dbman->create_table($table); 425 $this->fail('Exception expected'); 426 } catch (moodle_exception $e) { 427 $this->assertInstanceOf('coding_exception', $e); 428 } 429 430 // Invalid decimal decimals. 431 $table = new xmldb_table('test_table4'); 432 $table->add_field('id', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, XMLDB_SEQUENCE, null); 433 $table->add_field('num', XMLDB_TYPE_NUMBER, '10,11', null, XMLDB_NOTNULL, null, null); 434 $table->add_key('primary', XMLDB_KEY_PRIMARY, array('id')); 435 $table->setComment("This is a test'n drop table. You can drop it safely"); 436 437 $this->tables[$table->getName()] = $table; 438 439 try { 440 $dbman->create_table($table); 441 $this->fail('Exception expected'); 442 } catch (moodle_exception $e) { 443 $this->assertInstanceOf('coding_exception', $e); 444 } 445 446 // Invalid decimal default. 447 $table = new xmldb_table('test_table4'); 448 $table->add_field('id', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, XMLDB_SEQUENCE, null); 449 $table->add_field('num', XMLDB_TYPE_NUMBER, '10,5', null, XMLDB_NOTNULL, null, 'x'); 450 $table->add_key('primary', XMLDB_KEY_PRIMARY, array('id')); 451 $table->setComment("This is a test'n drop table. You can drop it safely"); 452 453 $this->tables[$table->getName()] = $table; 454 455 try { 456 $dbman->create_table($table); 457 $this->fail('Exception expected'); 458 } catch (moodle_exception $e) { 459 $this->assertInstanceOf('coding_exception', $e); 460 } 461 462 // Invalid float length. 463 $table = new xmldb_table('test_table4'); 464 $table->add_field('id', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, XMLDB_SEQUENCE, null); 465 $table->add_field('num', XMLDB_TYPE_FLOAT, '21,10', null, XMLDB_NOTNULL, null, null); 466 $table->add_key('primary', XMLDB_KEY_PRIMARY, array('id')); 467 $table->setComment("This is a test'n drop table. You can drop it safely"); 468 469 $this->tables[$table->getName()] = $table; 470 471 try { 472 $dbman->create_table($table); 473 $this->fail('Exception expected'); 474 } catch (moodle_exception $e) { 475 $this->assertInstanceOf('coding_exception', $e); 476 } 477 478 // Invalid float decimals. 479 $table = new xmldb_table('test_table4'); 480 $table->add_field('id', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, XMLDB_SEQUENCE, null); 481 $table->add_field('num', XMLDB_TYPE_FLOAT, '10,11', null, XMLDB_NOTNULL, null, null); 482 $table->add_key('primary', XMLDB_KEY_PRIMARY, array('id')); 483 $table->setComment("This is a test'n drop table. You can drop it safely"); 484 485 $this->tables[$table->getName()] = $table; 486 487 try { 488 $dbman->create_table($table); 489 $this->fail('Exception expected'); 490 } catch (moodle_exception $e) { 491 $this->assertInstanceOf('coding_exception', $e); 492 } 493 494 // Invalid float default. 495 $table = new xmldb_table('test_table4'); 496 $table->add_field('id', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, XMLDB_SEQUENCE, null); 497 $table->add_field('num', XMLDB_TYPE_FLOAT, '10,5', null, XMLDB_NOTNULL, null, 'x'); 498 $table->add_key('primary', XMLDB_KEY_PRIMARY, array('id')); 499 $table->setComment("This is a test'n drop table. You can drop it safely"); 500 501 $this->tables[$table->getName()] = $table; 502 503 try { 504 $dbman->create_table($table); 505 $this->fail('Exception expected'); 506 } catch (moodle_exception $e) { 507 $this->assertInstanceOf('coding_exception', $e); 508 } 509 } 510 511 /** 512 * Test if database supports tables with many TEXT fields, 513 * InnoDB is known to failed during data insertion instead 514 * of table creation when text fields contain actual data. 515 */ 516 public function test_row_size_limits() { 517 518 $DB = $this->tdb; // Do not use global $DB! 519 $dbman = $this->tdb->get_manager(); 520 521 $text = str_repeat('š', 1333); 522 523 $data = new stdClass(); 524 $data->name = 'test'; 525 $table = new xmldb_table('test_innodb'); 526 $table->add_field('id', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, XMLDB_SEQUENCE, null); 527 $table->add_field('name', XMLDB_TYPE_CHAR, '30', null, null, null, null); 528 $table->add_key('primary', XMLDB_KEY_PRIMARY, array('id')); 529 for ($i = 0; $i < 20; $i++) { 530 $table->add_field('text'.$i, XMLDB_TYPE_TEXT, null, null, null, null, null); 531 $data->{'text'.$i} = $text; 532 } 533 $dbman->create_table($table); 534 535 try { 536 $id = $DB->insert_record('test_innodb', $data); 537 $expected = (array)$data; 538 $expected['id'] = (string)$id; 539 $this->assertEquals($expected, (array)$DB->get_record('test_innodb', array('id' => $id)), '', 0, 10, true); 540 } catch (dml_exception $e) { 541 // Give some nice error message when known problematic MySQL with InnoDB detected. 542 if ($DB->get_dbfamily() === 'mysql') { 543 $engine = strtolower($DB->get_dbengine()); 544 if ($engine === 'innodb' or $engine === 'xtradb') { 545 if (!$DB->is_compressed_row_format_supported()) { 546 $this->fail("Row size limit reached in MySQL using InnoDB, configure server to use innodb_file_format=Barracuda and innodb_file_per_table=1"); 547 } 548 } 549 } 550 throw $e; 551 } 552 553 $dbman->drop_table($table); 554 555 $data = new stdClass(); 556 $data->name = 'test'; 557 $table = new xmldb_table('test_innodb'); 558 $table->add_field('id', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, XMLDB_SEQUENCE, null); 559 $table->add_field('name', XMLDB_TYPE_CHAR, '30', null, null, null, null); 560 $table->add_key('primary', XMLDB_KEY_PRIMARY, array('id')); 561 $dbman->create_table($table); 562 $DB->insert_record('test_innodb', array('name' => 'test')); 563 564 for ($i = 0; $i < 20; $i++) { 565 $field = new xmldb_field('text'.$i, XMLDB_TYPE_TEXT, null, null, null, null, null); 566 $dbman->add_field($table, $field); 567 $data->{'text'.$i} = $text; 568 569 $id = $DB->insert_record('test_innodb', $data); 570 $expected = (array)$data; 571 $expected['id'] = (string)$id; 572 $this->assertEquals($expected, (array)$DB->get_record('test_innodb', array('id' => $id)), '', 0, 10, true); 573 } 574 575 $dbman->drop_table($table); 576 577 // MySQL VARCHAR fields may hit a different 65535 row size limit when creating tables. 578 $data = new stdClass(); 579 $data->name = 'test'; 580 $table = new xmldb_table('test_innodb'); 581 $table->add_field('id', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, XMLDB_SEQUENCE, null); 582 $table->add_field('name', XMLDB_TYPE_CHAR, '30', null, null, null, null); 583 $table->add_key('primary', XMLDB_KEY_PRIMARY, array('id')); 584 for ($i = 0; $i < 15; $i++) { 585 $table->add_field('text'.$i, XMLDB_TYPE_CHAR, '1333', null, null, null, null); 586 $data->{'text'.$i} = $text; 587 } 588 $dbman->create_table($table); 589 590 $id = $DB->insert_record('test_innodb', $data); 591 $expected = (array)$data; 592 $expected['id'] = (string)$id; 593 $this->assertEquals($expected, (array)$DB->get_record('test_innodb', array('id' => $id)), '', 0, 10, true); 594 595 $dbman->drop_table($table); 596 } 597 598 /** 599 * Test behaviour of drop_table() 600 */ 601 public function test_drop_table() { 602 $DB = $this->tdb; // Do not use global $DB! 603 $dbman = $this->tdb->get_manager(); 604 605 // Initially table doesn't exist. 606 $this->assertFalse($dbman->table_exists('test_table0')); 607 608 // Create table with contents. 609 $table = $this->create_deftable('test_table0'); 610 $this->assertTrue($dbman->table_exists('test_table0')); 611 612 // Fill the table with some records before dropping it. 613 $this->fill_deftable('test_table0'); 614 615 // Drop by xmldb_table object. 616 $dbman->drop_table($table); 617 $this->assertFalse($dbman->table_exists('test_table0')); 618 619 // Basic get_tables() test. 620 $tables = $DB->get_tables(); 621 $this->assertArrayNotHasKey('test_table0', $tables); 622 623 // Columns cache must be empty. 624 $columns = $DB->get_columns('test_table0'); 625 $this->assertEmpty($columns); 626 627 $indexes = $DB->get_indexes('test_table0'); 628 $this->assertEmpty($indexes); 629 } 630 631 /** 632 * Test behaviour of rename_table() 633 */ 634 public function test_rename_table() { 635 $DB = $this->tdb; // Do not use global $DB! 636 $dbman = $this->tdb->get_manager(); 637 638 $table = $this->create_deftable('test_table1'); 639 640 // Fill the table with some records before renaming it. 641 $insertedrows = $this->fill_deftable('test_table1'); 642 643 $this->assertFalse($dbman->table_exists('test_table_cust1')); 644 $dbman->rename_table($table, 'test_table_cust1'); 645 $this->assertTrue($dbman->table_exists('test_table_cust1')); 646 647 // Check sequence returns $insertedrows + 1 for this insert (after rename). 648 $rec = (object)array( 649 'course' => 20, 650 'secondname' => 'not important', 651 'intro' => 'not important'); 652 $this->assertSame($insertedrows+1, $DB->insert_record('test_table_cust1', $rec)); 653 654 // Verify behavior when target table already exists. 655 $sourcetable = $this->create_deftable('test_table0'); 656 $targettable = $this->create_deftable('test_table1'); 657 try { 658 $dbman->rename_table($sourcetable, $targettable->getName()); 659 $this->fail('Exception expected'); 660 } catch (moodle_exception $e) { 661 $this->assertInstanceOf('ddl_exception', $e); 662 $this->assertEquals('Table "test_table1" already exists (can not rename table)', $e->getMessage()); 663 } 664 } 665 666 /** 667 * Test behaviour of field_exists() 668 */ 669 public function test_field_exists() { 670 $dbman = $this->tdb->get_manager(); 671 672 $table = $this->create_deftable('test_table0'); 673 674 // String params. 675 // Give a nonexistent table as first param (throw exception). 676 try { 677 $dbman->field_exists('nonexistenttable', 'id'); 678 $this->fail('Exception expected'); 679 } catch (moodle_exception $e) { 680 $this->assertInstanceOf('moodle_exception', $e); 681 } 682 683 // Give a nonexistent field as second param (return false). 684 $this->assertFalse($dbman->field_exists('test_table0', 'nonexistentfield')); 685 686 // Correct string params. 687 $this->assertTrue($dbman->field_exists('test_table0', 'id')); 688 689 // Object params. 690 $realfield = $table->getField('id'); 691 692 // Give a nonexistent table as first param (throw exception). 693 $nonexistenttable = new xmldb_table('nonexistenttable'); 694 try { 695 $dbman->field_exists($nonexistenttable, $realfield); 696 $this->fail('Exception expected'); 697 } catch (moodle_exception $e) { 698 $this->assertInstanceOf('moodle_exception', $e); 699 } 700 701 // Give a nonexistent field as second param (return false). 702 $nonexistentfield = new xmldb_field('nonexistentfield'); 703 $this->assertFalse($dbman->field_exists($table, $nonexistentfield)); 704 705 // Correct object params. 706 $this->assertTrue($dbman->field_exists($table, $realfield)); 707 708 // Mix string and object params. 709 // Correct ones. 710 $this->assertTrue($dbman->field_exists($table, 'id')); 711 $this->assertTrue($dbman->field_exists('test_table0', $realfield)); 712 // Non existing tables (throw exception). 713 try { 714 $this->assertFalse($dbman->field_exists($nonexistenttable, 'id')); 715 $this->fail('Exception expected'); 716 } catch (moodle_exception $e) { 717 $this->assertInstanceOf('moodle_exception', $e); 718 } 719 try { 720 $this->assertFalse($dbman->field_exists('nonexistenttable', $realfield)); 721 $this->fail('Exception expected'); 722 } catch (moodle_exception $e) { 723 $this->assertInstanceOf('moodle_exception', $e); 724 } 725 // Non existing fields (return false). 726 $this->assertFalse($dbman->field_exists($table, 'nonexistentfield')); 727 $this->assertFalse($dbman->field_exists('test_table0', $nonexistentfield)); 728 } 729 730 /** 731 * Test behaviour of add_field() 732 */ 733 public function test_add_field() { 734 $DB = $this->tdb; // Do not use global $DB! 735 $dbman = $this->tdb->get_manager(); 736 737 $table = $this->create_deftable('test_table1'); 738 739 // Fill the table with some records before adding fields. 740 $this->fill_deftable('test_table1'); 741 742 // Add one not null field without specifying default value (throws ddl_exception). 743 $field = new xmldb_field('onefield'); 744 $field->set_attributes(XMLDB_TYPE_INTEGER, '6', null, XMLDB_NOTNULL, null, null); 745 try { 746 $dbman->add_field($table, $field); 747 $this->fail('Exception expected'); 748 } catch (moodle_exception $e) { 749 $this->assertInstanceOf('ddl_exception', $e); 750 } 751 752 // Add one existing field (throws ddl_exception). 753 $field = new xmldb_field('course'); 754 $field->set_attributes(XMLDB_TYPE_INTEGER, '6', null, XMLDB_NOTNULL, null, 2); 755 try { 756 $dbman->add_field($table, $field); 757 $this->fail('Exception expected'); 758 } catch (moodle_exception $e) { 759 $this->assertInstanceOf('ddl_exception', $e); 760 } 761 762 // TODO: add one field with invalid type, must throw exception. 763 // TODO: add one text field with default, must throw exception. 764 // TODO: add one binary field with default, must throw exception. 765 766 // Add one integer field and check it. 767 $field = new xmldb_field('oneinteger'); 768 $field->set_attributes(XMLDB_TYPE_INTEGER, '6', null, XMLDB_NOTNULL, null, 2); 769 $dbman->add_field($table, $field); 770 $this->assertTrue($dbman->field_exists($table, 'oneinteger')); 771 $columns = $DB->get_columns('test_table1'); 772 $this->assertEquals('oneinteger', $columns['oneinteger']->name); 773 $this->assertTrue($columns['oneinteger']->not_null); 774 // Max_length and scale cannot be checked under all DBs at all for integer fields. 775 $this->assertFalse($columns['oneinteger']->primary_key); 776 $this->assertFalse($columns['oneinteger']->binary); 777 $this->assertTrue($columns['oneinteger']->has_default); 778 $this->assertEquals(2, $columns['oneinteger']->default_value); 779 $this->assertSame('I', $columns['oneinteger']->meta_type); 780 $this->assertEquals(2, $DB->get_field('test_table1', 'oneinteger', array(), IGNORE_MULTIPLE)); // Check default has been applied. 781 782 // Add one numeric field and check it. 783 $field = new xmldb_field('onenumber'); 784 $field->set_attributes(XMLDB_TYPE_NUMBER, '6,3', null, XMLDB_NOTNULL, null, 2.55); 785 $dbman->add_field($table, $field); 786 $this->assertTrue($dbman->field_exists($table, 'onenumber')); 787 $columns = $DB->get_columns('test_table1'); 788 $this->assertSame('onenumber', $columns['onenumber']->name); 789 $this->assertEquals(6, $columns['onenumber']->max_length); 790 $this->assertEquals(3, $columns['onenumber']->scale); 791 $this->assertTrue($columns['onenumber']->not_null); 792 $this->assertFalse($columns['onenumber']->primary_key); 793 $this->assertFalse($columns['onenumber']->binary); 794 $this->assertTrue($columns['onenumber']->has_default); 795 $this->assertEquals(2.550, $columns['onenumber']->default_value); 796 $this->assertSame('N', $columns['onenumber']->meta_type); 797 $this->assertEquals(2.550, $DB->get_field('test_table1', 'onenumber', array(), IGNORE_MULTIPLE)); // Check default has been applied. 798 799 // Add one numeric field with scale of 0 and check it. 800 $field = new xmldb_field('onenumberwith0scale'); 801 $field->set_attributes(XMLDB_TYPE_NUMBER, '6,0', null, XMLDB_NOTNULL, null, 2); 802 $dbman->add_field($table, $field); 803 $this->assertTrue($dbman->field_exists($table, 'onenumberwith0scale')); 804 $columns = $DB->get_columns('test_table1'); 805 $this->assertEquals(6, $columns['onenumberwith0scale']->max_length); 806 // We can not use assertEquals as that accepts null/false as a valid value. 807 $this->assertSame('0', strval($columns['onenumberwith0scale']->scale)); 808 809 // Add one float field and check it (not official type - must work as number). 810 $field = new xmldb_field('onefloat'); 811 $field->set_attributes(XMLDB_TYPE_FLOAT, '6,3', null, XMLDB_NOTNULL, null, 3.550); 812 $dbman->add_field($table, $field); 813 $this->assertTrue($dbman->field_exists($table, 'onefloat')); 814 $columns = $DB->get_columns('test_table1'); 815 $this->assertSame('onefloat', $columns['onefloat']->name); 816 $this->assertTrue($columns['onefloat']->not_null); 817 // Max_length and scale cannot be checked under all DBs at all for float fields. 818 $this->assertFalse($columns['onefloat']->primary_key); 819 $this->assertFalse($columns['onefloat']->binary); 820 $this->assertTrue($columns['onefloat']->has_default); 821 $this->assertEquals(3.550, $columns['onefloat']->default_value); 822 $this->assertSame('N', $columns['onefloat']->meta_type); 823 // Just rounding DB information to 7 decimal digits. Fair enough to test 3.550 and avoids one nasty bug 824 // in MSSQL core returning wrong floats (http://social.msdn.microsoft.com/Forums/en-US/sqldataaccess/thread/5e08de63-16bb-4f24-b645-0cf8fc669de3) 825 // In any case, floats aren't officially supported by Moodle, with number/decimal type being the correct ones, so 826 // this isn't a real problem at all. 827 $this->assertEquals(3.550, round($DB->get_field('test_table1', 'onefloat', array(), IGNORE_MULTIPLE), 7)); // Check default has been applied. 828 829 // Add one char field and check it. 830 $field = new xmldb_field('onechar'); 831 $field->set_attributes(XMLDB_TYPE_CHAR, '25', null, XMLDB_NOTNULL, null, 'Nice dflt!'); 832 $dbman->add_field($table, $field); 833 $this->assertTrue($dbman->field_exists($table, 'onechar')); 834 $columns = $DB->get_columns('test_table1'); 835 $this->assertSame('onechar', $columns['onechar']->name); 836 $this->assertEquals(25, $columns['onechar']->max_length); 837 $this->assertNull($columns['onechar']->scale); 838 $this->assertTrue($columns['onechar']->not_null); 839 $this->assertFalse($columns['onechar']->primary_key); 840 $this->assertFalse($columns['onechar']->binary); 841 $this->assertTrue($columns['onechar']->has_default); 842 $this->assertSame('Nice dflt!', $columns['onechar']->default_value); 843 $this->assertSame('C', $columns['onechar']->meta_type); 844 $this->assertEquals('Nice dflt!', $DB->get_field('test_table1', 'onechar', array(), IGNORE_MULTIPLE)); // Check default has been applied. 845 846 // Add one big text field and check it. 847 $field = new xmldb_field('onetext'); 848 $field->set_attributes(XMLDB_TYPE_TEXT, 'big'); 849 $dbman->add_field($table, $field); 850 $this->assertTrue($dbman->field_exists($table, 'onetext')); 851 $columns = $DB->get_columns('test_table1'); 852 $this->assertSame('onetext', $columns['onetext']->name); 853 $this->assertEquals(-1, $columns['onetext']->max_length); // -1 means unknown or big. 854 $this->assertNull($columns['onetext']->scale); 855 $this->assertFalse($columns['onetext']->not_null); 856 $this->assertFalse($columns['onetext']->primary_key); 857 $this->assertFalse($columns['onetext']->binary); 858 $this->assertFalse($columns['onetext']->has_default); 859 $this->assertNull($columns['onetext']->default_value); 860 $this->assertSame('X', $columns['onetext']->meta_type); 861 862 // Add one medium text field and check it. 863 $field = new xmldb_field('mediumtext'); 864 $field->set_attributes(XMLDB_TYPE_TEXT, 'medium'); 865 $dbman->add_field($table, $field); 866 $columns = $DB->get_columns('test_table1'); 867 $this->assertTrue(($columns['mediumtext']->max_length == -1) or ($columns['mediumtext']->max_length >= 16777215)); // -1 means unknown or big. 868 869 // Add one small text field and check it. 870 $field = new xmldb_field('smalltext'); 871 $field->set_attributes(XMLDB_TYPE_TEXT, 'small'); 872 $dbman->add_field($table, $field); 873 $columns = $DB->get_columns('test_table1'); 874 $this->assertTrue(($columns['smalltext']->max_length == -1) or ($columns['smalltext']->max_length >= 65535)); // -1 means unknown or big. 875 876 // Add one binary field and check it. 877 $field = new xmldb_field('onebinary'); 878 $field->set_attributes(XMLDB_TYPE_BINARY); 879 $dbman->add_field($table, $field); 880 $this->assertTrue($dbman->field_exists($table, 'onebinary')); 881 $columns = $DB->get_columns('test_table1'); 882 $this->assertSame('onebinary', $columns['onebinary']->name); 883 $this->assertEquals(-1, $columns['onebinary']->max_length); 884 $this->assertNull($columns['onebinary']->scale); 885 $this->assertFalse($columns['onebinary']->not_null); 886 $this->assertFalse($columns['onebinary']->primary_key); 887 $this->assertTrue($columns['onebinary']->binary); 888 $this->assertFalse($columns['onebinary']->has_default); 889 $this->assertNull($columns['onebinary']->default_value); 890 $this->assertSame('B', $columns['onebinary']->meta_type); 891 892 // TODO: check datetime type. Although unused should be fully supported. 893 } 894 895 /** 896 * Test behaviour of drop_field() 897 */ 898 public function test_drop_field() { 899 $DB = $this->tdb; // Do not use global $DB! 900 $dbman = $this->tdb->get_manager(); 901 902 $table = $this->create_deftable('test_table0'); 903 904 // Fill the table with some records before dropping fields. 905 $this->fill_deftable('test_table0'); 906 907 // Drop field with simple xmldb_field having indexes, must return exception. 908 $field = new xmldb_field('type'); // Field has indexes and default clause. 909 $this->assertTrue($dbman->field_exists($table, 'type')); 910 try { 911 $dbman->drop_field($table, $field); 912 $this->fail('Exception expected'); 913 } catch (moodle_exception $e) { 914 $this->assertInstanceOf('ddl_dependency_exception', $e); 915 } 916 $this->assertTrue($dbman->field_exists($table, 'type')); // Continues existing, drop aborted. 917 918 // Drop field with complete xmldb_field object and related indexes, must return exception. 919 $field = $table->getField('course'); // Field has indexes and default clause. 920 $this->assertTrue($dbman->field_exists($table, $field)); 921 try { 922 $dbman->drop_field($table, $field); 923 $this->fail('Exception expected'); 924 } catch (moodle_exception $e) { 925 $this->assertInstanceOf('ddl_dependency_exception', $e); 926 } 927 $this->assertTrue($dbman->field_exists($table, $field)); // Continues existing, drop aborted. 928 929 // Drop one non-existing field, must return exception. 930 $field = new xmldb_field('nonexistingfield'); 931 $this->assertFalse($dbman->field_exists($table, $field)); 932 try { 933 $dbman->drop_field($table, $field); 934 $this->fail('Exception expected'); 935 } catch (moodle_exception $e) { 936 $this->assertInstanceOf('ddl_field_missing_exception', $e); 937 } 938 939 // Drop field with simple xmldb_field, not having related indexes. 940 $field = new xmldb_field('forcesubscribe'); // Field has default clause. 941 $this->assertTrue($dbman->field_exists($table, 'forcesubscribe')); 942 $dbman->drop_field($table, $field); 943 $this->assertFalse($dbman->field_exists($table, 'forcesubscribe')); 944 945 // Drop field with complete xmldb_field object, not having related indexes. 946 $field = new xmldb_field('trackingtype'); // Field has default clause. 947 $this->assertTrue($dbman->field_exists($table, $field)); 948 $dbman->drop_field($table, $field); 949 $this->assertFalse($dbman->field_exists($table, $field)); 950 } 951 952 /** 953 * Test behaviour of change_field_type() 954 */ 955 public function test_change_field_type() { 956 $DB = $this->tdb; // Do not use global $DB! 957 $dbman = $this->tdb->get_manager(); 958 959 // Create table with indexed field and not indexed field to 960 // perform tests in both fields, both having defaults. 961 $table = new xmldb_table('test_table_cust0'); 962 $table->add_field('id', XMLDB_TYPE_INTEGER, '2', null, XMLDB_NOTNULL, XMLDB_SEQUENCE, null); 963 $table->add_field('onenumber', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, '2'); 964 $table->add_field('anothernumber', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, '4'); 965 $table->add_key('primary', XMLDB_KEY_PRIMARY, array('id')); 966 $table->add_index('onenumber', XMLDB_INDEX_NOTUNIQUE, array('onenumber')); 967 $dbman->create_table($table); 968 969 $record = new stdClass(); 970 $record->onenumber = 2; 971 $record->anothernumber = 4; 972 $recoriginal = $DB->insert_record('test_table_cust0', $record); 973 974 // Change column from integer to varchar. Must return exception because of dependent index. 975 $field = new xmldb_field('onenumber'); 976 $field->set_attributes(XMLDB_TYPE_CHAR, '30', null, XMLDB_NOTNULL, null, 'test'); 977 try { 978 $dbman->change_field_type($table, $field); 979 $this->fail('Exception expected'); 980 } catch (moodle_exception $e) { 981 $this->assertInstanceOf('ddl_dependency_exception', $e); 982 } 983 // Column continues being integer 10 not null default 2. 984 $columns = $DB->get_columns('test_table_cust0'); 985 $this->assertSame('I', $columns['onenumber']->meta_type); 986 // TODO: check the rest of attributes. 987 988 // Change column from integer to varchar. Must work because column has no dependencies. 989 $field = new xmldb_field('anothernumber'); 990 $field->set_attributes(XMLDB_TYPE_CHAR, '30', null, XMLDB_NOTNULL, null, 'test'); 991 $dbman->change_field_type($table, $field); 992 // Column is char 30 not null default 'test' now. 993 $columns = $DB->get_columns('test_table_cust0'); 994 $this->assertSame('C', $columns['anothernumber']->meta_type); 995 // TODO: check the rest of attributes. 996 997 // Change column back from char to integer. 998 $field = new xmldb_field('anothernumber'); 999 $field->set_attributes(XMLDB_TYPE_INTEGER, '8', null, XMLDB_NOTNULL, null, '5'); 1000 $dbman->change_field_type($table, $field); 1001 // Column is integer 8 not null default 5 now. 1002 $columns = $DB->get_columns('test_table_cust0'); 1003 $this->assertSame('I', $columns['anothernumber']->meta_type); 1004 // TODO: check the rest of attributes. 1005 1006 // Change column once more from integer to char. 1007 $field = new xmldb_field('anothernumber'); 1008 $field->set_attributes(XMLDB_TYPE_CHAR, '20', null, XMLDB_NOTNULL, null, "test'n drop"); 1009 $dbman->change_field_type($table, $field); 1010 // Column is char 30 not null default "test'n drop" now. 1011 $columns = $DB->get_columns('test_table_cust0'); 1012 $this->assertSame('C', $columns['anothernumber']->meta_type); 1013 // TODO: check the rest of attributes. 1014 1015 // Insert one string value and try to convert to integer. Must throw exception. 1016 $record = new stdClass(); 1017 $record->onenumber = 7; 1018 $record->anothernumber = 'string value'; 1019 $rectodrop = $DB->insert_record('test_table_cust0', $record); 1020 $field = new xmldb_field('anothernumber'); 1021 $field->set_attributes(XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, '5'); 1022 try { 1023 $dbman->change_field_type($table, $field); 1024 $this->fail('Exception expected'); 1025 } catch (moodle_exception $e) { 1026 $this->assertInstanceOf('ddl_change_structure_exception', $e); 1027 } 1028 // Column continues being char 30 not null default "test'n drop" now. 1029 $this->assertSame('C', $columns['anothernumber']->meta_type); 1030 // TODO: check the rest of attributes. 1031 $DB->delete_records('test_table_cust0', array('id' => $rectodrop)); // Delete the string record. 1032 1033 // Change the column from varchar to float. 1034 $field = new xmldb_field('anothernumber'); 1035 $field->set_attributes(XMLDB_TYPE_FLOAT, '20,10', null, null, null, null); 1036 $dbman->change_field_type($table, $field); 1037 // Column is float 20,10 null default null. 1038 $columns = $DB->get_columns('test_table_cust0'); 1039 $this->assertSame('N', $columns['anothernumber']->meta_type); // Floats are seen as number. 1040 // TODO: check the rest of attributes. 1041 1042 // Change the column back from float to varchar. 1043 $field = new xmldb_field('anothernumber'); 1044 $field->set_attributes(XMLDB_TYPE_CHAR, '20', null, XMLDB_NOTNULL, null, 'test'); 1045 $dbman->change_field_type($table, $field); 1046 // Column is char 20 not null default "test" now. 1047 $columns = $DB->get_columns('test_table_cust0'); 1048 $this->assertSame('C', $columns['anothernumber']->meta_type); 1049 // TODO: check the rest of attributes. 1050 1051 // Change the column from varchar to number. 1052 $field = new xmldb_field('anothernumber'); 1053 $field->set_attributes(XMLDB_TYPE_NUMBER, '20,10', null, null, null, null); 1054 $dbman->change_field_type($table, $field); 1055 // Column is number 20,10 null default null now. 1056 $columns = $DB->get_columns('test_table_cust0'); 1057 $this->assertSame('N', $columns['anothernumber']->meta_type); 1058 // TODO: check the rest of attributes. 1059 1060 // Change the column from number to integer. 1061 $field = new xmldb_field('anothernumber'); 1062 $field->set_attributes(XMLDB_TYPE_INTEGER, '2', null, null, null, null); 1063 $dbman->change_field_type($table, $field); 1064 // Column is integer 2 null default null now. 1065 $columns = $DB->get_columns('test_table_cust0'); 1066 $this->assertSame('I', $columns['anothernumber']->meta_type); 1067 // TODO: check the rest of attributes. 1068 1069 // Change the column from integer to text. 1070 $field = new xmldb_field('anothernumber'); 1071 $field->set_attributes(XMLDB_TYPE_TEXT, 'big', null, XMLDB_NOTNULL, null, null); 1072 $dbman->change_field_type($table, $field); 1073 // Column is char text not null default null. 1074 $columns = $DB->get_columns('test_table_cust0'); 1075 $this->assertSame('X', $columns['anothernumber']->meta_type); 1076 1077 // Change the column back from text to number. 1078 $field = new xmldb_field('anothernumber'); 1079 $field->set_attributes(XMLDB_TYPE_NUMBER, '20,10', null, null, null, null); 1080 $dbman->change_field_type($table, $field); 1081 // Column is number 20,10 null default null now. 1082 $columns = $DB->get_columns('test_table_cust0'); 1083 $this->assertSame('N', $columns['anothernumber']->meta_type); 1084 // TODO: check the rest of attributes. 1085 1086 // Change the column from number to text. 1087 $field = new xmldb_field('anothernumber'); 1088 $field->set_attributes(XMLDB_TYPE_TEXT, 'big', null, XMLDB_NOTNULL, null, null); 1089 $dbman->change_field_type($table, $field); 1090 // Column is char text not null default "test" now. 1091 $columns = $DB->get_columns('test_table_cust0'); 1092 $this->assertSame('X', $columns['anothernumber']->meta_type); 1093 // TODO: check the rest of attributes. 1094 1095 // Change the column back from text to integer. 1096 $field = new xmldb_field('anothernumber'); 1097 $field->set_attributes(XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, 10); 1098 $dbman->change_field_type($table, $field); 1099 // Column is integer 10 not null default 10. 1100 $columns = $DB->get_columns('test_table_cust0'); 1101 $this->assertSame('I', $columns['anothernumber']->meta_type); 1102 // TODO: check the rest of attributes. 1103 1104 // Check original value has survived to all the type changes. 1105 $this->assertnotEmpty($rec = $DB->get_record('test_table_cust0', array('id' => $recoriginal))); 1106 $this->assertEquals(4, $rec->anothernumber); 1107 1108 $dbman->drop_table($table); 1109 $this->assertFalse($dbman->table_exists($table)); 1110 } 1111 1112 /** 1113 * Test behaviour of test_change_field_precision() 1114 */ 1115 public function test_change_field_precision() { 1116 $DB = $this->tdb; // Do not use global $DB! 1117 $dbman = $this->tdb->get_manager(); 1118 1119 $table = $this->create_deftable('test_table1'); 1120 1121 // Fill the table with some records before dropping fields. 1122 $this->fill_deftable('test_table1'); 1123 1124 // Change text field from medium to big. 1125 $field = new xmldb_field('intro'); 1126 $field->set_attributes(XMLDB_TYPE_TEXT, 'big', null, XMLDB_NOTNULL, null, null); 1127 $dbman->change_field_precision($table, $field); 1128 $columns = $DB->get_columns('test_table1'); 1129 // Cannot check the text type, only the metatype. 1130 $this->assertSame('X', $columns['intro']->meta_type); 1131 // TODO: check the rest of attributes. 1132 1133 // Change char field from 30 to 20. 1134 $field = new xmldb_field('secondname'); 1135 $field->set_attributes(XMLDB_TYPE_CHAR, '20', null, XMLDB_NOTNULL, null, null); 1136 $dbman->change_field_precision($table, $field); 1137 $columns = $DB->get_columns('test_table1'); 1138 $this->assertSame('C', $columns['secondname']->meta_type); 1139 // TODO: check the rest of attributes. 1140 1141 // Change char field from 20 to 10, having contents > 10cc. Throw exception. 1142 $field = new xmldb_field('secondname'); 1143 $field->set_attributes(XMLDB_TYPE_CHAR, '10', null, XMLDB_NOTNULL, null, null); 1144 try { 1145 $dbman->change_field_precision($table, $field); 1146 $this->fail('Exception expected'); 1147 } catch (moodle_exception $e) { 1148 $this->assertInstanceOf('ddl_change_structure_exception', $e); 1149 } 1150 // No changes in field specs at all. 1151 $columns = $DB->get_columns('test_table1'); 1152 $this->assertSame('C', $columns['secondname']->meta_type); 1153 // TODO: check the rest of attributes. 1154 1155 // Change number field from 20,10 to 10,2. 1156 $field = new xmldb_field('grade'); 1157 $field->set_attributes(XMLDB_TYPE_NUMBER, '10,2', null, null, null, null); 1158 $dbman->change_field_precision($table, $field); 1159 $columns = $DB->get_columns('test_table1'); 1160 $this->assertSame('N', $columns['grade']->meta_type); 1161 // TODO: check the rest of attributes. 1162 1163 // Change integer field from 10 to 2. 1164 $field = new xmldb_field('userid'); 1165 $field->set_attributes(XMLDB_TYPE_INTEGER, '2', null, XMLDB_NOTNULL, null, '0'); 1166 $dbman->change_field_precision($table, $field); 1167 $columns = $DB->get_columns('test_table1'); 1168 $this->assertSame('I', $columns['userid']->meta_type); 1169 // TODO: check the rest of attributes. 1170 1171 // Change the column from integer (2) to integer (6) (forces change of type in some DBs). 1172 $field = new xmldb_field('userid'); 1173 $field->set_attributes(XMLDB_TYPE_INTEGER, '6', null, null, null, null); 1174 $dbman->change_field_precision($table, $field); 1175 // Column is integer 6 null default null now. 1176 $columns = $DB->get_columns('test_table1'); 1177 $this->assertSame('I', $columns['userid']->meta_type); 1178 // TODO: check the rest of attributes. 1179 1180 // Insert one record with 6-digit field. 1181 $record = new stdClass(); 1182 $record->course = 10; 1183 $record->secondname = 'third record'; 1184 $record->intro = 'third record'; 1185 $record->userid = 123456; 1186 $DB->insert_record('test_table1', $record); 1187 // Change integer field from 6 to 2, contents are bigger, must throw exception. 1188 $field = new xmldb_field('userid'); 1189 $field->set_attributes(XMLDB_TYPE_INTEGER, '2', null, XMLDB_NOTNULL, null, '0'); 1190 try { 1191 $dbman->change_field_precision($table, $field); 1192 $this->fail('Exception expected'); 1193 } catch (moodle_exception $e) { 1194 $this->assertInstanceOf('ddl_change_structure_exception', $e); 1195 } 1196 // No changes in field specs at all. 1197 $columns = $DB->get_columns('test_table1'); 1198 $this->assertSame('I', $columns['userid']->meta_type); 1199 // TODO: check the rest of attributes. 1200 1201 // Change integer field from 10 to 3, in field used by index. must throw exception. 1202 $field = new xmldb_field('course'); 1203 $field->set_attributes(XMLDB_TYPE_INTEGER, '3', null, XMLDB_NOTNULL, null, '0'); 1204 try { 1205 $dbman->change_field_precision($table, $field); 1206 $this->fail('Exception expected'); 1207 } catch (moodle_exception $e) { 1208 $this->assertInstanceOf('ddl_dependency_exception', $e); 1209 } 1210 // No changes in field specs at all. 1211 $columns = $DB->get_columns('test_table1'); 1212 $this->assertSame('I', $columns['course']->meta_type); 1213 // TODO: check the rest of attributes. 1214 } 1215 1216 public function testChangeFieldNullability() { 1217 $DB = $this->tdb; // Do not use global $DB! 1218 $dbman = $this->tdb->get_manager(); 1219 1220 $table = new xmldb_table('test_table_cust0'); 1221 $table->add_field('id', XMLDB_TYPE_INTEGER, '2', null, XMLDB_NOTNULL, XMLDB_SEQUENCE, null); 1222 $table->add_field('name', XMLDB_TYPE_CHAR, '30', null, XMLDB_NOTNULL, null, null); 1223 $table->add_key('primary', XMLDB_KEY_PRIMARY, array('id')); 1224 $dbman->create_table($table); 1225 1226 $record = new stdClass(); 1227 $record->name = null; 1228 1229 try { 1230 $result = $DB->insert_record('test_table_cust0', $record, false); 1231 } catch (dml_exception $e) { 1232 $result = false; 1233 } 1234 $this->resetDebugging(); 1235 $this->assertFalse($result); 1236 1237 $field = new xmldb_field('name'); 1238 $field->set_attributes(XMLDB_TYPE_CHAR, '30', null, null, null, null); 1239 $dbman->change_field_notnull($table, $field); 1240 1241 $this->assertTrue($DB->insert_record('test_table_cust0', $record, false)); 1242 1243 // TODO: add some tests with existing data in table. 1244 $DB->delete_records('test_table_cust0'); 1245 1246 $field = new xmldb_field('name'); 1247 $field->set_attributes(XMLDB_TYPE_CHAR, '30', null, XMLDB_NOTNULL, null, null); 1248 $dbman->change_field_notnull($table, $field); 1249 1250 try { 1251 $result = $DB->insert_record('test_table_cust0', $record, false); 1252 } catch (dml_exception $e) { 1253 $result = false; 1254 } 1255 $this->resetDebugging(); 1256 $this->assertFalse($result); 1257 1258 $dbman->drop_table($table); 1259 } 1260 1261 public function testChangeFieldDefault() { 1262 $DB = $this->tdb; // Do not use global $DB! 1263 $dbman = $this->tdb->get_manager(); 1264 1265 $table = new xmldb_table('test_table_cust0'); 1266 $table->add_field('id', XMLDB_TYPE_INTEGER, '2', null, XMLDB_NOTNULL, XMLDB_SEQUENCE, null); 1267 $table->add_field('onenumber', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, '0'); 1268 $table->add_field('name', XMLDB_TYPE_CHAR, '30', null, XMLDB_NOTNULL, null, 'Moodle'); 1269 $table->add_key('primary', XMLDB_KEY_PRIMARY, array('id')); 1270 $dbman->create_table($table); 1271 1272 $field = new xmldb_field('name'); 1273 $field->set_attributes(XMLDB_TYPE_CHAR, '30', null, XMLDB_NOTNULL, null, 'Moodle2'); 1274 $dbman->change_field_default($table, $field); 1275 1276 $record = new stdClass(); 1277 $record->onenumber = 666; 1278 $id = $DB->insert_record('test_table_cust0', $record); 1279 1280 $record = $DB->get_record('test_table_cust0', array('id'=>$id)); 1281 $this->assertSame('Moodle2', $record->name); 1282 1283 $field = new xmldb_field('onenumber'); 1284 $field->set_attributes(XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, 666); 1285 $dbman->change_field_default($table, $field); 1286 1287 $record = new stdClass(); 1288 $record->name = 'something'; 1289 $id = $DB->insert_record('test_table_cust0', $record); 1290 1291 $record = $DB->get_record('test_table_cust0', array('id'=>$id)); 1292 $this->assertSame('666', $record->onenumber); 1293 1294 $dbman->drop_table($table); 1295 } 1296 1297 public function testAddUniqueIndex() { 1298 $DB = $this->tdb; // Do not use global $DB! 1299 $dbman = $this->tdb->get_manager(); 1300 1301 $table = new xmldb_table('test_table_cust0'); 1302 $table->add_field('id', XMLDB_TYPE_INTEGER, '2', null, XMLDB_NOTNULL, XMLDB_SEQUENCE, null); 1303 $table->add_field('onenumber', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, '0'); 1304 $table->add_field('name', XMLDB_TYPE_CHAR, '30', null, XMLDB_NOTNULL, null, 'Moodle'); 1305 $table->add_key('primary', XMLDB_KEY_PRIMARY, array('id')); 1306 $dbman->create_table($table); 1307 1308 $record = new stdClass(); 1309 $record->onenumber = 666; 1310 $record->name = 'something'; 1311 $DB->insert_record('test_table_cust0', $record, false); 1312 1313 $index = new xmldb_index('onenumber-name'); 1314 $index->set_attributes(XMLDB_INDEX_UNIQUE, array('onenumber', 'name')); 1315 $dbman->add_index($table, $index); 1316 1317 try { 1318 $result = $DB->insert_record('test_table_cust0', $record, false); 1319 } catch (dml_exception $e) { 1320 $result = false; 1321 } 1322 $this->resetDebugging(); 1323 $this->assertFalse($result); 1324 1325 $dbman->drop_table($table); 1326 } 1327 1328 public function testAddNonUniqueIndex() { 1329 $dbman = $this->tdb->get_manager(); 1330 1331 $table = $this->create_deftable('test_table1'); 1332 $index = new xmldb_index('secondname'); 1333 $index->set_attributes(XMLDB_INDEX_NOTUNIQUE, array('course', 'name')); 1334 $dbman->add_index($table, $index); 1335 $this->assertTrue($dbman->index_exists($table, $index)); 1336 1337 try { 1338 $dbman->add_index($table, $index); 1339 $this->fail('Exception expected for duplicate indexes'); 1340 } catch (moodle_exception $e) { 1341 $this->assertInstanceOf('ddl_exception', $e); 1342 } 1343 1344 $index = new xmldb_index('third'); 1345 $index->set_attributes(XMLDB_INDEX_NOTUNIQUE, array('course')); 1346 try { 1347 $dbman->add_index($table, $index); 1348 $this->fail('Exception expected for duplicate indexes'); 1349 } catch (moodle_exception $e) { 1350 $this->assertInstanceOf('ddl_exception', $e); 1351 } 1352 1353 $table = new xmldb_table('test_table_cust0'); 1354 $table->add_field('id', XMLDB_TYPE_INTEGER, '2', null, XMLDB_NOTNULL, XMLDB_SEQUENCE, null); 1355 $table->add_field('onenumber', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, '0'); 1356 $table->add_field('name', XMLDB_TYPE_CHAR, '30', null, XMLDB_NOTNULL, null, 'Moodle'); 1357 $table->add_key('primary', XMLDB_KEY_PRIMARY, array('id')); 1358 $table->add_key('onenumber', XMLDB_KEY_FOREIGN, array('onenumber')); 1359 1360 try { 1361 $table->add_index('onenumber', XMLDB_INDEX_NOTUNIQUE, array('onenumber')); 1362 $this->fail('Coding exception expected'); 1363 } catch (moodle_exception $e) { 1364 $this->assertInstanceOf('coding_exception', $e); 1365 } 1366 1367 $table = new xmldb_table('test_table_cust0'); 1368 $table->add_field('id', XMLDB_TYPE_INTEGER, '2', null, XMLDB_NOTNULL, XMLDB_SEQUENCE, null); 1369 $table->add_field('onenumber', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, '0'); 1370 $table->add_field('name', XMLDB_TYPE_CHAR, '30', null, XMLDB_NOTNULL, null, 'Moodle'); 1371 $table->add_key('primary', XMLDB_KEY_PRIMARY, array('id')); 1372 $table->add_index('onenumber', XMLDB_INDEX_NOTUNIQUE, array('onenumber')); 1373 1374 try { 1375 $table->add_key('onenumber', XMLDB_KEY_FOREIGN, array('onenumber')); 1376 $this->fail('Coding exception expected'); 1377 } catch (moodle_exception $e) { 1378 $this->assertInstanceOf('coding_exception', $e); 1379 } 1380 1381 } 1382 1383 public function testFindIndexName() { 1384 $dbman = $this->tdb->get_manager(); 1385 1386 $table = $this->create_deftable('test_table1'); 1387 $index = new xmldb_index('secondname'); 1388 $index->set_attributes(XMLDB_INDEX_NOTUNIQUE, array('course', 'name')); 1389 $dbman->add_index($table, $index); 1390 1391 // DBM Systems name their indices differently - do not test the actual index name. 1392 $result = $dbman->find_index_name($table, $index); 1393 $this->assertTrue(!empty($result)); 1394 1395 $nonexistentindex = new xmldb_index('nonexistentindex'); 1396 $nonexistentindex->set_attributes(XMLDB_INDEX_NOTUNIQUE, array('name')); 1397 $this->assertFalse($dbman->find_index_name($table, $nonexistentindex)); 1398 } 1399 1400 public function testDropIndex() { 1401 $DB = $this->tdb; // Do not use global $DB! 1402 1403 $dbman = $this->tdb->get_manager(); 1404 1405 $table = $this->create_deftable('test_table1'); 1406 $index = new xmldb_index('secondname'); 1407 $index->set_attributes(XMLDB_INDEX_NOTUNIQUE, array('course', 'name')); 1408 $dbman->add_index($table, $index); 1409 1410 $dbman->drop_index($table, $index); 1411 $this->assertFalse($dbman->find_index_name($table, $index)); 1412 1413 // Test we are able to drop indexes having hyphens MDL-22804. 1414 // Create index with hyphens (by hand). 1415 $indexname = 'test-index-with-hyphens'; 1416 switch ($DB->get_dbfamily()) { 1417 case 'mysql': 1418 $indexname = '`' . $indexname . '`'; 1419 break; 1420 default: 1421 $indexname = '"' . $indexname . '"'; 1422 } 1423 $stmt = "CREATE INDEX {$indexname} ON {$DB->get_prefix()}test_table1 (course, name)"; 1424 $DB->change_database_structure($stmt); 1425 $this->assertNotEmpty($dbman->find_index_name($table, $index)); 1426 // Index created, let's drop it using db manager stuff. 1427 $index = new xmldb_index('indexname', XMLDB_INDEX_NOTUNIQUE, array('course', 'name')); 1428 $dbman->drop_index($table, $index); 1429 $this->assertFalse($dbman->find_index_name($table, $index)); 1430 } 1431 1432 public function testAddUniqueKey() { 1433 $dbman = $this->tdb->get_manager(); 1434 1435 $table = $this->create_deftable('test_table1'); 1436 $key = new xmldb_key('id-course-grade'); 1437 $key->set_attributes(XMLDB_KEY_UNIQUE, array('id', 'course', 'grade')); 1438 $dbman->add_key($table, $key); 1439 1440 // No easy way to test it, this just makes sure no errors are encountered. 1441 $this->assertTrue(true); 1442 } 1443 1444 public function testAddForeignUniqueKey() { 1445 $dbman = $this->tdb->get_manager(); 1446 1447 $table = $this->create_deftable('test_table1'); 1448 $this->create_deftable('test_table0'); 1449 1450 $key = new xmldb_key('course'); 1451 $key->set_attributes(XMLDB_KEY_FOREIGN_UNIQUE, array('course'), 'test_table0', array('id')); 1452 $dbman->add_key($table, $key); 1453 1454 // No easy way to test it, this just makes sure no errors are encountered. 1455 $this->assertTrue(true); 1456 } 1457 1458 public function testDropKey() { 1459 $dbman = $this->tdb->get_manager(); 1460 1461 $table = $this->create_deftable('test_table1'); 1462 $this->create_deftable('test_table0'); 1463 1464 $key = new xmldb_key('course'); 1465 $key->set_attributes(XMLDB_KEY_FOREIGN_UNIQUE, array('course'), 'test_table0', array('id')); 1466 $dbman->add_key($table, $key); 1467 1468 $dbman->drop_key($table, $key); 1469 1470 // No easy way to test it, this just makes sure no errors are encountered. 1471 $this->assertTrue(true); 1472 } 1473 1474 public function testAddForeignKey() { 1475 $dbman = $this->tdb->get_manager(); 1476 1477 $table = $this->create_deftable('test_table1'); 1478 $this->create_deftable('test_table0'); 1479 1480 $key = new xmldb_key('course'); 1481 $key->set_attributes(XMLDB_KEY_FOREIGN, array('course'), 'test_table0', array('id')); 1482 $dbman->add_key($table, $key); 1483 1484 // No easy way to test it, this just makes sure no errors are encountered. 1485 $this->assertTrue(true); 1486 } 1487 1488 public function testDropForeignKey() { 1489 $dbman = $this->tdb->get_manager(); 1490 1491 $table = $this->create_deftable('test_table1'); 1492 $this->create_deftable('test_table0'); 1493 1494 $key = new xmldb_key('course'); 1495 $key->set_attributes(XMLDB_KEY_FOREIGN, array('course'), 'test_table0', array('id')); 1496 $dbman->add_key($table, $key); 1497 1498 $dbman->drop_key($table, $key); 1499 1500 // No easy way to test it, this just makes sure no errors are encountered. 1501 $this->assertTrue(true); 1502 } 1503 1504 public function testRenameField() { 1505 $DB = $this->tdb; // Do not use global $DB! 1506 $dbman = $this->tdb->get_manager(); 1507 1508 $table = $this->create_deftable('test_table0'); 1509 $field = new xmldb_field('type'); 1510 $field->set_attributes(XMLDB_TYPE_CHAR, '20', null, XMLDB_NOTNULL, null, 'general', 'course'); 1511 1512 $dbman->rename_field($table, $field, 'newfieldname'); 1513 1514 $columns = $DB->get_columns('test_table0'); 1515 1516 $this->assertArrayNotHasKey('type', $columns); 1517 $this->assertArrayHasKey('newfieldname', $columns); 1518 } 1519 1520 public function testIndexExists() { 1521 // Skipping: this is just a test of find_index_name. 1522 } 1523 1524 public function testFindKeyName() { 1525 $dbman = $this->tdb->get_manager(); 1526 1527 $table = $this->create_deftable('test_table0'); 1528 $key = $table->getKey('primary'); 1529 1530 // With Mysql, the return value is actually "mdl_test_id_pk". 1531 $result = $dbman->find_key_name($table, $key); 1532 $this->assertTrue(!empty($result)); 1533 } 1534 1535 public function testDeleteTablesFromXmldbFile() { 1536 $dbman = $this->tdb->get_manager(); 1537 1538 $this->create_deftable('test_table1'); 1539 1540 $this->assertTrue($dbman->table_exists('test_table1')); 1541 1542 // Feed nonexistent file. 1543 try { 1544 $dbman->delete_tables_from_xmldb_file('fpsoiudfposui'); 1545 $this->fail('Exception expected'); 1546 } catch (moodle_exception $e) { 1547 $this->resetDebugging(); 1548 $this->assertInstanceOf('moodle_exception', $e); 1549 } 1550 1551 try { 1552 $dbman->delete_tables_from_xmldb_file(__DIR__ . '/fixtures/invalid.xml'); 1553 $this->fail('Exception expected'); 1554 } catch (moodle_exception $e) { 1555 $this->resetDebugging(); 1556 $this->assertInstanceOf('moodle_exception', $e); 1557 } 1558 1559 // Check that the table has not been deleted from DB. 1560 $this->assertTrue($dbman->table_exists('test_table1')); 1561 1562 // Real and valid xml file. 1563 // TODO: drop UNSINGED completely in Moodle 2.4. 1564 $dbman->delete_tables_from_xmldb_file(__DIR__ . '/fixtures/xmldb_table.xml'); 1565 1566 // Check that the table has been deleted from DB. 1567 $this->assertFalse($dbman->table_exists('test_table1')); 1568 } 1569 1570 public function testInstallFromXmldbFile() { 1571 $dbman = $this->tdb->get_manager(); 1572 1573 // Feed nonexistent file. 1574 try { 1575 $dbman->install_from_xmldb_file('fpsoiudfposui'); 1576 $this->fail('Exception expected'); 1577 } catch (moodle_exception $e) { 1578 $this->resetDebugging(); 1579 $this->assertInstanceOf('moodle_exception', $e); 1580 } 1581 1582 try { 1583 $dbman->install_from_xmldb_file(__DIR__ . '/fixtures/invalid.xml'); 1584 $this->fail('Exception expected'); 1585 } catch (moodle_exception $e) { 1586 $this->resetDebugging(); 1587 $this->assertInstanceOf('moodle_exception', $e); 1588 } 1589 1590 // Check that the table has not yet been created in DB. 1591 $this->assertFalse($dbman->table_exists('test_table1')); 1592 1593 // Real and valid xml file. 1594 $dbman->install_from_xmldb_file(__DIR__ . '/fixtures/xmldb_table.xml'); 1595 $this->assertTrue($dbman->table_exists('test_table1')); 1596 } 1597 1598 public function test_temp_tables() { 1599 $DB = $this->tdb; // Do not use global $DB! 1600 $dbman = $this->tdb->get_manager(); 1601 1602 // Create temp table0. 1603 $table0 = $this->tables['test_table0']; 1604 $dbman->create_temp_table($table0); 1605 $this->assertTrue($dbman->table_exists('test_table0')); 1606 1607 // Try to create temp table with same name, must throw exception. 1608 $dupetable = $this->tables['test_table0']; 1609 try { 1610 $dbman->create_temp_table($dupetable); 1611 $this->fail('Exception expected'); 1612 } catch (moodle_exception $e) { 1613 $this->assertInstanceOf('ddl_exception', $e); 1614 } 1615 1616 // Try to create table with same name, must throw exception. 1617 $dupetable = $this->tables['test_table0']; 1618 try { 1619 $dbman->create_table($dupetable); 1620 $this->fail('Exception expected'); 1621 } catch (moodle_exception $e) { 1622 $this->assertInstanceOf('ddl_exception', $e); 1623 } 1624 1625 // Create another temp table1. 1626 $table1 = $this->tables['test_table1']; 1627 $dbman->create_temp_table($table1); 1628 $this->assertTrue($dbman->table_exists('test_table1')); 1629 1630 // Get columns and perform some basic tests. 1631 $columns = $DB->get_columns('test_table1'); 1632 $this->assertCount(11, $columns); 1633 $this->assertTrue($columns['name'] instanceof database_column_info); 1634 $this->assertEquals(30, $columns['name']->max_length); 1635 $this->assertTrue($columns['name']->has_default); 1636 $this->assertEquals('Moodle', $columns['name']->default_value); 1637 1638 // Insert some records. 1639 $inserted = $this->fill_deftable('test_table1'); 1640 $records = $DB->get_records('test_table1'); 1641 $this->assertCount($inserted, $records); 1642 $this->assertSame($records[1]->course, $this->records['test_table1'][0]->course); 1643 $this->assertSame($records[1]->secondname, $this->records['test_table1'][0]->secondname); 1644 $this->assertSame($records[2]->intro, $this->records['test_table1'][1]->intro); 1645 1646 // Collect statistics about the data in the temp table. 1647 $DB->update_temp_table_stats(); 1648 1649 // Drop table1. 1650 $dbman->drop_table($table1); 1651 $this->assertFalse($dbman->table_exists('test_table1')); 1652 1653 // Try to drop non-existing temp table, must throw exception. 1654 $noetable = $this->tables['test_table1']; 1655 try { 1656 $dbman->drop_table($noetable); 1657 $this->fail('Exception expected'); 1658 } catch (moodle_exception $e) { 1659 $this->assertInstanceOf('ddl_table_missing_exception', $e); 1660 } 1661 1662 // Collect statistics about the data in the temp table with less tables. 1663 $DB->update_temp_table_stats(); 1664 1665 // Fill/modify/delete a few table0 records. 1666 1667 // Drop table0. 1668 $dbman->drop_table($table0); 1669 $this->assertFalse($dbman->table_exists('test_table0')); 1670 1671 // Create another temp table1. 1672 $table1 = $this->tables['test_table1']; 1673 $dbman->create_temp_table($table1); 1674 $this->assertTrue($dbman->table_exists('test_table1')); 1675 1676 // Make sure it can be dropped using deprecated drop_temp_table(). 1677 $dbman->drop_temp_table($table1); 1678 $this->assertFalse($dbman->table_exists('test_table1')); 1679 $this->assertDebuggingCalled(); 1680 1681 // Try join with normal tables - MS SQL may use incompatible collation. 1682 $table1 = new xmldb_table('test_table'); 1683 $table1->add_field('id', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, XMLDB_SEQUENCE, null); 1684 $table1->add_field('name', XMLDB_TYPE_CHAR, 255, null, XMLDB_NOTNULL, null); 1685 $table1->add_key('primary', XMLDB_KEY_PRIMARY, array('id')); 1686 $dbman->create_table($table1); 1687 1688 $table2 = new xmldb_table('test_temp'); 1689 $table2->add_field('id', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, XMLDB_SEQUENCE, null); 1690 $table2->add_field('name', XMLDB_TYPE_CHAR, 255, null, XMLDB_NOTNULL, null); 1691 $table2->add_key('primary', XMLDB_KEY_PRIMARY, array('id')); 1692 $dbman->create_temp_table($table2); 1693 1694 $record = array('name' => 'a'); 1695 $DB->insert_record('test_table', $record); 1696 $DB->insert_record('test_temp', $record); 1697 1698 $record = array('name' => 'b'); 1699 $DB->insert_record('test_table', $record); 1700 1701 $record = array('name' => 'c'); 1702 $DB->insert_record('test_temp', $record); 1703 1704 $sql = "SELECT * 1705 FROM {test_table} n 1706 JOIN {test_temp} t ON t.name = n.name"; 1707 $records = $DB->get_records_sql($sql); 1708 $this->assertCount(1, $records); 1709 1710 // Drop temp table. 1711 $dbman->drop_table($table2); 1712 $this->assertFalse($dbman->table_exists('test_temp')); 1713 } 1714 1715 public function test_concurrent_temp_tables() { 1716 $DB = $this->tdb; // Do not use global $DB! 1717 $dbman = $this->tdb->get_manager(); 1718 1719 // Define 2 records. 1720 $record1 = (object)array( 1721 'course' => 1, 1722 'secondname' => '11 important', 1723 'intro' => '111 important'); 1724 $record2 = (object)array( 1725 'course' => 2, 1726 'secondname' => '22 important', 1727 'intro' => '222 important'); 1728 1729 // Create temp table1 and insert 1 record (in DB). 1730 $table = $this->tables['test_table1']; 1731 $dbman->create_temp_table($table); 1732 $this->assertTrue($dbman->table_exists('test_table1')); 1733 $inserted = $DB->insert_record('test_table1', $record1); 1734 1735 // Switch to new connection. 1736 $cfg = $DB->export_dbconfig(); 1737 if (!isset($cfg->dboptions)) { 1738 $cfg->dboptions = array(); 1739 } 1740 $DB2 = moodle_database::get_driver_instance($cfg->dbtype, $cfg->dblibrary); 1741 $DB2->connect($cfg->dbhost, $cfg->dbuser, $cfg->dbpass, $cfg->dbname, $cfg->prefix, $cfg->dboptions); 1742 $dbman2 = $DB2->get_manager(); 1743 $this->assertFalse($dbman2->table_exists('test_table1')); // Temp table not exists in DB2. 1744 1745 // Create temp table1 and insert 1 record (in DB2). 1746 $table = $this->tables['test_table1']; 1747 $dbman2->create_temp_table($table); 1748 $this->assertTrue($dbman2->table_exists('test_table1')); 1749 $inserted = $DB2->insert_record('test_table1', $record2); 1750 1751 $dbman2->drop_table($table); // Drop temp table before closing DB2. 1752 $this->assertFalse($dbman2->table_exists('test_table1')); 1753 $DB2->dispose(); // Close DB2. 1754 1755 $this->assertTrue($dbman->table_exists('test_table1')); // Check table continues existing for DB. 1756 $dbman->drop_table($table); // Drop temp table. 1757 $this->assertFalse($dbman->table_exists('test_table1')); 1758 } 1759 1760 public function test_reset_sequence() { 1761 $DB = $this->tdb; 1762 $dbman = $DB->get_manager(); 1763 1764 $table = new xmldb_table('testtable'); 1765 $table->add_field('id', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, XMLDB_SEQUENCE, null); 1766 $table->add_field('course', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, '0'); 1767 $table->add_key('primary', XMLDB_KEY_PRIMARY, array('id')); 1768 1769 // Drop if exists. 1770 if ($dbman->table_exists($table)) { 1771 $dbman->drop_table($table); 1772 } 1773 $dbman->create_table($table); 1774 $tablename = $table->getName(); 1775 $this->tables[$tablename] = $table; 1776 1777 $record = (object)array('id'=>666, 'course'=>10); 1778 $DB->import_record('testtable', $record); 1779 $DB->delete_records('testtable'); // This delete performs one TRUNCATE. 1780 1781 $dbman->reset_sequence($table); // Using xmldb object. 1782 $this->assertEquals(1, $DB->insert_record('testtable', (object)array('course'=>13))); 1783 1784 $record = (object)array('id'=>666, 'course'=>10); 1785 $DB->import_record('testtable', $record); 1786 $DB->delete_records('testtable', array()); // This delete performs one DELETE. 1787 1788 $dbman->reset_sequence($table); // Using xmldb object. 1789 $this->assertEquals(1, $DB->insert_record('testtable', (object)array('course'=>13)), 1790 'Some versions of MySQL 5.6.x are known to not support lowering of auto-increment numbers.'); 1791 1792 $DB->import_record('testtable', $record); 1793 $dbman->reset_sequence($tablename); // Using string. 1794 $this->assertEquals(667, $DB->insert_record('testtable', (object)array('course'=>13))); 1795 1796 $dbman->drop_table($table); 1797 } 1798 1799 public function test_reserved_words() { 1800 $reserved = sql_generator::getAllReservedWords(); 1801 $this->assertTrue(count($reserved) > 1); 1802 } 1803 1804 public function test_index_hints() { 1805 $DB = $this->tdb; 1806 $dbman = $DB->get_manager(); 1807 1808 $table = new xmldb_table('testtable'); 1809 $table->add_field('id', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, XMLDB_SEQUENCE, null); 1810 $table->add_field('name', XMLDB_TYPE_CHAR, 255, null, XMLDB_NOTNULL, null); 1811 $table->add_field('path', XMLDB_TYPE_CHAR, 255, null, XMLDB_NOTNULL, null); 1812 $table->add_key('primary', XMLDB_KEY_PRIMARY, array('id')); 1813 $table->add_index('name', XMLDB_INDEX_NOTUNIQUE, array('name'), array('xxxx,yyyy')); 1814 $table->add_index('path', XMLDB_INDEX_NOTUNIQUE, array('path'), array('varchar_pattern_ops')); 1815 1816 // Drop if exists. 1817 if ($dbman->table_exists($table)) { 1818 $dbman->drop_table($table); 1819 } 1820 $dbman->create_table($table); 1821 $tablename = $table->getName(); 1822 $this->tables[$tablename] = $table; 1823 1824 $table = new xmldb_table('testtable'); 1825 $index = new xmldb_index('name', XMLDB_INDEX_NOTUNIQUE, array('name'), array('xxxx,yyyy')); 1826 $this->assertTrue($dbman->index_exists($table, $index)); 1827 1828 $table = new xmldb_table('testtable'); 1829 $index = new xmldb_index('path', XMLDB_INDEX_NOTUNIQUE, array('path'), array('varchar_pattern_ops')); 1830 $this->assertTrue($dbman->index_exists($table, $index)); 1831 1832 // Try unique indexes too. 1833 $dbman->drop_table($this->tables[$tablename]); 1834 1835 $table = new xmldb_table('testtable'); 1836 $table->add_field('id', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, XMLDB_SEQUENCE, null); 1837 $table->add_field('path', XMLDB_TYPE_CHAR, 255, null, XMLDB_NOTNULL, null); 1838 $table->add_key('primary', XMLDB_KEY_PRIMARY, array('id')); 1839 $table->add_index('path', XMLDB_INDEX_UNIQUE, array('path'), array('varchar_pattern_ops')); 1840 $dbman->create_table($table); 1841 $this->tables[$tablename] = $table; 1842 1843 $table = new xmldb_table('testtable'); 1844 $index = new xmldb_index('path', XMLDB_INDEX_UNIQUE, array('path'), array('varchar_pattern_ops')); 1845 $this->assertTrue($dbman->index_exists($table, $index)); 1846 } 1847 1848 public function test_index_max_bytes() { 1849 $DB = $this->tdb; 1850 $dbman = $DB->get_manager(); 1851 1852 $maxstr = ''; 1853 for ($i=0; $i<255; $i++) { 1854 $maxstr .= '言'; // Random long string that should fix exactly the limit for one char column. 1855 } 1856 1857 $table = new xmldb_table('testtable'); 1858 $table->add_field('id', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, XMLDB_SEQUENCE, null); 1859 $table->add_field('name', XMLDB_TYPE_CHAR, 255, null, XMLDB_NOTNULL, null); 1860 $table->add_key('primary', XMLDB_KEY_PRIMARY, array('id')); 1861 $table->add_index('name', XMLDB_INDEX_NOTUNIQUE, array('name')); 1862 1863 // Drop if exists. 1864 if ($dbman->table_exists($table)) { 1865 $dbman->drop_table($table); 1866 } 1867 $dbman->create_table($table); 1868 $tablename = $table->getName(); 1869 $this->tables[$tablename] = $table; 1870 1871 $rec = new stdClass(); 1872 $rec->name = $maxstr; 1873 1874 $id = $DB->insert_record($tablename, $rec); 1875 $this->assertTrue(!empty($id)); 1876 1877 $rec = $DB->get_record($tablename, array('id'=>$id)); 1878 $this->assertSame($maxstr, $rec->name); 1879 1880 $dbman->drop_table($table); 1881 1882 $table = new xmldb_table('testtable'); 1883 $table->add_field('id', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, XMLDB_SEQUENCE, null); 1884 $table->add_field('name', XMLDB_TYPE_CHAR, 255+1, null, XMLDB_NOTNULL, null); 1885 $table->add_key('primary', XMLDB_KEY_PRIMARY, array('id')); 1886 $table->add_index('name', XMLDB_INDEX_NOTUNIQUE, array('name')); 1887 1888 try { 1889 $dbman->create_table($table); 1890 $this->fail('Exception expected'); 1891 } catch (moodle_exception $e) { 1892 $this->assertInstanceOf('coding_exception', $e); 1893 } 1894 } 1895 1896 public function test_index_composed_max_bytes() { 1897 $DB = $this->tdb; 1898 $dbman = $DB->get_manager(); 1899 1900 $maxstr = ''; 1901 for ($i=0; $i<200; $i++) { 1902 $maxstr .= '言'; 1903 } 1904 $reststr = ''; 1905 for ($i=0; $i<133; $i++) { 1906 $reststr .= '言'; 1907 } 1908 1909 $table = new xmldb_table('testtable'); 1910 $table->add_field('id', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, XMLDB_SEQUENCE, null); 1911 $table->add_field('name1', XMLDB_TYPE_CHAR, 200, null, XMLDB_NOTNULL, null); 1912 $table->add_field('name2', XMLDB_TYPE_CHAR, 133, null, XMLDB_NOTNULL, null); 1913 $table->add_key('primary', XMLDB_KEY_PRIMARY, array('id')); 1914 $table->add_index('name1-name2', XMLDB_INDEX_NOTUNIQUE, array('name1', 'name2')); 1915 1916 // Drop if exists. 1917 if ($dbman->table_exists($table)) { 1918 $dbman->drop_table($table); 1919 } 1920 $dbman->create_table($table); 1921 $tablename = $table->getName(); 1922 $this->tables[$tablename] = $table; 1923 1924 $rec = new stdClass(); 1925 $rec->name1 = $maxstr; 1926 $rec->name2 = $reststr; 1927 1928 $id = $DB->insert_record($tablename, $rec); 1929 $this->assertTrue(!empty($id)); 1930 1931 $rec = $DB->get_record($tablename, array('id'=>$id)); 1932 $this->assertSame($maxstr, $rec->name1); 1933 $this->assertSame($reststr, $rec->name2); 1934 1935 $table = new xmldb_table('testtable'); 1936 $table->add_field('id', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, XMLDB_SEQUENCE, null); 1937 $table->add_field('name1', XMLDB_TYPE_CHAR, 201, null, XMLDB_NOTNULL, null); 1938 $table->add_field('name2', XMLDB_TYPE_CHAR, 133, null, XMLDB_NOTNULL, null); 1939 $table->add_key('primary', XMLDB_KEY_PRIMARY, array('id')); 1940 $table->add_index('name1-name2', XMLDB_INDEX_NOTUNIQUE, array('name1', 'name2')); 1941 1942 // Drop if exists. 1943 if ($dbman->table_exists($table)) { 1944 $dbman->drop_table($table); 1945 } 1946 1947 try { 1948 $dbman->create_table($table); 1949 $this->fail('Exception expected'); 1950 } catch (moodle_exception $e) { 1951 $this->assertInstanceOf('coding_exception', $e); 1952 } 1953 } 1954 1955 public function test_char_size_limit() { 1956 $DB = $this->tdb; 1957 $dbman = $DB->get_manager(); 1958 1959 $table = new xmldb_table('testtable'); 1960 $table->add_field('id', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, XMLDB_SEQUENCE, null); 1961 $table->add_field('name', XMLDB_TYPE_CHAR, xmldb_field::CHAR_MAX_LENGTH, null, XMLDB_NOTNULL, null); 1962 $table->add_key('primary', XMLDB_KEY_PRIMARY, array('id')); 1963 1964 // Drop if exists. 1965 if ($dbman->table_exists($table)) { 1966 $dbman->drop_table($table); 1967 } 1968 $dbman->create_table($table); 1969 $tablename = $table->getName(); 1970 $this->tables[$tablename] = $table; 1971 1972 // This has to work in all DBs. 1973 $maxstr = ''; 1974 for ($i=0; $i<xmldb_field::CHAR_MAX_LENGTH; $i++) { 1975 $maxstr .= 'a'; // Ascii only. 1976 } 1977 1978 $rec = new stdClass(); 1979 $rec->name = $maxstr; 1980 1981 $id = $DB->insert_record($tablename, $rec); 1982 $this->assertTrue(!empty($id)); 1983 1984 $rec = $DB->get_record($tablename, array('id'=>$id)); 1985 $this->assertSame($maxstr, $rec->name); 1986 1987 // Following test is supposed to fail in oracle. 1988 $maxstr = ''; 1989 for ($i=0; $i<xmldb_field::CHAR_MAX_LENGTH; $i++) { 1990 $maxstr .= '言'; // Random long string that should fix exactly the limit for one char column. 1991 } 1992 1993 $rec = new stdClass(); 1994 $rec->name = $maxstr; 1995 1996 try { 1997 $id = $DB->insert_record($tablename, $rec); 1998 $this->assertTrue(!empty($id)); 1999 2000 $rec = $DB->get_record($tablename, array('id'=>$id)); 2001 $this->assertSame($maxstr, $rec->name); 2002 } catch (dml_exception $e) { 2003 if ($DB->get_dbfamily() === 'oracle') { 2004 $this->fail('Oracle does not support text fields larger than 4000 bytes, this is not a big problem for mostly ascii based languages'); 2005 } else { 2006 throw $e; 2007 } 2008 } 2009 2010 $table = new xmldb_table('testtable'); 2011 $table->add_field('id', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, XMLDB_SEQUENCE, null); 2012 $table->add_field('name', XMLDB_TYPE_CHAR, xmldb_field::CHAR_MAX_LENGTH+1, null, XMLDB_NOTNULL, null); 2013 $table->add_key('primary', XMLDB_KEY_PRIMARY, array('id')); 2014 2015 // Drop if exists. 2016 if ($dbman->table_exists($table)) { 2017 $dbman->drop_table($table); 2018 } 2019 $tablename = $table->getName(); 2020 $this->tables[$tablename] = $table; 2021 2022 try { 2023 $dbman->create_table($table); 2024 $this->fail('Exception expected'); 2025 } catch (moodle_exception $e) { 2026 $this->assertInstanceOf('coding_exception', $e); 2027 } 2028 } 2029 2030 public function test_object_name() { 2031 $gen = $this->tdb->get_manager()->generator; 2032 2033 // This will form short object name and max length should not be exceeded. 2034 $table = 'tablename'; 2035 $fields = 'id'; 2036 $suffix = 'pk'; 2037 for ($i=0; $i<12; $i++) { 2038 $this->assertLessThanOrEqual($gen->names_max_length, 2039 strlen($gen->getNameForObject($table, $fields, $suffix)), 2040 'Generated object name is too long. $i = '.$i); 2041 } 2042 2043 // This will form too long object name always and it must be trimmed to exactly 30 chars. 2044 $table = 'aaaa_bbbb_cccc_dddd_eeee_ffff_gggg'; 2045 $fields = 'aaaaa,bbbbb,ccccc,ddddd'; 2046 $suffix = 'idx'; 2047 for ($i=0; $i<12; $i++) { 2048 $this->assertEquals($gen->names_max_length, 2049 strlen($gen->getNameForObject($table, $fields, $suffix)), 2050 'Generated object name is too long. $i = '.$i); 2051 } 2052 2053 // Same test without suffix. 2054 $table = 'bbbb_cccc_dddd_eeee_ffff_gggg_hhhh'; 2055 $fields = 'aaaaa,bbbbb,ccccc,ddddd'; 2056 $suffix = ''; 2057 for ($i=0; $i<12; $i++) { 2058 $this->assertEquals($gen->names_max_length, 2059 strlen($gen->getNameForObject($table, $fields, $suffix)), 2060 'Generated object name is too long. $i = '.$i); 2061 } 2062 2063 // This must only trim name when counter is 10 or more. 2064 $table = 'cccc_dddd_eeee_ffff_gggg_hhhh_iiii'; 2065 $fields = 'id'; 2066 $suffix = 'idx'; 2067 // Since we don't know how long prefix is, loop to generate tablename that gives exactly maxlengh-1 length. 2068 // Skip this test if prefix is too long. 2069 while (strlen($table) && strlen($gen->prefix.preg_replace('/_/','',$table).'_id_'.$suffix) >= $gen->names_max_length) { 2070 $table = rtrim(substr($table, 0, strlen($table) - 1), '_'); 2071 } 2072 if (strlen($table)) { 2073 $this->assertEquals($gen->names_max_length - 1, 2074 strlen($gen->getNameForObject($table, $fields, $suffix))); 2075 for ($i=0; $i<12; $i++) { 2076 $this->assertEquals($gen->names_max_length, 2077 strlen($gen->getNameForObject($table, $fields, $suffix)), 2078 'Generated object name is too long. $i = '.$i); 2079 } 2080 } 2081 } 2082 2083 // Following methods are not supported == Do not test. 2084 /* 2085 public function testRenameIndex() { 2086 // Unsupported! 2087 $dbman = $this->tdb->get_manager(); 2088 2089 $table = $this->create_deftable('test_table0'); 2090 $index = new xmldb_index('course'); 2091 $index->set_attributes(XMLDB_INDEX_UNIQUE, array('course')); 2092 2093 $this->assertTrue($dbman->rename_index($table, $index, 'newindexname')); 2094 } 2095 2096 public function testRenameKey() { 2097 // Unsupported! 2098 $dbman = $this->tdb->get_manager(); 2099 2100 $table = $this->create_deftable('test_table0'); 2101 $key = new xmldb_key('course'); 2102 $key->set_attributes(XMLDB_KEY_UNIQUE, array('course')); 2103 2104 $this->assertTrue($dbman->rename_key($table, $key, 'newkeyname')); 2105 } 2106 */ 2107 2108 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
Generated: Fri Nov 28 20:29:05 2014 | Cross-referenced by PHPXref 0.7.1 |