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