Skip to content

Commit

Permalink
MDL-19695 field dependencies - defined new exception ddl_dependency_e…
Browse files Browse the repository at this point in the history
…xception that

will be thrown when one DDL operation (drop only for now) is attempted over one
field being part of indexes.
  • Loading branch information
stronk7 committed Jul 2, 2009
1 parent 4276a19 commit 2baf138
Show file tree
Hide file tree
Showing 3 changed files with 64 additions and 15 deletions.
1 change: 1 addition & 0 deletions lang/en_utf8/error.php
Expand Up @@ -171,6 +171,7 @@
$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';
Expand Down
61 changes: 46 additions & 15 deletions lib/ddl/database_manager.php
Expand Up @@ -611,6 +611,8 @@ public function drop_field(xmldb_table $xmldb_table, xmldb_field $xmldb_field) {
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');
Expand Down Expand Up @@ -679,15 +681,14 @@ public function change_field_notnull(xmldb_table $xmldb_table, xmldb_field $xmld
}

/**
* 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());
}
Expand All @@ -696,28 +697,23 @@ public function drop_enum_from_field(xmldb_table $xmldb_table, xmldb_field $xmld
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
}

$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
* 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());
}
Expand All @@ -726,7 +722,13 @@ public function change_field_default(xmldb_table $xmldb_table, xmldb_field $xmld
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
}

Expand Down Expand Up @@ -777,6 +779,35 @@ public function rename_field(xmldb_table $xmldb_table, xmldb_field $xmldb_field,
$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
*
Expand Down
17 changes: 17 additions & 0 deletions lib/ddllib.php
Expand Up @@ -130,3 +130,20 @@ function __construct($error, $sql=null) {
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);
}
}

0 comments on commit 2baf138

Please sign in to comment.