data/MailCacheHeaderRows.cpp
| Line | Branch | Exec | Source |
|---|---|---|---|
| 1 | // MailCache: the per-row steps of storeHeaderBatch (split out of | ||
| 2 | // MailCache.cpp, Sprint 105): write order, the unchanged-row check, the | ||
| 3 | // address index rows (S105.5.1) and the UPSERT binding; and the two fenced | ||
| 4 | // batch entry points (streaming and other-connection headers, Sprint 106). | ||
| 5 | #include "MailCache.h" | ||
| 6 | |||
| 7 | #include "MailAddressIndex.h" | ||
| 8 | |||
| 9 | #include <QLoggingCategory> | ||
| 10 | #include <QSet> | ||
| 11 | #include <QSqlError> | ||
| 12 | #include <utility> | ||
| 13 | |||
| 14 | Q_DECLARE_LOGGING_CATEGORY(lcCache) | ||
| 15 | |||
| 16 | // storeHeaderBatch step: a FETCH stream must not carry a UID twice; if it | ||
| 17 | // still does, the last occurrence wins and each uid is written once. | ||
| 18 | 15460 | QList<int> MailCache::lastWinsWriteOrder(const QList<MailHeader> &headers) { | |
| 19 | 15460 | QList<int> writes; | |
| 20 |
1/1✓ Branch 3 → 4 taken 15460 times.
|
15460 | writes.reserve(headers.size()); |
| 21 | { | ||
| 22 | 15460 | QSet<qint64> batchUids; | |
| 23 |
2/2✓ Branch 15 → 7 taken 413811 times.
✓ Branch 15 → 16 taken 15460 times.
|
429271 | for (int i = headers.size() - 1; i >= 0; --i) { |
| 24 |
2/2✓ Branch 9 → 10 taken 1 time.
✓ Branch 9 → 11 taken 413810 times.
|
413811 | if (batchUids.contains(headers.at(i).uid)) continue; |
| 25 |
1/1✓ Branch 12 → 13 taken 413810 times.
|
413810 | batchUids.insert(headers.at(i).uid); |
| 26 |
1/1✓ Branch 13 → 14 taken 413810 times.
|
413810 | writes.prepend(i); |
| 27 | } | ||
| 28 | 15460 | } | |
| 29 | 15460 | return writes; | |
| 30 | ✗ | } | |
| 31 | |||
| 32 | // storeHeaderBatch step: an existing row already holds exactly this header | ||
| 33 | // (a semantically unchanged sync is skipped). Fields this writer did not | ||
| 34 | // read (recipients, spam filter) never count as a change. | ||
| 35 | 2732 | bool MailCache::storedRowMatches(const ExistingHeader &prior, const MailHeader &h, const QVariant &dateValue, | |
| 36 | const QString &canonicalMessageId, const QString &encodedReplyIds, | ||
| 37 | const QString &encodedReferences) { | ||
| 38 |
4/4✓ Branch 5 → 6 taken 2593 times.
✓ Branch 5 → 46 taken 1 time.
✓ Branch 7 → 8 taken 2589 times.
✓ Branch 7 → 46 taken 4 times.
|
5326 | return prior.subject == h.subject && prior.from == h.from && prior.to == h.to && |
| 39 |
2/4✓ Branch 11 → 14 taken 18 times.
✗ Branch 11 → 46 not taken.
✓ Branch 13 → 14 taken 2571 times.
✗ Branch 13 → 46 not taken.
|
5178 | (prior.date.isNull() ? dateValue.isNull() : prior.date == dateValue) && |
| 40 |
6/6✓ Branch 14 → 15 taken 2561 times.
✓ Branch 14 → 46 taken 28 times.
✓ Branch 15 → 16 taken 2560 times.
✓ Branch 15 → 46 taken 1 time.
✓ Branch 19 → 20 taken 2559 times.
✓ Branch 19 → 46 taken 1 time.
|
5149 | prior.flags == h.flags && prior.size == h.size && |
| 41 |
4/4✓ Branch 16 → 17 taken 2 times.
✓ Branch 16 → 18 taken 2558 times.
✓ Branch 21 → 22 taken 2558 times.
✓ Branch 21 → 46 taken 1 time.
|
5119 | prior.hasAttachments == (h.hasAttachments ? 1 : 0) && |
| 42 |
4/4✓ Branch 23 → 24 taken 2557 times.
✓ Branch 23 → 46 taken 1 time.
✓ Branch 25 → 26 taken 1858 times.
✓ Branch 25 → 46 taken 699 times.
|
7674 | prior.messageId == canonicalMessageId && prior.inReplyTo == encodedReplyIds && |
| 43 |
4/4✓ Branch 26 → 27 taken 2 times.
✓ Branch 26 → 28 taken 1856 times.
✓ Branch 29 → 30 taken 1855 times.
✓ Branch 29 → 46 taken 3 times.
|
4415 | prior.refIds == encodedReferences && prior.isSpam == (h.isSpam ? 1 : 0) && |
| 44 |
5/12✓ Branch 3 → 4 taken 2594 times.
✓ Branch 3 → 46 taken 138 times.
✓ Branch 9 → 10 taken 18 times.
✓ Branch 9 → 12 taken 2571 times.
✗ Branch 30 → 31 not taken.
✓ Branch 30 → 36 taken 1855 times.
✗ Branch 31 → 32 not taken.
✗ Branch 31 → 46 not taken.
✗ Branch 33 → 34 not taken.
✗ Branch 33 → 46 not taken.
✗ Branch 35 → 36 not taken.
✗ Branch 35 → 46 not taken.
|
9770 | (!h.recipientsKnown || (prior.recipientsKnown && prior.cc == h.cc && prior.listId == h.listId)) && |
| 45 |
3/8✓ Branch 36 → 37 taken 4 times.
✓ Branch 36 → 45 taken 1851 times.
✗ Branch 38 → 39 not taken.
✓ Branch 38 → 46 taken 4 times.
✗ Branch 40 → 41 not taken.
✗ Branch 40 → 46 not taken.
✗ Branch 42 → 43 not taken.
✗ Branch 42 → 46 not taken.
|
1855 | (!h.spamKnown || (!prior.spamTool.isNull() && prior.spamTool == h.spamTool && |
| 46 |
0/2✗ Branch 44 → 45 not taken.
✗ Branch 44 → 46 not taken.
|
2732 | prior.spamScore == h.spamScore && prior.spamThreshold == h.spamThreshold)); |
| 47 | } | ||
| 48 | |||
| 49 | // storeHeaderBatch step (Sprint 105 S105.5.1): queue the address index | ||
| 50 | // rows of one written header when its From/To/Cc or date changed (its old | ||
| 51 | // rows are deleted now, the new ones written by flushAddressRows() in | ||
| 52 | // multi-row INSERTs). A writer without envelope data (recipientsKnown | ||
| 53 | // false) keeps the existing rows. | ||
| 54 | namespace { | ||
| 55 | bool addressIndexWrites = true; | ||
| 56 | } // namespace | ||
| 57 | |||
| 58 | ✗ | void MailCache::setAddressIndexWritesForBenchmark(bool enabled) { addressIndexWrites = enabled; } | |
| 59 | |||
| 60 | 411954 | bool MailCache::indexHeaderAddresses(qint64 hid, const MailHeader &h, const QVariant &dateValue, | |
| 61 | const ExistingHeader *prior) { | ||
| 62 |
1/2✗ Branch 2 → 3 not taken.
✓ Branch 2 → 4 taken 411954 times.
|
411954 | if (!addressIndexWrites) return true; |
| 63 |
7/8✓ Branch 4 → 5 taken 882 times.
✓ Branch 4 → 19 taken 411072 times.
✓ Branch 5 → 6 taken 1 time.
✓ Branch 5 → 18 taken 881 times.
✓ Branch 7 → 8 taken 1 time.
✗ Branch 7 → 19 not taken.
✓ Branch 20 → 21 taken 881 times.
✓ Branch 20 → 22 taken 411073 times.
|
411956 | if (prior && (!h.recipientsKnown || |
| 64 |
1/4✗ Branch 9 → 10 not taken.
✓ Branch 9 → 19 taken 1 time.
✗ Branch 11 → 12 not taken.
✗ Branch 11 → 19 not taken.
|
2 | (prior->from == h.from && prior->to == h.to && prior->cc == h.cc && |
| 65 | ✗ | (prior->date.isNull() ? dateValue.isNull() : prior->date == dateValue)))) | |
| 66 | 881 | return true; | |
| 67 |
2/2✓ Branch 22 → 23 taken 1 time.
✓ Branch 22 → 62 taken 411072 times.
|
411073 | if (prior) { |
| 68 |
1/1✓ Branch 23 → 24 taken 1 time.
|
1 | QSqlQuery remove(m_db); |
| 69 |
1/1✓ Branch 27 → 28 taken 1 time.
|
1 | remove.prepare(QStringLiteral("DELETE FROM message_addresses WHERE header_id = ?")); |
| 70 |
1/1✓ Branch 32 → 33 taken 1 time.
|
1 | remove.addBindValue(hid); |
| 71 |
2/3✓ Branch 34 → 35 taken 1 time.
✗ Branch 35 → 36 not taken.
✓ Branch 35 → 56 taken 1 time.
|
1 | if (!remove.exec()) { |
| 72 | ✗ | m_lastError = remove.lastError().text(); | |
| 73 | ✗ | qCWarning(lcCache) << "Failed to replace the address rows of header" << hid << ":" << m_lastError; | |
| 74 | ✗ | m_db.rollback(); | |
| 75 | ✗ | return false; | |
| 76 | } | ||
| 77 | 1 | } | |
| 78 |
5/5✓ Branch 62 → 63 taken 411073 times.
✓ Branch 63 → 64 taken 411073 times.
✓ Branch 64 → 65 taken 411073 times.
✓ Branch 73 → 66 taken 653553 times.
✓ Branch 73 → 74 taken 411073 times.
|
1064626 | for (const MailAddressIndex::Entry &entry : MailAddressIndex::entriesOf(h)) |
| 79 | 1064626 | m_pendingAddressRows.append({hid, entry.address, entry.role, dateValue}); | |
| 80 | 411073 | return true; | |
| 81 | 653553 | } | |
| 82 | |||
| 83 | // storeHeaderBatch step: write the queued address rows, 100 per statement | ||
| 84 | // (one statement per row cost about 30 % of a header sync, S105.5.6). | ||
| 85 | 15451 | bool MailCache::flushAddressRows() { | |
| 86 | 15451 | constexpr int kRowsPerStatement = 100; | |
| 87 | 16127 | const auto statement = [this](int rows) { | |
| 88 | 16127 | QStringList tuples; | |
| 89 |
3/3✓ Branch 6 → 7 taken 160251 times.
✓ Branch 10 → 3 taken 160251 times.
✓ Branch 10 → 11 taken 16127 times.
|
176378 | for (int i = 0; i < rows; ++i) tuples << QStringLiteral("(?,?,?,?)"); |
| 90 |
1/1✓ Branch 11 → 12 taken 16127 times.
|
16127 | QSqlQuery query(m_db); |
| 91 |
1/1✓ Branch 19 → 20 taken 16127 times.
|
48381 | query.prepare(QStringLiteral("INSERT OR IGNORE INTO message_addresses (header_id, address, role, date) VALUES ") |
| 92 |
2/2✓ Branch 14 → 15 taken 16127 times.
✓ Branch 18 → 19 taken 16127 times.
|
64508 | + tuples.join(QLatin1Char(','))); |
| 93 | 16127 | return query; | |
| 94 | 16127 | }; | |
| 95 |
4/4✓ Branch 3 → 4 taken 1149 times.
✓ Branch 3 → 10 taken 14302 times.
✓ Branch 4 → 5 taken 1149 times.
✓ Branch 5 → 6 taken 1149 times.
|
15451 | if (!m_addressStatements) m_addressStatements = std::make_unique<QSqlQuery>(statement(kRowsPerStatement)); |
| 96 | 15451 | const QList<PendingAddressRow> rows = std::exchange(m_pendingAddressRows, {}); | |
| 97 |
2/2✓ Branch 76 → 14 taken 21060 times.
✓ Branch 76 → 77 taken 15451 times.
|
36511 | for (qsizetype at = 0; at < rows.size(); at += kRowsPerStatement) { |
| 98 | 21060 | const qsizetype count = std::min<qsizetype>(kRowsPerStatement, rows.size() - at); | |
| 99 |
9/13✓ Branch 16 → 17 taken 6082 times.
✓ Branch 16 → 20 taken 14978 times.
✓ Branch 17 → 18 taken 6082 times.
✓ Branch 19 → 21 taken 6082 times.
✓ Branch 20 → 21 taken 14978 times.
✓ Branch 21 → 22 taken 6082 times.
✓ Branch 21 → 23 taken 14978 times.
✓ Branch 23 → 24 taken 6082 times.
✓ Branch 23 → 25 taken 14978 times.
✗ Branch 85 → 86 not taken.
✗ Branch 85 → 87 not taken.
✗ Branch 89 → 90 not taken.
✗ Branch 89 → 91 not taken.
|
21060 | QSqlQuery partial = count == kRowsPerStatement ? QSqlQuery() : statement(int(count)); |
| 100 |
2/2✓ Branch 25 → 26 taken 6082 times.
✓ Branch 25 → 27 taken 14978 times.
|
21060 | QSqlQuery &insert = count == kRowsPerStatement ? *m_addressStatements : partial; |
| 101 |
2/2✓ Branch 48 → 29 taken 653551 times.
✓ Branch 48 → 49 taken 21060 times.
|
674611 | for (qsizetype i = at; i < at + count; ++i) { |
| 102 |
1/1✓ Branch 32 → 33 taken 653551 times.
|
653551 | insert.addBindValue(rows.at(i).headerId); |
| 103 |
1/1✓ Branch 37 → 38 taken 653551 times.
|
653551 | insert.addBindValue(rows.at(i).address); |
| 104 |
1/1✓ Branch 42 → 43 taken 653551 times.
|
653551 | insert.addBindValue(rows.at(i).role); |
| 105 |
1/1✓ Branch 46 → 47 taken 653551 times.
|
653551 | insert.addBindValue(rows.at(i).date); |
| 106 | } | ||
| 107 |
2/3✓ Branch 49 → 50 taken 21060 times.
✗ Branch 50 → 51 not taken.
✓ Branch 50 → 69 taken 21060 times.
|
21060 | if (!insert.exec()) { |
| 108 | ✗ | m_lastError = insert.lastError().text(); | |
| 109 | ✗ | qCWarning(lcCache) << "Failed to write the address index:" << m_lastError; | |
| 110 | ✗ | m_db.rollback(); | |
| 111 | ✗ | return false; | |
| 112 | } | ||
| 113 | 21060 | } | |
| 114 | 15451 | return true; | |
| 115 | 15451 | } | |
| 116 | |||
| 117 | // storeHeaderBatch step: bind one header to the prepared UPSERT. | ||
| 118 | 411963 | void MailCache::bindHeaderUpsert(QSqlQuery &q, qint64 folderId, const MailHeader &h, | |
| 119 | const QVariant &dateValue, const QString &canonicalMessageId, | ||
| 120 | const QString &encodedReplyIds, | ||
| 121 | const QString &encodedReferences) { | ||
| 122 |
1/1✓ Branch 7 → 8 taken 411963 times.
|
823926 | q.bindValue(QStringLiteral(":fid"), folderId); |
| 123 |
1/1✓ Branch 16 → 17 taken 411963 times.
|
823926 | q.bindValue(QStringLiteral(":uid"), h.uid); |
| 124 |
1/1✓ Branch 25 → 26 taken 411963 times.
|
823926 | q.bindValue(QStringLiteral(":subj"), h.subject); |
| 125 |
1/1✓ Branch 34 → 35 taken 411963 times.
|
823926 | q.bindValue(QStringLiteral(":from"), h.from); |
| 126 |
1/1✓ Branch 43 → 44 taken 411963 times.
|
823926 | q.bindValue(QStringLiteral(":to"), h.to); |
| 127 |
1/1✓ Branch 51 → 52 taken 411963 times.
|
411963 | q.bindValue(QStringLiteral(":date"), dateValue); |
| 128 |
1/1✓ Branch 59 → 60 taken 411963 times.
|
823926 | q.bindValue(QStringLiteral(":flags"), h.flags); |
| 129 |
1/1✓ Branch 68 → 69 taken 411963 times.
|
823926 | q.bindValue(QStringLiteral(":size"), h.size); |
| 130 |
3/3✓ Branch 73 → 74 taken 32835 times.
✓ Branch 73 → 75 taken 379128 times.
✓ Branch 80 → 81 taken 411963 times.
|
823926 | q.bindValue(QStringLiteral(":att"), h.hasAttachments ? 1 : 0); |
| 131 |
1/1✓ Branch 89 → 90 taken 411963 times.
|
823926 | q.bindValue(QStringLiteral(":msgid"), canonicalMessageId); |
| 132 |
1/1✓ Branch 98 → 99 taken 411963 times.
|
823926 | q.bindValue(QStringLiteral(":irt"), encodedReplyIds); |
| 133 |
1/1✓ Branch 107 → 108 taken 411963 times.
|
823926 | q.bindValue(QStringLiteral(":refs"), encodedReferences); |
| 134 |
3/3✓ Branch 112 → 113 taken 12 times.
✓ Branch 112 → 114 taken 411951 times.
✓ Branch 119 → 120 taken 411963 times.
|
823926 | q.bindValue(QStringLiteral(":spam"), h.isSpam ? 1 : 0); |
| 135 | // Sprint 95 S95.1.11: NULL marks "not known" (rows from before schema v24 | ||
| 136 | // or writers without an ENVELOPE); "" is a known empty value. | ||
| 137 | 823926 | const auto knownText = [&h](const QString &value) { | |
| 138 |
2/2✓ Branch 2 → 3 taken 767640 times.
✓ Branch 2 → 5 taken 56286 times.
|
823926 | if (!h.recipientsKnown) return QVariant(QMetaType::fromType<QString>()); // SQL NULL |
| 139 |
6/6✓ Branch 6 → 7 taken 53273 times.
✓ Branch 6 → 11 taken 3013 times.
✓ Branch 13 → 14 taken 53273 times.
✓ Branch 13 → 15 taken 3013 times.
✓ Branch 15 → 16 taken 53273 times.
✓ Branch 15 → 17 taken 3013 times.
|
109559 | return value.isNull() ? QVariant(QStringLiteral("")) : QVariant(value); // never a null QString |
| 140 | 411963 | }; | |
| 141 |
2/2✓ Branch 124 → 125 taken 411963 times.
✓ Branch 128 → 129 taken 411963 times.
|
823926 | q.bindValue(QStringLiteral(":cc"), knownText(h.cc)); |
| 142 |
2/2✓ Branch 133 → 134 taken 411963 times.
✓ Branch 137 → 138 taken 411963 times.
|
823926 | q.bindValue(QStringLiteral(":list"), knownText(h.listId)); |
| 143 |
2/2✓ Branch 141 → 142 taken 411963 times.
✓ Branch 142 → 143 taken 411963 times.
|
411963 | const QVariant null(QMetaType::fromType<double>()); |
| 144 |
6/6✓ Branch 144 → 145 taken 6 times.
✓ Branch 144 → 149 taken 411957 times.
✓ Branch 146 → 147 taken 5 times.
✓ Branch 146 → 149 taken 1 time.
✓ Branch 149 → 150 taken 411958 times.
✓ Branch 153 → 154 taken 411963 times.
|
823926 | q.bindValue(QStringLiteral(":sscore"), h.spamKnown && h.spamScore ? QVariant(*h.spamScore) : null); |
| 145 |
6/6✓ Branch 158 → 159 taken 6 times.
✓ Branch 158 → 163 taken 411957 times.
✓ Branch 160 → 161 taken 5 times.
✓ Branch 160 → 163 taken 1 time.
✓ Branch 163 → 164 taken 411958 times.
✓ Branch 167 → 168 taken 411963 times.
|
823926 | q.bindValue(QStringLiteral(":sthreshold"), h.spamKnown && h.spamThreshold ? QVariant(*h.spamThreshold) : null); |
| 146 |
11/15✓ Branch 172 → 173 taken 6 times.
✓ Branch 172 → 180 taken 411957 times.
✓ Branch 174 → 175 taken 1 time.
✓ Branch 174 → 178 taken 5 times.
✓ Branch 180 → 181 taken 411957 times.
✓ Branch 181 → 182 taken 411957 times.
✓ Branch 185 → 186 taken 411963 times.
✓ Branch 189 → 190 taken 6 times.
✓ Branch 189 → 191 taken 411957 times.
✓ Branch 191 → 192 taken 1 time.
✓ Branch 191 → 193 taken 411962 times.
✗ Branch 370 → 371 not taken.
✗ Branch 370 → 372 not taken.
✗ Branch 374 → 375 not taken.
✗ Branch 374 → 376 not taken.
|
823927 | q.bindValue(QStringLiteral(":stool"), h.spamKnown ? QVariant(h.spamTool.isNull() ? QStringLiteral("") : h.spamTool) |
| 147 | : QVariant(QMetaType::fromType<QString>())); | ||
| 148 | 411963 | } | |
| 149 | |||
| 150 | 6 | bool MailCache::storeEpochHeaders(qint64 folderId, quint32 uidValidity, | |
| 151 | const QList<MailHeader> &headers) { | ||
| 152 |
1/2✗ Branch 3 → 4 not taken.
✓ Branch 3 → 5 taken 6 times.
|
6 | if (headers.isEmpty()) |
| 153 | ✗ | return true; | |
| 154 |
2/2✓ Branch 5 → 6 taken 1 time.
✓ Branch 5 → 27 taken 5 times.
|
6 | if (uidValidity == 0) { |
| 155 | 1 | m_lastError = QStringLiteral("Headers without a mailbox epoch are not stored"); | |
| 156 |
8/8✓ Branch 12 → 13 taken 1 time.
✓ Branch 16 → 17 taken 1 time.
✓ Branch 17 → 18 taken 1 time.
✓ Branch 19 → 20 taken 1 time.
✓ Branch 20 → 21 taken 1 time.
✓ Branch 21 → 22 taken 1 time.
✓ Branch 25 → 14 taken 1 time.
✓ Branch 25 → 26 taken 1 time.
|
2 | qCWarning(lcCache) << "Refused" << headers.size() << "headers without an epoch for folder" << folderId; |
| 157 | 1 | return false; | |
| 158 | } | ||
| 159 |
6/8✓ Branch 27 → 28 taken 5 times.
✓ Branch 28 → 29 taken 1 time.
✓ Branch 28 → 32 taken 4 times.
✓ Branch 29 → 30 taken 1 time.
✗ Branch 30 → 31 not taken.
✓ Branch 30 → 32 taken 1 time.
✗ Branch 33 → 34 not taken.
✓ Branch 33 → 35 taken 5 times.
|
5 | if (this->uidValidity(folderId) == 0 && !setUidValidity(folderId, uidValidity)) |
| 160 | ✗ | return false; | |
| 161 | 5 | const auto writeMutex = m_writeMutex; | |
| 162 | 5 | QMutexLocker publication(writeMutex.get()); | |
| 163 | 5 | auto batch = headers; | |
| 164 |
2/2✓ Branch 39 → 40 taken 5 times.
✓ Branch 40 → 41 taken 5 times.
|
5 | const bool stored = storeHeaderBatch(folderId, batch, [&] { |
| 165 |
1/1✓ Branch 2 → 3 taken 5 times.
|
5 | QSqlQuery epoch(m_db); |
| 166 |
1/1✓ Branch 6 → 7 taken 5 times.
|
5 | epoch.prepare(QStringLiteral("SELECT uidvalidity FROM folders WHERE id=?")); |
| 167 |
1/1✓ Branch 11 → 12 taken 5 times.
|
5 | epoch.addBindValue(folderId); |
| 168 |
5/8✓ Branch 13 → 14 taken 5 times.
✓ Branch 14 → 15 taken 5 times.
✗ Branch 14 → 17 not taken.
✓ Branch 15 → 16 taken 5 times.
✗ Branch 16 → 17 not taken.
✓ Branch 16 → 18 taken 5 times.
✗ Branch 19 → 20 not taken.
✓ Branch 19 → 36 taken 5 times.
|
5 | if (!epoch.exec() || !epoch.next()) { |
| 169 | ✗ | m_lastError = epoch.lastError().isValid() ? epoch.lastError().text() | |
| 170 | ✗ | : QStringLiteral("Folder is gone"); | |
| 171 | ✗ | return false; | |
| 172 | } | ||
| 173 |
4/4✓ Branch 36 → 37 taken 5 times.
✓ Branch 37 → 38 taken 5 times.
✓ Branch 39 → 40 taken 2 times.
✓ Branch 39 → 47 taken 3 times.
|
5 | if (epoch.value(0).toUInt() != uidValidity) { |
| 174 | 2 | m_lastError = QStringLiteral("Mailbox epoch changed before header persistence"); | |
| 175 | 2 | return false; | |
| 176 | } | ||
| 177 | 3 | return true; | |
| 178 | 5 | }); | |
| 179 |
2/2✓ Branch 42 → 43 taken 2 times.
✓ Branch 42 → 62 taken 3 times.
|
5 | if (!stored) { |
| 180 |
7/7✓ Branch 43 → 44 taken 2 times.
✓ Branch 47 → 48 taken 2 times.
✓ Branch 48 → 49 taken 2 times.
✓ Branch 50 → 51 taken 2 times.
✓ Branch 51 → 52 taken 2 times.
✓ Branch 60 → 45 taken 2 times.
✓ Branch 60 → 61 taken 2 times.
|
4 | qCWarning(lcCache) << "Dropped" << headers.size() << "headers for folder" << folderId |
| 181 |
5/5✓ Branch 52 → 53 taken 2 times.
✓ Branch 53 → 54 taken 2 times.
✓ Branch 54 → 55 taken 2 times.
✓ Branch 55 → 56 taken 2 times.
✓ Branch 56 → 57 taken 2 times.
|
2 | << "fetched under epoch" << uidValidity << ":" << m_lastError; |
| 182 | 2 | return false; | |
| 183 | } | ||
| 184 |
5/5✓ Branch 62 → 63 taken 3 times.
✓ Branch 63 → 64 taken 3 times.
✓ Branch 66 → 67 taken 3 times.
✓ Branch 69 → 65 taken 3 times.
✓ Branch 69 → 70 taken 3 times.
|
6 | for (const auto &header : batch) emit headerStateReplaced(folderId, header); |
| 185 | 3 | return true; | |
| 186 | 5 | } | |
| 187 | |||
| 188 | 31 | bool MailCache::storeStreamingHeaders( | |
| 189 | const QString &account, const QString &folder, qint64 folderId, | ||
| 190 | quint32 uidValidity, QList<MailHeader> &headers, | ||
| 191 | const std::function<QString(QList<MailHeader> &)> &prepare) { | ||
| 192 | 31 | const auto writeMutex = m_writeMutex; | |
| 193 | 31 | QMutexLocker publication(writeMutex.get()); | |
| 194 |
2/2✓ Branch 5 → 6 taken 31 times.
✓ Branch 6 → 7 taken 31 times.
|
62 | return storeHeaderBatch(folderId, headers, [&] { |
| 195 |
1/1✓ Branch 2 → 3 taken 30 times.
|
30 | QSqlQuery identity(m_db); |
| 196 |
1/1✓ Branch 6 → 7 taken 30 times.
|
30 | identity.prepare(QStringLiteral("SELECT 1 FROM folders WHERE id=? AND account=? " |
| 197 | "AND path=? AND uidvalidity=?")); | ||
| 198 |
2/2✓ Branch 11 → 12 taken 30 times.
✓ Branch 15 → 16 taken 30 times.
|
30 | identity.addBindValue(folderId); identity.addBindValue(account); |
| 199 |
2/2✓ Branch 19 → 20 taken 30 times.
✓ Branch 23 → 24 taken 30 times.
|
30 | identity.addBindValue(folder); identity.addBindValue(uidValidity); |
| 200 |
7/8✓ Branch 25 → 26 taken 30 times.
✓ Branch 26 → 27 taken 30 times.
✗ Branch 26 → 29 not taken.
✓ Branch 27 → 28 taken 30 times.
✓ Branch 28 → 29 taken 3 times.
✓ Branch 28 → 30 taken 27 times.
✓ Branch 31 → 32 taken 3 times.
✓ Branch 31 → 48 taken 27 times.
|
30 | if (!identity.exec() || !identity.next()) { |
| 201 |
3/8✓ Branch 32 → 33 taken 3 times.
✓ Branch 33 → 34 taken 3 times.
✗ Branch 34 → 35 not taken.
✓ Branch 34 → 37 taken 3 times.
✗ Branch 35 → 36 not taken.
✗ Branch 36 → 40 not taken.
✗ Branch 84 → 85 not taken.
✗ Branch 84 → 86 not taken.
|
12 | m_lastError = identity.lastError().isValid() ? identity.lastError().text() |
| 202 |
2/6✓ Branch 42 → 43 taken 3 times.
✗ Branch 42 → 44 not taken.
✗ Branch 44 → 45 not taken.
✓ Branch 44 → 46 taken 3 times.
✗ Branch 80 → 81 not taken.
✗ Branch 80 → 82 not taken.
|
6 | : QStringLiteral("Mailbox identity changed before header persistence"); |
| 203 | 3 | return false; | |
| 204 | } | ||
| 205 |
2/3✓ Branch 49 → 50 taken 27 times.
✗ Branch 49 → 54 not taken.
✓ Branch 50 → 51 taken 27 times.
|
27 | if (prepare) m_lastError = prepare(headers); |
| 206 | 27 | return m_lastError.isEmpty(); | |
| 207 | 92 | }); | |
| 208 | 31 | } | |
| 209 |