2 * Copyright (c) 2021 Samsung Electronics Co., Ltd All Rights Reserved
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
17 #include "query_handler.hh"
19 #include <shared_mutex>
23 #include "utils/logging.hh"
24 #include "cache_flag.hh"
25 #include "db_handle_provider.hh"
27 #include "pkgmgrinfo_debug.h"
28 #include "pkgmgrinfo_internal.h"
29 #include "pkgmgr_query_index.h"
33 constexpr const char query_appinfo_get_localed_label[] =
34 "SELECT COALESCE((SELECT app_label FROM package_app_localized_info "
35 "WHERE app_id=? AND app_locale=?),"
36 "(SELECT app_label FROM package_app_localized_info WHERE "
37 "app_id=? AND app_locale='No Locale'))";
39 constexpr const char query_appinfo_get_datacontrol_info[] =
40 "SELECT app_id, access FROM "
41 "package_app_data_control WHERE "
42 "providerid=? AND type=?";
44 constexpr const char query_appinfo_get_datacontrol_appid[] =
45 "SELECT app_id FROM package_app_data_control "
48 constexpr const char query_appinfo_get_datacontrol_trusted_info[] =
49 "SELECT app_id, trusted FROM package_app_data_control "
50 "WHERE providerid=? AND type=?";
52 constexpr const char query_appinfo_get_datacontrol_privileges[] =
53 "SELECT privilege FROM package_app_data_control_privilege "
54 "WHERE providerid=? AND type=?";
56 constexpr const char query_appinfo_get_appcontrol_privileges[] =
57 "SELECT app_control, privilege FROM package_app_app_control_privilege "
60 constexpr const char query_plugininfo_get_appids[] =
62 "package_plugin_info WHERE pkgid=? AND "
63 "plugin_type=? AND plugin_name=?";
65 constexpr const char query_get_pkg_updateinfo_1[] =
66 "SELECT package, update_version, update_type "
67 "FROM package_update_info";
68 constexpr const char query_get_pkg_updateinfo_2[] =
69 "SELECT package, update_version, update_type "
70 "FROM package_update_info WHERE package=?";
72 constexpr const char query_pkginfo_set_usr_installed_storage_1[] =
73 "UPDATE package_info SET installed_storage=?, external_path=? "
75 constexpr const char query_pkginfo_set_usr_installed_storage_2[] =
76 "UPDATE package_app_info SET app_installed_storage=?, "
77 "app_external_path=? WHERE package=?";
79 constexpr const char query_certinfo_compare_pkg_certinfo[] =
81 "COALESCE(author_signer_cert, -1) FROM package_cert_info WHERE "
84 constexpr const char query_certinfo_compare_app_certinfo[] =
85 "SELECT app_id, package FROM "
86 "package_app_info WHERE app_id IN (?, ?)";
88 constexpr const char query_pkginfo_delete_certinfo[] =
89 "UPDATE package_cert_info SET "
90 "package_count = package_count - 1 WHERE package=?";
93 constexpr const char query_insert_package_plugin_execution_info[] =
94 "INSERT INTO package_plugin_info "
95 "(pkgid, appid, plugin_type, plugin_name) "
96 "VALUES (?, ?, ?, ?)";
98 constexpr const char query_delete_package_plugin_execution_info[] =
99 "DELETE FROM package_plugin_info WHERE pkgid=?";
101 constexpr const char query_update_global_app_disable[] =
102 "INSERT OR REPLACE INTO package_app_info_for_uid ("
103 " app_id, uid, is_disabled, is_splash_screen_enabled) "
105 " (SELECT app_splash_screen_display FROM package_app_info"
108 constexpr const char query_update_app_disable_info[] =
109 "UPDATE package_app_info SET app_disable=? "
112 constexpr const char query_update_pkg_disable_info[] =
113 "UPDATE package_info SET package_disable=? "
116 constexpr const char query_update_global_app_splash_screen_display_info[] =
117 "INSERT OR REPLACE INTO package_app_info_for_uid("
118 " app_id, uid, is_splash_screen_enabled) "
121 constexpr const char query_update_app_splash_screen_display_info[] =
122 "UPDATE package_app_info SET app_splash_screen_display=? "
125 constexpr const char query_update_app_label_info[] =
126 "UPDATE package_app_localized_info SET app_label=? "
127 "WHERE app_id=? AND app_label IS NOT NULL";
129 constexpr const char query_update_app_icon_info[] =
130 "UPDATE package_app_localized_info SET app_icon=? "
131 "WHERE app_id=? AND app_icon IS NOT NULL";
133 constexpr const char query_update_tep_info[] =
134 "UPDATE package_info SET package_tep_name=? "
137 constexpr const char query_register_pkg_update_info[] =
138 "UPDATE package_update_info "
139 "SET update_version=?, update_type=? "
142 constexpr const char query_unregister_pkg_update_info[] =
143 "UPDATE package_update_info "
144 "SET update_type='none' WHERE package=?";
146 constexpr const char query_unregister_all_pkg_update_info[] =
147 "UPDATE package_update_info "
148 "SET update_type='none'";
152 using CacheChangeFlag = pkgmgr_server::database::CacheChangeFlag;
153 std::vector<std::tuple<const char*, CacheChangeFlag, int>> query_raw_ = {
154 { query_appinfo_get_localed_label, CacheChangeFlag::NONE, 0 },
155 { query_appinfo_get_datacontrol_info, CacheChangeFlag::NONE, 0 },
156 { query_appinfo_get_datacontrol_appid, CacheChangeFlag::NONE, 0 },
157 { query_appinfo_get_datacontrol_trusted_info, CacheChangeFlag::NONE, 0 },
158 { query_appinfo_get_datacontrol_privileges, CacheChangeFlag::NONE, 0 },
159 { query_appinfo_get_appcontrol_privileges, CacheChangeFlag::NONE, 0 },
160 { query_plugininfo_get_appids, CacheChangeFlag::NONE, 0 },
161 { query_get_pkg_updateinfo_1, CacheChangeFlag::NONE, 0 },
162 { query_get_pkg_updateinfo_2, CacheChangeFlag::NONE, 0 },
163 { query_pkginfo_set_usr_installed_storage_1, CacheChangeFlag::PKG, 2 },
164 { query_pkginfo_set_usr_installed_storage_2, CacheChangeFlag::APPBYPKG, 2 },
165 { query_certinfo_compare_pkg_certinfo, CacheChangeFlag::NONE, 0 },
166 { query_certinfo_compare_app_certinfo, CacheChangeFlag::NONE, 0 },
167 { query_pkginfo_delete_certinfo, CacheChangeFlag::NONE, 0 },
169 { query_insert_package_plugin_execution_info, CacheChangeFlag::PKG, 0 },
170 { query_delete_package_plugin_execution_info, CacheChangeFlag::PKG, 0 },
171 { query_update_global_app_disable, CacheChangeFlag::APP, 0 },
172 { query_update_app_disable_info, CacheChangeFlag::APP, 1 },
173 { query_update_pkg_disable_info, CacheChangeFlag::PKG, 1 },
174 { query_update_global_app_splash_screen_display_info, CacheChangeFlag::APP, 0 },
175 { query_update_app_splash_screen_display_info, CacheChangeFlag::APP, 1 },
176 { query_update_app_label_info, CacheChangeFlag::APP, 1 },
177 { query_update_app_icon_info, CacheChangeFlag::APP, 1 },
178 { query_update_tep_info, CacheChangeFlag::PKG, 1 },
179 { query_register_pkg_update_info, CacheChangeFlag::NONE, 0 },
180 { query_unregister_pkg_update_info, CacheChangeFlag::NONE, 0 },
181 { query_unregister_all_pkg_update_info, CacheChangeFlag::NONE, 0 },
184 const std::tuple<const char*, CacheChangeFlag, int>& GetQueryInfo(int index) {
185 return query_raw_[index];
189 QueryMaker __query_maker;
191 void __free_argument(gpointer data) {
192 query_args* args = reinterpret_cast<query_args*>(data);
193 g_list_free(args->argument);
197 void __free_query_list(GList* queries, GList* args_list) {
198 g_list_free(queries);
199 g_list_free_full(args_list, __free_argument);
204 namespace pkgmgr_server {
207 QueryHandler::QueryHandler(uid_t uid, int pid)
208 : AbstractDBHandler(uid, pid), uid_(uid) {}
210 QueryHandler::~QueryHandler() {}
212 void QueryHandler::SetQueryArgs(
213 std::vector<pkgmgr_common::parcel::QueryArgs> query_args) {
214 query_args_ = std::move(query_args);
217 std::string QueryHandler::GetString() { return std::string(); }
218 int QueryHandler::GetInt() { return 0; }
219 int QueryHandler::GetRecordCount() { return 0; }
221 std::vector<pkgmgr_common::parcel::StrArgs> QueryHandler::GetResult() {
222 return std::move(result_);
225 int QueryHandler::ExecuteReadQuery(GList* queries, GList* args_list) {
226 std::shared_lock<std::shared_mutex> s(lock_);
228 LOG(ERROR) << "Failed to connect database";
229 return PMINFO_R_ERROR;
232 std::vector<std::pair<sqlite3*, uid_t>> conn_list = GetConnection();
233 int ret = PMINFO_R_ERROR;
234 for (auto& conn : conn_list) {
235 for (GList* it = args_list; it; it = it->next) {
236 GList* list = nullptr;
240 query_args* params = reinterpret_cast<query_args*>(it->data);
241 ret = get_query_result(conn.first, (const char *)queries->data,
242 params->argument, &list, &row, &col);
243 if (ret == PMINFO_R_ERROR) {
244 LOG(ERROR) << "Failed to execute query";
249 for (int i = 0; i < row; ++i) {
250 pkgmgr_common::parcel::StrArgs vt;
251 for (int j = 0; j < col; ++j) {
253 vt.emplace_back(std::nullopt);
255 vt.emplace_back(reinterpret_cast<char *>(tmp->data));
258 result_.emplace_back(std::move(vt));
261 g_list_free_full(list, free);
268 int QueryHandler::ExecuteWriteQuery(GList* queries, GList* args_list,
269 const std::vector<std::pair<CacheChangeFlag, std::string>>& changes) {
270 std::unique_lock<std::shared_mutex> u(lock_);
272 LOG(ERROR) << "Failed to connect database";
273 return PMINFO_R_ERROR;
276 std::vector<std::pair<sqlite3*, uid_t>> conn_list = GetConnection();
277 int ret = PMINFO_R_ERROR;
278 bool is_writer = DBHandleProvider::IsWriter(GetPID());
279 for (auto& conn : conn_list) {
280 ret = execute_write_queries(conn.first, queries, args_list);
281 if (ret != PMINFO_R_OK) {
282 LOG(ERROR) << "Failed to execute";
287 if (ret != PMINFO_R_OK || is_writer || changes.size() == 0 ||
288 CacheFlag::GetStatus() != CacheFlag::Status::PREPARED)
292 CacheFlag::SetStatus(CacheFlag::Status::PREPARING);
293 auto lock = CacheFlag::GetWriterLock();
294 for (auto& conn : conn_list) {
295 auto& provider = database::DBHandleProvider::GetInst(conn.second);
296 for (const auto& [flag, name] : changes) {
298 case CacheChangeFlag::PKG:
299 success = provider.UpdateCachePkg(conn.first, uid_, name, GetLocale());
301 case CacheChangeFlag::APP:
302 success = provider.UpdateCacheApp(conn.first, uid_, name, GetLocale());
304 case CacheChangeFlag::APPBYPKG:
306 provider.UpdateCacheAppByPkgid(conn.first, uid_, name, GetLocale());
313 LOG(ERROR) << "Write query failed. " << static_cast<int>(flag) << ' '
320 provider.TrimCache();
325 CacheFlag::SetStatus(success ?
326 CacheFlag::Status::PREPARED : CacheFlag::Status::UNPREPARED);
331 int QueryHandler::Execute() {
332 GList* queries = nullptr;
333 GList* args_list = nullptr;
334 std::vector<std::pair<CacheChangeFlag, std::string>> changes;
335 for (auto& [queryIndex, args] : query_args_) {
336 const auto& query_info = __query_maker.GetQueryInfo(queryIndex);
337 const char* query = std::get<0>(query_info);
338 if (query == nullptr) {
339 LOG(ERROR) << "Failed to get query";
340 __free_query_list(queries, args_list);
341 return PMINFO_R_ERROR;
344 queries = g_list_append(queries, (gpointer)query);
345 query_args* arg = reinterpret_cast<query_args*>(
346 calloc(1, sizeof(query_args)));
347 if (arg == nullptr) {
348 LOG(ERROR) << "Out of memory";
349 __free_query_list(queries, args_list);
350 return PMINFO_R_ERROR;
352 arg->len = args.size();
353 for (auto& argument : args) {
354 arg->argument = g_list_append(arg->argument,
355 gpointer(argument ? (*argument).c_str() : nullptr));
358 args_list = g_list_append(args_list, arg);
360 if (GetOpType() == pkgmgr_common::DBOperationType::OPERATION_TYPE_READ)
363 CacheChangeFlag flag = std::get<1>(query_info);
364 if (flag == CacheChangeFlag::NONE)
367 /* Cache changed query steps */
368 unsigned int idx = std::get<2>(query_info);
369 if (args.size() <= idx) {
370 LOG(ERROR) << "Invalid query argument";
371 __free_query_list(queries, args_list);
372 return PMINFO_R_ERROR;
378 changes.emplace_back(std::make_pair(flag, *args[idx]));
381 if (GetOpType() == pkgmgr_common::DBOperationType::OPERATION_TYPE_READ) {
382 int ret = ExecuteReadQuery(queries, args_list);
383 __free_query_list(queries, args_list);
386 int ret = ExecuteWriteQuery(queries, args_list, changes);
387 __free_query_list(queries, args_list);
392 } // namespace database
393 } // namespace pkgmgr_server