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