1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121
|
/*
Copyright (C) 2019-2024 Selwin van Dijk
This file is part of signalbackup-tools.
signalbackup-tools is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
signalbackup-tools is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with signalbackup-tools. If not, see <https://www.gnu.org/licenses/>.
*/
#include "signalbackup.ih"
void SignalBackup::compactIds(std::string const &table, std::string const &col)
{
//Logger::message(__FUNCTION__);
if (d_database.getSingleResultAs<long long int>("SELECT COUNT(*) FROM " + table, -1) == 0) // table is empty
return;
Logger::message(" Compacting table: ", table, " (", col, ")");
SqliteDB::QueryResults results;
// d_database.exec("SELECT " + col + " FROM " + table, &results);
// results.prettyPrint();
// gets first available _id in table
d_database.exec("SELECT t1." + col + "+1 FROM " + table + " t1 LEFT OUTER JOIN " + table + " t2 ON t2." + col + "=t1." + col + "+1 WHERE t2." + col + " IS NULL AND t1." + col + " > 0 ORDER BY t1." + col + " LIMIT 1", &results);
while (results.rows() > 0 && results.valueHasType<long long int>(0, 0))
{
long long int nid = results.getValueAs<long long int>(0, 0);
d_database.exec("SELECT MIN(" + col + ") FROM " + table + " WHERE " + col + " > ?", nid, &results);
if (results.rows() == 0 || !results.valueHasType<long long int>(0, 0))
break;
long long int valuetochange = results.getValueAs<long long int>(0, 0);
//std::cout << "Changing _id : " << valuetochange << " -> " << nid << std::endl;
d_database.exec("UPDATE " + table + " SET " + col + " = ? WHERE " + col + " = ?", {nid, valuetochange});
if (col == "_id") [[likely]]
{
for (auto const &dbl : s_databaselinks)
{
if (dbl.flags & SKIP)
continue;
if (!d_database.containsTable(dbl.table)) [[unlikely]]
continue;
if (table == dbl.table)
{
for (auto const &c : dbl.connections)
{
if (d_databaseversion >= c.mindbvversion && d_databaseversion <= c.maxdbvversion &&
d_database.containsTable(c.table) && d_database.tableContainsColumn(c.table, c.column))
{
if (!c.json_path.empty())
{
if (!d_database.exec("UPDATE " + c.table + " SET " + c.column + " = json_replace(" + c.column + ", " + c.json_path + ", ?) "
"WHERE json_extract(" + c.column + ", " + c.json_path + ") = ?", {nid, valuetochange}))
Logger::error("Compacting table '", table, "'");
}
else if (!d_database.exec("UPDATE " + c.table + " SET " + c.column + " = ? WHERE " + c.column + " = ?" + (c.whereclause.empty() ? "" : " AND " + c.whereclause), {nid, valuetochange}))
Logger::error("Compacting table '", table, "'");
}
}
}
}
if (table == d_part_table)
{
for (auto att = d_attachments.begin(); att != d_attachments.end(); )
{
if (reinterpret_cast<AttachmentFrame *>(att->second.get())->rowId() == static_cast<uint64_t>(valuetochange))
{
AttachmentFrame *af = reinterpret_cast<AttachmentFrame *>(att->second.release());
att = d_attachments.erase(att);
af->setRowId(nid);
int64_t uniqueid = af->attachmentId();
if (uniqueid == 0)
uniqueid = -1;
d_attachments.emplace(std::make_pair(af->rowId(), uniqueid), af);
}
else
++att;
}
}
else if (table == "sticker")
{
for (auto s = d_stickers.begin(); s != d_stickers.end(); )
{
if (reinterpret_cast<StickerFrame *>(s->second.get())->rowId() == static_cast<uint64_t>(valuetochange))
{
StickerFrame *sf = reinterpret_cast<StickerFrame *>(s->second.release());
s = d_stickers.erase(s);
sf->setRowId(nid);
d_stickers.emplace(std::make_pair(sf->rowId(), sf));
}
else
++s;
}
}
}
// gets first available _id in table
d_database.exec("SELECT t1." + col + "+1 FROM " + table + " t1 LEFT OUTER JOIN " + table + " t2 ON t2." + col + "=t1." + col + "+1 WHERE t2." + col + " IS NULL AND t1." + col + " > 0 ORDER BY t1." + col + " LIMIT 1", &results);
}
// d_database.exec("SELECT _id FROM " + table, &results);
// results.prettyPrint();
}
|