1 /*
2 * Copyright (c) 2023 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 "relational_sync_data_inserter.h"
17 #include "data_transformer.h"
18 #include "db_common.h"
19 #include "sqlite_utils.h"
20
21 namespace DistributedDB {
ResetStatements(bool isNeedFinalize)22 int SaveSyncDataStmt::ResetStatements(bool isNeedFinalize)
23 {
24 int errCode = E_OK;
25 if (saveDataStmt != nullptr) {
26 SQLiteUtils::ResetStatement(saveDataStmt, isNeedFinalize, errCode);
27 }
28 if (saveLogStmt != nullptr) {
29 SQLiteUtils::ResetStatement(saveLogStmt, isNeedFinalize, errCode);
30 }
31 if (queryStmt != nullptr) {
32 SQLiteUtils::ResetStatement(queryStmt, isNeedFinalize, errCode);
33 }
34 if (rmDataStmt != nullptr) {
35 SQLiteUtils::ResetStatement(rmDataStmt, isNeedFinalize, errCode);
36 }
37 if (rmLogStmt != nullptr) {
38 SQLiteUtils::ResetStatement(rmLogStmt, isNeedFinalize, errCode);
39 }
40 return errCode;
41 }
42
RelationalSyncDataInserter()43 RelationalSyncDataInserter::RelationalSyncDataInserter()
44 {
45 }
46
~RelationalSyncDataInserter()47 RelationalSyncDataInserter::~RelationalSyncDataInserter()
48 {
49 }
50
CreateInserter(const std::string & deviceName,const QueryObject & query,const RelationalSchemaObject & localSchema,const std::vector<FieldInfo> & remoteFields,const StoreInfo & info)51 RelationalSyncDataInserter RelationalSyncDataInserter::CreateInserter(const std::string &deviceName,
52 const QueryObject &query, const RelationalSchemaObject &localSchema, const std::vector<FieldInfo> &remoteFields,
53 const StoreInfo &info)
54 {
55 RelationalSyncDataInserter inserter;
56 inserter.SetHashDevId(DBCommon::TransferStringToHex(DBCommon::TransferHashString(deviceName)));
57 inserter.SetRemoteFields(remoteFields);
58 inserter.SetQuery(query);
59 TableInfo localTable = localSchema.GetTable(query.GetTableName());
60 inserter.SetLocalTable(localTable);
61 inserter.SetTableMode(localSchema.GetTableMode());
62 if (localSchema.GetTableMode() == DistributedTableMode::COLLABORATION) {
63 inserter.SetInsertTableName(localTable.GetTableName());
64 } else {
65 inserter.SetInsertTableName(DBCommon::GetDistributedTableName(deviceName, localTable.GetTableName(), info));
66 }
67 return inserter;
68 }
69
SetHashDevId(const std::string & hashDevId)70 void RelationalSyncDataInserter::SetHashDevId(const std::string &hashDevId)
71 {
72 hashDevId_ = hashDevId;
73 }
74
SetRemoteFields(std::vector<FieldInfo> remoteFields)75 void RelationalSyncDataInserter::SetRemoteFields(std::vector<FieldInfo> remoteFields)
76 {
77 remoteFields_ = std::move(remoteFields);
78 }
79
SetEntries(std::vector<DataItem> entries)80 void RelationalSyncDataInserter::SetEntries(std::vector<DataItem> entries)
81 {
82 entries_ = std::move(entries);
83 }
84
SetLocalTable(TableInfo localTable)85 void RelationalSyncDataInserter::SetLocalTable(TableInfo localTable)
86 {
87 localTable_ = std::move(localTable);
88 }
89
GetLocalTable() const90 const TableInfo &RelationalSyncDataInserter::GetLocalTable() const
91 {
92 return localTable_;
93 }
94
SetQuery(QueryObject query)95 void RelationalSyncDataInserter::SetQuery(QueryObject query)
96 {
97 query_ = std::move(query);
98 }
99
SetInsertTableName(std::string tableName)100 void RelationalSyncDataInserter::SetInsertTableName(std::string tableName)
101 {
102 insertTableName_ = std::move(tableName);
103 }
104
SetTableMode(DistributedTableMode mode)105 void RelationalSyncDataInserter::SetTableMode(DistributedTableMode mode)
106 {
107 mode_ = mode;
108 }
109
GetInsertStatement(sqlite3 * db,sqlite3_stmt * & stmt)110 int RelationalSyncDataInserter::GetInsertStatement(sqlite3 *db, sqlite3_stmt *&stmt)
111 {
112 if (stmt != nullptr) {
113 return -E_INVALID_ARGS;
114 }
115
116 const auto &localTableFields = localTable_.GetFields();
117 std::string colName;
118 std::string dataFormat;
119 for (const auto &it : remoteFields_) {
120 if (localTableFields.find(it.GetFieldName()) == localTableFields.end()) {
121 continue; // skip fields which is orphaned in remote
122 }
123 colName += "'" + it.GetFieldName() + "',";
124 dataFormat += "?,";
125 }
126 colName.pop_back();
127 dataFormat.pop_back();
128
129 const std::string sql = "INSERT OR REPLACE INTO '" + insertTableName_ + "'" +
130 " (" + colName + ") VALUES (" + dataFormat + ");";
131 int errCode = SQLiteUtils::GetStatement(db, sql, stmt);
132 if (errCode != E_OK) {
133 LOGE("Get saving data statement fail! errCode:%d", errCode);
134 }
135 return errCode;
136 }
137
BindInsertStatement(sqlite3_stmt * stmt,const DataItem & dataItem)138 int RelationalSyncDataInserter::BindInsertStatement(sqlite3_stmt *stmt, const DataItem &dataItem)
139 {
140 if (stmt == nullptr) {
141 return -E_INVALID_ARGS;
142 }
143
144 OptRowDataWithLog data;
145 // deserialize by remote field info
146 int errCode = DataTransformer::DeSerializeDataItem(dataItem, data, remoteFields_);
147 if (errCode != E_OK) {
148 LOGE("DeSerialize dataItem failed! errCode = [%d]", errCode);
149 return errCode;
150 }
151
152 size_t dataIdx = 0;
153 int bindIdx = 1;
154 const auto &localTableFields = localTable_.GetFields();
155 for (const auto &it : remoteFields_) {
156 if (localTableFields.find(it.GetFieldName()) == localTableFields.end()) {
157 LOGD("field %s not found in local schema.", it.GetFieldName().c_str());
158 dataIdx++;
159 continue; // skip fields which is orphaned in remote
160 }
161 if (dataIdx >= data.optionalData.size()) {
162 LOGD("field over size. cnt:%d, data size:%d", dataIdx, data.optionalData.size());
163 break; // cnt should less then optionalData size.
164 }
165 errCode = SQLiteUtils::BindDataValueByType(stmt, data.optionalData[dataIdx], bindIdx++);
166 if (errCode != E_OK) {
167 LOGE("Bind data failed, errCode:%d, cid:%zu.", errCode, dataIdx);
168 return errCode;
169 }
170 dataIdx++;
171 }
172
173 return E_OK;
174 }
175
GetDeleteLogStmt(sqlite3 * db,sqlite3_stmt * & stmt)176 int RelationalSyncDataInserter::GetDeleteLogStmt(sqlite3 *db, sqlite3_stmt *&stmt)
177 {
178 std::string sql = "DELETE FROM " + DBConstant::RELATIONAL_PREFIX + localTable_.GetTableName() + "_log ";
179 if (mode_ == DistributedTableMode::COLLABORATION) {
180 sql += "WHERE hash_key=?";
181 } else {
182 sql += "WHERE hash_key=? AND device=?";
183 }
184
185 int errCode = SQLiteUtils::GetStatement(db, sql, stmt);
186 if (errCode != E_OK) {
187 LOGE("[DeleteSyncLog] Get statement fail!");
188 }
189 return errCode;
190 }
191
GetDeleteSyncDataStmt(sqlite3 * db,sqlite3_stmt * & stmt)192 int RelationalSyncDataInserter::GetDeleteSyncDataStmt(sqlite3 *db, sqlite3_stmt *&stmt)
193 {
194 std::string sql = "DELETE FROM '" + insertTableName_ + "' WHERE " + std::string(DBConstant::SQLITE_INNER_ROWID) +
195 " IN (SELECT data_key FROM " + DBConstant::RELATIONAL_PREFIX + localTable_.GetTableName() + "_log ";
196 if (mode_ == DistributedTableMode::COLLABORATION) {
197 sql += "WHERE hash_key=?);";
198 } else {
199 sql += "WHERE hash_key=? AND device=? AND flag&0x01=0);";
200 }
201 int errCode = SQLiteUtils::GetStatement(db, sql, stmt);
202 if (errCode != E_OK) {
203 LOGE("[DeleteSyncDataItem] Get statement fail!, errCode:%d", errCode);
204 }
205 return errCode;
206 }
207
GetSaveLogStatement(sqlite3 * db,sqlite3_stmt * & logStmt,sqlite3_stmt * & queryStmt)208 int RelationalSyncDataInserter::GetSaveLogStatement(sqlite3 *db, sqlite3_stmt *&logStmt, sqlite3_stmt *&queryStmt)
209 {
210 const std::string tableName = DBConstant::RELATIONAL_PREFIX + query_.GetTableName() + "_log";
211 std::string dataFormat = "?, '" + hashDevId_ + "', ?, ?, ?, ?, ?";
212 std::string columnList = "data_key, device, ori_device, timestamp, wtimestamp, flag, hash_key";
213 std::string sql = "INSERT OR REPLACE INTO " + tableName +
214 " (" + columnList + ") VALUES (" + dataFormat + ");";
215 int errCode = SQLiteUtils::GetStatement(db, sql, logStmt);
216 if (errCode != E_OK) {
217 LOGE("[info statement] Get log statement fail! errCode:%d", errCode);
218 return errCode;
219 }
220 std::string selectSql = "select " + columnList + " from " + tableName;
221 if (mode_ == DistributedTableMode::COLLABORATION) {
222 selectSql += " where hash_key = ?;";
223 } else {
224 selectSql += " where hash_key = ? and device = ?;";
225 }
226 errCode = SQLiteUtils::GetStatement(db, selectSql, queryStmt);
227 if (errCode != E_OK) {
228 SQLiteUtils::ResetStatement(logStmt, true, errCode);
229 LOGE("[info statement] Get query statement fail! errCode:%d", errCode);
230 }
231 return errCode;
232 }
233
PrepareStatement(sqlite3 * db,SaveSyncDataStmt & stmt)234 int RelationalSyncDataInserter::PrepareStatement(sqlite3 *db, SaveSyncDataStmt &stmt)
235 {
236 int errCode = GetSaveLogStatement(db, stmt.saveLogStmt, stmt.queryStmt);
237 if (errCode != E_OK) {
238 LOGE("Get save log statement failed. err=%d", errCode);
239 return errCode;
240 }
241 errCode = GetInsertStatement(db, stmt.saveDataStmt);
242 if (errCode != E_OK) {
243 LOGE("Get insert statement failed. err=%d", errCode);
244 }
245 return errCode;
246 }
247
Iterate(const std::function<int (DataItem &)> & saveSyncDataItem)248 int RelationalSyncDataInserter::Iterate(const std::function<int (DataItem &)> &saveSyncDataItem)
249 {
250 int errCode = E_OK;
251 for (auto &it : entries_) {
252 it.dev = hashDevId_;
253 errCode = saveSyncDataItem(it);
254 if (errCode != E_OK) {
255 LOGE("Save sync data item failed. err=%d", errCode);
256 break;
257 }
258 }
259 return errCode;
260 }
261 } // namespace DistributedDB