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_extension_helper.h"
28 #include "ctsvc_record.h"
29 #include "ctsvc_db_query.h"
30 #include "ctsvc_list.h"
31 #include "ctsvc_notification.h"
34 static int __ctsvc_db_extension_insert_record(contacts_record_h record, int *id)
38 char query[CTS_SQL_MAX_LEN] = {0};
39 ctsvc_extension_s *extension = (ctsvc_extension_s*)record;
41 RETVM_IF(NULL == extension->data2 && NULL == extension->data3 && NULL == extension->data4
42 && NULL == extension->data5 && NULL == extension->data6 && NULL == extension->data7
43 && NULL == extension->data8 && NULL == extension->data9 && NULL == extension->data10
44 && NULL == extension->data11 && NULL == extension->data12,
45 CONTACTS_ERROR_INVALID_PARAMETER, "Invalid parameter");
47 ret = ctsvc_begin_trans();
48 if (CONTACTS_ERROR_NONE != ret) {
50 ERR("ctsvc_begin_trans() Fail(%d)", ret);
55 snprintf(query, sizeof(query),
56 "SELECT addressbook_id FROM "CTSVC_DB_VIEW_CONTACT" WHERE contact_id = %d", extension->contact_id);
57 ret = ctsvc_query_get_first_int_result(query, &addressbook_id);
58 if (CONTACTS_ERROR_NONE != ret) {
59 ctsvc_end_trans(false);
60 if (CONTACTS_ERROR_NO_DATA == ret) {
62 ERR("No data : contact_id (%d) is not exist", extension->contact_id);
63 return CONTACTS_ERROR_INVALID_PARAMETER;
67 ERR("ctsvc_query_get_first_int_result() Fail(%d)", ret);
73 if (false == ctsvc_have_ab_write_permission(addressbook_id, false)) {
75 ERR("No permission in this addresbook_id(%d)", addressbook_id);
76 ctsvc_end_trans(false);
77 return CONTACTS_ERROR_PERMISSION_DENIED;
81 ret = ctsvc_db_extension_insert(record, extension->contact_id, false, id);
82 if (CONTACTS_ERROR_NONE != ret) {
84 ERR("ctsvc_begin_trans() Fail(%d)", ret);
85 ctsvc_end_trans(false);
90 ret = ctsvc_db_contact_update_changed_time(extension->contact_id);
91 if (CONTACTS_ERROR_NONE != ret) {
93 ERR("ctsvc_db_contact_update_changed_time() Fail(%d)", ret);
94 ctsvc_end_trans(false);
98 ctsvc_set_person_noti();
100 ret = ctsvc_end_trans(true);
101 if (ret < CONTACTS_ERROR_NONE) {
102 /* LCOV_EXCL_START */
103 ERR("ctsvc_end_trans() Fail(%d)", ret);
107 return CONTACTS_ERROR_NONE;
111 static int __ctsvc_db_extension_get_record(int id, contacts_record_h *out_record)
114 cts_stmt stmt = NULL;
115 char query[CTS_SQL_MAX_LEN] = {0};
117 RETV_IF(NULL == out_record, CONTACTS_ERROR_INVALID_PARAMETER);
120 snprintf(query, sizeof(query),
121 "SELECT id, data.contact_id, is_default, data1, data2, "
122 "data3, data4, data5, data6, data7, data8, data9, data10, data11, data12 "
123 "FROM "CTS_TABLE_DATA", "CTSVC_DB_VIEW_CONTACT" "
124 "ON "CTS_TABLE_DATA".contact_id = "CTSVC_DB_VIEW_CONTACT".contact_id "
125 "WHERE id = %d AND datatype = %d ",
126 id, CONTACTS_DATA_TYPE_EXTENSION);
128 ret = ctsvc_query_prepare(query, &stmt);
129 RETVM_IF(NULL == stmt, ret, "ctsvc_query_prepare() Fail(%d)", ret);
131 ret = ctsvc_stmt_step(stmt);
132 if (1 /*CTS_TRUE*/ != ret) {
133 /* LCOV_EXCL_START */
134 ERR("ctsvc_stmt_step() Fail(%d)", ret);
135 ctsvc_stmt_finalize(stmt);
136 if (CONTACTS_ERROR_NONE == ret)
137 return CONTACTS_ERROR_NO_DATA;
143 ctsvc_db_extension_get_value_from_stmt(stmt, out_record, 0);
145 ctsvc_stmt_finalize(stmt);
147 return CONTACTS_ERROR_NONE;
150 static int __ctsvc_db_extension_update_record(contacts_record_h record)
154 char query[CTS_SQL_MAX_LEN] = {0};
155 ctsvc_extension_s *extension = (ctsvc_extension_s*)record;
157 RETVM_IF(NULL == extension->data2 && NULL == extension->data3 && NULL == extension->data4 &&
158 NULL == extension->data5 && NULL == extension->data6 && NULL == extension->data7 &&
159 NULL == extension->data8 && NULL == extension->data9 && NULL == extension->data10 &&
160 NULL == extension->data11 && NULL == extension->data12, CONTACTS_ERROR_INVALID_PARAMETER, "extension is empty");
162 ret = ctsvc_begin_trans();
163 if (CONTACTS_ERROR_NONE != ret) {
164 /* LCOV_EXCL_START */
165 ERR("ctsvc_begin_trans() Fail(%d)", ret);
170 snprintf(query, sizeof(query),
171 "SELECT addressbook_id FROM "CTSVC_DB_VIEW_CONTACT" WHERE contact_id = %d", extension->contact_id);
172 ret = ctsvc_query_get_first_int_result(query, &addressbook_id);
173 if (CONTACTS_ERROR_NONE != ret) {
174 /* LCOV_EXCL_START */
175 ERR("No data : contact_id (%d) is not exist", extension->contact_id);
176 ctsvc_end_trans(false);
181 if (false == ctsvc_have_ab_write_permission(addressbook_id, false)) {
182 /* LCOV_EXCL_START */
183 ERR("No permission in this addresbook_id(%d)", addressbook_id);
184 ctsvc_end_trans(false);
185 return CONTACTS_ERROR_PERMISSION_DENIED;
189 ret = ctsvc_db_extension_update(record);
190 if (CONTACTS_ERROR_NONE != ret) {
191 /* LCOV_EXCL_START */
192 ERR("update record Fail(%d)", ret);
193 ctsvc_end_trans(false);
198 ret = ctsvc_db_contact_update_changed_time(extension->contact_id);
199 if (CONTACTS_ERROR_NONE != ret) {
200 /* LCOV_EXCL_START */
201 ERR("ctsvc_db_contact_update_changed_time() Fail(%d)", ret);
202 ctsvc_end_trans(false);
206 ctsvc_set_person_noti();
208 ret = ctsvc_end_trans(true);
209 if (ret < CONTACTS_ERROR_NONE) {
210 /* LCOV_EXCL_START */
211 ERR("ctsvc_end_trans() Fail(%d)", ret);
215 return CONTACTS_ERROR_NONE;
219 static int __ctsvc_db_extension_delete_record(int id)
223 char query[CTS_SQL_MAX_LEN] = {0};
224 cts_stmt stmt = NULL;
227 ret = ctsvc_begin_trans();
228 if (CONTACTS_ERROR_NONE != ret) {
229 /* LCOV_EXCL_START */
230 ERR("ctsvc_begin_trans() Fail(%d)", ret);
235 snprintf(query, sizeof(query),
236 "SELECT contact_id, addressbook_id FROM "CTSVC_DB_VIEW_CONTACT " "
237 "WHERE contact_id = (SELECT contact_id FROM "CTS_TABLE_DATA" WHERE id = %d)", id);
238 ret = ctsvc_query_prepare(query, &stmt);
240 /* LCOV_EXCL_START */
241 ERR("ctsvc_query_prepare Fail(%d)", ret);
242 ctsvc_end_trans(false);
246 ret = ctsvc_stmt_step(stmt);
248 /* LCOV_EXCL_START */
249 ERR("The id(%d) is Invalid(%d)", id, ret);
250 ctsvc_stmt_finalize(stmt);
251 ctsvc_end_trans(false);
252 if (CONTACTS_ERROR_NONE == ret)
253 return CONTACTS_ERROR_NO_DATA;
259 contact_id = ctsvc_stmt_get_int(stmt, 0);
260 addressbook_id = ctsvc_stmt_get_int(stmt, 1);
261 ctsvc_stmt_finalize(stmt);
263 if (false == ctsvc_have_ab_write_permission(addressbook_id, false)) {
264 /* LCOV_EXCL_START */
265 ERR("No permission in this addresbook_id(%d)", addressbook_id);
266 ctsvc_end_trans(false);
267 return CONTACTS_ERROR_PERMISSION_DENIED;
271 ret = ctsvc_db_extension_delete(id, false);
272 if (CONTACTS_ERROR_NONE != ret) {
273 /* LCOV_EXCL_START */
274 ERR("ctsvc_begin_trans() Fail(%d)", ret);
275 ctsvc_end_trans(false);
280 ret = ctsvc_db_contact_update_changed_time(contact_id);
281 if (CONTACTS_ERROR_NONE != ret) {
282 /* LCOV_EXCL_START */
283 ERR("ctsvc_db_contact_update_changed_time() Fail(%d)", ret);
284 ctsvc_end_trans(false);
288 ctsvc_set_person_noti();
290 ret = ctsvc_end_trans(true);
291 if (ret < CONTACTS_ERROR_NONE) {
292 /* LCOV_EXCL_START */
293 ERR("ctsvc_end_trans() Fail(%d)", ret);
297 return CONTACTS_ERROR_NONE;
301 static int __ctsvc_db_extension_get_all_records(int offset, int limit, contacts_list_h *out_list)
305 contacts_list_h list;
306 ctsvc_extension_s *extension;
307 cts_stmt stmt = NULL;
308 char query[CTS_SQL_MAX_LEN] = {0};
310 len = snprintf(query, sizeof(query),
311 "SELECT id, data.contact_id, is_default, data1, data2, "
312 "data3, data4, data5, data6, data7, data8, data9, data10, data11, data12 "
313 "FROM "CTS_TABLE_DATA", "CTSVC_DB_VIEW_CONTACT" "
314 "ON "CTS_TABLE_DATA".contact_id = "CTSVC_DB_VIEW_CONTACT".contact_id "
315 "WHERE datatype = %d AND is_my_profile=0 ",
316 CONTACTS_DATA_TYPE_EXTENSION);
319 len += snprintf(query+len, sizeof(query)-len, " LIMIT %d", limit);
321 len += snprintf(query+len, sizeof(query)-len, " OFFSET %d", offset);
324 ret = ctsvc_query_prepare(query, &stmt);
325 RETVM_IF(NULL == stmt, ret, "ctsvc_query_prepare() Fail(%d)", ret);
327 contacts_list_create(&list);
328 while ((ret = ctsvc_stmt_step(stmt))) {
329 if (1 /*CTS_TRUE */ != ret) {
330 /* LCOV_EXCL_START */
331 ERR("DB : ctsvc_stmt_step fail(%d)", ret);
332 ctsvc_stmt_finalize(stmt);
333 contacts_list_destroy(list, true);
337 ctsvc_db_extension_get_value_from_stmt(stmt, (contacts_record_h*)&extension, 0);
338 ctsvc_list_prepend(list, (contacts_record_h)extension);
340 ctsvc_stmt_finalize(stmt);
341 ctsvc_list_reverse(list);
344 return CONTACTS_ERROR_NONE;
347 static int __ctsvc_db_extension_get_records_with_query(contacts_query_h query, int offset,
348 int limit, contacts_list_h *out_list)
353 ctsvc_query_s *s_query;
355 contacts_list_h list;
356 ctsvc_extension_s *extension;
358 RETV_IF(NULL == query, CONTACTS_ERROR_INVALID_PARAMETER);
359 s_query = (ctsvc_query_s*)query;
361 ret = ctsvc_db_make_get_records_query_stmt(s_query, offset, limit, &stmt);
362 RETVM_IF(CONTACTS_ERROR_NONE != ret, ret, "ctsvc_db_make_get_records_query_stmt fail(%d)", ret);
364 contacts_list_create(&list);
365 while ((ret = ctsvc_stmt_step(stmt))) {
366 contacts_record_h record;
367 if (1 /*CTS_TRUE */ != ret) {
368 /* LCOV_EXCL_START */
369 ERR("ctsvc_stmt_step() Fail(%d)", ret);
370 ctsvc_stmt_finalize(stmt);
371 contacts_list_destroy(list, true);
376 contacts_record_create(_contacts_extension._uri, &record);
377 extension = (ctsvc_extension_s*)record;
378 if (0 == s_query->projection_count) {
379 field_count = s_query->property_count;
381 field_count = s_query->projection_count;
382 ret = ctsvc_record_set_projection_flags(record, s_query->projection,
383 s_query->projection_count, s_query->property_count);
385 if (CONTACTS_ERROR_NONE != ret)
386 ASSERT_NOT_REACHED("To set projection is Fail.\n");
389 for (i = 0; i < field_count; i++) {
392 if (0 == s_query->projection_count)
393 property_id = s_query->properties[i].property_id;
395 property_id = s_query->projection[i];
397 switch (property_id) {
398 case CTSVC_PROPERTY_EXTENSION_ID:
399 extension->id = ctsvc_stmt_get_int(stmt, i);
401 case CTSVC_PROPERTY_EXTENSION_CONTACT_ID:
402 extension->contact_id = ctsvc_stmt_get_int(stmt, i);
404 case CTSVC_PROPERTY_EXTENSION_DATA1:
405 extension->data1 = ctsvc_stmt_get_int(stmt, i);
407 case CTSVC_PROPERTY_EXTENSION_DATA2:
408 temp = ctsvc_stmt_get_text(stmt, i);
409 free(extension->data2);
410 extension->data2 = SAFE_STRDUP(temp);
412 case CTSVC_PROPERTY_EXTENSION_DATA3:
413 temp = ctsvc_stmt_get_text(stmt, i);
414 free(extension->data3);
415 extension->data3 = SAFE_STRDUP(temp);
417 case CTSVC_PROPERTY_EXTENSION_DATA4:
418 temp = ctsvc_stmt_get_text(stmt, i);
419 free(extension->data4);
420 extension->data4 = SAFE_STRDUP(temp);
422 case CTSVC_PROPERTY_EXTENSION_DATA5:
423 temp = ctsvc_stmt_get_text(stmt, i);
424 free(extension->data5);
425 extension->data5 = SAFE_STRDUP(temp);
427 case CTSVC_PROPERTY_EXTENSION_DATA6:
428 temp = ctsvc_stmt_get_text(stmt, i);
429 free(extension->data6);
430 extension->data6 = SAFE_STRDUP(temp);
432 case CTSVC_PROPERTY_EXTENSION_DATA7:
433 temp = ctsvc_stmt_get_text(stmt, i);
434 free(extension->data7);
435 extension->data7 = SAFE_STRDUP(temp);
437 case CTSVC_PROPERTY_EXTENSION_DATA8:
438 temp = ctsvc_stmt_get_text(stmt, i);
439 free(extension->data8);
440 extension->data8 = SAFE_STRDUP(temp);
442 case CTSVC_PROPERTY_EXTENSION_DATA9:
443 temp = ctsvc_stmt_get_text(stmt, i);
444 free(extension->data9);
445 extension->data9 = SAFE_STRDUP(temp);
447 case CTSVC_PROPERTY_EXTENSION_DATA10:
448 temp = ctsvc_stmt_get_text(stmt, i);
449 free(extension->data10);
450 extension->data10 = SAFE_STRDUP(temp);
452 case CTSVC_PROPERTY_EXTENSION_DATA11:
453 temp = ctsvc_stmt_get_text(stmt, i);
454 free(extension->data11);
455 extension->data11 = SAFE_STRDUP(temp);
457 case CTSVC_PROPERTY_EXTENSION_DATA12:
458 temp = ctsvc_stmt_get_text(stmt, i);
459 free(extension->data12);
460 extension->data12 = SAFE_STRDUP(temp);
466 ctsvc_list_prepend(list, record);
468 ctsvc_stmt_finalize(stmt);
469 ctsvc_list_reverse(list);
472 return CONTACTS_ERROR_NONE;
475 ctsvc_db_plugin_info_s ctsvc_db_plugin_extension = {
476 .is_query_only = false,
477 .insert_record = __ctsvc_db_extension_insert_record,
478 .get_record = __ctsvc_db_extension_get_record,
479 .update_record = __ctsvc_db_extension_update_record,
480 .delete_record = __ctsvc_db_extension_delete_record,
481 .get_all_records = __ctsvc_db_extension_get_all_records,
482 .get_records_with_query = __ctsvc_db_extension_get_records_with_query,
483 .insert_records = NULL,
484 .update_records = NULL,
485 .delete_records = NULL,
487 .get_count_with_query = NULL,
488 .replace_record = NULL,
489 .replace_records = NULL,