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);
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;
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:
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;
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;
}
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)
case CTSVC_ENUM_URI_READ_ONLY_PERSON_NUMBER:
case CTSVC_ENUM_URI_READ_ONLY_PERSON_EMAIL:
default:
+ free(query);
return CONTACTS_ERROR_INVALID_PARAMETER;
}
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:
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");
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;
}
}
- 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);
return CONTACTS_ERROR_NONE;
}
+
typedef struct {
contacts_list_h list;
int *ids;
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);
+}
+