4 * Copyright (c) 2010 - 2015 Samsung Electronics Co., Ltd. All rights reserved.
6 * Licensed under the Apache License, Version 2.0 (the "License");
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
10 * http://www.apache.org/licenses/LICENSE-2.0
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
21 #include "ctsvc_internal.h"
22 #include "ctsvc_db_schema.h"
23 #include "ctsvc_db_sqlite.h"
24 #include "ctsvc_db_init.h"
25 #include "ctsvc_db_utils.h"
26 #include "ctsvc_notification.h"
27 #include "ctsvc_db_plugin_person_helper.h"
28 #include "ctsvc_db_plugin_contact_helper.h"
29 #include "ctsvc_db_access_control.h"
30 #include "ctsvc_notify.h"
31 #include "ctsvc_number_utils.h"
32 #include "ctsvc_server_setting.h"
33 #include "ctsvc_list.h"
34 #include "ctsvc_localize.h"
35 #include "ctsvc_db_plugin_image_helper.h"
37 #ifdef ENABLE_LOG_FEATURE
38 #include "ctsvc_server_phonelog.h"
39 #endif /* ENABLE_LOG_FEATURE */
41 #ifdef _CONTACTS_IPC_SERVER
42 #include "ctsvc_server_change_subject.h"
45 #define CTSVC_COMP_NAME_LEN 4
46 #define CTSVC_AGGREGATION_SUGGESTION_SCORE 2
49 CTSVC_GET_PERSON_DEFAULT_NUMBER_VALUE,
50 CTSVC_GET_PERSON_DEFAULT_EMAIL_VALUE,
51 CTSVC_GET_PERSON_DEFAULT_IMAGE_VALUE,
54 static inline int __ctsvc_get_person_default_number_value(int id, contacts_record_h *record)
58 ctsvc_number_s *number;
59 char query[CTS_SQL_MAX_LEN] = {0};
61 snprintf(query, sizeof(query),
62 "SELECT data.id, data.is_default, data.data1, data.data2, data.data3, data.data4 "
63 "FROM %s, %s ON data.is_primary_default=1 AND data.datatype=%d "
64 "AND data.contact_id = contacts.contact_id AND contacts.deleted = 0 "
65 "WHERE contacts.person_id = %d",
66 CTS_TABLE_CONTACTS, CTS_TABLE_DATA, CONTACTS_DATA_TYPE_NUMBER, id);
68 ret = ctsvc_query_prepare(query, &stmt);
69 RETVM_IF(NULL == stmt, ret, "ctsvc_query_prepare() Fail(%d)", ret);
71 ret = ctsvc_stmt_step(stmt);
72 if (1 /*CTS_TRUE*/ != ret) {
74 ctsvc_stmt_finalize(stmt);
75 ERR("ctsvc_stmt_step() Fail(%d)", ret);
76 if (CONTACTS_ERROR_NONE == ret)
77 return CONTACTS_ERROR_NO_DATA;
83 ret = contacts_record_create(_contacts_number._uri, (contacts_record_h*)&number);
86 number->id = ctsvc_stmt_get_int(stmt, 0);
87 number->is_default = ctsvc_stmt_get_int(stmt, 1);
88 number->type = ctsvc_stmt_get_int(stmt, 2);
89 temp = ctsvc_stmt_get_text(stmt, 3);
90 number->label = SAFE_STRDUP(temp);
91 temp = ctsvc_stmt_get_text(stmt, 4);
92 number->number = SAFE_STRDUP(temp);
93 temp = ctsvc_stmt_get_text(stmt, 5);
94 number->lookup = SAFE_STRDUP(temp);
96 *record = (contacts_record_h)number;
97 ret = CONTACTS_ERROR_NONE;
100 ERR("contacts_record_create() Fail");
104 ctsvc_stmt_finalize(stmt);
108 static inline int __ctsvc_get_person_default_email_value(int id, contacts_record_h *record)
112 ctsvc_email_s *email;
113 char query[CTS_SQL_MAX_LEN] = {0};
115 snprintf(query, sizeof(query),
116 "SELECT data.id, data.is_default, data.data1, data.data2, data.data3 "
117 "FROM %s, %s ON data.is_primary_default=1 AND data.datatype=%d "
118 "AND data.contact_id = contacts.contact_id AND contacts.deleted = 0 "
119 "WHERE contacts.person_id = %d",
120 CTS_TABLE_CONTACTS, CTS_TABLE_DATA, CONTACTS_DATA_TYPE_EMAIL, id);
122 ret = ctsvc_query_prepare(query, &stmt);
123 RETVM_IF(NULL == stmt, ret, "ctsvc_query_prepare() Fail(%d)", ret);
125 ret = ctsvc_stmt_step(stmt);
126 if (1 /*CTS_TRUE*/ != ret) {
127 /* LCOV_EXCL_START */
128 ctsvc_stmt_finalize(stmt);
129 ERR("ctsvc_stmt_step() Fail(%d)", ret);
130 if (CONTACTS_ERROR_NONE == ret)
131 return CONTACTS_ERROR_NO_DATA;
137 ret = contacts_record_create(_contacts_email._uri, (contacts_record_h*)&email);
140 email->id = ctsvc_stmt_get_int(stmt, 0);
141 email->is_default = ctsvc_stmt_get_int(stmt, 1);
142 email->type = ctsvc_stmt_get_int(stmt, 2);
143 temp = ctsvc_stmt_get_text(stmt, 3);
144 email->label = SAFE_STRDUP(temp);
145 temp = ctsvc_stmt_get_text(stmt, 4);
146 email->email_addr = SAFE_STRDUP(temp);
148 *record = (contacts_record_h)email;
149 ret = CONTACTS_ERROR_NONE;
151 /* LCOV_EXCL_START */
152 ERR("contacts_record_create() Fail");
156 ctsvc_stmt_finalize(stmt);
160 static inline int __ctsvc_get_person_default_image_value(int id, contacts_record_h *record)
164 ctsvc_image_s *image;
165 char query[CTS_SQL_MAX_LEN] = {0};
167 snprintf(query, sizeof(query),
168 "SELECT data.id, data.is_default, data.data1, data.data2, data.data3 "
169 "FROM "CTS_TABLE_CONTACTS", "CTS_TABLE_DATA" "
170 "ON data.is_primary_default=1 AND data.datatype=%d AND data.is_my_profile = 0 "
171 "AND data.contact_id = contacts.contact_id AND contacts.deleted = 0 "
172 "WHERE contacts.person_id = %d",
173 CONTACTS_DATA_TYPE_IMAGE, id);
175 ret = ctsvc_query_prepare(query, &stmt);
176 RETVM_IF(NULL == stmt, ret, "ctsvc_query_prepare() Fail(%d)", ret);
178 ret = ctsvc_stmt_step(stmt);
179 if (1 /*CTS_TRUE*/ != ret) {
180 /* LCOV_EXCL_START */
181 ctsvc_stmt_finalize(stmt);
182 ERR("ctsvc_stmt_step() Fail(%d)", ret);
183 if (CONTACTS_ERROR_NONE == ret)
184 return CONTACTS_ERROR_NO_DATA;
190 ret = contacts_record_create(_contacts_image._uri, (contacts_record_h*)&image);
193 image->id = ctsvc_stmt_get_int(stmt, 0);
194 image->is_default = ctsvc_stmt_get_int(stmt, 1);
195 image->type = ctsvc_stmt_get_int(stmt, 2);
196 temp = ctsvc_stmt_get_text(stmt, 3);
197 image->label = SAFE_STRDUP(temp);
198 temp = ctsvc_stmt_get_text(stmt, 4);
199 image->path = SAFE_STRDUP(temp);
201 *record = (contacts_record_h)image;
202 ret = CONTACTS_ERROR_NONE;
204 /* LCOV_EXCL_START */
205 ERR("contacts_record_create() Fail");
209 ctsvc_stmt_finalize(stmt);
213 static int __ctsvc_get_person_value(int op_code,
214 int person_id, contacts_record_h *record)
218 RETV_IF(NULL == record, CONTACTS_ERROR_INVALID_PARAMETER);
221 case CTSVC_GET_PERSON_DEFAULT_NUMBER_VALUE:
222 ret = __ctsvc_get_person_default_number_value(person_id, record);
223 RETVM_IF(ret != CONTACTS_ERROR_NONE, ret, "__ctsvc_get_person_default_number_value() Fail(%d)", ret);
225 case CTSVC_GET_PERSON_DEFAULT_EMAIL_VALUE:
226 ret = __ctsvc_get_person_default_email_value(person_id, record);
227 RETVM_IF(ret != CONTACTS_ERROR_NONE, ret, "__ctsvc_get_person_default_email_value() Fail(%d)", ret);
229 case CTSVC_GET_PERSON_DEFAULT_IMAGE_VALUE:
230 ret = __ctsvc_get_person_default_image_value(person_id, record);
231 RETVM_IF(ret != CONTACTS_ERROR_NONE, ret, "__ctsvc_get_person_default_image_value() Fail(%d)", ret);
234 /* LCOV_EXCL_START */
235 ERR("The op_code(%d) is not supported", op_code);
236 return CONTACTS_ERROR_INVALID_PARAMETER;
241 return CONTACTS_ERROR_NO_DATA;
246 static inline int __ctsvc_put_person_default_name(int person_id, int contact_id)
250 char query[CTS_SQL_MAX_LEN] = {0};
252 snprintf(query, sizeof(query),
253 "SELECT person_id FROM %s WHERE contact_id=%d AND deleted = 0",
254 CTS_TABLE_CONTACTS, contact_id);
256 ret = ctsvc_query_get_first_int_result(query, &id);
257 RETVM_IF(ret != CONTACTS_ERROR_NONE, ret, "ctsvc_query_get_first_int_result() Fail(%d)", ret);
259 if (id == person_id) {
260 ret = ctsvc_begin_trans();
261 RETVM_IF(ret < CONTACTS_ERROR_NONE, ret, "ctsvc_begin_trans() Fail(%d)", ret);
262 snprintf(query, sizeof(query),
263 "UPDATE %s SET name_contact_id=%d WHERE person_id=%d",
264 CTS_TABLE_PERSONS, contact_id, person_id);
266 ret = ctsvc_query_exec(query);
267 if (CONTACTS_ERROR_NONE != ret) {
268 /* LCOV_EXCL_START */
269 ERR("ctsvc_query_exec() Fail(%d)", ret);
270 ctsvc_end_trans(false);
274 ret = ctsvc_end_trans(true);
275 if (ret < CONTACTS_ERROR_NONE) {
276 /* LCOV_EXCL_START */
277 ERR("ctsvc_end_trans() Fail(%d)", ret);
280 return CONTACTS_ERROR_NONE;
285 /* LCOV_EXCL_START */
286 ERR("contact(%d) does not belong to person(%d), to person(%d)", contact_id, person_id, ret);
287 ret = CONTACTS_ERROR_NO_DATA;
294 static inline int __ctsvc_put_person_default_image(int person_id, int id)
301 char query[CTS_SQL_MAX_LEN] = {0};
302 char *thumbnail_path;
304 ret = ctsvc_begin_trans();
305 RETVM_IF(ret < CONTACTS_ERROR_NONE, ret, "ctsvc_begin_trans() Fail(%d)", ret);
307 snprintf(query, sizeof(query),
308 "SELECT D.is_default, D.contact_id, D.data3 "
309 "FROM "CTS_TABLE_DATA" D, "CTS_TABLE_CONTACTS" C "
310 "ON D.contact_id = C.contact_id AND C.deleted = 0 "
311 "WHERE D.datatype=%d AND D.is_my_profile = 0 AND C.person_id=%d AND D.id=%d",
312 CONTACTS_DATA_TYPE_IMAGE, person_id, id);
313 ret = ctsvc_query_prepare(query, &stmt);
315 /* LCOV_EXCL_START */
316 ERR("ctsvc_query_prepare Fail(%d)", ret);
317 ctsvc_end_trans(false);
322 ret = ctsvc_stmt_step(stmt);
324 /* LCOV_EXCL_START */
325 ctsvc_stmt_finalize(stmt);
326 ctsvc_end_trans(false);
331 is_default = ctsvc_stmt_get_int(stmt, 0);
332 contact_id = ctsvc_stmt_get_int(stmt, 1);
333 image_path = SAFE_STRDUP(ctsvc_stmt_get_text(stmt, 2));
334 ctsvc_stmt_finalize(stmt);
336 /* unset is_primary_default of all data of the person */
337 snprintf(query, sizeof(query),
338 "UPDATE "CTS_TABLE_DATA" SET is_primary_default=0 WHERE datatype=%d AND is_my_profile = 0 "
339 "AND contact_id IN (SELECT contact_id FROM "CTS_TABLE_CONTACTS" "
340 "WHERE person_id=%d AND deleted = 0) ",
341 CONTACTS_DATA_TYPE_IMAGE, person_id);
342 ret = ctsvc_query_exec(query);
343 if (ret < CONTACTS_ERROR_NONE) {
344 /* LCOV_EXCL_START */
345 ERR("ctsvc_query_exec() Fail(%d)", ret);
347 ctsvc_end_trans(false);
352 /* unset is_default of all data of person if the data is not default */
353 if (false == is_default) {
354 snprintf(query, sizeof(query),
355 "UPDATE "CTS_TABLE_DATA" SET is_default=0 WHERE datatype=%d AND is_my_profile = 0 "
356 "AND contact_id = %d ", CONTACTS_DATA_TYPE_IMAGE, contact_id);
358 ret = ctsvc_query_exec(query);
359 if (CONTACTS_ERROR_NONE != ret) {
360 /* LCOV_EXCL_START */
361 ERR("ctsvc_query_exec() Fail(%d)", ret);
363 ctsvc_end_trans(false);
368 thumbnail_path = ctsvc_utils_make_thumbnail(image_path);
370 thumbnail_path = ctsvc_utils_get_thumbnail_path(image_path);
375 /* set is_default, is _primary_default */
376 snprintf(query, sizeof(query),
377 "UPDATE "CTS_TABLE_DATA" SET is_primary_default=1, is_default=1 WHERE id=%d ", id);
378 ret = ctsvc_query_exec(query);
379 if (CONTACTS_ERROR_NONE != ret) {
380 /* LCOV_EXCL_START */
381 ERR("ctsvc_query_exec() Fail(%d)", ret);
382 free(thumbnail_path);
383 ctsvc_end_trans(false);
388 /* update person's image_thumbnail_path */
389 snprintf(query, sizeof(query),
390 "UPDATE "CTS_TABLE_PERSONS" SET image_thumbnail_path=? WHERE person_id=%d ", person_id);
391 ret = ctsvc_query_prepare(query, &stmt);
393 /* LCOV_EXCL_START */
394 ERR("ctsvc_query_prepare() Fail(%d)", ret);
395 free(thumbnail_path);
396 ctsvc_end_trans(false);
401 ctsvc_stmt_bind_text(stmt, 1, thumbnail_path);
402 ret = ctsvc_stmt_step(stmt);
403 if (CONTACTS_ERROR_NONE != ret) {
404 /* LCOV_EXCL_START */
405 ERR("ctsvc_stmt_step() Fail(%d)", ret);
406 ctsvc_stmt_finalize(stmt);
407 free(thumbnail_path);
408 ctsvc_end_trans(false);
412 ctsvc_stmt_finalize(stmt);
414 /* update contact's image_thumbnail_path */
415 if (false == is_default) {
416 snprintf(query, sizeof(query),
417 "UPDATE "CTS_TABLE_CONTACTS" SET image_thumbnail_path=? WHERE contact_id=%d ", contact_id);
418 ret = ctsvc_query_prepare(query, &stmt);
420 /* LCOV_EXCL_START */
421 ERR("ctsvc_query_prepare() Fail(%d)", ret);
422 free(thumbnail_path);
423 ctsvc_end_trans(false);
428 ctsvc_stmt_bind_text(stmt, 1, thumbnail_path);
429 ret = ctsvc_stmt_step(stmt);
430 if (CONTACTS_ERROR_NONE != ret) {
431 /* LCOV_EXCL_START */
432 ERR("ctsvc_stmt_step() Fail(%d)", ret);
433 ctsvc_stmt_finalize(stmt);
434 free(thumbnail_path);
435 ctsvc_end_trans(false);
439 ctsvc_stmt_finalize(stmt);
442 free(thumbnail_path);
444 ret = ctsvc_end_trans(true);
448 static inline int __ctsvc_put_person_default_data(int person_id, int id, int datatype)
453 int name_contact_id = 0;
454 char query[CTS_SQL_MAX_LEN] = {0};
455 cts_stmt stmt = NULL;
456 contacts_display_name_source_type_e source_type = CONTACTS_DISPLAY_NAME_SOURCE_TYPE_INVALID;
458 snprintf(query, sizeof(query),
459 "SELECT D.is_default, D.contact_id FROM %s D, %s C "
460 "ON (D.contact_id=C.contact_id AND C.deleted = 0) "
461 "WHERE D.datatype=%d AND C.person_id=%d AND D.id=%d",
462 CTS_TABLE_DATA, CTS_TABLE_CONTACTS, datatype, person_id, id);
464 ret = ctsvc_query_prepare(query, &stmt);
465 RETVM_IF(NULL == stmt, ret, "ctsvc_query_prepare() Fail(%d)", ret);
467 ret = ctsvc_stmt_step(stmt);
469 /* LCOV_EXCL_START */
470 ERR("ctsvc_stmt_step() Fail(%d)", ret);
471 ctsvc_stmt_finalize(stmt);
476 is_default = ctsvc_stmt_get_int(stmt, 0);
477 contact_id = ctsvc_stmt_get_int(stmt, 1);
479 ctsvc_stmt_finalize(stmt);
481 ret = ctsvc_begin_trans();
482 RETVM_IF(ret < CONTACTS_ERROR_NONE, ret, "ctsvc_begin_trans() Fail(%d)", ret);
484 /* unset is_primary_default of all data of the person */
485 snprintf(query, sizeof(query),
486 "UPDATE "CTS_TABLE_DATA" SET is_primary_default=0 WHERE datatype=%d AND is_my_profile = 0 "
487 "AND contact_id IN (SELECT contact_id FROM "CTS_TABLE_CONTACTS" "
488 "WHERE person_id=%d AND deleted = 0) ",
489 datatype, person_id);
491 ret = ctsvc_query_exec(query);
492 if (ret < CONTACTS_ERROR_NONE) {
493 /* LCOV_EXCL_START */
494 ERR("ctsvc_query_exec() Fail(%d)", ret);
495 ctsvc_end_trans(false);
500 /* unset is_default of all data of person if the data is not default */
501 if (false == is_default) {
502 snprintf(query, sizeof(query),
503 "UPDATE "CTS_TABLE_DATA" SET is_default=0 WHERE datatype=%d AND is_my_profile = 0 "
504 "AND contact_id = (SELECT contact_id FROM "CTS_TABLE_DATA" WHERE id=%d) ",
507 ret = ctsvc_query_exec(query);
508 if (CONTACTS_ERROR_NONE != ret) {
509 /* LCOV_EXCL_START */
510 ERR("ctsvc_query_exec() Fail(%d)", ret);
511 ctsvc_end_trans(false);
517 /* set is_default, is _primary_default */
518 snprintf(query, sizeof(query),
519 "UPDATE "CTS_TABLE_DATA" SET is_primary_default=1, is_default=1 WHERE id=%d ", id);
521 ret = ctsvc_query_exec(query);
522 if (CONTACTS_ERROR_NONE != ret) {
523 /* LCOV_EXCL_START */
524 ERR("ctsvc_query_exec() Fail(%d)", ret);
525 ctsvc_end_trans(false);
530 if (datatype == CONTACTS_DATA_TYPE_NUMBER)
531 source_type = CONTACTS_DISPLAY_NAME_SOURCE_TYPE_NUMBER;
532 else if (datatype == CONTACTS_DATA_TYPE_EMAIL)
533 source_type = CONTACTS_DISPLAY_NAME_SOURCE_TYPE_EMAIL;
535 if (CONTACTS_DISPLAY_NAME_SOURCE_TYPE_INVALID != source_type)
536 ctsvc_contact_update_display_name(contact_id, source_type);
538 snprintf(query, sizeof(query),
539 "SELECT name_contact_id FROM "CTS_TABLE_PERSONS" WHERE person_id = %d", person_id);
540 ret = ctsvc_query_get_first_int_result(query, &name_contact_id);
541 if (CONTACTS_ERROR_NONE != ret) {
542 /* LCOV_EXCL_START */
543 ERR("ctsvc_query_get_first_int_result() Fail(%d)", ret);
544 ctsvc_end_trans(false);
549 if (name_contact_id != contact_id) {
550 int org_source_type = CONTACTS_DISPLAY_NAME_SOURCE_TYPE_INVALID;
551 snprintf(query, sizeof(query),
552 "SELECT display_name_source FROM "CTS_TABLE_CONTACTS" WHERE contact_id = %d", name_contact_id);
553 ret = ctsvc_query_get_first_int_result(query, &org_source_type);
554 if (CONTACTS_ERROR_NONE != ret) {
555 /* LCOV_EXCL_START */
556 ERR("ctsvc_query_get_first_int_result() Fail(%d)", ret);
557 ctsvc_end_trans(false);
562 if (org_source_type <= source_type) {
563 snprintf(query, sizeof(query),
564 "UPDATE %s SET name_contact_id=%d WHERE person_id=%d",
565 CTS_TABLE_PERSONS, contact_id, person_id);
566 ret = ctsvc_query_exec(query);
567 if (CONTACTS_ERROR_NONE != ret) {
568 /* LCOV_EXCL_START */
569 ERR("ctsvc_query_exec() Fail(%d)", ret);
570 ctsvc_end_trans(false);
577 ret = ctsvc_end_trans(true);
578 if (ret < CONTACTS_ERROR_NONE) {
579 /* LCOV_EXCL_START */
580 ERR("ctsvc_end_trans() Fail(%d)", ret);
584 return CONTACTS_ERROR_NONE;
588 void ctsvc_db_person_delete_callback(sqlite3_context *context,
589 int argc, sqlite3_value **argv)
591 #ifdef _CONTACTS_IPC_SERVER
595 sqlite3_result_null(context);
599 person_id = sqlite3_value_int(argv[0]);
600 ctsvc_change_subject_add_changed_person_id(CONTACTS_CHANGE_DELETED, person_id);
602 #ifdef ENABLE_LOG_FEATURE
605 * CASE : do not know the proper new person_id
607 ctsvc_db_phone_log_update_person_id(NULL, person_id, -1, false, NULL);
608 #endif /* ENABLE_LOG_FEATURE */
609 sqlite3_result_null(context);
614 int ctsvc_person_aggregate(int person_id)
620 char *addressbook_ids = NULL;
621 int addressbooks_len = 100;
622 int name_contact_id = 0;
623 int person_name_contact_id = 0;
624 int display_name_source_type = CONTACTS_DISPLAY_NAME_SOURCE_TYPE_INVALID;
625 char query[CTS_SQL_MIN_LEN] = {0};
626 char *ringtone_path = NULL;
627 char *image_thumbnail_path = NULL;
628 char *vibration = NULL;
629 char *message_alert = NULL;
633 ctsvc_person_s *person;
634 bool person_is_favorite = false;
637 * person aggregation : person link/unlink, contact insert (auto link),
638 * contact delete, garbage collection (addressbook delete)
639 * It should be get all contacts of person regardless of permission
640 * Get person info directly instead of contacts_db_get_record(_contacts_person._uri, person_id, (contacts_record_h*)&person);
642 snprintf(query, sizeof(query),
645 "image_thumbnail_path, "
649 "FROM "CTS_TABLE_PERSONS" "
650 "WHERE persons.person_id = %d", person_id);
651 ret = ctsvc_query_prepare(query, &stmt);
652 RETVM_IF(NULL == stmt, ret, "ctsvc_query_prepare() Fail(%d)", ret);
654 if (1 != ctsvc_stmt_step(stmt)) {
655 /* LCOV_EXCL_START */
656 ERR("ctsvc_stmt_step() Fail\n");
657 return CONTACTS_ERROR_DB;
660 ret = contacts_record_create(_contacts_person._uri, (contacts_record_h*)&person);
661 if (CONTACTS_ERROR_NONE != ret) {
662 /* LCOV_EXCL_START */
663 ERR("contacts_record_create() Fail\n");
664 return CONTACTS_ERROR_INTERNAL;
667 person->person_id = ctsvc_stmt_get_int(stmt, 0);
668 person->name_contact_id = ctsvc_stmt_get_int(stmt, 1);
669 temp = ctsvc_stmt_get_text(stmt, 2);
670 person->image_thumbnail_path = SAFE_STRDUP(temp);
671 temp = ctsvc_stmt_get_text(stmt, 3);
672 person->ringtone_path = SAFE_STRDUP(temp);
673 temp = ctsvc_stmt_get_text(stmt, 4);
674 person->vibration = SAFE_STRDUP(temp);
675 temp = ctsvc_stmt_get_text(stmt, 5);
676 person->message_alert = SAFE_STRDUP(temp);
677 ctsvc_stmt_finalize(stmt);
679 /* check image_thumbnail_path */
680 if (person->image_thumbnail_path) {
681 char *image_path = NULL;
683 image_path = ctsvc_utils_get_image_path(person->image_thumbnail_path);
684 snprintf(query, sizeof(query),
685 "SELECT D.id FROM "CTS_TABLE_CONTACTS" C, "CTS_TABLE_DATA" D "
686 "WHERE C.person_id=%d AND C.contact_id=D.contact_id AND C.deleted = 0 "
687 "AND D.datatype=%d AND D.is_primary_default = 1 AND D.data3='%s'",
688 person->person_id, CONTACTS_DATA_TYPE_IMAGE, image_path);
690 ret = ctsvc_query_get_first_int_result(query, &id);
691 if (ret == CONTACTS_ERROR_NONE)
692 image_thumbnail_path = SAFE_STRDUP(person->image_thumbnail_path);
695 /* check name_contact_id */
696 snprintf(query, sizeof(query),
697 "SELECT contact_id FROM %s "
698 "WHERE person_id=%d AND contact_id=%d AND deleted = 0",
699 CTS_TABLE_CONTACTS, person->person_id, person->name_contact_id);
701 ret = ctsvc_query_get_first_int_result(query, &id);
702 if (ret == CONTACTS_ERROR_NONE) {
703 name_contact_id = person->name_contact_id;
704 person_name_contact_id = person->name_contact_id;
707 person_name_contact_id = 0;
710 /* get status of person */
711 snprintf(query, sizeof(query),
712 "SELECT a.status FROM %s c, %s a "
713 "ON c.contact_id = a.contact_id AND c.deleted = 0 "
714 "WHERE c.person_id=%d "
715 "ORDER BY timestamp DESC LIMIT 1",
716 CTS_TABLE_CONTACTS, CTS_TABLE_ACTIVITIES, person->person_id);
717 ret = ctsvc_query_prepare(query, &stmt);
719 /* LCOV_EXCL_START */
720 ERR("ctsvc_query_prepare() Fail(%d)", ret);
721 free(image_thumbnail_path);
722 contacts_record_destroy((contacts_record_h)person, true);
727 if (1 == ctsvc_stmt_step(stmt)) {
728 temp = ctsvc_stmt_get_text(stmt, 0);
729 status = SAFE_STRDUP(temp);
731 ctsvc_stmt_finalize(stmt);
733 /* check ringtone_path */
734 if (person->ringtone_path) {
735 snprintf(query, sizeof(query),
736 "SELECT C.contact_id FROM "CTS_TABLE_CONTACTS" C "
737 "WHERE C.person_id=%d AND C.deleted = 0 "
738 "AND C.ringtone_path = '%s'",
739 person->person_id, person->ringtone_path);
740 ret = ctsvc_query_get_first_int_result(query, &id);
741 if (ret == CONTACTS_ERROR_NONE)
742 ringtone_path = SAFE_STRDUP(person->ringtone_path);
744 ringtone_path = NULL;
747 /* check vibration */
748 if (person->vibration) {
749 snprintf(query, sizeof(query),
750 "SELECT C.contact_idFROM "CTS_TABLE_CONTACTS" C "
751 "WHERE C.person_id=%d AND C.deleted = 0 "
752 "AND C.vibration = '%s'",
753 person->person_id, person->vibration);
754 ret = ctsvc_query_get_first_int_result(query, &id);
755 if (ret == CONTACTS_ERROR_NONE)
756 vibration = SAFE_STRDUP(person->vibration);
761 /* check vibration */
762 if (person->message_alert) {
763 snprintf(query, sizeof(query),
764 "SELECT C.contact_id FROM "CTS_TABLE_CONTACTS" C "
765 "WHERE C.person_id=%d AND C.deleted = 0 "
766 "AND C.message_alert = '%s'",
767 person->person_id, person->message_alert);
768 ret = ctsvc_query_get_first_int_result(query, &id);
769 if (ret == CONTACTS_ERROR_NONE)
770 message_alert = SAFE_STRDUP(person->message_alert);
772 message_alert = NULL;
774 contacts_record_destroy((contacts_record_h)person, true);
776 snprintf(query, sizeof(query),
777 "SELECT contact_id, contacts.addressbook_id, display_name_source, "
778 "image_thumbnail_path, ringtone_path, vibration, message_alert, is_favorite "
780 "WHERE person_id = %d AND contacts.deleted = 0 "
781 "ORDER BY contact_id",
782 CTS_TABLE_CONTACTS, person_id);
783 ret = ctsvc_query_prepare(query, &stmt);
785 /* LCOV_EXCL_START */
786 ERR("ctsvc_query_prepare() Fail(%d)", ret);
787 free(image_thumbnail_path);
798 while ((ret = ctsvc_stmt_step(stmt))) {
799 const char *temp_str;
803 int contact_display_name_source_type = CONTACTS_DISPLAY_NAME_SOURCE_TYPE_INVALID;
804 char *contact_ringtone_path = NULL;
805 char *contact_image_thumbnail_path = NULL;
806 char *contact_vibration = NULL;
807 char *contact_message_alert = NULL;
808 bool is_favorite = false;
812 contact_id = ctsvc_stmt_get_int(stmt, i++);
813 addressbook_id = ctsvc_stmt_get_int(stmt, i++);
814 contact_display_name_source_type = ctsvc_stmt_get_int(stmt, i++);
815 temp = ctsvc_stmt_get_text(stmt, i++);
817 contact_image_thumbnail_path = strdup(temp);
818 temp = ctsvc_stmt_get_text(stmt, i++);
819 contact_ringtone_path = SAFE_STRDUP(temp);
820 temp = ctsvc_stmt_get_text(stmt, i++);
821 contact_vibration = SAFE_STRDUP(temp);
822 temp = ctsvc_stmt_get_text(stmt, i++);
823 contact_message_alert = SAFE_STRDUP(temp);
824 is_favorite = ctsvc_stmt_get_int(stmt, i++);
828 if (display_name_source_type < contact_display_name_source_type) {
829 display_name_source_type = contact_display_name_source_type;
830 name_contact_id = contact_id;
831 } else if (contact_display_name_source_type == display_name_source_type) {
832 if (name_contact_id != person_name_contact_id && person_name_contact_id != 0)
833 name_contact_id = person_name_contact_id;
834 else if (person_name_contact_id == 0 && name_contact_id == 0)
835 name_contact_id = contact_id;
838 addr_len = snprintf(addr, sizeof(addr), "%d%s", addressbook_id, ADDRESSBOOK_ID_DELIM);
839 if (NULL == addressbook_ids) {
840 addressbook_ids = calloc(addressbooks_len + 1, sizeof(char));
841 if (NULL == addressbook_ids)
842 ERR("alloc() failed");
843 } else if (addressbooks_len <= strlen(addressbook_ids) + addr_len) {
844 int new_addressbooks_len = MAX(addressbooks_len * 2, strlen(addressbook_ids) + addr_len + 1);
845 char *new_addressbook_ids = realloc(addressbook_ids, new_addressbooks_len);
846 if (new_addressbook_ids) {
847 addressbook_ids = new_addressbook_ids;
848 addressbooks_len = new_addressbooks_len;
850 ERR("realloc() failed");
854 if (addressbook_ids && addressbooks_len - len > addr_len)
855 len += snprintf(addressbook_ids + len, addressbooks_len - len, "%d%s", addressbook_id, ADDRESSBOOK_ID_DELIM);
857 if (NULL == image_thumbnail_path && contact_image_thumbnail_path && *contact_image_thumbnail_path) {
858 image_thumbnail_path = SAFE_STRDUP(contact_image_thumbnail_path);
860 /*update data table : is_primary_default */
861 ctsvc_db_image_set_primary_default(contact_id, image_thumbnail_path, true);
863 free(contact_image_thumbnail_path);
865 temp_str = contact_ringtone_path;
866 if (NULL == ringtone_path && temp_str && strlen(temp_str))
867 ringtone_path = SAFE_STRDUP(temp_str);
868 free(contact_ringtone_path);
870 temp_str = contact_vibration;
871 if (NULL == vibration && temp_str && strlen(temp_str))
872 vibration = SAFE_STRDUP(temp_str);
873 free(contact_vibration);
875 temp_str = contact_message_alert;
876 if (NULL == message_alert && temp_str && strlen(temp_str))
877 message_alert = SAFE_STRDUP(temp_str);
878 free(contact_message_alert);
881 person_is_favorite = true;
883 ctsvc_stmt_finalize(stmt);
884 version = ctsvc_get_next_ver();
886 snprintf(query, sizeof(query),
887 "UPDATE "CTS_TABLE_PERSONS" SET dirty=0, name_contact_id = %d, changed_ver = %d, "
888 "has_phonenumber = EXISTS(SELECT contact_id FROM "CTS_TABLE_CONTACTS" "
889 "WHERE person_id = %d AND has_phonenumber = 1 AND deleted = 0), "
890 "has_email = EXISTS(SELECT contact_id FROM "CTS_TABLE_CONTACTS" "
891 "WHERE person_id = %d AND has_email = 1 AND deleted = 0), "
892 "link_count = %d, addressbook_ids = ?, ringtone_path=?, vibration=?, message_alert=?, status=?, image_thumbnail_path=? "
893 "WHERE person_id = %d ",
894 name_contact_id, version, person_id,
895 person_id, link_count, person_id);
897 ret = ctsvc_query_prepare(query, &stmt);
899 /* LCOV_EXCL_START */
900 ERR("ctsvc_query_prepare() Fail(%d)", ret);
901 free(addressbook_ids);
902 free(image_thumbnail_path);
912 ctsvc_stmt_bind_text(stmt, 1, addressbook_ids);
914 ctsvc_stmt_bind_text(stmt, 2, ringtone_path);
916 ctsvc_stmt_bind_text(stmt, 3, vibration);
918 ctsvc_stmt_bind_text(stmt, 4, message_alert);
920 ctsvc_stmt_bind_text(stmt, 5, status);
921 if (image_thumbnail_path)
922 ctsvc_stmt_bind_text(stmt, 6, image_thumbnail_path);
924 ret = ctsvc_stmt_step(stmt);
925 if (CONTACTS_ERROR_NONE != ret) {
926 /* LCOV_EXCL_START */
927 ERR("ctsvc_stmt_step() Fail(%d)", ret);
928 ctsvc_stmt_finalize(stmt);
929 free(addressbook_ids);
930 free(image_thumbnail_path);
939 ctsvc_stmt_finalize(stmt);
941 free(addressbook_ids);
942 free(image_thumbnail_path);
948 if (false == person_is_favorite) {
949 snprintf(query, sizeof(query),
950 "DELETE FROM "CTS_TABLE_FAVORITES" WHERE person_id = %d", person_id);
951 ret = ctsvc_query_exec(query);
952 if (CONTACTS_ERROR_NONE != ret) {
953 /* LCOV_EXCL_START */
954 ERR("ctsvc_query_exec() Fail(%d)", ret);
960 ctsvc_set_person_noti();
961 #ifdef _CONTACTS_IPC_SERVER
962 ctsvc_change_subject_add_changed_person_id(CONTACTS_CHANGE_UPDATED, person_id);
965 return CONTACTS_ERROR_NONE;
968 static bool __ctsvc_get_person_favorite_info(int person_id, double *priority)
972 char query[CTS_SQL_MIN_LEN] = {0};
973 snprintf(query, sizeof(query),
974 "SELECT favorite_prio FROM "CTS_TABLE_FAVORITES" WHERE person_id = %d", person_id);
975 ret = ctsvc_query_prepare(query, &stmt);
976 RETVM_IF(NULL == stmt, ret, "ctsvc_query_prepare() Fail(%d)", ret);
978 ret = ctsvc_stmt_step(stmt);
980 *priority = ctsvc_stmt_get_dbl(stmt, 0);
981 ctsvc_stmt_finalize(stmt);
984 ctsvc_stmt_finalize(stmt);
988 int ctsvc_person_link_person(int base_person_id, int person_id)
991 char query[CTS_SQL_MIN_LEN] = {0};
992 int default_number_id = 0;
993 int default_email_id = 0;
994 int default_image_id = 0;
995 contacts_record_h record = NULL;
996 bool base_is_favorite = false;
997 bool is_favorite = false;
998 double favorite_prio = 0.0;
1000 RETVM_IF(base_person_id == person_id, CONTACTS_ERROR_INVALID_PARAMETER,
1001 "base_person_id(%d), person_id(%d)", base_person_id, person_id);
1003 ret = ctsvc_begin_trans();
1004 RETVM_IF(ret < CONTACTS_ERROR_NONE, ret, "ctsvc_begin_trans() Fail(%d)", ret);
1006 ret = __ctsvc_get_person_value(CTSVC_GET_PERSON_DEFAULT_NUMBER_VALUE, base_person_id, &record);
1007 if (CONTACTS_ERROR_NONE != ret) {
1008 ret = __ctsvc_get_person_value(CTSVC_GET_PERSON_DEFAULT_NUMBER_VALUE, person_id, &record);
1009 if (CONTACTS_ERROR_NONE == ret) {
1010 contacts_record_get_int(record, CTSVC_PROPERTY_NUMBER_ID, &default_number_id);
1011 contacts_record_destroy(record, true);
1014 contacts_record_get_int(record, CTSVC_PROPERTY_NUMBER_ID, &default_number_id);
1015 contacts_record_destroy(record, true);
1018 ret = __ctsvc_get_person_value(CTSVC_GET_PERSON_DEFAULT_EMAIL_VALUE, base_person_id, &record);
1019 if (CONTACTS_ERROR_NONE != ret) {
1020 ret = __ctsvc_get_person_value(CTSVC_GET_PERSON_DEFAULT_EMAIL_VALUE, person_id, &record);
1021 if (CONTACTS_ERROR_NONE == ret) {
1022 contacts_record_get_int(record, CTSVC_PROPERTY_EMAIL_ID, &default_email_id);
1023 contacts_record_destroy(record, true);
1026 contacts_record_get_int(record, CTSVC_PROPERTY_EMAIL_ID, &default_email_id);
1027 contacts_record_destroy(record, true);
1030 ret = __ctsvc_get_person_value(CTSVC_GET_PERSON_DEFAULT_IMAGE_VALUE, base_person_id, &record);
1031 if (CONTACTS_ERROR_NONE != ret) {
1032 ret = __ctsvc_get_person_value(CTSVC_GET_PERSON_DEFAULT_IMAGE_VALUE, person_id, &record);
1033 if (CONTACTS_ERROR_NONE == ret) {
1034 contacts_record_get_int(record, CTSVC_PROPERTY_IMAGE_ID, &default_image_id);
1035 contacts_record_destroy(record, true);
1038 contacts_record_get_int(record, CTSVC_PROPERTY_IMAGE_ID, &default_image_id);
1039 contacts_record_destroy(record, true);
1042 base_is_favorite = __ctsvc_get_person_favorite_info(base_person_id, &favorite_prio);
1043 if (false == base_is_favorite)
1044 is_favorite = __ctsvc_get_person_favorite_info(person_id, &favorite_prio);
1046 snprintf(query, sizeof(query),
1047 "UPDATE %s SET person_id = %d WHERE person_id = %d AND deleted = 0",
1048 CTS_TABLE_CONTACTS, base_person_id, person_id);
1049 ret = ctsvc_query_exec(query);
1050 if (CONTACTS_ERROR_NONE != ret) {
1051 /* LCOV_EXCL_START */
1052 ERR("ctsvc_query_exec() Fail(%d)", ret);
1053 ctsvc_end_trans(false);
1055 /* LCOV_EXCL_STOP */
1058 ctsvc_person_aggregate(base_person_id);
1060 if (default_number_id)
1061 __ctsvc_put_person_default_data(base_person_id, default_number_id, CONTACTS_DATA_TYPE_NUMBER);
1063 if (default_email_id)
1064 __ctsvc_put_person_default_data(base_person_id, default_email_id, CONTACTS_DATA_TYPE_EMAIL);
1066 if (default_image_id)
1067 __ctsvc_put_person_default_image(base_person_id, default_image_id);
1069 #ifdef ENABLE_LOG_FEATURE
1072 * Updating phonelog person_id before deleting person
1073 * Because, when deleting, ctsvc_db_person_delete_callback will be called
1074 * the logic takes more time to find proper person_id (base_person_id)
1076 ctsvc_db_phone_log_update_person_id(NULL, person_id, base_person_id, true, NULL);
1077 #endif /* ENABLE_LOG_FEATURE */
1079 snprintf(query, sizeof(query), "DELETE FROM %s WHERE person_id = %d",
1080 CTS_TABLE_PERSONS, person_id);
1081 ret = ctsvc_query_exec(query);
1082 if (CONTACTS_ERROR_NONE != ret) {
1083 /* LCOV_EXCL_START */
1084 ERR("ctsvc_query_exec() Fail(%d)", ret);
1085 ctsvc_end_trans(false);
1087 /* LCOV_EXCL_STOP */
1090 *#ifdef _CONTACTS_IPC_SERVER
1091 * It will be added in ctsvc_db_person_delete_callback
1092 * ctsvc_change_subject_add_changed_person_id(CONTACTS_CHANGE_DELETED, person_id);
1097 snprintf(query, sizeof(query),
1098 "INSERT INTO "CTS_TABLE_FAVORITES" values(%d, %f)", base_person_id, favorite_prio);
1099 ret = ctsvc_query_exec(query);
1100 if (CONTACTS_ERROR_NONE != ret) {
1101 /* LCOV_EXCL_START */
1102 ERR("ctsvc_query_exec() Fail(%d)", ret);
1103 ctsvc_end_trans(false);
1105 /* LCOV_EXCL_STOP */
1109 ctsvc_set_person_noti();
1110 ret = ctsvc_end_trans(true);
1111 if (ret < CONTACTS_ERROR_NONE) {
1112 /* LCOV_EXCL_START */
1113 ERR("ctsvc_end_trans() Fail(%d)", ret);
1115 /* LCOV_EXCL_STOP */
1117 return CONTACTS_ERROR_NONE;
1121 static int __ctsvc_update_primary_default_data(int person_id)
1124 contacts_record_h record = NULL;
1125 char query[CTS_SQL_MIN_LEN] = {0};
1128 ret = __ctsvc_get_person_value(CTSVC_GET_PERSON_DEFAULT_NUMBER_VALUE, person_id, &record);
1129 if (CONTACTS_ERROR_NONE != ret) {
1130 snprintf(query, sizeof(query),
1131 "SELECT contact_id "
1133 "WHERE person_id = %d AND deleted = 0 "
1134 "ORDER BY contact_id",
1135 CTS_TABLE_CONTACTS, person_id);
1136 ret = ctsvc_query_prepare(query, &stmt);
1137 RETVM_IF(NULL == stmt, ret, "ctsvc_query_prepare() Fail(%d)", ret);
1139 while (1 == ctsvc_stmt_step(stmt)) {
1140 int contact_id = ctsvc_stmt_get_int(stmt, 0);
1141 cts_stmt stmt_number;
1143 snprintf(query, sizeof(query),
1144 "SELECT id, is_default FROM %s "
1145 "WHERE contact_id = %d AND datatype = %d AND is_default = 1 AND is_my_profile = 0",
1146 CTS_TABLE_DATA, contact_id, CONTACTS_DATA_TYPE_NUMBER);
1148 ret = ctsvc_query_prepare(query, &stmt_number);
1149 if (NULL == stmt_number) {
1150 /* LCOV_EXCL_START */
1151 ERR("ctsvc_query_prepare() Fail(%d)", ret);
1152 ctsvc_stmt_finalize(stmt);
1154 /* LCOV_EXCL_STOP */
1157 if (1 == ctsvc_stmt_step(stmt_number)) {
1158 int default_number_id = ctsvc_stmt_get_int(stmt_number, 0);
1159 __ctsvc_put_person_default_data(person_id, default_number_id, CONTACTS_DATA_TYPE_NUMBER);
1160 ctsvc_stmt_finalize(stmt_number);
1163 ctsvc_stmt_finalize(stmt_number);
1165 ctsvc_stmt_finalize(stmt);
1167 contacts_record_destroy(record, true);
1170 ret = __ctsvc_get_person_value(CTSVC_GET_PERSON_DEFAULT_EMAIL_VALUE, person_id, &record);
1171 if (CONTACTS_ERROR_NONE != ret) {
1172 snprintf(query, sizeof(query),
1173 "SELECT contact_id "
1175 "WHERE person_id = %d AND deleted = 0 "
1176 "ORDER BY contact_id",
1177 CTS_TABLE_CONTACTS, person_id);
1178 ret = ctsvc_query_prepare(query, &stmt);
1179 RETVM_IF(NULL == stmt, ret, "ctsvc_query_prepare() Fail(%d)", ret);
1181 while (1 == ctsvc_stmt_step(stmt)) {
1182 int contact_id = ctsvc_stmt_get_int(stmt, 0);
1183 cts_stmt stmt_email;
1185 snprintf(query, sizeof(query),
1186 "SELECT id, is_default FROM %s "
1187 "WHERE contact_id = %d AND datatype = %d AND is_default = 1 AND is_my_profile = 0",
1188 CTS_TABLE_DATA, contact_id, CONTACTS_DATA_TYPE_EMAIL);
1190 ret = ctsvc_query_prepare(query, &stmt_email);
1191 if (NULL == stmt_email) {
1192 /* LCOV_EXCL_START */
1193 ERR("ctsvc_query_prepare() Fail(%d)", ret);
1194 ctsvc_stmt_finalize(stmt);
1196 /* LCOV_EXCL_STOP */
1199 if (1 == ctsvc_stmt_step(stmt_email)) {
1200 int default_email_id = ctsvc_stmt_get_int(stmt_email, 0);
1201 __ctsvc_put_person_default_data(person_id, default_email_id, CONTACTS_DATA_TYPE_EMAIL);
1202 ctsvc_stmt_finalize(stmt_email);
1205 ctsvc_stmt_finalize(stmt_email);
1207 ctsvc_stmt_finalize(stmt);
1209 contacts_record_destroy(record, true);
1212 ret = __ctsvc_get_person_value(CTSVC_GET_PERSON_DEFAULT_IMAGE_VALUE, person_id, &record);
1213 if (CONTACTS_ERROR_NONE != ret) {
1214 snprintf(query, sizeof(query),
1215 "SELECT contact_id "
1217 "WHERE person_id = %d AND deleted = 0 "
1218 "ORDER BY contact_id",
1219 CTS_TABLE_CONTACTS, person_id);
1220 ret = ctsvc_query_prepare(query, &stmt);
1221 RETVM_IF(NULL == stmt, ret, "ctsvc_query_prepare() Fail(%d)", ret);
1223 while (1 == ctsvc_stmt_step(stmt)) {
1224 int contact_id = ctsvc_stmt_get_int(stmt, 0);
1225 cts_stmt stmt_image;
1227 snprintf(query, sizeof(query),
1228 "SELECT id, is_default FROM %s "
1229 "WHERE contact_id = %d AND datatype = %d AND is_default = 1 AND is_my_profile = 0",
1230 CTS_TABLE_DATA, contact_id, CONTACTS_DATA_TYPE_IMAGE);
1232 ret = ctsvc_query_prepare(query, &stmt_image);
1233 if (NULL == stmt_image) {
1234 /* LCOV_EXCL_START */
1235 ERR("ctsvc_query_prepare() Fail(%d)", ret);
1236 ctsvc_stmt_finalize(stmt);
1238 /* LCOV_EXCL_STOP */
1241 if (1 == ctsvc_stmt_step(stmt_image)) {
1242 int default_image_id = ctsvc_stmt_get_int(stmt_image, 0);
1243 __ctsvc_put_person_default_image(person_id, default_image_id);
1244 ctsvc_stmt_finalize(stmt_image);
1247 ctsvc_stmt_finalize(stmt_image);
1249 ctsvc_stmt_finalize(stmt);
1251 contacts_record_destroy(record, true);
1254 return CONTACTS_ERROR_NONE;
1257 int ctsvc_person_unlink_contact(int person_id, int contact_id, int *out_person_id)
1262 char query[CTS_SQL_MIN_LEN] = {0};
1263 contacts_record_h record = NULL;
1264 bool is_favorite = false;
1265 double priority = 0.0;
1267 RETVM_IF(person_id <= 0 || contact_id <= 0, CONTACTS_ERROR_INVALID_PARAMETER,
1268 "person_id(%d), person_id(%d)", person_id, person_id);
1273 ret = ctsvc_begin_trans();
1274 RETVM_IF(ret, ret, "ctsvc_begin_trans() Fail(%d)", ret);
1276 snprintf(query, sizeof(query),
1277 "SELECT link_count FROM "CTS_TABLE_PERSONS" WHERE person_id=%d", person_id);
1278 ret = ctsvc_query_get_first_int_result(query, &link_count);
1279 if (CONTACTS_ERROR_NONE != ret) {
1280 ctsvc_end_trans(false);
1284 if (link_count == 1) {
1285 /* LCOV_EXCL_START */
1286 ERR("This person(%d) has one contact(%d)", person_id, contact_id);
1287 ctsvc_end_trans(false);
1288 return CONTACTS_ERROR_INVALID_PARAMETER;
1289 /* LCOV_EXCL_STOP */
1292 ret = ctsvc_db_contact_get(contact_id, (contacts_record_h*)&record);
1293 if (CONTACTS_ERROR_NONE != ret) {
1294 /* LCOV_EXCL_START */
1295 ERR("ctsvc_db_contact_get() Fail(%d)", ret);
1296 ctsvc_end_trans(false);
1298 /* LCOV_EXCL_STOP */
1301 /* create new person */
1302 id = ctsvc_db_insert_person(record);
1303 if (id < CONTACTS_ERROR_NONE) {
1304 /* LCOV_EXCL_START */
1305 ERR("ctsvc_db_insert_person() Fail(%d)", id);
1306 ctsvc_end_trans(false);
1307 contacts_record_destroy(record, true);
1309 /* LCOV_EXCL_STOP */
1312 /* insert statistic info for new person */
1313 snprintf(query, sizeof(query),
1314 "INSERT INTO %s (person_id, usage_type, times_used) "
1315 "SELECT %d, usage_type, times_used FROM %s WHERE person_id = %d",
1316 CTS_TABLE_CONTACT_STAT, id, CTS_TABLE_CONTACT_STAT, person_id);
1317 ret = ctsvc_query_exec(query);
1318 if (CONTACTS_ERROR_NONE != ret) {
1319 /* LCOV_EXCL_START */
1320 ERR("ctsvc_query_exec() Fail(%d)", ret);
1321 ctsvc_end_trans(false);
1322 contacts_record_destroy(record, true);
1324 /* LCOV_EXCL_STOP */
1327 is_favorite = __ctsvc_get_person_favorite_info(person_id, &priority);
1329 /* update person_id of unlinked contact */
1330 snprintf(query, sizeof(query),
1331 "UPDATE %s SET person_id = %d WHERE contact_id = %d",
1332 CTS_TABLE_CONTACTS, id, contact_id);
1333 ret = ctsvc_query_exec(query);
1334 if (CONTACTS_ERROR_NONE != ret) {
1335 /* LCOV_EXCL_START */
1336 ERR("ctsvc_query_exec() Fail(%d)", ret);
1337 ctsvc_end_trans(false);
1338 contacts_record_destroy(record, true);
1340 /* LCOV_EXCL_STOP */
1343 /* update bsae person info */
1344 ret = ctsvc_person_aggregate(person_id);
1345 if (CONTACTS_ERROR_NONE != ret) {
1346 /* LCOV_EXCL_START */
1347 ERR("ctsvc_person_aggregate(%d) Fail(%d)", person_id, ret);
1348 ctsvc_end_trans(false);
1349 contacts_record_destroy(record, true);
1351 /* LCOV_EXCL_STOP */
1354 if (is_favorite && ((ctsvc_contact_s*)record)->is_favorite) {
1355 snprintf(query, sizeof(query),
1356 "INSERT OR REPLACE INTO "CTS_TABLE_FAVORITES" values(%d, %f)", id, priority);
1357 ret = ctsvc_query_exec(query);
1358 if (CONTACTS_ERROR_NONE != ret) {
1359 /* LCOV_EXCL_START */
1360 ERR("ctsvc_query_exec() Fail(%d)", ret);
1361 ctsvc_end_trans(false);
1362 contacts_record_destroy(record, true);
1364 /* LCOV_EXCL_STOP */
1367 contacts_record_destroy(record, true);
1369 __ctsvc_update_primary_default_data(person_id);
1371 #ifdef ENABLE_LOG_FEATURE
1372 /* update phonelog */
1373 ctsvc_db_phone_log_update_person_id(NULL, person_id, id, false, NULL);
1374 #endif /* ENABLE_LOG_FEATURE */
1377 *out_person_id = id;
1378 ctsvc_set_person_noti();
1379 ret = ctsvc_end_trans(true);
1380 if (ret < CONTACTS_ERROR_NONE) {
1381 /* LCOV_EXCL_START */
1382 ERR("ctsvc_end_trans() Fail(%d)", ret);
1384 /* LCOV_EXCL_STOP */
1386 return CONTACTS_ERROR_NONE;
1390 int ctsvc_person_do_garbage_collection(void)
1393 cts_stmt stmt = NULL;
1394 char query[CTS_SQL_MIN_LEN] = {0};
1396 snprintf(query, sizeof(query), "SELECT person_id FROM "CTS_TABLE_PERSONS" WHERE dirty=1");
1398 ret = ctsvc_query_prepare(query, &stmt);
1399 RETVM_IF(NULL == stmt, ret, "ctsvc_query_prepare() Fail(%d)", ret);
1401 while (1 /*CTS_TRUE*/ == ctsvc_stmt_step(stmt)) {
1403 person_id = ctsvc_stmt_get_int(stmt, 0);
1404 ctsvc_person_aggregate(person_id);
1405 #ifdef ENABLE_LOG_FEATURE
1406 /* update phonelog */
1407 ctsvc_db_phone_log_update_person_id(NULL, person_id, -1, false, NULL);
1408 #endif /* ENABLE_LOG_FEATURE */
1410 ctsvc_stmt_finalize(stmt);
1412 return CONTACTS_ERROR_NONE;
1415 int ctsvc_person_reset_usage(int person_id, contacts_usage_type_e type)
1418 char query[CTS_SQL_MAX_LEN] = {0};
1420 RETVM_IF(person_id <= 0, CONTACTS_ERROR_INVALID_PARAMETER, "contact_id should be greater than 0");
1422 snprintf(query, sizeof(query),
1423 "UPDATE %s SET times_used = 0 WHERE person_id = %d AND usage_type = %d",
1424 CTS_TABLE_CONTACT_STAT, person_id, type);
1426 ret = ctsvc_begin_trans();
1427 RETVM_IF(ret, ret, "ctsvc_begin_trans() Fail(%d)", ret);
1429 ret = ctsvc_query_exec(query);
1430 if (CONTACTS_ERROR_NONE != ret) {
1431 /* LCOV_EXCL_START */
1432 ERR("ctsvc_query_exec() Fail(%d)", ret);
1433 ctsvc_end_trans(false);
1435 /* LCOV_EXCL_STOP */
1438 ret = ctsvc_end_trans(true);
1439 if (ret < CONTACTS_ERROR_NONE) {
1440 /* LCOV_EXCL_START */
1441 ERR("ctsvc_end_trans() Fail(%d)", ret);
1443 /* LCOV_EXCL_STOP */
1445 return CONTACTS_ERROR_NONE;
1449 int ctsvc_person_set_favorite_order(int person_id, int front_person_id, int back_person_id)
1452 double front_prio = 0.0;
1453 double back_prio = 0.0;
1456 char query[CTS_SQL_MAX_LEN] = {0};
1458 snprintf(query, sizeof(query), "SELECT favorite_prio FROM "CTS_TABLE_FAVORITES" WHERE person_id = ?");
1460 ret = ctsvc_query_prepare(query, &stmt);
1461 RETVM_IF(NULL == stmt, ret, "ctsvc_query_prepare() Fail(%d)", ret);
1463 ctsvc_stmt_bind_int(stmt, 1, front_person_id);
1464 ret = ctsvc_stmt_step(stmt);
1465 if (1 /*CTS_TRUE*/ == ret)
1466 front_prio = ctsvc_stmt_get_dbl(stmt, 0);
1467 ctsvc_stmt_reset(stmt);
1468 ctsvc_stmt_bind_int(stmt, 1, back_person_id);
1469 ret = ctsvc_stmt_step(stmt);
1470 if (1 /*CTS_TRUE*/ == ret)
1471 back_prio = ctsvc_stmt_get_dbl(stmt, 0);
1472 ctsvc_stmt_finalize(stmt);
1474 RETVM_IF(0.0 == front_prio && 0.0 == back_prio, CONTACTS_ERROR_INVALID_PARAMETER,
1475 "The indexes for front and back are invalid.");
1477 if (0.0 == back_prio)
1478 prio = front_prio + 1;
1480 prio = (front_prio + back_prio) / 2;
1482 ret = ctsvc_begin_trans();
1483 RETVM_IF(ret, ret, "ctsvc_begin_trans() Fail(%d)", ret);
1485 snprintf(query, sizeof(query),
1486 "UPDATE %s SET favorite_prio = %f WHERE person_id = %d",
1487 CTS_TABLE_FAVORITES, prio, person_id);
1489 ret = ctsvc_query_exec(query);
1490 if (CONTACTS_ERROR_NONE != ret) {
1491 /* LCOV_EXCL_START */
1492 ERR("ctsvc_query_exec() Fail(%d)", ret);
1493 ctsvc_end_trans(false);
1495 /* LCOV_EXCL_STOP */
1498 ctsvc_set_person_noti();
1500 ret = ctsvc_end_trans(true);
1501 if (ret < CONTACTS_ERROR_NONE) {
1502 /* LCOV_EXCL_START */
1503 ERR("ctsvc_end_trans() Fail(%d)", ret);
1505 /* LCOV_EXCL_STOP */
1507 return CONTACTS_ERROR_NONE;
1511 int ctsvc_person_set_default_property(contacts_person_property_e property, int person_id,
1516 ret = ctsvc_begin_trans();
1517 RETVM_IF(ret < CONTACTS_ERROR_NONE, CONTACTS_ERROR_DB, "ctsvc_begin_trans() Fail(%d)", ret);
1520 case CONTACTS_PERSON_PROPERTY_NAME_CONTACT:
1521 ret = __ctsvc_put_person_default_name(person_id, id); /* contact id */
1523 case CONTACTS_PERSON_PROPERTY_NUMBER:
1524 ret = __ctsvc_put_person_default_data(person_id, id, CONTACTS_DATA_TYPE_NUMBER); /* number id */
1526 case CONTACTS_PERSON_PROPERTY_EMAIL:
1527 ret = __ctsvc_put_person_default_data(person_id, id, CONTACTS_DATA_TYPE_EMAIL); /* email id */
1529 case CONTACTS_PERSON_PROPERTY_IMAGE:
1530 ret = __ctsvc_put_person_default_image(person_id, id); /* image id */
1533 ret = CONTACTS_ERROR_INVALID_PARAMETER;
1536 if (ret < CONTACTS_ERROR_NONE) {
1537 /* LCOV_EXCL_START */
1538 ERR("contacts_person_set_default_property() Fail(%d) : person property (%d)", ret, property);
1539 ctsvc_end_trans(false);
1541 /* LCOV_EXCL_STOP */
1544 #ifdef _CONTACTS_IPC_SERVER
1545 ctsvc_change_subject_add_changed_person_id(CONTACTS_CHANGE_UPDATED, person_id);
1547 ctsvc_set_person_noti();
1548 ret = ctsvc_end_trans(true);
1553 int ctsvc_person_get_default_property(contacts_person_property_e property, int person_id,
1556 int ret = CONTACTS_ERROR_NONE;
1557 char query[CTS_SQL_MAX_LEN] = {0};
1559 RETVM_IF(person_id <= 0 || id == NULL, CONTACTS_ERROR_INVALID_PARAMETER, "id should be greater than 0");
1563 case CONTACTS_PERSON_PROPERTY_NAME_CONTACT:
1564 snprintf(query, sizeof(query),
1565 "SELECT name_contact_id FROM "CTS_TABLE_PERSONS" WHERE person_id = %d",
1568 case CONTACTS_PERSON_PROPERTY_NUMBER:
1569 snprintf(query, sizeof(query),
1570 "SELECT id FROM "CTS_TABLE_DATA" WHERE is_primary_default = 1 AND datatype = %d AND is_my_profile = 0 AND "
1571 "contact_id in (SELECT contact_id FROM "CTS_TABLE_CONTACTS" "
1572 "WHERE person_id = %d AND deleted = 0)",
1573 CONTACTS_DATA_TYPE_NUMBER, person_id);
1575 case CONTACTS_PERSON_PROPERTY_EMAIL:
1576 snprintf(query, sizeof(query),
1577 "SELECT id FROM "CTS_TABLE_DATA" WHERE is_primary_default = 1 AND datatype = %d AND is_my_profile = 0 AND "
1578 "contact_id in (SELECT contact_id FROM "CTS_TABLE_CONTACTS" "
1579 "WHERE person_id = %d AND deleted = 0)",
1580 CONTACTS_DATA_TYPE_EMAIL, person_id);
1582 case CONTACTS_PERSON_PROPERTY_IMAGE:
1583 snprintf(query, sizeof(query),
1584 "SELECT id FROM "CTS_TABLE_DATA" WHERE is_primary_default = 1 AND datatype = %d AND is_my_profile = 0 AND "
1585 "contact_id in (SELECT contact_id FROM "CTS_TABLE_CONTACTS" "
1586 "WHERE person_id = %d AND deleted = 0)",
1587 CONTACTS_DATA_TYPE_IMAGE, person_id);
1590 ret = CONTACTS_ERROR_INVALID_PARAMETER;
1596 ret = ctsvc_query_get_first_int_result(query, &result);
1597 RETVM_IF(ret != CONTACTS_ERROR_NONE, ret, "ctsvc_query_get_first_int_result() Fail(%d)", ret);
1604 static void __ctsvc_collate_numbers(contacts_record_h record, GSList **nums)
1606 int ret = CONTACTS_ERROR_NONE;
1607 GList *cursor = NULL;
1608 ctsvc_contact_s *contact = (ctsvc_contact_s*)record;
1609 ctsvc_number_s *number_data;
1611 if (NULL == contact->numbers) {
1612 DBG("NULL == contact->numbers");
1616 for (cursor = contact->numbers->records; cursor; cursor = cursor->next) {
1617 number_data = cursor->data;
1618 if (number_data && number_data->normalized && number_data->normalized[0]) {
1619 char minmatch[strlen(number_data->normalized) + 1];
1620 ret = ctsvc_get_minmatch_number(number_data->normalized, minmatch, sizeof(minmatch),
1621 ctsvc_get_phonenumber_min_match_digit());
1623 if (CONTACTS_ERROR_NONE != ret)
1626 if (NULL == *nums || NULL == g_slist_find(*nums, minmatch))
1627 *nums = g_slist_append(*nums, strdup(minmatch));
1633 static void __ctsvc_collate_emails(contacts_record_h record, GSList **emails)
1635 GList *cursor = NULL;
1636 ctsvc_contact_s *contact = (ctsvc_contact_s*)record;
1637 ctsvc_email_s *email_data;
1638 int local_part_len = 0;
1639 char local_part[256] = {0};
1641 if (NULL == contact->emails) {
1642 DBG("NULL == contact->emails");
1646 for (cursor = contact->emails->records; cursor; cursor = cursor->next) {
1647 email_data = cursor->data;
1648 if (email_data && email_data->email_addr && email_data->email_addr[0]) {
1649 local_part_len = strcspn(email_data->email_addr, "@");
1650 if (local_part_len <= 0 || strlen(email_data->email_addr) <= local_part_len)
1653 strncpy(local_part, email_data->email_addr, local_part_len + 1);
1655 if (NULL == *emails || NULL == g_slist_find(*emails, local_part))
1656 *emails = g_slist_append(*emails, strdup(local_part));
1661 static void __ctsvc_collate_names(contacts_record_h record, GSList **names)
1663 ctsvc_contact_s *contact = (ctsvc_contact_s*)record;
1664 int comp_name_len = CTSVC_COMP_NAME_LEN;
1665 char comp_name[256] = {0};
1668 if (CONTACTS_DISPLAY_NAME_SOURCE_TYPE_NAME == contact->display_source_type)
1669 name = contact->reverse_sort_name;
1671 if (name && comp_name_len <= strlen(name)) {
1672 if (CTSVC_SORT_KOREAN == contact->display_name_language) { /*compare first name*/
1673 strncpy(comp_name, name + (strlen(name) -comp_name_len),
1675 } else { /*compare last name*/
1676 comp_name_len = strcspn(name, ", ");
1677 strncpy(comp_name, name, comp_name_len);
1680 if (NULL == *names || NULL == g_slist_find(*names, comp_name))
1681 *names = g_slist_append(*names, strdup(comp_name));
1686 static int __ctsvc_get_person_info_by_person_id(int person_id, GSList **nums, GSList **emails, GSList **names)
1688 int ret = CONTACTS_ERROR_NONE;
1689 GSList *contact_ids = NULL;
1690 GSList *cursor = NULL;
1692 char query[CTS_SQL_MIN_LEN] = {0};
1695 snprintf(query, sizeof(query),
1696 "SELECT contact_id FROM "CTS_TABLE_CONTACTS" "
1697 "WHERE deleted = 0 AND person_id = %d", person_id);
1699 ret = ctsvc_query_prepare(query, &stmt);
1700 RETVM_IF(NULL == stmt, ret, "ctsvc_query_prepare() Fail(%d)", ret);
1702 while ((ret = ctsvc_stmt_step(stmt))) {
1706 /* LCOV_EXCL_START */
1707 ERR("ctsvc_stmt_step() Fail(%d)", ret);
1708 ctsvc_stmt_finalize(stmt);
1710 /* LCOV_EXCL_STOP */
1712 contact_id = ctsvc_stmt_get_int(stmt, 0);
1714 contact_ids = g_slist_append(contact_ids, GINT_TO_POINTER(contact_id));
1716 ctsvc_stmt_finalize(stmt);
1718 if (NULL == contact_ids) {
1719 /* LCOV_EXCL_START */
1720 ERR("Fail to get contacts by person_id");
1721 return CONTACTS_ERROR_DB;
1722 /* LCOV_EXCL_STOP */
1725 for (cursor = contact_ids; cursor; cursor = cursor->next) {
1726 contacts_record_h record = NULL;
1728 int contact_id = GPOINTER_TO_INT(cursor->data);
1729 ret = ctsvc_db_contact_get(contact_id, &record);
1730 if (CONTACTS_ERROR_NONE != ret) {
1731 WARN("ctsvc_db_contact_get() Fail(%d), contact_id = %d", ret, contact_id);
1735 __ctsvc_collate_numbers(record, nums);
1736 __ctsvc_collate_emails(record, emails);
1737 __ctsvc_collate_names(record, names);
1739 contacts_record_destroy(record, true);
1742 g_slist_free(contact_ids);
1747 static void __ctsvc_make_sub_query_by_num(GSList *nums, int person_id,
1748 char **sub_query, int *sub_size, int *sub_len)
1750 GSList *cursor = NULL;
1751 char temp_query[CTS_SQL_MIN_LEN] = {0};
1753 /* Add 2 points whenever a number is matched */
1754 snprintf(temp_query, CTS_SQL_MIN_LEN,
1755 "SELECT C.person_id, 2 score FROM "CTS_TABLE_CONTACTS" C, "CTS_TABLE_DATA" D "
1756 "ON C.contact_id=D.contact_id AND D.datatype=%d AND C.deleted = 0 "
1757 "AND C.person_id <> %d AND D.is_my_profile = 0 "
1758 "WHERE D.data4 = '",
1759 CONTACTS_DATA_TYPE_NUMBER, person_id);
1761 for (cursor = nums; cursor; cursor = cursor->next) {
1762 char *minmatch = cursor->data;
1763 if (NULL == minmatch)
1767 *sub_len += SAFE_SNPRINTF(sub_query, sub_size, *sub_len, " UNION ALL ");
1769 *sub_len += SAFE_SNPRINTF(sub_query, sub_size, *sub_len, temp_query);
1770 *sub_len += SAFE_SNPRINTF(sub_query, sub_size, *sub_len, minmatch);
1771 *sub_len += SAFE_SNPRINTF(sub_query, sub_size, *sub_len, "'");
1775 static void __ctsvc_make_sub_query_by_email(GSList *emails, int person_id,
1776 char **sub_query, int *sub_size, int *sub_len)
1778 GSList *cursor = NULL;
1779 char temp_query[CTS_SQL_MIN_LEN] = {0};
1781 /* Add 2 points whenever a email id is matched */
1782 snprintf(temp_query, CTS_SQL_MIN_LEN,
1783 "SELECT C.person_id, 2 score FROM "CTS_TABLE_CONTACTS" C, "CTS_TABLE_DATA" D "
1784 "ON C.contact_id=D.contact_id AND D.datatype=%d AND C.deleted = 0 "
1785 "AND C.person_id <> %d AND D.is_my_profile = 0 "
1786 "WHERE D.data3 LIKE '",
1787 CONTACTS_DATA_TYPE_EMAIL, person_id);
1789 for (cursor = emails; cursor; cursor = cursor->next) {
1790 char *local_part = cursor->data;
1791 if (NULL == local_part)
1795 *sub_len += SAFE_SNPRINTF(sub_query, sub_size, *sub_len, " UNION ALL ");
1797 *sub_len += SAFE_SNPRINTF(sub_query, sub_size, *sub_len, temp_query);
1798 *sub_len += SAFE_SNPRINTF(sub_query, sub_size, *sub_len, local_part);
1799 *sub_len += SAFE_SNPRINTF(sub_query, sub_size, *sub_len, "%'");
1803 static void __ctsvc_make_sub_query_by_name(GSList *names, int person_id,
1804 char **sub_query, int *sub_size, int *sub_len)
1806 GSList *cursor = NULL;
1807 char temp_query[CTS_SQL_MIN_LEN] = {0};
1809 /* Add 1 point whenever last name is matched (first name in case of Korean) */
1810 snprintf(temp_query, CTS_SQL_MIN_LEN,
1811 "SELECT person_id, 1 score FROM "CTS_TABLE_CONTACTS" "
1812 "WHERE person_id <> %d AND display_name_source=%d "
1813 "AND reverse_sort_name LIKE '",
1814 person_id, CONTACTS_DISPLAY_NAME_SOURCE_TYPE_NAME);
1816 for (cursor = names; cursor; cursor = cursor->next) {
1817 char *name = cursor->data;
1821 int sort_type = ctsvc_get_name_sort_type(name);
1824 *sub_len += SAFE_SNPRINTF(sub_query, sub_size, *sub_len, " UNION ALL ");
1826 *sub_len += SAFE_SNPRINTF(sub_query, sub_size, *sub_len, temp_query);
1827 if (CTSVC_SORT_KOREAN == sort_type) { /*compare first name*/
1828 *sub_len += SAFE_SNPRINTF(sub_query, sub_size, *sub_len, "%");
1829 *sub_len += SAFE_SNPRINTF(sub_query, sub_size, *sub_len, name);
1830 *sub_len += SAFE_SNPRINTF(sub_query, sub_size, *sub_len, "'");
1831 } else { /*compare last name*/
1832 *sub_len += SAFE_SNPRINTF(sub_query, sub_size, *sub_len, name);
1833 *sub_len += SAFE_SNPRINTF(sub_query, sub_size, *sub_len, "%'");
1838 int ctsvc_person_get_aggregation_suggestions(int person_id, int limit, contacts_list_h *out_list)
1840 int ret = CONTACTS_ERROR_NONE;
1844 GSList *nums = NULL;
1845 GSList *emails = NULL;
1846 GSList *names = NULL;
1848 char *sub_query = NULL;
1851 int sub_size = CTS_SQL_MAX_LEN;
1852 contacts_list_h list = NULL;
1853 cts_stmt stmt = NULL;
1855 RETV_IF(person_id <= 0, CONTACTS_ERROR_INVALID_PARAMETER);
1856 RETV_IF(NULL == out_list, CONTACTS_ERROR_INVALID_PARAMETER);
1860 ret = __ctsvc_get_person_info_by_person_id(person_id, &nums, &emails, &names);
1861 if (CONTACTS_ERROR_NONE != ret) {
1862 /* LCOV_EXCL_START */
1863 ERR("__ctsvc_get_person_info_by_person_id() Fail(%d)", ret);
1865 /* LCOV_EXCL_STOP */
1868 sub_query = calloc(1, sub_size);
1869 if (NULL == sub_query) {
1870 /* LCOV_EXCL_START */
1871 ERR("calloc() Fail");
1872 g_slist_free_full(nums, free);
1873 g_slist_free_full(emails, free);
1874 g_slist_free_full(names, free);
1875 return CONTACTS_ERROR_OUT_OF_MEMORY;
1876 /* LCOV_EXCL_STOP */
1880 __ctsvc_make_sub_query_by_num(nums, person_id, &sub_query, &sub_size, &sub_len);
1881 g_slist_free_full(nums, free);
1885 __ctsvc_make_sub_query_by_email(emails, person_id, &sub_query, &sub_size, &sub_len);
1886 g_slist_free_full(emails, free);
1890 __ctsvc_make_sub_query_by_name(names, person_id, &sub_query, &sub_size, &sub_len);
1891 g_slist_free_full(names, free);
1897 DBG("no numbers, emails, names for query");
1898 return CONTACTS_ERROR_NO_DATA;
1901 query_size = CTS_SQL_MIN_LEN + sub_len;
1902 query = calloc(1, query_size);
1903 if (NULL == query) {
1904 /* LCOV_EXCL_START */
1905 ERR("calloc() Fail");
1907 return CONTACTS_ERROR_OUT_OF_MEMORY;
1908 /* LCOV_EXCL_STOP */
1911 snprintf(query, query_size,
1912 "SELECT person_id, sum(score) FROM (%s) "
1913 "GROUP BY person_id ORDER BY score DESC",
1915 ret = ctsvc_query_prepare(query, &stmt);
1917 /* LCOV_EXCL_START */
1918 ERR("ctsvc_query_prepare fail(%d)", ret);
1922 /* LCOV_EXCL_STOP */
1926 while ((ret = ctsvc_stmt_step(stmt))) {
1928 /* LCOV_EXCL_START */
1929 ERR("ctsvc_stmt_step() Fail(%d)", ret);
1930 ctsvc_stmt_finalize(stmt);
1934 /* LCOV_EXCL_STOP */
1936 id = ctsvc_stmt_get_int(stmt, 0);
1937 score = ctsvc_stmt_get_int(stmt, 1);
1938 DBG("person_id : %d, score : %d", id, score);
1940 /* Add 2 points whenever a email id or a number is matched */
1941 /* and 1 point whenever some part of name is matched */
1942 /* Aggregation suggestions: the persons who get more than 2 points */
1943 if (CTSVC_AGGREGATION_SUGGESTION_SCORE <= score && (0 == limit || cnt < limit)) {
1946 sub_len += snprintf(sub_query + sub_len, sub_size -sub_len, ", %d", id);
1948 sub_len += snprintf(sub_query + sub_len, sub_size -sub_len, "%d", id);
1951 ctsvc_stmt_finalize(stmt);
1956 DBG("no person_id for aggregation suggestions");
1957 return CONTACTS_ERROR_NO_DATA;
1960 snprintf(query, query_size,
1961 "SELECT DISTINCT persons.person_id, "
1963 "_NORMALIZE_INDEX_(%s), "
1965 "persons.image_thumbnail_path, "
1966 "persons.ringtone_path, "
1967 "persons.vibration, "
1968 "persons.message_alert, "
1972 "persons.has_phonenumber, "
1973 "persons.has_email, "
1974 "EXISTS(SELECT person_id FROM "CTS_TABLE_FAVORITES" WHERE person_id=persons.person_id) is_favorite "
1975 "FROM "CTS_TABLE_PERSONS" "
1976 "LEFT JOIN "CTS_TABLE_CONTACTS" "
1977 "ON (name_contact_id = contacts.contact_id AND contacts.deleted = 0) "
1978 "WHERE persons.person_id IN (%s)",
1979 ctsvc_get_display_column(), ctsvc_get_sort_name_column(), sub_query);
1983 ret = ctsvc_query_prepare(query, &stmt);
1986 /* LCOV_EXCL_START */
1987 ERR("ctsvc_query_prepare fail(%d)", ret);
1989 /* LCOV_EXCL_STOP */
1992 contacts_list_create(&list);
1993 while ((ret = ctsvc_stmt_step(stmt))) {
1994 contacts_record_h record;
1996 /* LCOV_EXCL_START */
1997 ERR("ctsvc_stmt_step() Fail(%d)", ret);
1998 ctsvc_stmt_finalize(stmt);
1999 contacts_list_destroy(list, true);
2001 /* LCOV_EXCL_STOP */
2003 ret = ctsvc_db_person_create_record_from_stmt(stmt, &record);
2004 if (CONTACTS_ERROR_NONE != ret) {
2005 /* LCOV_EXCL_START */
2006 ERR("ctsvc_db_person_create_record_from_stmt() Fail(%d)", ret);
2007 ctsvc_stmt_finalize(stmt);
2008 contacts_list_destroy(list, true);
2010 /* LCOV_EXCL_STOP */
2013 ctsvc_list_prepend(list, record);
2015 ctsvc_stmt_finalize(stmt);
2016 ctsvc_list_reverse(list);