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) {
82 ERR("cal_db_query_create_condition() Fail(%d), ret");
88 /* make: projection */
89 if (0 < que->projection_count)
90 ret = cal_db_query_create_projection(query, &projection);
92 _cal_db_search_make_projection(query, &projection);
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);
110 /* LCOV_EXCL_START */
111 ERR("uri(%s) not support get records with query", que->view_uri);
112 CAL_FREE(projection);
114 return CALENDAR_ERROR_INVALID_PARAMETER;
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);
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);
130 CAL_FREE(projection);
131 CAL_FREE(table_name);
133 /* query: condition */
135 cal_db_append_string(&query_str, "WHERE (");
136 cal_db_append_string(&query_str, condition);
137 cal_db_append_string(&query_str, ")");
142 ret = cal_db_query_create_order(query, condition, &order);
144 cal_db_append_string(&query_str, order);
150 char buf[CAL_STR_SHORT_LEN32] = {0};
152 snprintf(buf, sizeof(buf), "LIMIT %d", limit);
153 cal_db_append_string(&query_str, buf);
156 snprintf(buf, sizeof(buf), "OFFSET %d", offset);
157 cal_db_append_string(&query_str, buf);
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);
168 g_slist_free_full(bind_text, free);
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);
183 ret = calendar_list_create(out_list);
184 if (CALENDAR_ERROR_NONE != ret) {
185 /* LCOV_EXCL_START */
186 ERR("calendar_list_create() Fail");
188 g_slist_free_full(bind_text, free);
191 sqlite3_finalize(stmt);
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);
206 g_slist_free_full(bind_text, free);
209 sqlite3_finalize(stmt);
214 if (0 < que->projection_count) {
215 _cal_db_search_get_projection_stmt(stmt, que->projection, que->projection_count,
218 _cal_db_search_get_stmt(stmt, query, record);
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);
226 calendar_record_destroy(record, true);
229 g_slist_free_full(bind_text, free);
232 sqlite3_finalize(stmt);
240 g_slist_free_full(bind_text, free);
243 sqlite3_finalize(stmt);
246 return CALENDAR_ERROR_NONE;
249 static int _cal_db_search_get_count_with_query(calendar_query_h query, int *out_count)
251 cal_query_s *que = NULL;
252 int ret = CALENDAR_ERROR_NONE;
253 char *condition = NULL;
254 char *projection = NULL;
257 GSList *bind_text = NULL;
259 que = (cal_query_s *)query;
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");
277 /* LCOV_EXCL_START */
278 ERR("uri(%s) not support get records with query", que->view_uri);
279 return CALENDAR_ERROR_INVALID_PARAMETER;
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);
296 char *query_str = NULL;
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);
305 cal_db_append_string(&query_str, "SELECT count(*) FROM");
306 cal_db_append_string(&query_str, table_name);
308 CAL_FREE(projection);
309 CAL_FREE(table_name);
311 /* query: condition */
313 cal_db_append_string(&query_str, "WHERE (");
314 cal_db_append_string(&query_str, condition);
315 cal_db_append_string(&query_str, ")");
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");
325 g_slist_free_full(bind_text, free);
333 DBG("count(%d) str[%s]", count, query_str);
335 if (out_count) *out_count = count;
337 g_slist_free_full(bind_text, free);
342 return CALENDAR_ERROR_NONE;
345 static void _cal_db_search_get_stmt(sqlite3_stmt *stmt, calendar_query_h query,
346 calendar_record_h record)
350 cal_query_s *query_s = NULL;
351 cal_property_info_s *properties = NULL;
353 query_s = (cal_query_s *)query;
355 for (i = 0; i < query_s->property_count; i++) {
356 properties = &(query_s->properties[i]);
358 if (CAL_PROPERTY_CHECK_FLAGS(properties->property_id, CAL_PROPERTY_FLAGS_FILTER) == true)
361 _cal_db_search_get_property_stmt(stmt, properties->property_id, &stmt_count, record);
366 static void _cal_db_search_get_property_stmt(sqlite3_stmt *stmt,
367 unsigned int property, int *stmt_count, calendar_record_h record)
370 const unsigned char *temp;
373 long long int lli_tmp = 0;
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 */
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);
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));
409 ret = cal_record_set_caltime(record, property, caltime_tmp);
410 WARN_IF(CALENDAR_ERROR_NONE != ret, "Failed to cal_record_set_caltime()");
412 sqlite3_column_int(stmt, *stmt_count);
415 *stmt_count = *stmt_count+1;
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)
424 for (i = 0; i < projection_count; i++)
425 _cal_db_search_get_property_stmt(stmt, projection[i], &stmt_count, record);
428 static int _cal_db_search_make_projection(calendar_query_h query, char **projection)
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;
437 RETV_IF(NULL == query, CALENDAR_ERROR_INVALID_PARAMETER);
438 query_s = (cal_query_s *)query;
440 properties = &(query_s->properties[0]);
441 field_name = properties->fields;
443 len += snprintf(out_projection+len, sizeof(out_projection)-len, "%s", field_name);
445 if (sizeof(out_projection) <= len) {
446 /* LCOV_EXCL_START */
448 return CALENDAR_ERROR_SYSTEM;
452 for (i = 1; i < query_s->property_count; i++) {
453 properties = &(query_s->properties[i]);
454 field_name = properties->fields;
456 if (CAL_PROPERTY_CHECK_FLAGS(properties->property_id, CAL_PROPERTY_FLAGS_FILTER) == true)
460 len += snprintf(out_projection+len, sizeof(out_projection)-len, ", %s", field_name);
461 if (sizeof(out_projection) <= len) {
462 /* LCOV_EXCL_START */
464 return CALENDAR_ERROR_SYSTEM;
470 *projection = g_strdup(out_projection);
472 return CALENDAR_ERROR_NONE;