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.
22 #include "ctsvc_internal.h"
23 #include "ctsvc_db_schema.h"
24 #include "ctsvc_db_sqlite.h"
25 #include "ctsvc_db_utils.h"
26 #include "ctsvc_list.h"
27 #include "ctsvc_db_init.h"
28 #include "ctsvc_db_query.h"
29 #include "ctsvc_db_plugin_person_helper.h"
30 #include "ctsvc_server_person.h"
31 #include "ctsvc_record.h"
32 #include "ctsvc_notification.h"
33 #include "ctsvc_db_access_control.h"
34 #include "ctsvc_db_plugin_addressbook_helper.h"
37 static int __ctsvc_db_addressbook_value_set(cts_stmt stmt, contacts_record_h *record)
42 ctsvc_addressbook_s *addressbook;
44 ret = contacts_record_create(_contacts_address_book._uri, record);
45 RETVM_IF(CONTACTS_ERROR_NONE != ret, ret, "contacts_record_create Fail(%d)", ret);
46 addressbook = (ctsvc_addressbook_s*)*record;
49 addressbook->id = ctsvc_stmt_get_int(stmt, i++);
50 temp = ctsvc_stmt_get_text(stmt, i++);
51 addressbook->name = SAFE_STRDUP(temp);
52 addressbook->account_id = ctsvc_stmt_get_int(stmt, i++);
53 addressbook->mode = ctsvc_stmt_get_int(stmt, i++);
55 return CONTACTS_ERROR_NONE;
58 static int __ctsvc_db_addressbook_get_record(int id, contacts_record_h *out_record)
62 char query[CTS_SQL_MAX_LEN] = {0};
63 contacts_record_h record;
65 RETV_IF(NULL == out_record, CONTACTS_ERROR_INVALID_PARAMETER);
68 snprintf(query, sizeof(query),
69 "SELECT addressbook_id, addressbook_name, account_id, mode, last_sync_ver "
70 "FROM "CTS_TABLE_ADDRESSBOOKS" WHERE addressbook_id = %d", id);
72 ret = ctsvc_query_prepare(query, &stmt);
73 RETVM_IF(NULL == stmt, ret, "ctsvc_query_prepare() Fail(%d)", ret);
75 ret = ctsvc_stmt_step(stmt);
76 if (1 /*CTS_TRUE*/ != ret) {
78 ERR("ctsvc_stmt_step() Fail(%d)", ret);
79 ctsvc_stmt_finalize(stmt);
80 if (CONTACTS_ERROR_NONE == ret)
81 return CONTACTS_ERROR_NO_DATA;
87 ret = __ctsvc_db_addressbook_value_set(stmt, &record);
89 ctsvc_stmt_finalize(stmt);
90 if (CONTACTS_ERROR_NONE != ret) {
92 ERR("__ctsvc_db_addressbook_value_set(ALL) Fail(%d)", ret);
99 return CONTACTS_ERROR_NONE;
103 static int __ctsvc_db_addressbook_insert_record(contacts_record_h record, int *id)
106 cts_stmt stmt = NULL;
107 char query[CTS_SQL_MAX_LEN] = {0};
109 ctsvc_addressbook_s *addressbook = (ctsvc_addressbook_s*)record;
111 RETV_IF(NULL == record, CONTACTS_ERROR_INVALID_PARAMETER);
112 RETV_IF(NULL == addressbook->name, CONTACTS_ERROR_INVALID_PARAMETER);
113 RETVM_IF(CTSVC_RECORD_ADDRESSBOOK != addressbook->base.r_type, CONTACTS_ERROR_INVALID_PARAMETER,
114 "record is invalid type(%d)", addressbook->base.r_type);
116 ret = ctsvc_begin_trans();
117 RETVM_IF(ret < CONTACTS_ERROR_NONE, ret, "ctsvc_begin_trans() Fail(%d)", ret);
119 /* Can not insert addressbook which has same account_id */
121 account_h account = NULL;
122 snprintf(query, sizeof(query),
123 "SELECT addressbook_id FROM "CTS_TABLE_ADDRESSBOOKS" WHERE account_id = %d",
124 addressbook->account_id);
125 ret = ctsvc_query_get_first_int_result(query, &addresbook_id);
126 if (CONTACTS_ERROR_NO_DATA != ret) {
127 /* LCOV_EXCL_START */
128 ctsvc_end_trans(false);
129 if (CONTACTS_ERROR_NONE == ret) {
130 ERR("One addressbook which has account_id(%d) already exists", addressbook->account_id);
131 return CONTACTS_ERROR_INVALID_PARAMETER;
133 ERR("ctsvc_query_get_first_int_result() Fail(%d)", ret);
139 /* check account_id validation */
140 ret = account_create(&account);
141 if (ACCOUNT_ERROR_NONE != ret) {
142 /* LCOV_EXCL_START */
143 ERR("account_create() Fail(%d)", ret);
144 ctsvc_end_trans(false);
145 return CONTACTS_ERROR_SYSTEM;
148 ret = account_query_account_by_account_id(addressbook->account_id, &account);
149 if (ACCOUNT_ERROR_NONE != ret) {
150 /* LCOV_EXCL_START */
151 ERR("account_query_account_by_account_id Faild(%d) : account_id(%d)", ret, addressbook->account_id);
152 ret = account_destroy(account);
153 WARN_IF(ret != ACCOUNT_ERROR_NONE, "account_destroy Fail(%d)", ret);
154 ctsvc_end_trans(false);
155 return CONTACTS_ERROR_INVALID_PARAMETER;
158 ret = account_destroy(account);
159 WARN_IF(ret != ACCOUNT_ERROR_NONE, "account_destroy Fail(%d)", ret);
161 snprintf(query, sizeof(query),
162 "INSERT INTO %s(addressbook_name, account_id, mode, smack_label) "
163 "VALUES(?, %d, %d, ?)",
164 CTS_TABLE_ADDRESSBOOKS, addressbook->account_id, addressbook->mode);
166 ret = ctsvc_query_prepare(query, &stmt);
168 /* LCOV_EXCL_START */
169 ERR("ctsvc_query_prepare() Fail(%d)", ret);
170 ctsvc_end_trans(false);
175 ctsvc_stmt_bind_text(stmt, 1, addressbook->name);
177 smack = ctsvc_get_client_smack_label();
179 ctsvc_stmt_bind_text(stmt, 2, smack);
183 ret = ctsvc_stmt_step(stmt);
184 if (CONTACTS_ERROR_NONE != ret) {
185 /* LCOV_EXCL_START */
186 ERR("ctsvc_stmt_step() Fail(%d)", ret);
187 ctsvc_stmt_finalize(stmt);
192 /* int index = ctsvc_db_get_last_insert_id(); */
194 *id = ctsvc_db_get_last_insert_id();
195 ctsvc_stmt_finalize(stmt);
197 ctsvc_set_addressbook_noti();
198 ret = ctsvc_end_trans(true);
199 if (ret < CONTACTS_ERROR_NONE) {
200 /* LCOV_EXCL_START */
201 ERR("ctsvc_end_trans() Fail(%d)", ret);
206 /* addressbook->id = index; */
209 return CONTACTS_ERROR_NONE;
213 /* ROLLBACK TRANSACTION */
214 ctsvc_end_trans(false);
219 static int __ctsvc_db_addressbook_update_record(contacts_record_h record)
221 int ret = CONTACTS_ERROR_NONE;
223 GSList *bind_text = NULL;
224 GSList *cursor = NULL;
225 ctsvc_addressbook_s *addressbook = (ctsvc_addressbook_s*)record;
227 RETV_IF(NULL == record, CONTACTS_ERROR_INVALID_PARAMETER);
228 RETVM_IF(CTSVC_PROPERTY_FLAG_DIRTY != (addressbook->base.property_flag & CTSVC_PROPERTY_FLAG_DIRTY), CONTACTS_ERROR_NONE, "No update");
229 RETV_IF(NULL == addressbook->name, CONTACTS_ERROR_INVALID_PARAMETER);
230 RETVM_IF(CTSVC_RECORD_ADDRESSBOOK != addressbook->base.r_type, CONTACTS_ERROR_INVALID_PARAMETER,
231 "record is invalid type(%d)", addressbook->base.r_type);
233 ret = ctsvc_begin_trans();
234 RETVM_IF(ret, ret, "ctsvc_begin_trans() Fail(%d)", ret);
236 ret = ctsvc_is_owner(addressbook->id);
237 if (CONTACTS_ERROR_NONE != ret) {
238 /* LCOV_EXCL_START */
239 if (CONTACTS_ERROR_PERMISSION_DENIED == ret)
240 ERR("Does not have permission of address_book (%d)", addressbook->id);
242 ERR("ctsvc_is_owner Fail(%d)", ret);
243 ctsvc_end_trans(false);
249 char query[CTS_SQL_MAX_LEN] = {0};
250 cts_stmt stmt = NULL;
252 if (CONTACTS_ERROR_NONE != (ret = ctsvc_db_create_set_query(record, &set, &bind_text))) break;
253 if (NULL == set || '\0' == *set)
256 snprintf(query, sizeof(query), "UPDATE %s SET %s WHERE addressbook_id = %d", CTS_TABLE_ADDRESSBOOKS, set, addressbook->id);
257 ret = ctsvc_query_prepare(query, &stmt);
259 ERR("ctsvc_query_prepare() Fail(%d)", ret);
264 for (cursor = bind_text, i = 1; cursor; cursor = cursor->next, i++) {
265 const char *text = cursor->data;
267 ctsvc_stmt_bind_text(stmt, i, text);
270 ret = ctsvc_stmt_step(stmt);
271 if (CONTACTS_ERROR_NONE != ret) {
272 ERR("ctsvc_stmt_step() Fail(%d)", ret);
273 ctsvc_stmt_finalize(stmt);
276 ctsvc_stmt_finalize(stmt);
278 ctsvc_set_addressbook_noti();
280 CTSVC_RECORD_RESET_PROPERTY_FLAGS((ctsvc_record_s*)record);
284 for (cursor = bind_text; cursor; cursor = cursor->next) {
288 g_slist_free(bind_text);
291 if (CONTACTS_ERROR_NONE != ret) {
292 ctsvc_end_trans(false);
296 ret = ctsvc_end_trans(true);
297 RETVM_IF(ret < CONTACTS_ERROR_NONE, ret, "ctsvc_end_trans() Fail(%d)", ret);
299 return CONTACTS_ERROR_NONE;
302 static int __ctsvc_db_addressbook_delete_record(int addressbook_id)
306 if (0 /*CTS_ADDRESSBOOK_INTERNAL*/ == addressbook_id)
307 return ctsvc_addressbook_reset_internal_addressbook();
309 char query[CTS_SQL_MAX_LEN] = {0};
310 int ret = ctsvc_begin_trans();
311 RETVM_IF(ret < CONTACTS_ERROR_NONE, ret, "ctsvc_begin_trans() Fail(%d)", ret);
313 ret = ctsvc_is_owner(addressbook_id);
314 if (CONTACTS_ERROR_NONE != ret) {
315 if (CONTACTS_ERROR_PERMISSION_DENIED == ret)
316 ERR("Does not have permission to delete address_book (%d)", addressbook_id);
318 ERR("ctsvc_is_owner Fail(%d)", ret);
319 ctsvc_end_trans(false);
323 snprintf(query, sizeof(query), "DELETE FROM %s WHERE addressbook_id = %d",
324 CTS_TABLE_ADDRESSBOOKS, addressbook_id);
328 ret = ctsvc_query_exec(query);
329 if (CONTACTS_ERROR_NONE != ret) {
330 /* LCOV_EXCL_START */
331 ERR("ctsvc_query_exec() Fail(%d)", ret);
336 ret = ctsvc_db_change();
338 ctsvc_set_my_profile_noti();
339 ctsvc_set_contact_noti();
340 /* person noti will set in ctsvc_person_do_garbage_collection : ctsvc_set_person_noti(); */
341 ctsvc_set_group_noti();
342 ctsvc_set_addressbook_noti();
344 ret = CONTACTS_ERROR_NO_DATA;
348 ret = ctsvc_person_do_garbage_collection();
349 if (CONTACTS_ERROR_NONE != ret) {
350 /* LCOV_EXCL_START */
351 ERR("ctsvc_person_garbagecollection() Fail(%d)", ret);
356 ret = ctsvc_end_trans(true);
357 if (ret < CONTACTS_ERROR_NONE) {
358 /* LCOV_EXCL_START */
359 ERR("ctsvc_end_trans() Fail(%d)", ret);
364 return CONTACTS_ERROR_NONE;
368 ctsvc_end_trans(false);
373 static int __ctsvc_db_addressbook_get_all_records(int offset, int limit,
374 contacts_list_h *out_list)
379 char query[CTS_SQL_MAX_LEN] = {0};
380 contacts_list_h list;
382 len = snprintf(query, sizeof(query),
383 "SELECT addressbook_id, addressbook_name, account_id, mode, last_sync_ver "
384 "FROM "CTS_TABLE_ADDRESSBOOKS);
386 len += snprintf(query+len, sizeof(query)-len,
387 " ORDER BY account_id, addressbook_id");
390 len += snprintf(query+len, sizeof(query)-len, " LIMIT %d", limit);
392 len += snprintf(query+len, sizeof(query)-len, " OFFSET %d", offset);
395 ret = ctsvc_query_prepare(query, &stmt);
396 RETVM_IF(NULL == stmt, ret, "ctsvc_query_prepare() Fail(%d)", ret);
398 contacts_list_create(&list);
399 while ((ret = ctsvc_stmt_step(stmt))) {
400 contacts_record_h record;
402 /* LCOV_EXCL_START */
403 ERR("ctsvc_stmt_step() Fail(%d)", ret);
404 ctsvc_stmt_finalize(stmt);
405 contacts_list_destroy(list, true);
409 __ctsvc_db_addressbook_value_set(stmt, &record);
411 ctsvc_list_prepend(list, record);
413 ctsvc_stmt_finalize(stmt);
414 ctsvc_list_reverse(list);
416 *out_list = (contacts_list_h)list;
417 return CONTACTS_ERROR_NONE;
420 static int __ctsvc_db_addressbook_get_records_with_query(contacts_query_h query, int offset, int limit, contacts_list_h *out_list)
425 ctsvc_query_s *s_query;
427 contacts_list_h list;
428 ctsvc_addressbook_s *addressbook;
430 RETV_IF(NULL == query, CONTACTS_ERROR_INVALID_PARAMETER);
431 s_query = (ctsvc_query_s*)query;
433 ret = ctsvc_db_make_get_records_query_stmt(s_query, offset, limit, &stmt);
434 RETVM_IF(CONTACTS_ERROR_NONE != ret, ret, "ctsvc_db_make_get_records_query_stmt fail(%d)", ret);
436 contacts_list_create(&list);
437 while ((ret = ctsvc_stmt_step(stmt))) {
438 contacts_record_h record;
440 /* LCOV_EXCL_START */
441 ERR("ctsvc_stmt_step() Fail(%d)", ret);
442 ctsvc_stmt_finalize(stmt);
443 contacts_list_destroy(list, true);
448 contacts_record_create(_contacts_address_book._uri, &record);
449 addressbook = (ctsvc_addressbook_s*)record;
450 if (0 == s_query->projection_count) {
451 field_count = s_query->property_count;
453 field_count = s_query->projection_count;
454 ret = ctsvc_record_set_projection_flags(record, s_query->projection,
455 s_query->projection_count, s_query->property_count);
457 if (CONTACTS_ERROR_NONE != ret)
458 ASSERT_NOT_REACHED("To set projection is Fail.\n");
461 for (i = 0; i < field_count; i++) {
464 if (0 == s_query->projection_count)
465 property_id = s_query->properties[i].property_id;
467 property_id = s_query->projection[i];
469 switch (property_id) {
470 case CTSVC_PROPERTY_ADDRESSBOOK_ID:
471 addressbook->id = ctsvc_stmt_get_int(stmt, i);
473 case CTSVC_PROPERTY_ADDRESSBOOK_NAME:
474 temp = ctsvc_stmt_get_text(stmt, i);
475 free(addressbook->name);
476 addressbook->name = SAFE_STRDUP(temp);
478 case CTSVC_PROPERTY_ADDRESSBOOK_MODE:
479 addressbook->mode = ctsvc_stmt_get_int(stmt, i);
481 case CTSVC_PROPERTY_ADDRESSBOOK_ACCOUNT_ID:
482 addressbook->account_id = ctsvc_stmt_get_int(stmt, i);
488 ctsvc_list_prepend(list, record);
490 ctsvc_stmt_finalize(stmt);
491 ctsvc_list_reverse(list);
493 *out_list = (contacts_list_h)list;
495 return CONTACTS_ERROR_NONE;
498 ctsvc_db_plugin_info_s ctsvc_db_plugin_addressbook = {
499 .is_query_only = false,
500 .insert_record = __ctsvc_db_addressbook_insert_record,
501 .get_record = __ctsvc_db_addressbook_get_record,
502 .update_record = __ctsvc_db_addressbook_update_record,
503 .delete_record = __ctsvc_db_addressbook_delete_record,
504 .get_all_records = __ctsvc_db_addressbook_get_all_records,
505 .get_records_with_query = __ctsvc_db_addressbook_get_records_with_query,
506 .insert_records = NULL,
507 .update_records = NULL,
508 .delete_records = NULL,
510 .get_count_with_query = NULL,
511 .replace_record = NULL,
512 .replace_records = NULL,