1 /*
2 * Copyright (c) 2022 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include "sqlite_relational_database_upgrader.h"
17
18 #include "db_constant.h"
19 #include "db_errno.h"
20 #include "relational_schema_object.h"
21 #include "log_table_manager_factory.h"
22
23 namespace DistributedDB {
SqliteRelationalDatabaseUpgrader(sqlite3 * db)24 SqliteRelationalDatabaseUpgrader::SqliteRelationalDatabaseUpgrader(sqlite3 *db)
25 : db_(db)
26 {}
27
~SqliteRelationalDatabaseUpgrader()28 SqliteRelationalDatabaseUpgrader::~SqliteRelationalDatabaseUpgrader() {}
29
Upgrade()30 int SqliteRelationalDatabaseUpgrader::Upgrade()
31 {
32 int errCode = BeginUpgrade();
33 if (errCode != E_OK) {
34 LOGE("[Relational][Upgrade] Begin upgrade failed. err=%d", errCode);
35 return errCode;
36 }
37
38 errCode = ExecuteUpgrade();
39 if (errCode != E_OK) {
40 LOGE("[Relational][Upgrade] Execute upgrade failed. err=%d", errCode);
41 (void)EndUpgrade(false);
42 return errCode;
43 }
44
45 errCode = EndUpgrade(true);
46 if (errCode != E_OK) {
47 LOGE("[Relational][Upgrade] End upgrade failed. err=%d", errCode);
48 }
49 return errCode;
50 }
51
BeginUpgrade()52 int SqliteRelationalDatabaseUpgrader::BeginUpgrade()
53 {
54 return SQLiteUtils::BeginTransaction(db_, TransactType::IMMEDIATE);
55 }
56
ExecuteUpgrade()57 int SqliteRelationalDatabaseUpgrader::ExecuteUpgrade()
58 {
59 std::string logTableVersion;
60 int errCode = SQLiteUtils::GetLogTableVersion(db_, logTableVersion);
61 if (errCode != E_OK) {
62 LOGW("[Relational][Upgrade] Get log table version return %d", errCode);
63 return (errCode == -E_NOT_FOUND) ? E_OK : errCode;
64 }
65
66 errCode = UpgradeLogTable(logTableVersion);
67 if (errCode != E_OK) {
68 LOGE("[Relational][Upgrade] Upgrade log table failed, err = %d.", errCode);
69 return errCode;
70 }
71
72 return UpgradeTrigger(logTableVersion);
73 }
74
EndUpgrade(bool isSuccess)75 int SqliteRelationalDatabaseUpgrader::EndUpgrade(bool isSuccess)
76 {
77 if (isSuccess) {
78 return SQLiteUtils::CommitTransaction(db_);
79 }
80
81 return SQLiteUtils::RollbackTransaction(db_);
82 }
83
IsNewestVersion(const std::string & logTableVersion)84 bool SqliteRelationalDatabaseUpgrader::IsNewestVersion(const std::string &logTableVersion)
85 {
86 return logTableVersion == DBConstant::LOG_TABLE_VERSION_CURRENT;
87 }
88
UpgradeTrigger(const std::string & logTableVersion)89 int SqliteRelationalDatabaseUpgrader::UpgradeTrigger(const std::string &logTableVersion)
90 {
91 if (IsNewestVersion(logTableVersion)) {
92 LOGD("[Relational][Upgrade] No need upgrade trigger.");
93 return E_OK;
94 }
95
96 // get schema from meta
97 std::string schemaDefine;
98 int errCode = SQLiteUtils::GetRelationalSchema(db_, schemaDefine);
99 if (errCode != E_OK) {
100 LOGW("[Relational][Upgrade] Get relational schema from meta return %d.", errCode);
101 return (errCode == -E_NOT_FOUND) ? E_OK : errCode;
102 }
103
104 RelationalSchemaObject schemaObject;
105 errCode = schemaObject.ParseFromSchemaString(schemaDefine);
106 if (errCode != E_OK) {
107 LOGE("[Relational][Upgrade] Parse to relational schema failed.", errCode);
108 return errCode;
109 }
110
111 DistributedTableMode mode = schemaObject.GetTableMode();
112 for (const auto &[tableName, tableInfo] : schemaObject.GetTables()) {
113 std::string dropTriggerSql = "DROP TRIGGER IF EXISTS " + DBConstant::SYSTEM_TABLE_PREFIX + tableName +
114 "_ON_UPDATE";
115 errCode = SQLiteUtils::ExecuteRawSQL(db_, dropTriggerSql);
116 if (errCode != E_OK) {
117 LOGE("[Relational][Upgrade] drop trigger failed.", errCode);
118 return errCode;
119 }
120 auto manager = LogTableManagerFactory::GetTableManager(mode, tableInfo.GetTableSyncType());
121 errCode = manager->AddRelationalLogTableTrigger(db_, tableInfo, "");
122 if (errCode != E_OK) {
123 LOGE("[Relational][Upgrade] recreate trigger failed.", errCode);
124 return errCode;
125 }
126 }
127 return E_OK;
128 }
129
NoNeedUpdateLogTable(const std::string & logTableVersion)130 static bool inline NoNeedUpdateLogTable(const std::string &logTableVersion)
131 {
132 return logTableVersion > DBConstant::LOG_TABLE_VERSION_2;
133 }
134
UpgradeLogTable(const std::string & logTableVersion)135 int SqliteRelationalDatabaseUpgrader::UpgradeLogTable(const std::string &logTableVersion)
136 {
137 if (NoNeedUpdateLogTable(logTableVersion)) {
138 LOGD("[Relational][Upgrade] No need upgrade log table.");
139 return E_OK;
140 }
141
142 // get schema from meta
143 std::string schemaDefine;
144 int errCode = SQLiteUtils::GetRelationalSchema(db_, schemaDefine);
145 if (errCode != E_OK) {
146 LOGW("[Relational][UpgradeLogTable] Get relational schema from meta return %d.", errCode);
147 return (errCode == -E_NOT_FOUND) ? E_OK : errCode;
148 }
149
150 RelationalSchemaObject schemaObject;
151 errCode = schemaObject.ParseFromSchemaString(schemaDefine);
152 if (errCode != E_OK) {
153 LOGE("[Relational][UpgradeLogTable] Parse to relational schema failed.", errCode);
154 return errCode;
155 }
156
157 for (const auto &item : schemaObject.GetTables()) {
158 std::string addColumnSql = "alter table " + DBConstant::RELATIONAL_PREFIX + item.first +
159 "_log add cloud_gid text after hash_key;";
160 errCode = SQLiteUtils::ExecuteRawSQL(db_, addColumnSql);
161 if (errCode != E_OK) {
162 LOGE("[Relational][UpgradeLogTable] add column failed.", errCode);
163 return errCode;
164 }
165 }
166 return E_OK;
167 }
168 } // namespace DistributedDB