+
+bool Core::migrateBackend(const QString &backend) {
+ AbstractSqlStorage *sqlStorage = qobject_cast<AbstractSqlStorage *>(_storage);
+ if(!sqlStorage) {
+ qWarning() << "Core::migrateDb(): only SQL based backends can be migrated!";
+ return false;
+ }
+
+ AbstractSqlMigrationReader *reader = sqlStorage->createMigrationReader();
+ if(!reader) {
+ qWarning() << qPrintable(QString("Core::migrateDb(): unable to migrate storage backend! (No migration reader for %1)").arg(sqlStorage->displayName()));
+ return false;
+ }
+
+
+ // reregister all storage backends
+ registerStorageBackends();
+ if(_storageBackends.contains(sqlStorage->displayName())) {
+ unregisterStorageBackend(_storageBackends[sqlStorage->displayName()]);
+ }
+ if(!_storageBackends.contains(backend)) {
+ qWarning() << qPrintable(QString("Core::migrateBackend(): unsupported migration target: %1").arg(backend));
+ qWarning() << " supported Targets:" << qPrintable(QStringList(_storageBackends.keys()).join(", "));
+ return false;
+ }
+
+ Storage *storage = _storageBackends[backend];
+ QVariantMap settings = promptForSettings(storage->setupKeys());
+
+ Storage::State storageState = storage->init(settings);
+ switch(storageState) {
+ case Storage::NotAvailable:
+ qCritical() << "Core::migrateBackend(): selected storage backend is not available:" << backend;
+ return false;
+ case Storage::NeedsSetup:
+ if(!storage->setup(settings)) {
+ qWarning() << qPrintable(QString("Core::migrateBackend(): unable to setup target: %1").arg(backend));
+ return false;
+ }
+
+ if(storage->init(settings) != Storage::IsReady) {
+ qWarning() << qPrintable(QString("Core::migrateBackend(): unable to initialize target: %1").arg(backend));
+ return false;
+ }
+ case Storage::IsReady:
+ break;
+ }
+
+ sqlStorage = qobject_cast<AbstractSqlStorage *>(storage);
+ if(!sqlStorage) {
+ qWarning() << "Core::migrateDb(): only SQL based backends can be migrated!";
+ return false;
+ }
+ AbstractSqlMigrationWriter *writer = sqlStorage->createMigrationWriter();
+ if(!writer) {
+ qWarning() << qPrintable(QString("Core::migrateDb(): unable to migrate storage backend! (No migration writer for %1)").arg(backend));
+ return false;
+ }
+
+ qDebug() << qPrintable(QString("Migrating Storage backend %1 to %2...").arg(_storage->displayName(), storage->displayName()));
+ delete _storage;
+ _storage = 0;
+ delete storage;
+ storage = 0;
+ if(reader->migrateTo(writer)) {
+ qDebug() << "Migration finished!";
+ saveBackendSettings(backend, settings);
+ return true;
+ }
+ return false;
+}
+
+bool Core::switchBackend(const QString &backend) {
+ if(!_storageBackends.contains(backend)) {
+ qWarning() << qPrintable(QString("Core::switchBackend(): unsupported backend: %1").arg(backend));
+ qWarning() << " supported backends:" << qPrintable(QStringList(_storageBackends.keys()).join(", "));
+ return false;
+ }
+
+ Storage *storage = _storageBackends[backend];
+ QVariantMap settings = promptForSettings(storage->setupKeys());
+
+ bool ok = initStorage(backend, settings, true /* initial setup is allowed */);
+ if(ok) {
+ saveBackendSettings(backend, settings);
+ qWarning() << "Switched backend to:" << qPrintable(backend);
+ } else {
+ qWarning() << "Failed to switch backend to:" << qPrintable(backend);
+ }
+ return ok;
+}
+
+void Core::saveBackendSettings(const QString &backend, const QVariantMap &settings) {
+ QVariantMap dbsettings;
+ dbsettings["Backend"] = backend;
+ dbsettings["ConnectionProperties"] = settings;
+ CoreSettings().setStorageSettings(dbsettings);
+}
+
+QVariantMap Core::promptForSettings(const QVariantMap &map) {
+ QVariantMap settings;
+ if(map.isEmpty())
+ return settings;
+
+ QTextStream out(stdout);
+ QTextStream in(stdin);
+ out << "!!!Warning: echo mode is always on even if asked for a password!!!" << endl;
+
+ QVariantMap::const_iterator iter;
+ QString value;
+ for(iter = map.constBegin(); iter != map.constEnd(); iter++) {
+ out << iter.key() << " (" << iter.value().toString() << "): ";
+ out.flush();
+ value = in.readLine();
+
+ if(value.isEmpty()) {
+ settings[iter.key()] = iter.value();
+ } else {
+ value = value.trimmed();
+ QVariant val;
+ switch(iter.value().type()) {
+ case QVariant::Int:
+ val = QVariant(value.toInt());
+ break;
+ default:
+ val = QVariant(value);
+ }
+ settings[iter.key()] = val;
+ }
+ }
+ return settings;
+}