Moodle  2.2.1
http://www.collinsharper.com
C:/xampp/htdocs/moodle/lib/ddl/database_manager.php
Go to the documentation of this file.
00001 <?php
00002 
00003 // This file is part of Moodle - http://moodle.org/
00004 //
00005 // Moodle is free software: you can redistribute it and/or modify
00006 // it under the terms of the GNU General Public License as published by
00007 // the Free Software Foundation, either version 3 of the License, or
00008 // (at your option) any later version.
00009 //
00010 // Moodle is distributed in the hope that it will be useful,
00011 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00012 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00013 // GNU General Public License for more details.
00014 //
00015 // You should have received a copy of the GNU General Public License
00016 // along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
00017 
00018 
00031 defined('MOODLE_INTERNAL') || die();
00032 
00038 class database_manager {
00039 
00040     protected $mdb;
00041     public $generator; // public because XMLDB editor needs to access it
00042 
00047     public function __construct($mdb, $generator) {
00048         global $CFG;
00049 
00050         $this->mdb       = $mdb;
00051         $this->generator = $generator;
00052     }
00053 
00057     public function dispose() {
00058         if ($this->generator) {
00059             $this->generator->dispose();
00060             $this->generator = null;
00061         }
00062         $this->mdb = null;
00063     }
00064 
00073     protected function execute_sql_arr(array $sqlarr) {
00074         foreach ($sqlarr as $sql) {
00075             $this->execute_sql($sql);
00076         }
00077     }
00078 
00087     protected function execute_sql($sql) {
00088         if (!$this->mdb->change_database_structure($sql)) {
00089             // in case driver does not throw exceptions yet ;-)
00090             throw new ddl_change_structure_exception($this->mdb->get_last_error(), $sql);
00091         }
00092     }
00093 
00100     public function table_exists($table) {
00101         if (!is_string($table) and !($table instanceof xmldb_table)) {
00102             throw new ddl_exception('ddlunknownerror', NULL, 'incorrect table parameter!');
00103         }
00104         return $this->generator->table_exists($table);
00105     }
00106 
00112     public function reset_sequence($table) {
00113         if (!is_string($table) and !($table instanceof xmldb_table)) {
00114             throw new ddl_exception('ddlunknownerror', NULL, 'incorrect table parameter!');
00115         }
00116 
00118         if (!$this->table_exists($table)) {
00119             throw new ddl_table_missing_exception($table);
00120         }
00121 
00122         if (!$sqlarr = $this->generator->getResetSequenceSQL($table)) {
00123             throw new ddl_exception('ddlunknownerror', null, 'table reset sequence sql not generated');
00124         }
00125 
00126         $this->execute_sql_arr($sqlarr);
00127     }
00128 
00136     public function field_exists($table, $field) {
00138         if (is_string($table)) {
00139             $tablename = $table;
00140         } else {
00141             $tablename = $table->getName();
00142         }
00143 
00145         if (!$this->table_exists($table)) {
00146             throw new ddl_table_missing_exception($tablename);
00147         }
00148 
00149         if (is_string($field)) {
00150             $fieldname = $field;
00151         } else {
00153             $fieldname = $field->getName();
00154         }
00155 
00157         $columns = $this->mdb->get_columns($tablename);
00158 
00159         $exists = array_key_exists($fieldname,  $columns);
00160 
00161         return $exists;
00162     }
00163 
00172     public function find_index_name(xmldb_table $xmldb_table, xmldb_index $xmldb_index) {
00174         $tablename = $xmldb_table->getName();
00175 
00177         if (!$this->table_exists($xmldb_table)) {
00178             throw new ddl_table_missing_exception($tablename);
00179         }
00180 
00182         $indcolumns = $xmldb_index->getFields();
00183 
00185         $indexes = $this->mdb->get_indexes($tablename);
00186 
00188         foreach ($indexes as $indexname => $index) {
00189             $columns = $index['columns'];
00191             $diferences = array_merge(array_diff($columns, $indcolumns), array_diff($indcolumns, $columns));
00193             if (empty($diferences)) {
00194                 return $indexname;
00195             }
00196         }
00197 
00199         return false;
00200     }
00201 
00209     public function index_exists(xmldb_table $xmldb_table, xmldb_index $xmldb_index) {
00210         if (!$this->table_exists($xmldb_table)) {
00211             return false;
00212         }
00213         return ($this->find_index_name($xmldb_table, $xmldb_index) !== false);
00214     }
00215 
00228     public function find_check_constraint_name(xmldb_table $xmldb_table, xmldb_field $xmldb_field) {
00229 
00231         if (!$this->table_exists($xmldb_table)) {
00232             throw new ddl_table_missing_exception($xmldb_table->getName());
00233         }
00234 
00236         if (!$this->field_exists($xmldb_table, $xmldb_field)) {
00237             throw new ddl_field_missing_exception($xmldb_field->getName(), $xmldb_table->getName());
00238         }
00239 
00241         $checks = false;
00242         if ($objchecks = $this->generator->getCheckConstraintsFromDB($xmldb_table, $xmldb_field)) {
00244             $objcheck = array_shift($objchecks);
00245             if ($objcheck) {
00246                 $checks = strtolower($objcheck->name);
00247             }
00248         }
00249 
00251         return $checks;
00252     }
00253 
00263     public function check_constraint_exists(xmldb_table $xmldb_table, xmldb_field $xmldb_field) {
00264         return ($this->find_check_constraint_name($xmldb_table, $xmldb_field) !== false);
00265     }
00266 
00278     public function find_key_name(xmldb_table $xmldb_table, xmldb_key $xmldb_key) {
00279 
00280         $keycolumns = $xmldb_key->getFields();
00281 
00292 
00295         if ($this->generator->primary_key_name && $xmldb_key->getType() == XMLDB_KEY_PRIMARY) {
00296             return $this->generator->primary_key_name;
00297         } else {
00299             switch ($xmldb_key->getType()) {
00300                 case XMLDB_KEY_PRIMARY:
00301                     $suffix = 'pk';
00302                     break;
00303                 case XMLDB_KEY_UNIQUE:
00304                     $suffix = 'uk';
00305                     break;
00306                 case XMLDB_KEY_FOREIGN_UNIQUE:
00307                 case XMLDB_KEY_FOREIGN:
00308                     $suffix = 'fk';
00309                     break;
00310             }
00312             return $this->generator->getNameForObject($xmldb_table->getName(), implode(', ', $xmldb_key->getFields()), $suffix);
00313         }
00314     }
00315 
00322     public function delete_tables_from_xmldb_file($file) {
00323 
00324         $xmldb_file = new xmldb_file($file);
00325 
00326         if (!$xmldb_file->fileExists()) {
00327             throw new ddl_exception('ddlxmlfileerror', null, 'File does not exist');
00328         }
00329 
00330         $loaded    = $xmldb_file->loadXMLStructure();
00331         $structure = $xmldb_file->getStructure();
00332 
00333         if (!$loaded || !$xmldb_file->isLoaded()) {
00335             if ($structure) {
00336                 if ($errors = $structure->getAllErrors()) {
00337                     throw new ddl_exception('ddlxmlfileerror', null, 'Errors found in XMLDB file: '. implode (', ', $errors));
00338                 }
00339             }
00340             throw new ddl_exception('ddlxmlfileerror', null, 'not loaded??');
00341         }
00342 
00343         if ($xmldb_tables = $structure->getTables()) {
00344             foreach($xmldb_tables as $table) {
00345                 if ($this->table_exists($table)) {
00346                     $this->drop_table($table);
00347                 }
00348             }
00349         }
00350     }
00351 
00360     public function drop_table(xmldb_table $xmldb_table) {
00362         if (!$this->table_exists($xmldb_table)) {
00363             throw new ddl_table_missing_exception($xmldb_table->getName());
00364         }
00365 
00366         if (!$sqlarr = $this->generator->getDropTableSQL($xmldb_table)) {
00367             throw new ddl_exception('ddlunknownerror', null, 'table drop sql not generated');
00368         }
00369 
00370         $this->execute_sql_arr($sqlarr);
00371     }
00372 
00378     private function load_xmldb_file($file) {
00379         $xmldb_file = new xmldb_file($file);
00380 
00381         if (!$xmldb_file->fileExists()) {
00382             throw new ddl_exception('ddlxmlfileerror', null, 'File does not exist');
00383         }
00384 
00385         $loaded = $xmldb_file->loadXMLStructure();
00386         if (!$loaded || !$xmldb_file->isLoaded()) {
00388             if ($structure =& $xmldb_file->getStructure()) {
00389                 if ($errors = $structure->getAllErrors()) {
00390                     throw new ddl_exception('ddlxmlfileerror', null, 'Errors found in XMLDB file: '. implode (', ', $errors));
00391                 }
00392             }
00393             throw new ddl_exception('ddlxmlfileerror', null, 'not loaded??');
00394         }
00395 
00396         return $xmldb_file;
00397     }
00398 
00405     public function install_from_xmldb_file($file) {
00406         $xmldb_file = $this->load_xmldb_file($file);
00407         $xmldb_structure = $xmldb_file->getStructure();
00408         $this->install_from_xmldb_structure($xmldb_structure);
00409     }
00410 
00419     public function install_one_table_from_xmldb_file($file, $tablename, $cachestructures = false) {
00420 
00421         static $xmldbstructurecache = array(); // To store cached structures
00422         if (!empty($xmldbstructurecache) && array_key_exists($file, $xmldbstructurecache)) {
00423             $xmldb_structure = $xmldbstructurecache[$file];
00424         } else {
00425             $xmldb_file = $this->load_xmldb_file($file);
00426             $xmldb_structure = $xmldb_file->getStructure();
00427             if ($cachestructures) {
00428                 $xmldbstructurecache[$file] = $xmldb_structure;
00429             }
00430         }
00431 
00432         $targettable = $xmldb_structure->getTable($tablename);
00433         if (is_null($targettable)) {
00434             throw new ddl_exception('ddlunknowntable', null, 'The table ' . $tablename . ' is not defined in file ' . $file);
00435         }
00436         $targettable->setNext(NULL);
00437         $targettable->setPrevious(NULL);
00438 
00439         $tempstructure = new xmldb_structure('temp');
00440         $tempstructure->addTable($targettable);
00441         $this->install_from_xmldb_structure($tempstructure);
00442     }
00443 
00451     public function install_from_xmldb_structure($xmldb_structure) {
00452 
00453         if (!$sqlarr = $this->generator->getCreateStructureSQL($xmldb_structure)) {
00454             return; // nothing to do
00455         }
00456         $this->execute_sql_arr($sqlarr);
00457     }
00458 
00466     public function create_table(xmldb_table $xmldb_table) {
00468         if ($this->table_exists($xmldb_table)) {
00469             throw new ddl_exception('ddltablealreadyexists', $xmldb_table->getName());
00470         }
00471 
00472         if (!$sqlarr = $this->generator->getCreateTableSQL($xmldb_table)) {
00473             throw new ddl_exception('ddlunknownerror', null, 'table create sql not generated');
00474         }
00475         $this->execute_sql_arr($sqlarr);
00476     }
00477 
00488     public function create_temp_table(xmldb_table $xmldb_table) {
00489 
00490         // Check table doesn't exist
00491         if ($this->table_exists($xmldb_table)) {
00492             throw new ddl_exception('ddltablealreadyexists', $xmldb_table->getName());
00493         }
00494 
00495         if (!$sqlarr = $this->generator->getCreateTempTableSQL($xmldb_table)) {
00496             throw new ddl_exception('ddlunknownerror', null, 'temp table create sql not generated');
00497         }
00498 
00499         $this->execute_sql_arr($sqlarr);
00500     }
00501 
00511     public function drop_temp_table(xmldb_table $xmldb_table) {
00512 
00514         if (!$this->table_exists($xmldb_table)) {
00515             throw new ddl_table_missing_exception($xmldb_table->getName());
00516         }
00517 
00518         if (!$sqlarr = $this->generator->getDropTempTableSQL($xmldb_table)) {
00519             throw new ddl_exception('ddlunknownerror', null, 'temp table drop sql not generated');
00520         }
00521 
00522         $this->execute_sql_arr($sqlarr);
00523     }
00524 
00533     public function rename_table(xmldb_table $xmldb_table, $newname) {
00535         if (!$newname) {
00536             throw new ddl_exception('ddlunknownerror', null, 'newname can not be empty');
00537         }
00538 
00539         $check = new xmldb_table($newname);
00540 
00542         if (!$this->table_exists($xmldb_table)) {
00543             if ($this->table_exists($check)) {
00544                 throw new ddl_exception('ddlunknownerror', null, 'table probably already renamed');
00545             } else {
00546                 throw new ddl_table_missing_exception($xmldb_table->getName());
00547             }
00548         }
00549 
00551         if ($this->table_exists($check)) {
00552             throw new ddl_exception('ddltablealreadyexists', $xmldb_table->getName(), 'can not rename table');
00553         }
00554 
00555         if (!$sqlarr = $this->generator->getRenameTableSQL($xmldb_table, $newname)) {
00556             throw new ddl_exception('ddlunknownerror', null, 'table rename sql not generated');
00557         }
00558 
00559         $this->execute_sql_arr($sqlarr);
00560     }
00561 
00562 
00570     public function add_field(xmldb_table $xmldb_table, xmldb_field $xmldb_field) {
00572         if ($this->field_exists($xmldb_table, $xmldb_field)) {
00573             throw new ddl_exception('ddlfieldalreadyexists', $xmldb_field->getName());
00574         }
00575 
00578         if ($xmldb_field->getNotNull() && $this->generator->getDefaultValue($xmldb_field) === NULL && $this->mdb->count_records($xmldb_table->getName())) {
00579             throw new ddl_exception('ddlunknownerror', null, 'Field ' . $xmldb_table->getName() . '->' . $xmldb_field->getName() .
00580                       ' cannot be added. Not null fields added to non empty tables require default value. Create skipped');
00581         }
00582 
00583         if (!$sqlarr = $this->generator->getAddFieldSQL($xmldb_table, $xmldb_field)) {
00584             throw new ddl_exception('ddlunknownerror', null, 'addfield sql not generated');
00585         }
00586         $this->execute_sql_arr($sqlarr);
00587     }
00588 
00596     public function drop_field(xmldb_table $xmldb_table, xmldb_field $xmldb_field) {
00597         if (!$this->table_exists($xmldb_table)) {
00598             throw new ddl_table_missing_exception($xmldb_table->getName());
00599         }
00601         if (!$this->field_exists($xmldb_table, $xmldb_field)) {
00602             throw new ddl_field_missing_exception($xmldb_field->getName(), $xmldb_table->getName());
00603         }
00605         $this->check_field_dependencies($xmldb_table, $xmldb_field);
00606 
00607         if (!$sqlarr = $this->generator->getDropFieldSQL($xmldb_table, $xmldb_field)) {
00608             throw new ddl_exception('ddlunknownerror', null, 'drop_field sql not generated');
00609         }
00610 
00611         $this->execute_sql_arr($sqlarr);
00612     }
00613 
00621     public function change_field_type(xmldb_table $xmldb_table, xmldb_field $xmldb_field) {
00622         if (!$this->table_exists($xmldb_table)) {
00623             throw new ddl_table_missing_exception($xmldb_table->getName());
00624         }
00626         if (!$this->field_exists($xmldb_table, $xmldb_field)) {
00627             throw new ddl_field_missing_exception($xmldb_field->getName(), $xmldb_table->getName());
00628         }
00630         $this->check_field_dependencies($xmldb_table, $xmldb_field);
00631 
00632         if (!$sqlarr = $this->generator->getAlterFieldSQL($xmldb_table, $xmldb_field)) {
00633             return; // probably nothing to do
00634         }
00635 
00636         $this->execute_sql_arr($sqlarr);
00637     }
00638 
00646     public function change_field_precision(xmldb_table $xmldb_table, xmldb_field $xmldb_field) {
00648         $this->change_field_type($xmldb_table, $xmldb_field);
00649     }
00650 
00658     public function change_field_unsigned(xmldb_table $xmldb_table, xmldb_field $xmldb_field) {
00660         $this->change_field_type($xmldb_table, $xmldb_field);
00661     }
00662 
00670     public function change_field_notnull(xmldb_table $xmldb_table, xmldb_field $xmldb_field) {
00672         $this->change_field_type($xmldb_table, $xmldb_field);
00673     }
00674 
00683     public function change_field_default(xmldb_table $xmldb_table, xmldb_field $xmldb_field) {
00684         if (!$this->table_exists($xmldb_table)) {
00685             throw new ddl_table_missing_exception($xmldb_table->getName());
00686         }
00688         if (!$this->field_exists($xmldb_table, $xmldb_field)) {
00689             throw new ddl_field_missing_exception($xmldb_field->getName(), $xmldb_table->getName());
00690         }
00692         $this->check_field_dependencies($xmldb_table, $xmldb_field);
00693 
00694         if (!$sqlarr = $this->generator->getModifyDefaultSQL($xmldb_table, $xmldb_field)) {
00695             return; //Empty array = nothing to do = no error
00696         }
00697 
00698         $this->execute_sql_arr($sqlarr);
00699     }
00700 
00710     public function drop_enum_from_field(xmldb_table $xmldb_table, xmldb_field $xmldb_field) {
00711         if (!$this->table_exists($xmldb_table)) {
00712             throw new ddl_table_missing_exception($xmldb_table->getName());
00713         }
00715         if (!$this->field_exists($xmldb_table, $xmldb_field)) {
00716             throw new ddl_field_missing_exception($xmldb_field->getName(), $xmldb_table->getName());
00717         }
00718 
00719         if (!$this->check_constraint_exists($xmldb_table, $xmldb_field)) {
00720             debugging('Enum for ' . $xmldb_table->getName() . '->' . $xmldb_field->getName() .
00721                       ' does not exist. Delete skipped', DEBUG_DEVELOPER);
00722             return; //Enum does not exist, nothing to delete
00723         }
00724 
00725         if (!$sqlarr = $this->generator->getDropEnumSQL($xmldb_table, $xmldb_field)) {
00726             return; //Empty array = nothing to do = no error
00727         }
00728 
00729         $this->execute_sql_arr($sqlarr);
00730     }
00731 
00741     public function rename_field(xmldb_table $xmldb_table, xmldb_field $xmldb_field, $newname) {
00742         if (empty($newname)) {
00743             throw new ddl_exception('ddlunknownerror', null, 'newname can not be empty');
00744         }
00745 
00746         if (!$this->table_exists($xmldb_table)) {
00747             throw new ddl_table_missing_exception($xmldb_table->getName());
00748         }
00749 
00751         if (!$this->field_exists($xmldb_table, $xmldb_field)) {
00752             throw new ddl_field_missing_exception($xmldb_field->getName(), $xmldb_table->getName());
00753         }
00754 
00756         if (!$xmldb_field->getType()) {
00757             throw new ddl_exception('ddlunknownerror', null,
00758                       'Field ' . $xmldb_table->getName() . '->' . $xmldb_field->getName() .
00759                       ' must contain full specs. Rename skipped');
00760         }
00761 
00763         if ($xmldb_field->getName() == 'id') {
00764             throw new ddl_exception('ddlunknownerror', null,
00765                       'Field ' . $xmldb_table->getName() . '->' . $xmldb_field->getName() .
00766                       ' cannot be renamed. Rename skipped');
00767         }
00768 
00769         if (!$sqlarr = $this->generator->getRenameFieldSQL($xmldb_table, $xmldb_field, $newname)) {
00770             return; //Empty array = nothing to do = no error
00771         }
00772 
00773         $this->execute_sql_arr($sqlarr);
00774     }
00775 
00781     private function check_field_dependencies(xmldb_table $xmldb_table, xmldb_field $xmldb_field) {
00782 
00784         if (!$this->table_exists($xmldb_table)) {
00785             throw new ddl_table_missing_exception($xmldb_table->getName());
00786         }
00787 
00789         if (!$this->field_exists($xmldb_table, $xmldb_field)) {
00790             throw new ddl_field_missing_exception($xmldb_field->getName(), $xmldb_table->getName());
00791         }
00792 
00794         if ($indexes = $this->mdb->get_indexes($xmldb_table->getName(), false)) {
00795             foreach ($indexes as $indexname => $index) {
00796                 $columns = $index['columns'];
00797                 if (in_array($xmldb_field->getName(), $columns)) {
00798                     throw new ddl_dependency_exception('column', $xmldb_table->getName() . '->' . $xmldb_field->getName(),
00799                                                        'index', $indexname . ' (' . implode(', ', $columns)  . ')');
00800                 }
00801             }
00802         }
00803     }
00804 
00812     public function add_key(xmldb_table $xmldb_table, xmldb_key $xmldb_key) {
00813 
00814         if ($xmldb_key->getType() == XMLDB_KEY_PRIMARY) { // Prevent PRIMARY to be added (only in create table, being serious  :-P)
00815             throw new ddl_exception('ddlunknownerror', null, 'Primary Keys can be added at table create time only');
00816         }
00817 
00818         if (!$sqlarr = $this->generator->getAddKeySQL($xmldb_table, $xmldb_key)) {
00819             return; //Empty array = nothing to do = no error
00820         }
00821 
00822         $this->execute_sql_arr($sqlarr);
00823     }
00824 
00832     public function drop_key(xmldb_table $xmldb_table, xmldb_key $xmldb_key) {
00833         if ($xmldb_key->getType() == XMLDB_KEY_PRIMARY) { // Prevent PRIMARY to be dropped (only in drop table, being serious  :-P)
00834             throw new ddl_exception('ddlunknownerror', null, 'Primary Keys can be deleted at table drop time only');
00835         }
00836 
00837         if (!$sqlarr = $this->generator->getDropKeySQL($xmldb_table, $xmldb_key)) {
00838             return; //Empty array = nothing to do = no error
00839         }
00840 
00841         $this->execute_sql_arr($sqlarr);
00842     }
00843 
00853     public function rename_key(xmldb_table $xmldb_table, xmldb_key $xmldb_key, $newname) {
00854         debugging('rename_key() is one experimental feature. You must not use it in production!', DEBUG_DEVELOPER);
00855 
00857         if (!$newname) {
00858             throw new ddl_exception('ddlunknownerror', null, 'newname can not be empty');
00859         }
00860 
00861         if (!$sqlarr = $this->generator->getRenameKeySQL($xmldb_table, $xmldb_key, $newname)) {
00862             throw new ddl_exception('ddlunknownerror', null, 'Some DBs do not support key renaming (MySQL, PostgreSQL, MsSQL). Rename skipped');
00863         }
00864 
00865         $this->execute_sql_arr($sqlarr);
00866     }
00867 
00876     public function add_index($xmldb_table, $xmldb_intex) {
00877         if (!$this->table_exists($xmldb_table)) {
00878             throw new ddl_table_missing_exception($xmldb_table->getName());
00879         }
00880 
00882         if ($this->index_exists($xmldb_table, $xmldb_intex)) {
00883             throw new ddl_exception('ddlunknownerror', null,
00884                       'Index ' . $xmldb_table->getName() . '->' . $xmldb_intex->getName() .
00885                       ' already exists. Create skipped');
00886         }
00887 
00888         if (!$sqlarr = $this->generator->getAddIndexSQL($xmldb_table, $xmldb_intex)) {
00889             throw new ddl_exception('ddlunknownerror', null, 'add_index sql not generated');
00890         }
00891 
00892         $this->execute_sql_arr($sqlarr);
00893     }
00894 
00903     public function drop_index($xmldb_table, $xmldb_intex) {
00904         if (!$this->table_exists($xmldb_table)) {
00905             throw new ddl_table_missing_exception($xmldb_table->getName());
00906         }
00907 
00909         if (!$this->index_exists($xmldb_table, $xmldb_intex)) {
00910             throw new ddl_exception('ddlunknownerror', null,
00911                       'Index ' . $xmldb_table->getName() . '->' . $xmldb_intex->getName() .
00912                       ' does not exist. Drop skipped');
00913         }
00914 
00915         if (!$sqlarr = $this->generator->getDropIndexSQL($xmldb_table, $xmldb_intex)) {
00916             throw new ddl_exception('ddlunknownerror', null, 'drop_index sql not generated');
00917         }
00918 
00919         $this->execute_sql_arr($sqlarr);
00920     }
00921 
00932     public function rename_index($xmldb_table, $xmldb_intex, $newname) {
00933         debugging('rename_index() is one experimental feature. You must not use it in production!', DEBUG_DEVELOPER);
00934 
00936         if (!$newname) {
00937             throw new ddl_exception('ddlunknownerror', null, 'newname can not be empty');
00938         }
00939 
00941         if (!$this->index_exists($xmldb_table, $xmldb_intex)) {
00942             throw new ddl_exception('ddlunknownerror', null,
00943                       'Index ' . $xmldb_table->getName() . '->' . $xmldb_intex->getName() .
00944                       ' does not exist. Rename skipped');
00945         }
00946 
00947         if (!$sqlarr = $this->generator->getRenameIndexSQL($xmldb_table, $xmldb_intex, $newname)) {
00948             throw new ddl_exception('ddlunknownerror', null, 'Some DBs do not support index renaming (MySQL). Rename skipped');
00949         }
00950 
00951         $this->execute_sql_arr($sqlarr);
00952     }
00953 
00959     public function get_install_xml_schema() {
00960         global $CFG;
00961         require_once($CFG->libdir.'/adminlib.php');
00962 
00963         $schema = new xmldb_structure('export');
00964         $schema->setVersion($CFG->version);
00965         $dbdirs = get_db_directories();
00966         foreach ($dbdirs as $dbdir) {
00967             $xmldb_file = new xmldb_file($dbdir.'/install.xml');
00968             if (!$xmldb_file->fileExists() or !$xmldb_file->loadXMLStructure()) {
00969                 continue;
00970             }
00971             $structure = $xmldb_file->getStructure();
00972             $tables = $structure->getTables();
00973             foreach ($tables as $table) {
00974                 $table->setPrevious(null);
00975                 $table->setNext(null);
00976                 $schema->addTable($table);
00977             }
00978         }
00979         return $schema;
00980     }
00981 
00987     public function check_database_schema(xmldb_structure $schema) {
00988         $errors = array();
00989 
00990         $dbtables = $this->mdb->get_tables();
00991         $tables   = $schema->getTables();
00992 
00993         //TODO: maybe add several levels error/warning
00994 
00995         // make sure that current and schema tables match exactly
00996         foreach ($tables as $table) {
00997             $tablename = $table->getName();
00998             if (empty($dbtables[$tablename])) {
00999                 if (!isset($errors[$tablename])) {
01000                     $errors[$tablename] = array();
01001                 }
01002                 $errors[$tablename][] = "Table $tablename is missing in database."; //TODO: localize
01003                 continue;
01004             }
01005 
01006             // a) check for required fields
01007             $dbfields = $this->mdb->get_columns($tablename);
01008             $fields   = $table->getFields();
01009             foreach ($fields as $field) {
01010                 $fieldname = $field->getName();
01011                 if (empty($dbfields[$fieldname])) {
01012                     if (!isset($errors[$tablename])) {
01013                         $errors[$tablename] = array();
01014                     }
01015                     $errors[$tablename][] = "Field $fieldname is missing in table $tablename.";  //TODO: localize
01016                 }
01017                 unset($dbfields[$fieldname]);
01018             }
01019 
01020             // b) check for extra fields (indicates unsupported hacks) - modify install.xml if you want the script to continue ;-)
01021             foreach ($dbfields as $fieldname=>$info) {
01022                 if (!isset($errors[$tablename])) {
01023                     $errors[$tablename] = array();
01024                 }
01025                 $errors[$tablename][] = "Field $fieldname is not expected in table $tablename.";  //TODO: localize
01026             }
01027             unset($dbtables[$tablename]);
01028         }
01029 
01030         // look for unsupported tables - local custom tables should be in /local/xxxx/db/install.xml ;-)
01031         // if there is no prefix, we can not say if tale is ours :-(
01032         if ($this->generator->prefix !== '') {
01033             foreach ($dbtables as $tablename=>$unused) {
01034                 if (strpos($tablename, 'pma_') === 0) {
01035                     // ignore phpmyadmin tables for now
01036                     continue;
01037                 }
01038                 if (strpos($tablename, 'test') === 0) {
01039                     // ignore broken results of unit tests
01040                     continue;
01041                 }
01042                 if (!isset($errors[$tablename])) {
01043                     $errors[$tablename] = array();
01044                 }
01045                 $errors[$tablename][] = "Table $tablename is not expected.";  //TODO: localize
01046             }
01047         }
01048 
01049         return $errors;
01050     }
01051 }
 All Data Structures Namespaces Files Functions Variables Enumerations