[misc] fixed freq update bug
[framework/pim/calendar-service.git] / native / cal_db_rrule.c
1 /*
2  * Calendar Service
3  *
4  * Copyright (c) 2012 - 2013 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 <stdlib.h>
21 #include "cal_internal.h"
22 #include "cal_typedef.h"
23 #include "cal_db_util.h"
24 #include "cal_db.h"
25 #include "cal_view.h"
26 #include "cal_time.h"
27
28 void _cal_db_rrule_set_default(calendar_record_h record)
29 {
30         cal_event_s *event = NULL;
31         retm_if(record == NULL, "Invalid argument: rrule is NULL");
32
33         event = (cal_event_s *)record;
34
35         switch (event->freq)
36         {
37         case CALENDAR_RECURRENCE_NONE:
38                 break;
39         case CALENDAR_RECURRENCE_DAILY:
40                 break;
41         case CALENDAR_RECURRENCE_WEEKLY:
42                 if (event->bymonthday || event->byday)
43                         break;
44
45                 event->byday = _cal_time_extract_by(event->start_tzid, event->wkst,
46                                 &event->start, CAL_DAY_OF_WEEK);
47                 DBG("Not enough field in weekly, so set byda[%s]", event->byday);
48                 break;
49
50         case CALENDAR_RECURRENCE_MONTHLY:
51                 if (event->bymonthday || event->byday)
52                         break;
53
54                 event->bymonthday = _cal_time_extract_by(event->start_tzid, event->wkst,
55                                 &event->start, CAL_DATE);
56                 DBG("Not enough field in monthly, so set bymonthday[%s]", event->bymonthday);
57                 break;
58
59         case CALENDAR_RECURRENCE_YEARLY:
60                 if (event->bymonth && (event->bymonthday || event->byday))
61                         break;
62                 else if (event->byyearday || event->byweekno)
63                         break;
64
65                 event->bymonth = _cal_time_extract_by(event->start_tzid, event->wkst,
66                                 &event->start, CAL_MONTH);
67                 event->bymonthday = _cal_time_extract_by(event->start_tzid, event->wkst,
68                                 &event->start, CAL_DATE);
69                 DBG("Not enough field in yearly, so set bymonth[%s] bymonthday[%s]",
70                                 event->bymonth, event->bymonthday);
71                 break;
72
73         default:
74                 break;
75         }
76 }
77
78 void _cal_db_rrule_get_rrule_from_event(calendar_record_h event, cal_rrule_s **rrule)
79 {
80         cal_rrule_s *_rrule;
81         cal_event_s *_event;
82
83         retm_if(event == NULL, "Invalid argument: rrule is NULL");
84         _event = (cal_event_s *)event;
85         if (_event->freq == CALENDAR_RECURRENCE_NONE)
86         {
87                 return;
88         }
89
90         _rrule = calloc(1, sizeof(cal_rrule_s));
91         retm_if(_rrule == NULL, "Failed to calloc");
92
93         _rrule->freq = _event->freq;
94
95         _rrule->range_type = _event->range_type;
96         switch (_rrule->range_type)
97         {
98         case CALENDAR_RANGE_UNTIL:
99                 _rrule->until_type = _event->until_type;
100                 switch (_rrule->until_type)
101                 {
102                 case CALENDAR_TIME_UTIME:
103                         _rrule->until_utime = _event->until_utime;
104                         break;
105
106                 case CALENDAR_TIME_LOCALTIME:
107                         _rrule->until_year = _event->until_year;
108                         _rrule->until_month = _event->until_month;
109                         _rrule->until_mday = _event->until_mday;
110                         break;
111                 }
112                 break;
113
114         case CALENDAR_RANGE_COUNT:
115                 break;
116         case CALENDAR_RANGE_NONE:
117                 break;
118         }
119
120         _rrule->count = _event->count;
121         _rrule->interval = _event->interval;
122         _rrule->bysecond = _event->bysecond;
123         _rrule->byminute = _event->byminute;
124         _rrule->byhour = _event->byhour;
125         _rrule->byday = _event->byday;
126         _rrule->bymonthday = _event->bymonthday;
127         _rrule->byyearday = _event->byyearday;
128         _rrule->byweekno = _event->byweekno;
129         _rrule->bymonth = _event->bymonth;
130         _rrule->bysetpos = _event->bysetpos;
131         _rrule->wkst = _event->wkst;
132
133         *rrule = _rrule;
134 }
135
136 void _cal_db_rrule_set_rrule_to_event(cal_rrule_s *rrule, calendar_record_h event)
137 {
138         cal_event_s *_event;
139
140         retm_if(rrule == NULL, "Invalid argument: rrule is NULL");
141         retm_if(event == NULL, "Invalid argument: rrule is NULL");
142
143         _event = (cal_event_s *)event;
144
145         _event->freq = rrule->freq;
146         _event->range_type = rrule->range_type;
147         _event->until_type = rrule->until_type;
148         _event->until_utime = rrule->until_utime;
149         _event->until_year = rrule->until_year;
150         _event->until_month = rrule->until_month;
151         _event->until_mday = rrule->until_mday;
152         _event->count = rrule->count;
153         _event->interval = rrule->interval;
154         _event->bysecond = rrule->bysecond;
155         _event->byminute = rrule->byminute;
156         _event->byhour = rrule->byhour;
157         _event->byday = rrule->byday;
158         _event->bymonthday = rrule->bymonthday;
159         _event->byyearday = rrule->byyearday;
160         _event->byweekno = rrule->byweekno;
161         _event->bymonth = rrule->bymonth;
162         _event->bysetpos = rrule->bysetpos;
163         _event->wkst = rrule->wkst;
164 }
165
166 void _cal_db_rrule_set_rrule_to_todo(cal_rrule_s *rrule, calendar_record_h todo)
167 {
168         cal_todo_s *_todo;
169
170         retm_if(rrule == NULL, "Invalid argument: rrule is NULL");
171         retm_if(todo == NULL, "Invalid argument: todo is NULL");
172
173         _todo = (cal_todo_s *)todo;
174
175         _todo->freq = rrule->freq;
176         _todo->range_type = rrule->range_type;
177         _todo->until_type = rrule->until_type;
178         _todo->until_utime = rrule->until_utime;
179         _todo->until_year = rrule->until_year;
180         _todo->until_month = rrule->until_month;
181         _todo->until_mday = rrule->until_mday;
182         _todo->count = rrule->count;
183         _todo->interval = rrule->interval;
184         _todo->bysecond = rrule->bysecond;
185         _todo->byminute = rrule->byminute;
186         _todo->byhour = rrule->byhour;
187         _todo->byday = rrule->byday;
188         _todo->bymonthday = rrule->bymonthday;
189         _todo->byyearday = rrule->byyearday;
190         _todo->byweekno = rrule->byweekno;
191         _todo->bymonth = rrule->bymonth;
192         _todo->bysetpos = rrule->bysetpos;
193         _todo->wkst = rrule->wkst;
194 }
195
196 void _cal_db_rrule_get_rrule_from_todo(calendar_record_h todo, cal_rrule_s **rrule)
197 {
198         cal_rrule_s *_rrule;
199         cal_todo_s *_todo;
200
201         retm_if(todo == NULL, "Invalid argument: rrule is NULL");
202
203         _todo = (cal_todo_s *)todo;
204
205         _rrule = calloc(1, sizeof(cal_rrule_s));
206         retm_if(_rrule == NULL, "Failed to calloc");
207
208         _rrule->freq = _todo->freq;
209         _rrule->range_type = _todo->range_type;
210         _rrule->until_type = _todo->until_type;
211         _rrule->until_utime = _todo->until_utime;
212         _rrule->until_year = _todo->until_year;
213         _rrule->until_month = _todo->until_month;
214         _rrule->until_mday = _todo->until_mday;
215         _rrule->count = _todo->count;
216         _rrule->interval = _todo->interval;
217         _rrule->bysecond = _todo->bysecond;
218         _rrule->byminute = _todo->byminute;
219         _rrule->byhour = _todo->byhour;
220         _rrule->byday = _todo->byday;
221         _rrule->bymonthday = _todo->bymonthday;
222         _rrule->byyearday = _todo->byyearday;
223         _rrule->byweekno = _todo->byweekno;
224         _rrule->bymonth = _todo->bymonth;
225         _rrule->bysetpos = _todo->bysetpos;
226         _rrule->wkst = _todo->wkst;
227
228         *rrule = _rrule;
229 }
230
231 int __cal_db_rrule_insert_record(int id, cal_rrule_s *rrule)
232 {
233         int rrule_id;
234         int index;
235         char query[CAL_DB_SQL_MAX_LEN] = {0};
236         char until_datetime[32] = {0};
237         sqlite3_stmt *stmt = NULL;
238     cal_db_util_error_e dbret = CAL_DB_OK;
239
240         retvm_if(rrule == NULL, CALENDAR_ERROR_INVALID_PARAMETER,
241                         "Invalid argument: rrule is NULL");
242
243         snprintf(query, sizeof(query),
244                         "INSERT INTO %s ( "
245                         "event_id, freq, range_type, "
246                         "until_type, until_utime, until_datetime, "
247                         "count, interval, "
248                         "bysecond, byminute, byhour, byday, "
249                         "bymonthday, byyearday, byweekno, bymonth, "
250                         "bysetpos, wkst "
251                         ") VALUES ( "
252                         "%d, %d, %d, "
253                         "%d, %lld, ?, "
254                         "%d, %d, "
255                         "?, ?, ?, ?, "
256                         "?, ?, ?, ?, "
257                         "?, %d "
258                         ") ",
259                         CAL_TABLE_RRULE,
260                         id, rrule->freq, rrule->range_type,
261                         rrule->until_type, rrule->until_type == CALENDAR_TIME_UTIME ? rrule->until_utime : 0,
262                         rrule->count, rrule->interval,
263                         rrule->wkst);
264
265         DBG("[%s]", query);
266         stmt = _cal_db_util_query_prepare(query);
267         if (NULL == stmt)
268         {
269                 DBG("query[%s]", query);
270                 ERR("_cal_db_util_query_prepare() Failed");
271                 return CALENDAR_ERROR_DB_FAILED;
272         }
273
274         index = 1;
275
276         if (CALENDAR_TIME_LOCALTIME == rrule->until_type)
277         {
278                 snprintf(until_datetime, sizeof(until_datetime), "%04d%02d%02d",
279                                 rrule->until_year, rrule->until_month, rrule->until_mday);
280                 _cal_db_util_stmt_bind_text(stmt, index, until_datetime);
281         }
282         index++;
283
284         if (rrule->bysecond)
285                 _cal_db_util_stmt_bind_text(stmt, index, rrule->bysecond);
286         index++;
287
288         if (rrule->byminute)
289                 _cal_db_util_stmt_bind_text(stmt, index, rrule->byminute);
290         index++;
291
292         if (rrule->byhour)
293                 _cal_db_util_stmt_bind_text(stmt, index, rrule->byhour);
294         index++;
295
296         if (rrule->byday)
297                 _cal_db_util_stmt_bind_text(stmt, index, rrule->byday);
298         index++;
299
300         if (rrule->bymonthday)
301                 _cal_db_util_stmt_bind_text(stmt, index, rrule->bymonthday);
302         index++;
303
304         if (rrule->byyearday)
305                 _cal_db_util_stmt_bind_text(stmt, index, rrule->byyearday);
306         index++;
307
308         if (rrule->byweekno)
309                 _cal_db_util_stmt_bind_text(stmt, index, rrule->byweekno);
310         index++;
311
312         if (rrule->bymonth)
313                 _cal_db_util_stmt_bind_text(stmt, index, rrule->bymonth);
314         index++;
315
316         if (rrule->bysetpos)
317                 _cal_db_util_stmt_bind_text(stmt, index, rrule->bysetpos);
318         index++;
319
320         dbret = _cal_db_util_stmt_step(stmt);
321         sqlite3_finalize(stmt);
322         if (CAL_DB_OK != dbret)
323         {
324                 ERR("_cal_db_util_stmt_step() Failed(%d)", dbret);
325                 switch (dbret)
326                 {
327                 case CAL_DB_ERROR_NO_SPACE:
328                         return CALENDAR_ERROR_FILE_NO_SPACE;
329                 default:
330                         return CALENDAR_ERROR_DB_FAILED;
331                 }
332         }
333
334         rrule_id = _cal_db_util_last_insert_id();
335         DBG("rrule_id(%d)", rrule_id);
336         return CALENDAR_ERROR_NONE;
337 }
338
339 int _cal_db_rrule_get_rrule(int id, cal_rrule_s **rrule)
340 {
341         char query[CAL_DB_SQL_MAX_LEN];
342         int index;
343         sqlite3_stmt *stmt = NULL;
344         cal_rrule_s *_rrule = NULL;
345         const unsigned char *temp;
346         cal_db_util_error_e dbret = CAL_DB_OK;
347
348         _rrule = calloc(1, sizeof(cal_rrule_s));
349         retvm_if(_rrule == NULL, CALENDAR_ERROR_OUT_OF_MEMORY,
350                         "Failed to calloc");
351
352         snprintf(query, sizeof(query),
353                         "SELECT * FROM %s "
354                         "WHERE event_id = %d ",
355                         CAL_TABLE_RRULE,
356                         id);
357
358         stmt = _cal_db_util_query_prepare(query);
359         if (NULL == stmt)
360         {
361                 ERR("_cal_db_util_query_prepare() Failed");
362                 CAL_FREE(_rrule);
363                 return CALENDAR_ERROR_DB_FAILED;
364         }
365
366         dbret = _cal_db_util_stmt_step(stmt);
367         if (dbret != CAL_DB_ROW) {
368                 ERR("Failed to step stmt(%d)", dbret);
369                 sqlite3_finalize(stmt);
370                 CAL_FREE(_rrule);
371                 switch (dbret)
372                 {
373                 case CAL_DB_ERROR_NO_SPACE:
374                         return CALENDAR_ERROR_FILE_NO_SPACE;
375                 default:
376                         return CALENDAR_ERROR_DB_FAILED;
377                 }
378         }
379
380         index = 0;
381         sqlite3_column_int(stmt, index++); // id
382         sqlite3_column_int(stmt, index++); // event_id
383         _rrule->freq = sqlite3_column_int(stmt, index++);
384
385         //rrule->_rrule_id = 1;
386         _rrule->range_type = sqlite3_column_int(stmt, index++);
387         _rrule->until_type = sqlite3_column_int(stmt, index++);
388         _rrule->until_utime = sqlite3_column_int64(stmt, index++);
389
390         temp = sqlite3_column_text(stmt, index++);
391         if (CALENDAR_TIME_LOCALTIME == _rrule->until_type)
392         {
393                 sscanf((const char *)temp, "%04d%02d%02d",
394                                 &_rrule->until_year, &_rrule->until_month, &_rrule->until_mday);
395         }
396
397         _rrule->count = sqlite3_column_int(stmt, index++);
398         _rrule->interval = sqlite3_column_int(stmt, index++);
399
400         temp = sqlite3_column_text(stmt, index++);
401         _rrule->bysecond = SAFE_STRDUP(temp);
402
403         temp = sqlite3_column_text(stmt, index++);
404         _rrule->byminute = SAFE_STRDUP(temp);
405
406         temp = sqlite3_column_text(stmt, index++);
407         _rrule->byhour = SAFE_STRDUP(temp);
408
409         temp = sqlite3_column_text(stmt, index++);
410         _rrule->byday= SAFE_STRDUP(temp);
411
412         temp = sqlite3_column_text(stmt, index++);
413         _rrule->bymonthday= SAFE_STRDUP(temp);
414
415         temp = sqlite3_column_text(stmt, index++);
416         _rrule->byyearday= SAFE_STRDUP(temp);
417
418         temp = sqlite3_column_text(stmt, index++);
419         _rrule->byweekno= SAFE_STRDUP(temp);
420
421         temp = sqlite3_column_text(stmt, index++);
422         _rrule->bymonth= SAFE_STRDUP(temp);
423
424         temp = sqlite3_column_text(stmt, index++);
425         _rrule->bysetpos = SAFE_STRDUP(temp);
426
427         _rrule->wkst = sqlite3_column_int(stmt, index++);
428
429         sqlite3_finalize(stmt);
430
431         *rrule = _rrule;
432         return CALENDAR_ERROR_NONE;
433 }
434
435 static int __cal_db_rrule_delete_record(int id)
436 {
437         char query[CAL_DB_SQL_MAX_LEN] = {0};
438         cal_db_util_error_e dbret = CAL_DB_OK;
439
440         snprintf(query, sizeof(query),
441                         "DELETE FROM %s WHERE event_id = %d ",
442                         CAL_TABLE_RRULE, id);
443
444         dbret = _cal_db_util_query_exec(query);
445         if(CAL_DB_DONE != dbret)
446         {
447                 ERR("_cal_db_util_query_exec() Failed");
448                 switch (dbret)
449                 {
450                 case CAL_DB_ERROR_NO_SPACE:
451                         return CALENDAR_ERROR_FILE_NO_SPACE;
452                 default:
453                         return CALENDAR_ERROR_DB_FAILED;
454                 }
455         }
456         return CALENDAR_ERROR_NONE;
457 }
458
459 static int __cal_db_rrule_has_record(int id, int *has_record)
460 {
461         int ret;
462     int count = 0;
463         char query[CAL_DB_SQL_MAX_LEN] = {0};
464
465         snprintf(query, sizeof(query),
466                         "SELECT count(*) FROM %s WHERE event_id = %d ",
467                         CAL_TABLE_RRULE, id);
468
469         ret = _cal_db_util_query_get_first_int_result(query, NULL, &count);
470         if (CALENDAR_ERROR_NONE != ret)
471         {
472                 ERR("_cal_db_util_query_get_first_int_result() failed");
473                 return ret;
474         }
475
476         *has_record = count > 0 ? 1 : 0;
477         return CALENDAR_ERROR_NONE;
478 }
479
480 static int __cal_db_rrule_update_record(int id, cal_rrule_s *rrule)
481 {
482         char query[CAL_DB_SQL_MAX_LEN] = {0};
483         char until_datetime[32] = {0};
484         cal_db_util_error_e dbret = CAL_DB_OK;
485         sqlite3_stmt *stmt = NULL;
486
487         snprintf(query, sizeof(query),
488                         "UPDATE %s SET "
489                         "freq = %d, "
490                         "range_type = %d, "
491                         "until_type = %d, "
492                         "until_utime = %lld, "
493                         "until_datetime = ?, "
494                         "count = %d, "
495                         "interval = %d, "
496                         "bysecond = ?, "
497                         "byminute= ?, "
498                         "byhour = ?, "
499                         "byday = ?, "
500                         "bymonthday = ?, "
501                         "byyearday = ?, "
502                         "byweekno = ?, "
503                         "bymonth = ?, "
504                         "bysetpos = ?, "
505                         "wkst = %d "
506                         "WHERE event_id = %d ",
507                         CAL_TABLE_RRULE,
508                         rrule->freq,
509                         rrule->range_type,
510                         rrule->until_type,
511                         rrule->until_type == CALENDAR_TIME_UTIME ? rrule->until_utime : 0,
512                         rrule->count,
513                         rrule->interval,
514                         rrule->wkst,
515                         id);
516
517         stmt = _cal_db_util_query_prepare(query);
518         if (NULL == stmt)
519         {
520                 DBG("query[%s]", query);
521                 ERR("_cal_db_util_query_prepare() Failed");
522                 return CALENDAR_ERROR_DB_FAILED;
523         }
524
525         int index = 1;
526         if (CALENDAR_TIME_LOCALTIME == rrule->until_type)
527         {
528                 snprintf(until_datetime, sizeof(until_datetime), "%04d%02d%02d",
529                                 rrule->until_year, rrule->until_month, rrule->until_mday);
530                 _cal_db_util_stmt_bind_text(stmt, index, until_datetime);
531         }
532         index++;
533
534         if (rrule->bysecond)
535                 _cal_db_util_stmt_bind_text(stmt, index, rrule->bysecond);
536         index++;
537
538         if (rrule->byminute)
539                 _cal_db_util_stmt_bind_text(stmt, index, rrule->byminute);
540         index++;
541
542         if (rrule->byhour)
543                 _cal_db_util_stmt_bind_text(stmt, index, rrule->byhour);
544         index++;
545
546         if (rrule->byday)
547                 _cal_db_util_stmt_bind_text(stmt, index, rrule->byday);
548         index++;
549
550         if (rrule->bymonthday)
551                 _cal_db_util_stmt_bind_text(stmt, index, rrule->bymonthday);
552         index++;
553
554         if (rrule->byyearday)
555                 _cal_db_util_stmt_bind_text(stmt, index, rrule->byyearday);
556         index++;
557
558         if (rrule->byweekno)
559                 _cal_db_util_stmt_bind_text(stmt, index, rrule->byweekno);
560         index++;
561
562         if (rrule->bymonth)
563                 _cal_db_util_stmt_bind_text(stmt, index, rrule->bymonth);
564         index++;
565
566         if (rrule->bysetpos)
567                 _cal_db_util_stmt_bind_text(stmt, index, rrule->bysetpos);
568         index++;
569
570         dbret = _cal_db_util_stmt_step(stmt);
571         sqlite3_finalize(stmt);
572         if (CAL_DB_DONE != dbret) {
573                 ERR("sqlite3_step() Failed(%d)", dbret);
574                 switch (dbret)
575                 {
576                 case CAL_DB_ERROR_NO_SPACE:
577                         return CALENDAR_ERROR_FILE_NO_SPACE;
578                 default:
579                         return CALENDAR_ERROR_DB_FAILED;
580                 }
581         }
582         return CALENDAR_ERROR_NONE;
583 }
584
585 int _cal_db_rrule_insert_record(int id, cal_rrule_s *rrule)
586 {
587         retvm_if(rrule == NULL, CALENDAR_ERROR_INVALID_PARAMETER,
588                         "Invalid argument: rrule is NULL");
589
590         if (rrule->freq == CALENDAR_RECURRENCE_NONE)
591         {
592         }
593         else
594         {
595                 __cal_db_rrule_insert_record(id, rrule);
596         }
597         return CALENDAR_ERROR_NONE;
598 }
599
600 int _cal_db_rrule_update_record(int id, cal_rrule_s *rrule)
601 {
602         int has_record = 0;
603
604         if (NULL == rrule || rrule->freq == CALENDAR_RECURRENCE_NONE)
605         {
606                 DBG("freq is NONE");
607                 __cal_db_rrule_delete_record(id);
608                 return CALENDAR_ERROR_NONE;
609         }
610         else
611         {
612                 __cal_db_rrule_has_record(id, &has_record);
613                 if (has_record)
614                 {
615                         __cal_db_rrule_update_record(id, rrule);
616                 }
617                 else
618                 {
619                         __cal_db_rrule_insert_record(id, rrule);
620                 }
621         }
622         return CALENDAR_ERROR_NONE;
623 }
624