implement search count APIs 64/229864/5
authorkamaljeet chauhan <kamal.jc@samsung.com>
Mon, 6 Apr 2020 06:28:03 +0000 (11:58 +0530)
committerkamaljeet chauhan <kamal.jc@samsung.com>
Thu, 16 Apr 2020 10:16:51 +0000 (15:46 +0530)
Change-Id: I5fb994ae0ae1b2bf836a9caf699e5db377a189a8
Signed-off-by: kamaljeet chauhan <kamal.jc@samsung.com>
13 files changed:
client/ctsvc_client_db.c
client/ctsvc_client_db_helper.c
client/ctsvc_client_db_helper.h
common/ipc/ctsvc_ipc_define.h
include/contacts_db.h
server/ctsvc_ipc_server.c
server/ctsvc_ipc_server.h
server/ctsvc_server.c
server/ctsvc_utils_string.h
server/db/ctsvc_db_access_control.c
server/db/ctsvc_db_access_control.h
server/db/ctsvc_db_query.c
server/db/ctsvc_db_query.h

index c8be785..d383e5d 100644 (file)
@@ -407,3 +407,48 @@ EXPORT_API int contacts_db_remove_status_changed_cb(
        return ret;
 }
 
+
+EXPORT_API int contacts_db_get_count_for_search_records(const char *view_uri, const char *keyword, unsigned int *out_count)
+{
+       CHECK_CONTACT_SUPPORTED(CONTACT_FEATURE);
+       int ret;
+       contacts_h contact = NULL;
+
+       ret = ctsvc_client_handle_get_p(&contact);
+       RETVM_IF(CONTACTS_ERROR_NONE != ret, ret, "ctsvc_client_handle_get_p() Fail(%d)", ret);
+
+       ret = ctsvc_client_db_get_count_for_search_records(contact, view_uri, keyword, out_count);
+
+       return ret;
+}
+
+EXPORT_API int contacts_db_get_count_for_search_records_with_range(const char *view_uri, const char *keyword, int range, unsigned int *out_count)
+{
+       CHECK_CONTACT_SUPPORTED(CONTACT_FEATURE);
+       int ret;
+       contacts_h contact = NULL;
+
+       ret = ctsvc_client_handle_get_p(&contact);
+       RETVM_IF(CONTACTS_ERROR_NONE != ret, ret, "ctsvc_client_handle_get_p() Fail(%d)", ret);
+
+       ret = ctsvc_client_db_get_count_for_search_records_with_range(contact, view_uri, keyword, range, out_count);
+
+       return ret;
+}
+
+EXPORT_API int contacts_db_get_count_for_search_records_with_query(contacts_query_h query, const char *keyword, unsigned int *out_count)
+{
+       CHECK_CONTACT_SUPPORTED(CONTACT_FEATURE);
+       int ret;
+       contacts_h contact = NULL;
+
+       ret = ctsvc_client_handle_get_p(&contact);
+       RETVM_IF(CONTACTS_ERROR_NONE != ret, ret, "ctsvc_client_handle_get_p() Fail(%d)", ret);
+
+       ret = ctsvc_client_db_get_count_for_search_records_with_query(contact, query, keyword, out_count);
+
+       return ret;
+}
+
+
+
index f03a6c8..28e8ce1 100644 (file)
@@ -2193,3 +2193,262 @@ int ctsvc_client_db_remove_status_changed_cb(contacts_h contact,
        ctsvc_mutex_unlock(CTS_MUTEX_PIMS_IPC_PUBSUB);
        return CONTACTS_ERROR_NONE;
 }
+
+
+
+int ctsvc_client_db_get_count_for_search_records(contacts_h contact, const char *view_uri, const char *keyword, int *out_count)
+{
+       int ret = CONTACTS_ERROR_NONE;
+       pims_ipc_data_h indata = NULL;
+       pims_ipc_data_h outdata = NULL;
+
+       RETV_IF(NULL == contact, CONTACTS_ERROR_INVALID_PARAMETER);
+       RETV_IF(NULL == out_count, CONTACTS_ERROR_INVALID_PARAMETER);
+       *out_count = 0;
+
+       /* make indata */
+       indata = pims_ipc_data_create(0);
+       if (indata == NULL) {
+               /* LCOV_EXCL_START */
+               ERR("pims_ipc_data_create() Fail");
+               return CONTACTS_ERROR_OUT_OF_MEMORY;
+               /* LCOV_EXCL_STOP */
+       }
+
+       ret = ctsvc_ipc_marshal_handle(contact, indata);
+       if (CONTACTS_ERROR_NONE != ret) {
+               /* LCOV_EXCL_START */
+               ERR("ctsvc_ipc_marshal_handle() Fail(%d)", ret);
+               pims_ipc_data_destroy(indata);
+               return ret;
+               /* LCOV_EXCL_STOP */
+       }
+
+       ret = ctsvc_ipc_marshal_string(view_uri, indata);
+       if (ret != CONTACTS_ERROR_NONE) {
+               /* LCOV_EXCL_START */
+               ERR("ctsvc_ipc_marshal_query() Fail(%d)", ret);
+               pims_ipc_data_destroy(indata);
+               return ret;
+               /* LCOV_EXCL_STOP */
+       }
+
+       ret = ctsvc_ipc_marshal_string(keyword, indata);
+       if (ret != CONTACTS_ERROR_NONE) {
+               /* LCOV_EXCL_START */
+               ERR("ctsvc_ipc_marshal_string() Fail(%d)", ret);
+               pims_ipc_data_destroy(indata);
+               return ret;
+               /* LCOV_EXCL_STOP */
+       }
+
+       /* ipc call */
+       if (ctsvc_ipc_call(CTSVC_IPC_DB_MODULE, CTSVC_IPC_SERVER_DB_GET_COUNT_FOR_SEARCH_RECORDS, indata, &outdata) != 0) {
+               /* LCOV_EXCL_START */
+               ERR("ctsvc_ipc_call() Fail");
+               pims_ipc_data_destroy(indata);
+               return CONTACTS_ERROR_IPC;
+               /* LCOV_EXCL_STOP */
+       }
+
+       pims_ipc_data_destroy(indata);
+
+       if (outdata) {
+               if (CONTACTS_ERROR_NONE != ctsvc_ipc_unmarshal_int(outdata, &ret)) {
+                       /* LCOV_EXCL_START */
+                       ERR("ctsvc_ipc_unmarshal_int() Fail");
+                       pims_ipc_data_destroy(outdata);
+                       return CONTACTS_ERROR_IPC;
+                       /* LCOV_EXCL_STOP */
+               }
+
+               if (CONTACTS_ERROR_NONE == ret) {
+                       if (CONTACTS_ERROR_NONE != ctsvc_ipc_unmarshal_int(outdata, out_count)) {
+                               /* LCOV_EXCL_START */
+                               ERR("ctsvc_ipc_unmarshal_int() Fail");
+                               pims_ipc_data_destroy(outdata);
+                               return CONTACTS_ERROR_IPC;
+                               /* LCOV_EXCL_STOP */
+                       }
+               }
+
+               pims_ipc_data_destroy(outdata);
+       }
+
+       return ret;
+
+}
+
+int ctsvc_client_db_get_count_for_search_records_with_range(contacts_h contact, const char *view_uri, const char *keyword, int range, int *out_count)
+{
+       int ret = CONTACTS_ERROR_NONE;
+       pims_ipc_data_h indata = NULL;
+       pims_ipc_data_h outdata = NULL;
+
+       RETV_IF(NULL == contact, CONTACTS_ERROR_INVALID_PARAMETER);
+       RETV_IF(NULL == out_count, CONTACTS_ERROR_INVALID_PARAMETER);
+       *out_count = 0;
+
+       /* make indata */
+       indata = pims_ipc_data_create(0);
+       if (indata == NULL) {
+               /* LCOV_EXCL_START */
+               ERR("pims_ipc_data_create() Fail");
+               return CONTACTS_ERROR_OUT_OF_MEMORY;
+               /* LCOV_EXCL_STOP */
+       }
+
+       ret = ctsvc_ipc_marshal_handle(contact, indata);
+       if (CONTACTS_ERROR_NONE != ret) {
+               /* LCOV_EXCL_START */
+               ERR("ctsvc_ipc_marshal_handle() Fail(%d)", ret);
+               pims_ipc_data_destroy(indata);
+               return ret;
+               /* LCOV_EXCL_STOP */
+       }
+
+       ret = ctsvc_ipc_marshal_string(view_uri, indata);
+       if (ret != CONTACTS_ERROR_NONE) {
+               /* LCOV_EXCL_START */
+               ERR("ctsvc_ipc_marshal_query() Fail(%d)", ret);
+               pims_ipc_data_destroy(indata);
+               return ret;
+               /* LCOV_EXCL_STOP */
+       }
+
+       ret = ctsvc_ipc_marshal_string(keyword, indata);
+       if (ret != CONTACTS_ERROR_NONE) {
+               /* LCOV_EXCL_START */
+               ERR("ctsvc_ipc_marshal_string() Fail(%d)", ret);
+               pims_ipc_data_destroy(indata);
+               return ret;
+               /* LCOV_EXCL_STOP */
+       }
+
+       ret = ctsvc_ipc_marshal_int(range, indata);
+       if (ret != CONTACTS_ERROR_NONE) {
+               /* LCOV_EXCL_START */
+               ERR("ctsvc_ipc_marshal_string() Fail(%d)", ret);
+               pims_ipc_data_destroy(indata);
+               return ret;
+               /* LCOV_EXCL_STOP */
+       }
+
+       /* ipc call */
+       if (ctsvc_ipc_call(CTSVC_IPC_DB_MODULE, CTSVC_IPC_SERVER_DB_GET_COUNT_FOR_SEARCH_RECORDS_WITH_RANGE, indata, &outdata) != 0) {
+               /* LCOV_EXCL_START */
+               ERR("ctsvc_ipc_call() Fail");
+               pims_ipc_data_destroy(indata);
+               return CONTACTS_ERROR_IPC;
+               /* LCOV_EXCL_STOP */
+       }
+
+       pims_ipc_data_destroy(indata);
+
+       if (outdata) {
+               if (CONTACTS_ERROR_NONE != ctsvc_ipc_unmarshal_int(outdata, &ret)) {
+                       /* LCOV_EXCL_START */
+                       ERR("ctsvc_ipc_unmarshal_int() Fail");
+                       pims_ipc_data_destroy(outdata);
+                       return CONTACTS_ERROR_IPC;
+                       /* LCOV_EXCL_STOP */
+               }
+
+               if (CONTACTS_ERROR_NONE == ret) {
+                       if (CONTACTS_ERROR_NONE != ctsvc_ipc_unmarshal_int(outdata, out_count)) {
+                               /* LCOV_EXCL_START */
+                               ERR("ctsvc_ipc_unmarshal_int() Fail");
+                               pims_ipc_data_destroy(outdata);
+                               return CONTACTS_ERROR_IPC;
+                               /* LCOV_EXCL_STOP */
+                       }
+               }
+
+               pims_ipc_data_destroy(outdata);
+       }
+
+       return ret;
+}
+
+int ctsvc_client_db_get_count_for_search_records_with_query(contacts_h contact, contacts_query_h query, const char *keyword, int *out_count)
+{
+       int ret = CONTACTS_ERROR_NONE;
+       pims_ipc_data_h indata = NULL;
+       pims_ipc_data_h outdata = NULL;
+
+       RETV_IF(NULL == contact, CONTACTS_ERROR_INVALID_PARAMETER);
+       RETV_IF(NULL == query, CONTACTS_ERROR_INVALID_PARAMETER);
+       RETV_IF(NULL == out_count, CONTACTS_ERROR_INVALID_PARAMETER);
+       *out_count = 0;
+
+       /* make indata */
+       indata = pims_ipc_data_create(0);
+       if (indata == NULL) {
+               /* LCOV_EXCL_START */
+               ERR("pims_ipc_data_create() Fail");
+               return CONTACTS_ERROR_OUT_OF_MEMORY;
+               /* LCOV_EXCL_STOP */
+       }
+
+       ret = ctsvc_ipc_marshal_handle(contact, indata);
+       if (CONTACTS_ERROR_NONE != ret) {
+               /* LCOV_EXCL_START */
+               ERR("ctsvc_ipc_marshal_handle() Fail(%d)", ret);
+               pims_ipc_data_destroy(indata);
+               return ret;
+               /* LCOV_EXCL_STOP */
+       }
+       ret = ctsvc_ipc_marshal_query(query, indata);
+       if (ret != CONTACTS_ERROR_NONE) {
+               /* LCOV_EXCL_START */
+               ERR("ctsvc_ipc_marshal_query() Fail(%d)", ret);
+               pims_ipc_data_destroy(indata);
+               return ret;
+               /* LCOV_EXCL_STOP */
+       }
+       ret = ctsvc_ipc_marshal_string(keyword, indata);
+       if (ret != CONTACTS_ERROR_NONE) {
+               /* LCOV_EXCL_START */
+               ERR("ctsvc_ipc_marshal_string() Fail(%d)", ret);
+               pims_ipc_data_destroy(indata);
+               return ret;
+               /* LCOV_EXCL_STOP */
+       }
+
+       /* ipc call */
+       if (ctsvc_ipc_call(CTSVC_IPC_DB_MODULE, CTSVC_IPC_SERVER_DB_GET_COUNT_FOR_SEARCH_RECORDS_WITH_QUERY, indata, &outdata) != 0) {
+               /* LCOV_EXCL_START */
+               ERR("ctsvc_ipc_call() Fail");
+               pims_ipc_data_destroy(indata);
+               return CONTACTS_ERROR_IPC;
+               /* LCOV_EXCL_STOP */
+       }
+
+       pims_ipc_data_destroy(indata);
+
+       if (outdata) {
+               if (CONTACTS_ERROR_NONE != ctsvc_ipc_unmarshal_int(outdata, &ret)) {
+                       /* LCOV_EXCL_START */
+                       ERR("ctsvc_ipc_unmarshal_int() Fail");
+                       pims_ipc_data_destroy(outdata);
+                       return CONTACTS_ERROR_IPC;
+                       /* LCOV_EXCL_STOP */
+               }
+
+               if (CONTACTS_ERROR_NONE == ret) {
+                       if (CONTACTS_ERROR_NONE != ctsvc_ipc_unmarshal_int(outdata, out_count)) {
+                               /* LCOV_EXCL_START */
+                               ERR("ctsvc_ipc_unmarshal_int() Fail");
+                               pims_ipc_data_destroy(outdata);
+                               return CONTACTS_ERROR_IPC;
+                               /* LCOV_EXCL_STOP */
+                       }
+               }
+
+               pims_ipc_data_destroy(outdata);
+       }
+
+       return ret;
+}
+
+
index f7609a6..4283663 100644 (file)
@@ -72,6 +72,10 @@ int ctsvc_client_db_get_last_change_version(contacts_h contact, int *last_versio
 int ctsvc_client_db_get_status(contacts_h contact, contacts_db_status_e *status);
 int ctsvc_client_db_add_status_changed_cb(contacts_h contact, contacts_db_status_changed_cb cb, void *user_data);
 int ctsvc_client_db_remove_status_changed_cb(contacts_h contact, contacts_db_status_changed_cb cb, void *user_data);
+int ctsvc_client_db_get_count_for_search_records(contacts_h contact, const char *view_uri, const char *keyword, int *out_count);
+int ctsvc_client_db_get_count_for_search_records_with_range(contacts_h contact, const char *view_uri, const char *keyword, int range, int *out_count);
+int ctsvc_client_db_get_count_for_search_records_with_query(contacts_h contact, contacts_query_h query, const char *keyword, int *out_count);
+
 
 #endif /* __CTSVC_CLIENT_DB_HELPER_H__ */
 
index 6fdcb37..c139690 100644 (file)
@@ -59,7 +59,9 @@
 #define CTSVC_IPC_SERVER_DB_SEARCH_RECORDS_WITH_QUERY_FOR_SNIPPET "search_records_with_query_for_snippet"
 #define CTSVC_IPC_SERVER_DB_GET_STATUS                                 "get_db_status"
 #define CTSVC_IPC_SERVER_DB_STATUS_CHANGED                     "db_status_changed"
-
+#define CTSVC_IPC_SERVER_DB_GET_COUNT_FOR_SEARCH_RECORDS    "get_count_for_search_records"
+#define CTSVC_IPC_SERVER_DB_GET_COUNT_FOR_SEARCH_RECORDS_WITH_RANGE    "get_count_for_search_records_with_range"
+#define CTSVC_IPC_SERVER_DB_GET_COUNT_FOR_SEARCH_RECORDS_WITH_QUERY    "get_count_for_search_records_with_query"
 
 #define CTSVC_IPC_SERVER_ACTIVITY_DELETE_BY_CONTACT_ID   "activity_delete_by_contact_id"
 #define CTSVC_IPC_SERVER_ACTIVITY_DELETE_BY_ACCOUNT_ID   "activity_delete_by_account_id"
index 48414e6..755dbc0 100644 (file)
@@ -883,6 +883,89 @@ int contacts_db_get_last_change_version(int *last_change_version);
 
 
 /**
+ * @brief Gets the number of found records based on a given keyword.
+ * @since_tizen 5.5
+ * @privlevel public
+ * @privilege %http://tizen.org/privilege/contact.read
+ * @remarks This function works only for @ref CAPI_SOCIAL_CONTACTS_SVC_VIEW_MODULE_contacts_person, @ref CAPI_SOCIAL_CONTACTS_SVC_VIEW_MODULE_contacts_person_contact, \n
+ *                      @ref CAPI_SOCIAL_CONTACTS_SVC_VIEW_MODULE_contacts_person_grouprel, @ref CAPI_SOCIAL_CONTACTS_SVC_VIEW_MODULE_contacts_person_group_assigned \n
+ *                      and @ref CAPI_SOCIAL_CONTACTS_SVC_VIEW_MODULE_contacts_person_group_not_assigned.
+ * @param[in] view_uri The view URI
+ * @param[in] keyword The keyword
+ * @param[out] count The number of records
+ * @return @c 0 on success,
+ *         otherwise a negative error value
+ * @retval #CONTACTS_ERROR_NONE Successful
+ * @retval #CONTACTS_ERROR_NOT_SUPPORTED Not supported
+ * @retval #CONTACTS_ERROR_PERMISSION_DENIED Permission denied. This application does not have the privilege to call this method
+ * @retval #CONTACTS_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #CONTACTS_ERROR_OUT_OF_MEMORY Out of memory
+ * @retval #CONTACTS_ERROR_DB Database operation failure
+ * @retval #CONTACTS_ERROR_IPC IPC error
+ * @retval #CONTACTS_ERROR_SYSTEM Internal system module error
+ * @pre contacts_connect() should be called to open a connection to the contacts service.
+ * @see contacts_connect()
+ */
+int contacts_db_get_count_for_search_records(const char *view_uri, const char *keyword, unsigned int *count);
+
+
+/**
+ * @brief Gets the number of found records based on a given keyword and range.
+ * @since_tizen 5.5
+ * @privlevel public
+ * @privilege %http://tizen.org/privilege/contact.read
+ * @remarks This function works only for @ref CAPI_SOCIAL_CONTACTS_SVC_VIEW_MODULE_contacts_person, @ref CAPI_SOCIAL_CONTACTS_SVC_VIEW_MODULE_contacts_person_contact, \n
+ *          @ref CAPI_SOCIAL_CONTACTS_SVC_VIEW_MODULE_contacts_person_grouprel, @ref CAPI_SOCIAL_CONTACTS_SVC_VIEW_MODULE_contacts_person_group_assigned, \n
+ *          @ref CAPI_SOCIAL_CONTACTS_SVC_VIEW_MODULE_contacts_person_group_not_assigned. For these views the valid search ranges are: #CONTACTS_SEARCH_RANGE_NAME, #CONTACTS_SEARCH_RANGE_NUMBER, #CONTACTS_SEARCH_RANGE_DATA. \n
+ *          For @ref CAPI_SOCIAL_CONTACTS_SVC_VIEW_MODULE_contacts_person_number the valid search ranges are #CONTACTS_SEARCH_RANGE_NAME and #CONTACTS_SEARCH_RANGE_NUMBER.\n
+ *          For @ref CAPI_SOCIAL_CONTACTS_SVC_VIEW_MODULE_contacts_person_email the valid search ranges are #CONTACTS_SEARCH_RANGE_NAME and #CONTACTS_SEARCH_RANGE_EMAIL.
+ * @param[in] view_uri The view URI
+ * @param[in] keyword The keyword
+ * @param[in] range The search range
+ * @param[out] count The number of records
+ * @return @c 0 on success,
+ *         otherwise a negative error value
+ * @retval #CONTACTS_ERROR_NONE Successful
+ * @retval #CONTACTS_ERROR_NOT_SUPPORTED Not supported
+ * @retval #CONTACTS_ERROR_PERMISSION_DENIED Permission denied. This application does not have the privilege to call this method
+ * @retval #CONTACTS_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #CONTACTS_ERROR_OUT_OF_MEMORY Out of memory
+ * @retval #CONTACTS_ERROR_DB Database operation failure
+ * @retval #CONTACTS_ERROR_IPC IPC error
+ * @retval #CONTACTS_ERROR_SYSTEM Internal system module error
+ * @pre contacts_connect() should be called to open a connection to the contacts service.
+ * @see contacts_connect()
+ */
+int contacts_db_get_count_for_search_records_with_range(const char *view_uri, const char *keyword, int range, unsigned int *count);
+
+
+/**
+ * @brief Gets the number of found records based on a given keyword and query.
+ * @since_tizen 5.5
+ * @privlevel public
+ * @privilege %http://tizen.org/privilege/contact.read
+ * @remarks This function works only for @ref CAPI_SOCIAL_CONTACTS_SVC_VIEW_MODULE_contacts_person, @ref CAPI_SOCIAL_CONTACTS_SVC_VIEW_MODULE_contacts_person_contact, \n
+ *          @ref CAPI_SOCIAL_CONTACTS_SVC_VIEW_MODULE_contacts_person_grouprel, @ref CAPI_SOCIAL_CONTACTS_SVC_VIEW_MODULE_contacts_person_group_assigned \n
+ *          and @ref CAPI_SOCIAL_CONTACTS_SVC_VIEW_MODULE_contacts_person_group_not_assigned.
+ * @param[in] query The query handle to filter
+ * @param[in] keyword The keyword
+ * @param[out] count The number of records
+ * @return @c 0 on success,
+ *         otherwise a negative error value
+ * @retval #CONTACTS_ERROR_NONE Successful
+ * @retval #CONTACTS_ERROR_NOT_SUPPORTED Not supported
+ * @retval #CONTACTS_ERROR_PERMISSION_DENIED Permission denied. This application does not have the privilege to call this method
+ * @retval #CONTACTS_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #CONTACTS_ERROR_OUT_OF_MEMORY Out of memory
+ * @retval #CONTACTS_ERROR_DB Database operation failure
+ * @retval #CONTACTS_ERROR_IPC IPC error
+ * @retval #CONTACTS_ERROR_SYSTEM Internal system module error
+ * @pre contacts_connect() should be called to open a connection to the contacts service.
+ * @see contacts_connect()
+ */
+int contacts_db_get_count_for_search_records_with_query(contacts_query_h query, const char *keyword, unsigned int *count);
+
+/**
  * @}
  */
 
index b9ab3b5..3cda369 100644 (file)
@@ -2887,3 +2887,358 @@ DATA_FREE:
        return;
 }
 
