4 * Copyright (c) 2010 - 2012 Samsung Electronics Co., Ltd. All rights reserved.
6 * Licensed under the Apache License, Version 2.0 (the "License");
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
10 * http://www.apache.org/licenses/LICENSE-2.0
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
22 #include "ctsvc_internal.h"
23 #include "ctsvc_schema.h"
24 #include "ctsvc_sqlite.h"
25 #include "ctsvc_normalize.h"
26 #include "ctsvc_number_utils.h"
27 #include "ctsvc_utils.h"
28 #include "ctsvc_list.h"
29 #include "ctsvc_record.h"
30 #include "ctsvc_db_query.h"
31 #include "ctsvc_db_init.h"
32 #include "ctsvc_notification.h"
33 #include "ctsvc_setting.h"
34 #include "ctsvc_db_access_control.h"
35 #include "ctsvc_localize_utils.h"
36 #include "ctsvc_phonelog.h"
38 #ifdef _CONTACTS_IPC_SERVER
39 #include "ctsvc_server_change_subject.h"
40 #ifdef ENABLE_SIM_FEATURE
41 #include "ctsvc_server_sim.h"
42 #endif // ENABLE_SIM_FEATURE
45 static int __ctsvc_db_phonelog_insert_record( contacts_record_h record, int *id );
46 static int __ctsvc_db_phonelog_get_record( int id, contacts_record_h* out_record );
47 static int __ctsvc_db_phonelog_update_record( contacts_record_h record );
48 static int __ctsvc_db_phonelog_delete_record( int id );
49 static int __ctsvc_db_phonelog_get_all_records( int offset, int limit, contacts_list_h* out_list );
50 static int __ctsvc_db_phonelog_get_records_with_query( contacts_query_h query, int offset, int limit, contacts_list_h* out_list );
51 //static int __ctsvc_db_phonelog_insert_records(const contacts_list_h in_list, int **ids);
52 //static int __ctsvc_db_phonelog_update_records(const contacts_list_h in_list);
53 //static int __ctsvc_db_phonelog_delete_records( int ids[], int count);
55 ctsvc_db_plugin_info_s ctsvc_db_plugin_phonelog = {
56 .is_query_only = false,
57 .insert_record = __ctsvc_db_phonelog_insert_record,
58 .get_record = __ctsvc_db_phonelog_get_record,
59 .update_record = __ctsvc_db_phonelog_update_record,
60 .delete_record = __ctsvc_db_phonelog_delete_record,
61 .get_all_records = __ctsvc_db_phonelog_get_all_records,
62 .get_records_with_query = __ctsvc_db_phonelog_get_records_with_query,
63 .insert_records = NULL,//__ctsvc_db_phonelog_insert_records,
64 .update_records = NULL,//__ctsvc_db_phonelog_update_records,
65 .delete_records = NULL,//__ctsvc_db_phonelog_delete_records
67 .get_count_with_query = NULL,
68 .replace_record = NULL,
69 .replace_records = NULL,
72 static int __ctsvc_db_phonelog_value_set(cts_stmt stmt, contacts_record_h *record)
77 ctsvc_phonelog_s *phonelog;
79 ret = contacts_record_create(_contacts_phone_log._uri, record);
80 RETVM_IF(CONTACTS_ERROR_NONE != ret, ret, "contacts_record_create is failed(%d)", ret);
81 phonelog = (ctsvc_phonelog_s*)*record;
84 phonelog->id = ctsvc_stmt_get_int(stmt, i++);
85 temp = ctsvc_stmt_get_text(stmt, i++);
86 phonelog->address = SAFE_STRDUP(temp);
87 phonelog->person_id = ctsvc_stmt_get_int(stmt, i++);
88 phonelog->log_type = ctsvc_stmt_get_int(stmt, i++);
89 phonelog->log_time = ctsvc_stmt_get_int(stmt, i++);
90 phonelog->extra_data1 = ctsvc_stmt_get_int(stmt, i++);
91 temp = ctsvc_stmt_get_text(stmt, i++);
92 phonelog->extra_data2 = SAFE_STRDUP(temp);
93 #ifdef _CONTACTS_IPC_SERVER
94 #ifdef ENABLE_SIM_FEATURE
95 phonelog->sim_slot_no = ctsvc_server_sim_get_sim_slot_no_by_info_id(ctsvc_stmt_get_int(stmt, i++));
96 #endif // ENABLE_SIM_FEATURE
98 return CONTACTS_ERROR_NONE;
101 static int __ctsvc_db_phonelog_get_record( int id, contacts_record_h* out_record )
104 cts_stmt stmt = NULL;
105 char query[CTS_SQL_MAX_LEN] = {0};
106 contacts_record_h record;
108 RETV_IF(NULL == out_record, CONTACTS_ERROR_INVALID_PARAMETER);
111 snprintf(query, sizeof(query),
112 "SELECT id, number, person_id, log_type, log_time, data1, data2, sim_id "
113 "FROM "CTS_TABLE_PHONELOGS" WHERE id = %d", id);
115 ret = ctsvc_query_prepare(query, &stmt);
116 RETVM_IF(NULL == stmt, ret, "DB error : ctsvc_query_prepare() Failed(%d)", ret);
118 ret = ctsvc_stmt_step(stmt);
119 if (1 /*CTS_TRUE*/ != ret) {
120 CTS_ERR("ctsvc_stmt_step() Failed(%d)", ret);
121 ctsvc_stmt_finalize(stmt);
122 if (CONTACTS_ERROR_NONE == ret)
123 return CONTACTS_ERROR_NO_DATA;
128 ret = __ctsvc_db_phonelog_value_set(stmt, &record);
130 ctsvc_stmt_finalize(stmt);
131 if (CONTACTS_ERROR_NONE != ret) {
132 CTS_ERR("__ctsvc_db_phonelog_value_set(ALL) Failed(%d)", ret);
136 *out_record = record;
138 return CONTACTS_ERROR_NONE;
141 static int __ctsvc_db_phonelog_update_record( contacts_record_h record )
144 char query[CTS_SQL_MIN_LEN] = {0};
145 ctsvc_phonelog_s *phonelog = (ctsvc_phonelog_s *)record;
146 int ret = CONTACTS_ERROR_NONE;
148 GSList *bind_text = NULL;
149 GSList *cursor = NULL;
151 RETVM_IF(NULL == record, CONTACTS_ERROR_INVALID_PARAMETER, "Invalid parameter : record is null");
152 RETVM_IF(phonelog->id <= 0, CONTACTS_ERROR_INVALID_PARAMETER,
153 "Invalid parameter : The phone_log has ID(%d)", phonelog->id);
154 RETVM_IF(phonelog->log_type != CONTACTS_PLOG_TYPE_VOICE_INCOMMING_SEEN &&
155 phonelog->log_type != CONTACTS_PLOG_TYPE_VIDEO_INCOMMING_SEEN, CONTACTS_ERROR_INVALID_PARAMETER,
156 "Invalid parameter : the type is can not updated(%d)", phonelog->log_type);
157 RETVM_IF(CTSVC_PROPERTY_FLAG_DIRTY != (phonelog->base.property_flag & CTSVC_PROPERTY_FLAG_DIRTY), CONTACTS_ERROR_NONE, "No update");
159 ret = ctsvc_begin_trans();
160 RETVM_IF(ret, ret, "ctsvc_begin_trans() Failed(%d)", ret);
162 snprintf(query, sizeof(query),
163 "SELECT id FROM "CTS_TABLE_PHONELOGS" WHERE id = %d", phonelog->id);
164 ret = ctsvc_query_get_first_int_result(query, &phonelog_id);
165 if (ret != CONTACTS_ERROR_NONE) {
166 CTS_ERR("ctsvc_query_get_first_int_result Fail(%d)", ret);
167 ctsvc_end_trans(false);
172 if (CONTACTS_ERROR_NONE != (ret = ctsvc_db_create_set_query(record, &set, &bind_text))) break;
173 if (CONTACTS_ERROR_NONE != (ret = ctsvc_db_update_record_with_set_query(set, bind_text, CTS_TABLE_PHONELOGS, phonelog->id))) break;
175 if (ctsvc_db_change()) {
176 ctsvc_set_phonelog_noti();
178 #ifdef _CONTACTS_IPC_SERVER
179 ctsvc_change_subject_add_changed_phone_log_id(CONTACTS_CHANGE_UPDATED, phonelog->id);
184 CTSVC_RECORD_RESET_PROPERTY_FLAGS((ctsvc_record_s *)record);
187 for (cursor=bind_text;cursor;cursor=cursor->next)
188 CONTACTS_FREE(cursor->data);
189 g_slist_free(bind_text);
192 ret = ctsvc_end_trans(true);
193 RETVM_IF(ret < CONTACTS_ERROR_NONE, ret, "DB error : ctsvc_end_trans() Failed(%d)", ret);
195 return CONTACTS_ERROR_NONE;
198 static int __ctsvc_db_phonelog_delete_record( int id )
202 char query[CTS_SQL_MAX_LEN] = {0};
204 ret = ctsvc_begin_trans();
205 RETVM_IF(ret, ret, "ctsvc_begin_trans() Failed(%d)", ret);
207 snprintf(query, sizeof(query),
208 "SELECT id FROM "CTS_TABLE_PHONELOGS" WHERE id = %d", id);
209 ret = ctsvc_query_get_first_int_result(query, &phonelog_id);
210 if (ret != CONTACTS_ERROR_NONE) {
211 CTS_ERR("ctsvc_query_get_first_int_result Fail(%d)", ret);
212 ctsvc_end_trans(false);
216 snprintf(query, sizeof(query), "DELETE FROM %s WHERE id = %d",
217 CTS_TABLE_PHONELOGS, id);
219 ret = ctsvc_query_exec(query);
220 if (CONTACTS_ERROR_NONE != ret) {
221 CTS_ERR("ctsvc_query_exec() Failed(%d)", ret);
222 ctsvc_end_trans(false);
226 ctsvc_set_phonelog_noti();
228 ret = ctsvc_end_trans(true);
229 if (ret < CONTACTS_ERROR_NONE)
231 CTS_ERR("DB error : ctsvc_end_trans() Failed(%d)", ret);
235 return CONTACTS_ERROR_NONE;
238 static int __ctsvc_db_phonelog_get_all_records( int offset, int limit,
239 contacts_list_h* out_list )
244 char query[CTS_SQL_MAX_LEN] = {0};
245 contacts_list_h list;
247 len = snprintf(query, sizeof(query),
248 "SELECT id, number, person_id, log_type, log_time, data1, data2, sim_id "
249 "FROM "CTS_TABLE_PHONELOGS);
252 len += snprintf(query+len, sizeof(query)-len, " LIMIT %d", limit);
254 len += snprintf(query+len, sizeof(query)-len, " OFFSET %d", offset);
257 ret = ctsvc_query_prepare(query, &stmt);
258 RETVM_IF(NULL == stmt, ret, "DB error : ctsvc_query_prepare() Failed(%d)", ret);
260 contacts_list_create(&list);
261 while ((ret = ctsvc_stmt_step(stmt))) {
262 contacts_record_h record;
264 CTS_ERR("DB error : ctsvc_stmt_step() Failed(%d)", ret);
265 ctsvc_stmt_finalize(stmt);
266 contacts_list_destroy(list, true);
269 __ctsvc_db_phonelog_value_set(stmt, &record);
271 ctsvc_list_prepend(list, record);
273 ctsvc_stmt_finalize(stmt);
274 ctsvc_list_reverse(list);
276 *out_list = (contacts_list_h)list;
277 return CONTACTS_ERROR_NONE;
280 static int __ctsvc_db_phonelog_get_records_with_query( contacts_query_h query, int offset,
281 int limit, contacts_list_h* out_list )
286 ctsvc_query_s *s_query;
288 contacts_list_h list;
289 ctsvc_phonelog_s *phonelog;
291 RETV_IF(NULL == query, CONTACTS_ERROR_INVALID_PARAMETER);
292 s_query = (ctsvc_query_s *)query;
294 ret = ctsvc_db_make_get_records_query_stmt(s_query, offset, limit, &stmt);
295 RETVM_IF(CONTACTS_ERROR_NONE != ret, ret, "ctsvc_db_make_get_records_query_stmt fail(%d)", ret);
297 contacts_list_create(&list);
298 while ((ret = ctsvc_stmt_step(stmt))) {
299 contacts_record_h record;
301 CTS_ERR("DB error : ctsvc_stmt_step() Failed(%d)", ret);
302 ctsvc_stmt_finalize(stmt);
303 contacts_list_destroy(list, true);
307 contacts_record_create(_contacts_phone_log._uri, &record);
308 phonelog = (ctsvc_phonelog_s*)record;
309 if (0 == s_query->projection_count)
310 field_count = s_query->property_count;
313 field_count = s_query->projection_count;
315 if( CONTACTS_ERROR_NONE != ctsvc_record_set_projection_flags(record, s_query->projection, s_query->projection_count, s_query->property_count) )
317 ASSERT_NOT_REACHED("To set projection is failed.\n");
321 for(i=0;i<field_count;i++) {
324 if (0 == s_query->projection_count)
325 property_id = s_query->properties[i].property_id;
327 property_id = s_query->projection[i];
329 switch(property_id) {
330 case CTSVC_PROPERTY_PHONELOG_ID:
331 phonelog->id = ctsvc_stmt_get_int(stmt, i);
333 case CTSVC_PROPERTY_PHONELOG_PERSON_ID:
334 phonelog->person_id = ctsvc_stmt_get_int(stmt, i);
336 case CTSVC_PROPERTY_PHONELOG_ADDRESS:
337 temp = ctsvc_stmt_get_text(stmt, i);
338 phonelog->address = SAFE_STRDUP(temp);
340 case CTSVC_PROPERTY_PHONELOG_LOG_TIME:
341 phonelog->log_time = ctsvc_stmt_get_int(stmt, i);
343 case CTSVC_PROPERTY_PHONELOG_LOG_TYPE:
344 phonelog->log_type = ctsvc_stmt_get_int(stmt, i);
346 case CTSVC_PROPERTY_PHONELOG_EXTRA_DATA1:
347 phonelog->extra_data1 = ctsvc_stmt_get_int(stmt, i);
349 case CTSVC_PROPERTY_PHONELOG_EXTRA_DATA2:
350 temp = ctsvc_stmt_get_text(stmt, i);
351 phonelog->extra_data2 = SAFE_STRDUP(temp);
353 #ifdef ENABLE_SIM_FEATURE
354 case CTSVC_PROPERTY_PHONELOG_SIM_SLOT_NO:
355 phonelog->sim_slot_no = ctsvc_server_sim_get_sim_slot_no_by_info_id(ctsvc_stmt_get_int(stmt, i));
357 #endif // ENABLE_SIM_FEATURE
362 ctsvc_list_prepend(list, record);
365 ctsvc_stmt_finalize(stmt);
366 ctsvc_list_reverse(list);
370 return CONTACTS_ERROR_NONE;
372 //static int __ctsvc_db_phonelog_insert_records(const contacts_list_h in_list, int **ids) { return CONTACTS_ERROR_NONE; }
373 //static int __ctsvc_db_phonelog_update_records(const contacts_list_h in_list) { return CONTACTS_ERROR_NONE; }
374 //static int __ctsvc_db_phonelog_delete_records( int ids[], int count) { return CONTACTS_ERROR_NONE; }
376 static int __ctsvc_db_phonelog_increase_outgoing_count(ctsvc_phonelog_s *phonelog)
380 int type = CONTACTS_USAGE_STAT_TYPE_NONE;
381 char query[CTS_SQL_MIN_LEN] = {0};
383 if (phonelog->log_type == CONTACTS_PLOG_TYPE_VOICE_OUTGOING ||
384 phonelog->log_type == CONTACTS_PLOG_TYPE_VIDEO_OUTGOING)
385 type = CONTACTS_USAGE_STAT_TYPE_OUTGOING_CALL;
386 else if (phonelog->log_type == CONTACTS_PLOG_TYPE_MMS_OUTGOING ||
387 phonelog->log_type == CONTACTS_PLOG_TYPE_SMS_OUTGOING)
388 type = CONTACTS_USAGE_STAT_TYPE_OUTGOING_MSG;
390 return CONTACTS_ERROR_NONE;
392 snprintf(query, sizeof(query),
393 "SELECT person_id FROM %s WHERE person_id = %d and usage_type = %d ",
394 CTS_TABLE_CONTACT_STAT, phonelog->person_id, type);
396 ret = ctsvc_query_get_first_int_result(query, &id);
397 if (CONTACTS_ERROR_NO_DATA == ret) {
398 snprintf(query, sizeof(query),
399 "INSERT INTO %s(person_id, usage_type, times_used) VALUES(%d, %d, 1)",
400 CTS_TABLE_CONTACT_STAT, phonelog->person_id, type);
403 snprintf(query, sizeof(query),
404 "UPDATE %s SET times_used = times_used + 1 WHERE person_id = %d and usage_type = %d",
405 CTS_TABLE_CONTACT_STAT, phonelog->person_id, type);
408 ret = ctsvc_query_exec(query);
409 RETVM_IF(CONTACTS_ERROR_NONE != ret, ret, "DB error : ctsvc_query_exec() Failed(%d)", ret);
411 return CONTACTS_ERROR_NONE;
414 static int __ctsvc_db_phonelog_insert(ctsvc_phonelog_s *phonelog, int *id)
417 cts_stmt stmt = NULL;
418 char query[CTS_SQL_MAX_LEN] = {0};
420 RETVM_IF((phonelog->log_type < CONTACTS_PLOG_TYPE_NONE
421 || CONTACTS_PLOG_TYPE_EMAIL_SENT < phonelog->log_type)
422 , CONTACTS_ERROR_INVALID_PARAMETER, "phonelog type(%d) is invaid", phonelog->log_type);
424 snprintf(query, sizeof(query), "INSERT INTO "CTS_TABLE_PHONELOGS"("
425 "number, normal_num, minmatch, clean_num, person_id, log_type,log_time, data1, data2, sim_id) "
426 "VALUES(?, ?, ?, ?, ?, %d, %d, %d, ?, ?)",
427 phonelog->log_type, phonelog->log_time, phonelog->extra_data1);
429 ret = ctsvc_query_prepare(query, &stmt);
430 RETVM_IF(NULL == stmt, ret, "DB error : ctsvc_query_prepare() Failed(%d)", ret);
432 if (phonelog->address) {
433 ctsvc_stmt_bind_text(stmt, 1, phonelog->address);
434 if (phonelog->log_type < CONTACTS_PLOG_TYPE_EMAIL_RECEIVED) {
435 char clean_num[strlen(phonelog->address) + 1];
436 ret = ctsvc_clean_number(phonelog->address, clean_num, sizeof(clean_num), true);
438 char normal_num[sizeof(clean_num) + 20];
439 ctsvc_stmt_bind_copy_text(stmt, 4, clean_num, strlen(clean_num));
440 ret = ctsvc_normalize_number(clean_num, normal_num, sizeof(normal_num), true);
442 char minmatch[sizeof(normal_num) + 1];
443 ctsvc_stmt_bind_copy_text(stmt, 2, normal_num, strlen(normal_num));
444 ret = ctsvc_get_minmatch_number(normal_num, minmatch, sizeof(minmatch), ctsvc_get_phonenumber_min_match_digit());
445 ctsvc_stmt_bind_copy_text(stmt, 3, minmatch, strlen(minmatch));
451 if (0 < phonelog->person_id)
452 ctsvc_stmt_bind_int(stmt, 5, phonelog->person_id);
454 if (phonelog->extra_data2)
455 ctsvc_stmt_bind_text(stmt, 6, phonelog->extra_data2);
457 #ifdef ENABLE_SIM_FEATURE
458 if (phonelog->sim_slot_no >= 0) {
460 sim_info_id = ctsvc_server_sim_get_info_id_by_sim_slot_no(phonelog->sim_slot_no);
462 ctsvc_stmt_bind_int(stmt, 7, sim_info_id);
465 #endif // ENABLE_SIM_FEATURE
466 ctsvc_stmt_bind_int(stmt, 7, -1);
468 ret = ctsvc_stmt_step(stmt);
469 if (CONTACTS_ERROR_NONE != ret) {
470 CTS_ERR("ctsvc_stmt_step() Failed(%d)", ret);
471 ctsvc_stmt_finalize(stmt);
475 *id = ctsvc_db_get_last_insert_id();
476 ctsvc_stmt_finalize(stmt);
479 ctsvc_db_phone_log_update_person_id(phonelog->address, phonelog->person_id, -1, false);
481 ctsvc_set_phonelog_noti();
482 return CONTACTS_ERROR_NONE;
485 static int __ctsvc_db_phonelog_insert_record( contacts_record_h record, int *id )
488 ctsvc_phonelog_s *phonelog = (ctsvc_phonelog_s *)record;
490 RETVM_IF(NULL == record, CONTACTS_ERROR_INVALID_PARAMETER, "Invalid parameter : record is null");
491 RETVM_IF(phonelog->id, CONTACTS_ERROR_INVALID_PARAMETER,
492 "Invalid parameter : The phone_log has ID(%d)", phonelog->id);
494 ret = ctsvc_begin_trans();
495 RETVM_IF(ret, ret, "ctsvc_begin_trans() Failed(%d)", ret);
497 ret = __ctsvc_db_phonelog_insert(phonelog, id);
498 if (CONTACTS_ERROR_NONE != ret) {
499 CTS_ERR("__ctsvc_db_phonelog_insert() Failed(%d)", ret);
500 ctsvc_end_trans(false);
504 if (0 < phonelog->person_id) {
505 ret = __ctsvc_db_phonelog_increase_outgoing_count(phonelog);
506 WARN_IF(CONTACTS_ERROR_NONE != ret, "__ctsvc_db_phonelog_increase_outgoing_count() Failed(%d)", ret);
509 #ifdef _CONTACTS_IPC_SERVER
510 // add id for subscribe
511 ctsvc_change_subject_add_changed_phone_log_id(CONTACTS_CHANGE_INSERTED, *id);
514 ret = ctsvc_end_trans(true);
515 if (ret < CONTACTS_ERROR_NONE) {
516 CTS_ERR("DB error : ctsvc_end_trans() Failed(%d)", ret);
519 return CONTACTS_ERROR_NONE;