~ubuntu-branches/ubuntu/trusty/digikam/trusty

« back to all changes in this revision

Viewing changes to core/libs/database/schemaupdater.cpp

  • Committer: Package Import Robot
  • Author(s): Mark Purcell
  • Date: 2012-09-27 21:41:30 UTC
  • mfrom: (1.2.43)
  • mto: This revision was merged to the branch mainline in revision 86.
  • Revision ID: package-import@ubuntu.com-20120927214130-i8v3ufr21nesp29i
Tags: 4:3.0.0~beta1a-1
* New upstream release

* Fix "wrongly conflicts phonon-backend-vlc" dropped (Closes: #688142)
* debian/watch include download.kde.org

* digikam 3.0.0 uses features from unreleased kdegraphics >=4.10 & ships 
a private version of the kdegraphics libs - this is not the Debian way :-(
* Unsatisfactory Conflicts: libkipi8, libkexiv2-10, libkdcraw20, libksane0
* Suspend digikam-dbg >130Mb

Show diffs side-by-side

added added

removed removed

Lines of Context:
6
6
 * Date        : 2007-04-16
7
7
 * Description : Schema update
8
8
 *
9
 
 * Copyright (C) 2007-2009 by Marcel Wiesweg <marcel dot wiesweg at gmx dot de>
 
9
 * Copyright (C) 2007-2012 by Marcel Wiesweg <marcel dot wiesweg at gmx dot de>
10
10
 *
11
11
 * This program is free software; you can redistribute it
12
12
 * and/or modify it under the terms of the GNU General
60
60
 
61
61
int SchemaUpdater::schemaVersion()
62
62
{
63
 
    return 6;
 
63
    return 7;
64
64
}
65
65
 
66
66
int SchemaUpdater::filterSettingsVersion()
67
67
{
68
 
    return 3;
 
68
    return 4;
69
69
}
70
70
 
71
71
int SchemaUpdater::uniqueHashVersion()
78
78
    return DatabaseAccess().db()->getUniqueHashVersion() >= uniqueHashVersion();
79
79
}
80
80
 
 
81
// --------------------------------------------------------------------------------------
 
82
 
 
83
class SchemaUpdater::Private
 
84
{
 
85
 
 
86
public:
 
87
 
 
88
    Private()
 
89
    {
 
90
        setError = false;
 
91
        backend  = 0;
 
92
        albumDB  = 0;
 
93
        access   = 0;
 
94
        observer = 0;
 
95
    }
 
96
 
 
97
    bool                    setError;
 
98
 
 
99
    QVariant                currentVersion;
 
100
    QVariant                currentRequiredVersion;
 
101
 
 
102
    DatabaseBackend*        backend;
 
103
    AlbumDB*                albumDB;
 
104
    DatabaseParameters      parameters;
 
105
 
 
106
    // legacy
 
107
    DatabaseAccess*         access;
 
108
 
 
109
    QString                 lastErrorMessage;
 
110
    InitializationObserver* observer;
 
111
};
 
112
 
 
113
SchemaUpdater::SchemaUpdater(AlbumDB* const albumDB, DatabaseBackend* const backend, DatabaseParameters parameters)
 
114
    : d(new Private)
 
115
{
 
116
    d->backend    = backend;
 
117
    d->albumDB    = albumDB;
 
118
    d->parameters = parameters;
 
119
 
 
120
}
 
121
 
 
122
SchemaUpdater::~SchemaUpdater()
 
123
{
 
124
    delete d;
 
125
}
 
126
 
 
127
void SchemaUpdater::setDatabaseAccess(DatabaseAccess* const access)
 
128
{
 
129
    d->access = access;
 
130
}
 
131
 
81
132
const QString SchemaUpdater::getLastErrorMessage()
82
133
{
83
 
    return m_LastErrorMessage;
84
 
}
85
 
 
86
 
void SchemaUpdater::setDatabaseAccess(DatabaseAccess* access)
87
 
{
88
 
    m_access=access;
89
 
}
90
 
 
91
 
SchemaUpdater::SchemaUpdater(AlbumDB* albumDB, DatabaseBackend* backend, DatabaseParameters parameters)
92
 
{
93
 
    m_Backend         = backend;
94
 
    m_AlbumDB         = albumDB;
95
 
    m_Parameters      = parameters;
96
 
    m_observer        = 0;
97
 
    m_setError        = false;
 
134
    return d->lastErrorMessage;
98
135
}
99
136
 
100
137
bool SchemaUpdater::update()
103
140
    bool success = startUpdates();
104
141
 
105
142
    // cancelled?
106
 
    if (m_observer && !m_observer->continueQuery())
 
143
    if (d->observer && !d->observer->continueQuery())
107
144
    {
108
145
        return false;
109
146
    }
118
155
 
119
156
    updateFilterSettings();
120
157
 
121
 
    if (m_observer)
 
158
    if (d->observer)
122
159
    {
123
 
        m_observer->finishedSchemaUpdate(InitializationObserver::UpdateSuccess);
 
160
        d->observer->finishedSchemaUpdate(InitializationObserver::UpdateSuccess);
124
161
    }
125
162
 
126
163
    return success;
128
165
 
129
166
void SchemaUpdater::setVersionSettings()
130
167
{
131
 
    if (m_currentVersion.isValid())
 
168
    if (d->currentVersion.isValid())
132
169
    {
133
 
        m_AlbumDB->setSetting("DBVersion", QString::number(m_currentVersion.toInt()));
 
170
        d->albumDB->setSetting("DBVersion", QString::number(d->currentVersion.toInt()));
134
171
    }
135
172
 
136
 
    if (m_currentRequiredVersion.isValid())
 
173
    if (d->currentRequiredVersion.isValid())
137
174
    {
138
 
        m_AlbumDB->setSetting("DBVersionRequired", QString::number(m_currentRequiredVersion.toInt()));
 
175
        d->albumDB->setSetting("DBVersionRequired", QString::number(d->currentRequiredVersion.toInt()));
139
176
    }
140
177
}
141
178
 
153
190
 
154
191
void SchemaUpdater::readVersionSettings()
155
192
{
156
 
    m_currentVersion         = safeToVariant(m_AlbumDB->getSetting("DBVersion"));
157
 
    m_currentRequiredVersion = safeToVariant(m_AlbumDB->getSetting("DBVersionRequired"));
 
193
    d->currentVersion         = safeToVariant(d->albumDB->getSetting("DBVersion"));
 
194
    d->currentRequiredVersion = safeToVariant(d->albumDB->getSetting("DBVersionRequired"));
158
195
}
159
196
 
160
 
void SchemaUpdater::setObserver(InitializationObserver* observer)
 
197
void SchemaUpdater::setObserver(InitializationObserver* const observer)
161
198
{
162
 
    m_observer = observer;
 
199
    d->observer = observer;
163
200
}
164
201
 
165
202
bool SchemaUpdater::startUpdates()
166
203
{
167
 
    if (!m_Parameters.isSQLite())
 
204
    if (!d->parameters.isSQLite())
168
205
    {
169
206
        // Do we have sufficient privileges
170
207
        QStringList insufficientRights;
171
 
        DatabasePrivilegesChecker checker(m_Parameters);
 
208
        DatabasePrivilegesChecker checker(d->parameters);
172
209
 
173
210
        if (!checker.checkPrivileges(insufficientRights))
174
211
        {
180
217
                                insufficientRights.join(",\n")
181
218
                            );
182
219
 
183
 
            m_LastErrorMessage=errorMsg;
 
220
            d->lastErrorMessage=errorMsg;
184
221
 
185
 
            if (m_observer)
 
222
            if (d->observer)
186
223
            {
187
 
                m_observer->error(errorMsg);
188
 
                m_observer->finishedSchemaUpdate(InitializationObserver::UpdateErrorMustAbort);
 
224
                d->observer->error(errorMsg);
 
225
                d->observer->finishedSchemaUpdate(InitializationObserver::UpdateErrorMustAbort);
189
226
            }
190
227
 
191
228
            return false;
193
230
    }
194
231
 
195
232
    // First step: do we have an empty database?
196
 
    QStringList tables = m_Backend->tables();
 
233
    QStringList tables = d->backend->tables();
197
234
 
198
235
    if (tables.contains("Albums", Qt::CaseInsensitive))
199
236
    {
200
237
        // Find out schema version of db file
201
238
        readVersionSettings();
202
 
        kDebug() << "Have a database structure version " << m_currentVersion.toInt();
 
239
        kDebug() << "Have a database structure version " << d->currentVersion.toInt();
203
240
 
204
241
        // We absolutely require the DBVersion setting
205
 
        if (!m_currentVersion.isValid())
 
242
        if (!d->currentVersion.isValid())
206
243
        {
207
244
            // Something is damaged. Give up.
208
245
            kError() << "DBVersion not available! Giving up schema upgrading.";
212
249
                                   "The current database schema version cannot be verified. "
213
250
                                   "Try to start with an empty database. "
214
251
                               );
215
 
            m_LastErrorMessage=errorMsg;
 
252
            d->lastErrorMessage=errorMsg;
216
253
 
217
 
            if (m_observer)
 
254
            if (d->observer)
218
255
            {
219
 
                m_observer->error(errorMsg);
220
 
                m_observer->finishedSchemaUpdate(InitializationObserver::UpdateErrorMustAbort);
 
256
                d->observer->error(errorMsg);
 
257
                d->observer->finishedSchemaUpdate(InitializationObserver::UpdateErrorMustAbort);
221
258
            }
222
259
 
223
260
            return false;
225
262
 
226
263
        // current version describes the current state of the schema in the db,
227
264
        // schemaVersion is the version required by the program.
228
 
        if (m_currentVersion.toInt() > schemaVersion())
 
265
        if (d->currentVersion.toInt() > schemaVersion())
229
266
        {
230
267
            // trying to open a database with a more advanced than this SchemaUpdater supports
231
 
            if (m_currentRequiredVersion.isValid() && m_currentRequiredVersion.toInt() <= schemaVersion())
 
268
            if (d->currentRequiredVersion.isValid() && d->currentRequiredVersion.toInt() <= schemaVersion())
232
269
            {
233
270
                // version required may be less than current version
234
271
                return true;
241
278
                                       "(This means this digiKam version is too old, or the database format is too recent.) "
242
279
                                       "Please use the more recent version of digiKam that you used before. "
243
280
                                   );
244
 
                m_LastErrorMessage=errorMsg;
 
281
                d->lastErrorMessage=errorMsg;
245
282
 
246
 
                if (m_observer)
 
283
                if (d->observer)
247
284
                {
248
 
                    m_observer->error(errorMsg);
249
 
                    m_observer->finishedSchemaUpdate(InitializationObserver::UpdateErrorMustAbort);
 
285
                    d->observer->error(errorMsg);
 
286
                    d->observer->finishedSchemaUpdate(InitializationObserver::UpdateErrorMustAbort);
250
287
                }
251
288
 
252
289
                return false;
274
311
        //  no schema changes.
275
312
        // Version 4 writes "4", and from now on version x writes "x".
276
313
        // Version 5 includes the schema changes from 0.9 to 0.10
 
314
        // Version 6 brought new tables for history and ImageTagProperties, with version 2.0
 
315
        // Version 7 brought the VideoMetadata table with 3.0
277
316
 
278
 
        if (m_Parameters.isSQLite())
 
317
        if (d->parameters.isSQLite())
279
318
        {
280
 
            QFileInfo currentDBFile(m_Parameters.databaseName);
 
319
            QFileInfo currentDBFile(d->parameters.databaseName);
281
320
            QFileInfo digikam3DB(currentDBFile.dir(), "digikam3.db");
282
321
            QFileInfo digikamDB(currentDBFile.dir(), "digikam.db");
283
322
 
288
327
                    return false;
289
328
                }
290
329
 
291
 
                // m_currentVersion is now 4;
 
330
                // d->currentVersion is now 4;
292
331
                return makeUpdates();
293
332
            }
294
333
            else if (digikamDB.exists())
298
337
                    return false;
299
338
                }
300
339
 
301
 
                // m_currentVersion is now 4;
 
340
                // d->currentVersion is now 4;
302
341
                return makeUpdates();
303
342
            }
304
343
 
308
347
        // No legacy handling: start with a fresh db
309
348
        if (!createDatabase() || !createFilterSettings())
310
349
        {
311
 
            QString errorMsg = i18n("Failed to create tables in database.\n ")
312
 
                               + m_Backend->lastError();
313
 
            m_LastErrorMessage=errorMsg;
 
350
            QString errorMsg   = i18n("Failed to create tables in database.\n ") + d->backend->lastError();
 
351
            d->lastErrorMessage = errorMsg;
314
352
 
315
 
            if (m_observer)
 
353
            if (d->observer)
316
354
            {
317
 
                m_observer->error(errorMsg);
318
 
                m_observer->finishedSchemaUpdate(InitializationObserver::UpdateErrorMustAbort);
 
355
                d->observer->error(errorMsg);
 
356
                d->observer->finishedSchemaUpdate(InitializationObserver::UpdateErrorMustAbort);
319
357
            }
320
358
 
321
359
            return false;
327
365
 
328
366
bool SchemaUpdater::beginWrapSchemaUpdateStep()
329
367
{
330
 
    if (!m_Backend->beginTransaction())
 
368
    if (!d->backend->beginTransaction())
331
369
    {
332
 
        QFileInfo currentDBFile(m_Parameters.databaseName);
 
370
        QFileInfo currentDBFile(d->parameters.databaseName);
333
371
        QString errorMsg = i18n("Failed to open a database transaction on your database file \"%1\". "
334
372
                                "This is unusual. Please check that you can access the file and no "
335
373
                                "other process has currently locked the file. "
336
374
                                "If the problem persists you can get help from the digikam-devel@kde.org "
337
375
                                "mailing list. As well, please have a look at what digiKam prints on the console. ",
338
376
                                currentDBFile.filePath());
339
 
        m_observer->error(errorMsg);
340
 
        m_observer->finishedSchemaUpdate(InitializationObserver::UpdateErrorMustAbort);
 
377
        d->observer->error(errorMsg);
 
378
        d->observer->finishedSchemaUpdate(InitializationObserver::UpdateErrorMustAbort);
341
379
        return false;
342
380
    }
343
381
 
348
386
{
349
387
    if (!stepOperationSuccess)
350
388
    {
351
 
        m_Backend->rollbackTransaction();
 
389
        d->backend->rollbackTransaction();
352
390
 
353
 
        if (m_observer)
 
391
        if (d->observer)
354
392
        {
355
393
            // error or cancelled?
356
 
            if (!m_observer->continueQuery())
 
394
            if (!d->observer->continueQuery())
357
395
            {
358
396
                kDebug() << "Schema update cancelled by user";
359
397
            }
360
 
            else if (!m_setError)
 
398
            else if (!d->setError)
361
399
            {
362
 
                m_observer->error(errorMsg);
363
 
                m_observer->finishedSchemaUpdate(InitializationObserver::UpdateErrorMustAbort);
 
400
                d->observer->error(errorMsg);
 
401
                d->observer->finishedSchemaUpdate(InitializationObserver::UpdateErrorMustAbort);
364
402
            }
365
403
        }
366
404
 
368
406
    }
369
407
 
370
408
    kDebug() << "Success updating to v5";
371
 
    m_Backend->commitTransaction();
 
409
    d->backend->commitTransaction();
372
410
    return true;
373
411
}
374
412
 
375
413
bool SchemaUpdater::makeUpdates()
376
414
{
377
 
    kDebug() << "makeUpdates " << m_currentVersion.toInt() << " to " << schemaVersion();
 
415
    kDebug() << "makeUpdates " << d->currentVersion.toInt() << " to " << schemaVersion();
378
416
 
379
 
    if (m_currentVersion.toInt() < schemaVersion())
 
417
    if (d->currentVersion.toInt() < schemaVersion())
380
418
    {
381
 
        if (m_currentVersion.toInt() < 5)
 
419
        if (d->currentVersion.toInt() < 5)
382
420
        {
383
421
            if (!beginWrapSchemaUpdateStep())
384
422
            {
386
424
            }
387
425
 
388
426
            // v4 was always SQLite
389
 
            QFileInfo currentDBFile(m_Parameters.databaseName);
 
427
            QFileInfo currentDBFile(d->parameters.databaseName);
390
428
            QString errorMsg = i18n("The schema updating process from version 4 to 6 failed, "
391
429
                                    "caused by an error that we did not expect. "
392
430
                                    "You can try to discard your old database and start with an empty one. "
407
445
            setLegacySettingEntries();
408
446
        }
409
447
 
410
 
        if (m_currentVersion.toInt() < 6)
 
448
        // Incremental updates, starting from version 5
 
449
        for (int v = d->currentVersion.toInt(); v < schemaVersion(); v++)
411
450
        {
412
 
            //updateV5toV6();
 
451
            int targetVersion = v + 1;
 
452
 
413
453
            if (!beginWrapSchemaUpdateStep())
414
454
            {
415
455
                return false;
416
456
            }
417
457
 
418
 
            QString errorMsg = i18n("Failed to update the database schema from version 5 to version 6. "
 
458
            QString errorMsg = i18n("Failed to update the database schema from version %1 to version %2. "
419
459
                                    "Please read the error messages printed on the console and "
420
 
                                    "report this error as a bug at bugs.kde.org. ");
 
460
                                    "report this error as a bug at bugs.kde.org. ",
 
461
                                    d->currentVersion.toInt(), targetVersion);
421
462
 
422
 
            if (!endWrapSchemaUpdateStep(updateV5toV6(), errorMsg))
 
463
            if (!endWrapSchemaUpdateStep(updateToVersion(targetVersion), errorMsg))
423
464
            {
424
465
                return false;
425
466
            }
426
467
 
427
 
            kDebug() << "Success updating to v6";
 
468
            kDebug() << "Success updating to v" << d->currentVersion;
428
469
        }
429
470
 
430
471
        // add future updates here
433
474
    return true;
434
475
}
435
476
 
436
 
void SchemaUpdater::defaultFilterSettings(QStringList& defaultImageFilter,
437
 
        QStringList& defaultVideoFilter,
438
 
        QStringList& defaultAudioFilter)
 
477
void SchemaUpdater::defaultFilterSettings(QStringList& defaultImageFilter, QStringList& defaultVideoFilter,
 
478
                                          QStringList& defaultAudioFilter)
439
479
{
440
480
    //NOTE for updating:
441
481
    //When changing anything here, just increment filterSettingsVersion() so that the changes take effect
449
489
 
450
490
    defaultImageFilter << KDcrawIface::KDcraw::rawFilesList();
451
491
 
452
 
    defaultVideoFilter << "mpeg" << "mpg" << "mpo" << "mpe"     // MPEG
453
 
                       << "avi"  << "mov" << "wmf" << "asf" << "mp4" << "3gp" << "wmv";
 
492
    defaultVideoFilter << "mpeg" << "mpg" << "mpo" << "mpe"                              // MPEG
 
493
                       << "avi" << "divx"                                                // RIFF
 
494
                       << "wmv" << "wmf" << "asf"                                        // ASF
 
495
                       << "mp4" << "3gp" << "mov"  << "3g2" << "m4v" << "m2v"            // QuickTime
 
496
                       << "mkv" << "webm";                                               // Matroska
454
497
 
455
498
    defaultAudioFilter << "ogg" << "mp3" << "wma" << "wav";
456
499
}
460
503
    QStringList defaultImageFilter, defaultVideoFilter, defaultAudioFilter;
461
504
    defaultFilterSettings(defaultImageFilter, defaultVideoFilter, defaultAudioFilter);
462
505
 
463
 
    m_AlbumDB->setFilterSettings(defaultImageFilter, defaultVideoFilter, defaultAudioFilter);
464
 
    m_AlbumDB->setSetting("FilterSettingsVersion", QString::number(filterSettingsVersion()));
465
 
    m_AlbumDB->setSetting("DcrawFilterSettingsVersion", QString::number(KDcrawIface::KDcraw::rawFilesVersion()));
 
506
    d->albumDB->setFilterSettings(defaultImageFilter, defaultVideoFilter, defaultAudioFilter);
 
507
    d->albumDB->setSetting("FilterSettingsVersion", QString::number(filterSettingsVersion()));
 
508
    d->albumDB->setSetting("DcrawFilterSettingsVersion", QString::number(KDcrawIface::KDcraw::rawFilesVersion()));
466
509
 
467
510
    return true;
468
511
}
469
512
 
470
513
bool SchemaUpdater::updateFilterSettings()
471
514
{
472
 
    QString filterVersion = m_AlbumDB->getSetting("FilterSettingsVersion");
473
 
    QString dcrawFilterVersion = m_AlbumDB->getSetting("DcrawFilterSettingsVersion");
 
515
    QString filterVersion = d->albumDB->getSetting("FilterSettingsVersion");
 
516
    QString dcrawFilterVersion = d->albumDB->getSetting("DcrawFilterSettingsVersion");
474
517
 
475
518
    if (
476
519
        filterVersion.toInt() < filterSettingsVersion() ||
491
534
    {
492
535
        setLegacySettingEntries();
493
536
 
494
 
        m_currentVersion = schemaVersion();
 
537
        d->currentVersion = schemaVersion();
495
538
 
496
539
        // if we start with the V2 hash, version 6 is required
497
 
        m_AlbumDB->setUniqueHashVersion(uniqueHashVersion());
498
 
        m_currentRequiredVersion = schemaVersion();
 
540
        d->albumDB->setUniqueHashVersion(uniqueHashVersion());
 
541
        d->currentRequiredVersion = schemaVersion();
499
542
        /*
500
543
        // Digikam for database version 5 can work with version 6, though not using the new features
501
 
        m_currentRequiredVersion = 5;
 
544
        d->currentRequiredVersion = 5;
502
545
        */
503
546
        return true;
504
547
    }
510
553
 
511
554
bool SchemaUpdater::createTables()
512
555
{
513
 
    return m_Backend->execDBAction(m_Backend->getDBAction("CreateDB"));
 
556
    return d->backend->execDBAction(d->backend->getDBAction("CreateDB"));
514
557
}
515
558
 
516
559
bool SchemaUpdater::createIndices()
517
560
{
518
561
    // TODO: see which more indices are needed
519
562
    // create indices
520
 
    return m_Backend->execDBAction(m_Backend->getDBAction("CreateIndices"));
 
563
    return d->backend->execDBAction(d->backend->getDBAction("CreateIndices"));
521
564
}
522
565
 
523
566
bool SchemaUpdater::createTriggers()
524
567
{
525
 
    return m_Backend->execDBAction(m_Backend->getDBAction(QString("CreateTriggers")));
 
568
    return d->backend->execDBAction(d->backend->getDBAction(QString("CreateTriggers")));
526
569
}
527
570
 
528
571
bool SchemaUpdater::updateUniqueHash()
542
585
        CollectionScanner scanner;
543
586
        scanner.setNeedFileCount(true);
544
587
        scanner.setUpdateHashHint();
545
 
        if (m_observer)
 
588
        if (d->observer)
546
589
        {
547
 
            m_observer->connectCollectionScanner(&scanner);
548
 
            scanner.setObserver(m_observer);
 
590
            d->observer->connectCollectionScanner(&scanner);
 
591
            scanner.setObserver(d->observer);
549
592
        }
550
593
        scanner.completeScan();
551
594
 
552
595
        // earlier digikam does not know about the hash
553
 
        if (m_currentRequiredVersion.toInt() < 6)
 
596
        if (d->currentRequiredVersion.toInt() < 6)
554
597
        {
555
 
            m_currentRequiredVersion = 6;
 
598
            d->currentRequiredVersion = 6;
556
599
            setVersionSettings();
557
600
        }
558
601
    }
559
602
    return true;
560
603
}
561
604
 
562
 
bool SchemaUpdater::updateV5toV6()
 
605
bool SchemaUpdater::performUpdateToVersion(const QString& actionName, int newVersion, int newRequiredVersion)
563
606
{
564
 
    if (m_observer)
 
607
    if (d->observer)
565
608
    {
566
 
        if (!m_observer->continueQuery())
 
609
        if (!d->observer->continueQuery())
567
610
        {
568
611
            return false;
569
612
        }
570
613
 
571
 
        m_observer->moreSchemaUpdateSteps(1);
 
614
        d->observer->moreSchemaUpdateSteps(1);
572
615
    }
573
616
 
574
 
    DatabaseAction updateAction = m_Backend->getDBAction("UpdateSchemaFromV5ToV6");
 
617
    DatabaseAction updateAction = d->backend->getDBAction(actionName);
575
618
    if (updateAction.name.isNull())
576
619
    {
577
620
        QString errorMsg = i18n("The database update action cannot be found. Please ensure that "
579
622
                                "at the correct place. ");
580
623
    }
581
624
 
582
 
    if (!m_Backend->execDBAction(updateAction))
 
625
    if (!d->backend->execDBAction(updateAction))
583
626
    {
584
 
        kError() << "Schema update to V6 failed!";
 
627
        kError() << "Schema update to V" << newVersion << "failed!";
585
628
        // resort to default error message, set above
586
629
        return false;
587
630
    }
588
631
 
589
 
    if (m_observer)
 
632
    if (d->observer)
590
633
    {
591
 
        if (!m_observer->continueQuery())
 
634
        if (!d->observer->continueQuery())
592
635
        {
593
636
            return false;
594
637
        }
595
638
 
596
 
        m_observer->schemaUpdateProgress(i18n("Updated schema to version 6."));
 
639
        d->observer->schemaUpdateProgress(i18n("Updated schema to version %1.", newVersion));
597
640
    }
598
641
 
599
 
    m_currentVersion = 6;
 
642
    d->currentVersion = newVersion;
600
643
    // Digikam for database version 5 can work with version 6, though not using the new features
601
644
    // Note: We do not upgrade the uniqueHash
602
 
    m_currentRequiredVersion = 5;
 
645
    d->currentRequiredVersion = newRequiredVersion;
603
646
    return true;
604
647
}
605
648
 
 
649
 
 
650
bool SchemaUpdater::updateToVersion(int targetVersion)
 
651
{
 
652
    if (d->currentVersion != targetVersion-1)
 
653
    {
 
654
        kError() << "updateToVersion performs only incremental updates. Called to update from"
 
655
                 << d->currentVersion << "to" << targetVersion << ", aborting.";
 
656
        return false;
 
657
    }
 
658
 
 
659
    switch (targetVersion)
 
660
    {
 
661
        case 6:
 
662
            // Digikam for database version 5 can work with version 6, though not using the new features
 
663
            // Note: We do not upgrade the uniqueHash
 
664
            return performUpdateToVersion("UpdateSchemaFromV5ToV6", 6, 5);
 
665
        case 7:
 
666
            // Digikam for database version 5 and 6 can work with version 7, though not using the support for video files.
 
667
            return performUpdateToVersion("UpdateSchemaFromV6ToV7", 7, 5);
 
668
        default:
 
669
            kError() << "Unsupported update to version" << targetVersion;
 
670
            return false;
 
671
    }
 
672
}
 
673
 
606
674
bool SchemaUpdater::copyV3toV4(const QString& digikam3DBPath, const QString& currentDBPath)
607
675
{
608
 
    if (m_observer)
 
676
    if (d->observer)
609
677
    {
610
 
        m_observer->moreSchemaUpdateSteps(2);
 
678
        d->observer->moreSchemaUpdateSteps(2);
611
679
    }
612
680
 
613
 
    m_Backend->close();
 
681
    d->backend->close();
614
682
 
615
683
    // We cannot use KIO here because KIO only works from the main thread
616
684
    QFile oldFile(digikam3DBPath);
626
694
                                "Please make sure that the file can be copied, "
627
695
                                "or delete it.",
628
696
                                digikam3DBPath, currentDBPath, oldFile.errorString());
629
 
        m_LastErrorMessage=errorMsg;
630
 
        m_setError = true;
 
697
        d->lastErrorMessage=errorMsg;
 
698
        d->setError = true;
631
699
 
632
 
        if (m_observer)
 
700
        if (d->observer)
633
701
        {
634
 
            m_observer->error(errorMsg);
635
 
            m_observer->finishedSchemaUpdate(InitializationObserver::UpdateErrorMustAbort);
 
702
            d->observer->error(errorMsg);
 
703
            d->observer->finishedSchemaUpdate(InitializationObserver::UpdateErrorMustAbort);
636
704
        }
637
705
 
638
706
        return false;
639
707
    }
640
708
 
641
 
    if (m_observer)
 
709
    if (d->observer)
642
710
    {
643
 
        m_observer->schemaUpdateProgress(i18n("Copied database file"));
 
711
        d->observer->schemaUpdateProgress(i18n("Copied database file"));
644
712
    }
645
713
 
646
 
    if (!m_Backend->open(m_Parameters))
 
714
    if (!d->backend->open(d->parameters))
647
715
    {
648
716
        QString errorMsg = i18n("The old database file (\"%1\") has been copied "
649
717
                                "to the new location (\"%2\") but it cannot be opened. "
651
719
                                "starting with an empty database. ",
652
720
                                digikam3DBPath, currentDBPath);
653
721
 
654
 
        m_LastErrorMessage=errorMsg;
655
 
        m_setError = true;
 
722
        d->lastErrorMessage=errorMsg;
 
723
        d->setError = true;
656
724
 
657
 
        if (m_observer)
 
725
        if (d->observer)
658
726
        {
659
 
            m_observer->error(errorMsg);
660
 
            m_observer->finishedSchemaUpdate(InitializationObserver::UpdateErrorMustAbort);
 
727
            d->observer->error(errorMsg);
 
728
            d->observer->finishedSchemaUpdate(InitializationObserver::UpdateErrorMustAbort);
661
729
        }
662
730
 
663
731
        return false;
664
732
    }
665
733
 
666
 
    if (m_observer)
 
734
    if (d->observer)
667
735
    {
668
 
        m_observer->schemaUpdateProgress(i18n("Opened new database file"));
 
736
        d->observer->schemaUpdateProgress(i18n("Opened new database file"));
669
737
    }
670
738
 
671
 
    m_currentVersion = 4;
 
739
    d->currentVersion = 4;
672
740
    return true;
673
741
}
674
742
 
675
743
bool SchemaUpdater::updateV2toV4(const QString& sqlite2DBPath)
676
744
{
677
 
    if (m_observer)
 
745
    if (d->observer)
678
746
    {
679
 
        m_observer->moreSchemaUpdateSteps(1);
 
747
        d->observer->moreSchemaUpdateSteps(1);
680
748
    }
681
749
 
682
 
    if (upgradeDB_Sqlite2ToSqlite3(m_AlbumDB, m_Backend, sqlite2DBPath))
 
750
    if (upgradeDB_Sqlite2ToSqlite3(d->albumDB, d->backend, sqlite2DBPath))
683
751
    {
684
 
        m_currentVersion = 4;
 
752
        d->currentVersion = 4;
685
753
        return true;
686
754
    }
687
755
    else
689
757
        QString errorMsg = i18n("Could not update from the old SQLite2 file (\"%1\"). "
690
758
                                "Please delete this file and try again, "
691
759
                                "starting with an empty database. ", sqlite2DBPath);
692
 
        m_LastErrorMessage=errorMsg;
 
760
        d->lastErrorMessage=errorMsg;
693
761
 
694
 
        if (m_observer)
 
762
        if (d->observer)
695
763
        {
696
 
            m_observer->error(errorMsg);
697
 
            m_observer->finishedSchemaUpdate(InitializationObserver::UpdateErrorMustAbort);
 
764
            d->observer->error(errorMsg);
 
765
            d->observer->finishedSchemaUpdate(InitializationObserver::UpdateErrorMustAbort);
698
766
        }
699
767
 
700
768
        return false;
701
769
    }
702
770
 
703
771
    // FIXME: We are not returning anything, if we land in this section of the code!
704
 
    if (m_observer)
 
772
    if (d->observer)
705
773
    {
706
 
        m_observer->schemaUpdateProgress(i18n("Updated from 0.7 database"));
 
774
        d->observer->schemaUpdateProgress(i18n("Updated from 0.7 database"));
707
775
    }
708
776
}
709
777
 
742
810
{
743
811
    kDebug() << "updateV4toV6";
744
812
 
745
 
    if (m_observer)
 
813
    if (d->observer)
746
814
    {
747
 
        if (!m_observer->continueQuery())
 
815
        if (!d->observer->continueQuery())
748
816
        {
749
817
            return false;
750
818
        }
751
819
 
752
 
        m_observer->moreSchemaUpdateSteps(11);
 
820
        d->observer->moreSchemaUpdateSteps(11);
753
821
    }
754
822
 
755
823
    // This update was introduced from digikam version 0.9 to digikam 0.10
756
824
    // We operator on an SQLite3 database under a transaction (which will be rolled back on error)
757
825
 
758
826
    // --- Make space for new tables ---
759
 
    if (!m_Backend->execSql(QString("ALTER TABLE Albums RENAME TO AlbumsV3;")))
760
 
    {
761
 
        return false;
762
 
    }
763
 
 
764
 
    if (!m_Backend->execSql(QString("ALTER TABLE Images RENAME TO ImagesV3;")))
765
 
    {
766
 
        return false;
767
 
    }
768
 
 
769
 
    if (!m_Backend->execSql(QString("ALTER TABLE Searches RENAME TO SearchesV3;")))
 
827
    if (!d->backend->execSql(QString("ALTER TABLE Albums RENAME TO AlbumsV3;")))
 
828
    {
 
829
        return false;
 
830
    }
 
831
 
 
832
    if (!d->backend->execSql(QString("ALTER TABLE Images RENAME TO ImagesV3;")))
 
833
    {
 
834
        return false;
 
835
    }
 
836
 
 
837
    if (!d->backend->execSql(QString("ALTER TABLE Searches RENAME TO SearchesV3;")))
770
838
    {
771
839
        return false;
772
840
    }
775
843
    // --- Drop some triggers and indices ---
776
844
 
777
845
    // Don't check for errors here. The "IF EXISTS" clauses seem not supported in SQLite
778
 
    m_Backend->execSql(QString("DROP TRIGGER delete_album;"));
779
 
    m_Backend->execSql(QString("DROP TRIGGER delete_image;"));
780
 
    m_Backend->execSql(QString("DROP TRIGGER delete_tag;"));
781
 
    m_Backend->execSql(QString("DROP TRIGGER insert_tagstree;"));
782
 
    m_Backend->execSql(QString("DROP TRIGGER delete_tagstree;"));
783
 
    m_Backend->execSql(QString("DROP TRIGGER move_tagstree;"));
784
 
    m_Backend->execSql(QString("DROP INDEX dir_index;"));
785
 
    m_Backend->execSql(QString("DROP INDEX tag_index;"));
 
846
    d->backend->execSql(QString("DROP TRIGGER delete_album;"));
 
847
    d->backend->execSql(QString("DROP TRIGGER delete_image;"));
 
848
    d->backend->execSql(QString("DROP TRIGGER delete_tag;"));
 
849
    d->backend->execSql(QString("DROP TRIGGER insert_tagstree;"));
 
850
    d->backend->execSql(QString("DROP TRIGGER delete_tagstree;"));
 
851
    d->backend->execSql(QString("DROP TRIGGER move_tagstree;"));
 
852
    d->backend->execSql(QString("DROP INDEX dir_index;"));
 
853
    d->backend->execSql(QString("DROP INDEX tag_index;"));
786
854
 
787
 
    if (m_observer)
 
855
    if (d->observer)
788
856
    {
789
 
        if (!m_observer->continueQuery())
 
857
        if (!d->observer->continueQuery())
790
858
        {
791
859
            return false;
792
860
        }
793
861
 
794
 
        m_observer->schemaUpdateProgress(i18n("Prepared table creation"));
 
862
        d->observer->schemaUpdateProgress(i18n("Prepared table creation"));
795
863
    }
796
864
 
797
865
    kDebug() << "Dropped triggers";
803
871
        return false;
804
872
    }
805
873
 
806
 
    if (m_observer)
 
874
    if (d->observer)
807
875
    {
808
 
        if (!m_observer->continueQuery())
 
876
        if (!d->observer->continueQuery())
809
877
        {
810
878
            return false;
811
879
        }
812
880
 
813
 
        m_observer->schemaUpdateProgress(i18n("Created tables"));
 
881
        d->observer->schemaUpdateProgress(i18n("Created tables"));
814
882
    }
815
883
 
816
884
    // --- Populate AlbumRoots (from config) ---
826
894
        QString errorMsg = i18n("No album library path has been found in the configuration file. "
827
895
                                "Giving up the schema updating process. "
828
896
                                "Please try with an empty database, or repair your configuration.");
829
 
        m_LastErrorMessage=errorMsg;
830
 
        m_setError = true;
 
897
        d->lastErrorMessage=errorMsg;
 
898
        d->setError = true;
831
899
 
832
 
        if (m_observer)
 
900
        if (d->observer)
833
901
        {
834
 
            m_observer->error(errorMsg);
835
 
            m_observer->finishedSchemaUpdate(InitializationObserver::UpdateErrorMustAbort);
 
902
            d->observer->error(errorMsg);
 
903
            d->observer->finishedSchemaUpdate(InitializationObserver::UpdateErrorMustAbort);
836
904
        }
837
905
 
838
906
        return false;
852
920
                                "The database updating process will now be aborted because we do not want "
853
921
                                "to create a new database based on false assumptions from a broken installation.",
854
922
                                albumLibraryPath);
