Avoid duplicated contacts, improve contact deletion, avoid memory issues

This commit is contained in:
Michael 2018-12-02 16:25:25 +00:00
parent 00011dfeae
commit 066a040cc7
4 changed files with 74 additions and 73 deletions

View file

@ -34,7 +34,7 @@
use Friendica\Database\DBA;
if (!defined('DB_UPDATE_VERSION')) {
define('DB_UPDATE_VERSION', 1290);
define('DB_UPDATE_VERSION', 1291);
}
return [
@ -643,6 +643,7 @@ return [
"uid_contactid_created" => ["uid", "contact-id", "created"],
"authorid_created" => ["author-id", "created"],
"ownerid" => ["owner-id"],
"contact-id" => ["contact-id"],
"uid_uri" => ["uid", "uri(190)"],
"resource-id" => ["resource-id"],
"deleted_changed" => ["deleted", "changed"],
@ -894,7 +895,9 @@ return [
"fid" => ["type" => "int unsigned", "not null" => "1", "relation" => ["fcontact" => "id"], "comment" => ""],
],
"indexes" => [
"PRIMARY" => ["iid", "server"]
"PRIMARY" => ["iid", "server"],
"cid" => ["cid"],
"fid" => ["fid"]
]
],
"pconfig" => [

View file

@ -118,6 +118,8 @@ class Update
Lock::release('dbupdate');
}
}
} elseif ($force) {
DBStructure::update($verbose, true);
}
return '';

View file

@ -1044,12 +1044,11 @@ class DBA
* @param array $options
* - cascade: If true we delete records in other tables that depend on the one we're deleting through
* relations (default: true)
* @param boolean $in_process Internal use: Only do a commit after the last delete
* @param array $callstack Internal use: prevent endless loops
*
* @return boolean|array was the delete successful? When $in_process is set: deletion data
* @return boolean was the delete successful?
*/
public static function delete($table, array $conditions, array $options = [], $in_process = false, array &$callstack = [])
public static function delete($table, array $conditions, array $options = [], array &$callstack = [])
{
if (empty($table) || empty($conditions)) {
Logger::log('Table and conditions have to be set');
@ -1098,22 +1097,18 @@ class DBA
if ((count($conditions) == 1) && ($field == array_keys($conditions)[0])) {
foreach ($rel_def AS $rel_table => $rel_fields) {
foreach ($rel_fields AS $rel_field) {
$retval = self::delete($rel_table, [$rel_field => array_values($conditions)[0]], $options, true, $callstack);
$commands = array_merge($commands, $retval);
$retval = self::delete($rel_table, [$rel_field => array_values($conditions)[0]], $options, $callstack);
}
}
// We quit when this key already exists in the callstack.
} elseif (!isset($callstack[$qkey])) {
$callstack[$qkey] = true;
// Fetch all rows that are to be deleted
$data = self::select($table, [$field], $conditions);
while ($row = self::fetch($data)) {
// Now we accumulate the delete commands
$retval = self::delete($table, [$field => $row[$field]], $options, true, $callstack);
$commands = array_merge($commands, $retval);
self::delete($table, [$field => $row[$field]], $options, $callstack);
}
self::close($data);
@ -1123,7 +1118,6 @@ class DBA
}
}
if (!$in_process) {
// Now we finalize the process
$do_transaction = !self::$in_transaction;
@ -1190,9 +1184,6 @@ class DBA
return true;
}
return $commands;
}
/**
* @brief Updates rows
*

View file

@ -1147,7 +1147,7 @@ class Contact extends BaseObject
$url = $data["url"];
if (!$contact_id) {
DBA::insert('contact', [
$fields = [
'uid' => $uid,
'created' => DateTimeFormat::utcNow(),
'url' => $data["url"],
@ -1176,10 +1176,13 @@ class Contact extends BaseObject
'writable' => 1,
'blocked' => 0,
'readonly' => 0,
'pending' => 0]
);
'pending' => 0];
$s = DBA::select('contact', ['id'], ['nurl' => Strings::normaliseLink($data["url"]), 'uid' => $uid], ['order' => ['id'], 'limit' => 2]);
$condition = ['nurl' => Strings::normaliseLink($data["url"]), 'uid' => $uid, 'deleted' => false];
DBA::update('contact', $fields, $condition, true);
$s = DBA::select('contact', ['id'], $condition, ['order' => ['id'], 'limit' => 2]);
$contacts = DBA::toArray($s);
if (!DBA::isResult($contacts)) {
return 0;
@ -1204,8 +1207,10 @@ class Contact extends BaseObject
}
if (count($contacts) > 1 && $uid == 0 && $contact_id != 0 && $data["url"] != "") {
DBA::delete('contact', ["`nurl` = ? AND `uid` = 0 AND `id` != ? AND NOT `self`",
Strings::normaliseLink($data["url"]), $contact_id]);
$condition = ["`nurl` = ? AND `uid` = ? AND `id` != ? AND NOT `self`",
Strings::normaliseLink($data["url"]), 0, $contact_id];
Logger::log('Deleting duplicate contact ' . json_encode($condition), Logger::DEBUG);
DBA::delete('contact', $condition);
}
}