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