Moodle  2.2.1
http://www.collinsharper.com
C:/xampp/htdocs/moodle/lib/ddl/simpletest/testddl.php
Go to the documentation of this file.
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 }
 All Data Structures Namespaces Files Functions Variables Enumerations