QxOrm
1.5.0
C++ Object Relational Mapping library
|
00001 /**************************************************************************** 00002 ** 00003 ** https://www.qxorm.com/ 00004 ** Copyright (C) 2013 Lionel Marty (contact@qxorm.com) 00005 ** 00006 ** This file is part of the QxOrm library 00007 ** 00008 ** This software is provided 'as-is', without any express or implied 00009 ** warranty. In no event will the authors be held liable for any 00010 ** damages arising from the use of this software 00011 ** 00012 ** Commercial Usage 00013 ** Licensees holding valid commercial QxOrm licenses may use this file in 00014 ** accordance with the commercial license agreement provided with the 00015 ** Software or, alternatively, in accordance with the terms contained in 00016 ** a written agreement between you and Lionel Marty 00017 ** 00018 ** GNU General Public License Usage 00019 ** Alternatively, this file may be used under the terms of the GNU 00020 ** General Public License version 3.0 as published by the Free Software 00021 ** Foundation and appearing in the file 'license.gpl3.txt' included in the 00022 ** packaging of this file. Please review the following information to 00023 ** ensure the GNU General Public License version 3.0 requirements will be 00024 ** met : http://www.gnu.org/copyleft/gpl.html 00025 ** 00026 ** If you are unsure which license is appropriate for your use, or 00027 ** if you have questions regarding the use of this file, please contact : 00028 ** contact@qxorm.com 00029 ** 00030 ****************************************************************************/ 00031 00032 #ifndef _QX_REPOSITORY_H_ 00033 #define _QX_REPOSITORY_H_ 00034 00035 #ifdef _MSC_VER 00036 #pragma once 00037 #endif 00038 00046 #include <QxDao/QxRepository/IxRepository.h> 00047 #include <QxDao/QxRepository/QxRepositoryX.h> 00048 00049 #include <QxDao/QxDao.h> 00050 #include <QxDao/QxSession.h> 00051 #include <QxDao/QxSqlError.h> 00052 00053 #include <QxRegister/QxClass.h> 00054 00055 #include <QxCollection/QxCollection.h> 00056 00057 #include <QxTraits/get_primary_key.h> 00058 00059 #define QX_REPOSITORY_COLLECTION_DYNAMIC_CAST_ERROR QSqlError("[QxOrm] qx::QxRepository<T> : 'invalid collection pointer, dynamic_cast failed'", "", QSqlError::UnknownError) 00060 #define QX_REPOSITORY_POINTER_DYNAMIC_CAST_ERROR QSqlError("[QxOrm] qx::QxRepository<T> : 'invalid pointer, dynamic_cast failed'", "", QSqlError::UnknownError) 00061 #define QX_REPOSITORY_QOBJECT_BASE_CLASS_ERROR QSqlError("[QxOrm] qx::QxRepository<T> : 'invalid pointer, need to inherit from QObject class to use qx::IxRepository interface'", "", QSqlError::UnknownError) 00062 00063 #ifndef _QX_NO_RTTI 00064 #define QX_REPOSITORY_CAST_COLLECTION \ 00065 type_collection_qt * x = dynamic_cast<type_collection_qt *>(p); \ 00066 type_collection_boost * y = (x ? NULL : dynamic_cast<type_collection_boost *>(p)); \ 00067 if (! x && ! y) { throw qx::dao::sql_error(QX_REPOSITORY_COLLECTION_DYNAMIC_CAST_ERROR); } 00068 #else // _QX_NO_RTTI 00069 #define QX_REPOSITORY_CAST_COLLECTION \ 00070 type_collection_qt * x = NULL; \ 00071 type_collection_boost * y = static_cast<type_collection_boost *>(p); 00072 #endif // _QX_NO_RTTI 00073 00074 namespace qx { 00075 00076 template <class T> 00077 inline void register_repository(const QString & sKey); 00078 00083 template <class T> 00084 class QxRepository : public IxRepository 00085 { 00086 00087 template <class U> 00088 friend inline void register_repository(const QString & sKey); 00089 00090 private: 00091 00092 QxRepository(const QString & sKey) : IxRepository(true, sKey) { ; } 00093 00094 public: 00095 00096 QxRepository() : IxRepository(false, QString("")) { ; } 00097 QxRepository(const QSqlDatabase & database) : IxRepository(false, QString(""), database) { ; } 00098 QxRepository(QxSession * pSession) : IxRepository(false, QString(""), pSession) { ; } 00099 virtual ~QxRepository() { ; } 00100 00101 long count(const qx::QxSqlQuery & query = qx::QxSqlQuery()) 00102 { return qx::dao::count<T>(query, this->database()); } 00103 00104 T * fetchById(const QVariant & id, const QStringList & columns = QStringList(), const QStringList & relation = QStringList()) 00105 { 00106 IxDataMemberX * pDataMemberX = QxClass<T>::getSingleton()->getDataMemberX(); 00107 IxDataMember * pDataMemberId = (pDataMemberX ? pDataMemberX->getId_WithDaoStrategy() : NULL); 00108 if (! pDataMemberId) { qAssert(false); return NULL; } 00109 T * t = new T(); QSqlError err; 00110 pDataMemberId->fromVariant(t, id, -1, qx::cvt::context::e_database); 00111 if (relation.count() == 0) { err = qx::dao::fetch_by_id((* t), this->database(), columns); } 00112 else { err = qx::dao::fetch_by_id_with_relation(relation, (* t), this->database()); } 00113 if (err.isValid() && m_pSession) { delete t; t = NULL; (* m_pSession) += err; } 00114 else if (err.isValid()) { delete t; t = NULL; } 00115 return t; 00116 } 00117 00118 template <class U> 00119 QSqlError fetchById(U & u, const QStringList & columns = QStringList(), const QStringList & relation = QStringList()) 00120 { 00121 QSqlError err; 00122 if (relation.count() == 0) { err = qx::dao::fetch_by_id(u, this->database(), columns); } 00123 else { err = qx::dao::fetch_by_id_with_relation(relation, u, this->database()); } 00124 if (err.isValid() && m_pSession) { (* m_pSession) += err; } 00125 return err; 00126 } 00127 00128 template <class U> 00129 QSqlError fetchAll(U & u, const QStringList & columns = QStringList(), const QStringList & relation = QStringList()) 00130 { 00131 QSqlError err; 00132 if (relation.count() == 0) { err = qx::dao::fetch_all(u, this->database(), columns); } 00133 else { err = qx::dao::fetch_all_with_relation(relation, u, this->database()); } 00134 if (err.isValid() && m_pSession) { (* m_pSession) += err; } 00135 return err; 00136 } 00137 00138 template <class U> 00139 QSqlError fetchByQuery(const qx::QxSqlQuery & query, U & u, const QStringList & columns = QStringList(), const QStringList & relation = QStringList()) 00140 { 00141 QSqlError err; 00142 if (relation.count() == 0) { err = qx::dao::fetch_by_query(query, u, this->database(), columns); } 00143 else { err = qx::dao::fetch_by_query_with_relation(relation, query, u, this->database()); } 00144 if (err.isValid() && m_pSession) { (* m_pSession) += err; } 00145 return err; 00146 } 00147 00148 template <class U> 00149 QSqlError insert(U & u, const QStringList & relation = QStringList(), bool bUseExecBatch = false) 00150 { 00151 QSqlError err; 00152 if (relation.count() == 0) { err = qx::dao::insert(u, this->database(), bUseExecBatch); } 00153 else { err = qx::dao::insert_with_relation(relation, u, this->database()); } 00154 if (err.isValid() && m_pSession) { (* m_pSession) += err; } 00155 return err; 00156 } 00157 00158 template <class U> 00159 QSqlError update(U & u, const qx::QxSqlQuery & query = qx::QxSqlQuery(), const QStringList & columns = QStringList(), const QStringList & relation = QStringList(), bool bUseExecBatch = false) 00160 { 00161 QSqlError err; 00162 if (relation.count() == 0) { err = qx::dao::update_by_query(query, u, this->database(), columns, bUseExecBatch); } 00163 else { err = qx::dao::update_by_query_with_relation(relation, query, u, this->database()); } 00164 if (err.isValid() && m_pSession) { (* m_pSession) += err; } 00165 return err; 00166 } 00167 00168 template <class U> 00169 QSqlError save(U & u, const QStringList & relation = QStringList()) 00170 { 00171 QSqlError err; 00172 if (relation.count() == 0) { err = qx::dao::save(u, this->database()); } 00173 else { err = qx::dao::save_with_relation(relation, u, this->database()); } 00174 if (err.isValid() && m_pSession) { (* m_pSession) += err; } 00175 return err; 00176 } 00177 00178 QSqlError deleteById(const QVariant & id) 00179 { 00180 IxDataMemberX * pDataMemberX = QxClass<T>::getSingleton()->getDataMemberX(); 00181 IxDataMember * pDataMemberId = (pDataMemberX ? pDataMemberX->getId_WithDaoStrategy() : NULL); 00182 if (! pDataMemberId) { qAssert(false); return QSqlError(); } 00183 std::shared_ptr<T> t = std::make_shared<T>(); 00184 pDataMemberId->fromVariant(t.get(), id, -1, qx::cvt::context::e_database); 00185 QSqlError err = qx::dao::delete_by_id((* t), this->database()); 00186 if (err.isValid() && m_pSession) { (* m_pSession) += err; } 00187 return err; 00188 } 00189 00190 template <class U> 00191 QSqlError deleteById(U & u, bool bUseExecBatch = false) 00192 { 00193 QSqlError err = qx::dao::delete_by_id(u, this->database(), bUseExecBatch); 00194 if (err.isValid() && m_pSession) { (* m_pSession) += err; } 00195 return err; 00196 } 00197 00198 QSqlError deleteAll() 00199 { 00200 QSqlError err = qx::dao::delete_all<T>(this->database()); 00201 if (err.isValid() && m_pSession) { (* m_pSession) += err; } 00202 return err; 00203 } 00204 00205 QSqlError deleteByQuery(const qx::QxSqlQuery & query) 00206 { 00207 QSqlError err = qx::dao::delete_by_query<T>(query, this->database()); 00208 if (err.isValid() && m_pSession) { (* m_pSession) += err; } 00209 return err; 00210 } 00211 00212 QSqlError destroyById(const QVariant & id) 00213 { 00214 IxDataMemberX * pDataMemberX = QxClass<T>::getSingleton()->getDataMemberX(); 00215 IxDataMember * pDataMemberId = (pDataMemberX ? pDataMemberX->getId_WithDaoStrategy() : NULL); 00216 if (! pDataMemberId) { qAssert(false); return QSqlError(); } 00217 std::shared_ptr<T> t = std::make_shared<T>(); 00218 pDataMemberId->fromVariant(t.get(), id, -1, qx::cvt::context::e_database); 00219 QSqlError err = qx::dao::destroy_by_id((* t), this->database()); 00220 if (err.isValid() && m_pSession) { (* m_pSession) += err; } 00221 return err; 00222 } 00223 00224 template <class U> 00225 QSqlError destroyById(U & u, bool bUseExecBatch = false) 00226 { 00227 QSqlError err = qx::dao::destroy_by_id(u, this->database(), bUseExecBatch); 00228 if (err.isValid() && m_pSession) { (* m_pSession) += err; } 00229 return err; 00230 } 00231 00232 QSqlError destroyAll() 00233 { 00234 QSqlError err = qx::dao::destroy_all<T>(this->database()); 00235 if (err.isValid() && m_pSession) { (* m_pSession) += err; } 00236 return err; 00237 } 00238 00239 QSqlError destroyByQuery(const qx::QxSqlQuery & query) 00240 { 00241 QSqlError err = qx::dao::destroy_by_query<T>(query, this->database()); 00242 if (err.isValid() && m_pSession) { (* m_pSession) += err; } 00243 return err; 00244 } 00245 00246 template <class U> 00247 qx_bool exist(U & u) 00248 { return qx::dao::exist(u, this->database()); } 00249 00250 private: 00251 00252 typedef typename qx::trait::get_primary_key<T>::type type_primary_key; 00253 typedef qx::QxCollection< type_primary_key, QSharedPointer<T> > type_collection_qt; 00254 typedef qx::QxCollection< type_primary_key, std::shared_ptr<T> > type_collection_boost; 00255 00256 template <bool bIsQObject /* = false */, int dummy> 00257 struct qxVerifyPointer 00258 { static inline T * get(QObject * p) { Q_UNUSED(p); throw qx::dao::sql_error(QX_REPOSITORY_QOBJECT_BASE_CLASS_ERROR); return NULL; } }; 00259 00260 template <int dummy> 00261 struct qxVerifyPointer<true, dummy> 00262 #ifdef _QX_NO_RTTI 00263 { static inline T * get(QObject * p) { T * t = qobject_cast<T *>(p); if (! t) { throw qx::dao::sql_error(QX_REPOSITORY_POINTER_DYNAMIC_CAST_ERROR); }; return t; } }; 00264 #else // _QX_NO_RTTI 00265 { static inline T * get(QObject * p) { T * t = dynamic_cast<T *>(p); if (! t) { throw qx::dao::sql_error(QX_REPOSITORY_POINTER_DYNAMIC_CAST_ERROR); }; return t; } }; 00266 #endif // _QX_NO_RTTI 00267 00268 public: 00269 00270 virtual long _count(const qx::QxSqlQuery & query = qx::QxSqlQuery()) 00271 { return this->count(query); } 00272 00273 virtual void * _fetchById(const QVariant & id, const QStringList & columns = QStringList(), const QStringList & relation = QStringList()) 00274 { return static_cast<void *>(this->fetchById(id, columns, relation)); } 00275 00276 virtual QSqlError _fetchById(QObject * p, const QStringList & columns = QStringList(), const QStringList & relation = QStringList()) 00277 { 00278 T * t = qxVerifyPointer<std::is_base_of<QObject, T>::value, 0>::get(p); 00279 return this->fetchById((* t), columns, relation); 00280 } 00281 00282 virtual QSqlError _fetchById(qx::IxCollection * p, const QStringList & columns = QStringList(), const QStringList & relation = QStringList()) 00283 { 00284 QX_REPOSITORY_CAST_COLLECTION 00285 return (x ? this->fetchById((* x), columns, relation) : this->fetchById((* y), columns, relation)); 00286 } 00287 00288 virtual QSqlError _fetchAll(QObject * p, const QStringList & columns = QStringList(), const QStringList & relation = QStringList()) 00289 { 00290 T * t = qxVerifyPointer<std::is_base_of<QObject, T>::value, 0>::get(p); 00291 return this->fetchAll((* t), columns, relation); 00292 } 00293 00294 virtual QSqlError _fetchAll(qx::IxCollection * p, const QStringList & columns = QStringList(), const QStringList & relation = QStringList()) 00295 { 00296 QX_REPOSITORY_CAST_COLLECTION 00297 return (x ? this->fetchAll((* x), columns, relation) : this->fetchAll((* y), columns, relation)); 00298 } 00299 00300 virtual QSqlError _fetchByQuery(const qx::QxSqlQuery & query, QObject * p, const QStringList & columns = QStringList(), const QStringList & relation = QStringList()) 00301 { 00302 T * t = qxVerifyPointer<std::is_base_of<QObject, T>::value, 0>::get(p); 00303 return this->fetchByQuery(query, (* t), columns, relation); 00304 } 00305 00306 virtual QSqlError _fetchByQuery(const qx::QxSqlQuery & query, qx::IxCollection * p, const QStringList & columns = QStringList(), const QStringList & relation = QStringList()) 00307 { 00308 QX_REPOSITORY_CAST_COLLECTION 00309 return (x ? this->fetchByQuery(query, (* x), columns, relation) : this->fetchByQuery(query, (* y), columns, relation)); 00310 } 00311 00312 virtual QSqlError _insert(QObject * p, const QStringList & relation = QStringList()) 00313 { 00314 T * t = qxVerifyPointer<std::is_base_of<QObject, T>::value, 0>::get(p); 00315 return this->insert((* t), relation); 00316 } 00317 00318 virtual QSqlError _insert(qx::IxCollection * p, const QStringList & relation = QStringList()) 00319 { 00320 QX_REPOSITORY_CAST_COLLECTION 00321 return (x ? this->insert((* x), relation) : this->insert((* y), relation)); 00322 } 00323 00324 virtual QSqlError _update(QObject * p, const qx::QxSqlQuery & query = qx::QxSqlQuery(), const QStringList & columns = QStringList(), const QStringList & relation = QStringList()) 00325 { 00326 T * t = qxVerifyPointer<std::is_base_of<QObject, T>::value, 0>::get(p); 00327 return this->update((* t), query, columns, relation); 00328 } 00329 00330 virtual QSqlError _update(qx::IxCollection * p, const qx::QxSqlQuery & query = qx::QxSqlQuery(), const QStringList & columns = QStringList(), const QStringList & relation = QStringList()) 00331 { 00332 QX_REPOSITORY_CAST_COLLECTION 00333 return (x ? this->update((* x), query, columns, relation) : this->update((* y), query, columns, relation)); 00334 } 00335 00336 virtual QSqlError _save(QObject * p, const QStringList & relation = QStringList()) 00337 { 00338 T * t = qxVerifyPointer<std::is_base_of<QObject, T>::value, 0>::get(p); 00339 return this->save((* t), relation); 00340 } 00341 00342 virtual QSqlError _save(qx::IxCollection * p, const QStringList & relation = QStringList()) 00343 { 00344 QX_REPOSITORY_CAST_COLLECTION 00345 return (x ? this->save((* x), relation) : this->save((* y), relation)); 00346 } 00347 00348 virtual QSqlError _deleteById(const QVariant & id) 00349 { return this->deleteById(id); } 00350 00351 virtual QSqlError _deleteById(QObject * p) 00352 { 00353 T * t = qxVerifyPointer<std::is_base_of<QObject, T>::value, 0>::get(p); 00354 return this->deleteById(* t); 00355 } 00356 00357 virtual QSqlError _deleteById(qx::IxCollection * p) 00358 { 00359 QX_REPOSITORY_CAST_COLLECTION 00360 return (x ? this->deleteById(* x) : this->deleteById(* y)); 00361 } 00362 00363 virtual QSqlError _deleteAll() 00364 { return this->deleteAll(); } 00365 00366 virtual QSqlError _deleteByQuery(const qx::QxSqlQuery & query) 00367 { return this->deleteByQuery(query); } 00368 00369 virtual QSqlError _destroyById(const QVariant & id) 00370 { return this->destroyById(id); } 00371 00372 virtual QSqlError _destroyById(QObject * p) 00373 { 00374 T * t = qxVerifyPointer<std::is_base_of<QObject, T>::value, 0>::get(p); 00375 return this->destroyById(* t); 00376 } 00377 00378 virtual QSqlError _destroyById(qx::IxCollection * p) 00379 { 00380 QX_REPOSITORY_CAST_COLLECTION 00381 return (x ? this->destroyById(* x) : this->destroyById(* y)); 00382 } 00383 00384 virtual QSqlError _destroyAll() 00385 { return this->destroyAll(); } 00386 00387 virtual QSqlError _destroyByQuery(const qx::QxSqlQuery & query) 00388 { return this->destroyByQuery(query); } 00389 00390 virtual qx_bool _exist(QObject * p) 00391 { 00392 T * t = qxVerifyPointer<std::is_base_of<QObject, T>::value, 0>::get(p); 00393 return this->exist(* t); 00394 } 00395 00396 virtual qx_bool _exist(qx::IxCollection * p) 00397 { 00398 QX_REPOSITORY_CAST_COLLECTION 00399 return (x ? this->exist(* x) : this->exist(* y)); 00400 } 00401 00402 virtual qx::IxCollection_ptr _newCollection() const 00403 { 00404 qx::IxCollection_ptr lst = std::make_shared<type_collection_boost>(); 00405 return lst; 00406 } 00407 00408 virtual qx::IxClass * _getClass() const 00409 { return qx::QxClass<T>::getSingleton(); } 00410 00411 public: 00412 00413 static T * getById(const QVariant & id, const QStringList & columns = QStringList(), const QStringList & relation = QStringList()) 00414 { 00415 IxDataMemberX * pDataMemberX = QxClass<T>::getSingleton()->getDataMemberX(); 00416 IxDataMember * pDataMemberId = (pDataMemberX ? pDataMemberX->getId_WithDaoStrategy() : NULL); 00417 if (! pDataMemberId) { qAssert(false); return NULL; } 00418 T * t = new T(); QSqlError err; 00419 pDataMemberId->fromVariant(t, id, -1, qx::cvt::context::e_database); 00420 if (relation.count() == 0) { err = qx::dao::fetch_by_id((* t), NULL, columns); } 00421 else { err = qx::dao::fetch_by_id_with_relation(relation, (* t), NULL); } 00422 if (err.isValid()) { delete t; t = NULL; } 00423 return t; 00424 } 00425 00426 }; 00427 00428 template <class T> 00429 inline void register_repository(const QString & sKey) 00430 { 00431 // 'pNewRepository' instance will be destroyed by 'qx::QxRepositoryX::unregisterRepository()' method 00432 qx::QxRepository<T> * pNewRepository = new qx::QxRepository<T>(sKey); 00433 Q_UNUSED(pNewRepository); 00434 } 00435 00436 } // namespace qx 00437 00438 #endif // _QX_REPOSITORY_H_