• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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