Merge "Add default viewer launch feature for ex-noti" into tizen
[platform/core/api/notification.git] / notification-ex / db_manager.cc
1 /*
2  * Copyright (c) 2019 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 <dlog.h>
18 #include <unistd.h>
19 #include <sqlite3.h>
20 #include <vconf.h>
21 #include <pkgmgr-info.h>
22 #include <tzplatform_config.h>
23 #include <inttypes.h>
24
25 #include <string.h>
26 #include <list>
27 #include <map>
28
29 #include "notification-ex/common.h"
30 #include "notification-ex/db_manager.h"
31 #include "notification-ex/item_inflator.h"
32 #include "notification-ex/iitem_info_internal.h"
33 #include "notification-ex/ex_util.h"
34
35 #ifdef LOG_TAG
36 #undef LOG_TAG
37 #endif
38 #define LOG_TAG "NOTIFICATION_EX"
39
40 #define CREATE_NOTIFICATION_TABLE \
41   "PRAGMA journal_mode = PERSIST;\n" \
42   "PRAGMA synchronous = FULL;\n" \
43   "PRAGMA foreign_keys = ON;\n" \
44   "CREATE TABLE IF NOT EXISTS noti_ex_list (\n" \
45   " root_id TEXT NOT NULL,\n" \
46   " app_id TEXT NOT NULL,\n" \
47   " uid INTEGER,\n" \
48   " channel TEXT,\n" \
49   " priv_id INTEGER PRIMARY KEY,\n" \
50   " pkg_id TEXT,\n" \
51   " policy INTEGER,\n" \
52   " data TEXT NOT NULL,\n" \
53   " insert_time INTEGER,\n" \
54   " hide_list TEXT,\n" \
55   " UNIQUE (root_id, app_id, uid));\n" \
56   "CREATE TABLE IF NOT EXISTS receiver_list (\n" \
57   " root_id TEXT NOT NULL,\n" \
58   " app_id TEXT NOT NULL,\n" \
59   " uid INTEGER,\n" \
60   " receiver_group TEXT NOT NULL,\n" \
61   " FOREIGN KEY (root_id, app_id, uid)\n" \
62   " REFERENCES noti_ex_list(root_id, app_id, uid) ON DELETE CASCADE);\n"
63
64 #define DBPATH tzplatform_mkpath(TZ_SYS_DB, ".notification.db")
65 #define NOTI_LIMIT 100
66
67 using namespace std;
68 using namespace tizen_base;
69 using namespace notification::item;
70
71 namespace notification {
72
73 DBManager::DBManager() = default;
74 DBManager::~DBManager() = default;
75
76 sqlite3* DBManager::OpenDB() {
77   int ret;
78   sqlite3* db;
79
80   ret = sqlite3_open_v2(DBPATH, &db, SQLITE_OPEN_READWRITE, nullptr);
81   if (ret != SQLITE_OK) {
82     LOGE("open db(%s) error: %d", DBPATH, ret);
83     return nullptr;
84   }
85
86   return db;
87 }
88
89 void DBManager::CloseDB(sqlite3* db) {
90   int ret = SQLITE_OK;
91
92   if (db)
93     ret = sqlite3_close_v2(db);
94
95   if (ret != SQLITE_OK)
96     LOGE("close db error");
97 }
98
99 int DBManager::ExecuteQuery(sqlite3* db, const char* query, int* num_changes) {
100   int ret = ERROR_NONE;
101   sqlite3_stmt *stmt;
102
103   if (db == nullptr || query == nullptr)
104     return ERROR_INVALID_PARAMETER;
105
106   ret = sqlite3_prepare_v2(db, query, strlen(query), &stmt, nullptr);
107   if (ret != SQLITE_OK) {
108     /* LCOV_EXCL_START */
109     LOGE("Sqlite3 err[%d][%s]", ret, sqlite3_errmsg(db));
110     return ERROR_FROM_DB;
111     /* LCOV_EXCL_STOP */
112   }
113
114   ret = sqlite3_step(stmt);
115   if (ret == SQLITE_OK || ret == SQLITE_DONE) {
116     if (num_changes != nullptr)
117     *num_changes = sqlite3_changes(db);
118     ret = ERROR_NONE;
119   } else {
120     /* LCOV_EXCL_START */
121     LOGE("Sqlite err[%d][%s]", ret, sqlite3_errmsg(db));
122     ret = ERROR_FROM_DB;
123     /* LCOV_EXCL_STOP */
124   }
125
126   sqlite3_finalize(stmt);
127   return ret;
128 }
129
130 int DBManager::ExecuteQuery(const char* query, int* num_changes) {
131   int ret;
132
133   if (query == nullptr)
134     return ERROR_INVALID_PARAMETER;
135
136   sqlite3* db = OpenDB();
137   if (db == nullptr)
138     return ERROR_FROM_DB;
139
140   ret = ExecuteQuery(db, query, num_changes);
141   CloseDB(db);
142
143   return ret;
144 }
145
146 int DBManager::GetSequence(sqlite3* db, int64_t* seq) {
147   int ret = ERROR_NONE;
148   sqlite3_stmt *stmt;
149
150   if (db == nullptr || seq == nullptr)
151     return ERROR_INVALID_PARAMETER;
152
153   string query = "SELECT IFNULL(MIN(priv_id), 0), IFNULL(MAX(priv_id), 0)"
154       " FROM noti_ex_list";
155   sqlite3_prepare_v2(db, query.c_str(), query.size(), &stmt, nullptr);
156   ret = sqlite3_step(stmt);
157   if (ret == SQLITE_ROW) {
158     int64_t min_p = sqlite3_column_int64(stmt, 0);
159     if (min_p > 1)
160       *seq = min_p - 1;
161     else
162       *seq = sqlite3_column_int64(stmt, 1) + 1;
163     ret = ERROR_NONE;
164   } else {
165     /* LCOV_EXCL_START */
166     LOGE("Sqlite err [%d][%s]", ret, sqlite3_errmsg(db));
167     ret = ERROR_FROM_DB;
168     /* LCOV_EXCL_STOP */
169   }
170
171   sqlite3_finalize(stmt);
172   return ret;
173 }
174
175 int DBManager::CheckDBIntegrity(void* user_data, int argc,
176                                        char** argv, char** notUsed) {
177   bool* is_db_corrupted = static_cast<bool*>(user_data);
178
179   if (std::string(argv[0]).compare("ok")) {
180     LOGE("db integrity result : %s", argv[0]);
181     *is_db_corrupted = true;
182     return -1;
183   }
184
185   LOGI("db integrity result : %s", argv[0]);
186   return 0;
187 }
188
189 int DBManager::RecoverCorruptedDB(sqlite3* db) {
190   int ret = ERROR_NONE;
191   char* errmsg = nullptr;
192
193   LOGI("DB is corrupted, start to recover corrupted db");
194   if (db)
195     sqlite3_close(db);
196   unlink(DBPATH);
197
198   ret = sqlite3_open_v2(DBPATH, &db,
199                         SQLITE_OPEN_CREATE | SQLITE_OPEN_READWRITE, nullptr);
200   if (ret != SQLITE_OK) {
201     LOGE("Failed to open db[%d]", ret);
202     unlink(DBPATH);
203     ret = ERROR_FROM_DB;
204     goto out;
205   }
206
207   ret = sqlite3_exec(db, CREATE_NOTIFICATION_TABLE, nullptr, nullptr, &errmsg);
208   if (ret != SQLITE_OK) {
209     LOGE("Failed to exec query[%d][%s]", ret, errmsg);
210     ret = ERROR_FROM_DB;
211   }
212
213 out:
214   if (errmsg)
215     sqlite3_free(errmsg);
216
217   return ret;
218 }
219
220 int DBManager::InitializeDB() {
221   int ret = ERROR_NONE;
222   int sql_ret;
223   sqlite3* db;
224   char *errmsg = nullptr;
225   bool is_db_corrupted = false;
226
227   sql_ret = sqlite3_open_v2(DBPATH, &db,
228                  SQLITE_OPEN_CREATE | SQLITE_OPEN_READWRITE, nullptr);
229   if (sql_ret != SQLITE_OK) {
230     LOGE("Failed to open db[%d]", ret);
231     ret = ERROR_FROM_DB;
232     goto out;
233   }
234
235   sql_ret = sqlite3_exec(db, CREATE_NOTIFICATION_TABLE, nullptr, nullptr, &errmsg);
236   if (sql_ret != SQLITE_OK) {
237     LOGE("Failed to exec sqlite[%d][%s]", ret, errmsg);
238     ret = ERROR_FROM_DB;
239     goto out;
240   }
241
242   sql_ret = sqlite3_exec(db, "PRAGMA foreign_keys = ON", NULL, NULL, NULL);
243   if (sql_ret != SQLITE_OK) {
244     LOGE("Failed to exec sqlite[%d][%s]", ret, errmsg);
245     ret = ERROR_FROM_DB;
246     goto out;
247   }
248
249   sql_ret = sqlite3_exec(db, "PRAGMA integrity_check",
250               CheckDBIntegrity, &is_db_corrupted, &errmsg);
251   if (sql_ret != SQLITE_OK || is_db_corrupted) {
252     LOGE("Failed to exec query[%d][%s]", sql_ret, errmsg);
253     ret = ERROR_FROM_DB;
254   }
255
256 out:
257   if (sql_ret == SQLITE_CORRUPT || sql_ret == SQLITE_NOTADB || is_db_corrupted)
258     ret = RecoverCorruptedDB(db);
259   if (errmsg)
260     sqlite3_free(errmsg);
261   if (db)
262     sqlite3_close(db);
263
264   return ret;
265 }
266
267 void DBManager::InitializeData() {
268   char* query;
269
270   query = sqlite3_mprintf("DELETE FROM noti_ex_list WHERE policy & %d",
271   static_cast<int>(item::AbstractItem::Policy::OnBootClear));
272   if (!query) {
273     LOGE("OOM - sql query");
274     return;
275   }
276
277   ExecuteQuery(query, nullptr);
278   sqlite3_free(query);
279 }
280
281 void DBManager::CheckLimit(shared_ptr<item::AbstractItem> addedItem, sqlite3* db) {
282   int ret, count;
283   char* query;
284   sqlite3_stmt* stmt = nullptr;
285   sqlite3_stmt* delete_stmt = nullptr;
286   uid_t uid =
287       static_pointer_cast<IItemInfoInternal>(addedItem->GetInfo())->GetUid();
288
289   ret = GetCount(addedItem->GetSenderAppId(), uid, &count);
290   if (ret != ERROR_NONE || count <= NOTI_LIMIT)
291     return;
292
293   query = sqlite3_mprintf("SELECT root_id FROM noti_ex_list WHERE uid = %d"
294                           " AND app_id = %Q ORDER BY insert_time ASC",
295                           uid, addedItem->GetSenderAppId().c_str());
296   if (query == nullptr) {
297     LOGE("OOM - sql query");
298     return;
299   }
300
301   ret = sqlite3_prepare_v2(db, query, -1, &stmt, nullptr);
302   if (ret != SQLITE_OK) {
303     /* LCOV_EXCL_START */
304     LOGE("sqlite3_prepare_v2 Failed [%d][%s]", ret, sqlite3_errmsg(db));
305     goto out;
306     /* LCOV_EXCL_STOP */
307   }
308
309   count -= NOTI_LIMIT;
310
311   sqlite3_free(query);
312   query = sqlite3_mprintf("DELETE FROM noti_ex_list"
313                           " WHERE root_id = ? AND app_id = %Q AND uid = %d",
314                           addedItem->GetSenderAppId().c_str(), uid);
315   if (query == nullptr) {
316     LOGE("OOM - sql query");
317     sqlite3_finalize(stmt);
318     return;
319   }
320
321   ret = sqlite3_prepare_v2(db, query, -1, &delete_stmt, nullptr);
322   if (ret != SQLITE_OK) {
323     /* LCOV_EXCL_START */
324     LOGE("sqlite3_prepare_v2 Failed [%d][%s]", ret, sqlite3_errmsg(db));
325     goto out;
326     /* LCOV_EXCL_STOP */
327   }
328
329   while (sqlite3_step(stmt) == SQLITE_ROW && count > 0) {
330     ret = sqlite3_bind_text(delete_stmt, 1,
331             reinterpret_cast<const char *>(sqlite3_column_text(stmt, 0)),
332             -1, SQLITE_TRANSIENT);
333     if (ret != SQLITE_OK) {
334       LOGE("sqlite3_bind_int() error: %d(%s)", ret, sqlite3_errmsg(db));
335       goto out;
336     }
337
338     ret = sqlite3_step(delete_stmt);
339     if (ret != SQLITE_DONE) {
340       LOGE("step error: %d(%s)", ret, sqlite3_errmsg(db));
341       goto out;
342     }
343
344     ret = sqlite3_reset(delete_stmt);
345     if (ret != SQLITE_OK) {
346       LOGE("sqlite3_reset() error: %d", ret);
347       goto out;
348     }
349
350     sqlite3_clear_bindings(delete_stmt);
351
352     count--;
353   }
354
355 out:
356   if (stmt)
357     sqlite3_finalize(stmt);
358   if (delete_stmt)
359     sqlite3_finalize(delete_stmt);
360   if (query)
361     sqlite3_free(query);
362 }
363
364 int DBManager::UpdateReceiverList
365     (shared_ptr<item::AbstractItem> updatedItem,  sqlite3* db) {
366   int ret;
367   char* query;
368   uid_t uid =
369       static_pointer_cast<IItemInfoInternal>(updatedItem->GetInfo())->GetUid();
370
371   query = sqlite3_mprintf("DELETE FROM receiver_list"
372             " WHERE root_id = %Q AND app_id = %Q AND uid = %d",
373             updatedItem->GetId().c_str(), updatedItem->GetSenderAppId().c_str(),
374             uid);
375   if (!query) {
376     LOGE("OOM - sql query");
377     return ERROR_OUT_OF_MEMORY;
378   }
379
380   ret = ExecuteQuery(db, query, nullptr);
381   sqlite3_free(query);
382
383   if (ret != ERROR_NONE)
384     return ret;
385
386   for (auto& i : updatedItem->GetReceiverList()) {
387     query = sqlite3_mprintf("INSERT INTO receiver_list"
388                             " (root_id, app_id, uid, receiver_group)"
389                             " VALUES (%Q, %Q, %d, %Q)",
390                             updatedItem->GetId().c_str(),
391                             updatedItem->GetSenderAppId().c_str(),
392                             uid,
393                             i.c_str());
394
395     if (!query) {
396       LOGE("OOM - sql query");
397       return ERROR_OUT_OF_MEMORY;
398     }
399
400     ret = ExecuteQuery(db, query, nullptr);
401     sqlite3_free(query);
402
403     if (ret != ERROR_NONE)
404       return ret;
405   }
406   return ERROR_NONE;
407 }
408
409 int DBManager::InsertNotification(list<shared_ptr<item::AbstractItem>> addedItem) {
410   int ret = ERROR_NONE;
411   int count;
412   char* query;
413   int64_t seq;
414   sqlite3* db = OpenDB();
415
416   if (db == nullptr)
417     return ERROR_FROM_DB;
418
419   if (sqlite3_exec(db, "BEGIN TRANSACTION", nullptr, nullptr, nullptr)) {
420     LOGE("begin transaction error : %s", sqlite3_errmsg(db));
421     CloseDB(db);
422     return ERROR_FROM_DB;
423   }
424
425   for (auto& i : addedItem) {
426     uid_t uid = static_pointer_cast<IItemInfoInternal>(i->GetInfo())->GetUid();
427     ret = GetCount(0, i->GetId(), i->GetSenderAppId(), uid, &count);
428     if (ret != ERROR_NONE)
429        break;
430
431     if (count > 0) {
432       LOGE("already exist id :[%s] appid[%s]",
433                i->GetId().c_str(), i->GetSenderAppId().c_str());
434       ret = ERROR_ALREADY_EXIST_ID;
435       break;
436     }
437
438     ret = GetSequence(db, &seq);
439     if (ret != ERROR_NONE)
440       break;
441
442     static_pointer_cast<IItemInfoInternal>(i->GetInfo())->SetPrivateId(seq);
443     Bundle b = i->Serialize();
444     query = sqlite3_mprintf("INSERT INTO noti_ex_list"
445           " (root_id, app_id, uid, channel, priv_id, pkg_id, policy, data, insert_time)"
446           " VALUES (%Q, %Q, %d, %Q, %" PRId64 ", %Q, %d, %Q, %d)",
447           i->GetId().c_str(),
448           i->GetSenderAppId().c_str(),
449           uid,
450           i->GetChannel().c_str(),
451           static_pointer_cast<IItemInfoInternal>(i->GetInfo())->GetPrivateId(),
452           GetPkgId(i->GetSenderAppId(), uid).c_str(),
453           static_cast<int>(i->GetPolicy()),
454           reinterpret_cast<char*>(b.ToRaw().first.get()),
455           static_pointer_cast<IItemInfo>(i->GetInfo())->GetTime());
456
457     if (!query) {
458       LOGE("OOM - sql query");
459       ret = ERROR_OUT_OF_MEMORY;
460       break;
461     }
462
463     ret = ExecuteQuery(db, query, nullptr);
464     sqlite3_free(query);
465     if (ret != ERROR_NONE)
466       break;
467
468     ret = UpdateReceiverList(i, db);
469     if (ret != ERROR_NONE)
470       break;
471   }
472
473   if (ret == ERROR_NONE) {
474     CheckLimit(*(addedItem.begin()), db);
475     if (sqlite3_exec(db, "END TRANSACTION", nullptr, nullptr, nullptr)) {
476       LOGE("end transaction error : %s", sqlite3_errmsg(db));
477       ret = ERROR_FROM_DB;
478     }
479   } else {
480     if (sqlite3_exec(db, "ROLLBACK TRANSACTION", nullptr, nullptr, nullptr))
481     LOGE("rollback transaction error : %s", sqlite3_errmsg(db));
482   }
483
484   CloseDB(db);
485   return ret;
486 }
487
488 map<string, string> DBManager::GetHideMap() {
489   map<string, string> hide_map;
490   char* query;
491   sqlite3_stmt* stmt;
492   sqlite3* db;
493   int ret;
494   string key;
495
496   query = sqlite3_mprintf("SELECT root_id, app_id, uid, hide_list FROM noti_ex_list"
497                             " WHERE hide_list IS NOT NULL");
498   if (!query) {
499     LOGE("OOM - sql query");
500     return hide_map;
501   }
502
503   db = OpenDB();
504   if (db == nullptr) {
505     sqlite3_free(query);
506     return hide_map;
507   }
508
509   ret = sqlite3_prepare_v2(db, query, strlen(query), &stmt, nullptr);
510   if (ret != SQLITE_OK) {
511     LOGE("Failed to sqlite3_prepare [%d][%s]", ret,     sqlite3_errmsg(db));
512     CloseDB(db);
513     sqlite3_free(query);
514     return hide_map;
515   }
516   sqlite3_free(query);
517
518   while (sqlite3_step(stmt) == SQLITE_ROW) {
519     key = string(reinterpret_cast<const char*>(sqlite3_column_text(stmt, 0))) \
520           + string(reinterpret_cast<const char*>(sqlite3_column_text(stmt, 1))) \
521           + string(to_string(sqlite3_column_int(stmt, 2)));
522     hide_map[key] = string(reinterpret_cast<const char*>(sqlite3_column_text(stmt, 3)));
523   }
524
525   sqlite3_finalize(stmt);
526   CloseDB(db);
527   return hide_map;
528 }
529
530 int DBManager::GetCount(const string& app_id, uid_t uid, int* count) {
531   return GetCount(0, string(), app_id, uid, count);
532 }
533
534 int DBManager::GetCount(int64_t priv_id, const string& root_id, const string& app_id,
535                               uid_t uid, int* count) {
536   int ret;
537   char* query;
538   sqlite3_stmt *stmt;
539   sqlite3* db;
540
541   if (priv_id != 0) {
542     query = sqlite3_mprintf("SELECT count(*) FROM noti_ex_list"
543                             " WHERE priv_id = %" PRId64 "", priv_id);
544   } else if (root_id.empty()) {
545     query = sqlite3_mprintf("SELECT count(*) FROM noti_ex_list"
546                             " WHERE app_id = %Q AND uid = %d", app_id.c_str(), uid);
547   } else {
548     query = sqlite3_mprintf("SELECT count(*) FROM noti_ex_list"
549                             " WHERE root_id = %Q AND app_id = %Q AND uid = %d",
550                             root_id.c_str(), app_id.c_str(), uid);
551   }
552   if (!query) {
553     LOGE("OOM - sql query");
554     return ERROR_OUT_OF_MEMORY;
555   }
556
557   db = OpenDB();
558   if (db == nullptr) {
559     sqlite3_free(query);
560     return ERROR_FROM_DB;
561   }
562
563   ret = sqlite3_prepare_v2(db, query, strlen(query), &stmt, nullptr);
564   if (ret != SQLITE_OK) {
565     LOGE("Failed to sqlite3_prepare [%d][%s]", ret,     sqlite3_errmsg(db));
566     sqlite3_free(query);
567     CloseDB(db);
568     return ERROR_FROM_DB;
569   }
570   sqlite3_free(query);
571
572   ret = sqlite3_step(stmt);
573   if (ret == SQLITE_ROW)
574     *count = sqlite3_column_int(stmt, 0);
575   else
576     *count = 0;
577
578   sqlite3_finalize(stmt);
579   CloseDB(db);
580   return ERROR_NONE;
581 }
582
583 int DBManager::UpdateHideList(shared_ptr<item::AbstractItem> updatedItem,
584     const string& hide_list) {
585   int ret;
586   char* query;
587
588   query = sqlite3_mprintf("UPDATE noti_ex_list SET hide_list = %Q"
589             " WHERE root_id = %Q AND app_id = %Q AND uid = %d",
590             hide_list.c_str(), updatedItem->GetId().c_str(),
591             updatedItem->GetSenderAppId().c_str(),
592             static_pointer_cast<IItemInfoInternal>(updatedItem->GetInfo())->GetUid());
593   if (!query) {
594     LOGE("OOM - sql query");
595     return ERROR_OUT_OF_MEMORY;
596   }
597
598   ret = ExecuteQuery(query, nullptr);
599   sqlite3_free(query);
600
601   return ret;
602 }
603
604 int DBManager::UpdateNotification(shared_ptr<item::AbstractItem> updatedItem) {
605   int count, ret;
606   char* query;
607   uid_t uid =
608       static_pointer_cast<IItemInfoInternal>(updatedItem->GetInfo())->GetUid();
609   int64_t priv_id = static_pointer_cast<IItemInfoInternal>(
610       updatedItem->GetInfo())->GetPrivateId();
611
612   ret = GetCount(priv_id,
613       updatedItem->GetId(), updatedItem->GetSenderAppId(), uid, &count);
614   if (ret != ERROR_NONE) {
615     LOGE("fail to get count");
616     return ret;
617   }
618
619   if (count <= 0) {
620     LOGE("not exist priv_id(%" PRId64 ") id(%s) for appid(%s)", priv_id,
621         updatedItem->GetId().c_str(), updatedItem->GetSenderAppId().c_str());
622     return ERROR_NOT_EXIST_ID;
623   }
624
625   sqlite3* db = OpenDB();
626   if (db == nullptr)
627     return ERROR_FROM_DB;
628
629   Bundle b = updatedItem->Serialize();
630   query = sqlite3_mprintf("UPDATE noti_ex_list SET"
631      " pkg_id = %Q, channel = %Q, policy = %d, data = %Q, insert_time = %d"
632      " WHERE priv_id = %" PRId64 "",
633      GetPkgId(updatedItem->GetSenderAppId(), uid).c_str(),
634      updatedItem->GetChannel().c_str(),
635      static_cast<int>(updatedItem->GetPolicy()),
636      reinterpret_cast<char*>(b.ToRaw().first.get()),
637      static_pointer_cast<IItemInfo>(updatedItem->GetInfo())->GetTime(),
638      priv_id);
639
640   if (!query) {
641     LOGE("OOM - sql query");
642     CloseDB(db);
643     return ERROR_OUT_OF_MEMORY;
644   }
645
646   if (sqlite3_exec(db, "BEGIN TRANSACTION", nullptr, nullptr, nullptr)) {
647     LOGE("begin transaction error : %s", sqlite3_errmsg(db));
648     sqlite3_free(query);
649     CloseDB(db);
650     return ERROR_FROM_DB;
651   }
652
653   ret = ExecuteQuery(db, query, nullptr);
654   sqlite3_free(query);
655   if (ret != ERROR_NONE)
656     goto out;
657
658   ret = UpdateReceiverList(updatedItem, db);
659
660 out:
661   if (ret == ERROR_NONE) {
662     if (sqlite3_exec(db, "END TRANSACTION", nullptr, nullptr, nullptr)) {
663       LOGE("end transaction error : %s", sqlite3_errmsg(db));
664       ret = ERROR_FROM_DB;
665     }
666   } else {
667     if (sqlite3_exec(db, "ROLLBACK TRANSACTION", nullptr, nullptr, nullptr))
668     LOGE("rollback transaction error : %s", sqlite3_errmsg(db));
669   }
670
671   CloseDB(db);
672   return ret;
673 }
674
675 list<shared_ptr<item::AbstractItem>> DBManager::ExecuteGetList(char* query) {
676   sqlite3_stmt *stmt;
677   sqlite3* db;
678   int ret;
679   list<shared_ptr<item::AbstractItem>> item_list;
680
681   if (!query) {
682     LOGE("Invalid parameter");
683     return item_list;
684   }
685
686   db = OpenDB();
687   if (db == nullptr)
688     return item_list;
689
690   ret = sqlite3_prepare_v2(db, query, strlen(query), &stmt, nullptr);
691   if (ret != SQLITE_OK) {
692     LOGE("Failed to sqlite3_prepare [%d][%s]", ret, sqlite3_errmsg(db));
693     CloseDB(db);
694     return item_list;
695   }
696
697   while (sqlite3_step(stmt) == SQLITE_ROW) {
698     LOGE("[%s]", sqlite3_column_text(stmt, 0));
699
700     Bundle serialized(reinterpret_cast<const char*>(sqlite3_column_text(stmt, 0)));
701     shared_ptr<item::AbstractItem> gen_item = item::ItemInflator::Create(serialized);
702     item_list.emplace_back(gen_item);
703   }
704
705   sqlite3_finalize(stmt);
706   CloseDB(db);
707   return item_list;
708 }
709
710 list<shared_ptr<item::AbstractItem>> DBManager::GetNotificationList(
711     string app_id, uid_t uid) {
712   char* query;
713   list<shared_ptr<item::AbstractItem>> item_list;
714
715   query = sqlite3_mprintf("SELECT data FROM noti_ex_list"
716                     " WHERE uid = %d AND app_id = %Q ORDER BY insert_time DESC",
717                     uid, app_id.c_str());
718   if (!query) {
719     LOGE("OOM - sql query");
720     return item_list;
721   }
722
723   item_list = ExecuteGetList(query);
724   sqlite3_free(query);
725
726   return item_list;
727 }
728
729 list<shared_ptr<item::AbstractItem>> DBManager::GetNotificationList
730                              (string app_id, string root_id, uid_t uid) {
731   char* query;
732   list<shared_ptr<item::AbstractItem>> item_list;
733
734   query = sqlite3_mprintf("SELECT data FROM noti_ex_list"
735                            " WHERE uid = %d AND app_id = %Q AND root_id = %Q",
736                            uid, app_id.c_str(), root_id.c_str());
737
738   if (!query) {
739     LOGE("OOM - sql query");
740     return item_list;
741   }
742
743   item_list = ExecuteGetList(query);
744   sqlite3_free(query);
745
746   return item_list;
747 }
748
749 list<shared_ptr<item::AbstractItem>> DBManager::GetNotificationList
750                              (string app_id, int64_t priv_id, uid_t uid) {
751   char* query;
752   list<shared_ptr<item::AbstractItem>> item_list;
753
754   query = sqlite3_mprintf("SELECT data FROM noti_ex_list"
755       " WHERE uid = %d AND app_id = %Q AND priv_id = %" PRId64 "",
756       uid, app_id.c_str(), priv_id);
757
758   if (!query) {
759     LOGE("OOM - sql query");
760     return item_list;
761   }
762
763   item_list = ExecuteGetList(query);
764   sqlite3_free(query);
765
766   return item_list;
767 }
768
769 list<shared_ptr<item::AbstractItem>> DBManager::GetNotificationList(
770       uid_t uid, string channel) {
771   int ret, sim_mode;
772   char* query;
773   list<shared_ptr<item::AbstractItem>> item_list;
774
775   /* Check current sim status */
776   ret = vconf_get_int(VCONFKEY_TELEPHONY_SIM_SLOT, &sim_mode);
777   if (ret < 0) {
778     sim_mode = VCONFKEY_TELEPHONY_SIM_INSERTED;
779     LOGI("vconf_get_int");
780   }
781
782   string channel_query;
783   if (!channel.empty())
784     channel_query = " AND channel = '" + channel + "' ";
785
786   string simmode_query;
787   if (sim_mode != VCONFKEY_TELEPHONY_SIM_INSERTED) {
788     simmode_query = " AND (policy & " +
789         to_string(static_cast<int>(item::AbstractItem::Policy::SimMode)) +
790         ") == 0 ";
791   }
792
793   string query_str = "SELECT data FROM noti_ex_list WHERE uid = %d " +
794       channel_query +
795       simmode_query;
796
797   query = sqlite3_mprintf(query_str.c_str(), uid);
798   if (!query) {
799     LOGE("OOM - sql query");
800     return item_list;
801   }
802
803   item_list = ExecuteGetList(query);
804   sqlite3_free(query);
805
806   return item_list;
807 }
808
809 int DBManager::DeleteNotification(shared_ptr<item::AbstractItem> deletedItem) {
810   int ret;
811   char* query;
812   int64_t priv_id = static_pointer_cast<IItemInfoInternal>(
813       deletedItem->GetInfo())->GetPrivateId();
814
815   query = sqlite3_mprintf("DELETE FROM noti_ex_list WHERE priv_id = %" PRId64 "",
816       priv_id);
817   if (!query) {
818     LOGE("OOM - sql query");
819     return ERROR_OUT_OF_MEMORY;
820   }
821
822   ret = ExecuteQuery(query, nullptr);
823   sqlite3_free(query);
824   return ret;
825 }
826
827 string DBManager::GetPkgId(const string& app_id, uid_t uid) {
828   pkgmgrinfo_pkginfo_h handle;
829   char *buf = nullptr;
830   string pkgid;
831
832   if (pkgmgrinfo_appinfo_get_usr_appinfo(app_id.c_str(), uid, &handle) == PMINFO_R_OK) {
833     if (pkgmgrinfo_appinfo_get_pkgid(handle, &buf) == PMINFO_R_OK) {
834       if (buf)
835         pkgid = string(buf);
836     }
837     pkgmgrinfo_appinfo_destroy_appinfo(handle);
838   }
839   return pkgid;
840 }
841 }  // namespace notification