modify terminology:calendar->book,allday->localtime,normal->utime,svc->service
[platform/core/pim/calendar-service.git] / server / db / cal_db_plugin_search.c
1 /*
2  * Calendar Service
3  *
4  * Copyright (c) 2012 - 2015 Samsung Electronics Co., Ltd. All rights reserved.
5  *
6  * Licensed under the Apache License, Version 2.0 (the "License");
7  * you may not use this file except in compliance with the License.
8  * You may obtain a copy of the License at
9  *
10  * http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing, software
13  * distributed under the License is distributed on an "AS IS" BASIS,
14  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  * See the License for the specific language governing permissions and
16  * limitations under the License.
17  *
18  */
19 #include <stdlib.h>
20
21 #include "cal_internal.h"
22 #include "cal_typedef.h"
23 #include "cal_view.h"
24 #include "cal_record.h"
25
26 #include "cal_db.h"
27 #include "cal_db_util.h"
28 #include "cal_db_query.h"
29 #include "cal_access_control.h"
30 #include "cal_utils.h"
31
32 /*
33  * db plugin function
34  */
35 static int _cal_db_search_get_records_with_query(calendar_query_h query, int offset, int limit, calendar_list_h* out_list);
36 static int _cal_db_search_get_count_with_query(calendar_query_h query, int *out_count);
37
38 /*
39  * static function
40  */
41 static void _cal_db_search_get_stmt(sqlite3_stmt *stmt, calendar_query_h query, calendar_record_h record);
42 static void _cal_db_search_get_property_stmt(sqlite3_stmt *stmt, unsigned int property, int *stmt_count, calendar_record_h record);
43 static void _cal_db_search_get_projection_stmt(sqlite3_stmt *stmt, const unsigned int *projection, const int projection_count, calendar_record_h record);
44 static int _cal_db_search_make_projection(calendar_query_h query, char **projection);
45
46 cal_db_plugin_cb_s cal_db_search_plugin_cb = {
47         .is_query_only = true,
48         .insert_record = NULL,
49         .get_record = NULL,
50         .update_record = NULL,
51         .delete_record = NULL,
52         .get_all_records = NULL,
53         .get_records_with_query = _cal_db_search_get_records_with_query,
54         .insert_records = NULL,
55         .update_records = NULL,
56         .delete_records = NULL,
57         .get_count = NULL,
58         .get_count_with_query = _cal_db_search_get_count_with_query,
59         .replace_record = NULL,
60         .replace_records = NULL
61 };
62
63 static int _cal_db_search_get_records_with_query(calendar_query_h query, int offset, int limit, calendar_list_h* out_list)
64 {
65         cal_query_s *que = NULL;
66         int ret = CALENDAR_ERROR_NONE;
67         char *condition = NULL;
68         char *projection = NULL;
69         GSList *bind_text = NULL, *cursor = NULL;
70         sqlite3_stmt *stmt = NULL;
71         int i = 0;
72         char *table_name = NULL;
73
74         que = (cal_query_s *)query;
75
76         /* make filter */
77         if (que->filter) {
78                 ret = cal_db_query_create_condition(query,
79                                 &condition, &bind_text);
80                 if (CALENDAR_ERROR_NONE != ret) {
81                         /* LCOV_EXCL_START */
82                         ERR("cal_db_query_create_condition() Fail(%d), ret");
83                         return ret;
84                         /* LCOV_EXCL_STOP */
85                 }
86         }
87
88         /* make: projection */
89         if (0 < que->projection_count)
90                 ret = cal_db_query_create_projection(query, &projection);
91         else
92                 _cal_db_search_make_projection(query, &projection);
93
94         /* query - projection */
95         if (CAL_STRING_EQUAL == strcmp(que->view_uri, CALENDAR_VIEW_EVENT_BOOK)) {
96                 table_name = strdup(CAL_VIEW_TABLE_EVENT_BOOK);
97         } else if (CAL_STRING_EQUAL == strcmp(que->view_uri, CALENDAR_VIEW_TODO_BOOK)) {
98                 table_name = strdup(CAL_VIEW_TABLE_TODO_BOOK);
99         } else if (CAL_STRING_EQUAL == strcmp(que->view_uri, CALENDAR_VIEW_EVENT_BOOK_ATTENDEE)) {
100                 table_name = strdup(CAL_VIEW_TABLE_EVENT_BOOK_ATTENDEE);
101         } else if (CAL_STRING_EQUAL == strcmp(que->view_uri, CALENDAR_VIEW_INSTANCE_UTIME_BOOK)) {
102                 table_name = strdup(CAL_VIEW_TABLE_UTIME_INSTANCE);
103         } else if (CAL_STRING_EQUAL == strcmp(que->view_uri, CALENDAR_VIEW_INSTANCE_UTIME_BOOK_EXTENDED)) {
104                 table_name = strdup(CAL_VIEW_TABLE_UTIME_INSTANCE_EXTENDED);
105         } else if (CAL_STRING_EQUAL == strcmp(que->view_uri, CALENDAR_VIEW_INSTANCE_LOCALTIME_BOOK)) {
106                 table_name = strdup(CAL_VIEW_TABLE_LOCALTIME_INSTANCE);
107         } else if (CAL_STRING_EQUAL == strcmp(que->view_uri, CALENDAR_VIEW_INSTANCE_LOCALTIME_BOOK_EXTENDED)) {
108                 table_name = strdup(CAL_VIEW_TABLE_LOCALTIME_INSTANCE_EXTENDED);
109         } else {
110                 /* LCOV_EXCL_START */
111                 ERR("uri(%s) not support get records with query", que->view_uri);
112                 CAL_FREE(projection);
113                 CAL_FREE(condition);
114                 return CALENDAR_ERROR_INVALID_PARAMETER;
115                 /* LCOV_EXCL_STOP */
116         }
117
118         char *query_str = NULL;
119         if (que->distinct == true) {
120                 cal_db_append_string(&query_str, "SELECT DISTINCT");
121                 cal_db_append_string(&query_str, projection);
122                 cal_db_append_string(&query_str, "FROM");
123                 cal_db_append_string(&query_str, table_name);
124         } else {
125                 cal_db_append_string(&query_str, "SELECT");
126                 cal_db_append_string(&query_str, projection);
127                 cal_db_append_string(&query_str, "FROM");
128                 cal_db_append_string(&query_str, table_name);
129         }
130         CAL_FREE(projection);
131         CAL_FREE(table_name);
132
133         /* query: condition */
134         if (condition) {
135                 cal_db_append_string(&query_str, "WHERE (");
136                 cal_db_append_string(&query_str, condition);
137                 cal_db_append_string(&query_str, ")");
138         }
139
140         /* order */
141         char *order = NULL;
142         ret = cal_db_query_create_order(query, condition, &order);
143         if (order) {
144                 cal_db_append_string(&query_str, order);
145                 CAL_FREE(order);
146         }
147         CAL_FREE(condition);
148
149         /* limit, offset */
150         char buf[CAL_STR_SHORT_LEN32] = {0};
151         if (0 < limit) {
152                 snprintf(buf, sizeof(buf), "LIMIT %d", limit);
153                 cal_db_append_string(&query_str, buf);
154
155                 if (0 < offset) {
156                         snprintf(buf, sizeof(buf), "OFFSET %d", offset);
157                         cal_db_append_string(&query_str, buf);
158                 }
159         }
160
161         /* query */
162         ret = cal_db_util_query_prepare(query_str, &stmt);
163         if (CALENDAR_ERROR_NONE != ret) {
164                 /* LCOV_EXCL_START */
165                 ERR("cal_db_util_query_prepare() Fail(%d)", ret);
166                 SECURE("query[%s]", query_str);
167                 if (bind_text) {
168                         g_slist_free_full(bind_text, free);
169                         bind_text = NULL;
170                 }
171                 free(query_str);
172                 return ret;
173                 /* LCOV_EXCL_STOP */
174         }
175
176         /* bind text */
177         if (bind_text) {
178                 g_slist_length(bind_text);
179                 for (cursor = bind_text, i = 1; cursor; cursor = cursor->next, i++)
180                         cal_db_util_stmt_bind_text(stmt, i, cursor->data);
181         }
182
183         ret = calendar_list_create(out_list);
184         if (CALENDAR_ERROR_NONE != ret) {
185                 /* LCOV_EXCL_START */
186                 ERR("calendar_list_create() Fail");
187                 if (bind_text) {
188                         g_slist_free_full(bind_text, free);
189                         bind_text = NULL;
190                 }
191                 sqlite3_finalize(stmt);
192                 CAL_FREE(query_str);
193                 return ret;
194                 /* LCOV_EXCL_STOP */
195         }
196
197         while (CAL_SQLITE_ROW == cal_db_util_stmt_step(stmt)) {
198                 calendar_record_h record;
199                 ret = calendar_record_create(que->view_uri, &record);
200                 if (CALENDAR_ERROR_NONE != ret) {
201                         /* LCOV_EXCL_START */
202                         calendar_list_destroy(*out_list, true);
203                         *out_list = NULL;
204
205                         if (bind_text) {
206                                 g_slist_free_full(bind_text, free);
207                                 bind_text = NULL;
208                         }
209                         sqlite3_finalize(stmt);
210                         CAL_FREE(query_str);
211                         return ret;
212                         /* LCOV_EXCL_STOP */
213                 }
214                 if (0 < que->projection_count) {
215                         _cal_db_search_get_projection_stmt(stmt, que->projection, que->projection_count,
216                                         record);
217                 } else {
218                         _cal_db_search_get_stmt(stmt, query, record);
219                 }
220
221                 ret = calendar_list_add(*out_list, record);
222                 if (CALENDAR_ERROR_NONE != ret) {
223                         /* LCOV_EXCL_START */
224                         calendar_list_destroy(*out_list, true);
225                         *out_list = NULL;
226                         calendar_record_destroy(record, true);
227
228                         if (bind_text) {
229                                 g_slist_free_full(bind_text, free);
230                                 bind_text = NULL;
231                         }
232                         sqlite3_finalize(stmt);
233                         CAL_FREE(query_str);
234                         return ret;
235                         /* LCOV_EXCL_STOP */
236                 }
237         }
238
239         if (bind_text) {
240                 g_slist_free_full(bind_text, free);
241                 bind_text = NULL;
242         }
243         sqlite3_finalize(stmt);
244         CAL_FREE(query_str);
245
246         return CALENDAR_ERROR_NONE;
247 }
248
249 static int _cal_db_search_get_count_with_query(calendar_query_h query, int *out_count)
250 {
251         cal_query_s *que = NULL;
252         int ret = CALENDAR_ERROR_NONE;
253         char *condition = NULL;
254         char *projection = NULL;
255         char *table_name;
256         int count = 0;
257         GSList *bind_text = NULL;
258
259         que = (cal_query_s *)query;
260
261         if (CAL_STRING_EQUAL == strcmp(que->view_uri, CALENDAR_VIEW_EVENT_BOOK)) {
262                 table_name = cal_strdup(CAL_VIEW_TABLE_EVENT_BOOK);
263                 projection = cal_strdup("id");
264         } else if (CAL_STRING_EQUAL == strcmp(que->view_uri, CALENDAR_VIEW_TODO_BOOK)) {
265                 table_name = cal_strdup(CAL_VIEW_TABLE_TODO_BOOK);
266                 projection = cal_strdup("id");
267         } else if (CAL_STRING_EQUAL == strcmp(que->view_uri, CALENDAR_VIEW_EVENT_BOOK_ATTENDEE)) {
268                 table_name = cal_strdup(CAL_VIEW_TABLE_EVENT_BOOK_ATTENDEE);
269                 projection = cal_strdup("id");
270         } else if (CAL_STRING_EQUAL == strcmp(que->view_uri, CALENDAR_VIEW_INSTANCE_UTIME_BOOK)) {
271                 table_name = cal_strdup(CAL_VIEW_TABLE_UTIME_INSTANCE);
272                 projection = cal_strdup("event_id");
273         } else if (CAL_STRING_EQUAL == strcmp(que->view_uri, CALENDAR_VIEW_INSTANCE_LOCALTIME_BOOK)) {
274                 table_name = cal_strdup(CAL_VIEW_TABLE_LOCALTIME_INSTANCE);
275                 projection = cal_strdup("event_id");
276         } else {
277                 /* LCOV_EXCL_START */
278                 ERR("uri(%s) not support get records with query", que->view_uri);
279                 return CALENDAR_ERROR_INVALID_PARAMETER;
280                 /* LCOV_EXCL_STOP */
281         }
282
283         /* make filter */
284         if (que->filter) {
285                 ret = cal_db_query_create_condition(query, &condition, &bind_text);
286                 if (CALENDAR_ERROR_NONE != ret) {
287                         /* LCOV_EXCL_START */
288                         ERR("cal_db_query_create_condition() Fail(%d), ret");
289                         CAL_FREE(table_name);
290                         CAL_FREE(projection);
291                         return ret;
292                         /* LCOV_EXCL_STOP */
293                 }
294         }
295
296         char *query_str = NULL;
297
298         /* query: select */
299         if (que->distinct == true) {
300                 cal_db_append_string(&query_str, "SELECT count(DISTINCT");
301                 cal_db_append_string(&query_str, projection);
302                 cal_db_append_string(&query_str, ") FROM");
303                 cal_db_append_string(&query_str, table_name);
304         } else {
305                 cal_db_append_string(&query_str, "SELECT count(*) FROM");
306                 cal_db_append_string(&query_str, table_name);
307         }
308         CAL_FREE(projection);
309         CAL_FREE(table_name);
310
311         /* query: condition */
312         if (condition) {
313                 cal_db_append_string(&query_str, "WHERE (");
314                 cal_db_append_string(&query_str, condition);
315                 cal_db_append_string(&query_str, ")");
316                 CAL_FREE(condition);
317         }
318
319         /* query */
320         ret = cal_db_util_query_get_first_int_result(query_str, bind_text, &count);
321         if (CALENDAR_ERROR_NONE != ret) {
322                 /* LCOV_EXCL_START */
323                 ERR("cal_db_util_query_get_first_int_result() Failed");
324                 if (bind_text) {
325                         g_slist_free_full(bind_text, free);
326                         bind_text = NULL;
327                 }
328
329                 CAL_FREE(query_str);
330                 return ret;
331                 /* LCOV_EXCL_STOP */
332         }
333         DBG("count(%d) str[%s]", count, query_str);
334
335         if (out_count) *out_count = count;
336         if (bind_text) {
337                 g_slist_free_full(bind_text, free);
338                 bind_text = NULL;
339         }
340
341         CAL_FREE(query_str);
342         return CALENDAR_ERROR_NONE;
343 }
344
345 static void _cal_db_search_get_stmt(sqlite3_stmt *stmt, calendar_query_h query,
346                 calendar_record_h record)
347 {
348         int i = 0;
349         int stmt_count = 0;
350         cal_query_s *query_s = NULL;
351         cal_property_info_s *properties = NULL;
352
353         query_s = (cal_query_s *)query;
354
355         for (i = 0; i < query_s->property_count; i++) {
356                 properties = &(query_s->properties[i]);
357
358                 if (CAL_PROPERTY_CHECK_FLAGS(properties->property_id, CAL_PROPERTY_FLAGS_FILTER) == true)
359                         break;
360
361                 _cal_db_search_get_property_stmt(stmt, properties->property_id, &stmt_count, record);
362         }
363         return ;
364 }
365
366 static void _cal_db_search_get_property_stmt(sqlite3_stmt *stmt,
367                 unsigned int property, int *stmt_count, calendar_record_h record)
368 {
369         int ret = 0;
370         const unsigned char *temp;
371         int int_tmp = 0;
372         double d_tmp = 0;
373         long long int lli_tmp = 0;
374
375         if (CAL_PROPERTY_CHECK_DATA_TYPE(property, CAL_PROPERTY_DATA_TYPE_INT) == true) {
376                 int_tmp = sqlite3_column_int(stmt, *stmt_count);
377                 cal_record_set_int(record, property, int_tmp);
378         } else if (CAL_PROPERTY_CHECK_DATA_TYPE(property, CAL_PROPERTY_DATA_TYPE_STR) == true) {
379                 temp = sqlite3_column_text(stmt, *stmt_count);
380                 cal_record_set_str(record, property, (const char*)temp);
381         } else if (CAL_PROPERTY_CHECK_DATA_TYPE(property, CAL_PROPERTY_DATA_TYPE_DOUBLE) == true) {
382                 d_tmp = sqlite3_column_double(stmt, *stmt_count);
383                 cal_record_set_double(record, property, d_tmp);
384         } else if (CAL_PROPERTY_CHECK_DATA_TYPE(property, CAL_PROPERTY_DATA_TYPE_LLI) == true) {
385                 lli_tmp = sqlite3_column_int64(stmt, *stmt_count);
386                 cal_record_set_lli(record, property, lli_tmp);
387         } else if (CAL_PROPERTY_CHECK_DATA_TYPE(property, CAL_PROPERTY_DATA_TYPE_CALTIME) == true) {
388                 calendar_time_s caltime_tmp;
389                 caltime_tmp.type = sqlite3_column_int(stmt, *stmt_count);
390                 switch (caltime_tmp.type) {
391                 case CALENDAR_TIME_UTIME:
392                         *stmt_count = *stmt_count+1;
393                         caltime_tmp.time.utime = sqlite3_column_int64(stmt, *stmt_count);
394                         *stmt_count = *stmt_count+1; /* datatime */
395                         break;
396
397                 case CALENDAR_TIME_LOCALTIME:
398                         *stmt_count = *stmt_count+1; /* utime */
399                         *stmt_count = *stmt_count+1;
400                         temp = sqlite3_column_text(stmt, *stmt_count);
401                         if (temp) {
402                                 sscanf((const char *)temp, CAL_FORMAT_LOCAL_DATETIME, &(caltime_tmp.time.date.year),
403                                                 &(caltime_tmp.time.date.month), &(caltime_tmp.time.date.mday),
404                                                 &(caltime_tmp.time.date.hour), &(caltime_tmp.time.date.minute),
405                                                 &(caltime_tmp.time.date.second));
406                         }
407                         break;
408                 }
409                 ret = cal_record_set_caltime(record, property, caltime_tmp);
410                 WARN_IF(CALENDAR_ERROR_NONE != ret, "Failed to cal_record_set_caltime()");
411         } else {
412                 sqlite3_column_int(stmt, *stmt_count);
413         }
414
415         *stmt_count = *stmt_count+1;
416 }
417 static void _cal_db_search_get_projection_stmt(sqlite3_stmt *stmt,
418                 const unsigned int *projection, const int projection_count,
419                 calendar_record_h record)
420 {
421         int i = 0;
422         int stmt_count = 0;
423
424         for (i = 0; i < projection_count; i++)
425                 _cal_db_search_get_property_stmt(stmt, projection[i], &stmt_count, record);
426 }
427
428 static int _cal_db_search_make_projection(calendar_query_h query, char **projection)
429 {
430         int i = 0;
431         int len = 0;
432         const char *field_name;
433         char out_projection[CAL_DB_SQL_MAX_LEN] = {0};
434         cal_query_s *query_s = NULL;
435         cal_property_info_s *properties = NULL;
436
437         RETV_IF(NULL == query, CALENDAR_ERROR_INVALID_PARAMETER);
438         query_s = (cal_query_s *)query;
439
440         properties = &(query_s->properties[0]);
441         field_name = properties->fields;
442         if (field_name)
443                 len += snprintf(out_projection+len, sizeof(out_projection)-len, "%s", field_name);
444
445         if (sizeof(out_projection) <= len) {
446                 /* LCOV_EXCL_START */
447                 ERR("buf len max");
448                 return CALENDAR_ERROR_SYSTEM;
449                 /* LCOV_EXCL_STOP */
450         }
451
452         for (i = 1; i < query_s->property_count; i++) {
453                 properties = &(query_s->properties[i]);
454                 field_name = properties->fields;
455
456                 if (CAL_PROPERTY_CHECK_FLAGS(properties->property_id, CAL_PROPERTY_FLAGS_FILTER) == true)
457                         break;
458
459                 if (field_name) {
460                         len += snprintf(out_projection+len, sizeof(out_projection)-len, ", %s", field_name);
461                         if (sizeof(out_projection) <= len) {
462                                 /* LCOV_EXCL_START */
463                                 ERR("buf len max");
464                                 return CALENDAR_ERROR_SYSTEM;
465                                 /* LCOV_EXCL_STOP */
466                         }
467                 }
468         }
469
470         *projection = g_strdup(out_projection);
471
472         return CALENDAR_ERROR_NONE;
473 }