data/CollectedAddressStore.cpp
| Line | Branch | Exec | Source |
|---|---|---|---|
| 1 | #include "CollectedAddressStore.h" | ||
| 2 | |||
| 3 | #include "ContactIndex.h" | ||
| 4 | #include "ContactSqlValue.h" | ||
| 5 | |||
| 6 | #include <QLoggingCategory> | ||
| 7 | #include <QSet> | ||
| 8 | #include <QSqlError> | ||
| 9 | #include <QSqlQuery> | ||
| 10 | |||
| 11 |
4/7✓ Branch 2 → 3 taken 11 times.
✓ Branch 2 → 8 taken 112 times.
✓ Branch 4 → 5 taken 11 times.
✗ Branch 4 → 8 not taken.
✓ Branch 5 → 6 taken 11 times.
✗ Branch 10 → 11 not taken.
✗ Branch 10 → 12 not taken.
|
123 | Q_LOGGING_CATEGORY(lcContactCollect, "mailjd.contacts.collect") |
| 12 | |||
| 13 | 120 | bool CollectedAddressStore::recordSent(const QList<Recipient> &recipients, bool collect, const QDateTime &now) { | |
| 14 |
6/6✓ Branch 2 → 3 taken 120 times.
✓ Branch 3 → 4 taken 111 times.
✓ Branch 3 → 5 taken 9 times.
✓ Branch 5 → 6 taken 9 times.
✓ Branch 6 → 7 taken 120 times.
✓ Branch 7 → 8 taken 120 times.
|
120 | const QString stamp = (now.isValid() ? now : QDateTime::currentDateTimeUtc()).toUTC().toString(Qt::ISODate); |
| 15 | 120 | QSet<QString> seen; | |
| 16 | 120 | int counted = 0; | |
| 17 | 120 | int collected = 0; | |
| 18 | // S106-169: without the transaction nothing is written (the writes used | ||
| 19 | // to run one by one in autocommit and the call still reported failure). | ||
| 20 |
3/3✓ Branch 11 → 12 taken 120 times.
✓ Branch 12 → 13 taken 1 time.
✓ Branch 12 → 29 taken 119 times.
|
120 | if (!m_db.transaction()) { |
| 21 |
8/8✓ Branch 13 → 14 taken 1 time.
✓ Branch 17 → 18 taken 1 time.
✓ Branch 18 → 19 taken 1 time.
✓ Branch 19 → 20 taken 1 time.
✓ Branch 20 → 21 taken 1 time.
✓ Branch 21 → 22 taken 1 time.
✓ Branch 27 → 15 taken 1 time.
✓ Branch 27 → 28 taken 1 time.
|
2 | qCWarning(lcContactCollect) << "Recording sent recipients: transaction:" << m_db.lastError().text(); |
| 22 | 1 | return false; | |
| 23 | } | ||
| 24 | 119 | bool ok = true; | |
| 25 |
2/2✓ Branch 167 → 31 taken 362 times.
✓ Branch 167 → 168 taken 119 times.
|
481 | for (const Recipient &recipient : recipients) { |
| 26 |
1/1✓ Branch 32 → 33 taken 362 times.
|
362 | const QString key = ContactIndex::addressKey(recipient.address); |
| 27 |
7/9✓ Branch 34 → 35 taken 362 times.
✗ Branch 34 → 41 not taken.
✓ Branch 37 → 38 taken 362 times.
✓ Branch 38 → 39 taken 362 times.
✗ Branch 38 → 41 not taken.
✓ Branch 40 → 41 taken 1 time.
✓ Branch 40 → 42 taken 361 times.
✓ Branch 43 → 44 taken 1 time.
✓ Branch 43 → 45 taken 361 times.
|
362 | if (key.isEmpty() || !key.contains(QLatin1Char('@')) || seen.contains(key)) |
| 28 | 1 | continue; | |
| 29 |
1/1✓ Branch 45 → 46 taken 361 times.
|
361 | seen.insert(key); |
| 30 | 361 | bool known = false; | |
| 31 | { | ||
| 32 |
1/1✓ Branch 46 → 47 taken 361 times.
|
361 | QSqlQuery card(m_db); |
| 33 |
1/1✓ Branch 50 → 51 taken 361 times.
|
361 | card.prepare(QStringLiteral("SELECT 1 FROM card_addresses WHERE address_key = ? LIMIT 1")); |
| 34 |
2/2✓ Branch 55 → 56 taken 361 times.
✓ Branch 56 → 57 taken 361 times.
|
361 | card.addBindValue(sqlValue(key)); |
| 35 |
6/6✓ Branch 59 → 60 taken 361 times.
✓ Branch 60 → 61 taken 360 times.
✓ Branch 60 → 64 taken 1 time.
✓ Branch 61 → 62 taken 360 times.
✓ Branch 62 → 63 taken 200 times.
✓ Branch 62 → 64 taken 160 times.
|
361 | known = card.exec() && card.next(); |
| 36 | 361 | } | |
| 37 |
4/4✓ Branch 66 → 67 taken 161 times.
✓ Branch 66 → 69 taken 200 times.
✓ Branch 67 → 68 taken 2 times.
✓ Branch 67 → 69 taken 159 times.
|
361 | if (!known && !collect) |
| 38 | 2 | continue; | |
| 39 |
1/1✓ Branch 69 → 70 taken 359 times.
|
359 | QSqlQuery usage(m_db); |
| 40 |
1/1✓ Branch 73 → 74 taken 359 times.
|
359 | usage.prepare(QStringLiteral("INSERT INTO address_usage (address_key, use_count, last_used) VALUES (?, 1, ?) " |
| 41 | "ON CONFLICT(address_key) DO UPDATE SET use_count = use_count + 1, last_used = ?")); | ||
| 42 |
2/2✓ Branch 78 → 79 taken 359 times.
✓ Branch 79 → 80 taken 359 times.
|
359 | usage.addBindValue(sqlValue(key)); |
| 43 |
2/2✓ Branch 84 → 85 taken 359 times.
✓ Branch 85 → 86 taken 359 times.
|
359 | usage.addBindValue(sqlValue(stamp)); |
| 44 |
2/2✓ Branch 90 → 91 taken 359 times.
✓ Branch 91 → 92 taken 359 times.
|
359 | usage.addBindValue(sqlValue(stamp)); |
| 45 |
4/5✓ Branch 94 → 95 taken 359 times.
✓ Branch 95 → 96 taken 358 times.
✓ Branch 95 → 98 taken 1 time.
✓ Branch 96 → 97 taken 358 times.
✗ Branch 96 → 98 not taken.
|
359 | ok = usage.exec() && ok; |
| 46 | 359 | ++counted; | |
| 47 |
2/2✓ Branch 99 → 100 taken 200 times.
✓ Branch 99 → 101 taken 159 times.
|
359 | if (known) |
| 48 | 200 | continue; | |
| 49 |
1/1✓ Branch 101 → 102 taken 159 times.
|
159 | QSqlQuery insert(m_db); |
| 50 |
1/1✓ Branch 105 → 106 taken 159 times.
|
159 | insert.prepare(QStringLiteral( |
| 51 | "INSERT INTO collected_addresses (address_key, address, display_name, first_used, last_used) " | ||
| 52 | "VALUES (?, ?, ?, ?, ?) ON CONFLICT(address_key) DO UPDATE SET last_used = excluded.last_used, " | ||
| 53 | "display_name = CASE WHEN excluded.display_name <> '' THEN excluded.display_name ELSE display_name END")); | ||
| 54 |
2/2✓ Branch 110 → 111 taken 159 times.
✓ Branch 111 → 112 taken 159 times.
|
159 | insert.addBindValue(sqlValue(key)); |
| 55 |
3/3✓ Branch 115 → 116 taken 159 times.
✓ Branch 117 → 118 taken 159 times.
✓ Branch 118 → 119 taken 159 times.
|
159 | insert.addBindValue(sqlValue(recipient.address.trimmed())); |
| 56 |
6/7✓ Branch 123 → 124 taken 159 times.
✓ Branch 124 → 125 taken 159 times.
✗ Branch 126 → 127 not taken.
✓ Branch 126 → 128 taken 159 times.
✓ Branch 128 → 129 taken 159 times.
✓ Branch 130 → 131 taken 159 times.
✓ Branch 131 → 132 taken 159 times.
|
159 | insert.addBindValue(sqlValue(recipient.name.trimmed() == recipient.address.trimmed() ? QString() : recipient.name.trimmed())); |
| 57 |
2/2✓ Branch 139 → 140 taken 159 times.
✓ Branch 140 → 141 taken 159 times.
|
159 | insert.addBindValue(sqlValue(stamp)); |
| 58 |
2/2✓ Branch 145 → 146 taken 159 times.
✓ Branch 146 → 147 taken 159 times.
|
159 | insert.addBindValue(sqlValue(stamp)); |
| 59 |
4/5✓ Branch 149 → 150 taken 159 times.
✓ Branch 150 → 151 taken 158 times.
✓ Branch 150 → 153 taken 1 time.
✓ Branch 151 → 152 taken 158 times.
✗ Branch 151 → 153 not taken.
|
159 | ok = insert.exec() && ok; |
| 60 | 159 | ++collected; | |
| 61 | 562 | } | |
| 62 |
2/2✓ Branch 168 → 169 taken 1 time.
✓ Branch 168 → 181 taken 118 times.
|
119 | if (!ok) { |
| 63 |
1/1✓ Branch 169 → 170 taken 1 time.
|
1 | m_db.rollback(); |
| 64 |
5/5✓ Branch 170 → 171 taken 1 time.
✓ Branch 174 → 175 taken 1 time.
✓ Branch 175 → 176 taken 1 time.
✓ Branch 179 → 172 taken 1 time.
✓ Branch 179 → 180 taken 1 time.
|
2 | qCWarning(lcContactCollect) << "Recording sent recipients failed"; |
| 65 | 1 | return false; | |
| 66 | } | ||
| 67 |
1/1✓ Branch 181 → 182 taken 118 times.
|
118 | ok = m_db.commit(); |
| 68 | // Counts only: addresses are contact data (privacy rule 14). | ||
| 69 |
9/9✓ Branch 182 → 183 taken 118 times.
✓ Branch 186 → 187 taken 118 times.
✓ Branch 187 → 188 taken 118 times.
✓ Branch 188 → 189 taken 118 times.
✓ Branch 189 → 190 taken 118 times.
✓ Branch 190 → 191 taken 118 times.
✓ Branch 191 → 192 taken 118 times.
✓ Branch 195 → 184 taken 118 times.
✓ Branch 195 → 196 taken 118 times.
|
236 | qCInfo(lcContactCollect) << "Recorded" << counted << "recipients," << collected << "collected"; |
| 70 | 118 | return ok; | |
| 71 | 120 | } | |
| 72 | |||
| 73 | // Both deletes or neither (S106-169). | ||
| 74 | 5 | bool CollectedAddressStore::inTransaction(const std::function<bool()> &write) { | |
| 75 |
1/2✗ Branch 3 → 4 not taken.
✓ Branch 3 → 5 taken 5 times.
|
5 | if (!m_db.transaction()) |
| 76 | ✗ | return false; | |
| 77 |
3/6✓ Branch 6 → 7 taken 5 times.
✗ Branch 6 → 10 not taken.
✓ Branch 8 → 9 taken 5 times.
✗ Branch 8 → 10 not taken.
✓ Branch 11 → 12 taken 5 times.
✗ Branch 11 → 13 not taken.
|
5 | if (write() && m_db.commit()) |
| 78 | 5 | return true; | |
| 79 | ✗ | m_db.rollback(); | |
| 80 | ✗ | return false; | |
| 81 | } | ||
| 82 | |||
| 83 | 3 | bool CollectedAddressStore::forgetAll() { | |
| 84 |
1/1✓ Branch 3 → 4 taken 3 times.
|
3 | const bool ok = inTransaction([this] { |
| 85 |
1/1✓ Branch 2 → 3 taken 3 times.
|
3 | QSqlQuery collected(m_db); |
| 86 |
1/1✓ Branch 3 → 4 taken 3 times.
|
3 | QSqlQuery usage(m_db); |
| 87 |
3/9✓ Branch 7 → 8 taken 3 times.
✓ Branch 8 → 9 taken 3 times.
✗ Branch 8 → 15 not taken.
✓ Branch 22 → 23 taken 3 times.
✗ Branch 22 → 24 not taken.
✗ Branch 36 → 37 not taken.
✗ Branch 36 → 38 not taken.
✗ Branch 40 → 41 not taken.
✗ Branch 40 → 42 not taken.
|
12 | return collected.exec(QStringLiteral("DELETE FROM collected_addresses")) && |
| 88 |
4/11✓ Branch 12 → 13 taken 3 times.
✓ Branch 13 → 14 taken 3 times.
✗ Branch 13 → 15 not taken.
✓ Branch 18 → 19 taken 3 times.
✗ Branch 18 → 20 not taken.
✓ Branch 20 → 21 taken 3 times.
✗ Branch 20 → 22 not taken.
✗ Branch 28 → 29 not taken.
✗ Branch 28 → 30 not taken.
✗ Branch 32 → 33 not taken.
✗ Branch 32 → 34 not taken.
|
6 | usage.exec(QStringLiteral("DELETE FROM address_usage WHERE address_key NOT IN " |
| 89 |
1/2✓ Branch 16 → 17 taken 3 times.
✗ Branch 16 → 18 not taken.
|
6 | "(SELECT address_key FROM card_addresses)")); |
| 90 | 3 | }); | |
| 91 |
6/6✓ Branch 5 → 6 taken 3 times.
✓ Branch 9 → 10 taken 3 times.
✓ Branch 10 → 11 taken 3 times.
✓ Branch 11 → 12 taken 3 times.
✓ Branch 15 → 7 taken 3 times.
✓ Branch 15 → 16 taken 3 times.
|
6 | qCInfo(lcContactCollect) << "Forgot collected addresses:" << ok; |
| 92 | 3 | return ok; | |
| 93 | } | ||
| 94 | |||
| 95 | 2 | bool CollectedAddressStore::forget(const QString &address) { | |
| 96 |
1/1✓ Branch 2 → 3 taken 2 times.
|
2 | const QString key = ContactIndex::addressKey(address); |
| 97 |
1/1✓ Branch 4 → 5 taken 2 times.
|
4 | return inTransaction([this, &key] { |
| 98 |
1/1✓ Branch 2 → 3 taken 2 times.
|
2 | QSqlQuery collected(m_db); |
| 99 |
1/1✓ Branch 6 → 7 taken 2 times.
|
2 | collected.prepare(QStringLiteral("DELETE FROM collected_addresses WHERE address_key = ?")); |
| 100 |
2/2✓ Branch 11 → 12 taken 2 times.
✓ Branch 12 → 13 taken 2 times.
|
2 | collected.addBindValue(sqlValue(key)); |
| 101 |
1/1✓ Branch 15 → 16 taken 2 times.
|
2 | QSqlQuery usage(m_db); |
| 102 |
1/1✓ Branch 19 → 20 taken 2 times.
|
2 | usage.prepare(QStringLiteral("DELETE FROM address_usage WHERE address_key = ? AND address_key NOT IN " |
| 103 | "(SELECT address_key FROM card_addresses)")); | ||
| 104 |
2/2✓ Branch 24 → 25 taken 2 times.
✓ Branch 25 → 26 taken 2 times.
|
2 | usage.addBindValue(sqlValue(key)); |
| 105 |
4/6✓ Branch 28 → 29 taken 2 times.
✓ Branch 29 → 30 taken 2 times.
✗ Branch 29 → 33 not taken.
✓ Branch 30 → 31 taken 2 times.
✓ Branch 31 → 32 taken 2 times.
✗ Branch 31 → 33 not taken.
|
4 | return collected.exec() && usage.exec(); |
| 106 | 6 | }); | |
| 107 | 2 | } | |
| 108 | |||
| 109 | 5 | int CollectedAddressStore::collectedCount() const { | |
| 110 |
1/1✓ Branch 2 → 3 taken 5 times.
|
5 | QSqlQuery q(m_db); |
| 111 |
2/8✓ Branch 14 → 15 taken 5 times.
✗ Branch 14 → 16 not taken.
✓ Branch 16 → 17 taken 5 times.
✗ Branch 16 → 22 not taken.
✗ Branch 26 → 27 not taken.
✗ Branch 26 → 28 not taken.
✗ Branch 30 → 31 not taken.
✗ Branch 30 → 32 not taken.
|
10 | if (q.exec(QStringLiteral("SELECT COUNT(*) FROM collected_addresses WHERE address_key NOT IN " |
| 112 |
3/5✓ Branch 6 → 7 taken 5 times.
✓ Branch 7 → 8 taken 5 times.
✗ Branch 7 → 11 not taken.
✓ Branch 12 → 13 taken 5 times.
✗ Branch 12 → 14 not taken.
|
15 | "(SELECT address_key FROM card_addresses)")) && |
| 113 |
2/3✓ Branch 8 → 9 taken 5 times.
✓ Branch 9 → 10 taken 5 times.
✗ Branch 9 → 11 not taken.
|
5 | q.next()) |
| 114 |
2/2✓ Branch 17 → 18 taken 5 times.
✓ Branch 18 → 19 taken 5 times.
|
5 | return q.value(0).toInt(); |
| 115 | ✗ | return 0; | |
| 116 | 5 | } | |
| 117 |