4 * Copyright (c) 2012 - 2015 Samsung Electronics Co., Ltd. All rights reserved.
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
10 * http://www.apache.org/licenses/LICENSE-2.0
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.
21 #include "cal_internal.h"
22 #include "cal_typedef.h"
24 #include "cal_record.h"
27 #include "cal_db_util.h"
28 #include "cal_db_query.h"
29 #include "cal_access_control.h"
30 #include "cal_utils.h"
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);
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);
46 cal_db_plugin_cb_s cal_db_search_plugin_cb = {
47 .is_query_only = true,
48 .insert_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,
58 .get_count_with_query = _cal_db_search_get_count_with_query,
59 .replace_record = NULL,
60 .replace_records = NULL
63 static int _cal_db_search_get_records_with_query(calendar_query_h query, int offset, int limit, calendar_list_h* out_list)
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;
72 char *table_name = NULL;
74 que = (cal_query_s *)query;
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");
86 /* make: projection */
87 if (0 < que->projection_count)
88 ret = cal_db_query_create_projection(query, &projection);
90 _cal_db_search_make_projection(query, &projection);
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);
108 ERR("uri(%s) not support get records with query", que->view_uri);
109 CAL_FREE(projection);
111 return CALENDAR_ERROR_INVALID_PARAMETER;
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);
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);
126 CAL_FREE(projection);
127 CAL_FREE(table_name);
129 /* query: condition */
131 cal_db_append_string(&query_str, "WHERE (");
132 cal_db_append_string(&query_str, condition);
133 cal_db_append_string(&query_str, ")");
138 ret = cal_db_query_create_order(query, condition, &order);
140 cal_db_append_string(&query_str, order);
146 char buf[CAL_STR_SHORT_LEN32] = {0};
148 snprintf(buf, sizeof(buf), "LIMIT %d", limit);
149 cal_db_append_string(&query_str, buf);
152 snprintf(buf, sizeof(buf), "OFFSET %d", offset);
153 cal_db_append_string(&query_str, buf);
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);
163 g_slist_free_full(bind_text, free);
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);
177 ret = calendar_list_create(out_list);
178 if (CALENDAR_ERROR_NONE != ret) {
180 g_slist_free_full(bind_text, free);
183 ERR("calendar_list_create() Fail");
184 sqlite3_finalize(stmt);
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);
197 g_slist_free_full(bind_text, free);
200 sqlite3_finalize(stmt);
204 if (0 < que->projection_count) {
205 _cal_db_search_get_projection_stmt(stmt, que->projection, que->projection_count,
208 _cal_db_search_get_stmt(stmt, query, record);
211 ret = calendar_list_add(*out_list, record);
212 if (CALENDAR_ERROR_NONE != ret) {
213 calendar_list_destroy(*out_list, true);
215 calendar_record_destroy(record, true);
218 g_slist_free_full(bind_text, free);
221 sqlite3_finalize(stmt);
228 g_slist_free_full(bind_text, free);
231 sqlite3_finalize(stmt);
234 return CALENDAR_ERROR_NONE;
237 static int _cal_db_search_get_count_with_query(calendar_query_h query, int *out_count)
239 cal_query_s *que = NULL;
240 int ret = CALENDAR_ERROR_NONE;
241 char *condition = NULL;
242 char *projection = NULL;
245 GSList *bind_text = NULL;
247 que = (cal_query_s *)query;
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");
265 ERR("uri(%s) not support get records with query", que->view_uri);
266 return CALENDAR_ERROR_INVALID_PARAMETER;
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);
280 char *query_str = NULL;
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);
289 cal_db_append_string(&query_str, "SELECT count(*) FROM");
290 cal_db_append_string(&query_str, table_name);
292 CAL_FREE(projection);
293 CAL_FREE(table_name);
295 /* query: condition */
297 cal_db_append_string(&query_str, "WHERE (");
298 cal_db_append_string(&query_str, condition);
299 cal_db_append_string(&query_str, ")");
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");
308 g_slist_free_full(bind_text, free);
315 DBG("count(%d) str[%s]", count, query_str);
317 if (out_count) *out_count = count;
319 g_slist_free_full(bind_text, free);
324 return CALENDAR_ERROR_NONE;
327 static void _cal_db_search_get_stmt(sqlite3_stmt *stmt, calendar_query_h query,
328 calendar_record_h record)
332 cal_query_s *query_s = NULL;
333 cal_property_info_s *properties = NULL;
335 query_s = (cal_query_s *)query;
337 for (i = 0; i < query_s->property_count; i++) {
338 properties = &(query_s->properties[i]);
340 if (CAL_PROPERTY_CHECK_FLAGS(properties->property_id, CAL_PROPERTY_FLAGS_FILTER) == true)
343 _cal_db_search_get_property_stmt(stmt, properties->property_id, &stmt_count, record);
348 static void _cal_db_search_get_property_stmt(sqlite3_stmt *stmt,
349 unsigned int property, int *stmt_count, calendar_record_h record)
352 const unsigned char *temp;
355 long long int lli_tmp = 0;
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 */
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);
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));
391 ret = cal_record_set_caltime(record, property, caltime_tmp);
392 WARN_IF(CALENDAR_ERROR_NONE != ret, "Failed to cal_record_set_caltime()");
394 sqlite3_column_int(stmt, *stmt_count);
397 *stmt_count = *stmt_count+1;
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)
406 for (i = 0; i < projection_count; i++)
407 _cal_db_search_get_property_stmt(stmt, projection[i], &stmt_count, record);
410 static int _cal_db_search_make_projection(calendar_query_h query, char **projection)
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;
419 RETV_IF(NULL == query, CALENDAR_ERROR_INVALID_PARAMETER);
420 query_s = (cal_query_s *)query;
422 properties = &(query_s->properties[0]);
423 field_name = properties->fields;
425 len += snprintf(out_projection+len, sizeof(out_projection)-len, "%s", field_name);
427 if (sizeof(out_projection) <= len) {
429 return CALENDAR_ERROR_SYSTEM;
432 for (i = 1; i < query_s->property_count; i++) {
433 properties = &(query_s->properties[i]);
434 field_name = properties->fields;
436 if (CAL_PROPERTY_CHECK_FLAGS(properties->property_id, CAL_PROPERTY_FLAGS_FILTER) == true)
440 len += snprintf(out_projection+len, sizeof(out_projection)-len, ", %s", field_name);
441 if (sizeof(out_projection) <= len) {
443 return CALENDAR_ERROR_SYSTEM;
448 *projection = g_strdup(out_projection);
450 return CALENDAR_ERROR_NONE;