• 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 = "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