+void ctsvc_ipc_server_db_get_count_for_search_records(pims_ipc_h ipc,
+               pims_ipc_data_h indata, pims_ipc_data_h *outdata, void *userdata)
+{
+       int ret = CONTACTS_ERROR_NONE;
+       char *view_uri = NULL;
+       int count = 0;
+       contacts_h contact = NULL;
+       char *keyword = NULL;
+
+       if (indata) {
+               ret = ctsvc_ipc_unmarshal_handle(indata, &contact);
+               if (CONTACTS_ERROR_NONE != ret) {
+                       /* LCOV_EXCL_START */
+                       ERR("ctsvc_ipc_unmarshal_handle() Fail(%d)", ret);
+                       goto ERROR_RETURN;
+                       /* LCOV_EXCL_STOP */
+               }
+
+               ret = ctsvc_ipc_unmarshal_string(indata, &view_uri);
+               if (ret != CONTACTS_ERROR_NONE) {
+                       /* LCOV_EXCL_START */
+                       ERR("ctsvc_ipc_unmarshal_record() Fail");
+                       goto ERROR_RETURN;
+                       /* LCOV_EXCL_STOP */
+               }
+
+               ret = ctsvc_ipc_unmarshal_string(indata, &keyword);
+               if (ret != CONTACTS_ERROR_NONE) {
+                       /* LCOV_EXCL_START */
+                       ERR("ctsvc_ipc_unmarshal_string() Fail");
+                       goto ERROR_RETURN;
+                       /* LCOV_EXCL_STOP */
+               }
+       } else {
+               /* LCOV_EXCL_START */
+               ERR("ctsvc_ipc_server_db_insert_record() Fail");
+               goto ERROR_RETURN;
+               /* LCOV_EXCL_STOP */
+       }
+
+       if (!ctsvc_have_permission(ipc, ctsvc_required_read_permission(view_uri))) {
+               /* LCOV_EXCL_START */
+               ret = CONTACTS_ERROR_PERMISSION_DENIED;
+               goto ERROR_RETURN;
+               /* LCOV_EXCL_STOP */
+       }
+
+       ret = ctsvc_db_get_count_for_search_records(view_uri, keyword, &count);
+
+       if (outdata) {
+               *outdata = pims_ipc_data_create(0);
+               if (NULL == *outdata) {
+                       /* LCOV_EXCL_START */
+                       ERR("pims_ipc_data_create() Fail");
+                       goto DATA_FREE;
+                       /* LCOV_EXCL_STOP */
+               }
+               if (CONTACTS_ERROR_NONE != ctsvc_ipc_marshal_int(ret, *outdata)) {
+                       /* LCOV_EXCL_START */
+                       pims_ipc_data_destroy(*outdata);
+                       *outdata = NULL;
+                       ERR("ctsvc_ipc_marshal_int() Fail");
+                       goto DATA_FREE;
+                       /* LCOV_EXCL_STOP */
+               }
+
+               if (CONTACTS_ERROR_NO_DATA == ret) {
+                       DBG("no data");
+               } else if (CONTACTS_ERROR_NONE == ret) {
+                       ret = ctsvc_ipc_marshal_int(count, *outdata);
+
+                       if (ret != CONTACTS_ERROR_NONE) {
+                               /* LCOV_EXCL_START */
+                               ERR("ctsvc_ipc_unmarshal_int() Fail");
+                               goto DATA_FREE;
+                               /* LCOV_EXCL_STOP */
+                       }
+               }
+       } else {
+               /* LCOV_EXCL_START */
+               ERR("outdata is NULL");
+               /* LCOV_EXCL_STOP */
+       }
+       goto DATA_FREE;
+
+ERROR_RETURN:
+       if (outdata) {
+               *outdata = pims_ipc_data_create(0);
+               if (NULL == *outdata) {
+                       /* LCOV_EXCL_START */
+                       ERR("pims_ipc_data_create() Fail");
+                       goto DATA_FREE;
+                       /* LCOV_EXCL_STOP */
+               }
+               if (CONTACTS_ERROR_NONE != ctsvc_ipc_marshal_int(ret, *outdata)) {
+                       /* LCOV_EXCL_START */
+                       pims_ipc_data_destroy(*outdata);
+                       *outdata = NULL;
+                       ERR("ctsvc_ipc_marshal_int() Fail");
+                       goto DATA_FREE;
+                       /* LCOV_EXCL_STOP */
+               }
+       } else {
+               /* LCOV_EXCL_START */
+               ERR("outdata is NULL");
+               /* LCOV_EXCL_STOP */
+       }
+DATA_FREE:
+       ctsvc_handle_destroy(contact);
+       free(view_uri);
+       free(keyword);
+       ctsvc_server_start_timeout();
+       return;
+}
+
+void ctsvc_ipc_server_db_get_count_for_search_records_with_range(pims_ipc_h ipc,
+               pims_ipc_data_h indata, pims_ipc_data_h *outdata, void *userdata)
+{
+       int ret = CONTACTS_ERROR_NONE;
+       char *view_uri = NULL;
+       int count = 0;
+       contacts_h contact = NULL;
+       char *keyword = NULL;
+       int range = 0;
+
+       if (indata) {
+               ret = ctsvc_ipc_unmarshal_handle(indata, &contact);
+               if (CONTACTS_ERROR_NONE != ret) {
+                       /* LCOV_EXCL_START */
+                       ERR("ctsvc_ipc_unmarshal_handle() Fail(%d)", ret);
+                       goto ERROR_RETURN;
+                       /* LCOV_EXCL_STOP */
+               }
+
+               ret = ctsvc_ipc_unmarshal_string(indata, &view_uri);
+               if (ret != CONTACTS_ERROR_NONE) {
+                       /* LCOV_EXCL_START */
+                       ERR("ctsvc_ipc_unmarshal_record() Fail");
+                       goto ERROR_RETURN;
+                       /* LCOV_EXCL_STOP */
+               }
+
+               ret = ctsvc_ipc_unmarshal_string(indata, &keyword);
+               if (ret != CONTACTS_ERROR_NONE) {
+                       /* LCOV_EXCL_START */
+                       ERR("ctsvc_ipc_unmarshal_string() Fail");
+                       goto ERROR_RETURN;
+                       /* LCOV_EXCL_STOP */
+               }
+
+               ret = ctsvc_ipc_unmarshal_int(indata, &range);
+               if (ret != CONTACTS_ERROR_NONE) {
+                       /* LCOV_EXCL_START */
+                       ERR("ctsvc_ipc_unmarshal_string() Fail");
+                       goto ERROR_RETURN;
+                       /* LCOV_EXCL_STOP */
+               }
+       } else {
+               /* LCOV_EXCL_START */
+               ERR("ctsvc_ipc_server_db_insert_record() Fail");
+               goto ERROR_RETURN;
+               /* LCOV_EXCL_STOP */
+       }
+
+       if (!ctsvc_have_permission(ipc, ctsvc_required_read_permission(view_uri))) {
+               /* LCOV_EXCL_START */
+               ret = CONTACTS_ERROR_PERMISSION_DENIED;
+               goto ERROR_RETURN;
+               /* LCOV_EXCL_STOP */
+       }
+
+       ret = ctsvc_db_get_count_for_search_records_with_range(view_uri, keyword, range, &count);
+
+       if (outdata) {
+               *outdata = pims_ipc_data_create(0);
+               if (NULL == *outdata) {
+                       /* LCOV_EXCL_START */
+                       ERR("pims_ipc_data_create() Fail");
+                       goto DATA_FREE;
+                       /* LCOV_EXCL_STOP */
+               }
+               if (CONTACTS_ERROR_NONE != ctsvc_ipc_marshal_int(ret, *outdata)) {
+                       /* LCOV_EXCL_START */
+                       pims_ipc_data_destroy(*outdata);
+                       *outdata = NULL;
+                       ERR("ctsvc_ipc_marshal_int() Fail");
+                       goto DATA_FREE;
+                       /* LCOV_EXCL_STOP */
+               }
+
+               if (CONTACTS_ERROR_NO_DATA == ret) {
+                       DBG("no data");
+               } else if (CONTACTS_ERROR_NONE == ret) {
+                       ret = ctsvc_ipc_marshal_int(count, *outdata);
+
+                       if (ret != CONTACTS_ERROR_NONE) {
+                               /* LCOV_EXCL_START */
+                               ERR("ctsvc_ipc_unmarshal_int() Fail");
+                               goto DATA_FREE;
+                               /* LCOV_EXCL_STOP */
+                       }
+               }
+       } else {
+               /* LCOV_EXCL_START */
+               ERR("outdata is NULL");
+               /* LCOV_EXCL_STOP */
+       }
+       goto DATA_FREE;
+
+ERROR_RETURN:
+       if (outdata) {
+               *outdata = pims_ipc_data_create(0);
+               if (NULL == *outdata) {
+                       /* LCOV_EXCL_START */
+                       ERR("pims_ipc_data_create() Fail");
+                       goto DATA_FREE;
+                       /* LCOV_EXCL_STOP */
+               }
+               if (CONTACTS_ERROR_NONE != ctsvc_ipc_marshal_int(ret, *outdata)) {
+                       /* LCOV_EXCL_START */
+                       pims_ipc_data_destroy(*outdata);
+                       *outdata = NULL;
+                       ERR("ctsvc_ipc_marshal_int() Fail");
+                       goto DATA_FREE;
+                       /* LCOV_EXCL_STOP */
+               }
+       } else {
+               /* LCOV_EXCL_START */
+               ERR("outdata is NULL");
+               /* LCOV_EXCL_STOP */
+       }
+DATA_FREE:
+       ctsvc_handle_destroy(contact);
+       free(view_uri);
+       free(keyword);
+       ctsvc_server_start_timeout();
+       return;
+}
+
+void ctsvc_ipc_server_db_get_count_for_search_records_with_query(pims_ipc_h ipc,
+               pims_ipc_data_h indata, pims_ipc_data_h *outdata, void *userdata)
+{
+       int ret = CONTACTS_ERROR_NONE;
+       contacts_query_h query = NULL;
+       int count = 0;
+       contacts_h contact = NULL;
+       char *keyword = NULL;
+
+       if (indata) {
+               ret = ctsvc_ipc_unmarshal_handle(indata, &contact);
+               if (CONTACTS_ERROR_NONE != ret) {
+                       /* LCOV_EXCL_START */
+                       ERR("ctsvc_ipc_unmarshal_handle() Fail(%d)", ret);
+                       goto ERROR_RETURN;
+                       /* LCOV_EXCL_STOP */
+               }
+
+               ret = ctsvc_ipc_unmarshal_query(indata, &query);
+               if (ret != CONTACTS_ERROR_NONE) {
+                       /* LCOV_EXCL_START */
+                       ERR("ctsvc_ipc_unmarshal_query() Fail");
+                       goto ERROR_RETURN;
+                       /* LCOV_EXCL_STOP */
+               }
+
+               ret = ctsvc_ipc_unmarshal_string(indata, &keyword);
+               if (ret != CONTACTS_ERROR_NONE) {
+                       /* LCOV_EXCL_START */
+                       ERR("ctsvc_ipc_unmarshal_string() Fail");
+                       goto ERROR_RETURN;
+                       /* LCOV_EXCL_STOP */
+               }
+       } else {
+               /* LCOV_EXCL_START */
+               ERR("ctsvc_ipc_server_db_get_count_for_search_records_with_query() Fail");
+               goto ERROR_RETURN;
+               /* LCOV_EXCL_STOP */
+       }
+
+       if (!ctsvc_have_permission(ipc, ctsvc_required_read_permission(((ctsvc_query_s*)query)->view_uri))) {
+               /* LCOV_EXCL_START */
+               ret = CONTACTS_ERROR_PERMISSION_DENIED;
+               goto ERROR_RETURN;
+               /* LCOV_EXCL_STOP */
+       }
+
+       ret = ctsvc_db_get_count_for_search_records_with_query(query, keyword, &count);
+
+       if (outdata) {
+               *outdata = pims_ipc_data_create(0);
+               if (NULL == *outdata) {
+                       /* LCOV_EXCL_START */
+                       ERR("pims_ipc_data_create() Fail");
+                       goto DATA_FREE;
+                       /* LCOV_EXCL_STOP */
+               }
+               if (CONTACTS_ERROR_NONE != ctsvc_ipc_marshal_int(ret, *outdata)) {
+                       /* LCOV_EXCL_START */
+                       pims_ipc_data_destroy(*outdata);
+                       *outdata = NULL;
+                       ERR("ctsvc_ipc_marshal_int() Fail");
+                       goto DATA_FREE;
+                       /* LCOV_EXCL_STOP */
+               }
+
+               if (CONTACTS_ERROR_NO_DATA == ret) {
+                       DBG("no data");
+               } else if (CONTACTS_ERROR_NONE == ret) {
+                       ret = ctsvc_ipc_marshal_int(count, *outdata);
+
+                       if (ret != CONTACTS_ERROR_NONE) {
+                               /* LCOV_EXCL_START */
+                               ERR("ctsvc_ipc_unmarshal_int() Fail");
+                               goto DATA_FREE;
+                               /* LCOV_EXCL_STOP */
+                       }
+               }
+       } else {
+               /* LCOV_EXCL_START */
+               ERR("outdata is NULL");
+               /* LCOV_EXCL_STOP */
+       }
+       goto DATA_FREE;
+
+ERROR_RETURN:
+       if (outdata) {
+               *outdata = pims_ipc_data_create(0);
+               if (NULL == *outdata) {
+                       /* LCOV_EXCL_START */
+                       ERR("pims_ipc_data_create() Fail");
+                       goto DATA_FREE;
+                       /* LCOV_EXCL_STOP */
+               }
+               if (CONTACTS_ERROR_NONE != ctsvc_ipc_marshal_int(ret, *outdata)) {
+                       /* LCOV_EXCL_START */
+                       pims_ipc_data_destroy(*outdata);
+                       *outdata = NULL;
+                       ERR("ctsvc_ipc_marshal_int() Fail");
+                       goto DATA_FREE;
+                       /* LCOV_EXCL_STOP */
+               }
+       } else {
+               /* LCOV_EXCL_START */
+               ERR("outdata is NULL");
+               /* LCOV_EXCL_STOP */
+       }
+DATA_FREE:
+       ctsvc_handle_destroy(contact);
+       contacts_query_destroy(query);
+       free(keyword);
+       ctsvc_server_start_timeout();
+       return;
+}
+
+
index 9b7a881..6e16da4 100644 (file)
@@ -55,4 +55,8 @@ void ctsvc_ipc_server_db_search_records_with_query_for_snippet(pims_ipc_h ipc, p
 
 void ctsvc_ipc_server_db_get_status(pims_ipc_h ipc, pims_ipc_data_h indata, pims_ipc_data_h *outdata, void *userdata);
 
+void ctsvc_ipc_server_db_get_count_for_search_records(pims_ipc_h ipc, pims_ipc_data_h indata, pims_ipc_data_h *outdata, void *userdata);
+void ctsvc_ipc_server_db_get_count_for_search_records_with_range(pims_ipc_h ipc, pims_ipc_data_h indata, pims_ipc_data_h *outdata, void *userdata);
+void ctsvc_ipc_server_db_get_count_for_search_records_with_query(pims_ipc_h ipc, pims_ipc_data_h indata, pims_ipc_data_h *outdata, void *userdata);
+
 #endif /*__CTSVC_IPC_SERVER_H__*/
index d01839e..29cf79a 100644 (file)
@@ -164,6 +164,18 @@ static int __server_main(void)
                                        CTSVC_IPC_SERVER_DB_GET_STATUS,
                                        ctsvc_ipc_server_db_get_status, NULL) != 0)
                        break;
