1 /*
2 * Copyright (c) 2021-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 "merger_contacts.h"
17
18 #include "common.h"
19 #include "contacts_columns.h"
20 #include "contacts_database.h"
21 #include "hilog_wrapper.h"
22 #include "match_candidate.h"
23 #include "merge_utils.h"
24
25 namespace OHOS {
26 namespace Contacts {
27 static int g_isNeedMergeNum[2] = {0, 1};
28 static int g_isNeedMergeTargetNum[2] = {0, 1};
29
MergerContacts()30 MergerContacts::MergerContacts()
31 {
32 }
33
~MergerContacts()34 MergerContacts::~MergerContacts()
35 {
36 }
37
38 /**
39 * @brief AutoMerge operation for candidate contacts
40 *
41 * @param store Conditions for split operation
42 *
43 * @return The result returned by the AutoMerge operation
44 */
ContactMerge(std::shared_ptr<OHOS::NativeRdb::RdbStore> store)45 int MergerContacts::ContactMerge(std::shared_ptr<OHOS::NativeRdb::RdbStore> store)
46 {
47 if (store == nullptr) {
48 HILOG_ERROR("store is empty");
49 return RDB_OBJECT_EMPTY;
50 }
51 HILOG_INFO("MergerContacts::ContactMerge is starting");
52 // query all ids with merge_mode = 2
53 std::vector<std::set<int>> candidates = QueryMergeContacts(store, MERGE_MODE_AUTO);
54 int ret = MergeCircle(store, candidates);
55 return ret;
56 }
57
MergeCircle(std::shared_ptr<OHOS::NativeRdb::RdbStore> store,std::vector<std::set<int>> candidates)58 int MergerContacts::MergeCircle(std::shared_ptr<OHOS::NativeRdb::RdbStore> store, std::vector<std::set<int>> candidates)
59 {
60 if (candidates.empty()) {
61 HILOG_ERROR("Merge candidate is empty");
62 return RDB_EXECUTE_FAIL;
63 }
64 bool isModeHasError = false;
65 for (auto it = candidates.begin(); it != candidates.end(); ++it) {
66 std::set<int> ids = *it;
67 if (ids.size() == 1) {
68 HILOG_ERROR("MergeCircle continue ");
69 isModeHasError = true;
70 continue;
71 }
72 auto minIdPosition = ids.begin();
73 int minId = *minIdPosition;
74 UpdateRawContacts(store, minId, ids);
75 std::string sql = "UPDATE ";
76 sql.append(ContactTableName::RAW_CONTACT)
77 .append(" SET ")
78 .append(RawContactColumns::IS_NEED_MERGE)
79 .append(" = ")
80 .append(std::to_string(g_isNeedMergeNum[1]))
81 .append(", ")
82 .append(RawContactColumns::IS_MERGE_TARGET)
83 .append(" = ")
84 .append(std::to_string(g_isNeedMergeTargetNum[0]))
85 .append(" WHERE ")
86 .append(ContactPublicColumns::ID)
87 .append(" = ")
88 .append(std::to_string(minId));
89 int error = store->ExecuteSql(sql);
90 if (error != OHOS::NativeRdb::E_OK) {
91 HILOG_ERROR("MergeCircle ExecuteSql error : %{public}d ", error);
92 return RDB_EXECUTE_FAIL;
93 }
94 MatchCandidate matchCandidate;
95 matchCandidate.AddHasByRawId(store, minId);
96 matchCandidate.FindMatchContact(store, minId);
97 }
98 if (isModeHasError) {
99 HILOG_ERROR("MergerContacts::MergeCircle only one candidate has auto_merge_mode");
100 return RDB_EXECUTE_FAIL;
101 } else {
102 return RDB_EXECUTE_OK;
103 }
104 }
105
DeleteContacts(std::shared_ptr<OHOS::NativeRdb::RdbStore> store,int minId,std::set<int> handledIds)106 int MergerContacts::DeleteContacts(
107 std::shared_ptr<OHOS::NativeRdb::RdbStore> store, int minId, std::set<int> handledIds)
108 {
109 int ret = store->ExecuteSql("PRAGMA foreign_keys = OFF");
110 if (ret != OHOS::NativeRdb::E_OK) {
111 HILOG_ERROR("DeleteContacts foreign_keys close fail");
112 return ret;
113 }
114 std::set<int> ids;
115 std::string sql = "DELETE FROM ";
116 sql.append(ContactTableName::CONTACT).append(" WHERE ");
117 for (auto it = handledIds.begin(); it != handledIds.end(); ++it) {
118 if (*it != minId) {
119 ids.insert(*it);
120 }
121 }
122 for (auto id = ids.begin(); id != ids.end(); ++id) {
123 sql.append(ContactColumns::NAME_RAW_CONTACT_ID).append(" = ").append(std::to_string(*id));
124 if (*id != *ids.rbegin()) {
125 sql.append(" OR ");
126 }
127 }
128 int code = store->ExecuteSql(sql);
129 ret = store->ExecuteSql("PRAGMA foreign_keys = ON");
130 if (ret != OHOS::NativeRdb::E_OK) {
131 HILOG_ERROR("DeleteContacts foreign_keys open fail");
132 return ret;
133 }
134 return code;
135 }
136
HandleIds(std::shared_ptr<OHOS::NativeRdb::RdbStore> store,std::set<int> ids)137 std::set<int> MergerContacts::HandleIds(std::shared_ptr<OHOS::NativeRdb::RdbStore> store, std::set<int> ids)
138 {
139 std::set<int> rawIds;
140 for (auto id = ids.begin(); id != ids.end(); ++id) {
141 if (*id != *ids.rbegin()) {
142 std::string sqlBuilder = "SELECT ";
143 sqlBuilder.append(ContactPublicColumns::ID)
144 .append(" FROM ")
145 .append(ContactTableName::RAW_CONTACT)
146 .append(" WHERE ")
147 .append(RawContactColumns::CONTACT_ID)
148 .append(" = (SELECT ")
149 .append(RawContactColumns::CONTACT_ID)
150 .append(" FROM")
151 .append(ContactTableName::RAW_CONTACT)
152 .append(" WHERE ")
153 .append(ContactPublicColumns::ID)
154 .append(" = ")
155 .append(std::to_string(*id))
156 .append(")");
157 std::unique_ptr<OHOS::NativeRdb::AbsSharedResultSet> resultSet = store->QuerySql(sqlBuilder);
158 int resultSetNum = resultSet->GoToFirstRow();
159 while (resultSetNum == OHOS::NativeRdb::E_OK) {
160 int rawId = 0;
161 resultSet->GetInt(0, rawId);
162 rawIds.insert(rawId);
163 resultSetNum = resultSet->GoToNextRow();
164 }
165 resultSet->Close();
166 } else {
167 rawIds.insert(*id);
168 }
169 }
170 return rawIds;
171 }
172
UpdateRawContacts(std::shared_ptr<OHOS::NativeRdb::RdbStore> store,int minRawId,std::set<int> Ids)173 void MergerContacts::UpdateRawContacts(
174 std::shared_ptr<OHOS::NativeRdb::RdbStore> store, int minRawId, std::set<int> Ids)
175 {
176 std::string sqlBuilder = "SELECT ";
177 sqlBuilder.append(RawContactColumns::CONTACT_ID)
178 .append(" FROM ")
179 .append(ContactTableName::RAW_CONTACT)
180 .append(" WHERE ")
181 .append(ContactPublicColumns::ID)
182 .append(" = ")
183 .append(std::to_string(minRawId))
184 .append(" AND ")
185 .append(RawContactColumns::IS_DELETED)
186 .append(" = 0");
187 std::unique_ptr<OHOS::NativeRdb::AbsSharedResultSet> resultSet = store->QuerySql(sqlBuilder);
188 int minContactId = 0;
189 int resultSetNum = resultSet->GoToFirstRow();
190 while (resultSetNum == OHOS::NativeRdb::E_OK) {
191 resultSet->GetInt(0, minContactId);
192 resultSetNum = resultSet->GoToNextRow();
193 }
194 resultSet->Close();
195 UpdateRawContactsExecute(store, minContactId, Ids);
196 DeleteContacts(store, minRawId, Ids);
197 }
198
UpdateRawContactsExecute(std::shared_ptr<OHOS::NativeRdb::RdbStore> store,int minContactId,std::set<int> Ids)199 void MergerContacts::UpdateRawContactsExecute(
200 std::shared_ptr<OHOS::NativeRdb::RdbStore> store, int minContactId, std::set<int> Ids)
201 {
202 unsigned int size = Ids.size();
203 if (size < 0) {
204 return;
205 }
206 std::string updateRawContact = "UPDATE ";
207 updateRawContact.append(ContactTableName::RAW_CONTACT)
208 .append(" SET ")
209 .append(RawContactColumns::CONTACT_ID)
210 .append(" = ")
211 .append(std::to_string(minContactId))
212 .append(", ")
213 .append(RawContactColumns::MERGE_MODE)
214 .append(" = ")
215 .append(std::to_string(MERGE_MODE_DEFAULT))
216 .append(", ")
217 .append(RawContactColumns::IS_NEED_MERGE)
218 .append(" = ")
219 .append(std::to_string(g_isNeedMergeNum[0]))
220 .append(" WHERE ( ");
221 std::string updateSearchSql = "UPDATE ";
222 updateSearchSql.append(ContactTableName::SEARCH_CONTACT)
223 .append(" SET ")
224 .append(RawContactColumns::CONTACT_ID)
225 .append(" = ")
226 .append(std::to_string(minContactId))
227 .append(" WHERE ");
228 for (auto it = Ids.begin(); it != Ids.end(); ++it) {
229 updateRawContact.append("id = ").append(std::to_string(*it));
230 updateSearchSql.append("id = ").append(std::to_string(*it));
231 if (*it != *Ids.rbegin()) {
232 updateRawContact.append(" OR ");
233 updateSearchSql.append(" OR ");
234 }
235 }
236 updateRawContact.append(" ) AND is_deleted = 0");
237 int ret = store->ExecuteSql(updateRawContact);
238 int code = store->ExecuteSql(updateSearchSql);
239 if (ret != RDB_EXECUTE_OK || code != RDB_EXECUTE_OK) {
240 return;
241 }
242 }
243
QueryCandidateName(std::shared_ptr<OHOS::NativeRdb::RdbStore> store,int id)244 std::string MergerContacts::QueryCandidateName(std::shared_ptr<OHOS::NativeRdb::RdbStore> store, int id)
245 {
246 std::shared_ptr<ContactsDataBase> contactsDataBase = ContactsDataBase::GetInstance();
247 int nameType = contactsDataBase->GetTypeId(ContentTypeData::NAME);
248 std::string sqlBuilder = "SELECT ";
249 sqlBuilder.append(ContactDataColumns::DETAIL_INFO)
250 .append(" FROM ")
251 .append(ContactTableName::CONTACT_DATA)
252 .append(" WHERE ")
253 .append(ContactDataColumns::RAW_CONTACT_ID)
254 .append(" = ")
255 .append(std::to_string(id))
256 .append(" AND ")
257 .append(ContactDataColumns::TYPE_ID)
258 .append(" = ")
259 .append(std::to_string(nameType));
260 std::unique_ptr<OHOS::NativeRdb::AbsSharedResultSet> resultSet = store->QuerySql(sqlBuilder);
261 std::string candidateName;
262 int resultSetNum = resultSet->GoToFirstRow();
263 while (resultSetNum == OHOS::NativeRdb::E_OK) {
264 resultSet->GetString(0, candidateName);
265 resultSetNum = resultSet->GoToNextRow();
266 }
267 resultSet->Close();
268 return candidateName;
269 }
270
QueryTargetName(std::shared_ptr<OHOS::NativeRdb::RdbStore> store,int rawId,std::set<std::string> data)271 std::set<int> MergerContacts::QueryTargetName(
272 std::shared_ptr<OHOS::NativeRdb::RdbStore> store, int rawId, std::set<std::string> data)
273 {
274 std::shared_ptr<ContactsDataBase> contactsDataBase = ContactsDataBase::GetInstance();
275 int nameType = contactsDataBase->GetTypeId(ContentTypeData::NAME);
276 std::set<int> ids;
277 for (auto it = data.begin(); it != data.end(); it++) {
278 std::string query = "SELECT ";
279 query.append(ContactDataColumns::RAW_CONTACT_ID)
280 .append(" FROM ")
281 .append(ViewName::VIEW_CONTACT_DATA)
282 .append(" WHERE ")
283 .append(ContactDataColumns::DETAIL_INFO)
284 .append(" = '")
285 .append(*it)
286 .append("' AND ")
287 .append(ContactDataColumns::TYPE_ID)
288 .append(" = ")
289 .append(std::to_string(nameType))
290 .append(" AND is_deleted = 0");
291 std::unique_ptr<OHOS::NativeRdb::AbsSharedResultSet> resultSet = store->QuerySql(query);
292 int resultSetNum = resultSet->GoToFirstRow();
293 while (resultSetNum == OHOS::NativeRdb::E_OK) {
294 int value = 0;
295 resultSet->GetInt(0, value);
296 if (value != rawId) {
297 ids.insert(value);
298 }
299 resultSetNum = resultSet->GoToNextRow();
300 }
301 resultSet->Close();
302 }
303 return ids;
304 }
305
QueryMergeContacts(std::shared_ptr<OHOS::NativeRdb::RdbStore> store,int mode)306 std::vector<std::set<int>> MergerContacts::QueryMergeContacts(
307 std::shared_ptr<OHOS::NativeRdb::RdbStore> store, int mode)
308 {
309 std::string sqlBuilder = "SELECT ";
310 sqlBuilder.append(ContactPublicColumns::ID)
311 .append(" FROM ")
312 .append(ContactTableName::RAW_CONTACT)
313 .append(" WHERE ")
314 .append(RawContactColumns::IS_MERGE_TARGET)
315 .append(" = ")
316 .append(std::to_string(g_isNeedMergeTargetNum[1]))
317 .append(" AND ")
318 .append(RawContactColumns::IS_DELETED)
319 .append(" = 0")
320 .append(" AND ")
321 .append(RawContactColumns::MERGE_MODE)
322 .append(" = ")
323 .append(std::to_string(mode));
324 std::vector<int> currentIds;
325 std::unique_ptr<OHOS::NativeRdb::AbsSharedResultSet> resultSet = store->QuerySql(sqlBuilder);
326 int resultSetNum = resultSet->GoToFirstRow();
327 while (resultSetNum == OHOS::NativeRdb::E_OK) {
328 int currentId = 0;
329 resultSet->GetInt(0, currentId);
330 currentIds.push_back(currentId);
331 resultSetNum = resultSet->GoToNextRow();
332 }
333 resultSet->Close();
334 HILOG_INFO("QueryMergeContacts currentIds' size = %{public}zu", currentIds.size());
335 std::vector<std::set<int>> candidates;
336 UpdateCandidate(store, currentIds, candidates);
337 return candidates;
338 }
339
UpdateCandidate(std::shared_ptr<OHOS::NativeRdb::RdbStore> store,std::vector<int> currentIds,std::vector<std::set<int>> & candidates)340 void MergerContacts::UpdateCandidate(std::shared_ptr<OHOS::NativeRdb::RdbStore> store, std::vector<int> currentIds,
341 std::vector<std::set<int>> &candidates)
342 {
343 std::shared_ptr<ContactsDataBase> contactsDataBase = ContactsDataBase::GetInstance();
344 int nameType = contactsDataBase->GetTypeId(ContentTypeData::NAME);
345 int phoneType = contactsDataBase->GetTypeId(ContentTypeData::PHONE);
346 MergeUtils mergeUtils;
347 for (auto rawId : currentIds) {
348 std::set<std::string> names = mergeUtils.QueryRawContactByType(store, rawId, nameType);
349 std::set<std::string> phones = mergeUtils.QueryRawContactByType(store, rawId, phoneType);
350 if (names.empty()) {
351 HILOG_ERROR("MergerContacts::UpdateCandidate target names is empty");
352 break;
353 }
354 std::set<int> nameIds = QueryTargetName(store, rawId, names);
355 std::set<int> rawIds;
356 rawIds.insert(rawId);
357 for (auto nameId = nameIds.begin(); nameId != nameIds.end(); nameId++) {
358 std::set<std::string> otherPhones = mergeUtils.QueryRawContactByType(store, *nameId, phoneType);
359 bool isMatch = mergeUtils.SetEqual(phones, otherPhones);
360 if (isMatch) {
361 rawIds.insert(*nameId);
362 }
363 }
364 HILOG_INFO("rawIds' size = %{public}zu", rawIds.size());
365 candidates.push_back(rawIds);
366 }
367 HILOG_INFO("candidates' size = %{public}zu", candidates.size());
368 }
369
SelectCandidate(std::shared_ptr<OHOS::NativeRdb::RdbStore> store)370 std::shared_ptr<OHOS::NativeRdb::AbsSharedResultSet> MergerContacts::SelectCandidate(
371 std::shared_ptr<OHOS::NativeRdb::RdbStore> store)
372 {
373 std::unique_ptr<OHOS::NativeRdb::AbsSharedResultSet> resultSet;
374 if (store == nullptr) {
375 HILOG_ERROR("MergerContacts SelectCandidate store is nullptr");
376 return resultSet;
377 }
378 std::shared_ptr<ContactsDataBase> contactsDataBase = ContactsDataBase::GetInstance();
379 int nameType = contactsDataBase->GetTypeId(ContentTypeData::NAME);
380 int phoneType = contactsDataBase->GetTypeId(ContentTypeData::PHONE);
381 std::string sql = "SELECT ";
382 sql.append(ContactDataColumns::RAW_CONTACT_ID)
383 .append(", ")
384 .append(RawContactColumns::CONTACT_ID)
385 .append(", ")
386 .append(ContentTypeColumns::CONTENT_TYPE)
387 .append(", ")
388 .append(ContactDataColumns::TYPE_ID)
389 .append(", ")
390 .append(RawContactColumns::DISPLAY_NAME)
391 .append(", ")
392 .append(RawContactColumns::PHOTO_FIRST_NAME)
393 .append(", ")
394 .append(ContactDataColumns::DETAIL_INFO)
395 .append(" FROM ")
396 .append(ViewName::VIEW_CONTACT_DATA)
397 .append(" WHERE ")
398 .append(ContactDataColumns::RAW_CONTACT_ID)
399 .append(" IN(SELECT ")
400 .append(RawContactColumns::ID)
401 .append(" FROM ")
402 .append(ContactTableName::RAW_CONTACT)
403 .append(" WHERE ")
404 .append(RawContactColumns::IS_DELETED)
405 .append(" = 0")
406 .append(" AND ")
407 .append(RawContactColumns::MERGE_MODE)
408 .append(" = ")
409 .append(std::to_string(MERGE_MODE_MANUAL))
410 .append(") AND ( ")
411 .append(ContactDataColumns::TYPE_ID)
412 .append(" = ")
413 .append(std::to_string(phoneType))
414 .append(" OR ")
415 .append(ContactDataColumns::TYPE_ID)
416 .append(" = ")
417 .append(std::to_string(nameType))
418 .append(" ) GROUP BY ")
419 .append(RawContactColumns::CONTACT_ID);
420 resultSet = store->QuerySql(sql);
421 return resultSet;
422 }
423
424 /**
425 * @brief ManualMerge operation for candidate contacts
426 *
427 * @param store Conditions for split operation
428 * @param predicates Conditions for update operation
429 *
430 * @return The result returned by the ManualMerge operation
431 */
ReContactMerge(std::shared_ptr<OHOS::NativeRdb::RdbStore> store,const DataShare::DataSharePredicates & predicates)432 int MergerContacts::ReContactMerge(
433 std::shared_ptr<OHOS::NativeRdb::RdbStore> store, const DataShare::DataSharePredicates &predicates)
434 {
435 HILOG_INFO("MergerContacts::ReContactMerge is starting");
436 std::vector<std::string> whereArgs = predicates.GetWhereArgs();
437 std::set<int> ids;
438 for (auto value : whereArgs) {
439 ids.insert(atoi(value.c_str()));
440 }
441 if (ids.size() == 0) {
442 return RDB_EXECUTE_FAIL;
443 }
444 std::vector<std::set<int>> selectedIds = SelectIdsByName(store, ids);
445 int minId = 0;
446 bool isModeHasError = false;
447 for (auto it = selectedIds.begin(); it != selectedIds.end(); ++it) {
448 std::set<int> currentIds = *it;
449 std::set<int> handledIds = HandleIds(store, currentIds);
450 HILOG_INFO("ReContactMerge size = :%{public}zu", handledIds.size());
451 if (handledIds.size() == 1) {
452 HILOG_ERROR("MergeCircle continue ");
453 isModeHasError = true;
454 continue;
455 }
456 auto minIdPosition = handledIds.begin();
457 minId = *minIdPosition;
458 int ret = ManualMergeOperation(store, minId, handledIds);
459 if (ret != RDB_EXECUTE_OK) {
460 return RDB_EXECUTE_FAIL;
461 }
462 MatchCandidate matchCandidate;
463 matchCandidate.FindMatchContact(store, minId);
464 }
465 if (isModeHasError) {
466 HILOG_ERROR("MergerContacts::MergeCircle only one candidate has manual_merge_mode");
467 return RDB_EXECUTE_FAIL;
468 } else {
469 return RDB_EXECUTE_OK;
470 }
471 }
472
ManualMergeOperation(std::shared_ptr<OHOS::NativeRdb::RdbStore> store,int minId,std::set<int> handledIds)473 int MergerContacts::ManualMergeOperation(
474 std::shared_ptr<OHOS::NativeRdb::RdbStore> store, int minId, std::set<int> handledIds)
475 {
476 UpdateRawContacts(store, minId, handledIds);
477 DeleteContacts(store, minId, handledIds);
478 std::string sql = "UPDATE ";
479 sql.append(ContactTableName::RAW_CONTACT)
480 .append(" SET ")
481 .append(RawContactColumns::IS_NEED_MERGE)
482 .append(" = ")
483 .append(std::to_string(g_isNeedMergeNum[1]))
484 .append(", ")
485 .append(RawContactColumns::IS_MERGE_TARGET)
486 .append(" = ")
487 .append(std::to_string(g_isNeedMergeTargetNum[0]))
488 .append(" WHERE ")
489 .append(ContactPublicColumns::ID)
490 .append(" = ")
491 .append(std::to_string(minId));
492 int error = store->ExecuteSql(sql);
493 if (error != RDB_EXECUTE_OK) {
494 HILOG_ERROR("MergerContacts::ReContactMerge errorcode :%{public}d", error);
495 return error;
496 }
497 return RDB_EXECUTE_OK;
498 }
499
SelectIdsByName(std::shared_ptr<OHOS::NativeRdb::RdbStore> store,std::set<int> ids)500 std::vector<std::set<int>> MergerContacts::SelectIdsByName(
501 std::shared_ptr<OHOS::NativeRdb::RdbStore> store, std::set<int> ids)
502 {
503 HILOG_INFO("MergerContacts::SelectIdsByName is starting");
504 std::vector<std::set<int>> selectedIds;
505 std::set<std::string> names;
506 std::shared_ptr<ContactsDataBase> contactsDataBase = ContactsDataBase::GetInstance();
507 int nameType = contactsDataBase->GetTypeId(ContentTypeData::NAME);
508 for (auto id : ids) {
509 std::string sql = "SELECT ";
510 sql.append(ContactDataColumns::DETAIL_INFO)
511 .append(" FROM ")
512 .append(ContactTableName::CONTACT_DATA)
513 .append(" WHERE ")
514 .append(ContactDataColumns::RAW_CONTACT_ID)
515 .append(" = ")
516 .append(std::to_string(id))
517 .append(" AND ")
518 .append(ContactDataColumns::TYPE_ID)
519 .append(" = ")
520 .append(std::to_string(nameType));
521 std::unique_ptr<OHOS::NativeRdb::AbsSharedResultSet> resultSet = store->QuerySql(sql);
522 int resultSetNum = resultSet->GoToFirstRow();
523 while (resultSetNum == OHOS::NativeRdb::E_OK) {
524 std::string name;
525 resultSet->GetString(0, name);
526 names.insert(name);
527 resultSetNum = resultSet->GoToNextRow();
528 }
529 resultSet->Close();
530 }
531 UpdateIdsByName(store, names, ids, selectedIds);
532 return selectedIds;
533 }
534
UpdateIdsByName(std::shared_ptr<OHOS::NativeRdb::RdbStore> store,std::set<std::string> names,std::set<int> ids,std::vector<std::set<int>> & selectedIds)535 void MergerContacts::UpdateIdsByName(std::shared_ptr<OHOS::NativeRdb::RdbStore> store, std::set<std::string> names,
536 std::set<int> ids, std::vector<std::set<int>> &selectedIds)
537 {
538 for (auto name : names) {
539 std::string sqlBuilder = "SELECT ";
540 sqlBuilder.append(ContactDataColumns::RAW_CONTACT_ID)
541 .append(" FROM ")
542 .append(ContactTableName::CONTACT_DATA)
543 .append(" WHERE ")
544 .append(ContactDataColumns::DETAIL_INFO)
545 .append(" = '")
546 .append(name)
547 .append("' AND ")
548 .append(ContactDataColumns::RAW_CONTACT_ID)
549 .append(" IN(");
550 for (auto id = ids.begin(); id != ids.end(); ++id) {
551 if (*id == *ids.rbegin()) {
552 sqlBuilder.append(std::to_string(*id)).append(")");
553 } else {
554 sqlBuilder.append(std::to_string(*id)).append(", ");
555 }
556 }
557 std::set<int> currentIds;
558 std::unique_ptr<OHOS::NativeRdb::AbsSharedResultSet> resultSet = store->QuerySql(sqlBuilder);
559 int resultSetNum = resultSet->GoToFirstRow();
560 while (resultSetNum == OHOS::NativeRdb::E_OK) {
561 int id = 0;
562 resultSet->GetInt(0, id);
563 currentIds.insert(id);
564 resultSetNum = resultSet->GoToNextRow();
565 }
566 resultSet->Close();
567 selectedIds.push_back(currentIds);
568 }
569 }
570
isNameMatch(std::shared_ptr<OHOS::NativeRdb::RdbStore> store,std::set<int> ids)571 bool MergerContacts::isNameMatch(std::shared_ptr<OHOS::NativeRdb::RdbStore> store, std::set<int> ids)
572 {
573 std::set<std::string> names;
574 for (auto it : ids) {
575 std::string name = QueryCandidateName(store, it);
576 names.insert(name);
577 }
578 if (names.size() == 1) {
579 return true;
580 } else {
581 return false;
582 }
583 }
584
585 /**
586 * @brief Force contact merge for candidate contacts
587 *
588 * @param store Conditions for split operation
589 * @param ids Conditions for update operation
590 *
591 * @return The result returned by the ForceContactMerge operation
592 */
ForceContactMerge(std::shared_ptr<OHOS::NativeRdb::RdbStore> store,std::set<int> ids)593 int MergerContacts::ForceContactMerge(std::shared_ptr<OHOS::NativeRdb::RdbStore> store, std::set<int> ids)
594 {
595 if (store == nullptr) {
596 HILOG_ERROR("store is empty");
597 return RDB_OBJECT_EMPTY;
598 }
599 int minId = 0;
600 if (isNameMatch(store, ids)) {
601 std::set<int> handledIds = HandleIds(store, ids);
602 HILOG_INFO("ForceContactMerge size = %{public}zu", handledIds.size());
603 auto minIdPosition = handledIds.begin();
604 minId = *minIdPosition;
605 UpdateRawContacts(store, minId, handledIds);
606 DeleteContacts(store, minId, handledIds);
607 } else {
608 HILOG_ERROR("Invalid parameter passed");
609 return RDB_EXECUTE_FAIL;
610 }
611 std::string sql = "UPDATE ";
612 sql.append(ContactTableName::RAW_CONTACT)
613 .append(" SET ")
614 .append(RawContactColumns::IS_NEED_MERGE)
615 .append(" = ")
616 .append(std::to_string(g_isNeedMergeNum[1]))
617 .append(" WHERE ")
618 .append(ContactPublicColumns::ID)
619 .append(" = ")
620 .append(std::to_string(minId));
621 int error = store->ExecuteSql(sql);
622 if (error != RDB_EXECUTE_OK) {
623 HILOG_ERROR("MergerContacts::ForceMerge errorcode :%{public}d", error);
624 return error;
625 }
626 return RDB_EXECUTE_OK;
627 }
628 } // namespace Contacts
629 } // namespace OHOS
630