diff options
Diffstat (limited to 'native/ctsvc_db_plugin_person.c')
-rw-r--r-- | native/ctsvc_db_plugin_person.c | 609 |
1 files changed, 609 insertions, 0 deletions
diff --git a/native/ctsvc_db_plugin_person.c b/native/ctsvc_db_plugin_person.c new file mode 100644 index 0000000..b7e4eee --- /dev/null +++ b/native/ctsvc_db_plugin_person.c @@ -0,0 +1,609 @@ +/* + * Contacts Service + * + * Copyright (c) 2010 - 2012 Samsung Electronics Co., Ltd. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include "contacts.h" +#include "ctsvc_internal.h" +#include "ctsvc_schema.h" +#include "ctsvc_sqlite.h" +#include "ctsvc_db_plugin_person_helper.h" +#include "ctsvc_db_init.h" +#include "ctsvc_utils.h" +#include "ctsvc_list.h" +#include "ctsvc_db_query.h" +#include "ctsvc_record.h" +#include "ctsvc_normalize.h" +#include "ctsvc_notification.h" + +#ifdef _CONTACTS_IPC_SERVER +#include "ctsvc_server_change_subject.h" +#endif + +static int __ctsvc_db_person_insert_record( contacts_record_h record, int *id ); +static int __ctsvc_db_person_get_record( int id, contacts_record_h* out_record ); +static int __ctsvc_db_person_update_record( contacts_record_h record ); +static int __ctsvc_db_person_delete_record( int id ); +static int __ctsvc_db_person_get_all_records( int offset, int limit, contacts_list_h* out_list ); +static int __ctsvc_db_person_get_records_with_query( contacts_query_h query, int offset, int limit, contacts_list_h* out_list ); +//static int __ctsvc_db_person_insert_records(const contacts_list_h in_list, int **ids); +//static int __ctsvc_db_person_update_records(const contacts_list_h in_list); +//static int __ctsvc_db_person_delete_records(int ids[], int count); + +ctsvc_db_plugin_info_s ctsvc_db_plugin_person = { + .is_query_only = false, + .insert_record = __ctsvc_db_person_insert_record, + .get_record = __ctsvc_db_person_get_record, + .update_record = __ctsvc_db_person_update_record, + .delete_record = __ctsvc_db_person_delete_record, + .get_all_records = __ctsvc_db_person_get_all_records, + .get_records_with_query = __ctsvc_db_person_get_records_with_query, + .insert_records = NULL,//__ctsvc_db_person_insert_records, + .update_records = NULL,//__ctsvc_db_person_update_records, + .delete_records = NULL,//__ctsvc_db_person_delete_records + .get_count = NULL, + .get_count_with_query = NULL, + .replace_record = NULL, + .replace_records = NULL, +}; + +static int __ctsvc_db_person_insert_record( contacts_record_h record, int *id ) +{ + CTS_ERR("Can not insert person record directly"); + return CONTACTS_ERROR_INVALID_PARAMETER; +} + +static int __ctsvc_db_person_get_record( int id, contacts_record_h* out_record ) +{ + int ret; + cts_stmt stmt = NULL; + char query[CTS_SQL_MAX_LEN] = {0}; + contacts_record_h record; + + *out_record = NULL; + snprintf(query, sizeof(query), + "SELECT persons.person_id, " + "%s, " + "_NORMALIZE_INDEX_(%s), " + "name_contact_id, " + "persons.image_thumbnail_path, " + "persons.ringtone_path, " + "persons.vibration, " + "status, " + "link_count, " + "account_id1, " + "account_id2, " + "account_id3, " + "addressbook_ids, " + "persons.has_phonenumber, " + "persons.has_email, " + "EXISTS(SELECT person_id FROM "CTS_TABLE_FAVORITES" WHERE person_id=persons.person_id) is_favorite " + "FROM "CTS_TABLE_PERSONS" " + "LEFT JOIN "CTS_TABLE_CONTACTS" " + "ON (name_contact_id = contacts.contact_id AND contacts.deleted = 0) " + "WHERE persons.person_id = %d", + ctsvc_get_display_column(), ctsvc_get_display_column(), id); + + stmt = cts_query_prepare(query); + RETVM_IF(NULL == stmt, CONTACTS_ERROR_DB, "DB error : cts_query_prepare() Failed"); + + ret = cts_stmt_step(stmt); + if( 1 /*CTS_TRUE*/ != ret) { + CTS_ERR("cts_stmt_step() Failed(%d)", ret); + cts_stmt_finalize(stmt); + return CONTACTS_ERROR_NO_DATA; + } + ret = ctsvc_db_person_create_record_from_stmt(stmt, &record); + cts_stmt_finalize(stmt); + + if(CONTACTS_ERROR_NONE != ret) { + CTS_ERR("ctsvc_db_person_create_record_from_stmt() Failed(%d)", ret); + return ret; + } + + *out_record = record; + return CONTACTS_ERROR_NONE; +} + +static inline int __ctsvc_db_person_set_favorite(int person_id, bool set) +{ + int ret; + double prio = 0.0; + cts_stmt stmt = NULL; + char query[CTS_SQL_MIN_LEN] = {0}; + + if (set) { + snprintf(query, sizeof(query), + "SELECT MAX(favorite_prio) FROM "CTS_TABLE_FAVORITES); + + stmt = cts_query_prepare(query); + RETVM_IF(NULL == stmt, CONTACTS_ERROR_DB, "cts_query_prepare() Failed"); + + ret = cts_stmt_step(stmt); + if (1 /*CTS_TRUE*/ == ret) { + prio = ctsvc_stmt_get_dbl(stmt, 0); + } + else if (CONTACTS_ERROR_NONE != ret) { + CTS_ERR("cts_stmt_step() Failed(%d)", ret); + cts_stmt_finalize(stmt); + return ret; + } + cts_stmt_finalize(stmt); + + prio = prio + 1.0; + snprintf(query, sizeof(query), + "INSERT OR REPLACE INTO "CTS_TABLE_FAVORITES" values(%d, %f)", person_id, prio); + } + else { + snprintf(query, sizeof(query), + "DELETE FROM "CTS_TABLE_FAVORITES" WHERE person_id = %d", person_id); + } + + ret = ctsvc_query_exec(query); + if (CONTACTS_ERROR_NONE != ret) { + CTS_ERR("cts_query_exec() Failed(%d)", ret); + return ret; + } + + ret = cts_db_change(); + if (0 < ret) + ctsvc_set_favor_noti(); + + snprintf(query, sizeof(query), + "UPDATE "CTS_TABLE_CONTACTS" SET is_favorite = %d " + "WHERE person_id=%d AND deleted = 0", set?1:0, person_id); + ret = ctsvc_query_exec(query); + if (CONTACTS_ERROR_NONE != ret) { + CTS_ERR("cts_query_exec() Failed(%d)", ret); + return ret; + } + + return CONTACTS_ERROR_NONE; +} + +static int __ctsvc_db_person_update_record( contacts_record_h record ) +{ + int ret, i, len, len2; + cts_stmt stmt = NULL; + char query[CTS_SQL_MIN_LEN] = {0}; + char contact_query[CTS_SQL_MIN_LEN] = {0}; + ctsvc_person_s *person = (ctsvc_person_s *)record; + const char *display_name = NULL; + + RETV_IF(NULL == person, CONTACTS_ERROR_INVALID_PARAMETER); + RETV_IF(person->person_id <= 0, CONTACTS_ERROR_INVALID_PARAMETER); + + ret = ctsvc_begin_trans(); + RETVM_IF(ret, ret, "ctsvc_begin_trans() Failed(%d)", ret); + + len = snprintf(query, sizeof(query), + "UPDATE "CTS_TABLE_PERSONS" SET changed_ver=%d ", ctsvc_get_next_ver()); + + len2 = snprintf(contact_query, sizeof(contact_query), + "UPDATE "CTS_TABLE_CONTACTS" SET changed_ver=%d ", ctsvc_get_next_ver()); + + if (person->name_contact_id_changed) { + // check name_contact_id validation + char *temp; + char check_query[CTS_SQL_MIN_LEN] = {0}; + snprintf(check_query, sizeof(check_query), "SELECT contact_id, %s FROM "CTS_TABLE_CONTACTS + " WHERE person_id = %d AND contact_id = %d AND deleted = 0", + ctsvc_get_display_column(), person->person_id, person->name_contact_id); + stmt = cts_query_prepare(check_query); + if (NULL == stmt) { + CTS_ERR("cts_query_prepare() Failed"); + ctsvc_end_trans(false); + return CONTACTS_ERROR_DB; + } + + ret = cts_stmt_step(stmt); + if ( 1 != ret) { + if ( CONTACTS_ERROR_NONE == ret) { + CTS_ERR("Invalid paramter : the name_contact_id(%d) is not linked with person_id(%d)", + person->name_contact_id, person->person_id); + cts_stmt_finalize(stmt); + ctsvc_end_trans(false); + return CONTACTS_ERROR_INVALID_PARAMETER; + } + else { + CTS_ERR("cts_stmt_step() Failed(%d)", ret); + cts_stmt_finalize(stmt); + ctsvc_end_trans(false); + return ret; + } + } + temp = ctsvc_stmt_get_text(stmt, 0); + display_name = SAFE_STRDUP(temp); + + len += snprintf(query + len, sizeof(query) - len, ", name_contact_id = %d ", person->name_contact_id); + + cts_stmt_finalize(stmt); + } + if (person->image_thumbnail_changed) + len += snprintf(query + len, sizeof(query) - len, ", image_thumbnail_path=? "); + if (person->ringtone_changed) { + len += snprintf(query + len, sizeof(query) - len, ", ringtone_path=? "); + len2 += snprintf(contact_query + len2, sizeof(contact_query) - len2, ", ringtone_path=? "); + } + if (person->vibration_changed) { + len += snprintf(query + len, sizeof(query) - len, ", vibration=? "); + len2 += snprintf(contact_query + len2, sizeof(contact_query) - len2, ", vibration=? "); + } + + snprintf(query+len, sizeof(query)-len, " WHERE person_id=%d", person->person_id); + snprintf(contact_query+len2, sizeof(contact_query)-len2, + " WHERE person_id=%d AND deleted = 0", person->person_id); + + stmt = cts_query_prepare(query); + if (NULL == stmt) { + CTS_ERR("cts_query_prepare() Failed"); + ctsvc_end_trans(false); + return CONTACTS_ERROR_DB; + } + + i = 1; + if (person->image_thumbnail_changed) { + if (person->image_thumbnail_path) + cts_stmt_bind_text(stmt, i, person->image_thumbnail_path); + i++; + } + + if (person->ringtone_changed) { + if (person->ringtone_path) + cts_stmt_bind_text(stmt, i, person->ringtone_path); + i++; + } + if (person->vibration_changed) { + if (person->vibration) + cts_stmt_bind_text(stmt, i, person->vibration); + i++; + } + + ret = cts_stmt_step(stmt); + if (CONTACTS_ERROR_NONE != ret) { + CTS_ERR("cts_stmt_step() Failed(%d)", ret); + cts_stmt_finalize(stmt); + ctsvc_end_trans(false); + return ret; + } + cts_stmt_finalize(stmt); + + stmt = cts_query_prepare(contact_query); + if (NULL == stmt) { + CTS_ERR("cts_query_prepare() Failed"); + ctsvc_end_trans(false); + return CONTACTS_ERROR_DB; + } + + i = 1; + if (person->ringtone_changed) { + if (person->ringtone_path) + cts_stmt_bind_text(stmt, i, person->ringtone_path); + i++; + } + if (person->vibration_changed) { + if (person->vibration) + cts_stmt_bind_text(stmt, i, person->vibration); + i++; + } + + ret = cts_stmt_step(stmt); + if (CONTACTS_ERROR_NONE != ret) { + CTS_ERR("cts_stmt_step() Failed(%d)", ret); + cts_stmt_finalize(stmt); + ctsvc_end_trans(false); + return ret; + } + cts_stmt_finalize(stmt); + + // update favorite + if (person->is_favorite_changed) { + ret = __ctsvc_db_person_set_favorite(person->person_id, person->is_favorite); + if (CONTACTS_ERROR_NONE != ret) { + CTS_ERR("cts_stmt_step() Failed(%d)", ret); + ctsvc_end_trans(false); + return ret; + } + } + + // update person display_name + if (display_name) { + char temp[CTS_SQL_MAX_LEN] = {0}; + person->display_name = SAFE_STRDUP(display_name); + ret = ctsvc_normalize_index(person->display_name, temp, sizeof(temp)); + if (0 <= ret) + person->display_name_index = strdup(temp); + // TODO : update name primary_default?? + } + ctsvc_set_person_noti(); +#ifdef _CONTACTS_IPC_SERVER + ctsvc_change_subject_add_changed_person_id(CONTACTS_CHANGE_UPDATED, person->person_id); +#endif + + ret = ctsvc_end_trans(true); + if (ret < CONTACTS_ERROR_NONE) + { + CTS_ERR("DB error : ctsvc_end_trans() Failed(%d)", ret); + return ret; + } + else { + person->name_contact_id_changed = false; + person->image_thumbnail_changed = false; + person->ringtone_changed = false; + person->vibration_changed = false; + person->is_favorite_changed = false; + return CONTACTS_ERROR_NONE; + } +} + +static int __ctsvc_db_person_delete_record( int id ) +{ + int ret, rel_changed; + char query[CTS_SQL_MAX_LEN] = {0}; + + ret = ctsvc_begin_trans(); + RETVM_IF(ret, ret, "DB error : ctsvc_begin_trans() Failed(%d)", ret); + + snprintf(query, sizeof(query), + "UPDATE "CTS_TABLE_GROUPS" SET member_changed_ver=%d " + "WHERE group_id IN (SELECT distinct group_id " + "FROM "CTS_TABLE_CONTACTS" C, "CTS_TABLE_GROUP_RELATIONS" R " + "ON C.contact_id=R.contact_id AND R.deleted = 0 AND C.deleted = 0 " + "WHERE person_id = %d)", + ctsvc_get_next_ver(), id); + ret = ctsvc_query_exec(query); + if (CONTACTS_ERROR_NONE != ret) { + CTS_ERR("ctsvc_query_exec() Failed(%d)", ret); + ctsvc_end_trans(false); + return ret; + } + + rel_changed = cts_db_change(); + + // images are deleted by db trigger callback function in ctsvc_db_contact_delete_callback + snprintf(query, sizeof(query), "DELETE FROM "CTS_TABLE_CONTACTS" WHERE person_id = %d", id); + ret = ctsvc_query_exec(query); + if (CONTACTS_ERROR_NONE != ret) { + CTS_ERR("ctsvc_query_exec() Failed(%d)", ret); + ctsvc_end_trans(false); + return ret; + } + + snprintf(query, sizeof(query), "DELETE FROM "CTS_TABLE_PERSONS" WHERE person_id = %d", id); + ret = ctsvc_query_exec(query); + if (CONTACTS_ERROR_NONE != ret) { + CTS_ERR("ctsvc_query_exec() Failed(%d)", ret); + ctsvc_end_trans(false); + return ret; + } + + ctsvc_set_contact_noti(); + ctsvc_set_person_noti(); + if (rel_changed > 0) + ctsvc_set_group_rel_noti(); + + ret = ctsvc_end_trans(true); + if (ret < CONTACTS_ERROR_NONE) + { + CTS_ERR("DB error : ctsvc_end_trans() Failed(%d)", ret); + return ret; + } + else + return CONTACTS_ERROR_NONE; +} + +static int __ctsvc_db_person_get_all_records( int offset, int limit, contacts_list_h* out_list ) +{ + int ret; + int len; + cts_stmt stmt; + char query[CTS_SQL_MAX_LEN] = {0}; + contacts_list_h list; + + len = snprintf(query, sizeof(query), + "SELECT person_id, " + "%s, " + "_NORMALIZE_INDEX_(%s), " + "name_contact_id, " + "image_thumbnail_path, " + "ringtone_path, " + "vibration, " + "status, " + "link_count, " + "account_id1, " + "account_id2, " + "account_id3, " + "addressbook_ids, " + "has_phonenumber, " + "has_email, " + "is_favorite " + "FROM "CTSVC_DB_VIEW_PERSON" ORDER BY %s", + ctsvc_get_display_column(), ctsvc_get_display_column(), ctsvc_get_sort_column()); + + if (0 < limit) { + len += snprintf(query+len, sizeof(query)-len, " LIMIT %d", limit); + if (0 < offset) + len += snprintf(query+len, sizeof(query)-len, " OFFSET %d", offset); + } + + stmt = cts_query_prepare(query); + RETVM_IF(NULL == stmt, CONTACTS_ERROR_DB , "DB error : cts_query_prepare() Failed"); + + contacts_list_create(&list); + while ((ret = cts_stmt_step(stmt))) { + contacts_record_h record; + if (1 != ret) { + CTS_ERR("DB error : cts_stmt_step() Failed(%d)", ret); + cts_stmt_finalize(stmt); + contacts_list_destroy(list, true); + return ret; + } + ret = ctsvc_db_person_create_record_from_stmt(stmt, &record); + if (CONTACTS_ERROR_NONE != ret) { + CTS_ERR("DB error : cts_stmt_step() Failed(%d)", ret); + cts_stmt_finalize(stmt); + contacts_list_destroy(list, true); + return ret; + } + + ctsvc_list_prepend(list, record); + } + cts_stmt_finalize(stmt); + ctsvc_list_reverse(list); + + *out_list = list; + return CONTACTS_ERROR_NONE; +} + +static int __ctsvc_db_person_get_records_with_query( contacts_query_h query, int offset, int limit, contacts_list_h* out_list ) +{ + int ret; + int i; + int field_count; + ctsvc_query_s *s_query; + cts_stmt stmt; + contacts_list_h list; + ctsvc_person_s *person; + char full_path[CTSVC_IMG_FULL_PATH_SIZE_MAX] = {0}; + + RETV_IF(NULL == query, CONTACTS_ERROR_INVALID_PARAMETER); + s_query = (ctsvc_query_s *)query; + + ret = ctsvc_db_make_get_records_query_stmt(s_query, offset, limit, &stmt); + RETVM_IF(CONTACTS_ERROR_NONE != ret, ret, "ctsvc_db_make_get_records_query_stmt fail(%d)", ret); + + contacts_list_create(&list); + while ((ret = cts_stmt_step(stmt))) { + contacts_record_h record; + if (1 != ret) { + CTS_ERR("DB error : cts_stmt_step() Failed(%d)", ret); + cts_stmt_finalize(stmt); + contacts_list_destroy(list, true); + return ret; + } + + contacts_record_create(_contacts_person._uri, &record); + person = (ctsvc_person_s*)record; + if (0 == s_query->projection_count) + field_count = s_query->property_count; + else + { + field_count = s_query->projection_count; + + if( CONTACTS_ERROR_NONE != ctsvc_record_set_projection_flags(record, s_query->projection, s_query->projection_count, s_query->property_count) ) + { + ASSERT_NOT_REACHED("To set projection is failed.\n"); + } + } + + for(i=0;i<field_count;i++) { + char *temp; + int property_id; + if (0 == s_query->projection_count) + property_id = s_query->properties[i].property_id; + else + property_id = s_query->projection[i]; + + switch(property_id) { + case CTSVC_PROPERTY_PERSON_ID: + person->person_id = ctsvc_stmt_get_int(stmt, i); + break; + case CTSVC_PROPERTY_PERSON_DISPLAY_NAME: + temp = ctsvc_stmt_get_text(stmt, i); + person->display_name = SAFE_STRDUP(temp); + break; + case CTSVC_PROPERTY_PERSON_DISPLAY_NAME_INDEX: + temp = ctsvc_stmt_get_text(stmt, i); + person->display_name_index = SAFE_STRDUP(temp); + break; + case CTSVC_PROPERTY_PERSON_DISPLAY_CONTACT_ID: + person->name_contact_id = ctsvc_stmt_get_int(stmt, i); + break; + case CTSVC_PROPERTY_PERSON_RINGTONE: + temp = ctsvc_stmt_get_text(stmt, i); + person->ringtone_path = SAFE_STRDUP(temp); + break; + case CTSVC_PROPERTY_PERSON_IMAGE_THUMBNAIL: + temp = ctsvc_stmt_get_text(stmt, i); + if (temp && *temp) { + snprintf(full_path, sizeof(full_path), "%s/%s", CTS_IMG_FULL_LOCATION, temp); + person->image_thumbnail_path = strdup(full_path); + } + break; + case CTSVC_PROPERTY_PERSON_IS_FAVORITE: + person->is_favorite = ctsvc_stmt_get_int(stmt, i); + break; + case CTSVC_PROPERTY_PERSON_HAS_PHONENUMBER: + person->has_phonenumber = ctsvc_stmt_get_int(stmt, i); + break; + case CTSVC_PROPERTY_PERSON_HAS_EMAIL: + person->has_email = ctsvc_stmt_get_int(stmt, i); + break; + case CTSVC_PROPERTY_PERSON_LINK_COUNT: + person->link_count = ctsvc_stmt_get_int(stmt, i); + break; + case CTSVC_PROPERTY_PERSON_ACCOUNT_ID1: + person->account_id1 = ctsvc_stmt_get_int(stmt, i); + break; + case CTSVC_PROPERTY_PERSON_ACCOUNT_ID2: + person->account_id2 = ctsvc_stmt_get_int(stmt, i); + break; + case CTSVC_PROPERTY_PERSON_ACCOUNT_ID3: + person->account_id3 = ctsvc_stmt_get_int(stmt, i); + break; + case CTSVC_PROPERTY_PERSON_ADDRESSBOOK_IDS: + temp = ctsvc_stmt_get_text(stmt, i); + person->addressbook_ids = SAFE_STRDUP(temp); + break; + case CTSVC_PROPERTY_PERSON_VIBRATION: + temp = ctsvc_stmt_get_text(stmt, i); + person->vibration = SAFE_STRDUP(temp); + break; + case CTSVC_PROPERTY_PERSON_STATUS: + temp = ctsvc_stmt_get_text(stmt, i); + person->status = SAFE_STRDUP(temp); + break; + default: + break; + } + } + ctsvc_list_prepend(list, record); + } + cts_stmt_finalize(stmt); + ctsvc_list_reverse(list); + + *out_list = list; + + return CONTACTS_ERROR_NONE; +} + +#if 0 +static int __ctsvc_db_person_insert_records(const contacts_list_h in_list, int **ids) +{ + return CONTACTS_ERROR_NONE; +} + +static int __ctsvc_db_person_update_records(const contacts_list_h in_list) +{ + return CONTACTS_ERROR_NONE; +} + +static int __ctsvc_db_person_delete_records(int ids[], int count) +{ + return CONTACTS_ERROR_NONE; +} +#endif |