~aleteoryx/muditaos

d2fcc3020066150b09fa13ccefa8c15d1d0f8cf9 — Paweł Joński 4 years ago e1ef821
[BH-743] Add AlarmEvents

Add AlarmEvents to database
28 files changed, 1181 insertions(+), 6 deletions(-)

M image/user/db/events_001.sql
M module-db/CMakeLists.txt
M module-db/Databases/EventsDB.cpp
M module-db/Databases/EventsDB.hpp
A module-db/Interface/AlarmEventRecord.cpp
M module-db/Interface/AlarmEventRecord.hpp
M module-db/Interface/BaseInterface.hpp
A module-db/Tables/AlarmEventsTable.cpp
A module-db/Tables/AlarmEventsTable.hpp
M module-db/Tables/EventsTable.hpp
A module-db/queries/alarm_events/QueryAlarmEventsAdd.cpp
A module-db/queries/alarm_events/QueryAlarmEventsAdd.hpp
A module-db/queries/alarm_events/QueryAlarmEventsEdit.cpp
A module-db/queries/alarm_events/QueryAlarmEventsEdit.hpp
A module-db/queries/alarm_events/QueryAlarmEventsGet.cpp
A module-db/queries/alarm_events/QueryAlarmEventsGet.hpp
A module-db/queries/alarm_events/QueryAlarmEventsGetBetweenDates.cpp
A module-db/queries/alarm_events/QueryAlarmEventsGetBetweenDates.hpp
A module-db/queries/alarm_events/QueryAlarmEventsGetLimited.cpp
A module-db/queries/alarm_events/QueryAlarmEventsGetLimited.hpp
A module-db/queries/alarm_events/QueryAlarmEventsGetNext.cpp
A module-db/queries/alarm_events/QueryAlarmEventsGetNext.hpp
A module-db/queries/alarm_events/QueryAlarmEventsGetRecurringBetweenDates.cpp
A module-db/queries/alarm_events/QueryAlarmEventsGetRecurringBetweenDates.hpp
A module-db/queries/alarm_events/QueryAlarmEventsRemove.cpp
A module-db/queries/alarm_events/QueryAlarmEventsRemove.hpp
M module-services/service-db/ServiceDB.cpp
M module-services/service-db/ServiceDB.hpp
M image/user/db/events_001.sql => image/user/db/events_001.sql +9 -0
@@ 11,3 11,12 @@ CREATE TABLE IF NOT EXISTS events(
                  rrule TEXT DEFAULT ''
);

CREATE TABLE IF NOT EXISTS alarm_events(
                  _id INTEGER PRIMARY KEY,
                  event_id INTEGER,
                  music_tone TEXT,
                  enabled BOOLEAN,
                  snooze_duration INTEGER,
                  FOREIGN KEY (event_id) REFERENCES events (_id) ON DELETE CASCADE
);


