Fix constraint checking and only run it if not already constrained
This commit is contained in:
parent
558cbe5b6d
commit
195285ac2f
@ -3087,68 +3087,77 @@ class Notice extends Managed_DataObject
|
|||||||
$schema = Schema::get();
|
$schema = Schema::get();
|
||||||
$schemadef = $schema->getTableDef($table);
|
$schemadef = $schema->getTableDef($table);
|
||||||
|
|
||||||
printfnq("\nConstraint checking Notice table...\n");
|
|
||||||
/**
|
/**
|
||||||
* Improve typing and make sure no NULL values in any id-related columns are 0
|
* Make sure constraints are met before upgrading, if foreign keys
|
||||||
|
* are not already in use.
|
||||||
* 2016-03-31
|
* 2016-03-31
|
||||||
*/
|
*/
|
||||||
foreach (['reply_to', 'repeat_of'] as $field) {
|
if (!isset($schemadef['foreign keys'])) {
|
||||||
$notice = new Notice(); // reset the object
|
$newschemadef = self::schemaDef();
|
||||||
$notice->query(sprintf('UPDATE %1$s SET %2$s=NULL WHERE %2$s=0', $notice->escapedTableName(), $field));
|
printfnq("\nConstraint checking Notice table...\n");
|
||||||
// Now we're sure that no Notice entries have repeat_of=0, only an id > 0 or NULL
|
/**
|
||||||
unset($notice);
|
* Improve typing and make sure no NULL values in any id-related columns are 0
|
||||||
}
|
* 2016-03-31
|
||||||
|
*/
|
||||||
/**
|
foreach (['reply_to', 'repeat_of'] as $field) {
|
||||||
* Make sure constraints are met before upgrading.
|
$notice = new Notice(); // reset the object
|
||||||
* 2016-03-31
|
$notice->query(sprintf('UPDATE %1$s SET %2$s=NULL WHERE %2$s=0', $notice->escapedTableName(), $field));
|
||||||
*
|
// Now we're sure that no Notice entries have repeat_of=0, only an id > 0 or NULL
|
||||||
* Will find foreign keys which do not fulfill the constraints and fix
|
unset($notice);
|
||||||
* where appropriate, such as delete when "repeat_of" ID not found in notice.id
|
}
|
||||||
* or set to NULL for "reply_to" in the same case.
|
|
||||||
*
|
/**
|
||||||
* XXX: How does this work if we would use multicolumn foreign keys?
|
* This Will find foreign keys which do not fulfill the constraints and fix
|
||||||
*/
|
* where appropriate, such as delete when "repeat_of" ID not found in notice.id
|
||||||
foreach (['reply_to' => 'reset', 'repeat_of' => 'delete', 'profile' => 'delete'] as $field=>$action) {
|
* or set to NULL for "reply_to" in the same case.
|
||||||
$notice = new Notice();
|
* 2016-03-31
|
||||||
|
*
|
||||||
$fkeyname = $notice->tableName().'_'.$field.'_fkey';
|
* XXX: How does this work if we would use multicolumn foreign keys?
|
||||||
assert(isset($schemadef['foreign keys'][$fkeyname]) && $schemadef['foreign keys'][$fkeyname]);
|
*/
|
||||||
$foreign_key = $schemadef['foreign keys'][$fkeyname];
|
foreach (['reply_to' => 'reset', 'repeat_of' => 'delete', 'profile_id' => 'delete'] as $field=>$action) {
|
||||||
printfnq("\n"._ve($schemadef));
|
$notice = new Notice();
|
||||||
$fkeytable = $foreign_key[0];
|
|
||||||
assert(isset($foreign_key[1][$field]));
|
$fkeyname = $notice->tableName().'_'.$field.'_fkey';
|
||||||
$fkeycol = $foreign_key[1][$field];
|
assert(isset($newschemadef['foreign keys'][$fkeyname]));
|
||||||
|
assert($newschemadef['foreign keys'][$fkeyname]);
|
||||||
// NOTE: Above we set all repeat_of to NULL if they were 0, so this really gets them all.
|
|
||||||
$notice->whereAdd(sprintf('%1$s NOT IN (SELECT %2$s FROM %3$s)', $field, $fkeycol, $fkeytable));
|
$foreign_key = $newschemadef['foreign keys'][$fkeyname];
|
||||||
if ($notice->find()) {
|
$fkeytable = $foreign_key[0];
|
||||||
printfnq("\tFound {$notice->N} notices with {$field} NOT IN notice.id, {$action}ing...");
|
assert(isset($foreign_key[1][$field]));
|
||||||
switch ($action) {
|
$fkeycol = $foreign_key[1][$field];
|
||||||
case 'delete': // since it's a directly dependant notice for an unknown ID we don't want it in our DB
|
|
||||||
while ($notice->fetch()) {
|
printfnq("* {$fkeyname} ({$field} => {$fkeytable}.{$fkeycol})\n");
|
||||||
// $notice->delete();
|
|
||||||
printfnq("\n deleting {$notice->id}");
|
// NOTE: Above we set all repeat_of to NULL if they were 0, so this really gets them all.
|
||||||
}
|
$notice->whereAdd(sprintf('%1$s NOT IN (SELECT %2$s FROM %3$s)', $field, $fkeycol, $fkeytable));
|
||||||
break;
|
if ($notice->find()) {
|
||||||
case 'reset': // just set it to NULL to be compatible with our constraints, if it was related to an unknown ID
|
printfnq("\tFound {$notice->N} notices with {$field} NOT IN notice.id, {$action}ing...");
|
||||||
$ids = [];
|
switch ($action) {
|
||||||
foreach ($notice->fetchAll('id') as $id) {
|
case 'delete': // since it's a directly dependant notice for an unknown ID we don't want it in our DB
|
||||||
settype($id, 'int');
|
while ($notice->fetch()) {
|
||||||
$ids[] = $id;
|
$notice->delete();
|
||||||
}
|
}
|
||||||
$notice = new Notice();
|
break;
|
||||||
$notice->query(sprintf('UPDATE %1$s SET %2$s=NULL WHERE id IN (%3$s)',
|
case 'reset': // just set it to NULL to be compatible with our constraints, if it was related to an unknown ID
|
||||||
$notice->escapedTableName(),
|
$ids = [];
|
||||||
$field,
|
foreach ($notice->fetchAll('id') as $id) {
|
||||||
implode(',', $ids)));
|
settype($id, 'int');
|
||||||
break;
|
$ids[] = $id;
|
||||||
default:
|
}
|
||||||
throw new ServerException('The programmer sucks, invalid action name when fixing table.');
|
unset($notice);
|
||||||
}
|
$notice = new Notice();
|
||||||
printfnq("DONE.\n");
|
$notice->query(sprintf('UPDATE %1$s SET %2$s=NULL WHERE id IN (%3$s)',
|
||||||
|
$notice->escapedTableName(),
|
||||||
|
$field,
|
||||||
|
implode(',', $ids)));
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
throw new ServerException('The programmer sucks, invalid action name when fixing table.');
|
||||||
|
}
|
||||||
|
printfnq("DONE.\n");
|
||||||
|
}
|
||||||
|
unset($notice);
|
||||||
}
|
}
|
||||||
unset($notice);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 2015-09-04 We move Notice location data to Notice_location
|
// 2015-09-04 We move Notice location data to Notice_location
|
||||||
|
Loading…
Reference in New Issue
Block a user