modify terminology:calendar->book,allday->localtime,normal->utime,svc->service
[platform/core/pim/calendar-service.git] / server / db / cal_db_query.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 <stdlib.h>
21
22 #include "cal_internal.h"
23 #include "cal_typedef.h"
24 #include "cal_view.h"
25 #include "cal_record.h"
26
27 #include "cal_db_util.h"
28 #include "cal_db.h"
29 #include "cal_db_query.h"
30
31 #define CAL_DB_CALTIME_FIELD_MAX 3
32 #define CAL_DB_ESCAPE_CHAR      '\\'
33
34 static const char* _cal_db_utime_field_name[] = {
35         "dtstart_utime",
36         "dtend_utime",
37         "until_utime"
38 };
39 static const char* _cal_db_datetime_field_name[] = {
40         "dtstart_datetime",
41         "dtend_datetime",
42         "until_datetime"
43 };
44 static const char* _cal_db_timetype_field_name[] = {
45         "dtstart_type",
46         "dtend_type",
47         "until_type"
48 };
49
50 static int _cal_db_query_create_composite_condition(cal_composite_filter_s *com_filter,
51                 char **condition, GSList **bind_text);
52 static int _cal_db_query_create_attribute_condition(cal_composite_filter_s *com_filter,
53                 cal_attribute_filter_s *filter, char **condition, GSList **bind_text);
54 static int _cal_db_query_create_str_condition(cal_composite_filter_s *com_filter,
55                 cal_attribute_filter_s *filter, char **condition, GSList **bind_text);
56 static int _cal_db_query_create_int_condition(cal_composite_filter_s *com_filter,
57                 cal_attribute_filter_s *filter, char **condition);
58 static int _cal_db_query_create_double_condition(cal_composite_filter_s *com_filter,
59                 cal_attribute_filter_s *filter, char **condition);
60 static int _cal_db_query_create_lli_condition(cal_composite_filter_s *com_filter,
61                 cal_attribute_filter_s *filter, char **condition);
62 static int _cal_db_query_create_caltime_condition(cal_composite_filter_s *com_filter,
63                 cal_attribute_filter_s *filter, char **condition);
64 static const char * _cal_db_query_get_property_field_name(const cal_property_info_s *properties,
65                 int count, unsigned int property_id);
66 static const char * _cal_db_query_get_utime_field_name(const char* src);
67 static const char * _cal_db_query_get_datetime_field_name(const char* src);
68 static const char * _cal_db_query_get_timetype_field_name(const char* src);
69
70 int cal_db_query_create_condition(calendar_query_h query, char **condition, GSList **bind_text)
71 {
72         cal_query_s *que = NULL;
73         int ret = CALENDAR_ERROR_NONE;
74
75         RETV_IF(NULL == query, CALENDAR_ERROR_INVALID_PARAMETER);
76         RETV_IF(NULL == condition, CALENDAR_ERROR_INVALID_PARAMETER);
77         RETV_IF(NULL == bind_text, CALENDAR_ERROR_INVALID_PARAMETER);
78
79         que = (cal_query_s *)query;
80
81         ret = _cal_db_query_create_composite_condition(que->filter, condition, bind_text);
82
83         return ret;
84 }
85
86 int cal_db_query_create_projection(calendar_query_h query, char **projection)
87 {
88         int i = 0;
89         const char *field_name;
90         char *out_projection = NULL;
91         cal_query_s *query_s = NULL;
92         cal_property_info_s *properties = NULL;
93
94         RETV_IF(NULL == query, CALENDAR_ERROR_INVALID_PARAMETER);
95         query_s = (cal_query_s *)query;
96
97         properties = query_s->properties;
98
99         if (NULL == query_s->projection || '\0' == *(query_s->projection)) {
100                 *projection = g_strdup("* ");
101                 return CALENDAR_ERROR_NONE;
102         }
103
104         field_name = _cal_db_query_get_property_field_name(properties, query_s->property_count, query_s->projection[0]);
105         if (field_name)
106                 cal_db_append_string(&out_projection, (char*)field_name);
107
108         for (i = 1; i < query_s->projection_count; i++) {
109                 field_name = _cal_db_query_get_property_field_name(properties, query_s->property_count, query_s->projection[i]);
110                 if (field_name) {
111                         cal_db_append_string(&out_projection, ",");
112                         cal_db_append_string(&out_projection, (char*)field_name);
113                 }
114         }
115
116         *projection = out_projection;
117
118         return CALENDAR_ERROR_NONE;
119 }
120
121 int cal_db_query_create_order(calendar_query_h query, char *condition, char **order)
122 {
123         const char *field_name = NULL;
124         char out_order[CAL_DB_SQL_MAX_LEN] = {0};
125         cal_query_s *query_s = NULL;
126         cal_property_info_s *properties = NULL;
127
128         RETV_IF(NULL == query, CALENDAR_ERROR_INVALID_PARAMETER);
129         query_s = (cal_query_s *)query;
130         properties = query_s->properties;
131
132         if (query_s->sort_property_id <= 0)
133                 return CALENDAR_ERROR_NO_DATA;
134
135         field_name = _cal_db_query_get_property_field_name(properties, query_s->property_count, query_s->sort_property_id);
136         if (CAL_PROPERTY_CHECK_DATA_TYPE(query_s->sort_property_id, CAL_PROPERTY_DATA_TYPE_CALTIME) == true && field_name) {
137                 const char *p_utime = NULL;
138                 const char *p_datetime = NULL;
139
140                 p_utime = _cal_db_query_get_utime_field_name(field_name);
141                 p_datetime = _cal_db_query_get_datetime_field_name(field_name);
142
143                 if (!p_utime && !p_datetime) {
144                         if (condition) {
145                                 p_utime = _cal_db_query_get_utime_field_name(condition);
146                                 p_datetime = _cal_db_query_get_datetime_field_name(condition);
147                         } else {
148                                 DBG("No condition");
149                         }
150                 }
151
152                 if (p_utime && p_datetime) {
153                         cal_record_type_e type = cal_view_get_type(query_s->view_uri);
154                         switch (type) {
155                         case CAL_RECORD_TYPE_INSTANCE_UTIME_EXTENDED:
156                         case CAL_RECORD_TYPE_INSTANCE_UTIME:
157                                 snprintf(out_order, sizeof(out_order), "ORDER BY %s %s ", p_utime, query_s->asc == false ? "DESC" : "ASC");
158                                 break;
159                         case CAL_RECORD_TYPE_INSTANCE_LOCALTIME_EXTENDED:
160                         case CAL_RECORD_TYPE_INSTANCE_LOCALTIME:
161                                 snprintf(out_order, sizeof(out_order), "ORDER BY %s %s ", p_datetime, query_s->asc == false ? "DESC" : "ASC");
162                                 break;
163                         default:
164                                 snprintf(out_order, sizeof(out_order), "ORDER BY %s %s, %s %s ", p_utime, query_s->asc == false ? "DESC" : "ASC", p_datetime, query_s->asc == false ? "DESC" : "ASC");
165                                 break;
166                         }
167                 } else if (p_utime && !p_datetime) {
168                         snprintf(out_order, sizeof(out_order), "ORDER BY %s %s ", p_utime, query_s->asc == false ? "DESC" : "ASC");
169                 } else if (!p_utime && p_datetime) {
170                         snprintf(out_order, sizeof(out_order), "ORDER BY %s %s ", p_datetime, query_s->asc == false ? "DESC" : "ASC");
171                 } else {
172                         DBG("No utime, datetime");
173                 }
174         } else {
175                 snprintf(out_order, sizeof(out_order), "ORDER BY %s %s ", field_name, query_s->asc == false ? "DESC" : "ASC");
176         }
177         *order = strdup(out_order);
178
179         return CALENDAR_ERROR_NONE;
180 }
181
182 bool cal_db_query_find_projection_property(calendar_query_h query, unsigned int property)
183 {
184         int i = 0;
185         cal_query_s *query_s = NULL;
186
187         RETV_IF(NULL == query, CALENDAR_ERROR_INVALID_PARAMETER);
188         query_s = (cal_query_s *)query;
189
190         if (NULL == query_s->projection || '\0' == *query_s->projection)
191                 return true;
192
193         for (i = 0; i < query_s->projection_count; i++)
194                 if (query_s->projection[i] == property)
195                         return true;
196
197         return false;
198 }
199
200 int cal_db_query_create_projection_update_set(calendar_record_h record, char **set, GSList **bind_text)
201 {
202         cal_record_s *_record = NULL;
203         int i = 0;
204         const cal_property_info_s* property_info = NULL;
205         int property_info_count = 0;
206         char out_set[CAL_DB_SQL_MAX_LEN] = {0};
207         int len = 0;
208         const char *field_name;
209         int ret = CALENDAR_ERROR_NONE;
210
211         RETV_IF(NULL == record, -1);
212
213         _record = (cal_record_s *)record;
214
215         RETV_IF(0 == _record->properties_max_count, CALENDAR_ERROR_INVALID_PARAMETER);
216         RETV_IF(NULL == _record->properties_flags, CALENDAR_ERROR_INVALID_PARAMETER);
217
218         /* get propety_info_s from uri */
219         property_info = cal_view_get_property_info(_record->view_uri, &property_info_count);
220
221         for (i = 0; i < property_info_count; i++) {
222                 if (true == cal_record_check_property_flag(record, property_info[i].property_id , CAL_PROPERTY_FLAG_DIRTY)) {
223                         field_name = property_info[i].fields;
224
225                         if (NULL == field_name)
226                                 continue;
227
228                         if (CAL_PROPERTY_CHECK_DATA_TYPE(property_info[i].property_id, CAL_PROPERTY_DATA_TYPE_INT) == true) {
229                                 int tmp = 0;
230                                 ret = calendar_record_get_int(record, property_info[i].property_id, &tmp);
231                                 if (CALENDAR_ERROR_NONE != ret)
232                                         continue;
233                                 if (strlen(out_set) != 0)
234                                         len += snprintf(out_set+len, sizeof(out_set)-len, ", ");
235
236                                 len += snprintf(out_set+len, sizeof(out_set)-len, "%s=%d", field_name, tmp);
237                         } else if (CAL_PROPERTY_CHECK_DATA_TYPE(property_info[i].property_id, CAL_PROPERTY_DATA_TYPE_STR) == true) {
238                                 char *tmp = NULL;
239                                 ret = calendar_record_get_str(record, property_info[i].property_id, &tmp);
240                                 if (CALENDAR_ERROR_NONE != ret)
241                                         continue;
242                                 if (strlen(out_set) != 0)
243                                         len += snprintf(out_set+len, sizeof(out_set)-len, ", ");
244
245                                 len += snprintf(out_set+len, sizeof(out_set)-len, "%s=?", field_name);
246                                 *bind_text = g_slist_append(*bind_text, tmp);
247                         } else if (CAL_PROPERTY_CHECK_DATA_TYPE(property_info[i].property_id, CAL_PROPERTY_DATA_TYPE_DOUBLE) == true) {
248                                 double tmp = 0;
249                                 ret = calendar_record_get_double(record, property_info[i].property_id, &tmp);
250                                 if (CALENDAR_ERROR_NONE != ret)
251                                         continue;
252                                 if (strlen(out_set) != 0)
253                                         len += snprintf(out_set+len, sizeof(out_set)-len, ", ");
254
255                                 len += snprintf(out_set+len, sizeof(out_set)-len, "%s=%lf", field_name, tmp);
256                         } else if (CAL_PROPERTY_CHECK_DATA_TYPE(property_info[i].property_id, CAL_PROPERTY_DATA_TYPE_LLI) == true) {
257                                 long long int tmp = 0;
258                                 ret = calendar_record_get_lli(record, property_info[i].property_id, &tmp);
259                                 if (CALENDAR_ERROR_NONE != ret)
260                                         continue;
261                                 if (strlen(out_set) != 0)
262                                         len += snprintf(out_set+len, sizeof(out_set)-len, ", ");
263
264                                 len += snprintf(out_set+len, sizeof(out_set)-len, "%s=%lld", field_name, tmp);
265                         } else if (CAL_PROPERTY_CHECK_DATA_TYPE(property_info[i].property_id, CAL_PROPERTY_DATA_TYPE_CALTIME) == true) {
266                                 /*
267                                  * field_name
268                                  * dtstart_type, dtstart_utime, dtstart_datetime
269                                  *      -> dtstart_type=%d, dtstart_utime=%lli, dtstart_datetime=?
270                                  * dtend_type, dtend_utime, dtend_datetime
271                                  *      -> dtend_type=%d, dtend_utime=%lli, dtend_datetime=?
272                                  * until_type, until_utime, until_datetime
273                                  *      -> until_type=%d, until_utime=%lli, until_datetime=?
274                                  */
275                                 calendar_time_s tmp = {0,};
276                                 const char *timetype_field = NULL;
277                                 const char *utime_field = NULL;
278                                 const char *datetime_field = NULL;
279                                 timetype_field = _cal_db_query_get_timetype_field_name(field_name);
280                                 utime_field = _cal_db_query_get_utime_field_name(field_name);
281                                 datetime_field = _cal_db_query_get_datetime_field_name(field_name);
282                                 ret = calendar_record_get_caltime(record, property_info[i].property_id, &tmp);
283                                 if (CALENDAR_ERROR_NONE != ret)
284                                         continue;
285                                 if (tmp.type == CALENDAR_TIME_UTIME) {
286                                         if (strlen(out_set) != 0)
287                                                 len += snprintf(out_set+len, sizeof(out_set)-len, ", ");
288
289                                         len += snprintf(out_set+len, sizeof(out_set)-len, "%s=%d, %s=%lld",
290                                                         timetype_field, CALENDAR_TIME_UTIME, utime_field, tmp.time.utime);
291                                 } else {
292                                         char *bind_tmp = NULL;
293                                         char bind_datetime[CAL_STR_SHORT_LEN32] = {0};
294                                         snprintf(bind_datetime, sizeof(bind_datetime), CAL_FORMAT_LOCAL_DATETIME,
295                                                         tmp.time.date.year,
296                                                         tmp.time.date.month,
297                                                         tmp.time.date.mday,
298                                                         tmp.time.date.hour,
299                                                         tmp.time.date.minute,
300                                                         tmp.time.date.second);
301
302                                         if (strlen(out_set) != 0)
303                                                 len += snprintf(out_set+len, sizeof(out_set)-len, ", ");
304
305                                         len += snprintf(out_set+len, sizeof(out_set)-len, "%s=%d, %s=?",
306                                                         timetype_field, CALENDAR_TIME_LOCALTIME, datetime_field);
307
308                                         bind_tmp = strdup(bind_datetime);
309                                         *bind_text = g_slist_append(*bind_text, bind_tmp);
310                                 }
311                         }
312                 }
313         }
314
315         *set = strdup(out_set);
316         DBG("set=%s", *set);
317
318         return CALENDAR_ERROR_NONE;
319 }
320
321 int cal_db_query_create_projection_update_set_with_property(
322                 calendar_record_h record, unsigned int *properties, int properties_count,
323                 char **set, GSList **bind_text)
324 {
325         cal_record_s *_record = NULL;
326         int i = 0;
327         const cal_property_info_s* property_info = NULL;
328         int property_info_count = 0;
329         char out_set[CAL_DB_SQL_MAX_LEN] = {0};
330         int len = 0;
331         const char *field_name;
332         int ret = CALENDAR_ERROR_NONE;
333
334         RETV_IF(NULL == record, -1);
335
336         _record = (cal_record_s *)record;
337
338         if (_record->properties_max_count == 0 || NULL == _record->properties_flags)
339                 return CALENDAR_ERROR_NONE;
340
341         /* get propety_info_s from uri */
342         property_info = cal_view_get_property_info(_record->view_uri, &property_info_count);
343
344         for (i = 0; i < property_info_count; i++) {
345                 int j = 0;
346                 bool flag = false;
347                 for (j = 0; j < properties_count; j++) {
348                         if (property_info[i].property_id == properties[j]) {
349                                 flag = true;
350                                 break;
351                         }
352                 }
353                 if (true == flag &&
354                                 (true == cal_record_check_property_flag(record, property_info[i].property_id , CAL_PROPERTY_FLAG_DIRTY))) {
355                         field_name = property_info[i].fields;
356
357                         if (NULL == field_name)
358                                 continue;
359
360                         if (CAL_PROPERTY_CHECK_DATA_TYPE(property_info[i].property_id, CAL_PROPERTY_DATA_TYPE_INT) == true) {
361                                 int tmp = 0;
362                                 ret = calendar_record_get_int(record, property_info[i].property_id, &tmp);
363                                 if (CALENDAR_ERROR_NONE != ret)
364                                         continue;
365                                 if (strlen(out_set) != 0)
366                                         len += snprintf(out_set+len, sizeof(out_set)-len, ", ");
367
368                                 len += snprintf(out_set+len, sizeof(out_set)-len, "%s=%d", field_name, tmp);
369                         } else if (CAL_PROPERTY_CHECK_DATA_TYPE(property_info[i].property_id, CAL_PROPERTY_DATA_TYPE_STR) == true) {
370                                 char *tmp = NULL;
371                                 ret = calendar_record_get_str(record, property_info[i].property_id, &tmp);
372                                 if (CALENDAR_ERROR_NONE != ret)
373                                         continue;
374                                 if (strlen(out_set) != 0)
375                                         len += snprintf(out_set+len, sizeof(out_set)-len, ", ");
376
377                                 len += snprintf(out_set+len, sizeof(out_set)-len, "%s=?", field_name);
378                                 *bind_text = g_slist_append(*bind_text, tmp);
379                         } else if (CAL_PROPERTY_CHECK_DATA_TYPE(property_info[i].property_id, CAL_PROPERTY_DATA_TYPE_DOUBLE) == true) {
380                                 double tmp = 0;
381                                 ret = calendar_record_get_double(record, property_info[i].property_id, &tmp);
382                                 if (CALENDAR_ERROR_NONE != ret)
383                                         continue;
384                                 if (strlen(out_set) != 0)
385                                         len += snprintf(out_set+len, sizeof(out_set)-len, ", ");
386
387                                 len += snprintf(out_set+len, sizeof(out_set)-len, "%s=%lf", field_name, tmp);
388                         } else if (CAL_PROPERTY_CHECK_DATA_TYPE(property_info[i].property_id, CAL_PROPERTY_DATA_TYPE_LLI) == true) {
389                                 long long int tmp = 0;
390                                 ret = calendar_record_get_lli(record, property_info[i].property_id, &tmp);
391                                 if (CALENDAR_ERROR_NONE != ret)
392                                         continue;
393                                 if (strlen(out_set) != 0)
394                                         len += snprintf(out_set+len, sizeof(out_set)-len, ", ");
395
396                                 len += snprintf(out_set+len, sizeof(out_set)-len, "%s=%lld", field_name, tmp);
397                         } else if (CAL_PROPERTY_CHECK_DATA_TYPE(property_info[i].property_id, CAL_PROPERTY_DATA_TYPE_CALTIME) == true) {
398                                 /*
399                                  * field_name
400                                  * dtstart_type, dtstart_utime, dtstart_datetime
401                                  *      -> dtstart_type=%d, dtstart_utime=%lli, dtstart_datetime=?
402                                  * dtend_type, dtend_utime, dtend_datetime
403                                  *      -> dtend_type=%d, dtend_utime=%lli, dtend_datetime=?
404                                  * until_type, until_utime, until_datetime
405                                  *      -> until_type=%d, until_utime=%lli, until_datetime=?
406                                  */
407                                 calendar_time_s tmp = {0,};
408                                 const char *timetype_field = NULL;
409                                 const char *utime_field = NULL;
410                                 const char *datetime_field = NULL;
411                                 timetype_field = _cal_db_query_get_timetype_field_name(field_name);
412                                 utime_field = _cal_db_query_get_utime_field_name(field_name);
413                                 datetime_field = _cal_db_query_get_datetime_field_name(field_name);
414                                 ret = calendar_record_get_caltime(record, property_info[i].property_id, &tmp);
415                                 if (CALENDAR_ERROR_NONE != ret)
416                                         continue;
417                                 if (tmp.type == CALENDAR_TIME_UTIME) {
418                                         if (strlen(out_set) != 0)
419                                                 len += snprintf(out_set+len, sizeof(out_set)-len, ", ");
420
421                                         len += snprintf(out_set+len, sizeof(out_set)-len, "%s=%d, %s=%lld",
422                                                         timetype_field, CALENDAR_TIME_UTIME, utime_field, tmp.time.utime);
423                                 } else {
424                                         char *bind_tmp = NULL;
425                                         char bind_datetime[CAL_STR_SHORT_LEN32] = {0};
426                                         snprintf(bind_datetime, sizeof(bind_datetime), CAL_FORMAT_LOCAL_DATETIME,
427                                                         tmp.time.date.year,
428                                                         tmp.time.date.month,
429                                                         tmp.time.date.mday,
430                                                         tmp.time.date.hour,
431                                                         tmp.time.date.minute,
432                                                         tmp.time.date.second);
433
434                                         if (strlen(out_set) != 0)
435                                                 len += snprintf(out_set+len, sizeof(out_set)-len, ", ");
436
437                                         len += snprintf(out_set+len, sizeof(out_set)-len, "%s=%d, %s=?",
438                                                         timetype_field, CALENDAR_TIME_LOCALTIME, datetime_field);
439
440                                         bind_tmp = strdup(bind_datetime);
441                                         *bind_text = g_slist_append(*bind_text, bind_tmp);
442                                 }
443                         }
444                 }
445         }
446
447         *set = strdup(out_set);
448
449         return CALENDAR_ERROR_NONE;
450 }
451
452 static int _cal_db_query_create_composite_condition(cal_composite_filter_s *com_filter, char **condition, GSList **bind_text)
453 {
454         GSList *cursor_filter = NULL;
455         GSList *cursor_ops = NULL;
456         calendar_filter_operator_e op;
457         char *cond = NULL;
458         char *out_cond = NULL;
459         GSList *binds = NULL, *binds2 = NULL;
460         cal_filter_s *filter;
461         int ret = CALENDAR_ERROR_NONE;
462
463         RETV_IF(NULL == com_filter, CALENDAR_ERROR_INVALID_PARAMETER);
464         RETV_IF(NULL == com_filter->filters, CALENDAR_ERROR_INVALID_PARAMETER);
465
466         filter = (cal_filter_s *)com_filter->filters->data;
467         if (filter->filter_type == CAL_FILTER_COMPOSITE)
468                 ret = _cal_db_query_create_composite_condition((cal_composite_filter_s*)filter, &cond, &binds);
469         else
470                 ret = _cal_db_query_create_attribute_condition(com_filter, (cal_attribute_filter_s*)filter, &cond, &binds);
471
472         if (CALENDAR_ERROR_NONE != ret) {
473                 /* LCOV_EXCL_START */
474                 ERR("_cal_db_query_create_attribute_condition() Fail(%d)", ret);
475                 return CALENDAR_ERROR_INVALID_PARAMETER;
476                 /* LCOV_EXCL_STOP */
477         }
478
479         cursor_filter = com_filter->filters->next;
480
481         cal_db_append_string(&out_cond, "(");
482         cal_db_append_string(&out_cond, cond);
483         cal_db_append_string(&out_cond, ")");
484
485         CAL_FREE(cond);
486
487         for (cursor_ops = com_filter->filter_ops; cursor_ops && cursor_filter;
488                         cursor_filter = cursor_filter->next, cursor_ops = cursor_ops->next) {
489                 filter = (cal_filter_s *)cursor_filter->data;
490                 if (filter->filter_type == CAL_FILTER_COMPOSITE)
491                         ret = _cal_db_query_create_composite_condition((cal_composite_filter_s*)filter, &cond, &binds2);
492                 else
493                         ret = _cal_db_query_create_attribute_condition(com_filter, (cal_attribute_filter_s*)filter, &cond, &binds2);
494
495                 if (CALENDAR_ERROR_NONE != ret) {
496                         /* LCOV_EXCL_START */
497                         ERR("_cal_db_query_create_attribute_condition() Fail(%d)", ret);
498                         CAL_FREE(out_cond);
499                         if (binds) {
500                                 g_slist_free_full(binds, free);
501                                 binds = NULL;
502                         }
503                         return CALENDAR_ERROR_INVALID_PARAMETER;
504                         /* LCOV_EXCL_STOP */
505                 }
506
507                 op = (calendar_filter_operator_e)cursor_ops->data;
508                 if (op == CALENDAR_FILTER_OPERATOR_AND) {
509                         cal_db_append_string(&out_cond, "AND (");
510                         cal_db_append_string(&out_cond, cond);
511                         cal_db_append_string(&out_cond, ")");
512                 } else {
513                         cal_db_append_string(&out_cond, "OR (");
514                         cal_db_append_string(&out_cond, cond);
515                         cal_db_append_string(&out_cond, ")");
516                 }
517
518                 if (binds2)
519                         binds = g_slist_concat(binds, binds2);
520                 binds2 = NULL;
521
522                 CAL_FREE(cond);
523         }
524
525         *condition = out_cond;
526         *bind_text = binds;
527
528         return CALENDAR_ERROR_NONE;
529 }
530
531 static int _cal_db_query_create_attribute_condition(cal_composite_filter_s *com_filter,
532                 cal_attribute_filter_s *filter, char **condition, GSList **bind_text)
533 {
534         int ret;
535         char *cond = NULL;
536
537         RETV_IF(NULL == filter, CALENDAR_ERROR_INVALID_PARAMETER);
538
539         switch (filter->filter_type) {
540         case CAL_FILTER_INT:
541                 ret = _cal_db_query_create_int_condition(com_filter, filter, &cond);
542                 break;
543         case CAL_FILTER_STR:
544                 ret = _cal_db_query_create_str_condition(com_filter, filter, &cond, bind_text);
545                 break;
546         case CAL_FILTER_DOUBLE:
547                 ret = _cal_db_query_create_double_condition(com_filter, filter, &cond);
548                 break;
549         case CAL_FILTER_LLI:
550                 ret = _cal_db_query_create_lli_condition(com_filter, filter, &cond);
551                 break;
552         case CAL_FILTER_CALTIME:
553                 ret = _cal_db_query_create_caltime_condition(com_filter, filter, &cond);
554                 break;
555         default:
556                 /* LCOV_EXCL_START */
557                 ERR("The filter type is not supported (%d)", filter->filter_type);
558                 return CALENDAR_ERROR_INVALID_PARAMETER;
559                 /* LCOV_EXCL_STOP */
560         }
561
562         if (CALENDAR_ERROR_NONE == ret)
563                 *condition = (cond);
564
565         return ret;
566 }
567
568 static int _cal_db_query_create_int_condition(cal_composite_filter_s *com_filter,
569                 cal_attribute_filter_s *filter, char **condition)
570 {
571         const char *field_name;
572         char out_cond[CAL_DB_SQL_MAX_LEN] = {0};
573
574         field_name = _cal_db_query_get_property_field_name(com_filter->properties,
575                         com_filter->property_count, filter->property_id);
576         RETVM_IF(NULL == field_name, CALENDAR_ERROR_INVALID_PARAMETER,
577                         "Invalid parameter : property id(%d)", filter->property_id);
578
579         switch (filter->match) {
580         case CALENDAR_MATCH_EQUAL:
581                 snprintf(out_cond, sizeof(out_cond), "%s = %d", field_name, filter->value.i);
582                 break;
583         case CALENDAR_MATCH_GREATER_THAN:
584                 snprintf(out_cond, sizeof(out_cond), "%s > %d", field_name, filter->value.i);
585                 break;
586         case CALENDAR_MATCH_GREATER_THAN_OR_EQUAL:
587                 snprintf(out_cond, sizeof(out_cond), "%s >= %d", field_name, filter->value.i);
588                 break;
589         case CALENDAR_MATCH_LESS_THAN:
590                 snprintf(out_cond, sizeof(out_cond), "%s < %d", field_name, filter->value.i);
591                 break;
592         case CALENDAR_MATCH_LESS_THAN_OR_EQUAL:
593                 snprintf(out_cond, sizeof(out_cond), "%s <= %d", field_name, filter->value.i);
594                 break;
595         case CALENDAR_MATCH_NONE:
596                 snprintf(out_cond, sizeof(out_cond), "%s IS NULL", field_name);
597                 break;
598         case CALENDAR_MATCH_NOT_EQUAL:
599                 snprintf(out_cond, sizeof(out_cond), "%s <> %d", field_name, filter->value.i);
600                 break;
601         default:
602                 /* LCOV_EXCL_START */
603                 ERR("Invalid parameter : int match rule(%d) is not supported", filter->match);
604                 return CALENDAR_ERROR_INVALID_PARAMETER;
605                 /* LCOV_EXCL_STOP */
606         }
607
608         *condition = strdup(out_cond);
609         return CALENDAR_ERROR_NONE;
610 }
611
612 static int _cal_db_query_create_double_condition(cal_composite_filter_s *com_filter,
613                 cal_attribute_filter_s *filter, char **condition)
614 {
615         const char *field_name;
616         char out_cond[CAL_DB_SQL_MAX_LEN] = {0};
617
618         field_name = _cal_db_query_get_property_field_name(com_filter->properties,
619                         com_filter->property_count, filter->property_id);
620         RETVM_IF(NULL == field_name, CALENDAR_ERROR_INVALID_PARAMETER,
621                         "Invalid parameter : property id(%d)", filter->property_id);
622
623         switch (filter->match) {
624         case CALENDAR_MATCH_EQUAL:
625                 snprintf(out_cond, sizeof(out_cond), "%s = %lf", field_name, filter->value.d);
626                 break;
627         case CALENDAR_MATCH_GREATER_THAN:
628                 snprintf(out_cond, sizeof(out_cond), "%s > %lf", field_name, filter->value.d);
629                 break;
630         case CALENDAR_MATCH_GREATER_THAN_OR_EQUAL:
631                 snprintf(out_cond, sizeof(out_cond), "%s >= %lf", field_name, filter->value.d);
632                 break;
633         case CALENDAR_MATCH_LESS_THAN:
634                 snprintf(out_cond, sizeof(out_cond), "%s < %lf", field_name, filter->value.d);
635                 break;
636         case CALENDAR_MATCH_LESS_THAN_OR_EQUAL:
637                 snprintf(out_cond, sizeof(out_cond), "%s <= %lf", field_name, filter->value.d);
638                 break;
639         case CALENDAR_MATCH_NONE:
640                 snprintf(out_cond, sizeof(out_cond), "%s IS NULL", field_name);
641                 break;
642         case CALENDAR_MATCH_NOT_EQUAL:
643                 snprintf(out_cond, sizeof(out_cond), "%s <> %lf", field_name, filter->value.d);
644                 break;
645         default:
646                 /* LCOV_EXCL_START */
647                 ERR("Invalid parameter : int match rule(%d) is not supported", filter->match);
648                 return CALENDAR_ERROR_INVALID_PARAMETER;
649                 /* LCOV_EXCL_STOP */
650         }
651
652         *condition = strdup(out_cond);
653         return CALENDAR_ERROR_NONE;
654 }
655
656 static int _cal_db_query_create_lli_condition(cal_composite_filter_s *com_filter,
657                 cal_attribute_filter_s *filter, char **condition)
658 {
659         const char *field_name;
660         char out_cond[CAL_DB_SQL_MAX_LEN] = {0};
661
662         field_name = _cal_db_query_get_property_field_name(com_filter->properties,
663                         com_filter->property_count, filter->property_id);
664         RETVM_IF(NULL == field_name, CALENDAR_ERROR_INVALID_PARAMETER,
665                         "Invalid parameter : property id(%d)", filter->property_id);
666
667         switch (filter->match) {
668         case CALENDAR_MATCH_EQUAL:
669                 snprintf(out_cond, sizeof(out_cond), "%s = %lld", field_name, filter->value.lli);
670                 break;
671         case CALENDAR_MATCH_GREATER_THAN:
672                 snprintf(out_cond, sizeof(out_cond), "%s > %lld", field_name, filter->value.lli);
673                 break;
674         case CALENDAR_MATCH_GREATER_THAN_OR_EQUAL:
675                 snprintf(out_cond, sizeof(out_cond), "%s >= %lld", field_name, filter->value.lli);
676                 break;
677         case CALENDAR_MATCH_LESS_THAN:
678                 snprintf(out_cond, sizeof(out_cond), "%s < %lld", field_name, filter->value.lli);
679                 break;
680         case CALENDAR_MATCH_LESS_THAN_OR_EQUAL:
681                 snprintf(out_cond, sizeof(out_cond), "%s <= %lld", field_name, filter->value.lli);
682                 break;
683         case CALENDAR_MATCH_NONE:
684                 snprintf(out_cond, sizeof(out_cond), "%s IS NULL", field_name);
685                 break;
686         case CALENDAR_MATCH_NOT_EQUAL:
687                 snprintf(out_cond, sizeof(out_cond), "%s <> %lld", field_name, filter->value.lli);
688                 break;
689         default:
690                 /* LCOV_EXCL_START */
691                 ERR("Invalid parameter : int match rule(%d) is not supported", filter->match);
692                 return CALENDAR_ERROR_INVALID_PARAMETER;
693                 /* LCOV_EXCL_STOP */
694         }
695
696         *condition = strdup(out_cond);
697         return CALENDAR_ERROR_NONE;
698 }
699
700 static int _cal_db_query_create_caltime_condition(cal_composite_filter_s *com_filter,
701                 cal_attribute_filter_s *filter, char **condition)
702 {
703         const char *field_name;
704         char out_cond[CAL_DB_SQL_MAX_LEN] = {0};
705         const char *tmp = NULL;
706
707         field_name = _cal_db_query_get_property_field_name(com_filter->properties,
708                         com_filter->property_count, filter->property_id);
709         RETVM_IF(NULL == field_name, CALENDAR_ERROR_INVALID_PARAMETER,
710                         "Invalid parameter : property id(%d)", filter->property_id);
711
712         if (filter->value.caltime.type == CALENDAR_TIME_UTIME) {
713                 tmp = _cal_db_query_get_utime_field_name(field_name);
714                 if (NULL == tmp)
715                         tmp = field_name;
716
717                 switch (filter->match) {
718                 case CALENDAR_MATCH_EQUAL:
719                         snprintf(out_cond, sizeof(out_cond), "%s = %lld", tmp, filter->value.caltime.time.utime);
720                         break;
721                 case CALENDAR_MATCH_GREATER_THAN:
722                         snprintf(out_cond, sizeof(out_cond), "%s > %lld", tmp, filter->value.caltime.time.utime);
723                         break;
724                 case CALENDAR_MATCH_GREATER_THAN_OR_EQUAL:
725                         snprintf(out_cond, sizeof(out_cond), "%s >= %lld", tmp, filter->value.caltime.time.utime);
726                         break;
727                 case CALENDAR_MATCH_LESS_THAN:
728                         snprintf(out_cond, sizeof(out_cond), "%s < %lld", tmp, filter->value.caltime.time.utime);
729                         break;
730                 case CALENDAR_MATCH_LESS_THAN_OR_EQUAL:
731                         snprintf(out_cond, sizeof(out_cond), "%s <= %lld", tmp, filter->value.caltime.time.utime);
732                         break;
733                 case CALENDAR_MATCH_NONE:
734                         snprintf(out_cond, sizeof(out_cond), "%s IS NULL", tmp);
735                         break;
736                 case CALENDAR_MATCH_NOT_EQUAL:
737                         snprintf(out_cond, sizeof(out_cond), "%s <> %lld", tmp, filter->value.caltime.time.utime);
738                         break;
739                 default:
740                         /* LCOV_EXCL_START */
741                         ERR("Invalid parameter : int match rule(%d) is not supported", filter->match);
742                         return CALENDAR_ERROR_INVALID_PARAMETER;
743                         /* LCOV_EXCL_STOP */
744                 }
745         } else if (filter->value.caltime.type == CALENDAR_TIME_LOCALTIME) {
746                 char sdate[CAL_STR_SHORT_LEN32] = {0};
747                 snprintf(sdate, sizeof(sdate), CAL_FORMAT_LOCAL_DATETIME,
748                                 filter->value.caltime.time.date.year, filter->value.caltime.time.date.month, filter->value.caltime.time.date.mday,
749                                 filter->value.caltime.time.date.hour, filter->value.caltime.time.date.minute, filter->value.caltime.time.date.second);
750                 tmp = _cal_db_query_get_datetime_field_name(field_name);
751                 if (NULL == tmp)
752                         tmp = field_name;
753
754                 switch (filter->match) {
755                 case CALENDAR_MATCH_EQUAL:
756                         snprintf(out_cond, sizeof(out_cond), "%s = '%s'", tmp, sdate);
757                         break;
758                 case CALENDAR_MATCH_GREATER_THAN:
759                         snprintf(out_cond, sizeof(out_cond), "%s > '%s'", tmp, sdate);
760                         break;
761                 case CALENDAR_MATCH_GREATER_THAN_OR_EQUAL:
762                         snprintf(out_cond, sizeof(out_cond), "%s >= '%s'", tmp, sdate);
763                         break;
764                 case CALENDAR_MATCH_LESS_THAN:
765                         snprintf(out_cond, sizeof(out_cond), "%s < '%s'", tmp, sdate);
766                         break;
767                 case CALENDAR_MATCH_LESS_THAN_OR_EQUAL:
768                         snprintf(out_cond, sizeof(out_cond), "%s <= '%s'", tmp, sdate);
769                         break;
770                 case CALENDAR_MATCH_NOT_EQUAL:
771                         snprintf(out_cond, sizeof(out_cond), "%s <> '%s'", tmp, sdate);
772                         break;
773                 case CALENDAR_MATCH_NONE:
774                 default:
775                         /* LCOV_EXCL_START */
776                         ERR("Invalid parameter : int match rule(%d) is not supported", filter->match);
777                         return CALENDAR_ERROR_INVALID_PARAMETER;
778                         /* LCOV_EXCL_STOP */
779                 }
780         } else {
781                 /* LCOV_EXCL_START */
782                 ERR("Invalid parameter : property id(%d)", filter->property_id);
783                 return CALENDAR_ERROR_INVALID_PARAMETER;
784                 /* LCOV_EXCL_STOP */
785         }
786
787         cal_record_type_e record_type = cal_view_get_type(com_filter->view_uri);
788         if (record_type != CAL_RECORD_TYPE_INSTANCE_UTIME &&
789                         record_type != CAL_RECORD_TYPE_INSTANCE_LOCALTIME &&
790                         record_type != CAL_RECORD_TYPE_INSTANCE_UTIME_EXTENDED &&
791                         record_type != CAL_RECORD_TYPE_INSTANCE_LOCALTIME_EXTENDED) {
792                 int len = strlen(out_cond);
793                 const char *type_field = _cal_db_query_get_timetype_field_name(field_name);
794                 snprintf(out_cond + len, sizeof(out_cond) - len -1, " AND %s = %d ", type_field, filter->value.caltime.type);
795         }
796
797         *condition = strdup(out_cond);
798         return CALENDAR_ERROR_NONE;
799 }
800
801 static char * _cal_db_get_str_with_escape(char *str, int len, bool with_escape)
802 {
803         int i, j = 0;
804         char temp_str[len*2+1];
805
806         if (false == with_escape)
807                 return strdup(str);
808
809         for (i = 0; i < len; i++) {
810                 if (str[i] == '\'' || str[i] == '_' || str[i] == '%' || str[i] == '\\')
811                         temp_str[j++] = CAL_DB_ESCAPE_CHAR;
812
813                 temp_str[j++] = str[i];
814         }
815         temp_str[j] = '\0';
816
817         return strdup(temp_str);
818 }
819
820 static int _cal_db_query_create_str_condition(cal_composite_filter_s *com_filter,
821                 cal_attribute_filter_s *filter, char **condition, GSList **bind_text)
822 {
823         const char *field_name;
824         char out_cond[CAL_DB_SQL_MAX_LEN] = {0};
825         bool with_escape = true;
826
827         field_name = _cal_db_query_get_property_field_name(com_filter->properties,
828                         com_filter->property_count, filter->property_id);
829         RETVM_IF(NULL == field_name, CALENDAR_ERROR_INVALID_PARAMETER,
830                         "Invalid parameter : property id(%d)", filter->property_id);
831
832         switch (filter->match) {
833         case CALENDAR_MATCH_EXACTLY:
834                 snprintf(out_cond, sizeof(out_cond), "%s = ?", field_name);
835                 with_escape = false;
836                 break;
837         case CALENDAR_MATCH_FULLSTRING:
838                 snprintf(out_cond, sizeof(out_cond), "%s LIKE ? ESCAPE '%c'", field_name, CAL_DB_ESCAPE_CHAR);
839                 break;
840         case CALENDAR_MATCH_CONTAINS:
841                 snprintf(out_cond, sizeof(out_cond), "%s LIKE ('%%' || ? || '%%') ESCAPE '%c'", field_name, CAL_DB_ESCAPE_CHAR);
842                 break;
843         case CALENDAR_MATCH_STARTSWITH:
844                 snprintf(out_cond, sizeof(out_cond), "%s LIKE (? || '%%') ESCAPE '%c'", field_name, CAL_DB_ESCAPE_CHAR);
845                 break;
846         case CALENDAR_MATCH_ENDSWITH:
847                 snprintf(out_cond, sizeof(out_cond), "%s LIKE ('%%' || ?) ESCAPE '%c'", field_name, CAL_DB_ESCAPE_CHAR);
848                 break;
849         case CALENDAR_MATCH_EXISTS:
850                 snprintf(out_cond, sizeof(out_cond), "%s IS NOT NULL", field_name);
851                 break;
852         default:
853                 /* LCOV_EXCL_START */
854                 ERR("Invalid paramter : int match rule (%d) is not supported", filter->match);
855                 return CALENDAR_ERROR_INVALID_PARAMETER;
856                 /* LCOV_EXCL_STOP */
857         }
858
859         if (filter->value.s) {
860                 *bind_text = g_slist_append(*bind_text,
861                                 _cal_db_get_str_with_escape(filter->value.s, strlen(filter->value.s), with_escape));
862         }
863         *condition = strdup(out_cond);
864         return CALENDAR_ERROR_NONE;
865 }
866
867 static const char * _cal_db_query_get_property_field_name(const cal_property_info_s *properties,
868                 int count, unsigned int property_id)
869 {
870         int i;
871         for (i = 0; i < count; i++) {
872                 cal_property_info_s *p = (cal_property_info_s*)&(properties[i]);
873                 if (property_id == p->property_id) {
874                         if (p->fields)
875                                 return p->fields;
876                         else
877                                 return NULL;
878                 }
879         }
880         return NULL;
881 }
882
883 static const char * _cal_db_query_get_utime_field_name(const char* src)
884 {
885         char *tmp1 = NULL;
886         int i = 0;
887
888         for (i = 0; i < CAL_DB_CALTIME_FIELD_MAX; i++) {
889                 tmp1 = strstr(src, _cal_db_utime_field_name[i]);
890                 if (tmp1)
891                         return _cal_db_utime_field_name[i];
892         }
893
894         return NULL;
895 }
896
897 static const char * _cal_db_query_get_datetime_field_name(const char* src)
898 {
899         char *tmp1 = NULL;
900         int i = 0;
901
902         for (i = 0; i < CAL_DB_CALTIME_FIELD_MAX; i++) {
903                 tmp1 = strstr(src, _cal_db_datetime_field_name[i]);
904                 if (tmp1)
905                         return _cal_db_datetime_field_name[i];
906         }
907
908         return NULL;
909 }
910
911 static const char * _cal_db_query_get_timetype_field_name(const char* src)
912 {
913         char *tmp1 = NULL;
914         int i = 0;
915
916         for (i = 0; i < CAL_DB_CALTIME_FIELD_MAX; i++) {
917                 tmp1 = strstr(src, _cal_db_timetype_field_name[i]);
918                 if (tmp1)
919                         return _cal_db_timetype_field_name[i];
920         }
921
922         return NULL;
923 }
924