[SVACE Issue Fixes]
[platform/core/pim/contacts-service.git] / server / db / ctsvc_db_plugin_person.c
1 /*
2  * Contacts Service
3  *
4  * Copyright (c) 2010 - 2015 Samsung Electronics Co., Ltd. All rights reserved.
5  *
6  * Licensed under the Apache License, Version 2.0 (the "License");
7  * you may not use this file except in compliance with the License.
8  * You may obtain a copy of the License at
9  *
10  * http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing, software
13  * distributed under the License is distributed on an "AS IS" BASIS,
14  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  * See the License for the specific language governing permissions and
16  * limitations under the License.
17  *
18  */
19 #include "contacts.h"
20 #include "ctsvc_internal.h"
21 #include "ctsvc_db_schema.h"
22 #include "ctsvc_db_sqlite.h"
23 #include "ctsvc_db_plugin_person_helper.h"
24 #include "ctsvc_db_init.h"
25 #include "ctsvc_db_access_control.h"
26 #include "ctsvc_db_utils.h"
27 #include "ctsvc_list.h"
28 #include "ctsvc_db_query.h"
29 #include "ctsvc_record.h"
30 #include "ctsvc_normalize.h"
31 #include "ctsvc_notification.h"
32 #include "ctsvc_notify.h"
33
34 #ifdef _CONTACTS_IPC_SERVER
35 #include "ctsvc_server_change_subject.h"
36 #endif
37
38
39 static int __ctsvc_db_person_insert_record(contacts_record_h record, int *id)
40 {
41         /* LCOV_EXCL_START */
42         ERR("Can not insert person record directly");
43         return CONTACTS_ERROR_INVALID_PARAMETER;
44         /* LCOV_EXCL_STOP */
45 }
46
47 static int __ctsvc_db_person_get_record(int id, contacts_record_h *out_record)
48 {
49         int ret;
50         cts_stmt stmt = NULL;
51         char query[CTS_SQL_MAX_LEN] = {0};
52         contacts_record_h record;
53
54         *out_record = NULL;
55
56         snprintf(query, sizeof(query),
57                         "SELECT persons.person_id, "
58                         "%s, "
59                         "_NORMALIZE_INDEX_(%s), "
60                         "name_contact_id, "
61                         "persons.image_thumbnail_path, "
62                         "persons.ringtone_path, "
63                         "persons.vibration, "
64                         "persons.message_alert, "
65                         "status, "
66                         "link_count, "
67                         "addressbook_ids, "
68                         "persons.has_phonenumber, "
69                         "persons.has_email, "
70                         "EXISTS(SELECT person_id FROM "CTS_TABLE_FAVORITES" WHERE person_id=persons.person_id) is_favorite, "
71                         "(SELECT favorite_prio FROM "CTS_TABLE_FAVORITES" WHERE person_id=persons.person_id) favorite_prio "
72                         "FROM "CTS_TABLE_PERSONS" "
73                         "LEFT JOIN "CTS_TABLE_CONTACTS" "
74                         "ON (name_contact_id = contacts.contact_id AND contacts.deleted = 0) "
75                         "WHERE persons.person_id = %d",
76                         ctsvc_get_display_column(), ctsvc_get_sort_name_column(), id);
77
78         ret = ctsvc_query_prepare(query, &stmt);
79         RETVM_IF(NULL == stmt, ret, "ctsvc_query_prepare() Fail(%d)", ret);
80
81         ret = ctsvc_stmt_step(stmt);
82         if (1 /*CTS_TRUE*/ != ret) {
83                 /* LCOV_EXCL_START */
84                 ERR("ctsvc_stmt_step() Fail(%d)", ret);
85                 ctsvc_stmt_finalize(stmt);
86                 if (CONTACTS_ERROR_NONE == ret)
87                         return CONTACTS_ERROR_NO_DATA;
88                 else
89                         return ret;
90                 /* LCOV_EXCL_STOP */
91         }
92         ret = ctsvc_db_person_create_record_from_stmt(stmt, &record);
93         ctsvc_stmt_finalize(stmt);
94
95         if (CONTACTS_ERROR_NONE != ret) {
96                 /* LCOV_EXCL_START */
97                 ERR("ctsvc_db_person_create_record_from_stmt() Fail(%d)", ret);
98                 return ret;
99                 /* LCOV_EXCL_STOP */
100         }
101
102         *out_record = record;
103         return CONTACTS_ERROR_NONE;
104 }
105
106 static int __ctsvc_db_person_update_record(contacts_record_h record)
107 {
108         int ret, i, len;
109         int person_id;
110         cts_stmt stmt = NULL;
111         char *set = NULL;
112         GSList *bind_text = NULL;
113         GSList *cursor = NULL;
114         char contact_query[CTS_SQL_MIN_LEN] = {0};
115         char query[CTS_SQL_MIN_LEN] = {0};
116         ctsvc_person_s *person = (ctsvc_person_s*)record;
117         const char *display_name = NULL;
118         int index_favorite = 0;
119
120         RETV_IF(NULL == person, CONTACTS_ERROR_INVALID_PARAMETER);
121         RETV_IF(person->person_id <= 0, CONTACTS_ERROR_INVALID_PARAMETER);
122
123         ret = ctsvc_begin_trans();
124         RETVM_IF(ret, ret, "ctsvc_begin_trans() Fail(%d)", ret);
125
126         snprintf(query, sizeof(query),
127                         "SELECT person_id FROM "CTS_TABLE_PERSONS" WHERE person_id = %d", person->person_id);
128         ret = ctsvc_query_get_first_int_result(query, &person_id);
129         if (ret != CONTACTS_ERROR_NONE) {
130                 /* LCOV_EXCL_START */
131                 ERR("ctsvc_query_get_first_int_result() Fail(%d)", ret);
132                 ctsvc_end_trans(false);
133                 return ret;
134                 /* LCOV_EXCL_STOP */
135         }
136
137         if (ctsvc_record_check_property_flag((ctsvc_record_s*)person, _contacts_person.display_contact_id, CTSVC_PROPERTY_FLAG_DIRTY)) {
138                 /* check name_contact_id validation */
139                 char *temp;
140                 char check_query[CTS_SQL_MIN_LEN] = {0};
141                 snprintf(check_query, sizeof(check_query), "SELECT contact_id, %s FROM "CTS_TABLE_CONTACTS
142                                 " WHERE person_id = %d AND contact_id = %d AND deleted = 0",
143                                 ctsvc_get_display_column(), person->person_id, person->name_contact_id);
144                 ret = ctsvc_query_prepare(check_query, &stmt);
145                 if (NULL == stmt) {
146                         /* LCOV_EXCL_START */
147                         ERR("ctsvc_query_prepare() Fail(%d)", ret);
148                         ctsvc_end_trans(false);
149                         return ret;
150                         /* LCOV_EXCL_STOP */
151                 }
152
153                 ret = ctsvc_stmt_step(stmt);
154                 if (1 != ret) {
155                         if (CONTACTS_ERROR_NONE == ret) {
156                                 /* LCOV_EXCL_START */
157                                 ERR("the name_contact_id(%d) is not linked with person_id(%d)",
158                                                 person->name_contact_id, person->person_id);
159                                 ctsvc_stmt_finalize(stmt);
160                                 ctsvc_end_trans(false);
161                                 return CONTACTS_ERROR_INVALID_PARAMETER;
162                                 /* LCOV_EXCL_STOP */
163                         } else {
164                                 /* LCOV_EXCL_START */
165                                 ERR("ctsvc_stmt_step() Fail(%d)", ret);
166                                 ctsvc_stmt_finalize(stmt);
167                                 ctsvc_end_trans(false);
168                                 return ret;
169                                 /* LCOV_EXCL_STOP */
170                         }
171                 }
172                 temp = ctsvc_stmt_get_text(stmt, 0);
173                 display_name = SAFE_STRDUP(temp);
174
175                 ctsvc_stmt_finalize(stmt);
176         }
177
178         /* update favorite */
179         index_favorite = CTSVC_PROPERTY_PERSON_IS_FAVORITE & 0x000000FF;
180         if (person->base.properties_flags &&
181                         ctsvc_record_check_property_flag((ctsvc_record_s*)person, index_favorite, CTSVC_PROPERTY_FLAG_DIRTY)) {
182                 ret = ctsvc_db_person_set_favorite(person->person_id, person->is_favorite, true);
183                 if (CONTACTS_ERROR_NONE != ret) {
184                         /* LCOV_EXCL_START */
185                         ERR("ctsvc_db_person_set_favorite() Fail(%d)", ret);
186                         ctsvc_end_trans(false);
187                         return ret;
188                         /* LCOV_EXCL_STOP */
189                 }
190                 person->base.properties_flags[index_favorite] &= 0xFFFFFFFD; /* remove dirty bit */
191                 ctsvc_set_contact_noti();
192         }
193
194         do {
195                 int ret = CONTACTS_ERROR_NONE;
196                 char query[CTS_SQL_MAX_LEN] = {0};
197                 char query_set[CTS_SQL_MIN_LEN] = {0, };
198                 GSList *cursor = NULL;
199
200                 if (CONTACTS_ERROR_NONE != (ret = ctsvc_db_create_set_query(record, &set, &bind_text))) break;
201                 if (NULL == set || '\0' == *set)
202                         break;
203                 len = snprintf(query_set, sizeof(query_set), "%s, changed_ver=%d", set, ctsvc_get_next_ver());
204
205                 snprintf(query, sizeof(query), "UPDATE %s SET %s WHERE person_id = %d", CTS_TABLE_PERSONS, query_set, person->person_id);
206
207                 ret = ctsvc_query_prepare(query, &stmt);
208                 if (NULL == stmt) {
209                         /* LCOV_EXCL_START */
210                         ERR("ctsvc_query_prepare() Fail(%d)", ret);
211                         break;
212                         /* LCOV_EXCL_STOP */
213                 }
214
215                 if (bind_text) {
216                         int i = 0;
217                         for (cursor = bind_text, i = 1; cursor; cursor = cursor->next, i++) {
218                                 const char *text = cursor->data;
219                                 if (text && *text)
220                                         ctsvc_stmt_bind_text(stmt, i, text);
221                         }
222                 }
223                 ret = ctsvc_stmt_step(stmt);
224                 if (CONTACTS_ERROR_NONE != ret) {
225                         /* LCOV_EXCL_START */
226                         ERR("ctsvc_stmt_step() Fail(%d)", ret);
227                         ctsvc_stmt_finalize(stmt);
228                         break;
229                         /* LCOV_EXCL_STOP */
230                 }
231                 ctsvc_stmt_finalize(stmt);
232         } while (0);
233
234         if (CONTACTS_ERROR_NONE != ret) {
235                 ctsvc_end_trans(false);
236                 CTSVC_RECORD_RESET_PROPERTY_FLAGS((ctsvc_record_s*)record);
237                 free(set);
238
239                 if (bind_text) {
240                         for (cursor = bind_text; cursor; cursor = cursor->next) {
241                                 free(cursor->data);
242                                 cursor->data = NULL;
243                         }
244                         g_slist_free(bind_text);
245                 }
246                 return ret;
247         }
248
249         len = snprintf(contact_query, sizeof(contact_query), "UPDATE "CTS_TABLE_CONTACTS" SET changed_ver=%d ", ctsvc_get_next_ver());
250         if (ctsvc_record_check_property_flag((ctsvc_record_s*)person, _contacts_person.ringtone_path, CTSVC_PROPERTY_FLAG_DIRTY))
251                 len += snprintf(contact_query + len, sizeof(contact_query) - len, ", ringtone_path=? ");
252         if (ctsvc_record_check_property_flag((ctsvc_record_s*)person, _contacts_person.vibration, CTSVC_PROPERTY_FLAG_DIRTY))
253                 len += snprintf(contact_query + len, sizeof(contact_query) - len, ", vibration=? ");
254         if (ctsvc_record_check_property_flag((ctsvc_record_s*)person, _contacts_person.message_alert, CTSVC_PROPERTY_FLAG_DIRTY))
255                 len += snprintf(contact_query + len, sizeof(contact_query) - len, ", message_alert=? ");
256         snprintf(contact_query+len, sizeof(contact_query)-len, " WHERE person_id=%d AND deleted = 0", person->person_id);
257
258         ret = ctsvc_query_prepare(contact_query, &stmt);
259         if (NULL == stmt) {
260                 /* LCOV_EXCL_START */
261                 ERR("ctsvc_query_prepare() Fail(%d)", ret);
262                 ctsvc_end_trans(false);
263                 CTSVC_RECORD_RESET_PROPERTY_FLAGS((ctsvc_record_s*)record);
264                 free(set);
265
266                 if (bind_text) {
267                         for (cursor = bind_text; cursor; cursor = cursor->next) {
268                                 free(cursor->data);
269                                 cursor->data = NULL;
270                         }
271                         g_slist_free(bind_text);
272                 }
273                 return ret;
274                 /* LCOV_EXCL_STOP */
275         }
276
277         i = 1;
278         if (ctsvc_record_check_property_flag((ctsvc_record_s*)person, _contacts_person.ringtone_path, CTSVC_PROPERTY_FLAG_DIRTY)) {
279                 if (person->ringtone_path)
280                         ctsvc_stmt_bind_text(stmt, i, person->ringtone_path);
281                 i++;
282         }
283         if (ctsvc_record_check_property_flag((ctsvc_record_s*)person, _contacts_person.vibration, CTSVC_PROPERTY_FLAG_DIRTY)) {
284                 if (person->vibration)
285                         ctsvc_stmt_bind_text(stmt, i, person->vibration);
286                 i++;
287         }
288         if (ctsvc_record_check_property_flag((ctsvc_record_s*)person, _contacts_person.message_alert, CTSVC_PROPERTY_FLAG_DIRTY)) {
289                 if (person->message_alert)
290                         ctsvc_stmt_bind_text(stmt, i, person->message_alert);
291                 i++;
292         }
293
294         ret = ctsvc_stmt_step(stmt);
295         if (CONTACTS_ERROR_NONE != ret) {
296                 /* LCOV_EXCL_START */
297                 ERR("ctsvc_stmt_step() Fail(%d)", ret);
298                 ctsvc_stmt_finalize(stmt);
299                 ctsvc_end_trans(false);
300                 CTSVC_RECORD_RESET_PROPERTY_FLAGS((ctsvc_record_s*)record);
301                 free(set);
302
303                 if (bind_text) {
304                         for (cursor = bind_text; cursor; cursor = cursor->next) {
305                                 free(cursor->data);
306                                 cursor->data = NULL;
307                         }
308                         g_slist_free(bind_text);
309                 }
310                 return ret;
311                 /* LCOV_EXCL_STOP */
312         }
313         ctsvc_stmt_finalize(stmt);
314
315         CTSVC_RECORD_RESET_PROPERTY_FLAGS((ctsvc_record_s*)record);
316         free(set);
317
318         if (bind_text) {
319                 for (cursor = bind_text; cursor; cursor = cursor->next) {
320                         free(cursor->data);
321                         cursor->data = NULL;
322                 }
323                 g_slist_free(bind_text);
324         }
325
326         /* update person display_name */
327         if (display_name) {
328                 char *temp = NULL;
329                 person->display_name = SAFE_STRDUP(display_name);
330                 ret = ctsvc_normalize_index(person->display_name, &temp);
331                 if (0 <= ret)
332                         person->display_name_index = strdup(temp);
333
334                 free(temp);
335                 /* TODO : update name primary_default?? */
336         }
337         ctsvc_set_person_noti();
338 #ifdef _CONTACTS_IPC_SERVER
339         ctsvc_change_subject_add_changed_person_id(CONTACTS_CHANGE_UPDATED, person->person_id);
340 #endif
341
342         ret = ctsvc_end_trans(true);
343         RETVM_IF(ret < CONTACTS_ERROR_NONE, ret, "ctsvc_end_trans() Fail(%d)", ret);
344
345         return CONTACTS_ERROR_NONE;
346 }
347
348 static int __ctsvc_db_person_delete_record(int id)
349 {
350         int ret, rel_changed;
351         int person_id;
352         char query[CTS_SQL_MAX_LEN] = {0};
353         int version;
354         int *addressbook_ids = NULL;
355         int count;
356
357         ret = ctsvc_begin_trans();
358         RETVM_IF(ret, ret, "ctsvc_begin_trans() Fail(%d)", ret);
359
360         snprintf(query, sizeof(query),
361                         "SELECT person_id FROM "CTS_TABLE_PERSONS" WHERE person_id = %d", id);
362         ret = ctsvc_query_get_first_int_result(query, &person_id);
363         if (ret != CONTACTS_ERROR_NONE) {
364                 /* LCOV_EXCL_START */
365                 ERR("ctsvc_query_get_first_int_result() Fail(%d)", ret);
366                 ctsvc_end_trans(false);
367                 return ret;
368                 /* LCOV_EXCL_STOP */
369         }
370
371         version = ctsvc_get_next_ver();
372         snprintf(query, sizeof(query),
373                         "UPDATE "CTS_TABLE_GROUPS" SET member_changed_ver=%d "
374                         "WHERE group_id IN (SELECT distinct group_id "
375                         "FROM "CTS_TABLE_CONTACTS" C, "CTS_TABLE_GROUP_RELATIONS" R "
376                         "ON C.contact_id=R.contact_id AND R.deleted = 0 AND C.deleted = 0 "
377                         "WHERE person_id = %d)",
378                         version, id);
379         ret = ctsvc_query_exec(query);
380         if (CONTACTS_ERROR_NONE != ret) {
381                 /* LCOV_EXCL_START */
382                 ERR("ctsvc_query_exec() Fail(%d)", ret);
383                 ctsvc_end_trans(false);
384                 return ret;
385                 /* LCOV_EXCL_STOP */
386         }
387
388         rel_changed = ctsvc_db_change();
389
390         ret = ctsvc_get_write_permitted_addressbook_ids(&addressbook_ids, &count);
391         if (CONTACTS_ERROR_INTERNAL == ret) {
392                 /* LCOV_EXCL_START */
393                 ERR("ctsvc_get_write_permitted_addressbook_ids() Fail(%d)", ret);
394                 ctsvc_end_trans(false);
395                 return ret;
396                 /* LCOV_EXCL_STOP */
397         }
398
399         if (addressbook_ids && 0 < count) {
400                 int i;
401                 int len = snprintf(query, sizeof(query),
402                                 "UPDATE "CTS_TABLE_CONTACTS" SET deleted = 1, person_id = 0, changed_ver = %d "
403                                 "WHERE person_id = %d AND (",
404                                 version, id);
405
406                 for (i = 0; i < count; i++) {
407                         if (i == 0)
408                                 len += snprintf(query+len, sizeof(query) + len, "addressbook_id = %d ", addressbook_ids[i]);
409                         else
410                                 len += snprintf(query+len, sizeof(query) + len, "OR addressbook_id = %d ", addressbook_ids[i]);
411                 }
412                 len += snprintf(query+len, sizeof(query)-len, ") ");
413
414                 ret = ctsvc_query_exec(query);
415                 if (CONTACTS_ERROR_NONE != ret) {
416                         /* LCOV_EXCL_START */
417                         ERR("ctsvc_query_exec() Fail(%d)", ret);
418                         ctsvc_end_trans(false);
419                         free(addressbook_ids);
420                         return ret;
421                         /* LCOV_EXCL_STOP */
422                 }
423         }
424         free(addressbook_ids);
425
426         /* access control logic should be enabled */
427         snprintf(query, sizeof(query),
428                         "UPDATE "CTS_TABLE_CONTACTS" SET person_id = 0, changed_ver = %d WHERE person_id = %d",
429                         version, id);
430         ret = ctsvc_query_exec(query);
431         if (CONTACTS_ERROR_NONE != ret) {
432                 /* LCOV_EXCL_START */
433                 ERR("ctsvc_query_exec() Fail(%d)", ret);
434                 ctsvc_end_trans(false);
435                 return ret;
436                 /* LCOV_EXCL_STOP */
437         }
438
439         /*
440          * images are deleted by db trigger callback function
441          * in ctsvc_db_image_delete_callback
442          */
443         snprintf(query, sizeof(query), "DELETE FROM "CTS_TABLE_PERSONS" WHERE person_id = %d", id);
444         ret = ctsvc_query_exec(query);
445         if (CONTACTS_ERROR_NONE != ret) {
446                 /* LCOV_EXCL_START */
447                 ERR("ctsvc_query_exec() Fail(%d)", ret);
448                 ctsvc_end_trans(false);
449                 return ret;
450                 /* LCOV_EXCL_STOP */
451         }
452
453         ctsvc_set_contact_noti();
454         ctsvc_set_person_noti();
455         if (0 < rel_changed)
456                 ctsvc_set_group_rel_noti();
457
458         ret = ctsvc_end_trans(true);
459         if (ret < CONTACTS_ERROR_NONE) {
460                 /* LCOV_EXCL_START */
461                 ERR("ctsvc_end_trans() Fail(%d)", ret);
462                 return ret;
463                 /* LCOV_EXCL_STOP */
464         } else {
465                 return CONTACTS_ERROR_NONE;
466         }
467 }
468
469 static int __ctsvc_db_person_get_all_records(int offset, int limit, contacts_list_h *out_list)
470 {
471         int ret;
472         int len;
473         cts_stmt stmt;
474         char query[CTS_SQL_MAX_LEN] = {0};
475         contacts_list_h list;
476
477         len = snprintf(query, sizeof(query),
478                         "SELECT person_id, "
479                         "%s, "
480                         "_NORMALIZE_INDEX_(%s), "
481                         "name_contact_id, "
482                         "image_thumbnail_path, "
483                         "ringtone_path, "
484                         "vibration, "
485                         "message_alert, "
486                         "status, "
487                         "link_count, "
488                         "addressbook_ids, "
489                         "has_phonenumber, "
490                         "has_email, "
491                         "is_favorite, "
492                         "favorite_prio "
493                         "FROM "CTSVC_DB_VIEW_PERSON,
494                         ctsvc_get_display_column(), ctsvc_get_sort_name_column());
495
496         len += snprintf(query+len, sizeof(query)-len, " ORDER BY %s", ctsvc_get_sort_column());
497
498         if (0 != limit) {
499                 len += snprintf(query+len, sizeof(query)-len, " LIMIT %d", limit);
500                 if (0 < offset)
501                         len += snprintf(query+len, sizeof(query)-len, " OFFSET %d", offset);
502         }
503
504         ret = ctsvc_query_prepare(query, &stmt);
505         RETVM_IF(NULL == stmt, ret, "ctsvc_query_prepare() Fail(%d)", ret);
506
507         contacts_list_create(&list);
508         while ((ret = ctsvc_stmt_step(stmt))) {
509                 contacts_record_h record;
510                 if (1 != ret) {
511                         /* LCOV_EXCL_START */
512                         ERR("ctsvc_stmt_step() Fail(%d)", ret);
513                         ctsvc_stmt_finalize(stmt);
514                         contacts_list_destroy(list, true);
515                         return ret;
516                         /* LCOV_EXCL_STOP */
517                 }
518                 ret = ctsvc_db_person_create_record_from_stmt(stmt, &record);
519                 if (CONTACTS_ERROR_NONE != ret) {
520                         /* LCOV_EXCL_START */
521                         ERR("ctsvc_db_person_create_record_from_stmt() Fail(%d)", ret);
522                         ctsvc_stmt_finalize(stmt);
523                         contacts_list_destroy(list, true);
524                         return ret;
525                         /* LCOV_EXCL_STOP */
526                 }
527
528                 ctsvc_list_prepend(list, record);
529         }
530         ctsvc_stmt_finalize(stmt);
531         ctsvc_list_reverse(list);
532
533         *out_list = list;
534         return CONTACTS_ERROR_NONE;
535 }
536
537 static int __ctsvc_db_person_get_records_with_query(contacts_query_h query, int offset, int limit, contacts_list_h *out_list)
538 {
539         int ret;
540         int i;
541         int field_count;
542         ctsvc_query_s *s_query;
543         cts_stmt stmt;
544         contacts_list_h list;
545         ctsvc_person_s *person;
546         char full_path[CTSVC_IMG_FULL_PATH_SIZE_MAX] = {0};
547
548         RETV_IF(NULL == query, CONTACTS_ERROR_INVALID_PARAMETER);
549         s_query = (ctsvc_query_s*)query;
550
551         ret = ctsvc_db_make_get_records_query_stmt(s_query, offset, limit, &stmt);
552         RETVM_IF(CONTACTS_ERROR_NONE != ret, ret, "ctsvc_db_make_get_records_query_stmt fail(%d)", ret);
553
554         contacts_list_create(&list);
555         while ((ret = ctsvc_stmt_step(stmt))) {
556                 contacts_record_h record;
557                 if (1 != ret) {
558                         /* LCOV_EXCL_START */
559                         ERR("ctsvc_stmt_step() Fail(%d)", ret);
560                         ctsvc_stmt_finalize(stmt);
561                         contacts_list_destroy(list, true);
562                         return ret;
563                         /* LCOV_EXCL_STOP */
564                 }
565
566                 contacts_record_create(_contacts_person._uri, &record);
567                 person = (ctsvc_person_s*)record;
568                 if (0 == s_query->projection_count) {
569                         field_count = s_query->property_count;
570                 } else {
571                         field_count = s_query->projection_count;
572
573                         int err = ctsvc_record_set_projection_flags(record, s_query->projection,
574                                         s_query->projection_count, s_query->property_count);
575                         if (CONTACTS_ERROR_NONE != err)
576                                 ASSERT_NOT_REACHED("To set projection is Fail.\n");
577                 }
578
579                 for (i = 0; i < field_count; i++) {
580                         char *temp;
581                         int property_id;
582                         if (0 == s_query->projection_count)
583                                 property_id = s_query->properties[i].property_id;
584                         else
585                                 property_id = s_query->projection[i];
586
587                         switch (property_id) {
588                         case CTSVC_PROPERTY_PERSON_ID:
589                                 person->person_id = ctsvc_stmt_get_int(stmt, i);
590                                 break;
591                         case CTSVC_PROPERTY_PERSON_DISPLAY_NAME:
592                                 temp = ctsvc_stmt_get_text(stmt, i);
593                                 free(person->display_name);
594                                 person->display_name = SAFE_STRDUP(temp);
595                                 break;
596                         case CTSVC_PROPERTY_PERSON_DISPLAY_NAME_INDEX:
597                                 temp = ctsvc_stmt_get_text(stmt, i);
598                                 free(person->display_name_index);
599                                 person->display_name_index = SAFE_STRDUP(temp);
600                                 break;
601                         case CTSVC_PROPERTY_PERSON_DISPLAY_CONTACT_ID:
602                                 person->name_contact_id = ctsvc_stmt_get_int(stmt, i);
603                                 break;
604                         case CTSVC_PROPERTY_PERSON_RINGTONE:
605                                 temp = ctsvc_stmt_get_text(stmt, i);
606                                 free(person->ringtone_path);
607                                 person->ringtone_path = SAFE_STRDUP(temp);
608                                 break;
609                         case CTSVC_PROPERTY_PERSON_IMAGE_THUMBNAIL:
610                                 temp = ctsvc_stmt_get_text(stmt, i);
611                                 if (temp && *temp) {
612                                         snprintf(full_path, sizeof(full_path), "%s/%s", CTSVC_CONTACT_IMG_FULL_LOCATION, temp);
613                                         free(person->image_thumbnail_path);
614                                         person->image_thumbnail_path = strdup(full_path);
615                                 }
616                                 break;
617                         case CTSVC_PROPERTY_PERSON_IS_FAVORITE:
618                                 person->is_favorite = ctsvc_stmt_get_int(stmt, i);
619                                 break;
620                         case CTSVC_PROPERTY_PERSON_HAS_PHONENUMBER:
621                                 person->has_phonenumber = ctsvc_stmt_get_int(stmt, i);
622                                 break;
623                         case CTSVC_PROPERTY_PERSON_HAS_EMAIL:
624                                 person->has_email = ctsvc_stmt_get_int(stmt, i);
625                                 break;
626                         case CTSVC_PROPERTY_PERSON_LINK_COUNT:
627                                 person->link_count = ctsvc_stmt_get_int(stmt, i);
628                                 break;
629                         case CTSVC_PROPERTY_PERSON_ADDRESSBOOK_IDS:
630                                 temp = ctsvc_stmt_get_text(stmt, i);
631                                 free(person->addressbook_ids);
632                                 person->addressbook_ids = SAFE_STRDUP(temp);
633                                 break;
634                         case CTSVC_PROPERTY_PERSON_VIBRATION:
635                                 temp = ctsvc_stmt_get_text(stmt, i);
636                                 free(person->vibration);
637                                 person->vibration = SAFE_STRDUP(temp);
638                                 break;
639                         case CTSVC_PROPERTY_PERSON_STATUS:
640                                 temp = ctsvc_stmt_get_text(stmt, i);
641                                 free(person->status);
642                                 person->status = SAFE_STRDUP(temp);
643                                 break;
644                         case CTSVC_PROPERTY_PERSON_MESSAGE_ALERT:
645                                 temp = ctsvc_stmt_get_text(stmt, i);
646                                 free(person->message_alert);
647                                 person->message_alert = SAFE_STRDUP(temp);
648                                 break;
649                         case CTSVC_PROPERTY_PERSON_FAVORITE_PRIORITY:
650                                 person->favorite_prio = ctsvc_stmt_get_dbl(stmt, i);
651                                 break;
652                         default:
653                                 break;
654                         }
655                 }
656                 ctsvc_list_prepend(list, record);
657         }
658         ctsvc_stmt_finalize(stmt);
659         ctsvc_list_reverse(list);
660
661         *out_list = list;
662
663         return CONTACTS_ERROR_NONE;
664 }
665
666 ctsvc_db_plugin_info_s ctsvc_db_plugin_person = {
667         .is_query_only = false,
668         .insert_record = __ctsvc_db_person_insert_record,
669         .get_record = __ctsvc_db_person_get_record,
670         .update_record = __ctsvc_db_person_update_record,
671         .delete_record = __ctsvc_db_person_delete_record,
672         .get_all_records = __ctsvc_db_person_get_all_records,
673         .get_records_with_query = __ctsvc_db_person_get_records_with_query,
674         .insert_records = NULL,
675         .update_records = NULL,
676         .delete_records = NULL,
677         .get_count = NULL,
678         .get_count_with_query = NULL,
679         .replace_record = NULL,
680         .replace_records = NULL,
681 };
682