+               if (pims_ipc_svc_register(CTSVC_IPC_DB_MODULE,
+                                       CTSVC_IPC_SERVER_DB_GET_COUNT_FOR_SEARCH_RECORDS,
+                                       ctsvc_ipc_server_db_get_count_for_search_records, NULL) != 0)
+                       break;
+               if (pims_ipc_svc_register(CTSVC_IPC_DB_MODULE,
+                                       CTSVC_IPC_SERVER_DB_GET_COUNT_FOR_SEARCH_RECORDS_WITH_RANGE,
+                                       ctsvc_ipc_server_db_get_count_for_search_records_with_range, NULL) != 0)
+                       break;
+               if (pims_ipc_svc_register(CTSVC_IPC_DB_MODULE,
+                                       CTSVC_IPC_SERVER_DB_GET_COUNT_FOR_SEARCH_RECORDS_WITH_QUERY,
+                                       ctsvc_ipc_server_db_get_count_for_search_records_with_query, NULL) != 0)
+                       break;
                if (pims_ipc_svc_register(CTSVC_IPC_ACTIVITY_MODULE,
                                        CTSVC_IPC_SERVER_ACTIVITY_DELETE_BY_CONTACT_ID,
                                        ctsvc_ipc_activity_delete_by_contact_id, NULL) != 0)
index d20c26e..de56984 100644 (file)
@@ -31,6 +31,8 @@ enum {
        CTSVC_ENUM_URI_READ_ONLY_PERSON_GROUP,
        CTSVC_ENUM_URI_READ_ONLY_PERSON_GROUP_ASSIGNED,
        CTSVC_ENUM_URI_READ_ONLY_PERSON_GROUP_NOT_ASSIGNED,
+       CTSVC_ENUM_URI_READ_ONLY_PERSON_BUSINESS_CARD,
+       CTSVC_ENUM_URI_READ_ONLY_PERSON_CONTACT_COMPANY,
 };
 
 int ctsvc_utils_string_strstr(const char *haystack, const char *needle, int *len);
index 05f2d5c..eb90c20 100644 (file)
@@ -507,3 +507,17 @@ int ctsvc_is_owner(int addressbook_id)
        return ret;
 }
 
+
+bool ctsvc_can_access_restricted_addressbook(void)
+{
+#if 0
+       ctsvc_permission_info_s* permission_info = __ctsvc_find_access_info( (unsigned int)pthread_self());
+       if (permission_info) {
+               DBG("%s %s !!!!", permission_info->smack, permission_info->is_core_app?"is core app" : "is not core app");
+               return permission_info->is_core_app;
+       }
+#endif
+
+       return true;
+}
+
index 9493a2c..1873fa1 100644 (file)
@@ -40,6 +40,6 @@ char* ctsvc_get_client_smack_label(void);
 int ctsvc_get_write_permitted_addressbook_ids(int **addressbook_ids, int *count);
 bool ctsvc_have_ab_write_permission(int addressbook_id, bool allow_readonly);
 int ctsvc_is_owner(int addressbook_id);
-
+bool ctsvc_can_access_restricted_addressbook(void);
 
 #endif /* __CTSVC_DB_ACCESS_CONTROL_H__ */
index a61ea08..37d5614 100644 (file)
@@ -3081,109 +3081,1235 @@ static int __ctsvc_db_search_records_exec(const char *view_uri,
        return CONTACTS_ERROR_NONE;
 }
 
