Merge branch 'tizen' into tizen_5.5
[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>> addedItem) {
417   int ret = ERROR_NONE;
418   int count;
419   char* query;
420   int64_t seq;
421   sqlite3* db = OpenDB();
422
423   if (db == nullptr)
424     return ERROR_FROM_DB;
425
426   if (sqlite3_exec(db, "BEGIN TRANSACTION", nullptr, nullptr, nullptr)) {
427     LOGE("begin transaction error : %s", sqlite3_errmsg(db));
428     CloseDB(db);
429     return ERROR_FROM_DB;
430   }
431
432   for (auto& i : addedItem) {
433     uid_t uid = static_pointer_cast<IItemInfoInternal>(i->GetInfo())->GetUid();
434     ret = GetCount(0, i->GetId(), i->GetSenderAppId(), uid, &count);
435     if (ret != ERROR_NONE)
436        break;
437
438     if (count > 0) {
439       LOGE("already exist id :[%s] appid[%s]",
440                i->GetId().c_str(), i->GetSenderAppId().c_str());
441       ret = ERROR_ALREADY_EXIST_ID;
442       break;
443     }
444
445     ret = GetSequence(db, &seq);
446     if (ret != ERROR_NONE)
447       break;
448
449     static_pointer_cast<IItemInfoInternal>(i->GetInfo())->SetPrivateId(seq);
450     Bundle b = i->Serialize();
451     query = sqlite3_mprintf("INSERT INTO noti_ex_list"
452           " (root_id, app_id, uid, channel, priv_id, pkg_id, policy, data, insert_time)"
453           " VALUES (%Q, %Q, %d, %Q, %" PRId64 ", %Q, %d, %Q, %d)",
454           i->GetId().c_str(),
455           i->GetSenderAppId().c_str(),
456           uid,
457           i->GetChannel().c_str(),
458           static_pointer_cast<IItemInfoInternal>(i->GetInfo())->GetPrivateId(),
459           GetPkgId(i->GetSenderAppId(), uid).c_str(),
460           static_cast<int>(i->GetPolicy()),
461           reinterpret_cast<char*>(b.ToRaw().first.get()),
462           static_pointer_cast<IItemInfo>(i->GetInfo())->GetTime());
463
464     if (!query) {
465       LOGE("OOM - sql query");
466       ret = ERROR_OUT_OF_MEMORY;
467       break;
468     }
469
470     ret = ExecuteQuery(db, query, nullptr);
471     sqlite3_free(query);
472     if (ret != ERROR_NONE)
473       break;
474
475     ret = UpdateReceiverList(i, db);
476     if (ret != ERROR_NONE)
477       break;
478   }
479
480   if (ret == ERROR_NONE) {
481     CheckLimit(*(addedItem.begin()), db);
482     if (sqlite3_exec(db, "END TRANSACTION", nullptr, nullptr, nullptr)) {
483       LOGE("end transaction error : %s", sqlite3_errmsg(db));
484       ret = ERROR_FROM_DB;
485     }
486   } else {
487     if (sqlite3_exec(db, "ROLLBACK TRANSACTION", nullptr, nullptr, nullptr))
488     LOGE("rollback transaction error : %s", sqlite3_errmsg(db));
489   }
490
491   CloseDB(db);
492   return ret;
493 }
494
495 map<string, string> DBManager::GetHideMap() {
496   map<string, string> hide_map;
497   char* query;
498   sqlite3_stmt* stmt;
499   sqlite3* db;
500   int ret;
501   string key;
502
503   query = sqlite3_mprintf("SELECT root_id, app_id, uid, hide_list FROM noti_ex_list"
504                             " WHERE hide_list IS NOT NULL");
505   if (!query) {
506     LOGE("OOM - sql query");
507     return hide_map;
508   }
509
510   db = OpenDB();
511   if (db == nullptr) {
512     sqlite3_free(query);
513     return hide_map;
514   }
515
516   ret = sqlite3_prepare_v2(db, query, strlen(query), &stmt, nullptr);
517   if (ret != SQLITE_OK) {
518     LOGE("Failed to sqlite3_prepare [%d][%s]", ret,     sqlite3_errmsg(db));
519     CloseDB(db);
520     sqlite3_free(query);
521     return hide_map;
522   }
523   sqlite3_free(query);
524
525   while (sqlite3_step(stmt) == SQLITE_ROW) {
526     key = string(reinterpret_cast<const char*>(sqlite3_column_text(stmt, 0))) \
527           + string(reinterpret_cast<const char*>(sqlite3_column_text(stmt, 1))) \
528           + string(to_string(sqlite3_column_int(stmt, 2)));
529     hide_map[key] = string(reinterpret_cast<const char*>(sqlite3_column_text(stmt, 3)));
530   }
531
532   sqlite3_finalize(stmt);
533   CloseDB(db);
534   return hide_map;
535 }
536
537 int DBManager::GetCount(const string& app_id, uid_t uid, int* count) {
538   return GetCount(0, string(), app_id, uid, count);
539 }
540
541 int DBManager::GetCount(int64_t priv_id, const string& root_id, const string& app_id,
542                               uid_t uid, int* count) {
543   int ret;
544   char* query;
545   sqlite3_stmt *stmt;
546   sqlite3* db;
547
548   if (priv_id != 0) {
549     query = sqlite3_mprintf("SELECT count(*) FROM noti_ex_list"
550                             " WHERE priv_id = %" PRId64 "", priv_id);
551   } else if (root_id.empty()) {
552     query = sqlite3_mprintf("SELECT count(*) FROM noti_ex_list"
553                             " WHERE app_id = %Q AND uid = %d", app_id.c_str(), uid);
554   } else {
555     query = sqlite3_mprintf("SELECT count(*) FROM noti_ex_list"
556                             " WHERE root_id = %Q AND app_id = %Q AND uid = %d",
557                             root_id.c_str(), app_id.c_str(), uid);
558   }
559   if (!query) {
560     LOGE("OOM - sql query");
561     return ERROR_OUT_OF_MEMORY;
562   }
563
564   db = OpenDB();
565   if (db == nullptr) {
566     sqlite3_free(query);
567     return ERROR_FROM_DB;
568   }
569
570   ret = sqlite3_prepare_v2(db, query, strlen(query), &stmt, nullptr);
571   if (ret != SQLITE_OK) {
572     LOGE("Failed to sqlite3_prepare [%d][%s]", ret,     sqlite3_errmsg(db));
573     sqlite3_free(query);
574     CloseDB(db);
575     return ERROR_FROM_DB;
576   }
577   sqlite3_free(query);
578
579   ret = sqlite3_step(stmt);
580   if (ret == SQLITE_ROW)
581     *count = sqlite3_column_int(stmt, 0);
582   else
583     *count = 0;
584
585   sqlite3_finalize(stmt);
586   CloseDB(db);
587   return ERROR_NONE;
588 }
589
590 int DBManager::UpdateHideList(shared_ptr<item::AbstractItem> updatedItem,
591     const string& hide_list) {
592   int ret;
593   char* query;
594
595   query = sqlite3_mprintf("UPDATE noti_ex_list SET hide_list = %Q"
596             " WHERE root_id = %Q AND app_id = %Q AND uid = %d",
597             hide_list.c_str(), updatedItem->GetId().c_str(),
598             updatedItem->GetSenderAppId().c_str(),
599             static_pointer_cast<IItemInfoInternal>(updatedItem->GetInfo())->GetUid());
600   if (!query) {
601     LOGE("OOM - sql query");
602     return ERROR_OUT_OF_MEMORY;
603   }
604
605   ret = ExecuteQuery(query, nullptr);
606   sqlite3_free(query);
607
608   return ret;
609 }
610
611 int DBManager::UpdateNotification(shared_ptr<item::AbstractItem> updatedItem) {
612   int count, ret;
613   char* query;
614   uid_t uid =
615       static_pointer_cast<IItemInfoInternal>(updatedItem->GetInfo())->GetUid();
616   int64_t priv_id = static_pointer_cast<IItemInfoInternal>(
617       updatedItem->GetInfo())->GetPrivateId();
618
619   ret = GetCount(priv_id,
620       updatedItem->GetId(), updatedItem->GetSenderAppId(), uid, &count);
621   if (ret != ERROR_NONE) {
622     LOGE("fail to get count");
623     return ret;
624   }
625
626   if (count <= 0) {
627     LOGE("not exist priv_id(%" PRId64 ") id(%s) for appid(%s)", priv_id,
628         updatedItem->GetId().c_str(), updatedItem->GetSenderAppId().c_str());
629     return ERROR_NOT_EXIST_ID;
630   }
631
632   sqlite3* db = OpenDB();
633   if (db == nullptr)
634     return ERROR_FROM_DB;
635
636   Bundle b = updatedItem->Serialize();
637   query = sqlite3_mprintf("UPDATE noti_ex_list SET"
638      " pkg_id = %Q, channel = %Q, policy = %d, data = %Q, insert_time = %d"
639      " WHERE priv_id = %" PRId64 "",
640      GetPkgId(updatedItem->GetSenderAppId(), uid).c_str(),
641      updatedItem->GetChannel().c_str(),
642      static_cast<int>(updatedItem->GetPolicy()),
643      reinterpret_cast<char*>(b.ToRaw().first.get()),
644      static_pointer_cast<IItemInfo>(updatedItem->GetInfo())->GetTime(),
645      priv_id);
646
647   if (!query) {
648     LOGE("OOM - sql query");
649     CloseDB(db);
650     return ERROR_OUT_OF_MEMORY;
651   }
652
653   if (sqlite3_exec(db, "BEGIN TRANSACTION", nullptr, nullptr, nullptr)) {
654     LOGE("begin transaction error : %s", sqlite3_errmsg(db));
655     sqlite3_free(query);
656     CloseDB(db);
657     return ERROR_FROM_DB;
658   }
659
660   ret = ExecuteQuery(db, query, nullptr);
661   sqlite3_free(query);
662   if (ret != ERROR_NONE)
663     goto out;
664
665   ret = UpdateReceiverList(updatedItem, db);
666
667 out:
668   if (ret == ERROR_NONE) {
669     if (sqlite3_exec(db, "END TRANSACTION", nullptr, nullptr, nullptr)) {
670       LOGE("end transaction error : %s", sqlite3_errmsg(db));
671       ret = ERROR_FROM_DB;
672     }
673   } else {
674     if (sqlite3_exec(db, "ROLLBACK TRANSACTION", nullptr, nullptr, nullptr))
675     LOGE("rollback transaction error : %s", sqlite3_errmsg(db));
676   }
677
678   CloseDB(db);
679   return ret;
680 }
681
682 list<shared_ptr<item::AbstractItem>> DBManager::ExecuteGetList(char* query) {
683   sqlite3_stmt *stmt;
684   sqlite3* db;
685   int ret;
686   list<shared_ptr<item::AbstractItem>> item_list;
687
688   if (!query) {
689     LOGE("Invalid parameter");
690     return item_list;
691   }
692
693   db = OpenDB();
694   if (db == nullptr)
695     return item_list;
696
697   ret = sqlite3_prepare_v2(db, query, strlen(query), &stmt, nullptr);
698   if (ret != SQLITE_OK) {
699     LOGE("Failed to sqlite3_prepare [%d][%s]", ret, sqlite3_errmsg(db));
700     CloseDB(db);
701     return item_list;
702   }
703
704   while (sqlite3_step(stmt) == SQLITE_ROW) {
705     LOGE("[%s]", sqlite3_column_text(stmt, 0));
706
707     Bundle serialized(reinterpret_cast<const char*>(sqlite3_column_text(stmt, 0)));
708     shared_ptr<item::AbstractItem> gen_item = item::ItemInflator::Create(serialized);
709     item_list.emplace_back(gen_item);
710   }
711
712   sqlite3_finalize(stmt);
713   CloseDB(db);
714   return item_list;
715 }
716
717 list<shared_ptr<item::AbstractItem>> DBManager::GetNotificationList(
718     string app_id, uid_t uid) {
719   char* query;
720   list<shared_ptr<item::AbstractItem>> item_list;
721
722   query = sqlite3_mprintf("SELECT data FROM noti_ex_list"
723                     " WHERE uid = %d AND app_id = %Q ORDER BY insert_time DESC",
724                     uid, app_id.c_str());
725   if (!query) {
726     LOGE("OOM - sql query");
727     return item_list;
728   }
729
730   item_list = ExecuteGetList(query);
731   sqlite3_free(query);
732
733   return item_list;
734 }
735
736 list<shared_ptr<item::AbstractItem>> DBManager::GetNotificationList
737                              (string app_id, string root_id, uid_t uid) {
738   char* query;
739   list<shared_ptr<item::AbstractItem>> item_list;
740
741   query = sqlite3_mprintf("SELECT data FROM noti_ex_list"
742                            " WHERE uid = %d AND app_id = %Q AND root_id = %Q",
743                            uid, app_id.c_str(), root_id.c_str());
744
745   if (!query) {
746     LOGE("OOM - sql query");
747     return item_list;
748   }
749
750   item_list = ExecuteGetList(query);
751   sqlite3_free(query);
752
753   return item_list;
754 }
755
756 list<shared_ptr<item::AbstractItem>> DBManager::GetNotificationList
757                              (string app_id, int64_t priv_id, uid_t uid) {
758   char* query;
759   list<shared_ptr<item::AbstractItem>> item_list;
760
761   query = sqlite3_mprintf("SELECT data FROM noti_ex_list"
762       " WHERE uid = %d AND app_id = %Q AND priv_id = %" PRId64 "",
763       uid, app_id.c_str(), priv_id);
764
765   if (!query) {
766     LOGE("OOM - sql query");
767     return item_list;
768   }
769
770   item_list = ExecuteGetList(query);
771   sqlite3_free(query);
772
773   return item_list;
774 }
775
776 list<shared_ptr<item::AbstractItem>> DBManager::GetNotificationList(
777       uid_t uid, string channel) {
778   int ret, sim_mode;
779   char* query;
780   list<shared_ptr<item::AbstractItem>> item_list;
781
782   /* Check current sim status */
783   ret = vconf_get_int(VCONFKEY_TELEPHONY_SIM_SLOT, &sim_mode);
784   if (ret < 0) {
785     sim_mode = VCONFKEY_TELEPHONY_SIM_INSERTED;
786     LOGI("vconf_get_int");
787   }
788
789   string channel_query;
790   if (!channel.empty())
791     channel_query = " AND channel = '" + channel + "' ";
792
793   string simmode_query;
794   if (sim_mode != VCONFKEY_TELEPHONY_SIM_INSERTED) {
795     simmode_query = " AND (policy & " +
796         to_string(static_cast<int>(item::AbstractItem::Policy::SimMode)) +
797         ") == 0 ";
798   }
799
800   string query_str = "SELECT data FROM noti_ex_list WHERE uid = %d " +
801       channel_query +
802       simmode_query;
803
804   query = sqlite3_mprintf(query_str.c_str(), uid);
805   if (!query) {
806     LOGE("OOM - sql query");
807     return item_list;
808   }
809
810   item_list = ExecuteGetList(query);
811   sqlite3_free(query);
812
813   return item_list;
814 }
815
816 int DBManager::DeleteNotification(shared_ptr<item::AbstractItem> deletedItem) {
817   int ret;
818   char* query;
819   int64_t priv_id = static_pointer_cast<IItemInfoInternal>(
820       deletedItem->GetInfo())->GetPrivateId();
821
822   query = sqlite3_mprintf("DELETE FROM noti_ex_list WHERE priv_id = %" PRId64 "",
823       priv_id);
824   if (!query) {
825     LOGE("OOM - sql query");
826     return ERROR_OUT_OF_MEMORY;
827   }
828
829   ret = ExecuteQuery(query, nullptr);
830   sqlite3_free(query);
831   return ret;
832 }
833
834 string DBManager::GetPkgId(const string& app_id, uid_t uid) {
835   pkgmgrinfo_pkginfo_h handle;
836   char *buf = nullptr;
837   string pkgid;
838
839   if (pkgmgrinfo_appinfo_get_usr_appinfo(app_id.c_str(), uid, &handle) == PMINFO_R_OK) {
840     if (pkgmgrinfo_appinfo_get_pkgid(handle, &buf) == PMINFO_R_OK) {
841       if (buf)
842         pkgid = string(buf);
843     }
844     pkgmgrinfo_appinfo_destroy_appinfo(handle);
845   }
846   return pkgid;
847 }
848 }  // namespace notification