1 /*************************************************************************** 2 * SPDX-FileCopyrightText: 2006 Andreas Gungl <a.gungl@gmx.de> * 3 * * 4 * SPDX-License-Identifier: LGPL-2.0-or-later * 5 ***************************************************************************/ 6 7 #pragma once 8 9 #include <QString> 10 #include <QStringList> 11 12 class QVariant; 13 class QSqlDatabase; 14 15 namespace Akonadi 16 { 17 namespace Server 18 { 19 /** 20 Base class for classes representing database records. It also contains 21 low-level data access and manipulation template methods. 22 */ 23 class Entity 24 { 25 public: 26 using Id = qint64; 27 28 protected: 29 qint64 id() const; 30 void setId(qint64 id); 31 32 bool isValid() const; 33 34 public: joinByName(const QVector<T> & list,const QString & sep)35 template<typename T> static QString joinByName(const QVector<T> &list, const QString &sep) 36 { 37 QStringList tmp; 38 tmp.reserve(list.count()); 39 for (const T &t : list) { 40 tmp << t.name(); 41 } 42 return tmp.join(sep); 43 } 44 45 /** 46 Returns the number of records having @p value in @p column. 47 @param column The name of the key column. 48 @param value The value used to identify the record. 49 */ count(const QString & column,const QVariant & value)50 template<typename T> inline static int count(const QString &column, const QVariant &value) 51 { 52 return Entity::countImpl(T::tableName(), column, value); 53 } 54 55 /** 56 Deletes all records having @p value in @p column. 57 */ remove(const QString & column,const QVariant & value)58 template<typename T> inline static bool remove(const QString &column, const QVariant &value) 59 { 60 return Entity::removeImpl(T::tableName(), column, value); 61 } 62 63 /** 64 Checks whether an entry in a n:m relation table exists. 65 @param leftId Identifier of the left part of the relation. 66 @param rightId Identifier of the right part of the relation. 67 */ relatesTo(qint64 leftId,qint64 rightId)68 template<typename T> inline static bool relatesTo(qint64 leftId, qint64 rightId) 69 { 70 return Entity::relatesToImpl(T::tableName(), T::leftColumn(), T::rightColumn(), leftId, rightId); 71 } 72 73 /** 74 Adds an entry to a n:m relation table (specified by the template parameter). 75 @param leftId Identifier of the left part of the relation. 76 @param rightId Identifier of the right part of the relation. 77 */ addToRelation(qint64 leftId,qint64 rightId)78 template<typename T> inline static bool addToRelation(qint64 leftId, qint64 rightId) 79 { 80 return Entity::addToRelationImpl(T::tableName(), T::leftColumn(), T::rightColumn(), leftId, rightId); 81 } 82 83 /** 84 Removes an entry from a n:m relation table (specified by the template parameter). 85 @param leftId Identifier of the left part of the relation. 86 @param rightId Identifier of the right part of the relation. 87 */ removeFromRelation(qint64 leftId,qint64 rightId)88 template<typename T> inline static bool removeFromRelation(qint64 leftId, qint64 rightId) 89 { 90 return Entity::removeFromRelationImpl(T::tableName(), T::leftColumn(), T::rightColumn(), leftId, rightId); 91 } 92 93 enum RelationSide { 94 Left, 95 Right, 96 }; 97 98 /** 99 Clears all entries from a n:m relation table (specified by the given template parameter). 100 @param id Identifier on the relation side. 101 @param side The side of the relation. 102 */ 103 template<typename T> inline static bool clearRelation(qint64 id, RelationSide side = Left) 104 { 105 return Entity::clearRelationImpl(T::tableName(), T::leftColumn(), T::rightColumn(), id, side); 106 } 107 108 protected: 109 Entity(); 110 explicit Entity(qint64 id); 111 ~Entity(); 112 113 private: 114 static int countImpl(const QString &tableName, const QString &column, const QVariant &value); 115 static bool removeImpl(const QString &tableName, const QString &column, const QVariant &value); 116 static bool relatesToImpl(const QString &tableName, const QString &leftColumn, const QString &rightColumn, qint64 leftId, qint64 rightId); 117 static bool addToRelationImpl(const QString &tableName, const QString &leftColumn, const QString &rightColumn, qint64 leftId, qint64 rightId); 118 static bool removeFromRelationImpl(const QString &tableName, const QString &leftColumn, const QString &rightColumn, qint64 leftId, qint64 rightId); 119 static bool clearRelationImpl(const QString &tableName, const QString &leftColumn, const QString &rightColumn, qint64 id, RelationSide side); 120 121 private: 122 static QSqlDatabase database(); 123 qint64 m_id; 124 }; 125 126 namespace _detail 127 { 128 /*! 129 Binary predicate to sort collections of Entity subclasses by 130 their id. 131 132 Example for sorting: 133 \code 134 std::sort( coll.begin(), coll.end(), _detail::ById<std::less>() ); 135 \endcode 136 137 Example for finding by id: 138 \code 139 // linear: 140 std::find_if( coll.begin(), coll.end(), bind( _detail::ById<std::equal_to>(), _1, myId ) ); 141 // binary: 142 std::lower_bound( coll.begin(), coll.end(), myId, _detail::ById<std::less>() ); 143 \endcode 144 */ 145 template<template<typename U> class Op> struct ById { 146 using result_type = bool; operatorById147 bool operator()(Entity::Id lhs, Entity::Id rhs) const 148 { 149 return Op<Entity::Id>()(lhs, rhs); 150 } operatorById151 template<typename E> bool operator()(const E &lhs, const E &rhs) const 152 { 153 return this->operator()(lhs.id(), rhs.id()); 154 } operatorById155 template<typename E> bool operator()(const E &lhs, Entity::Id rhs) const 156 { 157 return this->operator()(lhs.id(), rhs); 158 } operatorById159 template<typename E> bool operator()(Entity::Id lhs, const E &rhs) const 160 { 161 return this->operator()(lhs, rhs.id()); 162 } 163 }; 164 } 165 166 } // namespace Server 167 } // namespace Akonadi 168 169