e91d8221feb1c5d7812d406e39719b823dcdf7eb
[platform/core/pim/calendar-service.git] / server / db / cal_db_plugin_todo.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
20 #include <stdio.h>
21 #include <stdlib.h>
22
23 #include "cal_internal.h"
24 #include "cal_typedef.h"
25 #include "cal_view.h"
26 #include "cal_record.h"
27 #include "cal_list.h"
28
29 #include "cal_db_util.h"
30 #include "cal_db.h"
31 #include "cal_db_query.h"
32 #include "cal_db_rrule.h"
33 #include "cal_db_plugin_alarm_helper.h"
34 #include "cal_db_plugin_attendee_helper.h"
35 #include "cal_db_plugin_extended_helper.h"
36 #include "cal_access_control.h"
37 #include "cal_utils.h"
38
39 static int _cal_db_todo_insert_record(calendar_record_h record, int* id);
40 static int _cal_db_todo_get_record(int id, calendar_record_h* out_record);
41 static int _cal_db_todo_update_record(calendar_record_h record);
42 static int _cal_db_todo_delete_record(int id);
43 static int _cal_db_todo_get_all_records(int offset, int limit, calendar_list_h* out_list);
44 static int _cal_db_todo_get_records_with_query(calendar_query_h query, int offset, int limit, calendar_list_h* out_list);
45 static int _cal_db_todo_delete_records(int ids[], int count);
46 static int _cal_db_todo_get_count(int *out_count);
47 static int _cal_db_todo_get_count_with_query(calendar_query_h query, int *out_count);
48 static int _cal_db_todo_replace_record(calendar_record_h record, int id);
49 static int _cal_db_todo_replace_records(const calendar_list_h list, int ids[], int count);
50
51 /*
52  * static function
53  */
54 static void _cal_db_todo_get_stmt(sqlite3_stmt *stmt, bool is_view_table, calendar_record_h record, int *extended);
55 static void _cal_db_todo_get_property_stmt(sqlite3_stmt *stmt,
56                 unsigned int property, int *stmt_count, calendar_record_h record);
57 static void _cal_db_todo_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_todo_update_dirty(calendar_record_h record);
61 static int _cal_db_todo_get_deleted_data(int id, int* calendar_book_id, int* created_ver);
62 static bool _cal_db_todo_check_calendar_book_type(calendar_record_h record);
63
64 cal_db_plugin_cb_s cal_db_todo_plugin_cb = {
65         .is_query_only = false,
66         .insert_record = _cal_db_todo_insert_record,
67         .get_record = _cal_db_todo_get_record,
68         .update_record = _cal_db_todo_update_record,
69         .delete_record = _cal_db_todo_delete_record,
70         .get_all_records = _cal_db_todo_get_all_records,
71         .get_records_with_query = _cal_db_todo_get_records_with_query,
72         .insert_records = NULL,
73         .update_records = NULL,
74         .delete_records = _cal_db_todo_delete_records,
75         .get_count = _cal_db_todo_get_count,
76         .get_count_with_query = _cal_db_todo_get_count_with_query,
77         .replace_record = _cal_db_todo_replace_record,
78         .replace_records = _cal_db_todo_replace_records
79 };
80
81 static int _cal_db_todo_insert_record(calendar_record_h record, int* id)
82 {
83         int ret = -1;
84         int index = -1;
85         int input_ver;
86         char query[CAL_DB_SQL_MAX_LEN] = {0};
87         char dtstart_datetime[CAL_STR_SHORT_LEN32] = {0};
88         char dtend_datetime[CAL_STR_SHORT_LEN32] = {0};
89         sqlite3_stmt *stmt = NULL;
90         cal_todo_s* todo =  (cal_todo_s*)(record);
91         cal_rrule_s *rrule = NULL;
92         int tmp = 0;
93         int calendar_book_id = 0;
94         calendar_record_h record_calendar = NULL;
95         int has_alarm = 0;
96
97         RETV_IF(NULL == todo, CALENDAR_ERROR_INVALID_PARAMETER);
98         RETV_IF(false == _cal_db_todo_check_calendar_book_type(record), CALENDAR_ERROR_INVALID_PARAMETER);
99
100         if (cal_access_control_have_write_permission(todo->calendar_id) == false) {
101                 /* LCOV_EXCL_START */
102                 ERR("cal_access_control_have_write_permission() Fail");
103                 return CALENDAR_ERROR_PERMISSION_DENIED;
104                 /* LCOV_EXCL_STOP */
105         }
106
107         ret = calendar_record_get_int(record,
108                         _calendar_todo.calendar_book_id, &calendar_book_id);
109         DBG("calendar_book_id(%d)", calendar_book_id);
110
111         ret = cal_db_get_record(_calendar_book._uri,
112                         calendar_book_id, &record_calendar);
113         RETVM_IF(CALENDAR_ERROR_NONE != ret, CALENDAR_ERROR_INVALID_PARAMETER, "calendar_book_id is invalid");
114
115         calendar_record_destroy(record_calendar, true);
116
117         has_alarm = cal_db_alarm_has_alarm(todo->alarm_list);
118         input_ver = cal_db_util_get_next_ver();
119         int is_allday = 0;
120         if (CALENDAR_TIME_LOCALTIME == todo->start.type
121                         && (0 == todo->start.time.date.hour)
122                         && (0 == todo->start.time.date.minute)
123                         && (0 == todo->start.time.date.second)
124                         && (0 == todo->due.time.date.hour)
125                         && (0 == todo->due.time.date.minute)
126                         && (0 == todo->due.time.date.second)) {
127                 is_allday = 1;
128         }
129
130         ret = snprintf(query, sizeof(query),
131                         "INSERT INTO %s ("
132                         "type, "
133                         "created_ver, changed_ver, "
134                         "summary, description, location, categories,  "
135                         "task_status, priority, "
136                         "sensitivity, uid, "
137                         "calendar_id, "
138                         "latitude, longitude, "
139                         "created_time, completed_time, progress, "
140                         "dtstart_type, dtstart_utime, dtstart_datetime, dtstart_tzid, "
141                         "dtend_type, dtend_utime, dtend_datetime, dtend_tzid, "
142                         "last_mod, rrule_id, "
143                         "has_alarm, system_type, updated, "
144                         "sync_data1, sync_data2, sync_data3, sync_data4, "
145                         "organizer_name, organizer_email, "
146                         "has_attendee, has_extended, "
147                         "freq, is_allday "
148                         ") VALUES ("
149                         "%d, "
150                         "%d, %d, "
151                         "?, ?, ?, ?, "
152                         "%d, %d, "
153                         "%d, ?, "
154                         "%d, "
155                         "%lf, %lf, "
156                         "strftime('%%s', 'now'), %lld, %d, "
157                         "%d, %lld, ?, ?, "
158                         "%d, %lld, ?, ?, "
159                         "strftime('%%s', 'now'), %d, "
160                         "%d, %d, %d, "
161                         "?, ?, ?, ?, "
162                         "?, ?, "
163                         "%d, %d, "
164                         "%d, %d) ",
165                 CAL_TABLE_SCHEDULE,
166                 CAL_SCH_TYPE_TODO, /*event->cal_type,*/
167                 input_ver, input_ver,
168                 todo->todo_status, todo->priority,
169                 todo->sensitivity,
170                 todo->calendar_id,
171                 todo->latitude, todo->longitude,
172                 todo->completed_time, todo->progress,
173                 todo->start.type, todo->start.type == CALENDAR_TIME_UTIME ? todo->start.time.utime : 0,
174                 todo->due.type, todo->due.type == CALENDAR_TIME_UTIME ? todo->due.time.utime : 0,
175                 0 < todo->freq ? 1 : 0,
176                 has_alarm,
177                 todo->system_type,
178                 todo->updated,
179                 (todo->attendee_list && 0 < todo->attendee_list->count) ? 1 : 0,
180                 (todo->extended_list && 0 < todo->extended_list->count) ? 1 : 0,
181                 todo->freq, is_allday);
182
183         ret = cal_db_util_query_prepare(query, &stmt);
184         if (CALENDAR_ERROR_NONE != ret) {
185                 /* LCOV_EXCL_START */
186                 ERR("cal_db_util_query_prepare() Fail(%d)", ret);
187                 SECURE("query[%s]", query);
188                 return ret;
189                 /* LCOV_EXCL_STOP */
190         }
191
192         int count = 1;
193
194         if (todo->summary)
195                 cal_db_util_stmt_bind_text(stmt, count, todo->summary);
196         count++;
197
198         if (todo->description)
199                 cal_db_util_stmt_bind_text(stmt, count, todo->description);
200         count++;
201
202         if (todo->location)
203                 cal_db_util_stmt_bind_text(stmt, count, todo->location);
204         count++;
205
206         if (todo->categories)
207                 cal_db_util_stmt_bind_text(stmt, count, todo->categories);
208         count++;
209
210         if (todo->uid)
211                 cal_db_util_stmt_bind_text(stmt, count, todo->uid);
212         count++;
213
214         if (CALENDAR_TIME_LOCALTIME == todo->start.type) {
215                 snprintf(dtstart_datetime, sizeof(dtstart_datetime), CAL_FORMAT_LOCAL_DATETIME,
216                                 todo->start.time.date.year,
217                                 todo->start.time.date.month,
218                                 todo->start.time.date.mday,
219                                 todo->start.time.date.hour,
220                                 todo->start.time.date.minute,
221                                 todo->start.time.date.second);
222                 cal_db_util_stmt_bind_text(stmt, count, dtstart_datetime);
223         }
224         count++;
225
226         if (todo->start_tzid)
227                 cal_db_util_stmt_bind_text(stmt, count, todo->start_tzid);
228         count++;
229
230         if (CALENDAR_TIME_LOCALTIME == todo->due.type) {
231                 snprintf(dtend_datetime, sizeof(dtend_datetime), CAL_FORMAT_LOCAL_DATETIME,
232                                 todo->due.time.date.year,
233                                 todo->due.time.date.month,
234                                 todo->due.time.date.mday,
235                                 todo->due.time.date.hour,
236                                 todo->due.time.date.minute,
237                                 todo->due.time.date.second);
238                 cal_db_util_stmt_bind_text(stmt, count, dtend_datetime);
239         }
240         count++;
241
242         if (todo->due_tzid)
243                 cal_db_util_stmt_bind_text(stmt, count, todo->due_tzid);
244         count++;
245
246         if (todo->sync_data1)
247                 cal_db_util_stmt_bind_text(stmt, count, todo->sync_data1);
248         count++;
249         if (todo->sync_data2)
250                 cal_db_util_stmt_bind_text(stmt, count, todo->sync_data2);
251         count++;
252         if (todo->sync_data3)
253                 cal_db_util_stmt_bind_text(stmt, count, todo->sync_data3);
254         count++;
255         if (todo->sync_data4)
256                 cal_db_util_stmt_bind_text(stmt, count, todo->sync_data4);
257         count++;
258         if (todo->organizer_name)
259                 cal_db_util_stmt_bind_text(stmt, count, todo->organizer_name);
260         count++;
261         if (todo->organizer_email)
262                 cal_db_util_stmt_bind_text(stmt, count, todo->organizer_email);
263         count++;
264
265         ret = cal_db_util_stmt_step(stmt);
266         if (CALENDAR_ERROR_NONE != ret) {
267                 /* LCOV_EXCL_START */
268                 ERR("cal_db_util_stmt_step() Fail(%d)", ret);
269                 SECURE("query[%s]", query);
270                 sqlite3_finalize(stmt);
271                 return ret;
272                 /* LCOV_EXCL_STOP */
273         }
274
275         index = cal_db_util_last_insert_id();
276         sqlite3_finalize(stmt);
277
278         calendar_record_get_int(record, _calendar_todo.id, &tmp);
279         cal_record_set_int(record, _calendar_todo.id, index);
280         if (id)
281                 *id = index;
282
283         cal_db_rrule_get_rrule_from_record(record, &rrule);
284         cal_db_rrule_insert_record(index, rrule);
285
286         if (todo->alarm_list && 0 < todo->alarm_list->count) {
287                 ret = cal_db_alarm_insert_records(todo->alarm_list, index);
288                 WARN_IF(CALENDAR_ERROR_NONE != ret, "cal_db_alarm_insert_records() Fail(%x)", ret);
289         }
290
291         if (todo->attendee_list && 0 < todo->attendee_list->count) {
292                 ret = cal_db_attendee_insert_records(todo->attendee_list, index);
293                 WARN_IF(CALENDAR_ERROR_NONE != ret, "cal_db_attendee_insert_records() Fail(%x)", ret);
294         }
295
296         if (todo->extended_list && 0 < todo->extended_list->count) {
297                 DBG("insert extended");
298                 ret = cal_db_extended_insert_records(todo->extended_list, index, CALENDAR_RECORD_TYPE_TODO);
299                 WARN_IF(CALENDAR_ERROR_NONE != ret, "cal_db_extended_insert_records() Fail(%x)", ret);
300         } else {
301                 DBG("No extended");
302         }
303
304         CAL_FREE(rrule);
305         cal_db_util_notify(CAL_NOTI_TYPE_TODO);
306
307         cal_record_set_int(record, _calendar_todo.id, tmp);
308
309         return CALENDAR_ERROR_NONE;
310 }
311
312 static int _cal_db_todo_get_record(int id, calendar_record_h* out_record)
313 {
314         char query[CAL_DB_SQL_MAX_LEN];
315         cal_todo_s *todo = NULL;
316         cal_rrule_s *rrule = NULL;
317         sqlite3_stmt *stmt = NULL;
318         int extended = 0;
319         calendar_record_h record_calendar;
320         calendar_book_sync_event_type_e sync_event_type = CALENDAR_BOOK_SYNC_EVENT_FOR_ME;
321         int ret = 0;
322
323         ret = calendar_record_create(_calendar_todo._uri, out_record);
324         if (CALENDAR_ERROR_NONE != ret) {
325                 /* LCOV_EXCL_START */
326                 ERR("calendar_record_create() Fail(%d)", ret);
327                 return CALENDAR_ERROR_OUT_OF_MEMORY;
328                 /* LCOV_EXCL_STOP */
329         }
330
331         todo =  (cal_todo_s*)(*out_record);
332
333         snprintf(query, sizeof(query), "SELECT "CAL_QUERY_SCHEDULE_A_ALL" FROM %s AS A "
334                         "WHERE id=%d AND (type = %d OR type = %d) AND calendar_id IN "
335                         "(select id from %s where deleted = 0)",
336                         CAL_TABLE_SCHEDULE,
337                         id, CALENDAR_BOOK_TYPE_TODO, CALENDAR_BOOK_TYPE_NONE,
338                         CAL_TABLE_CALENDAR);
339         ret = cal_db_util_query_prepare(query, &stmt);
340         if (CALENDAR_ERROR_NONE != ret) {
341                 /* LCOV_EXCL_START */
342                 ERR("cal_db_util_query_prepare() Fail(%d)", ret);
343                 SECURE("query[%s]", query);
344                 calendar_record_destroy(*out_record, true);
345                 *out_record = NULL;
346                 return ret;
347                 /* LCOV_EXCL_STOP */
348         }
349
350         ret = cal_db_util_stmt_step(stmt);
351         if (CAL_SQLITE_ROW != ret) {
352                 /* LCOV_EXCL_START */
353                 ERR("cal_db_util_stmt_step() Fail(%d)", ret);
354                 sqlite3_finalize(stmt);
355                 calendar_record_destroy(*out_record, true);
356                 *out_record = NULL;
357                 if (CALENDAR_ERROR_NONE == ret)
358                         return CALENDAR_ERROR_DB_RECORD_NOT_FOUND;
359                 return ret;
360                 /* LCOV_EXCL_STOP */
361         }
362
363         _cal_db_todo_get_stmt(stmt, false, *out_record, &extended);
364         sqlite3_finalize(stmt);
365         stmt = NULL;
366
367         ret = cal_db_get_record(_calendar_book._uri, todo->calendar_id, &record_calendar);
368         if (CALENDAR_ERROR_NONE == ret) {
369                 ret = calendar_record_get_int(record_calendar,
370                                 _calendar_book.sync_event, (int *)&sync_event_type);
371                 calendar_record_destroy(record_calendar, true);
372         }
373         if (todo->is_deleted == 1 && sync_event_type != CALENDAR_BOOK_SYNC_EVENT_FOR_EVERY_AND_REMAIN
374            ) {
375                 calendar_record_destroy(*out_record, true);
376                 *out_record = NULL;
377                 return CALENDAR_ERROR_DB_RECORD_NOT_FOUND;
378         }
379
380         if (CALENDAR_RECURRENCE_NONE != todo->freq) {
381                 ret = cal_db_rrule_get_rrule(todo->index, &rrule);
382                 if (CALENDAR_ERROR_NONE == ret) {
383                         cal_db_rrule_set_rrule_to_record(rrule, *out_record);
384                         CAL_FREE(rrule);
385                 }
386         }
387
388         if (todo->has_alarm == 1)
389                 cal_db_alarm_get_records(todo->index, todo->alarm_list);
390
391         if (todo->has_attendee == 1)
392                 cal_db_attendee_get_records(todo->index, todo->attendee_list);
393
394         if (extended == 1)
395                 cal_db_extended_get_records(todo->index, CALENDAR_RECORD_TYPE_TODO, todo->extended_list);
396
397         return CALENDAR_ERROR_NONE;
398 }
399
400 static int _cal_db_todo_update_record(calendar_record_h record)
401 {
402         char query[CAL_DB_SQL_MAX_LEN] = {0};
403         char dtstart_datetime[CAL_STR_SHORT_LEN32] = {0};
404         char dtend_datetime[CAL_STR_SHORT_LEN32] = {0};
405         sqlite3_stmt *stmt = NULL;
406         cal_todo_s* todo =  (cal_todo_s*)(record);
407         cal_rrule_s *rrule = NULL;
408         int ret = 0;
409         int has_alarm = 0;
410
411         RETV_IF(NULL == todo, CALENDAR_ERROR_INVALID_PARAMETER);
412
413         if (cal_access_control_have_write_permission(todo->calendar_id) == false) {
414                 /* LCOV_EXCL_START */
415                 ERR("cal_access_control_have_write_permission() Fail");
416                 return CALENDAR_ERROR_PERMISSION_DENIED;
417                 /* LCOV_EXCL_STOP */
418         }
419
420         if (todo->common.properties_flags != NULL)
421                 return _cal_db_todo_update_dirty(record);
422
423         has_alarm = cal_db_alarm_has_alarm(todo->alarm_list);
424         int is_allday = 0;
425         if (CALENDAR_TIME_LOCALTIME == todo->start.type
426                         && (0 == todo->start.time.date.hour)
427                         && (0 == todo->start.time.date.minute)
428                         && (0 == todo->start.time.date.second)
429                         && (0 == todo->due.time.date.hour)
430                         && (0 == todo->due.time.date.minute)
431                         && (0 == todo->due.time.date.second)) {
432                 is_allday = 1;
433         }
434
435         snprintf(query, sizeof(query), "UPDATE %s SET "
436                         "changed_ver = %d,"
437                         "type = %d,"
438                         "summary = ?,"
439                         "description = ?,"
440                         "location = ?,"
441                         "categories = ?,"
442                         "task_status = %d,"
443                         "priority = %d,"
444                         "sensitivity = %d, "
445                         "uid = ?, "
446                         "calendar_id = %d, "
447                         "latitude = %lf,"
448                         "longitude = %lf,"
449                         "completed_time = %lld,"
450                         "progress = %d, "
451                         "dtstart_type = %d, "
452                         "dtstart_utime = %lld, "
453                         "dtstart_datetime = ?, "
454                         "dtstart_tzid = ?, "
455                         "dtend_type = %d, "
456                         "dtend_utime = %lld, "
457                         "dtend_datetime = ?, "
458                         "dtend_tzid = ?, "
459                         "last_mod = strftime('%%s', 'now'), "
460                         "has_alarm = %d, "
461                         "system_type = %d, "
462                         "updated = %d, "
463                         "sync_data1 = ?, "
464                         "sync_data2 = ?, "
465                         "sync_data3 = ?, "
466                         "sync_data4 = ?, "
467                         "organizer_name = ?, "
468                         "organizer_email = ?, "
469                         "has_attendee = %d,"
470                         "has_extended = %d, "
471                         "is_allday = %d "
472                         "WHERE id = %d;",
473                 CAL_TABLE_SCHEDULE,
474                 cal_db_util_get_next_ver(),
475                 CAL_SCH_TYPE_TODO,/*todo->cal_type,*/
476                 todo->todo_status,
477                 todo->priority,
478                 todo->sensitivity,
479                 todo->calendar_id,
480                 todo->latitude,
481                 todo->longitude,
482                 todo->completed_time,
483                 todo->progress,
484                 todo->start.type,
485                 todo->start.type == CALENDAR_TIME_UTIME ? todo->start.time.utime : 0,
486                 todo->due.type,
487                 todo->due.type == CALENDAR_TIME_UTIME ? todo->due.time.utime : 0,
488                 has_alarm,
489                 todo->system_type,
490                 todo->updated,
491                 (todo->attendee_list && 0 < todo->attendee_list->count) ? 1 : 0,
492                 (todo->extended_list && 0 < todo->extended_list->count) ? 1 : 0,
493                 is_allday,
494                 todo->index);
495
496         ret = cal_db_util_query_prepare(query, &stmt);
497         if (CALENDAR_ERROR_NONE != ret) {
498                 /* LCOV_EXCL_START */
499                 ERR("cal_db_util_query_prepare() Fail(%d)", ret);
500                 SECURE("query[%s]", query);
501                 return ret;
502                 /* LCOV_EXCL_STOP */
503         }
504
505         int count = 1;
506
507         if (todo->summary)
508                 cal_db_util_stmt_bind_text(stmt, count, todo->summary);
509         count++;
510
511         if (todo->description)
512                 cal_db_util_stmt_bind_text(stmt, count, todo->description);
513         count++;
514
515         if (todo->location)
516                 cal_db_util_stmt_bind_text(stmt, count, todo->location);
517         count++;
518
519         if (todo->categories)
520                 cal_db_util_stmt_bind_text(stmt, count, todo->categories);
521         count++;
522
523         if (todo->uid)
524                 cal_db_util_stmt_bind_text(stmt, count, todo->uid);
525         count++;
526
527         if (CALENDAR_TIME_LOCALTIME == todo->start.type) {
528                 snprintf(dtstart_datetime, sizeof(dtstart_datetime), CAL_FORMAT_LOCAL_DATETIME,
529                                 todo->start.time.date.year,
530                                 todo->start.time.date.month,
531                                 todo->start.time.date.mday,
532                                 todo->start.time.date.hour,
533                                 todo->start.time.date.minute,
534                                 todo->start.time.date.second);
535                 cal_db_util_stmt_bind_text(stmt, count, dtstart_datetime);
536         }
537         count++;
538
539         if (todo->start_tzid)
540                 cal_db_util_stmt_bind_text(stmt, count, todo->start_tzid);
541         count++;
542
543         if (CALENDAR_TIME_LOCALTIME == todo->due.type) {
544                 snprintf(dtend_datetime, sizeof(dtend_datetime), CAL_FORMAT_LOCAL_DATETIME,
545                                 todo->due.time.date.year,
546                                 todo->due.time.date.month,
547                                 todo->due.time.date.mday,
548                                 todo->due.time.date.hour,
549                                 todo->due.time.date.minute,
550                                 todo->due.time.date.second);
551                 cal_db_util_stmt_bind_text(stmt, count, dtend_datetime);
552         }
553         count++;
554
555         if (todo->due_tzid)
556                 cal_db_util_stmt_bind_text(stmt, count, todo->due_tzid);
557         count++;
558
559         if (todo->sync_data1)
560                 cal_db_util_stmt_bind_text(stmt, count, todo->sync_data1);
561         count++;
562         if (todo->sync_data2)
563                 cal_db_util_stmt_bind_text(stmt, count, todo->sync_data2);
564         count++;
565         if (todo->sync_data3)
566                 cal_db_util_stmt_bind_text(stmt, count, todo->sync_data3);
567         count++;
568         if (todo->sync_data4)
569                 cal_db_util_stmt_bind_text(stmt, count, todo->sync_data4);
570         count++;
571         if (todo->organizer_name)
572                 cal_db_util_stmt_bind_text(stmt, count, todo->organizer_name);
573         count++;
574         if (todo->organizer_email)
575                 cal_db_util_stmt_bind_text(stmt, count, todo->organizer_email);
576         count++;
577
578         ret = cal_db_util_stmt_step(stmt);
579         sqlite3_finalize(stmt);
580         if (CALENDAR_ERROR_NONE != ret) {
581                 /* LCOV_EXCL_START */
582                 ERR("cal_db_util_stmt_step() Fail(%d)", ret);
583                 return ret;
584                 /* LCOV_EXCL_STOP */
585         }
586
587         cal_db_rrule_get_rrule_from_record(record, &rrule);
588         cal_db_rrule_update_record(todo->index, rrule);
589         CAL_FREE(rrule);
590
591         cal_db_alarm_delete_with_id(todo->index);
592         cal_db_attendee_delete_with_id(todo->index);
593         cal_db_extended_delete_with_id(todo->index, CALENDAR_RECORD_TYPE_TODO);
594
595         if (todo->alarm_list && 0 < todo->alarm_list->count) {
596                 ret = cal_db_alarm_insert_records(todo->alarm_list, todo->index);
597                 WARN_IF(CALENDAR_ERROR_NONE != ret, "cal_db_alarm_insert_records() Fail(%d)", ret);
598         }
599
600         if (todo->attendee_list && 0 < todo->attendee_list->count) {
601                 ret = cal_db_attendee_insert_records(todo->attendee_list, todo->index);
602                 WARN_IF(CALENDAR_ERROR_NONE != ret, "cal_db_attendee_insert_records() Fail(%d)", ret);
603         }
604
605
606         if (todo->extended_list && 0 < todo->extended_list->count) {
607                 DBG("insert extended");
608                 ret = cal_db_extended_insert_records(todo->extended_list, todo->index, CALENDAR_RECORD_TYPE_TODO);
609                 WARN_IF(CALENDAR_ERROR_NONE != ret, "cal_db_extended_insert_records() Fail(%d)", ret);
610         }
611
612         cal_db_util_notify(CAL_NOTI_TYPE_TODO);
613
614         return CALENDAR_ERROR_NONE;
615 }
616
617 static int _cal_db_todo_delete_record(int id)
618 {
619         int ret = 0;
620         int calendar_book_id = 0;
621         char query[CAL_DB_SQL_MAX_LEN] = {0};
622         int created_ver = 0;
623         calendar_book_sync_event_type_e sync_event_type = CALENDAR_BOOK_SYNC_EVENT_FOR_ME;
624
625         RETVM_IF(id < 0, CALENDAR_ERROR_INVALID_PARAMETER, "id(%d) < 0", id);
626
627         ret = _cal_db_todo_get_deleted_data(id, &calendar_book_id, &created_ver);
628         if (CALENDAR_ERROR_NONE != ret) {
629                 DBG("_cal_db_event_get_deleted_data() Fail");
630                 return ret;
631         }
632
633         if (cal_access_control_have_write_permission(calendar_book_id) == false) {
634                 /* LCOV_EXCL_START */
635                 ERR("cal_access_control_have_write_permission() Fail");
636                 return CALENDAR_ERROR_PERMISSION_DENIED;
637                 /* LCOV_EXCL_STOP */
638         }
639
640         snprintf(query, sizeof(query), "SELECT sync_event FROM %s WHERE id = %d ",
641                         CAL_TABLE_CALENDAR, calendar_book_id);
642         ret = cal_db_util_query_get_first_int_result(query, NULL, (int *)&sync_event_type);
643         if (CALENDAR_ERROR_NONE != ret) {
644                 /* LCOV_EXCL_START */
645                 ERR("cal_db_util_query_get_first_int_result() Fail");
646                 return ret;
647                 /* LCOV_EXCL_STOP */
648         }
649         DBG("sync_event_type(%d)", sync_event_type);
650
651         if (sync_event_type == CALENDAR_BOOK_SYNC_EVENT_FOR_EVERY_AND_REMAIN) {
652                 DBG("set is_delete");
653                 snprintf(query, sizeof(query), "UPDATE %s SET is_deleted = 1, changed_ver = %d, "
654                                 "last_mod = strftime('%%s','now') WHERE id = %d ",
655                                 CAL_TABLE_SCHEDULE, cal_db_util_get_next_ver(), id);
656
657                 ret = cal_db_util_query_exec(query);
658                 if (CALENDAR_ERROR_NONE != ret) {
659                         /* LCOV_EXCL_START */
660                         ERR("cal_db_util_query_exec() Fail(%d)", ret);
661                         SECURE("[%s]", query);
662                         return ret;
663                         /* LCOV_EXCL_STOP */
664                 }
665                 DBG("attendee, alarm and rrule will be deleted by trigger after sync clean");
666         } else {
667                 cal_db_util_get_next_ver();
668
669                 DBG("delete event");
670                 snprintf(query, sizeof(query), "DELETE FROM %s WHERE id = %d ", CAL_TABLE_SCHEDULE, id);
671                 ret = cal_db_util_query_exec(query);
672                 if (CALENDAR_ERROR_NONE != ret) {
673                         /* LCOV_EXCL_START */
674                         ERR("cal_db_util_query_exec() Fail(%d)", ret);
675                         SECURE("[%s]", query);
676                         return ret;
677                         /* LCOV_EXCL_STOP */
678                 }
679                 DBG("attendee, alarm and rrule is deleted by trigger");
680         }
681         cal_db_util_notify(CAL_NOTI_TYPE_TODO);
682
683         return CALENDAR_ERROR_NONE;
684 }
685
686 static int _cal_db_todo_replace_record(calendar_record_h record, int id)
687 {
688         int ret = CALENDAR_ERROR_NONE;
689         char query[CAL_DB_SQL_MAX_LEN] = {0};
690         char dtstart_datetime[CAL_STR_SHORT_LEN32] = {0};
691         char dtend_datetime[CAL_STR_SHORT_LEN32] = {0};
692         sqlite3_stmt *stmt = NULL;
693         cal_todo_s* todo =  (cal_todo_s*)(record);
694         cal_rrule_s *rrule = NULL;
695         int has_alarm = 0;
696
697         RETV_IF(NULL == todo, CALENDAR_ERROR_INVALID_PARAMETER);
698         todo->index = id;
699
700         if (cal_access_control_have_write_permission(todo->calendar_id) == false) {
701                 /* LCOV_EXCL_START */
702                 ERR("cal_access_control_have_write_permission() Fail");
703                 return CALENDAR_ERROR_PERMISSION_DENIED;
704                 /* LCOV_EXCL_STOP */
705         }
706
707         if (todo->common.properties_flags)
708                 return _cal_db_todo_update_dirty(record);
709
710         int is_allday = 0;
711         if (CALENDAR_TIME_LOCALTIME == todo->start.type
712                         && (0 == todo->start.time.date.hour)
713                         && (0 == todo->start.time.date.minute)
714                         && (0 == todo->start.time.date.second)
715                         && (0 == todo->due.time.date.hour)
716                         && (0 == todo->due.time.date.minute)
717                         && (0 == todo->due.time.date.second)) {
718                 is_allday = 1;
719         }
720
721         has_alarm = cal_db_alarm_has_alarm(todo->alarm_list);
722         snprintf(query, sizeof(query), "UPDATE %s SET "
723                         "changed_ver = %d,"
724                         "type = %d,"
725                         "summary = ?,"
726                         "description = ?,"
727                         "location = ?,"
728                         "categories = ?,"
729                         "task_status = %d,"
730                         "priority = %d,"
731                         "sensitivity = %d, "
732                         "uid = ?, "
733                         "calendar_id = %d, "
734                         "latitude = %lf,"
735                         "longitude = %lf,"
736                         "completed_time = %lld,"
737                         "progress = %d, "
738                         "dtstart_type = %d, "
739                         "dtstart_utime = %lld, "
740                         "dtstart_datetime = ?, "
741                         "dtstart_tzid = ?, "
742                         "dtend_type = %d, "
743                         "dtend_utime = %lld, "
744                         "dtend_datetime = ?, "
745                         "dtend_tzid = ?, "
746                         "last_mod = strftime('%%s', 'now'), "
747                         "has_alarm = %d, "
748                         "system_type = %d, "
749                         "updated = %d, "
750                         "sync_data1 = ?, "
751                         "sync_data2 = ?, "
752                         "sync_data3 = ?, "
753                         "sync_data4 = ?, "
754                         "organizer_name = ?, "
755                         "organizer_email = ?, "
756                         "has_attendee = %d,"
757                         "has_extended = %d, "
758                         "is_allday = %d "
759                         "WHERE id = %d;",
760                 CAL_TABLE_SCHEDULE,
761                 cal_db_util_get_next_ver(),
762                 CAL_SCH_TYPE_TODO,/*todo->cal_type,*/
763                 todo->todo_status,
764                 todo->priority,
765                 todo->sensitivity,
766                 todo->calendar_id,
767                 todo->latitude,
768                 todo->longitude,
769                 todo->completed_time,
770                 todo->progress,
771                 todo->start.type,
772                 todo->start.type == CALENDAR_TIME_UTIME ? todo->start.time.utime : 0,
773                 todo->due.type,
774                 todo->due.type == CALENDAR_TIME_UTIME ? todo->due.time.utime : 0,
775                 has_alarm,
776                 todo->system_type,
777                 todo->updated,
778                 (todo->attendee_list && 0 < todo->attendee_list->count) ? 1 : 0,
779                 (todo->extended_list && 0 < todo->extended_list->count) ? 1 : 0,
780                 is_allday,
781                 id);
782
783         ret = cal_db_util_query_prepare(query, &stmt);
784         if (CALENDAR_ERROR_NONE != ret) {
785                 /* LCOV_EXCL_START */
786                 ERR("cal_db_util_query_prepare() Fail(%d)", ret);
787                 SECURE("query[%s]", query);
788                 return ret;
789                 /* LCOV_EXCL_STOP */
790         }
791
792         int count = 1;
793
794         if (todo->summary)
795                 cal_db_util_stmt_bind_text(stmt, count, todo->summary);
796         count++;
797
798         if (todo->description)
799                 cal_db_util_stmt_bind_text(stmt, count, todo->description);
800         count++;
801
802         if (todo->location)
803                 cal_db_util_stmt_bind_text(stmt, count, todo->location);
804         count++;
805
806         if (todo->categories)
807                 cal_db_util_stmt_bind_text(stmt, count, todo->categories);
808         count++;
809
810         if (todo->uid)
811                 cal_db_util_stmt_bind_text(stmt, count, todo->uid);
812         count++;
813
814         if (CALENDAR_TIME_LOCALTIME == todo->start.type) {
815                 snprintf(dtstart_datetime, sizeof(dtstart_datetime), CAL_FORMAT_LOCAL_DATETIME,
816                                 todo->start.time.date.year,
817                                 todo->start.time.date.month,
818                                 todo->start.time.date.mday,
819                                 todo->start.time.date.hour,
820                                 todo->start.time.date.minute,
821                                 todo->start.time.date.second);
822                 cal_db_util_stmt_bind_text(stmt, count, dtstart_datetime);
823         }
824         count++;
825
826         if (todo->start_tzid)
827                 cal_db_util_stmt_bind_text(stmt, count, todo->start_tzid);
828         count++;
829
830         if (CALENDAR_TIME_LOCALTIME == todo->due.type) {
831                 snprintf(dtend_datetime, sizeof(dtend_datetime), CAL_FORMAT_LOCAL_DATETIME,
832                                 todo->due.time.date.year,
833                                 todo->due.time.date.month,
834                                 todo->due.time.date.mday,
835                                 todo->due.time.date.hour,
836                                 todo->due.time.date.minute,
837                                 todo->due.time.date.second);
838                 cal_db_util_stmt_bind_text(stmt, count, dtend_datetime);
839         }
840         count++;
841
842         if (todo->due_tzid)
843                 cal_db_util_stmt_bind_text(stmt, count, todo->due_tzid);
844         count++;
845
846         if (todo->sync_data1)
847                 cal_db_util_stmt_bind_text(stmt, count, todo->sync_data1);
848         count++;
849         if (todo->sync_data2)
850                 cal_db_util_stmt_bind_text(stmt, count, todo->sync_data2);
851         count++;
852         if (todo->sync_data3)
853                 cal_db_util_stmt_bind_text(stmt, count, todo->sync_data3);
854         count++;
855         if (todo->sync_data4)
856                 cal_db_util_stmt_bind_text(stmt, count, todo->sync_data4);
857         count++;
858         if (todo->organizer_name)
859                 cal_db_util_stmt_bind_text(stmt, count, todo->organizer_name);
860         count++;
861         if (todo->organizer_email)
862                 cal_db_util_stmt_bind_text(stmt, count, todo->organizer_email);
863         count++;
864
865         ret = cal_db_util_stmt_step(stmt);
866         sqlite3_finalize(stmt);
867         if (CALENDAR_ERROR_NONE != ret) {
868                 /* LCOV_EXCL_START */
869                 ERR("cal_db_util_stmt_step() Fail(%d)", ret);
870                 return ret;
871                 /* LCOV_EXCL_STOP */
872         }
873
874         cal_db_rrule_get_rrule_from_record(record, &rrule);
875         cal_db_rrule_update_record(id, rrule);
876         CAL_FREE(rrule);
877
878         cal_db_alarm_delete_with_id(id);
879         cal_db_attendee_delete_with_id(id);
880         cal_db_extended_delete_with_id(id, CALENDAR_RECORD_TYPE_TODO);
881
882         if (todo->alarm_list && 0 < todo->alarm_list->count) {
883                 ret = cal_db_alarm_insert_records(todo->alarm_list, id);
884                 WARN_IF(CALENDAR_ERROR_NONE != ret, "cal_db_alarm_insert_records() Fail(%x)", ret);
885         }
886
887         if (todo->attendee_list && 0 < todo->attendee_list->count) {
888                 ret = cal_db_attendee_insert_records(todo->attendee_list, id);
889                 WARN_IF(CALENDAR_ERROR_NONE != ret, "cal_db_attendee_insert_records() Fail(%x)", ret);
890         }
891
892         if (todo->extended_list && 0 < todo->extended_list->count) {
893                 DBG("insert extended");
894                 ret = cal_db_extended_insert_records(todo->extended_list, id, CALENDAR_RECORD_TYPE_TODO);
895                 WARN_IF(CALENDAR_ERROR_NONE != ret, "cal_db_extended_insert_records() Fail(%d)", ret);
896         }
897
898         cal_db_util_notify(CAL_NOTI_TYPE_TODO);
899
900         return CALENDAR_ERROR_NONE;
901 }
902
903 static int _cal_db_todo_get_all_records(int offset, int limit, calendar_list_h* out_list)
904 {
905         int ret = CALENDAR_ERROR_NONE;
906         char offsetquery[CAL_DB_SQL_MAX_LEN] = {0};
907         char limitquery[CAL_DB_SQL_MAX_LEN] = {0};
908         sqlite3_stmt *stmt = NULL;
909
910         RETV_IF(NULL == out_list, CALENDAR_ERROR_INVALID_PARAMETER);
911
912         ret = calendar_list_create(out_list);
913         RETVM_IF(CALENDAR_ERROR_NONE != ret, ret, "calendar_list_create() Fail(%d)", ret);
914
915         if (0 < offset)
916                 snprintf(offsetquery, sizeof(offsetquery), "OFFSET %d", offset);
917
918         if (0 < limit)
919                 snprintf(limitquery, sizeof(limitquery), "LIMIT %d", limit);
920
921         char *query_str = NULL;
922         cal_db_append_string(&query_str, "SELECT * FROM");
923         cal_db_append_string(&query_str, CAL_VIEW_TABLE_TODO);
924         cal_db_append_string(&query_str, limitquery);
925         cal_db_append_string(&query_str, offsetquery);
926
927         ret = cal_db_util_query_prepare(query_str, &stmt);
928         if (CALENDAR_ERROR_NONE != ret) {
929                 /* LCOV_EXCL_START */
930                 ERR("cal_db_util_query_prepare() Fail(%d)", ret);
931                 SECURE("query[%s]", query_str);
932                 calendar_list_destroy(*out_list, true);
933                 *out_list = NULL;
934                 CAL_FREE(query_str);
935                 return ret;
936                 /* LCOV_EXCL_STOP */
937         }
938
939         while (CAL_SQLITE_ROW == cal_db_util_stmt_step(stmt)) {
940                 calendar_record_h record;
941                 int extended = 0;
942                 ret = calendar_record_create(_calendar_todo._uri, &record);
943                 if (CALENDAR_ERROR_NONE != ret) {
944                         /* LCOV_EXCL_START */
945                         calendar_list_destroy(*out_list, true);
946                         *out_list = NULL;
947                         sqlite3_finalize(stmt);
948                         CAL_FREE(query_str);
949                         return ret;
950                         /* LCOV_EXCL_STOP */
951                 }
952                 _cal_db_todo_get_stmt(stmt, true, record, &extended);
953
954                 /* child */
955                 int has_attendee = 0, has_alarm = 0;
956                 int record_id = 0;
957                 cal_todo_s* ptodo = (cal_todo_s*) record;
958                 calendar_record_get_int(record, _calendar_todo.id, &record_id);
959                 if (CALENDAR_ERROR_NONE ==  calendar_record_get_int(record, _calendar_todo.has_attendee, &has_attendee)) {
960                         if (has_attendee == 1)
961                                 cal_db_attendee_get_records(record_id, ptodo->attendee_list);
962                 }
963                 if (CALENDAR_ERROR_NONE ==  calendar_record_get_int(record, _calendar_todo.has_alarm, &has_alarm)) {
964                         if (has_alarm == 1)
965                                 cal_db_alarm_get_records(record_id, ptodo->alarm_list);
966                 }
967
968                 if (extended == 1)
969                         cal_db_extended_get_records(record_id, CALENDAR_RECORD_TYPE_TODO, ptodo->extended_list);
970
971                 ret = calendar_list_add(*out_list, record);
972                 if (CALENDAR_ERROR_NONE != ret) {
973                         /* LCOV_EXCL_START */
974                         calendar_list_destroy(*out_list, true);
975                         *out_list = NULL;
976                         calendar_record_destroy(record, true);
977                         sqlite3_finalize(stmt);
978                         CAL_FREE(query_str);
979                         return ret;
980                         /* LCOV_EXCL_STOP */
981                 }
982         }
983         sqlite3_finalize(stmt);
984         CAL_FREE(query_str);
985
986         return CALENDAR_ERROR_NONE;
987 }
988
989 static int _cal_db_todo_get_records_with_query(calendar_query_h query, int offset, int limit, calendar_list_h* out_list)
990 {
991         cal_query_s *que = NULL;
992         int ret = CALENDAR_ERROR_NONE;
993         char *condition = NULL;
994         char *projection = NULL;
995         GSList *bind_text = NULL, *cursor = NULL;
996         sqlite3_stmt *stmt = NULL;
997         int i = 0;
998         char *table_name;
999
1000         que = (cal_query_s *)query;
1001
1002         if (CAL_STRING_EQUAL == strcmp(que->view_uri, CALENDAR_VIEW_TODO)) {
1003                 table_name = cal_strdup(CAL_VIEW_TABLE_TODO);
1004         } else if (CAL_STRING_EQUAL == strcmp(que->view_uri, CALENDAR_VIEW_TODO_CALENDAR)) {
1005                 table_name = cal_strdup(CAL_VIEW_TABLE_TODO_CALENDAR);
1006         } else {
1007                 /* LCOV_EXCL_START */
1008                 ERR("uri(%s) not support get records with query", que->view_uri);
1009                 return CALENDAR_ERROR_INVALID_PARAMETER;
1010                 /* LCOV_EXCL_STOP */
1011         }
1012
1013         /* make filter */
1014         if (que->filter) {
1015                 ret = cal_db_query_create_condition(query, &condition, &bind_text);
1016                 if (CALENDAR_ERROR_NONE != ret) {
1017                         /* LCOV_EXCL_START */
1018                         ERR("cal_db_query_create_condition() Fail(%d), ret");
1019                         CAL_FREE(table_name);
1020                         return ret;
1021                         /* LCOV_EXCL_STOP */
1022                 }
1023         }
1024
1025         /* make: projection */
1026         ret = cal_db_query_create_projection(query, &projection);
1027
1028         char *query_str = NULL;
1029
1030         /* query: projection */
1031         if (projection) {
1032                 cal_db_append_string(&query_str, "SELECT");
1033                 cal_db_append_string(&query_str, projection);
1034                 cal_db_append_string(&query_str, "FROM");
1035                 cal_db_append_string(&query_str, table_name);
1036                 CAL_FREE(projection);
1037         } else {
1038                 cal_db_append_string(&query_str, "SELECT * FROM");
1039                 cal_db_append_string(&query_str, table_name);
1040         }
1041         CAL_FREE(table_name);
1042
1043         /* query: condition */
1044         if (condition) {
1045                 cal_db_append_string(&query_str, "WHERE (");
1046                 cal_db_append_string(&query_str, condition);
1047                 cal_db_append_string(&query_str, ")");
1048         }
1049
1050         /* order */
1051         char *order = NULL;
1052         ret = cal_db_query_create_order(query, condition, &order);
1053         if (order) {
1054                 cal_db_append_string(&query_str, order);
1055                 CAL_FREE(order);
1056         }
1057         CAL_FREE(condition);
1058
1059         /* limit, offset */
1060         char buf[CAL_STR_SHORT_LEN32] = {0};
1061         if (0 < limit) {
1062                 snprintf(buf, sizeof(buf), "LIMIT %d", limit);
1063                 cal_db_append_string(&query_str, buf);
1064
1065                 if (0 < offset) {
1066                         snprintf(buf, sizeof(buf), "OFFSET %d", offset);
1067                         cal_db_append_string(&query_str, buf);
1068                 }
1069         }
1070
1071         /* query */
1072         ret = cal_db_util_query_prepare(query_str, &stmt);
1073         if (CALENDAR_ERROR_NONE != ret) {
1074                 /* LCOV_EXCL_START */
1075                 ERR("cal_db_util_query_prepare() Fail(%d)", ret);
1076                 SECURE("query[%s]", query_str);
1077                 if (bind_text) {
1078                         g_slist_free_full(bind_text, free);
1079                         bind_text = NULL;
1080                 }
1081                 free(query_str);
1082                 return ret;
1083                 /* LCOV_EXCL_STOP */
1084         }
1085
1086         /* bind text */
1087         if (bind_text) {
1088                 g_slist_length(bind_text);
1089                 for (cursor = bind_text, i = 1; cursor; cursor = cursor->next, i++)
1090                         cal_db_util_stmt_bind_text(stmt, i, cursor->data);
1091         }
1092
1093         ret = calendar_list_create(out_list);
1094         if (CALENDAR_ERROR_NONE != ret) {
1095                 /* LCOV_EXCL_START */
1096                 ERR("calendar_list_create() Fail");
1097                 if (bind_text) {
1098                         g_slist_free_full(bind_text, free);
1099                         bind_text = NULL;
1100                 }
1101                 sqlite3_finalize(stmt);
1102                 CAL_FREE(query_str);
1103                 return ret;
1104                 /* LCOV_EXCL_STOP */
1105         }
1106
1107         while (CAL_SQLITE_ROW == cal_db_util_stmt_step(stmt)) {
1108                 calendar_record_h record;
1109                 int extended = 1;
1110                 int attendee = 1, alarm = 1;
1111                 ret = calendar_record_create(_calendar_todo._uri, &record);
1112                 if (CALENDAR_ERROR_NONE != ret) {
1113                         /* LCOV_EXCL_START */
1114                         calendar_list_destroy(*out_list, true);
1115                         *out_list = NULL;
1116
1117                         if (bind_text) {
1118                                 g_slist_free_full(bind_text, free);
1119                                 bind_text = NULL;
1120                         }
1121                         sqlite3_finalize(stmt);
1122                         CAL_FREE(query_str);
1123                         return ret;
1124                         /* LCOV_EXCL_STOP */
1125                 }
1126                 if (0 < que->projection_count) {
1127                         cal_record_set_projection(record,
1128                                         que->projection, que->projection_count, que->property_count);
1129
1130                         _cal_db_todo_get_projection_stmt(stmt,
1131                                         que->projection, que->projection_count,
1132                                         record);
1133                 } else {
1134                         cal_todo_s *todo = NULL;
1135                         _cal_db_todo_get_stmt(stmt, true, record, &extended);
1136                         todo = (cal_todo_s*)(record);
1137                         if (todo) {
1138                                 attendee = todo->has_attendee;
1139                                 alarm = todo->has_alarm;
1140                         }
1141                 }
1142
1143                 /* child */
1144                 if (cal_db_query_find_projection_property(query, CAL_PROPERTY_TODO_CALENDAR_ALARM) == true && alarm == 1) {
1145                         cal_todo_s* todo = (cal_todo_s*) record;
1146                         cal_db_alarm_get_records(todo->index, todo->alarm_list);
1147                 }
1148                 if (cal_db_query_find_projection_property(query, CAL_PROPERTY_TODO_CALENDAR_ATTENDEE) == true && attendee == 1) {
1149                         cal_todo_s* todo = (cal_todo_s*) record;
1150                         cal_db_attendee_get_records(todo->index, todo->attendee_list);
1151                 }
1152                 if (cal_db_query_find_projection_property(query, CAL_PROPERTY_TODO_EXTENDED) == true && extended == 1) {
1153                         cal_todo_s* todo = (cal_todo_s*) record;
1154                         cal_db_extended_get_records(todo->index, CALENDAR_RECORD_TYPE_TODO, todo->extended_list);
1155                 }
1156
1157                 ret = calendar_list_add(*out_list, record);
1158                 if (CALENDAR_ERROR_NONE != ret) {
1159                         /* LCOV_EXCL_START */
1160                         calendar_list_destroy(*out_list, true);
1161                         *out_list = NULL;
1162                         calendar_record_destroy(record, true);
1163
1164                         if (bind_text) {
1165                                 g_slist_free_full(bind_text, free);
1166                                 bind_text = NULL;
1167                         }
1168                         sqlite3_finalize(stmt);
1169                         CAL_FREE(query_str);
1170                         return ret;
1171                         /* LCOV_EXCL_STOP */
1172                 }
1173         }
1174
1175         if (bind_text) {
1176                 g_slist_free_full(bind_text, free);
1177                 bind_text = NULL;
1178         }
1179
1180         sqlite3_finalize(stmt);
1181         CAL_FREE(query_str);
1182
1183         return CALENDAR_ERROR_NONE;
1184 }
1185
1186 static int _cal_db_todo_delete_records(int ids[], int count)
1187 {
1188         int ret = 0;
1189         int i = 0;
1190         for (i = 0; i < count; i++) {
1191                 ret = _cal_db_todo_delete_record(ids[i]);
1192                 if (CALENDAR_ERROR_NONE != ret) {
1193                         /* LCOV_EXCL_START */
1194                         ERR("_cal_db_todo_delete_record() Fail(%d)", ret);
1195                         return CALENDAR_ERROR_DB_FAILED;
1196                         /* LCOV_EXCL_STOP */
1197                 }
1198         }
1199         return CALENDAR_ERROR_NONE;
1200 }
1201
1202 static int _cal_db_todo_get_count(int *out_count)
1203 {
1204         RETV_IF(NULL == out_count, CALENDAR_ERROR_INVALID_PARAMETER);
1205
1206         char *query_str = NULL;
1207         cal_db_append_string(&query_str, "SELECT count(*) FROM");
1208         cal_db_append_string(&query_str, CAL_VIEW_TABLE_TODO);
1209
1210         int ret = 0;
1211         int count = 0;
1212         ret = cal_db_util_query_get_first_int_result(query_str, NULL, &count);
1213         if (CALENDAR_ERROR_NONE != ret) {
1214                 /* LCOV_EXCL_START */
1215                 ERR("cal_db_util_query_get_first_int_result() Fail");
1216                 CAL_FREE(query_str);
1217                 return ret;
1218                 /* LCOV_EXCL_STOP */
1219         }
1220         DBG("count(%d) str[%s]", count, query_str);
1221         CAL_FREE(query_str);
1222
1223         *out_count = count;
1224         return CALENDAR_ERROR_NONE;
1225 }
1226
1227 static int _cal_db_todo_replace_records(const calendar_list_h list, int ids[], int count)
1228 {
1229         calendar_record_h record;
1230         int i = 0;
1231         int ret = 0;
1232
1233         if (NULL == list) {
1234                 /* LCOV_EXCL_START */
1235                 ERR("Invalid argument: list is NULL");
1236                 return CALENDAR_ERROR_INVALID_PARAMETER;
1237                 /* LCOV_EXCL_STOP */
1238         }
1239
1240         ret = calendar_list_first(list);
1241         if (CALENDAR_ERROR_NONE != ret) {
1242                 /* LCOV_EXCL_START */
1243                 ERR("list first error");
1244                 return ret;
1245                 /* LCOV_EXCL_STOP */
1246         }
1247
1248         for (i = 0; i < count; i++) {
1249                 if (CALENDAR_ERROR_NONE ==  calendar_list_get_current_record_p(list, &record)) {
1250                         ret = _cal_db_todo_replace_record(record, ids[i]);
1251                         if (CALENDAR_ERROR_NONE != ret) {
1252                                 /* LCOV_EXCL_START */
1253                                 ERR("_cal_db_todo_replace_record() Fail(%d)", ret);
1254                                 return CALENDAR_ERROR_DB_FAILED;
1255                                 /* LCOV_EXCL_STOP */
1256                         }
1257                 }
1258                 if (CALENDAR_ERROR_NO_DATA != calendar_list_next(list))
1259                         break;
1260         }
1261
1262         return CALENDAR_ERROR_NONE;
1263 }
1264
1265
1266 static int _cal_db_todo_get_count_with_query(calendar_query_h query, int *out_count)
1267 {
1268         cal_query_s *que = NULL;
1269         int ret = CALENDAR_ERROR_NONE;
1270         char *condition = NULL;
1271         char *table_name;
1272         int count = 0;
1273         GSList *bind_text = NULL;
1274
1275         que = (cal_query_s *)query;
1276
1277         if (CAL_STRING_EQUAL == strcmp(que->view_uri, CALENDAR_VIEW_TODO)) {
1278                 table_name = cal_strdup(CAL_VIEW_TABLE_TODO);
1279         } else if (CAL_STRING_EQUAL == strcmp(que->view_uri, CALENDAR_VIEW_TODO_CALENDAR)) {
1280                 table_name = cal_strdup(CAL_VIEW_TABLE_TODO_CALENDAR);
1281         } else {
1282                 /* LCOV_EXCL_START */
1283                 ERR("uri(%s) not support get records with query", que->view_uri);
1284                 return CALENDAR_ERROR_INVALID_PARAMETER;
1285                 /* LCOV_EXCL_STOP */
1286         }
1287
1288         /* make filter */
1289         if (que->filter) {
1290                 ret = cal_db_query_create_condition(query, &condition, &bind_text);
1291                 if (CALENDAR_ERROR_NONE != ret) {
1292                         /* LCOV_EXCL_START */
1293                         ERR("cal_db_query_create_condition() Fail(%d), ret");
1294                         CAL_FREE(table_name);
1295                         return ret;
1296                         /* LCOV_EXCL_STOP */
1297                 }
1298         }
1299
1300         char *query_str = NULL;
1301         /* query: select */
1302         cal_db_append_string(&query_str, "SELECT count(*) FROM");
1303         cal_db_append_string(&query_str, table_name);
1304         CAL_FREE(table_name);
1305
1306         /* query: condition */
1307         if (condition) {
1308                 cal_db_append_string(&query_str,  "WHERE (");
1309                 cal_db_append_string(&query_str, condition);
1310                 cal_db_append_string(&query_str, ")");
1311                 CAL_FREE(condition);
1312         }
1313
1314         /* query */
1315         ret = cal_db_util_query_get_first_int_result(query_str, bind_text, &count);
1316         if (CALENDAR_ERROR_NONE != ret) {
1317                 /* LCOV_EXCL_START */
1318                 ERR("cal_db_util_query_get_first_int_result() Fail");
1319                 if (bind_text) {
1320                         g_slist_free_full(bind_text, free);
1321                         bind_text = NULL;
1322                 }
1323                 CAL_FREE(query_str);
1324                 return ret;
1325                 /* LCOV_EXCL_STOP */
1326         }
1327         DBG("count(%d) str[%s]", count, query_str);
1328
1329         if (out_count) *out_count = count;
1330         if (bind_text) {
1331                 g_slist_free_full(bind_text, free);
1332                 bind_text = NULL;
1333         }
1334
1335         CAL_FREE(query_str);
1336         return CALENDAR_ERROR_NONE;
1337 }
1338
1339 static void _cal_db_todo_get_stmt(sqlite3_stmt *stmt, bool is_view_table, calendar_record_h record, int *extended)
1340 {
1341         cal_todo_s *todo = NULL;
1342         const unsigned char *temp;
1343         int count = 0;
1344
1345         todo = (cal_todo_s*)(record);
1346
1347         todo->index = sqlite3_column_int(stmt, count++);
1348         sqlite3_column_int(stmt, count++);
1349
1350         temp = sqlite3_column_text(stmt, count++);
1351         todo->summary = cal_strdup((const char*)temp);
1352         temp = sqlite3_column_text(stmt, count++);
1353         todo->description = cal_strdup((const char*)temp);
1354
1355         temp = sqlite3_column_text(stmt, count++);
1356         todo->location = cal_strdup((const char*)temp);
1357
1358         temp = sqlite3_column_text(stmt, count++);
1359         todo->categories = cal_strdup((const char*)temp);
1360
1361         sqlite3_column_text(stmt, count++);
1362
1363         todo->todo_status = sqlite3_column_int(stmt, count++);
1364         todo->priority = sqlite3_column_int(stmt, count++);
1365         sqlite3_column_int(stmt, count++);
1366         sqlite3_column_int(stmt, count++);
1367         sqlite3_column_int(stmt, count++);
1368         todo->sensitivity = sqlite3_column_int(stmt, count++);
1369
1370         temp = sqlite3_column_text(stmt, count++);
1371         todo->uid = cal_strdup((const char*)temp);
1372
1373         temp = sqlite3_column_text(stmt, count++);
1374         todo->organizer_name = cal_strdup((const char*)temp);
1375
1376         temp = sqlite3_column_text(stmt, count++);
1377         todo->organizer_email = cal_strdup((const char*)temp);
1378
1379         sqlite3_column_int(stmt, count++);
1380
1381         todo->calendar_id = sqlite3_column_int(stmt, count++);
1382
1383         sqlite3_column_int(stmt, count++);
1384
1385         todo->latitude = sqlite3_column_double(stmt, count++);
1386         todo->longitude = sqlite3_column_double(stmt, count++);
1387         sqlite3_column_int(stmt, count++);
1388
1389         todo->created_time = sqlite3_column_int64(stmt, count++);
1390
1391         todo->completed_time = sqlite3_column_int64(stmt, count++);
1392
1393         todo->progress = sqlite3_column_int(stmt, count++);
1394
1395         sqlite3_column_int(stmt, count++);
1396         sqlite3_column_int(stmt, count++);
1397         todo->is_deleted = sqlite3_column_int(stmt, count++);
1398
1399         todo->start.type = sqlite3_column_int(stmt, count++);
1400
1401         if (todo->start.type == CALENDAR_TIME_UTIME) {
1402                 todo->start.time.utime = sqlite3_column_int64(stmt, count++);
1403                 count++; /* dtstart_datetime */
1404         } else {
1405                 count++; /* dtstart_utime */
1406                 temp = sqlite3_column_text(stmt, count++);
1407                 if (temp) {
1408                         sscanf((const char *)temp, CAL_FORMAT_LOCAL_DATETIME, &(todo->start.time.date.year),
1409                                         &(todo->start.time.date.month), &(todo->start.time.date.mday),
1410                                         &(todo->start.time.date.hour), &(todo->start.time.date.minute),
1411                                         &(todo->start.time.date.second));
1412                 }
1413         }
1414
1415         temp = sqlite3_column_text(stmt, count++);
1416         todo->start_tzid = cal_strdup((const char*)temp);
1417         todo->due.type = sqlite3_column_int(stmt, count++);
1418         if (todo->due.type == CALENDAR_TIME_UTIME) {
1419                 todo->due.time.utime = sqlite3_column_int64(stmt, count++);
1420                 count++; /* datatime */
1421         } else {
1422                 count++;
1423                 temp = sqlite3_column_text(stmt, count++);
1424                 if (temp) {
1425                         sscanf((const char *)temp, CAL_FORMAT_LOCAL_DATETIME, &(todo->due.time.date.year),
1426                                         &(todo->due.time.date.month), &(todo->due.time.date.mday),
1427                                         &(todo->due.time.date.hour), &(todo->due.time.date.minute),
1428                                         &(todo->due.time.date.second));
1429                 }
1430         }
1431         temp = sqlite3_column_text(stmt, count++);
1432         todo->due_tzid = cal_strdup((const char*)temp);
1433
1434         todo->last_mod = sqlite3_column_int64(stmt, count++);
1435         sqlite3_column_int(stmt, count++);
1436
1437         sqlite3_column_text(stmt, count++);
1438         sqlite3_column_text(stmt, count++);
1439         todo->has_attendee = sqlite3_column_int(stmt, count++);
1440         todo->has_alarm = sqlite3_column_int(stmt, count++);
1441         todo->system_type = sqlite3_column_int(stmt, count++);
1442         todo->updated = sqlite3_column_int(stmt, count++);
1443         temp = sqlite3_column_text(stmt, count++);
1444         todo->sync_data1 = cal_strdup((const char*)temp);
1445         temp = sqlite3_column_text(stmt, count++);
1446         todo->sync_data2 = cal_strdup((const char*)temp);
1447         temp = sqlite3_column_text(stmt, count++);
1448         todo->sync_data3 = cal_strdup((const char*)temp);
1449         temp = sqlite3_column_text(stmt, count++);
1450         todo->sync_data4 = cal_strdup((const char*)temp);
1451
1452         sqlite3_column_int(stmt, count++);
1453
1454         if (extended)
1455                 *extended = sqlite3_column_int(stmt, count++);
1456
1457         todo->freq = sqlite3_column_int(stmt, count++);
1458         todo->is_allday = sqlite3_column_int(stmt, count++);
1459
1460         if (is_view_table == true) {
1461                 if (todo->freq <= 0)
1462                         return;
1463
1464                 todo->range_type = sqlite3_column_int(stmt, count++);
1465                 todo->until.type = sqlite3_column_int(stmt, count++);
1466                 todo->until.time.utime = sqlite3_column_int64(stmt, count++);
1467
1468                 temp = sqlite3_column_text(stmt, count++);
1469                 if (temp) {
1470                         if (CALENDAR_TIME_LOCALTIME == todo->until.type) {
1471                                 sscanf((const char *)temp, CAL_FORMAT_LOCAL_DATETIME,
1472                                                 &todo->until.time.date.year,
1473                                                 &todo->until.time.date.month,
1474                                                 &todo->until.time.date.mday,
1475                                                 &todo->until.time.date.hour,
1476                                                 &todo->until.time.date.minute,
1477                                                 &todo->until.time.date.second);
1478                         }
1479                 }
1480
1481                 todo->count = sqlite3_column_int(stmt, count++);
1482                 todo->interval = sqlite3_column_int(stmt, count++);
1483
1484                 temp = sqlite3_column_text(stmt, count++);
1485                 todo->bysecond = cal_strdup((const char*)temp);
1486
1487                 temp = sqlite3_column_text(stmt, count++);
1488                 todo->byminute = cal_strdup((const char*)temp);
1489
1490                 temp = sqlite3_column_text(stmt, count++);
1491                 todo->byhour = cal_strdup((const char*)temp);
1492
1493                 temp = sqlite3_column_text(stmt, count++);
1494                 todo->byday = cal_strdup((const char*)temp);
1495
1496                 temp = sqlite3_column_text(stmt, count++);
1497                 todo->bymonthday = cal_strdup((const char*)temp);
1498
1499                 temp = sqlite3_column_text(stmt, count++);
1500                 todo->byyearday = cal_strdup((const char*)temp);
1501
1502                 temp = sqlite3_column_text(stmt, count++);
1503                 todo->byweekno = cal_strdup((const char*)temp);
1504
1505                 temp = sqlite3_column_text(stmt, count++);
1506                 todo->bymonth = cal_strdup((const char*)temp);
1507
1508                 temp = sqlite3_column_text(stmt, count++);
1509                 todo->bysetpos = cal_strdup((const char*)temp);
1510
1511                 todo->wkst = sqlite3_column_int(stmt, count++);
1512
1513                 sqlite3_column_int(stmt, count++);
1514         }
1515 }
1516
1517 static void _cal_db_todo_get_property_stmt(sqlite3_stmt *stmt,
1518                 unsigned int property, int *stmt_count, calendar_record_h record)
1519 {
1520         cal_todo_s *todo = NULL;
1521         const unsigned char *temp;
1522
1523         todo = (cal_todo_s*)(record);
1524
1525         switch (property) {
1526         case CAL_PROPERTY_TODO_ID:
1527                 todo->index = sqlite3_column_int(stmt, *stmt_count);
1528                 break;
1529         case CAL_PROPERTY_TODO_CALENDAR_ID:
1530                 todo->calendar_id = sqlite3_column_int(stmt, *stmt_count);
1531                 break;
1532         case CAL_PROPERTY_TODO_SUMMARY:
1533                 temp = sqlite3_column_text(stmt, *stmt_count);
1534                 todo->summary = cal_strdup((const char*)temp);
1535                 break;
1536         case CAL_PROPERTY_TODO_DESCRIPTION:
1537                 temp = sqlite3_column_text(stmt, *stmt_count);
1538                 todo->description = cal_strdup((const char*)temp);
1539                 break;
1540         case CAL_PROPERTY_TODO_LOCATION:
1541                 temp = sqlite3_column_text(stmt, *stmt_count);
1542                 todo->location = cal_strdup((const char*)temp);
1543                 break;
1544         case CAL_PROPERTY_TODO_CATEGORIES:
1545                 temp = sqlite3_column_text(stmt, *stmt_count);
1546                 todo->categories = cal_strdup((const char*)temp);
1547                 break;
1548         case CAL_PROPERTY_TODO_TODO_STATUS:
1549                 todo->todo_status = sqlite3_column_int(stmt, *stmt_count);
1550                 break;
1551         case CAL_PROPERTY_TODO_PRIORITY:
1552                 todo->priority = sqlite3_column_int(stmt, *stmt_count);
1553                 break;
1554         case CAL_PROPERTY_TODO_SENSITIVITY:
1555                 todo->sensitivity = sqlite3_column_int(stmt, *stmt_count);
1556                 break;
1557         case CAL_PROPERTY_TODO_UID:
1558                 temp = sqlite3_column_text(stmt, *stmt_count);
1559                 todo->uid = cal_strdup((const char*)temp);
1560                 break;
1561         case CAL_PROPERTY_TODO_LATITUDE:
1562                 todo->latitude = sqlite3_column_double(stmt, *stmt_count);
1563                 break;
1564         case CAL_PROPERTY_TODO_LONGITUDE:
1565                 todo->longitude = sqlite3_column_double(stmt, *stmt_count);
1566                 break;
1567         case CAL_PROPERTY_TODO_PROGRESS:
1568                 todo->progress = sqlite3_column_int(stmt, *stmt_count);
1569                 break;
1570         case CAL_PROPERTY_TODO_COMPLETED_TIME:
1571                 todo->completed_time = sqlite3_column_int64(stmt, *stmt_count);
1572                 break;
1573         case CAL_PROPERTY_TODO_CREATED_TIME:
1574                 todo->created_time = sqlite3_column_int64(stmt, *stmt_count);
1575                 break;
1576         case CAL_PROPERTY_TODO_LAST_MODIFIED_TIME:
1577                 todo->last_mod = sqlite3_column_int64(stmt, *stmt_count);
1578                 break;
1579         case CAL_PROPERTY_TODO_IS_DELETED:
1580                 todo->is_deleted = sqlite3_column_int(stmt, *stmt_count);
1581                 break;
1582         case CAL_PROPERTY_TODO_FREQ:
1583                 todo->freq = sqlite3_column_int(stmt, *stmt_count);
1584                 break;
1585         case CAL_PROPERTY_TODO_RANGE_TYPE:
1586                 todo->range_type = sqlite3_column_int(stmt, *stmt_count);
1587                 break;
1588         case CAL_PROPERTY_TODO_UNTIL:
1589                 todo->until.type = sqlite3_column_int(stmt, *stmt_count);
1590                 if (todo->until.type == CALENDAR_TIME_UTIME) {
1591                         *stmt_count = *stmt_count+1;
1592                         todo->until.time.utime = sqlite3_column_int64(stmt, *stmt_count);
1593                         *stmt_count = *stmt_count+1; /* until_datetime */
1594                 } else {
1595                         *stmt_count = *stmt_count+1;
1596                         *stmt_count = *stmt_count+1;
1597                         temp = sqlite3_column_text(stmt, *stmt_count);
1598                         if (temp) {
1599                                 sscanf((const char *)temp, CAL_FORMAT_LOCAL_DATETIME, &(todo->until.time.date.year),
1600                                                 &(todo->until.time.date.month), &(todo->until.time.date.mday),
1601                                                 &(todo->until.time.date.hour), &(todo->until.time.date.minute),
1602                                                 &(todo->until.time.date.second));
1603                         }
1604                 }
1605                 break;
1606         case CAL_PROPERTY_TODO_COUNT:
1607                 todo->count = sqlite3_column_int(stmt, *stmt_count);
1608                 break;
1609         case CAL_PROPERTY_TODO_INTERVAL:
1610                 todo->interval = sqlite3_column_int(stmt, *stmt_count);
1611                 break;
1612         case CAL_PROPERTY_TODO_BYSECOND:
1613                 temp = sqlite3_column_text(stmt, *stmt_count);
1614                 todo->bysecond = cal_strdup((const char*)temp);
1615                 break;
1616         case CAL_PROPERTY_TODO_BYMINUTE:
1617                 temp = sqlite3_column_text(stmt, *stmt_count);
1618                 todo->byminute = cal_strdup((const char*)temp);
1619                 break;
1620         case CAL_PROPERTY_TODO_BYHOUR:
1621                 temp = sqlite3_column_text(stmt, *stmt_count);
1622                 todo->byhour = cal_strdup((const char*)temp);
1623                 break;
1624         case CAL_PROPERTY_TODO_BYDAY:
1625                 temp = sqlite3_column_text(stmt, *stmt_count);
1626                 todo->byday = cal_strdup((const char*)temp);
1627                 break;
1628         case CAL_PROPERTY_TODO_BYMONTHDAY:
1629                 temp = sqlite3_column_text(stmt, *stmt_count);
1630                 todo->bymonthday = cal_strdup((const char*)temp);
1631                 break;
1632         case CAL_PROPERTY_TODO_BYYEARDAY:
1633                 temp = sqlite3_column_text(stmt, *stmt_count);
1634                 todo->byyearday = cal_strdup((const char*)temp);
1635                 break;
1636         case CAL_PROPERTY_TODO_BYWEEKNO:
1637                 temp = sqlite3_column_text(stmt, *stmt_count);
1638                 todo->byweekno = cal_strdup((const char*)temp);
1639                 break;
1640         case CAL_PROPERTY_TODO_BYMONTH:
1641                 temp = sqlite3_column_text(stmt, *stmt_count);
1642                 todo->bymonth = cal_strdup((const char*)temp);
1643                 break;
1644         case CAL_PROPERTY_TODO_BYSETPOS:
1645                 temp = sqlite3_column_text(stmt, *stmt_count);
1646                 todo->bysetpos = cal_strdup((const char*)temp);
1647                 break;
1648         case CAL_PROPERTY_TODO_WKST:
1649                 todo->wkst = sqlite3_column_int(stmt, *stmt_count);
1650                 break;
1651         case CAL_PROPERTY_TODO_HAS_ALARM:
1652                 todo->has_alarm = sqlite3_column_int(stmt, *stmt_count);
1653                 break;
1654         case CAL_PROPERTY_TODO_SYNC_DATA1:
1655                 temp = sqlite3_column_text(stmt, *stmt_count);
1656                 todo->sync_data1 = cal_strdup((const char*)temp);
1657                 break;
1658         case CAL_PROPERTY_TODO_SYNC_DATA2:
1659                 temp = sqlite3_column_text(stmt, *stmt_count);
1660                 todo->sync_data2 = cal_strdup((const char*)temp);
1661                 break;
1662         case CAL_PROPERTY_TODO_SYNC_DATA3:
1663                 temp = sqlite3_column_text(stmt, *stmt_count);
1664                 todo->sync_data3 = cal_strdup((const char*)temp);
1665                 break;
1666         case CAL_PROPERTY_TODO_SYNC_DATA4:
1667                 temp = sqlite3_column_text(stmt, *stmt_count);
1668                 todo->sync_data4 = cal_strdup((const char*)temp);
1669                 break;
1670         case CAL_PROPERTY_TODO_START:
1671                 todo->start.type = sqlite3_column_int(stmt, *stmt_count);
1672                 if (todo->start.type == CALENDAR_TIME_UTIME) {
1673                         *stmt_count = *stmt_count+1;
1674                         todo->start.time.utime = sqlite3_column_int64(stmt, *stmt_count);
1675                         *stmt_count = *stmt_count+1; /* datetime */
1676                 } else {
1677                         *stmt_count = *stmt_count+1; /* utime */
1678                         *stmt_count = *stmt_count+1;
1679                         temp = sqlite3_column_text(stmt, *stmt_count);
1680                         if (temp) {
1681                                 sscanf((const char *)temp, CAL_FORMAT_LOCAL_DATETIME, &(todo->start.time.date.year),
1682                                                 &(todo->start.time.date.month), &(todo->start.time.date.mday),
1683                                                 &(todo->start.time.date.hour), &(todo->start.time.date.minute),
1684                                                 &(todo->start.time.date.second));
1685                         }
1686                 }
1687                 break;
1688         case CAL_PROPERTY_TODO_START_TZID:
1689                 temp = sqlite3_column_text(stmt, *stmt_count);
1690                 todo->start_tzid = cal_strdup((const char*)temp);
1691                 break;
1692         case CAL_PROPERTY_TODO_DUE:
1693                 todo->due.type = sqlite3_column_int(stmt, *stmt_count);
1694                 if (todo->due.type == CALENDAR_TIME_UTIME) {
1695                         *stmt_count = *stmt_count+1;
1696                         todo->due.time.utime = sqlite3_column_int64(stmt, *stmt_count);
1697                         *stmt_count = *stmt_count+1; /* datatime */
1698                 } else {
1699                         *stmt_count = *stmt_count+1; /* utime */
1700                         *stmt_count = *stmt_count+1;
1701                         temp = sqlite3_column_text(stmt, *stmt_count);
1702                         if (temp) {
1703                                 sscanf((const char *)temp, CAL_FORMAT_LOCAL_DATETIME, &(todo->due.time.date.year),
1704                                                 &(todo->due.time.date.month), &(todo->due.time.date.mday),
1705                                                 &(todo->due.time.date.hour), &(todo->due.time.date.minute),
1706                                                 &(todo->due.time.date.second));
1707                         }
1708                 }
1709                 break;
1710         case CAL_PROPERTY_TODO_DUE_TZID:
1711                 temp = sqlite3_column_text(stmt, *stmt_count);
1712                 todo->due_tzid = cal_strdup((const char*)temp);
1713                 break;
1714         case CAL_PROPERTY_TODO_ORGANIZER_NAME:
1715                 temp = sqlite3_column_text(stmt, *stmt_count);
1716                 todo->organizer_name = cal_strdup((const char*)temp);
1717                 break;
1718         case CAL_PROPERTY_TODO_ORGANIZER_EMAIL:
1719                 temp = sqlite3_column_text(stmt, *stmt_count);
1720                 todo->organizer_email = cal_strdup((const char*)temp);
1721                 break;
1722         case CAL_PROPERTY_TODO_HAS_ATTENDEE:
1723                 todo->has_attendee = sqlite3_column_int(stmt, *stmt_count);
1724                 break;
1725         default:
1726                 sqlite3_column_int(stmt, *stmt_count);
1727                 break;
1728         }
1729
1730         *stmt_count = *stmt_count+1;
1731 }
1732
1733 static void _cal_db_todo_get_projection_stmt(sqlite3_stmt *stmt,
1734                 const unsigned int *projection, const int projection_count,
1735                 calendar_record_h record)
1736 {
1737         int i = 0;
1738         int stmt_count = 0;
1739
1740         for (i = 0; i < projection_count; i++)
1741                 _cal_db_todo_get_property_stmt(stmt, projection[i], &stmt_count, record);
1742 }
1743
1744 static bool _cal_db_todo_check_calendar_book_type(calendar_record_h record)
1745 {
1746         int ret = 0;
1747         int store_type = 0;
1748         cal_todo_s *todo = (cal_todo_s *)record;
1749         char query[CAL_DB_SQL_MAX_LEN];
1750         sqlite3_stmt *stmt = NULL;
1751
1752         snprintf(query, sizeof(query), "SELECT store_type FROM %s WHERE id = %d ",
1753                         CAL_TABLE_CALENDAR, todo->calendar_id);
1754
1755         ret = cal_db_util_query_prepare(query, &stmt);
1756         if (CALENDAR_ERROR_NONE != ret) {
1757                 /* LCOV_EXCL_START */
1758                 ERR("cal_db_util_query_prepare() Fail(%d)", ret);
1759                 SECURE("query[%s]", query);
1760                 return false;
1761                 /* LCOV_EXCL_STOP */
1762         }
1763
1764         ret = cal_db_util_stmt_step(stmt);
1765         if (CAL_SQLITE_ROW != ret) {
1766                 /* LCOV_EXCL_START */
1767                 ERR("cal_db_util_stmt_step() Fail(%d)", ret);
1768                 sqlite3_finalize(stmt);
1769                 return false;
1770                 /* LCOV_EXCL_STOP */
1771         }
1772         store_type = sqlite3_column_int(stmt, 0);
1773         sqlite3_finalize(stmt);
1774
1775         switch (store_type) {
1776         case CALENDAR_BOOK_TYPE_NONE:
1777         case CALENDAR_BOOK_TYPE_TODO:
1778                 ret = true;
1779                 break;
1780         case CALENDAR_BOOK_TYPE_EVENT:
1781         default:
1782                 ret = false;
1783                 break;
1784         }
1785         return ret;
1786 }
1787
1788
1789 static int _cal_db_todo_update_dirty(calendar_record_h record)
1790 {
1791         int todo_id = 0;
1792         int ret = CALENDAR_ERROR_NONE;
1793         calendar_record_h original_record;
1794
1795         ret = calendar_record_get_int(record, _calendar_todo.id, &todo_id);
1796         RETV_IF(CALENDAR_ERROR_NONE != ret, ret);
1797
1798         DBG("id=%d", todo_id);
1799
1800         RETV_IF(false == _cal_db_todo_check_calendar_book_type(record), CALENDAR_ERROR_INVALID_PARAMETER);
1801
1802         ret = _cal_db_todo_get_record(todo_id, &original_record);
1803         if (CALENDAR_ERROR_NONE != ret) {
1804                 /* LCOV_EXCL_START */
1805                 ERR("_cal_db_todo_get_record() Fail(%d)", ret);
1806                 return ret;
1807                 /* LCOV_EXCL_STOP */
1808         }
1809
1810         cal_record_s *_record = NULL;
1811         const cal_property_info_s* property_info = NULL;
1812         int property_info_count = 0;
1813         int i = 0;
1814
1815         _record = (cal_record_s *)record;
1816
1817         property_info = cal_view_get_property_info(_record->view_uri, &property_info_count);
1818
1819         for (i = 0; i < property_info_count; i++) {
1820                 if (true == cal_record_check_property_flag(record, property_info[i].property_id , CAL_PROPERTY_FLAG_DIRTY)) {
1821                         if (CAL_PROPERTY_CHECK_DATA_TYPE(property_info[i].property_id, CAL_PROPERTY_DATA_TYPE_INT) == true) {
1822                                 int tmp = 0;
1823                                 ret = calendar_record_get_int(record, property_info[i].property_id, &tmp);
1824                                 if (CALENDAR_ERROR_NONE != ret)
1825                                         continue;
1826                                 ret = cal_record_set_int(original_record, property_info[i].property_id, tmp);
1827                                 if (CALENDAR_ERROR_NONE != ret)
1828                                         continue;
1829                         } else if (CAL_PROPERTY_CHECK_DATA_TYPE(property_info[i].property_id, CAL_PROPERTY_DATA_TYPE_STR) == true) {
1830                                 char *tmp = NULL;
1831                                 ret = calendar_record_get_str_p(record, property_info[i].property_id, &tmp);
1832                                 if (CALENDAR_ERROR_NONE != ret)
1833                                         continue;
1834                                 ret = cal_record_set_str(original_record, property_info[i].property_id, tmp);
1835                                 if (CALENDAR_ERROR_NONE != ret)
1836                                         continue;
1837                         } else if (CAL_PROPERTY_CHECK_DATA_TYPE(property_info[i].property_id, CAL_PROPERTY_DATA_TYPE_DOUBLE) == true) {
1838                                 double tmp = 0;
1839                                 ret = calendar_record_get_double(record, property_info[i].property_id, &tmp);
1840                                 if (CALENDAR_ERROR_NONE != ret)
1841                                         continue;
1842                                 ret = cal_record_set_double(original_record, property_info[i].property_id, tmp);
1843                                 if (CALENDAR_ERROR_NONE != ret)
1844                                         continue;
1845                         } else if (CAL_PROPERTY_CHECK_DATA_TYPE(property_info[i].property_id, CAL_PROPERTY_DATA_TYPE_LLI) == true) {
1846                                 long long int tmp = 0;
1847                                 ret = calendar_record_get_lli(record, property_info[i].property_id, &tmp);
1848                                 if (CALENDAR_ERROR_NONE != ret)
1849                                         continue;
1850                                 ret = cal_record_set_lli(original_record, property_info[i].property_id, tmp);
1851                                 if (CALENDAR_ERROR_NONE != ret)
1852                                         continue;
1853                         } else if (CAL_PROPERTY_CHECK_DATA_TYPE(property_info[i].property_id, CAL_PROPERTY_DATA_TYPE_CALTIME) == true) {
1854                                 calendar_time_s tmp = {0,};
1855                                 ret = calendar_record_get_caltime(record, property_info[i].property_id, &tmp);
1856                                 if (CALENDAR_ERROR_NONE != ret)
1857                                         continue;
1858                                 ret = cal_record_set_caltime(original_record, property_info[i].property_id, tmp);
1859                                 if (CALENDAR_ERROR_NONE != ret)
1860                                         continue;
1861                         }
1862                 }
1863         }
1864
1865         cal_todo_s *tmp = (cal_todo_s *)original_record;
1866         cal_todo_s *tmp_src = (cal_todo_s *)record;
1867
1868         cal_list_clone((calendar_list_h)tmp_src->alarm_list, (calendar_list_h *)&tmp->alarm_list);
1869         cal_list_clone((calendar_list_h)tmp_src->attendee_list, (calendar_list_h *)&tmp->attendee_list);
1870         cal_list_clone((calendar_list_h)tmp_src->extended_list, (calendar_list_h *)&tmp->extended_list);
1871
1872         CAL_RECORD_RESET_COMMON((cal_record_s*)original_record);
1873         ret = _cal_db_todo_update_record(original_record);
1874
1875         calendar_record_destroy(original_record, true);
1876
1877         return ret;
1878 }
1879
1880 static int _cal_db_todo_get_deleted_data(int id, int* calendar_book_id, int* created_ver)
1881 {
1882         int ret = 0;
1883         char query[CAL_DB_SQL_MAX_LEN];
1884         sqlite3_stmt *stmt = NULL;
1885
1886         snprintf(query, sizeof(query), "SELECT calendar_id, created_ver "
1887                         "FROM %s WHERE id = %d ",
1888                         CAL_TABLE_SCHEDULE, id);
1889
1890         ret = cal_db_util_query_prepare(query, &stmt);
1891         if (CALENDAR_ERROR_NONE != ret) {
1892                 /* LCOV_EXCL_START */
1893                 ERR("cal_db_util_query_prepare() Fail(%d)", ret);
1894                 SECURE("query[%s]", query);
1895                 return ret;
1896                 /* LCOV_EXCL_STOP */
1897         }
1898
1899         ret = cal_db_util_stmt_step(stmt);
1900         if (CAL_SQLITE_ROW != ret) {
1901                 /* LCOV_EXCL_START */
1902                 ERR("cal_db_util_stmt_step() Fail(%d)", ret);
1903                 sqlite3_finalize(stmt);
1904                 return ret;
1905                 /* LCOV_EXCL_STOP */
1906         }
1907
1908         *calendar_book_id = sqlite3_column_int(stmt, 0);
1909         *created_ver = sqlite3_column_int(stmt, 1);
1910         sqlite3_finalize(stmt);
1911
1912         return CALENDAR_ERROR_NONE;
1913 }