1 /*
2 * Copyright (c) 2021 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_single_ver_schema_database_upgrader.h"
17 #include "db_errno.h"
18 #include "log_print.h"
19 #include "schema_utils.h"
20 #include "db_constant.h"
21
22 namespace DistributedDB {
SQLiteSingleVerSchemaDatabaseUpgrader(sqlite3 * db,const SchemaObject & newSchema,const SecurityOption & securityOpt,bool isMemDB)23 SQLiteSingleVerSchemaDatabaseUpgrader::SQLiteSingleVerSchemaDatabaseUpgrader(sqlite3 *db,
24 const SchemaObject &newSchema, const SecurityOption &securityOpt, bool isMemDB)
25 : SQLiteSingleVerDatabaseUpgrader(db, securityOpt, isMemDB), SingleVerSchemaDatabaseUpgrader(newSchema)
26 {
27 }
28
GetDatabaseSchema(std::string & dbSchema) const29 int SQLiteSingleVerSchemaDatabaseUpgrader::GetDatabaseSchema(std::string &dbSchema) const
30 {
31 int errCode = SQLiteUtils::GetSchema(db_, dbSchema);
32 if (errCode != E_OK && errCode != -E_NOT_FOUND) {
33 LOGE("[SqlSingleSchemaUp][GetSchema] ErrCode=%d", errCode);
34 return errCode;
35 }
36 return E_OK;
37 }
38
SetDatabaseSchema(const std::string & dbSchema)39 int SQLiteSingleVerSchemaDatabaseUpgrader::SetDatabaseSchema(const std::string &dbSchema)
40 {
41 int errCode = SQLiteUtils::SaveSchema(db_, dbSchema);
42 if (errCode != E_OK) {
43 LOGE("[SqlSingleSchemaUp][SetSchema] ErrCode=%d", errCode);
44 }
45 return errCode;
46 }
47
48 struct ValueUpgradeContext {
49 SchemaObject schema;
50 uint32_t checkCount = 0;
51 uint32_t getCount = 0;
52 int errCode = E_OK;
53 };
54
55 namespace {
56 const std::string FUNC_NAME_CHECK_AMEND_VALUE = "check_amend_value";
57 const std::string FUNC_NAME_GET_AMENDED_VALUE = "get_amended_value";
58 // Current implementation is not of ideal performance: at first, we hope to use check_amend_value to filter out values
59 // that do not need amend, and call get_amended_value immediately for those value that need amend and obtain amended
60 // value from ValueUpgradeContext which is cache by check_amend_value just before. It works well for case upgrading from
61 // kv to schema database, but in the case the original schema having index, the sqlite will gather all rowid of values
62 // that after filtering at first, then call get_amended_value for each value of rowid later.
63 // Finally we can only parse value the twice in get_amended_value.
64 const std::string VALUE_UPGRADE_SQL = "UPDATE sync_data SET value=get_amended_value(value) "
65 "WHERE (flag&0x01=0) AND check_amend_value(value) != 0;";
66 constexpr int USING_STR_LEN = -1;
67
CheckGetForJsonSchema(sqlite3_context * ctx,ValueUpgradeContext & context,const RawValue & inValue,bool checkTrueGetFalse)68 void CheckGetForJsonSchema(sqlite3_context *ctx, ValueUpgradeContext &context, const RawValue &inValue,
69 bool checkTrueGetFalse)
70 {
71 ValueObject valueObj;
72 int errCode = valueObj.Parse(inValue.first, inValue.first + inValue.second, context.schema.GetSkipSize());
73 if (errCode != E_OK) { // Unlikely
74 sqlite3_result_error(ctx, "[SqlSingleSchemaUp][CheckGet] Json value parse fail.", USING_STR_LEN);
75 LOGE("[SqlSingleSchemaUp][CheckGet] IsCheck=%d, Json value(cnt=%u) parse fail=%d.", checkTrueGetFalse,
76 (checkTrueGetFalse ? context.checkCount : context.getCount), errCode);
77 return;
78 }
79 errCode = context.schema.CheckValueAndAmendIfNeed(ValueSource::FROM_DBFILE, valueObj);
80 if (checkTrueGetFalse) {
81 if (errCode == -E_VALUE_MATCH) {
82 sqlite3_result_int(ctx, 0); // SQLiteResult 0 for check_ok_no_amend
83 } else if (errCode == -E_VALUE_MATCH_AMENDED) {
84 sqlite3_result_int(ctx, E_VALUE_MATCH_AMENDED); // SQLiteResult not 0 for check_ok_and_amend
85 } else {
86 sqlite3_result_error(ctx, "[SqlSingleSchemaUp][CheckGet] Json value check fail.", USING_STR_LEN);
87 LOGE("[SqlSingleSchemaUp][CheckGet] Json value(cnt=%u) check fail=%d.", context.checkCount, errCode);
88 context.errCode = -E_SCHEMA_VIOLATE_VALUE;
89 }
90 } else {
91 if (errCode != -E_VALUE_MATCH_AMENDED) { // Unlikely
92 sqlite3_result_error(ctx, "[SqlSingleSchemaUp][CheckGet] Json value no need amend.", USING_STR_LEN);
93 LOGE("[SqlSingleSchemaUp][CheckGet] Json value(cnt=%u) no need amend=%d.", context.getCount, errCode);
94 context.errCode = -E_INTERNAL_ERROR;
95 }
96 std::vector<uint8_t> valueAmended;
97 valueObj.WriteIntoVector(valueAmended);
98 if (valueAmended.size() > DBConstant::MAX_VALUE_SIZE) {
99 sqlite3_result_error(ctx, "[SqlSingleSchemaUp][CheckGet] ValSize exceed limit after amend.", USING_STR_LEN);
100 LOGE("[SqlSingleSchemaUp][CheckGet] Value(cnt=%u) size=%zu exceed limit after amend.", context.getCount,
101 valueAmended.size());
102 context.errCode = -E_SCHEMA_VIOLATE_VALUE;
103 return;
104 }
105 // For SQLITE_TRANSIENT, SQLite makes a copy of result into space obtained from sqlite3_malloc before it returns
106 sqlite3_result_blob(ctx, valueAmended.data(), valueAmended.size(), SQLITE_TRANSIENT);
107 }
108 }
109
CheckGetForFlatBufferSchema(sqlite3_context * ctx,ValueUpgradeContext & context,const RawValue & inValue,bool checkTrueGetFalse)110 void CheckGetForFlatBufferSchema(sqlite3_context *ctx, ValueUpgradeContext &context, const RawValue &inValue,
111 bool checkTrueGetFalse)
112 {
113 if (!checkTrueGetFalse) {
114 sqlite3_result_error(ctx, "[SqlSingleSchemaUp][CheckGet] FlatBuffer value no need amend.", USING_STR_LEN);
115 LOGE("[SqlSingleSchemaUp][CheckGet] FlatBuffer value(cnt=%u) no need amend.", context.getCount);
116 context.errCode = -E_INTERNAL_ERROR;
117 }
118 int errCode = context.schema.VerifyValue(ValueSource::FROM_DBFILE, inValue);
119 if (errCode != E_OK) {
120 sqlite3_result_error(ctx, "[SqlSingleSchemaUp][CheckGet] FlatBuffer value verify fail.", USING_STR_LEN);
121 LOGE("[SqlSingleSchemaUp][CheckGet] FlatBuffer value(cnt=%u) verify fail=%d.", context.checkCount, errCode);
122 context.errCode = -E_SCHEMA_VIOLATE_VALUE;
123 return;
124 }
125 sqlite3_result_int(ctx, 0); // SQLiteResult 0 for check_ok_no_amend
126 }
127
128 // SQLiteResult 0 for check_ok_no_amend, SQLiteResult not 0 for check_ok_and_amend, SQLiteResult error for check_fail
CheckValueOrGetAmendValue(sqlite3_context * ctx,int argc,sqlite3_value ** argv,bool checkTrueGetFalse)129 void CheckValueOrGetAmendValue(sqlite3_context *ctx, int argc, sqlite3_value **argv, bool checkTrueGetFalse)
130 {
131 if (ctx == nullptr || argc != 1 || argv == nullptr) { // 1 parameters, which are value. Unlikely
132 LOGE("[SqlSingleSchemaUp][CheckGet] Invalid parameter, argc=%d.", argc);
133 return;
134 }
135 auto context = static_cast<ValueUpgradeContext *>(sqlite3_user_data(ctx));
136 if (context == nullptr || !context->schema.IsSchemaValid()) { // Unlikely
137 sqlite3_result_error(ctx, "[SqlSingleSchemaUp][CheckGet] No context or schema invalid.", USING_STR_LEN);
138 LOGE("[SqlSingleSchemaUp][CheckGet] No context or schema invalid.");
139 return;
140 }
141 auto valueBlob = static_cast<const uint8_t *>(sqlite3_value_blob(argv[0]));
142 int valueBlobLen = sqlite3_value_bytes(argv[0]);
143 if ((valueBlob == nullptr) || (valueBlobLen <= 0)) { // Is delete record, Unlikely
144 // Currently delete records are filtered out of value upgrade sql, so not allowed here.
145 sqlite3_result_error(ctx, "[SqlSingleSchemaUp][CheckGet] Delete record not allowed.", USING_STR_LEN);
146 LOGE("[SqlSingleSchemaUp][CheckGet] Delete record not allowed.");
147 return;
148 }
149
150 if (context->schema.GetSchemaType() == SchemaType::JSON) {
151 CheckGetForJsonSchema(ctx, *context, RawValue{valueBlob, valueBlobLen}, checkTrueGetFalse);
152 } else {
153 CheckGetForFlatBufferSchema(ctx, *context, RawValue{valueBlob, valueBlobLen}, checkTrueGetFalse);
154 }
155 // Count only for non-delete value in check_func or get_func
156 if (checkTrueGetFalse) {
157 context->checkCount++;
158 } else {
159 context->getCount++;
160 }
161 }
162
CheckAmendValue(sqlite3_context * ctx,int argc,sqlite3_value ** argv)163 void CheckAmendValue(sqlite3_context *ctx, int argc, sqlite3_value **argv)
164 {
165 CheckValueOrGetAmendValue(ctx, argc, argv, true);
166 }
167
GetAmendedValue(sqlite3_context * ctx,int argc,sqlite3_value ** argv)168 void GetAmendedValue(sqlite3_context *ctx, int argc, sqlite3_value **argv)
169 {
170 CheckValueOrGetAmendValue(ctx, argc, argv, false);
171 }
172 }
173
UpgradeValues()174 int SQLiteSingleVerSchemaDatabaseUpgrader::UpgradeValues()
175 {
176 ValueUpgradeContext context;
177 context.schema = newSchema_;
178 LOGD("[SqlSingleSchemaUp][UpValue] Begin.");
179 int errCode = sqlite3_create_function_v2(db_, FUNC_NAME_CHECK_AMEND_VALUE.c_str(),
180 1, SQLITE_UTF8 | SQLITE_DETERMINISTIC, &context, &CheckAmendValue, nullptr, nullptr, nullptr); // 1 args
181 if (errCode != SQLITE_OK) {
182 LOGE("[SqlSingleSchemaUp][UpValue] Create func=check_amend_value return=%d.", errCode);
183 return SQLiteUtils::MapSQLiteErrno(errCode);
184 }
185 // GetAmendedValue is better not be of deterministic type, otherwise sqlite may take it as constant
186 errCode = sqlite3_create_function_v2(db_, FUNC_NAME_GET_AMENDED_VALUE.c_str(),
187 1, SQLITE_UTF8, &context, &GetAmendedValue, nullptr, nullptr, nullptr); // 1 args
188 if (errCode != SQLITE_OK) {
189 LOGE("[SqlSingleSchemaUp][UpValue] Create func=get_amended_value return=%d.", errCode);
190 return SQLiteUtils::MapSQLiteErrno(errCode);
191 }
192 errCode = SQLiteUtils::ExecuteRawSQL(db_, VALUE_UPGRADE_SQL);
193 if (errCode != E_OK) {
194 LOGE("[SqlSingleSchemaUp][UpValue] Execute value upgrade fail=%d, contextErr=%d.", errCode, context.errCode);
195 // If error caused by upgrade nor sqlite, using contextErr as the final errCode
196 errCode = ((context.errCode == E_OK ? errCode : context.errCode));
197 }
198 LOGD("[SqlSingleSchemaUp][UpValue] End.");
199 return errCode;
200 }
201
UpgradeIndexes(const IndexDifference & indexDiffer)202 int SQLiteSingleVerSchemaDatabaseUpgrader::UpgradeIndexes(const IndexDifference &indexDiffer)
203 {
204 uint32_t skipSize = newSchema_.GetSkipSize();
205 SchemaType theType = newSchema_.GetSchemaType();
206 // The order of index upgrade is not compulsory, we think order "decrease, change, increase" may be better.
207 LOGD("[SqlSingleSchemaUp][UpIndex] DecreaseIndex: %zu, ChangeIndex: %zu, IncreaseIndex: %zu",
208 indexDiffer.decrease.size(), indexDiffer.change.size(), indexDiffer.increase.size());
209 for (const auto &entry : indexDiffer.decrease) {
210 int errCode = SQLiteUtils::DecreaseIndex(db_, entry);
211 if (errCode != E_OK) {
212 LOGE("[SqlSingleSchemaUp][UpIndex] DecreaseIndex fail, errCode=%d.", errCode);
213 return errCode;
214 }
215 }
216 for (const auto &entry : indexDiffer.change) {
217 int errCode = SQLiteUtils::ChangeIndex(db_, entry.first, entry.second, theType, skipSize);
218 if (errCode != E_OK) {
219 LOGE("[SqlSingleSchemaUp][UpIndex] ChangeIndex fail, errCode=%d.", errCode);
220 return errCode;
221 }
222 }
223 for (const auto &entry : indexDiffer.increase) {
224 int errCode = SQLiteUtils::IncreaseIndex(db_, entry.first, entry.second, theType, skipSize);
225 if (errCode != E_OK) {
226 LOGE("[SqlSingleSchemaUp][UpIndex] IncreaseIndex fail, errCode=%d.", errCode);
227 return errCode;
228 }
229 }
230 return E_OK;
231 }
232 } // namespace DistributedDB
233