-static int __ctsvc_db_search_records(const char *view_uri,
+static int __ctsvc_db_get_count_for_search_records_exec(const char *view_uri,
+               int enum_uri,
+               const property_info_s *properties,
+               int ids_count,
+               const char *projection,
                const char *keyword,
-               int offset,
-               int limit,
+               int range,
                bool is_snippet,
                const char *start_match,
                const char *end_match,
                int token_number,
-               contacts_list_h *out_list)
+               int *out_count)
 {
+       char *query = NULL;
+       char temp_query[CTS_SQL_MAX_LEN];
+       int query_size;
+       int temp_len;
+       const char *table;
+       int len = 0;
        int ret;
-       unsigned int count;
-       char *projection;
-       const property_info_s *p;
-       bool can_keyword_search = false;
-       int enum_uri = 0;
-       int range = CONTACTS_SEARCH_RANGE_NAME | CONTACTS_SEARCH_RANGE_NUMBER | CONTACTS_SEARCH_RANGE_DATA;
+       const char *sortkey = NULL;
+       bool need_and = false;
 
-       RETV_IF(NULL == keyword, CONTACTS_ERROR_INVALID_PARAMETER);
+       ret = ctsvc_db_get_table_name(view_uri, &table);
+       RETVM_IF(CONTACTS_ERROR_NONE != ret, ret, "Invalid view uri (%s)", view_uri);
 
-       can_keyword_search = __ctsvc_db_view_can_keyword_search(view_uri, &enum_uri);
-       RETVM_IF(false == can_keyword_search, CONTACTS_ERROR_INVALID_PARAMETER,
-                       "can not keyword search");
+       query_size = CTS_SQL_MAX_LEN;
+       query = calloc(1, query_size);
+       if (NULL == query) {
+               /* LCOV_EXCL_START */
+               ERR("calloc() Fail");
+               return CONTACTS_ERROR_OUT_OF_MEMORY;
+               /* LCOV_EXCL_STOP */
+       }
 
-       p = ctsvc_view_get_all_property_infos(view_uri, &count);
-       ret = __db_create_projection(view_uri, p, count, NULL, 0, &projection, is_snippet);
-       if (CONTACTS_ERROR_NONE != ret) {
+       len = 0;
+
+       if (STRING_EQUAL == strcmp(keyword, "+"))
+               range &= ~CONTACTS_SEARCH_RANGE_NUMBER;
+
+       if (0 == range) {
                /* LCOV_EXCL_START */
-               ERR("__db_create_projection() Fail(%d)", ret);
-               return ret;
+               ERR("No range");
+               free(query);
+               return CONTACTS_ERROR_NONE;
                /* LCOV_EXCL_STOP */
        }
 
-       ret = __ctsvc_db_search_records_exec(view_uri, enum_uri, p, count, projection,
-                       keyword, offset, limit, range, is_snippet, start_match, end_match, token_number, out_list);
-       free(projection);
+       temp_len = SAFE_SNPRINTF(&query, &query_size, len, "SELECT COUNT(*) FROM (");
+       if (0 <= temp_len)
+               len += temp_len;
 
-       return ret;
-}
+       switch (enum_uri) {
+       case CTSVC_ENUM_URI_READ_ONLY_PERSON_CONTACT:
+       case CTSVC_ENUM_URI_READ_ONLY_PERSON_BUSINESS_CARD:
+       case CTSVC_ENUM_URI_READ_ONLY_PERSON_CONTACT_COMPANY:
+       case CTSVC_ENUM_URI_READ_ONLY_PERSON_GROUP:
+       case CTSVC_ENUM_URI_READ_ONLY_PERSON_GROUP_ASSIGNED:
+       case CTSVC_ENUM_URI_READ_ONLY_PERSON_GROUP_NOT_ASSIGNED:
 
-static int __ctsvc_db_search_records_with_range(const char *view_uri,
-               const char *keyword,
-               int offset,
-               int limit,
-               int range,
-               bool is_snippet,
-               const char *start_match,
-               const char *end_match,
-               int token_number,
-               contacts_list_h *out_list)
-{
-       int ret;
-       unsigned int count;
-       char *projection;
-       const property_info_s *p;
-       bool can_keyword_search = false;
-       int eunm_uri = 0;
+               if (range & CONTACTS_SEARCH_RANGE_EMAIL) {
+                       free(query);
+                       return CONTACTS_ERROR_INVALID_PARAMETER;
+               }
 
-       RETV_IF(NULL == keyword, CONTACTS_ERROR_INVALID_PARAMETER);
+               temp_len = SAFE_SNPRINTF(&query, &query_size, len, "SELECT ");
+               if (0 <= temp_len)
+                       len += temp_len;
+               temp_len = SAFE_SNPRINTF(&query, &query_size, len, projection);
+               if (0 <= temp_len)
+                       len += temp_len;
+               temp_len = SAFE_SNPRINTF(&query, &query_size, len, " FROM ");
+               if (0 <= temp_len)
+                       len += temp_len;
+               temp_len = SAFE_SNPRINTF(&query, &query_size, len, table);
+               if (0 <= temp_len)
+                       len += temp_len;
+               temp_len = SAFE_SNPRINTF(&query, &query_size, len, " as temp_contacts");
+               if (0 <= temp_len)
+                       len += temp_len;
+               break;
 
-       can_keyword_search = __ctsvc_db_view_can_keyword_search(view_uri, &eunm_uri);
-       RETV_IF(false == can_keyword_search, CONTACTS_ERROR_INVALID_PARAMETER);
+       case CTSVC_ENUM_URI_READ_ONLY_PERSON_NUMBER:
+               {
+                       bool need_or = false;
 
-       p = ctsvc_view_get_all_property_infos(view_uri, &count);
-       ret = __db_create_projection(view_uri, p, count, NULL, 0, &projection, is_snippet);
-       RETVM_IF(CONTACTS_ERROR_NONE != ret, ret, "__db_create_projection() Fail(%d)", ret);
+                       if (range & CONTACTS_SEARCH_RANGE_DATA || range & CONTACTS_SEARCH_RANGE_EMAIL) {
+                               /* LCOV_EXCL_START */
+                               ERR("Invalid range");
+                               free(query);
+                               return CONTACTS_ERROR_INVALID_PARAMETER;
+                               /* LCOV_EXCL_STOP */
+                       }
 
-       ret = __ctsvc_db_search_records_exec(view_uri, eunm_uri, p, count, projection,
-                       keyword, offset, limit, range, is_snippet, start_match, end_match, token_number, out_list);
-       free(projection);
+                       temp_len = SAFE_SNPRINTF(&query, &query_size, len, "SELECT ");
+                       if (0 <= temp_len) len += temp_len;
+                       temp_len = SAFE_SNPRINTF(&query, &query_size, len, projection);
+                       if (0 <= temp_len) len += temp_len;
+                       temp_len = SAFE_SNPRINTF(&query, &query_size, len, " FROM (SELECT * FROM ");
+                       if (0 <= temp_len) len += temp_len;
+                       temp_len = SAFE_SNPRINTF(&query, &query_size, len, table);
+                       if (0 <= temp_len) len += temp_len;
+
+                       if ((range & CONTACTS_SEARCH_RANGE_NUMBER) && ctsvc_is_phonenumber(keyword)) {
+                               char clean_num[strlen(keyword)+1+5];   /* for cc */
+
+                               /*
+                                * Original number can include '-' or special character. So search by cleaned_number
+                                * If contact has 010 1234 5678 (normalized number is +cc 10 1234 5678),
+                                *      then the contact should be searched by keyword +cc 10 1234 5678
+                                */
+                               temp_len = SAFE_SNPRINTF(&query, &query_size, len, " WHERE ");
+                               if (0 <= temp_len)
+                                       len += temp_len;
+
+                               ret = ctsvc_clean_number(keyword, clean_num, sizeof(clean_num), false);
+                               if (0 < ret) {
+                                       const char *cc = ctsvc_get_network_cc(false);
+
+                                       temp_len = SAFE_SNPRINTF(&query, &query_size, len, "(normalized_number LIKE '%%");
+                                       if (0 <= temp_len)
+                                               len += temp_len;
+
+                                       if (cc && cc[0] == '7' && clean_num[0] == '8') {   /* Russia */
+                                               char normal_num[strlen(clean_num)+1+5];   /* for cc */
+                                               ret = ctsvc_normalize_number(clean_num, normal_num,
+                                                               sizeof(normal_num), false);
+                                               if (0 < ret)
+                                                       temp_len = SAFE_SNPRINTF(&query, &query_size, len, normal_num);
+                                               else
+                                                       temp_len = SAFE_SNPRINTF(&query, &query_size, len, clean_num);
+                                       } else {
+                                               temp_len = SAFE_SNPRINTF(&query, &query_size, len, clean_num);
+                                       }
+                                       if (0 <= temp_len)
+                                               len += temp_len;
+
+                                       temp_len = SAFE_SNPRINTF(&query, &query_size, len, "%%' OR cleaned_number LIKE '%%");
+                                       if (0 <= temp_len)
+                                               len += temp_len;
+
+                                       temp_len = SAFE_SNPRINTF(&query, &query_size, len, clean_num);
+                                       if (0 <= temp_len)
+                                               len += temp_len;
+
+                                       temp_len = SAFE_SNPRINTF(&query, &query_size, len, "%%')");
+                                       if (0 <= temp_len)
+                                               len += temp_len;
+                               } else {
+                                       char *temp_keyword = __db_get_str_with_escape((char*)keyword,
+                                                       strlen(keyword), true);
+                                       if (NULL == temp_keyword) {
+                                               /* LCOV_EXCL_START */
+                                               ERR("__db_get_str_with_escape() Fail");
+                                               free(query);
+                                               return CONTACTS_ERROR_OUT_OF_MEMORY;
+                                               /* LCOV_EXCL_STOP */
+                                       }
+
+                                       temp_len = SAFE_SNPRINTF(&query, &query_size, len, "(SELECT * FROM ");
+                                       if (0 <= temp_len)
+                                               len += temp_len;
+
+                                       temp_len = SAFE_SNPRINTF(&query, &query_size, len, table);
+                                       if (0 <= temp_len)
+                                               len += temp_len;
+
+                                       temp_len = SAFE_SNPRINTF(&query, &query_size, len, " WHERE number LIKE '%%");
+                                       if (0 <= temp_len)
+                                               len += temp_len;
+
+                                       temp_len = SAFE_SNPRINTF(&query, &query_size, len, temp_keyword);
+                                       if (0 <= temp_len)
+                                               len += temp_len;
+
+                                       temp_len = SAFE_SNPRINTF(&query, &query_size, len, "%%' ESCAPE '\\')");
+                                       if (0 <= temp_len)
+                                               len += temp_len;
+                                       free(temp_keyword);
+                               }
+                               need_or = true;
+                       }
+
+                       if (range & CONTACTS_SEARCH_RANGE_NAME) {
+                               if (need_or)
+                                       temp_len = SAFE_SNPRINTF(&query, &query_size, len, " OR ");
+                               else
+                                       temp_len = SAFE_SNPRINTF(&query, &query_size, len, " WHERE ");
+
+                               if (0 <= temp_len)
+                                       len += temp_len;
+
+                               temp_len = SAFE_SNPRINTF(&query, &query_size, len, "person_id IN (SELECT "
+                                               "person_id FROM "CTS_TABLE_CONTACTS" WHERE deleted = 0 AND contact_id IN");
+                               if (0 <= temp_len)
+                                       len += temp_len;
+
+                               /*
+                                * search contact from search_index table by name and join the results
+                                * FTS can support to serach with multiple words
+                                * If contact display_name is 'abc def', then the contact should be searched by 'def'
+                                */
+#if 0 // bixby pinyin search - get count API does not treat offset so remove belows for pinyin search
+                               int name_range = CONTACTS_SEARCH_RANGE_NAME;
+                               if (OFFSET_FOR_BIXBY_PINYIN_SEARCH == offset) name_range |= MASKING_BIT_FOR_BIXBY_PINYIN_SEARCH;
+                               temp_len = __db_append_search_query(keyword, &query, &query_size, len,
+                                               name_range);
+#else
+                               temp_len = __db_append_search_query(keyword, &query, &query_size, len,
+                                               CONTACTS_SEARCH_RANGE_NAME);
+#endif
+                               if (0 <= temp_len)
+                                       len = temp_len;
+
+                               temp_len = SAFE_SNPRINTF(&query, &query_size, len, ") ");
+                               if (0 <= temp_len)
+                                       len += temp_len;
+                       }
+
+                       temp_len = SAFE_SNPRINTF(&query, &query_size, len, ") as temp_contacts");
+                       if (0 <= temp_len)
+                               len += temp_len;
+               }
+               break;
+
+       case CTSVC_ENUM_URI_READ_ONLY_PERSON_EMAIL:
+               {
+                       bool need_or = false;
+                       if (range & CONTACTS_SEARCH_RANGE_NUMBER || range & CONTACTS_SEARCH_RANGE_DATA) {
+                               free(query);
+                               return CONTACTS_ERROR_INVALID_PARAMETER;
+                       }
+
+                       temp_len = SAFE_SNPRINTF(&query, &query_size, len, "SELECT ");
+                       if (0 <= temp_len)
+                               len += temp_len;
+
+                       temp_len = SAFE_SNPRINTF(&query, &query_size, len, projection);
+                       if (0 <= temp_len)
+                               len += temp_len;
+
+                       temp_len = SAFE_SNPRINTF(&query, &query_size, len, " FROM (");
+                       if (0 <= temp_len)
+                               len += temp_len;
+
+                       if (range & CONTACTS_SEARCH_RANGE_EMAIL) {
+                               /* search contact which has email address started with keyword */
+                               char *temp_keyword = __db_get_str_with_escape((char*)keyword,
+                                               strlen(keyword), true);
+                               if (NULL == temp_keyword) {
+                                       /* LCOV_EXCL_START */
+                                       ERR("__db_get_str_with_escape() Fail");
+                                       free(query);
+                                       return CONTACTS_ERROR_OUT_OF_MEMORY;
+                                       /* LCOV_EXCL_STOP */
+                               }
+                               temp_len = SAFE_SNPRINTF(&query, &query_size, len, "SELECT * FROM ");
+                               if (0 <= temp_len)
+                                       len += temp_len;
+
+                               temp_len = SAFE_SNPRINTF(&query, &query_size, len, table);
+                               if (0 <= temp_len)
+                                       len += temp_len;
+
+                               temp_len = SAFE_SNPRINTF(&query, &query_size, len, " WHERE (email LIKE '");
+                               if (0 <= temp_len)
+                                       len += temp_len;
+
+                               temp_len = SAFE_SNPRINTF(&query, &query_size, len, temp_keyword);
+                               if (0 <= temp_len)
+                                       len += temp_len;
+
+                               temp_len = SAFE_SNPRINTF(&query, &query_size, len, "%%' ESCAPE '\\')");
+                               if (0 <= temp_len)
+                                       len += temp_len;
+                               free(temp_keyword);
+                               need_or = true;
+                       }
+
+                       if (range & CONTACTS_SEARCH_RANGE_NAME) {
+                               if (need_or) {
+                                       temp_len = SAFE_SNPRINTF(&query, &query_size, len, " OR ");
+                                       if (0 <= temp_len)
+                                               len += temp_len;
+
+                               } else {
+                                       temp_len = SAFE_SNPRINTF(&query, &query_size, len, "SELECT * FROM ");
+                                       if (0 <= temp_len)
+                                               len += temp_len;
+                                       temp_len = SAFE_SNPRINTF(&query, &query_size, len, table);
+                                       if (0 <= temp_len)
+                                               len += temp_len;
+                                       temp_len = SAFE_SNPRINTF(&query, &query_size, len, " WHERE ");
+                                       if (0 <= temp_len)
+                                               len += temp_len;
+                               }
+
+                               snprintf(temp_query, sizeof(temp_query), "person_id IN (SELECT person_id "
+                                               "FROM "CTS_TABLE_CONTACTS" WHERE deleted = 0 AND contact_id ");
+                               temp_len = SAFE_SNPRINTF(&query, &query_size, len, temp_query);
+                               if (0 <= temp_len)
+                                       len += temp_len;
+                               temp_len = SAFE_SNPRINTF(&query, &query_size, len, " IN ");
+                               if (0 <= temp_len)
+                                       len += temp_len;
+                               temp_len = __db_append_search_query(keyword, &query, &query_size, len,
+                                               CONTACTS_SEARCH_RANGE_NAME);
+                               if (0 <= temp_len)
+                                       len = temp_len;
+                               temp_len = SAFE_SNPRINTF(&query, &query_size, len, ") ");
+                               if (0 <= temp_len)
+                                       len += temp_len;
+                       }
+
+                       temp_len = SAFE_SNPRINTF(&query, &query_size, len, ") ");
+                       if (0 <= temp_len)
+                               len += temp_len;
+               }
+               break;
+
+       case CTSVC_ENUM_URI_PERSON:
+               if (range & CONTACTS_SEARCH_RANGE_EMAIL) {
+                       free(query);
+                       return CONTACTS_ERROR_INVALID_PARAMETER;
+               }
+               temp_len = SAFE_SNPRINTF(&query, &query_size, len, "SELECT ");
+               if (0 <= temp_len)
+                       len += temp_len;
+
+               temp_len = SAFE_SNPRINTF(&query, &query_size, len, projection);
+               if (0 <= temp_len)
+                       len += temp_len;
+
+               temp_len = SAFE_SNPRINTF(&query, &query_size, len, " FROM ");
+               if (0 <= temp_len)
+                       len += temp_len;
+
+               temp_len = SAFE_SNPRINTF(&query, &query_size, len, table);
+               if (0 <= temp_len)
+                       len += temp_len;
+       }
+
+       if (true == is_snippet) {
+               bool need_union = false;
+               char cond_data[CTS_SQL_MAX_LEN] = {0};
+               char clean_number[SAFE_STRLEN(keyword) + 1];
+               ctsvc_clean_number(keyword, clean_number, sizeof(clean_number), false);
+               temp_len = SAFE_SNPRINTF(&query, &query_size, len,
+                       ", (SELECT contact_id temp_contact_id, "
+                               "datatype, _priority, _data FROM (");
+               if (0 <= temp_len)
+                       len += temp_len;
+
+               if (range & CONTACTS_SEARCH_RANGE_NAME) {
+                       snprintf(cond_data, sizeof(cond_data), "SELECT contact_id, "
+                                       "datatype, %d as _priority, 'a' as _data FROM "CTS_TABLE_DATA" "
+                                       "WHERE contact_id IN (", CTSVC_SNIPPET_PRIO_NAME);
+                       temp_len = SAFE_SNPRINTF(&query, &query_size, len, cond_data);
+                       if (0 <= temp_len)
+                               len += temp_len;
+
+                       char *query_name = _get_search_query_for_name(keyword);
+                       temp_len = SAFE_SNPRINTF(&query, &query_size, len, query_name);
+                       if (0 <= temp_len)
+                               len += temp_len;
+                       free(query_name);
+
+                       /* datatype=1 NAME */
+                       temp_len = SAFE_SNPRINTF(&query, &query_size, len, ") AND datatype=1 AND is_my_profile=0 ");
+                       if (0 <= temp_len)
+                               len += temp_len;
+
+                       need_union = true;
+               }
+               if (range & CONTACTS_SEARCH_RANGE_NUMBER) {
+                       if (true == need_union) {
+                               temp_len = SAFE_SNPRINTF(&query, &query_size, len, " UNION ");
+                               if (0 <= temp_len)
+                                       len += temp_len;
+                       }
+                       snprintf(cond_data, sizeof(cond_data), "SELECT contact_id, "
+                                       "datatype, %d as _priority, data3 as _data FROM "CTS_TABLE_DATA" "
+                                       "WHERE contact_id IN (", CTSVC_SNIPPET_PRIO_NUMBER);
+                       temp_len = SAFE_SNPRINTF(&query, &query_size, len, cond_data);
+                       if (0 <= temp_len)
+                               len += temp_len;
+
+                       char *query_number = _get_search_query_for_number(keyword);
+                       temp_len = SAFE_SNPRINTF(&query, &query_size, len, query_number);
+                       if (0 <= temp_len)
+                               len += temp_len;
+                       free(query_number);
+
+                       /* datatype=8 NUMBER */
+                       temp_len = SAFE_SNPRINTF(&query, &query_size, len, ") AND datatype=8 AND is_my_profile=0 ");
+                       if (0 <= temp_len)
+                               len += temp_len;
+
+                       need_union = true;
+               }
+               if (range & CONTACTS_SEARCH_RANGE_DATA) {
+                       if (true == need_union) {
+                               temp_len = SAFE_SNPRINTF(&query, &query_size, len, " UNION ");
+                               if (0 <= temp_len)
+                                       len += temp_len;
+                       }
+                       snprintf(cond_data, sizeof(cond_data), "SELECT contact_id, datatype, "
+                                       "(CASE "
+                                       "WHEN datatype=%d THEN %d " /* POSTAL       */
+                                       "WHEN datatype=%d THEN %d " /* COMPANY      */
+                                       "WHEN datatype=%d THEN %d " /* NICKNAME     */
+                                       "WHEN datatype=%d THEN %d " /* EMAIL        */
+                                       "WHEN datatype=%d THEN %d " /* NOTE         */
+                                       "END) as _priority, "
+                                       "(CASE "
+                                       "WHEN datatype=%d THEN (COALESCE(data5||' ','')||"
+                                       "COALESCE(data6||' ','')||COALESCE(data7||' ','')||"
+                                       "COALESCE(data8||' ','')||COALESCE(data9,'')) " /* POSTAL       */
+                                       "WHEN datatype=%d THEN (COALESCE(data3||' ','')||"
+                                       "COALESCE(data4||' ','')||COALESCE(data5||' ','')||"
+                                       "COALESCE(data6||' ','')||COALESCE(data7||' ','')||"
+                                       "COALESCE(data8||' ','')||COALESCE(data9||' ','')||"
+                                       "COALESCE(data10||' ','')||COALESCE(data11||' ','')) " /* COMPANY      */
+                                       "WHEN datatype=%d THEN data3 " /* NICKNAME     */
+                                       "WHEN datatype=%d THEN data3 " /* EMAIL        */
+                                       "WHEN datatype=%d THEN data3 " /* NOTE         */
+                                       "END) as _data FROM "CTS_TABLE_DATA" WHERE is_my_profile=0 AND contact_id IN (",
+                               CONTACTS_DATA_TYPE_POSTAL, CTSVC_SNIPPET_PRIO_POSTAL,
+                               CONTACTS_DATA_TYPE_COMPANY, CTSVC_SNIPPET_PRIO_COMPANY,
+                               CONTACTS_DATA_TYPE_NICKNAME, CTSVC_SNIPPET_PRIO_NICKNAME,
+                               CONTACTS_DATA_TYPE_EMAIL, CTSVC_SNIPPET_PRIO_EMAIL,
+                               CONTACTS_DATA_TYPE_NOTE, CTSVC_SNIPPET_PRIO_NOTE,
+                               CONTACTS_DATA_TYPE_POSTAL,
+                               CONTACTS_DATA_TYPE_COMPANY,
+                               CONTACTS_DATA_TYPE_NICKNAME,
+                               CONTACTS_DATA_TYPE_EMAIL,
+                               CONTACTS_DATA_TYPE_NOTE);
+                       temp_len = SAFE_SNPRINTF(&query, &query_size, len, cond_data);
+                       if (0 <= temp_len)
+                               len += temp_len;
+
+                       char *query_data = _get_search_query_for_data(keyword);
+                       temp_len = SAFE_SNPRINTF(&query, &query_size, len, query_data);
+                       if (0 <= temp_len)
+                               len += temp_len;
+                       free(query_data);
+
+                       temp_len = SAFE_SNPRINTF(&query, &query_size, len, ") AND _data IS NOT NULL "
+                                       "AND _data LIKE ('%%' || '");
+                       if (0 <= temp_len)
+                               len += temp_len;
+                       temp_len = SAFE_SNPRINTF(&query, &query_size, len, keyword);
+                       if (0 <= temp_len)
+                               len += temp_len;
+                       temp_len = SAFE_SNPRINTF(&query, &query_size, len, "' || '%%') ");
+                       if (0 <= temp_len)
+                               len += temp_len;
+               }
+               temp_len = SAFE_SNPRINTF(&query, &query_size, len, ")) as temp_data ON "
+                               "temp_data.temp_contact_id = temp_contacts.contact_id ");
+               if (0 <= temp_len)
+                       len += temp_len;
+       }
+
+       switch (enum_uri) {
+       case CTSVC_ENUM_URI_READ_ONLY_PERSON_CONTACT:
+       case CTSVC_ENUM_URI_READ_ONLY_PERSON_GROUP:
+       case CTSVC_ENUM_URI_READ_ONLY_PERSON_GROUP_ASSIGNED:
+       case CTSVC_ENUM_URI_READ_ONLY_PERSON_GROUP_NOT_ASSIGNED:
+               temp_len = SAFE_SNPRINTF(&query, &query_size, len, " WHERE temp_contacts.contact_id IN ");
+               if (0 <= temp_len)
+                       len += temp_len;
+               temp_len = __db_append_search_query(keyword, &query, &query_size, len, range);
+               if (0 <= temp_len)
+                       len = temp_len;
+               need_and = true;
+               break;
+
+       case CTSVC_ENUM_URI_READ_ONLY_PERSON_NUMBER:
+               break;
+       case CTSVC_ENUM_URI_READ_ONLY_PERSON_EMAIL:
+               break;
+       case CTSVC_ENUM_URI_PERSON:
+               temp_len = SAFE_SNPRINTF(&query, &query_size, len, ", (SELECT contact_id, person_id "
+                               "person_id_in_contact, addressbook_id FROM "CTS_TABLE_CONTACTS" "
+                               "WHERE deleted = 0 AND contact_id IN ");
+               if (0 <= temp_len)
+                       len += temp_len;
+
+               temp_len = __db_append_search_query(keyword, &query, &query_size, len, range);
+               if (0 <= temp_len)
+                       len = temp_len;
+
+               temp_len = SAFE_SNPRINTF(&query, &query_size, len,
+                               "GROUP BY person_id_in_contact) temp_contacts ON ");
+               if (0 <= temp_len)
+                       len += temp_len;
+
+               temp_len = SAFE_SNPRINTF(&query, &query_size, len, table);
+               if (0 <= temp_len)
+                       len += temp_len;
+
+               temp_len = SAFE_SNPRINTF(&query, &query_size, len,
+                               ".person_id = temp_contacts.person_id_in_contact");
+               if (0 <= temp_len)
+                       len += temp_len;
+               need_and = true;
+               break;
+       }
+
+       if (!ctsvc_can_access_restricted_addressbook()) {
+               if (need_and) {
+                       temp_len = SAFE_SNPRINTF(&query, &query_size, len,
+                                       " AND is_restricted=0 ");
+                       if (0 <= temp_len)
+                               len += temp_len;
+               }
+               else {
+                       temp_len = SAFE_SNPRINTF(&query, &query_size, len,
+                                       " WHERE is_restricted=0 ");
+                       if (0 <= temp_len)
+                               len += temp_len;
+               }
+       }
+
+       if (__ctsvc_db_view_has_display_name(view_uri, properties, ids_count))
+               sortkey = ctsvc_get_sort_column();
+
+       if (true == is_snippet) {
+               temp_len = 0;
+               switch (enum_uri) {
+               case CTSVC_ENUM_URI_READ_ONLY_PERSON_CONTACT:
+               case CTSVC_ENUM_URI_READ_ONLY_PERSON_GROUP:
+               case CTSVC_ENUM_URI_READ_ONLY_PERSON_GROUP_ASSIGNED:
+               case CTSVC_ENUM_URI_READ_ONLY_PERSON_GROUP_NOT_ASSIGNED:
+               case CTSVC_ENUM_URI_READ_ONLY_PERSON_NUMBER:
+               case CTSVC_ENUM_URI_READ_ONLY_PERSON_EMAIL:
+                       temp_len = SAFE_SNPRINTF(&query, &query_size, len, " GROUP BY temp_data.temp_contact_id");
+                       break;
+               case CTSVC_ENUM_URI_PERSON:
+                       temp_len = SAFE_SNPRINTF(&query, &query_size, len, " GROUP BY person_id");
+                       break;
+               }
+               if (0 <= temp_len)
+                       len += temp_len;
+       }
+
+       if (sortkey) {
+               len = __ctsvc_db_search_records_append_sort(view_uri, sortkey, keyword, len,
+                               &query, &query_size);
+       } else if (STRING_EQUAL == strcmp(view_uri, CTSVC_VIEW_URI_GROUP)) {
+               temp_len = SAFE_SNPRINTF(&query, &query_size, len, " ORDER BY group_prio");
+               if (0 <= temp_len) len += temp_len;
+       }
+
+       temp_len = SAFE_SNPRINTF(&query, &query_size, len, ") ");
+       if (0 <= temp_len) len += temp_len;
+
+       ret = ctsvc_query_get_first_int_result(query, out_count);
+       free(query);
+       if (CONTACTS_ERROR_NONE != ret) {
+               /* LCOV_EXCL_START */
+               ERR("ctsvc_query_get_first_int_result() Fail(%d)", ret);
+               return ret;
+               /* LCOV_EXCL_STOP */
+       }
+
+       return CONTACTS_ERROR_NONE;
+}
+
+
+static int __ctsvc_db_search_records(const char *view_uri,
+               const char *keyword,
+               int offset,
+               int limit,
+               bool is_snippet,
+               const char *start_match,
+               const char *end_match,
+               int token_number,
+               contacts_list_h *out_list)
+{
+       int ret;
+       unsigned int count;
+       char *projection;
+       const property_info_s *p;
+       bool can_keyword_search = false;
+       int enum_uri = 0;
+       int range = CONTACTS_SEARCH_RANGE_NAME | CONTACTS_SEARCH_RANGE_NUMBER | CONTACTS_SEARCH_RANGE_DATA;
+
+       RETV_IF(NULL == keyword, CONTACTS_ERROR_INVALID_PARAMETER);
+
+       can_keyword_search = __ctsvc_db_view_can_keyword_search(view_uri, &enum_uri);
+       RETVM_IF(false == can_keyword_search, CONTACTS_ERROR_INVALID_PARAMETER,
+                       "can not keyword search");
+
+       p = ctsvc_view_get_all_property_infos(view_uri, &count);
+       ret = __db_create_projection(view_uri, p, count, NULL, 0, &projection, is_snippet);
+       if (CONTACTS_ERROR_NONE != ret) {
+               /* LCOV_EXCL_START */
+               ERR("__db_create_projection() Fail(%d)", ret);
+               return ret;
+               /* LCOV_EXCL_STOP */
+       }
+
+       ret = __ctsvc_db_search_records_exec(view_uri, enum_uri, p, count, projection,
+                       keyword, offset, limit, range, is_snippet, start_match, end_match, token_number, out_list);
+       free(projection);
+
+       return ret;
+}
+
+
+static int __ctsvc_db_get_count_for_search_records(const char *view_uri,
+               const char *keyword,
+               bool is_snippet,
+               const char *start_match,
+               const char *end_match,
+               int token_number,
+               int *out_count)
+{
+       int ret;
+       unsigned int count;
+       char *projection;
+       const property_info_s *p;
+       bool can_keyword_search = false;
+       int enum_uri = 0;
+       int range = CONTACTS_SEARCH_RANGE_NAME | CONTACTS_SEARCH_RANGE_NUMBER | CONTACTS_SEARCH_RANGE_DATA;
+
+       RETV_IF(NULL == keyword, CONTACTS_ERROR_INVALID_PARAMETER);
+
+       can_keyword_search = __ctsvc_db_view_can_keyword_search(view_uri, &enum_uri);
+       RETVM_IF(false == can_keyword_search, CONTACTS_ERROR_INVALID_PARAMETER, "can not keyword search");
+
+       p = ctsvc_view_get_all_property_infos(view_uri, &count);
+       ret = __db_create_projection(view_uri, p, count, NULL, 0, &projection, is_snippet);
+       if (CONTACTS_ERROR_NONE != ret) {
+               /* LCOV_EXCL_START */
+               ERR("__db_create_projection() Fail(%d)", ret);
+               return ret;
+               /* LCOV_EXCL_STOP */
+       }
+
+       ret = __ctsvc_db_get_count_for_search_records_exec(view_uri, enum_uri, p, count, projection,
+                       keyword, range, is_snippet, start_match, end_match, token_number, out_count);
+
+       free(projection);
+
+       return ret;
+}
+
+
+static int __ctsvc_db_search_records_with_range(const char *view_uri,
+               const char *keyword,
+               int offset,
+               int limit,
+               int range,
+               bool is_snippet,
+               const char *start_match,
+               const char *end_match,
+               int token_number,
+               contacts_list_h *out_list)
+{
+       int ret;
+       unsigned int count;
+       char *projection;
+       const property_info_s *p;
+       bool can_keyword_search = false;
+       int eunm_uri = 0;
+
+       RETV_IF(NULL == keyword, CONTACTS_ERROR_INVALID_PARAMETER);
+
+       can_keyword_search = __ctsvc_db_view_can_keyword_search(view_uri, &eunm_uri);
+       RETV_IF(false == can_keyword_search, CONTACTS_ERROR_INVALID_PARAMETER);
+
+       p = ctsvc_view_get_all_property_infos(view_uri, &count);
+       ret = __db_create_projection(view_uri, p, count, NULL, 0, &projection, is_snippet);
+       RETVM_IF(CONTACTS_ERROR_NONE != ret, ret, "__db_create_projection() Fail(%d)", ret);
+
+       ret = __ctsvc_db_search_records_exec(view_uri, eunm_uri, p, count, projection,
+                       keyword, offset, limit, range, is_snippet, start_match, end_match, token_number, out_list);
+       free(projection);
+
+       return ret;
+}
+
+
+static int __ctsvc_db_get_count_for_search_records_with_range(const char *view_uri,
+               const char *keyword,
+               int range,
+               bool is_snippet,
+               const char *start_match,
+               const char *end_match,
+               int token_number,
+               int *out_count)
+{
+       int ret;
+       unsigned int count;
+       char *projection;
+       const property_info_s *p;
+       bool can_keyword_search = false;
+       int eunm_uri = 0;
+
+       RETV_IF(NULL == keyword, CONTACTS_ERROR_INVALID_PARAMETER);
+
+       can_keyword_search = __ctsvc_db_view_can_keyword_search(view_uri, &eunm_uri);
+       RETV_IF(false == can_keyword_search, CONTACTS_ERROR_INVALID_PARAMETER);
+
+       p = ctsvc_view_get_all_property_infos(view_uri, &count);
+       ret = __db_create_projection(view_uri, p, count, NULL, 0, &projection, is_snippet);
+       RETVM_IF(CONTACTS_ERROR_NONE != ret, ret, "__db_create_projection() Fail(%d)", ret);
+
+       ret = __ctsvc_db_get_count_for_search_records_exec(view_uri, eunm_uri, p, count, projection,
+                       keyword, range, is_snippet, start_match, end_match, token_number, out_count);
+
+       free(projection);
+
+       return ret;
+}
+
+
+static inline int __ctsvc_db_search_records_with_query_exec(ctsvc_query_s *s_query,
+               int enum_uri,
+               const char *projection,
+               const char *condition,
+               GSList *bind,
+               const char *keyword,
+               int offset,
+               int limit,
+               bool is_snippet,
+               const char *start_match,
+               const char *end_match,
+               int token_number,
+               contacts_list_h *out_list)
+{
+       char *query = NULL;
+       int query_size;
+       int temp_len;
+       int len;
+       int ret;
+       int i;
+       int type;
+       bool person_contact_query = false;
+       GSList *cursor;
+       cts_stmt stmt = NULL;
+       contacts_list_h list = NULL;
+       const char *table;
+       const char *sortkey = NULL;
+       int range = CONTACTS_SEARCH_RANGE_NAME | CONTACTS_SEARCH_RANGE_NUMBER | CONTACTS_SEARCH_RANGE_DATA;
+
+       RETV_IF(NULL == projection || '\0' == *projection, CONTACTS_ERROR_INVALID_PARAMETER);
+
+       ret = ctsvc_db_get_table_name(s_query->view_uri, &table);
+       RETVM_IF(CONTACTS_ERROR_NONE != ret, ret, "Invalid view uri(%s)", s_query->view_uri);
+
+       query_size = CTS_SQL_MAX_LEN;
+       query = calloc(1, query_size);
+       if (NULL == query) {
+               /* LCOV_EXCL_START */
+               ERR("calloc() Fail");
+               return CONTACTS_ERROR_OUT_OF_MEMORY;
+               /* LCOV_EXCL_STOP */
+       }
+
+       len = 0;
+
+       temp_len = SAFE_SNPRINTF(&query, &query_size, len, "SELECT ");
+       if (0 <= temp_len)
+               len += temp_len;
+
+       if (s_query->distinct) {
+               temp_len = SAFE_SNPRINTF(&query, &query_size, len, "DISTINCT ");
+               if (0 <= temp_len)
+                       len += temp_len;
+       }
+       temp_len = SAFE_SNPRINTF(&query, &query_size, len, projection);
+       if (0 <= temp_len)
+               len += temp_len;
+       temp_len = SAFE_SNPRINTF(&query, &query_size, len, " FROM ");
+       if (0 <= temp_len)
+               len += temp_len;
+       temp_len = SAFE_SNPRINTF(&query, &query_size, len, table);
+       if (0 <= temp_len)
+               len += temp_len;
+
+       switch (enum_uri) {
+       case CTSVC_ENUM_URI_READ_ONLY_PERSON_CONTACT:
+       case CTSVC_ENUM_URI_READ_ONLY_PERSON_GROUP:
+       case CTSVC_ENUM_URI_READ_ONLY_PERSON_GROUP_ASSIGNED:
+       case CTSVC_ENUM_URI_READ_ONLY_PERSON_GROUP_NOT_ASSIGNED:
+       case CTSVC_ENUM_URI_PERSON:
+               break;
+
+       case CTSVC_ENUM_URI_READ_ONLY_PERSON_NUMBER:
+       case CTSVC_ENUM_URI_READ_ONLY_PERSON_EMAIL:
+       default:
+               free(query);
+               return CONTACTS_ERROR_INVALID_PARAMETER;
+       }
+
+       if (true == is_snippet) {
+               bool need_union = false;
+               char cond_data[CTS_SQL_MAX_LEN] = {0};
+               char clean_number[SAFE_STRLEN(keyword) + 1];
+               ctsvc_clean_number(keyword, clean_number, sizeof(clean_number), false);
+               temp_len = SAFE_SNPRINTF(&query, &query_size, len, ", (SELECT contact_id temp_contact_id, "
+                               "datatype, _priority, _data FROM (");
+               if (0 <= temp_len)
+                       len += temp_len;
+
+               if (range & CONTACTS_SEARCH_RANGE_NAME) {
+                       snprintf(cond_data, sizeof(cond_data), "SELECT contact_id, "
+                                       "datatype, %d as _priority, 'a' as _data FROM "CTS_TABLE_DATA" "
+                                       "WHERE contact_id IN (", CTSVC_SNIPPET_PRIO_NAME);
+                       temp_len = SAFE_SNPRINTF(&query, &query_size, len, cond_data);
+                       if (0 <= temp_len)
+                               len += temp_len;
+
+                       char *query_name = _get_search_query_for_name(keyword);
+                       temp_len = SAFE_SNPRINTF(&query, &query_size, len, query_name);
+                       if (0 <= temp_len)
+                               len += temp_len;
+                       free(query_name);
+
+                       /* datatype=1 NAME */
+                       temp_len = SAFE_SNPRINTF(&query, &query_size, len, ") AND datatype=1 ");
+                       if (0 <= temp_len)
+                               len += temp_len;
+
+                       need_union = true;
+               }
+               if (range & CONTACTS_SEARCH_RANGE_NUMBER) {
+                       if (true == need_union) {
+                               temp_len = SAFE_SNPRINTF(&query, &query_size, len, " UNION ");
+                               if (0 <= temp_len)
+                                       len += temp_len;
+                       }
+                       snprintf(cond_data, sizeof(cond_data), "SELECT contact_id, "
+                                       "datatype, %d as _priority, data3 as _data FROM "CTS_TABLE_DATA" "
+                                       "WHERE contact_id IN (", CTSVC_SNIPPET_PRIO_NUMBER);
+                       temp_len = SAFE_SNPRINTF(&query, &query_size, len, cond_data);
+                       if (0 <= temp_len)
+                               len += temp_len;
+
+                       char *query_number = _get_search_query_for_number(keyword);
+                       temp_len = SAFE_SNPRINTF(&query, &query_size, len, query_number);
+                       if (0 <= temp_len)
+                               len += temp_len;
+                       free(query_number);
+
+                       /* datatype=8 NUMBER */
+                       temp_len = SAFE_SNPRINTF(&query, &query_size, len, ") AND datatype=8 ");
+                       if (0 <= temp_len)
+                               len += temp_len;
+
+                       need_union = true;
+               }
+               if (range & CONTACTS_SEARCH_RANGE_DATA) {
+                       if (true == need_union) {
+                               temp_len = SAFE_SNPRINTF(&query, &query_size, len, " UNION ");
+                               if (0 <= temp_len)
+                                       len += temp_len;
+                       }
+                       snprintf(cond_data, sizeof(cond_data), "SELECT contact_id, datatype, "
+                                       "(CASE "
+                                       "WHEN datatype=%d THEN %d " /* POSTAL       */
+                                       "WHEN datatype=%d THEN %d " /* COMPANY      */
+                                       "WHEN datatype=%d THEN %d " /* NICKNAME     */
+                                       "WHEN datatype=%d THEN %d " /* EMAIL        */
+                                       "WHEN datatype=%d THEN %d " /* NOTE         */
+                                       "END) as _priority, "
+                                       "(CASE "
+                                       "WHEN datatype=%d THEN (COALESCE(data5||' ','')||"
+                                       "COALESCE(data6||' ','')||COALESCE(data7||' ','')||"
+                                       "COALESCE(data8||' ','')||COALESCE(data9,'')) " /* POSTAL       */
+                                       "WHEN datatype=%d THEN (COALESCE(data3||' ','')||"
+                                       "COALESCE(data4||' ','')||COALESCE(data5||' ','')||"
+                                       "COALESCE(data6||' ','')||COALESCE(data7||' ','')||"
+                                       "COALESCE(data8||' ','')||COALESCE(data9||' ','')||"
+                                       "COALESCE(data10||' ','')||COALESCE(data11||' ','')) " /* COMPANY      */
+                                       "WHEN datatype=%d THEN data3 " /* NICKNAME     */
+                                       "WHEN datatype=%d THEN data3 " /* EMAIL        */
+                                       "WHEN datatype=%d THEN data3 " /* NOTE         */
+                                       "END) as _data FROM "CTS_TABLE_DATA" WHERE contact_id IN (",
+                               CONTACTS_DATA_TYPE_POSTAL, CTSVC_SNIPPET_PRIO_POSTAL,
+                               CONTACTS_DATA_TYPE_COMPANY, CTSVC_SNIPPET_PRIO_COMPANY,
+                               CONTACTS_DATA_TYPE_NICKNAME, CTSVC_SNIPPET_PRIO_NICKNAME,
+                               CONTACTS_DATA_TYPE_EMAIL, CTSVC_SNIPPET_PRIO_EMAIL,
+                               CONTACTS_DATA_TYPE_NOTE, CTSVC_SNIPPET_PRIO_NOTE,
+                               CONTACTS_DATA_TYPE_POSTAL,
+                               CONTACTS_DATA_TYPE_COMPANY,
+                               CONTACTS_DATA_TYPE_NICKNAME,
+                               CONTACTS_DATA_TYPE_EMAIL,
+                               CONTACTS_DATA_TYPE_NOTE);
+                       temp_len = SAFE_SNPRINTF(&query, &query_size, len, cond_data);
+                       if (0 <= temp_len)
+                               len += temp_len;
+
+                       char *query_data = _get_search_query_for_data(keyword);
+                       temp_len = SAFE_SNPRINTF(&query, &query_size, len, query_data);
+                       if (0 <= temp_len)
+                               len += temp_len;
+                       free(query_data);
+
+                       temp_len = SAFE_SNPRINTF(&query, &query_size, len, ") AND _data IS NOT NULL "
+                                       "AND _data LIKE ('%%' || '");
+                       if (0 <= temp_len)
+                               len += temp_len;
+                       temp_len = SAFE_SNPRINTF(&query, &query_size, len, keyword);
+                       if (0 <= temp_len)
+                               len += temp_len;
+                       temp_len = SAFE_SNPRINTF(&query, &query_size, len, "' || '%%') ");
+                       if (0 <= temp_len)
+                               len += temp_len;
+               }
+               temp_len = SAFE_SNPRINTF(&query, &query_size, len, ")) as temp_data ON "
+                               "temp_data.temp_contact_id = contact_id ");
+               if (0 <= temp_len)
+                       len += temp_len;
+       }
+
+       switch (enum_uri) {
+       case CTSVC_ENUM_URI_READ_ONLY_PERSON_CONTACT:
+       case CTSVC_ENUM_URI_READ_ONLY_PERSON_GROUP:
+       case CTSVC_ENUM_URI_READ_ONLY_PERSON_GROUP_ASSIGNED:
+       case CTSVC_ENUM_URI_READ_ONLY_PERSON_GROUP_NOT_ASSIGNED:
+               temp_len = SAFE_SNPRINTF(&query, &query_size, len, " WHERE person_id IN (SELECT "
+                               "person_id FROM "CTS_TABLE_CONTACTS" WHERE deleted = 0 AND contact_id IN ");
+               if (0 <= temp_len)
+                       len += temp_len;
+
+               person_contact_query = true;
+               break;
+
+       case CTSVC_ENUM_URI_PERSON:
+               temp_len = SAFE_SNPRINTF(&query, &query_size, len, ", (SELECT contact_id, "
+                               "person_id person_id_in_contact, addressbook_id FROM "CTS_TABLE_CONTACTS" "
+                               "WHERE deleted = 0) temp_contacts ON ");
+               if (0 <= temp_len)
+                       len += temp_len;
+
+               temp_len = SAFE_SNPRINTF(&query, &query_size, len, table);
+               if (0 <= temp_len)
+                       len += temp_len;
+
+               temp_len = SAFE_SNPRINTF(&query, &query_size, len,
+                               ".person_id = temp_contacts.person_id_in_contact WHERE temp_contacts.contact_id IN ");
+               if (0 <= temp_len)
+                       len += temp_len;
+               break;
+
+       case CTSVC_ENUM_URI_READ_ONLY_PERSON_NUMBER:
+       case CTSVC_ENUM_URI_READ_ONLY_PERSON_EMAIL:
+       default:
+               return CONTACTS_ERROR_INVALID_PARAMETER;
+       }
+
+       temp_len = __db_append_search_query(keyword, &query, &query_size, len, range);
+       if (0 <= temp_len)
+               len = temp_len;
+
+       if (person_contact_query) {
+               temp_len = SAFE_SNPRINTF(&query, &query_size, len, ") ");
+               if (0 <= temp_len)
+                       len += temp_len;
+       }
+
+       if (condition && *condition) {
+               if (person_contact_query) {
+                       temp_len = SAFE_SNPRINTF(&query, &query_size, len, " AND contact_id IN "
+                                       "(SELECT contact_id FROM ");
+                       if (0 <= temp_len)
+                               len += temp_len;
+                       temp_len = SAFE_SNPRINTF(&query, &query_size, len, table);
+                       if (0 <= temp_len)
+                               len += temp_len;
+                       temp_len = SAFE_SNPRINTF(&query, &query_size, len, " WHERE ");
+                       if (0 <= temp_len)
+                               len += temp_len;
+               } else {
+                       temp_len = SAFE_SNPRINTF(&query, &query_size, len, " AND (");
+                       if (0 <= temp_len)
+                               len += temp_len;
+               }
+               temp_len = SAFE_SNPRINTF(&query, &query_size, len, condition);
+               if (0 <= temp_len)
+                       len += temp_len;
+               temp_len = SAFE_SNPRINTF(&query, &query_size, len, ")");
+               if (0 <= temp_len)
+                       len += temp_len;
+       }
+
+       if (true == is_snippet) {
+               switch (enum_uri) {
+               case CTSVC_ENUM_URI_READ_ONLY_PERSON_CONTACT:
+               case CTSVC_ENUM_URI_READ_ONLY_PERSON_GROUP:
+               case CTSVC_ENUM_URI_READ_ONLY_PERSON_GROUP_ASSIGNED:
+               case CTSVC_ENUM_URI_READ_ONLY_PERSON_GROUP_NOT_ASSIGNED:
+               case CTSVC_ENUM_URI_READ_ONLY_PERSON_NUMBER:
+               case CTSVC_ENUM_URI_READ_ONLY_PERSON_EMAIL:
+                       temp_len = SAFE_SNPRINTF(&query, &query_size, len, " GROUP BY temp_data.temp_contact_id");
+                       break;
+               case CTSVC_ENUM_URI_PERSON:
+                       temp_len = SAFE_SNPRINTF(&query, &query_size, len, " GROUP BY person_id");
+                       break;
+               }
+               if (0 <= temp_len)
+                       len += temp_len;
+       }
+
+       if (__ctsvc_db_view_has_display_name(s_query->view_uri, s_query->properties, s_query->property_count))
+               sortkey = ctsvc_get_sort_column();
+
+       if (s_query->sort_property_id) {
+               const char *field_name;
+
+               switch (s_query->sort_property_id) {
+               case CTSVC_PROPERTY_PERSON_DISPLAY_NAME:
+               case CTSVC_PROPERTY_CONTACT_DISPLAY_NAME:
+                       if (sortkey) {
+                               temp_len = SAFE_SNPRINTF(&query, &query_size, len, " ORDER BY ");
+                               if (0 <= temp_len)
+                                       len += temp_len;
+                               temp_len = SAFE_SNPRINTF(&query, &query_size, len, sortkey);
+                               if (0 <= temp_len)
+                                       len += temp_len;
+                               if (false == s_query->sort_asc) {
+                                       temp_len = SAFE_SNPRINTF(&query, &query_size, len, " DESC ");
+                                       if (0 <= temp_len)
+                                               len += temp_len;
+                               }
+                       }
+                       break;
+               default:
+                       field_name = __ctsvc_db_get_property_field_name(s_query->properties,
+                                       s_query->property_count, QUERY_SORTKEY, s_query->sort_property_id);
+                       if (field_name) {
+                               temp_len = SAFE_SNPRINTF(&query, &query_size, len, " ORDER BY ");
+                               if (0 <= temp_len)
+                                       len += temp_len;
+                               temp_len = SAFE_SNPRINTF(&query, &query_size, len, field_name);
+                               if (0 <= temp_len)
+                                       len += temp_len;
+                               if (false == s_query->sort_asc) {
+                                       temp_len = SAFE_SNPRINTF(&query, &query_size, len, " DESC ");
+                                       if (0 <= temp_len)
+                                               len += temp_len;
+                               }
+                       } else if (sortkey) {
+                               len += snprintf(query+len, sizeof(query)-len, " ORDER BY %s", sortkey);
+                               temp_len = SAFE_SNPRINTF(&query, &query_size, len, " ORDER BY ");
+                               if (0 <= temp_len)
+                                       len += temp_len;
+                               temp_len = SAFE_SNPRINTF(&query, &query_size, len, sortkey);
+                               if (0 <= temp_len)
+                                       len += temp_len;
+                       }
+                       break;
+               }
+       } else if (sortkey) {
+               len = __ctsvc_db_search_records_append_sort(s_query->view_uri, sortkey, keyword,
+                               len, &query, &query_size);
+       } else if (STRING_EQUAL == strcmp(s_query->view_uri, CTSVC_VIEW_URI_GROUP)) {
+               temp_len = SAFE_SNPRINTF(&query, &query_size, len, " ORDER BY group_prio");
+               if (0 <= temp_len)
+                       len += temp_len;
+       }
+
+       do {
+               if (0 == limit)
+                       break;
+
+               char temp_str[20] = {0};
+               snprintf(temp_str, sizeof(temp_str), " LIMIT %d", limit);
+               temp_len = SAFE_SNPRINTF(&query, &query_size, len, temp_str);
+               if (0 <= temp_len)
+                       len += temp_len;
+
+               if (offset <= 0)
+                       break;
+
+               snprintf(temp_str, sizeof(temp_str), " OFFSET %d", offset);
+               temp_len = SAFE_SNPRINTF(&query, &query_size, len, temp_str);
+               if (0 <= temp_len)
+                       len += temp_len;
+       } while (0);
+
+       ret = ctsvc_query_prepare(query, &stmt);
+       if (NULL == stmt) {
+               /* LCOV_EXCL_START */
+               ERR("ctsvc_query_prepare() Fail(%d)[%s]", ret, query);
+               free(query);
+               return ret;
+               /* LCOV_EXCL_STOP */
+       }
+       free(query);
+
+       i = 1;
+       len = g_slist_length(bind);
+       for (cursor = bind; cursor; cursor = cursor->next, i++)
+               ctsvc_stmt_bind_text(stmt, i, cursor->data);
+
+       contacts_list_create(&list);
+       while ((ret = ctsvc_stmt_step(stmt))) {
+               contacts_record_h record;
+               if (1 != ret) {
+                       /* LCOV_EXCL_START */
+                       ERR("ctsvc_stmt_step() Fail(%d)", ret);
+                       ctsvc_stmt_finalize(stmt);
+                       contacts_list_destroy(list, true);
+                       return ret;
+                       /* LCOV_EXCL_STOP */
+               }
+
+               if (ctsvc_view_get_record_type(s_query->view_uri) == CTSVC_RECORD_PERSON) {
+                       unsigned int ids_count;
+                       unsigned int *project;
+                       if (0 == s_query->projection_count)
+                               ids_count = s_query->property_count;
+                       else
+                               ids_count = s_query->projection_count;
+
+                       project = malloc(sizeof(unsigned int)*ids_count);
+
+                       for (i = 0; i < ids_count; i++) {
+                               if (0 == s_query->projection_count)
+                                       project[i] = s_query->properties[i].property_id;
+                               else
+                                       project[i] = s_query->projection[i];
+                       }
+
+                       ret = ctsvc_db_person_create_record_from_stmt_with_projection(stmt, project,
+                                       ids_count, is_snippet, keyword, start_match, end_match, token_number, &record);
+                       if (CONTACTS_ERROR_NONE != ret)
+                               /* LCOV_EXCL_START */
+                               ERR("ctsvc_db_person_create_record_from_stmt_with_projection() Fail(%d)", ret);
+                       /* LCOV_EXCL_STOP */
+
+                       free(project);
+               } else {
+                       contacts_record_create(s_query->view_uri, (contacts_record_h*)&record);
+                       int field_count;
+                       if (0 == s_query->projection_count) {
+                               field_count = s_query->property_count;
+                       } else {
+                               field_count = s_query->projection_count;
+
+                               int err = ctsvc_record_set_projection_flags(record, s_query->projection,
+                                               s_query->projection_count, s_query->property_count);
+                               if (CONTACTS_ERROR_NONE != err)
+                                       ASSERT_NOT_REACHED("To set projection is Fail");
+                       }
+
+                       for (i = 0; i < field_count; i++) {
+                               int property_id;
+
+                               if (0 == s_query->projection_count)
+                                       property_id = s_query->properties[i].property_id;
+                               else
+                                       property_id = s_query->projection[i];
+
+                               type = __ctsvc_db_get_property_type(s_query->properties,
+                                               s_query->property_count, property_id);
+
+                               char *temp = NULL;
+                               switch (type) {
+                               case CTSVC_VIEW_DATA_TYPE_INT:
+                                       ctsvc_record_set_int(record, property_id, ctsvc_stmt_get_int(stmt, i));
+                                       break;
+                               case CTSVC_VIEW_DATA_TYPE_STR:
+                                       temp = ctsvc_stmt_get_text(stmt, i);
+                                       if (CTSVC_PROPERTY_PERSON_SNIPPET_STRING == property_id) {
+                                               temp = ctsvc_utils_get_modified_str(temp, is_snippet, keyword,
+                                                               start_match, end_match, token_number);
+                                       }
+                                       ctsvc_record_set_str(record, property_id, temp);
+                                       break;
+                               case CTSVC_VIEW_DATA_TYPE_BOOL:
+                                       ctsvc_record_set_bool(record, property_id, (ctsvc_stmt_get_int(stmt, i) ? true : false));
+                                       break;
+                               case CTSVC_VIEW_DATA_TYPE_LLI:
+                                       ctsvc_record_set_lli(record, property_id, ctsvc_stmt_get_int64(stmt, i));
+                                       break;
+                               case CTSVC_VIEW_DATA_TYPE_DOUBLE:
+                                       ctsvc_record_set_double(record, property_id, ctsvc_stmt_get_dbl(stmt, i));
+                                       break;
+                               default:
+                                       /* LCOV_EXCL_START */
+                                       ERR("unknown type (%d)", type);
+                                       break;
+                                       /* LCOV_EXCL_STOP */
+                               }
+                       }
+               }
+               ctsvc_list_prepend(list, record);
+       }
+       ctsvc_stmt_finalize(stmt);
+       ctsvc_list_reverse(list);
 
-       return ret;
+       *out_list = list;
+       return CONTACTS_ERROR_NONE;
 }
 
-static inline int __ctsvc_db_search_records_with_query_exec(ctsvc_query_s *s_query,
+static inline int __ctsvc_db_get_count_for_search_records_with_query_exec(ctsvc_query_s *s_query,
                int enum_uri,
                const char *projection,
                const char *condition,
                GSList *bind,
                const char *keyword,
-               int offset,
-               int limit,
                bool is_snippet,
                const char *start_match,
                const char *end_match,
                int token_number,
-               contacts_list_h *out_list)
+               int *out_count)
 {
        char *query = NULL;
        int query_size;
        int temp_len;
        int len;
        int ret;
-       int i;
        int type;
        bool person_contact_query = false;
-       GSList *cursor;
-       cts_stmt stmt = NULL;
-       contacts_list_h list = NULL;
        const char *table;
        const char *sortkey = NULL;
        int range = CONTACTS_SEARCH_RANGE_NAME | CONTACTS_SEARCH_RANGE_NUMBER | CONTACTS_SEARCH_RANGE_DATA;
 
+#if 0 // bixby pinyin search - get count API does not treat offset so remove belows for pinyin search
+       if (OFFSET_FOR_BIXBY_PINYIN_SEARCH == offset) range |= MASKING_BIT_FOR_BIXBY_PINYIN_SEARCH;
+#endif
+
        RETV_IF(NULL == projection || '\0' == *projection, CONTACTS_ERROR_INVALID_PARAMETER);
 
        ret = ctsvc_db_get_table_name(s_query->view_uri, &table);
@@ -3200,6 +4326,10 @@ static inline int __ctsvc_db_search_records_with_query_exec(ctsvc_query_s *s_que
 
        len = 0;
 
+       temp_len = SAFE_SNPRINTF(&query, &query_size, len, "SELECT COUNT(*) FROM (");
+       if (0 <= temp_len)
+               len += temp_len;
+
        temp_len = SAFE_SNPRINTF(&query, &query_size, len, "SELECT ");
        if (0 <= temp_len)
                len += temp_len;
@@ -3225,6 +4355,7 @@ static inline int __ctsvc_db_search_records_with_query_exec(ctsvc_query_s *s_que
        case CTSVC_ENUM_URI_READ_ONLY_PERSON_GROUP_ASSIGNED:
        case CTSVC_ENUM_URI_READ_ONLY_PERSON_GROUP_NOT_ASSIGNED:
        case CTSVC_ENUM_URI_PERSON:
+       case CTSVC_ENUM_URI_READ_ONLY_PERSON_CONTACT_COMPANY:
                break;
 
        case CTSVC_ENUM_URI_READ_ONLY_PERSON_NUMBER:
@@ -3239,7 +4370,7 @@ static inline int __ctsvc_db_search_records_with_query_exec(ctsvc_query_s *s_que
                char cond_data[CTS_SQL_MAX_LEN] = {0};
                char clean_number[SAFE_STRLEN(keyword) + 1];
                ctsvc_clean_number(keyword, clean_number, sizeof(clean_number), false);
-               temp_len = SAFE_SNPRINTF(&query, &query_size, len, ", (SELECT contact_id temp_contact_id, "
+               temp_len = SAFE_SNPRINTF(&query, &query_size, len, ", (SELECT person_id as temp_person_id, "
                                "datatype, _priority, _data FROM (");
                if (0 <= temp_len)
                        len += temp_len;
@@ -3349,8 +4480,15 @@ static inline int __ctsvc_db_search_records_with_query_exec(ctsvc_query_s *s_que
                        if (0 <= temp_len)
                                len += temp_len;
                }
-               temp_len = SAFE_SNPRINTF(&query, &query_size, len, ")) as temp_data ON "
-                               "temp_data.temp_contact_id = contact_id ");
+
+               if (enum_uri != CTSVC_ENUM_URI_PERSON) {
+                       temp_len = SAFE_SNPRINTF(&query, &query_size, len, ") as temp, contacts on temp.contact_id = contacts.contact_id where deleted=0) as temp_data ON "
+                                       "temp_data.temp_person_id = person_id ");
+               }
+               else {
+                       temp_len = SAFE_SNPRINTF(&query, &query_size, len, ") as temp, contacts on temp.contact_id = contacts.contact_id where deleted=0) as temp_data ON "
+                                       "temp_data.temp_person_id = temp_contacts.person_id_in_contact ");
+               }
                if (0 <= temp_len)
                        len += temp_len;
        }
@@ -3360,6 +4498,7 @@ static inline int __ctsvc_db_search_records_with_query_exec(ctsvc_query_s *s_que
        case CTSVC_ENUM_URI_READ_ONLY_PERSON_GROUP:
        case CTSVC_ENUM_URI_READ_ONLY_PERSON_GROUP_ASSIGNED:
        case CTSVC_ENUM_URI_READ_ONLY_PERSON_GROUP_NOT_ASSIGNED:
+       case CTSVC_ENUM_URI_READ_ONLY_PERSON_CONTACT_COMPANY:
                temp_len = SAFE_SNPRINTF(&query, &query_size, len, " WHERE person_id IN (SELECT "
                                "person_id FROM "CTS_TABLE_CONTACTS" WHERE deleted = 0 AND contact_id IN ");
                if (0 <= temp_len)
@@ -3388,6 +4527,7 @@ static inline int __ctsvc_db_search_records_with_query_exec(ctsvc_query_s *s_que
        case CTSVC_ENUM_URI_READ_ONLY_PERSON_NUMBER:
        case CTSVC_ENUM_URI_READ_ONLY_PERSON_EMAIL:
        default:
+               free(query);
                return CONTACTS_ERROR_INVALID_PARAMETER;
        }
 
@@ -3426,6 +4566,12 @@ static inline int __ctsvc_db_search_records_with_query_exec(ctsvc_query_s *s_que
                        len += temp_len;
        }
 
+       if (!ctsvc_can_access_restricted_addressbook()) {
+               temp_len = SAFE_SNPRINTF(&query, &query_size, len, "AND is_restricted=0 ");
+               if (0 <= temp_len)
+                       len += temp_len;
+       }
+
        if (true == is_snippet) {
                switch (enum_uri) {
                case CTSVC_ENUM_URI_READ_ONLY_PERSON_CONTACT:
@@ -3434,7 +4580,7 @@ static inline int __ctsvc_db_search_records_with_query_exec(ctsvc_query_s *s_que
                case CTSVC_ENUM_URI_READ_ONLY_PERSON_GROUP_NOT_ASSIGNED:
                case CTSVC_ENUM_URI_READ_ONLY_PERSON_NUMBER:
                case CTSVC_ENUM_URI_READ_ONLY_PERSON_EMAIL:
-                       temp_len = SAFE_SNPRINTF(&query, &query_size, len, " GROUP BY temp_data.temp_contact_id");
+                       temp_len = SAFE_SNPRINTF(&query, &query_size, len, " GROUP BY contact_id");
                        break;
                case CTSVC_ENUM_URI_PERSON:
                        temp_len = SAFE_SNPRINTF(&query, &query_size, len, " GROUP BY person_id");
@@ -3502,150 +4648,124 @@ static inline int __ctsvc_db_search_records_with_query_exec(ctsvc_query_s *s_que
                        len += temp_len;
        }
 
-       do {
-               if (0 == limit)
-                       break;
-
-               char temp_str[20] = {0};
-               snprintf(temp_str, sizeof(temp_str), " LIMIT %d", limit);
-               temp_len = SAFE_SNPRINTF(&query, &query_size, len, temp_str);
-               if (0 <= temp_len)
-                       len += temp_len;
-
-               if (offset <= 0)
-                       break;
-
-               snprintf(temp_str, sizeof(temp_str), " OFFSET %d", offset);
-               temp_len = SAFE_SNPRINTF(&query, &query_size, len, temp_str);
-               if (0 <= temp_len)
-                       len += temp_len;
-       } while (0);
+       temp_len = SAFE_SNPRINTF(&query, &query_size, len, ") ");
+       if (0 <= temp_len) len += temp_len;
 
-       ret = ctsvc_query_prepare(query, &stmt);
-       if (NULL == stmt) {
-               /* LCOV_EXCL_START */
-               ERR("ctsvc_query_prepare() Fail(%d)[%s]", ret, query);
+       if (bind) {
+               cts_stmt stmt;
+               GSList *cursor;
+               int i;
+               ret = ctsvc_query_prepare(query, &stmt);
+               if (NULL == stmt) {
+                       /* LCOV_EXCL_START */
+                       ERR("ctsvc_query_prepare() Fail(%d)[%s]", ret, query);
+                       free(query);
+                       return ret;
+                       /* LCOV_EXCL_STOP */
+               }
                free(query);
-               return ret;
-               /* LCOV_EXCL_STOP */
-       }
-       free(query);
 
-       i = 1;
-       len = g_slist_length(bind);
-       for (cursor = bind; cursor; cursor = cursor->next, i++)
-               ctsvc_stmt_bind_text(stmt, i, cursor->data);
+               for (cursor = bind, i = 1; cursor; cursor = cursor->next, i++)
+                       ctsvc_stmt_bind_text(stmt, i, cursor->data);
 
-       contacts_list_create(&list);
-       while ((ret = ctsvc_stmt_step(stmt))) {
-               contacts_record_h record;
-               if (1 != ret) {
+               ret = ctsvc_stmt_get_first_int_result(stmt, out_count);
+               if (CONTACTS_ERROR_NONE != ret) {
                        /* LCOV_EXCL_START */
-                       ERR("ctsvc_stmt_step() Fail(%d)", ret);
-                       ctsvc_stmt_finalize(stmt);
-                       contacts_list_destroy(list, true);
+                       ERR("ctsvc_stmt_get_first_int_result() Fail(%d)", ret);
+                       return ret;
+                       /* LCOV_EXCL_STOP */
+               }
+       }
+       else {
+               ret = ctsvc_query_get_first_int_result(query, out_count);
+               free(query);
+               if (CONTACTS_ERROR_NONE != ret) {
+                       /* LCOV_EXCL_START */
+                       ERR("ctsvc_query_get_first_int_result() Fail(%d)", ret);
                        return ret;
                        /* LCOV_EXCL_STOP */
                }
+       }
 
-               if (ctsvc_view_get_record_type(s_query->view_uri) == CTSVC_RECORD_PERSON) {
-                       unsigned int ids_count;
-                       unsigned int *project;
-                       if (0 == s_query->projection_count)
-                               ids_count = s_query->property_count;
-                       else
-                               ids_count = s_query->projection_count;
+       return CONTACTS_ERROR_NONE;
+}
 
-                       project = malloc(sizeof(unsigned int)*ids_count);
 
-                       for (i = 0; i < ids_count; i++) {
-                               if (0 == s_query->projection_count)
-                                       project[i] = s_query->properties[i].property_id;
-                               else
-                                       project[i] = s_query->projection[i];
-                       }
 
-                       ret = ctsvc_db_person_create_record_from_stmt_with_projection(stmt, project,
-                                       ids_count, is_snippet, keyword, start_match, end_match, token_number, &record);
-                       if (CONTACTS_ERROR_NONE != ret)
-                               /* LCOV_EXCL_START */
-                               ERR("ctsvc_db_person_create_record_from_stmt_with_projection() Fail(%d)", ret);
-                       /* LCOV_EXCL_STOP */
+static int __ctsvc_db_search_records_with_query(contacts_query_h query,
+               const char *keyword,
+               int offset,
+               int limit,
+               bool is_snippet,
+               const char *start_match,
+               const char *end_match,
+               int token_number,
+               contacts_list_h *out_list)
+{
+       int ret;
+       char *condition = NULL;
+       char *projection;
+       ctsvc_query_s *s_query = (ctsvc_query_s*)query;
+       GSList *bind_text = NULL;
+       GSList *cursor = NULL;
+       bool can_keyword_search;
+       int enum_uri = 0;
 
-                       free(project);
-               } else {
-                       contacts_record_create(s_query->view_uri, (contacts_record_h*)&record);
-                       int field_count;
-                       if (0 == s_query->projection_count) {
-                               field_count = s_query->property_count;
-                       } else {
-                               field_count = s_query->projection_count;
+       RETV_IF(NULL == query, CONTACTS_ERROR_INVALID_PARAMETER);
+       RETV_IF(NULL == keyword, CONTACTS_ERROR_INVALID_PARAMETER);
 
-                               int err = ctsvc_record_set_projection_flags(record, s_query->projection,
-                                               s_query->projection_count, s_query->property_count);
-                               if (CONTACTS_ERROR_NONE != err)
-                                       ASSERT_NOT_REACHED("To set projection is Fail");
-                       }
+       can_keyword_search = __ctsvc_db_view_can_keyword_search(s_query->view_uri, &enum_uri);
+       RETV_IF(false == can_keyword_search, CONTACTS_ERROR_INVALID_PARAMETER);
 
-                       for (i = 0; i < field_count; i++) {
-                               int property_id;
+       ret = __db_create_projection(s_query->view_uri, s_query->properties,
+                       s_query->property_count, s_query->projection, s_query->projection_count,
+                       &projection, is_snippet);
+       RETVM_IF(CONTACTS_ERROR_NONE != ret, ret, "__db_create_projection Fail(%d)", ret);
 
-                               if (0 == s_query->projection_count)
-                                       property_id = s_query->properties[i].property_id;
-                               else
-                                       property_id = s_query->projection[i];
+       if (s_query->filter) {
+               ret = __db_create_composite_condition(s_query->filter, &condition,
+                               &bind_text);
+               if (CONTACTS_ERROR_NONE != ret) {
+                       /* LCOV_EXCL_START */
+                       ERR("__db_create_composite_condition Fail(%d)", ret);
+                       free(projection);
+                       return ret;
+                       /* LCOV_EXCL_STOP */
+               }
+       }
 
-                               type = __ctsvc_db_get_property_type(s_query->properties,
-                                               s_query->property_count, property_id);
+       ret = __ctsvc_db_search_records_with_query_exec(s_query, enum_uri, projection, condition,
+                       bind_text, keyword, offset, limit, is_snippet, start_match, end_match, token_number, out_list);
+       if (CONTACTS_ERROR_NONE != ret) {
+               /* LCOV_EXCL_START */
+               ERR("__ctsvc_db_search_records_with_query_exec Fail(%d)", ret);
+               for (cursor = bind_text; cursor; cursor = cursor->next)
+                       free(cursor->data);
+               g_slist_free(bind_text);
 
-                               char *temp = NULL;
-                               switch (type) {
-                               case CTSVC_VIEW_DATA_TYPE_INT:
-                                       ctsvc_record_set_int(record, property_id, ctsvc_stmt_get_int(stmt, i));
-                                       break;
-                               case CTSVC_VIEW_DATA_TYPE_STR:
-                                       temp = ctsvc_stmt_get_text(stmt, i);
-                                       if (CTSVC_PROPERTY_PERSON_SNIPPET_STRING == property_id) {
-                                               temp = ctsvc_utils_get_modified_str(temp, is_snippet, keyword,
-                                                               start_match, end_match, token_number);
-                                       }
-                                       ctsvc_record_set_str(record, property_id, temp);
-                                       break;
-                               case CTSVC_VIEW_DATA_TYPE_BOOL:
-                                       ctsvc_record_set_bool(record, property_id, (ctsvc_stmt_get_int(stmt, i) ? true : false));
-                                       break;
-                               case CTSVC_VIEW_DATA_TYPE_LLI:
-                                       ctsvc_record_set_lli(record, property_id, ctsvc_stmt_get_int64(stmt, i));
-                                       break;
-                               case CTSVC_VIEW_DATA_TYPE_DOUBLE:
-                                       ctsvc_record_set_double(record, property_id, ctsvc_stmt_get_dbl(stmt, i));
-                                       break;
-                               default:
-                                       /* LCOV_EXCL_START */
-                                       ERR("unknown type (%d)", type);
-                                       break;
-                                       /* LCOV_EXCL_STOP */
-                               }
-                       }
-               }
-               ctsvc_list_prepend(list, record);
+               free(condition);
+               free(projection);
+               return ret;
+               /* LCOV_EXCL_STOP */
        }
-       ctsvc_stmt_finalize(stmt);
-       ctsvc_list_reverse(list);
 
-       *out_list = list;
+       for (cursor = bind_text; cursor; cursor = cursor->next)
+               free(cursor->data);
+       g_slist_free(bind_text);
+
+       free(condition);
+       free(projection);
+
        return CONTACTS_ERROR_NONE;
 }
 
-static int __ctsvc_db_search_records_with_query(contacts_query_h query,
+static int __ctsvc_db_get_count_for_search_records_with_query(contacts_query_h query,
                const char *keyword,
-               int offset,
-               int limit,
                bool is_snippet,
                const char *start_match,
                const char *end_match,
                int token_number,
-               contacts_list_h *out_list)
+               int *out_count)
 {
        int ret;
        char *condition = NULL;
@@ -3679,8 +4799,8 @@ static int __ctsvc_db_search_records_with_query(contacts_query_h query,
                }
        }
 
-       ret = __ctsvc_db_search_records_with_query_exec(s_query, enum_uri, projection, condition,
-                       bind_text, keyword, offset, limit, is_snippet, start_match, end_match, token_number, out_list);
+       ret = __ctsvc_db_get_count_for_search_records_with_query_exec(s_query, enum_uri, projection, condition,
+                       bind_text, keyword, is_snippet, start_match, end_match, token_number, out_count);
        if (CONTACTS_ERROR_NONE != ret) {
                /* LCOV_EXCL_START */
                ERR("__ctsvc_db_search_records_with_query_exec Fail(%d)", ret);
@@ -3704,6 +4824,7 @@ static int __ctsvc_db_search_records_with_query(contacts_query_h query,
        return CONTACTS_ERROR_NONE;
 }
 
+
 typedef struct {
        contacts_list_h list;
        int *ids;
@@ -4873,3 +5994,31 @@ void ctsvc_db_set_status(contacts_db_status_e status)
        return;
 }
 
+int ctsvc_db_get_count_for_search_records(const char *view_uri, const char *keyword, int *out_count)
+{
+       RETV_IF(NULL == out_count, CONTACTS_ERROR_INVALID_PARAMETER);
+       *out_count = 0;
+       RETV_IF(NULL == view_uri, CONTACTS_ERROR_INVALID_PARAMETER);
+
+       return __ctsvc_db_get_count_for_search_records(view_uri, keyword, false, NULL, NULL, -1, out_count);
+}
+
+int ctsvc_db_get_count_for_search_records_with_range(const char *view_uri, const char *keyword, int range, int *out_count)
+{
+       RETV_IF(NULL == out_count, CONTACTS_ERROR_INVALID_PARAMETER);
+       *out_count = 0;
+       RETV_IF(range == 0, CONTACTS_ERROR_INVALID_PARAMETER);
+       RETV_IF(NULL == view_uri, CONTACTS_ERROR_INVALID_PARAMETER);
+
+       return __ctsvc_db_get_count_for_search_records_with_range(view_uri, keyword, range, false, NULL, NULL, -1, out_count);
+}
+
+int ctsvc_db_get_count_for_search_records_with_query(contacts_query_h query, const char *keyword, int *out_count)
+{
+       RETV_IF(NULL == out_count, CONTACTS_ERROR_INVALID_PARAMETER);
+       *out_count = 0;
+       RETV_IF(NULL == query, CONTACTS_ERROR_INVALID_PARAMETER);
+
+       return __ctsvc_db_get_count_for_search_records_with_query(query, keyword, false, NULL, NULL, -1, out_count);
+}
+
index 4353556..2672fc1 100644 (file)
@@ -89,5 +89,11 @@ int ctsvc_db_update_record_with_set_query(const char *set, GSList *bind_text,
 
 void ctsvc_db_set_status(contacts_db_status_e status);
 
+int ctsvc_db_get_count_for_search_records(const char *view_uri, const char *keyword, int *out_count);
+int ctsvc_db_get_count_for_search_records_with_range(const char *view_uri, const char *keyword, int range, int *out_count);
+int ctsvc_db_get_count_for_search_records_with_query(contacts_query_h query, const char *keyword, int *out_count);
+
+
+
 #endif /*  __CTSVC_DB_QUERY_H__ */