Update description for chat_message item
[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   ret = sqlite3_prepare_v2(db, query.c_str(), query.size(), &stmt, nullptr);
156   if (ret != SQLITE_OK) {
157     /* LCOV_EXCL_START */
158     LOGE("Sqlite3 err[%d][%s]", ret, sqlite3_errmsg(db));
159     return ERROR_FROM_DB;
160     /* LCOV_EXCL_STOP */
161   }
162
163   ret = sqlite3_step(stmt);
164   if (ret == SQLITE_ROW) {
165     int64_t min_p = sqlite3_column_int64(stmt, 0);
166     if (min_p > 1)
167       *seq = min_p - 1;
168     else
169       *seq = sqlite3_column_int64(stmt, 1) + 1;
170     ret = ERROR_NONE;
171   } else {
172     /* LCOV_EXCL_START */
173     LOGE("Sqlite err [%d][%s]", ret, sqlite3_errmsg(db));
174     ret = ERROR_FROM_DB;
175     /* LCOV_EXCL_STOP */
176   }
177
178   sqlite3_finalize(stmt);
179   return ret;
180 }
181
182 int DBManager::CheckDBIntegrity(void* user_data, int argc,
183                                        char** argv, char** notUsed) {
184   bool* is_db_corrupted = static_cast<bool*>(user_data);
185
186   if (std::string(argv[0]).compare("ok")) {
187     LOGE("db integrity result : %s", argv[0]);
188     *is_db_corrupted = true;
189     return -1;
190   }
191
192   LOGI("db integrity result : %s", argv[0]);
193   return 0;
194 }
195
196 int DBManager::RecoverCorruptedDB(sqlite3* db) {
197   int ret = ERROR_NONE;
198   char* errmsg = nullptr;
199
200   LOGI("DB is corrupted, start to recover corrupted db");
201   if (db)
202     sqlite3_close(db);
203   unlink(DBPATH);
204
205   ret = sqlite3_open_v2(DBPATH, &db,
206                         SQLITE_OPEN_CREATE | SQLITE_OPEN_READWRITE, nullptr);
207   if (ret != SQLITE_OK) {
208     LOGE("Failed to open db[%d]", ret);
209     unlink(DBPATH);
210     ret = ERROR_FROM_DB;
211     goto out;
212   }
213
214   ret = sqlite3_exec(db, CREATE_NOTIFICATION_TABLE, nullptr, nullptr, &errmsg);
215   if (ret != SQLITE_OK) {
216     LOGE("Failed to exec query[%d][%s]", ret, errmsg);
217     ret = ERROR_FROM_DB;
218   }
219
220 out:
221   if (errmsg)
222     sqlite3_free(errmsg);
223
224   return ret;
225 }
226
227 int DBManager::InitializeDB() {
228   int ret = ERROR_NONE;
229   int sql_ret;
230   sqlite3* db;
231   char *errmsg = nullptr;
232   bool is_db_corrupted = false;
233
234   sql_ret = sqlite3_open_v2(DBPATH, &db,
235                  SQLITE_OPEN_CREATE | SQLITE_OPEN_READWRITE, nullptr);
236   if (sql_ret != SQLITE_OK) {
237     LOGE("Failed to open db[%d]", ret);
238     ret = ERROR_FROM_DB;
239     goto out;
240   }
241
242   sql_ret = sqlite3_exec(db, CREATE_NOTIFICATION_TABLE, nullptr, nullptr, &errmsg);
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 foreign_keys = ON", NULL, NULL, NULL);
250   if (sql_ret != SQLITE_OK) {
251     LOGE("Failed to exec sqlite[%d][%s]", ret, errmsg);
252     ret = ERROR_FROM_DB;
253     goto out;
254   }
255
256   sql_ret = sqlite3_exec(db, "PRAGMA integrity_check",
257               CheckDBIntegrity, &is_db_corrupted, &errmsg);
258   if (sql_ret != SQLITE_OK || is_db_corrupted) {
259     LOGE("Failed to exec query[%d][%s]", sql_ret, errmsg);
260     ret = ERROR_FROM_DB;
261   }
262
263 out:
264   if (sql_ret == SQLITE_CORRUPT || sql_ret == SQLITE_NOTADB || is_db_corrupted)
265     ret = RecoverCorruptedDB(db);
266   if (errmsg)
267     sqlite3_free(errmsg);
268   if (db)
269     sqlite3_close(db);
270
271   return ret;
272 }
273
274 void DBManager::InitializeData() {
275   char* query;
276
277   query = sqlite3_mprintf("DELETE FROM noti_ex_list WHERE policy & %d",
278   static_cast<int>(item::AbstractItem::Policy::OnBootClear));
279   if (!query) {
280     LOGE("OOM - sql query");
281     return;
282   }
283
284   ExecuteQuery(query, nullptr);
285   sqlite3_free(query);
286 }
287
288 void DBManager::CheckLimit(shared_ptr<item::AbstractItem> addedItem, sqlite3* db) {
289   int ret, count;
290   char* query;
291   sqlite3_stmt* stmt = nullptr;
292   sqlite3_stmt* delete_stmt = nullptr;
293   uid_t uid =
294       static_pointer_cast<IItemInfoInternal>(addedItem->GetInfo())->GetUid();
295
296   ret = GetCount(addedItem->GetSenderAppId(), uid, &count);
297   if (ret != ERROR_NONE || count <= NOTI_LIMIT)
298     return;
299
300   query = sqlite3_mprintf("SELECT root_id FROM noti_ex_list WHERE uid = %d"
301                           " AND app_id = %Q ORDER BY insert_time ASC",
302                           uid, addedItem->GetSenderAppId().c_str());
303   if (query == nullptr) {
304     LOGE("OOM - sql query");
305     return;
306   }
307
308   ret = sqlite3_prepare_v2(db, query, -1, &stmt, nullptr);
309   if (ret != SQLITE_OK) {
310     /* LCOV_EXCL_START */
311     LOGE("sqlite3_prepare_v2 Failed [%d][%s]", ret, sqlite3_errmsg(db));
312     goto out;
313     /* LCOV_EXCL_STOP */
314   }
315
316   count -= NOTI_LIMIT;
317
318   sqlite3_free(query);
319   query = sqlite3_mprintf("DELETE FROM noti_ex_list"
320                           " WHERE root_id = ? AND app_id = %Q AND uid = %d",
321                           addedItem->GetSenderAppId().c_str(), uid);
322   if (query == nullptr) {
323     LOGE("OOM - sql query");
324     sqlite3_finalize(stmt);
325     return;
326   }
327
328   ret = sqlite3_prepare_v2(db, query, -1, &delete_stmt, nullptr);
329   if (ret != SQLITE_OK) {
330     /* LCOV_EXCL_START */
331     LOGE("sqlite3_prepare_v2 Failed [%d][%s]", ret, sqlite3_errmsg(db));
332     goto out;
333     /* LCOV_EXCL_STOP */
334   }
335
336   while (sqlite3_step(stmt) == SQLITE_ROW && count > 0) {
337     ret = sqlite3_bind_text(delete_stmt, 1,
338             reinterpret_cast<const char *>(sqlite3_column_text(stmt, 0)),
339             -1, SQLITE_TRANSIENT);
340     if (ret != SQLITE_OK) {
341       LOGE("sqlite3_bind_int() error: %d(%s)", ret, sqlite3_errmsg(db));
342       goto out;
343     }
344
345     ret = sqlite3_step(delete_stmt);
346     if (ret != SQLITE_DONE) {
347       LOGE("step error: %d(%s)", ret, sqlite3_errmsg(db));
348       goto out;
349     }
350
351     ret = sqlite3_reset(delete_stmt);
352     if (ret != SQLITE_OK) {
353       LOGE("sqlite3_reset() error: %d", ret);
354       goto out;
355     }
356
357     sqlite3_clear_bindings(delete_stmt);
358
359     count--;
360   }
361
362 out:
363   if (stmt)
364     sqlite3_finalize(stmt);
365   if (delete_stmt)
366     sqlite3_finalize(delete_stmt);
367   if (query)
368     sqlite3_free(query);
369 }
370
371 int DBManager::UpdateReceiverList
372     (shared_ptr<item::AbstractItem> updatedItem,  sqlite3* db) {
373   int ret;
374   char* query;
375   uid_t uid =
376       static_pointer_cast<IItemInfoInternal>(updatedItem->GetInfo())->GetUid();
377
378   query = sqlite3_mprintf("DELETE FROM receiver_list"
379             " WHERE root_id = %Q AND app_id = %Q AND uid = %d",
380             updatedItem->GetId().c_str(), updatedItem->GetSenderAppId().c_str(),
381             uid);
382   if (!query) {
383     LOGE("OOM - sql query");
384     return ERROR_OUT_OF_MEMORY;
385   }
386
387   ret = ExecuteQuery(db, query, nullptr);
388   sqlite3_free(query);
389
390   if (ret != ERROR_NONE)
391     return ret;
392
393   for (auto& i : updatedItem->GetReceiverList()) {
394     query = sqlite3_mprintf("INSERT INTO receiver_list"
395                             " (root_id, app_id, uid, receiver_group)"
396                             " VALUES (%Q, %Q, %d, %Q)",
397                             updatedItem->GetId().c_str(),
398                             updatedItem->GetSenderAppId().c_str(),
399                             uid,
400                             i.c_str());
401
402     if (!query) {
403       LOGE("OOM - sql query");
404       return ERROR_OUT_OF_MEMORY;
405     }
406
407     ret = ExecuteQuery(db, query, nullptr);
408     sqlite3_free(query);
409
410     if (ret != ERROR_NONE)
411       return ret;
412   }
413   return ERROR_NONE;
414 }
415
416 int DBManager::InsertNotification(list<shared_ptr<item::AbstractItem>> addedList) {
417   int ret = ERROR_NONE;
418   char* query;
419   int64_t priv_id = 0;
420   sqlite3* db = OpenDB();
421
422   if (db == nullptr)
423     return ERROR_FROM_DB;
424
425   if (sqlite3_exec(db, "BEGIN TRANSACTION", nullptr, nullptr, nullptr)) {
426     LOGE("begin transaction error : %s", sqlite3_errmsg(db));
427     CloseDB(db);
428     return ERROR_FROM_DB;
429   }
430
431   for (auto& i : addedList) {
432     uid_t uid = static_pointer_cast<IItemInfoInternal>(i->GetInfo())->GetUid();
433     list<shared_ptr<item::AbstractItem>> item_list =
434         GetNotificationList(i->GetSenderAppId(), i->GetId(), uid);
435
436     if (!item_list.empty())
437       priv_id =
438         static_pointer_cast<IItemInfoInternal>(item_list.front()->GetInfo())->GetPrivateId();
439     else
440       ret = GetSequence(db, &priv_id);
441
442     if (ret != ERROR_NONE || priv_id == 0) {
443       LOGE("Failed to get pirv_id");
444       break;
445     }
446
447     static_pointer_cast<IItemInfoInternal>(i->GetInfo())->SetPrivateId(priv_id);
448     Bundle b = i->Serialize();
449
450     query = sqlite3_mprintf("INSERT OR REPLACE INTO noti_ex_list"
451           " (root_id, app_id, uid, channel, priv_id, pkg_id, policy, data, insert_time)"
452           " VALUES (%Q, %Q, %d, %Q, %" PRId64 ", %Q, %d, %Q, %d)",
453           i->GetId().c_str(),
454           i->GetSenderAppId().c_str(),
455           uid,
456           i->GetChannel().c_str(),
457           priv_id,
458           GetPkgId(i->GetSenderAppId(), uid).c_str(),
459           static_cast<int>(i->GetPolicy()),
460           reinterpret_cast<char*>(b.ToRaw().first.get()),
461           static_pointer_cast<IItemInfo>(i->GetInfo())->GetTime());
462     if (!query) {
463       LOGE("OOM - sql query");
464       ret = ERROR_OUT_OF_MEMORY;
465       break;
466     }
467
468     ret = ExecuteQuery(db, query, nullptr);
469     sqlite3_free(query);
470     if (ret != ERROR_NONE)
471       break;
472
473     ret = UpdateReceiverList(i, db);
474     if (ret != ERROR_NONE)
475       break;
476   }
477
478   if (ret == ERROR_NONE) {
479     CheckLimit(*(addedList.begin()), db);
480     if (sqlite3_exec(db, "END TRANSACTION", nullptr, nullptr, nullptr)) {
481       LOGE("end transaction error : %s", sqlite3_errmsg(db));
482       ret = ERROR_FROM_DB;
483     }
484   } else {
485     if (sqlite3_exec(db, "ROLLBACK TRANSACTION", nullptr, nullptr, nullptr))
486     LOGE("rollback transaction error : %s", sqlite3_errmsg(db));
487   }
488
489   CloseDB(db);
490   return ret;
491 }
492
493 map<string, string> DBManager::GetHideMap() {
494   map<string, string> hide_map;
495   char* query;
496   sqlite3_stmt* stmt;
497   sqlite3* db;
498   int ret;
499   string key;
500
501   query = sqlite3_mprintf("SELECT root_id, app_id, uid, hide_list FROM noti_ex_list"
502                             " WHERE hide_list IS NOT NULL");
503   if (!query) {
504     LOGE("OOM - sql query");
505     return hide_map;
506   }
507
508   db = OpenDB();
509   if (db == nullptr) {
510     sqlite3_free(query);
511     return hide_map;
512   }
513
514   ret = sqlite3_prepare_v2(db, query, strlen(query), &stmt, nullptr);
515   if (ret != SQLITE_OK) {
516     LOGE("Failed to sqlite3_prepare [%d][%s]", ret,     sqlite3_errmsg(db));
517     CloseDB(db);
518     sqlite3_free(query);
519     return hide_map;
520   }
521   sqlite3_free(query);
522
523   while (sqlite3_step(stmt) == SQLITE_ROW) {
524     key = string(reinterpret_cast<const char*>(sqlite3_column_text(stmt, 0))) \
525           + string(reinterpret_cast<const char*>(sqlite3_column_text(stmt, 1))) \
526           + string(to_string(sqlite3_column_int(stmt, 2)));
527     hide_map[key] = string(reinterpret_cast<const char*>(sqlite3_column_text(stmt, 3)));
528   }
529
530   sqlite3_finalize(stmt);
531   CloseDB(db);
532   return hide_map;
533 }
534
535 int DBManager::GetCount(const string& app_id, uid_t uid, int* count) {
536   return GetCount(0, string(), app_id, uid, count);
537 }
538
539 int DBManager::GetCount(int64_t priv_id, const string& root_id, const string& app_id,
540                               uid_t uid, int* count) {
541   int ret;
542   char* query;
543   sqlite3_stmt *stmt;
544   sqlite3* db;
545
546   if (priv_id != 0) {
547     query = sqlite3_mprintf("SELECT count(*) FROM noti_ex_list"
548                             " WHERE priv_id = %" PRId64 "", priv_id);
549   } else if (root_id.empty()) {
550     query = sqlite3_mprintf("SELECT count(*) FROM noti_ex_list"
551                             " WHERE app_id = %Q AND uid = %d", app_id.c_str(), uid);
552   } else {
553     query = sqlite3_mprintf("SELECT count(*) FROM noti_ex_list"
554                             " WHERE root_id = %Q AND app_id = %Q AND uid = %d",
555                             root_id.c_str(), app_id.c_str(), uid);
556   }
557   if (!query) {
558     LOGE("OOM - sql query");
559     return ERROR_OUT_OF_MEMORY;
560   }
561
562   db = OpenDB();
563   if (db == nullptr) {
564     sqlite3_free(query);
565     return ERROR_FROM_DB;
566   }
567
568   ret = sqlite3_prepare_v2(db, query, strlen(query), &stmt, nullptr);
569   if (ret != SQLITE_OK) {
570     LOGE("Failed to sqlite3_prepare [%d][%s]", ret,     sqlite3_errmsg(db));
571     sqlite3_free(query);
572     CloseDB(db);
573     return ERROR_FROM_DB;
574   }
575   sqlite3_free(query);
576
577   ret = sqlite3_step(stmt);
578   if (ret == SQLITE_ROW)
579     *count = sqlite3_column_int(stmt, 0);
580   else
581     *count = 0;
582
583   sqlite3_finalize(stmt);
584   CloseDB(db);
585   return ERROR_NONE;
586 }
587
588 int DBManager::UpdateHideList(shared_ptr<item::AbstractItem> updatedItem,
589     const string& hide_list) {
590   int ret;
591   char* query;
592
593   query = sqlite3_mprintf("UPDATE noti_ex_list SET hide_list = %Q"
594             " WHERE root_id = %Q AND app_id = %Q AND uid = %d",
595             hide_list.c_str(), updatedItem->GetId().c_str(),
596             updatedItem->GetSenderAppId().c_str(),
597             static_pointer_cast<IItemInfoInternal>(updatedItem->GetInfo())->GetUid());
598   if (!query) {
599     LOGE("OOM - sql query");
600     return ERROR_OUT_OF_MEMORY;
601   }
602
603   ret = ExecuteQuery(query, nullptr);
604   sqlite3_free(query);
605
606   return ret;
607 }
608
609 int DBManager::UpdateNotification(list<shared_ptr<item::AbstractItem>> updatedList) {
610   int ret = ERROR_NONE;
611   char* query;
612   sqlite3* db = OpenDB();
613   if (db == nullptr)
614     return ERROR_FROM_DB;
615
616   if (sqlite3_exec(db, "BEGIN TRANSACTION", nullptr, nullptr, nullptr)) {
617     LOGE("begin transaction error : %s", sqlite3_errmsg(db));
618     CloseDB(db);
619     return ERROR_FROM_DB;
620   }
621
622   for (auto& i : updatedList) {
623     uid_t uid = static_pointer_cast<IItemInfoInternal>(i->GetInfo())->GetUid();
624     list<shared_ptr<item::AbstractItem>> item_list =
625         GetNotificationList(i->GetSenderAppId(), i->GetId(), uid);
626
627     if (item_list.empty()) {
628       LOGE("not exist id(%s) for appid(%s)", i->GetId().c_str(), i->GetSenderAppId().c_str());
629       ret = ERROR_NOT_EXIST_ID;
630       break;
631     }
632
633     Bundle b = i->Serialize();
634     query = sqlite3_mprintf("UPDATE noti_ex_list SET"
635         " pkg_id = %Q, channel = %Q, policy = %d, data = %Q, insert_time = %d"
636         " WHERE priv_id = %" PRId64 "",
637         GetPkgId(i->GetSenderAppId(), uid).c_str(),
638         i->GetChannel().c_str(),
639         static_cast<int>(i->GetPolicy()),
640         reinterpret_cast<char*>(b.ToRaw().first.get()),
641         static_pointer_cast<IItemInfo>(i->GetInfo())->GetTime(),
642         static_pointer_cast<IItemInfoInternal>(item_list.front()->GetInfo())->GetPrivateId());
643     if (!query) {
644       LOGE("OOM - sql query");
645       ret = ERROR_OUT_OF_MEMORY;
646       break;
647     }
648
649     ret = ExecuteQuery(db, query, nullptr);
650     sqlite3_free(query);
651     if (ret != ERROR_NONE)
652       break;
653
654     ret = UpdateReceiverList(i, db);
655     if (ret != ERROR_NONE)
656       break;
657   }
658
659   if (ret == ERROR_NONE) {
660     if (sqlite3_exec(db, "END TRANSACTION", nullptr, nullptr, nullptr)) {
661       LOGE("end transaction error : %s", sqlite3_errmsg(db));
662       ret = ERROR_FROM_DB;
663     }
664   } else {
665     if (sqlite3_exec(db, "ROLLBACK TRANSACTION", nullptr, nullptr, nullptr))
666       LOGE("rollback transaction error : %s", sqlite3_errmsg(db));
667   }
668
669   CloseDB(db);
670   return ret;
671 }
672
673 list<shared_ptr<item::AbstractItem>> DBManager::ExecuteGetList(char* query) {
674   sqlite3_stmt *stmt;
675   sqlite3* db;
676   int ret;
677   list<shared_ptr<item::AbstractItem>> item_list;
678
679   if (!query) {
680     LOGE("Invalid parameter");
681     return item_list;
682   }
683
684   db = OpenDB();
685   if (db == nullptr)
686     return item_list;
687
688   ret = sqlite3_prepare_v2(db, query, strlen(query), &stmt, nullptr);
689   if (ret != SQLITE_OK) {
690     LOGE("Failed to sqlite3_prepare [%d][%s]", ret, sqlite3_errmsg(db));
691     CloseDB(db);
692     return item_list;
693   }
694
695   while (sqlite3_step(stmt) == SQLITE_ROW) {
696     LOGE("[%s]", sqlite3_column_text(stmt, 0));
697
698     Bundle serialized(reinterpret_cast<const char*>(sqlite3_column_text(stmt, 0)));
699     shared_ptr<item::AbstractItem> gen_item = item::ItemInflator::Create(serialized);
700     item_list.emplace_back(gen_item);
701   }
702
703   sqlite3_finalize(stmt);
704   CloseDB(db);
705   return item_list;
706 }
707
708 list<shared_ptr<item::AbstractItem>> DBManager::GetNotificationList(
709     string app_id, uid_t uid, string channel) {
710   char* query;
711   list<shared_ptr<item::AbstractItem>> item_list;
712
713   if (!channel.empty()) {
714     query = sqlite3_mprintf("SELECT data FROM noti_ex_list WHERE uid = %d "
715       "AND app_id = %Q AND channel = %Q ORDER BY insert_time DESC", uid,
716       app_id.c_str(), channel.c_str());
717   } else {
718     query = sqlite3_mprintf("SELECT data FROM noti_ex_list WHERE uid = %d "
719       "AND app_id = %Q ORDER BY insert_time DESC", uid, app_id.c_str());
720   }
721
722   if (!query) {
723     LOGE("OOM - sql query");
724     return item_list;
725   }
726
727   item_list = ExecuteGetList(query);
728   sqlite3_free(query);
729
730   return item_list;
731 }
732
733 list<shared_ptr<item::AbstractItem>> DBManager::GetNotificationList(
734     string app_id, string root_id, uid_t uid) {
735   char* query;
736   list<shared_ptr<item::AbstractItem>> item_list;
737
738   query = sqlite3_mprintf("SELECT data FROM noti_ex_list"
739                            " WHERE uid = %d AND app_id = %Q AND root_id = %Q",
740                            uid, app_id.c_str(), root_id.c_str());
741
742   if (!query) {
743     LOGE("OOM - sql query");
744     return item_list;
745   }
746
747   item_list = ExecuteGetList(query);
748   sqlite3_free(query);
749
750   return item_list;
751 }
752
753 list<shared_ptr<item::AbstractItem>> DBManager::GetNotificationList(
754     string app_id, int64_t priv_id, uid_t uid) {
755   char* query;
756   list<shared_ptr<item::AbstractItem>> item_list;
757
758   query = sqlite3_mprintf("SELECT data FROM noti_ex_list"
759       " WHERE uid = %d AND app_id = %Q AND priv_id = %" PRId64 "",
760       uid, app_id.c_str(), priv_id);
761
762   if (!query) {
763     LOGE("OOM - sql query");
764     return item_list;
765   }
766
767   item_list = ExecuteGetList(query);
768   sqlite3_free(query);
769
770   return item_list;
771 }
772
773 list<shared_ptr<item::AbstractItem>> DBManager::GetNotificationList(
774     uid_t uid, string channel) {
775   int ret, sim_mode;
776   char* query;
777   list<shared_ptr<item::AbstractItem>> item_list;
778
779   /* Check current sim status */
780   ret = vconf_get_int(VCONFKEY_TELEPHONY_SIM_SLOT, &sim_mode);
781   if (ret < 0) {
782     sim_mode = VCONFKEY_TELEPHONY_SIM_INSERTED;
783     LOGI("vconf_get_int");
784   }
785
786   string channel_query;
787   if (!channel.empty())
788     channel_query = " AND channel = '" + channel + "' ";
789
790   string simmode_query;
791   if (sim_mode != VCONFKEY_TELEPHONY_SIM_INSERTED) {
792     simmode_query = " AND (policy & " +
793         to_string(static_cast<int>(item::AbstractItem::Policy::SimMode)) +
794         ") == 0 ";
795   }
796
797   string query_str = "SELECT data FROM noti_ex_list WHERE uid = %d " +
798       channel_query +
799       simmode_query;
800
801   query = sqlite3_mprintf(query_str.c_str(), uid);
802   if (!query) {
803     LOGE("OOM - sql query");
804     return item_list;
805   }
806
807   item_list = ExecuteGetList(query);
808   sqlite3_free(query);
809
810   return item_list;
811 }
812
813 int DBManager::DeleteNotification(
814     list<shared_ptr<item::AbstractItem>> deletedList) {
815   int ret = ERROR_NONE;
816   char* query;
817   sqlite3* db = OpenDB();
818   if (db == nullptr)
819     return ERROR_FROM_DB;
820
821   if (sqlite3_exec(db, "BEGIN TRANSACTION", nullptr, nullptr, nullptr)) {
822     LOGE("begin transaction error : %s", sqlite3_errmsg(db));
823     CloseDB(db);
824     return ERROR_FROM_DB;
825   }
826
827   for (auto& i : deletedList) {
828     query = sqlite3_mprintf("DELETE FROM noti_ex_list WHERE priv_id = %" PRId64 "",
829       static_pointer_cast<IItemInfoInternal>(i->GetInfo())->GetPrivateId());
830     if (!query) {
831       LOGE("OOM - sql query");
832       ret = ERROR_OUT_OF_MEMORY;
833       break;
834     }
835
836     ret = ExecuteQuery(db, query, nullptr);
837     sqlite3_free(query);
838     if (ret != ERROR_NONE)
839       break;
840   }
841
842   if (ret == ERROR_NONE) {
843     if (sqlite3_exec(db, "END TRANSACTION", nullptr, nullptr, nullptr)) {
844       LOGE("end transaction error : %s", sqlite3_errmsg(db));
845       ret = ERROR_FROM_DB;
846     }
847   } else {
848     if (sqlite3_exec(db, "ROLLBACK TRANSACTION", nullptr, nullptr, nullptr))
849     LOGE("rollback transaction error : %s", sqlite3_errmsg(db));
850   }
851
852   CloseDB(db);
853   return ret;
854 }
855
856 string DBManager::GetPkgId(const string& app_id, uid_t uid) {
857   pkgmgrinfo_pkginfo_h handle;
858   char *buf = nullptr;
859   string pkgid;
860
861   if (pkgmgrinfo_appinfo_get_usr_appinfo(app_id.c_str(), uid, &handle) == PMINFO_R_OK) {
862     if (pkgmgrinfo_appinfo_get_pkgid(handle, &buf) == PMINFO_R_OK) {
863       if (buf)
864         pkgid = string(buf);
865     }
866     pkgmgrinfo_appinfo_destroy_appinfo(handle);
867   }
868   return pkgid;
869 }
870 }  // namespace notification