modify terminology:calendar->book,allday->localtime,normal->utime,svc->service
[platform/core/pim/calendar-service.git] / server / db / cal_db_plugin_book.c
1 /*
2  * Calendar Service
3  *
4  * Copyright (c) 2012 - 2015 Samsung Electronics Co., Ltd. All rights reserved.
5  *
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
9  *
10  * http://www.apache.org/licenses/LICENSE-2.0
11  *
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.
17  *
18  */
19 #include <stdlib.h>
20
21 #include "cal_internal.h"
22 #include "cal_typedef.h"
23 #include "cal_view.h"
24 #include "cal_record.h"
25
26 #include "cal_db.h"
27 #include "cal_db_util.h"
28 #include "cal_db_query.h"
29 #include "cal_access_control.h"
30 #include "cal_utils.h"
31
32 #ifdef CAL_IPC_SERVER
33 #include "cal_server_calendar_delete.h"
34 #endif
35 #include "cal_access_control.h"
36
37 /*
38  * db plugin function
39  */
40 static int _cal_db_book_insert_record(calendar_record_h record, int* id);
41 static int _cal_db_book_get_record(int id, calendar_record_h* out_record);
42 static int _cal_db_book_update_record(calendar_record_h record);
43 static int _cal_db_book_delete_record(int id);
44 static int _cal_db_book_get_all_records(int offset, int limit, calendar_list_h* out_list);
45 static int _cal_db_book_get_records_with_query(calendar_query_h query, int offset, int limit, calendar_list_h* out_list);
46 static int _cal_db_book_delete_records(int ids[], int count);
47 static int _cal_db_book_get_count(int *out_count);
48 static int _cal_db_book_get_count_with_query(calendar_query_h query, int *out_count);
49 static int _cal_db_book_replace_record(calendar_record_h record, int id);
50
51 /*
52  * static function
53  */
54 static void _cal_db_book_get_stmt(sqlite3_stmt *stmt, calendar_record_h record);
55 static void _cal_db_book_get_property_stmt(sqlite3_stmt *stmt,
56                 unsigned int property, int stmt_count, calendar_record_h record);
57 static void _cal_db_book_get_projection_stmt(sqlite3_stmt *stmt,
58                 const unsigned int *projection, const int projection_count,
59                 calendar_record_h record);
60 static int _cal_db_book_update_projection(calendar_record_h record);
61
62 cal_db_plugin_cb_s cal_db_book_plugin_cb = {
63         .is_query_only = false,
64         .insert_record = _cal_db_book_insert_record,
65         .get_record = _cal_db_book_get_record,
66         .update_record = _cal_db_book_update_record,
67         .delete_record = _cal_db_book_delete_record,
68         .get_all_records = _cal_db_book_get_all_records,
69         .get_records_with_query = _cal_db_book_get_records_with_query,
70         .insert_records = NULL, /* use insert record with bulk count */
71         .update_records = NULL,
72         .delete_records = _cal_db_book_delete_records,
73         .get_count = _cal_db_book_get_count,
74         .get_count_with_query = _cal_db_book_get_count_with_query,
75         .replace_record = _cal_db_book_replace_record,
76         .replace_records = NULL
77 };
78
79 static bool _cal_db_book_check_value_validation(cal_book_s* calendar)
80 {
81         RETVM_IF(NULL == calendar, CALENDAR_ERROR_INVALID_PARAMETER, "calendar is NULL");
82
83         switch (calendar->store_type) {
84         case CALENDAR_BOOK_TYPE_NONE:
85         case CALENDAR_BOOK_TYPE_EVENT:
86         case CALENDAR_BOOK_TYPE_TODO:
87                 return true;
88
89         default:
90                 /* LCOV_EXCL_START */
91                 ERR("store type is invalid(%d)", calendar->store_type);
92                 return false;
93                 /* LCOV_EXCL_STOP */
94         }
95         return true;
96 }
97
98 static int _cal_db_book_insert_record(calendar_record_h record, int* id)
99 {
100         CAL_FN_CALL();
101
102         int ret = 0;
103
104         RETV_IF(NULL == record, CALENDAR_ERROR_INVALID_PARAMETER);
105
106         cal_book_s *book =  (cal_book_s *)(record);
107         if (false == _cal_db_book_check_value_validation(book)) {
108                 /* LCOV_EXCL_START */
109                 ERR("cal_db_book_check_value_validation() Fail");
110                 return CALENDAR_ERROR_INVALID_PARAMETER;
111                 /* LCOV_EXCL_STOP */
112         }
113
114         char *client_label = NULL;
115         client_label = cal_access_control_get_label();
116
117         char query[CAL_DB_SQL_MAX_LEN];
118         snprintf(query, sizeof(query), "INSERT INTO %s (uid, updated, name, description, "
119                         "color, location, visibility, sync_event, account_id, store_type, "
120                         "sync_data1, sync_data2, sync_data3, sync_data4, mode, owner_label) "
121                         "VALUES (?, %d, ?, ?, ?, ?, %d, %d, %d, %d, ?, ?, ?, ?, %d, ?)",
122                         CAL_TABLE_CALENDAR, book->updated, book->visibility, book->sync_event,
123                         book->account_id, book->store_type, book->mode);
124
125         sqlite3_stmt *stmt = NULL;
126         ret = cal_db_util_query_prepare(query, &stmt);
127         if (CALENDAR_ERROR_NONE != ret) {
128                 /* LCOV_EXCL_START */
129                 ERR("cal_db_util_query_prepare() Fail(%d)", ret);
130                 SECURE("query[%s]", query);
131                 free(client_label);
132                 return ret;
133                 /* LCOV_EXCL_STOP */
134         }
135
136         if (book->uid)
137                 cal_db_util_stmt_bind_text(stmt, 1, book->uid);
138         if (book->name)
139                 cal_db_util_stmt_bind_text(stmt, 2, book->name);
140         if (book->description)
141                 cal_db_util_stmt_bind_text(stmt, 3, book->description);
142         if (book->color)
143                 cal_db_util_stmt_bind_text(stmt, 4, book->color);
144         if (book->location)
145                 cal_db_util_stmt_bind_text(stmt, 5, book->location);
146         if (book->sync_data1)
147                 cal_db_util_stmt_bind_text(stmt, 6, book->sync_data1);
148         if (book->sync_data2)
149                 cal_db_util_stmt_bind_text(stmt, 7, book->sync_data2);
150         if (book->sync_data3)
151                 cal_db_util_stmt_bind_text(stmt, 8, book->sync_data3);
152         if (book->sync_data4)
153                 cal_db_util_stmt_bind_text(stmt, 9, book->sync_data4);
154         if (client_label)
155                 cal_db_util_stmt_bind_text(stmt, 10, client_label);
156
157         ret = cal_db_util_stmt_step(stmt);
158         if (CALENDAR_ERROR_NONE != ret) {
159                 /* LCOV_EXCL_START */
160                 ERR("cal_db_util_stmt_step() Fail(%d)", ret);
161                 sqlite3_finalize(stmt);
162                 free(client_label);
163                 return ret;
164                 /* LCOV_EXCL_STOP */
165         }
166         sqlite3_finalize(stmt);
167         free(client_label);
168
169         int index = 0;
170         index = cal_db_util_last_insert_id();
171         /* access control */
172         cal_access_control_reset();
173
174         if (id)
175                 *id = index;
176
177         cal_db_util_notify(CAL_NOTI_TYPE_BOOK);
178
179         return CALENDAR_ERROR_NONE;
180 }
181
182 static int _cal_db_book_get_record(int id, calendar_record_h* out_record)
183 {
184         char query[CAL_DB_SQL_MAX_LEN];
185         sqlite3_stmt *stmt = NULL;
186         int ret = 0;
187
188         ret = calendar_record_create(_calendar_book._uri, out_record);
189         if (CALENDAR_ERROR_NONE != ret) {
190                 /* LCOV_EXCL_START */
191                 ERR("calendar_record_create() Fail(%d)", ret);
192                 return CALENDAR_ERROR_OUT_OF_MEMORY;
193                 /* LCOV_EXCL_STOP */
194         }
195
196         snprintf(query, sizeof(query), "SELECT * FROM %s WHERE id=%d AND (deleted = 0)",
197                         CAL_TABLE_CALENDAR,     id);
198         ret = cal_db_util_query_prepare(query, &stmt);
199         if (CALENDAR_ERROR_NONE != ret) {
200                 /* LCOV_EXCL_START */
201                 ERR("cal_db_util_query_prepare() Fail(%d)", ret);
202                 SECURE("query[%s]", query);
203                 calendar_record_destroy(*out_record, true);
204                 *out_record = NULL;
205                 return ret;
206                 /* LCOV_EXCL_STOP */
207         }
208         ret = cal_db_util_stmt_step(stmt);
209         if (CAL_SQLITE_ROW != ret) {
210                 /* LCOV_EXCL_START */
211                 ERR("cal_db_util_stmt_step() Fail(%d)", ret);
212                 SECURE("query[%s]", query);
213                 sqlite3_finalize(stmt);
214                 calendar_record_destroy(*out_record, true);
215                 *out_record = NULL;
216                 if (CALENDAR_ERROR_NONE == ret)
217                         return CALENDAR_ERROR_DB_RECORD_NOT_FOUND;
218                 return ret;
219                 /* LCOV_EXCL_STOP */
220         }
221
222         _cal_db_book_get_stmt(stmt, *out_record);
223         sqlite3_finalize(stmt);
224
225         return CALENDAR_ERROR_NONE;
226 }
227
228 static int _cal_db_book_update_record(calendar_record_h record)
229 {
230         int ret = 0;
231
232         RETV_IF(NULL == record, CALENDAR_ERROR_INVALID_PARAMETER);
233
234         cal_book_s* book =  (cal_book_s*)(record);
235         if (false == _cal_db_book_check_value_validation(book)) {
236                 /* LCOV_EXCL_START */
237                 ERR("cal_db_book_check_value_validation() Fail");
238                 return CALENDAR_ERROR_INVALID_PARAMETER;
239                 /* LCOV_EXCL_STOP */
240         }
241
242         if (book->common.properties_flags != NULL)
243                 return _cal_db_book_update_projection(record);
244
245
246         char query[CAL_DB_SQL_MAX_LEN] = {0};
247         snprintf(query, sizeof(query), "UPDATE %s SET "
248                         "uid =?, updated = %d, name =?, description =?, color =?, location =?, "
249                         "visibility =%d, sync_event =%d, account_id =%d, store_type =%d, "
250                         "sync_data1 =?, sync_data2 =?, sync_data3 =?, sync_data4 =?, mode =%d "
251                         "WHERE id =%d",
252                         CAL_TABLE_CALENDAR, book->updated, book->visibility, book->sync_event,
253                         book->account_id, book->store_type, book->mode, book->index);
254
255         sqlite3_stmt *stmt = NULL;
256         ret = cal_db_util_query_prepare(query, &stmt);
257         if (CALENDAR_ERROR_NONE != ret) {
258                 /* LCOV_EXCL_START */
259                 ERR("cal_db_util_query_prepare() Fail(%d)", ret);
260                 SECURE("query[%s]", query);
261                 return ret;
262                 /* LCOV_EXCL_STOP */
263         }
264
265         if (book->uid)
266                 cal_db_util_stmt_bind_text(stmt, 1, book->uid);
267         if (book->name)
268                 cal_db_util_stmt_bind_text(stmt, 2, book->name);
269         if (book->description)
270                 cal_db_util_stmt_bind_text(stmt, 3, book->description);
271         if (book->color)
272                 cal_db_util_stmt_bind_text(stmt, 4, book->color);
273         if (book->location)
274                 cal_db_util_stmt_bind_text(stmt, 5, book->location);
275         if (book->sync_data1)
276                 cal_db_util_stmt_bind_text(stmt, 6, book->sync_data1);
277         if (book->sync_data2)
278                 cal_db_util_stmt_bind_text(stmt, 7, book->sync_data2);
279         if (book->sync_data3)
280                 cal_db_util_stmt_bind_text(stmt, 8, book->sync_data3);
281         if (book->sync_data4)
282                 cal_db_util_stmt_bind_text(stmt, 9, book->sync_data4);
283
284         ret = cal_db_util_stmt_step(stmt);
285         if (CALENDAR_ERROR_NONE != ret) {
286                 /* LCOV_EXCL_START */
287                 ERR("cal_db_util_stmt_step() Fail(%d)", ret);
288                 sqlite3_finalize(stmt);
289                 SECURE("query[%s]", query);
290                 return ret;
291                 /* LCOV_EXCL_STOP */
292         }
293         sqlite3_finalize(stmt);
294         cal_db_util_notify(CAL_NOTI_TYPE_BOOK);
295
296         return CALENDAR_ERROR_NONE;
297 }
298
299 static int _cal_db_book_delete_record(int id)
300 {
301         int ret = CALENDAR_ERROR_NONE;
302         char query[CAL_DB_SQL_MAX_LEN] = {0};
303         int calendar_book_id = -1;
304
305         snprintf(query, sizeof(query), "SELECT id FROM %s WHERE id = %d",
306                         CAL_TABLE_CALENDAR, id);
307         ret = cal_db_util_query_get_first_int_result(query, NULL, &calendar_book_id);
308         if (CALENDAR_ERROR_NONE != ret) {
309                 /* LCOV_EXCL_START */
310                 ERR("cal_db_util_query_get_first_int_result() Fail(%d)", ret);
311                 return ret;
312                 /* LCOV_EXCL_STOP */
313         }
314
315         int count = 0;
316         int count2 = 0;
317         snprintf(query, sizeof(query), "select count(*) from %s", CAL_TABLE_UTIME_INSTANCE);
318         ret = cal_db_util_query_get_first_int_result(query, NULL, &count);
319         if (CALENDAR_ERROR_NONE != ret) {
320                 /* LCOV_EXCL_START */
321                 ERR("cal_db_util_query_get_first_int_result() Fail");
322                 return ret;
323                 /* LCOV_EXCL_STOP */
324         }
325
326         snprintf(query, sizeof(query), "select count(*) from %s", CAL_TABLE_LOCALTIME_INSTANCE);
327         ret = cal_db_util_query_get_first_int_result(query, NULL, &count2);
328         if (CALENDAR_ERROR_NONE != ret) {
329                 /* LCOV_EXCL_START */
330                 ERR("cal_db_util_query_get_first_int_result() Fail");
331                 return ret;
332                 /* LCOV_EXCL_STOP */
333         }
334
335         count += count2;
336
337         if (1000 < count) {
338                 snprintf(query, sizeof(query), "UPDATE %s SET deleted = 1 WHERE id = %d", CAL_TABLE_CALENDAR, id);
339                 ret = cal_db_util_query_exec(query);
340                 RETVM_IF(CALENDAR_ERROR_NONE != ret, ret, "cal_db_util_query_exec() Fail(%d)", ret);
341                 cal_server_calendar_delete_start();
342         } else {
343                 snprintf(query, sizeof(query), "DELETE FROM %s WHERE id = %d", CAL_TABLE_CALENDAR, id);
344                 ret = cal_db_util_query_exec(query);
345                 RETVM_IF(CALENDAR_ERROR_NONE != ret, ret, "cal_db_util_query_exec() Fail(%d)", ret);
346
347                 snprintf(query, sizeof(query), "DELETE FROM %s WHERE calendar_id = %d", CAL_TABLE_SCHEDULE, id);
348                 ret = cal_db_util_query_exec(query);
349                 RETVM_IF(CALENDAR_ERROR_NONE != ret, ret, "cal_db_util_query_exec() Fail(%d)", ret);
350         }
351
352         snprintf(query, sizeof(query), "DELETE FROM %s WHERE calendar_id = %d", CAL_TABLE_DELETED, id);
353         ret = cal_db_util_query_exec(query);
354         RETVM_IF(CALENDAR_ERROR_NONE != ret, ret, "cal_db_util_query_exec() Fail(%d)", ret);
355
356         cal_access_control_reset();
357
358         cal_db_util_notify(CAL_NOTI_TYPE_BOOK);
359         return CALENDAR_ERROR_NONE;
360 }
361
362 static int _cal_db_book_replace_record(calendar_record_h record, int id)
363 {
364         int ret = 0;
365
366         RETV_IF(NULL == record, CALENDAR_ERROR_INVALID_PARAMETER);
367
368         cal_book_s *book =  (cal_book_s *)(record);
369         if (false == _cal_db_book_check_value_validation(book)) {
370                 /* LCOV_EXCL_START */
371                 ERR("cal_db_book_check_value_validation() Fail");
372                 return CALENDAR_ERROR_INVALID_PARAMETER;
373                 /* LCOV_EXCL_STOP */
374         }
375
376         book->index = id;
377         if (book->common.properties_flags)
378                 return _cal_db_book_update_projection(record);
379
380         char query[CAL_DB_SQL_MAX_LEN] = {0};
381         snprintf(query, sizeof(query), "UPDATE %s SET "
382                         "uid =?, updated =%d, name =?, description =?, color =?, location =?, "
383                         "visibility =%d, sync_event =%d, account_id =%d, store_type =%d, "
384                         "sync_data1 =?, sync_data2 =?, sync_data3 =?, sync_data4 =?, mode =%d "
385                         "WHERE id =%d",
386                         CAL_TABLE_CALENDAR, book->updated, book->visibility, book->sync_event,
387                         book->account_id, book->store_type, book->mode, id);
388
389         sqlite3_stmt *stmt = NULL;
390         ret = cal_db_util_query_prepare(query, &stmt);
391         if (CALENDAR_ERROR_NONE != ret) {
392                 /* LCOV_EXCL_START */
393                 ERR("cal_db_util_query_prepare() Fail(%d)", ret);
394                 SECURE("query[%s]", query);
395                 return ret;
396                 /* LCOV_EXCL_STOP */
397         }
398
399         if (book->uid)
400                 cal_db_util_stmt_bind_text(stmt, 1, book->uid);
401         if (book->name)
402                 cal_db_util_stmt_bind_text(stmt, 2, book->name);
403         if (book->description)
404                 cal_db_util_stmt_bind_text(stmt, 3, book->description);
405         if (book->color)
406                 cal_db_util_stmt_bind_text(stmt, 4, book->color);
407         if (book->location)
408                 cal_db_util_stmt_bind_text(stmt, 5, book->location);
409         if (book->sync_data1)
410                 cal_db_util_stmt_bind_text(stmt, 6, book->sync_data1);
411         if (book->sync_data2)
412                 cal_db_util_stmt_bind_text(stmt, 7, book->sync_data2);
413         if (book->sync_data3)
414                 cal_db_util_stmt_bind_text(stmt, 8, book->sync_data3);
415         if (book->sync_data4)
416                 cal_db_util_stmt_bind_text(stmt, 9, book->sync_data4);
417
418         ret = cal_db_util_stmt_step(stmt);
419         if (CALENDAR_ERROR_NONE != ret) {
420                 /* LCOV_EXCL_START */
421                 ERR("cal_db_util_stmt_step() Fail(%d)", ret);
422                 sqlite3_finalize(stmt);
423                 SECURE("query[%s]", query);
424                 return ret;
425                 /* LCOV_EXCL_STOP */
426         }
427         sqlite3_finalize(stmt);
428         cal_db_util_notify(CAL_NOTI_TYPE_BOOK);
429
430         return CALENDAR_ERROR_NONE;
431 }
432
433 static int _cal_db_book_get_all_records(int offset, int limit, calendar_list_h* out_list)
434 {
435         int ret = CALENDAR_ERROR_NONE;
436         char offsetquery[CAL_DB_SQL_MAX_LEN] = {0};
437         char limitquery[CAL_DB_SQL_MAX_LEN] = {0};
438         sqlite3_stmt *stmt = NULL;
439
440         RETV_IF(NULL == out_list, CALENDAR_ERROR_INVALID_PARAMETER);
441
442         ret = calendar_list_create(out_list);
443         RETVM_IF(CALENDAR_ERROR_NONE != ret, ret, "calendar_list_create() Fail(%d)", ret);
444
445         if (0 < offset)
446                 snprintf(offsetquery, sizeof(offsetquery), "OFFSET %d", offset);
447         if (0 < limit)
448                 snprintf(limitquery, sizeof(limitquery), "LIMIT %d", limit);
449
450         char *query_str = NULL;
451         cal_db_append_string(&query_str, "SELECT * FROM");
452         cal_db_append_string(&query_str, CAL_TABLE_CALENDAR);
453         cal_db_append_string(&query_str, "WHERE deleted = 0");
454         cal_db_append_string(&query_str, limitquery);
455         cal_db_append_string(&query_str, offsetquery);
456
457         ret = cal_db_util_query_prepare(query_str, &stmt);
458         if (CALENDAR_ERROR_NONE != ret) {
459                 /* LCOV_EXCL_START */
460                 ERR("cal_db_util_query_prepare() Fail(%d)", ret);
461                 SECURE("query[%s]", query_str);
462                 calendar_list_destroy(*out_list, true);
463                 *out_list = NULL;
464                 free(query_str);
465                 return ret;
466                 /* LCOV_EXCL_STOP */
467         }
468
469         while (CAL_SQLITE_ROW == cal_db_util_stmt_step(stmt)) {
470                 calendar_record_h record;
471                 ret = calendar_record_create(_calendar_book._uri, &record);
472                 if (CALENDAR_ERROR_NONE != ret) {
473                         /* LCOV_EXCL_START */
474                         calendar_list_destroy(*out_list, true);
475                         *out_list = NULL;
476                         sqlite3_finalize(stmt);
477                         CAL_FREE(query_str);
478                         return ret;
479                         /* LCOV_EXCL_STOP */
480                 }
481                 _cal_db_book_get_stmt(stmt, record);
482
483                 ret = calendar_list_add(*out_list, record);
484                 if (CALENDAR_ERROR_NONE != ret) {
485                         /* LCOV_EXCL_START */
486                         calendar_list_destroy(*out_list, true);
487                         *out_list = NULL;
488                         calendar_record_destroy(record, true);
489                         sqlite3_finalize(stmt);
490                         CAL_FREE(query_str);
491                         return ret;
492                         /* LCOV_EXCL_STOP */
493                 }
494         }
495
496         sqlite3_finalize(stmt);
497         CAL_FREE(query_str);
498         return CALENDAR_ERROR_NONE;
499 }
500
501 static int _cal_db_book_get_records_with_query(calendar_query_h query, int offset, int limit, calendar_list_h* out_list)
502 {
503         cal_query_s *que = NULL;
504         int i = 0;
505         int ret = CALENDAR_ERROR_NONE;
506         char *condition = NULL;
507         GSList *bind_text = NULL, *cursor = NULL;
508         sqlite3_stmt *stmt = NULL;
509
510         que = (cal_query_s *)query;
511
512         /* make filter */
513         if (que->filter) {
514                 ret = cal_db_query_create_condition(query, &condition, &bind_text);
515                 if (CALENDAR_ERROR_NONE != ret) {
516                         /* LCOV_EXCL_START */
517                         ERR("cal_db_query_create_condition() Fail(%d), ret");
518                         return ret;
519                         /* LCOV_EXCL_STOP */
520                 }
521         }
522
523         /* make: projection */
524         char *projection = NULL;
525         ret = cal_db_query_create_projection(query, &projection);
526
527         char *query_str = NULL;
528         /* query: projection */
529         if (projection) {
530                 cal_db_append_string(&query_str, "SELECT");
531                 cal_db_append_string(&query_str, projection);
532                 cal_db_append_string(&query_str, "FROM");
533                 cal_db_append_string(&query_str, CAL_TABLE_CALENDAR);
534                 CAL_FREE(projection);
535         } else {
536                 cal_db_append_string(&query_str, "SELECT * FROM");
537                 cal_db_append_string(&query_str, CAL_TABLE_CALENDAR);
538         }
539
540         /* query: condition */
541         if (condition) {
542                 cal_db_append_string(&query_str,  "WHERE (");
543                 cal_db_append_string(&query_str, condition);
544                 cal_db_append_string(&query_str, ") AND (deleted = 0)");
545         }
546
547         /* order */
548         char *order = NULL;
549         ret = cal_db_query_create_order(query, condition, &order);
550         if (order) {
551                 cal_db_append_string(&query_str, order);
552                 CAL_FREE(order);
553         }
554         CAL_FREE(condition);
555
556         /* limit, offset */
557         char buf[CAL_STR_SHORT_LEN32] = {0};
558         if (0 < limit) {
559                 snprintf(buf, sizeof(buf), "LIMIT %d", limit);
560                 cal_db_append_string(&query_str, buf);
561
562                 if (0 < offset) {
563                         snprintf(buf, sizeof(buf), "OFFSET %d", offset);
564                         cal_db_append_string(&query_str, buf);
565                 }
566         }
567
568         /* query */
569         ret = cal_db_util_query_prepare(query_str, &stmt);
570         SECURE("[TEST]---------query[%s]", query_str);
571         if (CALENDAR_ERROR_NONE != ret) {
572                 /* LCOV_EXCL_START */
573                 ERR("cal_db_util_query_prepare() Fail(%d)", ret);
574                 SECURE("query[%s]", query_str);
575                 if (bind_text) {
576                         g_slist_free_full(bind_text, free);
577                         bind_text = NULL;
578                 }
579                 free(query_str);
580                 return ret;
581                 /* LCOV_EXCL_STOP */
582         }
583
584         /* bind text */
585         if (bind_text) {
586                 g_slist_length(bind_text);
587                 for (cursor = bind_text, i = 1; cursor; cursor = cursor->next, i++)
588                         cal_db_util_stmt_bind_text(stmt, i, cursor->data);
589         }
590
591         ret = calendar_list_create(out_list);
592         if (CALENDAR_ERROR_NONE != ret) {
593                 /* LCOV_EXCL_START */
594                 ERR("calendar_list_create() Fail");
595                 if (bind_text) {
596                         g_slist_free_full(bind_text, free);
597                         bind_text = NULL;
598                 }
599                 sqlite3_finalize(stmt);
600                 CAL_FREE(query_str);
601                 return ret;
602                 /* LCOV_EXCL_STOP */
603         }
604
605         while (CAL_SQLITE_ROW == cal_db_util_stmt_step(stmt)) {
606                 calendar_record_h record;
607                 ret = calendar_record_create(_calendar_book._uri, &record);
608                 if (CALENDAR_ERROR_NONE != ret) {
609                         /* LCOV_EXCL_START */
610                         ERR("calendar_record_create() Fail(%d)", ret);
611                         calendar_list_destroy(*out_list, true);
612                         *out_list = NULL;
613
614                         if (bind_text) {
615                                 g_slist_free_full(bind_text, free);
616                                 bind_text = NULL;
617                         }
618                         sqlite3_finalize(stmt);
619                         CAL_FREE(query_str);
620                         return ret;
621                         /* LCOV_EXCL_STOP */
622                 }
623
624                 if (0 < que->projection_count) {
625                         cal_record_set_projection(record,
626                                         que->projection, que->projection_count, que->property_count);
627
628                         _cal_db_book_get_projection_stmt(stmt,
629                                         que->projection, que->projection_count,
630                                         record);
631                 } else {
632                         _cal_db_book_get_stmt(stmt, record);
633                 }
634
635                 ret = calendar_list_add(*out_list, record);
636                 if (CALENDAR_ERROR_NONE != ret) {
637                         /* LCOV_EXCL_START */
638                         ERR("calendar_list_add() Fail(%d)", ret);
639                         calendar_list_destroy(*out_list, true);
640                         *out_list = NULL;
641                         calendar_record_destroy(record, true);
642
643                         if (bind_text) {
644                                 g_slist_free_full(bind_text, free);
645                                 bind_text = NULL;
646                         }
647                         sqlite3_finalize(stmt);
648                         CAL_FREE(query_str);
649                         return ret;
650                         /* LCOV_EXCL_STOP */
651                 }
652         }
653
654         if (bind_text) {
655                 g_slist_free_full(bind_text, free);
656                 bind_text = NULL;
657         }
658         sqlite3_finalize(stmt);
659         CAL_FREE(query_str);
660
661         return CALENDAR_ERROR_NONE;
662 }
663
664 static int _cal_db_book_delete_records(int ids[], int count)
665 {
666         int ret = 0;
667         int i = 0;
668         for (i = 0; i < count; i++) {
669                 ret = _cal_db_book_delete_record(ids[i]);
670                 if (CALENDAR_ERROR_NONE != ret) {
671                         /* LCOV_EXCL_START */
672                         ERR("_cal_db_book_delete_record() Fail(%d)", ret);
673                         return CALENDAR_ERROR_DB_FAILED;
674                         /* LCOV_EXCL_STOP */
675                 }
676         }
677         return CALENDAR_ERROR_NONE;
678 }
679
680 static int _cal_db_book_get_count(int *out_count)
681 {
682         RETV_IF(NULL == out_count, CALENDAR_ERROR_INVALID_PARAMETER);
683
684         char *query_str = NULL;
685         cal_db_append_string(&query_str, "SELECT count(*) FROM");
686         cal_db_append_string(&query_str, CAL_TABLE_CALENDAR);
687         cal_db_append_string(&query_str, "WHERE deleted = 0");
688
689         int ret = 0;
690         int count = 0;
691         ret = cal_db_util_query_get_first_int_result(query_str, NULL, &count);
692         if (CALENDAR_ERROR_NONE != ret) {
693                 /* LCOV_EXCL_START */
694                 ERR("cal_db_util_query_get_first_int_result() failed");
695                 CAL_FREE(query_str);
696                 return ret;
697                 /* LCOV_EXCL_STOP */
698         }
699         DBG("count(%d) str[%s]", count, query_str);
700         CAL_FREE(query_str);
701
702         *out_count = count;
703         return CALENDAR_ERROR_NONE;
704 }
705
706 static int _cal_db_book_get_count_with_query(calendar_query_h query, int *out_count)
707 {
708         cal_query_s *que = NULL;
709         int ret = CALENDAR_ERROR_NONE;
710         char *condition = NULL;
711         char *table_name;
712         int count = 0;
713         GSList *bind_text = NULL;
714
715         que = (cal_query_s *)query;
716
717         if (CAL_STRING_EQUAL == strcmp(que->view_uri, CALENDAR_VIEW_BOOK)) {
718                 table_name = cal_strdup(CAL_TABLE_CALENDAR);
719         } else {
720                 /* LCOV_EXCL_START */
721                 ERR("uri(%s) not support get records with query", que->view_uri);
722                 return CALENDAR_ERROR_INVALID_PARAMETER;
723                 /* LCOV_EXCL_STOP */
724         }
725
726         /* make filter */
727         if (que->filter) {
728                 ret = cal_db_query_create_condition(query, &condition, &bind_text);
729                 if (CALENDAR_ERROR_NONE != ret) {
730                         /* LCOV_EXCL_START */
731                         ERR("cal_db_query_create_condition() Fail(%d), ret");
732                         CAL_FREE(table_name);
733                         return ret;
734                         /* LCOV_EXCL_STOP */
735                 }
736         }
737
738         char *query_str = NULL;
739         /* query: select */
740         cal_db_append_string(&query_str, "SELECT count(*) FROM");
741         cal_db_append_string(&query_str, table_name);
742         CAL_FREE(table_name);
743
744         /* query: condition */
745         if (condition) {
746                 cal_db_append_string(&query_str, "WHERE (");
747                 cal_db_append_string(&query_str, condition);
748                 cal_db_append_string(&query_str, ") AND (deleted = 0)");
749                 CAL_FREE(condition);
750         }
751
752         /* query */
753         ret = cal_db_util_query_get_first_int_result(query_str, bind_text, &count);
754         if (CALENDAR_ERROR_NONE != ret) {
755                 /* LCOV_EXCL_START */
756                 ERR("cal_db_util_query_get_first_int_result() failed");
757                 if (bind_text) {
758                         g_slist_free_full(bind_text, free);
759                         bind_text = NULL;
760                 }
761                 CAL_FREE(query_str);
762                 return ret;
763                 /* LCOV_EXCL_STOP */
764         }
765         DBG("count(%d) str[%s]", count, query_str);
766
767         if (out_count)
768                 *out_count = count;
769
770         if (bind_text) {
771                 g_slist_free_full(bind_text, free);
772                 bind_text = NULL;
773         }
774         CAL_FREE(query_str);
775         return CALENDAR_ERROR_NONE;
776 }
777
778 static void _cal_db_book_get_stmt(sqlite3_stmt *stmt, calendar_record_h record)
779 {
780         cal_book_s* calendar =  (cal_book_s*)(record);
781         int count = 0;
782         const unsigned char *temp;
783
784         calendar->index = sqlite3_column_int(stmt, count++);
785
786         temp = sqlite3_column_text(stmt, count++);
787         calendar->uid = cal_strdup((const char*)temp);
788
789         calendar->updated = sqlite3_column_int(stmt, count++);
790
791         temp = sqlite3_column_text(stmt, count++);
792         calendar->name = cal_strdup((const char*)temp);
793
794         temp = sqlite3_column_text(stmt, count++);
795         calendar->description = cal_strdup((const char*)temp);
796
797         temp = sqlite3_column_text(stmt, count++);
798         calendar->color = cal_strdup((const char*)temp);
799
800         temp = sqlite3_column_text(stmt, count++);
801         calendar->location = cal_strdup((const char*)temp);
802
803         calendar->visibility = sqlite3_column_int(stmt, count++);
804         calendar->sync_event = sqlite3_column_int(stmt, count++);
805         calendar->is_deleted = sqlite3_column_int(stmt, count++);
806         calendar->account_id = sqlite3_column_int(stmt, count++);
807         calendar->store_type = sqlite3_column_int(stmt, count++);
808
809         temp = sqlite3_column_text(stmt, count++);
810         calendar->sync_data1 = cal_strdup((const char*)temp);
811         temp = sqlite3_column_text(stmt, count++);
812         calendar->sync_data2 = cal_strdup((const char*)temp);
813         temp = sqlite3_column_text(stmt, count++);
814         calendar->sync_data3 = cal_strdup((const char*)temp);
815         temp = sqlite3_column_text(stmt, count++);
816         calendar->sync_data4 = cal_strdup((const char*)temp);
817
818         /* deleted */
819         sqlite3_column_int(stmt, count++);
820
821         /* mode */
822         calendar->mode = sqlite3_column_int(stmt, count++);
823
824         /* owner_label */
825         sqlite3_column_text(stmt, count++);
826 }
827
828 static void _cal_db_book_get_property_stmt(sqlite3_stmt *stmt,
829                 unsigned int property, int stmt_count, calendar_record_h record)
830 {
831         cal_book_s* calendar =  (cal_book_s*)(record);
832         const unsigned char *temp;
833
834         switch (property) {
835         case CAL_PROPERTY_BOOK_ID:
836                 calendar->index = sqlite3_column_int(stmt, stmt_count);
837                 break;
838         case CAL_PROPERTY_BOOK_UID:
839                 temp = sqlite3_column_text(stmt, stmt_count);
840                 calendar->uid = cal_strdup((const char*)temp);
841                 break;
842         case CAL_PROPERTY_BOOK_NAME:
843                 temp = sqlite3_column_text(stmt, stmt_count);
844                 calendar->name = cal_strdup((const char*)temp);
845                 break;
846         case CAL_PROPERTY_BOOK_DESCRIPTION:
847                 temp = sqlite3_column_text(stmt, stmt_count);
848                 calendar->description = cal_strdup((const char*)temp);
849                 break;
850         case CAL_PROPERTY_BOOK_COLOR:
851                 temp = sqlite3_column_text(stmt, stmt_count);
852                 calendar->color = cal_strdup((const char*)temp);
853                 break;
854         case CAL_PROPERTY_BOOK_LOCATION:
855                 temp = sqlite3_column_text(stmt, stmt_count);
856                 calendar->location = cal_strdup((const char*)temp);
857                 break;
858         case CAL_PROPERTY_BOOK_VISIBILITY:
859                 calendar->visibility = sqlite3_column_int(stmt, stmt_count);
860                 break;
861         case CAL_PROPERTY_BOOK_SYNC_EVENT:
862                 calendar->sync_event = sqlite3_column_int(stmt, stmt_count);
863                 break;
864         case CAL_PROPERTY_BOOK_ACCOUNT_ID:
865                 calendar->account_id = sqlite3_column_int(stmt, stmt_count);
866                 break;
867         case CAL_PROPERTY_BOOK_STORE_TYPE:
868                 calendar->store_type = sqlite3_column_int(stmt, stmt_count);
869                 break;
870         case CAL_PROPERTY_BOOK_SYNC_DATA1:
871                 temp = sqlite3_column_text(stmt, stmt_count);
872                 calendar->sync_data1 = cal_strdup((const char*)temp);
873                 break;
874         case CAL_PROPERTY_BOOK_SYNC_DATA2:
875                 temp = sqlite3_column_text(stmt, stmt_count);
876                 calendar->sync_data1 = cal_strdup((const char*)temp);
877                 break;
878         case CAL_PROPERTY_BOOK_SYNC_DATA3:
879                 temp = sqlite3_column_text(stmt, stmt_count);
880                 calendar->sync_data1 = cal_strdup((const char*)temp);
881                 break;
882         case CAL_PROPERTY_BOOK_SYNC_DATA4:
883                 temp = sqlite3_column_text(stmt, stmt_count);
884                 calendar->sync_data1 = cal_strdup((const char*)temp);
885                 break;
886         case CAL_PROPERTY_BOOK_MODE:
887                 calendar->mode = sqlite3_column_int(stmt, stmt_count);
888                 break;
889         default:
890                 break;
891         }
892
893         return;
894 }
895
896 static void _cal_db_book_get_projection_stmt(sqlite3_stmt *stmt,
897                 const unsigned int *projection, const int projection_count,
898                 calendar_record_h record)
899 {
900         int i = 0;
901
902         for (i = 0; i < projection_count; i++)
903                 _cal_db_book_get_property_stmt(stmt, projection[i], i, record);
904 }
905
906 static int _cal_db_book_update_projection(calendar_record_h record)
907 {
908         char query[CAL_DB_SQL_MAX_LEN] = {0};
909         sqlite3_stmt *stmt = NULL;
910         cal_book_s* calendar =  (cal_book_s*)(record);
911         int ret = 0;
912         char* set = NULL;
913         GSList *bind_text = NULL;
914         GSList *cursor = NULL;
915
916         ret = cal_db_query_create_projection_update_set(record, &set, &bind_text);
917         RETV_IF(CALENDAR_ERROR_NONE != ret, ret);
918
919         snprintf(query, sizeof(query), "UPDATE %s SET %s "
920                         "WHERE id = %d",
921                         CAL_TABLE_CALENDAR, set,
922                         calendar->index);
923
924         ret = cal_db_util_query_prepare(query, &stmt);
925         if (CALENDAR_ERROR_NONE != ret) {
926                 /* LCOV_EXCL_START */
927                 ERR("cal_db_util_query_prepare() Fail(%d)", ret);
928                 SECURE("query[%s]", query);
929                 free(set);
930                 if (bind_text) {
931                         g_slist_free_full(bind_text, free);
932                         bind_text = NULL;
933                 }
934                 return ret;
935                 /* LCOV_EXCL_STOP */
936         }
937
938         /* bind */
939         if (bind_text) {
940                 int i = 0;
941                 for (cursor = bind_text, i = 1; cursor; cursor = cursor->next, i++)
942                         cal_db_util_stmt_bind_text(stmt, i, cursor->data);
943         }
944
945         ret = cal_db_util_stmt_step(stmt);
946         if (CALENDAR_ERROR_NONE != ret) {
947                 /* LCOV_EXCL_START */
948                 ERR("cal_db_util_stmt_step() Fail(%d)", ret);
949                 SECURE("query[%s]", query);
950                 sqlite3_finalize(stmt);
951                 free(set);
952                 if (bind_text) {
953                         g_slist_free_full(bind_text, free);
954                         bind_text = NULL;
955                 }
956                 return ret;
957                 /* LCOV_EXCL_STOP */
958         }
959
960         sqlite3_finalize(stmt);
961
962         cal_db_util_notify(CAL_NOTI_TYPE_BOOK);
963
964         CAL_FREE(set);
965         if (bind_text) {
966                 g_slist_free_full(bind_text, free);
967                 bind_text = NULL;
968         }
969
970         return CALENDAR_ERROR_NONE;
971 }