[SVACE Issue Fixes]
[platform/core/pim/contacts-service.git] / server / db / ctsvc_db_plugin_contact.c
1 /*
2  * Contacts Service
3  *
4  * Copyright (c) 2010 - 2015 Samsung Electronics Co., Ltd. All rights reserved.
5  *
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
9  *
10  * http://www.apache.org/licenses/LICENSE-2.0
11  *
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.
17  *
18  */
19 #include <fcntl.h>
20 #include <unistd.h>
21
22 #include "contacts.h"
23 #include "ctsvc_internal.h"
24 #include "ctsvc_db_sqlite.h"
25 #include "ctsvc_db_schema.h"
26 #include "ctsvc_db_init.h"
27 #include "ctsvc_db_query.h"
28 #include "ctsvc_db_utils.h"
29 #include "ctsvc_record.h"
30 #include "ctsvc_normalize.h"
31 #include "ctsvc_number_utils.h"
32 #include "ctsvc_list.h"
33 #include "ctsvc_server_setting.h"
34 #include "ctsvc_localize_ch.h"
35 #include "ctsvc_server_group.h"
36 #include "ctsvc_notification.h"
37 #include "ctsvc_localize.h"
38 #include "ctsvc_localize_utils.h"
39 #include "ctsvc_server_person.h"
40 #include "ctsvc_notify.h"
41
42 #ifdef ENABLE_LOG_FEATURE
43 #include "ctsvc_server_phonelog.h"
44 #endif /* ENABLE_LOG_FEATURE */
45 #include "ctsvc_db_access_control.h"
46
47 #include "ctsvc_db_plugin_contact_helper.h"
48 #include "ctsvc_db_plugin_person_helper.h"
49
50
51 static int __ctsvc_db_get_contact_base_info(int id, ctsvc_contact_s *contact)
52 {
53         int ret;
54         int i;
55         cts_stmt stmt = NULL;
56         char query[CTS_SQL_MAX_LEN] = {0};
57         char *temp;
58         char full_path[CTSVC_IMG_FULL_PATH_SIZE_MAX] = {0};
59
60         snprintf(query, sizeof(query),
61                         "SELECT contact_id, addressbook_id, person_id, changed_time, changed_ver, link_mode, %s, "
62                         "display_name_source, image_thumbnail_path, "
63                         "ringtone_path, vibration, message_alert, "
64                         "uid, is_favorite, has_phonenumber, has_email, "
65                         "sort_name, reverse_sort_name "
66                         "FROM "CTS_TABLE_CONTACTS" WHERE contact_id = %d AND deleted = 0",
67                         ctsvc_get_display_column(), id);
68
69         ret = ctsvc_query_prepare(query, &stmt);
70         RETVM_IF(NULL == stmt, ret, "ctsvc_query_prepare() Fail(%d)", ret);
71
72         ret = ctsvc_stmt_step(stmt);
73         if (1 /*CTS_TRUE*/ != ret) {
74                 /* LCOV_EXCL_START */
75                 ERR("ctsvc_stmt_step() Fail(%d)", ret);
76                 ctsvc_stmt_finalize(stmt);
77                 if (CONTACTS_ERROR_NONE == ret)
78                         return CONTACTS_ERROR_NO_DATA;
79                 else
80                         return ret;
81                 /* LCOV_EXCL_STOP */
82         }
83
84         i = 0;
85         contact->id = ctsvc_stmt_get_int(stmt, i++);
86         contact->addressbook_id = ctsvc_stmt_get_int(stmt, i++);
87         contact->person_id = ctsvc_stmt_get_int(stmt, i++);
88         contact->changed_time = ctsvc_stmt_get_int(stmt, i++);
89         contact->changed_ver = ctsvc_stmt_get_int(stmt, i++);
90         contact->link_mode = ctsvc_stmt_get_int(stmt, i++);
91         temp = ctsvc_stmt_get_text(stmt, i++);
92         contact->display_name = SAFE_STRDUP(temp);
93         contact->display_source_type = ctsvc_stmt_get_int(stmt, i++);
94
95         temp = ctsvc_stmt_get_text(stmt, i++);
96         if (temp) {
97                 snprintf(full_path, sizeof(full_path), "%s/%s", CTSVC_CONTACT_IMG_FULL_LOCATION, temp);
98                 contact->image_thumbnail_path = strdup(full_path);
99         }
100
101         temp = ctsvc_stmt_get_text(stmt, i++);
102         contact->ringtone_path = SAFE_STRDUP(temp);
103         temp = ctsvc_stmt_get_text(stmt, i++);
104         contact->vibration = SAFE_STRDUP(temp);
105         temp = ctsvc_stmt_get_text(stmt, i++);
106         contact->message_alert = SAFE_STRDUP(temp);
107         temp = ctsvc_stmt_get_text(stmt, i++);
108         contact->uid = SAFE_STRDUP(temp);
109         contact->is_favorite = ctsvc_stmt_get_int(stmt, i++);
110         contact->has_phonenumber = ctsvc_stmt_get_int(stmt, i++);
111         contact->has_email = ctsvc_stmt_get_int(stmt, i++);
112         temp = ctsvc_stmt_get_text(stmt, i++);
113         contact->sort_name = SAFE_STRDUP(temp);
114         temp = ctsvc_stmt_get_text(stmt, i++);
115         contact->reverse_sort_name = SAFE_STRDUP(temp);
116         ctsvc_stmt_finalize(stmt);
117
118         return CONTACTS_ERROR_NONE;
119 }
120
121 static int __ctsvc_db_get_data(int id, ctsvc_contact_s *contact)
122 {
123         int ret;
124         int datatype;
125         cts_stmt stmt = NULL;
126         char query[CTS_SQL_MAX_LEN] = {0};
127
128         snprintf(query, sizeof(query),
129                         "SELECT datatype, id, data.contact_id, is_default, data1, data2, "
130                         "data3, data4, data5, data6, data7, data8, data9, data10, data11, data12 "
131                         "FROM "CTS_TABLE_DATA", "CTSVC_DB_VIEW_CONTACT" "
132                         "ON "CTS_TABLE_DATA".contact_id = "CTSVC_DB_VIEW_CONTACT".contact_id "
133                         "WHERE data.contact_id = %d  AND is_my_profile = 0 "
134                         "ORDER BY is_default DESC", id);
135
136         ret = ctsvc_query_prepare(query, &stmt);
137         RETVM_IF(NULL == stmt, ret, "ctsvc_query_prepare() Fail(%d)", ret);
138
139         ret = ctsvc_stmt_step(stmt);
140         if (1 /*CTS_TRUE */!= ret) {
141                 /* LCOV_EXCL_START */
142                 ERR("ctsvc_stmt_step() Fail(%d)", ret);
143                 ctsvc_stmt_finalize(stmt);
144                 return ret;
145                 /* LCOV_EXCL_STOP */
146         }
147
148         do {
149                 datatype = ctsvc_stmt_get_int(stmt, 0);
150                 switch (datatype) {
151                 case CONTACTS_DATA_TYPE_NAME:
152                         ctsvc_get_data_info_name(stmt, (contacts_list_h)contact->name);
153                         break;
154                 case CONTACTS_DATA_TYPE_EVENT:
155                         ctsvc_get_data_info_event(stmt, (contacts_list_h)contact->events);
156                         break;
157                 case CONTACTS_DATA_TYPE_MESSENGER:
158                         ctsvc_get_data_info_messenger(stmt, (contacts_list_h)contact->messengers);
159                         break;
160                 case CONTACTS_DATA_TYPE_POSTAL:
161                         ctsvc_get_data_info_address(stmt, (contacts_list_h)contact->postal_addrs);
162                         break;
163                 case CONTACTS_DATA_TYPE_URL:
164                         ctsvc_get_data_info_url(stmt, (contacts_list_h)contact->urls);
165                         break;
166                 case CONTACTS_DATA_TYPE_NICKNAME:
167                         ctsvc_get_data_info_nickname(stmt, (contacts_list_h)contact->nicknames);
168                         break;
169                 case CONTACTS_DATA_TYPE_NUMBER:
170                         ctsvc_get_data_info_number(stmt, (contacts_list_h)contact->numbers);
171                         break;
172                 case CONTACTS_DATA_TYPE_EMAIL:
173                         ctsvc_get_data_info_email(stmt, (contacts_list_h)contact->emails);
174                         break;
175                 case CONTACTS_DATA_TYPE_PROFILE:
176                         ctsvc_get_data_info_profile(stmt, (contacts_list_h)contact->profiles);
177                         break;
178                 case CONTACTS_DATA_TYPE_RELATIONSHIP:
179                         ctsvc_get_data_info_relationship(stmt, (contacts_list_h)contact->relationships);
180                         break;
181                 case CONTACTS_DATA_TYPE_IMAGE:
182                         ctsvc_get_data_info_image(stmt, (contacts_list_h)contact->images);
183                         break;
184                 case CONTACTS_DATA_TYPE_COMPANY:
185                         ctsvc_get_data_info_company(stmt, (contacts_list_h)contact->company);
186                         break;
187                 case CONTACTS_DATA_TYPE_NOTE:
188                         ctsvc_get_data_info_note(stmt, (contacts_list_h)contact->note);
189                         break;
190                 case CONTACTS_DATA_TYPE_EXTENSION:
191                         ctsvc_get_data_info_extension(stmt, (contacts_list_h)contact->extensions);
192                         break;
193                 case CONTACTS_DATA_TYPE_SIP:
194                         ctsvc_get_data_info_sip(stmt, (contacts_list_h)contact->sips);
195                         break;
196                 default:
197                         /* LCOV_EXCL_START */
198                         ERR("Intenal : Not supported data type (%d)", datatype);
199                         break;
200                         /* LCOV_EXCL_STOP */
201                 }
202
203         } while (1 == ctsvc_stmt_step(stmt));
204
205         ctsvc_stmt_finalize(stmt);
206
207         return CONTACTS_ERROR_NONE;
208
209 }
210
211 static inline int __ctsvc_get_contact_grouprel(int contact_id, ctsvc_contact_s *contact)
212 {
213         CTS_FN_CALL;
214         int ret;
215         ctsvc_group_relation_s *grouprel;
216         cts_stmt stmt = NULL;
217         char query[CTS_SQL_MAX_LEN] = {0};
218         char *temp;
219
220         snprintf(query, sizeof(query),
221                         "SELECT group_id, contact_id, group_name "
222                         " FROM "CTSVC_DB_VIEW_GROUP_RELATION" WHERE contact_id = %d", contact_id);
223
224         ret = ctsvc_query_prepare(query, &stmt);
225         RETVM_IF(NULL == stmt, ret, "ctsvc_query_prepare() Fail(%d)", ret);
226
227         while (1 /*CTS_TRUE */ == ctsvc_stmt_step(stmt)) {
228                 contacts_record_create(_contacts_group_relation._uri, (contacts_record_h*)&grouprel);
229
230                 if (grouprel) {
231                         grouprel->group_id = ctsvc_stmt_get_int(stmt, 0);
232                         grouprel->id = grouprel->group_id;
233                         grouprel->contact_id = ctsvc_stmt_get_int(stmt, 1);
234                         temp = ctsvc_stmt_get_text(stmt, 2);
235                         grouprel->group_name = SAFE_STRDUP(temp);
236
237                         ctsvc_list_prepend((contacts_list_h)contact->grouprelations, (contacts_record_h)grouprel);
238                 }
239         }
240
241         ctsvc_stmt_finalize(stmt);
242         ctsvc_list_reverse((contacts_list_h)contact->grouprelations);
243         return CONTACTS_ERROR_NONE;
244 }
245
246 static int __ctsvc_db_contact_get_record(int id, contacts_record_h *out_record)
247 {
248         int ret;
249         contacts_record_h record;
250         ctsvc_contact_s *contact;
251
252         RETV_IF(NULL == out_record, CONTACTS_ERROR_INVALID_PARAMETER);
253         *out_record = NULL;
254
255         contacts_record_create(_contacts_contact._uri, &record);
256         contact = (ctsvc_contact_s*)record;
257         ret = __ctsvc_db_get_contact_base_info(id, contact);
258         if (CONTACTS_ERROR_NONE != ret) {
259                 /* LCOV_EXCL_START */
260                 ERR("__ctsvc_db_get_contact_base_info(ALL) Fail(%d)", ret);
261                 contacts_record_destroy(record, true);
262                 return ret;
263                 /* LCOV_EXCL_STOP */
264         }
265
266         ret = __ctsvc_db_get_data(id, contact);
267         if (CONTACTS_ERROR_NONE != ret && CONTACTS_ERROR_NO_DATA != ret) {
268                 /* LCOV_EXCL_START */
269                 ERR("ctsvc_get_data_info Fail(%d)", ret);
270                 contacts_record_destroy(record, true);
271                 return ret;
272                 /* LCOV_EXCL_STOP */
273         }
274
275         ret = __ctsvc_get_contact_grouprel(id, contact);
276         if (CONTACTS_ERROR_NONE != ret) {
277                 /* LCOV_EXCL_START */
278                 ERR("ctsvc_get_group_relations Fail(%d)", ret);
279                 contacts_record_destroy(record, true);
280                 return ret;
281                 /* LCOV_EXCL_STOP */
282         }
283
284         *out_record = record;
285
286         return CONTACTS_ERROR_NONE;
287 }
288
289 static int __ctsvc_db_contact_delete_record(int id)
290 {
291         return ctsvc_db_contact_delete(id);
292 }
293
294 static inline int __ctsvc_contact_update_data(ctsvc_contact_s *contact)
295 {
296         int ret;
297
298         if (contact->name) {
299                 ret = ctsvc_contact_update_data_name((contacts_list_h)contact->name, contact->id, false);
300                 if (CONTACTS_ERROR_NONE != ret) {
301                         /* LCOV_EXCL_START */
302                         ERR("ctsvc_contact_update_data_name() Fail(%d)", ret);
303                         return ret;
304                         /* LCOV_EXCL_STOP */
305                 }
306         }
307
308         if (contact->company) {
309                 ret = ctsvc_contact_update_data_company((contacts_list_h)contact->company, contact->id, false);
310                 if (CONTACTS_ERROR_NONE != ret) {
311                         /* LCOV_EXCL_START */
312                         ERR("ctsvc_contact_update_data_company() Fail(%d)", ret);
313                         return ret;
314                         /* LCOV_EXCL_STOP */
315                 }
316         }
317
318         if (contact->note) {
319                 ret = ctsvc_contact_update_data_note((contacts_list_h)contact->note, contact->id, false);
320                 if (CONTACTS_ERROR_NONE != ret) {
321                         /* LCOV_EXCL_START */
322                         ERR("ctsvc_contact_update_data_note() Fail(%d)", ret);
323                         return ret;
324                         /* LCOV_EXCL_STOP */
325                 }
326         }
327
328         if (contact->events) {
329                 ret = ctsvc_contact_update_data_event((contacts_list_h)contact->events, contact->id, false);
330                 if (CONTACTS_ERROR_NONE != ret) {
331                         /* LCOV_EXCL_START */
332                         ERR("ctsvc_contact_update_data_events() Fail(%d)", ret);
333                         return ret;
334                         /* LCOV_EXCL_STOP */
335                 }
336         }
337
338         if (contact->messengers) {
339                 ret = ctsvc_contact_update_data_messenger((contacts_list_h)contact->messengers, contact->id, false);
340                 if (CONTACTS_ERROR_NONE != ret) {
341                         /* LCOV_EXCL_START */
342                         ERR("ctsvc_contact_update_data_messengers() Fail(%d)", ret);
343                         return ret;
344                         /* LCOV_EXCL_STOP */
345                 }
346         }
347
348         if (contact->postal_addrs) {
349                 ret = ctsvc_contact_update_data_address((contacts_list_h)contact->postal_addrs, contact->id, false);
350                 if (CONTACTS_ERROR_NONE != ret) {
351                         /* LCOV_EXCL_START */
352                         ERR("ctsvc_contact_update_data_address() Fail(%d)", ret);
353                         return ret;
354                         /* LCOV_EXCL_STOP */
355                 }
356         }
357
358         if (contact->urls) {
359                 ret = ctsvc_contact_update_data_url((contacts_list_h)contact->urls, contact->id, false);
360                 if (CONTACTS_ERROR_NONE != ret) {
361                         /* LCOV_EXCL_START */
362                         ERR("ctsvc_contact_update_data_url() Fail(%d)", ret);
363                         return ret;
364                         /* LCOV_EXCL_STOP */
365                 }
366         }
367
368         if (contact->nicknames) {
369                 ret = ctsvc_contact_update_data_nickname((contacts_list_h)contact->nicknames, contact->id, false);
370                 if (CONTACTS_ERROR_NONE != ret) {
371                         /* LCOV_EXCL_START */
372                         ERR("ctsvc_contact_update_data_nickname() Fail(%d)", ret);
373                         return ret;
374                         /* LCOV_EXCL_STOP */
375                 }
376         }
377
378         if (contact->numbers) {
379                 bool had_phonenumber;
380                 ret = ctsvc_contact_update_data_number((contacts_list_h)contact->numbers, contact->id, false, &had_phonenumber);
381                 if (CONTACTS_ERROR_NONE != ret) {
382                         /* LCOV_EXCL_START */
383                         ERR("ctsvc_contact_update_data_number() Fail(%d)", ret);
384                         return ret;
385                         /* LCOV_EXCL_STOP */
386                 }
387                 contact->has_phonenumber = had_phonenumber;
388         }
389
390         if (contact->emails) {
391                 bool had_email;
392                 ret = ctsvc_contact_update_data_email((contacts_list_h)contact->emails, contact->id, false, &had_email);
393                 if (CONTACTS_ERROR_NONE != ret) {
394                         /* LCOV_EXCL_START */
395                         ERR("ctsvc_contact_update_data_email() Fail(%d)", ret);
396                         return ret;
397                         /* LCOV_EXCL_STOP */
398                 }
399                 contact->has_email = had_email;
400         }
401
402         if (contact->profiles) {
403                 ret = ctsvc_contact_update_data_profile((contacts_list_h)contact->profiles, contact->id, false);
404                 if (CONTACTS_ERROR_NONE != ret) {
405                         /* LCOV_EXCL_START */
406                         ERR("ctsvc_contact_update_data_profile() Fail(%d)", ret);
407                         return ret;
408                         /* LCOV_EXCL_STOP */
409                 }
410         }
411
412         if (contact->relationships) {
413                 ret = ctsvc_contact_update_data_relationship((contacts_list_h)contact->relationships, contact->id, false);
414                 if (CONTACTS_ERROR_NONE != ret) {
415                         /* LCOV_EXCL_START */
416                         ERR("ctsvc_contact_update_data_relationship() Fail(%d)", ret);
417                         return ret;
418                         /* LCOV_EXCL_STOP */
419                 }
420         }
421
422         if (contact->images) {
423                 ret = ctsvc_contact_update_data_image((contacts_list_h)contact->images, contact->id, false);
424                 if (CONTACTS_ERROR_NONE != ret) {
425                         /* LCOV_EXCL_START */
426                         ERR("ctsvc_contact_update_data_image() Fail(%d)", ret);
427                         return ret;
428                         /* LCOV_EXCL_STOP */
429                 }
430         }
431
432         if (contact->extensions) {
433                 ret = ctsvc_contact_update_data_extension((contacts_list_h)contact->extensions, contact->id, false);
434                 if (CONTACTS_ERROR_NONE != ret) {
435                         /* LCOV_EXCL_START */
436                         ERR("ctsvc_contact_update_data_extension() Fail(%d)", ret);
437                         return ret;
438                         /* LCOV_EXCL_STOP */
439                 }
440         }
441
442         if (contact->sips) {
443                 ret = ctsvc_contact_update_data_sip((contacts_list_h)contact->sips, contact->id, false);
444                 if (CONTACTS_ERROR_NONE != ret) {
445                         /* LCOV_EXCL_START */
446                         ERR("ctsvc_contact_update_data_sips() Fail(%d)", ret);
447                         return ret;
448                         /* LCOV_EXCL_STOP */
449                 }
450         }
451         return CONTACTS_ERROR_NONE;
452 }
453
454 static void __ctsvc_contact_check_default_data(ctsvc_contact_s *contact)
455 {
456         if (contact->numbers)
457                 contact->has_phonenumber = ctsvc_contact_check_default_number((contacts_list_h)contact->numbers);
458         if (contact->emails)
459                 contact->has_email = ctsvc_contact_check_default_email((contacts_list_h)contact->emails);
460         if (contact->images)
461                 ctsvc_contact_check_default_image((contacts_list_h)contact->images);
462         if (contact->postal_addrs)
463                 ctsvc_contact_check_default_address((contacts_list_h)contact->postal_addrs);
464 }
465
466 static inline int __ctsvc_contact_update_grouprel(int contact_id, contacts_list_h group_list)
467 {
468         CTS_FN_CALL;
469         ctsvc_group_relation_s *grouprel;
470         ctsvc_list_s *list = (ctsvc_list_s*)group_list;
471         int rel_changed = 0;
472         int count;
473         int ret;
474         GList *cursor;
475
476         RETV_IF(NULL == group_list, CONTACTS_ERROR_INVALID_PARAMETER);
477
478         for (cursor = list->deleted_records; cursor; cursor = cursor->next) {
479                 grouprel = cursor->data;
480                 ret = ctsvc_group_remove_contact_in_transaction(grouprel->group_id, contact_id);
481                 if (0 < ret)
482                         rel_changed += ret;
483         }
484
485         ret = contacts_list_get_count(group_list, &count);
486         if (0 == count)
487                 return CONTACTS_ERROR_NONE;
488
489         contacts_list_first(group_list);
490         do {
491                 contacts_list_get_current_record_p(group_list, (contacts_record_h*)&grouprel);
492                 if (NULL == grouprel)
493                         continue;
494
495                 RETVM_IF(grouprel->group_id <= 0, CONTACTS_ERROR_INVALID_PARAMETER, "group_id(%d) invalid", grouprel->group_id);
496                 if (grouprel->group_id) {
497                         ret = ctsvc_group_add_contact_in_transaction(grouprel->group_id, contact_id);
498                         RETVM_IF(ret < CONTACTS_ERROR_NONE, ret, "ctsvc_db_group_set_relation() Fail(%d)", ret);
499                         if (0 < ret)
500                                 rel_changed += ret;
501                 }
502         } while (CONTACTS_ERROR_NONE == contacts_list_next(group_list));
503
504         if (rel_changed)
505                 return rel_changed;
506         else
507                 return CONTACTS_ERROR_NONE;
508 }
509
510 static bool __ctsvc_contact_check_token(char *src, char *dest, int len)
511 {
512         bool had = false;
513         int i = 0;
514
515         for (i = 0; i < len; i++) {
516                 if (src[i] == '@' || src[i] == '.') {
517                         dest[i] = ' ';
518                         had = true;
519                 } else {
520                         dest[i] = src[i];
521                 }
522         }
523         dest[i] = '\0';
524
525         return had;
526 }
527
528 /* Make search data by number, email, nicknames, address, note, messenger, relationship, company */
529 static inline int __ctsvc_contact_make_search_data(ctsvc_contact_s *contact,
530                 char **search_number, char **search_data)
531 {
532         int len = 0;
533
534         char *number = NULL;
535         char *data = NULL;
536         char *temp_number = NULL;
537         char *temp_data = NULL;
538         int buf_size = 0;
539
540         RETV_IF(NULL == contact, CONTACTS_ERROR_NO_DATA);
541
542         if (contact->numbers) {
543                 contacts_list_h number_list = (contacts_list_h)contact->numbers;
544                 ctsvc_number_s *number_record;
545                 contacts_list_first(number_list);
546                 do {
547                         contacts_list_get_current_record_p(number_list, (contacts_record_h*)&number_record);
548                         if (number_record && number_record->cleaned) {
549                                 buf_size = SAFE_STRLEN(number) + SAFE_STRLEN(number_record->cleaned) + SAFE_STRLEN(number_record->normalized) + 3;
550                                 temp_number = calloc(1, buf_size);
551                                 if (NULL == temp_number) {
552                                         /* LCOV_EXCL_START */
553                                         ERR("calloc() Fail");
554                                         free(number);
555                                         return CONTACTS_ERROR_OUT_OF_MEMORY;
556                                         /* LCOV_EXCL_STOP */
557                                 }
558
559                                 if (number)
560                                         snprintf(temp_number, buf_size, "%s %s %s", SAFE_STR(number), number_record->cleaned, number_record->normalized);
561                                 else
562                                         snprintf(temp_number, buf_size, "%s %s", number_record->cleaned, number_record->normalized);
563                                 free(number);
564                                 number = temp_number;
565                         }
566                 } while (CONTACTS_ERROR_NONE == contacts_list_next(number_list));
567         }
568
569         if (contact->emails) {
570                 contacts_list_h email_list = (contacts_list_h)contact->emails;
571                 ctsvc_email_s *email;
572                 contacts_list_first(email_list);
573                 do {
574                         contacts_list_get_current_record_p(email_list, (contacts_record_h*)&email);
575                         if (email && email->email_addr) {
576                                 int len = strlen(email->email_addr);
577                                 char temp[len+1];
578                                 bool had = __ctsvc_contact_check_token(email->email_addr, temp, len);
579
580                                 buf_size = SAFE_STRLEN(data) + SAFE_STRLEN(email->email_addr)
581                                         * (had ? 2 : 1) + 4;
582                                 temp_data = calloc(1, buf_size);
583                                 if (NULL == temp_data) {
584                                         /* LCOV_EXCL_START */
585                                         ERR("calloc() Fail");
586                                         free(data);
587                                         free(number);
588                                         return CONTACTS_ERROR_OUT_OF_MEMORY;
589                                         /* LCOV_EXCL_STOP */
590                                 }
591
592                                 if (data) {
593                                         snprintf(temp_data, buf_size, "%s %s %s", data, email->email_addr,
594                                                         (had ? temp : ""));
595                                 } else {
596                                         snprintf(temp_data, buf_size, "%s %s", email->email_addr,
597                                                         (had ? temp : ""));
598                                 }
599                                 free(data);
600                                 data = temp_data;
601                         }
602                 } while (CONTACTS_ERROR_NONE == contacts_list_next(email_list));
603         }
604
605         if (contact->nicknames) {
606                 contacts_list_h nickname_list = (contacts_list_h)contact->nicknames;
607                 ctsvc_nickname_s *nickname;
608                 contacts_list_first(nickname_list);
609                 do {
610                         contacts_list_get_current_record_p(nickname_list, (contacts_record_h*)&nickname);
611                         if (nickname && nickname->nickname) {
612                                 int len = strlen(nickname->nickname);
613                                 char temp[len+1];
614                                 bool had = __ctsvc_contact_check_token(nickname->nickname, temp, len);
615
616                                 buf_size = SAFE_STRLEN(data) + SAFE_STRLEN(nickname->nickname) * (had ? 2 : 1) + 4;
617                                 temp_data = calloc(1, buf_size);
618                                 if (NULL == temp_data) {
619                                         /* LCOV_EXCL_START */
620                                         ERR("calloc() Fail");
621                                         free(data);
622                                         free(number);
623                                         return CONTACTS_ERROR_OUT_OF_MEMORY;
624                                         /* LCOV_EXCL_STOP */
625                                 }
626
627                                 if (data)
628                                         snprintf(temp_data, buf_size, "%s %s %s", data, nickname->nickname, (had ? temp : ""));
629                                 else
630                                         snprintf(temp_data, buf_size, "%s %s", nickname->nickname, (had ? temp : ""));
631                                 free(data);
632                                 data = temp_data;
633                         }
634                 } while (CONTACTS_ERROR_NONE == contacts_list_next(nickname_list));
635         }
636
637         if (contact->postal_addrs) {
638                 contacts_list_h address_list = (contacts_list_h)contact->postal_addrs;
639                 ctsvc_address_s *address;
640                 contacts_list_first(address_list);
641                 do {
642                         contacts_list_get_current_record_p(address_list, (contacts_record_h*)&address);
643                         if (address) {
644                                 bool had;
645                                 int str_len = SAFE_STRLEN(address->country)
646                                         + SAFE_STRLEN(address->pobox)
647                                         + SAFE_STRLEN(address->postalcode)
648                                         + SAFE_STRLEN(address->region)
649                                         + SAFE_STRLEN(address->locality)
650                                         + SAFE_STRLEN(address->street)
651                                         + SAFE_STRLEN(address->extended);
652                                 len = 0;
653                                 buf_size = SAFE_STRLEN(data)
654                                         + str_len * 2 + 16;
655                                 temp_data = calloc(1, buf_size);
656                                 if (NULL == temp_data) {
657                                         /* LCOV_EXCL_START */
658                                         ERR("calloc() Fail");
659                                         free(data);
660                                         free(number);
661                                         return CONTACTS_ERROR_OUT_OF_MEMORY;
662                                         /* LCOV_EXCL_STOP */
663                                 }
664
665                                 char temp[str_len+1];
666
667                                 if (data)
668                                         len += snprintf(temp_data + len, buf_size - len, "%s ", data);
669
670                                 if (address->country) {
671                                         had = __ctsvc_contact_check_token(address->country, temp, SAFE_STRLEN(address->country));
672                                         len += snprintf(temp_data + len, buf_size - len, "%s %s ", address->country, had ? temp : "");
673                                 }
674                                 if (address->pobox) {
675                                         had = __ctsvc_contact_check_token(address->pobox, temp, SAFE_STRLEN(address->pobox));
676                                         len += snprintf(temp_data + len, buf_size - len, "%s %s ", address->pobox, had ? temp : "");
677                                 }
678                                 if (address->postalcode) {
679                                         had = __ctsvc_contact_check_token(address->postalcode, temp, SAFE_STRLEN(address->postalcode));
680                                         len += snprintf(temp_data + len, buf_size - len, "%s %s ", address->postalcode, had ? temp : "");
681                                 }
682                                 if (address->region) {
683                                         had = __ctsvc_contact_check_token(address->region, temp, SAFE_STRLEN(address->region));
684                                         len += snprintf(temp_data + len, buf_size - len, "%s %s ", address->region, had ? temp : "");
685                                 }
686                                 if (address->locality) {
687                                         had = __ctsvc_contact_check_token(address->locality, temp, SAFE_STRLEN(address->locality));
688                                         len += snprintf(temp_data + len, buf_size - len, "%s %s ", address->locality, had ? temp : "");
689                                 }
690                                 if (address->street) {
691                                         had = __ctsvc_contact_check_token(address->street, temp, SAFE_STRLEN(address->street));
692                                         len += snprintf(temp_data + len, buf_size - len, "%s %s ", address->street, had ? temp : "");
693                                 }
694                                 if (address->extended) {
695                                         had = __ctsvc_contact_check_token(address->extended, temp, SAFE_STRLEN(address->extended));
696                                         len += snprintf(temp_data + len, buf_size - len, "%s %s ", address->extended, had ? temp : "");
697                                 }
698                                 free(data);
699                                 data = temp_data;
700                         }
701                 } while (CONTACTS_ERROR_NONE == contacts_list_next(address_list));
702         }
703
704         if (contact->note) {
705                 contacts_list_h note_list = (contacts_list_h)contact->note;
706                 ctsvc_note_s *note;
707                 contacts_list_first(note_list);
708                 do {
709                         contacts_list_get_current_record_p(note_list, (contacts_record_h*)&note);
710                         if (note && note->note) {
711                                 int len = strlen(note->note);
712                                 char temp[len+1];
713                                 bool had = __ctsvc_contact_check_token(note->note, temp, len);
714
715                                 buf_size = SAFE_STRLEN(data) + SAFE_STRLEN(note->note) * (had ? 2 : 1) + 4;
716                                 temp_data = calloc(1, buf_size);
717                                 if (NULL == temp_data) {
718                                         /* LCOV_EXCL_START */
719                                         ERR("calloc() Fail");
720                                         free(data);
721                                         free(number);
722                                         return CONTACTS_ERROR_OUT_OF_MEMORY;
723                                         /* LCOV_EXCL_STOP */
724                                 }
725
726                                 if (data) {
727                                         snprintf(temp_data, buf_size, "%s %s %s", data, note->note,
728                                                         (had ? temp : ""));
729                                 } else {
730                                         snprintf(temp_data, buf_size, "%s %s", note->note,
731                                                         (had ? temp : ""));
732                                 }
733                                 free(data);
734                                 data = temp_data;
735                         }
736                 } while (CONTACTS_ERROR_NONE == contacts_list_next(note_list));
737         }
738
739         if (contact->messengers) {
740                 contacts_list_h messenger_list = (contacts_list_h)contact->messengers;
741                 ctsvc_messenger_s *messenger;
742                 contacts_list_first(messenger_list);
743                 do {
744                         contacts_list_get_current_record_p(messenger_list, (contacts_record_h*)&messenger);
745                         if (messenger && messenger->im_id) {
746                                 int len = strlen(messenger->im_id);
747                                 char temp[len+1];
748                                 bool had = __ctsvc_contact_check_token(messenger->im_id, temp, len);
749
750                                 buf_size = SAFE_STRLEN(data) + SAFE_STRLEN(messenger->im_id) * (had ? 2 : 1) + 4;
751                                 temp_data = calloc(1, buf_size);
752                                 if (NULL == temp_data) {
753                                         /* LCOV_EXCL_START */
754                                         ERR("calloc() Fail");
755                                         free(data);
756                                         free(number);
757                                         return CONTACTS_ERROR_OUT_OF_MEMORY;
758                                         /* LCOV_EXCL_STOP */
759                                 }
760
761                                 if (data) {
762                                         snprintf(temp_data, buf_size, "%s %s %s", data, messenger->im_id,
763                                                         (had ? temp : ""));
764                                 } else {
765                                         snprintf(temp_data, buf_size, "%s %s", messenger->im_id,
766                                                         (had ? temp : ""));
767                                 }
768                                 free(data);
769                                 data = temp_data;
770                         }
771                 } while (CONTACTS_ERROR_NONE == contacts_list_next(messenger_list));
772         }
773
774         if (contact->relationships) {
775                 contacts_list_h relationship_list = (contacts_list_h)contact->relationships;
776                 ctsvc_relationship_s *relationship;
777                 contacts_list_first(relationship_list);
778                 do {
779                         contacts_list_get_current_record_p(relationship_list, (contacts_record_h*)&relationship);
780                         if (relationship && relationship->name) {
781                                 int len = strlen(relationship->name);
782                                 char temp[len+1];
783                                 bool had = __ctsvc_contact_check_token(relationship->name, temp, len);
784
785                                 buf_size = SAFE_STRLEN(data) + SAFE_STRLEN(relationship->name) * (had ? 2 : 1) + 4;
786                                 temp_data = calloc(1, buf_size);
787                                 if (NULL == temp_data) {
788                                         /* LCOV_EXCL_START */
789                                         ERR("calloc() Fail");
790                                         free(data);
791                                         free(number);
792                                         return CONTACTS_ERROR_OUT_OF_MEMORY;
793                                         /* LCOV_EXCL_STOP */
794                                 }
795
796                                 if (data) {
797                                         snprintf(temp_data, buf_size, "%s %s %s", data, relationship->name,
798                                                         (had ? temp : ""));
799                                 } else {
800                                         snprintf(temp_data, buf_size, "%s %s", relationship->name,
801                                                         (had ? temp : ""));
802                                 }
803                                 free(data);
804                                 data = temp_data;
805                         }
806                 } while (CONTACTS_ERROR_NONE == contacts_list_next(relationship_list));
807         }
808
809         if (contact->company) {
810                 contacts_list_h company_list = (contacts_list_h)contact->company;
811                 ctsvc_company_s *company;
812                 contacts_list_first(company_list);
813                 do {
814                         contacts_list_get_current_record_p(company_list, (contacts_record_h*)&company);
815                         if (company) {
816                                 bool had;
817                                 int str_len = SAFE_STRLEN(company->name)
818                                         + SAFE_STRLEN(company->department)
819                                         + SAFE_STRLEN(company->job_title)
820                                         + SAFE_STRLEN(company->role)
821                                         + SAFE_STRLEN(company->assistant_name)
822                                         + SAFE_STRLEN(company->location)
823                                         + SAFE_STRLEN(company->description)
824                                         + SAFE_STRLEN(company->phonetic_name);
825                                 len = 0;
826                                 buf_size = SAFE_STRLEN(data) + str_len * 2 + 18;
827                                 temp_data = calloc(1, buf_size);
828                                 if (NULL == temp_data) {
829                                         /* LCOV_EXCL_START */
830                                         ERR("calloc() Fail");
831                                         free(data);
832                                         free(number);
833                                         return CONTACTS_ERROR_OUT_OF_MEMORY;
834                                         /* LCOV_EXCL_STOP */
835                                 }
836
837                                 char temp[str_len+1];
838
839                                 if (data)
840                                         len += snprintf(temp_data + len, buf_size - len, "%s ", data);
841                                 if (company->name) {
842                                         had = __ctsvc_contact_check_token(company->name, temp, SAFE_STRLEN(company->name));
843                                         len += snprintf(temp_data + len, buf_size - len, "%s %s ", company->name, had ? temp : "");
844                                 }
845                                 if (company->department) {
846                                         had = __ctsvc_contact_check_token(company->department, temp, SAFE_STRLEN(company->department));
847                                         len += snprintf(temp_data + len, buf_size - len, "%s %s ", company->department, had ? temp : "");
848                                 }
849                                 if (company->job_title) {
850                                         had = __ctsvc_contact_check_token(company->job_title, temp, SAFE_STRLEN(company->job_title));
851                                         len += snprintf(temp_data + len, buf_size - len, "%s %s ", company->job_title, had ? temp : "");
852                                 }
853                                 if (company->role) {
854                                         had = __ctsvc_contact_check_token(company->role, temp, SAFE_STRLEN(company->role));
855                                         len += snprintf(temp_data + len, buf_size - len, "%s %s ", company->role, had ? temp : "");
856                                 }
857                                 if (company->assistant_name) {
858                                         had = __ctsvc_contact_check_token(company->assistant_name, temp, SAFE_STRLEN(company->assistant_name));
859                                         len += snprintf(temp_data + len, buf_size - len, "%s %s ", company->assistant_name, had ? temp : "");
860                                 }
861                                 if (company->location) {
862                                         had = __ctsvc_contact_check_token(company->location, temp, SAFE_STRLEN(company->location));
863                                         len += snprintf(temp_data + len, buf_size - len, "%s %s ", company->location, had ? temp : "");
864                                 }
865                                 if (company->description) {
866                                         had = __ctsvc_contact_check_token(company->description, temp, SAFE_STRLEN(company->description));
867                                         len += snprintf(temp_data + len, buf_size - len, "%s %s ", company->description, had ? temp : "");
868                                 }
869                                 if (company->phonetic_name) {
870                                         had = __ctsvc_contact_check_token(company->phonetic_name, temp, SAFE_STRLEN(company->phonetic_name));
871                                         len += snprintf(temp_data + len, buf_size - len, "%s %s ", company->phonetic_name, had ? temp : "");
872                                 }
873
874                                 free(data);
875                                 data = temp_data;
876                         }
877                 } while (CONTACTS_ERROR_NONE == contacts_list_next(company_list));
878         }
879
880         *search_number = number;
881         if (data)
882                 *search_data = data;
883
884         return CONTACTS_ERROR_NONE;
885 }
886
887 static inline int __ctsvc_contact_refresh_lookup_data(int contact_id, ctsvc_contact_s *contact)
888 {
889         CTS_FN_CALL;
890         int ret, len = 0, temp_len = 0;
891         char query[CTS_SQL_MAX_LEN] = {0};
892
893         snprintf(query, sizeof(query), "DELETE FROM %s WHERE contact_id = %d",
894                         CTS_TABLE_NAME_LOOKUP, contact_id);
895         ret = ctsvc_query_exec(query);
896         if (CONTACTS_ERROR_NONE != ret) {
897                 /* LCOV_EXCL_START */
898                 ERR("ctsvc_query_exec() Fail(%d)", ret);
899                 return ret;
900                 /* LCOV_EXCL_STOP */
901         }
902
903         snprintf(query, sizeof(query), "DELETE FROM %s WHERE contact_id = %d",
904                         CTS_TABLE_PHONE_LOOKUP, contact_id);
905         ret = ctsvc_query_exec(query);
906         if (CONTACTS_ERROR_NONE != ret) {
907                 /* LCOV_EXCL_START */
908                 ERR("ctsvc_query_exec() Fail(%d)", ret);
909                 return ret;
910                 /* LCOV_EXCL_STOP */
911         }
912
913         if (contact == NULL)
914                 return CONTACTS_ERROR_NO_DATA;
915
916         if (contact->name) {
917                 contacts_list_h name_list = (contacts_list_h)contact->name;
918                 ctsvc_name_s *name_record;
919                 cts_stmt stmt = NULL;
920                 char *temp_name = NULL;
921                 contacts_list_first(name_list);
922                 len = 0;
923                 /* name record of contact should be one */
924                 do {
925                         contacts_list_get_current_record_p(name_list, (contacts_record_h*)&name_record);
926                         if (name_record
927                                         && (name_record->last
928                                                 || name_record->first
929                                                 || name_record->addition
930                                                 || name_record->suffix)) {
931                                 char *normalized_name = NULL;
932
933                                 /*
934                                  * Make reverse display name (Last name first)
935                                  * Default         : Prefix Last, First Middle(addition), Suffix
936                                  * Korean, Chinese : Prefix LastMiddleFirstSuffix
937                                  * Japanese        : Prefix Last Middle First Suffix
938                                  * reverse sort name does not include prefix
939                                  * But, if there is only prefix, reverse sort_name is prefix
940                                  */
941                                 /* make display name */
942                                 temp_len = SAFE_STRLEN(name_record->first)
943                                         + SAFE_STRLEN(name_record->addition)
944                                         + SAFE_STRLEN(name_record->last)
945                                         + SAFE_STRLEN(name_record->suffix)
946                                         + 1;
947                                 int reverse_lang_type = ctsvc_contact_get_name_language(name_record);
948                                 temp_name = calloc(1, temp_len);
949                                 if (NULL == temp_name) {
950                                         /* LCOV_EXCL_START */
951                                         ERR("calloc() Fail");
952                                         return CONTACTS_ERROR_OUT_OF_MEMORY;
953                                         /* LCOV_EXCL_STOP */
954                                 }
955
956                                 if (reverse_lang_type == CTSVC_LANG_KOREAN ||
957                                                 reverse_lang_type == CTSVC_LANG_CHINESE ||
958                                                 reverse_lang_type == CTSVC_LANG_JAPANESE) {
959                                         if (name_record->last)
960                                                 len += snprintf(temp_name + len, temp_len - len, "%s", name_record->last);
961                                         if (name_record->addition)
962                                                 len += snprintf(temp_name + len, temp_len - len, "%s", name_record->addition);
963                                         if (name_record->first)
964                                                 len += snprintf(temp_name + len, temp_len - len, "%s", name_record->first);
965                                         if (name_record->suffix)
966                                                 len += snprintf(temp_name + len, temp_len - len, "%s", name_record->suffix);
967                                 } else {
968                                         if (name_record->last)
969                                                 len += snprintf(temp_name + len, temp_len - len, "%s", name_record->last);
970                                         if (name_record->first)
971                                                 len += snprintf(temp_name + len, temp_len - len, "%s", name_record->first);
972                                         if (name_record->addition)
973                                                 len += snprintf(temp_name + len, temp_len - len, "%s", name_record->addition);
974                                         if (name_record->suffix)
975                                                 len += snprintf(temp_name + len, temp_len - len, "%s", name_record->suffix);
976                                 }
977
978                                 ctsvc_normalize_str(temp_name, &normalized_name);
979                                 snprintf(query, sizeof(query), "INSERT INTO %s(data_id, contact_id, name, type) "
980                                                 "VALUES(%d, %d, ?, %d)",        CTS_TABLE_NAME_LOOKUP, name_record->id,
981                                                 contact_id, 0);
982
983                                 ret = ctsvc_query_prepare(query, &stmt);
984                                 if (NULL == stmt) {
985                                         /* LCOV_EXCL_START */
986                                         ERR("ctsvc_query_prepare() Fail(%d)", ret);
987                                         free(temp_name);
988                                         free(normalized_name);
989                                         return ret;
990                                         /* LCOV_EXCL_STOP */
991                                 }
992
993                                 if (normalized_name)
994                                         ctsvc_stmt_bind_text(stmt, 1, normalized_name);
995
996                                 ret = ctsvc_stmt_step(stmt);
997
998                                 free(temp_name);
999                                 free(normalized_name);
1000
1001                                 ctsvc_stmt_finalize(stmt);
1002
1003                                 if (CONTACTS_ERROR_NONE != ret) {
1004                                         /* LCOV_EXCL_START */
1005                                         ERR("ctsvc_stmt_step() Fail(%d)", ret);
1006                                         return ret;
1007                                         /* LCOV_EXCL_STOP */
1008                                 }
1009                                 break;
1010                         }
1011                 } while (CONTACTS_ERROR_NONE == contacts_list_next(name_list));
1012         }
1013
1014         if (contact->numbers) {
1015                 contacts_list_h number_list = (contacts_list_h)contact->numbers;
1016                 cts_stmt stmt = NULL;
1017                 ctsvc_number_s *number_record;
1018                 contacts_list_first(number_list);
1019                 len = 0;
1020                 do {
1021                         contacts_list_get_current_record_p(number_list, (contacts_record_h*)&number_record);
1022                         if (number_record && number_record->number) {
1023                                 if (NULL == number_record->cleaned)
1024                                         continue;
1025
1026                                 /* actually phone_lookup minmatch is not used */
1027                                 snprintf(query, sizeof(query), "INSERT INTO %s(data_id, contact_id, number, min_match) "
1028                                                 "VALUES(%d, %d, ?, ?)", CTS_TABLE_PHONE_LOOKUP, number_record->id,
1029                                                 contact_id);
1030
1031                                 ret = ctsvc_query_prepare(query, &stmt);
1032                                 RETVM_IF(NULL == stmt, ret, "ctsvc_query_prepare() Fail(%d)", ret);
1033
1034                                 if (*number_record->cleaned)
1035                                         ctsvc_stmt_bind_text(stmt, 1, number_record->cleaned);
1036                                 ret = ctsvc_stmt_step(stmt);
1037                                 if (CONTACTS_ERROR_NONE != ret) {
1038                                         /* LCOV_EXCL_START */
1039                                         ERR("ctsvc_stmt_step() Fail(%d)", ret);
1040                                         ctsvc_stmt_finalize(stmt);
1041                                         return ret;
1042                                         /* LCOV_EXCL_STOP */
1043                                 }
1044                                 if (number_record->normalized && STRING_EQUAL != strcmp(number_record->cleaned, number_record->normalized)) {
1045                                         ctsvc_stmt_reset(stmt);
1046                                         if (*number_record->normalized)
1047                                                 ctsvc_stmt_bind_text(stmt, 1, number_record->normalized);
1048                                         ret = ctsvc_stmt_step(stmt);
1049                                         if (CONTACTS_ERROR_NONE != ret) {
1050                                                 /* LCOV_EXCL_START */
1051                                                 ERR("ctsvc_stmt_step() Fail(%d)", ret);
1052                                                 ctsvc_stmt_finalize(stmt);
1053                                                 return ret;
1054                                                 /* LCOV_EXCL_STOP */
1055                                         }
1056                                 }
1057                                 ctsvc_stmt_finalize(stmt);
1058                         }
1059                 } while (CONTACTS_ERROR_NONE == contacts_list_next(number_list));
1060         }
1061
1062         if (contact->nicknames) {
1063                 contacts_list_h nickname_list = (contacts_list_h)contact->nicknames;
1064                 cts_stmt stmt = NULL;
1065                 ctsvc_nickname_s *nickname;
1066                 contacts_list_first(nickname_list);
1067                 do {
1068                         contacts_list_get_current_record_p(nickname_list, (contacts_record_h*)&nickname);
1069                         if (nickname && nickname->nickname) {
1070                                 char *normalized_nickname = NULL;
1071                                 ctsvc_normalize_str(nickname->nickname, &normalized_nickname);
1072                                 snprintf(query, sizeof(query), "INSERT INTO %s(data_id, contact_id, name, type) "
1073                                                 "VALUES(%d, %d, ?, %d)",        CTS_TABLE_NAME_LOOKUP, nickname->id,
1074                                                 contact_id,  CONTACTS_DATA_TYPE_NICKNAME);
1075
1076                                 ret = ctsvc_query_prepare(query, &stmt);
1077                                 if (NULL == stmt) {
1078                                         /* LCOV_EXCL_START */
1079                                         ERR("ctsvc_query_prepare() Fail(%d)", ret);
1080                                         free(normalized_nickname);
1081                                         return ret;
1082                                         /* LCOV_EXCL_STOP */
1083                                 }
1084
1085                                 if (normalized_nickname && *normalized_nickname)
1086                                         ctsvc_stmt_bind_text(stmt, 1, normalized_nickname);
1087
1088                                 ret = ctsvc_stmt_step(stmt);
1089
1090                                 free(normalized_nickname);
1091
1092                                 ctsvc_stmt_finalize(stmt);
1093
1094                                 if (CONTACTS_ERROR_NONE != ret) {
1095                                         /* LCOV_EXCL_START */
1096                                         ERR("ctsvc_stmt_step() Fail(%d)", ret);
1097                                         return ret;
1098                                         /* LCOV_EXCL_STOP */
1099                                 }
1100                         }
1101                 } while (CONTACTS_ERROR_NONE == contacts_list_next(nickname_list));
1102         }
1103
1104         return CONTACTS_ERROR_NONE;
1105 }
1106
1107 static inline int __ctsvc_contact_update_search_data(int contact_id, bool need_refresh_lookup_data)
1108 {
1109         int ret;
1110         cts_stmt stmt = NULL;
1111         char query[CTS_SQL_MAX_LEN] = {0};
1112         char *search_name = NULL;
1113         char *search_number = NULL;
1114         char *search_data = NULL;
1115         ctsvc_contact_s *contact = NULL;
1116
1117         ret = ctsvc_begin_trans();
1118         RETVM_IF(ret, ret, "ctsvc_begin_trans() Fail(%d)", ret);
1119
1120         ret = ctsvc_db_contact_get(contact_id, (contacts_record_h*)&contact);
1121         if (CONTACTS_ERROR_NO_DATA == ret) {
1122                 int r;
1123                 snprintf(query, sizeof(query), "DELETE FROM %s WHERE contact_id = %d",
1124                                 CTS_TABLE_SEARCH_INDEX, contact_id);
1125                 r = ctsvc_query_exec(query);
1126                 if (CONTACTS_ERROR_NONE != r) {
1127                         /* LCOV_EXCL_START */
1128                         ERR("ctsvc_query_exec() Fail(%d)", r);
1129                         ctsvc_end_trans(false);
1130                         return r;
1131                         /* LCOV_EXCL_STOP */
1132                 }
1133                 ctsvc_end_trans(false);
1134                 return ret;
1135         } else if (CONTACTS_ERROR_NONE != ret) {
1136                 /* LCOV_EXCL_START */
1137                 ERR("ctsvc_db_contact_get() Fail(%d)", ret);
1138                 ctsvc_end_trans(false);
1139                 return ret;
1140                 /* LCOV_EXCL_STOP */
1141         }
1142
1143         ret = ctsvc_contact_make_search_name(contact, &search_name);
1144         if (CONTACTS_ERROR_NONE != ret) {
1145                 /* LCOV_EXCL_START */
1146                 ERR("ctsvc_contact_make_search_name() Fail(%d)", ret);
1147                 contacts_record_destroy((contacts_record_h)contact, true);
1148                 ctsvc_end_trans(false);
1149                 return ret;
1150                 /* LCOV_EXCL_STOP */
1151         }
1152
1153         ret = __ctsvc_contact_make_search_data(contact, &search_number, &search_data);
1154         if (CONTACTS_ERROR_NONE != ret) {
1155                 /* LCOV_EXCL_START */
1156                 ERR("__ctsvc_contact_make_search_data() Fail(%d)", ret);
1157                 contacts_record_destroy((contacts_record_h)contact, true);
1158                 ctsvc_end_trans(false);
1159                 free(search_name);
1160                 return ret;
1161                 /* LCOV_EXCL_STOP */
1162         }
1163
1164         snprintf(query, sizeof(query),
1165                         "UPDATE %s SET name=?, number=?, data=? "
1166                         "WHERE contact_id = %d",
1167                         CTS_TABLE_SEARCH_INDEX, contact_id);
1168
1169         ret = ctsvc_query_prepare(query, &stmt);
1170         if (NULL == stmt) {
1171                 /* LCOV_EXCL_START */
1172                 ERR("ctsvc_query_prepare() Fail(%d)", ret);
1173                 contacts_record_destroy((contacts_record_h)contact, true);
1174                 ctsvc_end_trans(false);
1175                 free(search_name);
1176                 free(search_number);
1177                 free(search_data);
1178                 return ret;
1179                 /* LCOV_EXCL_STOP */
1180         }
1181
1182         if (search_name)
1183                 ctsvc_stmt_bind_text(stmt, 1, search_name);
1184         if (search_number)
1185                 ctsvc_stmt_bind_text(stmt, 2, search_number);
1186         if (search_data)
1187                 ctsvc_stmt_bind_text(stmt, 3, search_data);
1188
1189         ret = ctsvc_stmt_step(stmt);
1190
1191         free(search_name);
1192         free(search_number);
1193         free(search_data);
1194
1195         if (CONTACTS_ERROR_NONE != ret) {
1196                 /* LCOV_EXCL_START */
1197                 ERR("ctsvc_stmt_step() Fail(%d)", ret);
1198                 contacts_record_destroy((contacts_record_h)contact, true);
1199                 ctsvc_stmt_finalize(stmt);
1200                 ctsvc_end_trans(false);
1201                 return ret;
1202                 /* LCOV_EXCL_STOP */
1203         }
1204         ctsvc_stmt_finalize(stmt);
1205
1206         if (need_refresh_lookup_data) {
1207                 /* update phone_lookup, name_lookup */
1208                 ret = __ctsvc_contact_refresh_lookup_data(contact_id, contact);
1209                 if (CONTACTS_ERROR_NONE != ret) {
1210                         /* LCOV_EXCL_START */
1211                         ERR("__ctsvc_contact_refresh_lookup_data() Fail(%d)", ret);
1212                         contacts_record_destroy((contacts_record_h)contact, true);
1213                         ctsvc_end_trans(false);
1214                         return ret;
1215                         /* LCOV_EXCL_STOP */
1216                 }
1217         }
1218
1219         contacts_record_destroy((contacts_record_h)contact, true);
1220
1221         ret = ctsvc_end_trans(true);
1222         RETVM_IF(ret < CONTACTS_ERROR_NONE, ret, "ctsvc_end_trans() Fail(%d)", ret);
1223
1224         return CONTACTS_ERROR_NONE;
1225 }
1226
1227 static bool __ctsvc_list_check_dirty(ctsvc_list_s *list)
1228 {
1229         if (list) {
1230                 if (list->deleted_records)
1231                         return true;
1232
1233                 GList *c = NULL;
1234                 for (c = list->records; c; c = c->next) {
1235                         ctsvc_record_s *s_record = c->data;
1236                         int i;
1237                         unsigned int property_info_count = 0;
1238                         const property_info_s *property_info = ctsvc_view_get_all_property_infos(s_record->view_uri, &property_info_count);
1239                         for (i = 0; i < property_info_count; i++) {
1240                                 bool ret = ctsvc_record_check_property_flag(s_record,
1241                                                 property_info[i].property_id, CTSVC_PROPERTY_FLAG_DIRTY);
1242                                 if (ret)
1243                                         return true;
1244                         }
1245                 }
1246         }
1247         return false;
1248 }
1249
1250 static bool __ctsvc_get_need_refresh_lookup_data(ctsvc_contact_s *contact)
1251 {
1252         if (__ctsvc_list_check_dirty(contact->name))
1253                 return true;
1254         if (__ctsvc_list_check_dirty(contact->numbers))
1255                 return true;
1256         if (__ctsvc_list_check_dirty(contact->nicknames))
1257                 return true;
1258         return false;
1259 }
1260
1261 static int __ctsvc_db_contact_update_record(contacts_record_h record)
1262 {
1263         int ret, len = 0;
1264         int rel_changed = 0;
1265         int version;
1266         char *set = NULL;
1267         char query[CTS_SQL_MAX_LEN] = {0};
1268         GSList *bind_text = NULL;
1269         GSList *cursor = NULL;
1270         ctsvc_contact_s *contact = (ctsvc_contact_s*)record;
1271         bool is_invalid = false;
1272         int current_version = 0;
1273
1274         ret = ctsvc_begin_trans();
1275         RETVM_IF(ret, ret, "ctsvc_begin_trans() Fail(%d)", ret);
1276
1277         snprintf(query, sizeof(query),
1278                         "SELECT changed_ver FROM "CTS_TABLE_CONTACTS" "
1279                         "WHERE contact_id = %d AND deleted = 0", contact->id);
1280         ret = ctsvc_query_get_first_int_result(query, &current_version);
1281         if (CONTACTS_ERROR_NONE != ret) {
1282                 /* LCOV_EXCL_START */
1283                 ERR("The index(%d) is Invalid. %d Record(s) is(are) found", contact->id, ret);
1284                 ctsvc_end_trans(false);
1285                 return ret;
1286                 /* LCOV_EXCL_STOP */
1287         }
1288
1289         if (false == ctsvc_have_ab_write_permission(contact->addressbook_id, false)) {
1290                 /* LCOV_EXCL_START */
1291                 ERR("No permission in this addresbook_id(%d)", contact->addressbook_id);
1292                 ctsvc_end_trans(false);
1293                 return CONTACTS_ERROR_PERMISSION_DENIED;
1294                 /* LCOV_EXCL_STOP */
1295         }
1296
1297         if (current_version != contact->changed_ver)
1298                 is_invalid = true;
1299         __ctsvc_contact_check_default_data(contact);
1300
1301         /* check lookup data is dirty */
1302         bool need_update_lookup = __ctsvc_get_need_refresh_lookup_data(contact);
1303
1304         /* update data */
1305         ret = __ctsvc_contact_update_data(contact);
1306         if (CONTACTS_ERROR_NONE != ret) {
1307                 /* LCOV_EXCL_START */
1308                 ERR("__ctsvc_contact_update_data() Fail(%d)", ret);
1309                 ctsvc_end_trans(false);
1310                 return ret;
1311                 /* LCOV_EXCL_STOP */
1312         }
1313
1314         if (contact->grouprelations) {
1315                 rel_changed = __ctsvc_contact_update_grouprel(contact->id, (contacts_list_h)contact->grouprelations);
1316                 if (rel_changed < CONTACTS_ERROR_NONE) {
1317                         /* LCOV_EXCL_START */
1318                         ERR("cts_update_contact_grouprel() Fail(%d)", rel_changed);
1319                         ctsvc_end_trans(false);
1320                         return rel_changed;
1321                         /* LCOV_EXCL_STOP */
1322                 }
1323         }
1324
1325         /* thumbnail */
1326         if (contact->images) {
1327                 int ret = CONTACTS_ERROR_NONE;
1328                 int count = 0;
1329                 ctsvc_image_s *image;
1330                 char *contact_image_path = NULL;
1331
1332                 contacts_list_get_count((contacts_list_h)contact->images, &count);
1333                 if (count) {
1334                         contacts_list_first((contacts_list_h)contact->images);
1335                         do {
1336                                 ret = contacts_list_get_current_record_p((contacts_list_h)contact->images, (contacts_record_h*)&image);
1337                                 if (CONTACTS_ERROR_NONE != ret) {
1338                                         /* LCOV_EXCL_START */
1339                                         ERR("contacts_list_get_current_record_p() Fail(%d)", ret);
1340                                         ctsvc_end_trans(false);
1341                                         return CONTACTS_ERROR_DB;
1342                                         /* LCOV_EXCL_STOP */
1343                                 }
1344
1345                                 if (image->is_default)
1346                                         break;
1347                         } while (CONTACTS_ERROR_NONE == contacts_list_next((contacts_list_h)contact->images));
1348
1349                         contact_image_path = ctsvc_utils_get_image_path(contact->image_thumbnail_path);
1350
1351                         if ((NULL == contact_image_path && image->path) ||
1352                                         (contact_image_path && NULL == image->path) ||
1353                                         (contact_image_path && image->path && (STRING_EQUAL != strcmp(contact_image_path, image->path)))) {
1354                                 free(contact->image_thumbnail_path);
1355                                 contact->image_thumbnail_path = NULL;
1356                                 ctsvc_record_set_property_flag((ctsvc_record_s*)contact, _contacts_contact.image_thumbnail_path, CTSVC_PROPERTY_FLAG_DIRTY);
1357
1358                                 if (image->path)
1359                                         contact->image_thumbnail_path = ctsvc_utils_make_thumbnail(image->path);
1360                         }
1361                         free(contact_image_path);
1362                 } else if (contact->image_thumbnail_path) {
1363                         free(contact->image_thumbnail_path);
1364                         contact->image_thumbnail_path = NULL;
1365                         bool is_changed = ctsvc_record_check_property_flag((ctsvc_record_s*)contact, _contacts_contact.image_thumbnail_path, CTSVC_PROPERTY_FLAG_DIRTY);
1366                         if ((false == is_changed && false == is_invalid) || (is_changed && false == is_invalid)) {
1367                                 ctsvc_record_set_property_flag((ctsvc_record_s*)contact, _contacts_contact.image_thumbnail_path, CTSVC_PROPERTY_FLAG_DIRTY);
1368                         } else {
1369                                 if (((ctsvc_record_s*)record)->properties_flags) {
1370                                         int index = _contacts_contact.image_thumbnail_path & 0x000000FF;
1371                                         ((ctsvc_record_s*)record)->properties_flags[index] = 0;
1372                                 }
1373                         }
1374                 }
1375         }
1376
1377         if (is_invalid) {
1378                 ctsvc_contact_s *temp_contact;
1379                 contacts_record_create(_contacts_contact._uri, (contacts_record_h*)&temp_contact);
1380                 ret = __ctsvc_db_get_data(contact->id, temp_contact);
1381                 ctsvc_contact_make_display_name(temp_contact);
1382
1383                 FREEandSTRDUP(contact->display_name, temp_contact->display_name);
1384                 FREEandSTRDUP(contact->reverse_display_name, temp_contact->reverse_display_name);
1385                 FREEandSTRDUP(contact->sort_name, temp_contact->sort_name);
1386                 FREEandSTRDUP(contact->reverse_sort_name, temp_contact->reverse_sort_name);
1387                 FREEandSTRDUP(contact->sortkey, temp_contact->sortkey);
1388                 FREEandSTRDUP(contact->reverse_sortkey, temp_contact->reverse_sortkey);
1389
1390                 contact->display_name_language = temp_contact->display_name_language;
1391                 contact->reverse_display_name_language = temp_contact->reverse_display_name_language;
1392                 contact->display_source_type = temp_contact->display_source_type;
1393
1394                 if (ctsvc_record_check_property_flag((ctsvc_record_s*)temp_contact, _contacts_contact.display_name, CTSVC_PROPERTY_FLAG_DIRTY))
1395                         ctsvc_record_set_property_flag((ctsvc_record_s*)contact, _contacts_contact.display_name, CTSVC_PROPERTY_FLAG_DIRTY);
1396
1397                 contacts_record_destroy((contacts_record_h)temp_contact, true);
1398         } else {
1399                 ctsvc_contact_make_display_name(contact);
1400         }
1401
1402         do {
1403                 char query[CTS_SQL_MAX_LEN] = {0};
1404                 char query_set[CTS_SQL_MIN_LEN] = {0, };
1405                 cts_stmt stmt = NULL;
1406
1407                 version = ctsvc_get_next_ver();
1408
1409                 ret = ctsvc_db_create_set_query(record, &set, &bind_text);
1410                 WARN_IF(CONTACTS_ERROR_NONE != ret, "ctsvc_db_create_set_query() Fail(%d)", ret);
1411
1412                 if (set && *set)
1413                         len = snprintf(query_set, sizeof(query_set), "%s, ", set);
1414                 len += snprintf(query_set+len, sizeof(query_set)-len, " changed_ver=%d, changed_time=%d, has_phonenumber=%d, has_email=%d",
1415                                 version, (int)time(NULL), contact->has_phonenumber, contact->has_email);
1416                 if (ctsvc_record_check_property_flag((ctsvc_record_s*)contact, _contacts_contact.display_name, CTSVC_PROPERTY_FLAG_DIRTY)) {
1417                         len += snprintf(query_set+len, sizeof(query_set)-len,
1418                                         ", display_name=?, reverse_display_name=?, display_name_source=%d, "
1419                                         "display_name_language=%d, reverse_display_name_language=%d, "
1420                                         "sort_name=?, reverse_sort_name=?, sortkey=?, reverse_sortkey=?",
1421                                         contact->display_source_type, contact->display_name_language, contact->reverse_display_name_language);
1422                         bind_text = g_slist_append(bind_text, strdup(SAFE_STR(contact->display_name)));
1423                         bind_text = g_slist_append(bind_text, strdup(SAFE_STR(contact->reverse_display_name)));
1424                         bind_text = g_slist_append(bind_text, strdup(SAFE_STR(contact->sort_name)));
1425                         bind_text = g_slist_append(bind_text, strdup(SAFE_STR(contact->reverse_sort_name)));
1426                         bind_text = g_slist_append(bind_text, strdup(SAFE_STR(contact->sortkey)));
1427                         bind_text = g_slist_append(bind_text, strdup(SAFE_STR(contact->reverse_sortkey)));
1428                 }
1429
1430                 if (ctsvc_record_check_property_flag((ctsvc_record_s*)contact, _contacts_contact.image_thumbnail_path, CTSVC_PROPERTY_FLAG_DIRTY))
1431                         len += snprintf(query_set+len, sizeof(query_set)-len, ", image_changed_ver=%d", version);
1432
1433                 snprintf(query, sizeof(query), "UPDATE %s SET %s WHERE contact_id = %d", CTS_TABLE_CONTACTS, query_set, contact->id);
1434
1435                 ret = ctsvc_query_prepare(query, &stmt);
1436                 if (NULL == stmt) {
1437                         /* LCOV_EXCL_START */
1438                         ERR("ctsvc_query_prepare() Fail(%d)", ret);
1439                         break;
1440                         /* LCOV_EXCL_STOP */
1441                 }
1442
1443                 if (bind_text) {
1444                         int i = 0;
1445                         for (cursor = bind_text, i = 1; cursor; cursor = cursor->next, i++) {
1446                                 const char *text = cursor->data;
1447                                 if (*text)
1448                                         ctsvc_stmt_bind_text(stmt, i, text);
1449                         }
1450                 }
1451                 ret = ctsvc_stmt_step(stmt);
1452                 if (CONTACTS_ERROR_NONE != ret) {
1453                         /* LCOV_EXCL_START */
1454                         ERR("ctsvc_stmt_step() Fail(%d)", ret);
1455                         ctsvc_stmt_finalize(stmt);
1456                         break;
1457                         /* LCOV_EXCL_STOP */
1458                 }
1459                 ctsvc_stmt_finalize(stmt);
1460         } while (0);
1461
1462         if (CONTACTS_ERROR_NONE != ret) {
1463                 ctsvc_end_trans(false);
1464                 CTSVC_RECORD_RESET_PROPERTY_FLAGS((ctsvc_record_s*)record);
1465                 free(set);
1466
1467                 if (bind_text) {
1468                         for (cursor = bind_text; cursor; cursor = cursor->next) {
1469                                 free(cursor->data);
1470                                 cursor->data = NULL;
1471                         }
1472                         g_slist_free(bind_text);
1473                 }
1474                 return ret;
1475         }
1476
1477         ctsvc_set_contact_noti();
1478         if (0 < rel_changed)
1479                 ctsvc_set_group_rel_noti();
1480
1481         __ctsvc_contact_update_search_data(contact->id, need_update_lookup);
1482         ctsvc_db_update_person((contacts_record_h)contact);
1483
1484         CTSVC_RECORD_RESET_PROPERTY_FLAGS((ctsvc_record_s*)record);
1485         free(set);
1486
1487         if (bind_text) {
1488                 for (cursor = bind_text; cursor; cursor = cursor->next) {
1489                         free(cursor->data);
1490                         cursor->data = NULL;
1491                 }
1492                 g_slist_free(bind_text);
1493         }
1494
1495         ret = ctsvc_end_trans(true);
1496         RETVM_IF(ret < CONTACTS_ERROR_NONE, ret, "ctsvc_end_trans() Fail(%d)", ret);
1497
1498         return CONTACTS_ERROR_NONE;
1499 }
1500
1501 static int __ctsvc_db_contact_get_all_records(int offset, int limit, contacts_list_h *out_list)
1502 {
1503         int ret;
1504         int len;
1505         int contact_id;
1506         cts_stmt stmt;
1507         char query[CTS_SQL_MAX_LEN] = {0};
1508         contacts_list_h list;
1509
1510         len = snprintf(query, sizeof(query),
1511                         "SELECT contact_id FROM "CTS_TABLE_CONTACTS" WHERE deleted = 0");
1512
1513         if (0 != limit) {
1514                 len += snprintf(query+len, sizeof(query)-len, " LIMIT %d", limit);
1515                 if (0 < offset)
1516                         len += snprintf(query+len, sizeof(query)-len, " OFFSET %d", offset);
1517         }
1518
1519         ret = ctsvc_query_prepare(query, &stmt);
1520         RETVM_IF(NULL == stmt, ret, "ctsvc_query_prepare() Fail(%d)", ret);
1521
1522         contacts_list_create(&list);
1523         while ((ret = ctsvc_stmt_step(stmt))) {
1524                 contacts_record_h record;
1525                 if (1 != ret) {
1526                         /* LCOV_EXCL_START */
1527                         ERR("ctsvc_stmt_step() Fail(%d)", ret);
1528                         ctsvc_stmt_finalize(stmt);
1529                         contacts_list_destroy(list, true);
1530                         return ret;
1531                         /* LCOV_EXCL_STOP */
1532                 }
1533                 contact_id = ctsvc_stmt_get_int(stmt, 0);
1534                 ret = ctsvc_db_contact_get(contact_id, &record);
1535                 if (CONTACTS_ERROR_NONE != ret) {
1536                         /* LCOV_EXCL_START */
1537                         ERR("ctsvc_db_contact_get() Fail(%d)", ret);
1538                         ctsvc_stmt_finalize(stmt);
1539                         contacts_list_destroy(list, true);
1540                         return ret;
1541                         /* LCOV_EXCL_STOP */
1542                 }
1543                 ctsvc_list_prepend(list, record);
1544         }
1545         ctsvc_stmt_finalize(stmt);
1546         ctsvc_list_reverse(list);
1547
1548         *out_list = (contacts_list_h)list;
1549         return CONTACTS_ERROR_NONE;
1550 }
1551
1552 static int __ctsvc_db_contact_get_changed_ver(int contact_id, ctsvc_contact_s *contact)
1553 {
1554         int ret;
1555         int version;
1556         char query[CTS_SQL_MAX_LEN] = {0};
1557
1558         snprintf(query, sizeof(query),
1559                         "SELECT changed_ver FROM "CTS_TABLE_CONTACTS
1560                         " WHERE contact_id = %d AND deleted = 0", contact_id);
1561         ret = ctsvc_query_get_first_int_result(query, &version);
1562         if (CONTACTS_ERROR_NONE == ret)
1563                 contact->changed_ver = version;
1564         return ret;
1565 }
1566
1567 static int __ctsvc_db_contact_get_records_with_query(contacts_query_h query, int offset, int limit, contacts_list_h *out_list)
1568 {
1569         int ret;
1570         int i;
1571         int field_count;
1572         ctsvc_query_s *s_query;
1573         cts_stmt stmt;
1574         contacts_list_h list;
1575         ctsvc_contact_s *contact;
1576         char full_path[CTSVC_IMG_FULL_PATH_SIZE_MAX] = {0};
1577         bool had_contact_id = false;
1578         int contact_id = 0;
1579
1580         RETV_IF(NULL == query, CONTACTS_ERROR_INVALID_PARAMETER);
1581         s_query = (ctsvc_query_s*)query;
1582
1583         if (s_query->projection) {
1584                 for (i = 0; i < s_query->projection_count; i++) {
1585                         if (s_query->projection[i] == CTSVC_PROPERTY_CONTACT_ID) {
1586                                 had_contact_id = true;
1587                                 break;
1588                         }
1589                 }
1590         } else {
1591                 s_query->projection_count = 0;
1592                 had_contact_id = true;
1593         }
1594
1595         if (false == had_contact_id) {
1596                 s_query->projection = realloc(s_query->projection, s_query->projection_count+1);
1597                 if (NULL == s_query->projection) {
1598                         /* LCOV_EXCL_START */
1599                         ERR("realloc() Fail");
1600                         return CONTACTS_ERROR_OUT_OF_MEMORY;
1601                         /* LCOV_EXCL_STOP */
1602                 }
1603
1604                 s_query->projection[s_query->projection_count] = CTSVC_PROPERTY_CONTACT_ID;
1605                 s_query->projection_count++;
1606         }
1607
1608         ret = ctsvc_db_make_get_records_query_stmt(s_query, offset, limit, &stmt);
1609         RETVM_IF(CONTACTS_ERROR_NONE != ret, ret, "ctsvc_db_make_get_records_query_stmt fail(%d)", ret);
1610
1611         contacts_list_create(&list);
1612         while ((ret = ctsvc_stmt_step(stmt))) {
1613                 contacts_record_h record;
1614                 if (1 != ret) {
1615                         /* LCOV_EXCL_START */
1616                         ERR("ctsvc_stmt_step() Fail(%d)", ret);
1617                         ctsvc_stmt_finalize(stmt);
1618                         contacts_list_destroy(list, true);
1619                         return ret;
1620                         /* LCOV_EXCL_STOP */
1621                 }
1622
1623                 contacts_record_create(_contacts_contact._uri, &record);
1624                 contact = (ctsvc_contact_s*)record;
1625                 if (0 == s_query->projection_count) {
1626                         field_count = s_query->property_count;
1627                 } else {
1628                         field_count = s_query->projection_count;
1629                         ret = ctsvc_record_set_projection_flags(record, s_query->projection,
1630                                         s_query->projection_count, s_query->property_count);
1631
1632                         if (CONTACTS_ERROR_NONE != ret)
1633                                 ASSERT_NOT_REACHED("To set projection is failed.\n");
1634                 }
1635
1636                 for (i = 0; i < field_count; i++) {
1637                         char *temp;
1638                         int property_id;
1639                         if (0 == s_query->projection_count)
1640                                 property_id = s_query->properties[i].property_id;
1641                         else
1642                                 property_id = s_query->projection[i];
1643
1644                         switch (property_id) {
1645                         case CTSVC_PROPERTY_CONTACT_ID:
1646                                 contact_id = ctsvc_stmt_get_int(stmt, i);
1647                                 if (had_contact_id)
1648                                         contact->id = contact_id;
1649                                 break;
1650                         case CTSVC_PROPERTY_CONTACT_DISPLAY_NAME:
1651                                 temp = ctsvc_stmt_get_text(stmt, i);
1652                                 free(contact->display_name);
1653                                 contact->display_name = SAFE_STRDUP(temp);
1654                                 break;
1655                         case CTSVC_PROPERTY_CONTACT_DISPLAY_SOURCE_DATA_ID:
1656                                 contact->display_source_type = ctsvc_stmt_get_int(stmt, i);
1657                                 break;
1658                         case CTSVC_PROPERTY_CONTACT_ADDRESSBOOK_ID:
1659                                 contact->addressbook_id = ctsvc_stmt_get_int(stmt, i);
1660                                 break;
1661                         case CTSVC_PROPERTY_CONTACT_RINGTONE:
1662                                 temp = ctsvc_stmt_get_text(stmt, i);
1663                                 free(contact->ringtone_path);
1664                                 contact->ringtone_path = SAFE_STRDUP(temp);
1665                                 break;
1666                         case CTSVC_PROPERTY_CONTACT_IMAGE_THUMBNAIL:
1667                                 temp = ctsvc_stmt_get_text(stmt, i);
1668                                 if (temp && *temp) {
1669                                         snprintf(full_path, sizeof(full_path), "%s/%s", CTSVC_CONTACT_IMG_FULL_LOCATION, temp);
1670                                         free(contact->image_thumbnail_path);
1671                                         contact->image_thumbnail_path = strdup(full_path);
1672                                 }
1673                                 break;
1674                         case CTSVC_PROPERTY_CONTACT_IS_FAVORITE:
1675                                 contact->is_favorite = ctsvc_stmt_get_int(stmt, i);
1676                                 break;
1677                         case CTSVC_PROPERTY_CONTACT_HAS_PHONENUMBER:
1678                                 contact->has_phonenumber = ctsvc_stmt_get_int(stmt, i);
1679                                 break;
1680                         case CTSVC_PROPERTY_CONTACT_HAS_EMAIL:
1681                                 contact->has_email = ctsvc_stmt_get_int(stmt, i);
1682                                 break;
1683                         case CTSVC_PROPERTY_CONTACT_PERSON_ID:
1684                                 contact->person_id = ctsvc_stmt_get_int(stmt, i);
1685                                 break;
1686                         case CTSVC_PROPERTY_CONTACT_UID:
1687                                 temp = ctsvc_stmt_get_text(stmt, i);
1688                                 free(contact->uid);
1689                                 contact->uid = SAFE_STRDUP(temp);
1690                                 break;
1691                         case CTSVC_PROPERTY_CONTACT_VIBRATION:
1692                                 temp = ctsvc_stmt_get_text(stmt, i);
1693                                 free(contact->vibration);
1694                                 contact->vibration = SAFE_STRDUP(temp);
1695                                 break;
1696                         case CTSVC_PROPERTY_CONTACT_MESSAGE_ALERT:
1697                                 temp = ctsvc_stmt_get_text(stmt, i);
1698                                 free(contact->message_alert);
1699                                 contact->message_alert = SAFE_STRDUP(temp);
1700                                 break;
1701                         case CTSVC_PROPERTY_CONTACT_CHANGED_TIME:
1702                                 contact->changed_time = ctsvc_stmt_get_int(stmt, i);
1703                                 break;
1704                         case CTSVC_PROPERTY_CONTACT_LINK_MODE:
1705                                 contact->link_mode = ctsvc_stmt_get_int(stmt, i);
1706                                 break;
1707                         default:
1708                                 break;
1709                         }
1710                 }
1711                 /* get changed_ver */
1712                 ret = __ctsvc_db_contact_get_changed_ver(contact_id, contact);
1713                 if (CONTACTS_ERROR_NONE != ret) {
1714                         /* LCOV_EXCL_START */
1715                         ERR("__ctsvc_db_contact_get_changed_ver Fail(%d)", ret);
1716                         ctsvc_stmt_finalize(stmt);
1717                         contacts_list_destroy(list, true);
1718                         return ret;
1719                         /* LCOV_EXCL_STOP */
1720                 }
1721
1722                 ret = __ctsvc_db_get_data(contact_id, contact);
1723                 if (CONTACTS_ERROR_NONE != ret && CONTACTS_ERROR_NO_DATA != ret) {
1724                         /* LCOV_EXCL_START */
1725                         ERR("ctsvc_get_data_info Fail(%d)", ret);
1726                         ctsvc_stmt_finalize(stmt);
1727                         contacts_list_destroy(list, true);
1728                         return ret;
1729                         /* LCOV_EXCL_STOP */
1730                 }
1731
1732                 ret = __ctsvc_get_contact_grouprel(contact_id, contact);
1733                 if (CONTACTS_ERROR_NONE != ret) {
1734                         /* LCOV_EXCL_START */
1735                         ERR("ctsvc_get_group_relations Fail(%d)", ret);
1736                         ctsvc_stmt_finalize(stmt);
1737                         contacts_list_destroy(list, true);
1738                         return ret;
1739                         /* LCOV_EXCL_STOP */
1740                 }
1741
1742                 ctsvc_list_prepend(list, record);
1743         }
1744         ctsvc_stmt_finalize(stmt);
1745         ctsvc_list_reverse(list);
1746
1747         *out_list = (contacts_list_h)list;
1748
1749         return CONTACTS_ERROR_NONE;
1750 }
1751
1752
1753 static int __ctsvc_contact_insert_data(ctsvc_contact_s *contact)
1754 {
1755         int ret;
1756
1757         /* Insert the name */
1758         if (contact->name) {
1759                 ret = ctsvc_contact_insert_data_name((contacts_list_h)contact->name, contact->id, false);
1760                 if (CONTACTS_ERROR_NONE != ret) {
1761                         /* LCOV_EXCL_START */
1762                         ERR("ctsvc_contact_insert_data_name() Fail(%d)", ret);
1763                         return ret;
1764                         /* LCOV_EXCL_STOP */
1765                 }
1766         }
1767
1768         /* Insert the company */
1769         if (contact->company) {
1770                 ret = ctsvc_contact_insert_data_company((contacts_list_h)contact->company, contact->id, false);
1771                 if (CONTACTS_ERROR_NONE != ret) {
1772                         /* LCOV_EXCL_START */
1773                         ERR("ctsvc_insert_contact_data_company() Fail(%d)", ret);
1774                         return ret;
1775                         /* LCOV_EXCL_STOP */
1776                 }
1777         }
1778
1779         /* Insert the events */
1780         if (contact->events) {
1781                 ret = ctsvc_contact_insert_data_event((contacts_list_h)contact->events, contact->id, false);
1782                 if (CONTACTS_ERROR_NONE != ret) {
1783                         /* LCOV_EXCL_START */
1784                         ERR("ctsvc_insert_contact_data_event() Fail(%d)", ret);
1785                         return ret;
1786                         /* LCOV_EXCL_STOP */
1787                 }
1788         }
1789
1790         /* Insert the messengers */
1791         if (contact->messengers) {
1792                 ret = ctsvc_contact_insert_data_messenger((contacts_list_h)contact->messengers, contact->id, false);
1793                 if (CONTACTS_ERROR_NONE != ret) {
1794                         /* LCOV_EXCL_START */
1795                         ERR("ctsvc_insert_contact_data_messenger() Fail(%d)", ret);
1796                         return ret;
1797                         /* LCOV_EXCL_STOP */
1798                 }
1799         }
1800
1801         /* Insert the postals */
1802         if (contact->postal_addrs) {
1803                 ret = ctsvc_contact_insert_data_address((contacts_list_h)contact->postal_addrs, contact->id, false);
1804                 if (CONTACTS_ERROR_NONE != ret) {
1805                         /* LCOV_EXCL_START */
1806                         ERR("ctsvc_insert_contact_data_postal() Fail(%d)", ret);
1807                         return ret;
1808                         /* LCOV_EXCL_STOP */
1809                 }
1810         }
1811
1812         /* Insert the Web addrs */
1813         if (contact->urls) {
1814                 ret = ctsvc_contact_insert_data_url((contacts_list_h)contact->urls, contact->id, false);
1815                 if (CONTACTS_ERROR_NONE != ret) {
1816                         /* LCOV_EXCL_START */
1817                         ERR("ctsvc_insert_contact_data_web() Fail(%d)", ret);
1818                         return ret;
1819                         /* LCOV_EXCL_STOP */
1820                 }
1821         }
1822
1823         /* Insert the Nick names */
1824         if (contact->nicknames) {
1825                 ret = ctsvc_contact_insert_data_nickname((contacts_list_h)contact->nicknames, contact->id, false);
1826                 if (CONTACTS_ERROR_NONE != ret) {
1827                         /* LCOV_EXCL_START */
1828                         ERR("ctsvc_insert_contact_data_nickname() Fail(%d)", ret);
1829                         return ret;
1830                         /* LCOV_EXCL_STOP */
1831                 }
1832         }
1833
1834         /* Insert the numbers */
1835         if (contact->numbers) {
1836                 ret = ctsvc_contact_insert_data_number((contacts_list_h)contact->numbers, contact->id, false);
1837                 if (ret < CONTACTS_ERROR_NONE) {
1838                         /* LCOV_EXCL_START */
1839                         ERR("ctsvc_contact_insert_data_number() Fail(%d)", ret);
1840                         return ret;
1841                         /* LCOV_EXCL_STOP */
1842                 }
1843         }
1844
1845         /* Insert the emails */
1846         if (contact->emails) {
1847                 ret = ctsvc_contact_insert_data_email((contacts_list_h)contact->emails, contact->id, false);
1848                 if (ret < CONTACTS_ERROR_NONE) {
1849                         /* LCOV_EXCL_START */
1850                         ERR("ctsvc_insert_contact_data_email() Fail(%d)", ret);
1851                         return ret;
1852                         /* LCOV_EXCL_STOP */
1853                 }
1854         }
1855
1856         /* Insert the profile values */
1857         if (contact->profiles) {
1858                 ret = ctsvc_contact_insert_data_profile((contacts_list_h)contact->profiles, contact->id, false);
1859                 if (CONTACTS_ERROR_NONE != ret) {
1860                         /* LCOV_EXCL_START */
1861                         ERR("ctsvc_insert_contact_data_profile() Fail(%d)", ret);
1862                         return ret;
1863                         /* LCOV_EXCL_STOP */
1864                 }
1865         }
1866
1867         /* Insert the relationship values */
1868         if (contact->relationships) {
1869                 ret = ctsvc_contact_insert_data_relationship((contacts_list_h)contact->relationships, contact->id, false);
1870                 if (CONTACTS_ERROR_NONE != ret) {
1871                         /* LCOV_EXCL_START */
1872                         ERR("ctsvc_contact_insert_data_relationship() Fail(%d)", ret);
1873                         return ret;
1874                         /* LCOV_EXCL_STOP */
1875                 }
1876         }
1877
1878         /* Insert the image values */
1879         if (contact->images) {
1880                 ret = ctsvc_contact_insert_data_image((contacts_list_h)contact->images, contact->id, false);
1881                 if (CONTACTS_ERROR_NONE != ret) {
1882                         /* LCOV_EXCL_START */
1883                         ERR("ctsvc_contact_insert_data_image() Fail(%d)", ret);
1884                         return ret;
1885                         /* LCOV_EXCL_STOP */
1886                 }
1887         }
1888
1889         /* Insert the note values */
1890         if (contact->note) {
1891                 ret = ctsvc_contact_insert_data_note((contacts_list_h)contact->note, contact->id, false);
1892                 if (CONTACTS_ERROR_NONE != ret) {
1893                         /* LCOV_EXCL_START */
1894                         ERR("ctsvc_contact_insert_data_note() Fail(%d)", ret);
1895                         return ret;
1896                         /* LCOV_EXCL_STOP */
1897                 }
1898         }
1899
1900         /* Insert the extensions values */
1901         if (contact->extensions) {
1902                 ret = ctsvc_contact_insert_data_extension((contacts_list_h)contact->extensions, contact->id, false);
1903                 if (CONTACTS_ERROR_NONE != ret) {
1904                         /* LCOV_EXCL_START */
1905                         ERR("ctsvc_contact_insert_data_extension() Fail(%d)", ret);
1906                         return ret;
1907                         /* LCOV_EXCL_STOP */
1908                 }
1909         }
1910
1911         /* Insert the sips */
1912         if (contact->sips) {
1913                 ret = ctsvc_contact_insert_data_sip((contacts_list_h)contact->sips, contact->id, false);
1914                 if (CONTACTS_ERROR_NONE != ret) {
1915                         /* LCOV_EXCL_START */
1916                         ERR("ctsvc_insert_contact_data_sip() Fail(%d)", ret);
1917                         return ret;
1918                         /* LCOV_EXCL_STOP */
1919                 }
1920         }
1921
1922         return CONTACTS_ERROR_NONE;
1923 }
1924
1925 static inline int __ctsvc_contact_insert_search_data(int contact_id, bool need_insert_lookup_data)
1926 {
1927         int ret;
1928         cts_stmt stmt = NULL;
1929         char query[CTS_SQL_MAX_LEN] = {0};
1930         char *search_name = NULL;
1931         char *search_number = NULL;
1932         char *search_data = NULL;
1933         ctsvc_contact_s *contact = NULL;
1934
1935         ret = ctsvc_begin_trans();
1936         RETVM_IF(ret, ret, "contacts_begin_trans() Fail(%d)", ret);
1937
1938         ret = ctsvc_db_contact_get(contact_id, (contacts_record_h*)&contact);
1939         if (CONTACTS_ERROR_NONE != ret) {
1940                 /* LCOV_EXCL_START */
1941                 ERR("ctsvc_db_contact_get() Fail(%d)", ret);
1942                 ctsvc_end_trans(false);
1943                 return ret;
1944                 /* LCOV_EXCL_STOP */
1945         }
1946
1947         ret = ctsvc_contact_make_search_name(contact, &search_name);
1948         if (CONTACTS_ERROR_NONE != ret) {
1949                 /* LCOV_EXCL_START */
1950                 ERR("ctsvc_contact_make_search_name() Fail(%d)", ret);
1951                 contacts_record_destroy((contacts_record_h)contact, true);
1952                 ctsvc_end_trans(false);
1953                 return ret;
1954                 /* LCOV_EXCL_STOP */
1955         }
1956
1957         ret = __ctsvc_contact_make_search_data(contact, &search_number, &search_data);
1958         if (CONTACTS_ERROR_NONE != ret) {
1959                 /* LCOV_EXCL_START */
1960                 ERR("__ctsvc_contact_make_search_data() Fail(%d)", ret);
1961                 contacts_record_destroy((contacts_record_h)contact, true);
1962                 ctsvc_end_trans(false);
1963                 free(search_name);
1964                 return ret;
1965                 /* LCOV_EXCL_STOP */
1966         }
1967
1968         snprintf(query, sizeof(query),
1969                         "INSERT INTO %s(contact_id, name, number, data) "
1970                         "VALUES(%d, ?, ?, ?)",
1971                         CTS_TABLE_SEARCH_INDEX, contact_id);
1972
1973         ret = ctsvc_query_prepare(query, &stmt);
1974         if (NULL == stmt) {
1975                 /* LCOV_EXCL_START */
1976                 ERR("ctsvc_query_prepare() Fail(%d)", ret);
1977                 contacts_record_destroy((contacts_record_h)contact, true);
1978                 ctsvc_end_trans(false);
1979                 free(search_name);
1980                 free(search_number);
1981                 free(search_data);
1982                 return ret;
1983                 /* LCOV_EXCL_STOP */
1984         }
1985
1986         if (search_name)
1987                 ctsvc_stmt_bind_text(stmt, 1, search_name);
1988         if (search_number)
1989                 ctsvc_stmt_bind_text(stmt, 2, search_number);
1990         if (search_data)
1991                 ctsvc_stmt_bind_text(stmt, 3, search_data);
1992
1993         ret = ctsvc_stmt_step(stmt);
1994
1995         free(search_name);
1996         free(search_number);
1997         free(search_data);
1998
1999         if (CONTACTS_ERROR_NONE != ret) {
2000                 /* LCOV_EXCL_START */
2001                 ERR("ctsvc_stmt_step() Fail(%d)", ret);
2002                 contacts_record_destroy((contacts_record_h)contact, true);
2003                 ctsvc_stmt_finalize(stmt);
2004                 ctsvc_end_trans(false);
2005                 return ret;
2006                 /* LCOV_EXCL_STOP */
2007         }
2008         ctsvc_stmt_finalize(stmt);
2009
2010         /* update phone_lookup, name_lookup */
2011         if (need_insert_lookup_data) {
2012                 ret = __ctsvc_contact_refresh_lookup_data(contact_id, contact);
2013                 if (CONTACTS_ERROR_NONE != ret) {
2014                         /* LCOV_EXCL_START */
2015                         ERR("__ctsvc_contact_refresh_lookup_data() Fail(%d)", ret);
2016                         contacts_record_destroy((contacts_record_h)contact, true);
2017                         ctsvc_end_trans(false);
2018                         return ret;
2019                         /* LCOV_EXCL_STOP */
2020                 }
2021         }
2022
2023         contacts_record_destroy((contacts_record_h)contact, true);
2024
2025         ret = ctsvc_end_trans(true);
2026         RETVM_IF(ret < CONTACTS_ERROR_NONE, ret, "ctsvc_end_trans() Fail(%d)", ret);
2027
2028         return CONTACTS_ERROR_NONE;
2029 }
2030
2031 static inline int __ctsvc_contact_insert_grouprel(int contact_id, contacts_list_h group_list)
2032 {
2033         CTS_FN_CALL;
2034         ctsvc_group_relation_s *grouprel;
2035         int rel_changed = 0;
2036         int count;
2037         int ret;
2038
2039         RETV_IF(NULL == group_list, CONTACTS_ERROR_INVALID_PARAMETER);
2040         ret = contacts_list_get_count(group_list, &count);
2041         if (0 == count)
2042                 return CONTACTS_ERROR_NONE;
2043
2044         contacts_list_first(group_list);
2045         do {
2046                 contacts_list_get_current_record_p(group_list, (contacts_record_h*)&grouprel);
2047                 if (NULL == grouprel)
2048                         continue;
2049
2050                 RETVM_IF(grouprel->group_id <= 0, CONTACTS_ERROR_INVALID_PARAMETER, "group_id(%d) invalid", grouprel->group_id);
2051                 if (grouprel->group_id) {
2052                         ret = ctsvc_group_add_contact_in_transaction(grouprel->group_id, contact_id);
2053                         RETVM_IF(ret < CONTACTS_ERROR_NONE, ret, "ctsvc_db_group_set_relation() Fail(%d)", ret);
2054                         if (0 < ret)
2055                                 rel_changed += ret;
2056                 }
2057         } while (CONTACTS_ERROR_NONE == contacts_list_next(group_list));
2058
2059         if (rel_changed)
2060                 return rel_changed;
2061         else
2062                 return CONTACTS_ERROR_NONE;
2063 }
2064
2065 static inline int __ctsvc_find_person_to_link_with_number(const char *number,
2066                 int addressbook_id, int *person_id)
2067 {
2068         int ret;
2069         cts_stmt stmt = NULL;
2070         char query[CTS_SQL_MIN_LEN] = {0};
2071         int number_len = SAFE_STRLEN(number);
2072         char clean_num[number_len+1];
2073
2074         ret = ctsvc_clean_number(number, clean_num, sizeof(clean_num), true);
2075         if (0 < ret) {
2076                 char normal_num[sizeof(clean_num)+20];
2077                 ret = ctsvc_normalize_number(clean_num, normal_num, sizeof(normal_num), true);
2078                 char minmatch[sizeof(normal_num)+1];
2079                 if (0 < ret)
2080                         ret = ctsvc_get_minmatch_number(normal_num, minmatch, sizeof(minmatch), ctsvc_get_phonenumber_min_match_digit());
2081
2082                 snprintf(query, sizeof(query),
2083                                 "SELECT C.person_id FROM "CTS_TABLE_CONTACTS" C, "CTS_TABLE_DATA" D "
2084                                 "ON C.contact_id=D.contact_id AND D.datatype=%d AND C.deleted = 0 "
2085                                 "AND C.addressbook_id <> %d AND D.is_my_profile = 0 "
2086                                 "WHERE D.data4 = ?",
2087                                 /* Below condition takes long time, so omit the condition */
2088                                 /* AND _NUMBER_COMPARE_(D.data5, ?, NULL, NULL) */
2089                                 CONTACTS_DATA_TYPE_NUMBER, addressbook_id);
2090
2091                 ret = ctsvc_query_prepare(query, &stmt);
2092                 RETVM_IF(NULL == stmt, ret, "ctsvc_query_prepare fail(%d)", ret);
2093                 ctsvc_stmt_bind_text(stmt, 1, minmatch);
2094                 /* ctsvc_stmt_bind_text(stmt, 2, normal_num); */
2095                 ret = ctsvc_stmt_step(stmt);
2096                 if (1 == ret) {
2097                         *person_id = ctsvc_stmt_get_int(stmt, 0);
2098                         ret = CONTACTS_ERROR_NONE;
2099                 } else if (CONTACTS_ERROR_NONE == ret) {
2100                         ret = CONTACTS_ERROR_NO_DATA;
2101                 }
2102                 ctsvc_stmt_finalize(stmt);
2103                 DBG("result ret(%d) person_id(%d)", ret, *person_id);
2104                 return ret;
2105         }
2106
2107         return CONTACTS_ERROR_INVALID_PARAMETER;
2108 }
2109
2110 static inline int __ctsvc_find_person_to_link_with_email(const char *email_addr, int addressbook_id, int *person_id)
2111 {
2112         int ret;
2113         cts_stmt stmt = NULL;
2114         char query[CTS_SQL_MIN_LEN] = {0};
2115
2116         snprintf(query, sizeof(query),
2117                         "SELECT C.person_id FROM "CTS_TABLE_CONTACTS" C, "CTS_TABLE_DATA" D "
2118                         "ON C.contact_id=D.contact_id AND D.datatype=%d AND C.deleted = 0 AND D.is_my_profile = 0 "
2119                         "AND C.addressbook_id <> %d "
2120                         "WHERE D.data3 = ?",
2121                         CONTACTS_DATA_TYPE_EMAIL, addressbook_id);
2122
2123         ret = ctsvc_query_prepare(query, &stmt);
2124         RETVM_IF(NULL == stmt, ret, "ctsvc_query_prepare fail(%d)", ret);
2125
2126         ctsvc_stmt_bind_text(stmt, 1, email_addr);
2127         ret = ctsvc_stmt_step(stmt);
2128         if (1 == ret) {
2129                 *person_id = ctsvc_stmt_get_int(stmt, 0);
2130                 ret = CONTACTS_ERROR_NONE;
2131         } else if (CONTACTS_ERROR_NONE == ret) {
2132                 ret = CONTACTS_ERROR_NO_DATA;
2133         }
2134
2135         ctsvc_stmt_finalize(stmt);
2136         DBG("result ret(%d) person_id(%d)", ret, *person_id);
2137
2138         return ret;
2139 }
2140
2141 static inline int __ctsvc_find_person_to_link(contacts_record_h record, int addressbook_id, int *person_id)
2142 {
2143         int ret;
2144         ctsvc_contact_s *contact = (ctsvc_contact_s*)record;
2145         ctsvc_number_s *number_data;
2146         ctsvc_email_s *email_data;
2147         GList *cursor;
2148
2149         for (cursor = contact->numbers->records; cursor; cursor = cursor->next) {
2150                 number_data = cursor->data;
2151                 if (number_data && number_data->number && number_data->number[0]) {
2152                         ret = __ctsvc_find_person_to_link_with_number(number_data->number, addressbook_id, person_id);
2153
2154                         if (ret == CONTACTS_ERROR_NONE && 0 < *person_id)
2155                                 return ret;
2156                 }
2157         }
2158
2159         for (cursor = contact->emails->records; cursor; cursor = cursor->next) {
2160                 email_data = cursor->data;
2161                 if (email_data && email_data->email_addr && email_data->email_addr[0]) {
2162                         ret = __ctsvc_find_person_to_link_with_email(email_data->email_addr, addressbook_id, person_id);
2163
2164                         if (ret == CONTACTS_ERROR_NONE && 0 < *person_id)
2165                                 return ret;
2166                 }
2167         }
2168
2169         return CONTACTS_ERROR_NO_DATA;
2170 }
2171
2172 static int __ctsvc_db_contact_insert_record(contacts_record_h record, int *id)
2173 {
2174         int version;
2175         int ret, person_id = 0;
2176         char query[CTS_SQL_MAX_LEN] = {0};
2177         bool auto_link_enabled = true;
2178         bool auto_linked = false;
2179
2180         ctsvc_contact_s *contact = (ctsvc_contact_s*)record;
2181         int rel_changed = 0;
2182         cts_stmt stmt = NULL;
2183
2184         /* These check should be done in client side */
2185         RETV_IF(NULL == contact, CONTACTS_ERROR_INVALID_PARAMETER);
2186         RETVM_IF(contact->addressbook_id < 0, CONTACTS_ERROR_INVALID_PARAMETER,
2187                         "addressbook_id(%d) is mandatory field to insert contact record ", contact->addressbook_id);
2188         RETVM_IF(0 < contact->id, CONTACTS_ERROR_INVALID_PARAMETER,
2189                         "id(%d), This record is already inserted", contact->id);
2190
2191         if (contact->link_mode == CONTACTS_CONTACT_LINK_MODE_IGNORE_ONCE)
2192                 auto_link_enabled = false;
2193
2194         ret = ctsvc_begin_trans();
2195         RETVM_IF(ret < CONTACTS_ERROR_NONE, ret, "ctsvc_begin_trans() Fail(%d)", ret);
2196
2197         if (false == ctsvc_have_ab_write_permission(contact->addressbook_id, false)) {
2198                 /* LCOV_EXCL_START */
2199                 ERR("No permission in this addresbook_id(%d)", contact->addressbook_id);
2200                 ctsvc_end_trans(false);
2201                 return CONTACTS_ERROR_PERMISSION_DENIED;
2202                 /* LCOV_EXCL_STOP */
2203         }
2204
2205         ret = ctsvc_db_get_next_id(CTS_TABLE_CONTACTS);
2206         if (ret < CONTACTS_ERROR_NONE) {
2207                 /* LCOV_EXCL_START */
2208                 ERR("ctsvc_db_get_next_id() Fail(%d)", ret);
2209                 ctsvc_end_trans(false);
2210                 return ret;
2211                 /* LCOV_EXCL_STOP */
2212         }
2213         contact->id = ret;
2214         if (id)
2215                 *id = ret;
2216
2217         ctsvc_contact_make_display_name(contact);
2218         __ctsvc_contact_check_default_data(contact);
2219
2220         /* check lookup data is dirty */
2221         bool need_insert_lookup = __ctsvc_get_need_refresh_lookup_data(contact);
2222
2223         /* Insert Data */
2224         ret = __ctsvc_contact_insert_data(contact);
2225         if (CONTACTS_ERROR_NONE != ret) {
2226                 /* LCOV_EXCL_START */
2227                 ERR("cts_insert_contact_data() Fail(%d)", ret);
2228                 ctsvc_end_trans(false);
2229                 return ret;
2230                 /* LCOV_EXCL_STOP */
2231         }
2232
2233         /* thumbnail */
2234         free(contact->image_thumbnail_path);
2235         contact->image_thumbnail_path = NULL;
2236         if (contact->images) {
2237                 int count = 0;
2238                 ctsvc_image_s *image;
2239
2240                 contacts_list_get_count((contacts_list_h)contact->images, &count);
2241                 if (count) {
2242                         contacts_list_first((contacts_list_h)contact->images);
2243                         do {
2244                                 ret = contacts_list_get_current_record_p((contacts_list_h)contact->images, (contacts_record_h*)&image);
2245                                 if (CONTACTS_ERROR_NONE != ret) {
2246                                         /* LCOV_EXCL_START */
2247                                         ERR("contacts_list_get_current_record_p() Fail(%d)", ret);
2248                                         ctsvc_end_trans(false);
2249                                         return CONTACTS_ERROR_DB;
2250                                         /* LCOV_EXCL_STOP */
2251                                 }
2252
2253                                 if (image->path && image->is_default) {
2254                                         contact->image_thumbnail_path = ctsvc_utils_make_thumbnail(image->path);
2255                                         break;
2256                                 }
2257                         } while (CONTACTS_ERROR_NONE == contacts_list_next((contacts_list_h)contact->images));
2258                 }
2259         }
2260
2261         version = ctsvc_get_next_ver();
2262
2263         if (contact->person_id) {
2264                 int id;
2265
2266                 snprintf(query, sizeof(query),
2267                                 "SELECT contact_id FROM "CTSVC_DB_VIEW_CONTACT" "
2268                                 "WHERE person_id = %d", contact->person_id);
2269                 ret = ctsvc_query_get_first_int_result(query, &id);
2270                 if (CONTACTS_ERROR_NONE != ret) {
2271                         /* LCOV_EXCL_START */
2272                         ERR("Invalid person_id(%d)", contact->person_id);
2273                         ctsvc_end_trans(false);
2274                         return CONTACTS_ERROR_INVALID_PARAMETER;
2275                         /* LCOV_EXCL_STOP */
2276                 }
2277
2278                 auto_linked = true;
2279         } else if (auto_link_enabled) {
2280                 ret = __ctsvc_find_person_to_link((contacts_record_h)contact, contact->addressbook_id, &person_id);
2281                 DBG("__ctsvc_find_person_to_link return %d, person_id(%d)", ret, person_id);
2282                 if (ret == CONTACTS_ERROR_NONE && 0 < person_id) {
2283                         contact->person_id = person_id;
2284                         auto_linked = true;
2285                 } else {
2286                         ret = ctsvc_db_insert_person((contacts_record_h)contact);
2287                         DBG("ctsvc_db_insert_person return %d, person_id(%d)", ret, ret);
2288                         if (ret < CONTACTS_ERROR_NONE) {
2289                                 /* LCOV_EXCL_START */
2290                                 ERR("ctsvc_db_insert_person() Fail(%d)", ret);
2291                                 ctsvc_end_trans(false);
2292                                 return ret;
2293                                 /* LCOV_EXCL_STOP */
2294                         }
2295                         contact->person_id = ret;
2296                 }
2297         } else {
2298                 ret = ctsvc_db_insert_person((contacts_record_h)contact);
2299                 DBG("ctsvc_db_insert_person return %d, person_id(%d)", ret, ret);
2300                 if (ret < CONTACTS_ERROR_NONE) {
2301                         /* LCOV_EXCL_START */
2302                         ERR("ctsvc_db_insert_person() Fail(%d)", ret);
2303                         ctsvc_end_trans(false);
2304                         return ret;
2305                         /* LCOV_EXCL_STOP */
2306                 }
2307                 contact->person_id = ret;
2308         }
2309
2310         snprintf(query, sizeof(query),
2311                         "INSERT INTO "CTS_TABLE_CONTACTS"(contact_id, person_id, addressbook_id, is_favorite, "
2312                         "created_ver, changed_ver, changed_time, link_mode, "
2313                         "image_changed_ver, has_phonenumber, has_email, "
2314                         "display_name, reverse_display_name, display_name_source, "
2315                         "display_name_language, reverse_display_name_language, "
2316                         "sort_name, reverse_sort_name, "
2317                         "sortkey, reverse_sortkey, "
2318                         "uid, ringtone_path, vibration, message_alert, image_thumbnail_path) "
2319                         "VALUES(%d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, ?, ?, %d, %d, %d, ?, ?, ?, ?, ?, ?, ?, ?, ?)",
2320                         contact->id, contact->person_id, contact->addressbook_id, contact->is_favorite,
2321                         version, version, (int)time(NULL), contact->link_mode,
2322                         (contact->image_thumbnail_path) ? version : 0, contact->has_phonenumber, contact->has_email,
2323                         contact->display_source_type, contact->display_name_language, contact->reverse_display_name_language);
2324
2325         ret = ctsvc_query_prepare(query, &stmt);
2326         if (NULL == stmt) {
2327                 /* LCOV_EXCL_START */
2328                 ERR("ctsvc_query_prepare() Fail(%d)", ret);
2329                 ctsvc_end_trans(false);
2330                 return ret;
2331                 /* LCOV_EXCL_STOP */
2332         }
2333
2334         if (contact->display_name)
2335                 ctsvc_stmt_bind_text(stmt, 1, contact->display_name);
2336         if (contact->reverse_display_name)
2337                 ctsvc_stmt_bind_text(stmt, 2, contact->reverse_display_name);
2338         if (contact->sort_name)
2339                 ctsvc_stmt_bind_text(stmt, 3, contact->sort_name);
2340         if (contact->reverse_sort_name)
2341                 ctsvc_stmt_bind_text(stmt, 4, contact->reverse_sort_name);
2342         if (contact->sortkey)
2343                 ctsvc_stmt_bind_text(stmt, 5, contact->sortkey);
2344         if (contact->reverse_sortkey)
2345                 ctsvc_stmt_bind_text(stmt, 6, contact->reverse_sortkey);
2346         if (contact->uid)
2347                 ctsvc_stmt_bind_text(stmt, 7, contact->uid);
2348         if (contact->ringtone_path)
2349                 ctsvc_stmt_bind_text(stmt, 8, contact->ringtone_path);
2350         if (contact->vibration)
2351                 ctsvc_stmt_bind_text(stmt, 9, contact->vibration);
2352         if (contact->message_alert)
2353                 ctsvc_stmt_bind_text(stmt, 10, contact->message_alert);
2354         if (contact->image_thumbnail_path)
2355                 ctsvc_stmt_bind_text(stmt, 11, contact->image_thumbnail_path);
2356
2357         ret = ctsvc_stmt_step(stmt);
2358         if (CONTACTS_ERROR_NONE != ret) {
2359                 /* LCOV_EXCL_START */
2360                 ERR("ctsvc_stmt_step() Fail(%d)", ret);
2361                 ctsvc_stmt_finalize(stmt);
2362                 ctsvc_end_trans(false);
2363                 return ret;
2364                 /* LCOV_EXCL_STOP */
2365         }
2366         ctsvc_stmt_finalize(stmt);
2367
2368         /* Insert group Info */
2369         if (contact->grouprelations) {
2370                 rel_changed = __ctsvc_contact_insert_grouprel(contact->id, (contacts_list_h)contact->grouprelations);
2371                 if (rel_changed < CONTACTS_ERROR_NONE) {
2372                         /* LCOV_EXCL_START */
2373                         ERR("__ctsvc_contact_insert_grouprel() Fail(%d)", rel_changed);
2374                         ctsvc_end_trans(false);
2375                         return rel_changed;
2376                         /* LCOV_EXCL_STOP */
2377                 }
2378         }
2379
2380         ret = __ctsvc_contact_insert_search_data(contact->id, need_insert_lookup);
2381         if (ret != CONTACTS_ERROR_NONE) {
2382                 /* LCOV_EXCL_START */
2383                 ERR("__ctsvc_contact_insert_search_data() Fail(%d)", ret);
2384                 ctsvc_end_trans(false);
2385                 return ret;
2386                 /* LCOV_EXCL_STOP */
2387         }
2388
2389         /* person aggregation when auto_linked */
2390         if (auto_linked)
2391                 ctsvc_person_aggregate(contact->person_id);
2392
2393 #ifdef ENABLE_LOG_FEATURE
2394         /* update phonelog */
2395         if (contact->numbers) {
2396                 int count;
2397                 ret = contacts_list_get_count((contacts_list_h)contact->numbers, &count);
2398                 contacts_list_first((contacts_list_h)contact->numbers);
2399                 if (0 < count) {
2400                         ctsvc_number_s *number_record;
2401                         do {
2402                                 contacts_list_get_current_record_p((contacts_list_h)contact->numbers, (contacts_record_h*)&number_record);
2403                                 if (number_record->number)
2404                                         ctsvc_db_phone_log_update_person_id(number_record->number, -1, contact->person_id, false, NULL);
2405                         } while (CONTACTS_ERROR_NONE == contacts_list_next((contacts_list_h)contact->numbers));
2406                 }
2407         }
2408 #endif /* ENABLE_LOG_FEATURE */
2409         if (rel_changed)
2410                 ctsvc_set_group_rel_noti();
2411         ctsvc_set_contact_noti();
2412
2413         ret = ctsvc_end_trans(true);
2414         RETVM_IF(ret < CONTACTS_ERROR_NONE, ret, "contacts_svc_end_trans() Fail(%d)", ret);
2415
2416         return CONTACTS_ERROR_NONE;
2417 }
2418
2419 static int __ctsvc_db_contact_replace_record(contacts_record_h record, int contact_id)
2420 {
2421         CTS_FN_CALL;
2422         int ret, len;
2423         int rel_changed = 0;
2424         int person_id;
2425         int addressbook_id;
2426         char query[CTS_SQL_MAX_LEN] = {0};
2427         ctsvc_contact_s *contact = (ctsvc_contact_s*)record;
2428         cts_stmt stmt = NULL;
2429         int version;
2430
2431         ret = ctsvc_begin_trans();
2432         RETVM_IF(ret, ret, "ctsvc_begin_trans() Fail(%d)", ret);
2433
2434         snprintf(query, sizeof(query),
2435                         "SELECT addressbook_id, person_id FROM "CTS_TABLE_CONTACTS" "
2436                         "WHERE contact_id = %d AND deleted = 0", contact_id);
2437         ret = ctsvc_query_prepare(query, &stmt);
2438         if (NULL == stmt) {
2439                 /* LCOV_EXCL_START */
2440                 ERR("ctsvc_query_prepare fail(%d)", ret);
2441                 ctsvc_end_trans(false);
2442                 return ret;
2443                 /* LCOV_EXCL_STOP */
2444         }
2445         ret = ctsvc_stmt_step(stmt);
2446         if (1 != ret) {
2447                 /* LCOV_EXCL_START */
2448                 ERR("The contact_id(%d) is Invalid(%d)", contact_id, ret);
2449                 ctsvc_stmt_finalize(stmt);
2450                 ctsvc_end_trans(false);
2451                 if (CONTACTS_ERROR_NONE == ret)
2452                         return CONTACTS_ERROR_NO_DATA;
2453                 else
2454                         return ret;
2455                 /* LCOV_EXCL_STOP */
2456         }
2457
2458         addressbook_id = ctsvc_stmt_get_int(stmt, 0);
2459         person_id = ctsvc_stmt_get_int(stmt, 1);
2460         ctsvc_stmt_finalize(stmt);
2461
2462         if (false == ctsvc_have_ab_write_permission(addressbook_id, false)) {
2463                 /* LCOV_EXCL_START */
2464                 ERR("No permission in this addresbook_id(%d)", addressbook_id);
2465                 ctsvc_end_trans(false);
2466                 return CONTACTS_ERROR_PERMISSION_DENIED;
2467                 /* LCOV_EXCL_STOP */
2468         }
2469
2470         contact->id = contact_id;
2471         contact->person_id = person_id;
2472         ctsvc_contact_make_display_name(contact);
2473         __ctsvc_contact_check_default_data(contact);
2474
2475         /* remove current child data */
2476         snprintf(query, sizeof(query), "DELETE FROM "CTS_TABLE_DATA" WHERE contact_id = %d",
2477                         contact_id);
2478         ret = ctsvc_query_exec(query);
2479         if (CONTACTS_ERROR_NONE != ret) {
2480                 /* LCOV_EXCL_START */
2481                 ERR("ctsvc_query_exec() Fail(%d)", ret);
2482                 ctsvc_end_trans(false);
2483                 return ret;
2484                 /* LCOV_EXCL_STOP */
2485         }
2486
2487         ret = __ctsvc_contact_insert_data(contact);
2488         if (CONTACTS_ERROR_NONE != ret) {
2489                 /* LCOV_EXCL_START */
2490                 ERR("__ctsvc_contact_insert_data() Fail(%d)", ret);
2491                 ctsvc_end_trans(false);
2492                 return ret;
2493                 /* LCOV_EXCL_STOP */
2494         }
2495
2496         /* remove current child data */
2497         snprintf(query, sizeof(query),
2498                         "DELETE FROM "CTS_TABLE_GROUP_RELATIONS" WHERE contact_id = %d", contact_id);
2499         ret = ctsvc_query_exec(query);
2500         if (CONTACTS_ERROR_NONE != ret) {
2501                 /* LCOV_EXCL_START */
2502                 ERR("ctsvc_query_exec() Fail(%d)", ret);
2503                 ctsvc_end_trans(false);
2504                 return ret;
2505                 /* LCOV_EXCL_STOP */
2506         }
2507
2508         if (contact->grouprelations) {
2509                 rel_changed = __ctsvc_contact_insert_grouprel(contact_id,
2510                                 (contacts_list_h)contact->grouprelations);
2511                 if (rel_changed < CONTACTS_ERROR_NONE) {
2512                         /* LCOV_EXCL_START */
2513                         ERR("__ctsvc_contact_insert_grouprel() Fail(%d)", rel_changed);
2514                         ctsvc_end_trans(false);
2515                         return rel_changed;
2516                         /* LCOV_EXCL_STOP */
2517                 }
2518         }
2519
2520         /* thumbnail */
2521         if (contact->images) {
2522                 int ret = CONTACTS_ERROR_NONE;
2523                 int count = 0;
2524                 ctsvc_image_s *image;
2525                 char *contact_image_path = NULL;
2526
2527                 contacts_list_get_count((contacts_list_h)contact->images, &count);
2528                 if (count) {
2529                         contacts_list_first((contacts_list_h)contact->images);
2530                         do {
2531                                 ret = contacts_list_get_current_record_p((contacts_list_h)contact->images,
2532                                                 (contacts_record_h*)&image);
2533                                 if (CONTACTS_ERROR_NONE != ret) {
2534                                         /* LCOV_EXCL_START */
2535                                         ERR("contacts_list_get_current_record_p() Fail(%d)", ret);
2536                                         ctsvc_end_trans(false);
2537                                         return CONTACTS_ERROR_DB;
2538                                         /* LCOV_EXCL_STOP */
2539                                 }
2540
2541                                 if (image->is_default)
2542                                         break;
2543                         } while (CONTACTS_ERROR_NONE == contacts_list_next((contacts_list_h)contact->images));
2544
2545                         contact_image_path = ctsvc_utils_get_image_path(contact->image_thumbnail_path);
2546                         if ((NULL == contact_image_path && image->path) ||
2547                                         (contact_image_path && NULL == image->path) ||
2548                                         (contact_image_path && image->path && STRING_EQUAL != strcmp(contact_image_path, image->path))) {
2549                                 ctsvc_record_set_property_flag((ctsvc_record_s*)contact, _contacts_contact.image_thumbnail_path, CTSVC_PROPERTY_FLAG_DIRTY);
2550
2551                                 if (image->path)
2552                                         contact->image_thumbnail_path = ctsvc_utils_make_thumbnail(image->path);
2553                         }
2554                         free(contact_image_path);
2555                 } else if (contact->image_thumbnail_path) {
2556                         free(contact->image_thumbnail_path);
2557                         contact->image_thumbnail_path = NULL;
2558                         if (false == ctsvc_record_check_property_flag((ctsvc_record_s*)contact, _contacts_contact.image_thumbnail_path, CTSVC_PROPERTY_FLAG_DIRTY)) {
2559                                 ctsvc_record_set_property_flag((ctsvc_record_s*)contact, _contacts_contact.image_thumbnail_path, CTSVC_PROPERTY_FLAG_DIRTY);
2560                         } else {
2561                                 if (((ctsvc_record_s*)record)->properties_flags) {
2562                                         int index = _contacts_contact.image_thumbnail_path & 0x000000FF;
2563                                         ((ctsvc_record_s*)record)->properties_flags[index] = 0;
2564                                 }
2565                         }
2566                 }
2567         }
2568         version = ctsvc_get_next_ver();
2569
2570         len = snprintf(query, sizeof(query),
2571                         "UPDATE "CTS_TABLE_CONTACTS" SET changed_ver=%d, changed_time=%d, is_favorite=%d, "
2572                         "has_phonenumber=%d, has_email=%d, display_name=?, "
2573                         "reverse_display_name=?, display_name_source=%d, "
2574                         "display_name_language=%d, reverse_display_name_language=%d, "
2575                         "sort_name=?, reverse_sort_name=?, "
2576                         "sortkey=?, reverse_sortkey=?, uid=?, ringtone_path=?, vibration=?, "
2577                         "message_alert =?, image_thumbnail_path=?",
2578                         version, (int)time(NULL), contact->is_favorite,
2579                         contact->has_phonenumber, contact->has_email,
2580                         contact->display_source_type,
2581                         contact->display_name_language, contact->reverse_display_name_language);
2582
2583         if (ctsvc_record_check_property_flag((ctsvc_record_s*)contact, _contacts_contact.image_thumbnail_path, CTSVC_PROPERTY_FLAG_DIRTY))
2584                 len += snprintf(query+len, sizeof(query)-len, ", image_changed_ver = %d", version);
2585
2586         len += snprintf(query+len, sizeof(query)-len, " WHERE contact_id=%d", contact->id);
2587
2588         ret = ctsvc_query_prepare(query, &stmt);
2589         if (NULL == stmt) {
2590                 /* LCOV_EXCL_START */
2591                 ERR("ctsvc_query_prepare() Fail(%d)", ret);
2592                 ctsvc_end_trans(false);
2593                 return ret;
2594                 /* LCOV_EXCL_STOP */
2595         }
2596
2597         if (contact->display_name)
2598                 ctsvc_stmt_bind_text(stmt, 1, contact->display_name);
2599         if (contact->reverse_display_name)
2600                 ctsvc_stmt_bind_text(stmt, 2, contact->reverse_display_name);
2601         if (contact->sort_name)
2602                 ctsvc_stmt_bind_text(stmt, 3, contact->sort_name);
2603         if (contact->reverse_sort_name)
2604                 ctsvc_stmt_bind_text(stmt, 4, contact->reverse_sort_name);
2605         if (contact->sortkey)
2606                 ctsvc_stmt_bind_text(stmt, 5, contact->sortkey);
2607         if (contact->reverse_sortkey)
2608                 ctsvc_stmt_bind_text(stmt, 6, contact->reverse_sortkey);
2609         if (contact->uid)
2610                 ctsvc_stmt_bind_text(stmt, 7, contact->uid);
2611         if (contact->ringtone_path)
2612                 ctsvc_stmt_bind_text(stmt, 8, contact->ringtone_path);
2613         if (contact->vibration)
2614                 ctsvc_stmt_bind_text(stmt, 9, contact->vibration);
2615         if (contact->message_alert)
2616                 ctsvc_stmt_bind_text(stmt, 10, contact->message_alert);
2617         if (contact->image_thumbnail_path)
2618                 ctsvc_stmt_bind_text(stmt, 11, contact->image_thumbnail_path);
2619
2620         ret = ctsvc_stmt_step(stmt);
2621         if (CONTACTS_ERROR_NONE != ret) {
2622                 /* LCOV_EXCL_START */
2623                 ERR("ctsvc_stmt_step() Fail(%d)", ret);
2624                 ctsvc_stmt_finalize(stmt);
2625                 ctsvc_end_trans(false);
2626                 return ret;
2627                 /* LCOV_EXCL_STOP */
2628         }
2629         ctsvc_stmt_finalize(stmt);
2630
2631         ctsvc_set_contact_noti();
2632         if (0 < rel_changed)
2633                 ctsvc_set_group_rel_noti();
2634
2635         __ctsvc_contact_update_search_data(contact->id, true);
2636         ctsvc_db_update_person((contacts_record_h)contact);
2637
2638         ret = ctsvc_end_trans(true);
2639
2640         if (ret < CONTACTS_ERROR_NONE)
2641                 return ret;
2642         else
2643                 return CONTACTS_ERROR_NONE;
2644 }
2645
2646 ctsvc_db_plugin_info_s ctsvc_db_plugin_contact = {
2647         .is_query_only = false,
2648         .insert_record = __ctsvc_db_contact_insert_record,
2649         .get_record = __ctsvc_db_contact_get_record,
2650         .update_record = __ctsvc_db_contact_update_record,
2651         .delete_record = __ctsvc_db_contact_delete_record,
2652         .get_all_records = __ctsvc_db_contact_get_all_records,
2653         .get_records_with_query = __ctsvc_db_contact_get_records_with_query,
2654         .insert_records = NULL,
2655         .update_records = NULL,
2656         .delete_records = NULL,
2657         .get_count = NULL,
2658         .get_count_with_query = NULL,
2659         .replace_record = __ctsvc_db_contact_replace_record,
2660         .replace_records = NULL,
2661 };
2662