File indexing completed on 2024-11-10 04:30:21
0001 /* 0002 * SPDX-FileCopyrightText: 2015-2016 Ivan Cukic <ivan.cukic@kde.org> 0003 * 0004 * SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL 0005 */ 0006 0007 #include "ResourcesDatabaseSchema.h" 0008 0009 #include <QCoreApplication> 0010 #include <QStandardPaths> 0011 #include <QVariant> 0012 0013 namespace Common 0014 { 0015 namespace ResourcesDatabaseSchema 0016 { 0017 0018 const QString name = QStringLiteral("Resources"); 0019 0020 QString version() 0021 { 0022 return QStringLiteral("2015.02.09"); 0023 } 0024 0025 QStringList schema() 0026 { 0027 // If only we could use initializer lists here ... 0028 0029 return QStringList() 0030 0031 << // Schema information table, used for versioning 0032 QStringLiteral( 0033 "CREATE TABLE IF NOT EXISTS SchemaInfo (" 0034 "key text PRIMARY KEY, value text" 0035 ")") 0036 0037 << QStringLiteral("INSERT OR IGNORE INTO schemaInfo VALUES ('version', '%1')").arg(version()) 0038 << QStringLiteral("UPDATE schemaInfo SET value = '%1' WHERE key = 'version'").arg(version()) 0039 0040 << // The ResourceEvent table saves the Opened/Closed event pairs for 0041 // a resource. The Accessed event is mapped to those. 0042 // Focusing events are not stored in order not to get a 0043 // huge database file and to lessen writes to the disk. 0044 QStringLiteral( 0045 "CREATE TABLE IF NOT EXISTS ResourceEvent (" 0046 "usedActivity TEXT, " 0047 "initiatingAgent TEXT, " 0048 "targettedResource TEXT, " 0049 "start INTEGER, " 0050 "end INTEGER " 0051 ")") 0052 0053 << // The ResourceScoreCache table stores the calculated scores 0054 // for resources based on the recorded events. 0055 QStringLiteral( 0056 "CREATE TABLE IF NOT EXISTS ResourceScoreCache (" 0057 "usedActivity TEXT, " 0058 "initiatingAgent TEXT, " 0059 "targettedResource TEXT, " 0060 "scoreType INTEGER, " 0061 "cachedScore FLOAT, " 0062 "firstUpdate INTEGER, " 0063 "lastUpdate INTEGER, " 0064 "PRIMARY KEY(usedActivity, initiatingAgent, targettedResource)" 0065 ")") 0066 0067 << // @since 2014.05.05 0068 // The ResourceLink table stores the information, formerly kept by 0069 // Nepomuk, of which resources are linked to which activities. 0070 // The additional features compared to the old days are 0071 // the ability to limit the link to specific applications, and 0072 // to create global links. 0073 QStringLiteral( 0074 "CREATE TABLE IF NOT EXISTS ResourceLink (" 0075 "usedActivity TEXT, " 0076 "initiatingAgent TEXT, " 0077 "targettedResource TEXT, " 0078 "PRIMARY KEY(usedActivity, initiatingAgent, targettedResource)" 0079 ")") 0080 0081 << // @since 2015.01.18 0082 // The ResourceInfo table stores the collected information about a 0083 // resource that is not agent nor activity related like the 0084 // title and the mime type. 0085 // If these are automatically retrieved (works for files), the 0086 // flag is set to true. This is done for the agents to be able to 0087 // override these. 0088 QStringLiteral( 0089 "CREATE TABLE IF NOT EXISTS ResourceInfo (" 0090 "targettedResource TEXT, " 0091 "title TEXT, " 0092 "mimetype TEXT, " 0093 "autoTitle INTEGER, " 0094 "autoMimetype INTEGER, " 0095 "PRIMARY KEY(targettedResource)" 0096 ")") 0097 0098 ; 0099 } 0100 0101 // TODO: This will require some refactoring after we introduce more databases 0102 QString defaultPath() 0103 { 0104 return QStandardPaths::writableLocation(QStandardPaths::GenericDataLocation) + QStringLiteral("/kactivitymanagerd/resources/database"); 0105 } 0106 0107 const char *overrideFlagProperty = "org.kde.KActivities.ResourcesDatabase.overrideDatabase"; 0108 const char *overrideFileProperty = "org.kde.KActivities.ResourcesDatabase.overrideDatabaseFile"; 0109 0110 QString path() 0111 { 0112 auto app = QCoreApplication::instance(); 0113 0114 return (app->property(overrideFlagProperty).toBool()) ? app->property(overrideFileProperty).toString() : defaultPath(); 0115 } 0116 0117 void overridePath(const QString &path) 0118 { 0119 auto app = QCoreApplication::instance(); 0120 0121 app->setProperty(overrideFlagProperty, true); 0122 app->setProperty(overrideFileProperty, path); 0123 } 0124 0125 void initSchema(Database &database) 0126 { 0127 QString dbSchemaVersion; 0128 0129 auto query = database.execQuery(QStringLiteral("SELECT value FROM SchemaInfo WHERE key = 'version'"), 0130 /* ignore error */ true); 0131 0132 if (query.next()) { 0133 dbSchemaVersion = query.value(0).toString(); 0134 } 0135 0136 // Early bail-out if the schema is up-to-date 0137 if (dbSchemaVersion == version()) { 0138 return; 0139 } 0140 0141 // Transition to KF5: 0142 // We left the world of Nepomuk, and all the ontologies went 0143 // across the sea to the Undying Lands. 0144 // This needs to be done before executing the schema() queries 0145 // so that we do not create new (empty) tables and block these 0146 // queries from being executed. 0147 if (dbSchemaVersion < QStringLiteral("2014.04.14")) { 0148 database.execQuery(QStringLiteral("ALTER TABLE nuao_DesktopEvent RENAME TO ResourceEvent"), 0149 /* ignore error */ true); 0150 database.execQuery(QStringLiteral("ALTER TABLE kext_ResourceScoreCache RENAME TO ResourceScoreCache"), 0151 /* ignore error */ true); 0152 } 0153 0154 database.execQueries(ResourcesDatabaseSchema::schema()); 0155 0156 // We can not allow empty fields for activity and agent, they need to 0157 // be at least magic values. These do not change the structure 0158 // of the database, but the old data. 0159 if (dbSchemaVersion < QStringLiteral("2015.02.09")) { 0160 const QString updateActivity = QStringLiteral( 0161 "SET usedActivity=':global' " 0162 "WHERE usedActivity IS NULL OR usedActivity = ''"); 0163 0164 const QString updateAgent = QStringLiteral( 0165 "SET initiatingAgent=':global' " 0166 "WHERE initiatingAgent IS NULL OR initiatingAgent = ''"); 0167 0168 // When the activity field was empty, it meant the file was 0169 // linked to all activities (aka :global) 0170 database.execQuery("UPDATE ResourceLink " + updateActivity); 0171 0172 // When the agent field was empty, it meant the file was not 0173 // linked to a specified agent (aka :global) 0174 database.execQuery("UPDATE ResourceLink " + updateAgent); 0175 0176 // These were not supposed to be empty, but in the case they were, 0177 // deal with them as well 0178 database.execQuery("UPDATE ResourceEvent " + updateActivity); 0179 database.execQuery("UPDATE ResourceEvent " + updateAgent); 0180 database.execQuery("UPDATE ResourceScoreCache " + updateActivity); 0181 database.execQuery("UPDATE ResourceScoreCache " + updateAgent); 0182 } 0183 } 0184 0185 } // namespace Common 0186 } // namespace ResourcesDatabaseSchema