4 * Copyright (c) 2010 - 2015 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.
20 #include "ctsvc_internal.h"
21 #include "ctsvc_db_schema.h"
22 #include "ctsvc_db_sqlite.h"
23 #include "ctsvc_db_utils.h"
24 #include "ctsvc_db_init.h"
25 #include "ctsvc_db_access_control.h"
26 #include "ctsvc_db_plugin_contact_helper.h"
27 #include "ctsvc_db_plugin_email_helper.h"
28 #include "ctsvc_record.h"
29 #include "ctsvc_notification.h"
30 #include "ctsvc_db_query.h"
31 #include "ctsvc_list.h"
34 static int __ctsvc_db_email_get_person_default_email(int person_id)
38 char query[CTS_SQL_MAX_LEN] = {0};
40 snprintf(query, sizeof(query),
41 "SELECT id FROM "CTSVC_DB_VIEW_CONTACT" c, "CTS_TABLE_DATA" d "
42 "WHERE c.person_id = %d AND d.datatype = %d AND c.contact_id = d.contact_id AND d.is_default = 1",
43 person_id, CTSVC_DATA_EMAIL);
44 ret = ctsvc_query_get_first_int_result(query, &default_email_id);
45 if (CONTACTS_ERROR_NONE != ret)
47 return default_email_id;
50 static int __ctsvc_db_email_update_person_has_email(int person_id, bool has_email)
53 char query[CTS_SQL_MAX_LEN] = {0};
55 snprintf(query, sizeof(query),
56 "UPDATE "CTS_TABLE_PERSONS" SET has_email = %d WHERE person_id = %d",
57 has_email, person_id);
59 ret = ctsvc_query_exec(query);
60 WARN_IF(CONTACTS_ERROR_NONE != ret, "ctsvc_query_exec() Fail(%d)", ret);
64 static int __ctsvc_db_email_update_default(int email_id, int contact_id, bool is_default, bool is_primary_default)
67 char query[CTS_SQL_MAX_LEN] = {0};
69 snprintf(query, sizeof(query),
70 "UPDATE "CTS_TABLE_DATA" SET is_default = %d, is_primary_default = %d WHERE id = %d",
71 is_default, is_primary_default, email_id);
72 ret = ctsvc_query_exec(query);
74 WARN_IF(CONTACTS_ERROR_NONE != ret, "ctsvc_query_exec() Fail(%d)", ret);
78 static int __ctsvc_db_email_get_default_email_id(int contact_id)
82 char query[CTS_SQL_MAX_LEN] = {0};
83 snprintf(query, sizeof(query),
84 "SELECT id FROM "CTS_TABLE_DATA" WHERE datatype=%d AND contact_id=%d AND is_default=1",
85 CTSVC_DATA_EMAIL, contact_id);
86 ret = ctsvc_query_get_first_int_result(query, &email_id);
87 if (CONTACTS_ERROR_NONE != ret)
92 static int __ctsvc_db_email_get_primary_default_email_id(int contact_id)
96 char query[CTS_SQL_MAX_LEN] = {0};
97 snprintf(query, sizeof(query),
98 "SELECT id FROM "CTS_TABLE_DATA" WHERE datatype=%d AND contact_id=%d AND is_primary_default=1",
99 CTSVC_DATA_EMAIL, contact_id);
100 ret = ctsvc_query_get_first_int_result(query, &email_id);
101 if (CONTACTS_ERROR_NONE != ret)
106 static int __ctsvc_db_email_get_primary_default_contact_id(int person_id)
109 int default_contact_id;
110 char query[CTS_SQL_MAX_LEN] = {0};
112 snprintf(query, sizeof(query),
113 "SELECT c.contact_id FROM "CTS_TABLE_CONTACTS" c, "CTS_TABLE_DATA" d "
114 "WHERE c.person_id = %d AND d.datatype = %d AND c.contact_id = d.contact_id AND d.is_primary_default = 1",
115 person_id, CTSVC_DATA_EMAIL);
116 ret = ctsvc_query_get_first_int_result(query, &default_contact_id);
117 if (CONTACTS_ERROR_NONE != ret)
119 return default_contact_id;
122 static int __ctsvc_db_email_set_primary_default(int email_id, bool is_primary_default)
125 char query[CTS_SQL_MAX_LEN] = {0};
127 snprintf(query, sizeof(query),
128 "UPDATE "CTS_TABLE_DATA" SET is_primary_default = %d WHERE id = %d",
129 is_primary_default, email_id);
130 ret = ctsvc_query_exec(query);
131 WARN_IF(CONTACTS_ERROR_NONE != ret, "ctsvc_query_exec() Fail(%d)", ret);
135 static int __ctsvc_db_email_insert_record(contacts_record_h record, int *id)
138 int addressbook_id = 0;
140 int old_default_email_id = 0;
141 char query[CTS_SQL_MAX_LEN] = {0};
142 cts_stmt stmt = NULL;
143 ctsvc_email_s *email = (ctsvc_email_s*)record;
144 RETV_IF(NULL == email->email_addr, CONTACTS_ERROR_INVALID_PARAMETER);
146 ret = ctsvc_begin_trans();
147 if (CONTACTS_ERROR_NONE != ret) {
148 ERR("ctsvc_begin_trans() Fail(%d)", ret);
152 snprintf(query, sizeof(query),
153 "SELECT addressbook_id, person_id FROM "CTSVC_DB_VIEW_CONTACT" WHERE contact_id = %d", email->contact_id);
154 ret = ctsvc_query_prepare(query, &stmt);
156 ERR("ctsvc_query_prepare() Fail(%d)", ret);
157 ctsvc_end_trans(false);
161 ret = ctsvc_stmt_step(stmt);
163 ERR("ctsvc_stmt_step() Fail(%d)", ret);
164 ctsvc_stmt_finalize(stmt);
165 ctsvc_end_trans(false);
166 if (CONTACTS_ERROR_NONE == ret)
167 return CONTACTS_ERROR_INVALID_PARAMETER;
171 addressbook_id = ctsvc_stmt_get_int(stmt, 0);
172 person_id = ctsvc_stmt_get_int(stmt, 1);
173 ctsvc_stmt_finalize(stmt);
175 if (false == ctsvc_have_ab_write_permission(addressbook_id)) {
176 ERR("Does not have permission to update this email record : addresbook_id(%d)", addressbook_id);
177 ctsvc_end_trans(false);
178 return CONTACTS_ERROR_PERMISSION_DENIED;
181 old_default_email_id = __ctsvc_db_email_get_default_email_id(email->contact_id);
182 if (0 == old_default_email_id)
183 email->is_default = true;
185 ret = ctsvc_db_email_insert(record, email->contact_id, false, id);
186 if (CONTACTS_ERROR_NONE != ret) {
187 ERR("ctsvc_begin_trans() Fail(%d)", ret);
188 ctsvc_end_trans(false);
192 snprintf(query, sizeof(query),
193 "UPDATE "CTS_TABLE_CONTACTS" SET has_email = %d, changed_ver = %d, changed_time = %d "
194 "WHERE contact_id = %d",
195 1, ctsvc_get_next_ver(), (int)time(NULL), email->contact_id);
197 ret = ctsvc_query_exec(query);
198 if (CONTACTS_ERROR_NONE != ret) {
199 ERR("ctsvc_query_exec() Fail(%d)", ret);
200 ctsvc_end_trans(false);
204 if (email->is_default) {
205 int primary_default_contact_id = 0;
207 __ctsvc_db_email_update_person_has_email(person_id, true);
209 primary_default_contact_id = __ctsvc_db_email_get_primary_default_contact_id(person_id);
210 if (0 == primary_default_contact_id || email->contact_id == primary_default_contact_id)
211 __ctsvc_db_email_set_primary_default(*id, true);
213 ctsvc_contact_update_display_name(email->contact_id, CONTACTS_DISPLAY_NAME_SOURCE_TYPE_EMAIL);
216 ctsvc_set_contact_noti();
217 ctsvc_set_person_noti();
219 ret = ctsvc_end_trans(true);
220 if (ret < CONTACTS_ERROR_NONE) {
221 ERR("ctsvc_end_trans() Fail(%d)", ret);
224 return CONTACTS_ERROR_NONE;
228 static int __ctsvc_db_email_get_record(int id, contacts_record_h *out_record)
231 cts_stmt stmt = NULL;
232 char query[CTS_SQL_MAX_LEN] = {0};
234 RETV_IF(NULL == out_record, CONTACTS_ERROR_INVALID_PARAMETER);
237 snprintf(query, sizeof(query),
238 "SELECT id, data.contact_id, is_default, data1, data2, data3 "
239 "FROM "CTS_TABLE_DATA", "CTSVC_DB_VIEW_CONTACT" "
240 "ON "CTS_TABLE_DATA".contact_id = "CTSVC_DB_VIEW_CONTACT".contact_id "
241 "WHERE id = %d AND datatype = %d ",
242 id, CTSVC_DATA_EMAIL);
244 ret = ctsvc_query_prepare(query, &stmt);
245 RETVM_IF(NULL == stmt, ret, "ctsvc_query_prepare() Fail(%d)", ret);
247 ret = ctsvc_stmt_step(stmt);
248 if (1 /*CTS_TRUE*/ != ret) {
249 ERR("ctsvc_stmt_step() Fail(%d)", ret);
250 ctsvc_stmt_finalize(stmt);
251 if (CONTACTS_ERROR_NONE == ret)
252 return CONTACTS_ERROR_NO_DATA;
257 ctsvc_db_email_get_value_from_stmt(stmt, out_record, 0);
259 ctsvc_stmt_finalize(stmt);
261 return CONTACTS_ERROR_NONE;
264 static int __ctsvc_db_email_update_record(contacts_record_h record)
268 char query[CTS_SQL_MAX_LEN] = {0};
269 ctsvc_email_s *email = (ctsvc_email_s*)record;
270 RETVM_IF(NULL == email->email_addr, CONTACTS_ERROR_INVALID_PARAMETER, "email is empty");
272 ret = ctsvc_begin_trans();
273 if (CONTACTS_ERROR_NONE != ret) {
274 ERR("ctsvc_begin_trans() Fail(%d)", ret);
278 snprintf(query, sizeof(query),
279 "SELECT addressbook_id FROM "CTSVC_DB_VIEW_CONTACT" WHERE contact_id = %d", email->contact_id);
280 ret = ctsvc_query_get_first_int_result(query, &addressbook_id);
281 if (CONTACTS_ERROR_NONE != ret) {
282 ERR("No data : contact_id (%d) is not exist", email->contact_id);
283 ctsvc_end_trans(false);
287 if (false == ctsvc_have_ab_write_permission(addressbook_id)) {
288 ERR("Does not have permission to update this email record : addresbook_id(%d)", addressbook_id);
289 ctsvc_end_trans(false);
290 return CONTACTS_ERROR_PERMISSION_DENIED;
293 ret = ctsvc_db_email_update(record, false);
294 if (CONTACTS_ERROR_NONE != ret) {
295 ERR("update record Fail(%d)", ret);
296 ctsvc_end_trans(false);
300 if (email->is_default) {
301 int old_primary_default_email_id = 0;
302 old_primary_default_email_id = __ctsvc_db_email_get_primary_default_email_id(email->contact_id);
303 if (old_primary_default_email_id)
304 __ctsvc_db_email_set_primary_default(email->id, true);
306 ctsvc_contact_update_display_name(email->contact_id, CONTACTS_DISPLAY_NAME_SOURCE_TYPE_EMAIL);
308 ret = ctsvc_db_contact_update_changed_time(email->contact_id);
309 if (CONTACTS_ERROR_NONE != ret) {
310 ERR("ctsvc_db_contact_update_changed_time() Fail(%d)", ret);
311 ctsvc_end_trans(false);
314 ctsvc_set_person_noti();
316 ret = ctsvc_end_trans(true);
317 if (ret < CONTACTS_ERROR_NONE) {
318 ERR("ctsvc_end_trans() Fail(%d)", ret);
321 return CONTACTS_ERROR_NONE;
325 static int __ctsvc_db_email_delete_record(int id)
332 int is_primary_default;
333 char query[CTS_SQL_MAX_LEN] = {0};
334 bool has_email = false;
335 cts_stmt stmt = NULL;
338 ret = ctsvc_begin_trans();
339 if (CONTACTS_ERROR_NONE != ret) {
340 ERR("ctsvc_begin_trans() Fail(%d)", ret);
344 snprintf(query, sizeof(query),
345 "SELECT contact_id, person_id, addressbook_id FROM "CTSVC_DB_VIEW_CONTACT " "
346 "WHERE contact_id = (SELECT contact_id FROM "CTS_TABLE_DATA" WHERE id = %d)", id);
348 ret = ctsvc_query_prepare(query, &stmt);
350 ERR("ctsvc_query_prepare() Fail(%d)", ret);
351 ctsvc_end_trans(false);
355 ret = ctsvc_stmt_step(stmt);
357 ERR("ctsvc_stmt_step() Fail(%d)", ret);
358 ctsvc_stmt_finalize(stmt);
359 ctsvc_end_trans(false);
360 if (CONTACTS_ERROR_NONE == ret)
361 return CONTACTS_ERROR_NO_DATA;
365 contact_id = ctsvc_stmt_get_int(stmt, 0);
366 person_id = ctsvc_stmt_get_int(stmt, 1);
367 addressbook_id = ctsvc_stmt_get_int(stmt, 2);
368 ctsvc_stmt_finalize(stmt);
370 if (false == ctsvc_have_ab_write_permission(addressbook_id)) {
371 ERR("Does not have permission to delete this email record : addresbook_id(%d)", addressbook_id);
372 ctsvc_end_trans(false);
373 return CONTACTS_ERROR_PERMISSION_DENIED;
376 snprintf(query, sizeof(query),
377 "SELECT is_default, is_primary_default FROM "CTS_TABLE_DATA" WHERE id = %d", id);
379 ret = ctsvc_query_prepare(query, &stmt);
380 RETVM_IF(NULL == stmt, ret, "ctsvc_query_prepare() Fail(%d)", ret);
382 ret = ctsvc_stmt_step(stmt);
384 ERR("ctsvc_stmt_step() Fail(%d)", ret);
385 ctsvc_stmt_finalize(stmt);
386 ctsvc_end_trans(false);
387 if (CONTACTS_ERROR_NONE == ret)
388 return CONTACTS_ERROR_NO_DATA;
392 is_default = ctsvc_stmt_get_int(stmt, 0);
393 is_primary_default = ctsvc_stmt_get_int(stmt, 1);
394 ctsvc_stmt_finalize(stmt);
396 ret = ctsvc_db_email_delete(id, false);
397 if (CONTACTS_ERROR_NONE != ret) {
398 ERR("ctsvc_begin_trans() Fail(%d)", ret);
399 ctsvc_end_trans(false);
403 snprintf(query, sizeof(query),
404 "SELECT id FROM "CTS_TABLE_DATA" WHERE datatype = %d AND contact_id = %d AND is_my_profile = 0 limit 1",
405 CTSVC_DATA_EMAIL, contact_id);
406 ret = ctsvc_query_get_first_int_result(query, &email_id);
410 snprintf(query, sizeof(query),
411 "UPDATE "CTS_TABLE_CONTACTS" SET has_email = %d, changed_ver = %d, changed_time = %d "
412 "WHERE contact_id = %d",
413 has_email, ctsvc_get_next_ver(), (int)time(NULL), contact_id);
415 ret = ctsvc_query_exec(query);
416 if (CONTACTS_ERROR_NONE != ret) {
417 ERR("ctsvc_query_exec() Fail(%d)", ret);
418 ctsvc_end_trans(false);
425 __ctsvc_db_email_update_default(email_id, contact_id, is_default, is_primary_default);
426 } else if (is_primary_default) {
427 int default_email_id = 0;
428 default_email_id = __ctsvc_db_email_get_person_default_email(person_id);
429 if (default_email_id)
430 __ctsvc_db_email_set_primary_default(default_email_id, true);
432 __ctsvc_db_email_update_person_has_email(person_id, false);
434 ctsvc_contact_update_display_name(contact_id, CONTACTS_DISPLAY_NAME_SOURCE_TYPE_EMAIL);
437 ctsvc_set_contact_noti();
438 ctsvc_set_person_noti();
440 ret = ctsvc_end_trans(true);
441 RETVM_IF(ret < CONTACTS_ERROR_NONE, ret, "ctsvc_end_trans() Fail(%d)", ret);
442 return CONTACTS_ERROR_NONE;
445 static int __ctsvc_db_email_get_all_records(int offset, int limit, contacts_list_h *out_list)
449 contacts_list_h list;
450 ctsvc_email_s *email;
451 cts_stmt stmt = NULL;
452 char query[CTS_SQL_MAX_LEN] = {0};
454 len = snprintf(query, sizeof(query),
455 "SELECT id, data.contact_id, is_default, data1, data2, data3 "
456 "FROM "CTS_TABLE_DATA", "CTSVC_DB_VIEW_CONTACT" "
457 "ON "CTS_TABLE_DATA".contact_id = "CTSVC_DB_VIEW_CONTACT".contact_id "
458 "WHERE datatype = %d AND is_my_profile=0 ",
462 len += snprintf(query+len, sizeof(query)-len, " LIMIT %d", limit);
464 len += snprintf(query+len, sizeof(query)-len, " OFFSET %d", offset);
467 ret = ctsvc_query_prepare(query, &stmt);
468 RETVM_IF(NULL == stmt, ret, "ctsvc_query_prepare() Fail(%d)", ret);
470 contacts_list_create(&list);
471 while ((ret = ctsvc_stmt_step(stmt))) {
472 if (1 /*CTS_TRUE */ != ret) {
473 ERR("DB : ctsvc_stmt_step() Fail(%d)", ret);
474 ctsvc_stmt_finalize(stmt);
475 contacts_list_destroy(list, true);
478 ctsvc_db_email_get_value_from_stmt(stmt, (contacts_record_h*)&email, 0);
479 ctsvc_list_prepend(list, (contacts_record_h)email);
481 ctsvc_stmt_finalize(stmt);
482 ctsvc_list_reverse(list);
485 return CONTACTS_ERROR_NONE;
488 static int __ctsvc_db_email_get_records_with_query(contacts_query_h query, int offset,
489 int limit, contacts_list_h *out_list)
494 ctsvc_query_s *s_query;
496 contacts_list_h list;
497 ctsvc_email_s *email;
499 RETV_IF(NULL == query, CONTACTS_ERROR_INVALID_PARAMETER);
500 s_query = (ctsvc_query_s*)query;
502 ret = ctsvc_db_make_get_records_query_stmt(s_query, offset, limit, &stmt);
503 RETVM_IF(CONTACTS_ERROR_NONE != ret, ret, "ctsvc_db_make_get_records_query_stmt fail(%d)", ret);
505 contacts_list_create(&list);
506 while ((ret = ctsvc_stmt_step(stmt))) {
507 contacts_record_h record;
508 if (1 /*CTS_TRUE */ != ret) {
509 ERR("ctsvc_stmt_step() Fail(%d)", ret);
510 ctsvc_stmt_finalize(stmt);
511 contacts_list_destroy(list, true);
515 contacts_record_create(_contacts_email._uri, &record);
516 email = (ctsvc_email_s*)record;
517 if (0 == s_query->projection_count) {
518 field_count = s_query->property_count;
520 field_count = s_query->projection_count;
521 ret = ctsvc_record_set_projection_flags(record, s_query->projection,
522 s_query->projection_count, s_query->property_count);
524 if (CONTACTS_ERROR_NONE != ret)
525 ASSERT_NOT_REACHED("To set projection is Fail.\n");
528 for (i = 0; i < field_count; i++) {
531 if (0 == s_query->projection_count)
532 property_id = s_query->properties[i].property_id;
534 property_id = s_query->projection[i];
536 switch (property_id) {
537 case CTSVC_PROPERTY_EMAIL_ID:
538 email->id = ctsvc_stmt_get_int(stmt, i);
540 case CTSVC_PROPERTY_EMAIL_CONTACT_ID:
541 email->contact_id = ctsvc_stmt_get_int(stmt, i);
543 case CTSVC_PROPERTY_EMAIL_TYPE:
544 email->type = ctsvc_stmt_get_int(stmt, i);
546 case CTSVC_PROPERTY_EMAIL_LABEL:
547 temp = ctsvc_stmt_get_text(stmt, i);
549 email->label = SAFE_STRDUP(temp);
551 case CTSVC_PROPERTY_EMAIL_EMAIL:
552 temp = ctsvc_stmt_get_text(stmt, i);
553 free(email->email_addr);
554 email->email_addr = SAFE_STRDUP(temp);
556 case CTSVC_PROPERTY_EMAIL_IS_DEFAULT:
557 email->is_default = ctsvc_stmt_get_int(stmt, i);
563 ctsvc_list_prepend(list, record);
565 ctsvc_stmt_finalize(stmt);
566 ctsvc_list_reverse(list);
569 return CONTACTS_ERROR_NONE;
572 ctsvc_db_plugin_info_s ctsvc_db_plugin_email = {
573 .is_query_only = false,
574 .insert_record = __ctsvc_db_email_insert_record,
575 .get_record = __ctsvc_db_email_get_record,
576 .update_record = __ctsvc_db_email_update_record,
577 .delete_record = __ctsvc_db_email_delete_record,
578 .get_all_records = __ctsvc_db_email_get_all_records,
579 .get_records_with_query = __ctsvc_db_email_get_records_with_query,
580 .insert_records = NULL,
581 .update_records = NULL,
582 .delete_records = NULL,
584 .get_count_with_query = NULL,
585 .replace_record = NULL,
586 .replace_records = NULL,