From 2baf1380d4898e15328fa6aa62e13115ce6092a8 Mon Sep 17 00:00:00 2001 From: stronk7 Date: Thu, 2 Jul 2009 16:08:44 +0000 Subject: [PATCH] MDL-19695 field dependencies - defined new exception ddl_dependency_exception that will be thrown when one DDL operation (drop only for now) is attempted over one field being part of indexes. --- lang/en_utf8/error.php | 1 + lib/ddl/database_manager.php | 79 +++++++++++++++++++++++++----------- lib/ddllib.php | 17 ++++++++ 3 files changed, 73 insertions(+), 24 deletions(-) diff --git a/lang/en_utf8/error.php b/lang/en_utf8/error.php index 5a0b4fbb52e..211ee8d06c7 100644 --- a/lang/en_utf8/error.php +++ b/lang/en_utf8/error.php @@ -171,6 +171,7 @@ $string['dbsessionmysqlpacketsize'] = 'Serious session error detected.

field_exists($xmldb_table, $xmldb_field)) { throw new ddl_field_missing_exception($xmldb_field->getName(), $xmldb_table->getName()); } + /// Check for dependencies in the DB before performing any action + $this->check_field_dependencies($xmldb_table, $xmldb_field); if (!$sqlarr = $this->generator->getDropFieldSQL($xmldb_table, $xmldb_field)) { throw new ddl_exception('ddlunknownerror', null, 'drop_field sql not generated'); @@ -678,6 +680,30 @@ class database_manager { $this->change_field_type($xmldb_table, $xmldb_field); } + /** + * This function will change the default of the field in the table passed as arguments + * One null value in the default field means delete the default + * + * @param xmldb_table table object (just the name is mandatory) + * @param xmldb_field field object (full specs are required) + * @return void + */ + public function change_field_default(xmldb_table $xmldb_table, xmldb_field $xmldb_field) { + if (!$this->table_exists($xmldb_table)) { + throw new ddl_table_missing_exception($xmldb_table->getName()); + } + /// Check the field exists + if (!$this->field_exists($xmldb_table, $xmldb_field)) { + throw new ddl_field_missing_exception($xmldb_field->getName(), $xmldb_table->getName()); + } + + if (!$sqlarr = $this->generator->getModifyDefaultSQL($xmldb_table, $xmldb_field)) { + return; //Empty array = nothing to do = no error + } + + $this->execute_sql_arr($sqlarr); + } + /** * This function will drop the existing enum of the field in the table passed as arguments * @@ -709,30 +735,6 @@ class database_manager { $this->execute_sql_arr($sqlarr); } - /** - * This function will change the default of the field in the table passed as arguments - * One null value in the default field means delete the default - * - * @param xmldb_table table object (just the name is mandatory) - * @param xmldb_field field object (full specs are required) - * @return void - */ - public function change_field_default(xmldb_table $xmldb_table, xmldb_field $xmldb_field) { - if (!$this->table_exists($xmldb_table)) { - throw new ddl_table_missing_exception($xmldb_table->getName()); - } - /// Check the field exists - if (!$this->field_exists($xmldb_table, $xmldb_field)) { - throw new ddl_field_missing_exception($xmldb_field->getName(), $xmldb_table->getName()); - } - - if (!$sqlarr = $this->generator->getModifyDefaultSQL($xmldb_table, $xmldb_field)) { - return; //Empty array = nothing to do = no error - } - - $this->execute_sql_arr($sqlarr); - } - /** * This function will rename the field in the table passed as arguments * Before renaming the field, the function will check it exists @@ -777,6 +779,35 @@ class database_manager { $this->execute_sql_arr($sqlarr); } + /** + * This function will check, for the given table and field, if there there is any dependency + * preventing the field to be modified. It's used by all the public methods that perform any + * DDL change on fields, throwing one ddl_dependency_exception if dependencies are found + */ + private function check_field_dependencies(xmldb_table $xmldb_table, xmldb_field $xmldb_field) { + + /// Check the table exists + if (!$this->table_exists($xmldb_table)) { + throw new ddl_table_missing_exception($xmldb_table->getName()); + } + + /// Check the field exists + if (!$this->field_exists($xmldb_table, $xmldb_field)) { + throw new ddl_field_missing_exception($xmldb_field->getName(), $xmldb_table->getName()); + } + + /// Check the field isn't in use by any index in the table + if ($indexes = $this->mdb->get_indexes($xmldb_table->getName(), false)) { + foreach ($indexes as $indexname => $index) { + $columns = $index['columns']; + if (in_array($xmldb_field->getName(), $columns)) { + throw new ddl_dependency_exception('column', $xmldb_table->getName() . '->' . $xmldb_field->getName(), + 'index', $indexname . ' (' . implode(', ', $columns) . ')'); + } + } + } + } + /** * This function will create the key in the table passed as arguments * diff --git a/lib/ddllib.php b/lib/ddllib.php index d61c6953ba1..75b069a198a 100644 --- a/lib/ddllib.php +++ b/lib/ddllib.php @@ -130,3 +130,20 @@ class ddl_change_structure_exception extends ddl_exception { parent::__construct('ddlexecuteerror', NULL, $errorinfo); } } + +/** + * Error changing db structure, caused by some depency found + * like trying to modify one field having related indexes. + */ +class ddl_dependency_exception extends ddl_exception { + + function __construct($targettype, $targetname, $offendingtype, $offendingname, $debuginfo=null) { + $a = new object(); + $a->targettype = $targettype; + $a->targetname = $targetname; + $a->offendingtype = $offendingtype; + $a->offendingname = $offendingname; + + parent::__construct('ddldependencyerror', $a, $debuginfo); + } +}