M module-db/CMakeLists.txt => module-db/CMakeLists.txt +10 -0
@@ 26,6 26,7 @@ set(SOURCES
        Databases/CountryCodesDB.cpp
        Databases/NotificationsDB.cpp

        Tables/AlarmEventsTable.cpp
        Tables/Table.cpp
        Tables/SMSTable.cpp
        Tables/ThreadsTable.cpp


@@ 43,6 44,7 @@ set(SOURCES
        Tables/SMSTemplateTable.cpp
        Tables/NotificationsTable.cpp

        Interface/AlarmEventRecord.cpp
        Interface/EventRecord.cpp
        Interface/Record.cpp
        Interface/SMSRecord.cpp


@@ 55,6 57,14 @@ set(SOURCES
        Interface/NotificationsRecord.cpp

        queries/RecordQuery.cpp
        queries/alarm_events/QueryAlarmEventsAdd.cpp
        queries/alarm_events/QueryAlarmEventsEdit.cpp
        queries/alarm_events/QueryAlarmEventsGet.cpp
        queries/alarm_events/QueryAlarmEventsGetRecurringBetweenDates.cpp
        queries/alarm_events/QueryAlarmEventsGetLimited.cpp
        queries/alarm_events/QueryAlarmEventsGetBetweenDates.cpp
        queries/alarm_events/QueryAlarmEventsGetNext.cpp
        queries/alarm_events/QueryAlarmEventsRemove.cpp
        queries/messages/sms/QuerySMSSearchByType.cpp
        queries/messages/sms/QuerySMSGet.cpp
        queries/messages/sms/QuerySMSGetCount.cpp

M module-db/Databases/EventsDB.cpp => module-db/Databases/EventsDB.cpp +1 -1
@@ 3,5 3,5 @@

#include "EventsDB.hpp"

EventsDB::EventsDB(const char *name) : Database(name)
EventsDB::EventsDB(const char *name) : Database(name), alarmEvents(this)
{}

M module-db/Databases/EventsDB.hpp => module-db/Databases/EventsDB.hpp +3 -0
@@ 4,9 4,12 @@
#pragma once

#include <Database/Database.hpp>
#include <Tables/AlarmEventsTable.hpp>

class EventsDB : public Database
{
  public:
    explicit EventsDB(const char *name);

    AlarmEventsTable alarmEvents;
};

A module-db/Interface/AlarmEventRecord.cpp => module-db/Interface/AlarmEventRecord.cpp +175 -0
@@ 0,0 1,175 @@
// Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#include "AlarmEventRecord.hpp"

#include <Databases/EventsDB.hpp>
#include <queries/alarm_events/QueryAlarmEventsAdd.hpp>
#include <queries/alarm_events/QueryAlarmEventsEdit.hpp>
#include <queries/alarm_events/QueryAlarmEventsGet.hpp>
#include <queries/alarm_events/QueryAlarmEventsGetBetweenDates.hpp>
#include <queries/alarm_events/QueryAlarmEventsGetLimited.hpp>
#include <queries/alarm_events/QueryAlarmEventsGetNext.hpp>
#include <queries/alarm_events/QueryAlarmEventsGetRecurringBetweenDates.hpp>
#include <queries/alarm_events/QueryAlarmEventsRemove.hpp>

#include <rrule/rrule.hpp>

std::vector<AlarmEventRecord> generateRecordsVector(const std::vector<AlarmEventsTableRow> &tableRowVector);

AlarmEventRecord::AlarmEventRecord(uint32_t id,
                                   const UTF8 &name,
                                   TimePoint startDate,
                                   uint32_t duration,
                                   bool isAllDay,
                                   const std::string &rruleText,
                                   const std::string &musicTone,
                                   bool enabled,
                                   uint32_t snoozeDuration)
    : EventRecord{id, name, startDate, duration, isAllDay, rruleText}, musicTone{musicTone}, enabled{enabled},
      snoozeDuration{snoozeDuration} {};

AlarmEventRecord::AlarmEventRecord(const AlarmEventsTableRow &aeRow)
    : EventRecord{aeRow.ID, aeRow.name, aeRow.startDate, aeRow.duration, aeRow.isAllDay, aeRow.rruleText},
      musicTone{aeRow.musicTone}, enabled{aeRow.enabled}, snoozeDuration{aeRow.snoozeDuration} {};

auto AlarmEventRecord::isValid() const -> bool
{
    return (startDate != TIME_POINT_INVALID && ID != 0);
}

AlarmEventRecordInterface::AlarmEventRecordInterface(EventsDB *eventsDB) : eventsDB(eventsDB)
{}

AlarmEventRecordInterface::~AlarmEventRecordInterface()
{}

std::unique_ptr<db::QueryResult> AlarmEventRecordInterface::runQuery(std::shared_ptr<db::Query> query)
{
    if (typeid(*query) == typeid(db::query::alarmEvents::Add)) {
        return runQueryImplAdd(std::static_pointer_cast<db::query::alarmEvents::Add>(query));
    }
    if (typeid(*query) == typeid(db::query::alarmEvents::Edit)) {
        return runQueryImplEdit(std::static_pointer_cast<db::query::alarmEvents::Edit>(query));
    }
    if (typeid(*query) == typeid(db::query::alarmEvents::Get)) {
        return runQueryImplGet(std::static_pointer_cast<db::query::alarmEvents::Get>(query));
    }
    if (typeid(*query) == typeid(db::query::alarmEvents::GetLimited)) {
        return runQueryImplGetLimited(std::static_pointer_cast<db::query::alarmEvents::GetLimited>(query));
    }
    if (typeid(*query) == typeid(db::query::alarmEvents::GetBetweenDates)) {
        return runQueryImplGetBetweenDates(std::static_pointer_cast<db::query::alarmEvents::GetBetweenDates>(query));
    }
    if (typeid(*query) == typeid(db::query::alarmEvents::GetNext)) {
        return runQueryImplGetNext(std::static_pointer_cast<db::query::alarmEvents::GetNext>(query));
    }
    if (typeid(*query) == typeid(db::query::alarmEvents::GetRecurringBetweenDates)) {
        return runQueryImplGetRecurringBetweenDates(
            std::static_pointer_cast<db::query::alarmEvents::GetRecurringBetweenDates>(query));
    }
    if (typeid(*query) == typeid(db::query::alarmEvents::Remove)) {
        return runQueryImplRemove(std::static_pointer_cast<db::query::alarmEvents::Remove>(query));
    }
    return nullptr;
}

std::unique_ptr<db::query::alarmEvents::AddResult> AlarmEventRecordInterface::runQueryImplAdd(
    std::shared_ptr<db::query::alarmEvents::Add> query)
{
    const auto result = eventsDB->alarmEvents.add(AlarmEventsTableRow(query->getRecord()));

    auto response = std::make_unique<db::query::alarmEvents::AddResult>(result);
    response->setRequestQuery(query);
    return response;
}

std::unique_ptr<db::query::alarmEvents::EditResult> AlarmEventRecordInterface::runQueryImplEdit(
    std::shared_ptr<db::query::alarmEvents::Edit> query)
{
    const auto result = eventsDB->alarmEvents.update(AlarmEventsTableRow(query->getRecord()));

    auto response = std::make_unique<db::query::alarmEvents::EditResult>(result);
    response->setRequestQuery(query);
    return response;
}

std::unique_ptr<db::query::alarmEvents::GetResult> AlarmEventRecordInterface::runQueryImplGet(
    std::shared_ptr<db::query::alarmEvents::Get> query)
{
    const auto record = eventsDB->alarmEvents.getById(query->id);

    auto response = std::make_unique<db::query::alarmEvents::GetResult>(AlarmEventRecord(record));
    response->setRequestQuery(query);
    return response;
}

std::unique_ptr<db::query::alarmEvents::GetBetweenDatesResult> AlarmEventRecordInterface::runQueryImplGetBetweenDates(
    std::shared_ptr<db::query::alarmEvents::GetBetweenDates> query)
{
    const auto alarmEventsRows =
        eventsDB->alarmEvents.getBetweenDates(query->start, query->end, query->offset, query->limit);
    const auto recordVector = generateRecordsVector(alarmEventsRows);

    auto response = std::make_unique<db::query::alarmEvents::GetBetweenDatesResult>(recordVector);
    response->setRequestQuery(query);

    return response;
}

std::unique_ptr<db::query::alarmEvents::GetLimitedResult> AlarmEventRecordInterface::runQueryImplGetLimited(
    std::shared_ptr<db::query::alarmEvents::GetLimited> query)
{
    const auto alarmEventsRows = eventsDB->alarmEvents.getLimitOffset(query->offset, query->limit);
    const auto recordVector    = generateRecordsVector(alarmEventsRows);

    auto response = std::make_unique<db::query::alarmEvents::GetLimitedResult>(recordVector);
    response->setRequestQuery(query);

    return response;
}

std::unique_ptr<db::query::alarmEvents::GetNextResult> AlarmEventRecordInterface::runQueryImplGetNext(
    std::shared_ptr<db::query::alarmEvents::GetNext> query)
{
    const auto alarmEventsRows = eventsDB->alarmEvents.getNext(query->start, query->offset, query->limit);
    const auto recordVector    = generateRecordsVector(alarmEventsRows);

    auto response = std::make_unique<db::query::alarmEvents::GetNextResult>(recordVector);
    response->setRequestQuery(query);

    return response;
}

std::unique_ptr<db::query::alarmEvents::GetRecurringBetweenDatesResult> AlarmEventRecordInterface::
    runQueryImplGetRecurringBetweenDates(std::shared_ptr<db::query::alarmEvents::GetRecurringBetweenDates> query)
{
    const auto alarmEventsRows =
        eventsDB->alarmEvents.getRecurringBetweenDates(query->start, query->end, query->offset, query->limit);
    const auto recordVector = generateRecordsVector(alarmEventsRows);

    auto response = std::make_unique<db::query::alarmEvents::GetRecurringBetweenDatesResult>(recordVector);
    response->setRequestQuery(query);

    return response;
}

std::unique_ptr<db::query::alarmEvents::RemoveResult> AlarmEventRecordInterface::runQueryImplRemove(
    std::shared_ptr<db::query::alarmEvents::Remove> query)
{
    const bool ret = eventsDB->alarmEvents.removeById(query->id);
    auto response  = std::make_unique<db::query::alarmEvents::RemoveResult>(ret);
    response->setRequestQuery(query);
    return response;
}

std::vector<AlarmEventRecord> generateRecordsVector(const std::vector<AlarmEventsTableRow> &tableRowVector)
{
    std::vector<AlarmEventRecord> recordVector;

    recordVector.reserve(tableRowVector.size());
    for (const auto &row : tableRowVector) {
        recordVector.emplace_back(row);
    }
    return recordVector;
}

M module-db/Interface/AlarmEventRecord.hpp => module-db/Interface/AlarmEventRecord.hpp +67 -2
@@ 4,11 4,76 @@
#pragma once

#include "EventRecord.hpp"
#include <Databases/EventsDB.hpp>

#include <stdint.h>
#include <cstdint>

namespace db::query::alarmEvents
{
    class Add;
    class AddResult;
    class Edit;
    class EditResult;
    class Get;
    class GetBetweenDates;
    class GetBetweenDatesResult;
    class GetLimited;
    class GetLimitedResult;
    class GetNext;
    class GetNextResult;
    class GetRecurringBetweenDates;
    class GetRecurringBetweenDatesResult;
    class GetResult;
    class Remove;
    class RemoveResult;
} // namespace db::query::alarmEvents

struct AlarmEventRecord : public EventRecord
{
    std::string musicTone{""};
    std::string musicTone;
    bool enabled{false};
    uint32_t snoozeDuration{0};

    AlarmEventRecord(uint32_t id,
                     const UTF8 &name,
                     TimePoint startDate,
                     uint32_t duration,
                     bool isAllDay,
                     const std::string &rruleText,
                     const std::string &musicTone,
                     bool enabled,
                     uint32_t snoozeDuration);

    AlarmEventRecord(const AlarmEventsTableRow &aeRow);

    auto isValid() const -> bool;
};

class AlarmEventRecordInterface : public db::Interface
{
  public:
    explicit AlarmEventRecordInterface(EventsDB *eventsDB);
    ~AlarmEventRecordInterface();

    std::unique_ptr<db::QueryResult> runQuery(std::shared_ptr<db::Query> query) override;

  private:
    EventsDB *eventsDB;

    std::unique_ptr<db::query::alarmEvents::AddResult> runQueryImplAdd(
        std::shared_ptr<db::query::alarmEvents::Add> query);
    std::unique_ptr<db::query::alarmEvents::EditResult> runQueryImplEdit(
        std::shared_ptr<db::query::alarmEvents::Edit> query);
    std::unique_ptr<db::query::alarmEvents::GetResult> runQueryImplGet(
        std::shared_ptr<db::query::alarmEvents::Get> query);
    std::unique_ptr<db::query::alarmEvents::GetBetweenDatesResult> runQueryImplGetBetweenDates(
        std::shared_ptr<db::query::alarmEvents::GetBetweenDates> query);
    std::unique_ptr<db::query::alarmEvents::GetLimitedResult> runQueryImplGetLimited(
        std::shared_ptr<db::query::alarmEvents::GetLimited> query);
    std::unique_ptr<db::query::alarmEvents::GetNextResult> runQueryImplGetNext(
        std::shared_ptr<db::query::alarmEvents::GetNext> query);
    std::unique_ptr<db::query::alarmEvents::GetRecurringBetweenDatesResult> runQueryImplGetRecurringBetweenDates(
        std::shared_ptr<db::query::alarmEvents::GetRecurringBetweenDates> query);
    std::unique_ptr<db::query::alarmEvents::RemoveResult> runQueryImplRemove(
        std::shared_ptr<db::query::alarmEvents::Remove> query);
};

M module-db/Interface/BaseInterface.hpp => module-db/Interface/BaseInterface.hpp +3 -0
@@ 18,6 18,7 @@ namespace db

        enum class Name
        {
            AlarmEvents,
            SMS,
            SMSThread,
            SMSTemplate,


@@ 35,6 36,8 @@ namespace db
constexpr const char *c_str(enum db::Interface::Name db)
{
    switch (db) {
    case db::Interface::Name::AlarmEvents:
        return "AlarmEvents";
    case db::Interface::Name::SMS:
        return "SMS";
    case db::Interface::Name::SMSThread:

A module-db/Tables/AlarmEventsTable.cpp => module-db/Tables/AlarmEventsTable.cpp +300 -0
@@ 0,0 1,300 @@
// Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#include "AlarmEventsTable.hpp"

#include <Interface/AlarmEventRecord.hpp>

std::vector<AlarmEventsTableRow> retQueryUnpack(std::unique_ptr<QueryResult> retQuery);

AlarmEventsTableRow::AlarmEventsTableRow(uint32_t id,
                                         const UTF8 &name,
                                         TimePoint startDate,
                                         TimePoint endDate,
                                         uint32_t duration,
                                         bool isAllDay,
                                         const std::string &rruleText,
                                         const std::string &musicTone,
                                         bool enabled,
                                         uint32_t snoozeDuration)
    : EventsTableRow{id, name, startDate, endDate, duration, isAllDay, rruleText}, musicTone{musicTone},
      enabled{enabled}, snoozeDuration{snoozeDuration}
{}

AlarmEventsTableRow::AlarmEventsTableRow(const AlarmEventRecord &rec)
    : AlarmEventsTableRow{rec.ID,
                          rec.name,
                          rec.startDate,
                          rec.endDate,
                          rec.duration,
                          rec.isAllDay,
                          rec.rruleText,
                          rec.musicTone,
                          rec.enabled,
                          rec.snoozeDuration}
{}

AlarmEventsTableRow::AlarmEventsTableRow(const QueryResult &result)
    : EventsTableRow{result[0].getUInt32(),
                     result[1].getString().c_str(),
                     TimePointFromString(result[2].getString().c_str()),
                     TimePointFromString(result[3].getString().c_str()),
                     result[4].getUInt32(),
                     result[5].getBool(),
                     result[6].getString().c_str()},
      musicTone{result[9].getString()}, enabled{result[10].getBool()}, snoozeDuration{result[11].getUInt32()}
{}

auto AlarmEventsTableRow::isValid() const -> bool
{
    return (startDate != TIME_POINT_INVALID && ID != 0);
}

AlarmEventsTable::AlarmEventsTable(Database *db) : Table(db)
{}

bool AlarmEventsTable::create()
{
    return true;
}

bool AlarmEventsTable::add(AlarmEventsTableRow entry)
{
    auto ret = db->execute("BEGIN TRANSACTION;"
                           "INSERT or ignore INTO events ( name, start_date, end_date, duration, is_all_day, rrule)"
                           "VALUES ('%q', '%q', '%q', %lu, %d, '%q');",
                           entry.name.c_str(),
                           TimePointToString(entry.startDate).c_str(),
                           TimePointToString(entry.endDate).c_str(),
                           entry.duration,
                           entry.isAllDay,
                           entry.rruleText.c_str());
    if (!ret) {
        return false;
    }
    auto eventId = db->getLastInsertRowId();
    if (eventId == 0) {
        return false;
    }
    return db->execute("INSERT or ignore INTO alarm_events ( event_id, music_tone, enabled, snooze_duration)"
                       "VALUES ('%lu', '%q', '%d', %lu);"
                       "COMMIT;",
                       eventId,
                       entry.musicTone.c_str(),
                       entry.enabled,
                       entry.snoozeDuration);
}

bool AlarmEventsTable::removeById(uint32_t id)
{
    return db->execute("DELETE FROM events "
                       "WHERE events._id = (SELECT event_id FROM alarm_events WHERE _id=%lu);",
                       id);
}

bool AlarmEventsTable::removeByField(AlarmEventsTableFields field, const char *str)
{
    const auto &fieldName = getFieldName(field);

    if (fieldName.empty()) {
        return false;
    }

    return db->execute("DELETE e "
                       "FROM events e "
                       "INNER JOIN alarm_events ae "
                       "  ON e._id = ae.event_id "
                       "WHERE %q = '%q';",
                       fieldName.c_str(),
                       str);
}

bool AlarmEventsTable::update(AlarmEventsTableRow entry)
{
    return db->execute(
        "BEGIN TRANSACTION; "
        "UPDATE events SET name = '%q', start_date = '%q', end_date = '%q', duration = %d, is_all_day = %d, "
        "rrule = '%q' WHERE _id= (SELECT event_id FROM alarm_events WHERE _id=%lu); "
        "UPDATE alarm_events SET music_tone = '%q', enabled = '%d', snooze_duration = '%d' "
        "WHERE _id=%lu; "
        "COMMIT;",
        entry.name.c_str(),
        TimePointToString(entry.startDate).c_str(),
        TimePointToString(entry.endDate).c_str(),
        entry.duration,
        entry.isAllDay,
        entry.rruleText.c_str(),
        entry.ID,
        entry.musicTone.c_str(),
        entry.enabled,
        entry.snoozeDuration,
        entry.ID);
}

AlarmEventsTableRow AlarmEventsTable::getById(uint32_t id)
{
    auto retQuery = db->query("SELECT * "
                              "FROM events as e, alarm_events as ae "
                              "WHERE e._id=ae.event_id AND e._id = %u",
                              id);

    if ((retQuery == nullptr) || (retQuery->getRowCount() == 0)) {
        return AlarmEventsTableRow();
    }

    return AlarmEventsTableRow(*retQuery);
}

std::vector<AlarmEventsTableRow> AlarmEventsTable::getLimitOffset(uint32_t offset, uint32_t limit)
{
    auto retQuery = db->query("SELECT * FROM events e "
                              "JOIN alarm_events ae ON ae.event_id = e._id "
                              "LIMIT %lu OFFSET %lu ",
                              limit,
                              offset);

    return retQueryUnpack(std::move(retQuery));
}

std::vector<AlarmEventsTableRow> AlarmEventsTable::getLimitOffsetByField(uint32_t offset,
                                                                         uint32_t limit,
                                                                         AlarmEventsTableFields field,
                                                                         const char *str)
{
    std::unique_ptr<QueryResult> retQuery = nullptr;
    const auto &fieldName                 = getFieldName(field);

    if (fieldName.empty()) {
        return {};
    }

    retQuery = db->query("SELECT * FROM events e "
                         "JOIN alarm_events ae ON ae.event_id = e._id "
                         "WHERE %q = '%q' "
                         "ORDER BY start_date LIMIT %lu OFFSET %lu;",
                         fieldName.c_str(),
                         str,
                         limit,
                         offset);

    return retQueryUnpack(std::move(retQuery));
}

std::vector<AlarmEventsTableRow> AlarmEventsTable::getBetweenDates(TimePoint startDate,
                                                                   TimePoint endDate,
                                                                   uint32_t offset,
                                                                   uint32_t limit)
{
    auto retQuery = db->query("SELECT * FROM events e "
                              "JOIN alarm_events ae ON ae.event_id = e._id "
                              "WHERE start_date BETWEEN '%q' and '%q'"
                              "ORDER BY start_date LIMIT %lu OFFSET %lu;",
                              TimePointToString(startDate).c_str(),
                              TimePointToString(endDate).c_str(),
                              limit,
                              offset);

    return retQueryUnpack(std::move(retQuery));
}

std::vector<AlarmEventsTableRow> AlarmEventsTable::getRecurringBetweenDates(TimePoint startDate,
                                                                            TimePoint endDate,
                                                                            uint32_t offset,
                                                                            uint32_t limit)
{
    auto retQuery = db->query("SELECT * FROM events e "
                              "JOIN alarm_events ae ON ae.event_id = e._id "
                              "WHERE start_date BETWEEN '%q' and '%q' "
                              "OR (start_date <= '%q' AND end_date >= '%q') "
                              "AND rrule <> '' "
                              "ORDER BY start_date LIMIT %lu OFFSET %lu;",
                              TimePointToString(startDate).c_str(),
                              TimePointToString(endDate).c_str(),
                              TimePointToString(startDate).c_str(),
                              TimePointToString(startDate).c_str(),
                              limit,
                              offset);

    return retQueryUnpack(std::move(retQuery));
}

std::vector<AlarmEventsTableRow> AlarmEventsTable::getNext(TimePoint start, uint32_t offset, uint32_t limit)
{
    auto retQuery = db->query("SELECT * FROM events e "
                              "JOIN alarm_events ae ON ae.event_id = e._id "
                              "WHERE start_date = "
                              "	("
                              "		SELECT MIN(e.start_date) FROM events as e "
                              "		WHERE e.start_date > '%q'"
                              "	) "
                              "LIMIT %lu OFFSET %lu;",
                              TimePointToString(start).c_str(),
                              limit,
                              offset);

    return retQueryUnpack(std::move(retQuery));
}

uint32_t AlarmEventsTable::count()
{
    auto queryRet = db->query("SELECT COUNT(*) FROM alarm_events;");
    if (!queryRet || queryRet->getRowCount() == 0) {
        return 0;
    }

    return (*queryRet)[0].getUInt32();
}

uint32_t AlarmEventsTable::countByFieldId(const char *field, uint32_t id)
{
    auto queryRet = db->query("SELECT COUNT(*) FROM alarm_events "
                              "JOIN events ON alarm_events.event_id = events._id "
                              "WHERE %q=%lu;",
                              field,
                              id);
    if ((queryRet == nullptr) || (queryRet->getRowCount() == 0)) {
        return 0;
    }

    return (*queryRet)[0].getUInt32();
}

std::string AlarmEventsTable::getFieldName(AlarmEventsTableFields field)
{
    switch (field) {
    case AlarmEventsTableFields::Name:
        return "name";
    case AlarmEventsTableFields::StartDate:
        return "start_date";
    case AlarmEventsTableFields::EndDate:
        return "end_date";
    case AlarmEventsTableFields::Duration:
        return "duration";
    case AlarmEventsTableFields::IsAllDay:
        return "is_all_day";
    case AlarmEventsTableFields::Rrule:
        return "rrule";
    case AlarmEventsTableFields::MusicTone:
        return "music_tone";
    case AlarmEventsTableFields::Enabled:
        return "enabled";
    case AlarmEventsTableFields::SnoozeDuration:
        return "snooze_duration";
    default:
        return "";
    }
}

std::vector<AlarmEventsTableRow> retQueryUnpack(std::unique_ptr<QueryResult> retQuery)
{
    if ((retQuery == nullptr) || (retQuery->getRowCount() == 0)) {
        return {};
    }

    std::vector<AlarmEventsTableRow> outVector;

    do {
        outVector.push_back(AlarmEventsTableRow(*retQuery));
    } while (retQuery->nextRow());
    return outVector;
}

A module-db/Tables/AlarmEventsTable.hpp => module-db/Tables/AlarmEventsTable.hpp +77 -0
@@ 0,0 1,77 @@
// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#pragma once

#include "EventsTable.hpp"

#include <Common/Common.hpp>
#include <Database/Database.hpp>

#include <utf8/UTF8.hpp>

struct AlarmEventRecord;

struct AlarmEventsTableRow : public EventsTableRow
{
    std::string musicTone{""};
    bool enabled{false};
    uint32_t snoozeDuration{0};

    AlarmEventsTableRow() = default;
    AlarmEventsTableRow(uint32_t id,
                        const UTF8 &name,
                        TimePoint startDate,
                        TimePoint endDate,
                        uint32_t duration,
                        bool isAllDay,
                        const std::string &rrule,
                        const std::string &musicTone,
                        bool enabled,
                        uint32_t snoozeDuration);
    explicit AlarmEventsTableRow(const AlarmEventRecord &rec);
    explicit AlarmEventsTableRow(const QueryResult &result);

    auto isValid() const -> bool;
};

enum class AlarmEventsTableFields
{
    Name,
    StartDate,
    EndDate,
    Duration,
    IsAllDay,
    Rrule,
    MusicTone,
    Enabled,
    SnoozeDuration,
};

class AlarmEventsTable : public Table<AlarmEventsTableRow, AlarmEventsTableFields>
{
  public:
    explicit AlarmEventsTable(Database *db);
    virtual ~AlarmEventsTable() = default;

    auto create() -> bool override;
    auto add(AlarmEventsTableRow entry) -> bool override;
    auto removeById(uint32_t id) -> bool override;
    auto removeByField(AlarmEventsTableFields field, const char *str) -> bool override;
    auto update(AlarmEventsTableRow entry) -> bool override;
    auto getById(uint32_t id) -> AlarmEventsTableRow override;
    auto getLimitOffset(uint32_t offset, uint32_t limit) -> std::vector<AlarmEventsTableRow> override;
    auto getLimitOffsetByField(uint32_t offset, uint32_t limit, AlarmEventsTableFields field, const char *str)
        -> std::vector<AlarmEventsTableRow> override;
    auto getBetweenDates(TimePoint startDate, TimePoint endDate, uint32_t offset, uint32_t limit)
        -> std::vector<AlarmEventsTableRow>;
    auto getRecurringBetweenDates(TimePoint startDate, TimePoint endDate, uint32_t offset, uint32_t limit)
        -> std::vector<AlarmEventsTableRow>;
    auto getNext(TimePoint start, uint32_t offset, uint32_t limit) -> std::vector<AlarmEventsTableRow>;

    auto count() -> uint32_t override;
    auto countByFieldId(const char *field, uint32_t id) -> uint32_t override;

  private:
    auto getFieldName(AlarmEventsTableFields field) -> std::string;
};

M module-db/Tables/EventsTable.hpp => module-db/Tables/EventsTable.hpp +3 -3
@@ 22,7 22,7 @@ struct EventsTableRow : public Record
    TimePoint endDate{TIME_POINT_INVALID};
    uint32_t duration{0};
    bool isAllDay{false};
    std::string rrule{""};
    std::string rruleText{""};

    EventsTableRow() = default;
    EventsTableRow(uint32_t id,


@@ 31,7 31,7 @@ struct EventsTableRow : public Record
                   TimePoint endDate,
                   uint32_t duration,
                   bool isAllDay,
                   std::string rrule)
                   std::string rruleText)
        : Record{id}, name{name}, startDate{startDate}, endDate{endDate}, duration{duration}, isAllDay{isAllDay},
          rrule{rrule} {};
          rruleText{rruleText} {};
};

A module-db/queries/alarm_events/QueryAlarmEventsAdd.cpp => module-db/queries/alarm_events/QueryAlarmEventsAdd.cpp +33 -0
@@ 0,0 1,33 @@
// Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#include "QueryAlarmEventsAdd.hpp"

namespace db::query::alarmEvents
{
    Add::Add(const AlarmEventRecord &record) : Query(Query::Type::Create), record(record)
    {}

    auto Add::getRecord() const -> AlarmEventRecord
    {
        return record;
    }

    auto Add::debugInfo() const -> std::string
    {
        return std::string{"Add"};
    }

    AddResult::AddResult(bool ret) : ret(ret)
    {}

    auto AddResult::succeed() const -> bool
    {
        return ret;
    }

    auto AddResult::debugInfo() const -> std::string
    {
        return std::string{"AddResult"};
    }
} // namespace db::query::alarmEvents

A module-db/queries/alarm_events/QueryAlarmEventsAdd.hpp => module-db/queries/alarm_events/QueryAlarmEventsAdd.hpp +34 -0
@@ 0,0 1,34 @@
// Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#pragma once

#include "Interface/AlarmEventRecord.hpp"

#include <Common/Query.hpp>

#include <string>

namespace db::query::alarmEvents
{
    class Add : public Query
    {
        const AlarmEventRecord record;

      public:
        explicit Add(const AlarmEventRecord &record);
        [[nodiscard]] auto getRecord() const -> AlarmEventRecord;
        [[nodiscard]] auto debugInfo() const -> std::string override;
    };

    class AddResult : public QueryResult
    {
        const bool ret = true;

      public:
        explicit AddResult(bool ret);
        [[nodiscard]] auto succeed() const -> bool;
        [[nodiscard]] auto debugInfo() const -> std::string override;
    };

} // namespace db::query::alarmEvents

A module-db/queries/alarm_events/QueryAlarmEventsEdit.cpp => module-db/queries/alarm_events/QueryAlarmEventsEdit.cpp +33 -0
@@ 0,0 1,33 @@
// Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#include "QueryAlarmEventsEdit.hpp"

namespace db::query::alarmEvents
{
    Edit::Edit(const AlarmEventRecord &record) : Query(Query::Type::Update), record(record)
    {}

    auto Edit::getRecord() const -> AlarmEventRecord
    {
        return record;
    }

    auto Edit::debugInfo() const -> std::string
    {
        return std::string{"Edit"};
    }

    EditResult::EditResult(bool ret) : ret(ret)
    {}

    auto EditResult::succeed() const -> bool
    {
        return ret;
    }

    auto EditResult::debugInfo() const -> std::string
    {
        return std::string{"EditResult"};
    }
} // namespace db::query::alarmEvents

A module-db/queries/alarm_events/QueryAlarmEventsEdit.hpp => module-db/queries/alarm_events/QueryAlarmEventsEdit.hpp +35 -0
@@ 0,0 1,35 @@
// Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#pragma once

#include "Interface/AlarmEventRecord.hpp"

#include <Common/Query.hpp>

#include <string>

namespace db::query::alarmEvents
{
    class Edit : public Query
    {
        const AlarmEventRecord record;

      public:
        explicit Edit(const AlarmEventRecord &record);

        [[nodiscard]] auto getRecord() const -> AlarmEventRecord;
        [[nodiscard]] auto debugInfo() const -> std::string override;
    };

    class EditResult : public QueryResult
    {
        const bool ret = true;

      public:
        explicit EditResult(bool ret);
        [[nodiscard]] auto succeed() const -> bool;
        [[nodiscard]] auto debugInfo() const -> std::string override;
    };

} // namespace db::query::alarmEvents

A module-db/queries/alarm_events/QueryAlarmEventsGet.cpp => module-db/queries/alarm_events/QueryAlarmEventsGet.cpp +28 -0
@@ 0,0 1,28 @@
// Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#include "QueryAlarmEventsGet.hpp"

namespace db::query::alarmEvents
{
    Get::Get(uint32_t id) : Query(Query::Type::Read), id(id)
    {}

    auto Get::debugInfo() const -> std::string
    {
        return std::string{"Get"};
    }

    GetResult::GetResult(const AlarmEventRecord &record) : record(record)
    {}

    auto GetResult::getResult() const -> AlarmEventRecord
    {
        return record;
    }

    auto GetResult::debugInfo() const -> std::string
    {
        return std::string{"GetResult"};
    }
} // namespace db::query::alarmEvents

A module-db/queries/alarm_events/QueryAlarmEventsGet.hpp => module-db/queries/alarm_events/QueryAlarmEventsGet.hpp +35 -0
@@ 0,0 1,35 @@
// Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#pragma once

#include <Common/Query.hpp>

#include <module-db/Interface/AlarmEventRecord.hpp>

#include <string>

namespace db::query::alarmEvents
{
    class Get : public Query
    {
      public:
        const uint32_t id;

        explicit Get(uint32_t id);

        [[nodiscard]] auto debugInfo() const -> std::string override;
    };

    class GetResult : public QueryResult
    {
        const AlarmEventRecord record;

      public:
        explicit GetResult(const AlarmEventRecord &record);
        [[nodiscard]] auto getResult() const -> AlarmEventRecord;

        [[nodiscard]] auto debugInfo() const -> std::string override;
    };

} // namespace db::query::alarmEvents

A module-db/queries/alarm_events/QueryAlarmEventsGetBetweenDates.cpp => module-db/queries/alarm_events/QueryAlarmEventsGetBetweenDates.cpp +31 -0
@@ 0,0 1,31 @@
// Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#include "QueryAlarmEventsGetBetweenDates.hpp"

#include <utility>

namespace db::query::alarmEvents
{
    GetBetweenDates::GetBetweenDates(TimePoint start, TimePoint end, uint32_t offset, uint32_t limit)
        : Query(Query::Type::Read), start(start), end(end), offset(offset), limit(limit)
    {}

    auto GetBetweenDates::debugInfo() const -> std::string
    {
        return std::string{"GetBetweenDates"};
    }

    GetBetweenDatesResult::GetBetweenDatesResult(std::vector<AlarmEventRecord> records) : records(std::move(records))
    {}

    auto GetBetweenDatesResult::getResult() const -> std::vector<AlarmEventRecord>
    {
        return records;
    }

    auto GetBetweenDatesResult::debugInfo() const -> std::string
    {
        return std::string{"GetBetweenDatesResult"};
    }
} // namespace db::query::alarmEvents

A module-db/queries/alarm_events/QueryAlarmEventsGetBetweenDates.hpp => module-db/queries/alarm_events/QueryAlarmEventsGetBetweenDates.hpp +37 -0
@@ 0,0 1,37 @@
// Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#pragma once

#include <Common/Query.hpp>

#include <module-db/Interface/AlarmEventRecord.hpp>

#include <string>

namespace db::query::alarmEvents
{
    class GetBetweenDates : public Query
    {
      public:
        GetBetweenDates(TimePoint start, TimePoint end, uint32_t offset, uint32_t limit);
        [[nodiscard]] auto debugInfo() const -> std::string override;

        const TimePoint start = TIME_POINT_INVALID;
        const TimePoint end   = TIME_POINT_INVALID;
        const uint32_t offset = 0;
        const uint32_t limit  = 0;
    };

    class GetBetweenDatesResult : public QueryResult
    {
        const std::vector<AlarmEventRecord> records;

      public:
        explicit GetBetweenDatesResult(std::vector<AlarmEventRecord> records);
        [[nodiscard]] auto getResult() const -> std::vector<AlarmEventRecord>;

        [[nodiscard]] auto debugInfo() const -> std::string override;
    };

} // namespace db::query::alarmEvents

A module-db/queries/alarm_events/QueryAlarmEventsGetLimited.cpp => module-db/queries/alarm_events/QueryAlarmEventsGetLimited.cpp +30 -0
@@ 0,0 1,30 @@
// Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#include "QueryAlarmEventsGetLimited.hpp"

#include <utility>

namespace db::query::alarmEvents
{
    GetLimited::GetLimited(uint32_t offset, uint32_t limit) : Query(Query::Type::Read), offset(offset), limit(limit)
    {}

    auto GetLimited::debugInfo() const -> std::string
    {
        return std::string{"GetLimited"};
    }

    GetLimitedResult::GetLimitedResult(std::vector<AlarmEventRecord> records) : records(std::move(records))
    {}

    auto GetLimitedResult::getResult() const -> std::vector<AlarmEventRecord>
    {
        return records;
    }

    auto GetLimitedResult::debugInfo() const -> std::string
    {
        return std::string{"GetLimitedResult"};
    }
} // namespace db::query::alarmEvents

A module-db/queries/alarm_events/QueryAlarmEventsGetLimited.hpp => module-db/queries/alarm_events/QueryAlarmEventsGetLimited.hpp +35 -0
@@ 0,0 1,35 @@
// Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#pragma once

#include "module-db/Interface/AlarmEventRecord.hpp"

#include <Common/Query.hpp>

#include <string>

namespace db::query::alarmEvents
{
    class GetLimited : public Query
    {
      public:
        GetLimited(uint32_t offset, uint32_t limit);
        [[nodiscard]] auto debugInfo() const -> std::string override;

        const uint32_t offset = 0;
        const uint32_t limit  = 0;
    };

    class GetLimitedResult : public QueryResult
    {
        const std::vector<AlarmEventRecord> records;

      public:
        explicit GetLimitedResult(std::vector<AlarmEventRecord> records);
        [[nodiscard]] auto getResult() const -> std::vector<AlarmEventRecord>;

        [[nodiscard]] auto debugInfo() const -> std::string override;
    };

} // namespace db::query::alarmEvents

A module-db/queries/alarm_events/QueryAlarmEventsGetNext.cpp => module-db/queries/alarm_events/QueryAlarmEventsGetNext.cpp +31 -0
@@ 0,0 1,31 @@
// Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#include "QueryAlarmEventsGetNext.hpp"

#include <utility>

namespace db::query::alarmEvents
{
    GetNext::GetNext(TimePoint start, uint32_t offset, uint32_t limit)
        : Query(Query::Type::Read), start(start), offset(offset), limit(limit)
    {}

    auto GetNext::debugInfo() const -> std::string
    {
        return std::string{"GetNext"};
    }

    GetNextResult::GetNextResult(std::vector<AlarmEventRecord> records) : records(std::move(records))
    {}

    auto GetNextResult::getResult() const -> std::vector<AlarmEventRecord>
    {
        return records;
    }

    auto GetNextResult::debugInfo() const -> std::string
    {
        return std::string{"GetNextResult"};
    }
} // namespace db::query::alarmEvents

A module-db/queries/alarm_events/QueryAlarmEventsGetNext.hpp => module-db/queries/alarm_events/QueryAlarmEventsGetNext.hpp +36 -0
@@ 0,0 1,36 @@
// Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#pragma once

#include "module-db/Interface/AlarmEventRecord.hpp"

#include <Common/Query.hpp>

#include <string>

namespace db::query::alarmEvents
{
    class GetNext : public Query
    {
      public:
        GetNext(TimePoint start, uint32_t offset, uint32_t limit);
        [[nodiscard]] auto debugInfo() const -> std::string override;

        const TimePoint start = TIME_POINT_INVALID;
        const uint32_t offset = 0;
        const uint32_t limit  = 0;
    };

    class GetNextResult : public QueryResult
    {
        const std::vector<AlarmEventRecord> records;

      public:
        explicit GetNextResult(std::vector<AlarmEventRecord> records);
        [[nodiscard]] auto getResult() const -> std::vector<AlarmEventRecord>;

        [[nodiscard]] auto debugInfo() const -> std::string override;
    };

} // namespace db::query::alarmEvents

A module-db/queries/alarm_events/QueryAlarmEventsGetRecurringBetweenDates.cpp => module-db/queries/alarm_events/QueryAlarmEventsGetRecurringBetweenDates.cpp +32 -0
@@ 0,0 1,32 @@
// Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#include "QueryAlarmEventsGetRecurringBetweenDates.hpp"

#include <utility>

namespace db::query::alarmEvents
{
    GetRecurringBetweenDates::GetRecurringBetweenDates(TimePoint start, TimePoint end, uint32_t offset, uint32_t limit)
        : Query(Query::Type::Read), start(start), end(end), offset(offset), limit(limit)
    {}

    auto GetRecurringBetweenDates::debugInfo() const -> std::string
    {
        return std::string{"GetRecurringBetweenDates"};
    }

    GetRecurringBetweenDatesResult::GetRecurringBetweenDatesResult(std::vector<AlarmEventRecord> records)
        : records(std::move(records))
    {}

    auto GetRecurringBetweenDatesResult::getResult() const -> std::vector<AlarmEventRecord>
    {
        return records;
    }

    auto GetRecurringBetweenDatesResult::debugInfo() const -> std::string
    {
        return std::string{"GetRecurringBetweenDatesResult"};
    }
} // namespace db::query::alarmEvents

A module-db/queries/alarm_events/QueryAlarmEventsGetRecurringBetweenDates.hpp => module-db/queries/alarm_events/QueryAlarmEventsGetRecurringBetweenDates.hpp +37 -0
@@ 0,0 1,37 @@
// Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#pragma once

#include "module-db/Interface/AlarmEventRecord.hpp"

#include <Common/Query.hpp>

#include <string>

namespace db::query::alarmEvents
{
    class GetRecurringBetweenDates : public Query
    {
      public:
        GetRecurringBetweenDates(TimePoint start, TimePoint end, uint32_t offset, uint32_t limit);
        [[nodiscard]] auto debugInfo() const -> std::string override;

        const TimePoint start = TIME_POINT_INVALID;
        const TimePoint end   = TIME_POINT_INVALID;
        const uint32_t offset = 0;
        const uint32_t limit  = 0;
    };

    class GetRecurringBetweenDatesResult : public QueryResult
    {
        const std::vector<AlarmEventRecord> records;

      public:
        explicit GetRecurringBetweenDatesResult(std::vector<AlarmEventRecord> records);
        [[nodiscard]] auto getResult() const -> std::vector<AlarmEventRecord>;

        [[nodiscard]] auto debugInfo() const -> std::string override;
    };

} // namespace db::query::alarmEvents

A module-db/queries/alarm_events/QueryAlarmEventsRemove.cpp => module-db/queries/alarm_events/QueryAlarmEventsRemove.cpp +28 -0
@@ 0,0 1,28 @@
// Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#include "QueryAlarmEventsRemove.hpp"

namespace db::query::alarmEvents
{
    Remove::Remove(const uint32_t id) : Query(Query::Type::Delete), id(id)
    {}

    auto Remove::debugInfo() const -> std::string
    {
        return std::string{"Remove"};
    }

    RemoveResult::RemoveResult(const bool ret) : ret(ret)
    {}

    auto RemoveResult::succeed() const -> bool
    {
        return ret;
    }

    auto RemoveResult::debugInfo() const -> std::string
    {
        return std::string{"RemoveResult"};
    }
} // namespace db::query::alarmEvents

A module-db/queries/alarm_events/QueryAlarmEventsRemove.hpp => module-db/queries/alarm_events/QueryAlarmEventsRemove.hpp +32 -0
@@ 0,0 1,32 @@
// Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#pragma once

#include <Common/Query.hpp>

#include <string>

namespace db::query::alarmEvents
{

    class Remove : public Query
    {
      public:
        explicit Remove(const uint32_t id);
        [[nodiscard]] auto debugInfo() const -> std::string override;

        const uint32_t id;
    };

    class RemoveResult : public QueryResult
    {
        const bool ret = true;

      public:
        explicit RemoveResult(const bool ret);
        [[nodiscard]] auto succeed() const -> bool;
        [[nodiscard]] auto debugInfo() const -> std::string override;
    };

} // namespace db::query::alarmEvents

M module-services/service-db/ServiceDB.cpp => module-services/service-db/ServiceDB.cpp +3 -0
@@ 68,6 68,8 @@ ServiceDB::~ServiceDB()
db::Interface *ServiceDB::getInterface(db::Interface::Name interface)
{
    switch (interface) {
    case db::Interface::Name::AlarmEvents:
        return alarmEventRecordInterface.get();
    case db::Interface::Name::SMS:
        return smsRecordInterface.get();
    case db::Interface::Name::SMSThread:


@@ 252,6 254,7 @@ sys::ReturnCodes ServiceDB::InitHandler()
    quotesDB        = std::make_unique<Database>((purefs::dir::getUserDiskPath() / "quotes.db").c_str());

    // Create record interfaces
    alarmEventRecordInterface    = std::make_unique<AlarmEventRecordInterface>(eventsDB.get());
    contactRecordInterface       = std::make_unique<ContactRecordInterface>(contactsDB.get());
    smsRecordInterface           = std::make_unique<SMSRecordInterface>(smsDB.get(), contactsDB.get());
    threadRecordInterface        = std::make_unique<ThreadRecordInterface>(smsDB.get(), contactsDB.get());

M module-services/service-db/ServiceDB.hpp => module-services/service-db/ServiceDB.hpp +3 -0
@@ 12,6 12,7 @@
#include "service-fileindexer/Constants.hpp"

#include <Common/Query.hpp>
#include <Interface/AlarmEventRecord.hpp>
#include <Interface/AlarmsRecord.hpp>
#include <Interface/BaseInterface.hpp>
#include <Interface/CalllogRecord.hpp>


@@ 30,6 31,7 @@
#include <string>

class AlarmsDB;
class AlarmEventRecordInterface;
class AlarmsRecordInterface;
class CalllogDB;
class CalllogRecordInterface;


@@ 66,6 68,7 @@ class ServiceDB : public sys::Service
    std::unique_ptr<NotificationsDB> notificationsDB;
    std::unique_ptr<Database> quotesDB;

    std::unique_ptr<AlarmEventRecordInterface> alarmEventRecordInterface;
    std::unique_ptr<SMSRecordInterface> smsRecordInterface;
    std::unique_ptr<ThreadRecordInterface> threadRecordInterface;
    std::unique_ptr<SMSTemplateRecordInterface> smsTemplateRecordInterface;