Fix 'frequency' statistics for the trigger to emit proper results
[platform/core/context/statistics-context-provider.git] / src / app / db_handle.cpp
1 /*
2  * Copyright (c) 2015 Samsung Electronics Co., Ltd.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 #include <sstream>
18 #include <types_internal.h>
19 #include <context_mgr.h>
20 #include <db_mgr.h>
21 #include "app_stats_types.h"
22 #include "db_handle.h"
23
24 ctx::app_db_handle::app_db_handle(const char* zone)
25         : stats_db_handle_base(zone)
26 {
27 }
28
29 ctx::app_db_handle::~app_db_handle()
30 {
31 }
32
33 int ctx::app_db_handle::read(const char* subject, ctx::json filter)
34 {
35         std::string query;
36
37         if (STR_EQ(subject, APP_SUBJ_RECENTLY_USED)) {
38                 query = create_sql_recently_used(filter);
39
40         } else if (STR_EQ(subject, APP_SUBJ_FREQUENTLY_USED)) {
41                 query = create_sql_frequently_used(filter);
42
43         } else if (STR_EQ(subject, APP_SUBJ_RARELY_USED)) {
44                 query = create_sql_rarely_used(filter);
45
46         } else if (STR_EQ(subject, APP_SUBJ_PEAK_TIME)) {
47                 query = create_sql_peak_time(filter);
48
49         } else if (STR_EQ(subject, APP_SUBJ_COMMON_SETTING)) {
50                 query = create_sql_common_setting(filter);
51
52         } else if (STR_EQ(subject, APP_SUBJ_FREQUENCY)) {
53                 is_trigger_item = true;
54                 query = create_sql_frequency(filter);
55         }
56
57         IF_FAIL_RETURN(!query.empty(), ERR_OPERATION_FAILED);
58
59         bool ret = execute_query(subject, filter, query.c_str());
60         IF_FAIL_RETURN(ret, ERR_OPERATION_FAILED);
61
62         return ERR_NONE;
63 }
64
65 std::string ctx::app_db_handle::create_where_clause_with_device_status(ctx::json filter)
66 {
67         std::stringstream where_clause;
68         std::string bssid;
69         int audio_jack;
70
71         where_clause << stats_db_handle_base::create_where_clause(filter);
72
73         if (filter.get(NULL, STATS_BSSID, &bssid))
74                 where_clause << " AND " STATS_BSSID " = '" << bssid << "'";
75
76         if (filter.get(NULL, STATS_AUDIO_JACK, &audio_jack))
77                 where_clause << " AND " STATS_AUDIO_JACK " = " << audio_jack;
78
79         return where_clause.str();
80 }
81
82 std::string ctx::app_db_handle::create_sql_peak_time(ctx::json filter)
83 {
84         return stats_db_handle_base::create_sql_peak_time(filter, APP_TABLE_USAGE_LOG, create_where_clause(filter));
85 }
86
87 std::string ctx::app_db_handle::create_sql_common_setting(ctx::json filter)
88 {
89         return stats_db_handle_base::create_sql_common_setting(filter, APP_TABLE_USAGE_LOG, create_where_clause(filter));
90 }
91
92 std::string ctx::app_db_handle::create_sql_frequency(ctx::json filter)
93 {
94         ctx::json filter_cleaned;
95         std::string week_str;
96         std::string time_of_day;
97         std::string app_id;
98
99         if (!filter.get(NULL, STATS_APP_ID, &app_id)) {
100                 _E("Invalid parameter");
101                 return "";
102         }
103
104         if (filter.get(NULL, STATS_DAY_OF_WEEK, &week_str))
105                 filter_cleaned.set(NULL, STATS_DAY_OF_WEEK, week_str);
106
107         if (filter.get(NULL, STATS_TIME_OF_DAY, &time_of_day))
108                 filter_cleaned.set(NULL, STATS_TIME_OF_DAY, time_of_day);
109
110         std::string where_clause = create_where_clause(filter_cleaned);
111
112         std::stringstream query;
113
114         query <<
115                 "DELETE FROM " APP_TEMP_USAGE_FREQ ";";
116
117         query <<
118                 "INSERT INTO " APP_TEMP_USAGE_FREQ \
119                 " SELECT " STATS_APP_ID ", COUNT(*) AS " STATS_TOTAL_COUNT \
120                 " FROM " APP_TABLE_USAGE_LOG \
121                 " WHERE " << where_clause <<
122                 " GROUP BY " STATS_APP_ID ";";
123
124         query <<
125                 "INSERT OR IGNORE INTO " APP_TEMP_USAGE_FREQ " (" STATS_APP_ID ")" \
126                 " VALUES ('" << app_id << "');";
127
128         query <<
129                 "SELECT S." STATS_APP_ID ", S." STATS_TOTAL_COUNT ", 1+COUNT(lesser." STATS_TOTAL_COUNT ") AS Rank" \
130                 " FROM " APP_TEMP_USAGE_FREQ " AS S" \
131                 " LEFT JOIN " APP_TEMP_USAGE_FREQ " AS lesser" \
132                 " ON S." STATS_TOTAL_COUNT " < lesser." STATS_TOTAL_COUNT \
133                 " WHERE S." STATS_APP_ID " = '" << app_id << "'";
134
135         return query.str();
136 }
137
138 std::string ctx::app_db_handle::create_sql_recently_used(ctx::json filter)
139 {
140         std::stringstream query;
141         int limit = DEFAULT_LIMIT;
142
143         filter.get(NULL, STATS_RESULT_SIZE, &limit);
144
145         query <<
146                 "SELECT " STATS_APP_ID ", " \
147                         "COUNT(*) AS " STATS_TOTAL_COUNT ", " \
148                         "SUM(" STATS_DURATION ") AS " STATS_TOTAL_DURATION ", " \
149                         "MAX(" STATS_UNIV_TIME ") AS " STATS_LAST_TIME \
150                 " FROM " APP_TABLE_USAGE_LOG \
151                 " WHERE " << create_where_clause_with_device_status(filter) <<
152                 " GROUP BY " STATS_APP_ID \
153                 " ORDER BY MAX(" STATS_UNIV_TIME ") DESC" \
154                 " LIMIT " << limit;
155
156         return query.str();
157 }
158
159 std::string ctx::app_db_handle::create_sql_frequently_used(ctx::json filter)
160 {
161         std::stringstream query;
162         int limit = DEFAULT_LIMIT;
163
164         filter.get(NULL, STATS_RESULT_SIZE, &limit);
165
166         query <<
167                 "SELECT " STATS_APP_ID ", " \
168                         "COUNT(*) AS " STATS_TOTAL_COUNT ", " \
169                         "SUM(" STATS_DURATION ") AS " STATS_TOTAL_DURATION ", " \
170                         "MAX(" STATS_UNIV_TIME ") AS " STATS_LAST_TIME \
171                 " FROM " APP_TABLE_USAGE_LOG \
172                 " WHERE " << create_where_clause_with_device_status(filter) <<
173                 " GROUP BY " STATS_APP_ID \
174                 " ORDER BY COUNT(*) DESC" \
175                 " LIMIT " << limit;
176
177         return query.str();
178 }
179
180 std::string ctx::app_db_handle::create_sql_rarely_used(ctx::json filter)
181 {
182         std::stringstream query;
183         int limit = DEFAULT_LIMIT;
184
185         filter.get(NULL, STATS_RESULT_SIZE, &limit);
186
187         query <<
188                 "SELECT i." STATS_APP_ID ", " \
189                         "COUNT(u." STATS_DURATION ") AS " STATS_TOTAL_COUNT ", " \
190                         "IFNULL(SUM(u." STATS_DURATION "),0) AS " STATS_TOTAL_DURATION ", " \
191                         "IFNULL(MAX(u." STATS_UNIV_TIME "),-1) AS " STATS_LAST_TIME \
192                 " FROM " APP_TABLE_REMOVABLE_APP " i LEFT OUTER JOIN (" \
193                         " SELECT * FROM " APP_TABLE_USAGE_LOG \
194                         " WHERE " << create_where_clause_with_device_status(filter) << ") u" \
195                         " ON i." STATS_APP_ID " = u." STATS_APP_ID \
196                 " GROUP BY i." STATS_APP_ID \
197                 " ORDER BY " STATS_TOTAL_COUNT " ASC" \
198                 " LIMIT " << limit;
199
200         return query.str();
201 }