diff --git a/src/database/database.cc b/src/database/database.cc index ef5cb883da..4928f6e66c 100644 --- a/src/database/database.cc +++ b/src/database/database.cc @@ -1112,7 +1112,7 @@ error Database::loadUsersRelatedData(locked &user) { return err; } - err = loadClients(user->ID(), user->GetRelatedData()->Clients); + err = loadModels(user->ID(), user->GetRelatedData()->Clients); if (err != noError) { return err; } @@ -1122,37 +1122,37 @@ error Database::loadUsersRelatedData(locked &user) { return err; } - err = loadTasks(user->ID(), user->GetRelatedData()->Tasks); + err = loadModels(user->ID(), user->GetRelatedData()->Tasks); if (err != noError) { return err; } - err = loadTags(user->ID(), user->GetRelatedData()->Tags); + err = loadModels(user->ID(), user->GetRelatedData()->Tags); if (err != noError) { return err; } - err = loadTimeEntries(user->ID(), user->GetRelatedData()->TimeEntries); + err = loadModels(user->ID(), user->GetRelatedData()->TimeEntries); if (err != noError) { return err; } - err = loadAutotrackerRules(user->ID(), user->GetRelatedData()->AutotrackerRules); + err = loadModels(user->ID(), user->GetRelatedData()->AutotrackerRules); if (err != noError) { return err; } - err = loadTimelineEvents(user->ID(), user->GetRelatedData()->TimelineEvents); + err = loadModels(user->ID(), user->GetRelatedData()->TimelineEvents); if (err != noError) { return err; } - err = loadObmActions(user->ID(), user->GetRelatedData()->ObmActions); + err = loadModels(user->ID(), user->GetRelatedData()->ObmActions); if (err != noError) { return err; } - err = loadObmExperiments(user->ID(), user->GetRelatedData()->ObmExperiments); + err = loadModels(user->ID(), user->GetRelatedData()->ObmExperiments); if (err != noError) { return err; } @@ -1259,65 +1259,6 @@ error Database::LoadUserByID( return noError; } -error Database::loadClients(const Poco::UInt64 &UID, - ProtectedContainer &list) { - - if (!UID) { - return error("Cannot load user clients without an user ID"); - } - - try { - list.clear(); - - Poco::Mutex::ScopedLock lock(session_m_); - - Poco::Data::Statement select(*session_); - select << - "SELECT local_id, id, uid, name, guid, wid " - "FROM clients " - "WHERE uid = :uid " - "ORDER BY name", - useRef(UID); - - error err = last_error("loadClients"); - if (err != noError) { - return err; - } - Poco::Data::RecordSet rs(select); - while (!select.done()) { - select.execute(); - bool more = rs.moveFirst(); - while (more) { - auto model = list.create(); - model->SetLocalID(rs[0].convert()); - if (rs[1].isEmpty()) { - model->SetID(0); - } else { - model->SetID(rs[1].convert()); - } - model->SetUID(rs[2].convert()); - model->SetName(rs[3].convert()); - if (rs[4].isEmpty()) { - model->SetGUID(""); - } else { - model->SetGUID(rs[4].convert()); - } - model->SetWID(rs[5].convert()); - model->ClearDirty(); - - more = rs.moveNext(); - } - } - } catch(const Poco::Exception& exc) { - return exc.displayText(); - } catch(const std::exception& ex) { - return ex.what(); - } catch(const std::string & ex) { - return ex; - } - return last_error("loadClients"); -} - error Database::loadProjects(const Poco::UInt64 &UID, ProtectedContainer &list) { @@ -1405,486 +1346,6 @@ error Database::loadProjects(const Poco::UInt64 &UID, return last_error("loadProjects"); } -error Database::loadTasks( - const Poco::UInt64 &UID, - ProtectedContainer &list) { - - if (!UID) { - return error("Cannot load user tasks without an user ID"); - } - - try { - list.clear(); - - Poco::Mutex::ScopedLock lock(session_m_); - - Poco::Data::Statement select(*session_); - select << - "SELECT local_id, id, uid, name, wid, pid, active " - "FROM tasks " - "WHERE uid = :uid " - "ORDER BY name", - useRef(UID); - error err = last_error("loadTasks"); - if (err != noError) { - return err; - } - Poco::Data::RecordSet rs(select); - while (!select.done()) { - select.execute(); - bool more = rs.moveFirst(); - while (more) { - auto model = list.create(); - model->SetLocalID(rs[0].convert()); - if (rs[1].isEmpty()) { - model->SetID(0); - } else { - model->SetID(rs[1].convert()); - } - model->SetUID(rs[2].convert()); - model->SetName(rs[3].convert()); - model->SetWID(rs[4].convert()); - if (rs[5].isEmpty()) { - model->SetPID(0); - } else { - model->SetPID(rs[5].convert()); - } - model->SetActive(rs[6].convert()); - model->ClearDirty(); - - more = rs.moveNext(); - } - } - } catch(const Poco::Exception& exc) { - return exc.displayText(); - } catch(const std::exception& ex) { - return ex.what(); - } catch(const std::string & ex) { - return ex; - } - return last_error("loadTasks"); -} - -error Database::loadTags(const Poco::UInt64 &UID, - ProtectedContainer &list) { - - if (!UID) { - return error("Cannot load user tags without an user ID"); - } - - try { - list.clear(); - - Poco::Mutex::ScopedLock lock(session_m_); - - Poco::Data::Statement select(*session_); - select << - "SELECT local_id, id, uid, name, wid, guid " - "FROM tags " - "WHERE uid = :uid " - "ORDER BY name", - useRef(UID); - error err = last_error("loadTags"); - if (err != noError) { - return err; - } - Poco::Data::RecordSet rs(select); - while (!select.done()) { - select.execute(); - bool more = rs.moveFirst(); - while (more) { - auto model = list.create(); - model->SetLocalID(rs[0].convert()); - if (rs[1].isEmpty()) { - model->SetID(0); - } else { - model->SetID(rs[1].convert()); - } - model->SetUID(rs[2].convert()); - model->SetName(rs[3].convert()); - model->SetWID(rs[4].convert()); - if (rs[5].isEmpty()) { - model->SetGUID(""); - } else { - model->SetGUID(rs[5].convert()); - } - model->ClearDirty(); - - more = rs.moveNext(); - } - } - } catch(const Poco::Exception& exc) { - return exc.displayText(); - } catch(const std::exception& ex) { - return ex.what(); - } catch(const std::string & ex) { - return ex; - } - return last_error("loadTags"); -} - -error Database::loadAutotrackerRules(const Poco::UInt64 &UID, - ProtectedContainer &list) { - - if (!UID) { - return error("Cannot load autotracker rules without an user ID"); - } - - try { - list.clear(); - - Poco::Mutex::ScopedLock lock(session_m_); - - Poco::Data::Statement select(*session_); - select << - "SELECT local_id, uid, term, pid, tid " - "FROM autotracker_settings " - "WHERE uid = :uid " - "ORDER BY term DESC", - useRef(UID); - error err = last_error("loadAutotrackerRules"); - if (err != noError) { - return err; - } - Poco::Data::RecordSet rs(select); - while (!select.done()) { - select.execute(); - bool more = rs.moveFirst(); - while (more) { - auto model = list.create(); - model->SetLocalID(rs[0].convert()); - model->SetUID(rs[1].convert()); - model->SetTerm(rs[2].convert()); - model->SetPID(rs[3].convert()); - if (!rs[4].isEmpty()) { - model->SetTID(rs[4].convert()); - } - model->ClearDirty(); - - more = rs.moveNext(); - } - } - } catch(const Poco::Exception& exc) { - return exc.displayText(); - } catch(const std::exception& ex) { - return ex.what(); - } catch(const std::string & ex) { - return ex; - } - return last_error("loadAutotrackerRules"); -} - -error Database::loadObmActions( - const Poco::UInt64 &UID, - ProtectedContainer &list) { - - if (!UID) { - return error("Cannot load OBM actions without an user ID"); - } - - try { - list.clear(); - - Poco::Mutex::ScopedLock lock(session_m_); - - Poco::Data::Statement select(*session_); - select << - "SELECT local_id, uid, " - "experiment_id, key, value " - "FROM obm_actions " - "WHERE uid = :uid ", - useRef(UID); - error err = last_error("loadObmActions"); - if (err != noError) { - return err; - } - Poco::Data::RecordSet rs(select); - while (!select.done()) { - select.execute(); - bool more = rs.moveFirst(); - while (more) { - auto model = list.create(); - model->SetLocalID(rs[0].convert()); - model->SetUID(rs[1].convert()); - model->SetExperimentID(rs[2].convert()); - model->SetKey(rs[3].convert()); - model->SetValue(rs[4].convert()); - model->ClearDirty(); - - more = rs.moveNext(); - } - } - } catch(const Poco::Exception& exc) { - return exc.displayText(); - } catch(const std::exception& ex) { - return ex.what(); - } catch(const std::string & ex) { - return ex; - } - return last_error("loadObmActions"); -} - -error Database::loadObmExperiments(const Poco::UInt64 &UID, - ProtectedContainer &list) { - - if (!UID) { - return error("Cannot load OBM experiments without an user ID"); - } - - try { - list.clear(); - - Poco::Mutex::ScopedLock lock(session_m_); - - Poco::Data::Statement select(*session_); - select << - "SELECT local_id, uid, " - "nr, included, has_seen, actions " - "FROM obm_experiments " - "WHERE uid = :uid ", - useRef(UID); - error err = last_error("loadObmExperiments"); - if (err != noError) { - return err; - } - Poco::Data::RecordSet rs(select); - while (!select.done()) { - select.execute(); - bool more = rs.moveFirst(); - while (more) { - auto model = list.create(); - model->SetLocalID(rs[0].convert()); - model->SetUID(rs[1].convert()); - model->SetNr(rs[2].convert()); - model->SetIncluded(rs[3].convert()); - model->SetHasSeen(rs[4].convert()); - model->SetActions(rs[5].convert()); - model->ClearDirty(); - - more = rs.moveNext(); - } - } - } catch(const Poco::Exception& exc) { - return exc.displayText(); - } catch(const std::exception& ex) { - return ex.what(); - } catch(const std::string & ex) { - return ex; - } - return last_error("loadObmExperiments"); -} - -error Database::loadTimelineEvents(const Poco::UInt64 &UID, - ProtectedContainer &list) { - - if (!UID) { - return error("Cannot load user timeline without an user ID"); - } - - try { - list.clear(); - - Poco::Mutex::ScopedLock lock(session_m_); - - Poco::Data::Statement select(*session_); - select << - "SELECT local_id, title, filename, " - "start_time, end_time, idle, " - "uploaded, chunked, guid " - "FROM timeline_events " - "WHERE uid = :uid", - useRef(UID); - error err = last_error("loadTimelineEvents"); - if (err != noError) { - return err; - } - Poco::Data::RecordSet rs(select); - while (!select.done()) { - select.execute(); - bool more = rs.moveFirst(); - while (more) { - auto model = list.create(); - model->SetLocalID(rs[0].convert()); - if (!rs[1].isEmpty()) { - model->SetTitle(rs[1].convert()); - } - if (!rs[2].isEmpty()) { - model->SetFilename(rs[2].convert()); - } - model->SetStart(rs[3].convert()); - if (!rs[4].isEmpty()) { - model->SetEndTime(rs[4].convert()); - } - model->SetIdle(rs[5].convert()); - model->SetUploaded(rs[6].convert()); - model->SetChunked(rs[7].convert()); - model->SetGUID(rs[8].convert()); - - model->SetUID(UID); - - model->ClearDirty(); - - more = rs.moveNext(); - } - } - - // Ensure all timeline events have a GUID. - for (auto model : list) { - model->EnsureGUID(); - } - } catch(const Poco::Exception& exc) { - return exc.displayText(); - } catch(const std::exception& ex) { - return ex.what(); - } catch(const std::string & ex) { - return ex; - } - return noError; -} - -error Database::loadTimeEntries(const Poco::UInt64 &UID, - ProtectedContainer &list) { - - if (!UID) { - return error("Cannot load user time entries without an user ID"); - } - - try { - list.clear(); - - Poco::Mutex::ScopedLock lock(session_m_); - - Poco::Data::Statement select(*session_); - select << - "SELECT local_id, id, uid, description, wid, guid, pid, " - "tid, billable, duronly, ui_modified_at, start, stop, " - "duration, tags, created_with, deleted_at, updated_at, " - "project_guid, validation_error " - "FROM time_entries " - "WHERE uid = :uid " - "ORDER BY start DESC", - useRef(UID); - error err = last_error("loadTimeEntries"); - if (err != noError) { - return err; - } - err = loadTimeEntriesFromSQLStatement(&select, list); - if (err != noError) { - return err; - } - - // Ensure all time entries have a GUID. - for (auto te : list) { - te->EnsureGUID(); - if (te->Dirty()) { - te->SetUIModified(); - } - } - } catch(const Poco::Exception& exc) { - return exc.displayText(); - } catch(const std::exception& ex) { - return ex.what(); - } catch(const std::string & ex) { - return ex; - } - return noError; -} - -error Database::loadTimeEntriesFromSQLStatement(Poco::Data::Statement *select, - ProtectedContainer &list) { - - poco_check_ptr(select); - - try { - Poco::Data::RecordSet rs(*select); - while (!select->done()) { - select->execute(); - bool more = rs.moveFirst(); - while (more) { - auto model = list.create(); - model->SetLocalID(rs[0].convert()); - if (rs[1].isEmpty()) { - model->SetID(0); - } else { - model->SetID(rs[1].convert()); - } - model->SetUID(rs[2].convert()); - if (rs[3].isEmpty()) { - model->SetDescription(""); - } else { - model->SetDescription(rs[3].convert()); - } - model->SetWID(rs[4].convert()); - model->SetGUID(rs[5].convert()); - if (rs[6].isEmpty()) { - model->SetPID(0); - } else { - model->SetPID(rs[6].convert()); - } - if (rs[7].isEmpty()) { - model->SetTID(0); - } else { - model->SetTID(rs[7].convert()); - } - model->SetBillable(rs[8].convert()); - model->SetDurOnly(rs[9].convert()); - if (rs[10].isEmpty()) { - model->SetUIModifiedAt(0); - } else { - model->SetUIModifiedAt(rs[10].convert()); - } - model->SetStart(rs[11].convert()); - if (rs[12].isEmpty()) { - model->SetStop(0); - } else { - model->SetStop(rs[12].convert()); - } - model->SetDurationInSeconds(rs[13].convert()); - if (rs[14].isEmpty()) { - model->SetTags(""); - } else { - model->SetTags(rs[14].convert()); - } - if (rs[15].isEmpty()) { - model->SetCreatedWith(""); - } else { - model->SetCreatedWith(rs[15].convert()); - } - if (rs[16].isEmpty()) { - model->SetDeletedAt(0); - } else { - model->SetDeletedAt(rs[16].convert()); - } - if (rs[17].isEmpty()) { - model->SetUpdatedAt(0); - } else { - model->SetUpdatedAt(rs[17].convert()); - } - if (rs[18].isEmpty()) { - model->SetProjectGUID(""); - } else { - model->SetProjectGUID(rs[18].convert()); - } - if (rs[19].isEmpty()) { - model->SetValidationError(""); - } else { - model->SetValidationError(rs[19].convert()); - } - model->ClearDirty(); - - more = rs.moveNext(); - } - } - } catch(const Poco::Exception& exc) { - return exc.displayText(); - } catch(const std::exception& ex) { - return ex.what(); - } catch(const std::string & ex) { - return ex; - } - return noError; -} - template error Database::saveRelatedModels(const Poco::UInt64 UID, const std::string &table_name, diff --git a/src/database/database.h b/src/database/database.h index d0117cae2e..cf6cf68d50 100644 --- a/src/database/database.h +++ b/src/database/database.h @@ -292,46 +292,10 @@ class TOGGL_INTERNAL_EXPORT Database { const Poco::UInt64 &UID, ProtectedContainer &list); - error loadClients( - const Poco::UInt64 &UID, - ProtectedContainer &list); - error loadProjects( const Poco::UInt64 &UID, ProtectedContainer &list); - error loadTasks( - const Poco::UInt64 &UID, - ProtectedContainer &list); - - error loadTags( - const Poco::UInt64 &UID, - ProtectedContainer &list); - - error loadAutotrackerRules( - const Poco::UInt64 &UID, - ProtectedContainer &list); - - error loadObmActions( - const Poco::UInt64 &UID, - ProtectedContainer &list); - - error loadObmExperiments( - const Poco::UInt64 &UID, - ProtectedContainer &list); - - error loadTimeEntries( - const Poco::UInt64 &UID, - ProtectedContainer &list); - - error loadTimelineEvents( - const Poco::UInt64 &UID, - ProtectedContainer &list); - - error loadTimeEntriesFromSQLStatement( - Poco::Data::Statement *select, - ProtectedContainer &list); - template error saveRelatedModels( const Poco::UInt64 UID, diff --git a/src/database/migrations.cc b/src/database/migrations.cc index eb46a7704e..06ba91d5ea 100644 --- a/src/database/migrations.cc +++ b/src/database/migrations.cc @@ -32,6 +32,8 @@ error Migrations::migrateObmActions() { if (err != noError) { return err; } + + return noError; } error Migrations::migrateObmExperiments() { @@ -121,8 +123,8 @@ error Migrations::migrateAutotracker() { err = db_->Migrate( "autotracker_settings.guid", - "ALTER TABLE autotracker_settings " - "ADD COLUMN guid VARCHAR;" + "ALTER TABLE autotracker_settings ADD COLUMN guid VARCHAR;" + "ALTER TABLE autotracker_settings ADD COLUMN id INTEGER;" "CREATE UNIQUE INDEX id_autotracker_settings_guid ON autotracker_settings (uid, guid);"); if (err != noError) { return err; @@ -571,6 +573,13 @@ error Migrations::migrateTimeline() { return err; } + err = db_->Migrate( + "timeline_events.id", + "ALTER TABLE timeline_events ADD COLUMN id INTEGER;"); + if (err != noError) { + return err; + } + return noError; } diff --git a/src/model/autotracker.h b/src/model/autotracker.h index 50ae5ae41b..abe09089e6 100644 --- a/src/model/autotracker.h +++ b/src/model/autotracker.h @@ -15,6 +15,30 @@ namespace toggl { class TOGGL_INTERNAL_EXPORT AutotrackerRule : public BaseModel { + inline static const std::string modelName{ kModelAutotrackerRule }; + inline static const Query query{ + Query::Table{"autotracker_settings"}, + Query::Columns { + { "term", true }, + { "pid", false }, + { "tid", true } + }, + Query::Join{}, + Query::OrderBy{"term"}, + &BaseModel::query + }; + AutotrackerRule(ProtectedBase *container, Poco::Data::RecordSet &rs) + : BaseModel(container, rs) + { + size_t ptr{ query.Offset() }; + load(rs, query.IsRequired(ptr), ptr, term_); + ptr++; + load(rs, query.IsRequired(ptr), ptr, pid_); + ptr++; + load(rs, query.IsRequired(ptr), ptr, tid_); + ptr++; + ClearDirty(); + } AutotrackerRule(ProtectedBase *container) : BaseModel(container) {} diff --git a/src/model/base_model.h b/src/model/base_model.h index 2cf43be709..e2dd81285a 100644 --- a/src/model/base_model.h +++ b/src/model/base_model.h @@ -129,10 +129,14 @@ class TOGGL_INTERNAL_EXPORT BaseModel { : container_(container) { size_t ptr { query.Offset() }; - load(rs, query.IsRequired(ptr), ptr++, local_id_); - load(rs, query.IsRequired(ptr), ptr++, id_); - load(rs, query.IsRequired(ptr), ptr++, uid_); - load(rs, query.IsRequired(ptr), ptr++, guid_); + load(rs, query.IsRequired(ptr), ptr, local_id_); + ptr++; + load(rs, query.IsRequired(ptr), ptr, id_); + ptr++; + load(rs, query.IsRequired(ptr), ptr, uid_); + ptr++; + load(rs, query.IsRequired(ptr), ptr, guid_); + ptr++; ClearDirty(); } diff --git a/src/model/client.h b/src/model/client.h index bbd614ed02..ae324092c5 100644 --- a/src/model/client.h +++ b/src/model/client.h @@ -16,6 +16,27 @@ namespace toggl { class TOGGL_INTERNAL_EXPORT Client : public BaseModel { + inline static const std::string modelName{ kModelClient }; + inline static const Query query{ + Query::Table{"clients"}, + Query::Columns { + { "name", true }, + { "wid", true } + }, + Query::Join{}, + Query::OrderBy{"name"}, + &BaseModel::query + }; + Client(ProtectedBase *container, Poco::Data::RecordSet &rs) + : BaseModel(container, rs) + { + size_t ptr{ query.Offset() }; + load(rs, query.IsRequired(ptr), ptr, name_); + ptr++; + load(rs, query.IsRequired(ptr), ptr, wid_); + ptr++; + ClearDirty(); + } Client(ProtectedBase *container) : BaseModel(container) {} diff --git a/src/model/obm_action.h b/src/model/obm_action.h index dbd96353bd..18abfb448c 100644 --- a/src/model/obm_action.h +++ b/src/model/obm_action.h @@ -14,6 +14,42 @@ namespace toggl { class TOGGL_INTERNAL_EXPORT ObmAction : public BaseModel { + inline static const std::string modelName{ kModelObmAction }; + inline static const Query query{ + Query::Table{"obm_actions"}, + Query::Columns { + { "local_id", true }, + { "guid", false }, + { "experiment_id", true }, + { "key", true }, + { "value", true } + }, + Query::Join{}, + Query::OrderBy{}, + // doesn't actually use stuff from BaseModel + nullptr + }; + ObmAction(ProtectedBase *container, Poco::Data::RecordSet &rs) + : BaseModel(container, rs) + { + size_t ptr{ query.Offset() }; + // hacky + Poco::Int64 localId; + load(rs, query.IsRequired(ptr), ptr, localId); + SetLocalID(localId); + ptr++; + guid uuid; + load(rs, query.IsRequired(ptr), ptr, uuid); + SetGUID(uuid); + ptr++; + load(rs, query.IsRequired(ptr), ptr, experiment_id_); + ptr++; + load(rs, query.IsRequired(ptr), ptr, key_); + ptr++; + load(rs, query.IsRequired(ptr), ptr, value_); + ptr++; + ClearDirty(); + } ObmAction(ProtectedBase *container) : BaseModel(container) {} @@ -48,6 +84,45 @@ class TOGGL_INTERNAL_EXPORT ObmAction : public BaseModel { }; class TOGGL_INTERNAL_EXPORT ObmExperiment : public BaseModel { + inline static const std::string modelName{ kModelObmExperiment }; + inline static const Query query{ + Query::Table{"obm_experiments"}, + Query::Columns { + { "local_id", true }, + { "guid", false }, + { "nr", true }, + { "included", true }, + { "has_seen", true }, + { "actions", true } + }, + Query::Join{}, + Query::OrderBy{}, + // doesn't actually use stuff from BaseModel + nullptr + }; + ObmExperiment(ProtectedBase *container, Poco::Data::RecordSet &rs) + : BaseModel(container, rs) + { + size_t ptr{ query.Offset() }; + // hacky + Poco::Int64 localId; + load(rs, query.IsRequired(ptr), ptr, localId); + SetLocalID(localId); + ptr++; + guid uuid; + load(rs, query.IsRequired(ptr), ptr, uuid); + SetGUID(uuid); + ptr++; + load(rs, query.IsRequired(ptr), ptr, nr_); + ptr++; + load(rs, query.IsRequired(ptr), ptr, included_); + ptr++; + load(rs, query.IsRequired(ptr), ptr, has_seen_); + ptr++; + load(rs, query.IsRequired(ptr), ptr, actions_); + ptr++; + ClearDirty(); + } ObmExperiment(ProtectedBase *container) : BaseModel(container) {} diff --git a/src/model/tag.h b/src/model/tag.h index 3d7864ef56..a8d6209998 100644 --- a/src/model/tag.h +++ b/src/model/tag.h @@ -12,6 +12,27 @@ namespace toggl { class TOGGL_INTERNAL_EXPORT Tag : public BaseModel { + inline static const std::string modelName{ kModelTag }; + inline static const Query query{ + Query::Table{"tags"}, + Query::Columns { + { "name", true }, + { "wid", true } + }, + Query::Join{}, + Query::OrderBy{"name"}, + &BaseModel::query + }; + Tag(ProtectedBase *container, Poco::Data::RecordSet &rs) + : BaseModel(container, rs) + { + size_t ptr{ query.Offset() }; + load(rs, query.IsRequired(ptr), ptr, name_); + ptr++; + load(rs, query.IsRequired(ptr), ptr, wid_); + ptr++; + ClearDirty(); + } Tag(ProtectedBase *container) : BaseModel(container) {} diff --git a/src/model/task.h b/src/model/task.h index 351fdb33f8..0764fba6b4 100644 --- a/src/model/task.h +++ b/src/model/task.h @@ -14,6 +14,33 @@ namespace toggl { class TOGGL_INTERNAL_EXPORT Task : public BaseModel { + inline static const std::string modelName{ kModelTask }; + inline static const Query query{ + Query::Table{"tasks"}, + Query::Columns { + { "name", true }, + { "wid", true }, + { "pid", false }, + { "active", true } + }, + Query::Join{}, + Query::OrderBy{"name"}, + &BaseModel::query + }; + Task(ProtectedBase *container, Poco::Data::RecordSet &rs) + : BaseModel(container, rs) + { + size_t ptr{ query.Offset() }; + load(rs, query.IsRequired(ptr), ptr, name_); + ptr++; + load(rs, query.IsRequired(ptr), ptr, wid_); + ptr++; + load(rs, query.IsRequired(ptr), ptr, pid_); + ptr++; + load(rs, query.IsRequired(ptr), ptr, active_); + ptr++; + ClearDirty(); + } Task(ProtectedBase *container) : BaseModel(container) {} diff --git a/src/model/time_entry.h b/src/model/time_entry.h index 3bf66ff9af..ef04e27e0d 100644 --- a/src/model/time_entry.h +++ b/src/model/time_entry.h @@ -15,6 +15,87 @@ namespace toggl { class TOGGL_INTERNAL_EXPORT TimeEntry : public BaseModel, public TimedEvent { + inline static const std::string modelName{ kModelTimeEntry }; + inline static const Query query{ + Query::Table{"time_entries"}, + Query::Columns { + { "description", false }, + { "wid", true }, + { "pid", false }, + { "tid", false }, + { "billable", true }, + { "duronly", true }, + { "ui_modified_at", false }, + { "start", true }, + { "stop", false }, + { "duration", true }, + { "tags", false }, + { "created_with", false }, + { "deleted_at", false }, + { "updated_at", false }, + { "project_guid", false }, + { "validation_error", false } + }, + Query::Join{}, + Query::OrderBy{"start DESC"}, + &BaseModel::query + }; + TimeEntry(ProtectedBase *container, Poco::Data::RecordSet &rs) + : BaseModel(container, rs) + { + size_t ptr{ query.Offset() }; + load(rs, query.IsRequired(ptr), ptr, description_); + ptr++; + load(rs, query.IsRequired(ptr), ptr, wid_); + ptr++; + load(rs, query.IsRequired(ptr), ptr, pid_); + ptr++; + load(rs, query.IsRequired(ptr), ptr, tid_); + ptr++; + load(rs, query.IsRequired(ptr), ptr, billable_); + ptr++; + load(rs, query.IsRequired(ptr), ptr, duronly_); + ptr++; + // HACKS AHEAD + Poco::Int64 modifiedAt; + load(rs, query.IsRequired(ptr), ptr, modifiedAt); + SetUIModifiedAt(modifiedAt); + ptr++; + load(rs, query.IsRequired(ptr), ptr, start_); + ptr++; + load(rs, query.IsRequired(ptr), ptr, stop_); + ptr++; + load(rs, query.IsRequired(ptr), ptr, duration_in_seconds_); + ptr++; + // MORE HACKS + std::string tags; + load(rs, query.IsRequired(ptr), ptr, tags); + SetTags(tags); + ptr++; + load(rs, query.IsRequired(ptr), ptr, created_with_); + ptr++; + // HACK + Poco::Int64 deletedAt; + load(rs, query.IsRequired(ptr), ptr, deletedAt); + SetDeletedAt(deletedAt); + ptr++; + // HACK + Poco::Int64 updatedAt; + load(rs, query.IsRequired(ptr), ptr, updatedAt); + SetUpdatedAt(updatedAt); + ptr++; + load(rs, query.IsRequired(ptr), ptr, project_guid_); + ptr++; + error validationError; + load(rs, query.IsRequired(ptr), ptr, validationError); + SetValidationError(validationError); + ptr++; + + ClearDirty(); + EnsureGUID(); + if (Dirty()) + SetUIModified(); + } TimeEntry(ProtectedBase *container) : BaseModel(container) {} diff --git a/src/model/timeline_event.h b/src/model/timeline_event.h index b8b2a28984..9ba80c48af 100644 --- a/src/model/timeline_event.h +++ b/src/model/timeline_event.h @@ -15,6 +15,42 @@ namespace toggl { class TOGGL_INTERNAL_EXPORT TimelineEvent : public BaseModel, public TimedEvent { public: + inline static const std::string modelName{ kModelTimelineEvent }; + inline static const Query query{ + Query::Table{"timeline_events"}, + Query::Columns { + { "title", true }, + { "filename", true }, + { "start_time", true }, + { "end_time", true }, + { "idle", true }, + { "uploaded", true }, + { "chunked", true }, + }, + Query::Join{}, + Query::OrderBy{}, + &BaseModel::query + }; + TimelineEvent(ProtectedBase *container, Poco::Data::RecordSet &rs) + : BaseModel(container, rs) + { + size_t ptr{ query.Offset() }; + load(rs, query.IsRequired(ptr), ptr, title_); + ptr++; + load(rs, query.IsRequired(ptr), ptr, filename_); + ptr++; + load(rs, query.IsRequired(ptr), ptr, start_time_); + ptr++; + load(rs, query.IsRequired(ptr), ptr, end_time_); + ptr++; + load(rs, query.IsRequired(ptr), ptr, idle_); + ptr++; + load(rs, query.IsRequired(ptr), ptr, uploaded_); + ptr++; + load(rs, query.IsRequired(ptr), ptr, chunked_); + ptr++; + ClearDirty(); + } // public because instances get created all over the place TimelineEvent(ProtectedBase *container) : BaseModel(container) diff --git a/src/model/workspace.h b/src/model/workspace.h index ef1e3482f6..022aafcc0f 100644 --- a/src/model/workspace.h +++ b/src/model/workspace.h @@ -32,13 +32,20 @@ class TOGGL_INTERNAL_EXPORT Workspace : public BaseModel { : BaseModel(container, rs) { size_t ptr{ query.Offset() }; - load(rs, query.IsRequired(ptr), ptr++, name_); - load(rs, query.IsRequired(ptr), ptr++, premium_); - load(rs, query.IsRequired(ptr), ptr++, only_admins_may_create_projects_); - load(rs, query.IsRequired(ptr), ptr++, admin_); - load(rs, query.IsRequired(ptr), ptr++, projects_billable_by_default_); - load(rs, query.IsRequired(ptr), ptr++, business_); - load(rs, query.IsRequired(ptr), ptr++, locked_time_); + load(rs, query.IsRequired(ptr), ptr, name_); + ptr++; + load(rs, query.IsRequired(ptr), ptr, premium_); + ptr++; + load(rs, query.IsRequired(ptr), ptr, only_admins_may_create_projects_); + ptr++; + load(rs, query.IsRequired(ptr), ptr, admin_); + ptr++; + load(rs, query.IsRequired(ptr), ptr, projects_billable_by_default_); + ptr++; + load(rs, query.IsRequired(ptr), ptr, business_); + ptr++; + load(rs, query.IsRequired(ptr), ptr, locked_time_); + ptr++; ClearDirty(); } Workspace(ProtectedBase* container)