1315854701c197a46d6fd7598696a8a6398d28e7
[platform/core/pim/contacts-service.git] / native / ctsvc_db_plugin_person_helper.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
20 #include "contacts.h"
21 #include "ctsvc_internal.h"
22 #include "ctsvc_schema.h"
23 #include "ctsvc_sqlite.h"
24 #include "ctsvc_db_plugin_person_helper.h"
25 #include "ctsvc_localize.h"
26 #include "ctsvc_normalize.h"
27 #include "ctsvc_db_init.h"
28 #include "ctsvc_utils.h"
29 #include "ctsvc_db_query.h"
30 #include "ctsvc_record.h"
31 #include "ctsvc_notification.h"
32
33 #ifdef _CONTACTS_IPC_SERVER
34 #include "ctsvc_server_change_subject.h"
35 #endif
36
37 int ctsvc_db_person_create_record_from_stmt_with_projection(cts_stmt stmt, unsigned int *projection, int projection_count, contacts_record_h *record)
38 {
39         ctsvc_person_s *person;
40         char full_path[CTSVC_IMG_FULL_PATH_SIZE_MAX] = {0};
41
42         contacts_record_create(_contacts_person._uri, record);
43         person = (ctsvc_person_s*)*record;
44
45         int i;
46         for(i=0;i<projection_count;i++) {
47                 char *temp;
48                 int property_id = projection[i];
49
50                 switch(property_id) {
51                 case CTSVC_PROPERTY_PERSON_ID:
52                         person->person_id = ctsvc_stmt_get_int(stmt, i);
53                         break;
54                 case CTSVC_PROPERTY_PERSON_DISPLAY_NAME:
55                         temp = ctsvc_stmt_get_text(stmt, i);
56                         person->display_name = SAFE_STRDUP(temp);
57                         break;
58                 case CTSVC_PROPERTY_PERSON_DISPLAY_NAME_INDEX:
59                         temp = ctsvc_stmt_get_text(stmt, i);
60                         person->display_name_index = SAFE_STRDUP(temp);
61                         break;
62                 case CTSVC_PROPERTY_PERSON_DISPLAY_CONTACT_ID:
63                         person->name_contact_id = ctsvc_stmt_get_int(stmt, i);
64                         break;
65                 case CTSVC_PROPERTY_PERSON_RINGTONE:
66                         temp = ctsvc_stmt_get_text(stmt, i);
67                         person->ringtone_path = SAFE_STRDUP(temp);
68                         break;
69                 case CTSVC_PROPERTY_PERSON_IMAGE_THUMBNAIL:
70                         temp = ctsvc_stmt_get_text(stmt, i);
71                         if (temp && *temp) {
72                                 snprintf(full_path, sizeof(full_path), "%s/%s", CTS_IMG_FULL_LOCATION, temp);
73                                 person->image_thumbnail_path = strdup(full_path);
74                         }
75                         break;
76                 case CTSVC_PROPERTY_PERSON_VIBRATION:
77                         temp = ctsvc_stmt_get_text(stmt, i);
78                         person->vibration = SAFE_STRDUP(temp);
79                         break;
80                 case CTSVC_PROPERTY_PERSON_MESSAGE_ALERT:
81                         temp = ctsvc_stmt_get_text(stmt, i);
82                         person->message_alert = SAFE_STRDUP(temp);
83                         break;
84                 case CTSVC_PROPERTY_PERSON_STATUS:
85                         temp = ctsvc_stmt_get_text(stmt, i);
86                         person->status = SAFE_STRDUP(temp);
87                         break;
88                 case CTSVC_PROPERTY_PERSON_IS_FAVORITE:
89                         person->is_favorite = ctsvc_stmt_get_int(stmt, i);
90                         break;
91                 case CTSVC_PROPERTY_PERSON_HAS_PHONENUMBER:
92                         person->has_phonenumber = ctsvc_stmt_get_int(stmt, i);
93                         break;
94                 case CTSVC_PROPERTY_PERSON_HAS_EMAIL:
95                         person->has_email = ctsvc_stmt_get_int(stmt, i);
96                         break;
97                 case CTSVC_PROPERTY_PERSON_LINK_COUNT:
98                         person->link_count = ctsvc_stmt_get_int(stmt, i);
99                         break;
100                 case CTSVC_PROPERTY_PERSON_ADDRESSBOOK_IDS:
101                         temp = ctsvc_stmt_get_text(stmt, i);
102                         person->addressbook_ids = SAFE_STRDUP(temp);
103                         break;
104                 case CTSVC_PROPERTY_PERSON_FAVORITE_PRIORITY:
105                         {
106                         // TODO: Fixme (BS)
107                                 int value = ctsvc_stmt_get_int(stmt, i);
108                                 value++; // fix warning
109                         }
110                         break;
111                         //      ASSERT_NOT_REACHED("Invalid parameter : property_id(0x%0x) is not supported in projection value(person)", property_id);
112                         // return CONTACTS_ERROR_INVALID_PARAMETER;
113                 default:
114                         ASSERT_NOT_REACHED("Invalid parameter : property_id(0x%0x) is not supported in value(person)", property_id);
115                         return CONTACTS_ERROR_INVALID_PARAMETER;
116                 }
117         }
118         return CONTACTS_ERROR_NONE;
119 }
120
121
122 int ctsvc_db_person_create_record_from_stmt_with_query(cts_stmt stmt, contacts_query_h query, contacts_record_h *record)
123 {
124         RETV_IF(NULL == query, CONTACTS_ERROR_INVALID_PARAMETER);
125         ctsvc_query_s *s_query = (ctsvc_query_s *)query;
126
127         if (0 == s_query->projection_count)
128         {
129                 unsigned int *projection = malloc(sizeof(unsigned int)*s_query->property_count);
130                 int i;
131                 for(i=0;i<s_query->property_count;i++)
132                 {
133                         projection[i] = s_query->properties[i].property_id;
134                 }
135
136                 int ret = ctsvc_db_person_create_record_from_stmt_with_projection(stmt, projection, s_query->property_count, record);
137
138                 free(projection);
139
140                 return ret;
141         }
142         else
143                 return ctsvc_db_person_create_record_from_stmt_with_projection(stmt, s_query->projection, s_query->projection_count, record);
144
145 }
146
147 int ctsvc_db_person_create_record_from_stmt(cts_stmt stmt, contacts_record_h *record)
148 {
149         int ret;
150         int i;
151         char *temp;
152         ctsvc_person_s *person;
153
154         i = 0;
155         ret = contacts_record_create(_contacts_person._uri, record);
156         RETVM_IF(CONTACTS_ERROR_NONE != ret, ret, "contacts_record_create is failed(%d)", ret);
157         person = (ctsvc_person_s *)*record;
158         person->person_id = ctsvc_stmt_get_int(stmt, i++);
159
160         temp = ctsvc_stmt_get_text(stmt, i++);
161         person->display_name = SAFE_STRDUP(temp);
162         temp = ctsvc_stmt_get_text(stmt, i++);
163         person->display_name_index = SAFE_STRDUP(temp);
164         person->name_contact_id = ctsvc_stmt_get_int(stmt, i++);
165
166         temp = ctsvc_stmt_get_text(stmt, i++);
167         if (temp && *temp) {
168                 char full_path[CTSVC_IMG_FULL_PATH_SIZE_MAX] = {0};
169                 snprintf(full_path, sizeof(full_path), "%s/%s", CTS_IMG_FULL_LOCATION, temp);
170                 person->image_thumbnail_path = strdup(full_path);
171         }
172
173         temp = ctsvc_stmt_get_text(stmt, i++);
174         person->ringtone_path = SAFE_STRDUP(temp);
175         temp = ctsvc_stmt_get_text(stmt, i++);
176         person->vibration = SAFE_STRDUP(temp);
177         temp = ctsvc_stmt_get_text(stmt, i++);
178         person->message_alert = SAFE_STRDUP(temp);
179         temp = ctsvc_stmt_get_text(stmt, i++);
180         person->status = SAFE_STRDUP(temp);
181
182         person->link_count = ctsvc_stmt_get_int(stmt, i++);
183         temp = ctsvc_stmt_get_text(stmt, i++);
184         person->addressbook_ids = SAFE_STRDUP(temp);
185
186         person->has_phonenumber = ctsvc_stmt_get_int(stmt, i++);
187         person->has_email = ctsvc_stmt_get_int(stmt, i++);
188         person->is_favorite = ctsvc_stmt_get_int(stmt, i++);
189
190         return CONTACTS_ERROR_NONE;
191 }
192
193 inline static const char* __cts_get_image_filename(const char* src)
194 {
195         const char* dir = CTS_IMG_FULL_LOCATION;
196         int pos=0;
197         while (dir[pos]==src[pos]) {
198                 pos++;
199         }
200
201         if ('/' == src[pos])
202                 return src + pos + 1;
203
204         return src+pos;
205 }
206
207 int ctsvc_db_person_set_favorite(int person_id, bool set, bool propagate)
208 {
209         int ret;
210         double prio = 0.0;
211         cts_stmt stmt = NULL;
212         char query[CTS_SQL_MIN_LEN] = {0};
213
214         if (set) {
215                 snprintf(query, sizeof(query),
216                         "SELECT MAX(favorite_prio) FROM "CTS_TABLE_FAVORITES);
217
218                 stmt = cts_query_prepare(query);
219                 RETVM_IF(NULL == stmt, CONTACTS_ERROR_DB, "cts_query_prepare() Failed");
220
221                 ret = cts_stmt_step(stmt);
222                 if (1 /*CTS_TRUE*/ == ret) {
223                         prio = ctsvc_stmt_get_dbl(stmt, 0);
224                 }
225                 else if (CONTACTS_ERROR_NONE != ret) {
226                         CTS_ERR("cts_stmt_step() Failed(%d)", ret);
227                         cts_stmt_finalize(stmt);
228                         return ret;
229                 }
230                 cts_stmt_finalize(stmt);
231
232                 prio = prio + 1.0;
233                 snprintf(query, sizeof(query),
234                         "INSERT OR REPLACE INTO "CTS_TABLE_FAVORITES" values(%d, %f)", person_id, prio);
235         }
236         else {
237                 snprintf(query, sizeof(query),
238                         "DELETE FROM "CTS_TABLE_FAVORITES" WHERE person_id = %d", person_id);
239         }
240
241         ret = ctsvc_query_exec(query);
242         if (CONTACTS_ERROR_NONE != ret) {
243                 CTS_ERR("cts_query_exec() Failed(%d)", ret);
244                 return ret;
245         }
246
247         if (propagate) {
248                 snprintf(query, sizeof(query),
249                                 "UPDATE "CTS_TABLE_CONTACTS" SET is_favorite = %d "
250                                         "WHERE person_id=%d AND deleted = 0", set?1:0, person_id);
251                 ret = ctsvc_query_exec(query);
252                 if (CONTACTS_ERROR_NONE != ret) {
253                         CTS_ERR("cts_query_exec() Failed(%d)", ret);
254                         return ret;
255                 }
256         }
257
258         return CONTACTS_ERROR_NONE;
259 }
260
261 int ctsvc_db_insert_person(contacts_record_h record)
262 {
263         int ret, index;
264         cts_stmt stmt = NULL;
265         char query[CTS_SQL_MIN_LEN] = {0};
266         int version;
267         ctsvc_contact_s *contact = (ctsvc_contact_s*)record;
268         char *status = NULL;
269
270         snprintf(query, sizeof(query),
271                 "SELECT status FROM %s "
272                 "WHERE contact_id=%d "
273                 "ORDER BY timestamp DESC LIMIT 1",
274                 CTS_TABLE_ACTIVITIES, contact->id);
275         stmt = cts_query_prepare(query);
276         if (NULL == stmt) {
277                 CTS_ERR("DB error : cts_query_prepare() Failed()");
278                 return CONTACTS_ERROR_DB;
279         }
280
281         if (1 == cts_stmt_step(stmt))
282                 status = SAFE_STRDUP(ctsvc_stmt_get_text(stmt, 0));
283         cts_stmt_finalize(stmt);
284
285         version = ctsvc_get_next_ver();
286         snprintf(query, sizeof(query),
287                 "INSERT INTO "CTS_TABLE_PERSONS"(name_contact_id, created_ver, changed_ver, "
288                         "has_phonenumber, has_email, ringtone_path, vibration, message_alert, status, "
289                         "image_thumbnail_path, link_count, addressbook_ids) "
290                         "VALUES(%d, %d, %d, %d, %d, ?, ?, ?, ?, ?, 1, '%d') ",
291                         contact->id, version, version,
292                         contact->has_phonenumber, contact->has_email, contact->addressbook_id);
293
294         stmt = cts_query_prepare(query);
295         if (NULL == stmt) {
296                 CTS_ERR("DB error : cts_query_prepare() Failed()");
297                 free(status);
298                 return CONTACTS_ERROR_DB;
299         }
300         if(contact->ringtone_path)
301                 cts_stmt_bind_text(stmt, 1, contact->ringtone_path);
302         if(contact->vibration)
303                 cts_stmt_bind_text(stmt, 2, contact->vibration);
304         if(contact->message_alert)
305                 cts_stmt_bind_text(stmt, 3, contact->message_alert);
306         if(status)
307                 cts_stmt_bind_text(stmt, 4, status);
308         if(contact->image_thumbnail_path)
309                 cts_stmt_bind_text(stmt, 5, __cts_get_image_filename(contact->image_thumbnail_path));
310
311         ret = cts_stmt_step(stmt);
312         if (CONTACTS_ERROR_NONE != ret) {
313                 CTS_ERR("cts_stmt_step() Failed(%d)", ret);
314                 cts_stmt_finalize(stmt);
315                 free(status);
316                 return ret;
317         }
318         index = cts_db_get_last_insert_id();
319
320         cts_stmt_finalize(stmt);
321
322         snprintf(query, sizeof(query),
323                 "UPDATE "CTS_TABLE_DATA" SET is_primary_default = 1 "
324                         "WHERE is_default = 1 AND contact_id = %d  AND is_my_profile = 0", contact->id);
325
326         ret = ctsvc_query_exec(query);
327         if (CONTACTS_ERROR_NONE != ret) {
328                 CTS_ERR("cts_query_exec Failed(%d)", ret);
329                 free(status);
330                 return ret;
331         }
332
333         // set favorite
334         if (contact->is_favorite) {
335                 ret = ctsvc_db_person_set_favorite(index, contact->is_favorite, false);
336                 if (CONTACTS_ERROR_NONE != ret) {
337                         CTS_ERR("cts_stmt_step() Failed(%d)", ret);
338                         return ret;
339                 }
340         }
341
342         free(status);
343         ctsvc_set_person_noti();
344 #ifdef _CONTACTS_IPC_SERVER
345         ctsvc_change_subject_add_changed_person_id(CONTACTS_CHANGE_INSERTED, index);
346 #endif
347
348         return index;
349 }
350
351 static inline int __ctsvc_db_update_person_default(int person_id, int datatype)
352 {
353         int ret, data_id;
354         cts_stmt stmt = NULL;
355         char query[CTS_SQL_MIN_LEN] = {0};
356         char *temp = NULL;
357         char *image_thumbnail_path = NULL;
358
359         snprintf(query, sizeof(query),
360                 "SELECT D.id FROM "CTS_TABLE_CONTACTS" C, "CTS_TABLE_DATA" D "
361                 "ON C.contact_id = D.contact_id AND C.deleted = 0 "
362                 "WHERE C.person_id=%d AND D.datatype=%d AND is_primary_default=1 AND D.is_my_profile = 0",
363                 person_id, datatype);
364
365         ret = ctsvc_query_get_first_int_result(query, &data_id);
366         if (CONTACTS_ERROR_NO_DATA == ret ) {
367                 snprintf(query, sizeof(query),
368                         "SELECT D.id, D.data3 FROM "CTS_TABLE_CONTACTS" C, "CTS_TABLE_DATA" D "
369                         "ON C.contact_id = D.contact_id AND C.deleted = 0 "
370                         "WHERE C.person_id=%d AND D.datatype=%d AND D.is_default=1 AND D.is_my_profile = 0 ORDER BY D.id",
371                         person_id, datatype);
372
373                 stmt = cts_query_prepare(query);
374                 if (NULL == stmt) {
375                         CTS_ERR("cts_query_prepare() Failed");
376                         return CONTACTS_ERROR_DB;
377                 }
378
379                 if ((ret = cts_stmt_step(stmt))) {
380                         data_id = ctsvc_stmt_get_int(stmt, 0);
381
382                         snprintf(query, sizeof(query),
383                                         "UPDATE "CTS_TABLE_DATA" SET is_primary_default=1 WHERE id=%d"
384                                         ,data_id);
385
386                         ret = ctsvc_query_exec(query);
387                         if (CONTACTS_ERROR_NONE != ret) {
388                                 CTS_ERR("cts_query_exec Failed(%d)", ret);
389                                 cts_stmt_finalize(stmt);
390                                 return ret;
391                         }
392                         temp = ctsvc_stmt_get_text(stmt, 1);
393                         image_thumbnail_path = SAFE_STRDUP(temp);
394                 }
395                 cts_stmt_finalize(stmt);
396
397                 if (CTSVC_DATA_IMAGE == datatype) {
398                         if (image_thumbnail_path) {
399                                 snprintf(query, sizeof(query),
400                                                 "UPDATE "CTS_TABLE_PERSONS" SET image_thumbnail_path=? WHERE person_id=%d", person_id);
401                                 stmt = cts_query_prepare(query);
402                                 cts_stmt_bind_text(stmt, 1, image_thumbnail_path);
403                                 ret = cts_stmt_step(stmt);
404                                 cts_stmt_finalize(stmt);
405                                 free(image_thumbnail_path);
406                                 if (CONTACTS_ERROR_NONE != ret) {
407                                         CTS_ERR("cts_query_exec Failed(%d)", ret);
408                                         return ret;
409                                 }
410                         }
411                 }
412                 else {
413                         free(image_thumbnail_path);
414                 }
415         }
416
417         return CONTACTS_ERROR_NONE;
418 }
419
420 static bool __ctsvc_get_has_column(int person_id, const char *culumn)
421 {
422         int ret;
423         int contact_count = 0;
424         char query[CTS_SQL_MIN_LEN] = {0};
425
426         snprintf(query, sizeof(query),
427                                 "SELECT count(contact_id) FROM "CTS_TABLE_CONTACTS" "
428                                 "WHERE person_id=%d AND %s=1 AND deleted = 0",
429                                 person_id, culumn);
430
431         ret = ctsvc_query_get_first_int_result(query, &contact_count);
432         RETV_IF(CONTACTS_ERROR_NONE != ret, false);
433
434         if (contact_count)
435                 return true;
436         return false;
437 }
438
439 static int __ctsvc_get_thumbnail_contact_id(int person_id)
440 {
441         int ret;
442         int contact_id = 0;
443         char query[CTS_SQL_MIN_LEN] = {0};
444
445         snprintf(query, sizeof(query),
446                         "SELECT D.contact_id FROM "CTS_TABLE_CONTACTS" C, "CTS_TABLE_DATA" D "
447                         "ON C.contact_id = D.contact_id AND C.deleted = 0 "
448                         "WHERE C.person_id=%d AND D.datatype=%d AND is_primary_default=1 AND D.is_my_profile = 0",
449                         person_id, CTSVC_DATA_IMAGE);
450         ret = ctsvc_query_get_first_int_result(query, &contact_id);
451         RETV_IF(CONTACTS_ERROR_NONE != ret, -1);
452         return contact_id;
453 }
454
455 int ctsvc_db_update_person(contacts_record_h record)
456 {
457         int ret, i=1, len=0;
458         cts_stmt stmt = NULL;
459         char query[CTS_SQL_MIN_LEN] = {0};
460         ctsvc_contact_s *contact = (ctsvc_contact_s*)record;
461         bool has_phonenumber=false, has_email=false;
462         int thumbnail_contact_id = 0;
463         int person_id = 0;
464         int is_favorite = 0;
465
466         ret = ctsvc_begin_trans();
467         RETVM_IF(ret, ret, "ctsvc_begin_trans() Failed(%d)", ret);
468
469         __ctsvc_db_update_person_default(contact->person_id, CTSVC_DATA_NUMBER);
470         __ctsvc_db_update_person_default(contact->person_id, CTSVC_DATA_EMAIL);
471         __ctsvc_db_update_person_default(contact->person_id, CTSVC_DATA_IMAGE);
472
473         has_phonenumber = __ctsvc_get_has_column(contact->person_id, "has_phonenumber");
474         has_email = __ctsvc_get_has_column(contact->person_id, "has_email");
475         thumbnail_contact_id = __ctsvc_get_thumbnail_contact_id(contact->person_id);
476
477         len = snprintf(query, sizeof(query),
478                         "UPDATE "CTS_TABLE_PERSONS" SET changed_ver=%d, has_phonenumber=%d, has_email=%d ",
479                         ctsvc_get_next_ver(), has_phonenumber, has_email);
480
481         if (ctsvc_record_check_property_flag((ctsvc_record_s *)record, _contacts_contact.ringtone_path, CTSVC_PROPERTY_FLAG_DIRTY))
482                 len += snprintf(query+len, sizeof(query)-len, ", ringtone_path=?");
483         if (ctsvc_record_check_property_flag((ctsvc_record_s *)record, _contacts_contact.vibration, CTSVC_PROPERTY_FLAG_DIRTY))
484                 len += snprintf(query+len, sizeof(query)-len, ", vibration=?");
485         if (ctsvc_record_check_property_flag((ctsvc_record_s *)record, _contacts_contact.message_alert, CTSVC_PROPERTY_FLAG_DIRTY))
486                 len += snprintf(query+len, sizeof(query)-len, ", message_alert=?");
487         if (ctsvc_record_check_property_flag((ctsvc_record_s *)record, _contacts_contact.image_thumbnail_path, CTSVC_PROPERTY_FLAG_DIRTY) &&
488                         (contact->id == thumbnail_contact_id || thumbnail_contact_id == -1))
489                 len += snprintf(query+len, sizeof(query)-len, ", image_thumbnail_path=?");
490
491         snprintf(query+len, sizeof(query)-len,
492                         " WHERE person_id=%d", contact->person_id);
493
494         stmt = cts_query_prepare(query);
495         if (NULL == stmt) {
496                 CTS_ERR("cts_query_prepare() Failed");
497                 ctsvc_end_trans(false);
498                 return CONTACTS_ERROR_DB;
499         }
500
501         if (ctsvc_record_check_property_flag((ctsvc_record_s *)record, _contacts_contact.ringtone_path, CTSVC_PROPERTY_FLAG_DIRTY)) {
502                 if (contact->ringtone_path)
503                         cts_stmt_bind_text(stmt, i, contact->ringtone_path);
504                 i++;
505         }
506         if (ctsvc_record_check_property_flag((ctsvc_record_s *)record, _contacts_contact.vibration, CTSVC_PROPERTY_FLAG_DIRTY)) {
507                 if (contact->vibration)
508                         cts_stmt_bind_text(stmt, i, contact->vibration);
509                 i++;
510         }
511         if (ctsvc_record_check_property_flag((ctsvc_record_s *)record, _contacts_contact.message_alert, CTSVC_PROPERTY_FLAG_DIRTY)) {
512                 if (contact->message_alert)
513                         cts_stmt_bind_text(stmt, i, contact->message_alert);
514                 i++;
515         }
516         if (ctsvc_record_check_property_flag((ctsvc_record_s *)record, _contacts_contact.image_thumbnail_path, CTSVC_PROPERTY_FLAG_DIRTY) &&
517                         (contact->id == thumbnail_contact_id || thumbnail_contact_id == -1)) {
518                 if (contact->image_thumbnail_path)
519                         cts_stmt_bind_text(stmt, i, contact->image_thumbnail_path);
520                 i++;
521         }
522
523         ret = cts_stmt_step(stmt);
524         if (CONTACTS_ERROR_NONE != ret) {
525                 CTS_ERR("cts_stmt_step() Failed(%d)", ret);
526                 cts_stmt_finalize(stmt);
527                 ctsvc_end_trans(false);
528                 return ret;
529         }
530         cts_stmt_finalize(stmt);
531
532         // update favorite
533         snprintf(query, sizeof(query),
534                         "SELECT is_favorite FROM "CTS_TABLE_CONTACTS" WHERE contact_id =%d ", contact->id);
535         ret = ctsvc_query_get_first_int_result(query, &is_favorite);
536         if (ret < CONTACTS_ERROR_NONE) {
537                 CTS_ERR("ctsvc_query_get_first_int_result() Failed(%d)", ret);
538                 ctsvc_end_trans(false);
539                 return ret;
540         }
541
542         snprintf(query, sizeof(query),
543                         "SELECT person_id FROM "CTS_TABLE_FAVORITES" WHERE person_id =%d ", contact->person_id);
544         ret = ctsvc_query_get_first_int_result(query, &person_id);
545         if (CONTACTS_ERROR_NO_DATA == ret && is_favorite) {
546                 ret = ctsvc_db_person_set_favorite(contact->person_id, true, false);
547                 if (CONTACTS_ERROR_NONE != ret) {
548                         CTS_ERR("ctsvc_db_person_set_favorite() Failed(%d)", ret);
549                         ctsvc_end_trans(false);
550                         return ret;
551                 }
552         }
553         else if (CONTACTS_ERROR_NONE == ret && !is_favorite) {
554                 snprintf(query, sizeof(query),
555                         "SELECT person_id FROM "CTS_TABLE_CONTACTS" WHERE person_id =%d AND is_favorite = 1", contact->person_id);
556                 ret = ctsvc_query_get_first_int_result(query, &person_id);
557                 if (CONTACTS_ERROR_NO_DATA == ret) {
558                         ret = ctsvc_db_person_set_favorite(contact->person_id, false, false);
559                         if (CONTACTS_ERROR_NONE != ret) {
560                                 CTS_ERR("ctsvc_db_person_set_favorite() Failed(%d)", ret);
561                                 ctsvc_end_trans(false);
562                                 return ret;
563                         }
564                 }
565                 else if (CONTACTS_ERROR_NONE != ret) {
566                         CTS_ERR("ctsvc_query_get_first_int_result() Failed(%d)", ret);
567                         ctsvc_end_trans(false);
568                         return ret;
569                 }
570         }
571         else if (ret < CONTACTS_ERROR_NONE && CONTACTS_ERROR_NO_DATA != ret) {
572                 CTS_ERR("ctsvc_query_get_first_int_result() Failed(%d)", ret);
573                 ctsvc_end_trans(false);
574                 return ret;
575         }
576
577         ctsvc_set_person_noti();
578
579 #ifdef _CONTACTS_IPC_SERVER
580         ctsvc_change_subject_add_changed_person_id(CONTACTS_CHANGE_UPDATED, contact->person_id);
581 #endif
582
583         ret = ctsvc_end_trans(true);
584         if (ret < CONTACTS_ERROR_NONE)
585         {
586                 CTS_ERR("DB error : ctsvc_end_trans() Failed(%d)", ret);
587                 return ret;
588         }
589         else
590                 return CONTACTS_ERROR_NONE;
591 }
592
593 void ctsvc_db_normalize_str_callback(sqlite3_context * context,
594                 int argc, sqlite3_value ** argv)
595 {
596         const char *display_name;
597         int display_name_language = CTSVC_LANG_OTHERS;
598
599         if (argc < 1) {
600                 sqlite3_result_null(context);
601                 return;
602         }
603
604         display_name_language = sqlite3_value_int(argv[1]);
605         if (display_name_language == CTSVC_SORT_OTHERS || display_name_language == CTSVC_SORT_NUMBER) {
606                 sqlite3_result_text(context, "#", 1, SQLITE_TRANSIENT);
607                 return;
608         }
609         else {
610                 display_name = (const char *)sqlite3_value_text(argv[0]);
611                 if (display_name) {
612                         int ret;
613                         char *dest = NULL;
614                         ret = ctsvc_normalize_index(display_name, &dest);
615                         if (ret < CONTACTS_ERROR_NONE) {
616                                 CTS_ERR("ctsvc_normalize_index() Failed(%d)", ret);
617                                 sqlite3_result_null(context);
618                                 return;
619                         }
620                         CTS_VERBOSE("normalize index : %s, %s", display_name, dest);
621                         sqlite3_result_text(context, dest, strlen(dest), SQLITE_TRANSIENT);
622                         free(dest);
623                         return;
624                 }
625         }
626
627         sqlite3_result_null(context);
628         return;
629 }
630