]> git.mjollnir.org Git - moodle.git/commitdiff
MDL-19695 field dependencies - defined new exception ddl_dependency_exception that
authorstronk7 <stronk7>
Thu, 2 Jul 2009 16:08:44 +0000 (16:08 +0000)
committerstronk7 <stronk7>
Thu, 2 Jul 2009 16:08:44 +0000 (16:08 +0000)
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
lib/ddl/database_manager.php
lib/ddllib.php

index 5a0b4fbb52e850e0408b74a013137d72d579c54b..211ee8d06c71a5d8100e8a676ab24a2886e73cde 100644 (file)
@@ -171,6 +171,7 @@ $string['dbsessionmysqlpacketsize'] = 'Serious session error detected.<br /><br
 $string['ddlexecuteerror'] = 'DDL sql execution error';
 $string['ddlfieldalreadyexists'] = 'Field \"$a\" does not exist';
 $string['ddlfieldnotexist'] = 'Field \"$a->fieldname\" does not exist in table \"$a->tablename\"';
+$string['ddldependencyerror'] = '$a->targettype \"$a->targetname\" cannot be modifed. Dependency found with $a->offendingtype \"$a->offendingname\"';
 $string['ddltablealreadyexists'] = 'Table \"$a\" already exists';
 $string['ddltablenotexist'] = 'Table \"$a\" does not exist';
 $string['ddlunknownerror'] = 'Unknown DDL library error';
index 0808d8ce8e4654f0f6346636500254b98b962d97..d3e33a7c3d5184ad3021c31547efc8fb242131e9 100644 (file)
@@ -611,6 +611,8 @@ class database_manager {
         if (!$this->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');
@@ -679,15 +681,14 @@ class database_manager {
     }
 
     /**
-     * This function will drop the existing enum of the field in the table passed as arguments
-     *
-     * TODO: Moodle 2.1 - Drop drop_enum_from_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 drop_enum_from_field(xmldb_table $xmldb_table, xmldb_field $xmldb_field) {
+    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());
         }
@@ -696,13 +697,7 @@ class database_manager {
             throw new ddl_field_missing_exception($xmldb_field->getName(), $xmldb_table->getName());
         }
 
-        if (!$this->check_constraint_exists($xmldb_table, $xmldb_field)) {
-            debugging('Enum for ' . $xmldb_table->getName() . '->' . $xmldb_field->getName() .
-                      ' does not exist. Delete skipped', DEBUG_DEVELOPER);
-            return; //Enum does not exist, nothing to delete
-        }
-
-        if (!$sqlarr = $this->generator->getDropEnumSQL($xmldb_table, $xmldb_field)) {
+        if (!$sqlarr = $this->generator->getModifyDefaultSQL($xmldb_table, $xmldb_field)) {
             return; //Empty array = nothing to do = no error
         }
 
@@ -710,14 +705,15 @@ class database_manager {
     }
 
     /**
-     * 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
+     * This function will drop the existing enum of the field in the table passed as arguments
+     *
+     * TODO: Moodle 2.1 - Drop drop_enum_from_field()
      *
      * @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) {
+    public function drop_enum_from_field(xmldb_table $xmldb_table, xmldb_field $xmldb_field) {
         if (!$this->table_exists($xmldb_table)) {
             throw new ddl_table_missing_exception($xmldb_table->getName());
         }
@@ -726,7 +722,13 @@ class database_manager {
             throw new ddl_field_missing_exception($xmldb_field->getName(), $xmldb_table->getName());
         }
 
-        if (!$sqlarr = $this->generator->getModifyDefaultSQL($xmldb_table, $xmldb_field)) {
+        if (!$this->check_constraint_exists($xmldb_table, $xmldb_field)) {
+            debugging('Enum for ' . $xmldb_table->getName() . '->' . $xmldb_field->getName() .
+                      ' does not exist. Delete skipped', DEBUG_DEVELOPER);
+            return; //Enum does not exist, nothing to delete
+        }
+
+        if (!$sqlarr = $this->generator->getDropEnumSQL($xmldb_table, $xmldb_field)) {
             return; //Empty array = nothing to do = no error
         }
 
@@ -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
      *
index d61c6953ba1372f7600c7c9dd56ce746a4c2b96f..75b069a198ac59a79f4aee8cf5b6e82dcc36d956 100644 (file)
@@ -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);
+    }
+}