855
 
        m_LastErrorMessage=errorMsg;
856
 
        m_setError = true;
 
923
        d->lastErrorMessage=errorMsg;
 
924
        d->setError = true;
857
925
 
858
 
        if (m_observer)
 
926
        if (d->observer)
859
927
        {
860
 
            m_observer->error(errorMsg);
861
 
            m_observer->finishedSchemaUpdate(InitializationObserver::UpdateErrorMustAbort);
 
928
            d->observer->error(errorMsg);
 
929
            d->observer->finishedSchemaUpdate(InitializationObserver::UpdateErrorMustAbort);
862
930
        }
863
931
 
864
932
        return false;
865
933
    }
866
934
 
867
 
    if (m_observer)
 
935
    if (d->observer)
868
936
    {
869
 
        if (!m_observer->continueQuery())
 
937
        if (!d->observer->continueQuery())
870
938
        {
871
939
            return false;
872
940
        }
873
941
 
874
 
        m_observer->schemaUpdateProgress(i18n("Configured one album root"));
 
942
        d->observer->schemaUpdateProgress(i18n("Configured one album root"));
875
943
    }
876
944
 
877
945
    kDebug() << "Inserted album root";
878
946
 
879
947
    // --- With the album root, populate albums ---
880
948
 
881
 
    if (!m_Backend->execSql(QString(
 
949
    if (!d->backend->execSql(QString(
882
950
                                "REPLACE INTO Albums "
883
951
                                " (id, albumRoot, relativePath, date, caption, collection, icon) "
884
952
                                "SELECT id, ?, url, date, caption, collection, icon "
890
958
        return false;
891
959
    }
892
960
 
893
 
    if (m_observer)
 
961
    if (d->observer)
894
962
    {
895
 
        if (!m_observer->continueQuery())
 
963
        if (!d->observer->continueQuery())
896
964
        {
897
965
            return false;
898
966
        }
899
967
 
900
 
        m_observer->schemaUpdateProgress(i18n("Imported albums"));
 
968
        d->observer->schemaUpdateProgress(i18n("Imported albums"));
901
969
    }
902
970
 
903
971
    kDebug() << "Populated albums";
904
972
 
905
973
    // --- Add images ---
906
974
 
907
 
    if (!m_Backend->execSql(QString(
 
975
    if (!d->backend->execSql(QString(
908
976
                                "REPLACE INTO Images "
909
977
                                " (id, album, name, status, category, modificationDate, fileSize, uniqueHash) "
910
978
                                "SELECT id, dirid, name, ?, ?, NULL, NULL, NULL"
916
984
        return false;
917
985
    }
918
986
 
919
 
    if (!m_access->backend()->execSql(QString(
 
987
    if (!d->access->backend()->execSql(QString(
920
988
                                          "REPLACE INTO ImageInformation (imageId) SELECT id FROM Images;"))
921
989
       )
922
990
    {
924
992
    }
925
993
 
926
994
    // remove orphan images that would not be removed by CollectionScanner
927
 
    m_Backend->execSql(QString("DELETE FROM Images WHERE album NOT IN (SELECT id FROM Albums);"));
 
995
    d->backend->execSql(QString("DELETE FROM Images WHERE album NOT IN (SELECT id FROM Albums);"));
928
996
 
929
 
    if (m_observer)
 
997
    if (d->observer)
930
998
    {
931
 
        if (!m_observer->continueQuery())
 
999
        if (!d->observer->continueQuery())
932
1000
        {
933
1001
            return false;
934
1002
        }
935
1003
 
936
 
        m_observer->schemaUpdateProgress(i18n("Imported images information"));
 
1004
        d->observer->schemaUpdateProgress(i18n("Imported images information"));
937
1005
    }
938
1006
 
939
1007
    kDebug() << "Populated Images";
940
1008
 
941
1009
    // --- Port searches ---
942
1010
 
943
 
    if (!m_Backend->execSql(QString(
 
1011
    if (!d->backend->execSql(QString(
944
1012
                                "REPLACE INTO Searches "
945
1013
                                " (id, type, name, query) "
946
1014
                                "SELECT id, ?, name, url"
951
1019
        return false;
952
1020
    }
953
1021
 
954
 
    SearchInfo::List sList = m_AlbumDB->scanSearches();
 
1022
    SearchInfo::List sList = d->albumDB->scanSearches();
955
1023
 
956
1024
    for (SearchInfo::List::const_iterator it = sList.constBegin(); it != sList.constEnd(); ++it)
957
1025
    {
969
1037
 
970
1038
        if (url.queryItem("type") == QString("datesearch"))
971
1039
        {
972
 
            m_AlbumDB->updateSearch((*it).id, DatabaseSearch::TimeLineSearch, name, query);
 
1040
            d->albumDB->updateSearch((*it).id, DatabaseSearch::TimeLineSearch, name, query);
973
1041
        }
974
1042
        else if (url.queryItem("1.key") == "keyword")
975
1043
        {
976
 
            m_AlbumDB->updateSearch((*it).id, DatabaseSearch::KeywordSearch, name, query);
 
1044
            d->albumDB->updateSearch((*it).id, DatabaseSearch::KeywordSearch, name, query);
977
1045
        }
978
1046
        else
979
1047
        {
980
 
            m_AlbumDB->updateSearch((*it).id, DatabaseSearch::AdvancedSearch, name, query);
 
1048
            d->albumDB->updateSearch((*it).id, DatabaseSearch::AdvancedSearch, name, query);
981
1049
        }
982
1050
    }
983
1051
 
1011
1079
    configVideoFilter.subtract(defaultVideoFilter.toSet());
1012
1080
    configAudioFilter.subtract(defaultAudioFilter.toSet());
1013
1081
 
1014
 
    m_AlbumDB->setUserFilterSettings(configImageFilter.toList(), configVideoFilter.toList(), configAudioFilter.toList());
 
1082
    d->albumDB->setUserFilterSettings(configImageFilter.toList(), configVideoFilter.toList(), configAudioFilter.toList());
1015
1083
    kDebug() << "Set initial filter settings with user settings" << configImageFilter;
1016
1084
 
1017
 
    if (m_observer)
 
1085
    if (d->observer)
1018
1086
    {
1019
 
        if (!m_observer->continueQuery())
 
1087
        if (!d->observer->continueQuery())
1020
1088
        {
1021
1089
            return false;
1022
1090
        }
1023
1091
 
1024
 
        m_observer->schemaUpdateProgress(i18n("Initialized and imported file suffix filter"));
 
1092
        d->observer->schemaUpdateProgress(i18n("Initialized and imported file suffix filter"));
1025
1093
    }
1026
1094
 
1027
1095
    // --- do a full scan ---
1028
1096
 
1029
1097
    CollectionScanner scanner;
1030
1098
 
1031
 
    if (m_observer)
 
1099
    if (d->observer)
1032
1100
    {
1033
 
        m_observer->connectCollectionScanner(&scanner);
1034
 
        scanner.setObserver(m_observer);
 
1101
        d->observer->connectCollectionScanner(&scanner);
 
1102
        scanner.setObserver(d->observer);
1035
1103
    }
1036
1104
 
1037
1105
    scanner.completeScan();
1038
1106
 
1039
 
    if (m_observer)
 
1107
    if (d->observer)
1040
1108
    {
1041
 
        if (!m_observer->continueQuery())
 
1109
        if (!d->observer->continueQuery())
1042
1110
        {
1043
1111
            return false;
1044
1112
        }
1045
1113
 
1046
 
        m_observer->schemaUpdateProgress(i18n("Did the initial full scan"));
 
1114
        d->observer->schemaUpdateProgress(i18n("Did the initial full scan"));
1047
1115
    }
1048
1116
 
1049
1117
    // --- Port date, comment and rating (_after_ the scan) ---
1050
1118
 
1051
1119
    // Port ImagesV3.date -> ImageInformation.creationDate
1052
 
    if (!m_Backend->execSql(QString(
 
1120
    if (!d->backend->execSql(QString(
1053
1121
                                "UPDATE ImageInformation SET "
1054
1122
                                " creationDate=(SELECT datetime FROM ImagesV3 WHERE ImagesV3.id=ImageInformation.imageid) "
1055
 
                                "WHERE imageid IN (SELECT id FROM ImagesV3);"
1056
 
                            )
 
1123
                                "WHERE imageid IN (SELECT id FROM ImagesV3);")
1057
1124
                           )
1058
1125
       )
1059
1126
    {
1060
1127
        return false;
1061
1128
    }
1062
1129
 
1063
 
    if (m_observer)
 
1130
    if (d->observer)
1064
1131
    {
1065
 
        if (!m_observer->continueQuery())
 
1132
        if (!d->observer->continueQuery())
1066
1133
        {
1067
1134
            return false;
1068
1135
        }
1069
1136
 
1070
 
        m_observer->schemaUpdateProgress(i18n("Imported creation dates"));
 
1137
        d->observer->schemaUpdateProgress(i18n("Imported creation dates"));
1071
1138
    }
1072
1139
 
1073
1140
    // Port ImagesV3.comment to ImageComments
1074
1141
 
1075
1142
    // An author of NULL will inhibt the UNIQUE restriction to take effect (but #189080). Work around.
1076
 
    m_Backend->execSql(QString(
 
1143
    d->backend->execSql(QString(
1077
1144
                           "DELETE FROM ImageComments WHERE "
1078
1145
                           "type=? AND language=? AND author IS NULL "
1079
1146
                           "AND imageid IN ( SELECT id FROM ImagesV3 ); "),
1080
1147
                       (int)DatabaseComment::Comment, QString("x-default"));
1081
1148
 
1082
 
    if (!m_Backend->execSql(QString(
 
1149
    if (!d->backend->execSql(QString(
1083
1150
                                "REPLACE INTO ImageComments "
1084
1151
                                " (imageid, type, language, comment) "
1085
1152
                                "SELECT id, ?, ?, caption FROM ImagesV3;"
1090
1157
        return false;
1091
1158
    }
1092
1159
 
1093
 
    if (m_observer)
 
1160
    if (d->observer)
1094
1161
    {
1095
 
        if (!m_observer->continueQuery())
 
1162
        if (!d->observer->continueQuery())
1096
1163
        {
1097
1164
            return false;
1098
1165
        }
1099
1166
 
1100
 
        m_observer->schemaUpdateProgress(i18n("Imported comments"));
 
1167
        d->observer->schemaUpdateProgress(i18n("Imported comments"));
1101
1168
    }
1102
1169
 
1103
1170
    // Port rating storage in ImageProperties to ImageInformation
1104
 
    if (!m_Backend->execSql(QString(
 
1171
    if (!d->backend->execSql(QString(
1105
1172
                                "UPDATE ImageInformation SET "
1106
1173
                                " rating=(SELECT value FROM ImageProperties "
1107
1174
                                "         WHERE ImageInformation.imageid=ImageProperties.imageid AND ImageProperties.property=?) "
1113
1180
        return false;
1114
1181
    }
1115
1182
 
1116
 
    m_Backend->execSql(QString("DELETE FROM ImageProperties WHERE property=?;"), QString("Rating"));
1117
 
    m_Backend->execSql(QString("UPDATE ImageInformation SET rating=0 WHERE rating<0;"));
 
1183
    d->backend->execSql(QString("DELETE FROM ImageProperties WHERE property=?;"), QString("Rating"));
 
1184
    d->backend->execSql(QString("UPDATE ImageInformation SET rating=0 WHERE rating<0;"));
1118
1185
 
1119
 
    if (m_observer)
 
1186
    if (d->observer)
1120
1187
    {
1121
 
        if (!m_observer->continueQuery())
 
1188
        if (!d->observer->continueQuery())
1122
1189
        {
1123
1190
            return false;
1124
1191
        }
1125
1192
 
1126
 
        m_observer->schemaUpdateProgress(i18n("Imported ratings"));
 
1193
        d->observer->schemaUpdateProgress(i18n("Imported ratings"));
1127
1194
    }
1128
1195
 
1129
1196
    // --- Drop old tables ---
1130
1197
 
1131
 
    m_Backend->execSql(QString("DROP TABLE ImagesV3;"));
1132
 
    m_Backend->execSql(QString("DROP TABLE AlbumsV3;"));
1133
 
    m_Backend->execSql(QString("DROP TABLE SearchesV3;"));
 
1198
    d->backend->execSql(QString("DROP TABLE ImagesV3;"));
 
1199
    d->backend->execSql(QString("DROP TABLE AlbumsV3;"));
 
1200
    d->backend->execSql(QString("DROP TABLE SearchesV3;"));
1134
1201
 
1135
 
    if (m_observer)
 
1202
    if (d->observer)
1136
1203
    {
1137
 
        m_observer->schemaUpdateProgress(i18n("Dropped v3 tables"));
 
1204
        d->observer->schemaUpdateProgress(i18n("Dropped v3 tables"));
1138
1205
    }
1139
1206
 
1140
 
    m_currentRequiredVersion = 5;
1141
 
    m_currentVersion = 6;
 
1207
    d->currentRequiredVersion = 5;
 
1208
    d->currentVersion = 6;
1142
1209
    kDebug() << "Returning true from updating to 5";
1143
1210
    return true;
1144
1211
}
1145
1212
 
1146
1213
void SchemaUpdater::setLegacySettingEntries()
1147
1214
{
1148
 
    m_AlbumDB->setSetting("preAlpha010Update1", "true");
1149
 
    m_AlbumDB->setSetting("preAlpha010Update2", "true");
1150
 
    m_AlbumDB->setSetting("preAlpha010Update3", "true");
1151
 
    m_AlbumDB->setSetting("beta010Update1", "true");
1152
 
    m_AlbumDB->setSetting("beta010Update2", "true");
 
1215
    d->albumDB->setSetting("preAlpha010Update1", "true");
 
1216
    d->albumDB->setSetting("preAlpha010Update2", "true");
 
1217
    d->albumDB->setSetting("preAlpha010Update3", "true");
 
1218
    d->albumDB->setSetting("beta010Update1", "true");
 
1219
    d->albumDB->setSetting("beta010Update2", "true");
1153
1220
}
1154
1221
 
1155
1222
// ---------- Legacy code ------------
1156
1223
 
1157
 
 
1158
1224
void SchemaUpdater::preAlpha010Update1()
1159
1225
{
1160
 
    QString hasUpdate = m_AlbumDB->getSetting("preAlpha010Update1");
 
1226
    QString hasUpdate = d->albumDB->getSetting("preAlpha010Update1");
1161
1227
 
1162
1228
    if (!hasUpdate.isNull())
1163
1229
    {
1164
1230
        return;
1165
1231
    }
1166
1232
 
1167
 
    if (!m_Backend->execSql(QString("ALTER TABLE Searches RENAME TO SearchesV3;")))
 
1233
    if (!d->backend->execSql(QString("ALTER TABLE Searches RENAME TO SearchesV3;")))
1168
1234
    {
1169
1235
        return;
1170
1236
    }
1171
1237
 
1172
 
    if ( !m_Backend->execSql(
 
1238
    if ( !d->backend->execSql(
1173
1239
             QString( "CREATE TABLE IF NOT EXISTS Searches  \n"
1174
1240
                      " (id INTEGER PRIMARY KEY, \n"
1175
1241
                      "  type INTEGER, \n"
1179
1245
        return;
1180
1246
    }
1181
1247
 
1182
 
    if (!m_Backend->execSql(QString(
 
1248
    if (!d->backend->execSql(QString(
1183
1249
                                "REPLACE INTO Searches "
1184
1250
                                " (id, type, name, query) "
1185
1251
                                "SELECT id, ?, name, url"
1190
1256
        return;
1191
1257
    }
1192
1258
 
1193
 
    SearchInfo::List sList = m_AlbumDB->scanSearches();
 
1259
    SearchInfo::List sList = d->albumDB->scanSearches();
1194
1260
 
1195
1261
    for (SearchInfo::List::const_iterator it = sList.constBegin(); it != sList.constEnd(); ++it)
1196
1262
    {
1201
1267
 
1202
1268
        if (url.queryItem("type") == QString("datesearch"))
1203
1269
        {
1204
 
            m_AlbumDB->updateSearch((*it).id, DatabaseSearch::TimeLineSearch, (*it).name, query);
 
1270
            d->albumDB->updateSearch((*it).id, DatabaseSearch::TimeLineSearch, (*it).name, query);
1205
1271
        }
1206
1272
        else if (url.queryItem("1.key") == "keyword")
1207
1273
        {
1208
 
            m_AlbumDB->updateSearch((*it).id, DatabaseSearch::KeywordSearch, (*it).name, query);
 
1274
            d->albumDB->updateSearch((*it).id, DatabaseSearch::KeywordSearch, (*it).name, query);
1209
1275
        }
1210
1276
        else
1211
1277
        {
1212
 
            m_AlbumDB->updateSearch((*it).id, DatabaseSearch::AdvancedSearch, (*it).name, query);
 
1278
            d->albumDB->updateSearch((*it).id, DatabaseSearch::AdvancedSearch, (*it).name, query);
1213
1279
        }
1214
1280
    }
1215
1281
 
1216
 
    m_Backend->execSql(QString("DROP TABLE SearchesV3;"));
 
1282
    d->backend->execSql(QString("DROP TABLE SearchesV3;"));
1217
1283
 
1218
 
    m_AlbumDB->setSetting("preAlpha010Update1", "true");
 
1284
    d->albumDB->setSetting("preAlpha010Update1", "true");
1219
1285
}
1220
1286
 
1221
1287
void SchemaUpdater::preAlpha010Update2()
1222
1288
{
1223
 
    QString hasUpdate = m_AlbumDB->getSetting("preAlpha010Update2");
 
1289
    QString hasUpdate = d->albumDB->getSetting("preAlpha010Update2");
1224
1290
 
1225
1291
    if (!hasUpdate.isNull())
1226
1292
    {
1227
1293
        return;
1228
1294
    }
1229
1295
 
1230
 
    if (!m_Backend->execSql(QString("ALTER TABLE ImagePositions RENAME TO ImagePositionsTemp;")))
1231
 
    {
1232
 
        return;
1233
 
    }
1234
 
 
1235
 
    if (!m_Backend->execSql(QString("ALTER TABLE ImageMetadata RENAME TO ImageMetadataTemp;")))
1236
 
    {
1237
 
        return;
1238
 
    }
1239
 
 
1240
 
    m_Backend->execSql(
 
1296
    if (!d->backend->execSql(QString("ALTER TABLE ImagePositions RENAME TO ImagePositionsTemp;")))
 
1297
    {
 
1298
        return;
 
1299
    }
 
1300
 
 
1301
    if (!d->backend->execSql(QString("ALTER TABLE ImageMetadata RENAME TO ImageMetadataTemp;")))
 
1302
    {
 
1303
        return;
 
1304
    }
 
1305
 
 
1306
    d->backend->execSql(
1241
1307
        QString("CREATE TABLE ImagePositions\n"
1242
1308
                " (imageid INTEGER PRIMARY KEY,\n"
1243
1309
                "  latitude TEXT,\n"
1251
1317
                "  accuracy REAL,\n"
1252
1318
                "  description TEXT);") );
1253
1319
 
1254
 
    m_Backend->execSql(QString(
 
1320
    d->backend->execSql(QString(
1255
1321
                           "REPLACE INTO ImagePositions "
1256
1322
                           " (imageid, latitude, latitudeNumber, longitude, longitudeNumber, "
1257
1323
                           "  altitude, orientation, tilt, roll, accuracy, description) "
1259
1325
                           "  altitude, orientation, tilt, roll, 0, description "
1260
1326
                           " FROM ImagePositionsTemp;"));
1261
1327
 
1262
 
    m_Backend->execSql(
 
1328
    d->backend->execSql(
1263
1329
        QString("CREATE TABLE ImageMetadata\n"
1264
1330
                " (imageid INTEGER PRIMARY KEY,\n"
1265
1331
                "  make TEXT,\n"
1279
1345
                "  subjectDistance REAL,\n"
1280
1346
                "  subjectDistanceCategory INTEGER);") );
1281
1347
 
1282
 
    m_Backend->execSql( QString("INSERT INTO ImageMetadata "
 
1348
    d->backend->execSql( QString("INSERT INTO ImageMetadata "
1283
1349
                                " (imageid, make, model, lens, aperture, focalLength, focalLength35, "
1284
1350
                                "  exposureTime, exposureProgram, exposureMode, sensitivity, flash, whiteBalance, "
1285
1351
                                "  whiteBalanceColorTemperature, meteringMode, subjectDistance, subjectDistanceCategory) "
1288
1354
                                "  whiteBalanceColorTemperature, meteringMode, subjectDistance, subjectDistanceCategory "
1289
1355
                                "FROM ImageMetadataTemp;"));
1290
1356
 
1291
 
    m_Backend->execSql(QString("DROP TABLE ImagePositionsTemp;"));
1292
 
    m_Backend->execSql(QString("DROP TABLE ImageMetadataTemp;"));
 
1357
    d->backend->execSql(QString("DROP TABLE ImagePositionsTemp;"));
 
1358
    d->backend->execSql(QString("DROP TABLE ImageMetadataTemp;"));
1293
1359
 
1294
 
    m_AlbumDB->setSetting("preAlpha010Update2", "true");
 
1360
    d->albumDB->setSetting("preAlpha010Update2", "true");
1295
1361
}
1296
1362
 
1297
1363
void SchemaUpdater::preAlpha010Update3()
1298
1364
{
1299
 
    QString hasUpdate = m_AlbumDB->getSetting("preAlpha010Update3");
 
1365
    QString hasUpdate = d->albumDB->getSetting("preAlpha010Update3");
1300
1366
 
1301
1367
    if (!hasUpdate.isNull())
1302
1368
    {
1303
1369
        return;
1304
1370
    }
1305
1371
 
1306
 
    m_Backend->execSql(QString("DROP TABLE ImageCopyright;"));
1307
 
    m_Backend->execSql(
 
1372
    d->backend->execSql(QString("DROP TABLE ImageCopyright;"));
 
1373
    d->backend->execSql(
1308
1374
        QString("CREATE TABLE ImageCopyright\n"
1309
1375
                " (imageid INTEGER,\n"
1310
1376
                "  property TEXT,\n"
1313
1379
                "  UNIQUE(imageid, property, value, extraValue));")
1314
1380
    );
1315
1381
 
1316
 
    m_AlbumDB->setSetting("preAlpha010Update3", "true");
 
1382
    d->albumDB->setSetting("preAlpha010Update3", "true");
1317
1383
}
1318
1384
 
1319
1385
void SchemaUpdater::beta010Update1()
1320
1386
{
1321
 
    QString hasUpdate = m_AlbumDB->getSetting("beta010Update1");
 
1387
    QString hasUpdate = d->albumDB->getSetting("beta010Update1");
1322
1388
 
1323
1389
    if (!hasUpdate.isNull())
1324
1390
    {
1326
1392
    }
1327
1393
 
1328
1394
    // if Image has been deleted
1329
 
    m_Backend->execSql("DROP TRIGGER delete_image;");
1330
 
    m_Backend->execSql(
 
1395
    d->backend->execSql("DROP TRIGGER delete_image;");
 
1396
    d->backend->execSql(
1331
1397
        "CREATE TRIGGER delete_image DELETE ON Images\n"
1332
1398
        "BEGIN\n"
1333
1399
        "  DELETE FROM ImageTags\n"
1353
1419
        "END;");
1354
1420
 
1355
1421
 
1356
 
    m_AlbumDB->setSetting("beta010Update1", "true");
 
1422
    d->albumDB->setSetting("beta010Update1", "true");
1357
1423
}
1358
1424
 
1359
1425
void SchemaUpdater::beta010Update2()
1360
1426
{
1361
 
    QString hasUpdate = m_AlbumDB->getSetting("beta010Update2");
 
1427
    QString hasUpdate = d->albumDB->getSetting("beta010Update2");
1362
1428
 
1363
1429
    if (!hasUpdate.isNull())
1364
1430
    {
1366
1432
    }
1367
1433
 
1368
1434
    // force rescan and creation of ImageInformation entry for videos and audio
1369
 
    m_Backend->execSql("DELETE FROM Images WHERE category=2 OR category=3;");
 
1435
    d->backend->execSql("DELETE FROM Images WHERE category=2 OR category=3;");
1370
1436
 
1371
 
    m_AlbumDB->setSetting("beta010Update2", "true");
 
1437
    d->albumDB->setSetting("beta010Update2", "true");
1372
1438
}
1373
1439
 
1374
1440
bool SchemaUpdater::createTablesV3()
1375
1441
{
1376
 
    if (!m_Backend->execSql( QString("CREATE TABLE Albums\n"
 
1442
    if (!d->backend->execSql( QString("CREATE TABLE Albums\n"
1377
1443
                                     " (id INTEGER PRIMARY KEY,\n"
1378
1444
                                     "  url TEXT NOT NULL UNIQUE,\n"
1379
1445
                                     "  date DATE NOT NULL,\n"
1384
1450
        return false;
1385
1451
    }
1386
1452
 
1387
 
    if (!m_Backend->execSql( QString("CREATE TABLE Tags\n"
 
1453
    if (!d->backend->execSql( QString("CREATE TABLE Tags\n"
1388
1454
                                     " (id INTEGER PRIMARY KEY,\n"
1389
1455
                                     "  pid INTEGER,\n"
1390
1456
                                     "  name TEXT NOT NULL,\n"
1395
1461
        return false;
1396
1462
    }
1397
1463
 
1398
 
    if (!m_Backend->execSql( QString("CREATE TABLE TagsTree\n"
 
1464
    if (!d->backend->execSql( QString("CREATE TABLE TagsTree\n"
1399
1465
                                     " (id INTEGER NOT NULL,\n"
1400
1466
                                     "  pid INTEGER NOT NULL,\n"
1401
1467
                                     "  UNIQUE (id, pid));") ))
1403
1469
        return false;
1404
1470
    }
1405
1471
 
1406
 
    if (!m_Backend->execSql( QString("CREATE TABLE Images\n"
 
1472
    if (!d->backend->execSql( QString("CREATE TABLE Images\n"
1407
1473
                                     " (id INTEGER PRIMARY KEY,\n"
1408
1474
                                     "  name TEXT NOT NULL,\n"
1409
1475
                                     "  dirid INTEGER NOT NULL,\n"
1415
1481
    }
1416
1482
 
1417
1483
 
1418
 
    if (!m_Backend->execSql( QString("CREATE TABLE ImageTags\n"
 
1484
    if (!d->backend->execSql( QString("CREATE TABLE ImageTags\n"
1419
1485
                                     " (imageid INTEGER NOT NULL,\n"
1420
1486
                                     "  tagid INTEGER NOT NULL,\n"
1421
1487
                                     "  UNIQUE (imageid, tagid));") ))
1423
1489
        return false;
1424
1490
    }
1425
1491
 
1426
 
    if (!m_Backend->execSql( QString("CREATE TABLE ImageProperties\n"
 
1492
    if (!d->backend->execSql( QString("CREATE TABLE ImageProperties\n"
1427
1493
                                     " (imageid  INTEGER NOT NULL,\n"
1428
1494
                                     "  property TEXT    NOT NULL,\n"
1429
1495
                                     "  value    TEXT    NOT NULL,\n"
1432
1498
        return false;
1433
1499
    }
1434
1500
 
1435
 
    if ( !m_Backend->execSql( QString( "CREATE TABLE Searches  \n"
 
1501
    if ( !d->backend->execSql( QString( "CREATE TABLE Searches  \n"
1436
1502
                                       " (id INTEGER PRIMARY KEY, \n"
1437
1503
                                       "  name TEXT NOT NULL UNIQUE, \n"
1438
1504
                                       "  url  TEXT NOT NULL);" ) ) )
1440
1506
        return false;
1441
1507
    }
1442
1508
 
1443
 
    if (!m_Backend->execSql( QString("CREATE TABLE Settings         \n"
 
1509
    if (!d->backend->execSql( QString("CREATE TABLE Settings         \n"
1444
1510
                                     "(keyword TEXT NOT NULL UNIQUE,\n"
1445
1511
                                     " value TEXT);") ))
1446
1512
    {
1449
1515
 
1450
1516
    // TODO: see which more indices are needed
1451
1517
    // create indices
1452
 
    m_Backend->execSql("CREATE INDEX dir_index ON Images    (dirid);");
1453
 
    m_Backend->execSql("CREATE INDEX tag_index ON ImageTags (tagid);");
 
1518
    d->backend->execSql("CREATE INDEX dir_index ON Images    (dirid);");
 
1519
    d->backend->execSql("CREATE INDEX tag_index ON ImageTags (tagid);");
1454
1520
 
1455
1521
    // create triggers
1456
1522
 
1457
1523
    // trigger: delete from Images/ImageTags/ImageProperties
1458
1524
    // if Album has been deleted
1459
 
    m_Backend->execSql("CREATE TRIGGER delete_album DELETE ON Albums\n"
 
1525
    d->backend->execSql("CREATE TRIGGER delete_album DELETE ON Albums\n"
1460
1526
                       "BEGIN\n"
1461
1527
                       " DELETE FROM ImageTags\n"
1462
1528
                       "   WHERE imageid IN (SELECT id FROM Images WHERE dirid=OLD.id);\n"
1468
1534
 
1469
1535
    // trigger: delete from ImageTags/ImageProperties
1470
1536
    // if Image has been deleted
1471
 
    m_Backend->execSql("CREATE TRIGGER delete_image DELETE ON Images\n"
 
1537
    d->backend->execSql("CREATE TRIGGER delete_image DELETE ON Images\n"
1472
1538
                       "BEGIN\n"
1473
1539
                       "  DELETE FROM ImageTags\n"
1474
1540
                       "    WHERE imageid=OLD.id;\n"
1481
1547
                       "END;");
1482
1548
 
1483
1549
    // trigger: delete from ImageTags if Tag has been deleted
1484
 
    m_Backend->execSql("CREATE TRIGGER delete_tag DELETE ON Tags\n"
 
1550
    d->backend->execSql("CREATE TRIGGER delete_tag DELETE ON Tags\n"
1485
1551
                       "BEGIN\n"
1486
1552
                       "  DELETE FROM ImageTags WHERE tagid=OLD.id;\n"
1487
1553
                       "END;");
1488
1554
 
1489
1555
    // trigger: insert into TagsTree if Tag has been added
1490
 
    m_Backend->execSql("CREATE TRIGGER insert_tagstree AFTER INSERT ON Tags\n"
 
1556
    d->backend->execSql("CREATE TRIGGER insert_tagstree AFTER INSERT ON Tags\n"
1491
1557
                       "BEGIN\n"
1492
1558
                       "  INSERT INTO TagsTree\n"
1493
1559
                       "    SELECT NEW.id, NEW.pid\n"
1496
1562
                       "END;");
1497
1563
 
1498
1564
    // trigger: delete from TagsTree if Tag has been deleted
1499
 
    m_Backend->execSql("CREATE TRIGGER delete_tagstree DELETE ON Tags\n"
 
1565
    d->backend->execSql("CREATE TRIGGER delete_tagstree DELETE ON Tags\n"
1500
1566
                       "BEGIN\n"
1501
1567
                       " DELETE FROM Tags\n"
1502
1568
                       "   WHERE id  IN (SELECT id FROM TagsTree WHERE pid=OLD.id);\n"
1507
1573
                       "END;");
1508
1574
 
1509
1575
    // trigger: delete from TagsTree if Tag has been deleted
1510
 
    m_Backend->execSql("CREATE TRIGGER move_tagstree UPDATE OF pid ON Tags\n"
 
1576
    d->backend->execSql("CREATE TRIGGER move_tagstree UPDATE OF pid ON Tags\n"
1511
1577
                       "BEGIN\n"
1512
1578
                       "  DELETE FROM TagsTree\n"
1513
1579
                       "    WHERE\n"