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_query.h"
26 #include "ctsvc_normalize.h"
27 #include "ctsvc_db_access_control.h"
28 #include "ctsvc_db_plugin_number_helper.h"
29 #include "ctsvc_db_plugin_contact_helper.h"
30 #include "ctsvc_record.h"
31 #include "ctsvc_notification.h"
32 #include "ctsvc_list.h"
35 static int __ctsvc_db_number_get_person_default_number(int person_id)
38 int default_number_id;
39 char query[CTS_SQL_MAX_LEN] = {0};
41 snprintf(query, sizeof(query),
42 "SELECT id FROM "CTS_TABLE_CONTACTS" c, "CTS_TABLE_DATA" d "
43 "WHERE c.person_id = %d AND d.datatype = %d AND c.contact_id = d.contact_id AND d.is_default = 1",
44 person_id, CONTACTS_DATA_TYPE_NUMBER);
45 ret = ctsvc_query_get_first_int_result(query, &default_number_id);
46 if (CONTACTS_ERROR_NONE != ret)
48 return default_number_id;
52 static int __ctsvc_db_number_update_person_has_phonenumber(int person_id, bool has_phonenumber)
55 char query[CTS_SQL_MAX_LEN] = {0};
57 snprintf(query, sizeof(query),
58 "UPDATE "CTS_TABLE_PERSONS" SET has_phonenumber = %d WHERE person_id = %d",
59 has_phonenumber, person_id);
61 ret = ctsvc_query_exec(query);
62 WARN_IF(CONTACTS_ERROR_NONE != ret, "ctsvc_query_exec() Fail(%d)", ret);
66 static int __ctsvc_db_number_get_default_number_id(int contact_id)
70 char query[CTS_SQL_MAX_LEN] = {0};
71 snprintf(query, sizeof(query),
72 "SELECT id FROM "CTS_TABLE_DATA" WHERE datatype=%d AND contact_id=%d AND is_default=1",
73 CONTACTS_DATA_TYPE_NUMBER, contact_id);
74 ret = ctsvc_query_get_first_int_result(query, &number_id);
75 if (CONTACTS_ERROR_NONE != ret)
80 static int __ctsvc_db_number_update_default(int number_id, int contact_id, bool is_default, bool is_primary_default)
83 char query[CTS_SQL_MAX_LEN] = {0};
85 snprintf(query, sizeof(query),
86 "UPDATE "CTS_TABLE_DATA" SET is_default = %d, is_primary_default = %d WHERE id = %d",
87 is_default, is_primary_default, number_id);
88 ret = ctsvc_query_exec(query);
89 WARN_IF(CONTACTS_ERROR_NONE != ret, "ctsvc_query_exec() Fail(%d)", ret);
93 static int __ctsvc_db_number_get_primary_default(int contact_id)
97 char query[CTS_SQL_MAX_LEN] = {0};
98 snprintf(query, sizeof(query),
99 "SELECT id FROM "CTS_TABLE_DATA" WHERE datatype=%d AND contact_id=%d AND is_primary_default=%d",
100 CONTACTS_DATA_TYPE_NUMBER, contact_id, 1);
101 ret = ctsvc_query_get_first_int_result(query, &number_id);
102 if (CONTACTS_ERROR_NONE != ret)
107 static int __ctsvc_db_number_get_primary_default_contact_id(int person_id)
110 int default_contact_id;
111 char query[CTS_SQL_MAX_LEN] = {0};
113 snprintf(query, sizeof(query),
114 "SELECT c.contact_id FROM "CTS_TABLE_CONTACTS" c, "CTS_TABLE_DATA" d "
115 "WHERE c.person_id = %d AND d.datatype = %d AND c.contact_id = d.contact_id AND d.is_primary_default = 1",
116 person_id, CONTACTS_DATA_TYPE_NUMBER);
117 ret = ctsvc_query_get_first_int_result(query, &default_contact_id);
118 if (CONTACTS_ERROR_NONE != ret)
120 return default_contact_id;
124 static int __ctsvc_db_number_set_primary_default(int number_id, bool is_primary_default)
127 char query[CTS_SQL_MAX_LEN] = {0};
129 snprintf(query, sizeof(query),
130 "UPDATE "CTS_TABLE_DATA" SET is_primary_default = %d WHERE id = %d",
131 is_primary_default, number_id);
132 ret = ctsvc_query_exec(query);
133 WARN_IF(CONTACTS_ERROR_NONE != ret, "ctsvc_query_exec() Fail(%d)", ret);
137 static int __ctsvc_db_number_insert_record(contacts_record_h record, int *id)
141 int old_default_number_id = 0;
143 char query[CTS_SQL_MAX_LEN] = {0};
144 cts_stmt stmt = NULL;
145 ctsvc_number_s *number = (ctsvc_number_s*)record;
146 RETV_IF(NULL == number->number, CONTACTS_ERROR_INVALID_PARAMETER);
148 ret = ctsvc_begin_trans();
149 if (CONTACTS_ERROR_NONE != ret) {
150 /* LCOV_EXCL_START */
151 ERR("ctsvc_begin_trans() Fail(%d)", ret);
156 snprintf(query, sizeof(query),
157 "SELECT addressbook_id, person_id FROM "CTSVC_DB_VIEW_CONTACT" WHERE contact_id = %d", number->contact_id);
158 ret = ctsvc_query_prepare(query, &stmt);
160 /* LCOV_EXCL_START */
161 ERR("ctsvc_query_prepare() Fail(%d)", ret);
162 ctsvc_end_trans(false);
167 ret = ctsvc_stmt_step(stmt);
169 /* LCOV_EXCL_START */
170 ERR("ctsvc_stmt_step() Fail(%d)", ret);
171 ctsvc_stmt_finalize(stmt);
172 ctsvc_end_trans(false);
173 if (CONTACTS_ERROR_NO_DATA)
174 return CONTACTS_ERROR_INVALID_PARAMETER;
179 addressbook_id = ctsvc_stmt_get_int(stmt, 0);
180 person_id = ctsvc_stmt_get_int(stmt, 1);
181 ctsvc_stmt_finalize(stmt);
183 if (false == ctsvc_have_ab_write_permission(addressbook_id, false)) {
184 /* LCOV_EXCL_START */
185 ERR("No permission in this addresbook_id(%d)", addressbook_id);
186 ctsvc_end_trans(false);
187 return CONTACTS_ERROR_PERMISSION_DENIED;
191 old_default_number_id = __ctsvc_db_number_get_default_number_id(number->contact_id);
192 if (0 == old_default_number_id)
193 number->is_default = true;
195 ret = ctsvc_db_number_insert(record, number->contact_id, false, id);
196 if (CONTACTS_ERROR_NONE != ret) {
197 /* LCOV_EXCL_START */
198 ERR("ctsvc_begin_trans() Fail(%d)", ret);
199 ctsvc_end_trans(false);
204 snprintf(query, sizeof(query),
205 "UPDATE "CTS_TABLE_CONTACTS" SET has_phonenumber = %d, changed_ver = %d, changed_time = %d "
206 "WHERE contact_id = %d",
207 1, ctsvc_get_next_ver(), (int)time(NULL), number->contact_id);
209 ret = ctsvc_query_exec(query);
210 if (CONTACTS_ERROR_NONE != ret) {
211 /* LCOV_EXCL_START */
212 ERR("ctsvc_query_exec() Fail(%d)", ret);
213 ctsvc_end_trans(false);
218 if (number->is_default) {
219 int primary_default_contact_id = 0;
220 __ctsvc_db_number_update_person_has_phonenumber(person_id, true);
222 primary_default_contact_id = __ctsvc_db_number_get_primary_default_contact_id(person_id);
223 if (0 == primary_default_contact_id || number->contact_id == primary_default_contact_id)
224 __ctsvc_db_number_set_primary_default(*id, true);
226 ctsvc_contact_update_display_name(number->contact_id, CONTACTS_DISPLAY_NAME_SOURCE_TYPE_NUMBER);
229 ctsvc_set_contact_noti();
230 ctsvc_set_person_noti();
232 ret = ctsvc_end_trans(true);
233 if (ret < CONTACTS_ERROR_NONE) {
234 /* LCOV_EXCL_START */
235 ERR("ctsvc_end_trans() Fail(%d)", ret);
239 return CONTACTS_ERROR_NONE;
243 static int __ctsvc_db_number_get_record(int id, contacts_record_h *out_record)
245 char query[CTS_SQL_MAX_LEN] = {0};
247 cts_stmt stmt = NULL;
249 snprintf(query, sizeof(query),
250 "SELECT id, contact_id, is_default, data1, data2, data3, data4, data5, data6 "
251 "FROM "CTSVC_DB_VIEW_NUMBER" WHERE id = %d", id);
253 ret = ctsvc_query_prepare(query, &stmt);
254 RETVM_IF(NULL == stmt, ret, "ctsvc_query_prepare() Fail(%d)", ret);
256 ret = ctsvc_stmt_step(stmt);
258 /* LCOV_EXCL_START */
259 ERR("ctsvc_stmt_step() Fail(%d)", ret);
260 ctsvc_stmt_finalize(stmt);
261 if (CONTACTS_ERROR_NONE == ret)
262 return CONTACTS_ERROR_NO_DATA;
268 ctsvc_db_number_get_value_from_stmt(stmt, out_record, 0);
269 ctsvc_stmt_finalize(stmt);
271 return CONTACTS_ERROR_NONE;
274 static int __ctsvc_db_number_update_record(contacts_record_h record)
278 char query[CTS_SQL_MAX_LEN] = {0};
279 ctsvc_number_s *number = (ctsvc_number_s*)record;
280 RETVM_IF(NULL == number->number, CONTACTS_ERROR_INVALID_PARAMETER, "number is empty");
282 ret = ctsvc_begin_trans();
283 if (CONTACTS_ERROR_NONE != ret) {
284 /* LCOV_EXCL_START */
285 ERR("ctsvc_begin_trans() Fail(%d)", ret);
290 snprintf(query, sizeof(query),
291 "SELECT addressbook_id FROM "CTSVC_DB_VIEW_CONTACT" WHERE contact_id = %d", number->contact_id);
292 ret = ctsvc_query_get_first_int_result(query, &addressbook_id);
293 if (CONTACTS_ERROR_NONE != ret) {
294 /* LCOV_EXCL_START */
295 ERR("No data : contact_id (%d) is not exist", number->contact_id);
296 ctsvc_end_trans(false);
301 if (false == ctsvc_have_ab_write_permission(addressbook_id, false)) {
302 /* LCOV_EXCL_START */
303 ERR("No permission in this addresbook_id(%d)", addressbook_id);
304 ctsvc_end_trans(false);
305 return CONTACTS_ERROR_PERMISSION_DENIED;
309 ret = ctsvc_db_number_update(record, false);
310 if (CONTACTS_ERROR_NONE != ret) {
311 /* LCOV_EXCL_START */
312 ERR("ctsvc_begin_trans() Fail(%d)", ret);
313 ctsvc_end_trans(false);
318 if (number->is_default) {
319 int old_primary_default_number_id = 0;
320 old_primary_default_number_id = __ctsvc_db_number_get_primary_default(number->contact_id);
321 if (old_primary_default_number_id)
322 __ctsvc_db_number_set_primary_default(number->id, true);
324 ctsvc_contact_update_display_name(number->contact_id, CONTACTS_DISPLAY_NAME_SOURCE_TYPE_NUMBER);
326 ret = ctsvc_db_contact_update_changed_time(number->contact_id);
327 if (CONTACTS_ERROR_NONE != ret) {
328 /* LCOV_EXCL_START */
329 ERR("ctsvc_db_contact_update_changed_time() Fail(%d)", ret);
330 ctsvc_end_trans(false);
334 ctsvc_set_person_noti();
336 ret = ctsvc_end_trans(true);
337 if (ret < CONTACTS_ERROR_NONE) {
338 /* LCOV_EXCL_START */
339 ERR("ctsvc_end_trans() Fail(%d)", ret);
343 return CONTACTS_ERROR_NONE;
347 static int __ctsvc_db_number_delete_record(int id)
355 int is_primary_default;
356 char query[CTS_SQL_MAX_LEN] = {0};
357 bool has_phonenumber = false;
358 cts_stmt stmt = NULL;
360 ret = ctsvc_begin_trans();
361 if (CONTACTS_ERROR_NONE != ret) {
362 /* LCOV_EXCL_START */
363 ERR("ctsvc_begin_trans() Fail(%d)", ret);
368 snprintf(query, sizeof(query),
369 "SELECT contact_id, person_id, addressbook_id FROM "CTSVC_DB_VIEW_CONTACT " "
370 "WHERE contact_id = (SELECT contact_id FROM "CTS_TABLE_DATA" WHERE id = %d)", id);
372 ret = ctsvc_query_prepare(query, &stmt);
374 /* LCOV_EXCL_START */
375 ERR("ctsvc_query_prepare() Fail(%d)", ret);
376 ctsvc_end_trans(false);
381 ret = ctsvc_stmt_step(stmt);
383 /* LCOV_EXCL_START */
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;
394 contact_id = ctsvc_stmt_get_int(stmt, 0);
395 person_id = ctsvc_stmt_get_int(stmt, 1);
396 addressbook_id = ctsvc_stmt_get_int(stmt, 2);
397 ctsvc_stmt_finalize(stmt);
399 if (false == ctsvc_have_ab_write_permission(addressbook_id, false)) {
400 /* LCOV_EXCL_START */
401 ERR("No permission in this addresbook_id(%d)", addressbook_id);
402 ctsvc_end_trans(false);
403 return CONTACTS_ERROR_PERMISSION_DENIED;
407 snprintf(query, sizeof(query),
408 "SELECT is_default, is_primary_default FROM "CTS_TABLE_DATA" WHERE id = %d", id);
409 ret = ctsvc_query_prepare(query, &stmt);
410 RETVM_IF(NULL == stmt, ret, "ctsvc_query_prepare() Fail(%d)", ret);
412 ret = ctsvc_stmt_step(stmt);
414 /* LCOV_EXCL_START */
415 ERR("ctsvc_stmt_step() Fail(%d)", ret);
416 ctsvc_stmt_finalize(stmt);
417 ctsvc_end_trans(false);
418 if (CONTACTS_ERROR_NONE == ret)
419 return CONTACTS_ERROR_NO_DATA;
424 is_default = ctsvc_stmt_get_int(stmt, 0);
425 is_primary_default = ctsvc_stmt_get_int(stmt, 1);
426 ctsvc_stmt_finalize(stmt);
428 ret = ctsvc_db_number_delete(id, false);
430 if (CONTACTS_ERROR_NONE != ret) {
431 /* LCOV_EXCL_START */
432 ERR("ctsvc_begin_trans() Fail(%d)", ret);
433 ctsvc_end_trans(false);
438 snprintf(query, sizeof(query),
439 "SELECT id FROM "CTS_TABLE_DATA" WHERE datatype = %d AND contact_id = %d AND is_my_profile = 0 limit 1",
440 CONTACTS_DATA_TYPE_NUMBER, contact_id);
441 ret = ctsvc_query_get_first_int_result(query, &number_id);
443 has_phonenumber = true;
445 snprintf(query, sizeof(query),
446 "UPDATE "CTS_TABLE_CONTACTS" SET has_phonenumber = %d, changed_ver = %d, changed_time = %d "
447 "WHERE contact_id = %d",
448 has_phonenumber, ctsvc_get_next_ver(), (int)time(NULL), contact_id);
450 ret = ctsvc_query_exec(query);
451 if (CONTACTS_ERROR_NONE != ret) {
452 /* LCOV_EXCL_START */
453 ERR("ctsvc_query_exec() Fail(%d)", ret);
454 ctsvc_end_trans(false);
461 __ctsvc_db_number_update_default(number_id, contact_id, is_default,
463 } else if (is_primary_default) {
464 int default_number_id = 0;
465 default_number_id = __ctsvc_db_number_get_person_default_number(person_id);
466 if (default_number_id)
467 __ctsvc_db_number_set_primary_default(default_number_id, true);
469 __ctsvc_db_number_update_person_has_phonenumber(person_id, false);
471 ctsvc_contact_update_display_name(contact_id, CONTACTS_DISPLAY_NAME_SOURCE_TYPE_NUMBER);
474 ctsvc_set_contact_noti();
475 ctsvc_set_person_noti();
477 ret = ctsvc_end_trans(true);
478 RETVM_IF(ret < CONTACTS_ERROR_NONE, ret, "ctsvc_end_trans() Fail(%d)", ret);
479 return CONTACTS_ERROR_NONE;
482 static int __ctsvc_db_number_get_all_records(int offset, int limit, contacts_list_h *out_list)
486 contacts_list_h list;
487 ctsvc_number_s *number;
488 cts_stmt stmt = NULL;
489 char query[CTS_SQL_MAX_LEN] = {0};
491 len = snprintf(query, sizeof(query),
492 "SELECT id, data.contact_id, is_default, data1, data2, data3, data4, data5, data6 "
493 "FROM "CTS_TABLE_DATA", "CTSVC_DB_VIEW_CONTACT" "
494 "ON "CTS_TABLE_DATA".contact_id = "CTSVC_DB_VIEW_CONTACT".contact_id "
495 "WHERE datatype = %d AND is_my_profile=0 ",
496 CONTACTS_DATA_TYPE_NUMBER);
499 len += snprintf(query+len, sizeof(query)-len, " LIMIT %d", limit);
501 len += snprintf(query+len, sizeof(query)-len, " OFFSET %d", offset);
504 ret = ctsvc_query_prepare(query, &stmt);
505 RETVM_IF(NULL == stmt, ret, "ctsvc_query_prepare() Fail(%d)", ret);
507 contacts_list_create(&list);
508 while ((ret = ctsvc_stmt_step(stmt))) {
510 /* LCOV_EXCL_START */
511 ERR("ctsvc_stmt_step() Fail(%d)", ret);
512 ctsvc_stmt_finalize(stmt);
513 contacts_list_destroy(list, true);
517 ctsvc_db_number_get_value_from_stmt(stmt, (contacts_record_h*)&number, 0);
518 ctsvc_list_prepend(list, (contacts_record_h)number);
520 ctsvc_stmt_finalize(stmt);
521 ctsvc_list_reverse(list);
524 return CONTACTS_ERROR_NONE;
527 static int __ctsvc_db_number_get_records_with_query(contacts_query_h query, int offset,
528 int limit, contacts_list_h *out_list)
533 ctsvc_query_s *s_query;
535 contacts_list_h list;
536 ctsvc_number_s *number;
538 RETV_IF(NULL == query, CONTACTS_ERROR_INVALID_PARAMETER);
539 s_query = (ctsvc_query_s*)query;
541 ret = ctsvc_db_make_get_records_query_stmt(s_query, offset, limit, &stmt);
542 RETVM_IF(CONTACTS_ERROR_NONE != ret, ret, "ctsvc_db_make_get_records_query_stmt fail(%d)", ret);
544 contacts_list_create(&list);
545 while ((ret = ctsvc_stmt_step(stmt))) {
546 contacts_record_h record;
548 /* LCOV_EXCL_START */
549 ERR("ctsvc_stmt_step() Fail(%d)", ret);
550 ctsvc_stmt_finalize(stmt);
551 contacts_list_destroy(list, true);
556 contacts_record_create(_contacts_number._uri, &record);
557 number = (ctsvc_number_s*)record;
558 if (0 == s_query->projection_count) {
559 field_count = s_query->property_count;
561 field_count = s_query->projection_count;
562 ret = ctsvc_record_set_projection_flags(record, s_query->projection,
563 s_query->projection_count, s_query->property_count);
565 if (CONTACTS_ERROR_NONE != ret)
566 ASSERT_NOT_REACHED("To set projection is Fail.\n");
569 for (i = 0; i < field_count; i++) {
572 if (0 == s_query->projection_count)
573 property_id = s_query->properties[i].property_id;
575 property_id = s_query->projection[i];
577 switch (property_id) {
578 case CTSVC_PROPERTY_NUMBER_ID:
579 number->id = ctsvc_stmt_get_int(stmt, i);
581 case CTSVC_PROPERTY_NUMBER_CONTACT_ID:
582 number->contact_id = ctsvc_stmt_get_int(stmt, i);
584 case CTSVC_PROPERTY_NUMBER_TYPE:
585 number->type = ctsvc_stmt_get_int(stmt, i);
587 case CTSVC_PROPERTY_NUMBER_IS_DEFAULT:
588 number->is_default = ctsvc_stmt_get_int(stmt, i);
590 case CTSVC_PROPERTY_NUMBER_LABEL:
591 temp = ctsvc_stmt_get_text(stmt, i);
593 number->label = SAFE_STRDUP(temp);
595 case CTSVC_PROPERTY_NUMBER_NUMBER:
596 temp = ctsvc_stmt_get_text(stmt, i);
597 free(number->number);
598 number->number = SAFE_STRDUP(temp);
600 case CTSVC_PROPERTY_NUMBER_NUMBER_FILTER:
601 temp = ctsvc_stmt_get_text(stmt, i);
602 free(number->lookup);
603 number->lookup = SAFE_STRDUP(temp);
609 ctsvc_list_prepend(list, record);
611 ctsvc_stmt_finalize(stmt);
612 ctsvc_list_reverse(list);
615 return CONTACTS_ERROR_NONE;
618 ctsvc_db_plugin_info_s ctsvc_db_plugin_number = {
619 .is_query_only = false,
620 .insert_record = __ctsvc_db_number_insert_record,
621 .get_record = __ctsvc_db_number_get_record,
622 .update_record = __ctsvc_db_number_update_record,
623 .delete_record = __ctsvc_db_number_delete_record,
624 .get_all_records = __ctsvc_db_number_get_all_records,
625 .get_records_with_query = __ctsvc_db_number_get_records_with_query,
626 .insert_records = NULL,
627 .update_records = NULL,
628 .delete_records = NULL,
630 .get_count_with_query = NULL,
631 .replace_record = NULL,
632 .replace_records = NULL,