Mercurial > dedupe
comparison SqliteDBLink.cpp @ 94:93981e675d67
Full support for bulkcommits.
| author | Tom Fredrik Blenning Klaussen <bfg@bfgconsult.no> |
|---|---|
| date | Tue, 22 Oct 2013 14:11:50 +0200 |
| parents | 308a718812ba |
| children | 7c935d3d5b74 |
comparison
equal
deleted
inserted
replaced
| 93:308a718812ba | 94:93981e675d67 |
|---|---|
| 7 #include <QtSql/QSqlQuery> | 7 #include <QtSql/QSqlQuery> |
| 8 #include <QtSql/QSqlRecord> | 8 #include <QtSql/QSqlRecord> |
| 9 | 9 |
| 10 #include "Exception/SQLException.hpp" | 10 #include "Exception/SQLException.hpp" |
| 11 #include "Exception/IOException.hpp" | 11 #include "Exception/IOException.hpp" |
| 12 | |
| 13 #include <cassert> | |
| 12 | 14 |
| 13 const QString SqliteDBLink::connectionName("SqliteDBLink"); | 15 const QString SqliteDBLink::connectionName("SqliteDBLink"); |
| 14 | 16 |
| 15 | 17 |
| 16 SqliteDBLink::SqliteDBLink(const QString& dbPath) | 18 SqliteDBLink::SqliteDBLink(const QString& dbPath) |
| 43 | 45 |
| 44 preparedTryAddQuery = new QSqlQuery(db); | 46 preparedTryAddQuery = new QSqlQuery(db); |
| 45 preparedTryAddQuery->prepare("INSERT INTO files (path, size, mtime, checksum)" | 47 preparedTryAddQuery->prepare("INSERT INTO files (path, size, mtime, checksum)" |
| 46 " VALUES (:path, :size, :mtime, :checksum)"); | 48 " VALUES (:path, :size, :mtime, :checksum)"); |
| 47 | 49 |
| 50 preparedUpdateQuery = new QSqlQuery(db); | |
| 51 preparedUpdateQuery->prepare( | |
| 52 "UPDATE files " | |
| 53 "SET size=:size, mtime=:mtime, checksum=:checksum " | |
| 54 "WHERE path=:path"); | |
| 48 } | 55 } |
| 49 | 56 |
| 50 SqliteDBLink::~SqliteDBLink() | 57 SqliteDBLink::~SqliteDBLink() |
| 51 { | 58 { |
| 52 delete preparedSizePrefixQuery; | 59 delete preparedSizePrefixQuery; |
| 53 delete preparedSizeQuery; | 60 delete preparedSizeQuery; |
| 61 delete preparedTryAddQuery; | |
| 62 delete preparedUpdateQuery; | |
| 54 db.close(); | 63 db.close(); |
| 55 } | 64 } |
| 56 | 65 |
| 57 bool SqliteDBLink::exists(const QString& path) | 66 bool SqliteDBLink::exists(const QString& path) |
| 58 { | 67 { |
| 116 { | 125 { |
| 117 if (lazy) { | 126 if (lazy) { |
| 118 operations.push_back(Operation(dbinfo, Update)); | 127 operations.push_back(Operation(dbinfo, Update)); |
| 119 } | 128 } |
| 120 else { | 129 else { |
| 121 QSqlQuery query(db); | 130 preparedUpdateQuery->bindValue(":path", dbinfo.path()); |
| 122 query.prepare("UPDATE files " | 131 preparedUpdateQuery->bindValue(":size", dbinfo.size()); |
| 123 "SET size=:size, mtime=:mtime, checksum=:checksum " | 132 preparedUpdateQuery->bindValue(":mtime", dbinfo.mtime()); |
| 124 "WHERE path=:path"); | 133 preparedUpdateQuery->bindValue(":checksum", dbinfo.checksum()); |
| 125 query.bindValue(":path", dbinfo.path()); | 134 if (!preparedUpdateQuery->exec()) { |
| 126 query.bindValue(":size", dbinfo.size()); | 135 throw SQLException(*preparedUpdateQuery); |
| 127 query.bindValue(":mtime", dbinfo.mtime()); | |
| 128 query.bindValue(":checksum", dbinfo.checksum()); | |
| 129 if (!query.exec()) { | |
| 130 throw SQLException(query); | |
| 131 } | 136 } |
| 132 } | 137 } |
| 133 } | 138 } |
| 134 | 139 |
| 135 void SqliteDBLink::addFile(const DBInfo& dbinfo, bool lazy) | 140 void SqliteDBLink::addFile(const DBInfo& dbinfo, bool lazy) |
| 252 } | 257 } |
| 253 | 258 |
| 254 return values; | 259 return values; |
| 255 } | 260 } |
| 256 | 261 |
| 262 void SqliteDBLink::executeOperation(QVariantList& paths, | |
| 263 QVariantList& sizes, | |
| 264 QVariantList& mtimes, | |
| 265 QVariantList& checksums, | |
| 266 OperationType operation) | |
| 267 { | |
| 268 assert(paths.size() == sizes.size()); | |
| 269 assert(paths.size() == mtimes.size()); | |
| 270 assert(paths.size() == checksums.size()); | |
| 271 QSqlQuery* query; | |
| 272 switch (operation) { | |
| 273 case Add: | |
| 274 query = preparedTryAddQuery; | |
| 275 break; | |
| 276 case Update: | |
| 277 query = preparedUpdateQuery; | |
| 278 break; | |
| 279 case None: | |
| 280 assert(paths.size() == 0); | |
| 281 return; | |
| 282 } | |
| 283 query->bindValue("path", paths); | |
| 284 query->bindValue("size", sizes); | |
| 285 query->bindValue("mtime", mtimes); | |
| 286 query->bindValue("checksum", checksums); | |
| 287 | |
| 288 if (!query->execBatch()) | |
| 289 throw SQLException(*query); | |
| 290 | |
| 291 paths.clear(); | |
| 292 sizes.clear(); | |
| 293 mtimes.clear(); | |
| 294 checksums.clear(); | |
| 295 } | |
| 296 | |
| 257 bool SqliteDBLink::commit() | 297 bool SqliteDBLink::commit() |
| 258 { | 298 { |
| 259 int n = 0; | 299 int n = 0; |
| 260 int max = operations.size(); | 300 OperationType last = None; |
| 301 QVariantList paths, sizes, mtimes, hashes; | |
| 302 | |
| 261 foreach(const Operation& operation, operations) { | 303 foreach(const Operation& operation, operations) { |
| 304 if (operation.second != last) { | |
| 305 executeOperation(paths, sizes, mtimes, hashes, last); | |
| 306 } | |
| 307 | |
| 262 switch (operation.second) { | 308 switch (operation.second) { |
| 263 case Add: | 309 case Add: |
| 264 addFile(operation.first); | 310 case Update: |
| 311 paths.push_back(operation.first.path()); | |
| 312 sizes.push_back(operation.first.size()); | |
| 313 mtimes.push_back(operation.first.mtime()); | |
| 314 hashes.push_back(operation.first.checksum()); | |
| 315 case None: | |
| 265 break; | 316 break; |
| 266 case Update: | 317 } |
| 267 updateFile(operation.first); | 318 last = operation.second; |
| 268 } | 319 } |
| 320 if (last != None) { | |
| 321 executeOperation(paths, sizes, mtimes, hashes, last); | |
| 322 } | |
| 323 | |
| 324 QSqlQuery whatToUpdate(db); | |
| 325 whatToUpdate.prepare("SELECT path FROM files WHERE checksum is NULL AND size in (SELECT size FROM files WHERE size <> 0 GROUP BY size HAVING count(*) > 1 ORDER BY SIZE) ORDER BY size"); | |
| 326 | |
| 327 if (!whatToUpdate.exec()) { | |
| 328 throw SQLException(whatToUpdate); | |
| 329 } | |
| 330 | |
| 331 int pathIndex = whatToUpdate.record().indexOf("path"); | |
| 332 QStringList updatePaths; | |
| 333 while (whatToUpdate.next()) { | |
| 334 updatePaths << whatToUpdate.value(pathIndex).toString(); | |
| 335 } | |
| 336 int max = updatePaths.size(); | |
| 337 QSqlQuery updateChecksum(db); | |
| 338 updateChecksum.prepare("UPDATE files " | |
| 339 "SET checksum=:checksum " | |
| 340 "WHERE path=:path"); | |
| 341 | |
| 342 foreach (const QString& path, updatePaths) { | |
| 343 QByteArray ohash = computeHash(path); | |
| 269 emit progressUpdate(++n, max); | 344 emit progressUpdate(++n, max); |
| 345 updateChecksum.bindValue("checksum", ohash); | |
| 346 updateChecksum.bindValue("path", path); | |
| 347 if (!updateChecksum.exec()) | |
| 348 throw SQLException(updateChecksum); | |
| 349 | |
| 270 } | 350 } |
| 271 return true; | 351 return true; |
| 272 } | 352 } |
