eb0656c5157d6ad421319daa89d1eec9cf898af2
[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                         ERR("cal_db_query_create_condition() Fail(%d), ret");
82                         return ret;
83                 }
84         }
85
86         /* make: projection */
87         if (0 < que->projection_count)
88                 ret = cal_db_query_create_projection(query, &projection);
89         else
90                 _cal_db_search_make_projection(query, &projection);
91
92         /* query - projection */
93         if (CAL_STRING_EQUAL == strcmp(que->view_uri, CALENDAR_VIEW_EVENT_CALENDAR)) {
94                 table_name = strdup(CAL_VIEW_TABLE_EVENT_CALENDAR);
95         } else if (CAL_STRING_EQUAL == strcmp(que->view_uri, CALENDAR_VIEW_TODO_CALENDAR)) {
96                 table_name = strdup(CAL_VIEW_TABLE_TODO_CALENDAR);
97         } else if (CAL_STRING_EQUAL == strcmp(que->view_uri, CALENDAR_VIEW_EVENT_CALENDAR_ATTENDEE)) {
98                 table_name = strdup(CAL_VIEW_TABLE_EVENT_CALENDAR_ATTENDEE);
99         } else if (CAL_STRING_EQUAL == strcmp(que->view_uri, CALENDAR_VIEW_INSTANCE_UTIME_CALENDAR)) {
100                 table_name = strdup(CAL_VIEW_TABLE_NORMAL_INSTANCE);
101         } else if (CAL_STRING_EQUAL == strcmp(que->view_uri, CALENDAR_VIEW_INSTANCE_UTIME_CALENDAR_EXTENDED)) {
102                 table_name = strdup(CAL_VIEW_TABLE_NORMAL_INSTANCE_EXTENDED);
103         } else if (CAL_STRING_EQUAL == strcmp(que->view_uri, CALENDAR_VIEW_INSTANCE_LOCALTIME_CALENDAR)) {
104                 table_name = strdup(CAL_VIEW_TABLE_ALLDAY_INSTANCE);
105         } else if (CAL_STRING_EQUAL == strcmp(que->view_uri, CALENDAR_VIEW_INSTANCE_LOCALTIME_CALENDAR_EXTENDED)) {
106                 table_name = strdup(CAL_VIEW_TABLE_ALLDAY_INSTANCE_EXTENDED);
107         } else {
108                 ERR("uri(%s) not support get records with query", que->view_uri);
109                 CAL_FREE(projection);
110                 CAL_FREE(condition);
111                 return CALENDAR_ERROR_INVALID_PARAMETER;
112         }
113
114         char *query_str = NULL;
115         if (que->distinct == true) {
116                 cal_db_append_string(&query_str, "SELECT DISTINCT");
117                 cal_db_append_string(&query_str, projection);
118                 cal_db_append_string(&query_str, "FROM");
119                 cal_db_append_string(&query_str, table_name);
120         } else {
121                 cal_db_append_string(&query_str, "SELECT");
122                 cal_db_append_string(&query_str, projection);
123                 cal_db_append_string(&query_str, "FROM");
124                 cal_db_append_string(&query_str, table_name);
125         }
126         CAL_FREE(projection);
127         CAL_FREE(table_name);
128
129         /* query: condition */
130         if (condition) {
131                 cal_db_append_string(&query_str, "WHERE (");
132                 cal_db_append_string(&query_str, condition);
133                 cal_db_append_string(&query_str, ")");
134         }
135
136         /* order */
137         char *order = NULL;
138         ret = cal_db_query_create_order(query, condition, &order);
139         if (order) {
140                 cal_db_append_string(&query_str, order);
141                 CAL_FREE(order);
142         }
143         CAL_FREE(condition);
144
145         /* limit, offset */
146         char buf[CAL_STR_SHORT_LEN32] = {0};
147         if (0 < limit) {
148                 snprintf(buf, sizeof(buf), "LIMIT %d", limit);
149                 cal_db_append_string(&query_str, buf);
150
151                 if (0 < offset) {
152                         snprintf(buf, sizeof(buf), "OFFSET %d", offset);
153                         cal_db_append_string(&query_str, buf);
154                 }
155         }
156
157         /* query */
158         ret = cal_db_util_query_prepare(query_str, &stmt);
159         if (CALENDAR_ERROR_NONE != ret) {
160                 ERR("cal_db_util_query_prepare() Fail(%d)", ret);
161                 SECURE("query[%s]", query_str);
162                 if (bind_text) {
163                         g_slist_free_full(bind_text, free);
164                         bind_text = NULL;
165                 }
166                 free(query_str);
167                 return ret;
168         }
169
170         /* bind text */
171         if (bind_text) {
172                 g_slist_length(bind_text);
173                 for (cursor = bind_text, i = 1; cursor; cursor = cursor->next, i++)
174                         cal_db_util_stmt_bind_text(stmt, i, cursor->data);
175         }
176
177         ret = calendar_list_create(out_list);
178         if (CALENDAR_ERROR_NONE != ret) {
179                 if (bind_text) {
180                         g_slist_free_full(bind_text, free);
181                         bind_text = NULL;
182                 }
183                 ERR("calendar_list_create() Fail");
184                 sqlite3_finalize(stmt);
185                 CAL_FREE(query_str);
186                 return ret;
187         }
188
189         while (CAL_SQLITE_ROW == cal_db_util_stmt_step(stmt)) {
190                 calendar_record_h record;
191                 ret = calendar_record_create(que->view_uri, &record);
192                 if (CALENDAR_ERROR_NONE != ret) {
193                         calendar_list_destroy(*out_list, true);
194                         *out_list = NULL;
195
196                         if (bind_text) {
197                                 g_slist_free_full(bind_text, free);
198                                 bind_text = NULL;
199                         }
200                         sqlite3_finalize(stmt);
201                         CAL_FREE(query_str);
202                         return ret;
203                 }
204                 if (0 < que->projection_count) {
205                         _cal_db_search_get_projection_stmt(stmt, que->projection, que->projection_count,
206                                         record);
207                 } else {
208                         _cal_db_search_get_stmt(stmt, query, record);
209                 }
210
211                 ret = calendar_list_add(*out_list, record);
212                 if (CALENDAR_ERROR_NONE != ret) {
213                         calendar_list_destroy(*out_list, true);
214                         *out_list = NULL;
215                         calendar_record_destroy(record, true);
216
217                         if (bind_text) {
218                                 g_slist_free_full(bind_text, free);
219                                 bind_text = NULL;
220                         }
221                         sqlite3_finalize(stmt);
222                         CAL_FREE(query_str);
223                         return ret;
224                 }
225         }
226
227         if (bind_text) {
228                 g_slist_free_full(bind_text, free);
229                 bind_text = NULL;
230         }
231         sqlite3_finalize(stmt);
232         CAL_FREE(query_str);
233
234         return CALENDAR_ERROR_NONE;
235 }
236
237 static int _cal_db_search_get_count_with_query(calendar_query_h query, int *out_count)
238 {
239         cal_query_s *que = NULL;
240         int ret = CALENDAR_ERROR_NONE;
241         char *condition = NULL;
242         char *projection = NULL;
243         char *table_name;
244         int count = 0;
245         GSList *bind_text = NULL;
246
247         que = (cal_query_s *)query;
248
249         if (CAL_STRING_EQUAL == strcmp(que->view_uri, CALENDAR_VIEW_EVENT_CALENDAR)) {
250                 table_name = cal_strdup(CAL_VIEW_TABLE_EVENT_CALENDAR);
251                 projection = cal_strdup("id");
252         } else if (CAL_STRING_EQUAL == strcmp(que->view_uri, CALENDAR_VIEW_TODO_CALENDAR)) {
253                 table_name = cal_strdup(CAL_VIEW_TABLE_TODO_CALENDAR);
254                 projection = cal_strdup("id");
255         } else if (CAL_STRING_EQUAL == strcmp(que->view_uri, CALENDAR_VIEW_EVENT_CALENDAR_ATTENDEE)) {
256                 table_name = cal_strdup(CAL_VIEW_TABLE_EVENT_CALENDAR_ATTENDEE);
257                 projection = cal_strdup("id");
258         } else if (CAL_STRING_EQUAL == strcmp(que->view_uri, CALENDAR_VIEW_INSTANCE_UTIME_CALENDAR)) {
259                 table_name = cal_strdup(CAL_VIEW_TABLE_NORMAL_INSTANCE);
260                 projection = cal_strdup("event_id");
261         } else if (CAL_STRING_EQUAL == strcmp(que->view_uri, CALENDAR_VIEW_INSTANCE_LOCALTIME_CALENDAR)) {
262                 table_name = cal_strdup(CAL_VIEW_TABLE_ALLDAY_INSTANCE);
263                 projection = cal_strdup("event_id");
264         } else {
265                 ERR("uri(%s) not support get records with query", que->view_uri);
266                 return CALENDAR_ERROR_INVALID_PARAMETER;
267         }
268
269         /* make filter */
270         if (que->filter) {
271                 ret = cal_db_query_create_condition(query, &condition, &bind_text);
272                 if (CALENDAR_ERROR_NONE != ret) {
273                         CAL_FREE(table_name);
274                         ERR("cal_db_query_create_condition() Fail(%d), ret");
275                         CAL_FREE(projection);
276                         return ret;
277                 }
278         }
279
280         char *query_str = NULL;
281
282         /* query: select */
283         if (que->distinct == true) {
284                 cal_db_append_string(&query_str, "SELECT count(DISTINCT");
285                 cal_db_append_string(&query_str, projection);
286                 cal_db_append_string(&query_str, ") FROM");
287                 cal_db_append_string(&query_str, table_name);
288         } else {
289                 cal_db_append_string(&query_str, "SELECT count(*) FROM");
290                 cal_db_append_string(&query_str, table_name);
291         }
292         CAL_FREE(projection);
293         CAL_FREE(table_name);
294
295         /* query: condition */
296         if (condition) {
297                 cal_db_append_string(&query_str, "WHERE (");
298                 cal_db_append_string(&query_str, condition);
299                 cal_db_append_string(&query_str, ")");
300                 CAL_FREE(condition);
301         }
302
303         /* query */
304         ret = cal_db_util_query_get_first_int_result(query_str, bind_text, &count);
305         if (CALENDAR_ERROR_NONE != ret) {
306                 ERR("cal_db_util_query_get_first_int_result() Failed");
307                 if (bind_text) {
308                         g_slist_free_full(bind_text, free);
309                         bind_text = NULL;
310                 }
311
312                 CAL_FREE(query_str);
313                 return ret;
314         }
315         DBG("count(%d) str[%s]", count, query_str);
316
317         if (out_count) *out_count = count;
318         if (bind_text) {
319                 g_slist_free_full(bind_text, free);
320                 bind_text = NULL;
321         }
322
323         CAL_FREE(query_str);
324         return CALENDAR_ERROR_NONE;
325 }
326
327 static void _cal_db_search_get_stmt(sqlite3_stmt *stmt, calendar_query_h query,
328                 calendar_record_h record)
329 {
330         int i = 0;
331         int stmt_count = 0;
332         cal_query_s *query_s = NULL;
333         cal_property_info_s *properties = NULL;
334
335         query_s = (cal_query_s *)query;
336
337         for (i = 0; i < query_s->property_count; i++) {
338                 properties = &(query_s->properties[i]);
339
340                 if (CAL_PROPERTY_CHECK_FLAGS(properties->property_id, CAL_PROPERTY_FLAGS_FILTER) == true)
341                         break;
342
343                 _cal_db_search_get_property_stmt(stmt, properties->property_id, &stmt_count, record);
344         }
345         return ;
346 }
347
348 static void _cal_db_search_get_property_stmt(sqlite3_stmt *stmt,
349                 unsigned int property, int *stmt_count, calendar_record_h record)
350 {
351         int ret = 0;
352         const unsigned char *temp;
353         int int_tmp = 0;
354         double d_tmp = 0;
355         long long int lli_tmp = 0;
356
357         if (CAL_PROPERTY_CHECK_DATA_TYPE(property, CAL_PROPERTY_DATA_TYPE_INT) == true) {
358                 int_tmp = sqlite3_column_int(stmt, *stmt_count);
359                 cal_record_set_int(record, property, int_tmp);
360         } else if (CAL_PROPERTY_CHECK_DATA_TYPE(property, CAL_PROPERTY_DATA_TYPE_STR) == true) {
361                 temp = sqlite3_column_text(stmt, *stmt_count);
362                 cal_record_set_str(record, property, (const char*)temp);
363         } else if (CAL_PROPERTY_CHECK_DATA_TYPE(property, CAL_PROPERTY_DATA_TYPE_DOUBLE) == true) {
364                 d_tmp = sqlite3_column_double(stmt, *stmt_count);
365                 cal_record_set_double(record, property, d_tmp);
366         } else if (CAL_PROPERTY_CHECK_DATA_TYPE(property, CAL_PROPERTY_DATA_TYPE_LLI) == true) {
367                 lli_tmp = sqlite3_column_int64(stmt, *stmt_count);
368                 cal_record_set_lli(record, property, lli_tmp);
369         } else if (CAL_PROPERTY_CHECK_DATA_TYPE(property, CAL_PROPERTY_DATA_TYPE_CALTIME) == true) {
370                 calendar_time_s caltime_tmp;
371                 caltime_tmp.type = sqlite3_column_int(stmt, *stmt_count);
372                 switch (caltime_tmp.type) {
373                 case CALENDAR_TIME_UTIME:
374                         *stmt_count = *stmt_count+1;
375                         caltime_tmp.time.utime = sqlite3_column_int64(stmt, *stmt_count);
376                         *stmt_count = *stmt_count+1; /* datatime */
377                         break;
378
379                 case CALENDAR_TIME_LOCALTIME:
380                         *stmt_count = *stmt_count+1; /* utime */
381                         *stmt_count = *stmt_count+1;
382                         temp = sqlite3_column_text(stmt, *stmt_count);
383                         if (temp) {
384                                 sscanf((const char *)temp, CAL_FORMAT_LOCAL_DATETIME, &(caltime_tmp.time.date.year),
385                                                 &(caltime_tmp.time.date.month), &(caltime_tmp.time.date.mday),
386                                                 &(caltime_tmp.time.date.hour), &(caltime_tmp.time.date.minute),
387                                                 &(caltime_tmp.time.date.second));
388                         }
389                         break;
390                 }
391                 ret = cal_record_set_caltime(record, property, caltime_tmp);
392                 WARN_IF(CALENDAR_ERROR_NONE != ret, "Failed to cal_record_set_caltime()");
393         } else {
394                 sqlite3_column_int(stmt, *stmt_count);
395         }
396
397         *stmt_count = *stmt_count+1;
398 }
399 static void _cal_db_search_get_projection_stmt(sqlite3_stmt *stmt,
400                 const unsigned int *projection, const int projection_count,
401                 calendar_record_h record)
402 {
403         int i = 0;
404         int stmt_count = 0;
405
406         for (i = 0; i < projection_count; i++)
407                 _cal_db_search_get_property_stmt(stmt, projection[i], &stmt_count, record);
408 }
409
410 static int _cal_db_search_make_projection(calendar_query_h query, char **projection)
411 {
412         int i = 0;
413         int len = 0;
414         const char *field_name;
415         char out_projection[CAL_DB_SQL_MAX_LEN] = {0};
416         cal_query_s *query_s = NULL;
417         cal_property_info_s *properties = NULL;
418
419         RETV_IF(NULL == query, CALENDAR_ERROR_INVALID_PARAMETER);
420         query_s = (cal_query_s *)query;
421
422         properties = &(query_s->properties[0]);
423         field_name = properties->fields;
424         if (field_name)
425                 len += snprintf(out_projection+len, sizeof(out_projection)-len, "%s", field_name);
426
427         if (sizeof(out_projection) <= len) {
428                 ERR("buf len max");
429                 return CALENDAR_ERROR_SYSTEM;
430         }
431
432         for (i = 1; i < query_s->property_count; i++) {
433                 properties = &(query_s->properties[i]);
434                 field_name = properties->fields;
435
436                 if (CAL_PROPERTY_CHECK_FLAGS(properties->property_id, CAL_PROPERTY_FLAGS_FILTER) == true)
437                         break;
438
439                 if (field_name) {
440                         len += snprintf(out_projection+len, sizeof(out_projection)-len, ", %s", field_name);
441                         if (sizeof(out_projection) <= len) {
442                                 ERR("buf len max");
443                                 return CALENDAR_ERROR_SYSTEM;
444                         }
445                 }
446         }
447
448         *projection = g_strdup(out_projection);
449
450         return CALENDAR_ERROR_NONE;
451 }