|
Moodle
2.2.1
http://www.collinsharper.com
|
00001 <?php 00007 if (!defined('MOODLE_INTERNAL')) { 00008 die('Direct access to this script is forbidden.'); 00009 } 00010 00011 require_once($CFG->libdir . '/adminlib.php'); 00012 00013 class ddl_test extends UnitTestCase { 00014 private $tables = array(); 00015 private $records= array(); 00016 private $tdb; 00017 public static $includecoverage = array('lib/ddl'); 00018 public static $excludecoverage = array('lib/ddl/simpletest'); 00019 00020 public function setUp() { 00021 global $CFG, $DB, $UNITTEST; 00022 00023 if (isset($UNITTEST->func_test_db)) { 00024 $this->tdb = $UNITTEST->func_test_db; 00025 } else { 00026 $this->tdb = $DB; 00027 } 00028 00029 unset($CFG->xmldbreconstructprevnext); // remove this unhack ;-) 00030 00031 $dbman = $this->tdb->get_manager(); 00032 00033 $table = new xmldb_table('test_table0'); 00034 $table->add_field('id', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, XMLDB_SEQUENCE, null); 00035 $table->add_field('course', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '0'); 00036 $table->add_field('type', XMLDB_TYPE_CHAR, '20', null, XMLDB_NOTNULL, null, 'general'); 00037 $table->add_field('name', XMLDB_TYPE_CHAR, '255', null, XMLDB_NOTNULL, null); 00038 $table->add_field('intro', XMLDB_TYPE_TEXT, 'small', null, XMLDB_NOTNULL, null, null); 00039 $table->add_field('logo', XMLDB_TYPE_BINARY, 'big', null, null, null); 00040 $table->add_field('assessed', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '0'); 00041 $table->add_field('assesstimestart', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '0'); 00042 $table->add_field('assesstimefinish', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '0'); 00043 $table->add_field('scale', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, '0'); 00044 $table->add_field('maxbytes', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '0'); 00045 $table->add_field('forcesubscribe', XMLDB_TYPE_INTEGER, '1', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '0'); 00046 $table->add_field('trackingtype', XMLDB_TYPE_INTEGER, '2', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '1'); 00047 $table->add_field('rsstype', XMLDB_TYPE_INTEGER, '2', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '0'); 00048 $table->add_field('rssarticles', XMLDB_TYPE_INTEGER, '2', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '0'); 00049 $table->add_field('timemodified', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '0'); 00050 $table->add_field('grade', XMLDB_TYPE_NUMBER, '20,0', XMLDB_UNSIGNED, null, null, null); 00051 $table->add_field('percent', XMLDB_TYPE_NUMBER, '5,2', null, null, null, 66.6); 00052 $table->add_field('warnafter', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '0'); 00053 $table->add_field('blockafter', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '0'); 00054 $table->add_field('blockperiod', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '0'); 00055 $table->add_key('primary', XMLDB_KEY_PRIMARY, array('id')); 00056 $table->add_key('course', XMLDB_KEY_UNIQUE, array('course')); 00057 $table->add_index('type-name', XMLDB_INDEX_UNIQUE, array('type', 'name')); 00058 $table->add_index('rsstype', XMLDB_INDEX_NOTUNIQUE, array('rsstype')); 00059 $table->setComment("This is a test'n drop table. You can drop it safely"); 00060 00061 $this->tables[$table->getName()] = $table; 00062 00063 // Define 2 initial records for this table 00064 $this->records[$table->getName()] = array( 00065 (object)array( 00066 'course' => '1', 00067 'type' => 'general', 00068 'name' => 'record', 00069 'intro' => 'first record'), 00070 (object)array( 00071 'course' => '2', 00072 'type' => 'social', 00073 'name' => 'record', 00074 'intro' => 'second record')); 00075 00076 // Second, smaller table 00077 $table = new xmldb_table ('test_table1'); 00078 $table->add_field('id', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, XMLDB_SEQUENCE, null); 00079 $table->add_field('course', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '0'); 00080 $table->add_field('name', XMLDB_TYPE_CHAR, '30', null, null, null, 'Moodle'); 00081 $table->add_field('secondname', XMLDB_TYPE_CHAR, '30', null, XMLDB_NOTNULL, null, null); 00082 $table->add_field('thirdname', XMLDB_TYPE_CHAR, '30', null, null, null, ''); // nullable column with empty default 00083 $table->add_field('intro', XMLDB_TYPE_TEXT, 'medium', null, XMLDB_NOTNULL, null, null); 00084 $table->add_field('avatar', XMLDB_TYPE_BINARY, 'medium', null, null, null, null); 00085 $table->add_field('grade', XMLDB_TYPE_NUMBER, '20,10', null, null, null); 00086 $table->add_field('gradefloat', XMLDB_TYPE_FLOAT, '20,0', XMLDB_UNSIGNED, null, null, null); 00087 $table->add_field('percentfloat', XMLDB_TYPE_FLOAT, '5,2', null, null, null, 99.9); 00088 $table->add_field('userid', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '0'); 00089 $table->add_key('primary', XMLDB_KEY_PRIMARY, array('id')); 00090 $table->add_key('course', XMLDB_KEY_FOREIGN_UNIQUE, array('course'), 'test_table0', array('course')); 00091 $table->setComment("This is a test'n drop table. You can drop it safely"); 00092 00093 $this->tables[$table->getName()] = $table; 00094 00095 // Define 2 initial records for this table 00096 $this->records[$table->getName()] = array( 00097 (object)array( 00098 'course' => '1', 00099 'secondname' => 'first record', // > 10 cc, please don't modify. Some tests below depend of this 00100 'intro' => 'first record'), 00101 (object)array( 00102 'course' => '2', 00103 'secondname' => 'second record', // > 10 cc, please don't modify. Some tests below depend of this 00104 'intro' => 'second record')); 00105 00106 // make sure no tables are present! 00107 $this->tearDown(); 00108 } 00109 00110 public function tearDown() { 00111 $dbman = $this->tdb->get_manager(); 00112 00113 // drop custom test tables 00114 for ($i=0; $i<3; $i++) { 00115 $table = new xmldb_table('test_table_cust'.$i); 00116 if ($dbman->table_exists($table)) { 00117 $dbman->drop_table($table); 00118 } 00119 } 00120 00121 // drop default tables 00122 foreach ($this->tables as $table) { 00123 if ($dbman->table_exists($table)) { 00124 $dbman->drop_table($table); 00125 } 00126 } 00127 } 00128 00129 private function create_deftable($tablename) { 00130 $dbman = $this->tdb->get_manager(); 00131 00132 if (!isset($this->tables[$tablename])) { 00133 return null; 00134 } 00135 00136 $table = $this->tables[$tablename]; 00137 00138 if ($dbman->table_exists($table)) { 00139 $dbman->drop_table($table); 00140 } 00141 $dbman->create_table($table); 00142 00143 return $table; 00144 } 00145 00151 private function fill_deftable($tablename) { 00152 $DB = $this->tdb; // do not use global $DB! 00153 $dbman = $this->tdb->get_manager(); 00154 00155 if (!isset($this->records[$tablename])) { 00156 return null; 00157 } 00158 00159 if ($dbman->table_exists($tablename)) { 00160 foreach ($this->records[$tablename] as $row) { 00161 $DB->insert_record($tablename, $row); 00162 } 00163 } else { 00164 return null; 00165 } 00166 00167 return count($this->records[$tablename]); 00168 } 00169 00173 public function test_table_exists() { 00174 $DB = $this->tdb; // do not use global $DB! 00175 $dbman = $this->tdb->get_manager(); 00176 00177 // first make sure it returns false if table does not exist 00178 $table = $this->tables['test_table0']; 00179 00180 ob_start(); // hide debug warning 00181 try { 00182 $result = $DB->get_records('test_table0'); 00183 } catch (dml_exception $e) { 00184 $result = false; 00185 } 00186 ob_end_clean(); 00187 00188 $this->assertFalse($result); 00189 00190 $this->assertFalse($dbman->table_exists('test_table0')); // by name 00191 $this->assertFalse($dbman->table_exists($table)); // by xmldb_table 00192 00193 // create table and test again 00194 $dbman->create_table($table); 00195 00196 $this->assertTrue($DB->get_records('test_table0') === array()); 00197 $this->assertTrue($dbman->table_exists('test_table0')); // by name 00198 $this->assertTrue($dbman->table_exists($table)); // by xmldb_table 00199 00200 // drop table and test again 00201 $dbman->drop_table($table); 00202 00203 ob_start(); // hide debug warning 00204 try { 00205 $result = $DB->get_records('test_table0'); 00206 } catch (dml_exception $e) { 00207 $result = false; 00208 } 00209 ob_end_clean(); 00210 00211 $this->assertFalse($result); 00212 00213 $this->assertFalse($dbman->table_exists('test_table0')); // by name 00214 $this->assertFalse($dbman->table_exists($table)); // by xmldb_table 00215 } 00216 00220 public function test_create_table() { 00221 $DB = $this->tdb; // do not use global $DB! 00222 $dbman = $this->tdb->get_manager(); 00223 00224 // create table 00225 $table = $this->tables['test_table1']; 00226 00227 $dbman->create_table($table); 00228 $this->assertTrue($dbman->table_exists($table)); 00229 00230 // basic get_tables() test 00231 $tables = $DB->get_tables(); 00232 $this->assertTrue(array_key_exists('test_table1', $tables)); 00233 00234 // basic get_columns() tests 00235 $columns = $DB->get_columns('test_table1'); 00236 $this->assertEqual($columns['id']->meta_type, 'R'); 00237 $this->assertEqual($columns['course']->meta_type, 'I'); 00238 $this->assertEqual($columns['name']->meta_type, 'C'); 00239 $this->assertEqual($columns['secondname']->meta_type, 'C'); 00240 $this->assertEqual($columns['thirdname']->meta_type, 'C'); 00241 $this->assertEqual($columns['intro']->meta_type, 'X'); 00242 $this->assertEqual($columns['avatar']->meta_type, 'B'); 00243 $this->assertEqual($columns['grade']->meta_type, 'N'); 00244 $this->assertEqual($columns['percentfloat']->meta_type, 'N'); 00245 $this->assertEqual($columns['userid']->meta_type, 'I'); 00246 // some defaults 00247 $this->assertTrue($columns['course']->has_default); 00248 $this->assertEqual($columns['course']->default_value, 0); 00249 $this->assertTrue($columns['name']->has_default); 00250 $this->assertEqual($columns['name']->default_value, 'Moodle'); 00251 $this->assertTrue($columns['secondname']->has_default); 00252 $this->assertEqual($columns['secondname']->default_value, ''); 00253 $this->assertTrue($columns['thirdname']->has_default); 00254 $this->assertEqual($columns['thirdname']->default_value, ''); 00255 $this->assertTrue($columns['percentfloat']->has_default); 00256 $this->assertEqual($columns['percentfloat']->default_value, 99.9); 00257 $this->assertTrue($columns['userid']->has_default); 00258 $this->assertEqual($columns['userid']->default_value, 0); 00259 00260 // basic get_indexes() test 00261 $indexes = $DB->get_indexes('test_table1'); 00262 $courseindex = reset($indexes); 00263 $this->assertEqual($courseindex['unique'], 1); 00264 $this->assertEqual($courseindex['columns'][0], 'course'); 00265 00266 // check sequence returns 1 for first insert 00267 $rec = (object)array( 00268 'course' => 10, 00269 'secondname' => 'not important', 00270 'intro' => 'not important'); 00271 $this->assertIdentical($DB->insert_record('test_table1', $rec), 1); 00272 00273 // check defined defaults are working ok 00274 $dbrec = $DB->get_record('test_table1', array('id' => 1)); 00275 $this->assertEqual($dbrec->name, 'Moodle'); 00276 $this->assertEqual($dbrec->thirdname, ''); 00277 00278 // check exceptions if multiple R columns 00279 $table = new xmldb_table ('test_table2'); 00280 $table->add_field('id', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, XMLDB_SEQUENCE, null); 00281 $table->add_field('rid', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, XMLDB_SEQUENCE, null); 00282 $table->add_field('course', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '0'); 00283 $table->add_key('primary', XMLDB_KEY_PRIMARY, array('id')); 00284 $table->add_key('primaryx', XMLDB_KEY_PRIMARY, array('id')); 00285 $table->setComment("This is a test'n drop table. You can drop it safely"); 00286 00287 $this->tables[$table->getName()] = $table; 00288 00289 try { 00290 $dbman->create_table($table); 00291 $this->fail('Exception expected'); 00292 } catch (Exception $e) { 00293 $this->assertTrue($e instanceof ddl_exception); 00294 } 00295 00296 // check exceptions missing primary key on R column 00297 $table = new xmldb_table ('test_table2'); 00298 $table->add_field('id', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, XMLDB_SEQUENCE, null); 00299 $table->add_field('course', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '0'); 00300 $table->setComment("This is a test'n drop table. You can drop it safely"); 00301 00302 $this->tables[$table->getName()] = $table; 00303 00304 try { 00305 $dbman->create_table($table); 00306 $this->fail('Exception expected'); 00307 } catch (Exception $e) { 00308 $this->assertTrue($e instanceof ddl_exception); 00309 } 00310 00311 } 00312 00316 public function test_drop_table() { 00317 $DB = $this->tdb; // do not use global $DB! 00318 $dbman = $this->tdb->get_manager(); 00319 00320 // initially table doesn't exist 00321 $this->assertFalse($dbman->table_exists('test_table0')); 00322 00323 // create table with contents 00324 $table = $this->create_deftable('test_table0'); 00325 $this->assertTrue($dbman->table_exists('test_table0')); 00326 00327 // fill the table with some records before dropping it 00328 $this->fill_deftable('test_table0'); 00329 00330 // drop by xmldb_table object 00331 $dbman->drop_table($table); 00332 $this->assertFalse($dbman->table_exists('test_table0')); 00333 00334 // basic get_tables() test 00335 $tables = $DB->get_tables(); 00336 $this->assertFalse(array_key_exists('test_table0', $tables)); 00337 00338 try { // columns cache must be empty, so sentence throw exception 00339 $columns = $DB->get_columns('test_table0'); 00340 } catch (dml_exception $e) { 00341 $columns = false; 00342 } 00343 $this->assertFalse($columns); 00344 00345 try { 00346 $indexes = $DB->get_indexes('test_table0'); 00347 } catch (dml_exception $e) { 00348 $indexes = false; 00349 } 00350 $this->assertFalse($indexes); 00351 } 00352 00356 public function test_rename_table() { 00357 $DB = $this->tdb; // do not use global $DB! 00358 $dbman = $this->tdb->get_manager(); 00359 00360 $table = $this->create_deftable('test_table1'); 00361 00362 // fill the table with some records before renaming it 00363 $insertedrows = $this->fill_deftable('test_table1'); 00364 00365 $this->assertFalse($dbman->table_exists('test_table_cust1')); 00366 $dbman->rename_table($table, 'test_table_cust1'); 00367 $this->assertTrue($dbman->table_exists('test_table_cust1')); 00368 00369 // check sequence returns $insertedrows + 1 for this insert (after rename) 00370 $rec = (object)array( 00371 'course' => 20, 00372 'secondname' => 'not important', 00373 'intro' => 'not important'); 00374 $this->assertIdentical($DB->insert_record('test_table_cust1', $rec), $insertedrows + 1); 00375 } 00376 00380 public function test_field_exists() { 00381 $dbman = $this->tdb->get_manager(); 00382 00383 $table = $this->create_deftable('test_table0'); 00384 00385 // String params 00386 // Give a nonexistent table as first param (throw exception) 00387 try { 00388 $dbman->field_exists('nonexistenttable', 'id'); 00389 $this->assertTrue(false); 00390 } catch (Exception $e) { 00391 $this->assertTrue($e instanceof moodle_exception); 00392 } 00393 00394 // Give a nonexistent field as second param (return false) 00395 $this->assertFalse($dbman->field_exists('test_table0', 'nonexistentfield')); 00396 00397 // Correct string params 00398 $this->assertTrue($dbman->field_exists('test_table0', 'id')); 00399 00400 // Object params 00401 $realfield = $table->getField('id'); 00402 00403 // Give a nonexistent table as first param (throw exception) 00404 $nonexistenttable = new xmldb_table('nonexistenttable'); 00405 try { 00406 $dbman->field_exists($nonexistenttable, $realfield); 00407 $this->assertTrue(false); 00408 } catch (Exception $e) { 00409 $this->assertTrue($e instanceof moodle_exception); 00410 } 00411 00412 // Give a nonexistent field as second param (return false) 00413 $nonexistentfield = new xmldb_field('nonexistentfield'); 00414 $this->assertFalse($dbman->field_exists($table, $nonexistentfield)); 00415 00416 // Correct object params 00417 $this->assertTrue($dbman->field_exists($table, $realfield)); 00418 00419 // Mix string and object params 00420 // Correct ones 00421 $this->assertTrue($dbman->field_exists($table, 'id')); 00422 $this->assertTrue($dbman->field_exists('test_table0', $realfield)); 00423 // Non existing tables (throw exception) 00424 try { 00425 $this->assertFalse($dbman->field_exists($nonexistenttable, 'id')); 00426 $this->assertTrue(false); 00427 } catch (Exception $e) { 00428 $this->assertTrue($e instanceof moodle_exception); 00429 } 00430 try { 00431 $this->assertFalse($dbman->field_exists('nonexistenttable', $realfield)); 00432 $this->assertTrue(false); 00433 } catch (Exception $e) { 00434 $this->assertTrue($e instanceof moodle_exception); 00435 } 00436 // Non existing fields (return false) 00437 $this->assertFalse($dbman->field_exists($table, 'nonexistentfield')); 00438 $this->assertFalse($dbman->field_exists('test_table0', $nonexistentfield)); 00439 } 00440 00444 public function test_add_field() { 00445 $DB = $this->tdb; // do not use global $DB! 00446 $dbman = $this->tdb->get_manager(); 00447 00448 $table = $this->create_deftable('test_table1'); 00449 00450 // fill the table with some records before adding fields 00451 $this->fill_deftable('test_table1'); 00452 00454 $field = new xmldb_field('onefield'); 00455 $field->set_attributes(XMLDB_TYPE_INTEGER, '6', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, null); 00456 try { 00457 $dbman->add_field($table, $field); 00458 $this->assertTrue(false); 00459 } catch (Exception $e) { 00460 $this->assertTrue($e instanceof ddl_exception); 00461 } 00462 00464 $field = new xmldb_field('course'); 00465 $field->set_attributes(XMLDB_TYPE_INTEGER, '6', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, 2); 00466 try { 00467 $dbman->add_field($table, $field); 00468 $this->assertTrue(false); 00469 } catch (Exception $e) { 00470 $this->assertTrue($e instanceof ddl_exception); 00471 } 00472 00473 // TODO: add one field with invalid type, must throw exception 00474 // TODO: add one text field with default, must throw exception 00475 // TODO: add one binary field with default, must throw exception 00476 00478 $field = new xmldb_field('oneinteger'); 00479 $field->set_attributes(XMLDB_TYPE_INTEGER, '6', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, 2); 00480 $dbman->add_field($table, $field); 00481 $this->assertTrue($dbman->field_exists($table, 'oneinteger')); 00482 $columns = $DB->get_columns('test_table1'); 00483 $this->assertEqual($columns['oneinteger']->name ,'oneinteger'); 00484 $this->assertEqual($columns['oneinteger']->not_null , true); 00485 // max_length and scale cannot be checked under all DBs at all for integer fields 00486 $this->assertEqual($columns['oneinteger']->primary_key , false); 00487 $this->assertEqual($columns['oneinteger']->binary , false); 00488 $this->assertEqual($columns['oneinteger']->has_default , true); 00489 $this->assertEqual($columns['oneinteger']->default_value, 2); 00490 $this->assertEqual($columns['oneinteger']->meta_type ,'I'); 00491 $this->assertEqual($DB->get_field('test_table1', 'oneinteger', array(), IGNORE_MULTIPLE), 2); //check default has been applied 00492 00494 $field = new xmldb_field('onenumber'); 00495 $field->set_attributes(XMLDB_TYPE_NUMBER, '6,3', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, 2.55); 00496 $dbman->add_field($table, $field); 00497 $this->assertTrue($dbman->field_exists($table, 'onenumber')); 00498 $columns = $DB->get_columns('test_table1'); 00499 $this->assertEqual($columns['onenumber']->name ,'onenumber'); 00500 $this->assertEqual($columns['onenumber']->max_length , 6); 00501 $this->assertEqual($columns['onenumber']->scale , 3); 00502 $this->assertEqual($columns['onenumber']->not_null , true); 00503 $this->assertEqual($columns['onenumber']->primary_key , false); 00504 $this->assertEqual($columns['onenumber']->binary , false); 00505 $this->assertEqual($columns['onenumber']->has_default , true); 00506 $this->assertEqual($columns['onenumber']->default_value, 2.550); 00507 $this->assertEqual($columns['onenumber']->meta_type ,'N'); 00508 $this->assertEqual($DB->get_field('test_table1', 'onenumber', array(), IGNORE_MULTIPLE), 2.550); //check default has been applied 00509 00511 $field = new xmldb_field('onefloat'); 00512 $field->set_attributes(XMLDB_TYPE_FLOAT, '6,3', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, 3.550); 00513 $dbman->add_field($table, $field); 00514 $this->assertTrue($dbman->field_exists($table, 'onefloat')); 00515 $columns = $DB->get_columns('test_table1'); 00516 $this->assertEqual($columns['onefloat']->name ,'onefloat'); 00517 $this->assertEqual($columns['onefloat']->not_null , true); 00518 // max_length and scale cannot be checked under all DBs at all for float fields 00519 $this->assertEqual($columns['onefloat']->primary_key , false); 00520 $this->assertEqual($columns['onefloat']->binary , false); 00521 $this->assertEqual($columns['onefloat']->has_default , true); 00522 $this->assertEqual($columns['onefloat']->default_value, 3.550); 00523 $this->assertEqual($columns['onefloat']->meta_type ,'N'); 00524 // Just rounding DB information to 7 decimal digits. Fair enough to test 3.550 and avoids one nasty bug 00525 // in MSSQL core returning wrong floats (http://social.msdn.microsoft.com/Forums/en-US/sqldataaccess/thread/5e08de63-16bb-4f24-b645-0cf8fc669de3) 00526 // In any case, floats aren't officially supported by Moodle, with number/decimal type being the correct ones, so 00527 // this isn't a real problem at all. 00528 $this->assertEqual(round($DB->get_field('test_table1', 'onefloat', array(), IGNORE_MULTIPLE), 7), 3.550); //check default has been applied 00529 00531 $field = new xmldb_field('onechar'); 00532 $field->set_attributes(XMLDB_TYPE_CHAR, '25', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, 'Nice dflt!'); 00533 $dbman->add_field($table, $field); 00534 $this->assertTrue($dbman->field_exists($table, 'onechar')); 00535 $columns = $DB->get_columns('test_table1'); 00536 $this->assertEqual($columns['onechar']->name ,'onechar'); 00537 $this->assertEqual($columns['onechar']->max_length , 25); 00538 $this->assertEqual($columns['onechar']->scale , null); 00539 $this->assertEqual($columns['onechar']->not_null , true); 00540 $this->assertEqual($columns['onechar']->primary_key , false); 00541 $this->assertEqual($columns['onechar']->binary , false); 00542 $this->assertEqual($columns['onechar']->has_default , true); 00543 $this->assertEqual($columns['onechar']->default_value,'Nice dflt!'); 00544 $this->assertEqual($columns['onechar']->meta_type ,'C'); 00545 $this->assertEqual($DB->get_field('test_table1', 'onechar', array(), IGNORE_MULTIPLE), 'Nice dflt!'); //check default has been applied 00546 00548 $field = new xmldb_field('onetext'); 00549 $field->set_attributes(XMLDB_TYPE_TEXT); 00550 $dbman->add_field($table, $field); 00551 $this->assertTrue($dbman->field_exists($table, 'onetext')); 00552 $columns = $DB->get_columns('test_table1'); 00553 $this->assertEqual($columns['onetext']->name ,'onetext'); 00554 $this->assertEqual($columns['onetext']->max_length , -1); 00555 $this->assertEqual($columns['onetext']->scale , null); 00556 $this->assertEqual($columns['onetext']->not_null , false); 00557 $this->assertEqual($columns['onetext']->primary_key , false); 00558 $this->assertEqual($columns['onetext']->binary , false); 00559 $this->assertEqual($columns['onetext']->has_default , false); 00560 $this->assertEqual($columns['onetext']->default_value, null); 00561 $this->assertEqual($columns['onetext']->meta_type ,'X'); 00562 00564 $field = new xmldb_field('onebinary'); 00565 $field->set_attributes(XMLDB_TYPE_BINARY); 00566 $dbman->add_field($table, $field); 00567 $this->assertTrue($dbman->field_exists($table, 'onebinary')); 00568 $columns = $DB->get_columns('test_table1'); 00569 $this->assertEqual($columns['onebinary']->name ,'onebinary'); 00570 $this->assertEqual($columns['onebinary']->max_length , -1); 00571 $this->assertEqual($columns['onebinary']->scale , null); 00572 $this->assertEqual($columns['onebinary']->not_null , false); 00573 $this->assertEqual($columns['onebinary']->primary_key , false); 00574 $this->assertEqual($columns['onebinary']->binary , true); 00575 $this->assertEqual($columns['onebinary']->has_default , false); 00576 $this->assertEqual($columns['onebinary']->default_value, null); 00577 $this->assertEqual($columns['onebinary']->meta_type ,'B'); 00578 00579 // TODO: check datetime type. Although unused should be fully supported. 00580 } 00581 00585 public function test_drop_field() { 00586 $DB = $this->tdb; // do not use global $DB! 00587 $dbman = $this->tdb->get_manager(); 00588 00589 $table = $this->create_deftable('test_table0'); 00590 00591 // fill the table with some records before dropping fields 00592 $this->fill_deftable('test_table0'); 00593 00594 // drop field with simple xmldb_field having indexes, must return exception 00595 $field = new xmldb_field('type'); // Field has indexes and default clause 00596 $this->assertTrue($dbman->field_exists($table, 'type')); 00597 try { 00598 $dbman->drop_field($table, $field); 00599 $this->assertTrue(false); 00600 } catch (Exception $e) { 00601 $this->assertTrue($e instanceof ddl_dependency_exception); 00602 } 00603 $this->assertTrue($dbman->field_exists($table, 'type')); // continues existing, drop aborted 00604 00605 // drop field with complete xmldb_field object and related indexes, must return exception 00606 $field = $table->getField('course'); // Field has indexes and default clause 00607 $this->assertTrue($dbman->field_exists($table, $field)); 00608 try { 00609 $dbman->drop_field($table, $field); 00610 $this->assertTrue(false); 00611 } catch (Exception $e) { 00612 $this->assertTrue($e instanceof ddl_dependency_exception); 00613 } 00614 $this->assertTrue($dbman->field_exists($table, $field)); // continues existing, drop aborted 00615 00616 // drop one non-existing field, must return exception 00617 $field = new xmldb_field('nonexistingfield'); 00618 $this->assertFalse($dbman->field_exists($table, $field)); 00619 try { 00620 $dbman->drop_field($table, $field); 00621 $this->assertTrue(false); 00622 } catch (Exception $e) { 00623 $this->assertTrue($e instanceof ddl_field_missing_exception); 00624 } 00625 00626 // drop field with simple xmldb_field, not having related indexes 00627 $field = new xmldb_field('forcesubscribe'); // Field has default clause 00628 $this->assertTrue($dbman->field_exists($table, 'forcesubscribe')); 00629 $dbman->drop_field($table, $field); 00630 $this->assertFalse($dbman->field_exists($table, 'forcesubscribe')); 00631 00632 00633 // drop field with complete xmldb_field object, not having related indexes 00634 $field = new xmldb_field('trackingtype'); // Field has default clause 00635 $this->assertTrue($dbman->field_exists($table, $field)); 00636 $dbman->drop_field($table, $field); 00637 $this->assertFalse($dbman->field_exists($table, $field)); 00638 } 00639 00643 public function test_change_field_type() { 00644 $DB = $this->tdb; // do not use global $DB! 00645 $dbman = $this->tdb->get_manager(); 00646 00647 // create table with indexed field and not indexed field to 00648 // perform tests in both fields, both having defaults 00649 $table = new xmldb_table('test_table_cust0'); 00650 $table->add_field('id', XMLDB_TYPE_INTEGER, '2', XMLDB_UNSIGNED, XMLDB_NOTNULL, XMLDB_SEQUENCE, null); 00651 $table->add_field('onenumber', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '2'); 00652 $table->add_field('anothernumber', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '4'); 00653 $table->add_key('primary', XMLDB_KEY_PRIMARY, array('id')); 00654 $table->add_index('onenumber', XMLDB_INDEX_NOTUNIQUE, array('onenumber')); 00655 $dbman->create_table($table); 00656 00657 $record = new stdClass(); 00658 $record->onenumber = 2; 00659 $record->anothernumber = 4; 00660 $recoriginal = $DB->insert_record('test_table_cust0', $record); 00661 00662 // change column from integer to varchar. Must return exception because of dependent index 00663 $field = new xmldb_field('onenumber'); 00664 $field->set_attributes(XMLDB_TYPE_CHAR, '30', null, XMLDB_NOTNULL, null, 'test'); 00665 try { 00666 $dbman->change_field_type($table, $field); 00667 $this->assertTrue(false); 00668 } catch (Exception $e) { 00669 $this->assertTrue($e instanceof ddl_dependency_exception); 00670 } 00671 // column continues being integer 10 not null default 2 00672 $columns = $DB->get_columns('test_table_cust0'); 00673 $this->assertEqual($columns['onenumber']->meta_type, 'I'); 00674 //TODO: check the rest of attributes 00675 00676 // change column from integer to varchar. Must work because column has no dependencies 00677 $field = new xmldb_field('anothernumber'); 00678 $field->set_attributes(XMLDB_TYPE_CHAR, '30', null, XMLDB_NOTNULL, null, 'test'); 00679 $dbman->change_field_type($table, $field); 00680 // column is char 30 not null default 'test' now 00681 $columns = $DB->get_columns('test_table_cust0'); 00682 $this->assertEqual($columns['anothernumber']->meta_type, 'C'); 00683 //TODO: check the rest of attributes 00684 00685 // change column back from char to integer 00686 $field = new xmldb_field('anothernumber'); 00687 $field->set_attributes(XMLDB_TYPE_INTEGER, '8', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '5'); 00688 $dbman->change_field_type($table, $field); 00689 // column is integer 8 not null default 5 now 00690 $columns = $DB->get_columns('test_table_cust0'); 00691 $this->assertEqual($columns['anothernumber']->meta_type, 'I'); 00692 //TODO: check the rest of attributes 00693 00694 // change column once more from integer to char 00695 $field = new xmldb_field('anothernumber'); 00696 $field->set_attributes(XMLDB_TYPE_CHAR, '20', null, XMLDB_NOTNULL, null, "test'n drop"); 00697 $dbman->change_field_type($table, $field); 00698 // column is char 30 not null default "test'n drop" now 00699 $columns = $DB->get_columns('test_table_cust0'); 00700 $this->assertEqual($columns['anothernumber']->meta_type, 'C'); 00701 //TODO: check the rest of attributes 00702 00703 // insert one string value and try to convert to integer. Must throw exception 00704 $record = new stdClass(); 00705 $record->onenumber = 7; 00706 $record->anothernumber = 'string value'; 00707 $rectodrop = $DB->insert_record('test_table_cust0', $record); 00708 $field = new xmldb_field('anothernumber'); 00709 $field->set_attributes(XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '5'); 00710 try { 00711 $dbman->change_field_type($table, $field); 00712 $this->assertTrue(false); 00713 } catch (Exception $e) { 00714 $this->assertTrue($e instanceof ddl_change_structure_exception); 00715 } 00716 // column continues being char 30 not null default "test'n drop" now 00717 $this->assertEqual($columns['anothernumber']->meta_type, 'C'); 00718 //TODO: check the rest of attributes 00719 $DB->delete_records('test_table_cust0', array('id' => $rectodrop)); // Delete the string record 00720 00721 // change the column from varchar to float 00722 $field = new xmldb_field('anothernumber'); 00723 $field->set_attributes(XMLDB_TYPE_FLOAT, '20,10', XMLDB_UNSIGNED, null, null, null); 00724 $dbman->change_field_type($table, $field); 00725 // column is float 20,10 null default null 00726 $columns = $DB->get_columns('test_table_cust0'); 00727 $this->assertEqual($columns['anothernumber']->meta_type, 'N'); // floats are seen as number 00728 //TODO: check the rest of attributes 00729 00730 // change the column back from float to varchar 00731 $field = new xmldb_field('anothernumber'); 00732 $field->set_attributes(XMLDB_TYPE_CHAR, '20', null, XMLDB_NOTNULL, null, 'test'); 00733 $dbman->change_field_type($table, $field); 00734 // column is char 20 not null default "test" now 00735 $columns = $DB->get_columns('test_table_cust0'); 00736 $this->assertEqual($columns['anothernumber']->meta_type, 'C'); 00737 //TODO: check the rest of attributes 00738 00739 // change the column from varchar to number 00740 $field = new xmldb_field('anothernumber'); 00741 $field->set_attributes(XMLDB_TYPE_NUMBER, '20,10', XMLDB_UNSIGNED, null, null, null); 00742 $dbman->change_field_type($table, $field); 00743 // column is number 20,10 null default null now 00744 $columns = $DB->get_columns('test_table_cust0'); 00745 $this->assertEqual($columns['anothernumber']->meta_type, 'N'); 00746 //TODO: check the rest of attributes 00747 00748 // change the column from number to integer 00749 $field = new xmldb_field('anothernumber'); 00750 $field->set_attributes(XMLDB_TYPE_INTEGER, '2', XMLDB_UNSIGNED, null, null, null); 00751 $dbman->change_field_type($table, $field); 00752 // column is integer 2 null default null now 00753 $columns = $DB->get_columns('test_table_cust0'); 00754 $this->assertEqual($columns['anothernumber']->meta_type, 'I'); 00755 //TODO: check the rest of attributes 00756 00757 // change the column from integer to text 00758 $field = new xmldb_field('anothernumber'); 00759 $field->set_attributes(XMLDB_TYPE_TEXT, 'big', null, XMLDB_NOTNULL, null, null); 00760 $dbman->change_field_type($table, $field); 00761 // column is char text not null default null 00762 $columns = $DB->get_columns('test_table_cust0'); 00763 $this->assertEqual($columns['anothernumber']->meta_type, 'X'); 00764 00765 // change the column back from text to number 00766 $field = new xmldb_field('anothernumber'); 00767 $field->set_attributes(XMLDB_TYPE_NUMBER, '20,10', XMLDB_UNSIGNED, null, null, null); 00768 $dbman->change_field_type($table, $field); 00769 // column is number 20,10 null default null now 00770 $columns = $DB->get_columns('test_table_cust0'); 00771 $this->assertEqual($columns['anothernumber']->meta_type, 'N'); 00772 //TODO: check the rest of attributes 00773 00774 // change the column from number to text 00775 $field = new xmldb_field('anothernumber'); 00776 $field->set_attributes(XMLDB_TYPE_TEXT, 'big', null, XMLDB_NOTNULL, null, null); 00777 $dbman->change_field_type($table, $field); 00778 // column is char text not null default "test" now 00779 $columns = $DB->get_columns('test_table_cust0'); 00780 $this->assertEqual($columns['anothernumber']->meta_type, 'X'); 00781 //TODO: check the rest of attributes 00782 00783 // change the column back from text to integer 00784 $field = new xmldb_field('anothernumber'); 00785 $field->set_attributes(XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, 10); 00786 $dbman->change_field_type($table, $field); 00787 // column is integer 10 not null default 10 00788 $columns = $DB->get_columns('test_table_cust0'); 00789 $this->assertEqual($columns['anothernumber']->meta_type, 'I'); 00790 //TODO: check the rest of attributes 00791 00792 // check original value has survived to all the type changes 00793 $this->assertTrue($rec = $DB->get_record('test_table_cust0', array('id' => $recoriginal))); 00794 $this->assertEqual($rec->anothernumber, 4); 00795 00796 $dbman->drop_table($table); 00797 $this->assertFalse($dbman->table_exists($table)); 00798 } 00799 00803 public function test_change_field_precision() { 00804 $DB = $this->tdb; // do not use global $DB! 00805 $dbman = $this->tdb->get_manager(); 00806 00807 $table = $this->create_deftable('test_table1'); 00808 00809 // fill the table with some records before dropping fields 00810 $this->fill_deftable('test_table1'); 00811 00812 // change text field from medium to big 00813 $field = new xmldb_field('intro'); 00814 $field->set_attributes(XMLDB_TYPE_TEXT, 'big', null, XMLDB_NOTNULL, null, null); 00815 $dbman->change_field_precision($table, $field); 00816 $columns = $DB->get_columns('test_table1'); 00817 // cannot check the text type, only the metatype 00818 $this->assertEqual($columns['intro']->meta_type, 'X'); 00819 //TODO: check the rest of attributes 00820 00821 // change char field from 30 to 20 00822 $field = new xmldb_field('secondname'); 00823 $field->set_attributes(XMLDB_TYPE_CHAR, '20', null, XMLDB_NOTNULL, null, null); 00824 $dbman->change_field_precision($table, $field); 00825 $columns = $DB->get_columns('test_table1'); 00826 $this->assertEqual($columns['secondname']->meta_type, 'C'); 00827 //TODO: check the rest of attributes 00828 00829 // change char field from 20 to 10, having contents > 10cc. Throw exception 00830 $field = new xmldb_field('secondname'); 00831 $field->set_attributes(XMLDB_TYPE_CHAR, '10', null, XMLDB_NOTNULL, null, null); 00832 try { 00833 $dbman->change_field_precision($table, $field); 00834 $this->assertTrue(false); 00835 } catch (Exception $e) { 00836 $this->assertTrue($e instanceof ddl_change_structure_exception); 00837 } 00838 // No changes in field specs at all 00839 $columns = $DB->get_columns('test_table1'); 00840 $this->assertEqual($columns['secondname']->meta_type, 'C'); 00841 //TODO: check the rest of attributes 00842 00843 // change number field from 20,10 to 10,2 00844 $field = new xmldb_field('grade'); 00845 $field->set_attributes(XMLDB_TYPE_NUMBER, '10,2', null, null, null, null); 00846 $dbman->change_field_precision($table, $field); 00847 $columns = $DB->get_columns('test_table1'); 00848 $this->assertEqual($columns['grade']->meta_type, 'N'); 00849 //TODO: check the rest of attributes 00850 00851 // change integer field from 10 to 2 00852 $field = new xmldb_field('userid'); 00853 $field->set_attributes(XMLDB_TYPE_INTEGER, '2', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '0'); 00854 $dbman->change_field_precision($table, $field); 00855 $columns = $DB->get_columns('test_table1'); 00856 $this->assertEqual($columns['userid']->meta_type, 'I'); 00857 //TODO: check the rest of attributes 00858 00859 // change the column from integer (2) to integer (6) (forces change of type in some DBs) 00860 $field = new xmldb_field('userid'); 00861 $field->set_attributes(XMLDB_TYPE_INTEGER, '6', XMLDB_UNSIGNED, null, null, null); 00862 $dbman->change_field_precision($table, $field); 00863 // column is integer 6 null default null now 00864 $columns = $DB->get_columns('test_table1'); 00865 $this->assertEqual($columns['userid']->meta_type, 'I'); 00866 //TODO: check the rest of attributes 00867 00868 // insert one record with 6-digit field 00869 $record = new stdClass(); 00870 $record->course = 10; 00871 $record->secondname = 'third record'; 00872 $record->intro = 'third record'; 00873 $record->userid = 123456; 00874 $DB->insert_record('test_table1', $record); 00875 // change integer field from 6 to 2, contents are bigger. must throw exception 00876 $field = new xmldb_field('userid'); 00877 $field->set_attributes(XMLDB_TYPE_INTEGER, '2', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '0'); 00878 try { 00879 $dbman->change_field_precision($table, $field); 00880 $this->assertTrue(false); 00881 } catch (Exception $e) { 00882 $this->assertTrue($e instanceof ddl_change_structure_exception); 00883 } 00884 // No changes in field specs at all 00885 $columns = $DB->get_columns('test_table1'); 00886 $this->assertEqual($columns['userid']->meta_type, 'I'); 00887 //TODO: check the rest of attributes 00888 00889 // change integer field from 10 to 3, in field used by index. must throw exception. 00890 $field = new xmldb_field('course'); 00891 $field->set_attributes(XMLDB_TYPE_INTEGER, '3', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '0'); 00892 try { 00893 $dbman->change_field_precision($table, $field); 00894 $this->assertTrue(false); 00895 } catch (Exception $e) { 00896 $this->assertTrue($e instanceof ddl_dependency_exception); 00897 } 00898 // No changes in field specs at all 00899 $columns = $DB->get_columns('test_table1'); 00900 $this->assertEqual($columns['course']->meta_type, 'I'); 00901 //TODO: check the rest of attributes 00902 } 00903 00904 public function testChangeFieldSign() { 00905 $dbman = $this->tdb->get_manager(); 00906 // TODO: verify the signed is changed in db 00907 00908 $table = $this->create_deftable('test_table1'); 00909 $field = new xmldb_field('grade'); 00910 $field->set_attributes(XMLDB_TYPE_NUMBER, '10,2', XMLDB_UNSIGNED, null, null, null); 00911 $dbman->change_field_unsigned($table, $field); 00912 00913 $field = new xmldb_field('grade'); 00914 $field->set_attributes(XMLDB_TYPE_NUMBER, '10,2', null, null, null, null); 00915 $dbman->change_field_unsigned($table, $field); 00916 } 00917 00918 public function testChangeFieldNullability() { 00919 $DB = $this->tdb; // do not use global $DB! 00920 $dbman = $this->tdb->get_manager(); 00921 00922 $table = new xmldb_table('test_table_cust0'); 00923 $table->add_field('id', XMLDB_TYPE_INTEGER, '2', XMLDB_UNSIGNED, XMLDB_NOTNULL, XMLDB_SEQUENCE, null); 00924 $table->add_field('name', XMLDB_TYPE_CHAR, '30', null, XMLDB_NOTNULL, null, null); 00925 $table->add_key('primary', XMLDB_KEY_PRIMARY, array('id')); 00926 $dbman->create_table($table); 00927 00928 $record = new stdClass(); 00929 $record->name = NULL; 00930 00931 ob_start(); // hide debug warning 00932 try { 00933 $result = $DB->insert_record('test_table_cust0', $record, false); 00934 } catch (dml_exception $e) { 00935 $result = false; 00936 } 00937 ob_end_clean(); 00938 $this->assertFalse($result); 00939 00940 $field = new xmldb_field('name'); 00941 $field->set_attributes(XMLDB_TYPE_CHAR, '30', null, null, null, null); 00942 $dbman->change_field_notnull($table, $field); 00943 00944 $this->assertTrue($DB->insert_record('test_table_cust0', $record, false)); 00945 00946 // TODO: add some tests with existing data in table 00947 $DB->delete_records('test_table_cust0'); 00948 00949 $field = new xmldb_field('name'); 00950 $field->set_attributes(XMLDB_TYPE_CHAR, '30', null, XMLDB_NOTNULL, null, null); 00951 $dbman->change_field_notnull($table, $field); 00952 00953 ob_start(); // hide debug warning 00954 try { 00955 $result = $DB->insert_record('test_table_cust0', $record, false); 00956 } catch (dml_exception $e) { 00957 $result = false; 00958 } 00959 ob_end_clean(); 00960 $this->assertFalse($result); 00961 00962 $dbman->drop_table($table); 00963 } 00964 00965 public function testChangeFieldDefault() { 00966 $DB = $this->tdb; // do not use global $DB! 00967 $dbman = $this->tdb->get_manager(); 00968 00969 $table = new xmldb_table('test_table_cust0'); 00970 $table->add_field('id', XMLDB_TYPE_INTEGER, '2', XMLDB_UNSIGNED, XMLDB_NOTNULL, XMLDB_SEQUENCE, null); 00971 $table->add_field('onenumber', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '0'); 00972 $table->add_field('name', XMLDB_TYPE_CHAR, '30', null, XMLDB_NOTNULL, null, 'Moodle'); 00973 $table->add_key('primary', XMLDB_KEY_PRIMARY, array('id')); 00974 $dbman->create_table($table); 00975 00976 $field = new xmldb_field('name'); 00977 $field->set_attributes(XMLDB_TYPE_CHAR, '30', null, XMLDB_NOTNULL, null, 'Moodle2'); 00978 $dbman->change_field_default($table, $field); 00979 00980 $record = new stdClass(); 00981 $record->onenumber = 666; 00982 $id = $DB->insert_record('test_table_cust0', $record); 00983 00984 $record = $DB->get_record('test_table_cust0', array('id'=>$id)); 00985 $this->assertEqual($record->name, 'Moodle2'); 00986 00987 00988 $field = new xmldb_field('onenumber'); 00989 $field->set_attributes(XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, 666); 00990 $dbman->change_field_default($table, $field); 00991 00992 $record = new stdClass(); 00993 $record->name = 'something'; 00994 $id = $DB->insert_record('test_table_cust0', $record); 00995 00996 $record = $DB->get_record('test_table_cust0', array('id'=>$id)); 00997 $this->assertEqual($record->onenumber, '666'); 00998 00999 $dbman->drop_table($table); 01000 } 01001 01002 public function testAddUniqueIndex() { 01003 $DB = $this->tdb; // do not use global $DB! 01004 $dbman = $this->tdb->get_manager(); 01005 01006 $table = new xmldb_table('test_table_cust0'); 01007 $table->add_field('id', XMLDB_TYPE_INTEGER, '2', XMLDB_UNSIGNED, XMLDB_NOTNULL, XMLDB_SEQUENCE, null); 01008 $table->add_field('onenumber', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '0'); 01009 $table->add_field('name', XMLDB_TYPE_CHAR, '30', null, XMLDB_NOTNULL, null, 'Moodle'); 01010 $table->add_key('primary', XMLDB_KEY_PRIMARY, array('id')); 01011 $dbman->create_table($table); 01012 01013 $record = new stdClass(); 01014 $record->onenumber = 666; 01015 $record->name = 'something'; 01016 $DB->insert_record('test_table_cust0', $record, false); 01017 01018 $index = new xmldb_index('onenumber-name'); 01019 $index->set_attributes(XMLDB_INDEX_UNIQUE, array('onenumber', 'name')); 01020 $dbman->add_index($table, $index); 01021 01022 ob_start(); // hide debug warning 01023 try { 01024 $result = $DB->insert_record('test_table_cust0', $record, false); 01025 } catch (dml_exception $e) { 01026 $result = false;; 01027 } 01028 ob_end_clean(); 01029 $this->assertFalse($result); 01030 01031 $dbman->drop_table($table); 01032 } 01033 01034 public function testAddNonUniqueIndex() { 01035 $dbman = $this->tdb->get_manager(); 01036 01037 $table = $this->create_deftable('test_table1'); 01038 $index = new xmldb_index('secondname'); 01039 $index->set_attributes(XMLDB_INDEX_NOTUNIQUE, array('course', 'name')); 01040 $dbman->add_index($table, $index); 01041 } 01042 01043 public function testFindIndexName() { 01044 $dbman = $this->tdb->get_manager(); 01045 01046 $table = $this->create_deftable('test_table1'); 01047 $index = new xmldb_index('secondname'); 01048 $index->set_attributes(XMLDB_INDEX_NOTUNIQUE, array('course', 'name')); 01049 $dbman->add_index($table, $index); 01050 01051 //DBM Systems name their indices differently - do not test the actual index name 01052 $result = $dbman->find_index_name($table, $index); 01053 $this->assertTrue(!empty($result)); 01054 01055 $nonexistentindex = new xmldb_index('nonexistentindex'); 01056 $nonexistentindex->set_attributes(XMLDB_INDEX_NOTUNIQUE, array('name')); 01057 $this->assertFalse($dbman->find_index_name($table, $nonexistentindex)); 01058 } 01059 01060 public function testDropIndex() { 01061 $DB = $this->tdb; // do not use global $DB! 01062 01063 $dbman = $this->tdb->get_manager(); 01064 01065 $table = $this->create_deftable('test_table1'); 01066 $index = new xmldb_index('secondname'); 01067 $index->set_attributes(XMLDB_INDEX_NOTUNIQUE, array('course', 'name')); 01068 $dbman->add_index($table, $index); 01069 01070 $dbman->drop_index($table, $index); 01071 $this->assertFalse($dbman->find_index_name($table, $index)); 01072 01073 // Test we are able to drop indexes having hyphens. MDL-22804 01074 // Create index with hyphens (by hand) 01075 $indexname = 'test-index-with-hyphens'; 01076 switch ($DB->get_dbfamily()) { 01077 case 'mysql': 01078 $indexname = '`' . $indexname . '`'; 01079 break; 01080 default: 01081 $indexname = '"' . $indexname . '"'; 01082 } 01083 $stmt = "CREATE INDEX {$indexname} ON {$DB->get_prefix()}test_table1 (course, name)"; 01084 $DB->change_database_structure($stmt); 01085 $this->assertTrue($dbman->find_index_name($table, $index)); 01086 // Index created, let's drop it using db manager stuff 01087 $index = new xmldb_index('indexname', XMLDB_INDEX_NOTUNIQUE, array('course', 'name')); 01088 $dbman->drop_index($table, $index); 01089 $this->assertFalse($dbman->find_index_name($table, $index)); 01090 } 01091 01092 public function testAddUniqueKey() { 01093 $dbman = $this->tdb->get_manager(); 01094 01095 $table = $this->create_deftable('test_table1'); 01096 $key = new xmldb_key('id-course-grade'); 01097 $key->set_attributes(XMLDB_KEY_UNIQUE, array('id', 'course', 'grade')); 01098 $dbman->add_key($table, $key); 01099 } 01100 01101 public function testAddForeignUniqueKey() { 01102 $dbman = $this->tdb->get_manager(); 01103 01104 $table = $this->create_deftable('test_table1'); 01105 $this->create_deftable('test_table0'); 01106 01107 $key = new xmldb_key('course'); 01108 $key->set_attributes(XMLDB_KEY_FOREIGN_UNIQUE, array('course'), 'test_table0', array('id')); 01109 $dbman->add_key($table, $key); 01110 } 01111 01112 public function testDropKey() { 01113 $dbman = $this->tdb->get_manager(); 01114 01115 $table = $this->create_deftable('test_table1'); 01116 $this->create_deftable('test_table0'); 01117 01118 $key = new xmldb_key('course'); 01119 $key->set_attributes(XMLDB_KEY_FOREIGN_UNIQUE, array('course'), 'test_table0', array('id')); 01120 $dbman->add_key($table, $key); 01121 01122 $dbman->drop_key($table, $key); 01123 } 01124 01125 public function testAddForeignKey() { 01126 $dbman = $this->tdb->get_manager(); 01127 01128 $table = $this->create_deftable('test_table1'); 01129 $this->create_deftable('test_table0'); 01130 01131 $key = new xmldb_key('course'); 01132 $key->set_attributes(XMLDB_KEY_FOREIGN, array('course'), 'test_table0', array('id')); 01133 $dbman->add_key($table, $key); 01134 } 01135 01136 public function testDropForeignKey() { 01137 $dbman = $this->tdb->get_manager(); 01138 01139 $table = $this->create_deftable('test_table1'); 01140 $this->create_deftable('test_table0'); 01141 01142 $key = new xmldb_key('course'); 01143 $key->set_attributes(XMLDB_KEY_FOREIGN, array('course'), 'test_table0', array('id')); 01144 $dbman->add_key($table, $key); 01145 01146 $dbman->drop_key($table, $key); 01147 } 01148 01160 public function test_drop_enum_from_field() { 01161 $DB = $this->tdb; // do not use global $DB! 01162 $dbman = $this->tdb->get_manager(); 01163 01164 // Create normal table, no enums. 01165 $table = new xmldb_table('test_table_cust0'); 01166 $table->add_field('id', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, XMLDB_SEQUENCE, null); 01167 $table->add_field('course', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '0'); 01168 $field = new xmldb_field('type'); 01169 $field->set_attributes(XMLDB_TYPE_CHAR, '20', null, XMLDB_NOTNULL, null, 'general'); 01170 $table->addField($field); 01171 $table->add_key('primary', XMLDB_KEY_PRIMARY, array('id')); 01172 $dbman->create_table($table); 01173 01174 $this->assertTrue($dbman->table_exists($table)); 01175 $this->assertTrue($dbman->field_exists($table, $field)); 01176 01177 // Check table hasn't enums at all 01178 $this->assertFalse($dbman->check_constraint_exists($table, $field)); 01179 $this->assertFalse($dbman->find_check_constraint_name($table, $field)); 01180 ob_start(); 01181 $this->assertFalse($dbman->drop_enum_from_field($table, $field)); // This just outputs debug warning if field hasn't enums 01182 ob_end_clean(); 01183 01184 // Insert some info 01185 $record = new stdClass(); 01186 $record->course = 666; 01187 $record->type = 'qanda'; 01188 $this->assertTrue($DB->insert_record('test_table_cust0', $record, false)); 01189 01190 // Hackery starts here, depending of the db family we are testing... execute 01191 // the needed SQL statements to get the "type" field defined as enum 01192 $stmt = ''; 01193 switch ($DB->get_dbfamily()) { 01194 case 'mysql': // It's ENUM field for mysql 01195 $stmt = "ALTER TABLE {$DB->get_prefix()}test_table_cust0 MODIFY type ENUM ('general', 'qanda', 'moodle') NOT NULL DEFAULT 'general'"; 01196 break; 01197 default: // It's check constraint for "normal" DBs 01198 $stmt = "ALTER TABLE {$DB->get_prefix()}test_table_cust0 ADD CONSTRAINT ttcu0_ck CHECK (type IN ('general', 'qanda', 'moodle'))"; 01199 } 01200 $DB->change_database_structure($stmt); 01201 01202 // Check table has enums now 01203 $this->assertTrue($dbman->check_constraint_exists($table, $field)); 01204 $this->assertTrue($dbman->find_check_constraint_name($table, $field)); 01205 01206 // Removing an enum value 01207 $dbman->drop_enum_from_field($table, $field); 01208 01209 // Chech table hasn't enum anymore 01210 $this->assertFalse($dbman->check_constraint_exists($table, $field)); 01211 $this->assertFalse($dbman->find_check_constraint_name($table, $field)); 01212 01213 $dbman->drop_table($table); 01214 } 01215 01216 public function testRenameField() { 01217 $DB = $this->tdb; // do not use global $DB! 01218 $dbman = $this->tdb->get_manager(); 01219 01220 $table = $this->create_deftable('test_table0'); 01221 $field = new xmldb_field('type'); 01222 $field->set_attributes(XMLDB_TYPE_CHAR, '20', null, XMLDB_NOTNULL, null, 'general', 'course'); 01223 01224 $dbman->rename_field($table, $field, 'newfieldname'); 01225 01226 $columns = $DB->get_columns('test_table0'); 01227 01228 $this->assertFalse(array_key_exists('type', $columns)); 01229 $this->assertTrue(array_key_exists('newfieldname', $columns)); 01230 } 01231 01232 01233 public function testIndexExists() { 01234 // Skipping: this is just a test of find_index_name 01235 } 01236 01237 public function testFindKeyName() { 01238 $dbman = $this->tdb->get_manager(); 01239 01240 $table = $this->create_deftable('test_table0'); 01241 $key = $table->getKey('primary'); 01242 01243 // With Mysql, the return value is actually "mdl_test_id_pk" 01244 $result = $dbman->find_key_name($table, $key); 01245 $this->assertTrue(!empty($result)); 01246 } 01247 01248 public function testDeleteTablesFromXmldbFile() { 01249 global $CFG; 01250 $dbman = $this->tdb->get_manager(); 01251 01252 $this->create_deftable('test_table1'); 01253 01254 $this->assertTrue($dbman->table_exists('test_table1')); 01255 01256 // feed nonexistent file 01257 try { 01258 ob_start(); // hide debug warning 01259 $dbman->delete_tables_from_xmldb_file('fpsoiudfposui'); 01260 ob_end_clean(); 01261 $this->assertTrue(false); 01262 } catch (Exception $e) { 01263 ob_end_clean(); 01264 $this->assertTrue($e instanceof moodle_exception); 01265 } 01266 01267 // Real file but invalid xml file 01268 $devhack = false; 01269 if (!empty($CFG->xmldbdisablenextprevchecking)) { 01270 $CFG->xmldbdisablenextprevchecking = false; 01271 $devhack = true; 01272 } 01273 try { 01274 ob_start(); // hide debug warning 01275 $dbman->delete_tables_from_xmldb_file($CFG->libdir . '/ddl/simpletest/fixtures/invalid.xml'); 01276 $this->assertTrue(false); 01277 ob_end_clean(); 01278 } catch (Exception $e) { 01279 ob_end_clean(); 01280 $this->assertTrue($e instanceof moodle_exception); 01281 } 01282 if ($devhack) { 01283 $CFG->xmldbdisablenextprevchecking = true; 01284 } 01285 01286 // Check that the table has not been deleted from DB 01287 $this->assertTrue($dbman->table_exists('test_table1')); 01288 01289 // Real and valid xml file 01290 $dbman->delete_tables_from_xmldb_file($CFG->libdir . '/ddl/simpletest/fixtures/xmldb_table.xml'); 01291 01292 // Check that the table has been deleted from DB 01293 $this->assertFalse($dbman->table_exists('test_table1')); 01294 } 01295 01296 public function testInstallFromXmldbFile() { 01297 global $CFG; 01298 $dbman = $this->tdb->get_manager(); 01299 01300 // feed nonexistent file 01301 try { 01302 ob_start(); // hide debug warning 01303 $dbman->install_from_xmldb_file('fpsoiudfposui'); 01304 ob_end_clean(); 01305 $this->assertTrue(false); 01306 } catch (Exception $e) { 01307 ob_end_clean(); 01308 $this->assertTrue($e instanceof moodle_exception); 01309 } 01310 01311 // Real but invalid xml file 01312 $devhack = false; 01313 if (!empty($CFG->xmldbdisablenextprevchecking)) { 01314 $CFG->xmldbdisablenextprevchecking = false; 01315 $devhack = true; 01316 } 01317 try { 01318 ob_start(); // hide debug warning 01319 $dbman->install_from_xmldb_file($CFG->libdir.'/ddl/simpletest/fixtures/invalid.xml'); 01320 ob_end_clean(); 01321 $this->assertTrue(false); 01322 } catch (Exception $e) { 01323 ob_end_clean(); 01324 $this->assertTrue($e instanceof moodle_exception); 01325 } 01326 if ($devhack) { 01327 $CFG->xmldbdisablenextprevchecking = true; 01328 } 01329 01330 // Check that the table has not yet been created in DB 01331 $this->assertFalse($dbman->table_exists('test_table1')); 01332 01333 // Real and valid xml file 01334 $dbman->install_from_xmldb_file($CFG->libdir.'/ddl/simpletest/fixtures/xmldb_table.xml'); 01335 $this->assertTrue($dbman->table_exists('test_table1')); 01336 } 01337 01338 public function test_temp_tables() { 01339 $DB = $this->tdb; // do not use global $DB! 01340 $dbman = $this->tdb->get_manager(); 01341 01342 // Create temp table0 01343 $table0 = $this->tables['test_table0']; 01344 $dbman->create_temp_table($table0); 01345 $this->assertTrue($dbman->table_exists('test_table0')); 01346 01347 // Try to create temp table with same name, must throw exception 01348 $dupetable = $this->tables['test_table0']; 01349 try { 01350 $dbman->create_temp_table($dupetable); 01351 $this->assertTrue(false); 01352 } catch (Exception $e) { 01353 $this->assertTrue($e instanceof ddl_exception); 01354 } 01355 01356 // Try to create table with same name, must throw exception 01357 $dupetable = $this->tables['test_table0']; 01358 try { 01359 $dbman->create_table($dupetable); 01360 $this->assertTrue(false); 01361 } catch (Exception $e) { 01362 $this->assertTrue($e instanceof ddl_exception); 01363 } 01364 01365 // Create another temp table1 01366 $table1 = $this->tables['test_table1']; 01367 $dbman->create_temp_table($table1); 01368 $this->assertTrue($dbman->table_exists('test_table1')); 01369 01370 // Get columns and perform some basic tests 01371 $columns = $DB->get_columns('test_table1'); 01372 $this->assertEqual(count($columns), 11); 01373 $this->assertTrue($columns['name'] instanceof database_column_info); 01374 $this->assertEqual($columns['name']->max_length, 30); 01375 $this->assertTrue($columns['name']->has_default); 01376 $this->assertEqual($columns['name']->default_value, 'Moodle'); 01377 01378 // Insert some records 01379 $inserted = $this->fill_deftable('test_table1'); 01380 $records = $DB->get_records('test_table1'); 01381 $this->assertEqual(count($records), $inserted); 01382 $this->assertEqual($records[1]->course, $this->records['test_table1'][0]->course); 01383 $this->assertEqual($records[1]->secondname, $this->records['test_table1'][0]->secondname); 01384 $this->assertEqual($records[2]->intro, $this->records['test_table1'][1]->intro); 01385 01386 // Drop table1 01387 $dbman->drop_temp_table($table1); 01388 $this->assertFalse($dbman->table_exists('test_table1')); 01389 01390 // Try to drop non-existing temp table, must throw exception 01391 $noetable = $this->tables['test_table1']; 01392 try { 01393 $dbman->drop_temp_table($noetable); 01394 $this->assertTrue(false); 01395 } catch (Exception $e) { 01396 $this->assertTrue($e instanceof ddl_table_missing_exception); 01397 } 01398 01399 // Fill/modify/delete a few table0 records 01400 // TODO: that's 01401 01402 // Drop table0 01403 $dbman->drop_temp_table($table0); 01404 $this->assertFalse($dbman->table_exists('test_table0')); 01405 01406 // Have dropped all these temp tables here, to avoid conflicts with other (normal tables) tests! 01407 } 01408 01409 public function test_concurrent_temp_tables() { 01410 $DB = $this->tdb; // do not use global $DB! 01411 $dbman = $this->tdb->get_manager(); 01412 01413 // Define 2 records 01414 $record1 = (object)array( 01415 'course' => 1, 01416 'secondname' => '11 important', 01417 'intro' => '111 important'); 01418 $record2 = (object)array( 01419 'course' => 2, 01420 'secondname' => '22 important', 01421 'intro' => '222 important'); 01422 01423 // Create temp table1 and insert 1 record (in DB) 01424 $table = $this->tables['test_table1']; 01425 $dbman->create_temp_table($table); 01426 $this->assertTrue($dbman->table_exists('test_table1')); 01427 $inserted = $DB->insert_record('test_table1', $record1); 01428 01429 // Switch to new connection 01430 $cfg = $DB->export_dbconfig(); 01431 if (!isset($cfg->dboptions)) { 01432 $cfg->dboptions = array(); 01433 } 01434 $DB2 = moodle_database::get_driver_instance($cfg->dbtype, $cfg->dblibrary); 01435 $DB2->connect($cfg->dbhost, $cfg->dbuser, $cfg->dbpass, $cfg->dbname, $cfg->prefix, $cfg->dboptions); 01436 $dbman2 = $DB2->get_manager(); 01437 $this->assertFalse($dbman2->table_exists('test_table1')); // Temp table not exists in DB2 01438 01439 // Create temp table1 and insert 1 record (in DB2) 01440 $table = $this->tables['test_table1']; 01441 $dbman2->create_temp_table($table); 01442 $this->assertTrue($dbman2->table_exists('test_table1')); 01443 $inserted = $DB2->insert_record('test_table1', $record2); 01444 01445 $dbman2->drop_temp_table($table); // Drop temp table before closing DB2 01446 $this->assertFalse($dbman2->table_exists('test_table1')); 01447 $DB2->dispose(); // Close DB2 01448 01449 $this->assertTrue($dbman->table_exists('test_table1')); // Check table continues existing for DB 01450 $dbman->drop_temp_table($table); // Drop temp table 01451 $this->assertFalse($dbman->table_exists('test_table1')); 01452 } 01453 01454 public function test_reset_sequence() { 01455 $DB = $this->tdb; 01456 $dbman = $DB->get_manager(); 01457 01458 $table = new xmldb_table('testtable'); 01459 $table->add_field('id', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, XMLDB_SEQUENCE, null); 01460 $table->add_field('course', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '0'); 01461 $table->add_key('primary', XMLDB_KEY_PRIMARY, array('id')); 01462 01463 // Drop if exists 01464 if ($dbman->table_exists($table)) { 01465 $dbman->drop_table($table); 01466 } 01467 $dbman->create_table($table); 01468 $tablename = $table->getName(); 01469 $this->tables[$tablename] = $table; 01470 01471 $record = (object)array('id'=>666, 'course'=>10); 01472 $DB->import_record('testtable', $record); 01473 $DB->delete_records('testtable'); 01474 01475 $dbman->reset_sequence($table); // using xmldb object 01476 $this->assertEqual(1, $DB->insert_record('testtable', (object)array('course'=>13))); 01477 01478 $DB->import_record('testtable', $record); 01479 $dbman->reset_sequence($tablename); // using string 01480 $this->assertEqual(667, $DB->insert_record('testtable', (object)array('course'=>13))); 01481 01482 $dbman->drop_table($table); 01483 } 01484 01485 public function test_reserved_words() { 01486 $reserved = sql_generator::getAllReservedWords(); 01487 $this->assertTrue(count($reserved) > 1); 01488 } 01489 01490 public function test_index_max_bytes() { 01491 $DB = $this->tdb; 01492 $dbman = $DB->get_manager(); 01493 01494 $maxstr = ''; 01495 for($i=0; $i<255; $i++) { 01496 $maxstr .= '言'; // random long string that should fix exactly the limit for one char column 01497 } 01498 01499 $table = new xmldb_table('testtable'); 01500 $table->add_field('id', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, XMLDB_SEQUENCE, null); 01501 $table->add_field('name', XMLDB_TYPE_CHAR, 255, null, XMLDB_NOTNULL, null); 01502 $table->add_key('primary', XMLDB_KEY_PRIMARY, array('id')); 01503 $table->add_index('name', XMLDB_INDEX_NOTUNIQUE, array('name')); 01504 01505 // Drop if exists 01506 if ($dbman->table_exists($table)) { 01507 $dbman->drop_table($table); 01508 } 01509 $dbman->create_table($table); 01510 $tablename = $table->getName(); 01511 $this->tables[$tablename] = $table; 01512 01513 $rec = new stdClass(); 01514 $rec->name = $maxstr; 01515 01516 $id = $DB->insert_record($tablename, $rec); 01517 $this->assertTrue(!empty($id)); 01518 01519 $rec = $DB->get_record($tablename, array('id'=>$id)); 01520 $this->assertIdentical($rec->name, $maxstr); 01521 01522 $dbman->drop_table($table); 01523 01524 01525 $table = new xmldb_table('testtable'); 01526 $table->add_field('id', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, XMLDB_SEQUENCE, null); 01527 $table->add_field('name', XMLDB_TYPE_CHAR, 255+1, null, XMLDB_NOTNULL, null); 01528 $table->add_key('primary', XMLDB_KEY_PRIMARY, array('id')); 01529 $table->add_index('name', XMLDB_INDEX_NOTUNIQUE, array('name')); 01530 01531 try { 01532 $dbman->create_table($table); 01533 $this->assertTrue(false); 01534 } catch (Exception $e) { 01535 $this->assertTrue($e instanceof coding_exception); 01536 } 01537 } 01538 01539 public function test_index_composed_max_bytes() { 01540 $DB = $this->tdb; 01541 $dbman = $DB->get_manager(); 01542 01543 $maxstr = ''; 01544 for($i=0; $i<200; $i++) { 01545 $maxstr .= '言'; 01546 } 01547 $reststr = ''; 01548 for($i=0; $i<133; $i++) { 01549 $reststr .= '言'; 01550 } 01551 01552 $table = new xmldb_table('testtable'); 01553 $table->add_field('id', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, XMLDB_SEQUENCE, null); 01554 $table->add_field('name1', XMLDB_TYPE_CHAR, 200, null, XMLDB_NOTNULL, null); 01555 $table->add_field('name2', XMLDB_TYPE_CHAR, 133, null, XMLDB_NOTNULL, null); 01556 $table->add_key('primary', XMLDB_KEY_PRIMARY, array('id')); 01557 $table->add_index('name1-name2', XMLDB_INDEX_NOTUNIQUE, array('name1','name2')); 01558 01559 // Drop if exists 01560 if ($dbman->table_exists($table)) { 01561 $dbman->drop_table($table); 01562 } 01563 $dbman->create_table($table); 01564 $tablename = $table->getName(); 01565 $this->tables[$tablename] = $table; 01566 01567 $rec = new stdClass(); 01568 $rec->name1 = $maxstr; 01569 $rec->name2 = $reststr; 01570 01571 $id = $DB->insert_record($tablename, $rec); 01572 $this->assertTrue(!empty($id)); 01573 01574 $rec = $DB->get_record($tablename, array('id'=>$id)); 01575 $this->assertIdentical($rec->name1, $maxstr); 01576 $this->assertIdentical($rec->name2, $reststr); 01577 01578 01579 $table = new xmldb_table('testtable'); 01580 $table->add_field('id', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, XMLDB_SEQUENCE, null); 01581 $table->add_field('name1', XMLDB_TYPE_CHAR, 201, null, XMLDB_NOTNULL, null); 01582 $table->add_field('name2', XMLDB_TYPE_CHAR, 133, null, XMLDB_NOTNULL, null); 01583 $table->add_key('primary', XMLDB_KEY_PRIMARY, array('id')); 01584 $table->add_index('name1-name2', XMLDB_INDEX_NOTUNIQUE, array('name1','name2')); 01585 01586 // Drop if exists 01587 if ($dbman->table_exists($table)) { 01588 $dbman->drop_table($table); 01589 } 01590 01591 try { 01592 $dbman->create_table($table); 01593 $this->assertTrue(false); 01594 } catch (Exception $e) { 01595 $this->assertTrue($e instanceof coding_exception); 01596 } 01597 } 01598 01599 public function test_char_size_limit() { 01600 $DB = $this->tdb; 01601 $dbman = $DB->get_manager(); 01602 01603 $table = new xmldb_table('testtable'); 01604 $table->add_field('id', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, XMLDB_SEQUENCE, null); 01605 $table->add_field('name', XMLDB_TYPE_CHAR, xmldb_field::CHAR_MAX_LENGTH, null, XMLDB_NOTNULL, null); 01606 $table->add_key('primary', XMLDB_KEY_PRIMARY, array('id')); 01607 01608 // Drop if exists 01609 if ($dbman->table_exists($table)) { 01610 $dbman->drop_table($table); 01611 } 01612 $dbman->create_table($table); 01613 $tablename = $table->getName(); 01614 $this->tables[$tablename] = $table; 01615 01616 // this has to work in all DBs 01617 $maxstr = ''; 01618 for($i=0; $i<xmldb_field::CHAR_MAX_LENGTH; $i++) { 01619 $maxstr .= 'a'; // ascii only 01620 } 01621 01622 $rec = new stdClass(); 01623 $rec->name = $maxstr; 01624 01625 $id = $DB->insert_record($tablename, $rec); 01626 $this->assertTrue(!empty($id)); 01627 01628 $rec = $DB->get_record($tablename, array('id'=>$id)); 01629 $this->assertIdentical($rec->name, $maxstr); 01630 01631 01632 // Following test is supposed to fail in oracle 01633 $maxstr = ''; 01634 for($i=0; $i<xmldb_field::CHAR_MAX_LENGTH; $i++) { 01635 $maxstr .= '言'; // random long string that should fix exactly the limit for one char column 01636 } 01637 01638 $rec = new stdClass(); 01639 $rec->name = $maxstr; 01640 01641 try { 01642 $id = $DB->insert_record($tablename, $rec); 01643 $this->assertTrue(!empty($id)); 01644 01645 $rec = $DB->get_record($tablename, array('id'=>$id)); 01646 $this->assertIdentical($rec->name, $maxstr); 01647 } catch (dml_exception $e) { 01648 if ($DB->get_dbfamily() === 'oracle') { 01649 $this->fail('Oracle does not support text fields larger than 4000 bytes, this is not a big problem for mostly ascii based languages'); 01650 } else { 01651 throw $e; 01652 } 01653 } 01654 01655 01656 $table = new xmldb_table('testtable'); 01657 $table->add_field('id', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, XMLDB_SEQUENCE, null); 01658 $table->add_field('name', XMLDB_TYPE_CHAR, xmldb_field::CHAR_MAX_LENGTH+1, null, XMLDB_NOTNULL, null); 01659 $table->add_key('primary', XMLDB_KEY_PRIMARY, array('id')); 01660 01661 // Drop if exists 01662 if ($dbman->table_exists($table)) { 01663 $dbman->drop_table($table); 01664 } 01665 $tablename = $table->getName(); 01666 $this->tables[$tablename] = $table; 01667 01668 try { 01669 $dbman->create_table($table); 01670 $this->assertTrue(false); 01671 } catch (Exception $e) { 01672 $this->assertTrue($e instanceof coding_exception); 01673 } 01674 } 01675 01676 // Following methods are not supported == Do not test 01677 /* 01678 public function testRenameIndex() { 01679 // unsupported! 01680 $dbman = $this->tdb->get_manager(); 01681 01682 $table = $this->create_deftable('test_table0'); 01683 $index = new xmldb_index('course'); 01684 $index->set_attributes(XMLDB_INDEX_UNIQUE, array('course')); 01685 01686 $this->assertTrue($dbman->rename_index($table, $index, 'newindexname')); 01687 } 01688 01689 public function testRenameKey() { 01690 //unsupported 01691 $dbman = $this->tdb->get_manager(); 01692 01693 $table = $this->create_deftable('test_table0'); 01694 $key = new xmldb_key('course'); 01695 $key->set_attributes(XMLDB_KEY_UNIQUE, array('course')); 01696 01697 $this->assertTrue($dbman->rename_key($table, $key, 'newkeyname')); 01698 } 01699 */ 01700 01701 }